diff --git a/prs/9045/2608050 b/prs/9045/91995995 similarity index 100% rename from prs/9045/2608050 rename to prs/9045/91995995 diff --git a/prs/9045/ct_logs/all_runs.html b/prs/9045/ct_logs/all_runs.html index cb0584148c50..a65a89295cb6 100644 --- a/prs/9045/ct_logs/all_runs.html +++ b/prs/9045/ct_logs/all_runs.html @@ -107,7 +107,7 @@

All test runs in "ct_logs"

-Mon Nov 25 2024 22:07:54test_server@911102fae525 +Tue Nov 26 2024 19:26:14test_server@bb0d16f6f554 - 1 make_test_dir.system_test @@ -119,7 +119,7 @@

All test runs in "ct_logs"

-Mon Nov 25 2024 20:52:52test_server@dd5ff18f51ea +Tue Nov 26 2024 18:10:42test_server@9ac2ce98127e - 1 make_test_dir.common_test_test @@ -136,7 +136,7 @@

All test runs in "ct_logs"



diff --git a/prs/9045/ct_logs/ct_log_cache b/prs/9045/ct_logs/ct_log_cache index 540eb33aaca3..c40ae22f1741 100644 Binary files a/prs/9045/ct_logs/ct_log_cache and b/prs/9045/ct_logs/ct_log_cache differ diff --git a/prs/9045/ct_logs/ct_run.test_server@911102fae525.2024-11-25_22.07.54/last_name b/prs/9045/ct_logs/ct_run.test_server@911102fae525.2024-11-25_22.07.54/last_name deleted file mode 100644 index 70940e346ac4..000000000000 --- a/prs/9045/ct_logs/ct_run.test_server@911102fae525.2024-11-25_22.07.54/last_name +++ /dev/null @@ -1 +0,0 @@ -/buildroot/otp/erts/make_test_dir/ct_logs/ct_run.test_server@911102fae525.2024-11-25_22.07.54/make_test_dir.system_test.logs/run.2024-11-25_22.07.54 diff --git a/prs/9045/ct_logs/ct_run.test_server@911102fae525.2024-11-25_22.07.54/make_test_dir.system_test.logs/last_name b/prs/9045/ct_logs/ct_run.test_server@911102fae525.2024-11-25_22.07.54/make_test_dir.system_test.logs/last_name deleted file mode 100644 index 70940e346ac4..000000000000 --- a/prs/9045/ct_logs/ct_run.test_server@911102fae525.2024-11-25_22.07.54/make_test_dir.system_test.logs/last_name +++ /dev/null @@ -1 +0,0 @@ -/buildroot/otp/erts/make_test_dir/ct_logs/ct_run.test_server@911102fae525.2024-11-25_22.07.54/make_test_dir.system_test.logs/run.2024-11-25_22.07.54 diff --git a/prs/9045/ct_logs/ct_run.test_server@911102fae525.2024-11-25_22.07.54/make_test_dir.system_test.logs/run.2024-11-25_22.07.54/suite.summary b/prs/9045/ct_logs/ct_run.test_server@911102fae525.2024-11-25_22.07.54/make_test_dir.system_test.logs/run.2024-11-25_22.07.54/suite.summary deleted file mode 100644 index 283d39d0edd5..000000000000 --- a/prs/9045/ct_logs/ct_run.test_server@911102fae525.2024-11-25_22.07.54/make_test_dir.system_test.logs/run.2024-11-25_22.07.54/suite.summary +++ /dev/null @@ -1 +0,0 @@ -{summary,{107,0,2,0,247399623}}. diff --git a/prs/9045/ct_logs/ct_run.test_server@911102fae525.2024-11-25_22.07.54/totals.info b/prs/9045/ct_logs/ct_run.test_server@911102fae525.2024-11-25_22.07.54/totals.info deleted file mode 100644 index ff8f93ef75bc..000000000000 Binary files a/prs/9045/ct_logs/ct_run.test_server@911102fae525.2024-11-25_22.07.54/totals.info and /dev/null differ diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/basic_compatible_no_nodes.spec b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/basic_compatible_no_nodes.spec similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/basic_compatible_no_nodes.spec rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/basic_compatible_no_nodes.spec diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/basic_compatible_nodes.spec b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/basic_compatible_nodes.spec similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/basic_compatible_nodes.spec rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/basic_compatible_nodes.spec diff --git a/prs/9045/ct_logs/ct_run.test_server@911102fae525.2024-11-25_22.07.54/ct_default.css b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/ct_default.css similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@911102fae525.2024-11-25_22.07.54/ct_default.css rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/ct_default.css diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/ctlog.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/ctlog.html similarity index 83% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/ctlog.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/ctlog.html index beb637e8727d..d67b74110397 100644 --- a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/ctlog.html +++ b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/ctlog.html @@ -118,89 +118,89 @@

PRE/POST TEST I/O LOG

PROGRESS LOG

 
-
*** CT 2024-11-25 20:52:52.640 *** Common Test Logger started
+
*** CT 2024-11-26 18:10:42.047 *** Common Test Logger started
 VERBOSITY LEVELS:
 general level            100
 default                  100
 
 
-
*** CT 2024-11-25 20:52:52.644 *** Test Specification file(s)
+
*** CT 2024-11-26 18:10:42.051 *** Test Specification file(s)
 /buildroot/otp/lib/common_test/make_test_dir/common_test_test/common_test_gh.spec 
 

-
*** CT 2024-11-25 20:52:55.288 *** TEST INFO
+
*** CT 2024-11-26 18:10:44.647 *** TEST INFO
 init_per_group/2 and end_per_group/2 missing for group find_groups in ct_groups_search_SUITE, using default.
 

-
*** CT 2024-11-25 20:52:55.288 *** TEST INFO
+
*** CT 2024-11-26 18:10:44.647 *** TEST INFO
 init_per_group/2 and end_per_group/2 missing for group run_groups in ct_groups_search_SUITE, using default.
 

-
*** CT 2024-11-25 20:52:55.288 *** TEST INFO
+
*** CT 2024-11-26 18:10:44.647 *** TEST INFO
 init_per_group/2 and end_per_group/2 missing for group cth_log_redirect in ct_hooks_SUITE, using default.
 

-
*** CT 2024-11-25 20:52:55.290 *** TEST INFO
+
*** CT 2024-11-26 18:10:44.649 *** TEST INFO
 init_per_group/2 and end_per_group/2 missing for group legacy in ct_telnet_SUITE, using default.
 

-
*** CT 2024-11-25 20:52:55.290 *** TEST INFO
+
*** CT 2024-11-26 18:10:44.649 *** TEST INFO
 init_per_group/2 and end_per_group/2 missing for group raw in ct_telnet_SUITE, using default.
 

-
*** CT 2024-11-25 20:52:55.290 *** TEST INFO
+
*** CT 2024-11-26 18:10:44.649 *** TEST INFO
 init_per_group/2 and end_per_group/2 missing for group html in ct_telnet_SUITE, using default.
 

-
*** CT 2024-11-25 20:52:55.290 *** TEST INFO
+
*** CT 2024-11-26 18:10:44.649 *** TEST INFO
 init_per_group/2 and end_per_group/2 missing for group silent in ct_telnet_SUITE, using default.
 

-
*** CT 2024-11-25 20:52:55.293 *** TEST INFO
+
*** CT 2024-11-26 18:10:44.651 *** TEST INFO
 1 test(s), 372 case(s) in 47 suite(s)
 

-
*** CT 2024-11-25 20:52:55.293 *** TEST INFO
+
*** CT 2024-11-26 18:10:44.651 *** TEST INFO
 Timetrap time multiplier = 1
 Timetrap scaling enabled = false
 

-
*** CT 2024-11-25 20:52:55.400 *** TEST INFO
+
*** CT 2024-11-26 18:10:44.757 *** TEST INFO
 init_per_group/2 and end_per_group/2 missing for group find_groups in ct_groups_search_SUITE, using default.
 

-
*** CT 2024-11-25 20:52:55.400 *** TEST INFO
+
*** CT 2024-11-26 18:10:44.757 *** TEST INFO
 init_per_group/2 and end_per_group/2 missing for group run_groups in ct_groups_search_SUITE, using default.
 

-
*** CT 2024-11-25 20:52:55.400 *** TEST INFO
+
*** CT 2024-11-26 18:10:44.758 *** TEST INFO
 init_per_group/2 and end_per_group/2 missing for group cth_log_redirect in ct_hooks_SUITE, using default.
 

-
*** CT 2024-11-25 20:52:55.402 *** TEST INFO
+
*** CT 2024-11-26 18:10:44.760 *** TEST INFO
 init_per_group/2 and end_per_group/2 missing for group legacy in ct_telnet_SUITE, using default.
 

-
*** CT 2024-11-25 20:52:55.402 *** TEST INFO
+
*** CT 2024-11-26 18:10:44.760 *** TEST INFO
 init_per_group/2 and end_per_group/2 missing for group raw in ct_telnet_SUITE, using default.
 

-
*** CT 2024-11-25 20:52:55.402 *** TEST INFO
+
*** CT 2024-11-26 18:10:44.760 *** TEST INFO
 init_per_group/2 and end_per_group/2 missing for group html in ct_telnet_SUITE, using default.
 

-
*** CT 2024-11-25 20:52:55.402 *** TEST INFO
+
*** CT 2024-11-26 18:10:44.760 *** TEST INFO
 init_per_group/2 and end_per_group/2 missing for group silent in ct_telnet_SUITE, using default.
 

-
*** CT 2024-11-25 22:04:32.359 *** Common Test Logger finished
+
*** CT 2024-11-26 19:22:27.974 *** Common Test Logger finished
 


diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/define_names_1.spec b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/define_names_1.spec similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/define_names_1.spec rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/define_names_1.spec diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/index.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/index.html similarity index 91% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/index.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/index.html index f570bf43c3a3..6ee2f4ff6672 100644 --- a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/index.html +++ b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/index.html @@ -3,7 +3,7 @@ -Test Results Mon Nov 25 2024 20:52:52 +Test Results Tue Nov 26 2024 18:10:42 @@ -81,7 +81,7 @@

Test Results

-

Mon Nov 25 2024 20:52:52

+

Tue Nov 26 2024 18:10:42


@@ -103,12 +103,12 @@

Mon Nov 25 2024 20:52:52

-make_test_dir.common_test_test +make_test_dir.common_test_test 359 0 13 (9/4) 0 -4295.735s +4301.995s @@ -118,7 +118,7 @@

Mon Nov 25 2024 20:52:52

0 13 (9/4) 0 -4295.735s +4301.995s @@ -130,7 +130,7 @@

Mon Nov 25 2024 20:52:52

diff --git a/prs/9045/ct_logs/ct_run.test_server@911102fae525.2024-11-25_22.07.54/jquery-latest.js b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/jquery-latest.js similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@911102fae525.2024-11-25_22.07.54/jquery-latest.js rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/jquery-latest.js diff --git a/prs/9045/ct_logs/ct_run.test_server@911102fae525.2024-11-25_22.07.54/jquery.tablesorter.min.js b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/jquery.tablesorter.min.js similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@911102fae525.2024-11-25_22.07.54/jquery.tablesorter.min.js rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/jquery.tablesorter.min.js diff --git a/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/last_name b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/last_name new file mode 100644 index 000000000000..583f2062752a --- /dev/null +++ b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/last_name @@ -0,0 +1 @@ +/buildroot/otp/lib/common_test/make_test_dir/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/run.2024-11-26_18.10.44 diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/last_test.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/last_test.html similarity index 77% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/last_test.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/last_test.html index 9d70a3b80853..67eacb6cf88c 100644 --- a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/last_test.html +++ b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/last_test.html @@ -8,6 +8,6 @@

Last test

-make_test_dir.common_test_test.logs +make_test_dir.common_test_test.logs diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_auto_clean_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_auto_clean_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_auto_clean_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_auto_clean_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_auto_compile_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_auto_compile_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_auto_compile_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_auto_compile_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_basic_html_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_basic_html_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_basic_html_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_basic_html_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_config_info_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_config_info_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_config_info_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_config_info_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_config_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_config_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_config_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_config_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_cover_nomerge_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_cover_nomerge_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_cover_nomerge_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_cover_nomerge_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_cover_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_cover_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_cover_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_cover_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_error_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_error_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_error_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_error_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_event_handler_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_event_handler_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_event_handler_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_event_handler_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_gen_conn_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_gen_conn_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_gen_conn_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_gen_conn_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_group_info_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_group_info_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_group_info_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_group_info_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_group_leader_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_group_leader_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_group_leader_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_group_leader_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_groups_search_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_groups_search_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_groups_search_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_groups_search_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_groups_spec_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_groups_spec_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_groups_spec_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_groups_spec_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_groups_test_1_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_groups_test_1_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_groups_test_1_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_groups_test_1_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_groups_test_2_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_groups_test_2_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_groups_test_2_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_groups_test_2_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_hooks_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_hooks_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_hooks_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_hooks_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_keep_logs_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_keep_logs_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_keep_logs_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_keep_logs_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_log_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_log_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_log_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_log_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_master_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_master_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_master_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_master_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_misc_1_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_misc_1_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_misc_1_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_misc_1_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_netconfc_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_netconfc_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_netconfc_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_netconfc_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_pre_post_test_io_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_pre_post_test_io_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_pre_post_test_io_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_pre_post_test_io_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_priv_dir_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_priv_dir_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_priv_dir_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_priv_dir_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_property_test_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_property_test_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_property_test_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_property_test_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_repeat_1_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_repeat_1_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_repeat_1_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_repeat_1_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_repeat_testrun_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_repeat_testrun_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_repeat_testrun_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_repeat_testrun_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_sequence_1_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_sequence_1_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_sequence_1_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_sequence_1_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_shell_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_shell_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_shell_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_shell_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_skip_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_skip_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_skip_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_skip_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_smoke_test_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_smoke_test_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_smoke_test_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_smoke_test_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_snmp_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_snmp_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_snmp_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_snmp_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_suite.src.html similarity index 100% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_suite.src.html diff --git a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_surefire_suite.src.html b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_surefire_suite.src.html similarity index 70% rename from prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_surefire_suite.src.html rename to prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_surefire_suite.src.html index 6b460f86c2a3..b0f2f5e601f3 100644 --- a/prs/9045/ct_logs/ct_run.test_server@dd5ff18f51ea.2024-11-25_20.52.52/make_test_dir.common_test_test.logs/ct_surefire_suite.src.html +++ b/prs/9045/ct_logs/ct_run.test_server@9ac2ce98127e.2024-11-26_18.10.42/make_test_dir.common_test_test.logs/ct_surefire_suite.src.html @@ -161,39 +161,39 @@ 151: Test = [{spec,Spec},{ct_hooks,CTHs},{label,Case}], 152: do_run(Case, Report, Test, Config). 153: - 154: do_run(Case, Report, Test, Config) -> - 155: {Opts,ERPid} = setup(Test, Config), - 156: ok = execute(Case, Opts, ERPid, Config), + 154: do_run(Case, Report, RunTestOpts0, Config) -> + 155: {RunTestOpts,ERPid} = setup(RunTestOpts0, Config), + 156: ok = execute(Case, RunTestOpts, ERPid, Config), 157: LogDir = - 158: case lists:keyfind(logdir,1,Opts) of + 158: case lists:keyfind(logdir,1,RunTestOpts) of 159: {logdir,LD} -> LD; 160: false -> ?config(priv_dir,Config) 161: end, 162: Re = filename:join([LogDir,"*",Report]), 163: check_xml(Case,Re). 164: - 165: setup(Test, Config) -> + 165: setup(RunTestOpts0, Config) -> 166: Opts0 = ct_test_support:get_opts(Config), 167: Opts1 = - 168: case lists:keymember(logdir,1,Test) of + 168: case lists:keymember(logdir,1,RunTestOpts0) of 169: true -> lists:keydelete(logdir,1,Opts0); 170: false -> Opts0 171: end, 172: Level = ?config(trace_level, Config), 173: EvHArgs = [{cbm,ct_test_support},{trace_level,Level}], - 174: Opts = Opts1 ++ [{event_handler,{?eh,EvHArgs}}|Test], + 174: RunTestOpts = Opts1 ++ [{event_handler,{?eh,EvHArgs}}|RunTestOpts0], 175: ERPid = ct_test_support:start_event_receiver(Config), - 176: {Opts,ERPid}. + 176: {RunTestOpts,ERPid}. 177: - 178: execute(Name, Opts, ERPid, Config) -> - 179: ok = ct_test_support:run(Opts, Config), + 178: execute(Case, RunTestOpts, ERPid, Config) -> + 179: ok = ct_test_support:run(RunTestOpts, Config), 180: Events = ct_test_support:get_events(ERPid, Config), - 181: ct_test_support:log_events(Name, + 181: ct_test_support:log_events(Case, 182: reformat(Events, ?eh), 183: ?config(priv_dir, Config), - 184: Opts), + 184: RunTestOpts), 185: - 186: TestEvents = events_to_check(Name), + 186: TestEvents = events_to_check(Case), 187: ct_test_support:verify_events(TestEvents, Events, Config). 188: 189: reformat(Events, EH) -> @@ -233,8 +233,8 @@ 223: {?eh,test_stats,{1,0,{0,0}}}, 224: {?eh,tc_start,{ct_framework,end_per_suite}}, 225: {?eh,tc_done,{ct_framework,end_per_suite,ok}}]; - 226: test_suite_events(skip_all_surefire_SUITE) -> - 227: [{?eh,tc_user_skip,{skip_all_surefire_SUITE,all,"skipped in spec"}}, + 226: test_suite_events(skip_suite_in_spec) -> + 227: [{?eh,tc_user_skip,{surefire_SUITE,all,"skipped in spec"}}, 228: {?eh,test_stats,{0,0,{1,0}}}]; 229: test_suite_events(Test) -> 230: [{?eh,tc_start,{surefire_SUITE,init_per_suite}}, @@ -311,7 +311,7 @@ 301: [{?eh,stop_logging,[]}]; 302: test_events(skip_suite_in_spec) -> 303: [{?eh,start_logging,'_'},{?eh,start_info,{1,1,0}}] ++ - 304: test_suite_events(skip_all_surefire_SUITE) ++ + 304: test_suite_events(skip_suite_in_spec) ++ 305: [{?eh,stop_logging,[]}]; 306: test_events(Test) -> 307: [{?eh,start_logging,'_'}, {?eh,start_info,{1,1,11}}] ++ @@ -363,173 +363,180 @@ 353: testsuite(Case,TS). 354: 355: testsuite(Case,[#xmlElement{name=testsuite,content=TC,attributes=A}|TS]) -> - 356: TestSuiteEvents = test_suite_events(get_ts_name(A)), - 357: {ET,EF,ES} = events_to_numbers(lists:flatten(TestSuiteEvents)), - 358: {T,E,F,S} = get_numbers_from_attrs(A,false,false,false,false), - 359: ct:log("Expecting total:~p, error:~p, failure:~p, skipped:~p~n",[ET,0,EF,ES]), - 360: ct:log("Actual total:~p, error:~p, failure:~p, skipped:~p~n",[T,E,F,S]), - 361: {ET,0,EF,ES} = {T,E,F,S}, - 362: - 363: %% properties should only be there if given a options to hook - 364: false = lists:keytake(properties,#xmlElement.name,TC), - 365: %% system-out and system-err is not used by common_test - 366: false = lists:keytake('system-out',#xmlElement.name,TC), - 367: false = lists:keytake('system-err',#xmlElement.name,TC), - 368: R=testcase(Case,TC), - 369: [R|testsuite(Case,TS)]; - 370: testsuite(_Case,[]) -> - 371: []. - 372: - 373: testcase(url=Case,[#xmlElement{name=testcase,attributes=A,content=C}|TC]) -> - 374: R = failed_or_skipped(C), - 375: assert_lines(Case,A), - 376: case R of - 377: [s] -> - 378: case lists:keyfind(url,#xmlAttribute.name,A) of - 379: false -> ok; - 380: #xmlAttribute{value=UrlAttr} -> - 381: lists:keyfind(url,#xmlAttribute.name,A), - 382: true = lists:prefix(?url_base,UrlAttr) - 383: end; - 384: _ -> - 385: #xmlAttribute{value=UrlAttr} = - 386: lists:keyfind(url,#xmlAttribute.name,A), - 387: true = lists:prefix(?url_base,UrlAttr) - 388: end, - 389: [R|testcase(Case,TC)]; - 390: testcase(Case,[#xmlElement{name=testcase,attributes=A,content=C}|TC]) -> - 391: false = lists:keyfind(url,#xmlAttribute.name,A), - 392: assert_lines(Case,A), - 393: R = failed_or_skipped(C), - 394: [R|testcase(Case,TC)]; - 395: testcase(_Case,[]) -> - 396: []. - 397: - 398: failed_or_skipped([#xmlElement{name=failure}|E]) -> - 399: [f|failed_or_skipped(E)]; - 400: failed_or_skipped([#xmlElement{name=error}|E]) -> - 401: [e|failed_or_skipped(E)]; - 402: failed_or_skipped([#xmlElement{name=skipped}|E]) -> - 403: [s|failed_or_skipped(E)]; - 404: failed_or_skipped([]) -> - 405: []. - 406: - 407: assert_lines(Case, A) when Case =/= fail_pre_init_per_suite, - 408: Case =/= skip_case_in_spec, - 409: Case =/= skip_suite_in_spec -> - 410: Name = lists:keyfind(name,#xmlAttribute.name,A), - 411: File = lists:keyfind(file,#xmlAttribute.name,A), - 412: Line = lists:keyfind(line,#xmlAttribute.name,A), - 413: ?assertMatch("surefire_SUITE.erl",filename:basename(File#xmlAttribute.value)), - 414: case Name#xmlAttribute.value of - 415: "init_per_suite" -> - 416: ?assertMatch("51", Line#xmlAttribute.value); - 417: "end_per_suite" -> - 418: ?assertMatch("54", Line#xmlAttribute.value); - 419: "tc_ok" -> - 420: ?assertMatch("80", Line#xmlAttribute.value); - 421: "tc_fail" -> - 422: ?assertMatch("85", Line#xmlAttribute.value); - 423: "tc_badmatch" -> - 424: ?assertMatch("89", Line#xmlAttribute.value); - 425: "tc_skip" -> - 426: ?assertMatch("91", Line#xmlAttribute.value); - 427: "tc_autoskip_require" -> - 428: ?assertMatch("96", Line#xmlAttribute.value); - 429: "init_per_group" -> - 430: ?assertMatch("57", Line#xmlAttribute.value); - 431: "end_per_group" -> - 432: ?assertMatch("62", Line#xmlAttribute.value) - 433: end; - 434: assert_lines(_, _) -> - 435: ok. - 436: - 437: - 438: %% Using the expected events to produce the expected result of the XML scanning. - 439: %% The result is a list of test suites: - 440: %% Testsuites = [Testsuite] - 441: %% Testsuite = [Testcase] - 442: %% Testcase = [] | [f] | [s], indicating ok, failed and skipped respectively - 443: events_to_result(E) -> - 444: events_to_result(E, []). - 445: - 446: events_to_result([{?eh,tc_user_skip,{_Suite,all,_}}|E], Result) -> - 447: events_to_result(E, [[[s]]|Result]); - 448: events_to_result([{?eh,tc_auto_skip,{_Suite,init_per_suite,_}}|E], Result) -> - 449: {Suite,Rest} = events_to_result1(E), - 450: events_to_result(Rest, [[[s]|Suite]|Result]); - 451: events_to_result([{?eh,tc_done,{_Suite,init_per_suite,R}}|E], Result) -> - 452: {Suite,Rest} = events_to_result1(E), - 453: events_to_result(Rest, [[result(R)|Suite]|Result]); - 454: events_to_result([_|E], Result) -> - 455: events_to_result(E, Result); - 456: events_to_result([], Result) -> - 457: Result. - 458: - 459: events_to_result1([{?eh,tc_auto_skip,{_Suite, end_per_suite,_}}|E]) -> - 460: {[[s]],E}; - 461: events_to_result1([{?eh,tc_done,{_Suite, end_per_suite,R}}|E]) -> - 462: {[result(R)],E}; - 463: events_to_result1([{?eh,tc_done,{_Suite,_Case,R}}|E]) -> - 464: {Suite,Rest} = events_to_result1(E), - 465: {[result(R)|Suite],Rest}; - 466: events_to_result1([{?eh,Skip,_}|E]) when Skip==tc_auto_skip; Skip==tc_user_skip -> - 467: {Suite,Rest} = events_to_result1(E), - 468: {[[s]|Suite],Rest}; - 469: events_to_result1([_|E]) -> - 470: events_to_result1(E). - 471: - 472: result(ok) ->[]; - 473: result({skipped,_}) -> [s]; - 474: result({auto_skipped,_}) -> [s]; - 475: result({failed,_}) -> [f]. - 476: - 477: %% Using the expected events' last test_stats element to produce the - 478: %% expected number of totla, errors, failed and skipped testcases. - 479: events_to_numbers(E) -> - 480: RevE = lists:reverse(E), - 481: {?eh,test_stats,{Ok,F,{US,AS}}} = lists:keyfind(test_stats,2,RevE), - 482: {Ok+F+US+AS,F,US+AS}. + 356: TestSuiteEvents = + 357: test_suite_events( + 358: case Case of + 359: skip_suite_in_spec -> + 360: skip_suite_in_spec; + 361: _ -> + 362: get_ts_name(A) + 363: end), + 364: {ET,EF,ES} = events_to_numbers(lists:flatten(TestSuiteEvents)), + 365: {T,E,F,S} = get_numbers_from_attrs(A,false,false,false,false), + 366: ct:log("Expecting total:~p, error:~p, failure:~p, skipped:~p~n",[ET,0,EF,ES]), + 367: ct:log("Actual total:~p, error:~p, failure:~p, skipped:~p~n",[T,E,F,S]), + 368: {ET,0,EF,ES} = {T,E,F,S}, + 369: + 370: %% properties should only be there if given a options to hook + 371: false = lists:keytake(properties,#xmlElement.name,TC), + 372: %% system-out and system-err is not used by common_test + 373: false = lists:keytake('system-out',#xmlElement.name,TC), + 374: false = lists:keytake('system-err',#xmlElement.name,TC), + 375: R=testcase(Case,TC), + 376: [R|testsuite(Case,TS)]; + 377: testsuite(_Case,[]) -> + 378: []. + 379: + 380: testcase(url=Case,[#xmlElement{name=testcase,attributes=A,content=C}|TC]) -> + 381: R = failed_or_skipped(C), + 382: assert_lines(Case,A), + 383: case R of + 384: [s] -> + 385: case lists:keyfind(url,#xmlAttribute.name,A) of + 386: false -> ok; + 387: #xmlAttribute{value=UrlAttr} -> + 388: lists:keyfind(url,#xmlAttribute.name,A), + 389: true = lists:prefix(?url_base,UrlAttr) + 390: end; + 391: _ -> + 392: #xmlAttribute{value=UrlAttr} = + 393: lists:keyfind(url,#xmlAttribute.name,A), + 394: true = lists:prefix(?url_base,UrlAttr) + 395: end, + 396: [R|testcase(Case,TC)]; + 397: testcase(Case,[#xmlElement{name=testcase,attributes=A,content=C}|TC]) -> + 398: false = lists:keyfind(url,#xmlAttribute.name,A), + 399: assert_lines(Case,A), + 400: R = failed_or_skipped(C), + 401: [R|testcase(Case,TC)]; + 402: testcase(_Case,[]) -> + 403: []. + 404: + 405: failed_or_skipped([#xmlElement{name=failure}|E]) -> + 406: [f|failed_or_skipped(E)]; + 407: failed_or_skipped([#xmlElement{name=error}|E]) -> + 408: [e|failed_or_skipped(E)]; + 409: failed_or_skipped([#xmlElement{name=skipped}|E]) -> + 410: [s|failed_or_skipped(E)]; + 411: failed_or_skipped([]) -> + 412: []. + 413: + 414: assert_lines(Case, A) when Case =/= fail_pre_init_per_suite, + 415: Case =/= skip_case_in_spec, + 416: Case =/= skip_suite_in_spec -> + 417: Name = lists:keyfind(name,#xmlAttribute.name,A), + 418: File = lists:keyfind(file,#xmlAttribute.name,A), + 419: Line = lists:keyfind(line,#xmlAttribute.name,A), + 420: ?assertMatch("surefire_SUITE.erl",filename:basename(File#xmlAttribute.value)), + 421: case Name#xmlAttribute.value of + 422: "init_per_suite" -> + 423: ?assertMatch("51", Line#xmlAttribute.value); + 424: "end_per_suite" -> + 425: ?assertMatch("54", Line#xmlAttribute.value); + 426: "tc_ok" -> + 427: ?assertMatch("80", Line#xmlAttribute.value); + 428: "tc_fail" -> + 429: ?assertMatch("85", Line#xmlAttribute.value); + 430: "tc_badmatch" -> + 431: ?assertMatch("89", Line#xmlAttribute.value); + 432: "tc_skip" -> + 433: ?assertMatch("91", Line#xmlAttribute.value); + 434: "tc_autoskip_require" -> + 435: ?assertMatch("96", Line#xmlAttribute.value); + 436: "init_per_group" -> + 437: ?assertMatch("57", Line#xmlAttribute.value); + 438: "end_per_group" -> + 439: ?assertMatch("62", Line#xmlAttribute.value) + 440: end; + 441: assert_lines(_, _) -> + 442: ok. + 443: + 444: + 445: %% Using the expected events to produce the expected result of the XML scanning. + 446: %% The result is a list of test suites: + 447: %% Testsuites = [Testsuite] + 448: %% Testsuite = [Testcase] + 449: %% Testcase = [] | [f] | [s], indicating ok, failed and skipped respectively + 450: events_to_result(E) -> + 451: events_to_result(E, []). + 452: + 453: events_to_result([{?eh,tc_user_skip,{_Suite,all,_}}|E], Result) -> + 454: events_to_result(E, [[[s]]|Result]); + 455: events_to_result([{?eh,tc_auto_skip,{_Suite,init_per_suite,_}}|E], Result) -> + 456: {Suite,Rest} = events_to_result1(E), + 457: events_to_result(Rest, [[[s]|Suite]|Result]); + 458: events_to_result([{?eh,tc_done,{_Suite,init_per_suite,R}}|E], Result) -> + 459: {Suite,Rest} = events_to_result1(E), + 460: events_to_result(Rest, [[result(R)|Suite]|Result]); + 461: events_to_result([_|E], Result) -> + 462: events_to_result(E, Result); + 463: events_to_result([], Result) -> + 464: Result. + 465: + 466: events_to_result1([{?eh,tc_auto_skip,{_Suite, end_per_suite,_}}|E]) -> + 467: {[[s]],E}; + 468: events_to_result1([{?eh,tc_done,{_Suite, end_per_suite,R}}|E]) -> + 469: {[result(R)],E}; + 470: events_to_result1([{?eh,tc_done,{_Suite,_Case,R}}|E]) -> + 471: {Suite,Rest} = events_to_result1(E), + 472: {[result(R)|Suite],Rest}; + 473: events_to_result1([{?eh,Skip,_}|E]) when Skip==tc_auto_skip; Skip==tc_user_skip -> + 474: {Suite,Rest} = events_to_result1(E), + 475: {[[s]|Suite],Rest}; + 476: events_to_result1([_|E]) -> + 477: events_to_result1(E). + 478: + 479: result(ok) ->[]; + 480: result({skipped,_}) -> [s]; + 481: result({auto_skipped,_}) -> [s]; + 482: result({failed,_}) -> [f]. 483: - 484: get_numbers_from_attrs([#xmlAttribute{name=tests,value=X}|A],false,E,F,S) -> - 485: get_numbers_from_attrs(A,list_to_integer(X),E,F,S); - 486: get_numbers_from_attrs([#xmlAttribute{name=errors,value=X}|A],T,false,F,S) -> - 487: get_numbers_from_attrs(A,T,list_to_integer(X),F,S); - 488: get_numbers_from_attrs([#xmlAttribute{name=failures,value=X}|A],T,E,false,S) -> - 489: get_numbers_from_attrs(A,T,E,list_to_integer(X),S); - 490: get_numbers_from_attrs([#xmlAttribute{name=skipped,value=X}|A],T,E,F,false) -> - 491: get_numbers_from_attrs(A,T,E,F,list_to_integer(X)); - 492: get_numbers_from_attrs([_|A],T,E,F,S) -> - 493: get_numbers_from_attrs(A,T,E,F,S); - 494: get_numbers_from_attrs([],T,E,F,S) -> - 495: {T,E,F,S}. - 496: - 497: ensure_exists_empty(Dir) -> - 498: case file:list_dir(Dir) of - 499: {error,enoent} -> - 500: file:make_dir(Dir); - 501: {ok,Files} -> - 502: del_files(Dir,Files) - 503: end. - 504: - 505: del_files(Dir,[F0|Fs] ) -> - 506: F = filename:join(Dir,F0), - 507: case file:read_file_info(F) of - 508: {ok,#file_info{type=directory}} -> - 509: {ok,Files} = file:list_dir(F), - 510: del_files(F,Files), - 511: file:del_dir(F), - 512: del_files(Dir,Fs); - 513: _ -> - 514: file:delete(F), - 515: del_files(Dir,Fs) - 516: end; - 517: del_files(_,[]) -> - 518: ok. - 519: - 520: get_ts_name(Attributes) -> - 521: {_,name,_,_,_,_,_,_,Name,_} = lists:keyfind(name, 2, Attributes), - 522: list_to_atom(Name). + 484: %% Using the expected events' last test_stats element to produce the + 485: %% expected number of totla, errors, failed and skipped testcases. + 486: events_to_numbers(E) -> + 487: RevE = lists:reverse(E), + 488: {?eh,test_stats,{Ok,F,{US,AS}}} = lists:keyfind(test_stats,2,RevE), + 489: {Ok+F+US+AS,F,US+AS}. + 490: + 491: get_numbers_from_attrs([#xmlAttribute{name=tests,value=X}|A],false,E,F,S) -> + 492: get_numbers_from_attrs(A,list_to_integer(X),E,F,S); + 493: get_numbers_from_attrs([#xmlAttribute{name=errors,value=X}|A],T,false,F,S) -> + 494: get_numbers_from_attrs(A,T,list_to_integer(X),F,S); + 495: get_numbers_from_attrs([#xmlAttribute{name=failures,value=X}|A],T,E,false,S) -> + 496: get_numbers_from_attrs(A,T,E,list_to_integer(X),S); + 497: get_numbers_from_attrs([#xmlAttribute{name=skipped,value=X}|A],T,E,F,false) -> + 498: get_numbers_from_attrs(A,T,E,F,list_to_integer(X)); + 499: get_numbers_from_attrs([_|A],T,E,F,S) -> + 500: get_numbers_from_attrs(A,T,E,F,S); + 501: get_numbers_from_attrs([],T,E,F,S) -> + 502: {T,E,F,S}. + 503: + 504: ensure_exists_empty(Dir) -> + 505: case file:list_dir(Dir) of + 506: {error,enoent} -> + 507: file:make_dir(Dir); + 508: {ok,Files} -> + 509: del_files(Dir,Files) + 510: end. + 511: + 512: del_files(Dir,[F0|Fs] ) -> + 513: F = filename:join(Dir,F0), + 514: case file:read_file_info(F) of + 515: {ok,#file_info{type=directory}} -> + 516: {ok,Files} = file:list_dir(F), + 517: del_files(F,Files), + 518: file:del_dir(F), + 519: del_files(Dir,Fs); + 520: _ -> + 521: file:delete(F), + 522: del_files(Dir,Fs) + 523: end; + 524: del_files(_,[]) -> + 525: ok. + 526: + 527: get_ts_name(Attributes) -> + 528: {_,name,_,_,_,_,_,_,Name,_} = lists:keyfind(name, 2, Attributes), + 529: list_to_atom(Name).
+

If release handling is used, exactly one system configuration file is to be used and that file is to be called sys.config.

The values in the .app file and the values in a system configuration file can be overridden directly from the command line:

% erl -ApplName Par1 Val1 ... ParN ValN

Example:

% erl -ch_app file '"testlog"'
-Erlang (BEAM) emulator version 5.2.3.6 [hipe] [threads:0]
+Erlang (BEAM) emulator version 5.2.3.6 [hipe] [threads:0]
 
-Eshell V5.2.3.6  (abort with ^G)
-1> application:start(ch_app).
+Eshell V5.2.3.6  (abort with ^G)
+1> application:start(ch_app).
 ok
-2> application:get_env(ch_app, file).
-{ok,"testlog"}

+2> application:get_env(ch_app, file). +{ok,"testlog"}

diff --git a/prs/9045/doc/system/appup_cookbook.html b/prs/9045/doc/system/appup_cookbook.html index 10a3d7a8fe1b..a4e4573b5b0b 100644 --- a/prs/9045/doc/system/appup_cookbook.html +++ b/prs/9045/doc/system/appup_cookbook.html @@ -130,10 +130,10 @@

When a functional module has been changed, for example, if a new function has been added or a bug has been corrected, simple code replacement is sufficient, -for example:

{"2",
- [{"1", [{load_module, m}]}],
- [{"1", [{load_module, m}]}]
-}.

+for example:

{"2",
+ [{"1", [{load_module, m}]}],
+ [{"1", [{load_module, m}]}]
+}.

@@ -152,10 +152,10 @@

A callback module is a functional module, and for code extensions simple code replacement is sufficient.

Example

When adding a function to ch3, as described in the example in -Release Handling, ch_app.appup looks as follows:

{"2",
- [{"1", [{load_module, ch3}]}],
- [{"1", [{load_module, ch3}]}]
-}.

OTP also supports changing the internal state of behaviour processes; see +Release Handling, ch_app.appup looks as follows:

{"2",
+ [{"1", [{load_module, ch3}]}],
+ [{"1", [{load_module, ch3}]}]
+}.

OTP also supports changing the internal state of behaviour processes; see Changing Internal State.

@@ -169,21 +169,21 @@

gen_server Behaviour. The internal state is a term Chs representing the available channels. Assume you want to add a counter N, which keeps track of the number of alloc requests so far. This means that the -format must be changed to {Chs,N}.

The .appup file can look as follows:

{"2",
- [{"1", [{update, ch3, {advanced, []}}]}],
- [{"1", [{update, ch3, {advanced, []}}]}]
-}.

The third element of the update instruction is a tuple {advanced,Extra}, +format must be changed to {Chs,N}.

The .appup file can look as follows:

{"2",
+ [{"1", [{update, ch3, {advanced, []}}]}],
+ [{"1", [{update, ch3, {advanced, []}}]}]
+}.

The third element of the update instruction is a tuple {advanced,Extra}, which says that the affected processes are to do a state transformation before loading the new version of the module. This is done by the processes calling the callback function code_change/3 (see gen_server in STDLIB). -The term Extra, in this case [], is passed as is to the function:

-module(ch3).
+The term Extra, in this case [], is passed as is to the function:

-module(ch3).
 ...
--export([code_change/3]).
+-export([code_change/3]).
 ...
-code_change({down, _Vsn}, {Chs, N}, _Extra) ->
-    {ok, Chs};
-code_change(_Vsn, Chs, _Extra) ->
-    {ok, {Chs, 0}}.

The first argument is {down,Vsn} if there is a downgrade, or Vsn if there is +code_change({down, _Vsn}, {Chs, N}, _Extra) -> + {ok, Chs}; +code_change(_Vsn, Chs, _Extra) -> + {ok, {Chs, 0}}.

The first argument is {down,Vsn} if there is a downgrade, or Vsn if there is a upgrade. The term Vsn is fetched from the 'original' version of the module, that is, the version you are upgrading from, or downgrading to.

The version is defined by the module attribute vsn, if any. There is no such attribute in ch3, so in this case the version is the checksum (a huge integer) @@ -200,29 +200,29 @@

can occur during release upgrade if the new version of m1 is loaded first and calls ch3:available/0 before the new version of ch3 is loaded.

Thus, ch3 must be loaded before m1, in the upgrade case, and conversely in the downgrade case. m1 is said to be dependent on ch3. In a release -handling instruction, this is expressed by the DepMods element:

{load_module, Module, DepMods}
-{update, Module, {advanced, Extra}, DepMods}

DepMods is a list of modules, on which Module is dependent.

Example

The module m1 in application myapp is dependent on ch3 when +handling instruction, this is expressed by the DepMods element:

{load_module, Module, DepMods}
+{update, Module, {advanced, Extra}, DepMods}

DepMods is a list of modules, on which Module is dependent.

Example

The module m1 in application myapp is dependent on ch3 when upgrading from "1" to "2", or downgrading from "2" to "1":

myapp.appup:
 
-{"2",
- [{"1", [{load_module, m1, [ch3]}]}],
- [{"1", [{load_module, m1, [ch3]}]}]
-}.
+{"2",
+ [{"1", [{load_module, m1, [ch3]}]}],
+ [{"1", [{load_module, m1, [ch3]}]}]
+}.
 
 ch_app.appup:
 
-{"2",
- [{"1", [{load_module, ch3}]}],
- [{"1", [{load_module, ch3}]}]
-}.

If instead m1 and ch3 belong to the same application, the .appup file can -look as follows:

{"2",
- [{"1",
-   [{load_module, ch3},
-    {load_module, m1, [ch3]}]}],
- [{"1",
-   [{load_module, ch3},
-    {load_module, m1, [ch3]}]}]
-}.

m1 is dependent on ch3 also when downgrading. systools knows the +{"2", + [{"1", [{load_module, ch3}]}], + [{"1", [{load_module, ch3}]}] +}.

If instead m1 and ch3 belong to the same application, the .appup file can +look as follows:

{"2",
+ [{"1",
+   [{load_module, ch3},
+    {load_module, m1, [ch3]}]}],
+ [{"1",
+   [{load_module, ch3},
+    {load_module, m1, [ch3]}]}]
+}.

m1 is dependent on ch3 also when downgrading. systools knows the difference between up- and downgrading and generates a correct relup, where ch3 is loaded before m1 when upgrading, but m1 is loaded before ch3 when downgrading.

@@ -237,22 +237,22 @@

synchronized code replacement must be used.

Note

The name(s) of the user-defined residence module(s) must be listed in the Modules part of the child specification for the special process. Otherwise the release handler cannot find the process.

Example

Consider the example ch4 in sys and proc_lib. -When started by a supervisor, the child specification can look as follows:

{ch4, {ch4, start_link, []},
- permanent, brutal_kill, worker, [ch4]}

If ch4 is part of the application sp_app and a new version of the module is +When started by a supervisor, the child specification can look as follows:

{ch4, {ch4, start_link, []},
+ permanent, brutal_kill, worker, [ch4]}

If ch4 is part of the application sp_app and a new version of the module is to be loaded when upgrading from version "1" to "2" of this application, -sp_app.appup can look as follows:

{"2",
- [{"1", [{update, ch4, {advanced, []}}]}],
- [{"1", [{update, ch4, {advanced, []}}]}]
-}.

The update instruction must contain the tuple {advanced,Extra}. The +sp_app.appup can look as follows:

{"2",
+ [{"1", [{update, ch4, {advanced, []}}]}],
+ [{"1", [{update, ch4, {advanced, []}}]}]
+}.

The update instruction must contain the tuple {advanced,Extra}. The instruction makes the special process call the callback function system_code_change/4, a function the user must implement. The term Extra, in -this case [], is passed as is to system_code_change/4:

-module(ch4).
+this case [], is passed as is to system_code_change/4:

-module(ch4).
 ...
--export([system_code_change/4]).
+-export([system_code_change/4]).
 ...
 
-system_code_change(Chs, _Module, _OldVsn, _Extra) ->
-    {ok, Chs}.
  • The first argument is the internal state State, passed from +system_code_change(Chs, _Module, _OldVsn, _Extra) -> + {ok, Chs}.
  • The first argument is the internal state State, passed from function sys:handle_system_msg(Request, From, Parent, Module, Deb, State), and called by the special process when a system message is received. In ch4, the internal state is the set of available channels Chs.
  • The second argument is the name of the module (ch4).
  • The third argument is Vsn or {down,Vsn}, as described for @@ -281,24 +281,24 @@

    of upgrade and downgrade. Then the new return value of init/1 can be checked and the internal state be changed accordingly.

    The following upgrade instruction is used for supervisors:

    {update, Module, supervisor}

    Example

    To change the restart strategy of ch_sup (from Supervisor Behaviour) from one_for_one to one_for_all, -change the callback function init/1 in ch_sup.erl:

    -module(ch_sup).
    +change the callback function init/1 in ch_sup.erl:

    -module(ch_sup).
     ...
     
    -init(_Args) ->
    -    {ok, {#{strategy => one_for_all, ...}, ...}}.

    The file ch_app.appup:

    {"2",
    - [{"1", [{update, ch_sup, supervisor}]}],
    - [{"1", [{update, ch_sup, supervisor}]}]
    -}.

    +init(_Args) -> + {ok, {#{strategy => one_for_all, ...}, ...}}.

    The file ch_app.appup:

    {"2",
    + [{"1", [{update, ch_sup, supervisor}]}],
    + [{"1", [{update, ch_sup, supervisor}]}]
    +}.

    Changing Child Specifications

    The instruction, and thus the .appup file, when changing an existing child -specification, is the same as when changing properties as described earlier:

    {"2",
    - [{"1", [{update, ch_sup, supervisor}]}],
    - [{"1", [{update, ch_sup, supervisor}]}]
    -}.

    The changes do not affect existing child processes. For example, changing the +specification, is the same as when changing properties as described earlier:

    {"2",
    + [{"1", [{update, ch_sup, supervisor}]}],
    + [{"1", [{update, ch_sup, supervisor}]}]
    +}.

    The changes do not affect existing child processes. For example, changing the start function only specifies how the child process is to be restarted, if needed later on.

    The id of the child specification cannot be changed.

    Changing the Modules field of the child specification can affect the release handling process itself, as this field is used to identify which processes are @@ -313,34 +313,34 @@

    Child processes are not automatically started or terminated, this must be done using apply instructions.

    Example

    Assume a new child process m1 is to be added to ch_sup when upgrading ch_app from "1" to "2". This means m1 is to be deleted when -downgrading from "2" to "1":

    {"2",
    - [{"1",
    -   [{update, ch_sup, supervisor},
    -    {apply, {supervisor, restart_child, [ch_sup, m1]}}
    -   ]}],
    - [{"1",
    -   [{apply, {supervisor, terminate_child, [ch_sup, m1]}},
    -    {apply, {supervisor, delete_child, [ch_sup, m1]}},
    -    {update, ch_sup, supervisor}
    -   ]}]
    -}.

    The order of the instructions is important.

    The supervisor must be registered as ch_sup for the script to work. If the +downgrading from "2" to "1":

    {"2",
    + [{"1",
    +   [{update, ch_sup, supervisor},
    +    {apply, {supervisor, restart_child, [ch_sup, m1]}}
    +   ]}],
    + [{"1",
    +   [{apply, {supervisor, terminate_child, [ch_sup, m1]}},
    +    {apply, {supervisor, delete_child, [ch_sup, m1]}},
    +    {update, ch_sup, supervisor}
    +   ]}]
    +}.

    The order of the instructions is important.

    The supervisor must be registered as ch_sup for the script to work. If the supervisor is not registered, it cannot be accessed directly from the script. Instead a help function that finds the pid of the supervisor and calls supervisor:restart_child, and so on, must be written. This function is then to be called from the script using the apply instruction.

    If the module m1 is introduced in version "2" of ch_app, it must also be -loaded when upgrading and deleted when downgrading:

    {"2",
    - [{"1",
    -   [{add_module, m1},
    -    {update, ch_sup, supervisor},
    -    {apply, {supervisor, restart_child, [ch_sup, m1]}}
    -   ]}],
    - [{"1",
    -   [{apply, {supervisor, terminate_child, [ch_sup, m1]}},
    -    {apply, {supervisor, delete_child, [ch_sup, m1]}},
    -    {update, ch_sup, supervisor},
    -    {delete_module, m1}
    -   ]}]
    -}.

    As stated earlier, the order of the instructions is important. When upgrading, +loaded when upgrading and deleted when downgrading:

    {"2",
    + [{"1",
    +   [{add_module, m1},
    +    {update, ch_sup, supervisor},
    +    {apply, {supervisor, restart_child, [ch_sup, m1]}}
    +   ]}],
    + [{"1",
    +   [{apply, {supervisor, terminate_child, [ch_sup, m1]}},
    +    {apply, {supervisor, delete_child, [ch_sup, m1]}},
    +    {update, ch_sup, supervisor},
    +    {delete_module, m1}
    +   ]}]
    +}.

    As stated earlier, the order of the instructions is important. When upgrading, m1 must be loaded, and the supervisor child specification changed, before the new child process can be started. When downgrading, the child process must be terminated before the child specification is changed and the module is deleted.

    @@ -349,9 +349,9 @@

    Adding or Deleting a Module

    -

    _Example

    _ A new functional module m is added to ch_app:

    {"2",
    - [{"1", [{add_module, m}]}],
    - [{"1", [{delete_module, m}]}]

    +

    _Example

    _ A new functional module m is added to ch_app:

    {"2",
    + [{"1", [{add_module, m}]}],
    + [{"1", [{delete_module, m}]}]

    @@ -379,10 +379,10 @@

    been restructured.

    Example

    When adding a child m1 to ch_sup, as in Adding and Deleting Child Processes in Changing a Supervisor, an alternative to updating the supervisor is to restart the entire -application:

    {"2",
    - [{"1", [{restart_application, ch_app}]}],
    - [{"1", [{restart_application, ch_app}]}]
    -}.

    +application:

    {"2",
    + [{"1", [{restart_application, ch_app}]}],
    + [{"1", [{restart_application, ch_app}]}]
    +}.

    @@ -390,10 +390,10 @@

    When installing a release, the application specifications are automatically updated before evaluating the relup script. Thus, no instructions are needed -in the .appup file:

    {"2",
    - [{"1", []}],
    - [{"1", []}]
    -}.

    +in the .appup file:

    {"2",
    + [{"1", []}],
    + [{"1", []}]
    +}.

    @@ -416,18 +416,18 @@

    manually created.

    Example

    Assume there is a release containing an application prim_app, which have a supervisor prim_sup in its supervision tree.

    In a new version of the release, the application ch_app is to be included in prim_app. That is, its topmost supervisor ch_sup is to be started as a child -process to prim_sup.

    The workflow is as follows:

    Step 1) Edit the code for prim_sup:

    init(...) ->
    -    {ok, {...supervisor flags...,
    -          [...,
    -           {ch_sup, {ch_sup,start_link,[]},
    -            permanent,infinity,supervisor,[ch_sup]},
    -           ...]}}.

    Step 2) Edit the .app file for prim_app:

    {application, prim_app,
    - [...,
    -  {vsn, "2"},
    +process to prim_sup.

    The workflow is as follows:

    Step 1) Edit the code for prim_sup:

    init(...) ->
    +    {ok, {...supervisor flags...,
    +          [...,
    +           {ch_sup, {ch_sup,start_link,[]},
    +            permanent,infinity,supervisor,[ch_sup]},
    +           ...]}}.

    Step 2) Edit the .app file for prim_app:

    {application, prim_app,
    + [...,
    +  {vsn, "2"},
       ...,
    -  {included_applications, [ch_app]},
    +  {included_applications, [ch_app]},
       ...
    - ]}.

    Step 3) Create a new .rel file, including ch_app:

    {release,
    + ]}.

    Step 3) Create a new .rel file, including ch_app:

    {release,
      ...,
      [...,
       {prim_app, "2"},
    @@ -446,38 +446,38 @@ 

    the case of downgrade). This is because ch_app is included in the new .rel file, but not in the old one.

    Instead, a correct relup file can be created manually, either from scratch or by editing the generated version. The instructions for starting/stopping -ch_app are replaced by instructions for loading/unloading the application:

    {"B",
    - [{"A",
    -   [],
    -   [{load_object_code,{ch_app,"1",[ch_sup,ch3]}},
    -    {load_object_code,{prim_app,"2",[prim_app,prim_sup]}},
    +ch_app are replaced by instructions for loading/unloading the application:

    {"B",
    + [{"A",
    +   [],
    +   [{load_object_code,{ch_app,"1",[ch_sup,ch3]}},
    +    {load_object_code,{prim_app,"2",[prim_app,prim_sup]}},
         point_of_no_return,
    -    {apply,{application,stop,[prim_app]}},
    -    {remove,{prim_app,brutal_purge,brutal_purge}},
    -    {remove,{prim_sup,brutal_purge,brutal_purge}},
    -    {purge,[prim_app,prim_sup]},
    -    {load,{prim_app,brutal_purge,brutal_purge}},
    -    {load,{prim_sup,brutal_purge,brutal_purge}},
    -    {load,{ch_sup,brutal_purge,brutal_purge}},
    -    {load,{ch3,brutal_purge,brutal_purge}},
    -    {apply,{application,load,[ch_app]}},
    -    {apply,{application,start,[prim_app,permanent]}}]}],
    - [{"A",
    -   [],
    -   [{load_object_code,{prim_app,"1",[prim_app,prim_sup]}},
    +    {apply,{application,stop,[prim_app]}},
    +    {remove,{prim_app,brutal_purge,brutal_purge}},
    +    {remove,{prim_sup,brutal_purge,brutal_purge}},
    +    {purge,[prim_app,prim_sup]},
    +    {load,{prim_app,brutal_purge,brutal_purge}},
    +    {load,{prim_sup,brutal_purge,brutal_purge}},
    +    {load,{ch_sup,brutal_purge,brutal_purge}},
    +    {load,{ch3,brutal_purge,brutal_purge}},
    +    {apply,{application,load,[ch_app]}},
    +    {apply,{application,start,[prim_app,permanent]}}]}],
    + [{"A",
    +   [],
    +   [{load_object_code,{prim_app,"1",[prim_app,prim_sup]}},
         point_of_no_return,
    -    {apply,{application,stop,[prim_app]}},
    -    {apply,{application,unload,[ch_app]}},
    -    {remove,{ch_sup,brutal_purge,brutal_purge}},
    -    {remove,{ch3,brutal_purge,brutal_purge}},
    -    {purge,[ch_sup,ch3]},
    -    {remove,{prim_app,brutal_purge,brutal_purge}},
    -    {remove,{prim_sup,brutal_purge,brutal_purge}},
    -    {purge,[prim_app,prim_sup]},
    -    {load,{prim_app,brutal_purge,brutal_purge}},
    -    {load,{prim_sup,brutal_purge,brutal_purge}},
    -    {apply,{application,start,[prim_app,permanent]}}]}]
    -}.

    + {apply,{application,stop,[prim_app]}}, + {apply,{application,unload,[ch_app]}}, + {remove,{ch_sup,brutal_purge,brutal_purge}}, + {remove,{ch3,brutal_purge,brutal_purge}}, + {purge,[ch_sup,ch3]}, + {remove,{prim_app,brutal_purge,brutal_purge}}, + {remove,{prim_sup,brutal_purge,brutal_purge}}, + {purge,[prim_app,prim_sup]}, + {load,{prim_app,brutal_purge,brutal_purge}}, + {load,{prim_sup,brutal_purge,brutal_purge}}, + {apply,{application,start,[prim_app,permanent]}}]}] +}.

    @@ -490,35 +490,35 @@

    generated version. Load all code for ch_app first, and also load the application specification, before prim_sup is updated. When downgrading, prim_sup is to updated first, before the code for ch_app and its application -specification are unloaded.

    {"B",
    - [{"A",
    -   [],
    -   [{load_object_code,{ch_app,"1",[ch_sup,ch3]}},
    -    {load_object_code,{prim_app,"2",[prim_sup]}},
    +specification are unloaded.

    {"B",
    + [{"A",
    +   [],
    +   [{load_object_code,{ch_app,"1",[ch_sup,ch3]}},
    +    {load_object_code,{prim_app,"2",[prim_sup]}},
         point_of_no_return,
    -    {load,{ch_sup,brutal_purge,brutal_purge}},
    -    {load,{ch3,brutal_purge,brutal_purge}},
    -    {apply,{application,load,[ch_app]}},
    -    {suspend,[prim_sup]},
    -    {load,{prim_sup,brutal_purge,brutal_purge}},
    -    {code_change,up,[{prim_sup,[]}]},
    -    {resume,[prim_sup]},
    -    {apply,{supervisor,restart_child,[prim_sup,ch_sup]}}]}],
    - [{"A",
    -   [],
    -   [{load_object_code,{prim_app,"1",[prim_sup]}},
    +    {load,{ch_sup,brutal_purge,brutal_purge}},
    +    {load,{ch3,brutal_purge,brutal_purge}},
    +    {apply,{application,load,[ch_app]}},
    +    {suspend,[prim_sup]},
    +    {load,{prim_sup,brutal_purge,brutal_purge}},
    +    {code_change,up,[{prim_sup,[]}]},
    +    {resume,[prim_sup]},
    +    {apply,{supervisor,restart_child,[prim_sup,ch_sup]}}]}],
    + [{"A",
    +   [],
    +   [{load_object_code,{prim_app,"1",[prim_sup]}},
         point_of_no_return,
    -    {apply,{supervisor,terminate_child,[prim_sup,ch_sup]}},
    -    {apply,{supervisor,delete_child,[prim_sup,ch_sup]}},
    -    {suspend,[prim_sup]},
    -    {load,{prim_sup,brutal_purge,brutal_purge}},
    -    {code_change,down,[{prim_sup,[]}]},
    -    {resume,[prim_sup]},
    -    {remove,{ch_sup,brutal_purge,brutal_purge}},
    -    {remove,{ch3,brutal_purge,brutal_purge}},
    -    {purge,[ch_sup,ch3]},
    -    {apply,{application,unload,[ch_app]}}]}]
    -}.

    + {apply,{supervisor,terminate_child,[prim_sup,ch_sup]}}, + {apply,{supervisor,delete_child,[prim_sup,ch_sup]}}, + {suspend,[prim_sup]}, + {load,{prim_sup,brutal_purge,brutal_purge}}, + {code_change,down,[{prim_sup,[]}]}, + {resume,[prim_sup]}, + {remove,{ch_sup,brutal_purge,brutal_purge}}, + {remove,{ch3,brutal_purge,brutal_purge}}, + {purge,[ch_sup,ch3]}, + {apply,{application,unload,[ch_app]}}]}] +}.

    @@ -528,28 +528,28 @@

    for example, a port program, is application-dependent and OTP provides no special support.

    Example

    When changing code for a port program, assume that the Erlang process controlling the port is a gen_server portc and that the port is opened in -the callback function init/1:

    init(...) ->
    +the callback function init/1:

    init(...) ->
         ...,
    -    PortPrg = filename:join(code:priv_dir(App), "portc"),
    -    Port = open_port({spawn,PortPrg}, [...]),
    +    PortPrg = filename:join(code:priv_dir(App), "portc"),
    +    Port = open_port({spawn,PortPrg}, [...]),
         ...,
    -    {ok, #state{port=Port, ...}}.

    If the port program is to be updated, the code for the gen_server can be + {ok, #state{port=Port, ...}}.

    If the port program is to be updated, the code for the gen_server can be extended with a code_change/3 function, which closes the old port and opens a new port. (If necessary, the gen_server can first request data that must be -saved from the port program and pass this data to the new port):

    code_change(_OldVsn, State, port) ->
    +saved from the port program and pass this data to the new port):

    code_change(_OldVsn, State, port) ->
         State#state.port ! close,
         receive
    -        {Port,close} ->
    +        {Port,close} ->
                 true
         end,
    -    PortPrg = filename:join(code:priv_dir(App), "portc"),
    -    Port = open_port({spawn,PortPrg}, [...]),
    -    {ok, #state{port=Port, ...}}.

    Update the application version number in the .app file and write an .appup -file:

    ["2",
    - [{"1", [{update, portc, {advanced,port}}]}],
    - [{"1", [{update, portc, {advanced,port}}]}]
    -].

    Ensure that the priv directory, where the C program is located, is included in -the new release package:

    1> systools:make_tar("my_release", [{dirs,[priv]}]).
    +    PortPrg = filename:join(code:priv_dir(App), "portc"),
    +    Port = open_port({spawn,PortPrg}, [...]),
    +    {ok, #state{port=Port, ...}}.

    Update the application version number in the .app file and write an .appup +file:

    ["2",
    + [{"1", [{update, portc, {advanced,port}}]}],
    + [{"1", [{update, portc, {advanced,port}}]}]
    +].

    Ensure that the priv directory, where the C program is located, is included in +the new release package:

    1> systools:make_tar("my_release", [{dirs,[priv]}]).
     ...

    @@ -565,14 +565,14 @@

    restart_emulator (Low-Level) in Release Handling Instructions.

If a runtime system restart is necessary and no upgrade instructions are needed, that is, if the restart itself is enough for the upgraded applications to start -running the new versions, a simple .relup file can be created manually:

{"B",
- [{"A",
-   [],
-   [restart_emulator]}],
- [{"A",
-   [],
-   [restart_emulator]}]
-}.

In this case, the release handler framework with automatic packing and unpacking +running the new versions, a simple .relup file can be created manually:

{"B",
+ [{"A",
+   [],
+   [restart_emulator]}],
+ [{"A",
+   [],
+   [restart_emulator]}]
+}.

In this case, the release handler framework with automatic packing and unpacking of release packages, automatic path updates, and so on, can be used without having to specify .appup files.

diff --git a/prs/9045/doc/system/benchmarking.html b/prs/9045/doc/system/benchmarking.html index d1615940d536..003174ef1c28 100644 --- a/prs/9045/doc/system/benchmarking.html +++ b/prs/9045/doc/system/benchmarking.html @@ -154,8 +154,8 @@

crypto:strong_rand_bytes(100). 1 1915 Ki 522 ns 90%

rand:bytes/1 is still faster when we generate 100 bytes at the time, but the relative difference is smaller.

% erlperf 'rand:bytes(1000).' 'crypto:strong_rand_bytes(1000).'
 Code                                    ||        QPS       Time   Rel
-crypto:strong_rand_bytes(1000).          1    1518 Ki     658 ns  100%
-rand:bytes(1000).                        1     284 Ki    3521 ns   19%

When we generate 1000 bytes at the time, crypto:strong_rand_bytes/1 is +crypto:strong_rand_bytes(1000). 1 1518 Ki 658 ns 100% +rand:bytes(1000). 1 284 Ki 3521 ns 19%

When we generate 1000 bytes at the time, crypto:strong_rand_bytes/1 is now the fastest.

diff --git a/prs/9045/doc/system/binaryhandling.html b/prs/9045/doc/system/binaryhandling.html index fb65e375cab5..a08b55bb23ac 100644 --- a/prs/9045/doc/system/binaryhandling.html +++ b/prs/9045/doc/system/binaryhandling.html @@ -124,35 +124,35 @@

This section gives a few examples on how to handle binaries in an efficient way. The sections that follow take an in-depth look at how binaries are implemented and how to best take advantages of the optimizations done by the compiler and -runtime system.

Binaries can be efficiently built in the following way:

DO

my_list_to_binary(List) ->
-    my_list_to_binary(List, <<>>).
+runtime system.

Binaries can be efficiently built in the following way:

DO

my_list_to_binary(List) ->
+    my_list_to_binary(List, <<>>).
 
-my_list_to_binary([H|T], Acc) ->
-    my_list_to_binary(T, <<Acc/binary,H>>);
-my_list_to_binary([], Acc) ->
+my_list_to_binary([H|T], Acc) ->
+    my_list_to_binary(T, <<Acc/binary,H>>);
+my_list_to_binary([], Acc) ->
     Acc.

Appending data to a binary as in the example is efficient because it is specially optimized by the runtime system to avoid copying the Acc binary -every time.

Prepending data to a binary in a loop is not efficient:

DO NOT

rev_list_to_binary(List) ->
-    rev_list_to_binary(List, <<>>).
+every time.

Prepending data to a binary in a loop is not efficient:

DO NOT

rev_list_to_binary(List) ->
+    rev_list_to_binary(List, <<>>).
 
-rev_list_to_binary([H|T], Acc) ->
-    rev_list_to_binary(T, <<H,Acc/binary>>);
-rev_list_to_binary([], Acc) ->
+rev_list_to_binary([H|T], Acc) ->
+    rev_list_to_binary(T, <<H,Acc/binary>>);
+rev_list_to_binary([], Acc) ->
     Acc.

This is not efficient for long lists because the Acc binary is copied every -time. One way to make the function more efficient is like this:

DO NOT

rev_list_to_binary(List) ->
-    rev_list_to_binary(lists:reverse(List), <<>>).
-
-rev_list_to_binary([H|T], Acc) ->
-    rev_list_to_binary(T, <<Acc/binary,H>>);
-rev_list_to_binary([], Acc) ->
-    Acc.

Another way to avoid copying the binary each time is like this:

DO

rev_list_to_binary([H|T]) ->
-    RevTail = rev_list_to_binary(T),
+time. One way to make the function more efficient is like this:

DO NOT

rev_list_to_binary(List) ->
+    rev_list_to_binary(lists:reverse(List), <<>>).
+
+rev_list_to_binary([H|T], Acc) ->
+    rev_list_to_binary(T, <<Acc/binary,H>>);
+rev_list_to_binary([], Acc) ->
+    Acc.

Another way to avoid copying the binary each time is like this:

DO

rev_list_to_binary([H|T]) ->
+    RevTail = rev_list_to_binary(T),
     <<RevTail/binary,H>>;
-rev_list_to_binary([]) ->
+rev_list_to_binary([]) ->
     <<>>.

Note that in each of the DO examples, the binary to be appended to is always -given as the first segment.

Binaries can be efficiently matched in the following way:

DO

my_binary_to_list(<<H,T/binary>>) ->
-    [H|my_binary_to_list(T)];
-my_binary_to_list(<<>>) -> [].

+given as the first segment.

Binaries can be efficiently matched in the following way:

DO

my_binary_to_list(<<H,T/binary>>) ->
+    [H|my_binary_to_list(T)];
+my_binary_to_list(<<>>) -> [].

@@ -229,7 +229,7 @@

Bin2 = <<Bin1/binary,4,5,6>>, %% 3 Bin3 = <<Bin2/binary,7,8,9>>, %% 4 Bin4 = <<Bin1/binary,17>>, %% 5 !!! -{Bin4,Bin3} %% 6

  • Line 1 (marked with the %% 1 comment), assigns a +{Bin4,Bin3} %% 6

  • Line 1 (marked with the %% 1 comment), assigns a heap binary to the Bin0 variable.

  • Line 2 is an append operation. As Bin0 has not been involved in an append operation, a new refc binary is created and the contents of Bin0 is copied into it. The ProcBin part of the refc @@ -263,15 +263,15 @@

    for every append operation, the runtime system must create a sub binary.

    When the compiler can determine that none of those situations need to be handled and that the append operation cannot possibly fail, the compiler generates code that causes the runtime system to apply a more efficient variant of the -optimization.

    Example:

    -module(repack).
    --export([repack/1]).
    +optimization.

    Example:

    -module(repack).
    +-export([repack/1]).
     
    -repack(Bin) when is_binary(Bin) ->
    -    repack(Bin, <<>>).
    +repack(Bin) when is_binary(Bin) ->
    +    repack(Bin, <<>>).
     
    -repack(<<C:8,T/binary>>, Result) ->
    -    repack(T, <<Result/binary,C:16>>);
    -repack(<<>>, Result) ->
    +repack(<<C:8,T/binary>>, Result) ->
    +    repack(T, <<Result/binary,C:16>>);
    +repack(<<>>, Result) ->
         Result.

    The repack/2 function only keeps a single version of the binary, so there is never any need to copy the binary. The compiler rewrites the creation of the empty binary in repack/1 to instead create a refc binary with 256 bytes @@ -314,9 +314,9 @@

    Matching Binaries

    -

    Let us revisit the example in the beginning of the previous section:

    DO

    my_binary_to_list(<<H,T/binary>>) ->
    -    [H|my_binary_to_list(T)];
    -my_binary_to_list(<<>>) -> [].

    The first time my_binary_to_list/1 is called, a +

    Let us revisit the example in the beginning of the previous section:

    DO

    my_binary_to_list(<<H,T/binary>>) ->
    +    [H|my_binary_to_list(T)];
    +my_binary_to_list(<<>>) -> [].

    The first time my_binary_to_list/1 is called, a match context is created. The match context points to the first byte of the binary. 1 byte is matched out and the match context is updated to point to the second byte in the binary.

    At this point it would make sense to create a @@ -331,24 +331,24 @@

    there is no longer any reference to it).

    To summarize, my_binary_to_list/1 only needs to create one match context and no sub binaries.

    Notice that the match context in my_binary_to_list/1 was discarded when the entire binary had been traversed. What happens if the iteration stops before it -has reached the end of the binary? Will the optimization still work?

    after_zero(<<0,T/binary>>) ->
    +has reached the end of the binary? Will the optimization still work?

    after_zero(<<0,T/binary>>) ->
         T;
    -after_zero(<<_,T/binary>>) ->
    -    after_zero(T);
    -after_zero(<<>>) ->
    +after_zero(<<_,T/binary>>) ->
    +    after_zero(T);
    +after_zero(<<>>) ->
         <<>>.

    Yes, it will. The compiler will remove the building of the sub binary in the second clause:

    ...
    -after_zero(<<_,T/binary>>) ->
    -    after_zero(T);
    -...

    But it will generate code that builds a sub binary in the first clause:

    after_zero(<<0,T/binary>>) ->
    +after_zero(<<_,T/binary>>) ->
    +    after_zero(T);
    +...

    But it will generate code that builds a sub binary in the first clause:

    after_zero(<<0,T/binary>>) ->
         T;
     ...

    Therefore, after_zero/1 builds one match context and one sub binary (assuming -it is passed a binary that contains a zero byte).

    Code like the following will also be optimized:

    all_but_zeroes_to_list(Buffer, Acc, 0) ->
    -    {lists:reverse(Acc),Buffer};
    -all_but_zeroes_to_list(<<0,T/binary>>, Acc, Remaining) ->
    -    all_but_zeroes_to_list(T, Acc, Remaining-1);
    -all_but_zeroes_to_list(<<Byte,T/binary>>, Acc, Remaining) ->
    -    all_but_zeroes_to_list(T, [Byte|Acc], Remaining-1).

    The compiler removes building of sub binaries in the second and third clauses, +it is passed a binary that contains a zero byte).

    Code like the following will also be optimized:

    all_but_zeroes_to_list(Buffer, Acc, 0) ->
    +    {lists:reverse(Acc),Buffer};
    +all_but_zeroes_to_list(<<0,T/binary>>, Acc, Remaining) ->
    +    all_but_zeroes_to_list(T, Acc, Remaining-1);
    +all_but_zeroes_to_list(<<Byte,T/binary>>, Acc, Remaining) ->
    +    all_but_zeroes_to_list(T, [Byte|Acc], Remaining-1).

    The compiler removes building of sub binaries in the second and third clauses, and it adds an instruction to the first clause that converts Buffer from a match context to a sub binary (or do nothing if Buffer is a binary already).

    But in more complicated code, how can one know whether the optimization is applied or not?

    @@ -364,13 +364,13 @@

    practical approach.

    The warnings look as follows:

    ./efficiency_guide.erl:60: Warning: NOT OPTIMIZED: binary is returned from the function
     ./efficiency_guide.erl:62: Warning: OPTIMIZED: match context reused

    To make it clearer exactly what code the warnings refer to, the warnings in the following examples are inserted as comments after the clause they refer to, for -example:

    after_zero(<<0,T/binary>>) ->
    +example:

    after_zero(<<0,T/binary>>) ->
              %% BINARY CREATED: binary is returned from the function
         T;
    -after_zero(<<_,T/binary>>) ->
    +after_zero(<<_,T/binary>>) ->
              %% OPTIMIZED: match context reused
    -    after_zero(T);
    -after_zero(<<>>) ->
    +    after_zero(T);
    +after_zero(<<>>) ->
         <<>>.

    The warning for the first clause says that the creation of a sub binary cannot be delayed, because it will be returned. The warning for the second clause says that a sub binary will not be created (yet).

    @@ -380,14 +380,14 @@

    Unused Variables

    The compiler figures out if a variable is unused. The same code is generated for -each of the following functions:

    count1(<<_,T/binary>>, Count) -> count1(T, Count+1);
    -count1(<<>>, Count) -> Count.
    +each of the following functions:

    count1(<<_,T/binary>>, Count) -> count1(T, Count+1);
    +count1(<<>>, Count) -> Count.
     
    -count2(<<H,T/binary>>, Count) -> count2(T, Count+1);
    -count2(<<>>, Count) -> Count.
    +count2(<<H,T/binary>>, Count) -> count2(T, Count+1);
    +count2(<<>>, Count) -> Count.
     
    -count3(<<_H,T/binary>>, Count) -> count3(T, Count+1);
    -count3(<<>>, Count) -> Count.

    In each iteration, the first 8 bits in the binary will be skipped, not matched +count3(<<_H,T/binary>>, Count) -> count3(T, Count+1); +count3(<<>>, Count) -> Count.

    In each iteration, the first 8 bits in the binary will be skipped, not matched out.

diff --git a/prs/9045/doc/system/bit_syntax.html b/prs/9045/doc/system/bit_syntax.html index 348b87d1eee0..81957509d710 100644 --- a/prs/9045/doc/system/bit_syntax.html +++ b/prs/9045/doc/system/bit_syntax.html @@ -151,17 +151,17 @@

variables, and Bin2 is bound, as in Example 2:

<<D:16, E, F/binary>> = Bin2

This gives D = 273, E = 00, and F binds to a binary of size 1: binary_to_list(F) = [42].

Example 4: The following is a more elaborate example of matching. Here, Dgram is bound to the consecutive bytes of an IP datagram of IP protocol -version 4. The ambition is to extract the header and the data of the datagram:

-define(IP_VERSION, 4).
--define(IP_MIN_HDR_LEN, 5).
+version 4. The ambition is to extract the header and the data of the datagram:

-define(IP_VERSION, 4).
+-define(IP_MIN_HDR_LEN, 5).
 
-DgramSize = byte_size(Dgram),
+DgramSize = byte_size(Dgram),
 case Dgram of
     <<?IP_VERSION:4, HLen:4, SrvcType:8, TotLen:16,
       ID:16, Flgs:3, FragOff:13,
       TTL:8, Proto:8, HdrChkSum:16,
       SrcIP:32,
       DestIP:32, RestDgram/binary>> when HLen>=5, 4*HLen=<DgramSize ->
-        OptsLen = 4*(HLen - ?IP_MIN_HDR_LEN),
+        OptsLen = 4*(HLen - ?IP_MIN_HDR_LEN),
         <<Opts:OptsLen/binary,Data/binary>> = RestDgram,
     ...
 end.

Here, the segment corresponding to the Opts variable has a type modifier, @@ -239,7 +239,7 @@

However, for syntactical reasons, both Value and Size must be enclosed in parenthesis if the expression consists of anything more than a single literal or a variable. The following gives a compiler syntax error:

<<X+1:8>>

This expression must be rewritten into the following, to be accepted by the -compiler:

<<(X+1):8>>

+compiler:

<<(X+1):8>>

@@ -259,11 +259,11 @@

restrictions on the size. A segment of type float must have size 64 or 32.

As mentioned earlier, segments have the following general syntax:

Value:Size/TypeSpecifierList

When matching Value, value must be either a variable or an integer, or a floating point literal. Expressions are not allowed.

Size must be a guard expression, which can use -literals and previously bound variables. The following is not allowed:

foo(N, <<X:N,T/binary>>) ->
-   {X,T}.

The two occurrences of N are not related. The compiler will complain that the -N in the size field is unbound.

The correct way to write this example is as follows:

foo(N, Bin) ->
+literals and previously bound variables. The following is not allowed:

foo(N, <<X:N,T/binary>>) ->
+   {X,T}.

The two occurrences of N are not related. The compiler will complain that the +N in the size field is unbound.

The correct way to write this example is as follows:

foo(N, Bin) ->
    <<X:N,T/binary>> = Bin,
-   {X,T}.

Note

Before OTP 23, Size was restricted to be an integer or a variable bound to + {X,T}.

Note

Before OTP 23, Size was restricted to be an integer or a variable bound to an integer.

@@ -272,28 +272,28 @@

There is one exception to the rule that a variable that is used as size must be previously bound. It is possible to match and bind a variable, and use it as a -size within the same binary pattern. For example:

bar(<<Sz:8,Payload:Sz/binary-unit:8,Rest/binary>>) ->
-   {Payload,Rest}.

Here Sz is bound to the value in the first byte of the binary. Sz is then -used at the number of bytes to match out as a binary.

Starting in OTP 23, the size can be a guard expression:

bar(<<Sz:8,Payload:((Sz-1)*8)/binary,Rest/binary>>) ->
-   {Payload,Rest}.

Here Sz is the combined size of the header and the payload, so we will need to +size within the same binary pattern. For example:

bar(<<Sz:8,Payload:Sz/binary-unit:8,Rest/binary>>) ->
+   {Payload,Rest}.

Here Sz is bound to the value in the first byte of the binary. Sz is then +used at the number of bytes to match out as a binary.

Starting in OTP 23, the size can be a guard expression:

bar(<<Sz:8,Payload:((Sz-1)*8)/binary,Rest/binary>>) ->
+   {Payload,Rest}.

Here Sz is the combined size of the header and the payload, so we will need to subtract one byte to get the size of the payload.

Getting the Rest of the Binary or Bitstring

-

To match out the rest of a binary, specify a binary field without size:

foo(<<A:8,Rest/binary>>) ->

The size of the tail must be evenly divisible by 8.

To match out the rest of a bitstring, specify a field without size:

foo(<<A:8,Rest/bitstring>>) ->

There are no restrictions on the number of bits in the tail.

+

To match out the rest of a binary, specify a binary field without size:

foo(<<A:8,Rest/binary>>) ->

The size of the tail must be evenly divisible by 8.

To match out the rest of a bitstring, specify a field without size:

foo(<<A:8,Rest/bitstring>>) ->

There are no restrictions on the number of bits in the tail.

Appending to a Binary

-

Appending to a binary in an efficient way can be done as follows:

triples_to_bin(T) ->
-    triples_to_bin(T, <<>>).
+

Appending to a binary in an efficient way can be done as follows:

triples_to_bin(T) ->
+    triples_to_bin(T, <<>>).
 
-triples_to_bin([{X,Y,Z} | T], Acc) ->
-    triples_to_bin(T, <<Acc/binary,X:32,Y:32,Z:32>>);
-triples_to_bin([], Acc) ->
+triples_to_bin([{X,Y,Z} | T], Acc) ->
+    triples_to_bin(T, <<Acc/binary,X:32,Y:32,Z:32>>);
+triples_to_bin([], Acc) ->
     Acc.

diff --git a/prs/9045/doc/system/c_port.html b/prs/9045/doc/system/c_port.html index c66cc7872d4a..04b684a2d1e0 100644 --- a/prs/9045/doc/system/c_port.html +++ b/prs/9045/doc/system/c_port.html @@ -158,93 +158,93 @@

length indicator is to be used to simplify the communication between C and Erlang. The Erlang port automatically adds the length indicator, but this must be done explicitly in the external C program.

The process is also set to trap exits, which enables detection of failure of the -external program:

-module(complex1).
--export([start/1, init/1]).
-
-start(ExtPrg) ->
-  spawn(?MODULE, init, [ExtPrg]).
-
-init(ExtPrg) ->
-  register(complex, self()),
-  process_flag(trap_exit, true),
-  Port = open_port({spawn, ExtPrg}, [{packet, 2}]),
-  loop(Port).

Now complex1:foo/1 and complex1:bar/1 can be implemented. Both send a -message to the complex process and receive the following replies:

foo(X) ->
-  call_port({foo, X}).
-bar(Y) ->
-  call_port({bar, Y}).
-
-call_port(Msg) ->
-  complex ! {call, self(), Msg},
+external program:

-module(complex1).
+-export([start/1, init/1]).
+
+start(ExtPrg) ->
+  spawn(?MODULE, init, [ExtPrg]).
+
+init(ExtPrg) ->
+  register(complex, self()),
+  process_flag(trap_exit, true),
+  Port = open_port({spawn, ExtPrg}, [{packet, 2}]),
+  loop(Port).

Now complex1:foo/1 and complex1:bar/1 can be implemented. Both send a +message to the complex process and receive the following replies:

foo(X) ->
+  call_port({foo, X}).
+bar(Y) ->
+  call_port({bar, Y}).
+
+call_port(Msg) ->
+  complex ! {call, self(), Msg},
   receive
-    {complex, Result} ->
+    {complex, Result} ->
       Result
-  end.

The complex process does the following:

  • Encodes the message into a sequence of bytes.
  • Sends it to the port.
  • Waits for a reply.
  • Decodes the reply.
  • Sends it back to the caller:
loop(Port) ->
+  end.

The complex process does the following:

  • Encodes the message into a sequence of bytes.
  • Sends it to the port.
  • Waits for a reply.
  • Decodes the reply.
  • Sends it back to the caller:
loop(Port) ->
   receive
-    {call, Caller, Msg} ->
-      Port ! {self(), {command, encode(Msg)}},
+    {call, Caller, Msg} ->
+      Port ! {self(), {command, encode(Msg)}},
       receive
-        {Port, {data, Data}} ->
-          Caller ! {complex, decode(Data)}
+        {Port, {data, Data}} ->
+          Caller ! {complex, decode(Data)}
       end,
-      loop(Port)
+      loop(Port)
   end.

Assuming that both the arguments and the results from the C functions are less than 256, a simple encoding/decoding scheme is employed. In this scheme, foo is represented by byte 1, bar is represented by 2, and the argument/result is -represented by a single byte as well:

encode({foo, X}) -> [1, X];
-encode({bar, Y}) -> [2, Y].
+represented by a single byte as well:

encode({foo, X}) -> [1, X];
+encode({bar, Y}) -> [2, Y].
 
-decode([Int]) -> Int.

The resulting Erlang program, including functionality for stopping the port and -detecting port failures, is as follows:

-module(complex1).
--export([start/1, stop/0, init/1]).
--export([foo/1, bar/1]).
+decode([Int]) -> Int.

The resulting Erlang program, including functionality for stopping the port and +detecting port failures, is as follows:

-module(complex1).
+-export([start/1, stop/0, init/1]).
+-export([foo/1, bar/1]).
 
-start(ExtPrg) ->
-    spawn(?MODULE, init, [ExtPrg]).
-stop() ->
+start(ExtPrg) ->
+    spawn(?MODULE, init, [ExtPrg]).
+stop() ->
     complex ! stop.
 
-foo(X) ->
-    call_port({foo, X}).
-bar(Y) ->
-    call_port({bar, Y}).
+foo(X) ->
+    call_port({foo, X}).
+bar(Y) ->
+    call_port({bar, Y}).
 
-call_port(Msg) ->
-    complex ! {call, self(), Msg},
+call_port(Msg) ->
+    complex ! {call, self(), Msg},
     receive
-	{complex, Result} ->
+	{complex, Result} ->
 	    Result
     end.
 
-init(ExtPrg) ->
-    register(complex, self()),
-    process_flag(trap_exit, true),
-    Port = open_port({spawn, ExtPrg}, [{packet, 2}]),
-    loop(Port).
+init(ExtPrg) ->
+    register(complex, self()),
+    process_flag(trap_exit, true),
+    Port = open_port({spawn, ExtPrg}, [{packet, 2}]),
+    loop(Port).
 
-loop(Port) ->
+loop(Port) ->
     receive
-	{call, Caller, Msg} ->
-	    Port ! {self(), {command, encode(Msg)}},
+	{call, Caller, Msg} ->
+	    Port ! {self(), {command, encode(Msg)}},
 	    receive
-		{Port, {data, Data}} ->
-		    Caller ! {complex, decode(Data)}
+		{Port, {data, Data}} ->
+		    Caller ! {complex, decode(Data)}
 	    end,
-	    loop(Port);
+	    loop(Port);
 	stop ->
-	    Port ! {self(), close},
+	    Port ! {self(), close},
 	    receive
-		{Port, closed} ->
-		    exit(normal)
+		{Port, closed} ->
+		    exit(normal)
 	    end;
-	{'EXIT', Port, Reason} ->
-	    exit(port_terminated)
+	{'EXIT', Port, Reason} ->
+	    exit(port_terminated)
     end.
 
-encode({foo, X}) -> [1, X];
-encode({bar, Y}) -> [2, Y].
+encode({foo, X}) -> [1, X];
+encode({bar, Y}) -> [2, Y].
 
-decode([Int]) -> Int.

+decode([Int]) -> Int.

@@ -261,55 +261,55 @@

typedef unsigned char byte; -int read_exact(byte *buf, int len) -{ +int read_exact(byte *buf, int len) +{ int i, got=0; - do { - if ((i = read(0, buf+got, len-got)) <= 0){ - return(i); - } + do { + if ((i = read(0, buf+got, len-got)) <= 0){ + return(i); + } got += i; - } while (got<len); + } while (got<len); - return(len); -} + return(len); +} -int write_exact(byte *buf, int len) -{ +int write_exact(byte *buf, int len) +{ int i, wrote = 0; - do { - if ((i = write(1, buf+wrote, len-wrote)) <= 0) - return (i); + do { + if ((i = write(1, buf+wrote, len-wrote)) <= 0) + return (i); wrote += i; - } while (wrote<len); + } while (wrote<len); - return (len); -} + return (len); +} -int read_cmd(byte *buf) -{ +int read_cmd(byte *buf) +{ int len; - if (read_exact(buf, 2) != 2) - return(-1); - len = (buf[0] << 8) | buf[1]; - return read_exact(buf, len); -} + if (read_exact(buf, 2) != 2) + return(-1); + len = (buf[0] << 8) | buf[1]; + return read_exact(buf, len); +} -int write_cmd(byte *buf, int len) -{ +int write_cmd(byte *buf, int len) +{ byte li; - li = (len >> 8) & 0xff; - write_exact(&li, 1); + li = (len >> 8) & 0xff; + write_exact(&li, 1); li = len & 0xff; - write_exact(&li, 1); + write_exact(&li, 1); - return write_exact(buf, len); -}

Notice that stdin and stdout are for buffered input/output and must not be + return write_exact(buf, len); +}

Notice that stdin and stdout are for buffered input/output and must not be used for the communication with Erlang.

In the main function, the C program is to listen for a message from Erlang and, according to the selected encoding/decoding scheme, use the first byte to determine which function to call and the second byte as argument to the @@ -317,24 +317,24 @@

typedef unsigned char byte; -int main() { +int main() { int fn, arg, res; - byte buf[100]; - - while (read_cmd(buf) > 0) { - fn = buf[0]; - arg = buf[1]; - - if (fn == 1) { - res = foo(arg); - } else if (fn == 2) { - res = bar(arg); - } - - buf[0] = res; - write_cmd(buf, 1); - } -}

Notice that the C program is in a while-loop, checking for the return value + byte buf[100]; + + while (read_cmd(buf) > 0) { + fn = buf[0]; + arg = buf[1]; + + if (fn == 1) { + res = foo(arg); + } else if (fn == 2) { + res = bar(arg); + } + + buf[0] = res; + write_cmd(buf, 1); + } +}

Notice that the C program is in a while-loop, checking for the return value of read_cmd/1. This is because the C program must detect when the port closes and terminates.

@@ -343,17 +343,17 @@

Running the Example

Step 1. Compile the C code:

$ gcc -o extprg complex.c erl_comm.c port.c

Step 2. Start Erlang and compile the Erlang code:

$ erl
-Erlang/OTP 26 [erts-14.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]
+Erlang/OTP 26 [erts-14.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]
 
-Eshell V14.2 (press Ctrl+G to abort, type help(). for help)
-1> c(complex1).
-{ok,complex1}

Step 3. Run the example:

2> complex1:start("./extprg").
+Eshell V14.2 (press Ctrl+G to abort, type help(). for help)
+1> c(complex1).
+{ok,complex1}

Step 3. Run the example:

2> complex1:start("./extprg").
 <0.34.0>
-3> complex1:foo(3).
+3> complex1:foo(3).
 4
-4> complex1:bar(5).
+4> complex1:bar(5).
 10
-5> complex1:stop().
+5> complex1:stop().
 stop

diff --git a/prs/9045/doc/system/c_portdriver.html b/prs/9045/doc/system/c_portdriver.html index 0edafb50a747..5567204c8af9 100644 --- a/prs/9045/doc/system/c_portdriver.html +++ b/prs/9045/doc/system/c_portdriver.html @@ -161,104 +161,104 @@

argument.

The port is then created using the BIF open_port/2, with the tuple {spawn, DriverName} as the first argument. The string SharedLib is the name of the port driver. The second argument is a list of options, none in this -case:

-module(complex5).
--export([start/1, init/1]).
+case:

-module(complex5).
+-export([start/1, init/1]).
 
-start(SharedLib) ->
-    case erl_ddll:load_driver(".", SharedLib) of
+start(SharedLib) ->
+    case erl_ddll:load_driver(".", SharedLib) of
         ok -> ok;
-        {error, already_loaded} -> ok;
-        _ -> exit({error, could_not_load_driver})
+        {error, already_loaded} -> ok;
+        _ -> exit({error, could_not_load_driver})
     end,
-    spawn(?MODULE, init, [SharedLib]).
-
-init(SharedLib) ->
-  register(complex, self()),
-  Port = open_port({spawn, SharedLib}, []),
-  loop(Port).

Now complex5:foo/1 and complex5:bar/1 can be implemented. Both send a -message to the complex process and receive the following reply:

foo(X) ->
-    call_port({foo, X}).
-bar(Y) ->
-    call_port({bar, Y}).
-
-call_port(Msg) ->
-    complex ! {call, self(), Msg},
+    spawn(?MODULE, init, [SharedLib]).
+
+init(SharedLib) ->
+  register(complex, self()),
+  Port = open_port({spawn, SharedLib}, []),
+  loop(Port).

Now complex5:foo/1 and complex5:bar/1 can be implemented. Both send a +message to the complex process and receive the following reply:

foo(X) ->
+    call_port({foo, X}).
+bar(Y) ->
+    call_port({bar, Y}).
+
+call_port(Msg) ->
+    complex ! {call, self(), Msg},
     receive
-        {complex, Result} ->
+        {complex, Result} ->
             Result
-    end.

The complex process performs the following:

  • Encodes the message into a sequence of bytes.
  • Sends it to the port.
  • Waits for a reply.
  • Decodes the reply.
  • Sends it back to the caller:
loop(Port) ->
+    end.

The complex process performs the following:

  • Encodes the message into a sequence of bytes.
  • Sends it to the port.
  • Waits for a reply.
  • Decodes the reply.
  • Sends it back to the caller:
loop(Port) ->
     receive
-        {call, Caller, Msg} ->
-            Port ! {self(), {command, encode(Msg)}},
+        {call, Caller, Msg} ->
+            Port ! {self(), {command, encode(Msg)}},
             receive
-                {Port, {data, Data}} ->
-                    Caller ! {complex, decode(Data)}
+                {Port, {data, Data}} ->
+                    Caller ! {complex, decode(Data)}
             end,
-            loop(Port)
+            loop(Port)
     end.

Assuming that both the arguments and the results from the C functions are less than 256, a simple encoding/decoding scheme is employed. In this scheme, foo is represented by byte 1, bar is represented by 2, and the argument/result is -represented by a single byte as well:

encode({foo, X}) -> [1, X];
-encode({bar, Y}) -> [2, Y].
+represented by a single byte as well:

encode({foo, X}) -> [1, X];
+encode({bar, Y}) -> [2, Y].
 
-decode([Int]) -> Int.

The resulting Erlang program, including functions for stopping the port and +decode([Int]) -> Int.

The resulting Erlang program, including functions for stopping the port and detecting port failures, is as follows:


--module(complex5).
--export([start/1, stop/0, init/1]).
--export([foo/1, bar/1]).
+-module(complex5).
+-export([start/1, stop/0, init/1]).
+-export([foo/1, bar/1]).
 
-start(SharedLib) ->
-    case erl_ddll:load_driver(".", SharedLib) of
+start(SharedLib) ->
+    case erl_ddll:load_driver(".", SharedLib) of
 	ok -> ok;
-	{error, already_loaded} -> ok;
-	_ -> exit({error, could_not_load_driver})
+	{error, already_loaded} -> ok;
+	_ -> exit({error, could_not_load_driver})
     end,
-    spawn(?MODULE, init, [SharedLib]).
+    spawn(?MODULE, init, [SharedLib]).
 
-init(SharedLib) ->
-    register(complex, self()),
-    Port = open_port({spawn, SharedLib}, []),
-    loop(Port).
+init(SharedLib) ->
+    register(complex, self()),
+    Port = open_port({spawn, SharedLib}, []),
+    loop(Port).
 
-stop() ->
+stop() ->
     complex ! stop.
 
-foo(X) ->
-    call_port({foo, X}).
-bar(Y) ->
-    call_port({bar, Y}).
+foo(X) ->
+    call_port({foo, X}).
+bar(Y) ->
+    call_port({bar, Y}).
 
-call_port(Msg) ->
-    complex ! {call, self(), Msg},
+call_port(Msg) ->
+    complex ! {call, self(), Msg},
     receive
-	{complex, Result} ->
+	{complex, Result} ->
 	    Result
     end.
 
-loop(Port) ->
+loop(Port) ->
     receive
-	{call, Caller, Msg} ->
-	    Port ! {self(), {command, encode(Msg)}},
+	{call, Caller, Msg} ->
+	    Port ! {self(), {command, encode(Msg)}},
 	    receive
-		{Port, {data, Data}} ->
-		    Caller ! {complex, decode(Data)}
+		{Port, {data, Data}} ->
+		    Caller ! {complex, decode(Data)}
 	    end,
-	    loop(Port);
+	    loop(Port);
 	stop ->
-	    Port ! {self(), close},
+	    Port ! {self(), close},
 	    receive
-		{Port, closed} ->
-		    exit(normal)
+		{Port, closed} ->
+		    exit(normal)
 	    end;
-	{'EXIT', Port, Reason} ->
-	    io:format("~p ~n", [Reason]),
-	    exit(port_terminated)
+	{'EXIT', Port, Reason} ->
+	    io:format("~p ~n", [Reason]),
+	    exit(port_terminated)
     end.
 
-encode({foo, X}) -> [1, X];
-encode({bar, Y}) -> [2, Y].
+encode({foo, X}) -> [1, X];
+encode({bar, Y}) -> [2, Y].
 
-decode([Int]) -> Int.

+decode([Int]) -> Int.

@@ -283,36 +283,36 @@

#include <stdio.h> #include "erl_driver.h" -typedef struct { +typedef struct { ErlDrvPort port; -} example_data; +} example_data; -static ErlDrvData example_drv_start(ErlDrvPort port, char *buff) -{ - example_data* d = (example_data*)driver_alloc(sizeof(example_data)); +static ErlDrvData example_drv_start(ErlDrvPort port, char *buff) +{ + example_data* d = (example_data*)driver_alloc(sizeof(example_data)); d->port = port; - return (ErlDrvData)d; -} - -static void example_drv_stop(ErlDrvData handle) -{ - driver_free((char*)handle); -} - -static void example_drv_output(ErlDrvData handle, char *buff, - ErlDrvSizeT bufflen) -{ - example_data* d = (example_data*)handle; - char fn = buff[0], arg = buff[1], res; - if (fn == 1) { - res = foo(arg); - } else if (fn == 2) { - res = bar(arg); - } - driver_output(d->port, &res, 1); -} - -ErlDrvEntry example_driver_entry = { + return (ErlDrvData)d; +} + +static void example_drv_stop(ErlDrvData handle) +{ + driver_free((char*)handle); +} + +static void example_drv_output(ErlDrvData handle, char *buff, + ErlDrvSizeT bufflen) +{ + example_data* d = (example_data*)handle; + char fn = buff[0], arg = buff[1], res; + if (fn == 1) { + res = foo(arg); + } else if (fn == 2) { + res = bar(arg); + } + driver_output(d->port, &res, 1); +} + +ErlDrvEntry example_driver_entry = { NULL, /* F_PTR init, called when driver is loaded */ example_drv_start, /* L_PTR start, called when port is opened */ example_drv_stop, /* F_PTR stop, called when port is closed */ @@ -344,12 +344,12 @@

monitored process dies */ NULL /* F_PTR stop_select, called to close an event object */ -}; +}; -DRIVER_INIT(example_drv) /* must match name in driver_entry */ -{ +DRIVER_INIT(example_drv) /* must match name in driver_entry */ +{ return &example_driver_entry; -}

+}

@@ -357,17 +357,17 @@

Step 1. Compile the C code:

unix> gcc -o example_drv.so -fpic -shared complex.c port_driver.c
 windows> cl -LD -MD -Fe example_drv.dll complex.c port_driver.c

Step 2. Start Erlang and compile the Erlang code:

> erl
-Erlang/OTP 26 [erts-14.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]
+Erlang/OTP 26 [erts-14.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]
 
-Eshell V14.2 (press Ctrl+G to abort, type help(). for help)
-1> c(complex5).
-{ok,complex5}

Step 3. Run the example:

2> complex5:start("example_drv").
+Eshell V14.2 (press Ctrl+G to abort, type help(). for help)
+1> c(complex5).
+{ok,complex5}

Step 3. Run the example:

2> complex5:start("example_drv").
 <0.34.0>
-3> complex5:foo(3).
+3> complex5:foo(3).
 4
-4> complex5:bar(5).
+4> complex5:bar(5).
 10
-5> complex5:stop().
+5> complex5:stop().
 stop

diff --git a/prs/9045/doc/system/code_loading.html b/prs/9045/doc/system/code_loading.html index 05cf4145a8de..ebd4b04bc354 100644 --- a/prs/9045/doc/system/code_loading.html +++ b/prs/9045/doc/system/code_loading.html @@ -132,8 +132,8 @@

Erlang programs must be compiled to object code. The compiler can generate a new file that contains the object code. The current abstract machine, which runs the object code, is called BEAM, therefore the object files get the suffix -.beam. The compiler can also generate a binary which can be loaded directly.

The compiler is located in the module compile in Compiler.

compile:file(Module)
-compile:file(Module, Options)

The Erlang shell understands the command c(Module), which both compiles and +.beam. The compiler can also generate a binary which can be loaded directly.

The compiler is located in the module compile in Compiler.

compile:file(Module)
+compile:file(Module, Options)

The Erlang shell understands the command c(Module), which both compiles and loads Module.

There is also a module make, which provides a set of functions similar to the UNIX type Make functions, see module make in Tools.

The compiler can also be accessed from the OS prompt using the erl executable in ERTS.

% erl -compile Module1...ModuleN
@@ -166,16 +166,16 @@ 

evaluated because of processes lingering in the old code.

If a third instance of the module is loaded, the code server removes (purges) the old code and any processes lingering in it is terminated. Then the third instance becomes 'current' and the previously current code becomes 'old'.

To change from old code to current code, a process must make a fully qualified -function call.

Example:

-module(m).
--export([loop/0]).
+function call.

Example:

-module(m).
+-export([loop/0]).
 
-loop() ->
+loop() ->
     receive
         code_switch ->
-            m:loop();
+            m:loop();
         Msg ->
             ...
-            loop()
+            loop()
     end.

To make the process change code, send the message code_switch to it. The process then makes a fully qualified call to m:loop() and changes to current code. Notice that m:loop/0 must be exported.

For code replacement of funs to work, use the syntax @@ -186,7 +186,7 @@

Running a Function When a Module is Loaded

The -on_load() directive names a function that is to be run automatically when -a module is loaded.

Its syntax is as follows:

-on_load(Name/0).

It is not necessary to export the function. It is called in a freshly spawned +a module is loaded.

Its syntax is as follows:

-on_load(Name/0).

It is not necessary to export the function. It is called in a freshly spawned process (which terminates as soon as the function returns).

The function must return ok if the module is to become the new current code for the module and become callable.

Returning any other value or generating an exception causes the new code to be unloaded. If the return value is not an atom, a warning error report is sent to @@ -199,13 +199,13 @@

code would become old, essentially leaving the system without any working and reachable instance of the module.

In embedded mode, first all modules are loaded. Then all on_load functions are called. The system is terminated unless all of the on_load functions return -ok.

Example:

-module(m).
--on_load(load_my_nifs/0).
+ok.

Example:

-module(m).
+-on_load(load_my_nifs/0).
 
-load_my_nifs() ->
+load_my_nifs() ->
     NifPath = ...,    %Set up the path to the NIF library.
     Info = ...,       %Initialize the Info term
-    erlang:load_nif(NifPath, Info).

If the call to erlang:load_nif/2 fails, the module is unloaded and a warning + erlang:load_nif(NifPath, Info).

If the call to erlang:load_nif/2 fails, the module is unloaded and a warning report is sent to the error loader.

diff --git a/prs/9045/doc/system/commoncaveats.html b/prs/9045/doc/system/commoncaveats.html index 40a2f1f31ca9..8d0b0bf52b15 100644 --- a/prs/9045/doc/system/commoncaveats.html +++ b/prs/9045/doc/system/commoncaveats.html @@ -128,23 +128,23 @@

Operator ++

The ++ operator copies its left-hand side operand. That is clearly -seen if we do our own implementation in Erlang:

my_plus_plus([H|T], Tail) ->
-    [H|my_plus_plus(T, Tail)];
-my_plus_plus([], Tail) ->
-    Tail.

We must be careful how we use ++ in a loop. First is how not to use it:

DO NOT

naive_reverse([H|T]) ->
-    naive_reverse(T) ++ [H];
-naive_reverse([]) ->
-    [].

As the ++ operator copies its left-hand side operand, the growing -result is copied repeatedly, leading to quadratic complexity.

On the other hand, using ++ in loop like this is perfectly fine:

OK

naive_but_ok_reverse(List) ->
-    naive_but_ok_reverse(List, []).
-
-naive_but_ok_reverse([H|T], Acc) ->
-    naive_but_ok_reverse(T, [H] ++ Acc);
-naive_but_ok_reverse([], Acc) ->
+seen if we do our own implementation in Erlang:

my_plus_plus([H|T], Tail) ->
+    [H|my_plus_plus(T, Tail)];
+my_plus_plus([], Tail) ->
+    Tail.

We must be careful how we use ++ in a loop. First is how not to use it:

DO NOT

naive_reverse([H|T]) ->
+    naive_reverse(T) ++ [H];
+naive_reverse([]) ->
+    [].

As the ++ operator copies its left-hand side operand, the growing +result is copied repeatedly, leading to quadratic complexity.

On the other hand, using ++ in loop like this is perfectly fine:

OK

naive_but_ok_reverse(List) ->
+    naive_but_ok_reverse(List, []).
+
+naive_but_ok_reverse([H|T], Acc) ->
+    naive_but_ok_reverse(T, [H] ++ Acc);
+naive_but_ok_reverse([], Acc) ->
     Acc.

Each list element is copied only once. The growing result Acc is the right-hand -side operand, which it is not copied.

Experienced Erlang programmers would probably write as follows:

DO

vanilla_reverse([H|T], Acc) ->
-    vanilla_reverse(T, [H|Acc]);
-vanilla_reverse([], Acc) ->
+side operand, which it is not copied.

Experienced Erlang programmers would probably write as follows:

DO

vanilla_reverse([H|T], Acc) ->
+    vanilla_reverse(T, [H|Acc]);
+vanilla_reverse([], Acc) ->
     Acc.

In principle, this is slightly more efficient because the list element [H] is not built before being copied and discarded. In practice, the compiler rewrites [H] ++ Acc to [H|Acc].

@@ -170,41 +170,41 @@

Accidental Copying and Loss of Sharing

When spawning a new process using a fun, one can accidentally copy more data to -the process than intended. For example:

DO NOT

accidental1(State) ->
-    spawn(fun() ->
-                  io:format("~p\n", [State#state.info])
-          end).

The code in the fun will extract one element from the record and print it. The +the process than intended. For example:

DO NOT

accidental1(State) ->
+    spawn(fun() ->
+                  io:format("~p\n", [State#state.info])
+          end).

The code in the fun will extract one element from the record and print it. The rest of the state record is not used. However, when the spawn/1 -function is executed, the entire record is copied to the newly created process.

The same kind of problem can happen with a map:

DO NOT

accidental2(State) ->
-    spawn(fun() ->
-                  io:format("~p\n", [map_get(info, State)])
-          end).

In the following example (part of a module implementing the gen_server -behavior) the created fun is sent to another process:

DO NOT

handle_call(give_me_a_fun, _From, State) ->
-    Fun = fun() -> State#state.size =:= 42 end,
-    {reply, Fun, State}.

How bad that unnecessary copy is depends on the contents of the record or the -map.

For example, if the state record is initialized like this:

init1() ->
-    #state{data=lists:seq(1, 10000)}.

a list with 10000 elements (or about 20000 heap words) will be copied to the +function is executed, the entire record is copied to the newly created process.

The same kind of problem can happen with a map:

DO NOT

accidental2(State) ->
+    spawn(fun() ->
+                  io:format("~p\n", [map_get(info, State)])
+          end).

In the following example (part of a module implementing the gen_server +behavior) the created fun is sent to another process:

DO NOT

handle_call(give_me_a_fun, _From, State) ->
+    Fun = fun() -> State#state.size =:= 42 end,
+    {reply, Fun, State}.

How bad that unnecessary copy is depends on the contents of the record or the +map.

For example, if the state record is initialized like this:

init1() ->
+    #state{data=lists:seq(1, 10000)}.

a list with 10000 elements (or about 20000 heap words) will be copied to the newly created process.

An unnecessary copy of 10000 element list can be bad enough, but it can get even worse if the state record contains shared subterms. Here is a simple example -of a term with a shared subterm:

{SubTerm, SubTerm}

When a term is copied to another process, sharing of subterms will be lost and -the copied term can be many times larger than the original term. For example:

init2() ->
-    SharedSubTerms = lists:foldl(fun(_, A) -> [A|A] end, [0], lists:seq(1, 15)),
-    #state{data=Shared}.

In the process that calls init2/0, the size of the data field in the state +of a term with a shared subterm:

{SubTerm, SubTerm}

When a term is copied to another process, sharing of subterms will be lost and +the copied term can be many times larger than the original term. For example:

init2() ->
+    SharedSubTerms = lists:foldl(fun(_, A) -> [A|A] end, [0], lists:seq(1, 15)),
+    #state{data=Shared}.

In the process that calls init2/0, the size of the data field in the state record will be 32 heap words. When the record is copied to the newly created process, sharing will be lost and the size of the copied data field will be 131070 heap words. More details about loss off sharing are found in a later section.

To avoid the problem, outside of the fun extract only the fields of the record -that are actually used:

DO

fixed_accidental1(State) ->
+that are actually used:

DO

fixed_accidental1(State) ->
     Info = State#state.info,
-    spawn(fun() ->
-                  io:format("~p\n", [Info])
-          end).

Similarly, outside of the fun extract only the map elements that are actually -used:

DO

fixed_accidental2(State) ->
-    Info = map_get(info, State),
-    spawn(fun() ->
-                  io:format("~p\n", [Info])
-          end).

+ spawn(fun() -> + io:format("~p\n", [Info]) + end).

Similarly, outside of the fun extract only the map elements that are actually +used:

DO

fixed_accidental2(State) ->
+    Info = map_get(info, State),
+    spawn(fun() ->
+                  io:format("~p\n", [Info])
+          end).

@@ -219,7 +219,7 @@

to guard against a denial-of-service attack. (All atoms that are allowed must have been created earlier, for example, by using all of them in a module and loading that module.)

Using list_to_atom/1 to construct an atom that -is passed to apply/3 is quite expensive.

DO NOT

apply(list_to_atom("some_prefix"++Var), foo, Args)

+is passed to apply/3 is quite expensive.

DO NOT

apply(list_to_atom("some_prefix"++Var), foo, Args)

@@ -231,8 +231,8 @@

execute in constant time.

Normally, there is no need to worry about the speed of length/1, because it is efficiently implemented in C. In time-critical code, you might want to avoid it if the input list could potentially be very long.

Some uses of length/1 can be replaced by matching. For example, -the following code:

foo(L) when length(L) >= 3 ->
-    ...

can be rewritten to:

foo([_,_,_|_]=L) ->
+the following code:

foo(L) when length(L) >= 3 ->
+    ...

can be rewritten to:

foo([_,_,_|_]=L) ->
    ...

One slight difference is that length(L) fails if L is an improper list, while the pattern in the second code fragment accepts an improper list.

@@ -248,10 +248,10 @@

as if the tuple was copied, the call to setelement/3 is replaced with a special destructive setelement instruction. In the following code sequence, the first setelement/3 call copies the tuple -and modifies the ninth element:

multiple_setelement(T0) when tuple_size(T0) =:= 9 ->
-    T1 = setelement(9, T0, bar),
-    T2 = setelement(7, T1, foobar),
-    setelement(5, T2, new_value).

The two following setelement/3 calls modify the tuple in +and modifies the ninth element:

multiple_setelement(T0) when tuple_size(T0) =:= 9 ->
+    T1 = setelement(9, T0, bar),
+    T2 = setelement(7, T1, foobar),
+    setelement(5, T2, new_value).

The two following setelement/3 calls modify the tuple in place.

For the optimization to be applied, all the following conditions must be true:

  • The tuple argument must be known to be a tuple of a known size.
  • The indices must be integer literals, not variables or expressions.
  • The indices must be given in descending order.
  • There must be no calls to another function in between the calls to setelement/3.
  • The tuple returned from one setelement/3 call must only be used in the subsequent call to setelement/3.

If the code cannot be structured as in the multiple_setelement/1 example, the diff --git a/prs/9045/doc/system/conc_prog.html b/prs/9045/doc/system/conc_prog.html index 7fea42d6125e..50a33b3e4dce 100644 --- a/prs/9045/doc/system/conc_prog.html +++ b/prs/9045/doc/system/conc_prog.html @@ -142,21 +142,21 @@

Threads of execution in Erlang share no data, that is why they are called processes).

The Erlang BIF spawn is used to create a new process: spawn(Module, Exported_Function, List of Arguments). Consider the following -module:

-module(tut14).
+module:

-module(tut14).
 
--export([start/0, say_something/2]).
+-export([start/0, say_something/2]).
 
-say_something(What, 0) ->
+say_something(What, 0) ->
     done;
-say_something(What, Times) ->
-    io:format("~p~n", [What]),
-    say_something(What, Times - 1).
-
-start() ->
-    spawn(tut14, say_something, [hello, 3]),
-    spawn(tut14, say_something, [goodbye, 3]).
5> c(tut14).
-{ok,tut14}
-6> tut14:say_something(hello, 3).
+say_something(What, Times) ->
+    io:format("~p~n", [What]),
+    say_something(What, Times - 1).
+
+start() ->
+    spawn(tut14, say_something, [hello, 3]),
+    spawn(tut14, say_something, [goodbye, 3]).
5> c(tut14).
+{ok,tut14}
+6> tut14:say_something(hello, 3).
 hello
 hello
 hello
@@ -165,7 +165,7 @@ 

processes, one that writes "hello" three times and one that writes "goodbye" three times. Both processes use the function say_something. Notice that a function used in this way by spawn, to start a process, must be exported from -the module (that is, in the -export at the start of the module).

9> tut14:start().
+the module (that is, in the -export at the start of the module).

9> tut14:start().
 hello
 goodbye
 <0.63.0>
@@ -176,7 +176,7 @@ 

Instead, the first process wrote a "hello", the second a "goodbye", the first another "hello" and so forth. But where did the <0.63.0> come from? The return value of a function is the return value of the last "thing" in the function. The -last thing in the function start is

spawn(tut14, say_something, [goodbye, 3]).

spawn returns a process identifier, or pid, which uniquely identifies the +last thing in the function start is

spawn(tut14, say_something, [goodbye, 3]).

spawn returns a process identifier, or pid, which uniquely identifies the process. So <0.63.0> is the pid of the spawn function call above. The next example shows how to use pids.

Notice also that ~p is used instead of ~w in io:format/2. To quote the manual:

~p Writes the data with standard syntax in the same way as ~w, but breaks terms whose printed representation is longer than one line into many lines and indents @@ -188,37 +188,37 @@

Message Passing

In the following example two processes are created and they send messages to -each other a number of times.

-module(tut15).
+each other a number of times.

-module(tut15).
 
--export([start/0, ping/2, pong/0]).
+-export([start/0, ping/2, pong/0]).
 
-ping(0, Pong_PID) ->
+ping(0, Pong_PID) ->
     Pong_PID ! finished,
-    io:format("ping finished~n", []);
+    io:format("ping finished~n", []);
 
-ping(N, Pong_PID) ->
-    Pong_PID ! {ping, self()},
+ping(N, Pong_PID) ->
+    Pong_PID ! {ping, self()},
     receive
         pong ->
-            io:format("Ping received pong~n", [])
+            io:format("Ping received pong~n", [])
     end,
-    ping(N - 1, Pong_PID).
+    ping(N - 1, Pong_PID).
 
-pong() ->
+pong() ->
     receive
         finished ->
-            io:format("Pong finished~n", []);
-        {ping, Ping_PID} ->
-            io:format("Pong received ping~n", []),
+            io:format("Pong finished~n", []);
+        {ping, Ping_PID} ->
+            io:format("Pong received ping~n", []),
             Ping_PID ! pong,
-            pong()
+            pong()
     end.
 
-start() ->
-    Pong_PID = spawn(tut15, pong, []),
-    spawn(tut15, ping, [3, Pong_PID]).
1> c(tut15).
-{ok,tut15}
-2> tut15: start().
+start() ->
+    Pong_PID = spawn(tut15, pong, []),
+    spawn(tut15, ping, [3, Pong_PID]).
1> c(tut15).
+{ok,tut15}
+2> tut15: start().
 <0.36.0>
 Pong received ping
 Ping received pong
@@ -227,14 +227,14 @@ 

Pong received ping Ping received pong ping finished -Pong finished

The function start first creates a process, let us call it "pong":

Pong_PID = spawn(tut15, pong, [])

This process executes tut15:pong(). Pong_PID is the process identity of the -"pong" process. The function start now creates another process "ping":

spawn(tut15, ping, [3, Pong_PID]),

This process executes:

tut15:ping(3, Pong_PID)

<0.36.0> is the return value from the start function.

The process "pong" now does:

receive
+Pong finished

The function start first creates a process, let us call it "pong":

Pong_PID = spawn(tut15, pong, [])

This process executes tut15:pong(). Pong_PID is the process identity of the +"pong" process. The function start now creates another process "ping":

spawn(tut15, ping, [3, Pong_PID]),

This process executes:

tut15:ping(3, Pong_PID)

<0.36.0> is the return value from the start function.

The process "pong" now does:

receive
     finished ->
-        io:format("Pong finished~n", []);
-    {ping, Ping_PID} ->
-        io:format("Pong received ping~n", []),
+        io:format("Pong finished~n", []);
+    {ping, Ping_PID} ->
+        io:format("Pong received ping~n", []),
         Ping_PID ! pong,
-        pong()
+        pong()
 end.

The receive construct is used to allow processes to wait for messages from other processes. It has the following format:

receive
    pattern1 ->
@@ -263,21 +263,21 @@ 

procedure is repeated.

The Erlang implementation is "clever" and minimizes the number of times each message is tested against the patterns in each receive.

Now back to the ping pong example.

"Pong" is waiting for messages. If the atom finished is received, "pong" writes "Pong finished" to the output and, as it has nothing more to do, -terminates. If it receives a message with the format:

{ping, Ping_PID}

it writes "Pong received ping" to the output and sends the atom pong to the +terminates. If it receives a message with the format:

{ping, Ping_PID}

it writes "Pong received ping" to the output and sends the atom pong to the process "ping":

Ping_PID ! pong

Notice how the operator "!" is used to send messages. The syntax of "!" is:

Pid ! Message

That is, Message (any Erlang term) is sent to the process with identity Pid.

After sending the message pong to the process "ping", "pong" calls the pong function again, which causes it to get back to the receive again and wait for -another message.

Now let us look at the process "ping". Recall that it was started by executing:

tut15:ping(3, Pong_PID)

Looking at the function ping/2, the second clause of ping/2 is executed +another message.

Now let us look at the process "ping". Recall that it was started by executing:

tut15:ping(3, Pong_PID)

Looking at the function ping/2, the second clause of ping/2 is executed since the value of the first argument is 3 (not 0) (first clause head is -ping(0,Pong_PID), second clause head is ping(N,Pong_PID), so N becomes 3).

The second clause sends a message to "pong":

Pong_PID ! {ping, self()},

self/0 returns the pid of the process that executes self/0, in this case the +ping(0,Pong_PID), second clause head is ping(N,Pong_PID), so N becomes 3).

The second clause sends a message to "pong":

Pong_PID ! {ping, self()},

self/0 returns the pid of the process that executes self/0, in this case the pid of "ping". (Recall the code for "pong", this lands up in the variable Ping_PID in the receive previously explained.)

"Ping" now waits for a reply from "pong":

receive
     pong ->
-        io:format("Ping received pong~n", [])
+        io:format("Ping received pong~n", [])
 end,

It writes "Ping received pong" when this reply arrives, after which "ping" calls -the ping function again.

ping(N - 1, Pong_PID)

N-1 causes the first argument to be decremented until it becomes 0. When this -occurs, the first clause of ping/2 is executed:

ping(0, Pong_PID) ->
+the ping function again.

ping(N - 1, Pong_PID)

N-1 causes the first argument to be decremented until it becomes 0. When this +occurs, the first clause of ping/2 is executed:

ping(0, Pong_PID) ->
     Pong_PID !  finished,
-    io:format("ping finished~n", []);

The atom finished is sent to "pong" (causing it to terminate as described + io:format("ping finished~n", []);

The atom finished is sent to "pong" (causing it to terminate as described above) and "ping finished" is written to the output. "Ping" then terminates as it has nothing left to do.

@@ -291,38 +291,38 @@

processes which need to know each other's identities are started independently of each other. Erlang thus provides a mechanism for processes to be given names so that these names can be used as identities instead of pids. This is done by -using the register BIF:

register(some_atom, Pid)

Let us now rewrite the ping pong example using this and give the name pong to -the "pong" process:

-module(tut16).
+using the register BIF:

register(some_atom, Pid)

Let us now rewrite the ping pong example using this and give the name pong to +the "pong" process:

-module(tut16).
 
--export([start/0, ping/1, pong/0]).
+-export([start/0, ping/1, pong/0]).
 
-ping(0) ->
+ping(0) ->
     pong ! finished,
-    io:format("ping finished~n", []);
+    io:format("ping finished~n", []);
 
-ping(N) ->
-    pong ! {ping, self()},
+ping(N) ->
+    pong ! {ping, self()},
     receive
         pong ->
-            io:format("Ping received pong~n", [])
+            io:format("Ping received pong~n", [])
     end,
-    ping(N - 1).
+    ping(N - 1).
 
-pong() ->
+pong() ->
     receive
         finished ->
-            io:format("Pong finished~n", []);
-        {ping, Ping_PID} ->
-            io:format("Pong received ping~n", []),
+            io:format("Pong finished~n", []);
+        {ping, Ping_PID} ->
+            io:format("Pong received ping~n", []),
             Ping_PID ! pong,
-            pong()
+            pong()
     end.
 
-start() ->
-    register(pong, spawn(tut16, pong, [])),
-    spawn(tut16, ping, [3]).
2> c(tut16).
-{ok, tut16}
-3> tut16:start().
+start() ->
+    register(pong, spawn(tut16, pong, [])),
+    spawn(tut16, ping, [3]).
2> c(tut16).
+{ok, tut16}
+3> tut16:start().
 <0.38.0>
 Pong received ping
 Ping received pong
@@ -331,8 +331,8 @@ 

Pong received ping Ping received pong ping finished -Pong finished

Here the start/0 function,

register(pong, spawn(tut16, pong, [])),

both spawns the "pong" process and gives it the name pong. In the "ping" -process, messages can be sent to pong by:

pong ! {ping, self()},

ping/2 now becomes ping/1 as the argument Pong_PID is not needed.

+Pong finished

Here the start/0 function,

register(pong, spawn(tut16, pong, [])),

both spawns the "pong" process and gives it the name pong. In the "ping" +process, messages can be sent to pong by:

pong ! {ping, self()},

ping/2 now becomes ping/1 as the argument Pong_PID is not needed.

@@ -360,37 +360,37 @@

Erlang system running on a computer is called an Erlang node.

(Note: erl -sname assumes that all nodes are in the same IP domain and we can use only the first component of the IP address, if we want to use nodes in different domains we use -name instead, but then all IP address must be given -in full.)

Here is the ping pong example modified to run on two separate nodes:

-module(tut17).
+in full.)

Here is the ping pong example modified to run on two separate nodes:

-module(tut17).
 
--export([start_ping/1, start_pong/0,  ping/2, pong/0]).
+-export([start_ping/1, start_pong/0,  ping/2, pong/0]).
 
-ping(0, Pong_Node) ->
-    {pong, Pong_Node} ! finished,
-    io:format("ping finished~n", []);
+ping(0, Pong_Node) ->
+    {pong, Pong_Node} ! finished,
+    io:format("ping finished~n", []);
 
-ping(N, Pong_Node) ->
-    {pong, Pong_Node} ! {ping, self()},
+ping(N, Pong_Node) ->
+    {pong, Pong_Node} ! {ping, self()},
     receive
         pong ->
-            io:format("Ping received pong~n", [])
+            io:format("Ping received pong~n", [])
     end,
-    ping(N - 1, Pong_Node).
+    ping(N - 1, Pong_Node).
 
-pong() ->
+pong() ->
     receive
         finished ->
-            io:format("Pong finished~n", []);
-        {ping, Ping_PID} ->
-            io:format("Pong received ping~n", []),
+            io:format("Pong finished~n", []);
+        {ping, Ping_PID} ->
+            io:format("Pong received ping~n", []),
             Ping_PID ! pong,
-            pong()
+            pong()
     end.
 
-start_pong() ->
-    register(pong, spawn(tut17, pong, [])).
+start_pong() ->
+    register(pong, spawn(tut17, pong, [])).
 
-start_ping(Pong_Node) ->
-    spawn(tut17, ping, [3, Pong_Node]).

Let us assume there are two computers called gollum and kosken. First a node is +start_ping(Pong_Node) -> + spawn(tut17, ping, [3, Pong_Node]).

Let us assume there are two computers called gollum and kosken. First a node is started on kosken, called ping, and then a node on gollum, called pong.

On kosken (on a Linux/UNIX system):

kosken> erl -sname ping
 Erlang (BEAM) emulator version 5.2.3.7 [hipe] [threads:0]
 
@@ -399,10 +399,10 @@ 

Erlang (BEAM) emulator version 5.2.3.7 [hipe] [threads:0] Eshell V5.2.3.7 (abort with ^G) -(pong@gollum)1>

Now the "pong" process on gollum is started:

(pong@gollum)1> tut17:start_pong().
+(pong@gollum)1>

Now the "pong" process on gollum is started:

(pong@gollum)1> tut17:start_pong().
 true

And the "ping" process on kosken is started (from the code above you can see that a parameter of the start_ping function is the node name of the Erlang -system where "pong" is running):

(ping@kosken)1> tut17:start_ping(pong@gollum).
+system where "pong" is running):

(ping@kosken)1> tut17:start_ping(pong@gollum).
 <0.37.0>
 Ping received pong
 Ping received pong
@@ -412,46 +412,46 @@ 

Pong received ping Pong received ping Pong finished -(pong@gollum)2>

Looking at the tut17 code, you see that the pong function itself is +(pong@gollum)2>

Looking at the tut17 code, you see that the pong function itself is unchanged, the following lines work in the same way irrespective of on which -node the "ping" process is executes:

{ping, Ping_PID} ->
-    io:format("Pong received ping~n", []),
+node the "ping" process is executes:

{ping, Ping_PID} ->
+    io:format("Pong received ping~n", []),
     Ping_PID ! pong,

Thus, Erlang pids contain information about where the process executes. So if you know the pid of a process, the ! operator can be used to send it a -message disregarding if the process is on the same node or on a different node.

A difference is how messages are sent to a registered process on another node:

{pong, Pong_Node} ! {ping, self()},

A tuple {registered_name,node_name} is used instead of just the +message disregarding if the process is on the same node or on a different node.

A difference is how messages are sent to a registered process on another node:

{pong, Pong_Node} ! {ping, self()},

A tuple {registered_name,node_name} is used instead of just the registered_name.

In the previous example, "ping" and "pong" were started from the shells of two separate Erlang nodes. spawn can also be used to start processes in other nodes.

The next example is the ping pong program, yet again, but this time "ping" is -started in another node:

-module(tut18).
+started in another node:

-module(tut18).
 
--export([start/1,  ping/2, pong/0]).
+-export([start/1,  ping/2, pong/0]).
 
-ping(0, Pong_Node) ->
-    {pong, Pong_Node} ! finished,
-    io:format("ping finished~n", []);
+ping(0, Pong_Node) ->
+    {pong, Pong_Node} ! finished,
+    io:format("ping finished~n", []);
 
-ping(N, Pong_Node) ->
-    {pong, Pong_Node} ! {ping, self()},
+ping(N, Pong_Node) ->
+    {pong, Pong_Node} ! {ping, self()},
     receive
         pong ->
-            io:format("Ping received pong~n", [])
+            io:format("Ping received pong~n", [])
     end,
-    ping(N - 1, Pong_Node).
+    ping(N - 1, Pong_Node).
 
-pong() ->
+pong() ->
     receive
         finished ->
-            io:format("Pong finished~n", []);
-        {ping, Ping_PID} ->
-            io:format("Pong received ping~n", []),
+            io:format("Pong finished~n", []);
+        {ping, Ping_PID} ->
+            io:format("Pong received ping~n", []),
             Ping_PID ! pong,
-            pong()
+            pong()
     end.
 
-start(Ping_Node) ->
-    register(pong, spawn(tut18, pong, [])),
-    spawn(Ping_Node, tut18, ping, [3, node()]).

Assuming an Erlang system called ping (but not the "ping" process) has already -been started on kosken, then on gollum this is done:

(pong@gollum)1> tut18:start(ping@kosken).
+start(Ping_Node) ->
+    register(pong, spawn(tut18, pong, [])),
+    spawn(Ping_Node, tut18, ping, [3, node()]).

Assuming an Erlang system called ping (but not the "ping" process) has already +been started on kosken, then on gollum this is done:

(pong@gollum)1> tut18:start(ping@kosken).
 <3934.39.0>
 Pong received ping
 Ping received pong
@@ -526,140 +526,140 @@ 

%%% Configuration: change the server_node() function to return the %%% name of the node where the messenger server runs --module(messenger). --export([start_server/0, server/1, logon/1, logoff/0, message/2, client/2]). +-module(messenger). +-export([start_server/0, server/1, logon/1, logoff/0, message/2, client/2]). %%% Change the function below to return the name of the node where the %%% messenger server runs -server_node() -> +server_node() -> messenger@super. %%% This is the server process for the "messenger" %%% the user list has the format [{ClientPid1, Name1},{ClientPid22, Name2},...] -server(User_List) -> +server(User_List) -> receive - {From, logon, Name} -> - New_User_List = server_logon(From, Name, User_List), - server(New_User_List); - {From, logoff} -> - New_User_List = server_logoff(From, User_List), - server(New_User_List); - {From, message_to, To, Message} -> - server_transfer(From, To, Message, User_List), - io:format("list is now: ~p~n", [User_List]), - server(User_List) + {From, logon, Name} -> + New_User_List = server_logon(From, Name, User_List), + server(New_User_List); + {From, logoff} -> + New_User_List = server_logoff(From, User_List), + server(New_User_List); + {From, message_to, To, Message} -> + server_transfer(From, To, Message, User_List), + io:format("list is now: ~p~n", [User_List]), + server(User_List) end. %%% Start the server -start_server() -> - register(messenger, spawn(messenger, server, [[]])). +start_server() -> + register(messenger, spawn(messenger, server, [[]])). %%% Server adds a new user to the user list -server_logon(From, Name, User_List) -> +server_logon(From, Name, User_List) -> %% check if logged on anywhere else - case lists:keymember(Name, 2, User_List) of + case lists:keymember(Name, 2, User_List) of true -> - From ! {messenger, stop, user_exists_at_other_node}, %reject logon + From ! {messenger, stop, user_exists_at_other_node}, %reject logon User_List; false -> - From ! {messenger, logged_on}, - [{From, Name} | User_List] %add user to the list + From ! {messenger, logged_on}, + [{From, Name} | User_List] %add user to the list end. %%% Server deletes a user from the user list -server_logoff(From, User_List) -> - lists:keydelete(From, 1, User_List). +server_logoff(From, User_List) -> + lists:keydelete(From, 1, User_List). %%% Server transfers a message between user -server_transfer(From, To, Message, User_List) -> +server_transfer(From, To, Message, User_List) -> %% check that the user is logged on and who he is - case lists:keysearch(From, 1, User_List) of + case lists:keysearch(From, 1, User_List) of false -> - From ! {messenger, stop, you_are_not_logged_on}; - {value, {From, Name}} -> - server_transfer(From, Name, To, Message, User_List) + From ! {messenger, stop, you_are_not_logged_on}; + {value, {From, Name}} -> + server_transfer(From, Name, To, Message, User_List) end. %%% If the user exists, send the message -server_transfer(From, Name, To, Message, User_List) -> +server_transfer(From, Name, To, Message, User_List) -> %% Find the receiver and send the message - case lists:keysearch(To, 2, User_List) of + case lists:keysearch(To, 2, User_List) of false -> - From ! {messenger, receiver_not_found}; - {value, {ToPid, To}} -> - ToPid ! {message_from, Name, Message}, - From ! {messenger, sent} + From ! {messenger, receiver_not_found}; + {value, {ToPid, To}} -> + ToPid ! {message_from, Name, Message}, + From ! {messenger, sent} end. %%% User Commands -logon(Name) -> - case whereis(mess_client) of +logon(Name) -> + case whereis(mess_client) of undefined -> - register(mess_client, - spawn(messenger, client, [server_node(), Name])); + register(mess_client, + spawn(messenger, client, [server_node(), Name])); _ -> already_logged_on end. -logoff() -> +logoff() -> mess_client ! logoff. -message(ToName, Message) -> - case whereis(mess_client) of % Test if the client is running +message(ToName, Message) -> + case whereis(mess_client) of % Test if the client is running undefined -> not_logged_on; - _ -> mess_client ! {message_to, ToName, Message}, + _ -> mess_client ! {message_to, ToName, Message}, ok end. %%% The client process which runs on each server node -client(Server_Node, Name) -> - {messenger, Server_Node} ! {self(), logon, Name}, - await_result(), - client(Server_Node). +client(Server_Node, Name) -> + {messenger, Server_Node} ! {self(), logon, Name}, + await_result(), + client(Server_Node). -client(Server_Node) -> +client(Server_Node) -> receive logoff -> - {messenger, Server_Node} ! {self(), logoff}, - exit(normal); - {message_to, ToName, Message} -> - {messenger, Server_Node} ! {self(), message_to, ToName, Message}, - await_result(); - {message_from, FromName, Message} -> - io:format("Message from ~p: ~p~n", [FromName, Message]) + {messenger, Server_Node} ! {self(), logoff}, + exit(normal); + {message_to, ToName, Message} -> + {messenger, Server_Node} ! {self(), message_to, ToName, Message}, + await_result(); + {message_from, FromName, Message} -> + io:format("Message from ~p: ~p~n", [FromName, Message]) end, - client(Server_Node). + client(Server_Node). %%% wait for a response from the server -await_result() -> +await_result() -> receive - {messenger, stop, Why} -> % Stop the client - io:format("~p~n", [Why]), - exit(normal); - {messenger, What} -> % Normal response - io:format("~p~n", [What]) + {messenger, stop, Why} -> % Stop the client + io:format("~p~n", [Why]), + exit(normal); + {messenger, What} -> % Normal response + io:format("~p~n", [What]) end.

To use this program, you need to:

  • Configure the server_node() function.
  • Copy the compiled code (messenger.beam) to the directory on each computer where you start Erlang.

In the following example using this program, nodes are started on four different computers. If you do not have that many machines available on your network, you can start several nodes on the same machine.

Four Erlang nodes are started up: messenger@super, c1@bilbo, c2@kosken, -c3@gollum.

First the server at messenger@super is started up:

(messenger@super)1> messenger:start_server().
-true

Now Peter logs on at c1@bilbo:

(c1@bilbo)1> messenger:logon(peter).
+c3@gollum.

First the server at messenger@super is started up:

(messenger@super)1> messenger:start_server().
+true

Now Peter logs on at c1@bilbo:

(c1@bilbo)1> messenger:logon(peter).
 true
-logged_on

James logs on at c2@kosken:

(c2@kosken)1> messenger:logon(james).
+logged_on

James logs on at c2@kosken:

(c2@kosken)1> messenger:logon(james).
 true
-logged_on

And Fred logs on at c3@gollum:

(c3@gollum)1> messenger:logon(fred).
+logged_on

And Fred logs on at c3@gollum:

(c3@gollum)1> messenger:logon(fred).
 true
-logged_on

Now Peter sends Fred a message:

(c1@bilbo)2> messenger:message(fred, "hello").
+logged_on

Now Peter sends Fred a message:

(c1@bilbo)2> messenger:message(fred, "hello").
 ok
 sent

Fred receives the message and sends a message to Peter and logs off:

Message from peter: "hello"
-(c3@gollum)2> messenger:message(peter, "go away, I'm busy").
+(c3@gollum)2> messenger:message(peter, "go away, I'm busy").
 ok
 sent
-(c3@gollum)3> messenger:logoff().
-logoff

James now tries to send a message to Fred:

(c2@kosken)2> messenger:message(fred, "peter doesn't like you").
+(c3@gollum)3> messenger:logoff().
+logoff

James now tries to send a message to Fred:

(c2@kosken)2> messenger:message(fred, "peter doesn't like you").
 ok
 receiver_not_found

But this fails as Fred has already logged off.

First let us look at some of the new concepts that have been introduced.

There are two versions of the server_transfer function: one with four arguments (server_transfer/4) and one with five (server_transfer/5). These @@ -673,12 +673,12 @@

lists:keymember(Key,Position,Lists) looks through a list of tuples and looks at Position in each tuple to see if it is the same as Key. The first element is position 1. If it finds a tuple where the element at Position is the same -as Key, it returns true, otherwise false.

3> lists:keymember(a, 2, [{x,y,z},{b,b,b},{b,a,c},{q,r,s}]).
+as Key, it returns true, otherwise false.

3> lists:keymember(a, 2, [{x,y,z},{b,b,b},{b,a,c},{q,r,s}]).
 true
-4> lists:keymember(p, 2, [{x,y,z},{b,b,b},{b,a,c},{q,r,s}]).
+4> lists:keymember(p, 2, [{x,y,z},{b,b,b},{b,a,c},{q,r,s}]).
 false

lists:keydelete works in the same way but deletes the first tuple found (if -any) and returns the remaining list:

5> lists:keydelete(a, 2, [{x,y,z},{b,b,b},{b,a,c},{q,r,s}]).
-[{x,y,z},{b,b,b},{q,r,s}]

lists:keysearch is like lists:keymember, but it returns +any) and returns the remaining list:

5> lists:keydelete(a, 2, [{x,y,z},{b,b,b},{b,a,c},{q,r,s}]).
+[{x,y,z},{b,b,b},{q,r,s}]

lists:keysearch is like lists:keymember, but it returns {value,Tuple_Found} or the atom false.

There are many very useful functions in the lists module.

An Erlang process (conceptually) runs until it does a receive and there is no message which it wants to receive in the message queue. "conceptually" is used here because the Erlang system shares the CPU time between the active processes @@ -691,15 +691,15 @@

of name RegisteredName exists. If it exists, the pid of that process is returned. If it does not exist, the atom undefined is returned.

You should by now be able to understand most of the code in the messenger-module. Let us study one case in detail: a message is sent from one -user to another.

The first user "sends" the message in the example above by:

messenger:message(fred, "hello")

After testing that the client process exists:

whereis(mess_client)

And a message is sent to mess_client:

mess_client ! {message_to, fred, "hello"}

The client sends the message to the server by:

{messenger, messenger@super} ! {self(), message_to, fred, "hello"},

And waits for a reply from the server.

The server receives this message and calls:

server_transfer(From, fred, "hello", User_List),

This checks that the pid From is in the User_List:

lists:keysearch(From, 1, User_List)

If keysearch returns the atom false, some error has occurred and the server -sends back the message:

From ! {messenger, stop, you_are_not_logged_on}

This is received by the client, which in turn does exit(normal) +user to another.

The first user "sends" the message in the example above by:

messenger:message(fred, "hello")

After testing that the client process exists:

whereis(mess_client)

And a message is sent to mess_client:

mess_client ! {message_to, fred, "hello"}

The client sends the message to the server by:

{messenger, messenger@super} ! {self(), message_to, fred, "hello"},

And waits for a reply from the server.

The server receives this message and calls:

server_transfer(From, fred, "hello", User_List),

This checks that the pid From is in the User_List:

lists:keysearch(From, 1, User_List)

If keysearch returns the atom false, some error has occurred and the server +sends back the message:

From ! {messenger, stop, you_are_not_logged_on}

This is received by the client, which in turn does exit(normal) and terminates. If keysearch returns {value,{From,Name}} it is certain that -the user is logged on and that his name (peter) is in variable Name.

Let us now call:

server_transfer(From, peter, fred, "hello", User_List)

Notice that as this is server_transfer/5, it is not the same as the previous +the user is logged on and that his name (peter) is in variable Name.

Let us now call:

server_transfer(From, peter, fred, "hello", User_List)

Notice that as this is server_transfer/5, it is not the same as the previous function server_transfer/4. Another keysearch is done on User_List to find -the pid of the client corresponding to fred:

lists:keysearch(fred, 2, User_List)

This time argument 2 is used, which is the second element in the tuple. If this +the pid of the client corresponding to fred:

lists:keysearch(fred, 2, User_List)

This time argument 2 is used, which is the second element in the tuple. If this returns the atom false, fred is not logged on and the following message is -sent:

From ! {messenger, receiver_not_found};

This is received by the client.

If keysearch returns:

{value, {ToPid, fred}}

The following message is sent to fred's client:

ToPid ! {message_from, peter, "hello"},

The following message is sent to peter's client:

From ! {messenger, sent}

Fred's client receives the message and prints it:

{message_from, peter, "hello"} ->
-    io:format("Message from ~p: ~p~n", [peter, "hello"])

Peter's client receives the message in the await_result function.

+sent:

From ! {messenger, receiver_not_found};

This is received by the client.

If keysearch returns:

{value, {ToPid, fred}}

The following message is sent to fred's client:

ToPid ! {message_from, peter, "hello"},

The following message is sent to peter's client:

From ! {messenger, sent}

Fred's client receives the message and prints it:

{message_from, peter, "hello"} ->
+    io:format("Message from ~p: ~p~n", [peter, "hello"])

Peter's client receives the message in the await_result function.

diff --git a/prs/9045/doc/system/create_target.html b/prs/9045/doc/system/create_target.html index 9cbcb326c344..0f061eebf53d 100644 --- a/prs/9045/doc/system/create_target.html +++ b/prs/9045/doc/system/create_target.html @@ -148,13 +148,13 @@

SASL), which specifies the ERTS version and lists all applications that are to be included in the new basic target system. An example is the following mysystem.rel file:

%% mysystem.rel
-{release,
- {"MYSYSTEM", "FIRST"},
- {erts, "5.10.4"},
- [{kernel, "2.16.4"},
-  {stdlib, "1.19.4"},
-  {sasl, "2.3.4"},
-  {pea, "1.0"}]}.

The listed applications are not only original Erlang/OTP applications but +{release, + {"MYSYSTEM", "FIRST"}, + {erts, "5.10.4"}, + [{kernel, "2.16.4"}, + {stdlib, "1.19.4"}, + {sasl, "2.3.4"}, + {pea, "1.0"}]}.

The listed applications are not only original Erlang/OTP applications but possibly also new applications that you have written (here exemplified by the application Pea (pea)).

Step 2. Start Erlang/OTP from the directory where the mysystem.rel file resides:

% erl -pa /home/user/target_system/myapps/pea-1.0/ebin

The -pa argument prepends the path to the ebin directory for @@ -252,17 +252,17 @@

In this example the Pea application has been changed, and so are the applications ERTS, Kernel, STDLIB and SASL.

Step 1. Create the file .rel:

%% mysystem2.rel
-{release,
- {"MYSYSTEM", "SECOND"},
- {erts, "6.0"},
- [{kernel, "3.0"},
-  {stdlib, "2.0"},
-  {sasl, "2.4"},
-  {pea, "2.0"}]}.

Step 2. Create the application upgrade file (see +{release, + {"MYSYSTEM", "SECOND"}, + {erts, "6.0"}, + [{kernel, "3.0"}, + {stdlib, "2.0"}, + {sasl, "2.4"}, + {pea, "2.0"}]}.

Step 2. Create the application upgrade file (see appup in SASL) for Pea, for example:

%% pea.appup
-{"2.0",
- [{"1.0",[{load_module,pea_lib}]}],
- [{"1.0",[{load_module,pea_lib}]}]}.

Step 3. From the directory where the file mysystem2.rel resides, start the +{"2.0", + [{"1.0",[{load_module,pea_lib}]}], + [{"1.0",[{load_module,pea_lib}]}]}.

Step 3. From the directory where the file mysystem2.rel resides, start the Erlang/OTP system, giving the path to the new version of Pea:

% erl -pa /home/user/target_system/myapps/pea-2.0/ebin

Step 4. Create the release upgrade file (see relup in SASL):

1> systools:make_relup("mysystem2",["mysystem"],["mysystem"],
     [{path,["/home/user/target_system/myapps/pea-1.0/ebin",
@@ -302,21 +302,21 @@ 

release_handler:install_release/1 means that the release_handler has restarted the node by using heart. This is always done when the upgrade involves a change of the applications ERTS, Kernel, STDLIB, or SASL. For more -information, see Upgrade when Erlang/OTP has Changed.

The node is accessible through a new pipe:

% /usr/local/erl-target/bin/to_erl /tmp/erlang.pipe.2

List the available releases in the system:

1> release_handler:which_releases().
-[{"MYSYSTEM","SECOND",
-  ["kernel-3.0","stdlib-2.0","sasl-2.4","pea-2.0"],
-  current},
- {"MYSYSTEM","FIRST",
-  ["kernel-2.16.4","stdlib-1.19.4","sasl-2.3.4","pea-1.0"],
-  permanent}]

Our new release, "SECOND", is now the current release, but we can also see that +information, see Upgrade when Erlang/OTP has Changed.

The node is accessible through a new pipe:

% /usr/local/erl-target/bin/to_erl /tmp/erlang.pipe.2

List the available releases in the system:

1> release_handler:which_releases().
+[{"MYSYSTEM","SECOND",
+  ["kernel-3.0","stdlib-2.0","sasl-2.4","pea-2.0"],
+  current},
+ {"MYSYSTEM","FIRST",
+  ["kernel-2.16.4","stdlib-1.19.4","sasl-2.3.4","pea-1.0"],
+  permanent}]

Our new release, "SECOND", is now the current release, but we can also see that our "FIRST" release is still permanent. This means that if the node would be -restarted now, it would come up running the "FIRST" release again.

Step 3. Make the new release permanent:

2> release_handler:make_permanent("SECOND").

Check the releases again:

3> release_handler:which_releases().
-[{"MYSYSTEM","SECOND",
-  ["kernel-3.0","stdlib-2.0","sasl-2.4","pea-2.0"],
-  permanent},
- {"MYSYSTEM","FIRST",
-  ["kernel-2.16.4","stdlib-1.19.4","sasl-2.3.4","pea-1.0"],
-  old}]

We see that the new release version is permanent, so it would be safe to +restarted now, it would come up running the "FIRST" release again.

Step 3. Make the new release permanent:

2> release_handler:make_permanent("SECOND").

Check the releases again:

3> release_handler:which_releases().
+[{"MYSYSTEM","SECOND",
+  ["kernel-3.0","stdlib-2.0","sasl-2.4","pea-2.0"],
+  permanent},
+ {"MYSYSTEM","FIRST",
+  ["kernel-2.16.4","stdlib-1.19.4","sasl-2.3.4","pea-1.0"],
+  old}]

We see that the new release version is permanent, so it would be safe to restart the node.

@@ -325,8 +325,8 @@

This module can also be found in the examples directory of the SASL application.


--module(target_system).
--export([create/1, create/2, install/2]).
+-module(target_system).
+-export([create/1, create/2, install/2]).
 
 %% Note: RelFileName below is the *stem* without trailing .rel,
 %% .script etc.
@@ -334,176 +334,176 @@ 

%% create(RelFileName) %% -create(RelFileName) -> - create(RelFileName,[]). +create(RelFileName) -> + create(RelFileName,[]). -create(RelFileName,SystoolsOpts) -> +create(RelFileName,SystoolsOpts) -> RelFile = RelFileName ++ ".rel", - Dir = filename:dirname(RelFileName), - PlainRelFileName = filename:join(Dir,"plain"), + Dir = filename:dirname(RelFileName), + PlainRelFileName = filename:join(Dir,"plain"), PlainRelFile = PlainRelFileName ++ ".rel", - io:fwrite("Reading file: ~ts ...~n", [RelFile]), - {ok, [RelSpec]} = file:consult(RelFile), - io:fwrite("Creating file: ~ts from ~ts ...~n", - [PlainRelFile, RelFile]), - {release, - {RelName, RelVsn}, - {erts, ErtsVsn}, - AppVsns} = RelSpec, - PlainRelSpec = {release, - {RelName, RelVsn}, - {erts, ErtsVsn}, - lists:filter(fun({kernel, _}) -> + io:fwrite("Reading file: ~ts ...~n", [RelFile]), + {ok, [RelSpec]} = file:consult(RelFile), + io:fwrite("Creating file: ~ts from ~ts ...~n", + [PlainRelFile, RelFile]), + {release, + {RelName, RelVsn}, + {erts, ErtsVsn}, + AppVsns} = RelSpec, + PlainRelSpec = {release, + {RelName, RelVsn}, + {erts, ErtsVsn}, + lists:filter(fun({kernel, _}) -> true; - ({stdlib, _}) -> + ({stdlib, _}) -> true; - (_) -> + (_) -> false - end, AppVsns) - }, - {ok, Fd} = file:open(PlainRelFile, [write]), - io:fwrite(Fd, "~p.~n", [PlainRelSpec]), - file:close(Fd), + end, AppVsns) + }, + {ok, Fd} = file:open(PlainRelFile, [write]), + io:fwrite(Fd, "~p.~n", [PlainRelSpec]), + file:close(Fd), - io:fwrite("Making \"~ts.script\" and \"~ts.boot\" files ...~n", - [PlainRelFileName,PlainRelFileName]), - make_script(PlainRelFileName,SystoolsOpts), + io:fwrite("Making \"~ts.script\" and \"~ts.boot\" files ...~n", + [PlainRelFileName,PlainRelFileName]), + make_script(PlainRelFileName,SystoolsOpts), - io:fwrite("Making \"~ts.script\" and \"~ts.boot\" files ...~n", - [RelFileName, RelFileName]), - make_script(RelFileName,SystoolsOpts), + io:fwrite("Making \"~ts.script\" and \"~ts.boot\" files ...~n", + [RelFileName, RelFileName]), + make_script(RelFileName,SystoolsOpts), TarFileName = RelFileName ++ ".tar.gz", - io:fwrite("Creating tar file ~ts ...~n", [TarFileName]), - make_tar(RelFileName,SystoolsOpts), + io:fwrite("Creating tar file ~ts ...~n", [TarFileName]), + make_tar(RelFileName,SystoolsOpts), - TmpDir = filename:join(Dir,"tmp"), - io:fwrite("Creating directory ~tp ...~n",[TmpDir]), - file:make_dir(TmpDir), + TmpDir = filename:join(Dir,"tmp"), + io:fwrite("Creating directory ~tp ...~n",[TmpDir]), + file:make_dir(TmpDir), - io:fwrite("Extracting ~ts into directory ~ts ...~n", [TarFileName,TmpDir]), - extract_tar(TarFileName, TmpDir), + io:fwrite("Extracting ~ts into directory ~ts ...~n", [TarFileName,TmpDir]), + extract_tar(TarFileName, TmpDir), - TmpBinDir = filename:join([TmpDir, "bin"]), - ErtsBinDir = filename:join([TmpDir, "erts-" ++ ErtsVsn, "bin"]), - io:fwrite("Deleting \"erl\" and \"start\" in directory ~ts ...~n", - [ErtsBinDir]), - file:delete(filename:join([ErtsBinDir, "erl"])), - file:delete(filename:join([ErtsBinDir, "start"])), + TmpBinDir = filename:join([TmpDir, "bin"]), + ErtsBinDir = filename:join([TmpDir, "erts-" ++ ErtsVsn, "bin"]), + io:fwrite("Deleting \"erl\" and \"start\" in directory ~ts ...~n", + [ErtsBinDir]), + file:delete(filename:join([ErtsBinDir, "erl"])), + file:delete(filename:join([ErtsBinDir, "start"])), - io:fwrite("Creating temporary directory ~ts ...~n", [TmpBinDir]), - file:make_dir(TmpBinDir), + io:fwrite("Creating temporary directory ~ts ...~n", [TmpBinDir]), + file:make_dir(TmpBinDir), - io:fwrite("Copying file \"~ts.boot\" to ~ts ...~n", - [PlainRelFileName, filename:join([TmpBinDir, "start.boot"])]), - copy_file(PlainRelFileName++".boot",filename:join([TmpBinDir, "start.boot"])), + io:fwrite("Copying file \"~ts.boot\" to ~ts ...~n", + [PlainRelFileName, filename:join([TmpBinDir, "start.boot"])]), + copy_file(PlainRelFileName++".boot",filename:join([TmpBinDir, "start.boot"])), - io:fwrite("Copying files \"epmd\", \"run_erl\" and \"to_erl\" from \n" + io:fwrite("Copying files \"epmd\", \"run_erl\" and \"to_erl\" from \n" "~ts to ~ts ...~n", - [ErtsBinDir, TmpBinDir]), - copy_file(filename:join([ErtsBinDir, "epmd"]), - filename:join([TmpBinDir, "epmd"]), [preserve]), - copy_file(filename:join([ErtsBinDir, "run_erl"]), - filename:join([TmpBinDir, "run_erl"]), [preserve]), - copy_file(filename:join([ErtsBinDir, "to_erl"]), - filename:join([TmpBinDir, "to_erl"]), [preserve]), + [ErtsBinDir, TmpBinDir]), + copy_file(filename:join([ErtsBinDir, "epmd"]), + filename:join([TmpBinDir, "epmd"]), [preserve]), + copy_file(filename:join([ErtsBinDir, "run_erl"]), + filename:join([TmpBinDir, "run_erl"]), [preserve]), + copy_file(filename:join([ErtsBinDir, "to_erl"]), + filename:join([TmpBinDir, "to_erl"]), [preserve]), %% This is needed if 'start' script created from 'start.src' shall %% be used as it points out this directory as log dir for 'run_erl' - TmpLogDir = filename:join([TmpDir, "log"]), - io:fwrite("Creating temporary directory ~ts ...~n", [TmpLogDir]), - ok = file:make_dir(TmpLogDir), - - StartErlDataFile = filename:join([TmpDir, "releases", "start_erl.data"]), - io:fwrite("Creating ~ts ...~n", [StartErlDataFile]), - StartErlData = io_lib:fwrite("~s ~s~n", [ErtsVsn, RelVsn]), - write_file(StartErlDataFile, StartErlData), - - io:fwrite("Recreating tar file ~ts from contents in directory ~ts ...~n", - [TarFileName,TmpDir]), - {ok, Tar} = erl_tar:open(TarFileName, [write, compressed]), + TmpLogDir = filename:join([TmpDir, "log"]), + io:fwrite("Creating temporary directory ~ts ...~n", [TmpLogDir]), + ok = file:make_dir(TmpLogDir), + + StartErlDataFile = filename:join([TmpDir, "releases", "start_erl.data"]), + io:fwrite("Creating ~ts ...~n", [StartErlDataFile]), + StartErlData = io_lib:fwrite("~s ~s~n", [ErtsVsn, RelVsn]), + write_file(StartErlDataFile, StartErlData), + + io:fwrite("Recreating tar file ~ts from contents in directory ~ts ...~n", + [TarFileName,TmpDir]), + {ok, Tar} = erl_tar:open(TarFileName, [write, compressed]), %% {ok, Cwd} = file:get_cwd(), %% file:set_cwd("tmp"), ErtsDir = "erts-"++ErtsVsn, - erl_tar:add(Tar, filename:join(TmpDir,"bin"), "bin", []), - erl_tar:add(Tar, filename:join(TmpDir,ErtsDir), ErtsDir, []), - erl_tar:add(Tar, filename:join(TmpDir,"releases"), "releases", []), - erl_tar:add(Tar, filename:join(TmpDir,"lib"), "lib", []), - erl_tar:add(Tar, filename:join(TmpDir,"log"), "log", []), - erl_tar:close(Tar), + erl_tar:add(Tar, filename:join(TmpDir,"bin"), "bin", []), + erl_tar:add(Tar, filename:join(TmpDir,ErtsDir), ErtsDir, []), + erl_tar:add(Tar, filename:join(TmpDir,"releases"), "releases", []), + erl_tar:add(Tar, filename:join(TmpDir,"lib"), "lib", []), + erl_tar:add(Tar, filename:join(TmpDir,"log"), "log", []), + erl_tar:close(Tar), %% file:set_cwd(Cwd), - io:fwrite("Removing directory ~ts ...~n",[TmpDir]), - remove_dir_tree(TmpDir), + io:fwrite("Removing directory ~ts ...~n",[TmpDir]), + remove_dir_tree(TmpDir), ok. -install(RelFileName, RootDir) -> +install(RelFileName, RootDir) -> TarFile = RelFileName ++ ".tar.gz", - io:fwrite("Extracting ~ts ...~n", [TarFile]), - extract_tar(TarFile, RootDir), - StartErlDataFile = filename:join([RootDir, "releases", "start_erl.data"]), - {ok, StartErlData} = read_txt_file(StartErlDataFile), - [ErlVsn, _RelVsn| _] = string:tokens(StartErlData, " \n"), - ErtsBinDir = filename:join([RootDir, "erts-" ++ ErlVsn, "bin"]), - BinDir = filename:join([RootDir, "bin"]), - io:fwrite("Substituting in erl.src, start.src and start_erl.src to " - "form erl, start and start_erl ...\n"), - subst_src_scripts(["erl", "start", "start_erl"], ErtsBinDir, BinDir, - [{"FINAL_ROOTDIR", RootDir}, {"EMU", "beam"}], - [preserve]), + io:fwrite("Extracting ~ts ...~n", [TarFile]), + extract_tar(TarFile, RootDir), + StartErlDataFile = filename:join([RootDir, "releases", "start_erl.data"]), + {ok, StartErlData} = read_txt_file(StartErlDataFile), + [ErlVsn, _RelVsn| _] = string:tokens(StartErlData, " \n"), + ErtsBinDir = filename:join([RootDir, "erts-" ++ ErlVsn, "bin"]), + BinDir = filename:join([RootDir, "bin"]), + io:fwrite("Substituting in erl.src, start.src and start_erl.src to " + "form erl, start and start_erl ...\n"), + subst_src_scripts(["erl", "start", "start_erl"], ErtsBinDir, BinDir, + [{"FINAL_ROOTDIR", RootDir}, {"EMU", "beam"}], + [preserve]), %%! Workaround for pre OTP 17.0: start.src and start_erl.src did %%! not have correct permissions, so the above 'preserve' option did not help - ok = file:change_mode(filename:join(BinDir,"start"),8#0755), - ok = file:change_mode(filename:join(BinDir,"start_erl"),8#0755), + ok = file:change_mode(filename:join(BinDir,"start"),8#0755), + ok = file:change_mode(filename:join(BinDir,"start_erl"),8#0755), - io:fwrite("Creating the RELEASES file ...\n"), - create_RELEASES(RootDir, filename:join([RootDir, "releases", - filename:basename(RelFileName)])). + io:fwrite("Creating the RELEASES file ...\n"), + create_RELEASES(RootDir, filename:join([RootDir, "releases", + filename:basename(RelFileName)])). %% LOCALS %% make_script(RelFileName,Opts) %% -make_script(RelFileName,Opts) -> - systools:make_script(RelFileName, [no_module_tests, - {outdir,filename:dirname(RelFileName)} - |Opts]). +make_script(RelFileName,Opts) -> + systools:make_script(RelFileName, [no_module_tests, + {outdir,filename:dirname(RelFileName)} + |Opts]). %% make_tar(RelFileName,Opts) %% -make_tar(RelFileName,Opts) -> - RootDir = code:root_dir(), - systools:make_tar(RelFileName, [{erts, RootDir}, - {outdir,filename:dirname(RelFileName)} - |Opts]). +make_tar(RelFileName,Opts) -> + RootDir = code:root_dir(), + systools:make_tar(RelFileName, [{erts, RootDir}, + {outdir,filename:dirname(RelFileName)} + |Opts]). %% extract_tar(TarFile, DestDir) %% -extract_tar(TarFile, DestDir) -> - erl_tar:extract(TarFile, [{cwd, DestDir}, compressed]). - -create_RELEASES(DestDir, RelFileName) -> - release_handler:create_RELEASES(DestDir, RelFileName ++ ".rel"). - -subst_src_scripts(Scripts, SrcDir, DestDir, Vars, Opts) -> - lists:foreach(fun(Script) -> - subst_src_script(Script, SrcDir, DestDir, - Vars, Opts) - end, Scripts). - -subst_src_script(Script, SrcDir, DestDir, Vars, Opts) -> - subst_file(filename:join([SrcDir, Script ++ ".src"]), - filename:join([DestDir, Script]), - Vars, Opts). - -subst_file(Src, Dest, Vars, Opts) -> - {ok, Conts} = read_txt_file(Src), - NConts = subst(Conts, Vars), - write_file(Dest, NConts), - case lists:member(preserve, Opts) of +extract_tar(TarFile, DestDir) -> + erl_tar:extract(TarFile, [{cwd, DestDir}, compressed]). + +create_RELEASES(DestDir, RelFileName) -> + release_handler:create_RELEASES(DestDir, RelFileName ++ ".rel"). + +subst_src_scripts(Scripts, SrcDir, DestDir, Vars, Opts) -> + lists:foreach(fun(Script) -> + subst_src_script(Script, SrcDir, DestDir, + Vars, Opts) + end, Scripts). + +subst_src_script(Script, SrcDir, DestDir, Vars, Opts) -> + subst_file(filename:join([SrcDir, Script ++ ".src"]), + filename:join([DestDir, Script]), + Vars, Opts). + +subst_file(Src, Dest, Vars, Opts) -> + {ok, Conts} = read_txt_file(Src), + NConts = subst(Conts, Vars), + write_file(Dest, NConts), + case lists:member(preserve, Opts) of true -> - {ok, FileInfo} = file:read_file_info(Src), - file:write_file_info(Dest, FileInfo); + {ok, FileInfo} = file:read_file_info(Src), + file:write_file_info(Dest, FileInfo); false -> ok end. @@ -514,71 +514,71 @@

%% Substitute all occurrences of %Var% for Val in Str, using the list %% of variables in Vars. %% -subst(Str, Vars) -> - subst(Str, Vars, []). - -subst([$%, C| Rest], Vars, Result) when $A =< C, C =< $Z -> - subst_var([C| Rest], Vars, Result, []); -subst([$%, C| Rest], Vars, Result) when $a =< C, C =< $z -> - subst_var([C| Rest], Vars, Result, []); -subst([$%, C| Rest], Vars, Result) when C == $_ -> - subst_var([C| Rest], Vars, Result, []); -subst([C| Rest], Vars, Result) -> - subst(Rest, Vars, [C| Result]); -subst([], _Vars, Result) -> - lists:reverse(Result). - -subst_var([$%| Rest], Vars, Result, VarAcc) -> - Key = lists:reverse(VarAcc), - case lists:keysearch(Key, 1, Vars) of - {value, {Key, Value}} -> - subst(Rest, Vars, lists:reverse(Value, Result)); +subst(Str, Vars) -> + subst(Str, Vars, []). + +subst([$%, C| Rest], Vars, Result) when $A =< C, C =< $Z -> + subst_var([C| Rest], Vars, Result, []); +subst([$%, C| Rest], Vars, Result) when $a =< C, C =< $z -> + subst_var([C| Rest], Vars, Result, []); +subst([$%, C| Rest], Vars, Result) when C == $_ -> + subst_var([C| Rest], Vars, Result, []); +subst([C| Rest], Vars, Result) -> + subst(Rest, Vars, [C| Result]); +subst([], _Vars, Result) -> + lists:reverse(Result). + +subst_var([$%| Rest], Vars, Result, VarAcc) -> + Key = lists:reverse(VarAcc), + case lists:keysearch(Key, 1, Vars) of + {value, {Key, Value}} -> + subst(Rest, Vars, lists:reverse(Value, Result)); false -> - subst(Rest, Vars, [$%| VarAcc ++ [$%| Result]]) + subst(Rest, Vars, [$%| VarAcc ++ [$%| Result]]) end; -subst_var([C| Rest], Vars, Result, VarAcc) -> - subst_var(Rest, Vars, Result, [C| VarAcc]); -subst_var([], Vars, Result, VarAcc) -> - subst([], Vars, [VarAcc ++ [$%| Result]]). +subst_var([C| Rest], Vars, Result, VarAcc) -> + subst_var(Rest, Vars, Result, [C| VarAcc]); +subst_var([], Vars, Result, VarAcc) -> + subst([], Vars, [VarAcc ++ [$%| Result]]). -copy_file(Src, Dest) -> - copy_file(Src, Dest, []). +copy_file(Src, Dest) -> + copy_file(Src, Dest, []). -copy_file(Src, Dest, Opts) -> - {ok,_} = file:copy(Src, Dest), - case lists:member(preserve, Opts) of +copy_file(Src, Dest, Opts) -> + {ok,_} = file:copy(Src, Dest), + case lists:member(preserve, Opts) of true -> - {ok, FileInfo} = file:read_file_info(Src), - file:write_file_info(Dest, FileInfo); + {ok, FileInfo} = file:read_file_info(Src), + file:write_file_info(Dest, FileInfo); false -> ok end. -write_file(FName, Conts) -> - Enc = file:native_name_encoding(), - {ok, Fd} = file:open(FName, [write]), - file:write(Fd, unicode:characters_to_binary(Conts,Enc,Enc)), - file:close(Fd). +write_file(FName, Conts) -> + Enc = file:native_name_encoding(), + {ok, Fd} = file:open(FName, [write]), + file:write(Fd, unicode:characters_to_binary(Conts,Enc,Enc)), + file:close(Fd). -read_txt_file(File) -> - {ok, Bin} = file:read_file(File), - {ok, binary_to_list(Bin)}. +read_txt_file(File) -> + {ok, Bin} = file:read_file(File), + {ok, binary_to_list(Bin)}. -remove_dir_tree(Dir) -> - remove_all_files(".", [Dir]). +remove_dir_tree(Dir) -> + remove_all_files(".", [Dir]). -remove_all_files(Dir, Files) -> - lists:foreach(fun(File) -> - FilePath = filename:join([Dir, File]), - case filelib:is_dir(FilePath) of +remove_all_files(Dir, Files) -> + lists:foreach(fun(File) -> + FilePath = filename:join([Dir, File]), + case filelib:is_dir(FilePath) of true -> - {ok, DirFiles} = file:list_dir(FilePath), - remove_all_files(FilePath, DirFiles), - file:del_dir(FilePath); + {ok, DirFiles} = file:list_dir(FilePath), + remove_all_files(FilePath, DirFiles), + file:del_dir(FilePath); _ -> - file:delete(FilePath) + file:delete(FilePath) end - end, Files).

+ end, Files).

diff --git a/prs/9045/doc/system/data_types.html b/prs/9045/doc/system/data_types.html index 699d3670172e..bd6afc802acb 100644 --- a/prs/9045/doc/system/data_types.html +++ b/prs/9045/doc/system/data_types.html @@ -202,10 +202,10 @@

arithmetic operations. This is because floats are represented by a fixed number of bits in a base-2 system while printed floats are represented with a base-10 system. Erlang uses 64-bit floats. Here are examples of this phenomenon:

1> 0.1+0.2.
-0.30000000000000004

The real numbers 0.1 and 0.2 cannot be represented exactly as floats.

1> {36028797018963968.0, 36028797018963968 == 36028797018963968.0,
-  36028797018963970.0, 36028797018963970 == 36028797018963970.0}.
-{3.602879701896397e16, true,
- 3.602879701896397e16, false}.

The value 36028797018963968 can be represented exactly as a float value but +0.30000000000000004

The real numbers 0.1 and 0.2 cannot be represented exactly as floats.

1> {36028797018963968.0, 36028797018963968 == 36028797018963968.0,
+  36028797018963970.0, 36028797018963970 == 36028797018963970.0}.
+{3.602879701896397e16, true,
+ 3.602879701896397e16, false}.

The value 36028797018963968 can be represented exactly as a float value but Erlang's pretty printer rounds 36028797018963968.0 to 3.602879701896397e16 (=36028797018963970.0) as all values in the range [36028797018963966.0, 36028797018963972.0] are represented by @@ -247,11 +247,11 @@

3> <<1:1,0:1>>. <<2:2>>

The is_bitstring/1 BIF tests whether a term is a bit string, and the is_binary/1 -BIF tests whether a term is a binary.

Examples:

1> is_bitstring(<<1:1>>).
+BIF tests whether a term is a binary.

Examples:

1> is_bitstring(<<1:1>>).
 true
-2> is_binary(<<1:1>>).
+2> is_binary(<<1:1>>).
 false
-3> is_binary(<<42>>).
+3> is_binary(<<42>>).
 true
 

For more examples, see Programming Examples.

@@ -263,9 +263,9 @@

among connected nodes. A reference is created by calling the make_ref/0 BIF. The is_reference/1 BIF tests whether a term -is a reference.

Examples:

1> Ref = make_ref().
+is a reference.

Examples:

1> Ref = make_ref().
 #Ref<0.76482849.3801088007.198204>
-2> is_reference(Ref).
+2> is_reference(Ref).
 true

@@ -274,17 +274,17 @@

A fun is a functional object. Funs make it possible to create an anonymous function and pass the function itself — not its name — as argument to other -functions.

Examples:

1> Fun1 = fun (X) -> X+1 end.
+functions.

Examples:

1> Fun1 = fun (X) -> X+1 end.
 #Fun<erl_eval.6.39074546>
-2> Fun1(2).
+2> Fun1(2).
 3

The is_function/1 and is_function/2 -BIFs tests whether a term is a fun.

Examples:

1> F = fun() -> ok end.
+BIFs tests whether a term is a fun.

Examples:

1> F = fun() -> ok end.
 #Fun<erl_eval.43.105768164>
-2> is_function(F).
+2> is_function(F).
 true
-3> is_function(F, 0).
+3> is_function(F, 0).
 true
-4> is_function(F, 1).
+4> is_function(F, 1).
 false

Read more about funs in Fun Expressions. For more examples, see Programming Examples.

@@ -310,17 +310,17 @@

a message, which is the case when calling the spawn_request/5 BIF. A Pid is typically used when when sending a process a signal. The -is_pid/1 BIF tests whether a term is a Pid.

Example:

-module(m).
--export([loop/0]).
+is_pid/1 BIF tests whether a term is a Pid.

Example:

-module(m).
+-export([loop/0]).
 
-loop() ->
+loop() ->
     receive
         who_are_you ->
-            io:format("I am ~p~n", [self()]),
-            loop()
+            io:format("I am ~p~n", [self()]),
+            loop()
     end.
 
-1> P = spawn(m, loop, []).
+1> P = spawn(m, loop, []).
 <0.58.0>
 2> P ! who_are_you.
 I am <0.58.0>
@@ -331,19 +331,19 @@ 

Tuple

A tuple is a compound data type with a fixed number of terms:

{Term1,...,TermN}

Each term Term in the tuple is called an element. The number of elements is -said to be the size of the tuple.

There exists a number of BIFs to manipulate tuples.

Examples:

1> P = {adam,24,{july,29}}.
-{adam,24,{july,29}}
-2> element(1,P).
+said to be the size of the tuple.

There exists a number of BIFs to manipulate tuples.

Examples:

1> P = {adam,24,{july,29}}.
+{adam,24,{july,29}}
+2> element(1,P).
 adam
-3> element(3,P).
-{july,29}
-4> P2 = setelement(2,P,25).
-{adam,25,{july,29}}
-5> tuple_size(P).
+3> element(3,P).
+{july,29}
+4> P2 = setelement(2,P,25).
+{adam,25,{july,29}}
+5> tuple_size(P).
 3
-6> tuple_size({}).
+6> tuple_size({}).
 0
-7> is_tuple({a,b,c}).
+7> is_tuple({a,b,c}).
 true

@@ -352,17 +352,17 @@

A map is a compound data type with a variable number of key-value associations:

#{Key1 => Value1, ..., KeyN => ValueN}

Each key-value association in the map is called an association pair. The key and value parts of the pair are called elements. The number of association -pairs is said to be the size of the map.

There exists a number of BIFs to manipulate maps.

Examples:

1> M1 = #{name => adam, age => 24, date => {july,29}}.
-#{age => 24,date => {july,29},name => adam}
-2> maps:get(name, M1).
+pairs is said to be the size of the map.

There exists a number of BIFs to manipulate maps.

Examples:

1> M1 = #{name => adam, age => 24, date => {july,29}}.
+#{age => 24,date => {july,29},name => adam}
+2> maps:get(name, M1).
 adam
-3> maps:get(date, M1).
-{july,29}
-4> M2 = maps:update(age, 25, M1).
-#{age => 25,date => {july,29},name => adam}
-5> map_size(M).
+3> maps:get(date, M1).
+{july,29}
+4> M2 = maps:update(age, 25, M1).
+#{age => 25,date => {july,29},name => adam}
+5> map_size(M).
 3
-6> map_size(#{}).
+6> map_size(#{}).
 0

A collection of maps processing functions are found in module maps in STDLIB.

Read more about maps in Map Expressions.

Change

Maps were introduced as an experimental feature in Erlang/OTP R17. Their functionality was extended and became fully supported in Erlang/OTP 18.

@@ -377,19 +377,19 @@

latter can be expressed as [H|T]. The notation [Term1,...,TermN] above is equivalent with the list [Term1|[...|[TermN|[]]]].

Example:

[] is a list, thus
[c|[]] is a list, thus
[b|[c|[]]] is a list, thus
[a|[b|[c|[]]]] is a list, or in short [a,b,c]

A list where the tail is a list is sometimes called a proper list. It is allowed to have a list where the tail is not a list, for example, [a|b]. -However, this type of list is of little practical use.

Examples:

1> L1 = [a,2,{c,4}].
-[a,2,{c,4}]
-2> [H|T] = L1.
-[a,2,{c,4}]
+However, this type of list is of little practical use.

Examples:

1> L1 = [a,2,{c,4}].
+[a,2,{c,4}]
+2> [H|T] = L1.
+[a,2,{c,4}]
 3> H.
 a
 4> T.
-[2,{c,4}]
-5> L2 = [d|T].
-[d,2,{c,4}]
-6> length(L1).
+[2,{c,4}]
+5> L2 = [d|T].
+[d,2,{c,4}]
+6> length(L1).
 3
-7> length([]).
+7> length([]).
 0

A collection of list processing functions are found in module lists in STDLIB.

@@ -517,16 +517,16 @@

data type. Instead, record expressions are translated to tuple expressions during compilation. Therefore, record expressions are not understood by the shell unless special actions are taken. For details, see module shell -in STDLIB.

Examples:

-module(person).
--export([new/2]).
+in STDLIB.

Examples:

-module(person).
+-export([new/2]).
 
--record(person, {name, age}).
+-record(person, {name, age}).
 
-new(Name, Age) ->
-    #person{name=Name, age=Age}.
+new(Name, Age) ->
+    #person{name=Name, age=Age}.
 
-1> person:new(ernie, 44).
-{person,ernie,44}

Read more about records in Records. More examples are +1> person:new(ernie, 44). +{person,ernie,44}

Read more about records in Records. More examples are found in Programming Examples.

@@ -539,11 +539,11 @@

true 2> true or false. true -3> is_boolean(true). +3> is_boolean(true). true -4> is_boolean(false). +4> is_boolean(false). true -5> is_boolean(ok). +5> is_boolean(ok). false

@@ -569,39 +569,39 @@

Type Conversions

-

There are a number of BIFs for type conversions.

Examples:

1> atom_to_list(hello).
+

There are a number of BIFs for type conversions.

Examples:

1> atom_to_list(hello).
 "hello"
-2> list_to_atom("hello").
+2> list_to_atom("hello").
 hello
-3> binary_to_list(<<"hello">>).
+3> binary_to_list(<<"hello">>).
 "hello"
-4> binary_to_list(<<104,101,108,108,111>>).
+4> binary_to_list(<<104,101,108,108,111>>).
 "hello"
-5> list_to_binary("hello").
+5> list_to_binary("hello").
 <<104,101,108,108,111>>
-6> float_to_list(7.0).
+6> float_to_list(7.0).
 "7.00000000000000000000e+00"
-7> list_to_float("7.000e+00").
+7> list_to_float("7.000e+00").
 7.0
-8> integer_to_list(77).
+8> integer_to_list(77).
 "77"
-9> list_to_integer("77").
+9> list_to_integer("77").
 77
-10> tuple_to_list({a,b,c}).
-[a,b,c]
-11> list_to_tuple([a,b,c]).
-{a,b,c}
-12> term_to_binary({a,b,c}).
+10> tuple_to_list({a,b,c}).
+[a,b,c]
+11> list_to_tuple([a,b,c]).
+{a,b,c}
+12> term_to_binary({a,b,c}).
 <<131,104,3,100,0,1,97,100,0,1,98,100,0,1,99>>
-13> binary_to_term(<<131,104,3,100,0,1,97,100,0,1,98,100,0,1,99>>).
-{a,b,c}
-14> binary_to_integer(<<"77">>).
+13> binary_to_term(<<131,104,3,100,0,1,97,100,0,1,98,100,0,1,99>>).
+{a,b,c}
+14> binary_to_integer(<<"77">>).
 77
-15> integer_to_binary(77).
+15> integer_to_binary(77).
 <<"77">>
-16> float_to_binary(7.0).
+16> float_to_binary(7.0).
 <<"7.00000000000000000000e+00">>
-17> binary_to_float(<<"7.000e+00">>).
+17> binary_to_float(<<"7.000e+00">>).
 7.0

diff --git a/prs/9045/doc/system/design_principles.html b/prs/9045/doc/system/design_principles.html index b075e04b077a..4cb27d0e01aa 100644 --- a/prs/9045/doc/system/design_principles.html +++ b/prs/9045/doc/system/design_principles.html @@ -162,94 +162,94 @@

specific part. Consider the following code (written in plain Erlang) for a simple server, which keeps track of a number of "channels". Other processes can allocate and free the channels by calling the functions alloc/0 and free/1, -respectively.

-module(ch1).
--export([start/0]).
--export([alloc/0, free/1]).
--export([init/0]).
+respectively.

-module(ch1).
+-export([start/0]).
+-export([alloc/0, free/1]).
+-export([init/0]).
 
-start() ->
-    spawn(ch1, init, []).
+start() ->
+    spawn(ch1, init, []).
 
-alloc() ->
-    ch1 ! {self(), alloc},
+alloc() ->
+    ch1 ! {self(), alloc},
     receive
-        {ch1, Res} ->
+        {ch1, Res} ->
             Res
     end.
 
-free(Ch) ->
-    ch1 ! {free, Ch},
+free(Ch) ->
+    ch1 ! {free, Ch},
     ok.
 
-init() ->
-    register(ch1, self()),
-    Chs = channels(),
-    loop(Chs).
+init() ->
+    register(ch1, self()),
+    Chs = channels(),
+    loop(Chs).
 
-loop(Chs) ->
+loop(Chs) ->
     receive
-        {From, alloc} ->
-            {Ch, Chs2} = alloc(Chs),
-            From ! {ch1, Ch},
-            loop(Chs2);
-        {free, Ch} ->
-            Chs2 = free(Ch, Chs),
-            loop(Chs2)
-    end.

The code for the server can be rewritten into a generic part server.erl:

-module(server).
--export([start/1]).
--export([call/2, cast/2]).
--export([init/1]).
-
-start(Mod) ->
-    spawn(server, init, [Mod]).
-
-call(Name, Req) ->
-    Name ! {call, self(), Req},
+        {From, alloc} ->
+            {Ch, Chs2} = alloc(Chs),
+            From ! {ch1, Ch},
+            loop(Chs2);
+        {free, Ch} ->
+            Chs2 = free(Ch, Chs),
+            loop(Chs2)
+    end.

The code for the server can be rewritten into a generic part server.erl:

-module(server).
+-export([start/1]).
+-export([call/2, cast/2]).
+-export([init/1]).
+
+start(Mod) ->
+    spawn(server, init, [Mod]).
+
+call(Name, Req) ->
+    Name ! {call, self(), Req},
     receive
-        {Name, Res} ->
+        {Name, Res} ->
             Res
     end.
 
-cast(Name, Req) ->
-    Name ! {cast, Req},
+cast(Name, Req) ->
+    Name ! {cast, Req},
     ok.
 
-init(Mod) ->
-    register(Mod, self()),
-    State = Mod:init(),
-    loop(Mod, State).
+init(Mod) ->
+    register(Mod, self()),
+    State = Mod:init(),
+    loop(Mod, State).
 
-loop(Mod, State) ->
+loop(Mod, State) ->
     receive
-        {call, From, Req} ->
-            {Res, State2} = Mod:handle_call(Req, State),
-            From ! {Mod, Res},
-            loop(Mod, State2);
-        {cast, Req} ->
-            State2 = Mod:handle_cast(Req, State),
-            loop(Mod, State2)
-    end.

And a callback module ch2.erl:

-module(ch2).
--export([start/0]).
--export([alloc/0, free/1]).
--export([init/0, handle_call/2, handle_cast/2]).
-
-start() ->
-    server:start(ch2).
-
-alloc() ->
-    server:call(ch2, alloc).
-
-free(Ch) ->
-    server:cast(ch2, {free, Ch}).
-
-init() ->
-    channels().
-
-handle_call(alloc, Chs) ->
-    alloc(Chs). % => {Ch,Chs2}
-
-handle_cast({free, Ch}, Chs) ->
-    free(Ch, Chs). % => Chs2

Notice the following:

  • The code in server can be reused to build many different servers.
  • The server name, in this example the atom ch2, is hidden from the users of + {call, From, Req} -> + {Res, State2} = Mod:handle_call(Req, State), + From ! {Mod, Res}, + loop(Mod, State2); + {cast, Req} -> + State2 = Mod:handle_cast(Req, State), + loop(Mod, State2) + end.

And a callback module ch2.erl:

-module(ch2).
+-export([start/0]).
+-export([alloc/0, free/1]).
+-export([init/0, handle_call/2, handle_cast/2]).
+
+start() ->
+    server:start(ch2).
+
+alloc() ->
+    server:call(ch2, alloc).
+
+free(Ch) ->
+    server:cast(ch2, {free, Ch}).
+
+init() ->
+    channels().
+
+handle_call(alloc, Chs) ->
+    alloc(Chs). % => {Ch,Chs2}
+
+handle_cast({free, Ch}, Chs) ->
+    free(Ch, Chs). % => Chs2

Notice the following:

Example:

-moduledoc {file, "../doc/arith.asciidoc"}.
--moduledoc #{since => "0.1", format => "text/asciidoc"}.
--moduledoc #{deprecated => "Use the Erlang arithmetic operators instead."}.

+of the format.

Example:

-moduledoc {file, "../doc/arith.asciidoc"}.
+-moduledoc #{since => "0.1", format => "text/asciidoc"}.
+-moduledoc #{deprecated => "Use the Erlang arithmetic operators instead."}.

@@ -230,7 +230,7 @@

We use a special number here so that we know that this number comes from this module. """. --opaque number() :: {arith, erlang:number()}. +-opaque number() :: {arith, erlang:number()}. -doc """ Adds two numbers. @@ -241,8 +241,8 @@

1> arith:add(arith:number(1), arith:number(2)). {number, 3} ``` """. --spec add(number(), number()) -> number(). -add({number, One}, {number, Two}) -> {number, One + Two}.

+-spec add(number(), number()) -> number(). +add({number, One}, {number, Two}) -> {number, One + Two}.

@@ -254,12 +254,12 @@

automatically insert this key if there is a -deprecated attribute marking a function as deprecated.

  • equiv => unicode:chardata() | F/A | F(...) - Notes that this function is equivalent to another function in this module. The equivalence can be described using either -Func/Arity, Func(Args) or a unicode string. For example:

    -doc #{equiv => add/3}.
    -add(One, Two) -> add(One, Two, []).
    -add(One, Two, Options) -> ...

    or

    -doc #{equiv => add(One, Two, [])}.
    --spec add(One :: number(), Two :: number()) -> number().
    -add(One, Two) -> add(One, Two, []).
    -add(One, Two, Options) -> ...

    The entry into the EEP-48 doc chunk metadata is +Func/Arity, Func(Args) or a unicode string. For example:

    -doc #{equiv => add/3}.
    +add(One, Two) -> add(One, Two, []).
    +add(One, Two, Options) -> ...

    or

    -doc #{equiv => add(One, Two, [])}.
    +-spec add(One :: number(), Two :: number()) -> number().
    +add(One, Two) -> add(One, Two, []).
    +add(One, Two, Options) -> ...

    The entry into the EEP-48 doc chunk metadata is the value converted to a string.

  • exported => boolean() - A boolean/0 signifying if the entry is exported or not. This value is automatically set by the compiler and should not be set by the user.

  • @@ -270,20 +270,20 @@

    The doc signature is a short text shown to describe the function and its arguments. By default it is determined by looking at the names of the arguments in the --spec or function. For example:

    add(One, Two) -> One + Two.
    +-spec or function. For example:

    add(One, Two) -> One + Two.
     
    --spec sub(One :: integer(), Two :: integer()) -> integer().
    -sub(X, Y) -> X - Y.

    will have a signature of add(One, Two) and sub(One, Two).

    For types or callbacks, the signature is derived from the type or callback -specification. For example:

    -type number(Value) :: {number, Value}.
    +-spec sub(One :: integer(), Two :: integer()) -> integer().
    +sub(X, Y) -> X - Y.

    will have a signature of add(One, Two) and sub(One, Two).

    For types or callbacks, the signature is derived from the type or callback +specification. For example:

    -type number(Value) :: {number, Value}.
     %% signature will be `number(Value)`
     
    --opaque number() :: {number, number()}.
    +-opaque number() :: {number, number()}.
     %% signature will be `number()`
     
    --callback increment(In :: number()) -> Out.
    +-callback increment(In :: number()) -> Out.
     %% signature will be `increment(In)`
     
    --callback increment(In) -> Out when In :: number().
    +-callback increment(In) -> Out when In :: number().
     %% signature will be `increment(In)`

    If it is not possible to "easily" figure out a nice signature from the code, the MFA syntax is used instead. For example: add/2, number/1, increment/1

    It is possible to supply a custom signature by placing it as the first line of the -doc attribute. The provided signature must be in the form of a function @@ -292,7 +292,7 @@

    Adds two numbers. """. -add(A, B) -> A + B.

    Will create the signature add(One, Two). The signature will be removed from the +add(A, B) -> A + B.

    Will create the signature add(One, Two). The signature will be removed from the documentation string, so in the example above only the text "Adds two numbers" will be part of the documentation. This works for functions, types, and callbacks.

    attributes. By default, all exported functions, exported types and callbacks are considered visible and part of the modules public API. In addition, any non-exported type that is referred to by any other visible type attribute is -also visible, but not considered to be part of the public API. For example:

    -export([example/0]).
    +also visible, but not considered to be part of the public API. For example:

    -export([example/0]).
     
    --type private() :: one.
    --spec example() -> private().
    -example() -> one.

    in the above code, the function example/0 is exported and it referenced the +-type private() :: one. +-spec example() -> private(). +example() -> one.

    in the above code, the function example/0 is exported and it referenced the un-exported type private/0. Therefore both example/0 and private/0 will be marked as visible. The private/0 type will have the metadata field exported set to false to show that it is not part of the public API.

    If you want to make a visible entity hidden you need to set the -doc attribute -to false. Let us revisit our previous example:

    -export([example/0]).
    +to false. Let us revisit our previous example:

    -export([example/0]).
     
    --type private() :: one.
    --spec example() -> private().
    +-type private() :: one.
    +-spec example() -> private().
     -doc false.
    -example() -> one.

    The function example/0 is exported but explicitly marked as hidden; therefore +example() -> one.

    The function example/0 is exported but explicitly marked as hidden; therefore both example/0 and private/0 will be hidden.

    Any documentation added to an automatically hidden entity (non-exported function or type) is ignored and will generate a warning. Such functions can be documented using comments.

    @@ -385,13 +385,13 @@

    rebar3_ex_doc plugin. To set up a rebar3 project to use ExDoc to generate documentation add the following to your rebar3.config.

    %% Enable the plugin
    -{plugins, [rebar3_ex_doc]}.
    +{plugins, [rebar3_ex_doc]}.
     
    -{ex_doc, [
    -  {extras, ["README.md"]},
    -  {main, "README.md"},
    -  {source_url, "https://github.com/namespace/your_app"}
    -]}.

    When configured you can run rebar3 ex_doc to generate the +{ex_doc, [ + {extras, ["README.md"]}, + {main, "README.md"}, + {source_url, "https://github.com/namespace/your_app"} +]}.

    When configured you can run rebar3 ex_doc to generate the documentation to doc/index.html. For more details and options see the rebar3_ex_doc documentation.

    You can also download the release escript bundle from diff --git a/prs/9045/doc/system/drivers.html b/prs/9045/doc/system/drivers.html index c61efba0f6b2..188004918950 100644 --- a/prs/9045/doc/system/drivers.html +++ b/prs/9045/doc/system/drivers.html @@ -132,15 +132,15 @@

    running.

    A driver can be configured to have one lock for each port instead.

    If a driver is used in a functional way (that is, holds no state, but only does some heavy calculation and returns a result), several ports with registered names can be opened beforehand, and the port to be used can be chosen based on -the scheduler ID as follows:

    -define(PORT_NAMES(),
    -	{some_driver_01, some_driver_02, some_driver_03, some_driver_04,
    +the scheduler ID as follows:

    -define(PORT_NAMES(),
    +	{some_driver_01, some_driver_02, some_driver_03, some_driver_04,
     	 some_driver_05, some_driver_06, some_driver_07, some_driver_08,
     	 some_driver_09, some_driver_10, some_driver_11, some_driver_12,
    -	 some_driver_13, some_driver_14, some_driver_15, some_driver_16}).
    +	 some_driver_13, some_driver_14, some_driver_15, some_driver_16}).
     
    -client_port() ->
    -    element(erlang:system_info(scheduler_id) rem tuple_size(?PORT_NAMES()) + 1,
    -	    ?PORT_NAMES()).

    As long as there are no more than 16 schedulers, there will never be any lock +client_port() -> + element(erlang:system_info(scheduler_id) rem tuple_size(?PORT_NAMES()) + 1, + ?PORT_NAMES()).

    As long as there are no more than 16 schedulers, there will never be any lock contention on the port lock for the driver.

    diff --git a/prs/9045/doc/system/eff_guide_functions.html b/prs/9045/doc/system/eff_guide_functions.html index 012cc19bbc00..8ddda6f76c11 100644 --- a/prs/9045/doc/system/eff_guide_functions.html +++ b/prs/9045/doc/system/eff_guide_functions.html @@ -132,13 +132,13 @@

    rearranging clauses.

    One exception is pattern matching of binaries. The compiler does not rearrange clauses that match binaries. Placing the clause that matches against the empty binary last is usually slightly faster than placing it first.

    The following is a rather unnatural example to show another exception where -rearranging clauses is beneficial:

    DO NOT

    atom_map1(one) -> 1;
    -atom_map1(two) -> 2;
    -atom_map1(three) -> 3;
    -atom_map1(Int) when is_integer(Int) -> Int;
    -atom_map1(four) -> 4;
    -atom_map1(five) -> 5;
    -atom_map1(six) -> 6.

    The problem is the clause with the variable Int. As a variable can match +rearranging clauses is beneficial:

    DO NOT

    atom_map1(one) -> 1;
    +atom_map1(two) -> 2;
    +atom_map1(three) -> 3;
    +atom_map1(Int) when is_integer(Int) -> Int;
    +atom_map1(four) -> 4;
    +atom_map1(five) -> 5;
    +atom_map1(six) -> 6.

    The problem is the clause with the variable Int. As a variable can match anything, including the atoms four, five, and six, which the following clauses also match, the compiler must generate suboptimal code that executes as follows:

    Rewriting to either:

    DO

    atom_map2(one) -> 1;
    -atom_map2(two) -> 2;
    -atom_map2(three) -> 3;
    -atom_map2(four) -> 4;
    -atom_map2(five) -> 5;
    -atom_map2(six) -> 6;
    -atom_map2(Int) when is_integer(Int) -> Int.

    or:

    DO

    atom_map3(Int) when is_integer(Int) -> Int;
    -atom_map3(one) -> 1;
    -atom_map3(two) -> 2;
    -atom_map3(three) -> 3;
    -atom_map3(four) -> 4;
    -atom_map3(five) -> 5;
    -atom_map3(six) -> 6.

    gives slightly more efficient matching code.

    Another example:

    DO NOT

    map_pairs1(_Map, [], Ys) ->
    +exception if none of the values matched.)

    Rewriting to either:

    DO

    atom_map2(one) -> 1;
    +atom_map2(two) -> 2;
    +atom_map2(three) -> 3;
    +atom_map2(four) -> 4;
    +atom_map2(five) -> 5;
    +atom_map2(six) -> 6;
    +atom_map2(Int) when is_integer(Int) -> Int.

    or:

    DO

    atom_map3(Int) when is_integer(Int) -> Int;
    +atom_map3(one) -> 1;
    +atom_map3(two) -> 2;
    +atom_map3(three) -> 3;
    +atom_map3(four) -> 4;
    +atom_map3(five) -> 5;
    +atom_map3(six) -> 6.

    gives slightly more efficient matching code.

    Another example:

    DO NOT

    map_pairs1(_Map, [], Ys) ->
         Ys;
    -map_pairs1(_Map, Xs, []) ->
    +map_pairs1(_Map, Xs, []) ->
         Xs;
    -map_pairs1(Map, [X|Xs], [Y|Ys]) ->
    -    [Map(X, Y)|map_pairs1(Map, Xs, Ys)].

    The first argument is not a problem. It is variable, but it is a variable in +map_pairs1(Map, [X|Xs], [Y|Ys]) -> + [Map(X, Y)|map_pairs1(Map, Xs, Ys)].

    The first argument is not a problem. It is variable, but it is a variable in all clauses. The problem is the variable in the second argument, Xs, in the middle clause. Because the variable can match anything, the compiler is not allowed to rearrange the clauses, but must generate code that matches them in the order written.

    If the function is rewritten as follows, the compiler is free to rearrange the -clauses:

    DO

    map_pairs2(_Map, [], Ys) ->
    +clauses:

    DO

    map_pairs2(_Map, [], Ys) ->
         Ys;
    -map_pairs2(_Map, [_|_]=Xs, [] ) ->
    +map_pairs2(_Map, [_|_]=Xs, [] ) ->
         Xs;
    -map_pairs2(Map, [X|Xs], [Y|Ys]) ->
    -    [Map(X, Y)|map_pairs2(Map, Xs, Ys)].

    The compiler will generate code similar to this:

    DO NOT (already done by the compiler)

    explicit_map_pairs(Map, Xs0, Ys0) ->
    +map_pairs2(Map, [X|Xs], [Y|Ys]) ->
    +    [Map(X, Y)|map_pairs2(Map, Xs, Ys)].

    The compiler will generate code similar to this:

    DO NOT (already done by the compiler)

    explicit_map_pairs(Map, Xs0, Ys0) ->
         case Xs0 of
    -	[X|Xs] ->
    +	[X|Xs] ->
     	    case Ys0 of
    -		[Y|Ys] ->
    -		    [Map(X, Y)|explicit_map_pairs(Map, Xs, Ys)];
    -		[] ->
    +		[Y|Ys] ->
    +		    [Map(X, Y)|explicit_map_pairs(Map, Xs, Ys)];
    +		[] ->
     		    Xs0
     	    end;
    -	[] ->
    +	[] ->
     	    Ys0
         end.

    This is slightly faster for probably the most common case that the input lists are not empty or very short. (Another advantage is that Dialyzer can deduce a diff --git a/prs/9045/doc/system/eff_guide_processes.html b/prs/9045/doc/system/eff_guide_processes.html index 2dafd61acfec..dd1f643acce9 100644 --- a/prs/9045/doc/system/eff_guide_processes.html +++ b/prs/9045/doc/system/eff_guide_processes.html @@ -129,37 +129,37 @@

    An Erlang process is lightweight compared to threads and processes in operating systems.

    A newly spawned Erlang process uses 327 words of memory. The size can be found -as follows:

    Erlang/OTP 27 [erts-14.2.3] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit]
    +as follows:

    Erlang/OTP 27 [erts-14.2.3] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit]
     
    -Eshell V14.2.3 (press Ctrl+G to abort, type help(). for help)
    -1> Fun = fun() -> receive after infinity -> ok end end.
    +Eshell V14.2.3 (press Ctrl+G to abort, type help(). for help)
    +1> Fun = fun() -> receive after infinity -> ok end end.
     #Fun<erl_eval.43.39164016>
    -2> {_,Bytes} = process_info(spawn(Fun), memory).
    -{memory,2616}
    -3> Bytes div erlang:system_info(wordsize).
    +2> {_,Bytes} = process_info(spawn(Fun), memory).
    +{memory,2616}
    +3> Bytes div erlang:system_info(wordsize).
     327

    The size includes 233 words for the heap area (which includes the stack). The garbage collector increases the heap as needed.

    The main (outer) loop for a process must be tail-recursive. Otherwise, the -stack grows until the process terminates.

    DO NOT

    loop() ->
    +stack grows until the process terminates.

    DO NOT

    loop() ->
       receive
    -     {sys, Msg} ->
    -         handle_sys_msg(Msg),
    -         loop();
    -     {From, Msg} ->
    -          Reply = handle_msg(Msg),
    +     {sys, Msg} ->
    +         handle_sys_msg(Msg),
    +         loop();
    +     {From, Msg} ->
    +          Reply = handle_msg(Msg),
               From ! Reply,
    -          loop()
    +          loop()
       end,
    -  io:format("Message is processed~n", []).

    The call to io:format/2 will never be executed, but a return address will + io:format("Message is processed~n", []).

    The call to io:format/2 will never be executed, but a return address will still be pushed to the stack each time loop/0 is called recursively. The -correct tail-recursive version of the function looks as follows:

    DO

    loop() ->
    +correct tail-recursive version of the function looks as follows:

    DO

    loop() ->
        receive
    -      {sys, Msg} ->
    -         handle_sys_msg(Msg),
    -         loop();
    -      {From, Msg} ->
    -         Reply = handle_msg(Msg),
    +      {sys, Msg} ->
    +         handle_sys_msg(Msg),
    +         loop();
    +      {From, Msg} ->
    +         Reply = handle_msg(Msg),
              From ! Reply,
    -         loop()
    +         loop()
      end.

    @@ -199,22 +199,22 @@

    The cost of receiving messages depends on how complicated the receive expression is. A simple expression that matches any message is very cheap because it retrieves the first message in the message queue:

    DO

    receive
    -    Message -> handle_msg(Message)
    +    Message -> handle_msg(Message)
     end.

    However, this is not always convenient: we can receive a message that we do not know how to handle at this point, so it is common to only match the messages we expect:

    receive
    -    {Tag, Message} -> handle_msg(Message)
    +    {Tag, Message} -> handle_msg(Message)
     end.

    While this is convenient it means that the entire message queue must be searched until it finds a matching message. This is very expensive for processes with long message queues, so there is an optimization for the common case of -sending a request and waiting for a response shortly after:

    DO

    MRef = monitor(process, Process),
    -Process ! {self(), MRef, Request},
    +sending a request and waiting for a response shortly after:

    DO

    MRef = monitor(process, Process),
    +Process ! {self(), MRef, Request},
     receive
    -    {MRef, Reply} ->
    -        erlang:demonitor(MRef, [flush]),
    -        handle_reply(Reply);
    -    {'DOWN', MRef, _, _, Reason} ->
    -        handle_error(Reason)
    +    {MRef, Reply} ->
    +        erlang:demonitor(MRef, [flush]),
    +        handle_reply(Reply);
    +    {'DOWN', MRef, _, _, Reason} ->
    +        handle_error(Reason)
     end.

    Since the compiler knows that the reference created by monitor/2 cannot exist before the call (since it is a globally unique identifier), and that the receive only matches messages that contain @@ -238,45 +238,45 @@

    efficiency_guide.erl:222: Warning: OPTIMIZED: all clauses match reference in function parameter 1

    To make it clearer exactly what code the warnings refer to, the warnings in the following examples are inserted as comments after the clause they refer to, for example:

    %% DO
    -simple_receive() ->
    +simple_receive() ->
     %% efficiency_guide.erl:194: Warning: INFO: not a selective receive, this is always fast
     receive
    -    Message -> handle_msg(Message)
    +    Message -> handle_msg(Message)
     end.
     
     %% DO NOT, unless Tag is known to be a suitable reference: see
     %% cross_function_receive/0 further down.
    -selective_receive(Tag, Message) ->
    +selective_receive(Tag, Message) ->
     %% efficiency_guide.erl:200: Warning: NOT OPTIMIZED: all clauses do not match a suitable reference
     receive
    -    {Tag, Message} -> handle_msg(Message)
    +    {Tag, Message} -> handle_msg(Message)
     end.
     
     %% DO
    -optimized_receive(Process, Request) ->
    +optimized_receive(Process, Request) ->
     %% efficiency_guide.erl:206: Warning: OPTIMIZED: reference used to mark a message queue position
    -    MRef = monitor(process, Process),
    -    Process ! {self(), MRef, Request},
    +    MRef = monitor(process, Process),
    +    Process ! {self(), MRef, Request},
         %% efficiency_guide.erl:208: Warning: OPTIMIZED: matches reference created by monitor/2 at efficiency_guide.erl:206
         receive
    -        {MRef, Reply} ->
    -        erlang:demonitor(MRef, [flush]),
    -        handle_reply(Reply);
    -    {'DOWN', MRef, _, _, Reason} ->
    -    handle_error(Reason)
    +        {MRef, Reply} ->
    +        erlang:demonitor(MRef, [flush]),
    +        handle_reply(Reply);
    +    {'DOWN', MRef, _, _, Reason} ->
    +    handle_error(Reason)
         end.
     
     %% DO
    -cross_function_receive() ->
    +cross_function_receive() ->
         %% efficiency_guide.erl:218: Warning: OPTIMIZED: reference used to mark a message queue position
    -    Ref = make_ref(),
    +    Ref = make_ref(),
         %% efficiency_guide.erl:219: Warning: INFO: passing reference created by make_ref/0 at efficiency_guide.erl:218
    -    cross_function_receive(Ref).
    +    cross_function_receive(Ref).
     
    -cross_function_receive(Ref) ->
    +cross_function_receive(Ref) ->
         %% efficiency_guide.erl:222: Warning: OPTIMIZED: all clauses match reference in function parameter 1
         receive
    -        {Ref, Message} -> handle_msg(Message)
    +        {Ref, Message} -> handle_msg(Message)
         end.

    @@ -287,8 +287,8 @@

    each loaded module has its own pool. The following function does not build the tuple every time it is called (only to have it discarded the next time the garbage collector was run), but the tuple is located in the module's literal -pool:

    DO

    days_in_month(M) ->
    -    element(M, {31,28,31,30,31,30,31,31,30,31,30,31}).

    If a literal, or a term that contains a literal, is inserted into an Ets table, +pool:

    DO

    days_in_month(M) ->
    +    element(M, {31,28,31,30,31,30,31,31,30,31,30,31}).

    If a literal, or a term that contains a literal, is inserted into an Ets table, it is copied. The reason is that the module containing the literal can be unloaded in the future.

    When a literal is sent to another process, it is not copied. When a module holding a literal is unloaded, the literal will be copied to the heap of all @@ -303,28 +303,28 @@

    Loss of Sharing

    -

    An Erlang term can have shared subterms. Here is a simple example:

    {SubTerm, SubTerm}

    Shared subterms are not preserved in the following cases:

    • When a term is sent to another process
    • When a term is passed as the initial process arguments in the spawn call
    • When a term is stored in an Ets table

    That is an optimization. Most applications do not send messages with shared -subterms.

    The following example shows how a shared subterm can be created:

    kilo_byte() ->
    -    kilo_byte(10, [42]).
    +

    An Erlang term can have shared subterms. Here is a simple example:

    {SubTerm, SubTerm}

    Shared subterms are not preserved in the following cases:

    • When a term is sent to another process
    • When a term is passed as the initial process arguments in the spawn call
    • When a term is stored in an Ets table

    That is an optimization. Most applications do not send messages with shared +subterms.

    The following example shows how a shared subterm can be created:

    kilo_byte() ->
    +    kilo_byte(10, [42]).
     
    -kilo_byte(0, Acc) ->
    +kilo_byte(0, Acc) ->
         Acc;
    -kilo_byte(N, Acc) ->
    -    kilo_byte(N-1, [Acc|Acc]).

    kilo_byte/1 creates a deep list. If list_to_binary/1 +kilo_byte(N, Acc) -> + kilo_byte(N-1, [Acc|Acc]).

    kilo_byte/1 creates a deep list. If list_to_binary/1 is called, the deep list can be converted to a binary of 1024 bytes:

    1> byte_size(list_to_binary(efficiency_guide:kilo_byte())).
     1024

    Using the erts_debug:size/1 BIF, it can be seen that the deep list only -requires 22 words of heap space:

    2> erts_debug:size(efficiency_guide:kilo_byte()).
    +requires 22 words of heap space:

    2> erts_debug:size(efficiency_guide:kilo_byte()).
     22

    Using the erts_debug:flat_size/1 BIF, the size of the deep list can be calculated if sharing is ignored. It becomes the size of the list when it has -been sent to another process or stored in an Ets table:

    3> erts_debug:flat_size(efficiency_guide:kilo_byte()).
    +been sent to another process or stored in an Ets table:

    3> erts_debug:flat_size(efficiency_guide:kilo_byte()).
     4094

    It can be verified that sharing will be lost if the data is inserted into an Ets -table:

    4> T = ets:new(tab, []).
    +table:

    4> T = ets:new(tab, []).
     #Ref<0.1662103692.2407923716.214181>
    -5> ets:insert(T, {key,efficiency_guide:kilo_byte()}).
    +5> ets:insert(T, {key,efficiency_guide:kilo_byte()}).
     true
    -6> erts_debug:size(element(2, hd(ets:lookup(T, key)))).
    +6> erts_debug:size(element(2, hd(ets:lookup(T, key)))).
     4094
    -7> erts_debug:flat_size(element(2, hd(ets:lookup(T, key)))).
    +7> erts_debug:flat_size(element(2, hd(ets:lookup(T, key)))).
     4094

    When the data has passed through an Ets table, erts_debug:size/1 and erts_debug:flat_size/1 return the same value. Sharing has been lost.

    It is possible to build an experimental variant of the runtime system that will preserve sharing when copying terms by giving the diff --git a/prs/9045/doc/system/erl_interface.html b/prs/9045/doc/system/erl_interface.html index d880fae6231c..b74debc44218 100644 --- a/prs/9045/doc/system/erl_interface.html +++ b/prs/9045/doc/system/erl_interface.html @@ -130,111 +130,111 @@

    Erlang Program

    The following example shows an Erlang program communicating with a C program -over a plain port with home made encoding:

    -module(complex1).
    --export([start/1, stop/0, init/1]).
    --export([foo/1, bar/1]).
    +over a plain port with home made encoding:

    -module(complex1).
    +-export([start/1, stop/0, init/1]).
    +-export([foo/1, bar/1]).
     
    -start(ExtPrg) ->
    -    spawn(?MODULE, init, [ExtPrg]).
    -stop() ->
    +start(ExtPrg) ->
    +    spawn(?MODULE, init, [ExtPrg]).
    +stop() ->
         complex ! stop.
     
    -foo(X) ->
    -    call_port({foo, X}).
    -bar(Y) ->
    -    call_port({bar, Y}).
    +foo(X) ->
    +    call_port({foo, X}).
    +bar(Y) ->
    +    call_port({bar, Y}).
     
    -call_port(Msg) ->
    -    complex ! {call, self(), Msg},
    +call_port(Msg) ->
    +    complex ! {call, self(), Msg},
         receive
    -	{complex, Result} ->
    +	{complex, Result} ->
     	    Result
         end.
     
    -init(ExtPrg) ->
    -    register(complex, self()),
    -    process_flag(trap_exit, true),
    -    Port = open_port({spawn, ExtPrg}, [{packet, 2}]),
    -    loop(Port).
    +init(ExtPrg) ->
    +    register(complex, self()),
    +    process_flag(trap_exit, true),
    +    Port = open_port({spawn, ExtPrg}, [{packet, 2}]),
    +    loop(Port).
     
    -loop(Port) ->
    +loop(Port) ->
         receive
    -	{call, Caller, Msg} ->
    -	    Port ! {self(), {command, encode(Msg)}},
    +	{call, Caller, Msg} ->
    +	    Port ! {self(), {command, encode(Msg)}},
     	    receive
    -		{Port, {data, Data}} ->
    -		    Caller ! {complex, decode(Data)}
    +		{Port, {data, Data}} ->
    +		    Caller ! {complex, decode(Data)}
     	    end,
    -	    loop(Port);
    +	    loop(Port);
     	stop ->
    -	    Port ! {self(), close},
    +	    Port ! {self(), close},
     	    receive
    -		{Port, closed} ->
    -		    exit(normal)
    +		{Port, closed} ->
    +		    exit(normal)
     	    end;
    -	{'EXIT', Port, Reason} ->
    -	    exit(port_terminated)
    +	{'EXIT', Port, Reason} ->
    +	    exit(port_terminated)
         end.
     
    -encode({foo, X}) -> [1, X];
    -encode({bar, Y}) -> [2, Y].
    +encode({foo, X}) -> [1, X];
    +encode({bar, Y}) -> [2, Y].
     
    -decode([Int]) -> Int.

    There are two differences when using Erl_Interface on the C side compared to the +decode([Int]) -> Int.

    There are two differences when using Erl_Interface on the C side compared to the example in Ports, using only the plain port:

    • As Erl_Interface operates on the Erlang external term format, the port must be set to use binaries.
    • Instead of inventing an encoding/decoding scheme, the term_to_binary/1 and -binary_to_term/1 BIFs are to be used.

    That is:

    open_port({spawn, ExtPrg}, [{packet, 2}])

    is replaced with:

    open_port({spawn, ExtPrg}, [{packet, 2}, binary])

    And:

    Port ! {self(), {command, encode(Msg)}},
    +binary_to_term/1 BIFs are to be used.

    That is:

    open_port({spawn, ExtPrg}, [{packet, 2}])

    is replaced with:

    open_port({spawn, ExtPrg}, [{packet, 2}, binary])

    And:

    Port ! {self(), {command, encode(Msg)}},
     receive
    -  {Port, {data, Data}} ->
    -    Caller ! {complex, decode(Data)}
    -end

    is replaced with:

    Port ! {self(), {command, term_to_binary(Msg)}},
    +  {Port, {data, Data}} ->
    +    Caller ! {complex, decode(Data)}
    +end

    is replaced with:

    Port ! {self(), {command, term_to_binary(Msg)}},
     receive
    -  {Port, {data, Data}} ->
    -    Caller ! {complex, binary_to_term(Data)}
    -end

    The resulting Erlang program is as follows:

    -module(complex2).
    --export([start/1, stop/0, init/1]).
    --export([foo/1, bar/1]).
    -
    -start(ExtPrg) ->
    -    spawn(?MODULE, init, [ExtPrg]).
    -stop() ->
    +  {Port, {data, Data}} ->
    +    Caller ! {complex, binary_to_term(Data)}
    +end

    The resulting Erlang program is as follows:

    -module(complex2).
    +-export([start/1, stop/0, init/1]).
    +-export([foo/1, bar/1]).
    +
    +start(ExtPrg) ->
    +    spawn(?MODULE, init, [ExtPrg]).
    +stop() ->
         complex ! stop.
     
    -foo(X) ->
    -    call_port({foo, X}).
    -bar(Y) ->
    -    call_port({bar, Y}).
    +foo(X) ->
    +    call_port({foo, X}).
    +bar(Y) ->
    +    call_port({bar, Y}).
     
    -call_port(Msg) ->
    -    complex ! {call, self(), Msg},
    +call_port(Msg) ->
    +    complex ! {call, self(), Msg},
         receive
    -	{complex, Result} ->
    +	{complex, Result} ->
     	    Result
         end.
     
    -init(ExtPrg) ->
    -    register(complex, self()),
    -    process_flag(trap_exit, true),
    -    Port = open_port({spawn, ExtPrg}, [{packet, 2}, binary]),
    -    loop(Port).
    +init(ExtPrg) ->
    +    register(complex, self()),
    +    process_flag(trap_exit, true),
    +    Port = open_port({spawn, ExtPrg}, [{packet, 2}, binary]),
    +    loop(Port).
     
    -loop(Port) ->
    +loop(Port) ->
         receive
    -	{call, Caller, Msg} ->
    -	    Port ! {self(), {command, term_to_binary(Msg)}},
    +	{call, Caller, Msg} ->
    +	    Port ! {self(), {command, term_to_binary(Msg)}},
     	    receive
    -		{Port, {data, Data}} ->
    -		    Caller ! {complex, binary_to_term(Data)}
    +		{Port, {data, Data}} ->
    +		    Caller ! {complex, binary_to_term(Data)}
     	    end,
    -	    loop(Port);
    +	    loop(Port);
     	stop ->
    -	    Port ! {self(), close},
    +	    Port ! {self(), close},
     	    receive
    -		{Port, closed} ->
    -		    exit(normal)
    +		{Port, closed} ->
    +		    exit(normal)
     	    end;
    -	{'EXIT', Port, Reason} ->
    -	    exit(port_terminated)
    +	{'EXIT', Port, Reason} ->
    +	    exit(port_terminated)
         end.

    Notice that calling complex2:foo/1 and complex2:bar/1 results in the tuple {foo,X} or {bar,Y} being sent to the complex process, which codes them as binaries and sends them to the port. This means that the C program must be able @@ -254,53 +254,53 @@

    typedef unsigned char byte; -int read_cmd(byte *buf); -int write_cmd(byte *buf, int len); -int foo(int x); -int bar(int y); +int read_cmd(byte *buf); +int write_cmd(byte *buf, int len); +int foo(int x); +int bar(int y); -static void fail(int place) { - fprintf(stderr, "Something went wrong %d\n", place); - exit(1); -} +static void fail(int place) { + fprintf(stderr, "Something went wrong %d\n", place); + exit(1); +} -int main() { - byte buf[100]; +int main() { + byte buf[100]; int index = 0; int version = 0; int arity = 0; - char atom[128]; + char atom[128]; long in = 0; int res = 0; ei_x_buff res_buf; - ei_init(); - while (read_cmd(buf) > 0) { - if (ei_decode_version(buf, &index, &version) != 0) - fail(1); - if (ei_decode_tuple_header(buf, &index, &arity) != 0) - fail(2); - if (arity != 2) - fail(3); - if (ei_decode_atom(buf, &index, atom) != 0) - fail(4); - if (ei_decode_long(buf, &index, &in) != 0) - fail(5); - if (strncmp(atom, "foo", 3) == 0) { - res = foo((int)in); - } else if (strncmp(atom, "bar", 3) == 0) { - res = bar((int)in); - } - if (ei_x_new_with_version(&res_buf) != 0) - fail(6); - if (ei_x_encode_long(&res_buf, res) != 0) - fail(7); - write_cmd(res_buf.buff, res_buf.index); - - if (ei_x_free(&res_buf) != 0) - fail(8); + ei_init(); + while (read_cmd(buf) > 0) { + if (ei_decode_version(buf, &index, &version) != 0) + fail(1); + if (ei_decode_tuple_header(buf, &index, &arity) != 0) + fail(2); + if (arity != 2) + fail(3); + if (ei_decode_atom(buf, &index, atom) != 0) + fail(4); + if (ei_decode_long(buf, &index, &in) != 0) + fail(5); + if (strncmp(atom, "foo", 3) == 0) { + res = foo((int)in); + } else if (strncmp(atom, "bar", 3) == 0) { + res = bar((int)in); + } + if (ei_x_new_with_version(&res_buf) != 0) + fail(6); + if (ei_x_encode_long(&res_buf, res) != 0) + fail(7); + write_cmd(res_buf.buff, res_buf.index); + + if (ei_x_free(&res_buf) != 0) + fail(8); index = 0; - } -}

    The following functions, read_cmd() and write_cmd(), from the erl_comm.c + } +}

    The following functions, read_cmd() and write_cmd(), from the erl_comm.c example in Ports can still be used for reading from and writing to the port:

    /* erl_comm.c */
     
    @@ -309,55 +309,55 @@ 

    typedef unsigned char byte; -int read_exact(byte *buf, int len) -{ +int read_exact(byte *buf, int len) +{ int i, got=0; - do { - if ((i = read(0, buf+got, len-got)) <= 0){ - return(i); - } + do { + if ((i = read(0, buf+got, len-got)) <= 0){ + return(i); + } got += i; - } while (got<len); + } while (got<len); - return(len); -} + return(len); +} -int write_exact(byte *buf, int len) -{ +int write_exact(byte *buf, int len) +{ int i, wrote = 0; - do { - if ((i = write(1, buf+wrote, len-wrote)) <= 0) - return (i); + do { + if ((i = write(1, buf+wrote, len-wrote)) <= 0) + return (i); wrote += i; - } while (wrote<len); + } while (wrote<len); - return (len); -} + return (len); +} -int read_cmd(byte *buf) -{ +int read_cmd(byte *buf) +{ int len; - if (read_exact(buf, 2) != 2) - return(-1); - len = (buf[0] << 8) | buf[1]; - return read_exact(buf, len); -} + if (read_exact(buf, 2) != 2) + return(-1); + len = (buf[0] << 8) | buf[1]; + return read_exact(buf, len); +} -int write_cmd(byte *buf, int len) -{ +int write_cmd(byte *buf, int len) +{ byte li; - li = (len >> 8) & 0xff; - write_exact(&li, 1); + li = (len >> 8) & 0xff; + write_exact(&li, 1); li = len & 0xff; - write_exact(&li, 1); + write_exact(&li, 1); - return write_exact(buf, len); -}

    + return write_exact(buf, len); +}

    @@ -372,19 +372,19 @@

    and VSN is the version of the Erl_interface application (3.2.1 in the recent example).

    In R4B and earlier versions of OTP, include and lib are situated under $OTPROOT/usr.

    Step 2. Start Erlang and compile the Erlang code:

    $ erl
    -Erlang/OTP 26 [erts-14.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]
    +Erlang/OTP 26 [erts-14.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]
     
    -Eshell V14.2 (press Ctrl+G to abort, type help(). for help)
    -1> c(complex2).
    -{ok,complex2}

    Step 3. Run the example:

    2> complex2:start("./extprg").
    +Eshell V14.2 (press Ctrl+G to abort, type help(). for help)
    +1> c(complex2).
    +{ok,complex2}

    Step 3. Run the example:

    2> complex2:start("./extprg").
     <0.34.0>
    -3> complex2:foo(3).
    +3> complex2:foo(3).
     4
    -4> complex2:bar(5).
    +4> complex2:bar(5).
     10
    -5> complex2:bar(352).
    +5> complex2:bar(352).
     704
    -6> complex2:stop().
    +6> complex2:stop().
     stop
    diff --git a/prs/9045/doc/system/error_logging.html b/prs/9045/doc/system/error_logging.html index 2900591c5e55..108fb196c10d 100644 --- a/prs/9045/doc/system/error_logging.html +++ b/prs/9045/doc/system/error_logging.html @@ -153,7 +153,7 @@

    logger_sasl_compatible to true. For more information, see SASL Error Logging in the SASL User's Guide.

    % erl -kernel logger_level info
    -Erlang/OTP 21 [erts-10.0] [source-13c50db] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]
    +Erlang/OTP 21 [erts-10.0] [source-13c50db] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]
     
     =PROGRESS REPORT==== 8-Jun-2018::16:54:19.916404 ===
         application: kernel
    @@ -162,22 +162,22 @@ 

    application: stdlib started_at: nonode@nohost =PROGRESS REPORT==== 8-Jun-2018::16:54:19.925755 === - supervisor: {local,kernel_safe_sup} - started: [{pid,<0.74.0>}, - {id,disk_log_sup}, - {mfargs,{disk_log_sup,start_link,[]}}, - {restart_type,permanent}, - {shutdown,1000}, - {child_type,supervisor}] + supervisor: {local,kernel_safe_sup} + started: [{pid,<0.74.0>}, + {id,disk_log_sup}, + {mfargs,{disk_log_sup,start_link,[]}}, + {restart_type,permanent}, + {shutdown,1000}, + {child_type,supervisor}] =PROGRESS REPORT==== 8-Jun-2018::16:54:19.926056 === - supervisor: {local,kernel_safe_sup} - started: [{pid,<0.75.0>}, - {id,disk_log_server}, - {mfargs,{disk_log_server,start_link,[]}}, - {restart_type,permanent}, - {shutdown,2000}, - {child_type,worker}] -Eshell V10.0 (abort with ^G) + supervisor: {local,kernel_safe_sup} + started: [{pid,<0.75.0>}, + {id,disk_log_server}, + {mfargs,{disk_log_server,start_link,[]}}, + {restart_type,permanent}, + {shutdown,2000}, + {child_type,worker}] +Eshell V10.0 (abort with ^G) 1>

    diff --git a/prs/9045/doc/system/errors.html b/prs/9045/doc/system/errors.html index 55267b5ff2da..df267848dfe3 100644 --- a/prs/9045/doc/system/errors.html +++ b/prs/9045/doc/system/errors.html @@ -161,14 +161,14 @@

    Exit Reason), and a stack trace (which aids in finding the code location of the exception).

    The stack trace can be bound to a variable from within a try expression for any exception class, or as part of the exit reason when a run-time error is -caught by a catch. Example:

    > {'EXIT',{test,Stacktrace}} = (catch error(test)), Stacktrace.
    -[{shell,apply_fun,3,[]},
    - {erl_eval,do_apply,6,[]},
    - ...]
    -> try throw(test) catch Class:Reason:Stacktrace -> Stacktrace end.
    -[{shell,apply_fun,3,[]},
    - {erl_eval,do_apply,6,[]},
    - ...]

    +caught by a catch. Example:

    > {'EXIT',{test,Stacktrace}} = (catch error(test)), Stacktrace.
    +[{shell,apply_fun,3,[]},
    + {erl_eval,do_apply,6,[]},
    + ...]
    +> try throw(test) catch Class:Reason:Stacktrace -> Stacktrace end.
    +[{shell,apply_fun,3,[]},
    + {erl_eval,do_apply,6,[]},
    + ...]

    diff --git a/prs/9045/doc/system/events.html b/prs/9045/doc/system/events.html index 9b1973f8d78e..9e8ea8c84dd5 100644 --- a/prs/9045/doc/system/events.html +++ b/prs/9045/doc/system/events.html @@ -145,35 +145,35 @@

    Example

    The callback module for the event handler writing error messages to the terminal -can look as follows:

    -module(terminal_logger).
    --behaviour(gen_event).
    +can look as follows:

    -module(terminal_logger).
    +-behaviour(gen_event).
     
    --export([init/1, handle_event/2, terminate/2]).
    +-export([init/1, handle_event/2, terminate/2]).
     
    -init(_Args) ->
    -    {ok, []}.
    +init(_Args) ->
    +    {ok, []}.
     
    -handle_event(ErrorMsg, State) ->
    -    io:format("***Error*** ~p~n", [ErrorMsg]),
    -    {ok, State}.
    +handle_event(ErrorMsg, State) ->
    +    io:format("***Error*** ~p~n", [ErrorMsg]),
    +    {ok, State}.
     
    -terminate(_Args, _State) ->
    +terminate(_Args, _State) ->
         ok.

    The callback module for the event handler writing error messages to a file can -look as follows:

    -module(file_logger).
    --behaviour(gen_event).
    +look as follows:

    -module(file_logger).
    +-behaviour(gen_event).
     
    --export([init/1, handle_event/2, terminate/2]).
    +-export([init/1, handle_event/2, terminate/2]).
     
    -init(File) ->
    -    {ok, Fd} = file:open(File, read),
    -    {ok, Fd}.
    +init(File) ->
    +    {ok, Fd} = file:open(File, read),
    +    {ok, Fd}.
     
    -handle_event(ErrorMsg, Fd) ->
    -    io:format(Fd, "***Error*** ~p~n", [ErrorMsg]),
    -    {ok, Fd}.
    +handle_event(ErrorMsg, Fd) ->
    +    io:format(Fd, "***Error*** ~p~n", [ErrorMsg]),
    +    {ok, Fd}.
     
    -terminate(_Args, Fd) ->
    -    file:close(Fd).

    The code is explained in the next sections.

    +terminate(_Args, Fd) -> + file:close(Fd).

    The code is explained in the next sections.

    @@ -194,19 +194,19 @@

    Adding an Event Handler

    The following example shows how to start an event manager and add an event -handler to it by using the shell:

    1> gen_event:start({local, error_man}).
    -{ok,<0.31.0>}
    -2> gen_event:add_handler(error_man, terminal_logger, []).
    +handler to it by using the shell:

    1> gen_event:start({local, error_man}).
    +{ok,<0.31.0>}
    +2> gen_event:add_handler(error_man, terminal_logger, []).
     ok

    This function sends a message to the event manager registered as error_man, telling it to add the event handler terminal_logger. The event manager calls the callback function terminal_logger:init([]), where the argument [] is the third argument to add_handler. init/1 is expected to return {ok, State}, -where State is the internal state of the event handler.

    init(_Args) ->
    -    {ok, []}.

    Here, init/1 does not need any input data and ignores its argument. For +where State is the internal state of the event handler.

    init(_Args) ->
    +    {ok, []}.

    Here, init/1 does not need any input data and ignores its argument. For terminal_logger, the internal state is not used. For file_logger, the -internal state is used to save the open file descriptor.

    init(File) ->
    -    {ok, Fd} = file:open(File, read),
    -    {ok, Fd}.

    +internal state is used to save the open file descriptor.

    init(File) ->
    +    {ok, Fd} = file:open(File, read),
    +    {ok, Fd}.

    @@ -218,25 +218,25 @@

    is received, the event manager calls handle_event(Event, State) for each installed event handler, in the same order as they were added. The function is expected to return a tuple {ok,State1}, where State1 is a new value for the -state of the event handler.

    In terminal_logger:

    handle_event(ErrorMsg, State) ->
    -    io:format("***Error*** ~p~n", [ErrorMsg]),
    -    {ok, State}.

    In file_logger:

    handle_event(ErrorMsg, Fd) ->
    -    io:format(Fd, "***Error*** ~p~n", [ErrorMsg]),
    -    {ok, Fd}.

    +state of the event handler.

    In terminal_logger:

    handle_event(ErrorMsg, State) ->
    +    io:format("***Error*** ~p~n", [ErrorMsg]),
    +    {ok, State}.

    In file_logger:

    handle_event(ErrorMsg, Fd) ->
    +    io:format(Fd, "***Error*** ~p~n", [ErrorMsg]),
    +    {ok, Fd}.

    Deleting an Event Handler

    -
    4> gen_event:delete_handler(error_man, terminal_logger, []).
    +
    4> gen_event:delete_handler(error_man, terminal_logger, []).
     ok

    This function sends a message to the event manager registered as error_man, telling it to delete the event handler terminal_logger. The event manager calls the callback function terminal_logger:terminate([], State), where the argument [] is the third argument to delete_handler. terminate/2 is to be the opposite of init/1 and do any necessary cleaning up. Its return value is -ignored.

    For terminal_logger, no cleaning up is necessary:

    terminate(_Args, _State) ->
    -    ok.

    For file_logger, the file descriptor opened in init must be closed:

    terminate(_Args, Fd) ->
    -    file:close(Fd).

    +ignored.

    For terminal_logger, no cleaning up is necessary:

    terminate(_Args, _State) ->
    +    ok.

    For file_logger, the file descriptor opened in init must be closed:

    terminate(_Args, Fd) ->
    +    file:close(Fd).

    @@ -259,7 +259,7 @@

    Standalone Event Managers

    -

    An event manager can also be stopped by calling:

    1> gen_event:stop(error_man).
    +

    An event manager can also be stopped by calling:

    1> gen_event:stop(error_man).
     ok

    @@ -271,13 +271,13 @@

    implemented to handle them. Examples of other messages are exit messages if the event manager is linked to other processes than the supervisor (for example via gen_event:add_sup_handler/3) and is -trapping exit signals.

    handle_info({'EXIT', Pid, Reason}, State) ->
    +trapping exit signals.

    handle_info({'EXIT', Pid, Reason}, State) ->
         %% Code to handle exits here.
         ...
    -    {noreply, State1}.

    The final function to implement is code_change/3:

    code_change(OldVsn, State, Extra) ->
    +    {noreply, State1}.

    The final function to implement is code_change/3:

    code_change(OldVsn, State, Extra) ->
         %% Code to convert state (and more) during code change.
         ...
    -    {ok, NewState}.
    +
    {ok, NewState}.
    diff --git a/prs/9045/doc/system/example.html b/prs/9045/doc/system/example.html index 46dd42bc8fd8..d86c1645177a 100644 --- a/prs/9045/doc/system/example.html +++ b/prs/9045/doc/system/example.html @@ -131,17 +131,17 @@

    code, solving a complex problem, in your Erlang program. Suppose for example, that you have the following C functions that you would like to call from Erlang:

    /* complex.c */
     
    -int foo(int x) {
    +int foo(int x) {
       return x+1;
    -}
    +}
     
    -int bar(int y) {
    +int bar(int y) {
       return y*2;
    -}

    The functions are deliberately kept as simple as possible, for readability +}

    The functions are deliberately kept as simple as possible, for readability reasons.

    From an Erlang perspective, it is preferable to be able to call foo and bar without having to bother about that they are C functions:

    % Erlang code
     ...
    -Res = complex:foo(X),
    +Res = complex:foo(X),
     ...

    Here, the communication with C is hidden in the implementation of complex.erl. In the following sections, it is shown how this module can be implemented using the different interoperability mechanisms.

    diff --git a/prs/9045/doc/system/expressions.html b/prs/9045/doc/system/expressions.html index b4c9a108bca5..6ca67d9e9be8 100644 --- a/prs/9045/doc/system/expressions.html +++ b/prs/9045/doc/system/expressions.html @@ -161,12 +161,12 @@

    single assignment, that is, a variable can only be bound once.

    The anonymous variable is denoted by underscore (_) and can be used when a variable is required but its value can be ignored.

    Example:

    [H|_] = [1,2,3]

    Variables starting with underscore (_), for example, _Height, are normal variables, not anonymous. However, they are ignored by the compiler in the sense -that they do not generate warnings.

    Example:

    The following code:

    member(_, []) ->
    -    [].

    can be rewritten to be more readable:

    member(Elem, []) ->
    -    [].

    This causes a warning for an unused variable, Elem. To avoid the warning, -the code can be rewritten to:

    member(_Elem, []) ->
    -    [].

    Notice that since variables starting with an underscore are not anonymous, the -following example matches:

    {_,_} = {1,2}

    But this example fails:

    {_N,_N} = {1,2}

    The scope for a variable is its function clause. Variables bound in a branch of +that they do not generate warnings.

    Example:

    The following code:

    member(_, []) ->
    +    [].

    can be rewritten to be more readable:

    member(Elem, []) ->
    +    [].

    This causes a warning for an unused variable, Elem. To avoid the warning, +the code can be rewritten to:

    member(_Elem, []) ->
    +    [].

    Notice that since variables starting with an underscore are not anonymous, the +following example matches:

    {_,_} = {1,2}

    But this example fails:

    {_N,_N} = {1,2}

    The scope for a variable is its function clause. Variables bound in a branch of an if, case, or receive expression must be bound in all branches to have a value outside the expression. Otherwise they are regarded as unsafe outside the expression.

    For the try expression variable scoping is limited so that variables bound in @@ -177,8 +177,8 @@

    Patterns

    A pattern has the same structure as a term but can contain unbound variables.

    Example:

    Name1
    -[H|T]
    -{error,Reason}

    Patterns are allowed in clause heads, case expressions, +[H|T] +{error,Reason}

    Patterns are allowed in clause heads, case expressions, receive expressions, and match expressions.

    @@ -188,13 +188,13 @@

    If Pattern1 and Pattern2 are valid patterns, the following is also a valid pattern:

    Pattern1 = Pattern2

    When matched against a term, both Pattern1 and Pattern2 are matched against -the term. The idea behind this feature is to avoid reconstruction of terms.

    Example:

    f({connect,From,To,Number,Options}, To) ->
    -    Signal = {connect,From,To,Number,Options},
    +the term. The idea behind this feature is to avoid reconstruction of terms.

    Example:

    f({connect,From,To,Number,Options}, To) ->
    +    Signal = {connect,From,To,Number,Options},
         ...;
    -f(Signal, To) ->
    -    ignore.

    can instead be written as

    f({connect,_,To,_,_} = Signal, To) ->
    +f(Signal, To) ->
    +    ignore.

    can instead be written as

    f({connect,_,To,_,_} = Signal, To) ->
         ...;
    -f(Signal, To) ->
    +f(Signal, To) ->
         ignore.

    The compound pattern operator does not imply that its operands are matched in any particular order. That means that it is not legal to bind a variable in Pattern1 and use it in Pattern2, or vice versa.

    @@ -203,15 +203,15 @@

    String Prefix in Patterns

    -

    When matching strings, the following is a valid pattern:

    f("prefix" ++ Str) -> ...

    This is syntactic sugar for the equivalent, but harder to read:

    f([$p,$r,$e,$f,$i,$x | Str]) -> ...

    +

    When matching strings, the following is a valid pattern:

    f("prefix" ++ Str) -> ...

    This is syntactic sugar for the equivalent, but harder to read:

    f([$p,$r,$e,$f,$i,$x | Str]) -> ...

    Expressions in Patterns

    An arithmetic expression can be used within a pattern if it meets both of the -following two conditions:

    • It uses only numeric or bitwise operators.
    • Its value can be evaluated to a constant when complied.

    Example:

    case {Value, Result} of
    -    {?THRESHOLD+1, ok} -> ...

    +following two conditions:

    • It uses only numeric or bitwise operators.
    • Its value can be evaluated to a constant when complied.

    Example:

    case {Value, Result} of
    +    {?THRESHOLD+1, ok} -> ...

    @@ -219,15 +219,15 @@

    The following matches Pattern against Expr:

    Pattern = Expr

    If the matching succeeds, any unbound variable in the pattern becomes bound and the value of Expr is returned.

    If multiple match operators are applied in sequence, they will be evaluated from -right to left.

    If the matching fails, a badmatch run-time error occurs.

    Examples:

    1> {A, B} = T = {answer, 42}.
    -{answer,42}
    +right to left.

    If the matching fails, a badmatch run-time error occurs.

    Examples:

    1> {A, B} = T = {answer, 42}.
    +{answer,42}
     2> A.
     answer
     3> B.
     42
     4> T.
    -{answer,42}
    -5> {C, D} = [1, 2].
    +{answer,42}
    +5> {C, D} = [1, 2].
     ** exception error: no match of right-hand side value [1,2]

    Because multiple match operators are evaluated from right to left, it means that:

    Pattern1 = Pattern2 = . . . = PatternN = Expression

    is equivalent to:

    Temporary = Expression,
     PatternN = Temporary,
    @@ -249,20 +249,20 @@ 

    compound pattern matches if all of its constituent patterns match. It is not legal for a pattern that is part of a compound pattern to use variables (as keys in map patterns or sizes in binary patterns) bound in other sub patterns of the -same compound pattern.

    Examples:

    1> fun(#{Key := Value} = #{key := Key}) -> Value end.
    +same compound pattern.

    Examples:

    1> fun(#{Key := Value} = #{key := Key}) -> Value end.
     * 1:7: variable 'Key' is unbound
    -2> F = fun({A, B} = E) -> {E, A + B} end, F({1,2}).
    -{{1,2},3}
    -3> G = fun(<<A:8,B:8>> = <<C:16>>) -> {A, B, C} end, G(<<42,43>>).
    -{42,43,10795}

    The match operator is allowed everywhere an expression is allowed. It is used +2> F = fun({A, B} = E) -> {E, A + B} end, F({1,2}). +{{1,2},3} +3> G = fun(<<A:8,B:8>> = <<C:16>>) -> {A, B, C} end, G(<<42,43>>). +{42,43,10795}

    The match operator is allowed everywhere an expression is allowed. It is used to match the value of an expression to a pattern. If multiple match operators -are applied in sequence, they will be evaluated from right to left.

    Examples:

    1> M = #{key => key2, key2 => value}.
    -#{key => key2,key2 => value}
    -2> f(Key), #{Key := Value} = #{key := Key} = M, Value.
    +are applied in sequence, they will be evaluated from right to left.

    Examples:

    1> M = #{key => key2, key2 => value}.
    +#{key => key2,key2 => value}
    +2> f(Key), #{Key := Value} = #{key := Key} = M, Value.
     value
    -3> f(Key), #{Key := Value} = (#{key := Key} = M), Value.
    +3> f(Key), #{Key := Value} = (#{key := Key} = M), Value.
     value
    -4> f(Key), (#{Key := Value} = #{key := Key}) = M, Value.
    +4> f(Key), (#{Key := Value} = #{key := Key}) = M, Value.
     * 1:12: variable 'Key' is unbound
     5> <<X:Y>> = begin Y = 8, <<42:8>> end, X.
     42

    The expression at prompt 2> first matches the value of variable M against @@ -286,22 +286,22 @@

    Function Calls

    -
    ExprF(Expr1,...,ExprN)
    -ExprM:ExprF(Expr1,...,ExprN)

    In the first form of function calls, ExprM:ExprF(Expr1,...,ExprN), each of +

    ExprF(Expr1,...,ExprN)
    +ExprM:ExprF(Expr1,...,ExprN)

    In the first form of function calls, ExprM:ExprF(Expr1,...,ExprN), each of ExprM and ExprF must be an atom or an expression that evaluates to an atom. The function is said to be called by using the fully qualified function name. -This is often referred to as a remote or external function call.

    Example:

    lists:keyfind(Name, 1, List)

    In the second form of function calls, ExprF(Expr1,...,ExprN), ExprF must be +This is often referred to as a remote or external function call.

    Example:

    lists:keyfind(Name, 1, List)

    In the second form of function calls, ExprF(Expr1,...,ExprN), ExprF must be an atom or evaluate to a fun.

    If ExprF is an atom, the function is said to be called by using the implicitly qualified function name. If the function ExprF is locally defined, it is called. Alternatively, if ExprF is explicitly imported from the M module, M:ExprF(Expr1,...,ExprN) is called. If ExprF is neither declared locally nor explicitly imported, ExprF must be the name of an automatically -imported BIF.

    Examples:

    handle(Msg, State)
    -spawn(m, init, [])

    Examples where ExprF is a fun:

    1> Fun1 = fun(X) -> X+1 end,
    -Fun1(3).
    +imported BIF.

    Examples:

    handle(Msg, State)
    +spawn(m, init, [])

    Examples where ExprF is a fun:

    1> Fun1 = fun(X) -> X+1 end,
    +Fun1(3).
     4
    -2> fun lists:append/2([1,2], [3,4]).
    -[1,2,3,4]
    +2> fun lists:append/2([1,2], [3,4]).
    +[1,2,3,4]
     3>

    Notice that when calling a local function, there is a difference between using the implicitly or fully qualified function name. The latter always refers to the latest version of the module. See @@ -326,32 +326,32 @@

    (ERTS version 5.8) and have an implicitly qualified call to that function in your code, you either need to explicitly remove the auto-import using a compiler directive, or replace the call with a fully qualified function call. Otherwise -you get a compilation error. See the following example:

    -export([length/1,f/1]).
    +you get a compilation error. See the following example:

    -export([length/1,f/1]).
     
    --compile({no_auto_import,[length/1]}). % erlang:length/1 no longer autoimported
    +-compile({no_auto_import,[length/1]}). % erlang:length/1 no longer autoimported
     
    -length([]) ->
    +length([]) ->
         0;
    -length([H|T]) ->
    -    1 + length(T). %% Calls the local function length/1
    +length([H|T]) ->
    +    1 + length(T). %% Calls the local function length/1
     
    -f(X) when erlang:length(X) > 3 -> %% Calls erlang:length/1,
    +f(X) when erlang:length(X) > 3 -> %% Calls erlang:length/1,
                                       %% which is allowed in guards
         long.

    The same logic applies to explicitly imported functions from other modules, as to locally defined functions. It is not allowed to both import a function from -another module and have the function declared in the module at the same time:

    -export([f/1]).
    +another module and have the function declared in the module at the same time:

    -export([f/1]).
     
    --compile({no_auto_import,[length/1]}). % erlang:length/1 no longer autoimported
    +-compile({no_auto_import,[length/1]}). % erlang:length/1 no longer autoimported
     
    --import(mod,[length/1]).
    +-import(mod,[length/1]).
     
    -f(X) when erlang:length(X) > 33 -> %% Calls erlang:length/1,
    +f(X) when erlang:length(X) > 33 -> %% Calls erlang:length/1,
                                        %% which is allowed in guards
     
    -    erlang:length(X);              %% Explicit call to erlang:length in body
    +    erlang:length(X);              %% Explicit call to erlang:length in body
     
    -f(X) ->
    -    length(X).                     %% mod:length/1 is called

    For auto-imported BIFs added in Erlang/OTP R14A and thereafter, overriding the +f(X) -> + length(X). %% mod:length/1 is called

    For auto-imported BIFs added in Erlang/OTP R14A and thereafter, overriding the name with a local function or explicit import is always allowed. However, if the -compile({no_auto_import,[F/A]) directive is not used, the compiler issues a warning whenever the function is called in the module using the implicitly @@ -371,7 +371,7 @@

    sequence GuardSeq that evaluates to true is found. Then the corresponding Body (a sequence of expressions separated by ,) is evaluated.

    The return value of Body is the return value of the if expression.

    If no guard sequence is evaluated as true, an if_clause run-time error occurs. If necessary, the guard expression true can be used in the last branch, as -that guard sequence is always true.

    Example:

    is_greater_than(X, Y) ->
    +that guard sequence is always true.

    Example:

    is_greater_than(X, Y) ->
         if
             X > Y ->
                 true;
    @@ -384,19 +384,19 @@ 

    Case

    case Expr of
    -    Pattern1 [when GuardSeq1] ->
    +    Pattern1 [when GuardSeq1] ->
             Body1;
         ...;
    -    PatternN [when GuardSeqN] ->
    +    PatternN [when GuardSeqN] ->
             BodyN
     end

    The expression Expr is evaluated and the patterns Pattern are sequentially matched against the result. If a match succeeds and the optional guard sequence GuardSeq is true, the corresponding Body is evaluated.

    The return value of Body is the return value of the case expression.

    If there is no matching pattern with a true guard sequence, a case_clause -run-time error occurs.

    Example:

    is_valid_signal(Signal) ->
    +run-time error occurs.

    Example:

    is_valid_signal(Signal) ->
         case Signal of
    -        {signal, _What, _From, _To} ->
    +        {signal, _What, _From, _To} ->
                 true;
    -        {signal, _What, _To} ->
    +        {signal, _What, _To} ->
                 true;
             _Else ->
                 false
    @@ -422,9 +422,9 @@ 

    expressions in the maybe block are skipped and the return value of the maybe block is Expr2.

    None of the variables bound in a maybe block must be used in the code that follows the block.

    Here is an example:

    maybe
    -    {ok, A} ?= a(),
    +    {ok, A} ?= a(),
         true = A >= 0,
    -    {ok, B} ?= b(),
    +    {ok, B} ?= b(),
         A + B
     end

    Let us first assume that a() returns {ok,42} and b() returns {ok,58}. With those return values, all of the match operators will succeed, and the @@ -433,11 +433,11 @@

    the value of the expression that failed to match, namely error. Similarly, if b() returns wrong, the return value of the maybe block is wrong.

    Finally, let us assume that a() returns {ok,-1}. Because true = A >= 0 uses the match operator =, a {badmatch,false} run-time error occurs when the -expression fails to match the pattern.

    The example can be written in a less succinct way using nested case expressions:

    case a() of
    -    {ok, A} ->
    +expression fails to match the pattern.

    The example can be written in a less succinct way using nested case expressions:

    case a() of
    +    {ok, A} ->
             true = A >= 0,
    -        case b() of
    -            {ok, B} ->
    +        case b() of
    +            {ok, B} ->
                     A + B;
                 Other1 ->
                     Other1
    @@ -449,10 +449,10 @@ 

    ..., ExprN else - Pattern1 [when GuardSeq1] -> + Pattern1 [when GuardSeq1] -> Body1; ...; - PatternN [when GuardSeqN] -> + PatternN [when GuardSeqN] -> BodyN end

    If a conditional match operator fails, the failed expression is matched against the patterns in all clauses between the else and end keywords. If a match @@ -462,9 +462,9 @@

    run-time error occurs.

    None of the variables bound in a maybe block must be used in the else clauses. None of the variables bound in the else clauses must be used in the code that follows the maybe block.

    Here is the previous example augmented with else clauses:

    maybe
    -    {ok, A} ?= a(),
    +    {ok, A} ?= a(),
         true = A >= 0,
    -    {ok, B} ?= b(),
    +    {ok, B} ?= b(),
         A + B
     else
         error -> error;
    @@ -491,10 +491,10 @@ 

    Receive

    receive
    -    Pattern1 [when GuardSeq1] ->
    +    Pattern1 [when GuardSeq1] ->
             Body1;
         ...;
    -    PatternN [when GuardSeqN] ->
    +    PatternN [when GuardSeqN] ->
             BodyN
     end

    Fetches a received message present in the message queue of the process. The first message in the message queue is matched sequentially against the patterns @@ -506,19 +506,19 @@

    corresponding Body is evaluated. All other messages in the message queue remain unchanged.

    The return value of Body is the return value of the receive expression.

    receive never fails. The execution is suspended, possibly indefinitely, until a message arrives that matches one of the patterns and with a true guard -sequence.

    Example:

    wait_for_onhook() ->
    +sequence.

    Example:

    wait_for_onhook() ->
         receive
             onhook ->
    -            disconnect(),
    -            idle();
    -        {connect, B} ->
    -            B ! {busy, self()},
    -            wait_for_onhook()
    +            disconnect(),
    +            idle();
    +        {connect, B} ->
    +            B ! {busy, self()},
    +            wait_for_onhook()
         end.

    The receive expression can be augmented with a timeout:

    receive
    -    Pattern1 [when GuardSeq1] ->
    +    Pattern1 [when GuardSeq1] ->
             Body1;
         ...;
    -    PatternN [when GuardSeqN] ->
    +    PatternN [when GuardSeqN] ->
             BodyN
     after
         ExprT ->
    @@ -531,27 +531,27 @@ 

    timeout is almost 50 days. With a zero value the timeout occurs immediately if there is no matching message in the message queue.

    The atom infinity will make the process wait indefinitely for a matching message. This is the same as not using a timeout. It can be useful for timeout -values that are calculated at runtime.

    Example:

    wait_for_onhook() ->
    +values that are calculated at runtime.

    Example:

    wait_for_onhook() ->
         receive
             onhook ->
    -            disconnect(),
    -            idle();
    -        {connect, B} ->
    -            B ! {busy, self()},
    -            wait_for_onhook()
    +            disconnect(),
    +            idle();
    +        {connect, B} ->
    +            B ! {busy, self()},
    +            wait_for_onhook()
         after
             60000 ->
    -            disconnect(),
    -            error()
    +            disconnect(),
    +            error()
         end.

    It is legal to use a receive...after expression with no branches:

    receive
     after
         ExprT ->
             BodyT
     end

    This construction does not consume any messages, only suspends execution in the -process for ExprT milliseconds. This can be used to implement simple timers.

    Example:

    timer() ->
    -    spawn(m, timer, [self()]).
    +process for ExprT milliseconds. This can be used to implement simple timers.

    Example:

    timer() ->
    +    spawn(m, timer, [self()]).
     
    -timer(Pid) ->
    +timer(Pid) ->
         receive
         after
             5000 ->
    @@ -601,9 +601,9 @@ 

    true 6> 1 > a. false -7> #{c => 3} > #{a => 1, b => 2}. +7> #{c => 3} > #{a => 1, b => 2}. false -8> #{a => 1, b => 2} == #{a => 1.0, b => 2.0}. +8> #{a => 1, b => 2} == #{a => 1.0, b => 2.0}. true 9> <<2:2>> < <<128>>. true @@ -641,7 +641,7 @@

    ** exception error: an error occurred when evaluating an arithmetic expression in operator +/2 called as a + 10 -10> 1 bsl (1 bsl 64). +10> 1 bsl (1 bsl 64). ** exception error: a system limit has been reached in operator bsl/2 called as 1 bsl 18446744073709551616

    @@ -668,12 +668,12 @@

    Expr1 orelse Expr2
     Expr1 andalso Expr2

    Expr2 is evaluated only if necessary. That is, Expr2 is evaluated only if:

    • Expr1 evaluates to false in an orelse expression.

    or

    • Expr1 evaluates to true in an andalso expression.

    Returns either the value of Expr1 (that is, true or false) or the value of -Expr2 (if Expr2 is evaluated).

    Example 1:

    case A >= -1.0 andalso math:sqrt(A+1) > B of

    This works even if A is less than -1.0, since in that case, math:sqrt/1 is -never evaluated.

    Example 2:

    OnlyOne = is_atom(L) orelse
    -         (is_list(L) andalso length(L) == 1),

    Expr2 is not required to evaluate to a Boolean value. Because of that, -andalso and orelse are tail-recursive.

    Example 3 (tail-recursive function):

    all(Pred, [Hd|Tail]) ->
    -    Pred(Hd) andalso all(Pred, Tail);
    -all(_, []) ->
    +Expr2 (if Expr2 is evaluated).

    Example 1:

    case A >= -1.0 andalso math:sqrt(A+1) > B of

    This works even if A is less than -1.0, since in that case, math:sqrt/1 is +never evaluated.

    Example 2:

    OnlyOne = is_atom(L) orelse
    +         (is_list(L) andalso length(L) == 1),

    Expr2 is not required to evaluate to a Boolean value. Because of that, +andalso and orelse are tail-recursive.

    Example 3 (tail-recursive function):

    all(Pred, [Hd|Tail]) ->
    +    Pred(Hd) andalso all(Pred, Tail);
    +all(_, []) ->
         true.

    Change

    Before Erlang/OTP R13A, Expr2 was required to evaluate to a Boolean value, and as consequence, andalso and orelse were not tail-recursive.

    @@ -685,10 +685,10 @@

    Expr1 -- Expr2

    The list concatenation operator ++ appends its second argument to its first and returns the resulting list.

    The list subtraction operator -- produces a list that is a copy of the first argument. The procedure is as follows: for each element in the second argument, -the first occurrence of this element (if any) is removed.

    Example:

    1> [1,2,3] ++ [4,5].
    -[1,2,3,4,5]
    -2> [1,2,3,2,1,2] -- [2,1,2].
    -[3,1,2]

    +the first occurrence of this element (if any) is removed.

    Example:

    1> [1,2,3] ++ [4,5].
    +[1,2,3,4,5]
    +2> [1,2,3,2,1,2] -- [2,1,2].
    +[3,1,2]

    @@ -701,18 +701,18 @@

    Creating Maps

    Constructing a new map is done by letting an expression K be associated with -another expression V:

    #{K => V}

    New maps can include multiple associations at construction by listing every -association:

    #{K1 => V1, ..., Kn => Vn}

    An empty map is constructed by not associating any terms with each other:

    #{}

    All keys and values in the map are terms. Any expression is first evaluated and +another expression V:

    #{K => V}

    New maps can include multiple associations at construction by listing every +association:

    #{K1 => V1, ..., Kn => Vn}

    An empty map is constructed by not associating any terms with each other:

    #{}

    All keys and values in the map are terms. Any expression is first evaluated and then the resulting terms are used as key and value respectively.

    Keys and values are separated by the => arrow and associations are separated -by a comma (,).

    Examples:

    M0 = #{},                 % empty map
    -M1 = #{a => <<"hello">>}, % single association with literals
    -M2 = #{1 => 2, b => b},   % multiple associations with literals
    -M3 = #{k => {A,B}},       % single association with variables
    -M4 = #{{"w", 1} => f()}.  % compound key associated with an evaluated expression

    Here, A and B are any expressions and M0 through M4 are the resulting -map terms.

    If two matching keys are declared, the latter key takes precedence.

    Example:

    1> #{1 => a, 1 => b}.
    -#{1 => b }
    -2> #{1.0 => a, 1 => b}.
    -#{1 => b, 1.0 => a}

    The order in which the expressions constructing the keys (and their associated +by a comma (,).

    Examples:

    M0 = #{},                 % empty map
    +M1 = #{a => <<"hello">>}, % single association with literals
    +M2 = #{1 => 2, b => b},   % multiple associations with literals
    +M3 = #{k => {A,B}},       % single association with variables
    +M4 = #{{"w", 1} => f()}.  % compound key associated with an evaluated expression

    Here, A and B are any expressions and M0 through M4 are the resulting +map terms.

    If two matching keys are declared, the latter key takes precedence.

    Example:

    1> #{1 => a, 1 => b}.
    +#{1 => b }
    +2> #{1.0 => a, 1 => b}.
    +#{1 => b, 1.0 => a}

    The order in which the expressions constructing the keys (and their associated values) are evaluated is not defined. The syntactic order of the key-value pairs in the construction is of no relevance, except in the recently mentioned case of two matching keys.

    @@ -722,24 +722,24 @@

    Updating Maps

    Updating a map has a similar syntax as constructing it.

    An expression defining the map to be updated is put in front of the expression -defining the keys to be updated and their respective values:

    M#{K => V}

    Here M is a term of type map and K and V are any expression.

    If key K does not match any existing key in the map, a new association is +defining the keys to be updated and their respective values:

    M#{K => V}

    Here M is a term of type map and K and V are any expression.

    If key K does not match any existing key in the map, a new association is created from key K to value V.

    If key K matches an existing key in map M, its associated value is replaced by the new value V. In both cases, the evaluated map expression returns a new -map.

    If M is not of type map, an exception of type badmap is raised.

    To only update an existing value, the following syntax is used:

    M#{K := V}

    Here M is a term of type map, V is an expression and K is an expression +map.

    If M is not of type map, an exception of type badmap is raised.

    To only update an existing value, the following syntax is used:

    M#{K := V}

    Here M is a term of type map, V is an expression and K is an expression that evaluates to an existing key in M.

    If key K does not match any existing keys in map M, an exception of type badkey is raised at runtime. If a matching key K is present in map M, its associated value is replaced by the new value V, and the evaluated map -expression returns a new map.

    If M is not of type map, an exception of type badmap is raised.

    Examples:

    M0 = #{},
    -M1 = M0#{a => 0},
    -M2 = M1#{a => 1, b => 2},
    -M3 = M2#{"function" => fun() -> f() end},
    -M4 = M3#{a := 2, b := 3}.  % 'a' and 'b' was added in `M1` and `M2`.

    Here M0 is any map. It follows that M1 through M4 are maps as well.

    More examples:

    1> M = #{1 => a}.
    -#{1 => a }
    -2> M#{1.0 => b}.
    -#{1 => a, 1.0 => b}.
    -3> M#{1 := b}.
    -#{1 => b}
    -4> M#{1.0 := b}.
    +expression returns a new map.

    If M is not of type map, an exception of type badmap is raised.

    Examples:

    M0 = #{},
    +M1 = M0#{a => 0},
    +M2 = M1#{a => 1, b => 2},
    +M3 = M2#{"function" => fun() -> f() end},
    +M4 = M3#{a := 2, b := 3}.  % 'a' and 'b' was added in `M1` and `M2`.

    Here M0 is any map. It follows that M1 through M4 are maps as well.

    More examples:

    1> M = #{1 => a}.
    +#{1 => a }
    +2> M#{1.0 => b}.
    +#{1 => a, 1.0 => b}.
    +3> M#{1 := b}.
    +#{1 => b}
    +4> M#{1.0 := b}.
     ** exception error: bad argument

    As in construction, the order in which the key and value expressions are evaluated is not defined. The syntactic order of the key-value pairs in the update is of no relevance, except in the case where two keys match. In that @@ -749,31 +749,31 @@

    Maps in Patterns

    -

    Matching of key-value associations from maps is done as follows:

    #{K := V} = M

    Here M is any map. The key K must be a +

    Matching of key-value associations from maps is done as follows:

    #{K := V} = M

    Here M is any map. The key K must be a guard expression, with all variables already bound. V can be any pattern with either bound or unbound variables.

    If the variable V is unbound, it becomes bound to the value associated with the key K, which must exist in the map M. If the variable V is bound, it must match the value associated with K in M.

    Change

    Before Erlang/OTP 23, the expression defining the key K was restricted to be -either a single variable or a literal.

    Example:

    1> M = #{"tuple" => {1,2}}.
    -#{"tuple" => {1,2}}
    -2> #{"tuple" := {1,B}} = M.
    -#{"tuple" => {1,2}}
    +either a single variable or a literal.

    Example:

    1> M = #{"tuple" => {1,2}}.
    +#{"tuple" => {1,2}}
    +2> #{"tuple" := {1,B}} = M.
    +#{"tuple" => {1,2}}
     3> B.
    -2.

    This binds variable B to integer 2.

    Similarly, multiple values from the map can be matched:

    #{K1 := V1, ..., Kn := Vn} = M

    Here keys K1 through Kn are any expressions with literals or bound +2.

    This binds variable B to integer 2.

    Similarly, multiple values from the map can be matched:

    #{K1 := V1, ..., Kn := Vn} = M

    Here keys K1 through Kn are any expressions with literals or bound variables. If all key expressions evaluate successfully and all keys exist in map M, all variables in V1 .. Vn is matched to the associated values of their respective keys.

    If the matching conditions are not met the match fails.

    Note that when matching a map, only the := operator (not the =>) is allowed as a delimiter for the associations.

    The order in which keys are declared in matching has no relevance.

    Duplicate keys are allowed in matching and match each pattern associated to the -keys:

    #{K := V1, K := V2} = M

    The empty map literal (#{}) matches any map when used as a pattern:

    #{} = Expr

    This expression matches if the expression Expr is of type map, otherwise it -fails with an exception badmatch.

    Here the key to be retrieved is constructed from an expression:

    #{{tag,length(List)} := V} = Map

    List must be an already bound variable.

    Matching Syntax

    Matching of literals as keys are allowed in function heads:

    %% only start if not_started
    -handle_call(start, From, #{state := not_started} = S) ->
    +keys:

    #{K := V1, K := V2} = M

    The empty map literal (#{}) matches any map when used as a pattern:

    #{} = Expr

    This expression matches if the expression Expr is of type map, otherwise it +fails with an exception badmatch.

    Here the key to be retrieved is constructed from an expression:

    #{{tag,length(List)} := V} = Map

    List must be an already bound variable.

    Matching Syntax

    Matching of literals as keys are allowed in function heads:

    %% only start if not_started
    +handle_call(start, From, #{state := not_started} = S) ->
     ...
    -    {reply, ok, S#{state := start}};
    +    {reply, ok, S#{state := start}};
     
     %% only change if started
    -handle_call(change, From, #{state := start} = S) ->
    +handle_call(change, From, #{state := start} = S) ->
     ...
    -    {reply, ok, S#{state := changed}};

    + {reply, ok, S#{state := changed}};

    @@ -860,17 +860,17 @@

    types binary, bitstring, bytes, and bits.

    See also the paragraphs about Binaries.

    When constructing binaries and no size is specified for a binary segment, the entire binary value is interpolated into the binary being constructed. However, the size in bits of the binary being interpolated must be evenly divisible by -the unit value for the segment; otherwise an exception is raised.

    For example, the following examples all succeed:

    1> <<(<<"abc">>)/bitstring>>.
    +the unit value for the segment; otherwise an exception is raised.

    For example, the following examples all succeed:

    1> <<(<<"abc">>)/bitstring>>.
     <<"abc">>
    -2> <<(<<"abc">>)/binary-unit:1>>.
    +2> <<(<<"abc">>)/binary-unit:1>>.
     <<"abc">>
    -3> <<(<<"abc">>)/binary>>.
    +3> <<(<<"abc">>)/binary>>.
     <<"abc">>

    The first two examples have a unit value of 1 for the segment, while the third segment has a unit value of 8.

    Attempting to interpolate a bit string of size 1 into a binary segment with unit -8 (the default unit for binary) fails as shown in this example:

    1> <<(<<1:1>>)/binary>>.
    -** exception error: bad argument

    For the construction to succeed, the unit value of the segment must be 1:

    2> <<(<<1:1>>)/bitstring>>.
    +8 (the default unit for binary) fails as shown in this example:

    1> <<(<<1:1>>)/binary>>.
    +** exception error: bad argument

    For the construction to succeed, the unit value of the segment must be 1:

    2> <<(<<1:1>>)/bitstring>>.
     <<1:1>>
    -3> <<(<<1:1>>)/binary-unit:1>>.
    +3> <<(<<1:1>>)/binary-unit:1>>.
     <<1:1>>

    Similarly, when matching a binary segment with no size specified, the match succeeds if and only if the size in bits of the rest of the binary is evenly divisible by the unit value:

    1> <<_/binary-unit:16>> = <<"">>.
    @@ -884,9 +884,9 @@ 

    5> <<_/binary-unit:16>> = <<"abcd">>. <<"abcd">>

    When a size is explicitly specified for a binary segment, the segment size in bits is the value of Size multiplied by the default or explicit unit value.

    When constructing binaries, the size of the binary being interpolated into the -constructed binary must be at least as large as the size of the binary segment.

    Examples:

    1> <<(<<"abc">>):2/binary>>.
    +constructed binary must be at least as large as the size of the binary segment.

    Examples:

    1> <<(<<"abc">>):2/binary>>.
     <<"ab">>
    -2> <<(<<"a">>):2/binary>>.
    +2> <<(<<"a">>):2/binary>>.
     ** exception error: construction of binary failed
             *** segment 1 of type 'binary': the value <<"a">> is shorter than the size of the segment

    @@ -950,30 +950,30 @@

    Fun Expressions

    fun
    -    [Name](Pattern11,...,Pattern1N) [when GuardSeq1] ->
    +    [Name](Pattern11,...,Pattern1N) [when GuardSeq1] ->
                   Body1;
         ...;
    -    [Name](PatternK1,...,PatternKN) [when GuardSeqK] ->
    +    [Name](PatternK1,...,PatternKN) [when GuardSeqK] ->
                   BodyK
     end

    A fun expression begins with the keyword fun and ends with the keyword end. Between them is to be a function declaration, similar to a regular function declaration, except that the function name is optional and is to be a variable, if any.

    Variables in a fun head shadow the function name and both shadow variables in the function clause surrounding the fun expression. Variables bound in a fun -body are local to the fun body.

    The return value of the expression is the resulting fun.

    Examples:

    1> Fun1 = fun (X) -> X+1 end.
    +body are local to the fun body.

    The return value of the expression is the resulting fun.

    Examples:

    1> Fun1 = fun (X) -> X+1 end.
     #Fun<erl_eval.6.39074546>
    -2> Fun1(2).
    +2> Fun1(2).
     3
    -3> Fun2 = fun (X) when X>=5 -> gt; (X) -> lt end.
    +3> Fun2 = fun (X) when X>=5 -> gt; (X) -> lt end.
     #Fun<erl_eval.6.39074546>
    -4> Fun2(7).
    +4> Fun2(7).
     gt
    -5> Fun3 = fun Fact(1) -> 1; Fact(X) when X > 1 -> X * Fact(X - 1) end.
    +5> Fun3 = fun Fact(1) -> 1; Fact(X) when X > 1 -> X * Fact(X - 1) end.
     #Fun<erl_eval.6.39074546>
    -6> Fun3(4).
    +6> Fun3(4).
     24

    The following fun expressions are also allowed:

    fun Name/Arity
     fun Module:Name/Arity

    In Name/Arity, Name is an atom and Arity is an integer. Name/Arity must -specify an existing local function. The expression is syntactic sugar for:

    fun (Arg1,...,ArgN) -> Name(Arg1,...,ArgN) end

    In Module:Name/Arity, Module, and Name are atoms and Arity is an +specify an existing local function. The expression is syntactic sugar for:

    fun (Arg1,...,ArgN) -> Name(Arg1,...,ArgN) end

    In Module:Name/Arity, Module, and Name are atoms and Arity is an integer. Module, Name, and Arity can also be variables. A fun defined in this way refers to the function Name with arity Arity in the latest version of module Module. A fun defined in this way is not dependent on the @@ -991,11 +991,11 @@

    recent function calls, see Exit Reasons.

    Examples:

    1> catch 1+2.
     3
     2> catch 1+a.
    -{'EXIT',{badarith,[...]}}

    The BIF throw(Any) can be used for non-local return from a -function. It must be evaluated within a catch, which returns the value Any.

    Example:

    3> catch throw(hello).
    +{'EXIT',{badarith,[...]}}

    The BIF throw(Any) can be used for non-local return from a +function. It must be evaluated within a catch, which returns the value Any.

    Example:

    3> catch throw(hello).
     hello

    If throw/1 is not evaluated within a catch, a nocatch run-time error occurs.

    Change

    Before Erlang/OTP 24, the catch operator had the lowest precedence, making -it necessary to add parentheses when combining it with the match operator:

    1> A = (catch 42).
    +it necessary to add parentheses when combining it with the match operator:

    1> A = (catch 42).
     42
     2> A.
     42

    Starting from Erlang/OTP 24, the parentheses can be omitted:

    1> A = catch 42.
    @@ -1009,9 +1009,9 @@ 

    try Exprs
     catch
    -    Class1:ExceptionPattern1[:Stacktrace] [when ExceptionGuardSeq1] ->
    +    Class1:ExceptionPattern1[:Stacktrace] [when ExceptionGuardSeq1] ->
             ExceptionBody1;
    -    ClassN:ExceptionPatternN[:Stacktrace] [when ExceptionGuardSeqN] ->
    +    ClassN:ExceptionPatternN[:Stacktrace] [when ExceptionGuardSeqN] ->
             ExceptionBodyN
     end

    This is an enhancement of catch. It gives the possibility to:

    Examples (using a guard expression as filter):

    1> List = [1,2,a,b,c,3,4].
    +[1,2,a,b,c,3,4]
    +2> [E || E <- List, E rem 2].
    +[]
    +3> [E || E <- List, E rem 2 =:= 0].
    +[2,4]

    Examples (using a non-guard expression as filter):

    1> List = [1,2,a,b,c,3,4].
    +[1,2,a,b,c,3,4]
    +2> FaultyIsEven = fun(E) -> E rem 2 end.
     #Fun<erl_eval.42.17316486>
    -3> [E || E <- List, FaultyIsEven(E)].
    +3> [E || E <- List, FaultyIsEven(E)].
     ** exception error: bad filter 1
    -4> IsEven = fun(E) -> E rem 2 =:= 0 end.
    +4> IsEven = fun(E) -> E rem 2 =:= 0 end.
     #Fun<erl_eval.42.17316486>
    -5> [E || E <- List, IsEven(E)].
    +5> [E || E <- List, IsEven(E)].
     ** exception error: an error occurred when evaluating an arithmetic expression
          in operator  rem/2
             called as a rem 2
    -6> [E || E <- List, is_integer(E), IsEven(E)].
    -[2,4]

    +6> [E || E <- List, is_integer(E), IsEven(E)]. +[2,4]

    diff --git a/prs/9045/doc/system/funs.html b/prs/9045/doc/system/funs.html index b26dc234faa3..0b36a730207f 100644 --- a/prs/9045/doc/system/funs.html +++ b/prs/9045/doc/system/funs.html @@ -127,14 +127,14 @@

    map

    -

    The following function, double, doubles every element in a list:

    double([H|T]) -> [2*H|double(T)];
    -double([])    -> [].

    Hence, the argument entered as input is doubled as follows:

    > double([1,2,3,4]).
    -[2,4,6,8]

    The following function, add_one, adds one to every element in a list:

    add_one([H|T]) -> [H+1|add_one(T)];
    -add_one([])    -> [].

    The functions double and add_one have a similar structure. This can be used -by writing a function map that expresses this similarity:

    map(F, [H|T]) -> [F(H)|map(F, T)];
    -map(F, [])    -> [].

    The functions double and add_one can now be expressed in terms of map as -follows:

    double(L)  -> map(fun(X) -> 2*X end, L).
    -add_one(L) -> map(fun(X) -> 1 + X end, L).

    map(F, List) is a function that takes a function F and a list L as +

    The following function, double, doubles every element in a list:

    double([H|T]) -> [2*H|double(T)];
    +double([])    -> [].

    Hence, the argument entered as input is doubled as follows:

    > double([1,2,3,4]).
    +[2,4,6,8]

    The following function, add_one, adds one to every element in a list:

    add_one([H|T]) -> [H+1|add_one(T)];
    +add_one([])    -> [].

    The functions double and add_one have a similar structure. This can be used +by writing a function map that expresses this similarity:

    map(F, [H|T]) -> [F(H)|map(F, T)];
    +map(F, [])    -> [].

    The functions double and add_one can now be expressed in terms of map as +follows:

    double(L)  -> map(fun(X) -> 2*X end, L).
    +add_one(L) -> map(fun(X) -> 1 + X end, L).

    map(F, List) is a function that takes a function F and a list L as arguments and returns a new list, obtained by applying F to each of the elements in L.

    The process of abstracting out the common features of a number of different programs is called procedural abstraction. Procedural abstraction can be used @@ -148,21 +148,21 @@

    foreach

    This section illustrates procedural abstraction. Initially, the following two -examples are written as conventional functions.

    This function prints all elements of a list onto a stream:

    print_list(Stream, [H|T]) ->
    -    io:format(Stream, "~p~n", [H]),
    -    print_list(Stream, T);
    -print_list(Stream, []) ->
    -    true.

    This function broadcasts a message to a list of processes:

    broadcast(Msg, [Pid|Pids]) ->
    +examples are written as conventional functions.

    This function prints all elements of a list onto a stream:

    print_list(Stream, [H|T]) ->
    +    io:format(Stream, "~p~n", [H]),
    +    print_list(Stream, T);
    +print_list(Stream, []) ->
    +    true.

    This function broadcasts a message to a list of processes:

    broadcast(Msg, [Pid|Pids]) ->
         Pid ! Msg,
    -    broadcast(Msg, Pids);
    -broadcast(_, []) ->
    +    broadcast(Msg, Pids);
    +broadcast(_, []) ->
         true.

    These two functions have a similar structure. They both iterate over a list and do something to each element in the list. The "something" is passed on as an -extra argument to the function that does this.

    The function foreach expresses this similarity:

    foreach(F, [H|T]) ->
    -    F(H),
    -    foreach(F, T);
    -foreach(F, []) ->
    -    ok.

    Using the function foreach, the function print_list becomes:

    foreach(fun(H) -> io:format(S, "~p~n",[H]) end, L)

    Using the function foreach, the function broadcast becomes:

    foreach(fun(Pid) -> Pid ! M end, L)

    foreach is evaluated for its side-effect and not its value. foreach(Fun ,L) +extra argument to the function that does this.

    The function foreach expresses this similarity:

    foreach(F, [H|T]) ->
    +    F(H),
    +    foreach(F, T);
    +foreach(F, []) ->
    +    ok.

    Using the function foreach, the function print_list becomes:

    foreach(fun(H) -> io:format(S, "~p~n",[H]) end, L)

    Using the function foreach, the function broadcast becomes:

    foreach(fun(Pid) -> Pid ! M end, L)

    foreach is evaluated for its side-effect and not its value. foreach(Fun ,L) calls Fun(X) for each element X in L and the processing occurs in the order that the elements were defined in L. map does not define the order in which its elements are processed.

    @@ -172,24 +172,24 @@

    Syntax of Funs

    Funs are written with the following syntax (see -Fun Expressions for full description):

    F = fun (Arg1, Arg2, ... ArgN) ->
    +Fun Expressions for full description):

    F = fun (Arg1, Arg2, ... ArgN) ->
             ...
         end

    This creates an anonymous function of N arguments and binds it to the variable F.

    Another function, FunctionName, written in the same module, can be passed as an argument, using the following syntax:

    F = fun FunctionName/Arity

    With this form of function reference, the function that is referred to does not need to be exported from the module.

    It is also possible to refer to a function defined in a different module, with -the following syntax:

    F = fun Module:FunctionName/Arity

    In this case, the function must be exported from the module in question.

    The following program illustrates the different ways of creating funs:

    -module(fun_test).
    --export([t1/0, t2/0]).
    --import(lists, [map/2]).
    +the following syntax:

    F = fun Module:FunctionName/Arity

    In this case, the function must be exported from the module in question.

    The following program illustrates the different ways of creating funs:

    -module(fun_test).
    +-export([t1/0, t2/0]).
    +-import(lists, [map/2]).
     
    -t1() -> map(fun(X) -> 2 * X end, [1,2,3,4,5]).
    +t1() -> map(fun(X) -> 2 * X end, [1,2,3,4,5]).
     
    -t2() -> map(fun double/1, [1,2,3,4,5]).
    +t2() -> map(fun double/1, [1,2,3,4,5]).
     
    -double(X) -> X * 2.

    The fun F can be evaluated with the following syntax:

    F(Arg1, Arg2, ..., Argn)

    To check whether a term is a fun, use the test -is_function/1 in a guard.

    Example:

    f(F, Args) when is_function(F) ->
    -   apply(F, Args);
    -f(N, _) when is_integer(N) ->
    +double(X) -> X * 2.

    The fun F can be evaluated with the following syntax:

    F(Arg1, Arg2, ..., Argn)

    To check whether a term is a fun, use the test +is_function/1 in a guard.

    Example:

    f(F, Args) when is_function(F) ->
    +   apply(F, Args);
    +f(N, _) when is_integer(N) ->
        N.

    Funs are a distinct type. The BIFs erlang:fun_info/1,2 can be used to retrieve information about a fun, and the BIF erlang:fun_to_list/1 returns a textual representation of a fun. The check_process_code/2 @@ -202,18 +202,18 @@

    The scope rules for variables that occur in funs are as follows:

    • All variables that occur in the head of a fun are assumed to be "fresh" variables.
    • Variables that are defined before the fun, and that occur in function calls or -guard tests within the fun, have the values they had outside the fun.
    • Variables cannot be exported from a fun.

    The following examples illustrate these rules:

    print_list(File, List) ->
    -    {ok, Stream} = file:open(File, write),
    -    foreach(fun(X) -> io:format(Stream,"~p~n",[X]) end, List),
    -    file:close(Stream).

    Here, the variable X, defined in the head of the fun, is a new variable. The +guard tests within the fun, have the values they had outside the fun.

  • Variables cannot be exported from a fun.
  • The following examples illustrate these rules:

    print_list(File, List) ->
    +    {ok, Stream} = file:open(File, write),
    +    foreach(fun(X) -> io:format(Stream,"~p~n",[X]) end, List),
    +    file:close(Stream).

    Here, the variable X, defined in the head of the fun, is a new variable. The variable Stream, which is used within the fun, gets its value from the file:open line.

    As any variable that occurs in the head of a fun is considered a new variable, -it is equally valid to write as follows:

    print_list(File, List) ->
    -    {ok, Stream} = file:open(File, write),
    -    foreach(fun(File) ->
    -                io:format(Stream,"~p~n",[File])
    -            end, List),
    -    file:close(Stream).

    Here, File is used as the new variable instead of X. This is not so wise +it is equally valid to write as follows:

    print_list(File, List) ->
    +    {ok, Stream} = file:open(File, write),
    +    foreach(fun(File) ->
    +                io:format(Stream,"~p~n",[File])
    +            end, List),
    +    file:close(Stream).

    Here, File is used as the new variable instead of X. This is not so wise because code in the fun body cannot refer to the variable File, which is defined outside of the fun. Compiling this example gives the following diagnostic:

    ./FileName.erl:Line: Warning: variable 'File'
    @@ -222,20 +222,20 @@ 

    pattern matching operations must be moved into guard expressions and cannot be written in the head of the fun. For example, you might write the following code if you intend the first clause of F to be evaluated when the value of its -argument is Y:

    f(...) ->
    +argument is Y:

    f(...) ->
         Y = ...
    -    map(fun(X) when X == Y ->
    +    map(fun(X) when X == Y ->
                  ;
    -           (_) ->
    +           (_) ->
                  ...
    -        end, ...)
    -    ...

    instead of writing the following code:

    f(...) ->
    +        end, ...)
    +    ...

    instead of writing the following code:

    f(...) ->
         Y = ...
    -    map(fun(Y) ->
    +    map(fun(Y) ->
                  ;
    -           (_) ->
    +           (_) ->
                  ...
    -        end, ...)
    +        end, ...)
         ...

    @@ -249,58 +249,58 @@

    map

    -

    lists:map/2 takes a function of one argument and a list of terms:

    map(F, [H|T]) -> [F(H)|map(F, T)];
    -map(F, [])    -> [].

    It returns the list obtained by applying the function to every argument in the +

    lists:map/2 takes a function of one argument and a list of terms:

    map(F, [H|T]) -> [F(H)|map(F, T)];
    +map(F, [])    -> [].

    It returns the list obtained by applying the function to every argument in the list.

    When a new fun is defined in the shell, the value of the fun is printed as -Fun#<erl_eval>:

    > Double = fun(X) -> 2 * X end.
    +Fun#<erl_eval>:

    > Double = fun(X) -> 2 * X end.
     #Fun<erl_eval.6.72228031>
    -> lists:map(Double, [1,2,3,4,5]).
    -[2,4,6,8,10]

    +> lists:map(Double, [1,2,3,4,5]). +[2,4,6,8,10]

    any

    -

    lists:any/2 takes a predicate P of one argument and a list of terms:

    any(Pred, [H|T]) ->
    -    case Pred(H) of
    +

    lists:any/2 takes a predicate P of one argument and a list of terms:

    any(Pred, [H|T]) ->
    +    case Pred(H) of
             true  ->  true;
    -        false ->  any(Pred, T)
    +        false ->  any(Pred, T)
         end;
    -any(Pred, []) ->
    +any(Pred, []) ->
         false.

    A predicate is a function that returns true or false. any is true if there is a term X in the list such that P(X) is true.

    A predicate Big(X) is defined, which is true if its argument is greater that -10:

    > Big =  fun(X) -> if X > 10 -> true; true -> false end end.
    +10:

    > Big =  fun(X) -> if X > 10 -> true; true -> false end end.
     #Fun<erl_eval.6.72228031>
    -> lists:any(Big, [1,2,3,4]).
    +> lists:any(Big, [1,2,3,4]).
     false
    -> lists:any(Big, [1,2,3,12,5]).
    +> lists:any(Big, [1,2,3,12,5]).
     true

    all

    -

    lists:all/2 has the same arguments as any:

    all(Pred, [H|T]) ->
    -    case Pred(H) of
    -        true  ->  all(Pred, T);
    +

    lists:all/2 has the same arguments as any:

    all(Pred, [H|T]) ->
    +    case Pred(H) of
    +        true  ->  all(Pred, T);
             false ->  false
         end;
    -all(Pred, []) ->
    -    true.

    It is true if the predicate applied to all elements in the list is true.

    > lists:all(Big, [1,2,3,4,12,6]).
    +all(Pred, []) ->
    +    true.

    It is true if the predicate applied to all elements in the list is true.

    > lists:all(Big, [1,2,3,4,12,6]).
     false
    -> lists:all(Big, [12,13,14,15]).
    +> lists:all(Big, [12,13,14,15]).
     true

    foreach

    -

    lists:foreach/2 takes a function of one argument and a list of terms:

    foreach(F, [H|T]) ->
    -    F(H),
    -    foreach(F, T);
    -foreach(F, []) ->
    +

    lists:foreach/2 takes a function of one argument and a list of terms:

    foreach(F, [H|T]) ->
    +    F(H),
    +    foreach(F, T);
    +foreach(F, []) ->
         ok.

    The function is applied to each argument in the list. foreach returns ok. It -is only used for its side-effect:

    > lists:foreach(fun(X) -> io:format("~w~n",[X]) end, [1,2,3,4]).
    +is only used for its side-effect:

    > lists:foreach(fun(X) -> io:format("~w~n",[X]) end, [1,2,3,4]).
     1
     2
     3
    @@ -311,106 +311,106 @@ 

    foldl

    -

    lists:foldl/3 takes a function of two arguments, an accumulator and a list:

    foldl(F, Accu, [Hd|Tail]) ->
    -    foldl(F, F(Hd, Accu), Tail);
    -foldl(F, Accu, []) -> Accu.

    The function is called with two arguments. The first argument is the successive +

    lists:foldl/3 takes a function of two arguments, an accumulator and a list:

    foldl(F, Accu, [Hd|Tail]) ->
    +    foldl(F, F(Hd, Accu), Tail);
    +foldl(F, Accu, []) -> Accu.

    The function is called with two arguments. The first argument is the successive elements in the list. The second argument is the accumulator. The function must return a new accumulator, which is used the next time the function is called.

    If you have a list of lists L = ["I","like","Erlang"], then you can sum the -lengths of all the strings in L as follows:

    > L = ["I","like","Erlang"].
    -["I","like","Erlang"]
    -10> lists:foldl(fun(X, Sum) -> length(X) + Sum end, 0, L).
    -11

    lists:foldl/3 works like a while loop in an imperative language:

    L =  ["I","like","Erlang"],
    +lengths of all the strings in L as follows:

    > L = ["I","like","Erlang"].
    +["I","like","Erlang"]
    +10> lists:foldl(fun(X, Sum) -> length(X) + Sum end, 0, L).
    +11

    lists:foldl/3 works like a while loop in an imperative language:

    L =  ["I","like","Erlang"],
     Sum = 0,
    -while( L != []){
    -    Sum += length(head(L)),
    -    L = tail(L)
    +while( L != []){
    +    Sum += length(head(L)),
    +    L = tail(L)
     end

    mapfoldl

    -

    lists:mapfoldl/3 simultaneously maps and folds over a list:

    mapfoldl(F, Accu0, [Hd|Tail]) ->
    -    {R,Accu1} = F(Hd, Accu0),
    -    {Rs,Accu2} = mapfoldl(F, Accu1, Tail),
    -    {[R|Rs], Accu2};
    -mapfoldl(F, Accu, []) -> {[], Accu}.

    The following example shows how to change all letters in L to upper case and -then count them.

    First the change to upper case:

    > Upcase =  fun(X) when $a =< X,  X =< $z -> X + $A - $a;
    -(X) -> X
    +

    lists:mapfoldl/3 simultaneously maps and folds over a list:

    mapfoldl(F, Accu0, [Hd|Tail]) ->
    +    {R,Accu1} = F(Hd, Accu0),
    +    {Rs,Accu2} = mapfoldl(F, Accu1, Tail),
    +    {[R|Rs], Accu2};
    +mapfoldl(F, Accu, []) -> {[], Accu}.

    The following example shows how to change all letters in L to upper case and +then count them.

    First the change to upper case:

    > Upcase =  fun(X) when $a =< X,  X =< $z -> X + $A - $a;
    +(X) -> X
     end.
     #Fun<erl_eval.6.72228031>
     > Upcase_word =
    -fun(X) ->
    -lists:map(Upcase, X)
    +fun(X) ->
    +lists:map(Upcase, X)
     end.
     #Fun<erl_eval.6.72228031>
    -> Upcase_word("Erlang").
    +> Upcase_word("Erlang").
     "ERLANG"
    -> lists:map(Upcase_word, L).
    -["I","LIKE","ERLANG"]

    Now, the fold and the map can be done at the same time:

    > lists:mapfoldl(fun(Word, Sum) ->
    -{Upcase_word(Word), Sum + length(Word)}
    -end, 0, L).
    -{["I","LIKE","ERLANG"],11}

    +> lists:map(Upcase_word, L). +["I","LIKE","ERLANG"]

    Now, the fold and the map can be done at the same time:

    > lists:mapfoldl(fun(Word, Sum) ->
    +{Upcase_word(Word), Sum + length(Word)}
    +end, 0, L).
    +{["I","LIKE","ERLANG"],11}

    filter

    lists:filter/2 takes a predicate of one argument and a list and returns all elements -in the list that satisfy the predicate:

    filter(F, [H|T]) ->
    -    case F(H) of
    -        true  -> [H|filter(F, T)];
    -        false -> filter(F, T)
    +in the list that satisfy the predicate:

    filter(F, [H|T]) ->
    +    case F(H) of
    +        true  -> [H|filter(F, T)];
    +        false -> filter(F, T)
         end;
    -filter(F, []) -> [].
    > lists:filter(Big, [500,12,2,45,6,7]).
    -[500,12,45]

    Combining maps and filters enables writing of very succinct code. For example, +filter(F, []) -> [].

    > lists:filter(Big, [500,12,2,45,6,7]).
    +[500,12,45]

    Combining maps and filters enables writing of very succinct code. For example, to define a set difference function diff(L1, L2) to be the difference between -the lists L1 and L2, the code can be written as follows:

    diff(L1, L2) ->
    -    filter(fun(X) -> not member(X, L2) end, L1).

    This gives the list of all elements in L1 that are not contained in L2.

    The AND intersection of the list L1 and L2 is also easily defined:

    intersection(L1,L2) -> filter(fun(X) -> member(X,L1) end, L2).

    +the lists L1 and L2, the code can be written as follows:

    diff(L1, L2) ->
    +    filter(fun(X) -> not member(X, L2) end, L1).

    This gives the list of all elements in L1 that are not contained in L2.

    The AND intersection of the list L1 and L2 is also easily defined:

    intersection(L1,L2) -> filter(fun(X) -> member(X,L1) end, L2).

    takewhile

    lists:takewhile/2 takes elements X from a list L as long as the predicate -P(X) is true:

    takewhile(Pred, [H|T]) ->
    -    case Pred(H) of
    -        true  -> [H|takewhile(Pred, T)];
    -        false -> []
    +P(X) is true:

    takewhile(Pred, [H|T]) ->
    +    case Pred(H) of
    +        true  -> [H|takewhile(Pred, T)];
    +        false -> []
         end;
    -takewhile(Pred, []) ->
    -    [].
    > lists:takewhile(Big, [200,500,45,5,3,45,6]).
    -[200,500,45]

    +takewhile(Pred, []) -> + [].

    > lists:takewhile(Big, [200,500,45,5,3,45,6]).
    +[200,500,45]

    dropwhile

    -

    lists:dropwhile/2 is the complement of takewhile:

    dropwhile(Pred, [H|T]) ->
    -    case Pred(H) of
    -        true  -> dropwhile(Pred, T);
    -        false -> [H|T]
    +

    lists:dropwhile/2 is the complement of takewhile:

    dropwhile(Pred, [H|T]) ->
    +    case Pred(H) of
    +        true  -> dropwhile(Pred, T);
    +        false -> [H|T]
         end;
    -dropwhile(Pred, []) ->
    -    [].
    > lists:dropwhile(Big, [200,500,45,5,3,45,6]).
    -[5,3,45,6]

    +dropwhile(Pred, []) -> + [].

    > lists:dropwhile(Big, [200,500,45,5,3,45,6]).
    +[5,3,45,6]

    splitwith

    lists:splitwith/2 splits the list L into the two sublists {L1, L2}, where -L = takewhile(P, L) and L2 = dropwhile(P, L):

    splitwith(Pred, L) ->
    -    splitwith(Pred, L, []).
    +L = takewhile(P, L) and L2 = dropwhile(P, L):

    splitwith(Pred, L) ->
    +    splitwith(Pred, L, []).
     
    -splitwith(Pred, [H|T], L) ->
    -    case Pred(H) of
    -        true  -> splitwith(Pred, T, [H|L]);
    -        false -> {reverse(L), [H|T]}
    +splitwith(Pred, [H|T], L) ->
    +    case Pred(H) of
    +        true  -> splitwith(Pred, T, [H|L]);
    +        false -> {reverse(L), [H|T]}
         end;
    -splitwith(Pred, [], L) ->
    -    {reverse(L), []}.
    > lists:splitwith(Big, [200,500,45,5,3,45,6]).
    -{[200,500,45],[5,3,45,6]}

    +splitwith(Pred, [], L) -> + {reverse(L), []}.

    > lists:splitwith(Big, [200,500,45,5,3,45,6]).
    +{[200,500,45],[5,3,45,6]}

    @@ -425,60 +425,60 @@

    Simple Higher Order Functions

    Adder(X) is a function that given X, returns a new function G such that -G(K) returns K + X:

    > Adder = fun(X) -> fun(Y) -> X + Y end end.
    +G(K) returns K + X:

    > Adder = fun(X) -> fun(Y) -> X + Y end end.
     #Fun<erl_eval.6.72228031>
    -> Add6 = Adder(6).
    +> Add6 = Adder(6).
     #Fun<erl_eval.6.72228031>
    -> Add6(10).
    +> Add6(10).
     16

    Infinite Lists

    -

    The idea is to write something like:

    -module(lazy).
    --export([ints_from/1]).
    -ints_from(N) ->
    -    fun() ->
    -            [N|ints_from(N+1)]
    -    end.

    Then proceed as follows:

    > XX = lazy:ints_from(1).
    +

    The idea is to write something like:

    -module(lazy).
    +-export([ints_from/1]).
    +ints_from(N) ->
    +    fun() ->
    +            [N|ints_from(N+1)]
    +    end.

    Then proceed as follows:

    > XX = lazy:ints_from(1).
     #Fun<lazy.0.29874839>
    -> XX().
    -[1|#Fun<lazy.0.29874839>]
    -> hd(XX()).
    +> XX().
    +[1|#Fun<lazy.0.29874839>]
    +> hd(XX()).
     1
    -> Y = tl(XX()).
    +> Y = tl(XX()).
     #Fun<lazy.0.29874839>
    -> hd(Y()).
    +> hd(Y()).
     2

    And so on. This is an example of "lazy embedding".

    Parsing

    -

    The following examples show parsers of the following type:

    Parser(Toks) -> {ok, Tree, Toks1} | fail

    Toks is the list of tokens to be parsed. A successful parse returns +

    The following examples show parsers of the following type:

    Parser(Toks) -> {ok, Tree, Toks1} | fail

    Toks is the list of tokens to be parsed. A successful parse returns {ok, Tree, Toks1}.

    • Tree is a parse tree.
    • Toks1 is a tail of Tree that contains symbols encountered after the structure that was correctly parsed.

    An unsuccessful parse returns fail.

    The following example illustrates a simple, functional parser that parses the grammar:

    (a | b) & (c | d)

    The following code defines a function pconst(X) in the module funparse, -which returns a fun that parses a list of tokens:

    pconst(X) ->
    -    fun (T) ->
    +which returns a fun that parses a list of tokens:

    pconst(X) ->
    +    fun (T) ->
            case T of
    -           [X|T1] -> {ok, {const, X}, T1};
    +           [X|T1] -> {ok, {const, X}, T1};
                _      -> fail
            end
    -    end.

    This function can be used as follows:

    > P1 = funparse:pconst(a).
    +    end.

    This function can be used as follows:

    > P1 = funparse:pconst(a).
     #Fun<funparse.0.22674075>
    -> P1([a,b,c]).
    -{ok,{const,a},[b,c]}
    -> P1([x,y,z]).
    +> P1([a,b,c]).
    +{ok,{const,a},[b,c]}
    +> P1([x,y,z]).
     fail

    Next, the two higher order functions pand and por are defined. They combine -primitive parsers to produce more complex parsers.

    First pand:

    pand(P1, P2) ->
    -    fun (T) ->
    -        case P1(T) of
    -            {ok, R1, T1} ->
    -                case P2(T1) of
    -                    {ok, R2, T2} ->
    -                        {ok, {'and', R1, R2}};
    +primitive parsers to produce more complex parsers.

    First pand:

    pand(P1, P2) ->
    +    fun (T) ->
    +        case P1(T) of
    +            {ok, R1, T1} ->
    +                case P2(T1) of
    +                    {ok, R2, T2} ->
    +                        {ok, {'and', R1, R2}};
                         fail ->
                             fail
                     end;
    @@ -488,33 +488,33 @@ 

    end.

    Given a parser P1 for grammar G1, and a parser P2 for grammar G2, pand(P1, P2) returns a parser for the grammar, which consists of sequences of tokens that satisfy G1, followed by sequences of tokens that satisfy G2.

    por(P1, P2) returns a parser for the language described by the grammar G1 or -G2:

    por(P1, P2) ->
    -    fun (T) ->
    -        case P1(T) of
    -            {ok, R, T1} ->
    -                {ok, {'or',1,R}, T1};
    +G2:

    por(P1, P2) ->
    +    fun (T) ->
    +        case P1(T) of
    +            {ok, R, T1} ->
    +                {ok, {'or',1,R}, T1};
                 fail ->
    -                case P2(T) of
    -                    {ok, R1, T1} ->
    -                        {ok, {'or',2,R1}, T1};
    +                case P2(T) of
    +                    {ok, R1, T1} ->
    +                        {ok, {'or',2,R1}, T1};
                         fail ->
                             fail
                     end
             end
         end.

    The original problem was to parse the grammar (a | b) & (c | d). The following -code addresses this problem:

    grammar() ->
    -    pand(
    -         por(pconst(a), pconst(b)),
    -         por(pconst(c), pconst(d))).

    The following code adds a parser interface to the grammar:

    parse(List) ->
    -    (grammar())(List).

    The parser can be tested as follows:

    > funparse:parse([a,c]).
    -{ok,{'and',{'or',1,{const,a}},{'or',1,{const,c}}}}
    -> funparse:parse([a,d]).
    -{ok,{'and',{'or',1,{const,a}},{'or',2,{const,d}}}}
    -> funparse:parse([b,c]).
    -{ok,{'and',{'or',2,{const,b}},{'or',1,{const,c}}}}
    -> funparse:parse([b,d]).
    -{ok,{'and',{'or',2,{const,b}},{'or',2,{const,d}}}}
    -> funparse:parse([a,b]).
    +code addresses this problem:

    grammar() ->
    +    pand(
    +         por(pconst(a), pconst(b)),
    +         por(pconst(c), pconst(d))).

    The following code adds a parser interface to the grammar:

    parse(List) ->
    +    (grammar())(List).

    The parser can be tested as follows:

    > funparse:parse([a,c]).
    +{ok,{'and',{'or',1,{const,a}},{'or',1,{const,c}}}}
    +> funparse:parse([a,d]).
    +{ok,{'and',{'or',1,{const,a}},{'or',2,{const,d}}}}
    +> funparse:parse([b,c]).
    +{ok,{'and',{'or',2,{const,b}},{'or',1,{const,c}}}}
    +> funparse:parse([b,d]).
    +{ok,{'and',{'or',2,{const,b}},{'or',2,{const,d}}}}
    +> funparse:parse([a,b]).
     fail
    diff --git a/prs/9045/doc/system/gen_server_concepts.html b/prs/9045/doc/system/gen_server_concepts.html index e36a3f16ca8f..af6d5a095962 100644 --- a/prs/9045/doc/system/gen_server_concepts.html +++ b/prs/9045/doc/system/gen_server_concepts.html @@ -167,40 +167,40 @@

    An example of a simple server written in plain Erlang is provided in Overview. The server can be reimplemented using -gen_server, resulting in this callback module:

    -module(ch3).
    --behaviour(gen_server).
    +gen_server, resulting in this callback module:

    -module(ch3).
    +-behaviour(gen_server).
     
    --export([start_link/0]).
    --export([alloc/0, free/1]).
    --export([init/1, handle_call/3, handle_cast/2]).
    +-export([start_link/0]).
    +-export([alloc/0, free/1]).
    +-export([init/1, handle_call/3, handle_cast/2]).
     
    -start_link() ->
    -    gen_server:start_link({local, ch3}, ch3, [], []).
    +start_link() ->
    +    gen_server:start_link({local, ch3}, ch3, [], []).
     
    -alloc() ->
    -    gen_server:call(ch3, alloc).
    +alloc() ->
    +    gen_server:call(ch3, alloc).
     
    -free(Ch) ->
    -    gen_server:cast(ch3, {free, Ch}).
    +free(Ch) ->
    +    gen_server:cast(ch3, {free, Ch}).
     
    -init(_Args) ->
    -    {ok, channels()}.
    +init(_Args) ->
    +    {ok, channels()}.
     
    -handle_call(alloc, _From, Chs) ->
    -    {Ch, Chs2} = alloc(Chs),
    -    {reply, Ch, Chs2}.
    +handle_call(alloc, _From, Chs) ->
    +    {Ch, Chs2} = alloc(Chs),
    +    {reply, Ch, Chs2}.
     
    -handle_cast({free, Ch}, Chs) ->
    -    Chs2 = free(Ch, Chs),
    -    {noreply, Chs2}.

    The code is explained in the next sections.

    +handle_cast({free, Ch}, Chs) -> + Chs2 = free(Ch, Chs), + {noreply, Chs2}.

    The code is explained in the next sections.

    Starting a Gen_Server

    In the example in the previous section, gen_server is started by calling -ch3:start_link():

    start_link() ->
    -    gen_server:start_link({local, ch3}, ch3, [], []) => {ok, Pid}

    start_link/0 calls function gen_server:start_link/4. This function +ch3:start_link():

    start_link() ->
    +    gen_server:start_link({local, ch3}, ch3, [], []) => {ok, Pid}

    start_link/0 calls function gen_server:start_link/4. This function spawns and links to a new process, a gen_server.

    • The first argument, {local, ch3}, specifies the name. The gen_server is then locally registered as ch3.

      If the name is omitted, the gen_server is not registered. Instead its pid must be used. The name can also be given as {global, Name}, in which case @@ -214,8 +214,8 @@

      for the available options.

    If name registration succeeds, the new gen_server process calls the callback function ch3:init([]). init is expected to return {ok, State}, where State is the internal state of the gen_server. In this case, the state is -the available channels.

    init(_Args) ->
    -    {ok, channels()}.

    gen_server:start_link/4 is synchronous. It does not return until the +the available channels.

    init(_Args) ->
    +    {ok, channels()}.

    gen_server:start_link/4 is synchronous. It does not return until the gen_server has been initialized and is ready to receive requests.

    gen_server:start_link/4 must be used if the gen_server is part of a supervision tree, meaning that it was started by a supervisor. There is another function, gen_server:start/4, to start a standalone @@ -231,9 +231,9 @@

    When the request is received, the gen_server calls handle_call(Request, From, State), which is expected to return a tuple {reply,Reply,State1}. Reply is the reply that is to be sent back -to the client, and State1 is a new value for the state of the gen_server.

    handle_call(alloc, _From, Chs) ->
    -    {Ch, Chs2} = alloc(Chs),
    -    {reply, Ch, Chs2}.

    In this case, the reply is the allocated channel Ch and the new state is the +to the client, and State1 is a new value for the state of the gen_server.

    handle_call(alloc, _From, Chs) ->
    +    {Ch, Chs2} = alloc(Chs),
    +    {reply, Ch, Chs2}.

    In this case, the reply is the allocated channel Ch and the new state is the set of remaining available channels Chs2.

    Thus, the call ch3:alloc() returns the allocated channel Ch and the gen_server then waits for new requests, now with an updated list of available channels.

    @@ -242,13 +242,13 @@

    Asynchronous Requests - Cast

    -

    The asynchronous request free(Ch) is implemented using gen_server:cast/2:

    free(Ch) ->
    -    gen_server:cast(ch3, {free, Ch}).

    ch3 is the name of the gen_server. {free, Ch} is the actual request.

    The request is made into a message and sent to the gen_server. +

    The asynchronous request free(Ch) is implemented using gen_server:cast/2:

    free(Ch) ->
    +    gen_server:cast(ch3, {free, Ch}).

    ch3 is the name of the gen_server. {free, Ch} is the actual request.

    The request is made into a message and sent to the gen_server. cast, and thus free, then returns ok.

    When the request is received, the gen_server calls handle_cast(Request, State), which is expected to return a tuple -{noreply,State1}. State1 is a new value for the state of the gen_server.

    handle_cast({free, Ch}, Chs) ->
    -    Chs2 = free(Ch, Chs),
    -    {noreply, Chs2}.

    In this case, the new state is the updated list of available channels Chs2. +{noreply,State1}. State1 is a new value for the state of the gen_server.

    handle_cast({free, Ch}, Chs) ->
    +    Chs2 = free(Ch, Chs),
    +    {noreply, Chs2}.

    In this case, the new state is the updated list of available channels Chs2. The gen_server is now ready for new requests.

    @@ -267,15 +267,15 @@

    set in the supervisor.

    If it is necessary to clean up before termination, the shutdown strategy must be a time-out value and the gen_server must be set to trap exit signals in function init. When ordered to shutdown, the gen_server then calls -the callback function terminate(shutdown, State):

    init(Args) ->
    +the callback function terminate(shutdown, State):

    init(Args) ->
         ...,
    -    process_flag(trap_exit, true),
    +    process_flag(trap_exit, true),
         ...,
    -    {ok, State}.
    +    {ok, State}.
     
     ...
     
    -terminate(shutdown, State) ->
    +terminate(shutdown, State) ->
         %% Code for cleaning up here
         ...
         ok.

    @@ -286,21 +286,21 @@

    If the gen_server is not part of a supervision tree, a stop function can be useful, for example:

    ...
    -export([stop/0]).
    +export([stop/0]).
     ...
     
    -stop() ->
    -    gen_server:cast(ch3, stop).
    +stop() ->
    +    gen_server:cast(ch3, stop).
     ...
     
    -handle_cast(stop, State) ->
    -    {stop, normal, State};
    -handle_cast({free, Ch}, State) ->
    +handle_cast(stop, State) ->
    +    {stop, normal, State};
    +handle_cast({free, Ch}, State) ->
         ...
     
     ...
     
    -terminate(normal, State) ->
    +terminate(normal, State) ->
         ok.

    The callback function handling the stop request returns a tuple {stop,normal,State1}, where normal specifies that it is a normal termination and State1 is a new value for the state @@ -315,13 +315,13 @@

    the callback function handle_info(Info, State) must be implemented to handle them. Examples of other messages are exit messages, if the gen_server is linked to other processes than the supervisor -and it is trapping exit signals.

    handle_info({'EXIT', Pid, Reason}, State) ->
    +and it is trapping exit signals.

    handle_info({'EXIT', Pid, Reason}, State) ->
         %% Code to handle exits here.
         ...
    -    {noreply, State1}.

    The final function to implement is code_change/3:

    code_change(OldVsn, State, Extra) ->
    +    {noreply, State1}.

    The final function to implement is code_change/3:

    code_change(OldVsn, State, Extra) ->
         %% Code to convert state (and more) during code change.
         ...
    -    {ok, NewState}.
    +
    {ok, NewState}.
    diff --git a/prs/9045/doc/system/included_applications.html b/prs/9045/doc/system/included_applications.html index 96c73fd2712f..732d742aded1 100644 --- a/prs/9045/doc/system/included_applications.html +++ b/prs/9045/doc/system/included_applications.html @@ -171,16 +171,16 @@

    Specifying Included Applications

    Which applications to include is defined by the included_applications key in -the .app file:

    {application, prim_app,
    - [{description, "Tree application"},
    -  {vsn, "1"},
    -  {modules, [prim_app_cb, prim_app_sup, prim_app_server]},
    -  {registered, [prim_app_server]},
    -  {included_applications, [incl_app]},
    -  {applications, [kernel, stdlib, sasl]},
    -  {mod, {prim_app_cb,[]}},
    -  {env, [{file, "/usr/local/log"}]}
    - ]}.

    +the .app file:

    {application, prim_app,
    + [{description, "Tree application"},
    +  {vsn, "1"},
    +  {modules, [prim_app_cb, prim_app_sup, prim_app_server]},
    +  {registered, [prim_app_server]},
    +  {included_applications, [incl_app]},
    +  {applications, [kernel, stdlib, sasl]},
    +  {mod, {prim_app_cb,[]}},
    +  {env, [{file, "/usr/local/log"}]}
    + ]}.

    @@ -194,27 +194,27 @@

    term.

    The value of the mod key of the including application must be set to {application_starter,[Module,StartArgs]}, where Module as usual is the application callback module. StartArgs is a term provided as argument to the -callback function Module:start/2:

    {application, prim_app,
    - [{description, "Tree application"},
    -  {vsn, "1"},
    -  {modules, [prim_app_cb, prim_app_sup, prim_app_server]},
    -  {registered, [prim_app_server]},
    -  {included_applications, [incl_app]},
    -  {start_phases, [{init,[]}, {go,[]}]},
    -  {applications, [kernel, stdlib, sasl]},
    -  {mod, {application_starter,[prim_app_cb,[]]}},
    -  {env, [{file, "/usr/local/log"}]}
    - ]}.
    -
    -{application, incl_app,
    - [{description, "Included application"},
    -  {vsn, "1"},
    -  {modules, [incl_app_cb, incl_app_sup, incl_app_server]},
    -  {registered, []},
    -  {start_phases, [{go,[]}]},
    -  {applications, [kernel, stdlib, sasl]},
    -  {mod, {incl_app_cb,[]}}
    - ]}.

    When starting a primary application with included applications, the primary +callback function Module:start/2:

    {application, prim_app,
    + [{description, "Tree application"},
    +  {vsn, "1"},
    +  {modules, [prim_app_cb, prim_app_sup, prim_app_server]},
    +  {registered, [prim_app_server]},
    +  {included_applications, [incl_app]},
    +  {start_phases, [{init,[]}, {go,[]}]},
    +  {applications, [kernel, stdlib, sasl]},
    +  {mod, {application_starter,[prim_app_cb,[]]}},
    +  {env, [{file, "/usr/local/log"}]}
    + ]}.
    +
    +{application, incl_app,
    + [{description, "Included application"},
    +  {vsn, "1"},
    +  {modules, [incl_app_cb, incl_app_sup, incl_app_server]},
    +  {registered, []},
    +  {start_phases, [{go,[]}]},
    +  {applications, [kernel, stdlib, sasl]},
    +  {mod, {incl_app_cb,[]}}
    + ]}.

    When starting a primary application with included applications, the primary application is started the normal way, that is:

    • The application controller creates an application master for the application
    • The application master calls Module:start(normal, StartArgs) to start the top supervisor.

    Then, for the primary application and each included application in top-down, left-to-right order, the application master calls @@ -227,11 +227,11 @@

    of specified phases must be a subset of the set of phases specified for the primary application.

    When starting prim_app as defined above, the application controller calls the following callback functions before application:start(prim_app) returns a -value:

    application:start(prim_app)
    - => prim_app_cb:start(normal, [])
    - => prim_app_cb:start_phase(init, normal, [])
    - => prim_app_cb:start_phase(go, normal, [])
    - => incl_app_cb:start_phase(go, normal, [])
    +value:

    application:start(prim_app)
    + => prim_app_cb:start(normal, [])
    + => prim_app_cb:start_phase(init, normal, [])
    + => prim_app_cb:start_phase(go, normal, [])
    + => incl_app_cb:start_phase(go, normal, [])
     ok

    diff --git a/prs/9045/doc/system/install-win32.html b/prs/9045/doc/system/install-win32.html index ea8e61eac90a..01fcc6e87cfb 100644 --- a/prs/9045/doc/system/install-win32.html +++ b/prs/9045/doc/system/install-win32.html @@ -305,7 +305,7 @@

    and sometimes

    $ cd $ERL_TOP
     $ make local_setup
     

    So now when you run $ERL_TOP/erl.exe, you should have a debug compiled -emulator, which you will see if you do a:

    1> erlang:system_info(system_version).

    in the erlang shell. If the returned string contains [debug], you +emulator, which you will see if you do a:

    1> erlang:system_info(system_version).

    in the erlang shell. If the returned string contains [debug], you got a debug compiled emulator.

    To hack the erlang libraries, you simply do a make opt in the specific "applications" directory, like:

    $ cd $ERL_TOP/lib/stdlib
     $ make opt
    @@ -328,11 +328,11 @@ 

    Remember that:

    • Windows specific C-code goes in the $ERL_TOP/erts/emulator/sys/win32, $ERL_TOP/erts/emulator/drivers/win32 or $ERL_TOP/erts/etc/win32.

    • Windows specific erlang code should be used conditionally and the host OS tested in runtime, the exactly same beam files should be -distributed for every platform! So write code like:

      case os:type() of
      -    {win32,_} ->
      -        do_windows_specific();
      +distributed for every platform! So write code like:

      case os:type() of
      +    {win32,_} ->
      +        do_windows_specific();
           Other ->
      -        do_fallback_or_exit()
      +        do_fallback_or_exit()
       end,

    That's basically all you need to get going.

    diff --git a/prs/9045/doc/system/list_comprehensions.html b/prs/9045/doc/system/list_comprehensions.html index fe8a642acaa7..2f957929affe 100644 --- a/prs/9045/doc/system/list_comprehensions.html +++ b/prs/9045/doc/system/list_comprehensions.html @@ -127,25 +127,25 @@

    Simple Examples

    -

    This section starts with a simple example, showing a generator and a filter:

    > [X || X <- [1,2,a,3,4,b,5,6], X > 3].
    -[a,4,b,5,6]

    This is read as follows: The list of X such that X is taken from the list +

    This section starts with a simple example, showing a generator and a filter:

    > [X || X <- [1,2,a,3,4,b,5,6], X > 3].
    +[a,4,b,5,6]

    This is read as follows: The list of X such that X is taken from the list [1,2,a,...] and X is greater than 3.

    The notation X <- [1,2,a,...] is a generator and the expression X > 3 is a filter.

    An additional filter, is_integer(X), can be added to -restrict the result to integers:

    > [X || X <- [1,2,a,3,4,b,5,6], is_integer(X), X > 3].
    -[4,5,6]

    Generators can be combined. For example, the Cartesian product of two lists can -be written as follows:

    > [{X, Y} || X <- [1,2,3], Y <- [a,b]].
    -[{1,a},{1,b},{2,a},{2,b},{3,a},{3,b}]

    +restrict the result to integers:

    > [X || X <- [1,2,a,3,4,b,5,6], is_integer(X), X > 3].
    +[4,5,6]

    Generators can be combined. For example, the Cartesian product of two lists can +be written as follows:

    > [{X, Y} || X <- [1,2,3], Y <- [a,b]].
    +[{1,a},{1,b},{2,a},{2,b},{3,a},{3,b}]

    Quick Sort

    -

    The well-known quick sort routine can be written as follows:

    sort([]) -> [];
    -sort([_] = L) -> L;
    -sort([Pivot|T]) ->
    -    sort([ X || X <- T, X < Pivot]) ++
    -    [Pivot] ++
    -    sort([ X || X <- T, X >= Pivot]).

    The expression [X || X <- T, X < Pivot] is the list of all elements in T +

    The well-known quick sort routine can be written as follows:

    sort([]) -> [];
    +sort([_] = L) -> L;
    +sort([Pivot|T]) ->
    +    sort([ X || X <- T, X < Pivot]) ++
    +    [Pivot] ++
    +    sort([ X || X <- T, X >= Pivot]).

    The expression [X || X <- T, X < Pivot] is the list of all elements in T that are less than Pivot.

    [X || X <- T, X >= Pivot] is the list of all elements in T that are greater than or equal to Pivot.

    With the algorithm above, a list is sorted as follows:

    • A list with zero or one element is trivially sorted.
    • For lists with more than one element:
      1. The first element in the list is isolated as the pivot element.
      2. The remaining list is partitioned into two sublists, such that:
      • The first sublist contains all elements that are smaller than the pivot element.
      • The second sublist contains all elements that are greater than or equal to @@ -161,11 +161,11 @@

        Permutations

        -

        The following example generates all permutations of the elements in a list:

        perms([]) -> [[]];
        -perms(L)  -> [[H|T] || H <- L, T <- perms(L--[H])].

        This takes H from L in all possible ways. The result is the set of all lists +

        The following example generates all permutations of the elements in a list:

        perms([]) -> [[]];
        +perms(L)  -> [[H|T] || H <- L, T <- perms(L--[H])].

        This takes H from L in all possible ways. The result is the set of all lists [H|T], where T is the set of all possible permutations of L, with H -removed:

        > perms([b,u,g]).
        -[[b,u,g],[b,g,u],[u,b,g],[u,g,b],[g,b,u],[g,u,b]]

        +removed:

        > perms([b,u,g]).
        +[[b,u,g],[b,g,u],[u,b,g],[u,g,b],[g,b,u],[g,u,b]]

        @@ -174,47 +174,47 @@

        Pythagorean triplets are sets of integers {A,B,C} such that A**2 + B**2 = C**2.

        The function pyth(N) generates a list of all integers {A,B,C} such that A**2 + B**2 = C**2 and where the sum of the sides is equal to, or less than, -N:

        pyth(N) ->
        -    [ {A,B,C} ||
        -        A <- lists:seq(1,N),
        -        B <- lists:seq(1,N),
        -        C <- lists:seq(1,N),
        +N:

        pyth(N) ->
        +    [ {A,B,C} ||
        +        A <- lists:seq(1,N),
        +        B <- lists:seq(1,N),
        +        C <- lists:seq(1,N),
                 A+B+C =< N,
                 A*A+B*B == C*C
        -    ].
        > pyth(3).
        -[].
        -> pyth(11).
        -[].
        -> pyth(12).
        -[{3,4,5},{4,3,5}]
        -> pyth(50).
        -[{3,4,5},
        - {4,3,5},
        - {5,12,13},
        - {6,8,10},
        - {8,6,10},
        - {8,15,17},
        - {9,12,15},
        - {12,5,13},
        - {12,9,15},
        - {12,16,20},
        - {15,8,17},
        - {16,12,20}]

        The following code reduces the search space and is more efficient:

        pyth1(N) ->
        -   [{A,B,C} ||
        -       A <- lists:seq(1,N-2),
        -       B <- lists:seq(A+1,N-1),
        -       C <- lists:seq(B+1,N),
        +    ].
        > pyth(3).
        +[].
        +> pyth(11).
        +[].
        +> pyth(12).
        +[{3,4,5},{4,3,5}]
        +> pyth(50).
        +[{3,4,5},
        + {4,3,5},
        + {5,12,13},
        + {6,8,10},
        + {8,6,10},
        + {8,15,17},
        + {9,12,15},
        + {12,5,13},
        + {12,9,15},
        + {12,16,20},
        + {15,8,17},
        + {16,12,20}]

        The following code reduces the search space and is more efficient:

        pyth1(N) ->
        +   [{A,B,C} ||
        +       A <- lists:seq(1,N-2),
        +       B <- lists:seq(A+1,N-1),
        +       C <- lists:seq(B+1,N),
                A+B+C =< N,
        -       A*A+B*B == C*C ].

        + A*A+B*B == C*C ].

        Simplifications With List Comprehensions

        As an example, list comprehensions can be used to simplify some of the functions -in lists.erl:

        append(L)   ->  [X || L1 <- L, X <- L1].
        -map(Fun, L) -> [Fun(X) || X <- L].
        -filter(Pred, L) -> [X || X <- L, Pred(X)].

        +in lists.erl:

        append(L)   ->  [X || L1 <- L, X <- L1].
        +map(Fun, L) -> [Fun(X) || X <- L].
        +filter(Pred, L) -> [X || X <- L, Pred(X)].

        @@ -226,20 +226,20 @@

        which selects certain elements from a list of tuples. Suppose you write select(X, L) -> [Y || {X, Y} <- L]. with the intention of extracting all tuples from L, where the first item is X.

        Compiling this gives the following diagnostic:

        ./FileName.erl:Line: Warning: variable 'X' shadowed in generate

        This diagnostic warns that the variable X in the pattern is not the same as -the variable X that occurs in the function head.

        Evaluating select gives the following result:

        > select(b,[{a,1},{b,2},{c,3},{b,7}]).
        -[1,2,3,7]

        This is not the wanted result. To achieve the desired effect, select must be -written as follows:

        select(X, L) ->  [Y || {X1, Y} <- L, X == X1].

        The generator now contains unbound variables and the test has been moved into -the filter.

        This now works as expected:

        > select(b,[{a,1},{b,2},{c,3},{b,7}]).
        -[2,7]

        Also note that a variable in a generator pattern will shadow a variable with the -same name bound in a previous generator pattern. For example:

        > [{X,Y} || X <- [1,2,3], X=Y <- [a,b,c]].
        -[{a,a},{b,b},{c,c},{a,a},{b,b},{c,c},{a,a},{b,b},{c,c}]

        A consequence of the rules for importing variables into a list comprehensions is +the variable X that occurs in the function head.

        Evaluating select gives the following result:

        > select(b,[{a,1},{b,2},{c,3},{b,7}]).
        +[1,2,3,7]

        This is not the wanted result. To achieve the desired effect, select must be +written as follows:

        select(X, L) ->  [Y || {X1, Y} <- L, X == X1].

        The generator now contains unbound variables and the test has been moved into +the filter.

        This now works as expected:

        > select(b,[{a,1},{b,2},{c,3},{b,7}]).
        +[2,7]

        Also note that a variable in a generator pattern will shadow a variable with the +same name bound in a previous generator pattern. For example:

        > [{X,Y} || X <- [1,2,3], X=Y <- [a,b,c]].
        +[{a,a},{b,b},{c,c},{a,a},{b,b},{c,c},{a,a},{b,b},{c,c}]

        A consequence of the rules for importing variables into a list comprehensions is that certain pattern matching operations must be moved into the filters and -cannot be written directly in the generators.

        To illustrate this, do not write as follows:

        f(...) ->
        +cannot be written directly in the generators.

        To illustrate this, do not write as follows:

        f(...) ->
             Y = ...
        -    [ Expression || PatternInvolving Y  <- Expr, ...]
        -    ...

        Instead, write as follows:

        f(...) ->
        +    [ Expression || PatternInvolving Y  <- Expr, ...]
        +    ...

        Instead, write as follows:

        f(...) ->
             Y = ...
        -    [ Expression || PatternInvolving Y1  <- Expr, Y == Y1, ...]
        +    [ Expression || PatternInvolving Y1  <- Expr, Y == Y1, ...]
             ...
        diff --git a/prs/9045/doc/system/listhandling.html b/prs/9045/doc/system/listhandling.html index c8d2a423a66d..23a8893a481b 100644 --- a/prs/9045/doc/system/listhandling.html +++ b/prs/9045/doc/system/listhandling.html @@ -130,47 +130,47 @@

        Lists can only be built starting from the end and attaching list elements at the beginning. If you use the ++ operator as follows, a new list is created that is a copy of the elements in List1, followed by List2:

        List1 ++ List2

        Looking at how lists:append/2 or ++ would be implemented in plain Erlang, -clearly the first list is copied:

        append([H|T], Tail) ->
        -    [H|append(T, Tail)];
        -append([], Tail) ->
        +clearly the first list is copied:

        append([H|T], Tail) ->
        +    [H|append(T, Tail)];
        +append([], Tail) ->
             Tail.

        When recursing and building a list, it is important to ensure that you attach the new elements to the beginning of the list. In this way, you will build one -list, not hundreds or thousands of copies of the growing result list.

        Let us first see how it is not to be done:

        DO NOT

        bad_fib(N) ->
        -    bad_fib(N, 0, 1, []).
        +list, not hundreds or thousands of copies of the growing result list.

        Let us first see how it is not to be done:

        DO NOT

        bad_fib(N) ->
        +    bad_fib(N, 0, 1, []).
         
        -bad_fib(0, _Current, _Next, Fibs) ->
        +bad_fib(0, _Current, _Next, Fibs) ->
             Fibs;
        -bad_fib(N, Current, Next, Fibs) ->
        -    bad_fib(N - 1, Next, Current + Next, Fibs ++ [Current]).

        Here more than one list is built. In each iteration step a new list is created +bad_fib(N, Current, Next, Fibs) -> + bad_fib(N - 1, Next, Current + Next, Fibs ++ [Current]).

        Here more than one list is built. In each iteration step a new list is created that is one element longer than the new previous list.

        To avoid copying the result in each iteration, build the list in reverse order -and reverse the list when you are done:

        DO

        tail_recursive_fib(N) ->
        -    tail_recursive_fib(N, 0, 1, []).
        +and reverse the list when you are done:

        DO

        tail_recursive_fib(N) ->
        +    tail_recursive_fib(N, 0, 1, []).
         
        -tail_recursive_fib(0, _Current, _Next, Fibs) ->
        -    lists:reverse(Fibs);
        -tail_recursive_fib(N, Current, Next, Fibs) ->
        -    tail_recursive_fib(N - 1, Next, Current + Next, [Current|Fibs]).

        +tail_recursive_fib(0, _Current, _Next, Fibs) -> + lists:reverse(Fibs); +tail_recursive_fib(N, Current, Next, Fibs) -> + tail_recursive_fib(N - 1, Next, Current + Next, [Current|Fibs]).

        List Comprehensions

        -

        A list comprehension:

        [Expr(E) || E <- List]

        is basically translated to a local function:

        'lc^0'([E|Tail], Expr) ->
        -    [Expr(E)|'lc^0'(Tail, Expr)];
        -'lc^0'([], _Expr) -> [].

        If the result of the list comprehension will obviously not be used, a list -will not be constructed. For example, in this code:

        [io:put_chars(E) || E <- List],
        +

        A list comprehension:

        [Expr(E) || E <- List]

        is basically translated to a local function:

        'lc^0'([E|Tail], Expr) ->
        +    [Expr(E)|'lc^0'(Tail, Expr)];
        +'lc^0'([], _Expr) -> [].

        If the result of the list comprehension will obviously not be used, a list +will not be constructed. For example, in this code:

        [io:put_chars(E) || E <- List],
         ok.

        or in this code:

        case Var of
             ... ->
        -        [io:put_chars(E) || E <- List];
        +        [io:put_chars(E) || E <- List];
             ... ->
         end,
        -some_function(...),

        the value is not assigned to a variable, not passed to another function, and not +some_function(...),

        the value is not assigned to a variable, not passed to another function, and not returned. This means that there is no need to construct a list and the compiler -will simplify the code for the list comprehension to:

        'lc^0'([E|Tail], Expr) ->
        -    Expr(E),
        -    'lc^0'(Tail, Expr);
        -'lc^0'([], _Expr) -> [].

        The compiler also understands that assigning to _ means that the value will -not be used. Therefore, the code in the following example will also be optimized:

        _ = [io:put_chars(E) || E <- List],
        +will simplify the code for the list comprehension to:

        'lc^0'([E|Tail], Expr) ->
        +    Expr(E),
        +    'lc^0'(Tail, Expr);
        +'lc^0'([], _Expr) -> [].

        The compiler also understands that assigning to _ means that the value will +not be used. Therefore, the code in the following example will also be optimized:

        _ = [io:put_chars(E) || E <- List],
         ok.

        @@ -183,11 +183,11 @@

        to flatten the list before sending it to the port.

      • When calling BIFs that accept deep lists, such as list_to_binary/1 or iolist_to_binary/1.
      • When you know that your list is only one level deep. Use lists:append/1 -instead.

      Examples:

      DO

      port_command(Port, DeepList)

      DO NOT

      port_command(Port, lists:flatten(DeepList))

      A common way to send a zero-terminated string to a port is the following:

      DO NOT

      TerminatedStr = String ++ [0],
      -port_command(Port, TerminatedStr)

      Instead:

      DO

      TerminatedStr = [String, 0],
      -port_command(Port, TerminatedStr)

      DO

      1> lists:append([[1], [2], [3]]).
      -[1,2,3]

      DO NOT

      1> lists:flatten([[1], [2], [3]]).
      -[1,2,3]

      +instead.

    Examples:

    DO

    port_command(Port, DeepList)

    DO NOT

    port_command(Port, lists:flatten(DeepList))

    A common way to send a zero-terminated string to a port is the following:

    DO NOT

    TerminatedStr = String ++ [0],
    +port_command(Port, TerminatedStr)

    Instead:

    DO

    TerminatedStr = [String, 0],
    +port_command(Port, TerminatedStr)

    DO

    1> lists:append([[1], [2], [3]]).
    +[1,2,3]

    DO NOT

    1> lists:flatten([[1], [2], [3]]).
    +[1,2,3]

    @@ -195,17 +195,17 @@

    There are two basic ways to write a function that traverses a list and produces a new list.

    The first way is writing a body-recursive function:

    %% Add 42 to each integer in the list.
    -add_42_body([H|T]) ->
    -    [H + 42 | add_42_body(T)];
    -add_42_body([]) ->
    -    [].

    The second way is writing a tail-recursive function:

    %% Add 42 to each integer in the list.
    -add_42_tail(List) ->
    -    add_42_tail(List, []).
    -
    -add_42_tail([H|T], Acc) ->
    -    add_42_tail(T, [H + 42 | Acc]);
    -add_42_tail([], Acc) ->
    -    lists:reverse(Acc).

    In early version of Erlang the tail-recursive function would typically +add_42_body([H|T]) -> + [H + 42 | add_42_body(T)]; +add_42_body([]) -> + [].

    The second way is writing a tail-recursive function:

    %% Add 42 to each integer in the list.
    +add_42_tail(List) ->
    +    add_42_tail(List, []).
    +
    +add_42_tail([H|T], Acc) ->
    +    add_42_tail(T, [H + 42 | Acc]);
    +add_42_tail([], Acc) ->
    +    lists:reverse(Acc).

    In early version of Erlang the tail-recursive function would typically be more efficient. In modern versions of Erlang, there is usually not much difference in performance between a body-recursive list function and tail-recursive function that reverses the list at the end. Therefore, @@ -216,11 +216,11 @@

    function that does not construct a list runs in constant space, while the corresponding body-recursive function uses stack space proportional to the length of the list.

    For example, a function that sums a list of integers, is not to be written as -follows:

    DO NOT

    recursive_sum([H|T]) -> H+recursive_sum(T);
    -recursive_sum([])    -> 0.

    Instead:

    DO

    sum(L) -> sum(L, 0).
    +follows:

    DO NOT

    recursive_sum([H|T]) -> H+recursive_sum(T);
    +recursive_sum([])    -> 0.

    Instead:

    DO

    sum(L) -> sum(L, 0).
     
    -sum([H|T], Sum) -> sum(T, Sum + H);
    -sum([], Sum)    -> Sum.
    +
    sum([H|T], Sum) -> sum(T, Sum + H); +sum([], Sum) -> Sum.
    diff --git a/prs/9045/doc/system/macros.html b/prs/9045/doc/system/macros.html index 52e99d20d912..eef6a62e4b93 100644 --- a/prs/9045/doc/system/macros.html +++ b/prs/9045/doc/system/macros.html @@ -127,8 +127,8 @@

    File Inclusion

    -

    A file can be included as follows:

    -include(File).
    --include_lib(File).

    File, a string, is to point out a file. The contents of this file are included +

    A file can be included as follows:

    -include(File).
    +-include_lib(File).

    File, a string, is to point out a file. The contents of this file are included as is, at the position of the directive.

    Include files are typically used for record and macro definitions that are shared by several modules. It is recommended to use the file name extension .hrl for include files.

    File can start with a path component $VAR, for some string VAR. If that is @@ -137,12 +137,12 @@

    $VAR is left as is.

    If the filename File is absolute (possibly after variable substitution), the include file with that name is included. Otherwise, the specified file is searched for in the following directories, and in this order:

    1. The current working directory
    2. The directory where the module is being compiled
    3. The directories given by the include option

    For details, see erlc in ERTS and -compile in Compiler.

    Examples:

    -include("my_records.hrl").
    --include("incdir/my_records.hrl").
    --include("/home/user/proj/my_records.hrl").
    --include("$PROJ_ROOT/my_records.hrl").

    include_lib is similar to include, but is not to point out an absolute file. +compile in Compiler.

    Examples:

    -include("my_records.hrl").
    +-include("incdir/my_records.hrl").
    +-include("/home/user/proj/my_records.hrl").
    +-include("$PROJ_ROOT/my_records.hrl").

    include_lib is similar to include, but is not to point out an absolute file. Instead, the first path component (possibly after variable substitution) is -assumed to be the name of an application.

    Example:

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

    The code server uses code:lib_dir(kernel) to find the directory of the current +assumed to be the name of an application.

    Example:

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

    The code server uses code:lib_dir(kernel) to find the directory of the current (latest) version of Kernel, and then the subdirectory include is searched for the file file.hrl.

    @@ -150,25 +150,25 @@

    Defining and Using Macros

    -

    A macro is defined as follows:

    -define(Const, Replacement).
    --define(Func(Var1,...,VarN), Replacement).

    A macro definition can be placed anywhere among the attributes and function +

    A macro is defined as follows:

    -define(Const, Replacement).
    +-define(Func(Var1,...,VarN), Replacement).

    A macro definition can be placed anywhere among the attributes and function declarations of a module, but the definition must come before any usage of the macro.

    If a macro is used in several modules, it is recommended that the macro definition is placed in an include file.

    A macro is used as follows:

    ?Const
     ?Func(Arg1,...,ArgN)

    Macros are expanded during compilation. A simple macro ?Const is replaced with -Replacement.

    Example:

    -define(TIMEOUT, 200).
    +Replacement.

    Example:

    -define(TIMEOUT, 200).
     ...
    -call(Request) ->
    -    server:call(refserver, Request, ?TIMEOUT).

    This is expanded to:

    call(Request) ->
    -    server:call(refserver, Request, 200).

    A macro ?Func(Arg1,...,ArgN) is replaced with Replacement, where all +call(Request) -> + server:call(refserver, Request, ?TIMEOUT).

    This is expanded to:

    call(Request) ->
    +    server:call(refserver, Request, 200).

    A macro ?Func(Arg1,...,ArgN) is replaced with Replacement, where all occurrences of a variable Var from the macro definition are replaced with the -corresponding argument Arg.

    Example:

    -define(MACRO1(X, Y), {a, X, b, Y}).
    +corresponding argument Arg.

    Example:

    -define(MACRO1(X, Y), {a, X, b, Y}).
     ...
    -bar(X) ->
    -    ?MACRO1(a, b),
    -    ?MACRO1(X, 123)

    This is expanded to:

    bar(X) ->
    -    {a,a,b,b},
    -    {a,X,b,123}.

    It is good programming practice, but not mandatory, to ensure that a macro +bar(X) -> + ?MACRO1(a, b), + ?MACRO1(X, 123)

    This is expanded to:

    bar(X) ->
    +    {a,a,b,b},
    +    {a,X,b,123}.

    It is good programming practice, but not mandatory, to ensure that a macro definition is a valid Erlang syntactic form.

    To view the result of macro expansion, a module can be compiled with the 'P' option. compile:file(File, ['P']). This produces a listing of the parsed code after preprocessing and parse transforms, in the file File.P.

    @@ -195,21 +195,21 @@

    It is possible to overload macros, except for predefined macros. An overloaded macro has more than one definition, each with a different number of arguments.

    Change

    Support for overloading of macros was added in Erlang 5.7.5/OTP R13B04.

    A macro ?Func(Arg1,...,ArgN) with a (possibly empty) list of arguments results in an error message if there is at least one definition of Func with -arguments, but none with N arguments.

    Assuming these definitions:

    -define(F0(), c).
    --define(F1(A), A).
    --define(C, m:f).

    the following does not work:

    f0() ->
    +arguments, but none with N arguments.

    Assuming these definitions:

    -define(F0(), c).
    +-define(F1(A), A).
    +-define(C, m:f).

    the following does not work:

    f0() ->
         ?F0. % No, an empty list of arguments expected.
     
    -f1(A) ->
    -    ?F1(A, A). % No, exactly one argument expected.

    On the other hand,

    f() ->
    -    ?C().

    is expanded to

    f() ->
    -    m:f().

    +f1(A) -> + ?F1(A, A). % No, exactly one argument expected.

    On the other hand,

    f() ->
    +    ?C().

    is expanded to

    f() ->
    +    m:f().

    Removing a macro definition

    -

    A definition of macro can be removed as follows:

    -undef(Macro).

    +

    A definition of macro can be removed as follows:

    -undef(Macro).

    @@ -229,13 +229,13 @@

    elif also supports calling the psuedo-function defined(Name), which tests whether the Name argument is the name of a previously defined macro. defined(Name) evaluates to true if the macro is defined and false -otherwise. An attempt to call other functions results in a compilation error.

    Example:

    -module(m).
    +otherwise. An attempt to call other functions results in a compilation error.

    Example:

    -module(m).
     ...
     
    --ifdef(debug).
    --define(LOG(X), io:format("{~p,~p}: ~p~n", [?MODULE,?LINE,X])).
    +-ifdef(debug).
    +-define(LOG(X), io:format("{~p,~p}: ~p~n", [?MODULE,?LINE,X])).
     -else.
    --define(LOG(X), true).
    +-define(LOG(X), true).
     -endif.
     
     ...

    When trace output is desired, debug is to be defined when the module m is @@ -243,21 +243,21 @@

    or -1> c(m, {d, debug}). -{ok,m}

    ?LOG(Arg) is then expanded to a call to io:format/2 and provide the user -with some simple trace output.

    Example:

    -module(m)
    +1> c(m, {d, debug}).
    +{ok,m}

    ?LOG(Arg) is then expanded to a call to io:format/2 and provide the user +with some simple trace output.

    Example:

    -module(m)
     ...
    --if(?OTP_RELEASE >= 25).
    +-if(?OTP_RELEASE >= 25).
     %% Code that will work in OTP 25 or higher
    --elif(?OTP_RELEASE >= 26).
    +-elif(?OTP_RELEASE >= 26).
     %% Code that will work in OTP 26 or higher
     -else.
     %% Code that will work in OTP 24 or lower.
     -endif.
     ...

    This code uses the OTP_RELEASE macro to conditionally select code depending on -release.

    Example:

    -module(m)
    +release.

    Example:

    -module(m)
     ...
    --if(?OTP_RELEASE >= 26 andalso defined(debug)).
    +-if(?OTP_RELEASE >= 26 andalso defined(debug)).
     %% Debugging code that requires OTP 26 or later.
     -else.
     %% Non-debug code that works in any release.
    @@ -280,23 +280,23 @@ 

    -error() and -warning() directives

    -

    The directive -error(Term) causes a compilation error.

    Example:

    -module(t).
    --export([version/0]).
    +

    The directive -error(Term) causes a compilation error.

    Example:

    -module(t).
    +-export([version/0]).
     
    --ifdef(VERSION).
    -version() -> ?VERSION.
    +-ifdef(VERSION).
    +version() -> ?VERSION.
     -else.
    --error("Macro VERSION must be defined.").
    -version() -> "".
    +-error("Macro VERSION must be defined.").
    +version() -> "".
     -endif.

    The error message will look like this:

    % erlc t.erl
    -t.erl:7: -error("Macro VERSION must be defined.").

    The directive -warning(Term) causes a compilation warning.

    Example:

    -module(t).
    --export([version/0]).
    +t.erl:7: -error("Macro VERSION must be defined.").

    The directive -warning(Term) causes a compilation warning.

    Example:

    -module(t).
    +-export([version/0]).
     
    --ifndef(VERSION).
    --warning("Macro VERSION not defined -- using default version.").
    --define(VERSION, "0").
    +-ifndef(VERSION).
    +-warning("Macro VERSION not defined -- using default version.").
    +-define(VERSION, "0").
     -endif.
    -version() -> ?VERSION.

    The warning message will look like this:

    % erlc t.erl
    +version() -> ?VERSION.

    The warning message will look like this:

    % erlc t.erl
     t.erl:5: Warning: -warning("Macro VERSION not defined -- using default version.").

    Change

    The -error() and -warning() directives were added in Erlang/OTP 19.

    @@ -305,11 +305,11 @@

    The construction ??Arg, where Arg is a macro argument, is expanded to a string containing the tokens of the argument. This is similar to the #arg -stringifying construction in C.

    Example:

    -define(TESTCALL(Call), io:format("Call ~s: ~w~n", [??Call, Call])).
    +stringifying construction in C.

    Example:

    -define(TESTCALL(Call), io:format("Call ~s: ~w~n", [??Call, Call])).
     
    -?TESTCALL(myfunction(1,2)),
    -?TESTCALL(you:function(2,1)).

    results in

    io:format("Call ~s: ~w~n",["myfunction ( 1 , 2 )",myfunction(1,2)]),
    -io:format("Call ~s: ~w~n",["you : function ( 2 , 1 )",you:function(2,1)]).

    That is, a trace output, with both the function called and the resulting value.

    +
    ?TESTCALL(myfunction(1,2)), +?TESTCALL(you:function(2,1)).

    results in

    io:format("Call ~s: ~w~n",["myfunction ( 1 , 2 )",myfunction(1,2)]),
    +io:format("Call ~s: ~w~n",["you : function ( 2 , 1 )",you:function(2,1)]).

    That is, a trace output, with both the function called and the resulting value.

    diff --git a/prs/9045/doc/system/maps.html b/prs/9045/doc/system/maps.html index 7b88d8a70231..4b522844f950 100644 --- a/prs/9045/doc/system/maps.html +++ b/prs/9045/doc/system/maps.html @@ -158,8 +158,8 @@

    values, sharing of keys between different instances of the map will be less effective, and it is not possible to match multiple elements having default values in one go.

  • To avoid having to deal with a map that may lack some keys, maps:merge/2 can -efficiently add multiple default values. For example:

    DefaultMap = #{shoe_size => 42, editor => emacs},
    -MapWithDefaultsApplied = maps:merge(DefaultMap, OtherMap)
  • +efficiently add multiple default values. For example:

    DefaultMap = #{shoe_size => 42, editor => emacs},
    +MapWithDefaultsApplied = maps:merge(DefaultMap, OtherMap)

    @@ -177,10 +177,10 @@

    Using Maps as Sets

    Starting in OTP 24, the sets module has an option to represent sets as maps. -Examples:

    1> sets:new([{version,2}]).
    -#{}
    -2> sets:from_list([x,y,z], [{version,2}]).
    -#{x => [],y => [],z => []}

    sets backed by maps is generally the most efficient set representation, with a +Examples:

    1> sets:new([{version,2}]).
    +#{}
    +2> sets:from_list([x,y,z], [{version,2}]).
    +#{x => [],y => [],z => []}

    sets backed by maps is generally the most efficient set representation, with a few possible exceptions:

    • ordsets:intersection/2 can be more efficient than sets:intersection/2. If the intersection operation is frequently used and operations that operate on a single element in a set (such as is_element/2) are avoided, ordsets can @@ -213,10 +213,10 @@

      allowing the key tuple to be shared with other instances of the map that have the same keys. In fact, the key tuple can be shared between all maps with the same keys with some care. To arrange that, define a function that returns a map. -For example:

      new() ->
      -    #{a => default, b => default, c => default}.

      Defined like this, the key tuple {a,b,c} will be a global literal. To ensure +For example:

      new() ->
      +    #{a => default, b => default, c => default}.

      Defined like this, the key tuple {a,b,c} will be a global literal. To ensure that the key tuple is shared when creating an instance of the map, always call -new() and modify the returned map:

          (SOME_MODULE:new())#{a := 42}.

      Using the map syntax with small maps is particularly efficient. As long as the +new() and modify the returned map:

          (SOME_MODULE:new())#{a := 42}.

      Using the map syntax with small maps is particularly efficient. As long as the keys are known at compile-time, the map is updated in one go, making the time to update a map essentially constant regardless of the number of keys updated. The same goes for matching. (When the keys are variables, one or more of the keys @@ -251,13 +251,13 @@

      Using the map syntax is usually slightly more efficient than using the corresponding function in the maps module.

      The gain in efficiency for the map syntax is more noticeable for the following -operations that can only be achieved using the map syntax:

      • Matching multiple literal keys
      • Updating multiple literal keys
      • Adding multiple literal keys to a map

      For example:

      DO

      Map = Map1#{x := X, y := Y, z := Z}

      DO NOT

      Map2 = maps:update(x, X, Map1),
      -Map3 = maps:update(y, Y, Map2),
      -Map = maps:update(z, Z, Map3)

      If the map is a small map, the first example runs roughly three times as fast.

      Note that for variable keys, the elements are updated sequentially from left to -right. For example, given the following update with variable keys:

      Map = Map1#{Key1 := X, Key2 := Y, Key3 := Z}

      the compiler rewrites it like this to ensure that the updates are applied from -left to right:

      Map2 = Map1#{Key1 := X},
      -Map3 = Map2#{Key2 := Y},
      -Map = Map3#{Key3 := Z}

      If a key is known to exist in a map, using the := operator is slightly more +operations that can only be achieved using the map syntax:

      • Matching multiple literal keys
      • Updating multiple literal keys
      • Adding multiple literal keys to a map

      For example:

      DO

      Map = Map1#{x := X, y := Y, z := Z}

      DO NOT

      Map2 = maps:update(x, X, Map1),
      +Map3 = maps:update(y, Y, Map2),
      +Map = maps:update(z, Z, Map3)

      If the map is a small map, the first example runs roughly three times as fast.

      Note that for variable keys, the elements are updated sequentially from left to +right. For example, given the following update with variable keys:

      Map = Map1#{Key1 := X, Key2 := Y, Key3 := Z}

      the compiler rewrites it like this to ensure that the updates are applied from +left to right:

      Map2 = Map1#{Key1 := X},
      +Map3 = Map2#{Key2 := Y},
      +Map = Map3#{Key3 := Z}

      If a key is known to exist in a map, using the := operator is slightly more efficient than using the => operator for a small map.

      @@ -316,15 +316,15 @@

      As an optimization, the compiler will rewrite a call to maps:get/3 to Erlang code similar to the following:

      Result = case Map of
      -             #{Key := Value} -> Value;
      -             #{} -> Default
      +             #{Key := Value} -> Value;
      +             #{} -> Default
                end

      This is reasonably efficient, but if a small map is used as an alternative to using a record it is often better not to rely on default values as it prevents sharing of keys, which may in the end use more memory than what you save from not storing default values in the map.

      If default values are nevertheless required, instead of calling maps:get/3 multiple times, consider putting the default values in a map and merging that -map with the other map:

      DefaultMap = #{Key1 => Value2, Key2 => Value2, ..., KeyN => ValueN},
      -MapWithDefaultsApplied = maps:merge(DefaultMap, OtherMap)

      This helps share keys between the default map and the one you applied defaults +map with the other map:

      DefaultMap = #{Key1 => Value2, Key2 => Value2, ..., KeyN => ValueN},
      +MapWithDefaultsApplied = maps:merge(DefaultMap, OtherMap)

      This helps share keys between the default map and the one you applied defaults to, as long as the default map contains all the keys that will ever be used and not just the ones with default values. Whether this is faster than calling maps:get/3 multiple times depends on the size of the map and the number of @@ -420,21 +420,21 @@

      maps:put/3 is implemented in C.

      If the key is known to already exist in the map, maps:update/3 is slightly more efficient than maps:put/3.

      If the compiler can determine that the third argument is always a map, it -will rewrite the call to maps:put/3 to use the map syntax for updating the map.

      For example, consider the following function:

      add_to_known_map(Map0, A, B, C) when is_map(Map0) ->
      -    Map1 = maps:put(a, A, Map0),
      -    Map2 = maps:put(b, B, Map1),
      -    maps:put(c, C, Map2).

      The compiler first rewrites each call to maps:put/3 to use the map +will rewrite the call to maps:put/3 to use the map syntax for updating the map.

      For example, consider the following function:

      add_to_known_map(Map0, A, B, C) when is_map(Map0) ->
      +    Map1 = maps:put(a, A, Map0),
      +    Map2 = maps:put(b, B, Map1),
      +    maps:put(c, C, Map2).

      The compiler first rewrites each call to maps:put/3 to use the map syntax, and subsequently combines the three update operations to a -single update operation:

      add_to_known_map(Map0, A, B, C) when is_map(Map0) ->
      -    Map0#{a => A, b => B, c => C}.

      If the compiler cannot determine that the third argument is always a +single update operation:

      add_to_known_map(Map0, A, B, C) when is_map(Map0) ->
      +    Map0#{a => A, b => B, c => C}.

      If the compiler cannot determine that the third argument is always a map, it retains the maps:put/3 call. For example, given this -function:

      add_to_map(Map0, A, B, C) ->
      -    Map1 = maps:put(a, A, Map0),
      -    Map2 = maps:put(b, B, Map1),
      -    maps:put(c, C, Map2).

      the compiler keeps the first call to maps:put/3, but rewrites -and combines the other two calls:

      add_to_map(Map0, A, B, C) ->
      -    Map1 = maps:put(a, A, Map0),
      -    Map1#{b => B, c => C}.

      Change

      The rewriting of maps:put/3 to the map syntax was introduced in +function:

      add_to_map(Map0, A, B, C) ->
      +    Map1 = maps:put(a, A, Map0),
      +    Map2 = maps:put(b, B, Map1),
      +    maps:put(c, C, Map2).

      the compiler keeps the first call to maps:put/3, but rewrites +and combines the other two calls:

      add_to_map(Map0, A, B, C) ->
      +    Map1 = maps:put(a, A, Map0),
      +    Map1#{b => B, c => C}.

      Change

      The rewriting of maps:put/3 to the map syntax was introduced in Erlang/OTP 28.

      diff --git a/prs/9045/doc/system/modules.html b/prs/9045/doc/system/modules.html index a27fa66d2c60..83b6c9067403 100644 --- a/prs/9045/doc/system/modules.html +++ b/prs/9045/doc/system/modules.html @@ -128,12 +128,12 @@

      Module Syntax

      Erlang code is divided into modules. A module consists of a sequence of -attributes and function declarations, each terminated by a period (.).

      Example:

      -module(m).          % module attribute
      --export([fact/1]).   % module attribute
      +attributes and function declarations, each terminated by a period (.).

      Example:

      -module(m).          % module attribute
      +-export([fact/1]).   % module attribute
       
      -fact(N) when N>0 ->  % beginning of function declaration
      -    N * fact(N-1);   %  |
      -fact(0) ->           %  |
      +fact(N) when N>0 ->  % beginning of function declaration
      +    N * fact(N-1);   %  |
      +fact(0) ->           %  |
           1.               % end of function declaration

      For a description of function declarations, see Function Declaration Syntax.

      @@ -186,9 +186,9 @@

      Behaviour Module Attribute

      It is possible to specify that the module is the callback module for a -behaviour:

      -behaviour(Behaviour).

      The atom Behaviour gives the name of the behaviour, which can be a +behaviour:

      -behaviour(Behaviour).

      The atom Behaviour gives the name of the behaviour, which can be a user-defined behaviour or one of the following OTP standard behaviours:

      • gen_server
      • gen_statem
      • gen_event
      • supervisor

      The spelling behavior is also accepted.

      The callback functions of the module can be specified either directly by the -exported function behaviour_info/1:

      behaviour_info(callbacks) -> Callbacks.

      or by a -callback attribute for each callback function:

      -callback Name(Arguments) -> Result.

      Here, Arguments is a list of zero or more arguments. The -callback attribute +exported function behaviour_info/1:

      behaviour_info(callbacks) -> Callbacks.

      or by a -callback attribute for each callback function:

      -callback Name(Arguments) -> Result.

      Here, Arguments is a list of zero or more arguments. The -callback attribute is to be preferred since the extra type information can be used by tools to produce documentation or find discrepancies.

      Read more about behaviours and callback modules in OTP Design Principles.

      @@ -197,7 +197,7 @@

      Record Definitions

      -

      The same syntax as for module attributes is used for record definitions:

      -record(Record, Fields).

      Record definitions are allowed anywhere in a module, also among the function +

      The same syntax as for module attributes is used for record definitions:

      -record(Record, Fields).

      Record definitions are allowed anywhere in a module, also among the function declarations. Read more in Records.

      @@ -205,15 +205,15 @@

      Preprocessor

      The same syntax as for module attributes is used by the preprocessor, which -supports file inclusion, macros, and conditional compilation:

      -include("SomeFile.hrl").
      --define(Macro, Replacement).

      Read more in Preprocessor.

      +supports file inclusion, macros, and conditional compilation:

      -include("SomeFile.hrl").
      +-define(Macro, Replacement).

      Read more in Preprocessor.

      Setting File and Line

      The same syntax as for module attributes is used for changing the pre-defined -macros ?FILE and ?LINE:

      -file(File, Line).

      This attribute is used by tools, such as Yecc, to inform the compiler that the +macros ?FILE and ?LINE:

      -file(File, Line).

      This attribute is used by tools, such as Yecc, to inform the compiler that the source program is generated by another tool. It also indicates the correspondence of source files to lines of the original user-written file, from which the source program is produced.

      @@ -223,8 +223,8 @@

      Types and function specifications

      A similar syntax as for module attributes is used for specifying types and -function specifications:

      -type my_type() :: atom() | integer().
      --spec my_function(integer()) -> integer().

      Read more in Types and Function specifications.

      The description is based on +function specifications:

      -type my_type() :: atom() | integer().
      +-spec my_function(integer()) -> integer().

      Read more in Types and Function specifications.

      The description is based on EEP8 - Types and function specifications, which is not to be further updated.

      @@ -233,16 +233,16 @@

      Documentation attributes

      The module attribute -doc(Documentation) is used to provide user documentation -for a function/type/callback:

      -doc("Example documentation").
      -example() -> ok.

      The attribute should be placed just before the entity it documents.The +for a function/type/callback:

      -doc("Example documentation").
      +example() -> ok.

      The attribute should be placed just before the entity it documents.The parenthesis are optional around Documentation. The allowed values for Documentation are:

      • literal string or utf-8 encoded binary string - The string documenting the entity. Any literal string is allowed, so both triple quoted strings and sigils that translate to literal strings can be used. -The following examples are equivalent:

        -doc("Example \"docs\"").
        --doc(<<"Example \"docs\""/utf8>>).
        +The following examples are equivalent:

        -doc("Example \"docs\"").
        +-doc(<<"Example \"docs\""/utf8>>).
         -doc ~S/Example "docs"/.
         -doc """
            Example "docs"
        @@ -263,7 +263,7 @@ 

        While not a module attribute, but rather a directive (since it might affect syntax), there is the -feature(..) directive used for enabling and disabling -features.

        The syntax is similar to that of an attribute, but has two arguments:

        -feature(FeatureName, enable | disable).

        Note that the feature directive can only appear +features.

        The syntax is similar to that of an attribute, but has two arguments:

        -feature(FeatureName, enable | disable).

        Note that the feature directive can only appear in a prefix of the module.

        diff --git a/prs/9045/doc/system/nif.html b/prs/9045/doc/system/nif.html index 35cb4bae8300..de933c740bd9 100644 --- a/prs/9045/doc/system/nif.html +++ b/prs/9045/doc/system/nif.html @@ -143,18 +143,18 @@

        they can also be used as fallback implementations for functions that do not have native implementations on some architectures.

        NIF libraries are loaded by calling erlang:load_nif/2, with the name of the shared library as argument. The second argument can be any term that will be -passed on to the library and used for initialization:

        -module(complex6).
        --export([foo/1, bar/1]).
        --nifs([foo/1, bar/1]).
        --on_load(init/0).
        -
        -init() ->
        -    ok = erlang:load_nif("./complex6_nif", 0).
        -
        -foo(_X) ->
        -    erlang:nif_error(nif_library_not_loaded).
        -bar(_Y) ->
        -    erlang:nif_error(nif_library_not_loaded).

        Here, the directive on_load is used to get function init to be automatically +passed on to the library and used for initialization:

        -module(complex6).
        +-export([foo/1, bar/1]).
        +-nifs([foo/1, bar/1]).
        +-on_load(init/0).
        +
        +init() ->
        +    ok = erlang:load_nif("./complex6_nif", 0).
        +
        +foo(_X) ->
        +    erlang:nif_error(nif_library_not_loaded).
        +bar(_Y) ->
        +    erlang:nif_error(nif_library_not_loaded).

        Here, the directive on_load is used to get function init to be automatically called when the module is loaded. If init returns anything other than ok, such when the loading of the NIF library fails in this example, the module is unloaded and calls to functions within it, fail.

        Loading the NIF library overrides the stub implementations and cause calls to @@ -175,35 +175,35 @@

        API functions. The environment contains information about the calling Erlang process:

        #include <erl_nif.h>
         
        -extern int foo(int x);
        -extern int bar(int y);
        +extern int foo(int x);
        +extern int bar(int y);
         
        -static ERL_NIF_TERM foo_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
        -{
        +static ERL_NIF_TERM foo_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
        +{
             int x, ret;
        -    if (!enif_get_int(env, argv[0], &x)) {
        -	return enif_make_badarg(env);
        -    }
        -    ret = foo(x);
        -    return enif_make_int(env, ret);
        -}
        -
        -static ERL_NIF_TERM bar_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
        -{
        +    if (!enif_get_int(env, argv[0], &x)) {
        +	return enif_make_badarg(env);
        +    }
        +    ret = foo(x);
        +    return enif_make_int(env, ret);
        +}
        +
        +static ERL_NIF_TERM bar_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
        +{
             int y, ret;
        -    if (!enif_get_int(env, argv[0], &y)) {
        -	return enif_make_badarg(env);
        -    }
        -    ret = bar(y);
        -    return enif_make_int(env, ret);
        -}
        -
        -static ErlNifFunc nif_funcs[] = {
        -    {"foo", 1, foo_nif},
        -    {"bar", 1, bar_nif}
        -};
        -
        -ERL_NIF_INIT(complex6, nif_funcs, NULL, NULL, NULL, NULL)

        Here, ERL_NIF_INIT has the following arguments:

        • The first argument must be the name of the Erlang module as a C-identifier. It + if (!enif_get_int(env, argv[0], &y)) { + return enif_make_badarg(env); + } + ret = bar(y); + return enif_make_int(env, ret); +} + +static ErlNifFunc nif_funcs[] = { + {"foo", 1, foo_nif}, + {"bar", 1, bar_nif} +}; + +ERL_NIF_INIT(complex6, nif_funcs, NULL, NULL, NULL, NULL)

        Here, ERL_NIF_INIT has the following arguments:

        • The first argument must be the name of the Erlang module as a C-identifier. It will be stringified by the macro.
        • The second argument is the array of ErlNifFunc structures containing name, arity, and function pointer of each NIF.
        • The remaining arguments are pointers to callback functions that can be used to initialize the library. They are not used in this simple example, hence they @@ -219,15 +219,15 @@

          Step 1. Compile the C code:

          unix> gcc -o complex6_nif.so -fpic -shared complex.c complex6_nif.c
           windows> cl -LD -MD -Fe complex6_nif.dll complex.c complex6_nif.c

          Step 2: Start Erlang and compile the Erlang code:

          > erl
          -Erlang R13B04 (erts-5.7.5) [64-bit] [smp:4:4] [rq:4] [async-threads:0] [kernel-poll:false]
          +Erlang R13B04 (erts-5.7.5) [64-bit] [smp:4:4] [rq:4] [async-threads:0] [kernel-poll:false]
           
          -Eshell V5.7.5  (abort with ^G)
          -1> c(complex6).
          -{ok,complex6}

          Step 3: Run the example:

          3> complex6:foo(3).
          +Eshell V5.7.5  (abort with ^G)
          +1> c(complex6).
          +{ok,complex6}

          Step 3: Run the example:

          3> complex6:foo(3).
           4
          -4> complex6:bar(5).
          +4> complex6:bar(5).
           10
          -5> complex6:foo("not an integer").
          +5> complex6:foo("not an integer").
           ** exception error: bad argument
                in function  complex6:foo/1
                   called as comlpex6:foo("not an integer")
          diff --git a/prs/9045/doc/system/opaques.html b/prs/9045/doc/system/opaques.html index c60a1e05239e..3bacc9eabf2c 100644 --- a/prs/9045/doc/system/opaques.html +++ b/prs/9045/doc/system/opaques.html @@ -132,16 +132,16 @@

          The runtime does not check opacity. Dialyzer provides some opacity-checking, but the rest is up to convention.

          This document explains what Erlang opacity is (and the trade-offs involved) via the example of the sets:set() data type. This type was -defined in the sets module like this:

          -opaque set(Element) :: #set{segs :: segs(Element)}.

          OTP 24 changed the definition to the following in -this commit.

          -opaque set(Element) :: #set{segs :: segs(Element)} | #{Element => ?VALUE}.

          And this change was safer and more backwards-compatible than if the type had +defined in the sets module like this:

          -opaque set(Element) :: #set{segs :: segs(Element)}.

          OTP 24 changed the definition to the following in +this commit.

          -opaque set(Element) :: #set{segs :: segs(Element)} | #{Element => ?VALUE}.

          And this change was safer and more backwards-compatible than if the type had been defined with -type instead of -opaque. Here is why: when a module defines an -opaque, the contract is that only the defining module should rely on the definition of the type: no other modules should rely on the definition.

          This means that code that pattern-matched on set as a record/tuple technically broke the contract, and opted in to being potentially broken when the definition of set() changed. Before OTP 24, this code printed ok. In OTP 24 it may -error:

          case sets:new() of
          -    Set when is_tuple(Set) ->
          -        io:format("ok")
          +error:

          case sets:new() of
          +    Set when is_tuple(Set) ->
          +        io:format("ok")
           end.

          When working with an opaque defined in another module, here are some recommendations:

          • Don't examine the underlying type using pattern-matching, guards, or functions that reveal the type, such as tuple_size/1 .
          • Instead, use functions provided by the module for working with the type. For diff --git a/prs/9045/doc/system/otp-patch-apply.html b/prs/9045/doc/system/otp-patch-apply.html index 5e5aeab58e97..34b089e08193 100644 --- a/prs/9045/doc/system/otp-patch-apply.html +++ b/prs/9045/doc/system/otp-patch-apply.html @@ -211,7 +211,7 @@

            Application dependencies are verified among installed applications by otp_patch_apply, but these are not necessarily those actually loaded. By calling system_information:sanity_check() one can validate -dependencies among applications actually loaded.

            1> system_information:sanity_check().
            +dependencies among applications actually loaded.

            1> system_information:sanity_check().
             ok

            Please take a look at the reference of sanity_check() for more information.

    diff --git a/prs/9045/doc/system/patterns.html b/prs/9045/doc/system/patterns.html index cf58b35093cc..0644c27e88e0 100644 --- a/prs/9045/doc/system/patterns.html +++ b/prs/9045/doc/system/patterns.html @@ -138,10 +138,10 @@

    2 3> X + 1. 3 -4> {X, Y} = {1, 2}. +4> {X, Y} = {1, 2}. ** exception error: no match of right hand side value {1,2} -5> {X, Y} = {2, 3}. -{2,3} +5> {X, Y} = {2, 3}. +{2,3} 6> Y. 3

    diff --git a/prs/9045/doc/system/prog_ex_records.html b/prs/9045/doc/system/prog_ex_records.html index df79ce1558aa..9a2ef8d12f52 100644 --- a/prs/9045/doc/system/prog_ex_records.html +++ b/prs/9045/doc/system/prog_ex_records.html @@ -132,17 +132,17 @@

    To illustrate these differences, suppose that you want to represent a person with the tuple {Name, Address, Phone}.

    To write functions that manipulate this data, remember the following:

    • The Name field is the first element of the tuple.
    • The Address field is the second element.
    • The Phone field is the third element.

    For example, to extract data from a variable P that contains such a tuple, you can write the following code and then use pattern matching to extract the -relevant fields:

    Name = element(1, P),
    -Address = element(2, P),
    +relevant fields:

    Name = element(1, P),
    +Address = element(2, P),
     ...

    Such code is difficult to read and understand, and errors occur if the numbering of the elements in the tuple is wrong. If the data representation of the fields is changed, by re-ordering, adding, or removing fields, all references to the person tuple must be checked and possibly modified.

    Records allow references to the fields by name, instead of by position. In the -following example, a record instead of a tuple is used to store the data:

    -record(person, {name, phone, address}).

    This enables references to the fields of the record by name. For example, if P +following example, a record instead of a tuple is used to store the data:

    -record(person, {name, phone, address}).

    This enables references to the fields of the record by name. For example, if P is a variable whose value is a person record, the following code access the name and address fields of the records:

    Name = P#person.name,
     Address = P#person.address,
    -...

    Internally, records are represented using tagged tuples:

    {person, Name, Phone, Address}

    +...

    Internally, records are represented using tagged tuples:

    {person, Name, Phone, Address}

    @@ -152,8 +152,8 @@

    section. Three fields are included, name, phone, and address. The default values for name and phone is "" and [], respectively. The default value for address is the atom undefined, since no default value is supplied for this -field:

    -record(person, {name = "", phone = [], address}).

    The record must be defined in the shell to enable use of the record syntax in -the examples:

    > rd(person, {name = "", phone = [], address}).
    +field:

    -record(person, {name = "", phone = [], address}).

    The record must be defined in the shell to enable use of the record syntax in +the examples:

    > rd(person, {name = "", phone = [], address}).
     person

    This is because record definitions are only available at compile time, not at runtime. For details on records in the shell, see the shell manual page in STDLIB.

    @@ -162,10 +162,10 @@

    Creating a Record

    -

    A new person record is created as follows:

    > #person{phone=[0,8,2,3,4,3,1,2], name="Robert"}.
    -#person{name = "Robert",phone = [0,8,2,3,4,3,1,2],address = undefined}

    As the address field was omitted, its default value is used.

    From Erlang 5.1/OTP R8B, a value to all fields in a record can be set with the -special field _. _ means "all fields not explicitly specified".

    Example:

    > #person{name = "Jakob", _ = '_'}.
    -#person{name = "Jakob",phone = '_',address = '_'}

    It is primarily intended to be used in ets:match/2 and +

    A new person record is created as follows:

    > #person{phone=[0,8,2,3,4,3,1,2], name="Robert"}.
    +#person{name = "Robert",phone = [0,8,2,3,4,3,1,2],address = undefined}

    As the address field was omitted, its default value is used.

    From Erlang 5.1/OTP R8B, a value to all fields in a record can be set with the +special field _. _ means "all fields not explicitly specified".

    Example:

    > #person{name = "Jakob", _ = '_'}.
    +#person{name = "Jakob",phone = '_',address = '_'}

    It is primarily intended to be used in ets:match/2 and mnesia:match_object/3, to set record fields to the atom '_'. (This is a wildcard in ets:match/2.)

    @@ -173,8 +173,8 @@

    Accessing a Record Field

    -

    The following example shows how to access a record field:

    > P = #person{name = "Joe", phone = [0,8,2,3,4,3,1,2]}.
    -#person{name = "Joe",phone = [0,8,2,3,4,3,1,2],address = undefined}
    +

    The following example shows how to access a record field:

    > P = #person{name = "Joe", phone = [0,8,2,3,4,3,1,2]}.
    +#person{name = "Joe",phone = [0,8,2,3,4,3,1,2],address = undefined}
     > P#person.name.
     "Joe"

    @@ -182,33 +182,33 @@

    Updating a Record

    -

    The following example shows how to update a record:

    > P1 = #person{name="Joe", phone=[1,2,3], address="A street"}.
    -#person{name = "Joe",phone = [1,2,3],address = "A street"}
    -> P2 = P1#person{name="Robert"}.
    -#person{name = "Robert",phone = [1,2,3],address = "A street"}

    +

    The following example shows how to update a record:

    > P1 = #person{name="Joe", phone=[1,2,3], address="A street"}.
    +#person{name = "Joe",phone = [1,2,3],address = "A street"}
    +> P2 = P1#person{name="Robert"}.
    +#person{name = "Robert",phone = [1,2,3],address = "A street"}

    Type Testing

    The following example shows that the guard succeeds if P is record of type -person:

    foo(P) when is_record(P, person) -> a_person;
    -foo(_) -> not_a_person.

    +person:

    foo(P) when is_record(P, person) -> a_person;
    +foo(_) -> not_a_person.

    Pattern Matching

    Matching can be used in combination with records, as shown in the following -example:

    > P3 = #person{name="Joe", phone=[0,0,7], address="A street"}.
    -#person{name = "Joe",phone = [0,0,7],address = "A street"}
    -> #person{name = Name} = P3, Name.
    +example:

    > P3 = #person{name="Joe", phone=[0,0,7], address="A street"}.
    +#person{name = "Joe",phone = [0,0,7],address = "A street"}
    +> #person{name = Name} = P3, Name.
     "Joe"

    The following function takes a list of person records and searches for the -phone number of a person with a particular name:

    find_phone([#person{name=Name, phone=Phone} | _], Name) ->
    -    {found,  Phone};
    -find_phone([_| T], Name) ->
    -    find_phone(T, Name);
    -find_phone([], Name) ->
    +phone number of a person with a particular name:

    find_phone([#person{name=Name, phone=Phone} | _], Name) ->
    +    {found,  Phone};
    +find_phone([_| T], Name) ->
    +    find_phone(T, Name);
    +find_phone([], Name) ->
         not_found.

    The fields referred to in the pattern can be given in any order.

    @@ -217,12 +217,12 @@

    The value of a field in a record can be an instance of a record. Retrieval of nested data can be done stepwise, or in a single step, as shown in the following -example:

    -record(name, {first = "Robert", last = "Ericsson"}).
    --record(person, {name = #name{}, phone}).
    +example:

    -record(name, {first = "Robert", last = "Ericsson"}).
    +-record(person, {name = #name{}, phone}).
     
    -demo() ->
    -  P = #person{name= #name{first="Robert",last="Virding"}, phone=123},
    -  First = (P#person.name)#name.first.

    Here, demo() evaluates to "Robert".

    +demo() -> + P = #person{name= #name{first="Robert",last="Virding"}, phone=123}, + First = (P#person.name)#name.first.

    Here, demo() evaluates to "Robert".

    @@ -240,40 +240,40 @@

    %% about the person. %% A {Key, Value} list (default is the empty list). %%------------------------------------------------------------ --record(person, {name, age, phone = [], dict = []}).

    -module(person).
    --include("person.hrl").
    --compile(export_all). % For test purposes only.
    +-record(person, {name, age, phone = [], dict = []}).
    -module(person).
    +-include("person.hrl").
    +-compile(export_all). % For test purposes only.
     
     %% This creates an instance of a person.
     %%   Note: The phone number is not supplied so the
     %%         default value [] will be used.
     
    -make_hacker_without_phone(Name, Age) ->
    -   #person{name = Name, age = Age,
    -           dict = [{computer_knowledge, excellent},
    -                   {drinks, coke}]}.
    +make_hacker_without_phone(Name, Age) ->
    +   #person{name = Name, age = Age,
    +           dict = [{computer_knowledge, excellent},
    +                   {drinks, coke}]}.
     
     %% This demonstrates matching in arguments
     
    -print(#person{name = Name, age = Age,
    -              phone = Phone, dict = Dict}) ->
    -  io:format("Name: ~s, Age: ~w, Phone: ~w ~n"
    -            "Dictionary: ~w.~n", [Name, Age, Phone, Dict]).
    +print(#person{name = Name, age = Age,
    +              phone = Phone, dict = Dict}) ->
    +  io:format("Name: ~s, Age: ~w, Phone: ~w ~n"
    +            "Dictionary: ~w.~n", [Name, Age, Phone, Dict]).
     
     %% Demonstrates type testing, selector, updating.
     
    -birthday(P) when is_record(P, person) ->
    -   P#person{age = P#person.age + 1}.
    +birthday(P) when is_record(P, person) ->
    +   P#person{age = P#person.age + 1}.
     
    -register_two_hackers() ->
    -   Hacker1 = make_hacker_without_phone("Joe", 29),
    -   OldHacker = birthday(Hacker1),
    +register_two_hackers() ->
    +   Hacker1 = make_hacker_without_phone("Joe", 29),
    +   OldHacker = birthday(Hacker1),
        % The central_register_server should have
        % an interface function for this.
    -   central_register_server ! {register_person, Hacker1},
    -   central_register_server ! {register_person,
    -             OldHacker#person{name = "Robert",
    -                              phone = [0,8,3,2,4,5,3,1]}}.
    +
    central_register_server ! {register_person, Hacker1}, + central_register_server ! {register_person, + OldHacker#person{name = "Robert", + phone = [0,8,3,2,4,5,3,1]}}.
    diff --git a/prs/9045/doc/system/records_macros.html b/prs/9045/doc/system/records_macros.html index 597ca3a01d2e..3cd3e3000059 100644 --- a/prs/9045/doc/system/records_macros.html +++ b/prs/9045/doc/system/records_macros.html @@ -134,7 +134,7 @@

    introduced:

    %%%----FILE mess_config.hrl----
     
     %%% Configure the location of the server node,
    --define(server_node, messenger@super).
    +-define(server_node, messenger@super).
     
     %%%----END FILE----
    %%%----FILE mess_interface.hrl----
     
    @@ -142,24 +142,24 @@ 

    %%% messenger program %%%Messages from Client to server received in server/1 function. --record(logon,{client_pid, username}). --record(message,{client_pid, to_name, message}). +-record(logon,{client_pid, username}). +-record(message,{client_pid, to_name, message}). %%% {'EXIT', ClientPid, Reason} (client terminated or unreachable. %%% Messages from Server to Client, received in await_result/0 function --record(abort_client,{message}). +-record(abort_client,{message}). %%% Messages are: user_exists_at_other_node, %%% you_are_not_logged_on --record(server_reply,{message}). +-record(server_reply,{message}). %%% Messages are: logged_on %%% receiver_not_found %%% sent (Message has been sent (no guarantee) %%% Messages from Server to Client received in client/1 function --record(message_from,{from_name, message}). +-record(message_from,{from_name, message}). %%% Messages from shell to Client received in client/1 function %%% spawn(mess_client, client, [server_node(), Name]) --record(message_to,{to_name, message}). +-record(message_to,{to_name, message}). %%% logoff %%%----END FILE----

    %%%----FILE user_interface.erl----
    @@ -180,27 +180,27 @@ 

    %%% function is not logged on or if ToName is not logged on at %%% any node. --module(user_interface). --export([logon/1, logoff/0, message/2]). --include("mess_interface.hrl"). --include("mess_config.hrl"). +-module(user_interface). +-export([logon/1, logoff/0, message/2]). +-include("mess_interface.hrl"). +-include("mess_config.hrl"). -logon(Name) -> - case whereis(mess_client) of +logon(Name) -> + case whereis(mess_client) of undefined -> - register(mess_client, - spawn(mess_client, client, [?server_node, Name])); + register(mess_client, + spawn(mess_client, client, [?server_node, Name])); _ -> already_logged_on end. -logoff() -> +logoff() -> mess_client ! logoff. -message(ToName, Message) -> - case whereis(mess_client) of % Test if the client is running +message(ToName, Message) -> + case whereis(mess_client) of % Test if the client is running undefined -> not_logged_on; - _ -> mess_client ! #message_to{to_name=ToName, message=Message}, + _ -> mess_client ! #message_to{to_name=ToName, message=Message}, ok end. @@ -208,107 +208,107 @@

    %%% The client process which runs on each user node --module(mess_client). --export([client/2]). --include("mess_interface.hrl"). +-module(mess_client). +-export([client/2]). +-include("mess_interface.hrl"). -client(Server_Node, Name) -> - {messenger, Server_Node} ! #logon{client_pid=self(), username=Name}, - await_result(), - client(Server_Node). +client(Server_Node, Name) -> + {messenger, Server_Node} ! #logon{client_pid=self(), username=Name}, + await_result(), + client(Server_Node). -client(Server_Node) -> +client(Server_Node) -> receive logoff -> - exit(normal); - #message_to{to_name=ToName, message=Message} -> - {messenger, Server_Node} ! - #message{client_pid=self(), to_name=ToName, message=Message}, - await_result(); - {message_from, FromName, Message} -> - io:format("Message from ~p: ~p~n", [FromName, Message]) + exit(normal); + #message_to{to_name=ToName, message=Message} -> + {messenger, Server_Node} ! + #message{client_pid=self(), to_name=ToName, message=Message}, + await_result(); + {message_from, FromName, Message} -> + io:format("Message from ~p: ~p~n", [FromName, Message]) end, - client(Server_Node). + client(Server_Node). %%% wait for a response from the server -await_result() -> +await_result() -> receive - #abort_client{message=Why} -> - io:format("~p~n", [Why]), - exit(normal); - #server_reply{message=What} -> - io:format("~p~n", [What]) + #abort_client{message=Why} -> + io:format("~p~n", [Why]), + exit(normal); + #server_reply{message=What} -> + io:format("~p~n", [What]) after 5000 -> - io:format("No response from server~n", []), - exit(timeout) + io:format("No response from server~n", []), + exit(timeout) end. %%%----END FILE---

    %%%----FILE mess_server.erl----
     
     %%% This is the server process of the messenger service
     
    --module(mess_server).
    --export([start_server/0, server/0]).
    --include("mess_interface.hrl").
    +-module(mess_server).
    +-export([start_server/0, server/0]).
    +-include("mess_interface.hrl").
     
    -server() ->
    -    process_flag(trap_exit, true),
    -    server([]).
    +server() ->
    +    process_flag(trap_exit, true),
    +    server([]).
     
     %%% the user list has the format [{ClientPid1, Name1},{ClientPid22, Name2},...]
    -server(User_List) ->
    -    io:format("User list = ~p~n", [User_List]),
    +server(User_List) ->
    +    io:format("User list = ~p~n", [User_List]),
         receive
    -        #logon{client_pid=From, username=Name} ->
    -            New_User_List = server_logon(From, Name, User_List),
    -            server(New_User_List);
    -        {'EXIT', From, _} ->
    -            New_User_List = server_logoff(From, User_List),
    -            server(New_User_List);
    -        #message{client_pid=From, to_name=To, message=Message} ->
    -            server_transfer(From, To, Message, User_List),
    -            server(User_List)
    +        #logon{client_pid=From, username=Name} ->
    +            New_User_List = server_logon(From, Name, User_List),
    +            server(New_User_List);
    +        {'EXIT', From, _} ->
    +            New_User_List = server_logoff(From, User_List),
    +            server(New_User_List);
    +        #message{client_pid=From, to_name=To, message=Message} ->
    +            server_transfer(From, To, Message, User_List),
    +            server(User_List)
         end.
     
     %%% Start the server
    -start_server() ->
    -    register(messenger, spawn(?MODULE, server, [])).
    +start_server() ->
    +    register(messenger, spawn(?MODULE, server, [])).
     
     %%% Server adds a new user to the user list
    -server_logon(From, Name, User_List) ->
    +server_logon(From, Name, User_List) ->
         %% check if logged on anywhere else
    -    case lists:keymember(Name, 2, User_List) of
    +    case lists:keymember(Name, 2, User_List) of
             true ->
    -            From ! #abort_client{message=user_exists_at_other_node},
    +            From ! #abort_client{message=user_exists_at_other_node},
                 User_List;
             false ->
    -            From ! #server_reply{message=logged_on},
    -            link(From),
    -            [{From, Name} | User_List]        %add user to the list
    +            From ! #server_reply{message=logged_on},
    +            link(From),
    +            [{From, Name} | User_List]        %add user to the list
         end.
     
     %%% Server deletes a user from the user list
    -server_logoff(From, User_List) ->
    -    lists:keydelete(From, 1, User_List).
    +server_logoff(From, User_List) ->
    +    lists:keydelete(From, 1, User_List).
     
     %%% Server transfers a message between user
    -server_transfer(From, To, Message, User_List) ->
    +server_transfer(From, To, Message, User_List) ->
         %% check that the user is logged on and who he is
    -    case lists:keysearch(From, 1, User_List) of
    +    case lists:keysearch(From, 1, User_List) of
             false ->
    -            From ! #abort_client{message=you_are_not_logged_on};
    -        {value, {_, Name}} ->
    -            server_transfer(From, Name, To, Message, User_List)
    +            From ! #abort_client{message=you_are_not_logged_on};
    +        {value, {_, Name}} ->
    +            server_transfer(From, Name, To, Message, User_List)
         end.
     %%% If the user exists, send the message
    -server_transfer(From, Name, To, Message, User_List) ->
    +server_transfer(From, Name, To, Message, User_List) ->
         %% Find the receiver and send the message
    -    case lists:keysearch(To, 2, User_List) of
    +    case lists:keysearch(To, 2, User_List) of
             false ->
    -            From ! #server_reply{message=receiver_not_found};
    -        {value, {ToPid, To}} ->
    -            ToPid ! #message_from{from_name=Name, message=Message},
    -            From !  #server_reply{message=sent}
    +            From ! #server_reply{message=receiver_not_found};
    +        {value, {ToPid, To}} ->
    +            ToPid ! #message_from{from_name=Name, message=Message},
    +            From !  #server_reply{message=sent}
         end.
     
     %%%----END FILE---

    @@ -318,7 +318,7 @@

    Header Files

    As shown above, some files have extension .hrl. These are header files that -are included in the .erl files by:

    -include("File_Name").

    for example:

    -include("mess_interface.hrl").

    In the case above the file is fetched from the same directory as all the other +are included in the .erl files by:

    -include("File_Name").

    for example:

    -include("mess_interface.hrl").

    In the case above the file is fetched from the same directory as all the other files in the messenger example. (manual).

    .hrl files can contain any valid Erlang code but are most often used for record and macro definitions.

    @@ -326,14 +326,14 @@

    Records

    -

    A record is defined as:

    -record(name_of_record,{field_name1, field_name2, field_name3, ......}).

    For example:

    -record(message_to,{to_name, message}).

    This is equivalent to:

    {message_to, To_Name, Message}

    Creating a record is best illustrated by an example:

    #message_to{message="hello", to_name=fred)

    This creates:

    {message_to, fred, "hello"}

    Notice that you do not have to worry about the order you assign values to the +

    A record is defined as:

    -record(name_of_record,{field_name1, field_name2, field_name3, ......}).

    For example:

    -record(message_to,{to_name, message}).

    This is equivalent to:

    {message_to, To_Name, Message}

    Creating a record is best illustrated by an example:

    #message_to{message="hello", to_name=fred)

    This creates:

    {message_to, fred, "hello"}

    Notice that you do not have to worry about the order you assign values to the various parts of the records when you create it. The advantage of using records is that by placing their definitions in header files you can conveniently define interfaces that are easy to change. For example, if you want to add a new field to the record, you only have to change the code where the new field is used and not at every place the record is referred to. If you leave out a field when creating a record, it gets the value of the atom undefined. (manual)

    Pattern matching with records is very similar to creating records. For example, -inside a case or receive:

    #message_to{to_name=ToName, message=Message} ->

    This is the same as:

    {message_to, ToName, Message}

    +inside a case or receive:

    #message_to{to_name=ToName, message=Message} ->

    This is the same as:

    {message_to, ToName, Message}

    @@ -341,8 +341,8 @@

    Another thing that has been added to the messenger is a macro. The file mess_config.hrl contains the definition:

    %%% Configure the location of the server node,
    --define(server_node, messenger@super).

    This file is included in mess_server.erl:

    -include("mess_config.hrl").

    Every occurrence of ?server_node in mess_server.erl is now replaced by -messenger@super.

    A macro is also used when spawning the server process:

    spawn(?MODULE, server, [])

    This is a standard macro (that is, defined by the system, not by the user). +-define(server_node, messenger@super).

    This file is included in mess_server.erl:

    -include("mess_config.hrl").

    Every occurrence of ?server_node in mess_server.erl is now replaced by +messenger@super.

    A macro is also used when spawning the server process:

    spawn(?MODULE, server, [])

    This is a standard macro (that is, defined by the system, not by the user). ?MODULE is always replaced by the name of the current module (that is, the -module definition near the start of the file). There are more advanced ways of using macros with, for example, parameters.

    The three Erlang (.erl) files in the messenger example are individually diff --git a/prs/9045/doc/system/ref_man_functions.html b/prs/9045/doc/system/ref_man_functions.html index cd8c7d4dd428..48b677117bb8 100644 --- a/prs/9045/doc/system/ref_man_functions.html +++ b/prs/9045/doc/system/ref_man_functions.html @@ -130,10 +130,10 @@

    A function declaration is a sequence of function clauses separated by semicolons, and terminated by a period (.).

    A function clause consists of a clause head and a clause body, separated by ->.

    A clause head consists of the function name, an argument list, and an optional -guard sequence beginning with the keyword when:

    Name(Pattern11,...,Pattern1N) [when GuardSeq1] ->
    +guard sequence beginning with the keyword when:

    Name(Pattern11,...,Pattern1N) [when GuardSeq1] ->
         Body1;
     ...;
    -Name(PatternK1,...,PatternKN) [when GuardSeqK] ->
    +Name(PatternK1,...,PatternKN) [when GuardSeqK] ->
         BodyK.

    The function name is an atom. Each argument is a pattern.

    The number of arguments N is the arity of the function. A function is uniquely defined by the module name, function name, and arity. That is, two functions with the same name and in the same module, but with different arities @@ -141,10 +141,10 @@

    mod:f/N.

    A clause body consists of a sequence of expressions separated by comma (,):

    Expr1,
     ...,
     ExprN

    Valid Erlang expressions and guard sequences are described in -Expressions.

    Example:

    fact(N) when N > 0 ->  % first clause head
    -    N * fact(N-1);     % first clause body
    +Expressions.

    Example:

    fact(N) when N > 0 ->  % first clause head
    +    N * fact(N-1);     % first clause body
     
    -fact(0) ->             % second clause head
    +fact(0) ->             % second clause head
         1.                 % second clause body

    @@ -157,16 +157,16 @@

    clause is found that fulfills both of the following two conditions:

    1. The patterns in the clause head can be successfully matched against the given arguments.
    2. The guard sequence, if any, is true.

    If such a clause cannot be found, a function_clause runtime error occurs.

    If such a clause is found, the corresponding clause body is evaluated. That is, the expressions in the body are evaluated sequentially and the value of the last -expression is returned.

    Consider the function fact:

    -module(mod).
    --export([fact/1]).
    +expression is returned.

    Consider the function fact:

    -module(mod).
    +-export([fact/1]).
     
    -fact(N) when N > 0 ->
    -    N * fact(N - 1);
    -fact(0) ->
    +fact(N) when N > 0 ->
    +    N * fact(N - 1);
    +fact(0) ->
         1.

    Assume that you want to calculate the factorial for 1:

    1> mod:fact(1).

    Evaluation starts at the first clause. The pattern N is matched against argument 1. The matching succeeds and the guard (N > 0) is true, thus N is -bound to 1, and the corresponding body is evaluated:

    N * fact(N-1) => (N is bound to 1)
    -1 * fact(0)

    Now, fact(0) is called, and the function clauses are scanned +bound to 1, and the corresponding body is evaluated:

    N * fact(N-1) => (N is bound to 1)
    +1 * fact(0)

    Now, fact(0) is called, and the function clauses are scanned sequentially again. First, the pattern N is matched against 0. The matching succeeds, but the guard (N > 0) is false. Second, the pattern 0 is matched against the argument 0. The matching succeeds @@ -183,9 +183,9 @@

    tail-recursive call is done. This is to ensure that no system resources, for example, call stack, are consumed. This means that an infinite loop using tail-recursive calls will not exhaust the call -stack and can (in principle) run forever.

    Example:

    loop(N) ->
    -    io:format("~w~n", [N]),
    -    loop(N+1).

    The earlier factorial example is a counter-example. It is not +stack and can (in principle) run forever.

    Example:

    loop(N) ->
    +    io:format("~w~n", [N]),
    +    loop(N+1).

    The earlier factorial example is a counter-example. It is not tail-recursive, since a multiplication is done on the result of the recursive call to fact(N-1).

    @@ -201,9 +201,9 @@

    not need to be prefixed with the module name. Which BIFs that are auto-imported is specified in the erlang module in ERTS. For example, standard-type conversion BIFs like atom_to_list and BIFs allowed in guards can be called -without specifying the module name.

    Examples:

    1> tuple_size({a,b,c}).
    +without specifying the module name.

    Examples:

    1> tuple_size({a,b,c}).
     3
    -2> atom_to_list('Erlang').
    +2> atom_to_list('Erlang').
     "Erlang"
    diff --git a/prs/9045/doc/system/ref_man_processes.html b/prs/9045/doc/system/ref_man_processes.html index 24f6bc2295d3..59926d032135 100644 --- a/prs/9045/doc/system/ref_man_processes.html +++ b/prs/9045/doc/system/ref_man_processes.html @@ -135,10 +135,10 @@

    Process Creation

    -

    A process is created by calling spawn():

    spawn(Module, Name, Args) -> pid()
    -  Module = Name = atom()
    -  Args = [Arg1,...,ArgN]
    -    ArgI = term()

    spawn() creates a new process and returns the pid.

    The new process starts executing in Module:Name(Arg1,...,ArgN) where the +

    A process is created by calling spawn():

    spawn(Module, Name, Args) -> pid()
    +  Module = Name = atom()
    +  Args = [Arg1,...,ArgN]
    +    ArgI = term()

    spawn() creates a new process and returns the pid.

    The new process starts executing in Module:Name(Arg1,...,ArgN) where the arguments are the elements of the (possible empty) Args argument list.

    There exist a number of different spawn BIFs:

    diff --git a/prs/9045/doc/system/ref_man_records.html b/prs/9045/doc/system/ref_man_records.html index ed0198289e76..936b32e35271 100644 --- a/prs/9045/doc/system/ref_man_records.html +++ b/prs/9045/doc/system/ref_man_records.html @@ -133,9 +133,9 @@

    A record definition consists of the name of the record, followed by the field names of the record. Record and field names must be atoms. Each field can be given an optional default value. If no default value is supplied, undefined is -used.

    -record(Name, {Field1 [= Expr1],
    +used.

    -record(Name, {Field1 [= Expr1],
                    ...
    -               FieldN [= ExprN]}).

    The default value for a field is an arbitrary expression, except that it must + FieldN [= ExprN]}).

    The default value for a field is an arbitrary expression, except that it must not use any variables.

    A record definition can be placed anywhere among the attributes and function declarations of a module, but the definition must come before any usage of the record.

    If a record is used in several modules, it is recommended that the record @@ -153,24 +153,24 @@

    default value instead.

    If several fields are to be assigned the same value, the following construction can be used:

    #Name{Field1=Expr1, ..., FieldK=ExprK, _=ExprL}

    Omitted fields then get the value of evaluating ExprL instead of their default values. This feature is primarily intended to be used to create patterns for ETS -and Mnesia match functions.

    Example:

    -record(person, {name, phone, address}).
    +and Mnesia match functions.

    Example:

    -record(person, {name, phone, address}).
     
    -lookup(Name, Tab) ->
    -    ets:match_object(Tab, #person{name=Name, _='_'}).

    +lookup(Name, Tab) -> + ets:match_object(Tab, #person{name=Name, _='_'}).

    Accessing Record Fields

    Expr#Name.Field

    Returns the value of the specified field. Expr is to evaluate to a Name -record.

    Example:

    -record(person, {name, phone, address}).
    +record.

    Example:

    -record(person, {name, phone, address}).
     
    -get_person_name(Person) ->
    +get_person_name(Person) ->
         Person#person.name.

    The following expression returns the position of the specified field in the -tuple representation of the record:

    #Name.Field

    Example:

    -record(person, {name, phone, address}).
    +tuple representation of the record:

    #Name.Field

    Example:

    -record(person, {name, phone, address}).
     
    -lookup(Name, List) ->
    -    lists:keyfind(Name, #person.name, List).

    +lookup(Name, List) -> + lists:keyfind(Name, #person.name, List).

    @@ -188,13 +188,13 @@

    Since record expressions are expanded to tuple expressions, creating records and accessing record fields are allowed in guards. However, all subexpressions (for initializing fields), must be valid guard -expressions as well.

    Examples:

    handle(Msg, State) when Msg =:= #msg{to=void, no=3} ->
    +expressions as well.

    Examples:

    handle(Msg, State) when Msg =:= #msg{to=void, no=3} ->
         ...
     
    -handle(Msg, State) when State#state.running =:= true ->
    -    ...

    There is also a type test BIF is_record(Term, RecordTag).

    Example:

    is_person(P) when is_record(P, person) ->
    +handle(Msg, State) when State#state.running =:= true ->
    +    ...

    There is also a type test BIF is_record(Term, RecordTag).

    Example:

    is_person(P) when is_record(P, person) ->
         true;
    -is_person(_P) ->
    +is_person(_P) ->
         false.

    @@ -208,11 +208,11 @@

    Nested Records

    -

    Assume the following record definitions:

    -record(nrec0, {name = "nested0"}).
    --record(nrec1, {name = "nested1", nrec0=#nrec0{}}).
    --record(nrec2, {name = "nested2", nrec1=#nrec1{}}).
    +

    Assume the following record definitions:

    -record(nrec0, {name = "nested0"}).
    +-record(nrec1, {name = "nested1", nrec0=#nrec0{}}).
    +-record(nrec2, {name = "nested2", nrec1=#nrec1{}}).
     
    -N2 = #nrec2{},

    Accessing or updating nested records can be written without parentheses:

    "nested0" = N2#nrec2.nrec1#nrec1.nrec0#nrec0.name,
    +N2 = #nrec2{},

    Accessing or updating nested records can be written without parentheses:

    "nested0" = N2#nrec2.nrec1#nrec1.nrec0#nrec0.name,
         N0n = N2#nrec2.nrec1#nrec1.nrec0#nrec0{name = "nested0a"},

    which is equivalent to:

    "nested0" = ((N2#nrec2.nrec1)#nrec1.nrec0)#nrec0.name,
     N0n = ((N2#nrec2.nrec1)#nrec1.nrec0)#nrec0{name = "nested0a"},

    Change

    Before Erlang/OTP R14, parentheses were necessary when accessing or updating nested records.

    @@ -222,9 +222,9 @@

    Internal Representation of Records

    Record expressions are translated to tuple expressions during compilation. A -record defined as:

    -record(Name, {Field1, ..., FieldN}).

    is internally represented by the tuple:

    {Name, Value1, ..., ValueN}

    Here each ValueI is the default value for FieldI.

    To each module using records, a pseudo function is added during compilation to -obtain information about records:

    record_info(fields, Record) -> [Field]
    -record_info(size, Record) -> Size

    Size is the size of the tuple representation, that is, one more than the +record defined as:

    -record(Name, {Field1, ..., FieldN}).

    is internally represented by the tuple:

    {Name, Value1, ..., ValueN}

    Here each ValueI is the default value for FieldI.

    To each module using records, a pseudo function is added during compilation to +obtain information about records:

    record_info(fields, Record) -> [Field]
    +record_info(size, Record) -> Size

    Size is the size of the tuple representation, that is, one more than the number of fields.

    diff --git a/prs/9045/doc/system/release_handling.html b/prs/9045/doc/system/release_handling.html index 7f72ff37ea40..eeab8c179217 100644 --- a/prs/9045/doc/system/release_handling.html +++ b/prs/9045/doc/system/release_handling.html @@ -233,15 +233,15 @@

    Instead, it is necessary to:

    • Suspend the processes using the module (to avoid that they try to handle any requests before the code replacement is completed).
    • Ask them to transform the internal state format and switch to the new version of the module.
    • Remove the old version.
    • Resume the processes.

    This is called synchronized code replacement and for this the following -instructions are used:

    {update, Module, {advanced, Extra}}
    -{update, Module, supervisor}

    update with argument {advanced,Extra} is used when changing the internal +instructions are used:

    {update, Module, {advanced, Extra}}
    +{update, Module, supervisor}

    update with argument {advanced,Extra} is used when changing the internal state of a behaviour as described above. It causes behaviour processes to call the callback function code_change/3, passing the term Extra and some other information as arguments. See the manual pages for the respective behaviours and Appup Cookbook.

    update with argument supervisor is used when changing the start specification of a supervisor. See Appup Cookbook.

    When a module is to be updated, the release handler finds which processes that are using the module by traversing the supervision tree of each running -application and checking all the child specifications:

    {Id, StartFunc, Restart, Shutdown, Type, Modules}

    A process uses a module if the name is listed in Modules in the child +application and checking all the child specifications:

    {Id, StartFunc, Restart, Shutdown, Type, Modules}

    A process uses a module if the name is listed in Modules in the child specification for the process.

    If Modules=dynamic, which is the case for event managers, the event manager process informs the release handler about the list of currently installed event handlers (gen_event), and it is checked if the module name is in this list @@ -253,10 +253,10 @@

    add_module and delete_module

    -

    If a new module is introduced, the following instruction is used:

    {add_module, Module}

    This instruction loads module Module. When running Erlang in +

    If a new module is introduced, the following instruction is used:

    {add_module, Module}

    This instruction loads module Module. When running Erlang in embedded mode it is necessary to use this this instruction. It is not strictly required when running Erlang in interactive mode, since the -code server automatically searches for and loads unloaded modules.

    The opposite of add_module is delete_module, which unloads a module:

    {delete_module, Module}

    Any process, in any application, with Module as residence module, is +code server automatically searches for and loads unloaded modules.

    The opposite of add_module is delete_module, which unloads a module:

    {delete_module, Module}

    Any process, in any application, with Module as residence module, is killed when the instruction is evaluated. Therefore, the user must ensure that all such processes are terminated before deleting module Module to avoid a situation with failing supervisor restarts.

    @@ -337,13 +337,13 @@

    To define how to upgrade/downgrade between the current version and previous versions of an application, an application upgrade file, or in short .appup file is created. The file is to be called Application.appup, where -Application is the application name:

    {Vsn,
    - [{UpFromVsn1, InstructionsU1},
    +Application is the application name:

    {Vsn,
    + [{UpFromVsn1, InstructionsU1},
       ...,
    -  {UpFromVsnK, InstructionsUK}],
    - [{DownToVsn1, InstructionsD1},
    +  {UpFromVsnK, InstructionsUK}],
    + [{DownToVsn1, InstructionsD1},
       ...,
    -  {DownToVsnK, InstructionsDK}]}.
    • Vsn, a string, is the current version of the application, as defined in the + {DownToVsnK, InstructionsDK}]}.
    • Vsn, a string, is the current version of the application, as defined in the .app file.
    • Each UpFromVsn is a previous version of the application to upgrade from.
    • Each DownToVsn is a previous version of the application to downgrade to.
    • Each Instructions is a list of release handling instructions.

    UpFromVsn and DownToVsn can also be specified as regular expressions. For more information about the syntax and contents of the .appup file, see appup in SASL.

    Appup Cookbook includes examples of .appup files for @@ -351,52 +351,52 @@

    Releases. Assume you want to add a function available/0 to server ch3, which returns the number of available channels (when trying out the example, make the change in a copy of the original -directory, to ensure that the first version is still available):

    -module(ch3).
    --behaviour(gen_server).
    +directory, to ensure that the first version is still available):

    -module(ch3).
    +-behaviour(gen_server).
     
    --export([start_link/0]).
    --export([alloc/0, free/1]).
    --export([available/0]).
    --export([init/1, handle_call/3, handle_cast/2]).
    -
    -start_link() ->
    -    gen_server:start_link({local, ch3}, ch3, [], []).
    -
    -alloc() ->
    -    gen_server:call(ch3, alloc).
    -
    -free(Ch) ->
    -    gen_server:cast(ch3, {free, Ch}).
    -
    -available() ->
    -    gen_server:call(ch3, available).
    -
    -init(_Args) ->
    -    {ok, channels()}.
    -
    -handle_call(alloc, _From, Chs) ->
    -    {Ch, Chs2} = alloc(Chs),
    -    {reply, Ch, Chs2};
    -handle_call(available, _From, Chs) ->
    -    N = available(Chs),
    -    {reply, N, Chs}.
    -
    -handle_cast({free, Ch}, Chs) ->
    -    Chs2 = free(Ch, Chs),
    -    {noreply, Chs2}.

    A new version of the ch_app.app file must now be created, where the version is -updated:

    {application, ch_app,
    - [{description, "Channel allocator"},
    -  {vsn, "2"},
    -  {modules, [ch_app, ch_sup, ch3]},
    -  {registered, [ch3]},
    -  {applications, [kernel, stdlib, sasl]},
    -  {mod, {ch_app,[]}}
    - ]}.

    To upgrade ch_app from "1" to "2" (and to downgrade from "2" to "1"), +-export([start_link/0]). +-export([alloc/0, free/1]). +-export([available/0]). +-export([init/1, handle_call/3, handle_cast/2]). + +start_link() -> + gen_server:start_link({local, ch3}, ch3, [], []). + +alloc() -> + gen_server:call(ch3, alloc). + +free(Ch) -> + gen_server:cast(ch3, {free, Ch}). + +available() -> + gen_server:call(ch3, available). + +init(_Args) -> + {ok, channels()}. + +handle_call(alloc, _From, Chs) -> + {Ch, Chs2} = alloc(Chs), + {reply, Ch, Chs2}; +handle_call(available, _From, Chs) -> + N = available(Chs), + {reply, N, Chs}. + +handle_cast({free, Ch}, Chs) -> + Chs2 = free(Ch, Chs), + {noreply, Chs2}.

    A new version of the ch_app.app file must now be created, where the version is +updated:

    {application, ch_app,
    + [{description, "Channel allocator"},
    +  {vsn, "2"},
    +  {modules, [ch_app, ch_sup, ch3]},
    +  {registered, [ch3]},
    +  {applications, [kernel, stdlib, sasl]},
    +  {mod, {ch_app,[]}}
    + ]}.

    To upgrade ch_app from "1" to "2" (and to downgrade from "2" to "1"), you only need to load the new (old) version of the ch3 callback module. Create -the application upgrade file ch_app.appup in the ebin directory:

    {"2",
    - [{"1", [{load_module, ch3}]}],
    - [{"1", [{load_module, ch3}]}]
    -}.

    +the application upgrade file ch_app.appup in the ebin directory:

    {"2",
    + [{"1", [{load_module, ch3}]}],
    + [{"1", [{load_module, ch3}]}]
    +}.

    @@ -415,14 +415,14 @@

    relup in SASL.

    Example, continued from the previous section: You have a new version "2" of ch_app and an .appup file. A new version of the .rel file is also needed. This time the file is called ch_rel-2.rel and the release version string is -changed from "A" to "B":

    {release,
    - {"ch_rel", "B"},
    - {erts, "14.2.5"},
    - [{kernel, "9.2.4"},
    -  {stdlib, "5.2.3"},
    -  {sasl, "4.2.1"},
    -  {ch_app, "2"}]
    -}.

    Now the relup file can be generated:

    1> systools:make_relup("ch_rel-2", ["ch_rel-1"], ["ch_rel-1"]).
    +changed from "A" to "B":

    {release,
    + {"ch_rel", "B"},
    + {erts, "14.2.5"},
    + [{kernel, "9.2.4"},
    +  {stdlib, "5.2.3"},
    +  {sasl, "4.2.1"},
    +  {ch_app, "2"}]
    +}.

    Now the relup file can be generated:

    1> systools:make_relup("ch_rel-2", ["ch_rel-1"], ["ch_rel-1"]).
     ok

    This generates a relup file with instructions for how to upgrade from version "A" ("ch_rel-1") to version "B" ("ch_rel-2") and how to downgrade from version "B" to version "A".

    Both the old and new versions of the .app and .rel files must be in the code @@ -443,17 +443,17 @@

    packages. The release_handler module communicates with this process.

    Assuming there is an operational target system with installation root directory $ROOT, the release package with the new version of the release is to be copied to $ROOT/releases.

    First, unpack the release package. The files are then extracted from the -package:

    release_handler:unpack_release(ReleaseName) => {ok, Vsn}
    • ReleaseName is the name of the release package except the .tar.gz +package:

      release_handler:unpack_release(ReleaseName) => {ok, Vsn}
      • ReleaseName is the name of the release package except the .tar.gz extension.
      • Vsn is the version of the unpacked release, as defined in its .rel file.

      A directory $ROOT/lib/releases/Vsn is created, where the .rel file, the boot script start.boot, the system configuration file sys.config, and relup are placed. For applications with new version numbers, the application directories are placed under $ROOT/lib. Unchanged applications are not affected.

      An unpacked release can be installed. The release handler then evaluates the -instructions in relup, step by step:

      release_handler:install_release(Vsn) => {ok, FromVsn, []}

      If an error occurs during the installation, the system is rebooted using the old +instructions in relup, step by step:

      release_handler:install_release(Vsn) => {ok, FromVsn, []}

      If an error occurs during the installation, the system is rebooted using the old version of the release. If installation succeeds, the system is afterwards using the new version of the release, but if anything happens and the system is rebooted, it starts using the previous version again.

      To be made the default version, the newly installed release must be made permanent, which means the previous version becomes old:

      release_handler:make_permanent(Vsn) => ok

      The system keeps information about which versions are old and permanent in the -files $ROOT/releases/RELEASES and $ROOT/releases/start_erl.data.

      To downgrade from Vsn to FromVsn, install_release must be called again:

      release_handler:install_release(FromVsn) => {ok, Vsn, []}

      An installed, but not permanent, release can be removed. Information about the +files $ROOT/releases/RELEASES and $ROOT/releases/start_erl.data.

      To downgrade from Vsn to FromVsn, install_release must be called again:

      release_handler:install_release(FromVsn) => {ok, Vsn, []}

      An installed, but not permanent, release can be removed. Information about the release is then deleted from $ROOT/releases/RELEASES and the release-specific code, that is, the new application directories and the $ROOT/releases/Vsn directory, are removed.

      release_handler:remove_release(Vsn) => ok

      @@ -472,9 +472,9 @@

      ...

    $ROOT is the installation directory of the target system.

    Step 3) In another Erlang shell, generate start scripts and create a release package for the new version "B". Remember to include (a possible updated) sys.config and the relup file. For more information, see -Release Upgrade File.

    1> systools:make_script("ch_rel-2").
    +Release Upgrade File.

    1> systools:make_script("ch_rel-2").
     ok
    -2> systools:make_tar("ch_rel-2").
    +2> systools:make_tar("ch_rel-2").
     ok

    The new release package now also contains version "2" of ch_app and the relup file:

    % tar tf ch_rel-2.tar
     lib/kernel-9.2.4/ebin/kernel.app
    @@ -495,23 +495,23 @@ 

    releases/B/sys.config releases/B/ch_rel-2.rel releases/ch_rel-2.rel

    Step 4) Copy the release package ch_rel-2.tar.gz to the $ROOT/releases -directory.

    Step 5) In the running target system, unpack the release package:

    1> release_handler:unpack_release("ch_rel-2").
    -{ok,"B"}

    The new application version ch_app-2 is installed under $ROOT/lib next to +directory.

    Step 5) In the running target system, unpack the release package:

    1> release_handler:unpack_release("ch_rel-2").
    +{ok,"B"}

    The new application version ch_app-2 is installed under $ROOT/lib next to ch_app-1. The kernel, stdlib, and sasl directories are not affected, as they have not changed.

    Under $ROOT/releases, a new directory B is created, containing -ch_rel-2.rel, start.boot, sys.config, and relup.

    Step 6) Check if the function ch3:available/0 is available:

    2> ch3:available().
    +ch_rel-2.rel, start.boot, sys.config, and relup.

    Step 6) Check if the function ch3:available/0 is available:

    2> ch3:available().
     ** exception error: undefined function ch3:available/0

    Step 7) Install the new release. The instructions in $ROOT/releases/B/relup are executed one by one, resulting in the new version of ch3 being loaded. The -function ch3:available/0 is now available:

    3> release_handler:install_release("B").
    -{ok,"A",[]}
    -4> ch3:available().
    +function ch3:available/0 is now available:

    3> release_handler:install_release("B").
    +{ok,"A",[]}
    +4> ch3:available().
     3
    -5> code:which(ch3).
    +5> code:which(ch3).
     ".../lib/ch_app-2/ebin/ch3.beam"
    -6> code:which(ch_sup).
    +6> code:which(ch_sup).
     ".../lib/ch_app-1/ebin/ch_sup.beam"

    Processes in ch_app for which code have not been updated, for example, the supervisor, are still evaluating code from ch_app-1.

    Step 8) If the target system is now rebooted, it uses version "A" again. The -"B" version must be made permanent, to be used when the system is rebooted.

    7> release_handler:make_permanent("B").
    +"B" version must be made permanent, to be used when the system is rebooted.

    7> release_handler:make_permanent("B").
     ok

    @@ -528,7 +528,7 @@

    values set using application:set_env/3 are disregarded.

    When an installed release is made permanent, the system process init is set to point out the new sys.config.

    After the installation, the application controller compares the old and new configuration parameters for all running applications and call the callback -function:

    Module:config_change(Changed, New, Removed)

    1
    110

    Table: NAMES_REQ (110)

    The response for a NAMES_REQ is as follows:

    4
    EPMDPortNoNodeInfo*

    Table: NAMES_RESP

    NodeInfo is a string written for each active node. When all NodeInfo has -been written the connection is closed by the EPMD.

    NodeInfo is, as expressed in Erlang:

    io:format("name ~ts at port ~p~n", [NodeName, Port]).

    +been written the connection is closed by the EPMD.

    NodeInfo is, as expressed in Erlang:

    io:format("name ~ts at port ~p~n", [NodeName, Port]).

    @@ -277,9 +277,9 @@

    client ->> EPMD: DUMP_REQ EPMD -->> client: DUMP_RESP

    1
    100

    Table: DUMP_REQ

    The response for a DUMP_REQ is as follows:

    4
    EPMDPortNoNodeInfo*

    Table: DUMP_RESP

    NodeInfo is a string written for each node kept in the EPMD. When all -NodeInfo has been written the connection is closed by the EPMD.

    NodeInfo is, as expressed in Erlang:

    io:format("active name     ~ts at port ~p, fd = ~p~n",
    -          [NodeName, Port, Fd]).

    or

    io:format("old/unused name ~ts at port ~p, fd = ~p ~n",
    -          [NodeName, Port, Fd]).

    +NodeInfo has been written the connection is closed by the EPMD.

    NodeInfo is, as expressed in Erlang:

    io:format("active name     ~ts at port ~p, fd = ~p~n",
    +          [NodeName, Port, Fd]).

    or

    io:format("old/unused name ~ts at port ~p, fd = ~p ~n",
    +          [NodeName, Port, Fd]).

    @@ -417,7 +417,7 @@

    Semigraphic View

    -
    A (initiator)                                      B (acceptor)
    +
    A (initiator)                                      B (acceptor)
     
     TCP connect ------------------------------------>
                                                        TCP accept
    @@ -427,36 +427,36 @@ 

    <---------------------------------------------- send_status recv_status -(if status was 'alive' +(if status was 'alive' send_status - - - - - - - - - - - - - - - - - -> - recv_status) + recv_status) - (ChB) ChB = gen_challenge() + (ChB) ChB = gen_challenge() <---------------------------------------------- send_challenge recv_challenge -(if old send_name +(if old send_name send_complement - - - - - - - - - - - - - - - -> - recv_complement) + recv_complement) -ChA = gen_challenge(), -OCA = out_cookie(B), -DiA = gen_digest(ChB, OCA) - (ChA, DiA) +ChA = gen_challenge(), +OCA = out_cookie(B), +DiA = gen_digest(ChB, OCA) + (ChA, DiA) send_challenge_reply ---------------------------> recv_challenge_reply - ICB = in_cookie(A), + ICB = in_cookie(A), check: - DiA == gen_digest (ChB, ICB)? + DiA == gen_digest (ChB, ICB)? - if OK: - OCB = out_cookie(A), - DiB = gen_digest (ChA, OCB) - (DiB) + OCB = out_cookie(A), + DiB = gen_digest (ChA, OCB) + (DiB) <----------------------------------------------- send_challenge_ack recv_challenge_ack DONE -ICA = in_cookie(B), - else: +ICA = in_cookie(B), - else: check: CLOSE -DiB == gen_digest(ChA, ICA)? +DiB == gen_digest(ChA, ICA)? - if OK: DONE - else: diff --git a/prs/9045/erts-15.1.2/doc/html/erl_driver.html b/prs/9045/erts-15.1.2/doc/html/erl_driver.html index 2a9105b738a2..f0d304399b27 100644 --- a/prs/9045/erts-15.1.2/doc/html/erl_driver.html +++ b/prs/9045/erts-15.1.2/doc/html/erl_driver.html @@ -339,7 +339,7 @@

    • ErlDrvSizeT - An unsigned integer type to be used as size_t.

    • ErlDrvSSizeT - A signed integer type, the size of -ErlDrvSizeT.

    • ErlDrvSysInfo

      typedef struct ErlDrvSysInfo {
      +ErlDrvSizeT.

    • ErlDrvSysInfo

      typedef struct ErlDrvSysInfo {
          int driver_major_version;
          int driver_minor_version;
          char *erts_version;
      @@ -351,7 +351,7 @@ 

      int nif_major_version; int nif_minor_version; int dirty_scheduler_support; -} ErlDrvSysInfo;

      The ErlDrvSysInfo structure is used for storage of information about the +} ErlDrvSysInfo;

    The ErlDrvSysInfo structure is used for storage of information about the Erlang runtime system. driver_system_info writes the system information when passed a reference to a ErlDrvSysInfo structure. The fields @@ -407,12 +407,12 @@

    aligned for storage of an array of doubles (usually 8-byte aligned).

  • ErlDrvData - A handle to driver-specific data, passed to the driver callbacks. It is a pointer, and is most often type cast to a specific pointer in the driver.

  • SysIOVec - A system I/O vector, as used by writev on Unix and -WSASend on Win32. It is used in ErlIOVec.

  • ErlIOVec

    typedef struct ErlIOVec {
    +WSASend on Win32. It is used in ErlIOVec.

  • ErlIOVec

    typedef struct ErlIOVec {
       int vsize;
       ErlDrvSizeT size;
       SysIOVec* iov;
       ErlDrvBinary** binv;
    -} ErlIOVec;

    The I/O vector used by the emulator and drivers is a list of binaries, with a +} ErlIOVec;

  • The I/O vector used by the emulator and drivers is a list of binaries, with a SysIOVec pointing to the buffers of the binaries. It is used in driver_outputv and the outputv driver callback. Also, the driver queue is an ErlIOVec.

  • ErlDrvMonitor - When a driver creates a monitor for a process, a @@ -491,8 +491,8 @@

    add_driver_entry()

    -
    void add_driver_entry(ErlDrvEntry
    -        *de);

    Adds a driver entry to the list of drivers known by Erlang. The +

    void add_driver_entry(ErlDrvEntry
    +        *de);

    Adds a driver entry to the list of drivers known by Erlang. The init function of parameter de is called.

    Note

    To use this function for adding drivers residing in dynamically loaded code is dangerous. If the driver code for the added driver resides in the same dynamically loaded module (that is, .so file) as a normal dynamically loaded @@ -504,7 +504,7 @@

    driver_alloc()

    -
    void * driver_alloc(ErlDrvSizeT size);

    Allocates a memory block of the size specified in size, and returns it. This +

    void * driver_alloc(ErlDrvSizeT size);

    Allocates a memory block of the size specified in size, and returns it. This fails only on out of memory, in which case NULL is returned. (This is most often a wrapper for malloc).

    Memory allocated must be explicitly freed with a corresponding call to driver_free (unless otherwise stated).

    This function is thread-safe.

    @@ -513,7 +513,7 @@

    driver_alloc_binary()

    -
    ErlDrvBinary * driver_alloc_binary(ErlDrvSizeT size);

    Allocates a driver binary with a memory block of at least size bytes, and +

    ErlDrvBinary * driver_alloc_binary(ErlDrvSizeT size);

    Allocates a driver binary with a memory block of at least size bytes, and returns a pointer to it, or NULL on failure (out of memory). When a driver binary has been sent to the emulator, it must not be changed. Every allocated binary is to be freed by a corresponding call to @@ -527,9 +527,9 @@

    driver_async()

    -
    long driver_async(ErlDrvPort port, unsigned
    -        int* key, void (*async_invoke)(void*), void* async_data, void
    -        (*async_free)(void*));

    Performs an asynchronous call. The function async_invoke is invoked in a +

    long driver_async(ErlDrvPort port, unsigned
    +        int* key, void (*async_invoke)(void*), void* async_data, void
    +        (*async_free)(void*));

    Performs an asynchronous call. The function async_invoke is invoked in a thread separate from the emulator thread. This enables the driver to perform time-consuming, blocking operations without blocking the emulator.

    The async thread pool size can be set with command-line argument +A in erl(1). If an async @@ -561,7 +561,7 @@

    driver_async_port_key()

    -
    unsigned int driver_async_port_key(ErlDrvPort port);

    Calculates a key for later use in driver_async. +

    unsigned int driver_async_port_key(ErlDrvPort port);

    Calculates a key for later use in driver_async. The keys are evenly distributed so that a fair mapping between port IDs and async thread IDs is achieved.

    Note

    Before Erlang/OTP R16, the port ID could be used as a key with proper casting, but after the rewrite of the port subsystem, this is no longer the case. With @@ -572,7 +572,7 @@

    driver_binary_dec_refc()

    -
    long driver_binary_dec_refc(ErlDrvBinary *bin);

    Decrements the reference count on bin and returns the reference count reached +

    long driver_binary_dec_refc(ErlDrvBinary *bin);

    Decrements the reference count on bin and returns the reference count reached after the decrement.

    This function is thread-safe.

    Note

    The reference count of driver binary is normally to be decremented by calling driver_free_binary.

    driver_binary_dec_refc does not free the binary if the reference count reaches zero. Only use driver_binary_dec_refc when you are sure not to @@ -582,21 +582,21 @@

    driver_binary_get_refc()

    -
    long driver_binary_get_refc(ErlDrvBinary *bin);

    Returns the current reference count on bin.

    This function is thread-safe.

    +
    long driver_binary_get_refc(ErlDrvBinary *bin);

    Returns the current reference count on bin.

    This function is thread-safe.

    driver_binary_inc_refc()

    -
    long driver_binary_inc_refc(ErlDrvBinary *bin);

    Increments the reference count on bin and returns the reference count reached +

    long driver_binary_inc_refc(ErlDrvBinary *bin);

    Increments the reference count on bin and returns the reference count reached after the increment.

    This function is thread-safe.

    driver_caller()

    -
    ErlDrvTermData driver_caller(ErlDrvPort
    -        port);

    Returns the process ID of the process that made the current call to the driver. +

    ErlDrvTermData driver_caller(ErlDrvPort
    +        port);

    Returns the process ID of the process that made the current call to the driver. The process ID can be used with driver_send_term to send back data to the caller. driver_caller only returns valid data when currently executing in one @@ -609,14 +609,14 @@

    driver_cancel_timer()

    -
    int driver_cancel_timer(ErlDrvPort port);

    Cancels a timer set with driver_set_timer.

    The return value is 0.

    +
    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 +

    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.

    @@ -624,16 +624,16 @@

    driver_connected()

    -
    ErlDrvTermData driver_connected(ErlDrvPort
    -        port);

    Returns the port owner process.

    Notice that this function is not thread-safe.

    +
    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,
    +
    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.

    • port - The port handle of the port (driver instance) creating the new port.

    • owner_pid - The process ID of the Erlang process to become owner of the new port. This process will be linked to the new port. You usually want to use @@ -654,15 +654,15 @@

      driver_demonitor_process()

      -
      int driver_demonitor_process(ErlDrvPort port,
      -        const ErlDrvMonitor *monitor);

      Cancels a monitor created earlier.

      Returns 0 if a monitor was removed and > 0 if the monitor no longer exists.

      +
      int driver_demonitor_process(ErlDrvPort port,
      +        const ErlDrvMonitor *monitor);

      Cancels a monitor created earlier.

      Returns 0 if a monitor was removed and > 0 if the monitor no longer exists.

      driver_deq()

      -
      ErlDrvSizeT driver_deq(ErlDrvPort port,
      -        ErlDrvSizeT size);

      Dequeues data by moving the head pointer forward in the driver queue by size +

      ErlDrvSizeT driver_deq(ErlDrvPort port,
      +        ErlDrvSizeT size);

      Dequeues data by moving the head pointer forward in the driver queue by size bytes. The data in the queue is deallocated.

      Returns the number of bytes remaining in the queue on success, otherwise -1.

      This function can be called from any thread if a port data lock associated with the port is locked by the calling thread during the call.

      @@ -671,8 +671,8 @@

      driver_enq()

      -
      int driver_enq(ErlDrvPort port, char* buf,
      -        ErlDrvSizeT len);

      Enqueues data in the driver queue. The data in buf is copied (len bytes) and +

      int driver_enq(ErlDrvPort port, char* buf,
      +        ErlDrvSizeT len);

      Enqueues data in the driver queue. The data in buf is copied (len bytes) and placed at the end of the driver queue. The driver queue is normally used in a FIFO way.

      The driver queue is available to queue output from the emulator to the driver (data from the driver to the emulator is queued by the emulator in normal Erlang @@ -687,8 +687,8 @@

      driver_enq_bin()

      -
      int driver_enq_bin(ErlDrvPort port,
      -        ErlDrvBinary *bin, ErlDrvSizeT offset, ErlDrvSizeT len);

      Enqueues a driver binary in the driver queue. The data in bin at offset with +

      int driver_enq_bin(ErlDrvPort port,
      +        ErlDrvBinary *bin, ErlDrvSizeT offset, ErlDrvSizeT len);

      Enqueues a driver binary in the driver queue. The data in bin at offset with length len is placed at the end of the queue. This function is most often faster than driver_enq, because no data must be copied.

      This function can be called from any thread if a @@ -699,8 +699,8 @@

      driver_enqv()

      -
      int driver_enqv(ErlDrvPort port, ErlIOVec *ev,
      -        ErlDrvSizeT skip);

      Enqueues the data in ev, skipping the first skip bytes of it, at the end of +

      int driver_enqv(ErlDrvPort port, ErlIOVec *ev,
      +        ErlDrvSizeT skip);

      Enqueues the data in ev, skipping the first skip bytes of it, at the end of the driver queue. It is faster than driver_enq, because no data must be copied.

      The return value is 0.

      This function can be called from any thread if a port data lock associated with the port is locked @@ -722,10 +722,10 @@

      driver_failure_posix()

      -
      int driver_failure(ErlDrvPort port, int
      -        error);
      int driver_failure_atom(ErlDrvPort port, char
      -        *string);
      int driver_failure_posix(ErlDrvPort port, int
      -        error);

      Signals to Erlang that the driver has encountered an error and is to be closed. +

      int driver_failure(ErlDrvPort port, int
      +        error);
      int driver_failure_atom(ErlDrvPort port, char
      +        *string);
      int driver_failure_posix(ErlDrvPort port, int
      +        error);

      Signals to Erlang that the driver has encountered an error and is to be closed. The port is closed and the tuple {'EXIT', error, Err} is sent to the port owner process, where error is an error atom (driver_failure_atom and driver_failure_posix) or an integer (driver_failure).

      The driver is to fail only when in severe error situations, when the driver @@ -737,8 +737,8 @@

      driver_failure_eof()

      -
      int driver_failure_eof(ErlDrvPort
      -        port);

      Signals to Erlang that the driver has encountered an EOF and is to be closed, +

      int driver_failure_eof(ErlDrvPort
      +        port);

      Signals to Erlang that the driver has encountered an EOF and is to be closed, unless the port was opened with option eof, in which case eof is sent to the port. Otherwise the port is closed and an 'EXIT' message is sent to the port owner process.

      The return value is 0.

      @@ -747,7 +747,7 @@

      driver_free()

      -
      void driver_free(void *ptr);

      Frees the memory pointed to by ptr. The memory is to have been allocated with +

      void driver_free(void *ptr);

      Frees the memory pointed to by ptr. The memory is to have been allocated with driver_alloc. All allocated memory is to be deallocated, only once. There is no garbage collection in drivers.

      This function is thread-safe.

      @@ -755,7 +755,7 @@

      driver_free_binary()

      -
      void driver_free_binary(ErlDrvBinary *bin);

      Frees a driver binary bin, allocated previously with +

      void driver_free_binary(ErlDrvBinary *bin);

      Frees a driver binary bin, allocated previously with driver_alloc_binary. As binaries in Erlang are reference counted, the binary can still be around.

      This function is thread-safe.

      @@ -763,8 +763,8 @@

      driver_get_monitored_process()

      -
      ErlDrvTermData driver_get_monitored_process(ErlDrvPort port, const
      -        ErlDrvMonitor *monitor);

      Returns the process ID associated with a living monitor. It can be used in the +

      ErlDrvTermData driver_get_monitored_process(ErlDrvPort port, const
      +        ErlDrvMonitor *monitor);

      Returns the process ID associated with a living monitor. It can be used in the process_exit callback to get the process identification for the exiting process.

      Returns driver_term_nil if the monitor no longer exists.

      @@ -772,7 +772,7 @@

      driver_get_now()

      -
      int driver_get_now(ErlDrvNowData *now);

      Warning

      This function is deprecated. Do not use it. Use +

      int driver_get_now(ErlDrvNowData *now);

      Warning

      This function is deprecated. Do not use it. Use erl_drv_monotonic_time (perhaps in combination with erl_drv_time_offset) instead.

      Reads a time stamp into the memory pointed to by parameter now. For @@ -784,8 +784,8 @@

      driver_lock_driver()

      -
      int driver_lock_driver(ErlDrvPort
      -        port);

      Locks the driver used by the port port in memory for the rest of the emulator +

      int driver_lock_driver(ErlDrvPort
      +        port);

      Locks the driver used by the port port in memory for the rest of the emulator process' lifetime. After this call, the driver behaves as one of Erlang's statically linked-in drivers.

      @@ -793,8 +793,8 @@

      driver_mk_atom()

      -
      ErlDrvTermData driver_mk_atom(char*
      -        string);

      Returns an atom given a name string. The atom is created and does not change, +

      ErlDrvTermData driver_mk_atom(char*
      +        string);

      Returns an atom given a name string. The atom is created and does not change, so the return value can be saved and reused, which is faster than looking up the atom several times.

      Notice that this function is not thread-safe.

      @@ -802,8 +802,8 @@

      driver_mk_port()

      -
      ErlDrvTermData driver_mk_port(ErlDrvPort
      -        port);

      Converts a port handle to the Erlang term format, usable in +

      ErlDrvTermData driver_mk_port(ErlDrvPort
      +        port);

      Converts a port handle to the Erlang term format, usable in erl_drv_output_term and erl_drv_send_term.

      Notice that this function is not thread-safe.

      @@ -811,8 +811,8 @@

      driver_monitor_process()

      -
      int driver_monitor_process(ErlDrvPort port,
      -        ErlDrvTermData process, ErlDrvMonitor *monitor);

      Starts monitoring a process from a driver. When a process is monitored, a +

      int driver_monitor_process(ErlDrvPort port,
      +        ErlDrvTermData process, ErlDrvMonitor *monitor);

      Starts monitoring a process from a driver. When a process is monitored, a process exit results in a call to the provided process_exit callback in the ErlDrvEntry structure. The ErlDrvMonitor structure is @@ -825,8 +825,8 @@

      driver_output()

      -
      int driver_output(ErlDrvPort port, char *buf,
      -        ErlDrvSizeT len);

      Sends data from the driver up to the emulator. The data is received as terms or +

      int driver_output(ErlDrvPort port, char *buf,
      +        ErlDrvSizeT len);

      Sends data from the driver up to the emulator. The data is received as terms or binary data, depending on how the driver port was opened.

      The data is queued in the port owner process' message queue. Notice that this does not yield to the emulator (as the driver and the emulator run in the same thread).

      Parameter buf points to the data to send, and len is the number of bytes.

      The return value for all output functions is 0 for normal use. If the driver @@ -836,9 +836,9 @@

      driver_output_binary()

      -
      int driver_output_binary(ErlDrvPort port, char
      +
      int driver_output_binary(ErlDrvPort port, char
               *hbuf, ErlDrvSizeT hlen, ErlDrvBinary* bin, ErlDrvSizeT offset,
      -        ErlDrvSizeT len);

      Sends data to a port owner process from a driver binary. It has a header buffer + ErlDrvSizeT len);

      Sends data to a port owner process from a driver binary. It has a header buffer (hbuf and hlen) just like driver_output2. Parameter hbuf can be NULL.

      Parameter offset is an offset into the binary and len is the number of bytes to send.

      Driver binaries are created with @@ -852,8 +852,8 @@

      driver_output_term()

      -
      int driver_output_term(ErlDrvPort port,
      -        ErlDrvTermData* term, int n);

      Warning

      This function is deprecated. Use +

      int driver_output_term(ErlDrvPort port,
      +        ErlDrvTermData* term, int n);

      Warning

      This function is deprecated. Use erl_drv_output_terminstead.

      Parameters term and n work as in erl_drv_output_term.

      Notice that this function is not thread-safe.

      @@ -861,8 +861,8 @@

      driver_output2()

      -
      int driver_output2(ErlDrvPort port, char *hbuf,
      -        ErlDrvSizeT hlen, char *buf, ErlDrvSizeT len);

      First sends hbuf (length in hlen) data as a list, regardless of port +

      int driver_output2(ErlDrvPort port, char *hbuf,
      +        ErlDrvSizeT hlen, char *buf, ErlDrvSizeT len);

      First sends hbuf (length in hlen) data as a list, regardless of port settings. Then sends buf as a binary or list. For example, if hlen is 3, the port owner process receives [H1, H2, H3 | T].

      The point of sending data as a list header, is to facilitate matching on the data received.

      The return value is 0 for normal use.

      @@ -871,8 +871,8 @@

      driver_outputv()

      -
      int driver_outputv(ErlDrvPort port, char* hbuf,
      -        ErlDrvSizeT hlen, ErlIOVec *ev, ErlDrvSizeT skip);

      Sends data from an I/O vector, ev, to the port owner process. It has a header +

      int driver_outputv(ErlDrvPort port, char* hbuf,
      +        ErlDrvSizeT hlen, ErlIOVec *ev, ErlDrvSizeT skip);

      Sends data from an I/O vector, ev, to the port owner process. It has a header buffer (hbuf and hlen), just like driver_output2.

      Parameter skip is a number of bytes to skip of the ev vector from the head.

      You get vectors of ErlIOVec type from the driver queue (see below), and the outputv driver entry function. You can also make @@ -884,7 +884,7 @@

      driver_pdl_create()

      -
      ErlDrvPDL driver_pdl_create(ErlDrvPort port);

      Creates a port data lock associated with the port.

      Note

      Once a port data lock has been created, it must be locked during all +

      ErlDrvPDL driver_pdl_create(ErlDrvPort port);

      Creates a port data lock associated with the port.

      Note

      Once a port data lock has been created, it must be locked during all operations on the driver queue of the port.

      Returns a newly created port data lock on success, otherwise NULL. The function fails if port is invalid or if a port data lock already has been associated with the port.

      @@ -893,40 +893,40 @@

      driver_pdl_dec_refc()

      -
      long driver_pdl_dec_refc(ErlDrvPDL
      -        pdl);

      Decrements the reference count of the port data lock passed as argument (pdl).

      The current reference count after the decrement has been performed is returned.

      This function is thread-safe.

      +
      long driver_pdl_dec_refc(ErlDrvPDL
      +        pdl);

      Decrements the reference count of the port data lock passed as argument (pdl).

      The current reference count after the decrement has been performed is returned.

      This function is thread-safe.

      driver_pdl_get_refc()

      -
      long driver_pdl_get_refc(ErlDrvPDL pdl);

      Returns the current reference count of the port data lock passed as argument +

      long driver_pdl_get_refc(ErlDrvPDL pdl);

      Returns the current reference count of the port data lock passed as argument (pdl).

      This function is thread-safe.

      driver_pdl_inc_refc()

      -
      long driver_pdl_inc_refc(ErlDrvPDL pdl);

      Increments the reference count of the port data lock passed as argument (pdl).

      The current reference count after the increment has been performed is returned.

      This function is thread-safe.

      +
      long driver_pdl_inc_refc(ErlDrvPDL pdl);

      Increments the reference count of the port data lock passed as argument (pdl).

      The current reference count after the increment has been performed is returned.

      This function is thread-safe.

      driver_pdl_lock()

      -
      void driver_pdl_lock(ErlDrvPDL pdl);

      Locks the port data lock passed as argument (pdl).

      This function is thread-safe.

      +
      void driver_pdl_lock(ErlDrvPDL pdl);

      Locks the port data lock passed as argument (pdl).

      This function is thread-safe.

      driver_pdl_unlock()

      -
      void driver_pdl_unlock(ErlDrvPDL pdl);

      Unlocks the port data lock passed as argument (pdl).

      This function is thread-safe.

      +
      void driver_pdl_unlock(ErlDrvPDL pdl);

      Unlocks the port data lock passed as argument (pdl).

      This function is thread-safe.

      driver_peekq()

      -
      SysIOVec * driver_peekq(ErlDrvPort port, int
      -        *vlen);

      Retrieves the driver queue as a pointer to an array of SysIOVecs. It also +

      SysIOVec * driver_peekq(ErlDrvPort port, int
      +        *vlen);

      Retrieves the driver queue as a pointer to an array of SysIOVecs. It also returns the number of elements in vlen. This is one of two ways to get data out of the queue.

      Nothing is removed from the queue by this function, that must be done with driver_deq.

      The returned array is suitable to use with the Unix system call writev.

      This function can be called from any thread if a @@ -937,8 +937,8 @@

      driver_peekqv()

      -
      ErlDrvSizeT driver_peekqv(ErlDrvPort port,
      -        ErlIOVec *ev);

      Retrieves the driver queue into a supplied ErlIOVec ev. It also returns the +

      ErlDrvSizeT driver_peekqv(ErlDrvPort port,
      +        ErlIOVec *ev);

      Retrieves the driver queue into a supplied ErlIOVec ev. It also returns the queue size. This is one of two ways to get data out of the queue.

      If ev is NULL, all ones that is -1 type cast to ErlDrvSizeT are returned.

      Nothing is removed from the queue by this function, that must be done with driver_deq.

      This function can be called from any thread if a @@ -949,8 +949,8 @@

      driver_pushq()

      -
      int driver_pushq(ErlDrvPort port, char* buf,
      -        ErlDrvSizeT len);

      Puts data at the head of the driver queue. The data in buf is copied (len +

      int driver_pushq(ErlDrvPort port, char* buf,
      +        ErlDrvSizeT len);

      Puts data at the head of the driver queue. The data in buf is copied (len bytes) and placed at the beginning of the queue.

      The return value is 0.

      This function can be called from any thread if a port data lock associated with the port is locked by the calling thread during the call.

      @@ -959,8 +959,8 @@

      driver_pushq_bin()

      -
      int driver_pushq_bin(ErlDrvPort port,
      -        ErlDrvBinary *bin, ErlDrvSizeT offset, ErlDrvSizeT len);

      Puts data in the binary bin, at offset with length len at the head of the +

      int driver_pushq_bin(ErlDrvPort port,
      +        ErlDrvBinary *bin, ErlDrvSizeT offset, ErlDrvSizeT len);

      Puts data in the binary bin, at offset with length len at the head of the driver queue. It is most often faster than driver_pushq, because no data must be copied.

      This function can be called from any thread if a port data lock associated with the port is locked @@ -970,8 +970,8 @@

      driver_pushqv()

      -
      int driver_pushqv(ErlDrvPort port, ErlIOVec
      -        *ev, ErlDrvSizeT skip);

      Puts the data in ev, skipping the first skip bytes of it, at the head of the +

      int driver_pushqv(ErlDrvPort port, ErlIOVec
      +        *ev, ErlDrvSizeT skip);

      Puts the data in ev, skipping the first skip bytes of it, at the head of the driver queue. It is faster than driver_pushq, because no data must be copied.

      The return value is 0.

      This function can be called from any thread if a port data lock associated with the port is locked @@ -981,15 +981,15 @@

      driver_read_timer()

      -
      int driver_read_timer(ErlDrvPort port, unsigned
      -        long *time_left);

      Reads the current time of a timer, and places the result in time_left. This is +

      int driver_read_timer(ErlDrvPort port, unsigned
      +        long *time_left);

      Reads the current time of a timer, and places the result in time_left. This is the time in milliseconds, before the time-out occurs.

      The return value is 0.

      driver_realloc()

      -
      void * driver_realloc(void *ptr, ErlDrvSizeT size);

      Resizes a memory block, either in place, or by allocating a new block, copying +

      void * driver_realloc(void *ptr, ErlDrvSizeT size);

      Resizes a memory block, either in place, or by allocating a new block, copying the data, and freeing the old block. A pointer is returned to the reallocated memory. On failure (out of memory), NULL is returned. (This is most often a wrapper for realloc.)

      This function is thread-safe.

      @@ -998,15 +998,15 @@

      driver_realloc_binary()

      -
      ErlDrvBinary * driver_realloc_binary(ErlDrvBinary *bin, ErlDrvSizeT size);

      Resizes a driver binary, while keeping the data.

      Returns the resized driver binary on success. Returns NULL on failure (out of +

      ErlDrvBinary * driver_realloc_binary(ErlDrvBinary *bin, ErlDrvSizeT size);

      Resizes a driver binary, while keeping the data.

      Returns the resized driver binary on success. Returns NULL on failure (out of memory).

      This function is thread-safe.

      driver_select()

      -
      int driver_select(ErlDrvPort port, ErlDrvEvent
      -        event, int mode, int on);

      This function is used by drivers to provide the emulator with events to check +

      int driver_select(ErlDrvPort port, ErlDrvEvent
      +        event, int mode, int on);

      This function is used by drivers to provide the emulator with events to check for. This enables the emulator to call the driver when something has occurred asynchronously.

      Parameter event identifies an OS-specific event object. On Unix systems, the functions select/poll are used. The event object must be a socket or pipe @@ -1036,8 +1036,8 @@

      driver_send_term()

      -
      int driver_send_term(ErlDrvPort port,
      -        ErlDrvTermData receiver, ErlDrvTermData* term, int n);

      Warning

      This function is deprecated. Use +

      int driver_send_term(ErlDrvPort port,
      +        ErlDrvTermData receiver, ErlDrvTermData* term, int n);

      Warning

      This function is deprecated. Use erl_drv_send_term instead.

      Note

      The parameters of this function cannot be properly checked by the runtime system when executed by arbitrary threads. This can cause the function not to fail when it should.

      Parameters term and n work as in @@ -1047,8 +1047,8 @@

      driver_set_timer()

      -
      int driver_set_timer(ErlDrvPort port, unsigned
      -        long time);

      Sets a timer on the driver, which will count down and call the driver when it is +

      int driver_set_timer(ErlDrvPort port, unsigned
      +        long time);

      Sets a timer on the driver, which will count down and call the driver when it is timed out. Parameter time is the time in milliseconds before the timer expires.

      When the timer reaches 0 and expires, the driver entry function timeout is called.

      Notice that only one timer exists on each driver instance; setting a new timer @@ -1059,7 +1059,7 @@

      driver_sizeq()

      -
      ErlDrvSizeT driver_sizeq(ErlDrvPort port);

      Returns the number of bytes currently in the driver queue.

      This function can be called from any thread if a +

      ErlDrvSizeT driver_sizeq(ErlDrvPort port);

      Returns the number of bytes currently in the driver queue.

      This function can be called from any thread if a port data lock associated with the port is locked by the calling thread during the call.

      @@ -1067,8 +1067,8 @@

      driver_system_info()

      -
      void driver_system_info(ErlDrvSysInfo
      -        *sys_info_ptr, size_t size);

      Writes information about the Erlang runtime system into the +

      void driver_system_info(ErlDrvSysInfo
      +        *sys_info_ptr, size_t size);

      Writes information about the Erlang runtime system into the ErlDrvSysInfo structure referred to by the first argument. The second argument is to be the size of the ErlDrvSysInfo structure, that is, @@ -1079,8 +1079,8 @@

      driver_vec_to_buf()

      -
      ErlDrvSizeT driver_vec_to_buf(ErlIOVec *ev,
      -        char *buf, ErlDrvSizeT len);

      Collects several segments of data, referenced by ev, by copying them in order +

      ErlDrvSizeT driver_vec_to_buf(ErlIOVec *ev,
      +        char *buf, ErlDrvSizeT len);

      Collects several segments of data, referenced by ev, by copying them in order to the buffer buf, of the size len.

      If the data is to be sent from the driver to the port owner process, it is faster to use driver_outputv.

      The return value is the space left in the buffer, that is, if ev contains less than len bytes it is the difference, and if ev contains len bytes or more, @@ -1091,8 +1091,8 @@

      erl_drv_busy_msgq_limits()

      -
      void erl_drv_busy_msgq_limits(ErlDrvPort port,
      -        ErlDrvSizeT *low, ErlDrvSizeT *high);

      Sets and gets limits that will be used for controlling the busy state of the +

      void erl_drv_busy_msgq_limits(ErlDrvPort port,
      +        ErlDrvSizeT *low, ErlDrvSizeT *high);

      Sets and gets limits that will be used for controlling the busy state of the port message queue.

      The port message queue is set into a busy state when the amount of command data queued on the message queue reaches the high limit. The port message queue is set into a not busy state when the amount of command data queued on the message @@ -1124,16 +1124,16 @@

      erl_drv_cond_broadcast()

      -
      void erl_drv_cond_broadcast(ErlDrvCond
      -        *cnd);

      Broadcasts on a condition variable. That is, if other threads are waiting on the +

      void erl_drv_cond_broadcast(ErlDrvCond
      +        *cnd);

      Broadcasts on a condition variable. That is, if other threads are waiting on the condition variable being broadcast on, all of them are woken.

      cnd is a pointer to a condition variable to broadcast on.

      This function is thread-safe.

      erl_drv_cond_create()

      -
      ErlDrvCond * erl_drv_cond_create(char
      -        *name);

      Creates a condition variable and returns a pointer to it.

      name is a string identifying the created condition variable. It is used to +

      ErlDrvCond * erl_drv_cond_create(char
      +        *name);

      Creates a condition variable and returns a pointer to it.

      name is a string identifying the created condition variable. It is used to identify the condition variable in planned future debug functionality.

      Returns NULL on failure. The driver creating the condition variable is responsible for destroying it before the driver is unloaded.

      This function is thread-safe.

      @@ -1141,31 +1141,31 @@

      erl_drv_cond_destroy()

      -
      void erl_drv_cond_destroy(ErlDrvCond
      -        *cnd);

      Destroys a condition variable previously created by +

      void erl_drv_cond_destroy(ErlDrvCond
      +        *cnd);

      Destroys a condition variable previously created by erl_drv_cond_create.

      cnd is a pointer to a condition variable to destroy.

      This function is thread-safe.

      erl_drv_cond_name()

      -
      char * erl_drv_cond_name(ErlDrvCond
      -        *cnd);

      Returns a pointer to the name of the condition.

      cnd is a pointer to an initialized condition.

      Note

      This function is intended for debugging purposes only.

      Available since OTP R16B02

      +
      char * erl_drv_cond_name(ErlDrvCond
      +        *cnd);

      Returns a pointer to the name of the condition.

      cnd is a pointer to an initialized condition.

      Note

      This function is intended for debugging purposes only.

      Available since OTP R16B02

      erl_drv_cond_signal()

      -
      void erl_drv_cond_signal(ErlDrvCond
      -        *cnd);

      Signals on a condition variable. That is, if other threads are waiting on the +

      void erl_drv_cond_signal(ErlDrvCond
      +        *cnd);

      Signals on a condition variable. That is, if other threads are waiting on the condition variable being signaled, one of them is woken.

      cnd is a pointer to a condition variable to signal on.

      This function is thread-safe.

      erl_drv_cond_wait()

      -
      void erl_drv_cond_wait(ErlDrvCond *cnd,
      -        ErlDrvMutex *mtx);

      Waits on a condition variable. The calling thread is blocked until another +

      void erl_drv_cond_wait(ErlDrvCond *cnd,
      +        ErlDrvMutex *mtx);

      Waits on a condition variable. The calling thread is blocked until another thread wakes it by signaling or broadcasting on the condition variable. Before the calling thread is blocked, it unlocks the mutex passed as argument. When the calling thread is woken, it locks the same mutex before returning. That is, the @@ -1181,8 +1181,8 @@

      erl_drv_consume_timeslice()

      -
      int erl_drv_consume_timeslice(ErlDrvPort port,
      -        int percent);

      Gives the runtime system a hint about how much CPU time the current driver +

      int erl_drv_consume_timeslice(ErlDrvPort port,
      +        int percent);

      Gives the runtime system a hint about how much CPU time the current driver callback call has consumed since the last hint, or since the the start of the callback if no previous hint has been given.

      • port - Port handle of the executing port.

      • percent - Approximate consumed fraction of a full time-slice in percent.

      The time is specified as a fraction, in percent, of a full time-slice that a port is allowed to execute before it is to surrender the CPU to other runnable @@ -1205,8 +1205,8 @@

      erl_drv_convert_time_unit()

      -
      ErlDrvTime erl_drv_convert_time_unit(ErlDrvTime
      -        val, ErlDrvTimeUnit from, ErlDrvTimeUnit to);

      Converts the val value of time unit from to the corresponding value of time +

      ErlDrvTime erl_drv_convert_time_unit(ErlDrvTime
      +        val, ErlDrvTimeUnit from, ErlDrvTimeUnit to);

      Converts the val value of time unit from to the corresponding value of time unit to. The result is rounded using the floor function.

      • val - Value to convert time unit for.

      • from - Time unit of val.

      • to - Time unit of returned value.

      Returns ERL_DRV_TIME_ERROR if called with an invalid time unit argument.

      See also ErlDrvTime and ErlDrvTimeUnit.

      Available since OTP 18.3

      @@ -1214,8 +1214,8 @@

      erl_drv_equal_tids()

      -
      int erl_drv_equal_tids(ErlDrvTid tid1,
      -        ErlDrvTid tid2);

      Compares two thread identifiers, tid1 and tid2, for equality.

      Returns 0 it they are not equal, and a value not equal to 0 if they are +

      int erl_drv_equal_tids(ErlDrvTid tid1,
      +        ErlDrvTid tid2);

      Compares two thread identifiers, tid1 and tid2, for equality.

      Returns 0 it they are not equal, and a value not equal to 0 if they are equal.

      Note

      A thread identifier can be reused very quickly after a thread has terminated. Therefore, if a thread corresponding to one of the involved thread identifiers has terminated since the thread identifier was saved, the result of @@ -1225,8 +1225,8 @@

      erl_drv_getenv()

      -
      int erl_drv_getenv(const char *key, char
      -        *value, size_t *value_size);

      Retrieves the value of an environment variable.

      • key - A NULL-terminated string containing the name of the environment +

        int erl_drv_getenv(const char *key, char
        +        *value, size_t *value_size);

        Retrieves the value of an environment variable.

        • key - A NULL-terminated string containing the name of the environment variable.

        • value - A pointer to an output buffer.

        • value_size - A pointer to an integer. The integer is used both for passing input and output sizes (see below).

        When this function is called, *value_size is to contain the size of the value buffer.

        On success, 0 is returned, the value of the environment variable has been @@ -1244,8 +1244,8 @@

        erl_drv_init_ack()

        -
        void erl_drv_init_ack(ErlDrvPort port,
        -        ErlDrvData res);

        Acknowledges the start of the port.

        • port - The port handle of the port (driver instance) doing the +

          void erl_drv_init_ack(ErlDrvPort port,
          +        ErlDrvData res);

          Acknowledges the start of the port.

          • port - The port handle of the port (driver instance) doing the acknowledgment.

          • res - The result of the port initialization. Can be the same values as the return value of start, that is, any of the error codes or the ErlDrvData that is to be used for this port.

          When this function is called the initiating erlang:open_port call is returned @@ -1258,7 +1258,7 @@

          erl_drv_monotonic_time()

          -
          ErlDrvTime erl_drv_monotonic_time(ErlDrvTimeUnit time_unit);

          Returns Erlang monotonic time. +

          ErlDrvTime erl_drv_monotonic_time(ErlDrvTimeUnit time_unit);

          Returns Erlang monotonic time. Notice that negative values are not uncommon.

          time_unit is time unit of returned value.

          Returns ERL_DRV_TIME_ERROR if called with an invalid time unit argument, or if called from a thread that is not a scheduler thread.

          See also ErlDrvTime and ErlDrvTimeUnit.

          Available since OTP 18.3

          @@ -1267,8 +1267,8 @@

          erl_drv_mutex_create()

          -
          ErlDrvMutex * erl_drv_mutex_create(char
          -        *name);

          Creates a mutex and returns a pointer to it.

          name is a string identifying the created mutex. It is used to identify the +

          ErlDrvMutex * erl_drv_mutex_create(char
          +        *name);

          Creates a mutex and returns a pointer to it.

          name is a string identifying the created mutex. It is used to identify the mutex in debug functionality (see note).

          Returns NULL on failure. The driver creating the mutex is responsible for destroying it before the driver is unloaded.

          This function is thread-safe.

          Note

          One such debug functionality is the lock checker, which can detect locking order violations and thereby potential deadlock bugs. For the lock checker to @@ -1285,8 +1285,8 @@

          erl_drv_mutex_destroy()

          -
          void erl_drv_mutex_destroy(ErlDrvMutex
          -        *mtx);

          Destroys a mutex previously created by +

          void erl_drv_mutex_destroy(ErlDrvMutex
          +        *mtx);

          Destroys a mutex previously created by erl_drv_mutex_create. The mutex must be in an unlocked state before it is destroyed.

          mtx is a pointer to a mutex to destroy.

          This function is thread-safe.

          @@ -1294,8 +1294,8 @@

          erl_drv_mutex_lock()

          -
          void erl_drv_mutex_lock(ErlDrvMutex
          -        *mtx);

          Locks a mutex. The calling thread is blocked until the mutex has been locked. A +

          void erl_drv_mutex_lock(ErlDrvMutex
          +        *mtx);

          Locks a mutex. The calling thread is blocked until the mutex has been locked. A thread that has currently locked the mutex cannot lock the same mutex again.

          mtx is a pointer to a mutex to lock.

          Warning

          If you leave a mutex locked in an emulator thread when you let the thread out of your control, you will very likely deadlock the whole emulator.

          This function is thread-safe.

          @@ -1303,15 +1303,15 @@

          erl_drv_mutex_name()

          -
          char * erl_drv_mutex_name(ErlDrvMutex
          -        *mtx);

          Returns a pointer to the mutex name.

          mtx is a pointer to an initialized mutex.

          Note

          This function is intended for debugging purposes only.

          Available since OTP R16B02

          +
          char * erl_drv_mutex_name(ErlDrvMutex
          +        *mtx);

          Returns a pointer to the mutex name.

          mtx is a pointer to an initialized mutex.

          Note

          This function is intended for debugging purposes only.

          Available since OTP R16B02

          erl_drv_mutex_trylock()

          -
          int erl_drv_mutex_trylock(ErlDrvMutex
          -        *mtx);

          Tries to lock a mutex. A thread that has currently locked the mutex cannot try +

          int erl_drv_mutex_trylock(ErlDrvMutex
          +        *mtx);

          Tries to lock a mutex. A thread that has currently locked the mutex cannot try to lock the same mutex again.

          mtx is a pointer to a mutex to try to lock.

          Returns 0 on success, otherwise EBUSY.

          Warning

          If you leave a mutex locked in an emulator thread when you let the thread out of your control, you will very likely deadlock the whole emulator.

          This function is thread-safe.

          @@ -1319,15 +1319,15 @@

          erl_drv_mutex_unlock()

          -
          void erl_drv_mutex_unlock(ErlDrvMutex
          -        *mtx);

          Unlocks a mutex. The mutex currently must be locked by the calling thread.

          mtx is a pointer to a mutex to unlock.

          This function is thread-safe.

          +
          void erl_drv_mutex_unlock(ErlDrvMutex
          +        *mtx);

          Unlocks a mutex. The mutex currently must be locked by the calling thread.

          mtx is a pointer to a mutex to unlock.

          This function is thread-safe.

          erl_drv_output_term()

          -
          int erl_drv_output_term(ErlDrvTermData port,
          -        ErlDrvTermData* term, int n);

          Sends data in the special driver term format to the port owner process. This is +

          int erl_drv_output_term(ErlDrvTermData port,
          +        ErlDrvTermData* term, int n);

          Sends data in the special driver term format to the port owner process. This is a fast way to deliver term data from a driver. It needs no binary conversion, so the port owner process receives data as normal Erlang terms. The erl_drv_send_term functions can be used for @@ -1385,20 +1385,20 @@

          concatenating the strings added to a list. The tail must be specified before ERL_DRV_STRING_CONS.

          ERL_DRV_STRING constructs a string, and ends it. (So it is the same as ERL_DRV_NIL followed by ERL_DRV_STRING_CONS.)

          /* to send [x, "abc", y] to the port: */
          -ErlDrvTermData spec[] = {
          -    ERL_DRV_ATOM, driver_mk_atom("x"),
          -    ERL_DRV_STRING, (ErlDrvTermData)"abc", 3,
          -    ERL_DRV_ATOM, driver_mk_atom("y"),
          +ErlDrvTermData spec[] = {
          +    ERL_DRV_ATOM, driver_mk_atom("x"),
          +    ERL_DRV_STRING, (ErlDrvTermData)"abc", 3,
          +    ERL_DRV_ATOM, driver_mk_atom("y"),
               ERL_DRV_NIL,
               ERL_DRV_LIST, 4
          -};
          -erl_drv_output_term(driver_mk_port(drvport), spec, sizeof(spec) / sizeof(spec[0]));
          /* to send "abc123" to the port: */
          -ErlDrvTermData spec[] = {
          +};
          +erl_drv_output_term(driver_mk_port(drvport), spec, sizeof(spec) / sizeof(spec[0]));
          /* to send "abc123" to the port: */
          +ErlDrvTermData spec[] = {
               ERL_DRV_NIL,        /* with STRING_CONS, the tail comes first */
          -    ERL_DRV_STRING_CONS, (ErlDrvTermData)"123", 3,
          -    ERL_DRV_STRING_CONS, (ErlDrvTermData)"abc", 3,
          -};
          -erl_drv_output_term(driver_mk_port(drvport), spec, sizeof(spec) / sizeof(spec[0]));

          The ERL_DRV_EXT2TERM term type is used for passing + ERL_DRV_STRING_CONS, (ErlDrvTermData)"123", 3, + ERL_DRV_STRING_CONS, (ErlDrvTermData)"abc", 3, +}; +erl_drv_output_term(driver_mk_port(drvport), spec, sizeof(spec) / sizeof(spec[0]));

  • The ERL_DRV_EXT2TERM term type is used for passing a term encoded with the external format, that is, a term that has been encoded by erlang:term_to_binary(), erl_interface:ei(3), and so on. For example, if @@ -1435,8 +1435,8 @@

    erl_drv_putenv()

    -
    int erl_drv_putenv(const char *key, char
    -        *value);

    Sets the value of an environment variable.

    key is a NULL-terminated string containing the name of the environment +

    int erl_drv_putenv(const char *key, char
    +        *value);

    Sets the value of an environment variable.

    key is a NULL-terminated string containing the name of the environment variable.

    value is a NULL-terminated string containing the new value of the environment variable.

    Returns 0 on success, otherwise a value != 0.

    Note

    The result of passing the empty string ("") as a value is platform-dependent. On some platforms the variable value is set to the empty @@ -1450,8 +1450,8 @@

    erl_drv_rwlock_create()

    -
    ErlDrvRWLock * erl_drv_rwlock_create(char
    -        *name);

    Creates an rwlock and returns a pointer to it.

    name is a string identifying the created rwlock. It is used to identify the +

    ErlDrvRWLock * erl_drv_rwlock_create(char
    +        *name);

    Creates an rwlock and returns a pointer to it.

    name is a string identifying the created rwlock. It is used to identify the rwlock in debug functionality (see note about the lock checker).

    Returns NULL on failure. The driver creating the rwlock is responsible for destroying it before the driver is unloaded.

    This function is thread-safe.

    @@ -1460,8 +1460,8 @@

    erl_drv_rwlock_destroy()

    -
    void erl_drv_rwlock_destroy(ErlDrvRWLock
    -        *rwlck);

    Destroys an rwlock previously created by +

    void erl_drv_rwlock_destroy(ErlDrvRWLock
    +        *rwlck);

    Destroys an rwlock previously created by erl_drv_rwlock_create. The rwlock must be in an unlocked state before it is destroyed.

    rwlck is a pointer to an rwlock to destroy.

    This function is thread-safe.

    @@ -1469,15 +1469,15 @@

    erl_drv_rwlock_name()

    -
    char * erl_drv_rwlock_name(ErlDrvRWLock
    -        *rwlck);

    Returns a pointer to the name of the rwlock.

    rwlck is a pointer to an initialized rwlock.

    Note

    This function is intended for debugging purposes only.

    Available since OTP R16B02

    +
    char * erl_drv_rwlock_name(ErlDrvRWLock
    +        *rwlck);

    Returns a pointer to the name of the rwlock.

    rwlck is a pointer to an initialized rwlock.

    Note

    This function is intended for debugging purposes only.

    Available since OTP R16B02

    erl_drv_rwlock_rlock()

    -
    void erl_drv_rwlock_rlock(ErlDrvRWLock
    -        *rwlck);

    Read locks an rwlock. The calling thread is blocked until the rwlock has been +

    void erl_drv_rwlock_rlock(ErlDrvRWLock
    +        *rwlck);

    Read locks an rwlock. The calling thread is blocked until the rwlock has been read locked. A thread that currently has read or read/write locked the rwlock cannot lock the same rwlock again.

    rwlck is a pointer to the rwlock to read lock.

    Warning

    If you leave an rwlock locked in an emulator thread when you let the thread out of your control, you will very likely deadlock the whole emulator.

    This function is thread-safe.

    @@ -1486,16 +1486,16 @@

    erl_drv_rwlock_runlock()

    -
    void erl_drv_rwlock_runlock(ErlDrvRWLock
    -        *rwlck);

    Read unlocks an rwlock. The rwlock currently must be read locked by the calling +

    void erl_drv_rwlock_runlock(ErlDrvRWLock
    +        *rwlck);

    Read unlocks an rwlock. The rwlock currently must be read locked by the calling thread.

    rwlck is a pointer to an rwlock to read unlock.

    This function is thread-safe.

    erl_drv_rwlock_rwlock()

    -
    void erl_drv_rwlock_rwlock(ErlDrvRWLock
    -        *rwlck);

    Read/write locks an rwlock. The calling thread is blocked until the rwlock has +

    void erl_drv_rwlock_rwlock(ErlDrvRWLock
    +        *rwlck);

    Read/write locks an rwlock. The calling thread is blocked until the rwlock has been read/write locked. A thread that currently has read or read/write locked the rwlock cannot lock the same rwlock again.

    rwlck is a pointer to an rwlock to read/write lock.

    Warning

    If you leave an rwlock locked in an emulator thread when you let the thread out of your control, you will very likely deadlock the whole emulator.

    This function is thread-safe.

    @@ -1504,16 +1504,16 @@

    erl_drv_rwlock_rwunlock()

    -
    void erl_drv_rwlock_rwunlock(ErlDrvRWLock
    -        *rwlck);

    Read/write unlocks an rwlock. The rwlock currently must be read/write locked by +

    void erl_drv_rwlock_rwunlock(ErlDrvRWLock
    +        *rwlck);

    Read/write unlocks an rwlock. The rwlock currently must be read/write locked by the calling thread.

    rwlck is a pointer to an rwlock to read/write unlock.

    This function is thread-safe.

    erl_drv_rwlock_tryrlock()

    -
    int erl_drv_rwlock_tryrlock(ErlDrvRWLock
    -        *rwlck);

    Tries to read lock an rwlock.

    rwlck is a pointer to an rwlock to try to read lock.

    Returns 0 on success, otherwise EBUSY. A thread that currently has read or +

    int erl_drv_rwlock_tryrlock(ErlDrvRWLock
    +        *rwlck);

    Tries to read lock an rwlock.

    rwlck is a pointer to an rwlock to try to read lock.

    Returns 0 on success, otherwise EBUSY. A thread that currently has read or read/write locked the rwlock cannot try to lock the same rwlock again.

    Warning

    If you leave an rwlock locked in an emulator thread when you let the thread out of your control, you will very likely deadlock the whole emulator.

    This function is thread-safe.

    @@ -1521,8 +1521,8 @@

    erl_drv_rwlock_tryrwlock()

    -
    int erl_drv_rwlock_tryrwlock(ErlDrvRWLock
    -        *rwlck);

    Tries to read/write lock an rwlock. A thread that currently has read or +

    int erl_drv_rwlock_tryrwlock(ErlDrvRWLock
    +        *rwlck);

    Tries to read/write lock an rwlock. A thread that currently has read or read/write locked the rwlock cannot try to lock the same rwlock again.

    rwlckis pointer to an rwlock to try to read/write lock.

    Returns 0 on success, otherwise EBUSY.

    Warning

    If you leave an rwlock locked in an emulator thread when you let the thread out of your control, you will very likely deadlock the whole emulator.

    This function is thread-safe.

    @@ -1530,8 +1530,8 @@

    erl_drv_send_term()

    -
    int erl_drv_send_term(ErlDrvTermData port,
    -        ErlDrvTermData receiver, ErlDrvTermData* term, int n);

    This function is the only way for a driver to send data to other processes +

    int erl_drv_send_term(ErlDrvTermData port,
    +        ErlDrvTermData receiver, ErlDrvTermData* term, int n);

    This function is the only way for a driver to send data to other processes than the port owner process. Parameter receiver specifies the process to receive the data.

    Note

    Parameter port is not an ordinary port handle, but a port handle converted using driver_mk_port.

    Parameters port, term, and n work as in @@ -1541,17 +1541,17 @@

    erl_drv_set_os_pid()

    -
    void erl_drv_set_os_pid(ErlDrvPort port,
    -        ErlDrvSInt pid);

    Sets the os_pid seen when doing erlang:port_info/2 on this port.

    port is the port handle of the port (driver instance) to set the pid on. +

    void erl_drv_set_os_pid(ErlDrvPort port,
    +        ErlDrvSInt pid);

    Sets the os_pid seen when doing erlang:port_info/2 on this port.

    port is the port handle of the port (driver instance) to set the pid on. pidis the pid to set.

    Available since OTP 19.0

    erl_drv_thread_create()

    -
    int erl_drv_thread_create(char *name, ErlDrvTid
    -        *tid, void * (*func)(void *), void *arg, ErlDrvThreadOpts
    -        *opts);

    Creates a new thread.

    • name - A string identifying the created thread. It is used to identify +

      int erl_drv_thread_create(char *name, ErlDrvTid
      +        *tid, void * (*func)(void *), void *arg, ErlDrvThreadOpts
      +        *opts);

      Creates a new thread.

      • name - A string identifying the created thread. It is used to identify the thread in planned future debug functionality.

      • tid - A pointer to a thread identifier variable.

      • func - A pointer to a function to execute in the created thread.

      • arg - A pointer to argument to the func function.

      • opts - A pointer to thread options to use or NULL.

      Returns 0 on success, otherwise an errno value is returned to indicate the error. The newly created thread begins executing in the function pointed to by func, and func is passed arg as argument. When erl_drv_thread_create @@ -1576,8 +1576,8 @@

      erl_drv_thread_exit()

      -
      void erl_drv_thread_exit(void
      -        *exit_value);

      Terminates the calling thread with the exit value passed as argument. +

      void erl_drv_thread_exit(void
      +        *exit_value);

      Terminates the calling thread with the exit value passed as argument. exit_value is a pointer to an exit value or NULL.

      You are only allowed to terminate threads created with erl_drv_thread_create.

      The exit value can later be retrieved by another thread through erl_drv_thread_join.

      This function is thread-safe.

      @@ -1586,8 +1586,8 @@

      erl_drv_thread_join()

      -
      int erl_drv_thread_join(ErlDrvTid tid, void
      -        **exit_value);

      Joins the calling thread with another thread, that is, the calling thread is +

      int erl_drv_thread_join(ErlDrvTid tid, void
      +        **exit_value);

      Joins the calling thread with another thread, that is, the calling thread is blocked until the thread identified by tid has terminated.

      tid is the thread identifier of the thread to join. exit_value is a pointer to a pointer to an exit value, or NULL.

      Returns 0 on success, otherwise an errno value is returned to indicate the error.

      A thread can only be joined once. The behavior of joining more than once is @@ -1599,14 +1599,14 @@

      erl_drv_thread_name()

      -
      char * erl_drv_thread_name(ErlDrvTid
      -        tid);

      Returns a pointer to the name of the thread.

      tid is a thread identifier.

      Note

      This function is intended for debugging purposes only.

      Available since OTP R16B02

      +
      char * erl_drv_thread_name(ErlDrvTid
      +        tid);

      Returns a pointer to the name of the thread.

      tid is a thread identifier.

      Note

      This function is intended for debugging purposes only.

      Available since OTP R16B02

      erl_drv_thread_opts_create()

      -
      ErlDrvThreadOpts * erl_drv_thread_opts_create(char *name);

      Allocates and initializes a thread option structure.

      name is a string identifying the created thread options. It is used to +

      ErlDrvThreadOpts * erl_drv_thread_opts_create(char *name);

      Allocates and initializes a thread option structure.

      name is a string identifying the created thread options. It is used to identify the thread options in planned future debug functionality.

      Returns NULL on failure. A thread option structure is used for passing options to erl_drv_thread_create. If the structure is not modified before it is passed to @@ -1619,21 +1619,21 @@

      erl_drv_thread_opts_destroy()

      -
      void erl_drv_thread_opts_destroy(ErlDrvThreadOpts *opts);

      Destroys thread options previously created by +

      void erl_drv_thread_opts_destroy(ErlDrvThreadOpts *opts);

      Destroys thread options previously created by erl_drv_thread_opts_create.

      opts is a pointer to thread options to destroy.

      This function is thread-safe.

      erl_drv_thread_self()

      -
      ErlDrvTid erl_drv_thread_self(void);

      Returns the thread identifier of the calling thread.

      This function is thread-safe.

      +
      ErlDrvTid erl_drv_thread_self(void);

      Returns the thread identifier of the calling thread.

      This function is thread-safe.

      erl_drv_time_offset()

      -
      ErlDrvTime erl_drv_time_offset(ErlDrvTimeUnit
      -        time_unit);

      Returns the current time offset between +

      ErlDrvTime erl_drv_time_offset(ErlDrvTimeUnit
      +        time_unit);

      Returns the current time offset between Erlang monotonic time and Erlang system time converted into the time_unit passed as argument.

      time_unit is time unit of returned value.

      Returns ERL_DRV_TIME_ERROR if called with an invalid time unit argument, or if @@ -1644,15 +1644,15 @@

      erl_drv_tsd_get()

      -
      void * erl_drv_tsd_get(ErlDrvTSDKey
      -        key);

      Returns the thread-specific data associated with key for the calling thread.

      key is a thread-specific data key.

      Returns NULL if no data has been associated with key for the calling thread.

      This function is thread-safe.

      +
      void * erl_drv_tsd_get(ErlDrvTSDKey
      +        key);

      Returns the thread-specific data associated with key for the calling thread.

      key is a thread-specific data key.

      Returns NULL if no data has been associated with key for the calling thread.

      This function is thread-safe.

      erl_drv_tsd_key_create()

      -
      int erl_drv_tsd_key_create(char *name,
      -        ErlDrvTSDKey *key);

      Creates a thread-specific data key.

      name is a string identifying the created key. It is used to identify the key +

      int erl_drv_tsd_key_create(char *name,
      +        ErlDrvTSDKey *key);

      Creates a thread-specific data key.

      name is a string identifying the created key. It is used to identify the key in planned future debug functionality.

      key is a pointer to a thread-specific data key variable.

      Returns 0 on success, otherwise an errno value is returned to indicate the error. The driver creating the key is responsible for destroying it before the driver is unloaded.

      This function is thread-safe.

      @@ -1661,8 +1661,8 @@

      erl_drv_tsd_key_destroy()

      -
      void erl_drv_tsd_key_destroy(ErlDrvTSDKey
      -        key);

      Destroys a thread-specific data key previously created by +

      void erl_drv_tsd_key_destroy(ErlDrvTSDKey
      +        key);

      Destroys a thread-specific data key previously created by erl_drv_tsd_key_create. All thread-specific data using this key in all threads must be cleared (see erl_drv_tsd_set) before the call to @@ -1675,8 +1675,8 @@

      erl_drv_tsd_set()

      -
      void erl_drv_tsd_set(ErlDrvTSDKey key, void
      -        *data);

      Sets thread-specific data associated with key for the calling thread. You are +

      void erl_drv_tsd_set(ErlDrvTSDKey key, void
      +        *data);

      Sets thread-specific data associated with key for the calling thread. You are only allowed to set thread-specific data for threads while they are fully under your control. For example, if you set thread-specific data in a thread calling a driver callback function, it must be cleared, that is, set to NULL, before @@ -1688,7 +1688,7 @@

      erl_errno_id()

      -
      char * erl_errno_id(int error);

      Returns the atom name of the Erlang error, given the error number in error. +

      char * erl_errno_id(int error);

      Returns the atom name of the Erlang error, given the error number in error. The error atoms are einval, enoent, and so on. It can be used to make error terms from the driver.

      @@ -1696,8 +1696,8 @@

      remove_driver_entry()

      -
      int remove_driver_entry(ErlDrvEntry
      -        *de);

      Removes a driver entry de previously added with +

      int remove_driver_entry(ErlDrvEntry
      +        *de);

      Removes a driver entry de previously added with add_driver_entry.

      Driver entries added by the erl_ddll Erlang interface cannot be removed by using this interface.

      @@ -1705,8 +1705,8 @@

      set_busy_port()

      -
      void set_busy_port(ErlDrvPort port, int
      -        on);

      Sets and unsets the busy state of the port. If on is non-zero, the port is set +

      void set_busy_port(ErlDrvPort port, int
      +        on);

      Sets and unsets the busy state of the port. If on is non-zero, the port is set to busy. If it is zero, the port is set to not busy. You typically want to combine this feature with the busy port message queue functionality.

      Processes sending command data to the port are suspended if either the port or @@ -1723,8 +1723,8 @@

      set_port_control_flags()

      -
      void set_port_control_flags(ErlDrvPort port,
      -        int flags);

      Sets flags for how the control driver entry +

      void set_port_control_flags(ErlDrvPort port,
      +        int flags);

      Sets flags for how the control driver entry function will return data to the port owner process. (The control function is called from erlang:port_control/3.)

      Currently there are only two meaningful values for flags: 0 means that data is returned in a list, and PORT_CONTROL_FLAG_BINARY means data is returned as diff --git a/prs/9045/erts-15.1.2/doc/html/erl_ext_dist.html b/prs/9045/erts-15.1.2/doc/html/erl_ext_dist.html index 6aeca06f8a14..5cfb86e70ed9 100644 --- a/prs/9045/erts-15.1.2/doc/html/erl_ext_dist.html +++ b/prs/9045/erts-15.1.2/doc/html/erl_ext_dist.html @@ -446,7 +446,7 @@

      positive and 1 if it is negative. The digits are stored with the least significant byte stored first. To calculate the integer, the following formula can be used:

      B = 256
      -(d0*B^0 + d1*B^1 + d2*B^2 + ... d(N-1)*B^(n-1))

      +(d0*B^0 + d1*B^1 + d2*B^2 + ... d(N-1)*B^(n-1))

    diff --git a/prs/9045/erts-15.1.2/doc/html/erl_nif.html b/prs/9045/erts-15.1.2/doc/html/erl_nif.html index 76cde6e17cae..8a7cd044e742 100644 --- a/prs/9045/erts-15.1.2/doc/html/erl_nif.html +++ b/prs/9045/erts-15.1.2/doc/html/erl_nif.html @@ -161,29 +161,29 @@

    A minimal example of a NIF library can look as follows:

    /* niftest.c */
     #include <erl_nif.h>
     
    -static ERL_NIF_TERM hello(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
    -{
    -    return enif_make_string(env, "Hello world!", ERL_NIF_LATIN1);
    -}
    +static ERL_NIF_TERM hello(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
    +{
    +    return enif_make_string(env, "Hello world!", ERL_NIF_LATIN1);
    +}
     
    -static ErlNifFunc nif_funcs[] =
    -{
    -    {"hello", 0, hello}
    -};
    +static ErlNifFunc nif_funcs[] =
    +{
    +    {"hello", 0, hello}
    +};
     
    -ERL_NIF_INIT(niftest,nif_funcs,NULL,NULL,NULL,NULL)

    The Erlang module can look as follows:

    -module(niftest).
    +ERL_NIF_INIT(niftest,nif_funcs,NULL,NULL,NULL,NULL)

    The Erlang module can look as follows:

    -module(niftest).
     
    --export([init/0, hello/0]).
    +-export([init/0, hello/0]).
     
    --nifs([hello/0]).
    +-nifs([hello/0]).
     
    --on_load(init/0).
    +-on_load(init/0).
     
    -init() ->
    -      erlang:load_nif("./niftest", 0).
    +init() ->
    +      erlang:load_nif("./niftest", 0).
     
    -hello() ->
    -      erlang:nif_error("NIF library not loaded").

    Compile and test can look as follows (on Linux):

    $> gcc -fPIC -shared -o niftest.so niftest.c -I $ERL_ROOT/usr/include/
    +hello() ->
    +      erlang:nif_error("NIF library not loaded").

    Compile and test can look as follows (on Linux):

    $> gcc -fPIC -shared -o niftest.so niftest.c -I $ERL_ROOT/usr/include/
     $> erl
     
     1> c(niftest).
    @@ -229,21 +229,21 @@ 

    ERL_NIF_TERM world_atom; -static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) -{ - world_atom = enif_make_atom(env, "world"); +static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) +{ + world_atom = enif_make_atom(env, "world"); return 0; -} +} -static ERL_NIF_TERM hello(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ - ERL_NIF_TERM hello_string = enif_make_string(env, "Hello", ERL_NIF_LATIN1); - return enif_make_tuple2(env, hello_string, world_atom); -} +static ERL_NIF_TERM hello(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + ERL_NIF_TERM hello_string = enif_make_string(env, "Hello", ERL_NIF_LATIN1); + return enif_make_tuple2(env, hello_string, world_atom); +} -static ErlNifFunc nif_funcs[] = { { "hello", 0, hello } }; +static ErlNifFunc nif_funcs[] = { { "hello", 0, hello } }; -ERL_NIF_INIT(niftest, nif_funcs, load, NULL, NULL, NULL)

  • Binaries - Terms of type binary are accessed with the help of struct type +ERL_NIF_INIT(niftest, nif_funcs, load, NULL, NULL, NULL)

  • Binaries - Terms of type binary are accessed with the help of struct type ErlNifBinary, which contains a pointer (data) to the raw binary data and the length (size) of the data in bytes. Both data and size are read-only and are only to be written using calls to API @@ -281,19 +281,19 @@

    garbage collector or enif_release_resource). Resource types are uniquely identified by a supplied name string and the name of the implementing module.

    The following is a template example of how to create and return a resource object.

    ERL_NIF_TERM term;
    -MyStruct* obj = enif_alloc_resource(my_resource_type, sizeof(MyStruct));
    +MyStruct* obj = enif_alloc_resource(my_resource_type, sizeof(MyStruct));
     
     /* initialize struct ... */
     
    -term = enif_make_resource(env, obj);
    +term = enif_make_resource(env, obj);
     
    -if (keep_a_reference_of_our_own) {
    +if (keep_a_reference_of_our_own) {
         /* store 'obj' in static variable, private data or other resource object */
    -}
    -else {
    -    enif_release_resource(obj);
    +}
    +else {
    +    enif_release_resource(obj);
         /* resource now only owned by "Erlang" */
    -}
    +}
     return term;

    Notice that once enif_make_resource creates the term to return to Erlang, the code can choose to either keep its own native pointer to the allocated struct and release it later, or release it immediately and rely only on the @@ -345,50 +345,50 @@

    libraries can however fail if deprecated features are used.

  • Time Measurement - Support for time measurement in NIF libraries:

  • I/O Queues
    The Erlang nif library contains function for easily working with I/O vectors as used by the unix system call writev. The I/O Queue is not thread safe, so -some other synchronization mechanism has to be used.

    Typical usage when writing to a file descriptor looks like this:

    int writeiovec(ErlNifEnv *env, ERL_NIF_TERM term, ERL_NIF_TERM *tail,
    -               ErlNifIOQueue *q, int fd) {
    +some other synchronization mechanism has to be used.

    Typical usage when writing to a file descriptor looks like this:

    int writeiovec(ErlNifEnv *env, ERL_NIF_TERM term, ERL_NIF_TERM *tail,
    +               ErlNifIOQueue *q, int fd) {
     
         ErlNifIOVec vec, *iovec = &vec;
         SysIOVec *sysiovec;
         int saved_errno;
         int iovcnt, n;
     
    -    if (!enif_inspect_iovec(env, 64, term, tail, &iovec))
    +    if (!enif_inspect_iovec(env, 64, term, tail, &iovec))
             return -2;
     
    -    if (enif_ioq_size(q) > 0) {
    +    if (enif_ioq_size(q) > 0) {
             /* If the I/O queue contains data we enqueue the iovec and
                then peek the data to write out of the queue. */
    -        if (!enif_ioq_enqv(q, iovec, 0))
    +        if (!enif_ioq_enqv(q, iovec, 0))
                 return -3;
     
    -        sysiovec = enif_ioq_peek(q, &iovcnt);
    -    } else {
    +        sysiovec = enif_ioq_peek(q, &iovcnt);
    +    } else {
             /* If the I/O queue is empty we skip the trip through it. */
             iovcnt = iovec->iovcnt;
             sysiovec = iovec->iov;
    -    }
    +    }
     
         /* Attempt to write the data */
    -    n = writev(fd, sysiovec, iovcnt);
    +    n = writev(fd, sysiovec, iovcnt);
         saved_errno = errno;
     
    -    if (enif_ioq_size(q) == 0) {
    +    if (enif_ioq_size(q) == 0) {
             /* If the I/O queue was initially empty we enqueue any
                remaining data into the queue for writing later. */
    -        if (n >= 0 && !enif_ioq_enqv(q, iovec, n))
    +        if (n >= 0 && !enif_ioq_enqv(q, iovec, n))
                 return -3;
    -    } else {
    +    } else {
             /* Dequeue any data that was written from the queue. */
    -        if (n > 0 && !enif_ioq_deq(q, n, NULL))
    +        if (n > 0 && !enif_ioq_deq(q, n, NULL))
                 return -4;
    -    }
    +    }
     
         /* return n, which is either number of bytes written or -1 if
            some error happened */
         errno = saved_errno;
         return n;
    -}
  • Long-running NIFs
    As mentioned in the warning text at the beginning of +}

  • Long-running NIFs
    As mentioned in the warning text at the beginning of this manual page, it is of vital importance that a native function returns relatively fast. It is difficult to give an exact maximum amount of time that a native function is allowed to work, but usually a well-behaving native @@ -518,12 +518,12 @@

    with all its terms is valid until you explicitly invalidate it with enif_free_env or enif_send.

  • 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.

    • fptr - A pointer to the function that implements the NIF.

    • argv - Contains the function arguments passed to the NIF.

    • argc - The array length, that is, the function arity. argv[N-1] thus +} ErlNifFunc;

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

    • fptr - A pointer to the function that implements the NIF.

    • argv - Contains the function arguments passed to the NIF.

    • argc - The array length, that is, the function arity. argv[N-1] thus denotes the Nth argument to the NIF. Notice that the argument argc allows for the same C function to implement several Erlang functions with different arity (but probably with the same name).

    • flags - Is 0 for a regular NIF (and so its value can be omitted for @@ -566,25 +566,25 @@

      type. It can be copied, moved in memory, forgotten, and so on.

    • ErlNifResourceType - Each instance of ErlNifResourceType represents a class of memory-managed resource objects that can be garbage collected. Each resource type has a unique name and a -destructor function that is called when objects of its type are released.

    • ErlNifResourceTypeInit

      typedef struct {
      +destructor function that is called when objects of its type are released.

    • ErlNifResourceTypeInit

      typedef struct {
           ErlNifResourceDtor* dtor;       // #1 Destructor
           ErlNifResourceStop* stop;       // #2 Select stop
           ErlNifResourceDown* down;       // #3 Monitor down
           int members;
           ErlNifResourceDynCall* dyncall; // #4 Dynamic call
      -} ErlNifResourceTypeInit;

      Initialization structure read by +} ErlNifResourceTypeInit;

    Initialization structure read by enif_open_resource_type_x enif_init_resource_type.

  • ErlNifResourceDtor

    typedef void ErlNifResourceDtor(ErlNifEnv* caller_env, void* obj);

    The function prototype of a resource destructor function.

    The obj argument is a pointer to the resource. The only allowed use for the resource in the destructor is to access its user data one final time. The destructor is guaranteed to be the last callback before the resource is -deallocated.

  • ErlNifResourceDown

    typedef void ErlNifResourceDown(ErlNifEnv* caller_env, void* obj, ErlNifPid* pid, ErlNifMonitor* mon);

    The function prototype of a resource down function, called on the behalf of +deallocated.

  • ErlNifResourceDown

    typedef void ErlNifResourceDown(ErlNifEnv* caller_env, void* obj, ErlNifPid* pid, ErlNifMonitor* mon);

    The function prototype of a resource down function, called on the behalf of enif_monitor_process. obj is the resource, pid is the identity of the monitored process that is exiting, and mon is the identity of the monitor.

  • ErlNifResourceStop

    typedef void ErlNifResourceStop(ErlNifEnv* caller_env, void* obj, ErlNifEvent event, int is_direct_call);

    The function prototype of a resource stop function, called on the behalf of enif_select. obj is the resource, event is OS event, is_direct_call is true if the call is made directly from enif_select or false if it is a scheduled call (potentially from another -thread).

  • ErlNifResourceDynCall

    typedef void ErlNifResourceDynCall(ErlNifEnv* caller_env, void* obj, void* call_data);

    The function prototype of a dynamic resource call function, called by +thread).

  • ErlNifResourceDynCall

    typedef void ErlNifResourceDynCall(ErlNifEnv* caller_env, void* obj, void* call_data);

    The function prototype of a dynamic resource call function, called by enif_dynamic_resource_call. Argument obj is the resource object and call_data is the last argument to enif_dynamic_resource_call passed through.

  • ErlNifCharEncoding

    typedef enum {
    @@ -607,11 +607,11 @@ 

    guarantees the same hash for the same term within one Erlang VM instance.

    It takes 32-bit salt values and generates hashes within 0..2^32-1.

  • ERL_NIF_PHASH2 - Portable hash function that gives the same hash for the same Erlang term regardless of machine architecture and ERTS version.

    It ignores salt values and generates hashes within 0..2^27-1.

    Slower than ERL_NIF_INTERNAL_HASH. It corresponds to erlang:phash2/1.

  • SysIOVec - A system I/O vector, as used by writev on Unix and WSASend on Win32. It is used in ErlNifIOVec and by -enif_ioq_peek.

  • ErlNifIOVec

    typedef struct {
    +enif_ioq_peek.

  • ErlNifIOVec

    typedef struct {
       int iovcnt;
       size_t size;
       SysIOVec* iov;
    -} ErlNifIOVec;

    An I/O vector containing iovcnt SysIOVecs pointing to the data. It is used +} ErlNifIOVec;

  • An I/O vector containing iovcnt SysIOVecs pointing to the data. It is used by enif_inspect_iovec and enif_ioq_enqv.

  • ErlNifIOQueueOpts - Options to configure a ErlNifIOQueue.

    • ERL_NIF_IOQ_NORMAL - Create a normal I/O Queue
  • @@ -620,17 +620,17 @@

    enif_alloc()

    -
    void * enif_alloc(
    -        size_t size);

    Allocates memory of size bytes.

    Returns NULL if the allocation fails.

    The returned pointer is suitably aligned for any built-in type that fit in the +

    void * enif_alloc(
    +        size_t size);

    Allocates memory of size bytes.

    Returns NULL if the allocation fails.

    The returned pointer is suitably aligned for any built-in type that fit in the allocated memory.

    enif_alloc_binary()

    -
    int enif_alloc_binary(
    +
    int enif_alloc_binary(
             size_t size,
    -        ErlNifBinary* bin);

    Allocates a new binary of size size bytes. Initializes the structure pointed + ErlNifBinary* bin);

    Allocates a new binary of size size bytes. Initializes the structure pointed to by bin to refer to the allocated binary. The binary must either be released by enif_release_binary or ownership transferred to an Erlang term with @@ -643,7 +643,7 @@

    enif_alloc_env()

    -
    ErlNifEnv * enif_alloc_env();

    Allocates a new process independent environment. +

    ErlNifEnv * enif_alloc_env();

    Allocates a new process independent environment. The environment can be used to hold terms that are not bound to any process. Such terms can later be copied to a process environment with enif_make_copy or be sent to a process as a @@ -653,20 +653,20 @@

    enif_alloc_resource()

    -
    void * enif_alloc_resource(
    +
    void * enif_alloc_resource(
             ErlNifResourceType* type,
    -        unsigned size);

    Allocates a memory-managed resource object of type type and size size bytes.

    Available since OTP R13B04

    + unsigned size);

    Allocates a memory-managed resource object of type type and size size bytes.

    Available since OTP R13B04

    enif_binary_to_term()

    -
    size_t enif_binary_to_term(
    +
    size_t enif_binary_to_term(
             ErlNifEnv *env,
             const unsigned char* data,
             size_t size,
             ERL_NIF_TERM *term,
    -        unsigned int opts);

    Creates a term that is the result of decoding the binary data at data, which + unsigned int opts);

    Creates a term that is the result of decoding the binary data at data, which must be encoded according to the Erlang external term format. No more than size bytes are read from data. Argument opts corresponds to the second argument to erlang:binary_to_term/2 and must be either 0 or @@ -679,16 +679,16 @@

    enif_clear_env()

    -
    void enif_clear_env(ErlNifEnv* env);

    Frees all terms in an environment and clears it for reuse. The environment must +

    void enif_clear_env(ErlNifEnv* env);

    Frees all terms in an environment and clears it for reuse. The environment must have been allocated with enif_alloc_env.

    Available since OTP R14B

    enif_compare()

    -
    int enif_compare(
    +
    int enif_compare(
             ERL_NIF_TERM lhs,
    -        ERL_NIF_TERM rhs);

    Returns an integer < 0 if lhs < rhs, 0 if lhs = rhs, and > 0 if + ERL_NIF_TERM rhs);

    Returns an integer < 0 if lhs < rhs, 0 if lhs = rhs, and > 0 if lhs > rhs. Corresponds to the Erlang operators ==, /=, =<, <, >=, and > (but not =:= or =/=).

    Available since OTP R13B04

    @@ -696,9 +696,9 @@

    enif_compare_monitors()

    -
    int enif_compare_monitors(
    +
    int enif_compare_monitors(
             const ErlNifMonitor *monitor1,
    -        const ErlNifMonitor *monitor2);

    Compares two ErlNifMonitors. Can also be used to + const ErlNifMonitor *monitor2);

    Compares two ErlNifMonitors. 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.

    Available since OTP 20.0

    @@ -706,61 +706,61 @@

    enif_compare_pids()

    -
    int enif_compare_pids(
    +
    int enif_compare_pids(
             const ErlNifPid *pid1,
    -        const ErlNifPid *pid2);

    Compares two ErlNifPid s according to term order.

    Returns 0 if pid1 and pid2 are equal, < 0 if pid1 < pid2, and > 0 + const ErlNifPid *pid2);

    Compares two ErlNifPid s according to term order.

    Returns 0 if pid1 and pid2 are equal, < 0 if pid1 < pid2, and > 0 if pid1 > pid2.

    Available since OTP 22.0

    enif_cond_broadcast()

    -
    void enif_cond_broadcast(
    -        ErlNifCond *cnd);

    Same as erl_drv_cond_broadcast.

    Available since OTP R13B04

    +
    void enif_cond_broadcast(
    +        ErlNifCond *cnd);

    Same as erl_drv_cond_broadcast.

    Available since OTP R13B04

    enif_cond_create()

    -
    ErlNifCond * enif_cond_create(
    -        char *name);

    Same as erl_drv_cond_create.

    Available since OTP R13B04

    +
    ErlNifCond * enif_cond_create(
    +        char *name);

    Same as erl_drv_cond_create.

    Available since OTP R13B04

    enif_cond_destroy()

    -
    void enif_cond_destroy(
    -        ErlNifCond *cnd);

    Same as erl_drv_cond_destroy.

    Available since OTP R13B04

    +
    void enif_cond_destroy(
    +        ErlNifCond *cnd);

    Same as erl_drv_cond_destroy.

    Available since OTP R13B04

    enif_cond_name()

    -
    char* enif_cond_name(
    -        ErlNifCond* cnd);

    Same as erl_drv_cond_name.

    Available since OTP 21.0

    +
    char* enif_cond_name(
    +        ErlNifCond* cnd);

    Same as erl_drv_cond_name.

    Available since OTP 21.0

    enif_cond_signal()

    -
    void enif_cond_signal(
    -        ErlNifCond *cnd);

    Same as erl_drv_cond_signal.

    Available since OTP R13B04

    +
    void enif_cond_signal(
    +        ErlNifCond *cnd);

    Same as erl_drv_cond_signal.

    Available since OTP R13B04

    enif_cond_wait()

    -
    void enif_cond_wait(
    +
    void enif_cond_wait(
             ErlNifCond *cnd,
    -        ErlNifMutex *mtx);

    Same as erl_drv_cond_wait.

    Available since OTP R13B04

    + ErlNifMutex *mtx);

    Same as erl_drv_cond_wait.

    Available since OTP R13B04

    enif_consume_timeslice()

    -
    int enif_consume_timeslice(
    +
    int enif_consume_timeslice(
             ErlNifEnv *env,
    -        int percent);

    Gives the runtime system a hint about how much CPU time the current NIF call has + int percent);

    Gives the runtime system a hint about how much CPU time the current NIF call has consumed since the last hint, or since the start of the NIF if no previous hint has been specified. The time is specified as a percent of the timeslice that a process is allowed to execute Erlang code until it can be suspended to give time @@ -782,10 +782,10 @@

    enif_convert_time_unit()

    -
    ErlNifTime enif_convert_time_unit(
    +
    ErlNifTime enif_convert_time_unit(
             ErlNifTime val,
             ErlNifTimeUnit from,
    -        ErlNifTimeUnit to);

    Converts the val value of time unit from to the corresponding value of time + ErlNifTimeUnit to);

    Converts the val value of time unit from to the corresponding value of time unit to. The result is rounded using the floor function.

    • val - Value to convert time unit for.

    • from - Time unit of val.

    • to - Time unit of returned value.

    Returns ERL_NIF_TIME_ERROR if called with an invalid time unit argument.

    See also ErlNifTime and ErlNifTimeUnit.

    Available since OTP 18.3

    @@ -793,8 +793,8 @@

    enif_cpu_time()

    -
    ERL_NIF_TERM enif_cpu_time(
    -        ErlNifEnv *env);

    Returns the CPU time in the same format as +

    ERL_NIF_TERM enif_cpu_time(
    +        ErlNifEnv *env);

    Returns the CPU time in the same format as erlang:timestamp(). The CPU time is the time the current logical CPU has spent executing since some arbitrary point in the past. If the OS does not support fetching this value, enif_cpu_time invokes @@ -804,10 +804,10 @@

    enif_demonitor_process()

    -
    int enif_demonitor_process(
    +
    int enif_demonitor_process(
             ErlNifEnv* caller_env,
             void* obj,
    -        const ErlNifMonitor* mon);

    Cancels a monitor created earlier with + const ErlNifMonitor* mon);

    Cancels a monitor created earlier with enif_monitor_process. Argument obj is a pointer to the resource holding the monitor and *mon identifies the monitor.

    Argument caller_env is the environment of the calling thread (process bound or @@ -819,12 +819,12 @@

    enif_dynamic_resource_call()

    -
    int enif_dynamic_resource_call(
    +
    int enif_dynamic_resource_call(
             ErlNifEnv* caller_env,
             ERL_NIF_TERM rt_module,
             ERL_NIF_TERM rt_name,
             ERL_NIF_TERM resource,
    -        void* call_data);

    Call code of a resource type implemented by another NIF module. The atoms + void* call_data);

    Call code of a resource type implemented by another NIF module. The atoms rt_module and rt_name identifies the resource type to be called. Argument resource identifies a resource object of that type.

    The callback dyncall of the identified resource type will be called with a pointer to the resource objects obj and @@ -839,18 +839,18 @@

    enif_equal_tids()

    -
    int enif_equal_tids(
    +
    int enif_equal_tids(
             ErlNifTid tid1,
    -        ErlNifTid tid2);

    Same as erl_drv_equal_tids.

    Available since OTP R13B04

    + ErlNifTid tid2);

    Same as erl_drv_equal_tids.

    Available since OTP R13B04

    enif_fprintf()

    -
    int enif_fprintf(
    +
    int enif_fprintf(
             FILE *stream,
             const char *format,
    -        ...);

    Similar to fprintf but this format string also accepts "%T", which formats + ...);

    Similar to fprintf but this format string also accepts "%T", which formats Erlang terms of type ERL_NIF_TERM.

    This function is primarily intended for debugging purpose. It is not recommended to print very large terms with %T. The function may change errno, even if successful.

    Available since OTP 21.0

    @@ -859,15 +859,15 @@

    enif_free()

    -
    void enif_free(
    -        void* ptr);

    Frees memory allocated by enif_alloc.

    +
    void enif_free(
    +        void* ptr);

    Frees memory allocated by enif_alloc.

    enif_free_env()

    -
    void enif_free_env(
    -        ErlNifEnv* env);

    Frees an environment allocated with +

    void enif_free_env(
    +        ErlNifEnv* env);

    Frees an environment allocated with enif_alloc_env. All terms created in the environment are freed as well.

    Available since OTP R14B

    @@ -875,31 +875,31 @@

    enif_free_iovec()

    -
    void enif_free_iovec(
    -        ErlNifIOVec* iov);

    Frees an io vector returned from +

    void enif_free_iovec(
    +        ErlNifIOVec* iov);

    Frees an io vector returned from enif_inspect_iovec. This is needed only if a NULL environment is passed to enif_inspect_iovec.

    ErlNifIOVec *iovec = NULL;
     size_t max_elements = 128;
     ERL_NIF_TERM tail;
    -if (!enif_inspect_iovec(NULL, max_elements, term, &tail, &iovec))
    +if (!enif_inspect_iovec(NULL, max_elements, term, &tail, &iovec))
       return 0;
     
     // Do things with the iovec
     
     /* Free the iovector, possibly in another thread or nif function call */
    -enif_free_iovec(iovec);

    Available since OTP 20.1

    +enif_free_iovec(iovec);

    Available since OTP 20.1

    enif_get_atom()

    -
    int enif_get_atom(
    +
    int enif_get_atom(
             ErlNifEnv *env,
             ERL_NIF_TERM term,
             char *buf,
             unsigned size,
    -        ErlNifCharEncoding encoding);

    Writes a NULL-terminated string in the buffer pointed to by buf of size + ErlNifCharEncoding encoding);

    Writes a NULL-terminated string in the buffer pointed to by buf of size size bytes, consisting of the string representation of the atom term with encoding.

    Returns the number of bytes written (including terminating NULL character) or 0 if term is not an atom with maximum length of size-1 bytes in @@ -909,11 +909,11 @@

    enif_get_atom_length()

    -
    int enif_get_atom_length(
    +
    int enif_get_atom_length(
             ErlNifEnv *env,
             ERL_NIF_TERM term,
             unsigned *len,
    -        ErlNifCharEncoding encoding);

    Sets *len to the length (number of bytes excluding terminating NULL + ErlNifCharEncoding encoding);

    Sets *len to the length (number of bytes excluding terminating NULL character) of the atom term with encoding.

    Returns true on success, or false if term is not an atom or if the atom cannot be encoded using encoding.

    Available since OTP R14B

    @@ -921,39 +921,39 @@

    enif_get_double()

    -
    int enif_get_double(
    +
    int enif_get_double(
             ErlNifEnv* env,
             ERL_NIF_TERM term,
    -        double* dp);

    Sets *dp to the floating-point value of term.

    Returns true on success, or false if term is not a float.

    Available since OTP R13B04

    + double* dp);

    Sets *dp to the floating-point value of term.

    Returns true on success, or false if term is not a float.

    Available since OTP R13B04

    enif_get_int()

    -
    int enif_get_int(
    +
    int enif_get_int(
             ErlNifEnv* env,
             ERL_NIF_TERM term,
    -        int* ip);

    Sets *ip to the integer value of term.

    Returns true on success, or false if term is not an integer or is outside + int* ip);

    Sets *ip to the integer value of term.

    Returns true on success, or false if term is not an integer or is outside the bounds of type int.

    enif_get_int64()

    -
    int enif_get_int64(
    +
    int enif_get_int64(
             ErlNifEnv* env,
             ERL_NIF_TERM term,
    -        ErlNifSInt64* ip);

    Sets *ip to the integer value of term.

    Returns true on success, or false if term is not an integer or is outside + ErlNifSInt64* ip);

    Sets *ip to the integer value of term.

    Returns true on success, or false if term is not an integer or is outside the bounds of a signed 64-bit integer.

    Available since OTP R14B

    enif_get_local_pid()

    -
    int enif_get_local_pid(
    +
    int enif_get_local_pid(
             ErlNifEnv* env,
             ERL_NIF_TERM term,
    -        ErlNifPid* pid);

    If term is the pid of a node local process, this function initializes the pid + ErlNifPid* pid);

    If term is the pid of a node local process, this function initializes the pid variable *pid from it and returns true. Otherwise returns false. No check is done to see if the process is alive.

    Note

    enif_get_local_pid will return false if argument term is the atom undefined.

    Available since OTP R14B

    @@ -962,10 +962,10 @@

    enif_get_local_port()

    -
    int enif_get_local_port(
    +
    int enif_get_local_port(
             ErlNifEnv* env,
             ERL_NIF_TERM term,
    -        ErlNifPort* port_id);

    If term identifies a node local port, this function initializes the port + ErlNifPort* port_id);

    If term identifies a node local port, this function initializes the port variable *port_id from it and returns true. Otherwise returns false. No check is done to see if the port is alive.

    Available since OTP 19.0

    @@ -973,60 +973,60 @@

    enif_get_list_cell()

    -
    int enif_get_list_cell(
    +
    int enif_get_list_cell(
             ErlNifEnv* env,
             ERL_NIF_TERM list,
             ERL_NIF_TERM* head,
    -        ERL_NIF_TERM* tail);

    Sets *head and *tail from list list.

    Returns true on success, or false if it is not a list or the list is empty.

    + ERL_NIF_TERM* tail);

    Sets *head and *tail from list list.

    Returns true on success, or false if it is not a list or the list is empty.

    enif_get_list_length()

    -
    int enif_get_list_length(
    +
    int enif_get_list_length(
             ErlNifEnv* env,
             ERL_NIF_TERM term,
    -        unsigned* len);

    Sets *len to the length of list term.

    Returns true on success, or false if term is not a proper list.

    Available since OTP R14B

    + unsigned* len);

    Sets *len to the length of list term.

    Returns true on success, or false if term is not a proper list.

    Available since OTP R14B

    enif_get_long()

    -
    int enif_get_long(
    +
    int enif_get_long(
             ErlNifEnv* env,
             ERL_NIF_TERM term,
    -        long int* ip);

    Sets *ip to the long integer value of term.

    Returns true on success, or false if term is not an integer or is outside + long int* ip);

    Sets *ip to the long integer value of term.

    Returns true on success, or false if term is not an integer or is outside the bounds of type long int.

    Available since OTP R13B04

    enif_get_map_size()

    -
    int enif_get_map_size(
    +
    int enif_get_map_size(
             ErlNifEnv* env,
             ERL_NIF_TERM term,
    -        size_t *size);

    Sets *size to the number of key-value pairs in the map term.

    Returns true on success, or false if term is not a map.

    Available since OTP 18.0

    + size_t *size);

    Sets *size to the number of key-value pairs in the map term.

    Returns true on success, or false if term is not a map.

    Available since OTP 18.0

    enif_get_map_value()

    -
    int enif_get_map_value(
    +
    int enif_get_map_value(
             ErlNifEnv* env,
             ERL_NIF_TERM map,
             ERL_NIF_TERM key,
    -        ERL_NIF_TERM* value);

    Sets *value to the value associated with key in the map map.

    Returns true on success, or false if map is not a map or if map does not + ERL_NIF_TERM* value);

    Sets *value to the value associated with key in the map map.

    Returns true on success, or false if map is not a map or if map does not contain key.

    Available since OTP 18.0

    enif_get_resource()

    -
    int enif_get_resource(
    +
    int enif_get_resource(
             ErlNifEnv* env,
             ERL_NIF_TERM term,
             ErlNifResourceType* type,
    -        void** objp);

    Sets *objp to point to the resource object referred to by term.

    Returns true on success, or false if term is not a handle to a resource + void** objp);

    Sets *objp to point to the resource object referred to by term.

    Returns true on success, or false if term is not a handle to a resource object of type type.

    enif_get_resource does not add a reference to the resource object. However, the pointer received in *objp is guaranteed to be valid at least as long as the resource handle term is valid.

    Available since OTP R13B04

    @@ -1035,12 +1035,12 @@

    enif_get_string()

    -
    int enif_get_string(
    +
    int enif_get_string(
             ErlNifEnv* env,
             ERL_NIF_TERM list,
             char* buf,
             unsigned size,
    -        ErlNifCharEncoding encoding);

    Writes a NULL-terminated string in the buffer pointed to by buf with size + ErlNifCharEncoding encoding);

    Writes a NULL-terminated string in the buffer pointed to by buf with size size, consisting of the characters in the string list. The characters are written using encoding.

    Returns one of the following:

    • The number of bytes written (including terminating NULL character)
    • -size if the string was truncated because of buffer space
    • 0 if list is not a string that can be encoded with encoding or if size was < 1.

    The written string is always NULL-terminated, unless buffer size is < 1.

    Available since OTP R13B04

    @@ -1049,11 +1049,11 @@

    enif_get_string_length()

    -
    int enif_get_string_length(
    +
    int enif_get_string_length(
             ErlNifEnv *env,
             ERL_NIF_TERM list,
             unsigned *len,
    -        ErlNifCharEncoding encoding);

    Sets *len to the length (number of bytes excluding terminating NULL + ErlNifCharEncoding encoding);

    Sets *len to the length (number of bytes excluding terminating NULL character) of the string list with encoding.

    Returns true on success, or false if list is not a string that can be encoded with encoding.

    Available since OTP 26.0

    @@ -1061,11 +1061,11 @@

    enif_get_tuple()

    -
    int enif_get_tuple(
    +
    int enif_get_tuple(
             ErlNifEnv* env,
             ERL_NIF_TERM term,
             int* arity,
    -        const ERL_NIF_TERM** array);

    If term is a tuple, this function sets *array to point to an array + const ERL_NIF_TERM** array);

    If term is a tuple, this function sets *array to point to an array containing the elements of the tuple, and sets *arity to the number of elements. Notice that the array is read-only and (*array)[N-1] is the Nth element of the tuple. *array is undefined if the arity of the tuple is zero.

    Returns true on success, or false if term is not a tuple.

    Available since OTP R13B04

    @@ -1074,48 +1074,48 @@

    enif_get_uint()

    -
    int enif_get_uint(
    +
    int enif_get_uint(
             ErlNifEnv* env,
             ERL_NIF_TERM term,
    -        unsigned int* ip);

    Sets *ip to the unsigned integer value of term.

    Returns true on success, or false if term is not an unsigned integer or is + unsigned int* ip);

    Sets *ip to the unsigned integer value of term.

    Returns true on success, or false if term is not an unsigned integer or is outside the bounds of type unsigned int.

    Available since OTP R13B04

    enif_get_uint64()

    -
    int enif_get_uint64(
    +
    int enif_get_uint64(
             ErlNifEnv* env,
             ERL_NIF_TERM term,
    -        ErlNifUInt64* ip);

    Sets *ip to the unsigned integer value of term.

    Returns true on success, or false if term is not an unsigned integer or is + ErlNifUInt64* ip);

    Sets *ip to the unsigned integer value of term.

    Returns true on success, or false if term is not an unsigned integer or is outside the bounds of an unsigned 64-bit integer.

    Available since OTP R14B

    enif_get_ulong()

    -
    int enif_get_ulong(
    +
    int enif_get_ulong(
             ErlNifEnv* env,
             ERL_NIF_TERM term,
    -        unsigned long* ip);

    Sets *ip to the unsigned long integer value of term.

    Returns true on success, or false if term is not an unsigned integer or is + unsigned long* ip);

    Sets *ip to the unsigned long integer value of term.

    Returns true on success, or false if term is not an unsigned integer or is outside the bounds of type unsigned long.

    enif_getenv()

    -
    int enif_getenv(
    +
    int enif_getenv(
             const char* key,
             char* value,
    -        size_t *value_size);

    Same as erl_drv_getenv.

    Available since OTP 18.2

    + size_t *value_size);

    Same as erl_drv_getenv.

    Available since OTP 18.2

    enif_has_pending_exception()

    -
    int enif_has_pending_exception(
    +
    int enif_has_pending_exception(
             ErlNifEnv* env,
    -        ERL_NIF_TERM* reason);

    Returns true if a pending exception is associated with the environment env. + ERL_NIF_TERM* reason);

    Returns true if a pending exception is associated with the environment env. If reason is a NULL pointer, ignore it. Otherwise, if a pending exception associated with env exists, set *reason to the value of the exception term. For example, if enif_make_badarg is called to @@ -1128,30 +1128,30 @@

    enif_hash()

    -
    ErlNifUInt64 enif_hash(
    +
    ErlNifUInt64 enif_hash(
             ErlNifHash type,
             ERL_NIF_TERM term,
    -        ErlNifUInt64 salt);

    Hashes term according to the specified ErlNifHash + ErlNifUInt64 salt);

    Hashes term according to the specified ErlNifHash type.

    Ranges of taken salt (if any) and returned value depend on the hash type.

    Available since OTP 20.0

    enif_inspect_binary()

    -
    int enif_inspect_binary(
    +
    int enif_inspect_binary(
             ErlNifEnv* env,
             ERL_NIF_TERM bin_term,
    -        ErlNifBinary* bin);

    Initializes the structure pointed to by bin with information about binary term + ErlNifBinary* bin);

    Initializes the structure pointed to by bin with information about binary term bin_term.

    Returns true on success, or false if bin_term is not a binary.

    enif_inspect_iolist_as_binary()

    -
    int enif_inspect_iolist_as_binary(
    +
    int enif_inspect_iolist_as_binary(
             ErlNifEnv* env,
             ERL_NIF_TERM term,
    -        ErlNifBinary* bin);

    Initializes the structure pointed to by bin with a continuous buffer with the + ErlNifBinary* bin);

    Initializes the structure pointed to by bin with a continuous buffer with the same byte content as iolist. As with inspect_binary, the data pointed to by bin is transient and does not need to be released.

    Returns true on success, or false if iolist is not an iolist.

    Available since OTP R13B04

    @@ -1159,23 +1159,23 @@

    enif_inspect_iovec()

    -
    int enif_inspect_iovec(
    +
    int enif_inspect_iovec(
             ErlNifEnv* env,
             size_t max_elements,
             ERL_NIF_TERM iovec_term,
             ERL_NIF_TERM* tail,
    -        ErlNifIOVec** iovec);

    Fills iovec with the list of binaries provided in iovec_term. The number of + ErlNifIOVec** iovec);

    Fills iovec with the list of binaries provided in iovec_term. The number of elements handled in the call is limited to max_elements, and tail is set to the remainder of the list. Note that the output may be longer than max_elements on some platforms.

    To create a list of binaries from an arbitrary iolist, use erlang:iolist_to_iovec/1.

    When calling this function, iovec should contain a pointer to NULL or a ErlNifIOVec structure that should be used if possible. e.g.

    /* Don't use a pre-allocated structure */
     ErlNifIOVec *iovec = NULL;
    -enif_inspect_iovec(env, max_elements, term, &tail, &iovec);
    +enif_inspect_iovec(env, max_elements, term, &tail, &iovec);
     
     /* Use a stack-allocated vector as an optimization for vectors with few elements */
     ErlNifIOVec vec, *iovec = &vec;
    -enif_inspect_iovec(env, max_elements, term, &tail, &iovec);

    The contents of the iovec is valid until the called nif function returns. If +enif_inspect_iovec(env, max_elements, term, &tail, &iovec);

    The contents of the iovec is valid until the called nif function returns. If the iovec should be valid after the nif call returns, it is possible to call this function with a NULL environment. If no environment is given the iovec owns the data in the vector and it has to be explicitly freed using @@ -1185,25 +1185,25 @@

    enif_ioq_create()

    -
    ErlNifIOQueue * enif_ioq_create(
    -        ErlNifIOQueueOpts opts);

    Create a new I/O Queue that can be used to store data. opts has to be set to +

    ErlNifIOQueue * enif_ioq_create(
    +        ErlNifIOQueueOpts opts);

    Create a new I/O Queue that can be used to store data. opts has to be set to ERL_NIF_IOQ_NORMAL.

    Available since OTP 20.1

    enif_ioq_destroy()

    -
    void enif_ioq_destroy(
    -        ErlNifIOQueue *q);

    Destroy the I/O queue and free all of it's contents

    Available since OTP 20.1

    +
    void enif_ioq_destroy(
    +        ErlNifIOQueue *q);

    Destroy the I/O queue and free all of it's contents

    Available since OTP 20.1

    enif_ioq_deq()

    -
    int enif_ioq_deq(
    +
    int enif_ioq_deq(
             ErlNifIOQueue *q,
             size_t count,
    -        size_t *size);

    Dequeue count bytes from the I/O queue. If size is not NULL, the new size + size_t *size);

    Dequeue count bytes from the I/O queue. If size is not NULL, the new size of the queue is placed there.

    Returns true on success, or false if the I/O does not contain count bytes. On failure the queue is left un-altered.

    Available since OTP 20.1

    @@ -1211,10 +1211,10 @@

    enif_ioq_enq_binary()

    -
    int enif_ioq_enq_binary(
    +
    int enif_ioq_enq_binary(
             ErlNifIOQueue *q,
             ErlNifBinary *bin,
    -        size_t skip);

    Enqueue the bin into q skipping the first skip bytes.

    Returns true on success, or false if skip is greater than the size of + size_t skip);

    Enqueue the bin into q skipping the first skip bytes.

    Returns true on success, or false if skip is greater than the size of bin. Any ownership of the binary data is transferred to the queue and bin is to be considered read-only for the rest of the NIF call and then as released.

    Available since OTP 20.1

    @@ -1222,19 +1222,19 @@

    enif_ioq_enqv()

    -
    int enif_ioq_enqv(
    +
    int enif_ioq_enqv(
             ErlNifIOQueue *q,
             ErlNifIOVec *iovec,
    -        size_t skip);

    Enqueue the iovec into q skipping the first skip bytes.

    Returns true on success, or false if skip is greater than the size of + size_t skip);

    Enqueue the iovec into q skipping the first skip bytes.

    Returns true on success, or false if skip is greater than the size of iovec.

    Available since OTP 20.1

    enif_ioq_peek()

    -
    SysIOVec * enif_ioq_peek(
    +
    SysIOVec * enif_ioq_peek(
             ErlNifIOQueue *q,
    -        int *iovlen);

    Get the I/O queue as a pointer to an array of SysIOVecs. It also returns the + int *iovlen);

    Get the I/O queue as a pointer to an array of SysIOVecs. It also returns the number of elements in iovlen.

    Nothing is removed from the queue by this function, that must be done with enif_ioq_deq.

    The returned array is suitable to use with the Unix system call writev.

    Available since OTP 20.1

    @@ -1242,42 +1242,42 @@

    enif_ioq_peek_head()

    -
    int enif_ioq_peek_head(
    +
    int enif_ioq_peek_head(
             ErlNifEnv *env,
             ErlNifIOQueue *q,
             size_t *size,
    -        ERL_NIF_TERM *bin_term);

    Get the head of the IO Queue as a binary term.

    If size is not NULL, the size of the head is placed there.

    Nothing is removed from the queue by this function, that must be done with + ERL_NIF_TERM *bin_term);

    Get the head of the IO Queue as a binary term.

    If size is not NULL, the size of the head is placed there.

    Nothing is removed from the queue by this function, that must be done with enif_ioq_deq.

    Returns true on success, or false if the queue is empty.

    Available since OTP 21.0

    enif_ioq_size()

    -
    size_t enif_ioq_size(
    -        ErlNifIOQueue *q);

    Get the size of q.

    Available since OTP 20.1

    +
    size_t enif_ioq_size(
    +        ErlNifIOQueue *q);

    Get the size of q.

    Available since OTP 20.1

    enif_is_atom()

    -
    int enif_is_atom(
    +
    int enif_is_atom(
             ErlNifEnv* env,
    -        ERL_NIF_TERM term);

    Returns true if term is an atom.

    Available since OTP R13B04

    + ERL_NIF_TERM term);

    Returns true if term is an atom.

    Available since OTP R13B04

    enif_is_binary()

    -
    int enif_is_binary(
    +
    int enif_is_binary(
             ErlNifEnv* env,
    -        ERL_NIF_TERM term);

    Returns true if term is a binary.

    + ERL_NIF_TERM term);

    Returns true if term is a binary.

    enif_is_current_process_alive()

    -
    int enif_is_current_process_alive(
    -        ErlNifEnv* env);

    Returns true if the currently executing process is currently alive, otherwise +

    int enif_is_current_process_alive(
    +        ErlNifEnv* env);

    Returns true if the currently executing process is currently alive, otherwise false.

    This function can only be used from a NIF-calling thread, and with an environment corresponding to currently executing processes.

    Available since OTP 19.0

    @@ -1285,121 +1285,121 @@

    enif_is_empty_list()

    -
    int enif_is_empty_list(
    +
    int enif_is_empty_list(
             ErlNifEnv* env,
    -        ERL_NIF_TERM term);

    Returns true if term is an empty list.

    Available since OTP R13B04

    + ERL_NIF_TERM term);

    Returns true if term is an empty list.

    Available since OTP R13B04

    enif_is_exception()

    -
    int enif_is_exception(
    +
    int enif_is_exception(
             ErlNifEnv* env,
    -        ERL_NIF_TERM term);

    Return true if term is an exception.

    Available since OTP R14B03

    + ERL_NIF_TERM term);

    Return true if term is an exception.

    Available since OTP R14B03

    enif_is_fun()

    -
    int enif_is_fun(
    +
    int enif_is_fun(
             ErlNifEnv* env,
    -        ERL_NIF_TERM term);

    Returns true if term is a fun.

    Available since OTP R13B04

    + ERL_NIF_TERM term);

    Returns true if term is a fun.

    Available since OTP R13B04

    enif_is_identical()

    -
    int enif_is_identical(
    +
    int enif_is_identical(
             ERL_NIF_TERM lhs,
    -        ERL_NIF_TERM rhs);

    Returns true if the two terms are identical. Corresponds to the Erlang + ERL_NIF_TERM rhs);

    Returns true if the two terms are identical. Corresponds to the Erlang operators =:= and =/=.

    Available since OTP R13B04

    enif_is_list()

    -
    int enif_is_list(
    +
    int enif_is_list(
             ErlNifEnv* env,
    -        ERL_NIF_TERM term);

    Returns true if term is a list.

    Available since OTP R14B

    + ERL_NIF_TERM term);

    Returns true if term is a list.

    Available since OTP R14B

    enif_is_map()

    -
    int enif_is_map(
    +
    int enif_is_map(
             ErlNifEnv* env,
    -        ERL_NIF_TERM term);

    Returns true if term is a map, otherwise false.

    Available since OTP 18.0

    + ERL_NIF_TERM term);

    Returns true if term is a map, otherwise false.

    Available since OTP 18.0

    enif_is_number()

    -
    int enif_is_number(
    +
    int enif_is_number(
             ErlNifEnv* env,
    -        ERL_NIF_TERM term);

    Returns true if term is a number.

    Available since OTP R15B

    + ERL_NIF_TERM term);

    Returns true if term is a number.

    Available since OTP R15B

    enif_is_pid()

    -
    int enif_is_pid(
    +
    int enif_is_pid(
             ErlNifEnv* env,
    -        ERL_NIF_TERM term);

    Returns true if term is a pid.

    Available since OTP R13B04

    + ERL_NIF_TERM term);

    Returns true if term is a pid.

    Available since OTP R13B04

    enif_is_pid_undefined()

    -
    int enif_is_pid_undefined(
    -        const ErlNifPid* pid);

    Returns true if pid has been set as undefined by +

    int enif_is_pid_undefined(
    +        const ErlNifPid* pid);

    Returns true if pid has been set as undefined by enif_set_pid_undefined .

    Available since OTP 22.0

    enif_is_port()

    -
    int enif_is_port(
    +
    int enif_is_port(
             ErlNifEnv* env,
    -        ERL_NIF_TERM term);

    Returns true if term is a port.

    Available since OTP R13B04

    + ERL_NIF_TERM term);

    Returns true if term is a port.

    Available since OTP R13B04

    enif_is_port_alive()

    -
    int enif_is_port_alive(
    +
    int enif_is_port_alive(
             ErlNifEnv* env,
    -        ErlNifPort *port_id);

    Returns true if port_id is alive.

    This function is thread-safe.

    Available since OTP 19.0

    + ErlNifPort *port_id);

    Returns true if port_id is alive.

    This function is thread-safe.

    Available since OTP 19.0

    enif_is_process_alive()

    -
    int enif_is_process_alive(
    +
    int enif_is_process_alive(
             ErlNifEnv* env,
    -        ErlNifPid *pid);

    Returns true if pid is alive.

    This function is thread-safe.

    Available since OTP 19.0

    + ErlNifPid *pid);

    Returns true if pid is alive.

    This function is thread-safe.

    Available since OTP 19.0

    enif_is_ref()

    -
    int enif_is_ref(
    +
    int enif_is_ref(
             ErlNifEnv* env,
    -        ERL_NIF_TERM term);

    Returns true if term is a reference.

    Available since OTP R13B04

    + ERL_NIF_TERM term);

    Returns true if term is a reference.

    Available since OTP R13B04

    enif_is_tuple()

    -
    int enif_is_tuple(
    +
    int enif_is_tuple(
             ErlNifEnv* env,
    -        ERL_NIF_TERM term);

    Returns true if term is a tuple.

    Available since OTP R14B

    + ERL_NIF_TERM term);

    Returns true if term is a tuple.

    Available since OTP R14B

    enif_keep_resource()

    -
    int enif_keep_resource(
    -        void* obj);

    Adds a reference to resource object obj obtained from +

    int enif_keep_resource(
    +        void* obj);

    Adds a reference to resource object obj obtained from enif_alloc_resource. Each call to enif_keep_resource for an object must be balanced by a call to enif_release_resource before the object is @@ -1409,9 +1409,9 @@

    enif_make_atom()

    -
    ERL_NIF_TERM enif_make_atom(
    +
    ERL_NIF_TERM enif_make_atom(
             ErlNifEnv *env,
    -        const char *name);

    Creates an atom term from the NULL-terminated C-string name with ISO + const char *name);

    Creates an atom term from the NULL-terminated C-string name with ISO Latin-1 encoding. If the length of name exceeds the maximum length allowed for an atom (255 characters), enif_make_atom invokes enif_make_badarg.

    @@ -1420,10 +1420,10 @@

    enif_make_atom_len()

    -
    ERL_NIF_TERM enif_make_atom_len(
    +
    ERL_NIF_TERM enif_make_atom_len(
             ErlNifEnv *env,
             const char *name,
    -        size_t len);

    Create an atom term from the string name with length len and ISO Latin-1 + size_t len);

    Create an atom term from the string name with length len and ISO Latin-1 encoding. NULL characters are treated as any other characters. If len exceeds the maximum length allowed for an atom (255 characters), enif_make_atom invokes enif_make_badarg .

    Available since OTP R14B

    @@ -1432,8 +1432,8 @@

    enif_make_badarg()

    -
    ERL_NIF_TERM enif_make_badarg(
    -        ErlNifEnv* env);

    Makes a badarg exception to be returned from a NIF, and associates it with +

    ERL_NIF_TERM enif_make_badarg(
    +        ErlNifEnv* env);

    Makes a badarg exception to be returned from a NIF, and associates it with environment env. Once a NIF or any function it calls invokes enif_make_badarg, the runtime ensures that a badarg exception is raised when the NIF returns, even if the NIF attempts to return a non-exception term @@ -1449,9 +1449,9 @@

    enif_make_binary()

    -
    ERL_NIF_TERM enif_make_binary(
    +
    ERL_NIF_TERM enif_make_binary(
             ErlNifEnv* env,
    -        ErlNifBinary* bin);

    Makes a binary term from bin. Any ownership of the binary data is transferred + ErlNifBinary* bin);

    Makes a binary term from bin. Any ownership of the binary data is transferred to the created term and bin is to be considered read-only for the rest of the NIF call and then as released.

    @@ -1459,18 +1459,18 @@

    enif_make_copy()

    -
    ERL_NIF_TERM enif_make_copy(
    +
    ERL_NIF_TERM enif_make_copy(
             ErlNifEnv* dst_env,
    -        ERL_NIF_TERM src_term);

    Makes a copy of term src_term. The copy is created in environment dst_env. + ERL_NIF_TERM src_term);

    Makes a copy of term src_term. The copy is created in environment dst_env. The source term can be located in any environment.

    Available since OTP R14B

    enif_make_double()

    -
    ERL_NIF_TERM enif_make_double(
    +
    ERL_NIF_TERM enif_make_double(
             ErlNifEnv* env,
    -        double d);

    Creates a floating-point term from a double. If argument double is not + double d);

    Creates a floating-point term from a double. If argument double is not finite or is NaN, enif_make_double invokes enif_make_badarg.

    Available since OTP R13B04

    @@ -1478,11 +1478,11 @@

    enif_make_existing_atom()

    -
    int enif_make_existing_atom(
    +
    int enif_make_existing_atom(
             ErlNifEnv *env,
             const char *name,
             ERL_NIF_TERM *atom,
    -        ErlNifCharEncoding encoding);

    Tries to create the term of an already existing atom from the NULL-terminated + ErlNifCharEncoding encoding);

    Tries to create the term of an already existing atom from the NULL-terminated C-string name with encoding.

    If the atom already exists, this function stores the term in *atom and returns true, otherwise returns false. It also returns false if the string name exceeds the maximum length allowed for an atom (255 characters) or if name is @@ -1492,12 +1492,12 @@

    enif_make_existing_atom_len()

    -
    int enif_make_existing_atom_len(
    +
    int enif_make_existing_atom_len(
             ErlNifEnv *env,
             const char *name,
             size_t len,
             ERL_NIF_TERM *atom,
    -        ErlNifCharEncoding encoding);

    Tries to create the term of an already existing atom from the string name with + ErlNifCharEncoding encoding);

    Tries to create the term of an already existing atom from the string name with length len bytes and encoding. NULL characters are treated as any other characters.

    If the atom already exists, this function stores the term in *atom and returns true, otherwise returns false. It also returns false if the string name @@ -1508,26 +1508,26 @@

    enif_make_int()

    -
    ERL_NIF_TERM enif_make_int(
    +
    ERL_NIF_TERM enif_make_int(
             ErlNifEnv* env,
    -        int i);

    Creates an integer term.

    + int i);

    Creates an integer term.

    enif_make_int64()

    -
    ERL_NIF_TERM enif_make_int64(
    +
    ERL_NIF_TERM enif_make_int64(
             ErlNifEnv* env,
    -        ErlNifSInt64 i);

    Creates an integer term from a signed 64-bit integer.

    Available since OTP R14B

    + ErlNifSInt64 i);

    Creates an integer term from a signed 64-bit integer.

    Available since OTP R14B

    enif_make_list()

    -
    ERL_NIF_TERM enif_make_list(
    +
    ERL_NIF_TERM enif_make_list(
             ErlNifEnv* env,
             unsigned cnt,
    -        ...);

    Creates an ordinary list term of length cnt. Expects cnt number of arguments + ...);

    Creates an ordinary list term of length cnt. Expects cnt number of arguments (after cnt) of type ERL_NIF_TERM as the elements of the list.

    Returns an empty list if cnt is 0.

    @@ -1582,25 +1582,25 @@

    enif_make_list9()

    -
    ERL_NIF_TERM enif_make_list1(
    +
    ERL_NIF_TERM enif_make_list1(
             ErlNifEnv* env,
    -        ERL_NIF_TERM e1);
    ERL_NIF_TERM enif_make_list2(
    +        ERL_NIF_TERM e1);
    ERL_NIF_TERM enif_make_list2(
             ErlNifEnv* env,
    -        ERL_NIF_TERM e1, ERL_NIF_TERM e2);
    ERL_NIF_TERM enif_make_list3(
    +        ERL_NIF_TERM e1, ERL_NIF_TERM e2);
    ERL_NIF_TERM enif_make_list3(
             ErlNifEnv* env,
    -        ERL_NIF_TERM e1, ERL_NIF_TERM e2, ERL_NIF_TERM e3);
    ERL_NIF_TERM enif_make_list4(
    +        ERL_NIF_TERM e1, ERL_NIF_TERM e2, ERL_NIF_TERM e3);
    ERL_NIF_TERM enif_make_list4(
             ErlNifEnv* env,
    -        ERL_NIF_TERM e1, ..., ERL_NIF_TERM e4);
    ERL_NIF_TERM enif_make_list5(
    +        ERL_NIF_TERM e1, ..., ERL_NIF_TERM e4);
    ERL_NIF_TERM enif_make_list5(
             ErlNifEnv* env,
    -        ERL_NIF_TERM e1, ..., ERL_NIF_TERM e5);
    ERL_NIF_TERM enif_make_list6(
    +        ERL_NIF_TERM e1, ..., ERL_NIF_TERM e5);
    ERL_NIF_TERM enif_make_list6(
             ErlNifEnv* env,
    -        ERL_NIF_TERM e1, ..., ERL_NIF_TERM e6);
    ERL_NIF_TERM enif_make_list7(
    +        ERL_NIF_TERM e1, ..., ERL_NIF_TERM e6);
    ERL_NIF_TERM enif_make_list7(
             ErlNifEnv* env,
    -        ERL_NIF_TERM e1, ..., ERL_NIF_TERM e7);
    ERL_NIF_TERM enif_make_list8(
    +        ERL_NIF_TERM e1, ..., ERL_NIF_TERM e7);
    ERL_NIF_TERM enif_make_list8(
             ErlNifEnv* env,
    -        ERL_NIF_TERM e1, ..., ERL_NIF_TERM e8);
    ERL_NIF_TERM enif_make_list9(
    +        ERL_NIF_TERM e1, ..., ERL_NIF_TERM e8);
    ERL_NIF_TERM enif_make_list9(
             ErlNifEnv* env,
    -        ERL_NIF_TERM e1, ..., ERL_NIF_TERM e9);

    Creates an ordinary list term with length indicated by the function name. Prefer + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e9);

    Creates an ordinary list term with length indicated by the function name. Prefer these functions (macros) over the variadic enif_make_list to get a compile-time error if the number of arguments does not match.

    Available since OTP R13B04

    @@ -1608,38 +1608,38 @@

    enif_make_list_cell()

    -
    ERL_NIF_TERM enif_make_list_cell(
    +
    ERL_NIF_TERM enif_make_list_cell(
             ErlNifEnv* env,
             ERL_NIF_TERM head,
    -        ERL_NIF_TERM tail);

    Creates a list cell [head | tail].

    + ERL_NIF_TERM tail);

    Creates a list cell [head | tail].

    enif_make_list_from_array()

    -
    ERL_NIF_TERM enif_make_list_from_array(
    +
    ERL_NIF_TERM enif_make_list_from_array(
             ErlNifEnv* env,
    -        const ERL_NIF_TERM arr[],
    -        unsigned cnt);

    Creates an ordinary list containing the elements of array arr of length cnt.

    Returns an empty list if cnt is 0.

    Available since OTP R13B04

    + const ERL_NIF_TERM arr[], + unsigned cnt);

    Creates an ordinary list containing the elements of array arr of length cnt.

    Returns an empty list if cnt is 0.

    Available since OTP R13B04

    enif_make_long()

    -
    ERL_NIF_TERM enif_make_long(
    +
    ERL_NIF_TERM enif_make_long(
             ErlNifEnv* env,
    -        long int i);

    Creates an integer term from a long int.

    Available since OTP R13B04

    + long int i);

    Creates an integer term from a long int.

    Available since OTP R13B04

    enif_make_map_put()

    -
    int enif_make_map_put(
    +
    int enif_make_map_put(
             ErlNifEnv* env,
             ERL_NIF_TERM map_in,
             ERL_NIF_TERM key,
             ERL_NIF_TERM value,
    -        ERL_NIF_TERM* map_out);

    Makes a copy of map map_in and inserts key with value. If key already + ERL_NIF_TERM* map_out);

    Makes a copy of map map_in and inserts key with value. If key already exists in map_in, the old associated value is replaced by value.

    If successful, this function sets *map_out to the new map and returns true. Returns false if map_in is not a map.

    The map_in term must belong to environment env.

    Available since OTP 18.0

    @@ -1647,11 +1647,11 @@

    enif_make_map_remove()

    -
    int enif_make_map_remove(
    +
    int enif_make_map_remove(
             ErlNifEnv* env,
             ERL_NIF_TERM map_in,
             ERL_NIF_TERM key,
    -        ERL_NIF_TERM* map_out);

    If map map_in contains key, this function makes a copy of map_in in + ERL_NIF_TERM* map_out);

    If map map_in contains key, this function makes a copy of map_in in *map_out, and removes key and the associated value. If map map_in does not contain key, *map_out is set to map_in.

    Returns true on success, or false if map_in is not a map.

    The map_in term must belong to environment env.

    Available since OTP 18.0

    @@ -1659,12 +1659,12 @@

    enif_make_map_update()

    -
    int enif_make_map_update(
    +
    int enif_make_map_update(
             ErlNifEnv* env,
             ERL_NIF_TERM map_in,
             ERL_NIF_TERM key,
             ERL_NIF_TERM new_value,
    -        ERL_NIF_TERM* map_out);

    Makes a copy of map map_in and replace the old associated value for key with + ERL_NIF_TERM* map_out);

    Makes a copy of map map_in and replace the old associated value for key with new_value.

    If successful, this function sets *map_out to the new map and returns true. Returns false if map_in is not a map or if it does not contain key.

    The map_in term must belong to environment env.

    Available since OTP 18.0

    @@ -1672,32 +1672,32 @@

    enif_make_map_from_arrays()

    -
    int enif_make_map_from_arrays(
    +
    int enif_make_map_from_arrays(
             ErlNifEnv* env,
    -        ERL_NIF_TERM keys[],
    -        ERL_NIF_TERM values[],
    +        ERL_NIF_TERM keys[],
    +        ERL_NIF_TERM values[],
             size_t cnt,
    -        ERL_NIF_TERM *map_out);

    Makes a map term from the given keys and values.

    If successful, this function sets *map_out to the new map and returns true. + ERL_NIF_TERM *map_out);

    Makes a map term from the given keys and values.

    If successful, this function sets *map_out to the new map and returns true. Returns false there are any duplicate keys.

    All keys and values must belong to env.

    Available since OTP 21.0

    enif_make_monitor_term()

    -
    ERL_NIF_TERM enif_make_monitor_term(
    +
    ERL_NIF_TERM enif_make_monitor_term(
             ErlNifEnv* env,
    -        const ErlNifMonitor* mon);

    Creates a term identifying the given monitor received from + const ErlNifMonitor* mon);

    Creates a term identifying the given monitor received from enif_monitor_process .

    This function is primarily intended for debugging purpose.

    Available since OTP 22.0

    enif_make_new_atom()

    -
    int enif_make_new_atom(
    +
    int enif_make_new_atom(
             ErlNifEnv *env,
             const char *name,
             ERL_NIF_TERM *atom,
    -        ErlNifCharEncoding encoding);

    Creates an atom term from the NULL-terminated C-string name with + ErlNifCharEncoding encoding);

    Creates an atom term from the NULL-terminated C-string name with encoding.

    If successful, true is returned and the atom term is stored in *atom.

    Otherwise, false is returned if the length of name exceeds the maximum length allowed for an atom (255 characters) or if name is not correctly encoded.

    Available since OTP 26.0

    @@ -1706,12 +1706,12 @@

    enif_make_new_atom_len()

    -
    int enif_make_new_atom_len(
    +
    int enif_make_new_atom_len(
             ErlNifEnv *env,
             const char *name,
             size_t len,
             ERL_NIF_TERM *atom,
    -        ErlNifCharEncoding encoding);

    Create an atom term from string name with length len bytes and + ErlNifCharEncoding encoding);

    Create an atom term from string name with length len bytes and encoding.

    If successful, true is returned and atom term is stored in *atom.

    Otherwise, false is returned if the string exceeds the maximum length allowed for an atom (255 characters) or if the string is not correctly encoded.

    Available since OTP 26.0

    @@ -1719,10 +1719,10 @@

    enif_make_new_binary()

    -
    unsigned char * enif_make_new_binary(
    +
    unsigned char * enif_make_new_binary(
     	 ErlNifEnv* env,
     	 size_t size,
    -	 ERL_NIF_TERM* termp);

    Allocates a binary of size size bytes and creates an owning term. The binary + ERL_NIF_TERM* termp);

    Allocates a binary of size size bytes and creates an owning term. The binary data is mutable until the calling NIF returns. This is a quick way to create a new binary without having to use ErlNifBinary. The drawbacks are that the binary cannot be kept between NIF calls and it cannot be @@ -1732,32 +1732,32 @@

    enif_make_new_map()

    -
    ERL_NIF_TERM enif_make_new_map(
    -        ErlNifEnv* env);

    Makes an empty map term.

    Available since OTP 18.0

    +
    ERL_NIF_TERM enif_make_new_map(
    +        ErlNifEnv* env);

    Makes an empty map term.

    Available since OTP 18.0

    enif_make_pid()

    -
    ERL_NIF_TERM enif_make_pid(
    +
    ERL_NIF_TERM enif_make_pid(
             ErlNifEnv* env,
    -        const ErlNifPid* pid);

    Makes a pid term or the atom undefined + const ErlNifPid* pid);

    Makes a pid term or the atom undefined from *pid.

    Available since OTP R14B

    enif_make_ref()

    -
    ERL_NIF_TERM enif_make_ref(
    -        ErlNifEnv* env);

    Creates a reference like erlang:make_ref/0.

    Available since OTP R13B04

    +
    ERL_NIF_TERM enif_make_ref(
    +        ErlNifEnv* env);

    Creates a reference like erlang:make_ref/0.

    Available since OTP R13B04

    enif_make_resource()

    -
    ERL_NIF_TERM enif_make_resource(
    +
    ERL_NIF_TERM enif_make_resource(
             ErlNifEnv* env,
    -        void* obj);

    Creates an opaque handle to a memory-managed resource object obtained by + void* obj);

    Creates an opaque handle to a memory-managed resource object obtained by enif_alloc_resource. No ownership transfer is done, as the resource object still needs to be released by enif_release_resource. However, notice @@ -1784,11 +1784,11 @@

    enif_make_resource_binary()

    -
    ERL_NIF_TERM enif_make_resource_binary(
    +
    ERL_NIF_TERM enif_make_resource_binary(
             ErlNifEnv* env,
             void* obj,
             const void* data,
    -        size_t size);

    Creates a binary term that is memory-managed by a resource object obj obtained + size_t size);

    Creates a binary term that is memory-managed by a resource object obj obtained by enif_alloc_resource. The returned binary term consists of size bytes pointed to by data. This raw binary data must be kept readable and unchanged until the destructor of the resource is called. The @@ -1803,10 +1803,10 @@

    enif_make_reverse_list()

    -
    int enif_make_reverse_list(
    +
    int enif_make_reverse_list(
             ErlNifEnv* env,
             ERL_NIF_TERM list_in,
    -        ERL_NIF_TERM *list_out);

    Sets *list_out to the reverse list of the list list_in and returns true, + ERL_NIF_TERM *list_out);

    Sets *list_out to the reverse list of the list list_in and returns true, or returns false if list_in is not a list.

    This function is only to be used on short lists, as a copy is created of the list, which is not released until after the NIF returns.

    The list_in term must belong to environment env.

    Available since OTP R15B

    @@ -1814,21 +1814,21 @@

    enif_make_string()

    -
    ERL_NIF_TERM enif_make_string(
    +
    ERL_NIF_TERM enif_make_string(
             ErlNifEnv *env,
             const char *string,
    -        ErlNifCharEncoding encoding);

    Creates a list containing the characters of the NULL-terminated string + ErlNifCharEncoding encoding);

    Creates a list containing the characters of the NULL-terminated string string with encoding.

    enif_make_string_len()

    -
    ERL_NIF_TERM enif_make_string_len(
    +
    ERL_NIF_TERM enif_make_string_len(
             ErlNifEnv *env,
             const char *string,
             size_t len,
    -        ErlNifCharEncoding encoding);

    Creates a list containing the characters of the string string with length + ErlNifCharEncoding encoding);

    Creates a list containing the characters of the string string with length len and encoding. NULL characters are treated as any other characters.

    Available since OTP R14B

    @@ -1836,11 +1836,11 @@

    enif_make_sub_binary()

    -
    ERL_NIF_TERM enif_make_sub_binary(
    +
    ERL_NIF_TERM enif_make_sub_binary(
             ErlNifEnv* env,
             ERL_NIF_TERM bin_term,
             size_t pos,
    -        size_t size);

    Makes a subbinary of binary bin_term, starting at zero-based position pos + size_t size);

    Makes a subbinary of binary bin_term, starting at zero-based position pos with a length of size bytes. bin_term must be a binary or bitstring. pos+size must be less or equal to the number of whole bytes in bin_term.

    Available since OTP R13B04

    @@ -1848,10 +1848,10 @@

    enif_make_tuple()

    -
    ERL_NIF_TERM enif_make_tuple(
    +
    ERL_NIF_TERM enif_make_tuple(
             ErlNifEnv* env,
             unsigned cnt,
    -        ...);

    Creates a tuple term of arity cnt. Expects cnt number of arguments (after + ...);

    Creates a tuple term of arity cnt. Expects cnt number of arguments (after cnt) of type ERL_NIF_TERM as the elements of the tuple.

    @@ -1906,25 +1906,25 @@

    enif_make_tuple9()

    -
    ERL_NIF_TERM enif_make_tuple1(
    +
    ERL_NIF_TERM enif_make_tuple1(
             ErlNifEnv* env,
    -        ERL_NIF_TERM e1);
    ERL_NIF_TERM enif_make_tuple2(
    +        ERL_NIF_TERM e1);
    ERL_NIF_TERM enif_make_tuple2(
             ErlNifEnv* env,
    -        ERL_NIF_TERM e1, ERL_NIF_TERM e2);
    ERL_NIF_TERM enif_make_tuple3(
    +        ERL_NIF_TERM e1, ERL_NIF_TERM e2);
    ERL_NIF_TERM enif_make_tuple3(
             ErlNifEnv* env,
    -        ERL_NIF_TERM e1, ERL_NIF_TERM e2, ERL_NIF_TERM e3);
    ERL_NIF_TERM enif_make_tuple4(
    +        ERL_NIF_TERM e1, ERL_NIF_TERM e2, ERL_NIF_TERM e3);
    ERL_NIF_TERM enif_make_tuple4(
             ErlNifEnv* env,
    -        ERL_NIF_TERM e1, ..., ERL_NIF_TERM e4);
    ERL_NIF_TERM enif_make_tuple5(
    +        ERL_NIF_TERM e1, ..., ERL_NIF_TERM e4);
    ERL_NIF_TERM enif_make_tuple5(
             ErlNifEnv* env,
    -        ERL_NIF_TERM e1, ..., ERL_NIF_TERM e5);
    ERL_NIF_TERM enif_make_tuple6(
    +        ERL_NIF_TERM e1, ..., ERL_NIF_TERM e5);
    ERL_NIF_TERM enif_make_tuple6(
             ErlNifEnv* env,
    -        ERL_NIF_TERM e1, ..., ERL_NIF_TERM e6);
    ERL_NIF_TERM enif_make_tuple7(
    +        ERL_NIF_TERM e1, ..., ERL_NIF_TERM e6);
    ERL_NIF_TERM enif_make_tuple7(
             ErlNifEnv* env,
    -        ERL_NIF_TERM e1, ..., ERL_NIF_TERM e7);
    ERL_NIF_TERM enif_make_tuple8(
    +        ERL_NIF_TERM e1, ..., ERL_NIF_TERM e7);
    ERL_NIF_TERM enif_make_tuple8(
             ErlNifEnv* env,
    -        ERL_NIF_TERM e1, ..., ERL_NIF_TERM e8);
    ERL_NIF_TERM enif_make_tuple9(
    +        ERL_NIF_TERM e1, ..., ERL_NIF_TERM e8);
    ERL_NIF_TERM enif_make_tuple9(
             ErlNifEnv* env,
    -        ERL_NIF_TERM e1, ..., ERL_NIF_TERM e9);

    Creates a tuple term with length indicated by the function name. Prefer these + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e9);

    Creates a tuple term with length indicated by the function name. Prefer these functions (macros) over the variadic enif_make_tuple to get a compile-time error if the number of arguments does not match.

    Available since OTP R13B04

    @@ -1932,42 +1932,42 @@

    enif_make_tuple_from_array()

    -
    ERL_NIF_TERM enif_make_tuple_from_array(
    +
    ERL_NIF_TERM enif_make_tuple_from_array(
             ErlNifEnv* env,
    -        const ERL_NIF_TERM arr[],
    -        unsigned cnt);

    Creates a tuple containing the elements of array arr of length cnt.

    Available since OTP R13B04

    + const ERL_NIF_TERM arr[], + unsigned cnt);

    Creates a tuple containing the elements of array arr of length cnt.

    Available since OTP R13B04

    enif_make_uint()

    -
    ERL_NIF_TERM enif_make_uint(
    +
    ERL_NIF_TERM enif_make_uint(
             ErlNifEnv* env,
    -        unsigned int i);

    Creates an integer term from an unsigned int.

    Available since OTP R13B04

    + unsigned int i);

    Creates an integer term from an unsigned int.

    Available since OTP R13B04

    enif_make_uint64()

    -
    ERL_NIF_TERM enif_make_uint64(
    +
    ERL_NIF_TERM enif_make_uint64(
             ErlNifEnv* env,
    -        ErlNifUInt64 i);

    Creates an integer term from an unsigned 64-bit integer.

    Available since OTP R14B

    + ErlNifUInt64 i);

    Creates an integer term from an unsigned 64-bit integer.

    Available since OTP R14B

    enif_make_ulong()

    -
    ERL_NIF_TERM enif_make_ulong(
    +
    ERL_NIF_TERM enif_make_ulong(
             ErlNifEnv* env,
    -        unsigned long i);

    Creates an integer term from an unsigned long int.

    + unsigned long i);

    Creates an integer term from an unsigned long int.

    enif_make_unique_integer()

    -
    ERL_NIF_TERM enif_make_unique_integer(
    +
    ERL_NIF_TERM enif_make_unique_integer(
             ErlNifEnv *env,
    -        ErlNifUniqueInteger properties);

    Returns a unique integer with the same properties as specified by + ErlNifUniqueInteger properties);

    Returns a unique integer with the same properties as specified by erlang:unique_integer/1.

    env is the environment to create the integer in.

    ERL_NIF_UNIQUE_POSITIVE and ERL_NIF_UNIQUE_MONOTONIC can be passed as the second argument to change the properties of the integer returned. They can be combined by OR:ing the two values together.

    See also ErlNifUniqueInteger.

    Available since OTP 19.0

    @@ -1976,23 +1976,23 @@

    enif_map_iterator_create()

    -
    int enif_map_iterator_create(
    +
    int enif_map_iterator_create(
             ErlNifEnv *env,
             ERL_NIF_TERM map,
             ErlNifMapIterator *iter,
    -        ErlNifMapIteratorEntry entry);

    Creates an iterator for the map map by initializing the structure pointed to + ErlNifMapIteratorEntry entry);

    Creates an iterator for the map map by initializing the structure pointed to by iter. Argument entry determines the start position of the iterator: ERL_NIF_MAP_ITERATOR_FIRST or ERL_NIF_MAP_ITERATOR_LAST.

    Returns true on success, or false if map is not a map.

    A map iterator is only useful during the lifetime of environment env that the map belongs to. The iterator must be destroyed by calling enif_map_iterator_destroy:

    ERL_NIF_TERM key, value;
     ErlNifMapIterator iter;
    -enif_map_iterator_create(env, my_map, &iter, ERL_NIF_MAP_ITERATOR_FIRST);
    +enif_map_iterator_create(env, my_map, &iter, ERL_NIF_MAP_ITERATOR_FIRST);
     
    -while (enif_map_iterator_get_pair(env, &iter, &key, &value)) {
    -    do_something(key,value);
    -    enif_map_iterator_next(env, &iter);
    -}
    -enif_map_iterator_destroy(env, &iter);

    Note

    The key-value pairs of a map have no defined iteration order. The only +while (enif_map_iterator_get_pair(env, &iter, &key, &value)) { + do_something(key,value); + enif_map_iterator_next(env, &iter); +} +enif_map_iterator_destroy(env, &iter);

    Note

    The key-value pairs of a map have no defined iteration order. The only guarantee is that the iteration order of a single map instance is preserved during the lifetime of the environment that the map belongs to.

    Available since OTP 18.0

    @@ -2000,65 +2000,65 @@

    enif_map_iterator_destroy()

    -
    void enif_map_iterator_destroy(
    +
    void enif_map_iterator_destroy(
             ErlNifEnv *env,
    -        ErlNifMapIterator *iter);

    Destroys a map iterator created by + ErlNifMapIterator *iter);

    Destroys a map iterator created by enif_map_iterator_create.

    Available since OTP 18.0

    enif_map_iterator_get_pair()

    -
    int enif_map_iterator_get_pair(
    +
    int enif_map_iterator_get_pair(
             ErlNifEnv *env,
             ErlNifMapIterator *iter,
             ERL_NIF_TERM *key,
    -        ERL_NIF_TERM *value);

    Gets key and value terms at the current map iterator position.

    On success, sets *key and *value and returns true. Returns false if the + ERL_NIF_TERM *value);

    Gets key and value terms at the current map iterator position.

    On success, sets *key and *value and returns true. Returns false if the iterator is positioned at head (before first entry) or tail (beyond last entry).

    Available since OTP 18.0

    enif_map_iterator_is_head()

    -
    int enif_map_iterator_is_head(
    +
    int enif_map_iterator_is_head(
             ErlNifEnv *env,
    -        ErlNifMapIterator *iter);

    Returns true if map iterator iter is positioned before the first entry.

    Available since OTP 18.0

    + ErlNifMapIterator *iter);

    Returns true if map iterator iter is positioned before the first entry.

    Available since OTP 18.0

    enif_map_iterator_is_tail()

    -
    int enif_map_iterator_is_tail(
    +
    int enif_map_iterator_is_tail(
             ErlNifEnv *env,
    -        ErlNifMapIterator *iter);

    Returns true if map iterator iter is positioned after the last entry.

    Available since OTP 18.0

    + ErlNifMapIterator *iter);

    Returns true if map iterator iter is positioned after the last entry.

    Available since OTP 18.0

    enif_map_iterator_next()

    -
    int enif_map_iterator_next(
    +
    int enif_map_iterator_next(
             ErlNifEnv *env,
    -        ErlNifMapIterator *iter);

    Increments map iterator to point to the next key-value entry.

    Returns true if the iterator is now positioned at a valid key-value entry, or + ErlNifMapIterator *iter);

    Increments map iterator to point to the next key-value entry.

    Returns true if the iterator is now positioned at a valid key-value entry, or false if the iterator is positioned at the tail (beyond the last entry).

    Available since OTP 18.0

    enif_map_iterator_prev()

    -
    int enif_map_iterator_prev(
    +
    int enif_map_iterator_prev(
             ErlNifEnv *env,
    -        ErlNifMapIterator *iter);

    Decrements map iterator to point to the previous key-value entry.

    Returns true if the iterator is now positioned at a valid key-value entry, or + ErlNifMapIterator *iter);

    Decrements map iterator to point to the previous key-value entry.

    Returns true if the iterator is now positioned at a valid key-value entry, or false if the iterator is positioned at the head (before the first entry).

    Available since OTP 18.0

    enif_monitor_process()

    -
    int enif_monitor_process(
    +
    int enif_monitor_process(
             ErlNifEnv* caller_env,
             void* obj,
             const ErlNifPid* target_pid,
    -        ErlNifMonitor* mon);

    Starts monitoring a process from a resource. When a process is monitored, a + ErlNifMonitor* mon);

    Starts monitoring a process from a resource. When a process is monitored, a process exit results in a call to the provided down callback associated with the resource type.

    Argument obj is pointer to the resource to hold the monitor and *target_pid @@ -2078,8 +2078,8 @@

    enif_monotonic_time()

    -
    ErlNifTime enif_monotonic_time(
    -        ErlNifTimeUnit time_unit);

    Returns the current +

    ErlNifTime enif_monotonic_time(
    +        ErlNifTimeUnit time_unit);

    Returns the current Erlang monotonic time. Notice that it is not uncommon with negative values.

    time_unit is the time unit of the returned value.

    Returns ERL_NIF_TIME_ERROR if called with an invalid time unit argument, or if called from a thread that is not a scheduler thread.

    See also ErlNifTime and @@ -2089,62 +2089,62 @@

    enif_mutex_create()

    -
    ErlNifMutex * enif_mutex_create(
    -        char *name);

    Same as erl_drv_mutex_create.

    Available since OTP R13B04

    +
    ErlNifMutex * enif_mutex_create(
    +        char *name);

    Same as erl_drv_mutex_create.

    Available since OTP R13B04

    enif_mutex_destroy()

    -
    void enif_mutex_destroy(
    -        ErlNifMutex *mtx);

    Same as erl_drv_mutex_destroy.

    Available since OTP R13B04

    +
    void enif_mutex_destroy(
    +        ErlNifMutex *mtx);

    Same as erl_drv_mutex_destroy.

    Available since OTP R13B04

    enif_mutex_lock()

    -
    void enif_mutex_lock(
    -        ErlNifMutex *mtx);

    Same as erl_drv_mutex_lock.

    Available since OTP R13B04

    +
    void enif_mutex_lock(
    +        ErlNifMutex *mtx);

    Same as erl_drv_mutex_lock.

    Available since OTP R13B04

    enif_mutex_name()

    -
    char* enif_mutex_name(
    -        ErlNifMutex* mtx);

    Same as erl_drv_mutex_name.

    Available since OTP 21.0

    +
    char* enif_mutex_name(
    +        ErlNifMutex* mtx);

    Same as erl_drv_mutex_name.

    Available since OTP 21.0

    enif_mutex_trylock()

    -
    int enif_mutex_trylock(
    -        ErlNifMutex *mtx);

    Same as erl_drv_mutex_trylock.

    Available since OTP R13B04

    +
    int enif_mutex_trylock(
    +        ErlNifMutex *mtx);

    Same as erl_drv_mutex_trylock.

    Available since OTP R13B04

    enif_mutex_unlock()

    -
    void enif_mutex_unlock(
    -        ErlNifMutex *mtx);

    Same as erl_drv_mutex_unlock.

    Available since OTP R13B04

    +
    void enif_mutex_unlock(
    +        ErlNifMutex *mtx);

    Same as erl_drv_mutex_unlock.

    Available since OTP R13B04

    enif_now_time()

    -
    ERL_NIF_TERM enif_now_time(
    -        ErlNifEnv *env);

    Returns an erlang:now() time stamp.

    This function is deprecated.

    Available since OTP 19.0

    +
    ERL_NIF_TERM enif_now_time(
    +        ErlNifEnv *env);

    Returns an erlang:now() time stamp.

    This function is deprecated.

    Available since OTP 19.0

    enif_open_resource_type()

    -
    ErlNifResourceType * enif_open_resource_type(
    +
    ErlNifResourceType * enif_open_resource_type(
             ErlNifEnv* env,
             const char* module_str,
             const char* name,
             ErlNifResourceDtor* dtor,
             ErlNifResourceFlags flags,
    -        ErlNifResourceFlags* tried);

    Creates or takes over a resource type identified by the string name and gives + ErlNifResourceFlags* tried);

    Creates or takes over a resource type identified by the string name and gives it the destructor function pointed to by dtor. Argument flags can have the following values:

    • ERL_NIF_RT_CREATE - Creates a new resource type that does not already @@ -2165,12 +2165,12 @@

      enif_open_resource_type_x()

      -
      ErlNifResourceType * enif_open_resource_type_x(
      +
      ErlNifResourceType * enif_open_resource_type_x(
               ErlNifEnv* env,
               const char* name,
               const ErlNifResourceTypeInit* init,
               ErlNifResourceFlags flags,
      -        ErlNifResourceFlags* tried);

      Same as enif_open_resource_type except + ErlNifResourceFlags* tried);

      Same as enif_open_resource_type except it accepts additional callback functions for resource types that are used together with enif_select and enif_monitor_process.

      Argument init is a pointer to an @@ -2185,12 +2185,12 @@

      enif_init_resource_type()

      -
      ErlNifResourceType * enif_init_resource_type(
      +
      ErlNifResourceType * enif_init_resource_type(
               ErlNifEnv* env,
               const char* name,
               const ErlNifResourceTypeInit* init,
               ErlNifResourceFlags flags,
      -        ErlNifResourceFlags* tried);

      Same as enif_open_resource_type_x + ErlNifResourceFlags* tried);

      Same as enif_open_resource_type_x except it accepts an additional callback function for resource types that are used together with enif_dynamic_resource_call.

      Argument init is a pointer to an @@ -2205,11 +2205,11 @@

      enif_port_command()

      -
      int enif_port_command(
      +
      int enif_port_command(
               ErlNifEnv* env, const
               ErlNifPort* to_port,
               ErlNifEnv *msg_env,
      -        ERL_NIF_TERM msg);

      Works as erlang:port_command/2, except that it is always completely + ERL_NIF_TERM msg);

      Works as erlang:port_command/2, except that it is always completely asynchronous.

      • env - The environment of the calling process. Must not be NULL.

      • *to_port - The port ID of the receiving port. The port ID is to refer to a port on the local node.

      • msg_env - The environment of the message term. Can be a process independent environment allocated with @@ -2224,17 +2224,17 @@

        enif_priv_data()

        -
        void * enif_priv_data(
        -        ErlNifEnv* env);

        Returns the pointer to the private data that was set by +

        void * enif_priv_data(
        +        ErlNifEnv* env);

        Returns the pointer to the private data that was set by load or upgrade.

        Available since OTP R13B04

        enif_raise_exception()

        -
        ERL_NIF_TERM enif_raise_exception(
        +
        ERL_NIF_TERM enif_raise_exception(
                 ErlNifEnv* env,
        -        ERL_NIF_TERM reason);

        Creates an error exception with the term reason to be returned from a NIF, and + ERL_NIF_TERM reason);

        Creates an error exception with the term reason to be returned from a NIF, and associates it with environment env. Once a NIF or any function it calls invokes enif_raise_exception, the runtime ensures that the exception it creates is raised when the NIF returns, even if the NIF attempts to return a @@ -2248,9 +2248,9 @@

        enif_realloc()

        -
        void * enif_realloc(
        +
        void * enif_realloc(
                 void* ptr,
        -        size_t size);

        Reallocates memory allocated by enif_alloc to size + size_t size);

        Reallocates memory allocated by enif_alloc to size bytes.

        Returns NULL if the reallocation fails.

        The returned pointer is suitably aligned for any built-in type that fit in the allocated memory.

        Available since OTP 20.2

        @@ -2258,9 +2258,9 @@

        enif_realloc_binary()

        -
        int enif_realloc_binary(
        +
        int enif_realloc_binary(
                 ErlNifBinary* bin,
        -        size_t size);

        Changes the size of a binary bin. The source binary can be read-only, in which + size_t size);

        Changes the size of a binary bin. The source binary can be read-only, in which case it is left untouched and a mutable copy is allocated and assigned to *bin.

        Returns true on success, or false if memory allocation failed.

        Available since OTP R13B04

        @@ -2268,16 +2268,16 @@

        enif_release_binary()

        -
        void enif_release_binary(
        -        ErlNifBinary* bin);

        Releases a binary obtained from +

        void enif_release_binary(
        +        ErlNifBinary* bin);

        Releases a binary obtained from enif_alloc_binary.

        enif_release_resource()

        -
        void enif_release_resource(
        -        void* obj);

        Removes a reference to resource object obj obtained from +

        void enif_release_resource(
        +        void* obj);

        Removes a reference to resource object obj obtained from enif_alloc_resource. The resource object is destructed when the last reference is removed. Each call to enif_release_resource must correspond to a previous call to @@ -2291,76 +2291,76 @@

        enif_rwlock_create()

        -
        ErlNifRWLock * enif_rwlock_create(
        -        char *name);

        Same as erl_drv_rwlock_create.

        Available since OTP R13B04

        +
        ErlNifRWLock * enif_rwlock_create(
        +        char *name);

        Same as erl_drv_rwlock_create.

        Available since OTP R13B04

        enif_rwlock_destroy()

        -
        void enif_rwlock_destroy(
        -        ErlNifRWLock *rwlck);

        Same as erl_drv_rwlock_destroy.

        Available since OTP R13B04

        +
        void enif_rwlock_destroy(
        +        ErlNifRWLock *rwlck);

        Same as erl_drv_rwlock_destroy.

        Available since OTP R13B04

        enif_rwlock_name()

        -
        char* enif_rwlock_name(
        -        ErlNifRWLock* rwlck);

        Same as erl_drv_rwlock_name.

        Available since OTP 21.0

        +
        char* enif_rwlock_name(
        +        ErlNifRWLock* rwlck);

        Same as erl_drv_rwlock_name.

        Available since OTP 21.0

        enif_rwlock_rlock()

        -
        void enif_rwlock_rlock(
        -        ErlNifRWLock *rwlck);

        Same as erl_drv_rwlock_rlock.

        Available since OTP R13B04

        +
        void enif_rwlock_rlock(
        +        ErlNifRWLock *rwlck);

        Same as erl_drv_rwlock_rlock.

        Available since OTP R13B04

        enif_rwlock_runlock()

        -
        void enif_rwlock_runlock(
        -        ErlNifRWLock *rwlck);

        Same as erl_drv_rwlock_runlock.

        Available since OTP R13B04

        +
        void enif_rwlock_runlock(
        +        ErlNifRWLock *rwlck);

        Same as erl_drv_rwlock_runlock.

        Available since OTP R13B04

        enif_rwlock_rwlock()

        -
        void enif_rwlock_rwlock(
        -        ErlNifRWLock *rwlck);

        Same as erl_drv_rwlock_rwlock.

        Available since OTP R13B04

        +
        void enif_rwlock_rwlock(
        +        ErlNifRWLock *rwlck);

        Same as erl_drv_rwlock_rwlock.

        Available since OTP R13B04

        enif_rwlock_rwunlock()

        -
        void enif_rwlock_rwunlock(
        -        ErlNifRWLock *rwlck);

        Same as erl_drv_rwlock_rwunlock.

        Available since OTP R13B04

        +
        void enif_rwlock_rwunlock(
        +        ErlNifRWLock *rwlck);

        Same as erl_drv_rwlock_rwunlock.

        Available since OTP R13B04

        enif_rwlock_tryrlock()

        -
        int enif_rwlock_tryrlock(
        -        ErlNifRWLock *rwlck);

        Same as erl_drv_rwlock_tryrlock.

        Available since OTP R13B04

        +
        int enif_rwlock_tryrlock(
        +        ErlNifRWLock *rwlck);

        Same as erl_drv_rwlock_tryrlock.

        Available since OTP R13B04

        enif_rwlock_tryrwlock()

        -
        int enif_rwlock_tryrwlock(
        -        ErlNifRWLock *rwlck);

        Same as erl_drv_rwlock_tryrwlock.

        Available since OTP R13B04

        +
        int enif_rwlock_tryrwlock(
        +        ErlNifRWLock *rwlck);

        Same as erl_drv_rwlock_tryrwlock.

        Available since OTP R13B04

        enif_schedule_nif()

        -
        ERL_NIF_TERM enif_schedule_nif(
        +
        ERL_NIF_TERM enif_schedule_nif(
                 ErlNifEnv* caller_env,
                 const char* fun_name,
                 int flags,
        -        ERL_NIF_TERM (*fp)(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]),
        +        ERL_NIF_TERM (*fp)(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]),
                 int argc,
        -        const ERL_NIF_TERM argv[]);

        Schedules NIF fp to execute. This function allows an application to break up + const ERL_NIF_TERM argv[]);

        Schedules NIF fp to execute. This function allows an application to break up long-running work into multiple regular NIF calls or to schedule a dirty NIF to execute on a dirty scheduler thread.

        • caller_env - Must be process bound environment of the calling NIF.

        • fun_name - Provides a name for the NIF that is scheduled for execution. @@ -2378,13 +2378,13 @@

          enif_select()

          -
          int enif_select(
          +
          int enif_select(
                   ErlNifEnv* env,
                   ErlNifEvent event,
                   enum ErlNifSelectFlags mode,
                   void* obj,
                   const ErlNifPid* pid,
          -        ERL_NIF_TERM ref);

          This function can be used to receive asynchronous notifications when OS-specific + ERL_NIF_TERM ref);

          This function can be used to receive asynchronous notifications when OS-specific event objects become ready for either read or write operations.

          Argument event identifies the event object. On Unix systems, the functions select/poll are used. The event object must be a socket, pipe or other file descriptor object that select/poll can use.

          Argument mode describes the type of events to wait for. It can be @@ -2439,14 +2439,14 @@

          to the poll set.

        Note

        Use bitwise AND to test for specific bits in the return value. New significant bits may be added in future releases to give more detailed information for both failed and successful calls. Do NOT use equality tests like ==, as that -may cause your application to stop working.

        Example:

        retval = enif_select(env, fd, ERL_NIF_SELECT_STOP, resource, ref);
        -if (retval < 0) {
        +may cause your application to stop working.

        Example:

        retval = enif_select(env, fd, ERL_NIF_SELECT_STOP, resource, ref);
        +if (retval < 0) {
             /* handle error */
        -}
        +}
         /* Success! */
        -if (retval & ERL_NIF_SELECT_STOP_CALLED) {
        +if (retval & ERL_NIF_SELECT_STOP_CALLED) {
             /* ... */
        -}

        Note

        The mode flag ERL_NIF_SELECT_CANCEL and the return flags +}

    Note

    The mode flag ERL_NIF_SELECT_CANCEL and the return flags ERL_NIF_SELECT_READ_CANCELLED and ERL_NIF_SELECT_WRITE_CANCELLED were introduced in erts-11.0 (OTP-22.0).

    Available since OTP 20.0

    @@ -2460,19 +2460,19 @@

    enif_select_write()

    -
    int enif_select_read(
    +
    int enif_select_read(
             ErlNifEnv* env,
             ErlNifEvent event,
             void* obj,
             const ErlNifPid* pid,
             ERL_NIF_TERM msg,
    -        ErlNifEnv* msg_env);
    int enif_select_write(
    +        ErlNifEnv* msg_env);
    int enif_select_write(
             ErlNifEnv* env,
             ErlNifEvent event,
             void* obj,
             const ErlNifPid* pid,
             ERL_NIF_TERM msg,
    -        ErlNifEnv* msg_env);

    These are variants of enif_select where you can supply + ErlNifEnv* msg_env);

    These are variants of enif_select where you can supply your own message term msg that will be sent to the process instead of the predefined tuple {select,_,_,_}.

    Argument msg_env must either be NULL or the environment of msg allocated with enif_alloc_env. If argument msg_env is @@ -2490,9 +2490,9 @@

    enif_self()

    -
    ErlNifPid * enif_self(
    +
    ErlNifPid * enif_self(
             ErlNifEnv* caller_env,
    -        ErlNifPid* pid);

    Initializes the ErlNifPid variable at *pid to + ErlNifPid* pid);

    Initializes the ErlNifPid variable at *pid to represent the calling process.

    Returns pid if successful, or NULL if caller_env is not a process bound environment.

    Available since OTP R14B

    @@ -2500,11 +2500,11 @@

    enif_send()

    -
    int enif_send(
    +
    int enif_send(
             ErlNifEnv* caller_env,
             ErlNifPid* to_pid,
             ErlNifEnv* msg_env,
    -        ERL_NIF_TERM msg);

    Sends a message to a process.

    • caller_env - The environment of the calling thread + ERL_NIF_TERM msg);

    Sends a message to a process.

    • caller_env - The environment of the calling thread (process bound or callback environment) or NULL if calling from a custom thread not spawned by ERTS.

    • *to_pid - The pid of the receiving process. The pid is to refer to a @@ -2523,11 +2523,11 @@

      enif_set_option()

      -
      int enif_set_option(
      +
      int enif_set_option(
               ErlNifEnv *env,
               ErlNifOption opt,
      -	...);

      Set an option. On success, zero will be returned. On failure, a non zero value -will be returned. Currently the following options can be set:

      Set an option. On success, zero will be returned. On failure, a non zero value +will be returned. Currently the following options can be set:

      • ERL_NIF_OPT_DELAY_HALT

        enif_set_option(env, ERL_NIF_OPT_DELAY_HALT)

        Enable delay of runtime system halt with flushing enabled until all calls to NIFs in the NIF library have returned. If the delay halt feature has not been enabled, a halt with flushing enabled may complete even though processes are still @@ -2557,7 +2557,7 @@

        case typically used to notify processes blocked in NIFs in the library that it is time to return in order to let the runtime system complete the halting. Such NIFs should be dirty NIFs, since ordinary NIFs should never block for a -long time.

      • ERL_NIF_OPT_ON_HALT

        enif_set_option(env, ERL_NIF_OPT_ON_HALT, on_halt)

        Install a callback that will be called when the runtime system halts with +long time.

      • ERL_NIF_OPT_ON_HALT

        enif_set_option(env, ERL_NIF_OPT_ON_HALT, on_halt)

        Install a callback that will be called when the runtime system halts with flushing enabled.

        The runtime system halts when one of the erlang:halt() BIFs are called. By default flushing is enabled, but can be disabled using the erlang:halt/2 BIF. When flushing has been disabled, the runtime system will @@ -2584,7 +2584,7 @@

        returned. The on halt callback is in this case typically used to notify processes blocked in NIFs in the library that it is time to return in order to let the runtime system complete the halting. Such NIFs should be dirty NIFs, -since ordinary NIFs should never block for a long time.

      • ERL_NIF_OPT_ON_UNLOAD_THREAD

        enif_set_option(env, ERL_NIF_OPT_ON_UNLOAD_THREAD, on_unload_thread)

        Install a callback that will be called by each scheduler thread when the +since ordinary NIFs should never block for a long time.

      • ERL_NIF_OPT_ON_UNLOAD_THREAD

        enif_set_option(env, ERL_NIF_OPT_ON_UNLOAD_THREAD, on_unload_thread)

        Install a callback that will be called by each scheduler thread when the module instance that the NIF library belongs to is purged as old. A typical use is to release thread specific data.

        The ERL_NIF_OPT_ON_UNLOAD_THREAD option can only be set during loading of a NIF library inside a call to load() or @@ -2609,27 +2609,27 @@

        enif_set_pid_undefined()

        -
        void enif_set_pid_undefined(
        -        ErlNifPid* pid);

        Sets an ErlNifPid variable as undefined. See +

        void enif_set_pid_undefined(
        +        ErlNifPid* pid);

        Sets an ErlNifPid variable as undefined. See enif_is_pid_undefined.

        Available since OTP 22.0

        enif_sizeof_resource()

        -
        unsigned enif_sizeof_resource(
        -        void* obj);

        Gets the byte size of resource object obj obtained by +

        unsigned enif_sizeof_resource(
        +        void* obj);

        Gets the byte size of resource object obj obtained by enif_alloc_resource.

        Available since OTP R13B04

        enif_snprintf()

        -
        int enif_snprintf(
        +
        int enif_snprintf(
                 char *str,
                 size_t size,
                 const char *format,
        -	...);

        Similar to snprintf but this format string also accepts "%T", which formats + ...);

        Similar to snprintf but this format string also accepts "%T", which formats Erlang terms of type ERL_NIF_TERM.

        This function is primarily intended for debugging purpose. It is not recommended to print very large terms with %T. The function may change errno, even if successful.

        Available since OTP 19.0

        @@ -2638,18 +2638,18 @@

        enif_system_info()

        -
        void enif_system_info(
        +
        void enif_system_info(
                 ErlNifSysInfo *sys_info_ptr,
        -        size_t size);

        Same as driver_system_info.

        Available since OTP R13B04

        + size_t size);

        Same as driver_system_info.

        Available since OTP R13B04

        enif_term_to_binary()

        -
        int enif_term_to_binary(
        +
        int enif_term_to_binary(
                 ErlNifEnv *env,
                 ERL_NIF_TERM term,
        -        ErlNifBinary *bin);

        Allocates a new binary with enif_alloc_binary + ErlNifBinary *bin);

        Allocates a new binary with enif_alloc_binary and stores the result of encoding term according to the Erlang external term format.

        Returns true on success, or false if the allocation fails.

        See also erlang:term_to_binary/1 and enif_binary_to_term.

        Available since OTP 19.0

        @@ -2658,9 +2658,9 @@

        enif_term_type()

        -
        ErlNifTermType enif_term_type(
        +
        ErlNifTermType enif_term_type(
                 ErlNifEnv *env,
        -        ERL_NIF_TERM term);

        Determines the type of the given term. The term must be an ordinary Erlang term + ERL_NIF_TERM term);

        Determines the type of the given term. The term must be an ordinary Erlang term and not one of the special terms returned by enif_raise_exception, enif_schedule_nif, or similar.

        The following types are defined at the moment:

        • ERL_NIF_TERM_TYPE_ATOM

        • ERL_NIF_TERM_TYPE_BITSTRING - A bitstring or binary

        • ERL_NIF_TERM_TYPE_FLOAT

        • ERL_NIF_TERM_TYPE_FUN

        • ERL_NIF_TERM_TYPE_INTEGER

        • ERL_NIF_TERM_TYPE_LIST - A list, empty or not

        • ERL_NIF_TERM_TYPE_MAP

        • ERL_NIF_TERM_TYPE_PID

        • ERL_NIF_TERM_TYPE_PORT

        • ERL_NIF_TERM_TYPE_REFERENCE

        • ERL_NIF_TERM_TYPE_TUPLE

        Note that new types may be added in the future, so the caller must be prepared @@ -2670,62 +2670,62 @@

        enif_thread_create()

        -
        int enif_thread_create(
        +
        int enif_thread_create(
                 char *name,
                 ErlNifTid *tid,
        -        void * (*func)(void *),
        +        void * (*func)(void *),
                 void *args,
        -        ErlNifThreadOpts *opts);

        Same as erl_drv_thread_create.

        Available since OTP R13B04

        + ErlNifThreadOpts *opts);

        Same as erl_drv_thread_create.

        Available since OTP R13B04

        enif_thread_exit()

        -
        void enif_thread_exit(
        -        void *resp);

        Same as erl_drv_thread_exit.

        Available since OTP R13B04

        +
        void enif_thread_exit(
        +        void *resp);

        Same as erl_drv_thread_exit.

        Available since OTP R13B04

        enif_thread_join()

        -
        int enif_thread_join(
        +
        int enif_thread_join(
                 ErlNifTid tid,
        -        void **respp);

        Same as erl_drv_thread_join.

        Available since OTP R13B04

        + void **respp);

        Same as erl_drv_thread_join.

        Available since OTP R13B04

        enif_thread_name()

        -
        char* enif_thread_name(
        -        ErlNifTid tid);

        Same as erl_drv_thread_name.

        Available since OTP 21.0

        +
        char* enif_thread_name(
        +        ErlNifTid tid);

        Same as erl_drv_thread_name.

        Available since OTP 21.0

        enif_thread_opts_create()

        -
        ErlNifThreadOpts * enif_thread_opts_create(
        -        char *name);

        Same as +

        ErlNifThreadOpts * enif_thread_opts_create(
        +        char *name);

        Same as erl_drv_thread_opts_create.

        Available since OTP R13B04

        enif_thread_opts_destroy()

        -
        void enif_thread_opts_destroy(
        -        ErlNifThreadOpts *opts);

        Same as +

        void enif_thread_opts_destroy(
        +        ErlNifThreadOpts *opts);

        Same as erl_drv_thread_opts_destroy.

        Available since OTP R13B04

        enif_thread_self()

        -
        ErlNifTid enif_thread_self(void);

        Same as erl_drv_thread_self.

        Available since OTP R13B04

        +
        ErlNifTid enif_thread_self(void);

        Same as erl_drv_thread_self.

        Available since OTP R13B04

        enif_thread_type()

        -
        int enif_thread_type(void);

        Determine the type of currently executing thread. A positive value indicates a +

        int enif_thread_type(void);

        Determine the type of currently executing thread. A positive value indicates a scheduler thread while a negative value or zero indicates another type of thread. Currently the following specific types exist (which may be extended in the future):

        • ERL_NIF_THR_UNDEFINED - Undefined thread that is not a scheduler thread.

        • ERL_NIF_THR_NORMAL_SCHEDULER - A normal scheduler thread.

        • ERL_NIF_THR_DIRTY_CPU_SCHEDULER - A dirty CPU scheduler thread.

        • ERL_NIF_THR_DIRTY_IO_SCHEDULER - A dirty I/O scheduler thread.

        Available since OTP 19.0

        @@ -2734,8 +2734,8 @@

        enif_time_offset()

        -
        ErlNifTime enif_time_offset(
        -        ErlNifTimeUnit time_unit);

        Returns the current time offset between +

        ErlNifTime enif_time_offset(
        +        ErlNifTimeUnit time_unit);

        Returns the current time offset between Erlang monotonic time and Erlang system time converted into the time_unit passed as argument.

        time_unit is the time unit of the returned value.

        Returns ERL_NIF_TIME_ERROR if called with an invalid time unit argument or if @@ -2746,61 +2746,61 @@

        enif_tsd_get()

        -
        void * enif_tsd_get(
        -        ErlNifTSDKey key);

        Same as erl_drv_tsd_get.

        Available since OTP R13B04

        +
        void * enif_tsd_get(
        +        ErlNifTSDKey key);

        Same as erl_drv_tsd_get.

        Available since OTP R13B04

        enif_tsd_key_create()

        -
        int enif_tsd_key_create(
        +
        int enif_tsd_key_create(
                 char *name,
        -        ErlNifTSDKey *key);

        Same as erl_drv_tsd_key_create.

        Available since OTP R13B04

        + ErlNifTSDKey *key);

        Same as erl_drv_tsd_key_create.

        Available since OTP R13B04

        enif_tsd_key_destroy()

        -
        void enif_tsd_key_destroy(
        -        ErlNifTSDKey key);

        Same as erl_drv_tsd_key_destroy.

        Available since OTP R13B04

        +
        void enif_tsd_key_destroy(
        +        ErlNifTSDKey key);

        Same as erl_drv_tsd_key_destroy.

        Available since OTP R13B04

        enif_tsd_set()

        -
        void enif_tsd_set(
        +
        void enif_tsd_set(
                 ErlNifTSDKey key,
        -        void *data);

        Same as erl_drv_tsd_set.

        Available since OTP R13B04

        + void *data);

        Same as erl_drv_tsd_set.

        Available since OTP R13B04

        enif_vfprintf()

        -
        int enif_vfprintf(
        +
        int enif_vfprintf(
                 FILE *stream,
                 const char *format,
        -        va_list ap);

        Equivalent to enif_fprintf except that its called + va_list ap);

        Equivalent to enif_fprintf except that its called with a va_list instead of a variable number of arguments.

        Available since OTP 21.0

        enif_vsnprintf()

        -
        int enif_vsnprintf(
        +
        int enif_vsnprintf(
                 char *str,
                 size_t size,
                 const char *format,
        -        va_list ap);

        Equivalent to enif_snprintf except that its called + va_list ap);

        Equivalent to enif_snprintf except that its called with a va_list instead of a variable number of arguments.

        Available since OTP 21.0

        enif_whereis_pid()

        -
        int enif_whereis_pid(
        +
        int enif_whereis_pid(
                 ErlNifEnv *caller_env,
                 ERL_NIF_TERM name,
        -        ErlNifPid *pid);

        Looks up a process by its registered name.

        • caller_env - The environment of the calling thread + ErlNifPid *pid);

        Looks up a process by its registered name.

        • caller_env - The environment of the calling thread (process bound or callback environment) or NULL if calling from a custom thread not spawned by ERTS.

        • name - The name of a registered process, as an atom.

        • *pid - The ErlNifPid in which the resolved @@ -2813,10 +2813,10 @@

          enif_whereis_port()

          -
          int enif_whereis_port(
          +
          int enif_whereis_port(
                   ErlNifEnv *caller_env,
                   ERL_NIF_TERM name,
          -        ErlNifPort *port);

          Looks up a port by its registered name.

          • caller_env - The environment of the calling thread + ErlNifPort *port);

          Looks up a port by its registered name.

          • caller_env - The environment of the calling thread (process bound or callback environment) or NULL if calling from a custom thread not spawned by ERTS.

          • name - The name of a registered port, as an atom.

          • *port - The ErlNifPort in which the resolved diff --git a/prs/9045/erts-15.1.2/doc/html/erl_prim_loader.html b/prs/9045/erts-15.1.2/doc/html/erl_prim_loader.html index aba45dc76596..bc7960cc7758 100644 --- a/prs/9045/erts-15.1.2/doc/html/erl_prim_loader.html +++ b/prs/9045/erts-15.1.2/doc/html/erl_prim_loader.html @@ -418,7 +418,7 @@

            read_file_info(Filename)

            Retrieves information about a file.

            Returns {ok, FileInfo} if successful, otherwise error. FileInfo is a record file_info, defined in the Kernel include file file.hrl. Include the following directive in the module from which the -function is called:

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

            For more information about the record see file:read_file_info/2.

            Filename can also be a file in an archive, for example, +function is called:

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

            For more information about the record see file:read_file_info/2.

            Filename can also be a file in an archive, for example, $OTPROOT/lib/mnesia-4.4.7.ez/mnesia-4.4.7/ebin/mnesia. For information about archive files, see code.

            diff --git a/prs/9045/erts-15.1.2/doc/html/erl_tracer.html b/prs/9045/erts-15.1.2/doc/html/erl_tracer.html index 23b74c7578ad..91abd258148c 100644 --- a/prs/9045/erts-15.1.2/doc/html/erl_tracer.html +++ b/prs/9045/erts-15.1.2/doc/html/erl_tracer.html @@ -155,107 +155,107 @@

            module, a much more lightweight message tracer is used, which only records who sent messages to who.

            The following is an example session using it on Linux:

            $ gcc -I erts-8.0/include/ -fPIC -shared -o erl_msg_tracer.so erl_msg_tracer.c
             $ erl
            -Erlang/OTP 19 [DEVELOPMENT] [erts-8.0] [source-ed2b56b] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false]
            +Erlang/OTP 19 [DEVELOPMENT] [erts-8.0] [source-ed2b56b] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false]
             
            -Eshell V8.0  (abort with ^G)
            -1> c(erl_msg_tracer), erl_msg_tracer:load().
            +Eshell V8.0  (abort with ^G)
            +1> c(erl_msg_tracer), erl_msg_tracer:load().
             ok
            -2> Tracer = spawn(fun F() -> receive M -> io:format("~p~n",[M]), F() end end).
            +2> Tracer = spawn(fun F() -> receive M -> io:format("~p~n",[M]), F() end end).
             <0.37.0>
            -3> erlang:trace(new, true, [send,{tracer, erl_msg_tracer, Tracer}]).
            +3> erlang:trace(new, true, [send,{tracer, erl_msg_tracer, Tracer}]).
             0
            -{trace,<0.39.0>,<0.27.0>}
            -4> {ok, D} = file:open("/tmp/tmp.data",[write]).
            -{trace,#Port<0.486>,<0.40.0>}
            -{trace,<0.40.0>,<0.21.0>}
            -{trace,#Port<0.487>,<0.4.0>}
            -{trace,#Port<0.488>,<0.4.0>}
            -{trace,#Port<0.489>,<0.4.0>}
            -{trace,#Port<0.490>,<0.4.0>}
            -{ok,<0.40.0>}
            -{trace,<0.41.0>,<0.27.0>}
            -5>

            erl_msg_tracer.erl:

            -module(erl_msg_tracer).
            +{trace,<0.39.0>,<0.27.0>}
            +4> {ok, D} = file:open("/tmp/tmp.data",[write]).
            +{trace,#Port<0.486>,<0.40.0>}
            +{trace,<0.40.0>,<0.21.0>}
            +{trace,#Port<0.487>,<0.4.0>}
            +{trace,#Port<0.488>,<0.4.0>}
            +{trace,#Port<0.489>,<0.4.0>}
            +{trace,#Port<0.490>,<0.4.0>}
            +{ok,<0.40.0>}
            +{trace,<0.41.0>,<0.27.0>}
            +5>

            erl_msg_tracer.erl:

            -module(erl_msg_tracer).
             
            --export([enabled/3, trace/5, load/0]).
            +-export([enabled/3, trace/5, load/0]).
             
            -load() ->
            -    erlang:load_nif("erl_msg_tracer", []).
            +load() ->
            +    erlang:load_nif("erl_msg_tracer", []).
             
            -enabled(_, _, _) ->
            +enabled(_, _, _) ->
                 error.
             
            -trace(_, _, _, _, _) ->
            +trace(_, _, _, _, _) ->
                 error.

            erl_msg_tracer.c:

            #include <erl_nif.h>
             
             /* NIF interface declarations */
            -static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info);
            -static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info);
            -static void unload(ErlNifEnv* env, void* priv_data);
            +static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info);
            +static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info);
            +static void unload(ErlNifEnv* env, void* priv_data);
             
             /* The NIFs: */
            -static ERL_NIF_TERM enabled(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
            -static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
            +static ERL_NIF_TERM enabled(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
            +static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
             
            -static ErlNifFunc nif_funcs[] = {
            -    {"enabled", 3, enabled},
            -    {"trace", 5, trace}
            -};
            +static ErlNifFunc nif_funcs[] = {
            +    {"enabled", 3, enabled},
            +    {"trace", 5, trace}
            +};
             
            -ERL_NIF_INIT(erl_msg_tracer, nif_funcs, load, NULL, upgrade, unload)
            +ERL_NIF_INIT(erl_msg_tracer, nif_funcs, load, NULL, upgrade, unload)
             
            -static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
            -{
            +static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
            +{
                 *priv_data = NULL;
                 return 0;
            -}
            +}
             
            -static void unload(ErlNifEnv* env, void* priv_data)
            -{
            +static void unload(ErlNifEnv* env, void* priv_data)
            +{
             
            -}
            +}
             
            -static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data,
            -		   ERL_NIF_TERM load_info)
            -{
            -    if (*old_priv_data != NULL || *priv_data != NULL) {
            +static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data,
            +		   ERL_NIF_TERM load_info)
            +{
            +    if (*old_priv_data != NULL || *priv_data != NULL) {
             	return -1; /* Don't know how to do that */
            -    }
            -    if (load(env, priv_data, load_info)) {
            +    }
            +    if (load(env, priv_data, load_info)) {
             	return -1;
            -    }
            +    }
                 return 0;
            -}
            +}
             
             /*
              * argv[0]: TraceTag
              * argv[1]: TracerState
              * argv[2]: Tracee
              */
            -static ERL_NIF_TERM enabled(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
            -{
            +static ERL_NIF_TERM enabled(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
            +{
                 ErlNifPid to_pid;
            -    if (enif_get_local_pid(env, argv[1], &to_pid))
            -        if (!enif_is_process_alive(env, &to_pid))
            -            if (enif_is_identical(enif_make_atom(env, "trace_status"), argv[0]))
            +    if (enif_get_local_pid(env, argv[1], &to_pid))
            +        if (!enif_is_process_alive(env, &to_pid))
            +            if (enif_is_identical(enif_make_atom(env, "trace_status"), argv[0]))
                             /* tracer is dead so we should remove this tracepoint */
            -                return enif_make_atom(env, "remove");
            +                return enif_make_atom(env, "remove");
                         else
            -                return enif_make_atom(env, "discard");
            +                return enif_make_atom(env, "discard");
             
                 /* Only generate trace for when tracer != tracee */
            -    if (enif_is_identical(argv[1], argv[2]))
            -        return enif_make_atom(env, "discard");
            +    if (enif_is_identical(argv[1], argv[2]))
            +        return enif_make_atom(env, "discard");
             
                 /* Only trigger trace messages on 'send' */
            -    if (enif_is_identical(enif_make_atom(env, "send"), argv[0]))
            -        return enif_make_atom(env, "trace");
            +    if (enif_is_identical(enif_make_atom(env, "send"), argv[0]))
            +        return enif_make_atom(env, "trace");
             
                 /* Have to answer trace_status */
            -    if (enif_is_identical(enif_make_atom(env, "trace_status"), argv[0]))
            -        return enif_make_atom(env, "trace");
            +    if (enif_is_identical(enif_make_atom(env, "trace_status"), argv[0]))
            +        return enif_make_atom(env, "trace");
             
            -    return enif_make_atom(env, "discard");
            -}
            +    return enif_make_atom(env, "discard");
            +}
             
             /*
              * argv[0]: TraceTag, should only be 'send'
            @@ -264,20 +264,20 @@ 

            * argv[3]: Message * argv[4]: Options, map containing Recipient */ -static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ +static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ ErlNifPid to_pid; ERL_NIF_TERM recipient, msg; - if (enif_get_local_pid(env, argv[1], &to_pid)) { - if (enif_get_map_value(env, argv[4], enif_make_atom(env, "extra"), &recipient)) { - msg = enif_make_tuple3(env, enif_make_atom(env, "trace"), argv[2], recipient); - enif_send(env, &to_pid, NULL, msg); - } - } + if (enif_get_local_pid(env, argv[1], &to_pid)) { + if (enif_get_map_value(env, argv[4], enif_make_atom(env, "extra"), &recipient)) { + msg = enif_make_tuple3(env, enif_make_atom(env, "trace"), argv[2], recipient); + enif_send(env, &to_pid, NULL, msg); + } + } - return enif_make_atom(env, "ok"); -}

            + return enif_make_atom(env, "ok"); +}

    diff --git a/prs/9045/erts-15.1.2/doc/html/erlang.html b/prs/9045/erts-15.1.2/doc/html/erlang.html index 6675f94bb6fd..917ef5672b5b 100644 --- a/prs/9045/erts-15.1.2/doc/html/erlang.html +++ b/prs/9045/erts-15.1.2/doc/html/erlang.html @@ -5549,7 +5549,7 @@

    bitstring_list()

    cpu_topology()

    - + View Source @@ -5729,7 +5729,7 @@

    fun_info_item()

    garbage_collection_defaults()

    - + View Source @@ -5789,7 +5789,7 @@

    halt_options()

    info_list()

    - + View Source @@ -5846,7 +5846,7 @@

    iovec()

    level_entry()

    - + View Source @@ -5876,7 +5876,7 @@

    level_entry()

    level_tag()

    - + View Source @@ -5904,7 +5904,7 @@

    level_tag()

    match_variable()

    - + View Source @@ -5932,7 +5932,7 @@

    match_variable()

    max_heap_size()

    - + View Source @@ -5967,7 +5967,7 @@

    max_heap_size()

    memory_type()

    - + View Source @@ -6213,10 +6213,10 @@

    process_info_item()

    current_stacktrace | dictionary | {dictionary, Key :: term()} | error_handler | garbage_collection | garbage_collection_info | group_leader | heap_size | - initial_call | links | last_calls | memory | message_queue_len | messages | min_heap_size | - min_bin_vheap_size | monitored_by | monitors | message_queue_data | parent | priority | - reductions | registered_name | sequential_trace_token | stack_size | status | suspending | - total_heap_size | trace | trap_exit.
    + initial_call | links | label | last_calls | memory | message_queue_len | messages | + min_heap_size | min_bin_vheap_size | monitored_by | monitors | message_queue_data | parent | + priority | reductions | registered_name | sequential_trace_token | stack_size | status | + suspending | total_heap_size | trace | trap_exit.

    @@ -6232,7 +6232,7 @@

    process_info_item()

    process_info_result_item()

    - + View Source @@ -6265,6 +6265,7 @@

    process_info_result_item()

    {heap_size, Size :: non_neg_integer()} | {initial_call, mfa()} | {links, PidsAndPorts :: [pid() | port()]} | + {label, term()} | {last_calls, false | (Calls :: [mfa()])} | {memory, Size :: non_neg_integer()} | {message_queue_len, MessageQueueLen :: non_neg_integer()} | @@ -6391,7 +6392,7 @@

    registered_process_identifier()

    scheduler_bind_type()

    - + View Source @@ -6421,7 +6422,7 @@

    scheduler_bind_type()

    send_destination()

    - + View Source @@ -6452,7 +6453,7 @@

    send_destination()

    spawn_opt_option()

    - + View Source @@ -6489,7 +6490,7 @@

    spawn_opt_option()

    stack_item()

    - + View Source @@ -6585,7 +6586,7 @@

    stacktrace_extrainfo()

    sub_level()

    - + View Source @@ -6896,7 +6897,7 @@

    trace_info_return()

    trace_match_spec()

    - + View Source @@ -6924,7 +6925,7 @@

    trace_match_spec()

    trace_pattern_flag()

    - + View Source @@ -6956,7 +6957,7 @@

    trace_pattern_flag()

    trace_pattern_mfa()

    - + View Source @@ -7041,8 +7042,8 @@

    adler32(OldAdler, Data)

    Continues computing the adler32 checksum by combining the previous checksum, -OldAdler, with the checksum of Data.

    The following code:

    X = erlang:adler32(Data1),
    -Y = erlang:adler32(X,Data2).

    assigns the same value to Y as this:

    Y = erlang:adler32([Data1,Data2]).
    +OldAdler, with the checksum of Data.

    The following code:

    X = erlang:adler32(Data1),
    +Y = erlang:adler32(X,Data2).

    assigns the same value to Y as this:

    Y = erlang:adler32([Data1,Data2]).
    @@ -7075,10 +7076,10 @@

    adler32_combine(FirstAdler, SecondAdler, Se

    Combines two previously computed adler32 checksums.

    This computation requires the size of the data object for the second checksum -to be known.

    The following code:

    Y = erlang:adler32(Data1),
    -Z = erlang:adler32(Y,Data2).

    assigns the same value to Z as this:

    X = erlang:adler32(Data1),
    -Y = erlang:adler32(Data2),
    -Z = erlang:adler32_combine(X,Y,iolist_size(Data2)).
    +to be known.

    The following code:

    Y = erlang:adler32(Data1),
    +Z = erlang:adler32(Y,Data2).

    assigns the same value to Z as this:

    X = erlang:adler32(Data1),
    +Y = erlang:adler32(Data2),
    +Z = erlang:adler32_combine(X,Y,iolist_size(Data2)).

    @@ -7135,8 +7136,8 @@

    crc32(OldCrc, Data)

    Continues computing the crc32 checksum by combining the previous checksum, -OldCrc, with the checksum of Data.

    The following code:

    X = erlang:crc32(Data1),
    -Y = erlang:crc32(X,Data2).

    assigns the same value to Y as this:

    Y = erlang:crc32([Data1,Data2]).
    +OldCrc, with the checksum of Data.

    The following code:

    X = erlang:crc32(Data1),
    +Y = erlang:crc32(X,Data2).

    assigns the same value to Y as this:

    Y = erlang:crc32([Data1,Data2]).
    @@ -7169,10 +7170,10 @@

    crc32_combine(FirstCrc, SecondCrc, SecondSi

    Combines two previously computed crc32 checksums.

    This computation requires the size of the data object for the second checksum -to be known.

    The following code:

    Y = erlang:crc32(Data1),
    -Z = erlang:crc32(Y,Data2).

    assigns the same value to Z as this:

    X = erlang:crc32(Data1),
    -Y = erlang:crc32(Data2),
    -Z = erlang:crc32_combine(X,Y,iolist_size(Data2)).
    +to be known.

    The following code:

    Y = erlang:crc32(Data1),
    +Z = erlang:crc32(Y,Data2).

    assigns the same value to Z as this:

    X = erlang:crc32(Data1),
    +Y = erlang:crc32(Data2),
    +Z = erlang:crc32_combine(X,Y,iolist_size(Data2)).

    @@ -7778,7 +7779,7 @@

    disconnect_node(Node)

    - + View Source @@ -7811,7 +7812,7 @@

    disconnect_node(Node)

    dist_ctrl_get_data(DHandle)

    - + View Source @@ -7854,7 +7855,7 @@

    dist_ctrl_get_data(DHandle)

    dist_ctrl_get_data_notification(DHandle)

    - + View Source @@ -7894,7 +7895,7 @@

    dist_ctrl_get_data_notification(DHandle)

    dist_ctrl_get_opt(DHandle, Opt)

    - + View Source @@ -7932,7 +7933,7 @@

    dist_ctrl_get_opt(DHandle, Opt)

    dist_ctrl_input_handler(DHandle, InputHandler)

    - + View Source @@ -7976,7 +7977,7 @@

    dist_ctrl_input_handler(DHandle, InputHandl

    dist_ctrl_put_data(DHandle, Data)

    - + View Source @@ -8015,7 +8016,7 @@

    dist_ctrl_put_data(DHandle, Data)

    dist_ctrl_set_opt(DHandle, Opt, Val)

    - + View Source @@ -8059,7 +8060,7 @@

    dist_ctrl_set_opt(DHandle, Opt, Val)

    get_cookie()

    - + View Source @@ -8088,7 +8089,7 @@

    get_cookie()

    get_cookie(Node)

    - + View Source @@ -8266,7 +8267,7 @@

    node()

    nodes()

    - + View Source @@ -8298,7 +8299,7 @@

    nodes()

    nodes(Arg)

    - + View Source @@ -8340,7 +8341,7 @@

    nodes(Arg)

    nodes(Arg, InfoOpts)

    - + View Source @@ -8396,11 +8397,11 @@

    nodes(Arg, InfoOpts)

    in the result returned by nodes/0.

  • hidden - The node is connected to the node of the calling process through a hidden connection. That is, the node name would not appear in the result returned by nodes/0.

  • this - This is the node of the calling process.

  • known - The node is not connected but known to the node of the calling -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>
    +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>
    @@ -8412,7 +8413,7 @@

    nodes(Arg, InfoOpts)

    set_cookie(Cookie)

    - + View Source @@ -8445,7 +8446,7 @@

    set_cookie(Cookie)

    set_cookie(Node, Cookie)

    - + View Source @@ -8510,9 +8511,9 @@

    abs(Number)

    Returns an integer or float that is the arithmetical absolute value of Float -or Int.

    For example:

    > abs(-3.33).
    +or Int.

    For example:

    > abs(-3.33).
     3.33
    -> abs(-3).
    +> abs(-3).
     3
    @@ -8544,8 +8545,8 @@

    append_element(Tuple1, Term)

    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 much -faster.

    For example:

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

    For example:

    > erlang:append_element({one, two}, three).
    +{one,two,three}
    @@ -8612,7 +8613,7 @@

    atom_to_binary(Atom, Encoding)

    representation. If Encoding is utf8 or unicode, the characters are encoded using UTF-8 where 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.

    Example:

    > atom_to_binary('Erlang', latin1).
    +representation for Atom contains a Unicode character > 255.

    Example:

    > atom_to_binary('Erlang', latin1).
     <<"Erlang">>
    @@ -8644,9 +8645,9 @@

    atom_to_list(Atom)

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

    For example:

    > atom_to_list('Erlang').
    -"Erlang"
    > atom_to_list('你好').
    -[20320,22909]

    See unicode for how to convert the resulting list to different formats.

    +of Atom.

    For example:

    > atom_to_list('Erlang').
    +"Erlang"
    > atom_to_list('你好').
    +[20320,22909]

    See unicode for how to convert the resulting list to different formats.

    @@ -8684,9 +8685,9 @@

    binary_part(Subject, PosLen)

    Extracts the part of the binary described by PosLen.

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

    For example:

    1> Bin = <<1,2,3,4,5,6,7,8,9,10>>.
    -2> binary_part(Bin,{byte_size(Bin), -5}).
    +2> binary_part(Bin,{byte_size(Bin), -5}).
     <<6,7,8,9,10>>

    Failure: badarg if PosLen in any way references outside the binary.

    Start is zero-based, that is:

    1> Bin = <<1,2,3>>
    -2> binary_part(Bin,{0,2}).
    +2> binary_part(Bin,{0,2}).
     <<1,2>>

    For details about the PosLen semantics, see binary.

    @@ -8794,8 +8795,8 @@

    binary_to_atom(Binary, Encoding)

    garbage collected. Therefore, it is recommended to consider whether binary_to_existing_atom/2 is a better option than binary_to_atom/2. The default limits can be found -in Efficiency Guide (section System Limits).

    Examples:

    > binary_to_atom(<<"Erlang">>, latin1).
    -'Erlang'
    > binary_to_atom(<<1024/utf8>>, utf8).
    +in Efficiency Guide (section System Limits).

    Examples:

    > binary_to_atom(<<"Erlang">>, latin1).
    +'Erlang'
    > binary_to_atom(<<1024/utf8>>, utf8).
     'Ѐ'
    @@ -8908,7 +8909,7 @@

    binary_to_float(Binary)

    -

    Returns the float whose text representation is Binary.

    For example:

    > binary_to_float(<<"2.2017764e+0">>).
    +

    Returns the float whose text representation is Binary.

    For example:

    > binary_to_float(<<"2.2017764e+0">>).
     2.2017764

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

    Failure: badarg if Binary contains a bad representation of a float.

    @@ -8943,7 +8944,7 @@

    binary_to_integer(Binary)

    -

    Returns an integer whose text representation is Binary.

    For example:

    > binary_to_integer(<<"123">>).
    +

    Returns an integer whose text representation is Binary.

    For example:

    > binary_to_integer(<<"123">>).
     123

    binary_to_integer/1 accepts the same string formats as list_to_integer/1.

    Failure: badarg if Binary contains a bad representation of an integer.

    @@ -8977,7 +8978,7 @@

    binary_to_integer(Binary, Base)

    -

    Returns an integer whose text representation in base Base is Binary.

    For example:

    > binary_to_integer(<<"3FF">>, 16).
    +

    Returns an integer whose text representation in base Base is Binary.

    For example:

    > binary_to_integer(<<"3FF">>, 16).
     1023

    binary_to_integer/2 accepts the same string formats as list_to_integer/2.

    Failure: badarg if Binary contains a bad representation of an integer.

    @@ -9076,9 +9077,9 @@

    binary_to_term(Binary)

    Returns an Erlang term that is the result of decoding binary object Binary, which must be encoded according to the -Erlang external term format.

    > Bin = term_to_binary(hello).
    +Erlang external term format.

    > Bin = term_to_binary(hello).
     <<131,100,0,5,104,101,108,108,111>>
    -> hello = binary_to_term(Bin).
    +> hello = binary_to_term(Bin).
     hello

    Warning

    When decoding binaries from untrusted sources, the untrusted source may submit data in a way to create resources, such as atoms and remote references, that cannot be garbage collected and lead to Denial of Service attack. In such @@ -9127,11 +9128,11 @@

    binary_to_term(Binary, Opts)

    (as they are embedded in certain structures, such as process identifiers, refs, and funs), and creation of new external function references. None of those resources are garbage collected, so unchecked creation of them can -exhaust available memory.

    > binary_to_term(<<131,100,0,5,"hello">>, [safe]).
    +exhaust available memory.

    > binary_to_term(<<131,100,0,5,"hello">>, [safe]).
     ** exception error: bad argument
     > hello.
     hello
    -> binary_to_term(<<131,100,0,5,"hello">>, [safe]).
    +> binary_to_term(<<131,100,0,5,"hello">>, [safe]).
     hello

    Warning

    The safe option ensures the data is safely processed by the Erlang runtime but it does not guarantee the data is safe to your application. You must always validate data from untrusted sources. If the binary is stored or @@ -9139,10 +9140,10 @@

    binary_to_term(Binary, Opts)

    cryptographically signing it.

  • used - Changes the return value to {Term, Used} where Used is the number of bytes actually read from Binary.

    > Input = <<131,100,0,5,"hello","world">>.
     <<131,100,0,5,104,101,108,108,111,119,111,114,108,100>>
    -> {Term, Used} = binary_to_term(Input, [used]).
    -{hello, 9}
    -> split_binary(Input, Used).
    -{<<131,100,0,5,104,101,108,108,111>>, <<"world">>}
  • Failure: badarg if safe is specified and unsafe data is decoded.

    See also term_to_binary/1, binary_to_term/1, and list_to_existing_atom/1.

    +>
    {Term, Used} = binary_to_term(Input, [used]). +{hello, 9} +> split_binary(Input, Used). +{<<131,100,0,5,104,101,108,108,111>>, <<"world">>}

    Failure: badarg if safe is specified and unsafe data is decoded.

    See also term_to_binary/1, binary_to_term/1, and list_to_existing_atom/1.

    @@ -9174,9 +9175,9 @@

    bit_size(Bitstring)

    -

    Returns an integer that is the size in bits of Bitstring.

    For example:

    > bit_size(<<433:16,3:3>>).
    +

    Returns an integer that is the size in bits of Bitstring.

    For example:

    > bit_size(<<433:16,3:3>>).
     19
    -> bit_size(<<1,2,3>>).
    +> bit_size(<<1,2,3>>).
     24
    @@ -9208,9 +9209,9 @@

    bitstring_to_list(Bitstring)

    Returns a list of integers corresponding to the bytes of Bitstring.

    If the number of bits in the binary is not divisible by 8, the last element of -the list is a bitstring containing the remaining 1-7 bits.

    For example:

    > bitstring_to_list(<<433:16>>).
    -[1,177]
    > bitstring_to_list(<<433:16,3:3>>).
    -[1,177,<<3:3>>]
    +the list is a bitstring containing the remaining 1-7 bits.

    For example:

    > bitstring_to_list(<<433:16>>).
    +[1,177]
    > bitstring_to_list(<<433:16,3:3>>).
    +[1,177,<<3:3>>]
    @@ -9244,9 +9245,9 @@

    byte_size(Bitstring)

    Returns an integer that is the number of bytes needed to contain Bitstring. That is, if the number of bits in Bitstring is not divisible by 8, the -resulting number of bytes is rounded up.

    For example:

    > byte_size(<<433:16,3:3>>).
    +resulting number of bytes is rounded up.

    For example:

    > byte_size(<<433:16,3:3>>).
     3
    -> byte_size(<<1,2,3>>).
    +> byte_size(<<1,2,3>>).
     3
    @@ -9281,7 +9282,7 @@

    ceil(Number)

    -

    Returns the smallest integer not less than Number.

    For example:

    > ceil(5.5).
    +

    Returns the smallest integer not less than Number.

    For example:

    > ceil(5.5).
     6
    @@ -9391,10 +9392,10 @@

    decode_packet(Type, Bin, Options)

    than the indicated length are truncated.

    Option line_length also applies to http* packet types as an alias for option packet_size if packet_size itself is not set. This use is only intended for backward compatibility.

  • {line_delimiter, 0 =< byte() =< 255} - For packet type line, sets the -delimiting byte. Default is the latin-1 character $\n.

  • Examples:

    > erlang:decode_packet(1,<<3,"abcd">>,[]).
    -{ok,<<"abc">>,<<"d">>}
    -> erlang:decode_packet(1,<<5,"abcd">>,[]).
    -{more,6}
    +delimiting byte. Default is the latin-1 character $\n.

    Examples:

    > erlang:decode_packet(1,<<3,"abcd">>,[]).
    +{ok,<<"abc">>,<<"d">>}
    +> erlang:decode_packet(1,<<5,"abcd">>,[]).
    +{more,6}
    @@ -9425,8 +9426,8 @@

    delete_element(Index, Tuple1)

    -

    Returns a new tuple with element at Index removed from tuple Tuple1.

    For example:

    > erlang:delete_element(2, {one, two, three}).
    -{one,three}
    +

    Returns a new tuple with element at Index removed from tuple Tuple1.

    For example:

    > erlang:delete_element(2, {one, two, three}).
    +{one,three}
    @@ -9488,7 +9489,7 @@

    element(N, Tuple)

    -

    Returns the Nth element (numbering from 1) of Tuple.

    For example:

    > element(2, {a, b, c}).
    +

    Returns the Nth element (numbering from 1) of Tuple.

    For example:

    > element(2, {a, b, c}).
     b
    @@ -9520,10 +9521,10 @@

    external_size(Term)

    Calculates, without doing the encoding, the maximum byte size for a term encoded -in the Erlang external term format.

    The following condition applies always:

    > Size1 = byte_size(term_to_binary(Term)),
    -> Size2 = erlang:external_size(Term),
    +in the Erlang external term format.

    The following condition applies always:

    > Size1 = byte_size(term_to_binary(Term)),
    +> Size2 = erlang:external_size(Term),
     > true = Size1 =< Size2.
    -true

    This is equivalent to a call to:

    erlang:external_size(Term, [])
    +
    true

    This is equivalent to a call to:

    erlang:external_size(Term, [])
    @@ -9562,8 +9563,8 @@

    external_size(Term, Options)

    Calculates, without doing the encoding, the maximum byte size for a term encoded -in the Erlang external term format.

    The following condition applies always:

    > Size1 = byte_size(term_to_binary(Term, Options)),
    -> Size2 = erlang:external_size(Term, Options),
    +in the Erlang external term format.

    The following condition applies always:

    > Size1 = byte_size(term_to_binary(Term, Options)),
    +> Size2 = erlang:external_size(Term, Options),
     > true = Size1 =< Size2.
     true

    Option {minor_version, Version} specifies how floats are encoded. For a detailed description, see term_to_binary/2.

    @@ -9598,7 +9599,7 @@

    float(Number)

    -

    Returns a float by converting Number to a float.

    For example:

    > float(55).
    +

    Returns a float by converting Number to a float.

    For example:

    > float(55).
     55.0

    Note

    If used on the top level in a guard, it tests whether the argument is a floating point number; for clarity, use is_float/1 instead.

    When float/1 is used in an expression in a guard, such as 'float(A) == 4.0', it converts a number as described earlier.

    @@ -9673,17 +9674,17 @@

    float_to_binary(Float, Options)

    Returns a binary corresponding to the text representation of Float using fixed -decimal point formatting.

    Options behaves in the same way as float_to_list/2.

    For example:

    > float_to_binary(7.12, [{decimals, 4}]).
    +decimal point formatting.

    Options behaves in the same way as float_to_list/2.

    For example:

    > float_to_binary(7.12, [{decimals, 4}]).
     <<"7.1200">>
    -> float_to_binary(7.12, [{decimals, 4}, compact]).
    +> float_to_binary(7.12, [{decimals, 4}, compact]).
     <<"7.12">>
    -> float_to_binary(7.12, [{scientific, 3}]).
    +> float_to_binary(7.12, [{scientific, 3}]).
     <<"7.120e+00">>
    -> float_to_binary(7.12, [short]).
    +> float_to_binary(7.12, [short]).
     <<"7.12">>
    -> float_to_binary(0.1+0.2, [short]).
    +> float_to_binary(0.1+0.2, [short]).
     <<"0.30000000000000004">>
    -> float_to_binary(0.1+0.2)
    +> float_to_binary(0.1+0.2)
     <<"3.00000000000000044409e-01">>
    @@ -9764,17 +9765,17 @@

    float_to_list(Float, Options)

    range (-2⁵³, 2⁵³), the notation that yields the smallest number of characters is used (scientific notation or normal decimal notation). Floats outside the range (-2⁵³, 2⁵³) are always formatted using scientific notation to avoid -confusing results when doing arithmetic operations.
  • If Options is [], the function behaves as float_to_list/1.
  • Examples:

    > float_to_list(7.12, [{decimals, 4}]).
    +confusing results when doing arithmetic operations.
  • If Options is [], the function behaves as float_to_list/1.
  • Examples:

    > float_to_list(7.12, [{decimals, 4}]).
     "7.1200"
    -> float_to_list(7.12, [{decimals, 4}, compact]).
    +> float_to_list(7.12, [{decimals, 4}, compact]).
     "7.12"
    -> float_to_list(7.12, [{scientific, 3}]).
    +> float_to_list(7.12, [{scientific, 3}]).
     "7.120e+00"
    -> float_to_list(7.12, [short]).
    +> float_to_list(7.12, [short]).
     "7.12"
    -> float_to_list(0.1+0.2, [short]).
    +> float_to_list(0.1+0.2, [short]).
     "0.30000000000000004"
    -> float_to_list(0.1+0.2)
    +> float_to_list(0.1+0.2)
     "3.00000000000000044409e-01"

    In the last example, float_to_list(0.1+0.2) evaluates to "3.00000000000000044409e-01". The reason for this is explained in Representation of Floating Point Numbers.

    @@ -9811,7 +9812,7 @@

    floor(Number)

    -

    Returns the largest integer not greater than Number.

    For example:

    > floor(-10.5).
    +

    Returns the largest integer not greater than Number.

    For example:

    > floor(-10.5).
     -11
    @@ -9824,7 +9825,7 @@

    floor(Number)

    fun_info(Fun)

    - + View Source @@ -9945,17 +9946,17 @@

    fun_to_list(Fun)

    funs are equal as fun_to_list/1 does not take the fun's environment into account. See erlang:fun_info/1 for how to get the environment of a fun.

    Change

    The output of fun_to_list/1 can differ between Erlang -implementations and may change in future versions.

    Examples:

    -module(test).
    --export([add/1, add2/0, fun_tuple/0]).
    -add(A) -> fun(B) -> A + B end.
    -add2() -> fun add/1.
    -fun_tuple() -> {fun() -> 1 end, fun() -> 1 end}.
    > {fun test:add/1, test:add2()}.
    -{fun test:add/1,#Fun<test.1.107738983>}

    Explanation: fun test:add/1 is upgradable but test:add2() is not upgradable.

    > {test:add(1), test:add(42)}.
    -{#Fun<test.0.107738983>,#Fun<test.0.107738983>}

    Explanation: test:add(1) and test:add(42) has the same string representation -as the environment is not taken into account.

    >test:fun_tuple().
    -{#Fun<test.2.107738983>,#Fun<test.3.107738983>}

    Explanation: The string representations differ because the funs come from -different fun expressions.

    > {fun() -> 1 end, fun() -> 1 end}. >
    -{#Fun<erl_eval.45.97283095>,#Fun<erl_eval.45.97283095>}

    Explanation: All funs created from fun expressions of this form in uncompiled +implementations and may change in future versions.

    Examples:

    -module(test).
    +-export([add/1, add2/0, fun_tuple/0]).
    +add(A) -> fun(B) -> A + B end.
    +add2() -> fun add/1.
    +fun_tuple() -> {fun() -> 1 end, fun() -> 1 end}.
    > {fun test:add/1, test:add2()}.
    +{fun test:add/1,#Fun<test.1.107738983>}

    Explanation: fun test:add/1 is upgradable but test:add2() is not upgradable.

    > {test:add(1), test:add(42)}.
    +{#Fun<test.0.107738983>,#Fun<test.0.107738983>}

    Explanation: test:add(1) and test:add(42) has the same string representation +as the environment is not taken into account.

    >test:fun_tuple().
    +{#Fun<test.2.107738983>,#Fun<test.3.107738983>}

    Explanation: The string representations differ because the funs come from +different fun expressions.

    > {fun() -> 1 end, fun() -> 1 end}. >
    +{#Fun<erl_eval.45.97283095>,#Fun<erl_eval.45.97283095>}

    Explanation: All funs created from fun expressions of this form in uncompiled code with the same arity are mapped to the same list by fun_to_list/1.

    @@ -9989,8 +9990,8 @@

    hd(List)

    -

    Returns the head of List, that is, the first element.

    It works with improper lists.

    Examples:

    > hd([1,2,3,4,5]).
    -1
    > hd([first, second, third, so_on | improper_end]).
    +

    Returns the head of List, that is, the first element.

    It works with improper lists.

    Examples:

    > hd([1,2,3,4,5]).
    +1
    > hd([first, second, third, so_on | improper_end]).
     first

    Failure: badarg if List is an empty list [].

    @@ -10025,8 +10026,8 @@

    insert_element(Index, Tuple1, Term)

    Returns a new tuple with element Term inserted at position Index in tuple Tuple1. All elements from position Index and upwards are pushed one step -higher in the new tuple Tuple2.

    For example:

    > erlang:insert_element(2, {one, two, three}, new).
    -{one,new,two,three}
    +higher in the new tuple Tuple2.

    For example:

    > erlang:insert_element(2, {one, two, three}, new).
    +{one,new,two,three}
    @@ -10058,7 +10059,7 @@

    integer_to_binary(Integer)

    -

    Returns a binary corresponding to the text representation of Integer.

    For example:

    > integer_to_binary(77).
    +

    Returns a binary corresponding to the text representation of Integer.

    For example:

    > integer_to_binary(77).
     <<"77">>
    @@ -10071,7 +10072,7 @@

    integer_to_binary(Integer)

    integer_to_binary(Integer, Base)

    - + View Source @@ -10092,7 +10093,7 @@

    integer_to_binary(Integer, Base)

    Returns a binary corresponding to the text representation of Integer in base -Base.

    For example:

    > integer_to_binary(1023, 16).
    +Base.

    For example:

    > integer_to_binary(1023, 16).
     <<"3FF">>
    @@ -10123,7 +10124,7 @@

    integer_to_list(Integer)

    -

    Returns a string corresponding to the text representation of Integer.

    For example:

    > integer_to_list(77).
    +

    Returns a string corresponding to the text representation of Integer.

    For example:

    > integer_to_list(77).
     "77"
    @@ -10136,7 +10137,7 @@

    integer_to_list(Integer)

    integer_to_list(Integer, Base)

    - + View Source @@ -10155,7 +10156,7 @@

    integer_to_list(Integer, Base)

    Returns a string corresponding to the text representation of Integer in base -Base.

    For example:

    > integer_to_list(1023, 16).
    +Base.

    For example:

    > integer_to_list(1023, 16).
     "3FF"
    @@ -10187,7 +10188,7 @@

    iolist_size(Item)

    Returns an integer, that is the size in bytes, of the binary that would be the -result of iolist_to_binary(Item).

    For example:

    > iolist_size([1,2|<<3,4>>]).
    +result of iolist_to_binary(Item).

    For example:

    > iolist_size([1,2|<<3,4>>]).
     4
    @@ -10225,7 +10226,7 @@

    iolist_to_binary(IoListOrBinary)

    <<4,5>> > Bin3 = <<6>>. <<6>> -> iolist_to_binary([Bin1,1,[2,3,Bin2],4|Bin3]). +> iolist_to_binary([Bin1,1,[2,3,Bin2],4|Bin3]). <<1,2,3,1,2,3,4,5,4,6>>
    @@ -10269,16 +10270,16 @@

    iolist_to_iovec(IoListOrBinary)

    >
    Bin3 = <<6>>. <<6>> %% If you pass small binaries and integers it works as iolist_to_binary -> erlang:iolist_to_iovec([Bin1,1,[2,3,Bin2],4|Bin3]). -[<<1,2,3,1,2,3,4,5,4,6>>] +> erlang:iolist_to_iovec([Bin1,1,[2,3,Bin2],4|Bin3]). +[<<1,2,3,1,2,3,4,5,4,6>>] %% If you pass larger binaries, they are split and returned in a form %% optimized for calling the C function writev. -> erlang:iolist_to_iovec([<<1>>,<<2:8096>>,<<3:8096>>]). -[<<1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +> erlang:iolist_to_iovec([<<1>>,<<2:8096>>,<<3:8096>>]). +[<<1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,...>>, <<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ...>>, - <<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,...>>]
    +
    <<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,...>>]
    @@ -10638,11 +10639,11 @@

    is_map_key(Key, Map)

    Returns true if map Map contains Key and returns false if it does not -contain the Key.

    The call fails with a {badmap,Map} exception if Map is not a map.

    Example:

    > Map = #{"42" => value}.
    -#{"42" => value}
    -> is_map_key("42",Map).
    +contain the Key.

    The call fails with a {badmap,Map} exception if Map is not a map.

    Example:

    > Map = #{"42" => value}.
    +#{"42" => value}
    +> is_map_key("42",Map).
     true
    -> is_map_key(value,Map).
    +> is_map_key(value,Map).
     false
    @@ -10909,7 +10910,7 @@

    length(List)

    -

    Returns the length of List.

    For example:

    > length([1,2,3,4,5,6,7,8,9]).
    +

    Returns the length of List.

    For example:

    > length([1,2,3,4,5,6,7,8,9]).
     9
    @@ -10949,7 +10950,7 @@

    list_to_atom(String)

    garbage collected. Therefore, it is recommended to consider if list_to_existing_atom/1 is a better option than list_to_atom/1. The default limits can be found in the -Efficiency Guide (section System Limits).

    Example:

    > list_to_atom("Erlang").
    +Efficiency Guide (section System Limits).

    Example:

    > list_to_atom("Erlang").
     'Erlang'
    @@ -10986,7 +10987,7 @@

    list_to_binary(IoList)

    <<4,5>> > Bin3 = <<6>>. <<6>> -> list_to_binary([Bin1,1,[2,3,Bin2],4|Bin3]). +> list_to_binary([Bin1,1,[2,3,Bin2],4|Bin3]). <<1,2,3,1,2,3,4,5,4,6>>
    @@ -11025,7 +11026,7 @@

    list_to_bitstring(BitstringList)

    <<4,5>> > Bin3 = <<6,7:4>>. <<6,7:4>> -> list_to_bitstring([Bin1,1,[2,3,Bin2],4|Bin3]). +> list_to_bitstring([Bin1,1,[2,3,Bin2],4|Bin3]). <<1,2,3,1,2,3,4,5,4,6,7:4>>
    @@ -11094,7 +11095,7 @@

    list_to_float(String)

    -

    Returns the float whose text representation is String.

    For example:

    > list_to_float("2.2017764e+0").
    +

    Returns the float whose text representation is String.

    For example:

    > list_to_float("2.2017764e+0").
     2.2017764

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

    Failure: badarg if String contains a bad representation of a float.

    @@ -11127,9 +11128,9 @@

    list_to_integer(String)

    -

    Returns an integer whose text representation is String.

    For example:

    > list_to_integer("123").
    -123
    > list_to_integer("-123").
    --123
    > list_to_integer("+123234982304982309482093833234234").
    +

    Returns an integer whose text representation is String.

    For example:

    > list_to_integer("123").
    +123
    > list_to_integer("-123").
    +-123
    > list_to_integer("+123234982304982309482093833234234").
     123234982304982309482093833234234

    String must contain at least one digit character and can have an optional prefix consisting of a single "+" or "-" character (that is, String must match the regular expression "^[+-]?[0-9]+$").

    Failure: badarg if String contains a bad representation of an integer.

    @@ -11162,11 +11163,11 @@

    list_to_integer(String, Base)

    -

    Returns an integer whose text representation in base Base is String.

    For example:

    > list_to_integer("3FF", 16).
    -1023
    > list_to_integer("+3FF", 16).
    -1023
    > list_to_integer("3ff", 16).
    -1023
    > list_to_integer("3fF", 16).
    -1023
    > list_to_integer("-3FF", 16).
    +

    Returns an integer whose text representation in base Base is String.

    For example:

    > list_to_integer("3FF", 16).
    +1023
    > list_to_integer("+3FF", 16).
    +1023
    > list_to_integer("3ff", 16).
    +1023
    > list_to_integer("3fF", 16).
    +1023
    > list_to_integer("-3FF", 16).
     -1023

    For example, when Base is 16, String must match the regular expression "^[+-]?([0-9]|[A-F]|[a-f])+$".

    Failure: badarg if String contains a bad representation of an integer.

    @@ -11198,7 +11199,7 @@

    list_to_pid(String)

    -

    Returns a process identifier whose text representation is a String.

    For example:

    > list_to_pid("<0.4.1>").
    +

    Returns a process identifier whose text representation is a String.

    For example:

    > list_to_pid("<0.4.1>").
     <0.4.1>

    Failure: badarg if String contains a bad representation of a process identifier.

    Warning

    This BIF is intended for debugging and is not to be used in application programs.

    @@ -11233,7 +11234,7 @@

    list_to_port(String)

    -

    Returns a port identifier whose text representation is a String.

    For example:

    > list_to_port("#Port<0.4>").
    +

    Returns a port identifier whose text representation is a String.

    For example:

    > list_to_port("#Port<0.4>").
     #Port<0.4>

    Failure: badarg if String contains a bad representation of a port identifier.

    Warning

    This BIF is intended for debugging and is not to be used in application programs.

    @@ -11268,7 +11269,7 @@

    list_to_ref(String)

    -

    Returns a reference whose text representation is a String.

    For example:

    > list_to_ref("#Ref<0.4192537678.4073193475.71181>").
    +

    Returns a reference whose text representation is a String.

    For example:

    > list_to_ref("#Ref<0.4192537678.4073193475.71181>").
     #Ref<0.4192537678.4073193475.71181>

    Failure: badarg if String contains a bad representation of a reference.

    Warning

    This BIF is intended for debugging and is not to be used in application programs.

    @@ -11300,8 +11301,8 @@

    list_to_tuple(List)

    -

    Returns a tuple corresponding to List, for example

    > list_to_tuple([share, ['Ericsson_B', 163]]).
    -{share, ['Ericsson_B', 163]}

    List can contain any Erlang terms.

    +

    Returns a tuple corresponding to List, for example

    > list_to_tuple([share, ['Ericsson_B', 163]]).
    +{share, ['Ericsson_B', 163]}

    List can contain any Erlang terms.

    @@ -11363,8 +11364,8 @@

    make_tuple(Arity, InitialValue)

    Creates a new tuple of the specified Arity, where all elements are -InitialValue.

    For example:

    > erlang:make_tuple(4, []).
    -{[],[],[],[]}
    +InitialValue.

    For example:

    > erlang:make_tuple(4, []).
    +{[],[],[],[]}
    @@ -11400,8 +11401,8 @@

    make_tuple(Arity, DefaultValue, InitList)InitList.

    Each list element in InitList must be a two-tuple, where the first element is a position in the newly created tuple and the second element is any term. If a position occurs more than once in the list, the term corresponding to the last -occurrence is used.

    For example:

    > erlang:make_tuple(5, [], [{2,ignored},{5,zz},{2,aa}]).
    -{[],aa,[],[],zz}
    +occurrence is used.

    For example:

    > erlang:make_tuple(5, [], [{2,ignored},{5,zz},{2,aa}]).
    +{[],aa,[],[],zz}

    @@ -11437,8 +11438,8 @@

    map_get(Key, Map)

    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.

    Example:

    > Key = 1337,
    -  Map = #{42 => value_two,1337 => "value one","a" => 1},
    -  map_get(Key,Map).
    +  Map = #{42 => value_two,1337 => "value one","a" => 1},
    +  map_get(Key,Map).
     "value one"
    @@ -11473,7 +11474,7 @@

    map_size(Map)

    -

    Returns an integer, which is the number of key-value pairs in Map.

    For example:

    > map_size(#{a=>1, b=>2, c=>3}).
    +

    Returns an integer, which is the number of key-value pairs in Map.

    For example:

    > map_size(#{a=>1, b=>2, c=>3}).
     3
    @@ -11534,7 +11535,7 @@

    match_spec_test(MatchAgainst, MatchSpec, Ty

    max(Term1, Term2)

    - + View Source @@ -11556,10 +11557,10 @@

    max(Term1, Term2)

    Returns the largest of Term1 and Term2. If the terms compare equal with the == operator, Term1 is returned.

    The Expressions section contains -descriptions of the == operator and how terms are ordered.

    Examples:

    > max(1, 2).
    -2
    > max(1.0, 1).
    -1.0
    > max(1, 1.0).
    -1
    > max("abc", "b").
    +descriptions of the == operator and how terms are ordered.

    Examples:

    > max(1, 2).
    +2
    > max(1.0, 1).
    +1.0
    > max(1, 1.0).
    +1
    > max("abc", "b").
     "b"

    Change

    Allowed in guards tests from Erlang/OTP 26.

    @@ -11572,7 +11573,7 @@

    max(Term1, Term2)

    min(Term1, Term2)

    - + View Source @@ -11594,10 +11595,10 @@

    min(Term1, Term2)

    Returns the smallest of Term1 and Term2. If the terms compare equal with the == operator, Term1 is returned.

    The Expressions section contains -descriptions of the == operator and how terms are ordered.

    Examples:

    > min(1, 2).
    -1
    > min(1.0, 1).
    -1.0
    > min(1, 1.0).
    -1
    > min("abc", "b").
    +descriptions of the == operator and how terms are ordered.

    Examples:

    > min(1, 2).
    +1
    > min(1.0, 1).
    +1.0
    > min(1, 1.0).
    +1
    > min("abc", "b").
     "abc"

    Change

    Allowed in guards tests from Erlang/OTP 26.

    @@ -11723,7 +11724,7 @@

    pid_to_list(Pid)

    -

    Returns a string corresponding to the text representation of Pid.

    For example:

    > erlang:pid_to_list(self()).
    +

    Returns a string corresponding to the text representation of Pid.

    For example:

    > erlang:pid_to_list(self()).
     "<0.85.0>"

    Note

    The creation for the node is not included in the list representation of Pid. This means that processes in different incarnations of a node with a specific name can get the same list representation.

    @@ -11820,10 +11821,10 @@

    round(Number)

    -

    Returns an integer by rounding Number.

    For example:

    round(42.1).
    -42
    round(5.5).
    -6
    round(-5.5).
    --6
    round(36028797018963969.0).
    +

    Returns an integer by rounding Number.

    For example:

    round(42.1).
    +42
    round(5.5).
    +6
    round(-5.5).
    +-6
    round(36028797018963969.0).
     36028797018963968

    In the last example, round(36028797018963969.0) evaluates to 36028797018963968. The reason for this is that the number 36028797018963969.0 cannot be represented exactly as a float value. Instead, @@ -11842,7 +11843,7 @@

    round(Number)

    setelement(Index, Tuple1, Value)

    - + View Source @@ -11863,8 +11864,8 @@

    setelement(Index, Tuple1, Value)

    Returns a tuple that is a copy of argument Tuple1 with the element specified by integer argument Index (the first element is the element with index 1) -replaced by argument Value.

    For example:

    > setelement(2, {10, green, bottles}, red).
    -{10,red,bottles}
    +replaced by argument Value.

    For example:

    > setelement(2, {10, green, bottles}, red).
    +{10,red,bottles}
    @@ -11897,9 +11898,9 @@

    size(Item)

    Returns the number of elements in a tuple or the number of bytes in a binary or -bitstring.

    For example:

    > size({morni, mulle, bwange}).
    +bitstring.

    For example:

    > size({morni, mulle, bwange}).
     3
    -> size(<<11, 22, 33>>).
    +> size(<<11, 22, 33>>).
     3

    For bitstrings, the number of whole bytes is returned. That is, if the number of bits in the bitstring is not divisible by 8, the resulting number of bytes is rounded down.

    See also tuple_size/1, byte_size/1, and bit_size/1.

    @@ -11933,15 +11934,15 @@

    split_binary(Bin, Pos)

    Returns a tuple containing the binaries that are the result of splitting Bin -into two parts at position Pos.

    This is not a destructive operation. After the operation, there are three binaries altogether.

    For example:

    > B = list_to_binary("0123456789").
    +into two parts at position Pos.

    This is not a destructive operation. After the operation, there are three binaries altogether.

    For example:

    > B = list_to_binary("0123456789").
     <<"0123456789">>
    -> byte_size(B).
    +> byte_size(B).
     10
    -> {B1, B2} = split_binary(B,3).
    -{<<"012">>,<<"3456789">>}
    -> byte_size(B1).
    +> {B1, B2} = split_binary(B,3).
    +{<<"012">>,<<"3456789">>}
    +> byte_size(B1).
     3
    -> byte_size(B2).
    +> byte_size(B2).
     7
    @@ -11954,7 +11955,7 @@

    split_binary(Bin, Pos)

    term_to_binary(Term)

    - + View Source @@ -11975,9 +11976,9 @@

    term_to_binary(Term)

    Returns a binary data object that is the result of encoding Term according to the Erlang external term format.

    This can be used for various purposes, for example, writing a term to a file in an efficient way, or sending an Erlang term to some type of communications -channel not supported by distributed Erlang.

    > Bin = term_to_binary(hello).
    +channel not supported by distributed Erlang.

    > Bin = term_to_binary(hello).
     <<131,100,0,5,104,101,108,108,111>>
    -> hello = binary_to_term(Bin).
    +> hello = binary_to_term(Bin).
     hello

    See also binary_to_term/1.

    Note

    There is no guarantee that this function will return the same encoded representation for the same term.

    @@ -11991,7 +11992,7 @@

    term_to_binary(Term)

    term_to_binary(Term, Options)

    - + View Source @@ -12104,7 +12105,7 @@

    term_to_binary(Term, Options)

    term_to_iovec(Term)

    - + View Source @@ -12143,7 +12144,7 @@

    term_to_iovec(Term)

    term_to_iovec(Term, Options)

    - + View Source @@ -12190,7 +12191,7 @@

    term_to_iovec(Term, Options)

    tl(List)

    - + View Source @@ -12210,10 +12211,10 @@

    tl(List)

    -

    Returns the tail of List, that is, the list minus the first element

    It works with improper lists.

    Examples:

    > tl([geesties, guilies, beasties]).
    -[guilies, beasties]
    > tl([geesties]).
    -[]
    > tl([geesties, guilies, beasties | improper_end]).
    -[guilies, beasties | improper_end]
    > tl([geesties | improper_end]).
    +

    Returns the tail of List, that is, the list minus the first element

    It works with improper lists.

    Examples:

    > tl([geesties, guilies, beasties]).
    +[guilies, beasties]
    > tl([geesties]).
    +[]
    > tl([geesties, guilies, beasties | improper_end]).
    +[guilies, beasties | improper_end]
    > tl([geesties | improper_end]).
     improper_end

    Failure: badarg if List is an empty list [].

    @@ -12246,10 +12247,10 @@

    trunc(Number)

    -

    Truncates the decimals of Number.

    For example:

    > trunc(5.7).
    -5
    > trunc(-5.7).
    --5
    > trunc(5).
    -5
    > trunc(36028797018963969.0).
    +

    Truncates the decimals of Number.

    For example:

    > trunc(5.7).
    +5
    > trunc(-5.7).
    +-5
    > trunc(5).
    +5
    > trunc(36028797018963969.0).
     36028797018963968

    In the last example, trunc(36028797018963969.0) evaluates to 36028797018963968. The reason for this is that the number 36028797018963969.0 cannot be represented exactly as a float value. Instead, @@ -12288,7 +12289,7 @@

    tuple_size(Tuple)

    -

    Returns an integer that is the number of elements in Tuple.

    For example:

    > tuple_size({morni, mulle, bwange}).
    +

    Returns an integer that is the number of elements in Tuple.

    For example:

    > tuple_size({morni, mulle, bwange}).
     3
    @@ -12301,7 +12302,7 @@

    tuple_size(Tuple)

    tuple_to_list(Tuple)

    - + View Source @@ -12320,8 +12321,8 @@

    tuple_to_list(Tuple)

    Returns a list corresponding to Tuple. Tuple can contain any Erlang terms. -Example:

    > tuple_to_list({share, {'Ericsson_B', 163}}).
    -[share,{'Ericsson_B',163}]
    +Example:

    > tuple_to_list({share, {'Ericsson_B', 163}}).
    +[share,{'Ericsson_B',163}]
    @@ -12492,27 +12493,27 @@

    alias(Opts)

    unalias/1. This is also the default behaviour if no options are passed or if alias/0 is called.

  • reply - The alias will be automatically deactivated when a reply message sent via the alias is received. The alias can also still be deactivated via a -call to unalias/1.

  • Example:

    server() ->
    +call to unalias/1.

    Example:

    server() ->
         receive
    -        {request, AliasReqId, Request} ->
    -            Result = perform_request(Request),
    -            AliasReqId ! {reply, AliasReqId, Result}
    +        {request, AliasReqId, Request} ->
    +            Result = perform_request(Request),
    +            AliasReqId ! {reply, AliasReqId, Result}
         end,
    -    server().
    +    server().
     
    -client(ServerPid, Request) ->
    -    AliasReqId = alias([reply]),
    -    ServerPid ! {request, AliasReqId, Request},
    +client(ServerPid, Request) ->
    +    AliasReqId = alias([reply]),
    +    ServerPid ! {request, AliasReqId, Request},
         %% Alias will be automatically deactivated if we receive a reply
         %% since we used the 'reply' option...
         receive
    -        {reply, AliasReqId, Result} -> Result
    +        {reply, AliasReqId, Result} -> Result
         after 5000 ->
    -            unalias(AliasReqId),
    +            unalias(AliasReqId),
                 %% Flush message queue in case the reply arrived
                 %% just before the alias was deactivated...
    -            receive {reply, AliasReqId, Result} -> Result
    -            after 0 -> exit(timeout)
    +            receive {reply, AliasReqId, Result} -> Result
    +            after 0 -> exit(timeout)
                 end
         end.

    Note that both the server and the client in this example must be executing on at least OTP 24 systems in order for this to work.

    For more information on process aliases see the @@ -12529,7 +12530,7 @@

    alias(Opts)

    apply(Fun, Args)

    - + View Source @@ -12562,7 +12563,7 @@

    apply(Fun, Args)

    apply(Module, Function, Args)

    - + View Source @@ -12583,9 +12584,9 @@

    apply(Module, Function, Args)

    Returns the result of applying Function in Module to Args. The applied function must be exported from Module. The arity of the function is the length -of Args.

    For example:

    > apply(lists, reverse, [[a, b, c]]).
    -[c,b,a]
    -> apply(erlang, atom_to_list, ['Erlang']).
    +of Args.

    For example:

    > apply(lists, reverse, [[a, b, c]]).
    +[c,b,a]
    +> apply(erlang, atom_to_list, ['Erlang']).
     "Erlang"

    If the number of arguments are known at compile time, the call is better written as Module:Function(Arg1, Arg2, ..., ArgN).

    Failure: error_handler:undefined_function/3 is called if the applied function is not exported. The error handler can be redefined (see process_flag/2). If @@ -12706,9 +12707,9 @@

    demonitor(MonitorRef, OptionList)

    The returned value is true unless info is part of OptionList.

    demonitor(MonitorRef, []) is equivalent to demonitor(MonitorRef).

    Options:

    • flush - Removes (one) {_, MonitorRef, _, _, _} message, if there is one, from the caller message queue after monitoring has been stopped.

      Calling demonitor(MonitorRef, [flush]) is equivalent to the -following, but more efficient:

      demonitor(MonitorRef),
      +following, but more efficient:

      demonitor(MonitorRef),
       receive
      -    {_, MonitorRef, _, _, _} ->
      +    {_, MonitorRef, _, _, _} ->
               true
       after 0 ->
               true
      @@ -12747,10 +12748,10 @@ 

      erase()

      -

      Returns the process dictionary and deletes it.

      For example:

      > put(key1, {1, 2, 3}),
      -put(key2, [a, b, c]),
      -erase().
      -[{key1,{1,2,3}},{key2,[a,b,c]}]
      +

      Returns the process dictionary and deletes it.

      For example:

      > put(key1, {1, 2, 3}),
      +put(key2, [a, b, c]),
      +erase().
      +[{key1,{1,2,3}},{key2,[a,b,c]}]
    @@ -12783,10 +12784,10 @@

    erase(Key)

    Returns the value Val associated with Key and deletes it from the process dictionary. Returns undefined if no value is associated with Key.

    The average time complexity for the current implementation of this function is O(1) and the worst case time complexity is O(N), where N is the number of -items in the process dictionary.

    For example:

    > put(key1, {merry, lambs, are, playing}),
    -X = erase(key1),
    -{X, erase(key1)}.
    -{{merry,lambs,are,playing},undefined}
    +items in the process dictionary.

    For example:

    > put(key1, {merry, lambs, are, playing}),
    +X = erase(key1),
    +{X, erase(key1)}.
    +{{merry,lambs,are,playing},undefined}
    @@ -12820,14 +12821,14 @@

    error(Reason)

    has happened (for example, a function is called with a parameter that has an incorrect type). See the guide about errors and error handling for additional information. -Example:

    > catch error(foobar).
    -{'EXIT',{foobar,[{shell,apply_fun,3,
    -                        [{file,"shell.erl"},{line,906}]},
    -                 {erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,677}]},
    -                 {erl_eval,expr,5,[{file,"erl_eval.erl"},{line,430}]},
    -                 {shell,exprs,7,[{file,"shell.erl"},{line,687}]},
    -                 {shell,eval_exprs,7,[{file,"shell.erl"},{line,642}]},
    -                 {shell,eval_loop,3,[{file,"shell.erl"},{line,627}]}]}}
    +Example:

    > catch error(foobar).
    +{'EXIT',{foobar,[{shell,apply_fun,3,
    +                        [{file,"shell.erl"},{line,906}]},
    +                 {erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,677}]},
    +                 {erl_eval,expr,5,[{file,"erl_eval.erl"},{line,430}]},
    +                 {shell,exprs,7,[{file,"shell.erl"},{line,687}]},
    +                 {shell,eval_exprs,7,[{file,"shell.erl"},{line,642}]},
    +                 {shell,eval_loop,3,[{file,"shell.erl"},{line,627}]}]}}
    @@ -12866,13 +12867,13 @@

    error(Reason, Args)

    has happened (for example, a function is called with a parameter that has an incorrect type). See the guide about errors and error handling for additional information. -Example:

    test.erl:

    -module(test).
    --export([example_fun/2]).
    +Example:

    test.erl:

    -module(test).
    +-export([example_fun/2]).
     
    -example_fun(A1, A2) ->
    -    erlang:error(my_error, [A1, A2]).

    Erlang shell:

    6> c(test).
    -{ok,test}
    -7> test:example_fun(arg1,"this is the second argument").
    +example_fun(A1, A2) ->
    +    erlang:error(my_error, [A1, A2]).

    Erlang shell:

    6> c(test).
    +{ok,test}
    +7> test:example_fun(arg1,"this is the second argument").
     ** exception error: my_error
          in function  test:example_fun/2
              called as test:example_fun(arg1,"this is the second argument")
    @@ -12961,10 +12962,10 @@

    exit(Reason)

    stopped (for example when a message telling a process to stop is received).

    This function differ from error/1,2,3 by causing an exception of a different class and by having a reason that does not include the list of functions from the call stack.

    See the guide about errors and error handling for -additional information.

    Example:

    > exit(foobar).
    +additional information.

    Example:

    > exit(foobar).
     ** exception exit: foobar
    -> catch exit(foobar).
    -{'EXIT',foobar}

    Note

    If a process calls exit(kill) and does not catch the exception, +> catch exit(foobar). +{'EXIT',foobar}

    Note

    If a process calls exit(kill) and does not catch the exception, it will terminate with exit reason kill and also emit exit signals with exit reason kill (not killed) to all linked processes. Such exit signals with exit reason kill can be trapped by the linked processes. Note that this @@ -13175,11 +13176,11 @@

    get()

    Returns the process dictionary as a list of {Key, Val} tuples. The items in -the returned list can be in any order.

    For example:

    > put(key1, merry),
    -put(key2, lambs),
    -put(key3, {are, playing}),
    -get().
    -[{key1,merry},{key2,lambs},{key3,{are,playing}}]
    +the returned list can be in any order.

    For example:

    > put(key1, merry),
    +put(key2, lambs),
    +put(key3, {are, playing}),
    +get().
    +[{key1,merry},{key2,lambs},{key3,{are,playing}}]
    @@ -13212,11 +13213,11 @@

    get(Key)

    Returns the value Val associated with Key in the process dictionary, or undefined if Key does not exist.

    The expected time complexity for the current implementation of this function is O(1) and the worst case time complexity is O(N), where N is the number of -items in the process dictionary.

    For example:

    > put(key1, merry),
    -put(key2, lambs),
    -put({any, [valid, term]}, {are, playing}),
    -get({any, [valid, term]}).
    -{are,playing}
    +items in the process dictionary.

    For example:

    > put(key1, merry),
    +put(key2, lambs),
    +put({any, [valid, term]}, {are, playing}),
    +get({any, [valid, term]}).
    +{are,playing}
    @@ -13249,11 +13250,11 @@

    get_keys()

    Returns a list of all keys present in the process dictionary. The items in the -returned list can be in any order.

    For example:

    > put(dog, {animal,1}),
    -put(cow, {animal,2}),
    -put(lamb, {animal,3}),
    -get_keys().
    -[dog,cow,lamb]
    +returned list can be in any order.

    For example:

    > put(dog, {animal,1}),
    +put(cow, {animal,2}),
    +put(lamb, {animal,3}),
    +get_keys().
    +[dog,cow,lamb]
    @@ -13284,14 +13285,14 @@

    get_keys(Val)

    Returns a list of keys that are associated with the value Val in the process -dictionary. The items in the returned list can be in any order.

    For example:

    > put(mary, {1, 2}),
    -put(had, {1, 2}),
    -put(a, {1, 2}),
    -put(little, {1, 2}),
    -put(dog, {1, 3}),
    -put(lamb, {1, 2}),
    -get_keys({1, 2}).
    -[mary,had,a,little,lamb]
    +dictionary. The items in the returned list can be in any order.

    For example:

    > put(mary, {1, 2}),
    +put(had, {1, 2}),
    +put(a, {1, 2}),
    +put(little, {1, 2}),
    +put(dog, {1, 3}),
    +put(lamb, {1, 2}),
    +get_keys({1, 2}).
    +[mary,had,a,little,lamb]
    @@ -13454,9 +13455,9 @@

    is_process_alive(Pid)

    aliveness of P2 is checked. This guarantee means that one can use is_process_alive/1 to let a process P1 wait until a process P2, which has got an exit signal with reason kill from P1, is -killed.

    For example:

    exit(P2Pid, kill),
    +killed.

    For example:

    exit(P2Pid, kill),
     % P2 might not be killed
    -is_process_alive(P2Pid),
    +is_process_alive(P2Pid),
     % P2 is not alive (the call above always return false)

    See the documentation about signals and erlang:exit/2 for more information about signals and exit signals.

    @@ -13549,7 +13550,7 @@

    monitor(Type, Item)

    Sends a monitor request of type Type to the entity identified by Item.

    If the monitored entity does not exist or it changes monitored state, the caller -of monitor/2 is notified by a message on the following format:

    {Tag, MonitorRef, Type, Object, Info}

    Note

    The monitor request is an asynchronous signal. That is, it takes time before +of monitor/2 is notified by a message on the following format:

    {Tag, MonitorRef, Type, Object, Info}

    Note

    The monitor request is an asynchronous signal. That is, it takes time before the signal reaches its destination.

    Type can be one of the following atoms: process, port or time_offset.

    A process or port monitor is triggered only once, after that it is removed from both monitoring process and the monitored entity. Monitors are fired when the monitored process or port terminates, does not exist at the moment of @@ -13558,7 +13559,7 @@

    monitor(Type, Item)

    demonitor/1 is called.

    A process or port monitor by name resolves the RegisteredName to pid/0 or port/0 only once at the moment of monitor instantiation, later changes to the name registration will not affect the existing monitor.

    When a process or port monitor is triggered, a 'DOWN' message is sent that -has the following pattern:

    {'DOWN', MonitorRef, Type, Object, Info}

    In the monitor message MonitorRef and Type are the same as described +has the following pattern:

    {'DOWN', MonitorRef, Type, Object, Info}

    In the monitor message MonitorRef and Type are the same as described earlier, and:

    • Object - The monitored entity, which triggered the event. When monitoring a process or a local port, Object will be equal to the pid/0 or port/0 that was being monitored. When monitoring process or port by @@ -13602,7 +13603,7 @@

      monitor(Type, Item)

      under normal operation this is to be detected within a minute, but during heavy load it can take longer time.

      The monitor is not automatically removed after it has been triggered. That is, repeated changes of the time offset trigger the monitor repeatedly.

      When the monitor is triggered a 'CHANGE' message is sent to the monitoring -process. A 'CHANGE' message has the following pattern:

      {'CHANGE', MonitorRef, Type, Item, NewTimeOffset}

      where MonitorRef, Type, and Item are the same as described above, and +process. A 'CHANGE' message has the following pattern:

      {'CHANGE', MonitorRef, Type, Item, NewTimeOffset}

      where MonitorRef, Type, and Item are the same as described above, and NewTimeOffset is the new time offset.

      When the 'CHANGE' message has been received you are guaranteed not to retrieve the old time offset when calling erlang:time_offset/0. Notice that you can observe the @@ -13668,25 +13669,25 @@

      monitor(Type, Item, Opts)

      monitor will be automatically removed regardless of whether the response is a reply or a 'DOWN' message. The alias can also still be deactivated via a call to unalias/1. Note that if the alias is removed using -the unalias/1 BIF, the monitor will still be left active.

    Example:

    server() ->
    +the unalias/1 BIF, the monitor will still be left active.

    Example:

    server() ->
         receive
    -        {request, AliasReqId, Request} ->
    -            Result = perform_request(Request),
    -            AliasReqId ! {reply, AliasReqId, Result}
    +        {request, AliasReqId, Request} ->
    +            Result = perform_request(Request),
    +            AliasReqId ! {reply, AliasReqId, Result}
         end,
    -    server().
    +    server().
     
    -client(ServerPid, Request) ->
    -    AliasMonReqId = monitor(process, ServerPid, [{alias, reply_demonitor}]),
    -    ServerPid ! {request, AliasMonReqId, Request},
    +client(ServerPid, Request) ->
    +    AliasMonReqId = monitor(process, ServerPid, [{alias, reply_demonitor}]),
    +    ServerPid ! {request, AliasMonReqId, Request},
         %% Alias as well as monitor will be automatically deactivated if we
         %% receive a reply or a 'DOWN' message since we used 'reply_demonitor'
         %% as unalias option...
         receive
    -        {reply, AliasMonReqId, Result} ->
    +        {reply, AliasMonReqId, Result} ->
                 Result;
    -        {'DOWN', AliasMonReqId, process, ServerPid, ExitReason} ->
    -            error(ExitReason)
    +        {'DOWN', AliasMonReqId, process, ServerPid, ExitReason} ->
    +            error(ExitReason)
         end.

    Note that both the server and the client in this example must be executing on at least OTP 24 systems in order for this to work.

    For more information on process aliases see the Process Aliases section @@ -13696,42 +13697,42 @@

    monitor(Type, Item, Opts)

    in the down message will be replaced by UserDefinedTag.

    An example of how the {tag, UserDefinedTag} option can be used in order to enable the new selective receive optimization, -introduced in OTP 24, when making multiple requests to different servers:

    server() ->
    +introduced in OTP 24, when making multiple requests to different servers:

    server() ->
         receive
    -        {request, From, ReqId, Request} ->
    -            Result = perform_request(Request),
    -            From ! {reply, self(), ReqId, Result}
    +        {request, From, ReqId, Request} ->
    +            Result = perform_request(Request),
    +            From ! {reply, self(), ReqId, Result}
         end,
    -    server().
    -
    -client(ServerPids, Request) when is_list(ServerPids) ->
    -    ReqId = make_ref(),
    -    lists:foreach(fun (ServerPid) ->
    -                          _ = monitor(process, ServerPid,
    -                                      [{tag, {'DOWN', ReqId}}]),
    -                          ServerPid ! {request, self(), ReqId, Request}
    +    server().
    +
    +client(ServerPids, Request) when is_list(ServerPids) ->
    +    ReqId = make_ref(),
    +    lists:foreach(fun (ServerPid) ->
    +                          _ = monitor(process, ServerPid,
    +                                      [{tag, {'DOWN', ReqId}}]),
    +                          ServerPid ! {request, self(), ReqId, Request}
                       end,
    -                  ServerPids),
    -    receive_replies(ReqId, length(ServerPids), []).
    +                  ServerPids),
    +    receive_replies(ReqId, length(ServerPids), []).
     
    -receive_replies(_ReqId, 0, Acc) ->
    +receive_replies(_ReqId, 0, Acc) ->
         Acc;
    -receive_replies(ReqId, N, Acc) ->
    +receive_replies(ReqId, N, Acc) ->
         %% The compiler will detect that we match on the 'ReqId'
         %% reference in all clauses, and will enable the selective
         %% receive optimization which makes the receive able to
         %% skip past all messages present in the message queue at
         %% the time when the 'ReqId' reference was created...
         Res = receive
    -              {reply, ServerPid, ReqId, Result} ->
    +              {reply, ServerPid, ReqId, Result} ->
                       %% Here we typically would have deactivated the
                       %% monitor by a call to demonitor(Mon, [flush]) but
                       %% we ignore this in this example for simplicity...
    -                  {ok, ServerPid, Result};
    -              {{'DOWN', ReqId}, _Mon, process, ServerPid, ExitReason} ->
    -                  {error, ServerPid, ExitReason}
    +                  {ok, ServerPid, Result};
    +              {{'DOWN', ReqId}, _Mon, process, ServerPid, ExitReason} ->
    +                  {error, ServerPid, ExitReason}
               end,
    -    receive_replies(ReqId, N-1, [Res | Acc]).

    In order for this example to work as intended, the client must be executing on + receive_replies(ReqId, N-1, [Res | Acc]).

    In order for this example to work as intended, the client must be executing on at least an OTP 24 system, but the servers may execute on older systems.

    @@ -14006,7 +14007,7 @@

    open_port(PortName, PortSettings)

    port_call(Port, Operation, Data)

    - + View Source @@ -14046,7 +14047,7 @@

    port_call(Port, Operation, Data)

    port_close(Port)

    - + View Source @@ -14094,7 +14095,7 @@

    port_close(Port)

    port_command(Port, Data)

    - + View Source @@ -14140,7 +14141,7 @@

    port_command(Port, Data)

    port_command(Port, Data, OptionList)

    - + View Source @@ -14187,7 +14188,7 @@

    port_command(Port, Data, OptionList)

    port_connect(Port, Pid)

    - + View Source @@ -14237,7 +14238,7 @@

    port_connect(Port, Pid)

    port_control(Port, Operation, Data)

    - + View Source @@ -14277,7 +14278,7 @@

    port_control(Port, Operation, Data)

    port_info(Port)

    - + View Source @@ -14321,7 +14322,7 @@

    port_info(Port)

    port_info(Port, Item)

    - + View Source @@ -14473,7 +14474,7 @@

    process_flag(Flag, Value)

    Sets the process flag indicated to the specified value. Returns the previous value -of the flag.

    Flag is one of the following:

    • process_flag(async_dist, boolean())

      Enable or disable fully asynchronous distributed signaling for the calling +of the flag.

      Flag is one of the following:

      • process_flag(async_dist, boolean())

        Enable or disable fully asynchronous distributed signaling for the calling process. When disabled, which is the default, the process sending a distributed signal will block in the send operation if the buffer for the distribution channel reach the distribution buffer busy limit. The @@ -14498,14 +14499,14 @@

        process_flag(Flag, Value)

        command line argument +pad <boolean> when starting the runtime system. If the +pad <boolean> command line argument is not passed, the default value of the async_dist flag will be false.

        You can inspect the state of the async_dist process flag of a process by -calling process_info(Pid, async_dist).

      • process_flag(trap_exit, boolean())

        When trap_exit is set to true, exit signals arriving to a process are +calling process_info(Pid, async_dist).

      • process_flag(trap_exit, boolean())

        When trap_exit is set to true, exit signals arriving to a process are converted to {'EXIT', From, Reason} messages, which can be received as ordinary messages. If trap_exit is set to false, the process exits if it receives an exit signal other than normal and the exit signal is propagated to -its linked processes. Application processes are normally not to trap exits.

        See also exit/2.

      • process_flag(error_handler, module())

        Used by a process to redefine the error_handler for undefined function calls and +its linked processes. Application processes are normally not to trap exits.

        See also exit/2.

      • process_flag(error_handler, module())

        Used by a process to redefine the error_handler for undefined function calls and undefined registered processes. Use this flag with substantial caution, as code -auto-loading depends on the correct operation of the error handling module.

      • process_flag(fullsweep_after,  non_neg_integer())

        Changes the maximum number of generational collections before forcing a -fullsweep for the calling process.

      • process_flag(min_heap_size, non_neg_integer())

        Changes the minimum heap size for the calling process.

      • process_flag(min_bin_vheap_size, non_neg_integer())

        Changes the minimum binary virtual heap size for the calling process.

      • process_flag(max_heap_size, max_heap_size())

        This flag sets the maximum heap size for the calling process. If MaxHeapSize +auto-loading depends on the correct operation of the error handling module.

      • process_flag(fullsweep_after,  non_neg_integer())

        Changes the maximum number of generational collections before forcing a +fullsweep for the calling process.

      • process_flag(min_heap_size, non_neg_integer())

        Changes the minimum heap size for the calling process.

      • process_flag(min_bin_vheap_size, non_neg_integer())

        Changes the minimum binary virtual heap size for the calling process.

      • process_flag(max_heap_size, max_heap_size())

        This flag sets the maximum heap size for the calling process. If MaxHeapSize is an integer, the system default values for kill and error_logger are used.

        For details on how the heap grows, see Sizing the heap in the ERTS internal documentation.

        • size - The maximum size in words of the process. If set to zero, the @@ -14541,7 +14542,7 @@

          process_flag(Flag, Value)

          memory that is used during the garbage collection. When contemplating using this option, it is recommended to first run it in production with kill set to false and inspect the log events to see what the normal peak sizes of the -processes in the system is and then tune the value accordingly.

        • process_flag(message_queue_data, message_queue_data())

          Determines how messages in the message queue are stored, as follows:

          • off_heap - All messages in the message queue will be stored outside +processes in the system is and then tune the value accordingly.

          • process_flag(message_queue_data, message_queue_data())

            Determines how messages in the message queue are stored, as follows:

            • off_heap - All messages in the message queue will be stored outside the process heap. This implies that no messages in the message queue will be part of a garbage collection of the process.

            • on_heap - All messages in the message queue will eventually be placed on the process heap. They can, however, be temporarily stored off the heap. This @@ -14553,7 +14554,7 @@

              process_flag(Flag, Value)

              consume large amounts of memory. The performance of the actual message passing is, however, generally better when the flag value is on_heap.

              Changing the flag value causes any existing messages to be moved. The move operation is initiated, but not necessarily completed, by the time the function -returns.

            • process_flag(priority, priority_level())

              Sets the process priority. Level is an atom. Four priority levels exist: +returns.

            • process_flag(priority, priority_level())

              Sets the process priority. Level is an atom. Four priority levels exist: low, normal, high, and max. Default is normal.

              Note

              Priority level max is reserved for internal use in the Erlang runtime system, and is not to be used by others.

              Internally in each priority level, processes are scheduled in a round robin fashion.

              Execution of processes on priority normal and low are interleaved. Processes @@ -14582,7 +14583,7 @@

              process_flag(Flag, Value)

              are used, use them with care, especially priority high. A process on priority high is only to perform work for short periods. Busy looping for long periods in a high priority process causes most likely problems, as important -OTP servers run on priority normal.

            • process_flag(save_calls, 0..10000)

              N must be an integer in the interval 0..10000. If N > 0, call saving is made +OTP servers run on priority normal.

            • process_flag(save_calls, 0..10000)

              N must be an integer in the interval 0..10000. If N > 0, call saving is made active for the process. This means that information about the N most recent global function calls, BIF calls, sends, and receives made by the process are saved in a list, which can be retrieved with @@ -14591,7 +14592,7 @@

              process_flag(Flag, Value)

              amount of information is saved, as follows:

              • A tuple {Module, Function, Arity} for function calls
              • The atoms send, 'receive', and timeout for sends and receives ('receive' when a message is received and timeout when a receive times out)

              If N = 0, call saving is disabled for the process, which is the default. -Whenever the size of the call saving list is set, its contents are reset.

            • process_flag(sensitive, boolean())

              Sets or clears flag sensitive for the current process. When a process has been +Whenever the size of the call saving list is set, its contents are reset.

            • process_flag(sensitive, boolean())

              Sets or clears flag sensitive for the current process. When a process has been marked as sensitive by calling process_flag(sensitive, true), features in the runtime system that can be used for examining the data or inner working of the process @@ -14690,7 +14691,7 @@

              process_info(Pid)

              process_info(Pid, ItemSpec)

              - + View Source @@ -14769,7 +14770,8 @@

              process_info(Pid, ItemSpec)

              information is highly implementation-dependent, and can change if the implementation changes.

            • {initial_call, {Module, Function, Arity}} - Module, Function, Arity is the initial function call with which the process was spawned.

            • {links, PidsAndPorts} - PidsAndPorts is a list of process identifiers -and port identifiers, with processes or ports to which the process has a link.

            • {last_calls, false|Calls} - The value is false if call saving is not +and port identifiers, with processes or ports to which the process has a link.

            • {label, Label} - +Label is the label for the process. See proc_lib:get_label/1.

              Since: OTP 27.2

            • {last_calls, false|Calls} - The value is false if call saving is not active for the process (see process_flag/3). If call saving is active, a list is returned, in which the last element is the most recent called.

            • {memory, Size} - Size is the size in bytes of the process. This includes call stack, heap, and internal structures.

            • {message_queue_len, MessageQueueLen} - MessageQueueLen is the number @@ -14850,8 +14852,8 @@

              processes()

              currently existing on the local node.

              Notice that an exiting process exists, but is not alive. That is, is_process_alive/1 returns false for an exiting process, but its process identifier is part of the result returned from -processes/0.

              Example:

              > processes().
              -[<0.0.0>,<0.2.0>,<0.4.0>,<0.5.0>,<0.7.0>,<0.8.0>]
              +processes/0.

              Example:

              > processes().
              +[<0.0.0>,<0.2.0>,<0.4.0>,<0.5.0>,<0.7.0>,<0.8.0>]
              @@ -14885,10 +14887,10 @@

              put(Key, Val)

              returns undefined. If Key exists, the old value is deleted and replaced by Val, and the function returns the old value.

              The average time complexity for the current implementation of this function is O(1) and the worst case time complexity is O(N), where N is the number of -items in the process dictionary.

              For example:

              > X = put(name, walrus), Y = put(name, carpenter),
              -Z = get(name),
              -{X, Y, Z}.
              -{undefined,walrus,carpenter}

              Note

              The values stored when put is evaluated within the scope of a catch are +items in the process dictionary.

              For example:

              > X = put(name, walrus), Y = put(name, carpenter),
              +Z = get(name),
              +{X, Y, Z}.
              +{undefined,walrus,carpenter}

              Note

              The values stored when put is evaluated within the scope of a catch are not retracted if a throw is evaluated, or if an error occurs.

              @@ -14971,7 +14973,7 @@

              register(RegName, PidOrPort)

              name registry. RegName, which must be an atom, can be used instead of the pid or port identifier in send operator (RegName ! Message) and most other BIFs that take -a pid or port identifies as an argument.

              For example:

              > register(db, Pid).
              +a pid or port identifies as an argument.

              For example:

              > register(db, Pid).
               true

              The registered name is considered a Directly Visible Erlang Resource and is automatically unregistered when the process terminates.

              Failures:

              • badarg - If PidOrPort is not an existing local process or port.

              • badarg - If RegName is already in use.

              • badarg - If the process or port is already registered (already has a @@ -15005,8 +15007,8 @@

                registered()

                -

                Returns a list of names that have been registered using register/2.

                For example:

                > registered().
                -[code_server, file_server, init, user, my_db]
                +

                Returns a list of names that have been registered using register/2.

                For example:

                > registered().
                +[code_server, file_server, init, user, my_db]
                @@ -15073,7 +15075,7 @@

                self()

                -

                Returns the process identifier of the calling process.

                For example:

                > self().
                +

                Returns the process identifier of the calling process.

                For example:

                > self().
                 <0.26.0>
                @@ -15086,7 +15088,7 @@

                self()

                send(Dest, Msg)

                - + View Source @@ -15121,7 +15123,7 @@

                send(Dest, Msg)

                send(Dest, Msg, Options)

                - + View Source @@ -15160,7 +15162,7 @@

                send(Dest, Msg, Options)

                send_nosuspend(Dest, Msg)

                - + View Source @@ -15208,7 +15210,7 @@

                send_nosuspend(Dest, Msg)

                send_nosuspend(Dest, Msg, Options)

                - + View Source @@ -15248,7 +15250,7 @@

                send_nosuspend(Dest, Msg, Options)

                spawn(Fun)

                - + View Source @@ -15279,7 +15281,7 @@

                spawn(Fun)

                spawn(Node, Fun)

                - + View Source @@ -15337,7 +15339,7 @@

                spawn(Module, Function, Args)

                (see process_flag/2). If error_handler is undefined, or the user has redefined the default error_handler and its replacement is undefined, a failure with reason undef -occurs.

                Example:

                > spawn(speed, regulator, [high_speed, thin_cut]).
                +occurs.

                Example:

                > spawn(speed, regulator, [high_speed, thin_cut]).
                 <0.13.1>
                @@ -15350,7 +15352,7 @@

                spawn(Module, Function, Args)

                spawn(Node, Module, Function, Args)

                - + View Source @@ -15383,7 +15385,7 @@

                spawn(Node, Module, Function, Args)

                spawn_link(Fun)

                - + View Source @@ -15415,7 +15417,7 @@

                spawn_link(Fun)

                spawn_link(Node, Fun)

                - + View Source @@ -15482,7 +15484,7 @@

                spawn_link(Module, Function, Args)

                spawn_link(Node, Module, Function, Args)

                - + View Source @@ -15517,7 +15519,7 @@

                spawn_link(Node, Module, Function, Args)

                spawn_monitor(Fun)

                - + View Source @@ -15549,7 +15551,7 @@

                spawn_monitor(Fun)

                spawn_monitor(Node, Fun)

                - + View Source @@ -15584,7 +15586,7 @@

                spawn_monitor(Node, Fun)

                spawn_monitor(Module, Function, Args)

                - + View Source @@ -15617,7 +15619,7 @@

                spawn_monitor(Module, Function, Args)

                spawn_monitor(Node, Module, Function, Args)

                - + View Source @@ -15653,7 +15655,7 @@

                spawn_monitor(Node, Module, Function, Args)

                spawn_opt(Fun, Options)

                - + View Source @@ -15686,7 +15688,7 @@

                spawn_opt(Fun, Options)

                spawn_opt(Node, Fun, Options)

                - + View Source @@ -15725,7 +15727,7 @@

                spawn_opt(Node, Fun, Options)

                spawn_opt(Module, Function, Args, Options)

                - + View Source @@ -15809,7 +15811,7 @@

                spawn_opt(Module, Function, Args, Options)<

                spawn_opt(Node, Module, Function, Args, Options)

                - + View Source @@ -15850,7 +15852,7 @@

                spawn_opt(Node, Module, Function, Args, Opt

                spawn_request(Fun)

                - + View Source @@ -15883,7 +15885,7 @@

                spawn_request(Fun)

                spawn_request(FunOrNode, OptionsOrFun)

                - + View Source @@ -15924,7 +15926,7 @@

                spawn_request(FunOrNode, OptionsOrFun)

                spawn_request(NodeOrModule, FunOrFunction, OptionsOrArgs)

                - + View Source @@ -15980,7 +15982,7 @@

                spawn_request(NodeOrModule, FunOrFunction,

                spawn_request(NodeOrModule, ModuleOrFunction, FunctionOrArgs, ArgsOrOptions)

                - + View Source @@ -16031,7 +16033,7 @@

                spawn_request(NodeOrModule, ModuleOrFunctio

                spawn_request(Node, Module, Function, Args, Options)

                - + View Source @@ -16157,7 +16159,7 @@

                spawn_request(Node, Module, Function, Args,

                spawn_request_abandon(ReqId)

                - + View Source @@ -16329,14 +16331,14 @@

                throw(Any)

                Raises an exception of class throw. Intended to be used to do non-local returns from functions.

                If evaluated within a catch expression, the -catch expression returns value Any.

                For example:

                > catch throw({hello, there}).
                -        {hello,there}

                If evaluated within a try-block of a +catch expression returns value Any.

                For example:

                > catch throw({hello, there}).
                +        {hello,there}

                If evaluated within a try-block of a try expression, the value Any can be caught within the catch block.

                For example:

                try
                -    throw({my_exception, "Something happened"})
                +    throw({my_exception, "Something happened"})
                 catch
                -    throw:{my_exception, Desc} ->
                -        io:format(standard_error, "Error: ~s~n", [Desc])
                +    throw:{my_exception, Desc} ->
                +        io:format(standard_error, "Error: ~s~n", [Desc])
                 end

                Failure: nocatch if not caught by an exception handler.

                See the guide about errors and error handling for additional information.

                @@ -16418,9 +16420,9 @@

                unlink(Id)

                result of the link, but may also be the result of the unlikee sending the caller an exit signal by calling the exit/2 BIF. Therefore, it may or may not be appropriate to clean up the message queue after a call to -unlink(Id) as follows, when trapping exits:

                unlink(Id),
                +unlink(Id) as follows, when trapping exits:

                unlink(Id),
                 receive
                -    {'EXIT', Id, _} ->
                +    {'EXIT', Id, _} ->
                         true
                 after 0 ->
                         true
                @@ -16461,7 +16463,7 @@ 

                unregister(RegName)

                Removes the registered name RegName associated with a process identifier or a port identifier from the -name registry.

                For example:

                > unregister(db).
                +name registry.

                For example:

                > unregister(db).
                 true

                Keep in mind that you can still receive signals associated with the registered name after it has been unregistered as the sender may have looked up the name before sending to it.

                Users are advised not to unregister system processes.

                Failure: badarg if RegName is not a registered name.

                @@ -16497,7 +16499,7 @@

                whereis(RegName)

                Returns the process identifier or port identifier with the registered name RegName from the name registry. Returns -undefined if the name is not registered.

                For example:

                > whereis(db).
                +undefined if the name is not registered.

                For example:

                > whereis(db).
                 <0.43.0>
                @@ -16510,7 +16512,7 @@

                whereis(RegName)

                yield()

                - + View Source @@ -16576,7 +16578,7 @@

                halt()

                -

                Equivalent to calling halt(0, []).

                For example:

                > halt().
                +

                Equivalent to calling halt(0, []).

                For example:

                > halt().
                 os_prompt%
                @@ -16609,7 +16611,7 @@

                halt(HaltType)

                -

                Equivalent to calling halt(HaltType, []).

                For example:

                > halt(17).
                +

                Equivalent to calling halt(HaltType, []).

                For example:

                > halt(17).
                 os_prompt% echo $?
                 17
                 os_prompt%
                @@ -16646,7 +16648,7 @@

                halt/2

                -

                Halt the runtime system.

                • halt(Status :: non_neg_integer(), Options :: halt_options())

                  Halt the runtime system with status code Status.

                  Note

                  On many platforms, the OS supports only status codes 0-255. A too large +

                  Halt the runtime system.

                  • halt(Status :: non_neg_integer(), Options :: halt_options())

                    Halt the runtime system with status code Status.

                    Note

                    On many platforms, the OS supports only status codes 0-255. A too large status code is truncated by clearing the high bits.

                    Currently the following options are valid:

                    • {flush, EnableFlushing} - If EnableFlushing equals true, which also is the default behavior, the runtime system will perform the following operations before terminating:

                      • Flush all outstanding output.
                      • Send all Erlang ports exit signals and wait for them to exit.
                      • Wait for all async threads to complete all outstanding async jobs.
                      • Call all installed NIF on halt callbacks.
                      • Wait for all ongoing @@ -16663,10 +16665,10 @@

                        halt/2

                        with the exit code 255. If flushing is not enabled, the timeout will have no effect on the system.

                        See also the erl +zhft <Timeout> command line flag. Note that the shortest timeout set by the command line flag and the -flush_timeout option will be the actual timeout value in effect.

                        Since: OTP 27.0

                    • halt(Abort :: abort, Options :: halt_options())

                      Halt the Erlang runtime system by aborting and produce a core dump if core +flush_timeout option will be the actual timeout value in effect.

                      Since: OTP 27.0

                  • halt(Abort :: abort, Options :: halt_options())

                    Halt the Erlang runtime system by aborting and produce a core dump if core dumping has been enabled in the environment that the runtime system is executing in.

                    Note

                    The {flush, boolean()} option will be ignored, and -flushing will be disabled.

                  • halt(CrashDumpSlogan :: string(), Options :: halt_options())

                    Halt the Erlang runtime system and generate an +flushing will be disabled.

                • halt(CrashDumpSlogan :: string(), Options :: halt_options())

                  Halt the Erlang runtime system and generate an Erlang crash dump. The string CrashDumpSlogan will be used as slogan in the Erlang crash dump created. The slogan will be trunkated if CrashDumpSlogan is longer than 1023 characters.

                  Note

                  The {flush, boolean()} option will be ignored, and @@ -16685,7 +16687,7 @@

                  halt/2

                  memory()

                  - + View Source @@ -16751,7 +16753,7 @@

                  memory()

                  memory/1

                  - + View Source @@ -16787,7 +16789,7 @@

                  memory/1

                  statistics(Item)

                  - + View Source @@ -16857,11 +16859,11 @@

                  statistics(Item)

                  -

                  Returns statistics about the current system.

                  The possible flags are:

                  • statistics(active_tasks) -> [non_neg_integer()]

                    Returns the same as +

                    Returns statistics about the current system.

                    The possible flags are:

                    • statistics(active_tasks) -> [non_neg_integer()]

                      Returns the same as statistics(active_tasks_all) with the exception that no information about the dirty IO run queue and its associated schedulers is part of the result. That is, only tasks that are -expected to be CPU bound are part of the result.

                      Available since OTP 18.3

                    • statistics(active_tasks_all) -> [non_neg_integer()]

                      Returns a list where each element represents the amount of active processes and +expected to be CPU bound are part of the result.

                      Available since OTP 18.3

                    • statistics(active_tasks_all) -> [non_neg_integer()]

                      Returns a list where each element represents the amount of active processes and ports on each run queue and its associated schedulers. That is, the number of processes and ports that are ready to run, or are currently running. Values for normal run queues and their associated schedulers are located first in the @@ -16883,11 +16885,11 @@

                      statistics(Item)

                      statistics(run_queue_lengths_all), statistics(total_run_queue_lengths), and -statistics(total_run_queue_lengths_all).

                      Available since OTP 20.0

                    • statistics(context_switches) -> {non_neg_integer(), 0}

                      Returns the total number of context switches since the system started.

                    • statistics(exact_reductions) -> {Total :: non_neg_integer(), SinceLastCall :: non_neg_integer()}

                      Returns the number of exact reductions.

                      Note

                      statistics(exact_reductions) is a more expensive operation -than statistics(reductions).

                    • statistics(garbage_collection) ->
                      -  { NumerOfGCs :: non_neg_integer(), WordsReclaimed :: non_neg_integer(), 0}

                      Returns information about garbage collection, for example:

                      > statistics(garbage_collection).
                      -{85,23961,0}

                      This information can be invalid for some implementations.

                    • statistics(io) -> {{input, non_neg_integer()}, {output, non_neg_integer()}}

                      Returns Input, which is the total number of bytes received through ports, and -Output, which is the total number of bytes output to ports.

                    • statistics(microstate_accounting) -> [MSAcc_Thread]

                      Microstate accounting can be used to measure how much time the Erlang runtime +statistics(total_run_queue_lengths_all).

                      Available since OTP 20.0

                    • statistics(context_switches) -> {non_neg_integer(), 0}

                      Returns the total number of context switches since the system started.

                    • statistics(exact_reductions) -> {Total :: non_neg_integer(), SinceLastCall :: non_neg_integer()}

                      Returns the number of exact reductions.

                      Note

                      statistics(exact_reductions) is a more expensive operation +than statistics(reductions).

                    • statistics(garbage_collection) ->
                      +  { NumerOfGCs :: non_neg_integer(), WordsReclaimed :: non_neg_integer(), 0}

                      Returns information about garbage collection, for example:

                      > statistics(garbage_collection).
                      +{85,23961,0}

                      This information can be invalid for some implementations.

                    • statistics(io) -> {{input, non_neg_integer()}, {output, non_neg_integer()}}

                      Returns Input, which is the total number of bytes received through ports, and +Output, which is the total number of bytes output to ports.

                    • statistics(microstate_accounting) -> [MSAcc_Thread]

                      Microstate accounting can be used to measure how much time the Erlang runtime system spends doing various tasks. It is designed to be as lightweight as possible, but some overhead exists when this is enabled. Microstate accounting is meant to be a profiling tool to help finding performance bottlenecks. To @@ -16896,23 +16898,23 @@

                      statistics(Item)

                      representing some of the OS threads within ERTS. Each map contains type and id fields that can be used to identify what thread it is, and also a counters field that contains data about how much time has been spent in the various -states.

                      Example:

                      > erlang:statistics(microstate_accounting).
                      -[#{counters => #{aux => 1899182914,
                      +states.

                      Example:

                      > erlang:statistics(microstate_accounting).
                      +[#{counters => #{aux => 1899182914,
                                        check_io => 2605863602,
                                        emulator => 45731880463,
                                        gc => 1512206910,
                                        other => 5421338456,
                                        port => 221631,
                      -                 sleep => 5150294100},
                      +                 sleep => 5150294100},
                          id => 1,
                      -   type => scheduler}|...]

                      The time unit is the same as returned by os:perf_counter/0. So, to convert it -to milliseconds, you can do something like this:

                      lists:map(
                      -  fun(#{ counters := Cnt } = M) ->
                      -         MsCnt = maps:map(fun(_K, PerfCount) ->
                      -                                    erlang:convert_time_unit(PerfCount, perf_counter, 1000)
                      -                           end, Cnt),
                      -         M#{ counters := MsCnt }
                      -  end, erlang:statistics(microstate_accounting)).

                      Notice that these values are not guaranteed to be the exact time spent in each + type => scheduler}|...]

                      The time unit is the same as returned by os:perf_counter/0. So, to convert it +to milliseconds, you can do something like this:

                      lists:map(
                      +  fun(#{ counters := Cnt } = M) ->
                      +         MsCnt = maps:map(fun(_K, PerfCount) ->
                      +                                    erlang:convert_time_unit(PerfCount, perf_counter, 1000)
                      +                           end, Cnt),
                      +         M#{ counters := MsCnt }
                      +  end, erlang:statistics(microstate_accounting)).

                      Notice that these values are not guaranteed to be the exact time spent in each state. This is because of various optimisation done to keep the overhead as small as possible.

                      MSAcc_Thread_Types:

                      • scheduler - The main execution threads that do most of the work. See erl +S for more details.

                      • dirty_cpu_scheduler - The threads for long running cpu intensive work. @@ -16944,20 +16946,20 @@

                        statistics(Item)

                        statistics.

                        Returns undefined if system flag microstate_accounting is turned off.

                        The list of thread information is unsorted and can appear in different order -between calls.

                        Note

                        The threads and states are subject to change without any prior notice.

                        Available since OTP 19.0

                      • statistics(reductions) -> {Reductions :: non_neg_integer(), SinceLastCall :: non_neg_integer()}

                        Returns information about reductions, for example:

                        > statistics(reductions).
                        -{2046,11}

                        Change

                        As from ERTS 5.5 (Erlang/OTP R11B), this value does not include reductions +between calls.

                        Note

                        The threads and states are subject to change without any prior notice.

                        Available since OTP 19.0

                      • statistics(reductions) -> {Reductions :: non_neg_integer(), SinceLastCall :: non_neg_integer()}

                        Returns information about reductions, for example:

                        > statistics(reductions).
                        +{2046,11}

                        Change

                        As from ERTS 5.5 (Erlang/OTP R11B), this value does not include reductions performed in current time slices of currently scheduled processes. If an exact value is wanted, use -statistics(exact_reductions).

                      • statistics(run_queue) -> non_neg_integer()

                        Returns the total length of all normal and dirty CPU run queues. That is, queued +statistics(exact_reductions).

                • statistics(run_queue) -> non_neg_integer()

                  Returns the total length of all normal and dirty CPU run queues. That is, queued work that is expected to be CPU bound. The information is gathered atomically. That is, the result is a consistent snapshot of the state, but this operation is much more expensive compared to statistics(total_run_queue_lengths), -especially when a large amount of schedulers is used.

                • statistics(run_queue_lengths) -> [non_neg_integer()]

                  Returns the same as +especially when a large amount of schedulers is used.

                • statistics(run_queue_lengths) -> [non_neg_integer()]

                  Returns the same as statistics(run_queue_lengths_all) with the exception that no information about the dirty IO run queue is part of the result. That is, only run queues with work that is expected to be CPU bound -is part of the result.

                  Available since OTP 18.3

                • statistics(run_queue_lengths_all) -> [non_neg_integer()]

                  Returns a list where each element represents the amount of processes and ports +is part of the result.

                  Available since OTP 18.3

                • statistics(run_queue_lengths_all) -> [non_neg_integer()]

                  Returns a list where each element represents the amount of processes and ports ready to run for each run queue. Values for normal run queues are located first in the resulting list. The first element corresponds to the normal run queue of scheduler number 1 and so on. If support for dirty schedulers exist, values for @@ -16977,13 +16979,13 @@

                  statistics(Item)

                  statistics(active_tasks), statistics(active_tasks_all), and statistics(total_active_tasks), -statistics(total_active_tasks_all).

                  Available since OTP 20.0

                • statistics(runtime) -> {Total :: non_neg_integer(), SinceLastCall :: non_neg_integer()}

                  Returns information about runtime, in milliseconds.

                  This is the sum of the runtime for all threads in the Erlang runtime system and +statistics(total_active_tasks_all).

                  Available since OTP 20.0

                • statistics(runtime) -> {Total :: non_neg_integer(), SinceLastCall :: non_neg_integer()}

                  Returns information about runtime, in milliseconds.

                  This is the sum of the runtime for all threads in the Erlang runtime system and can therefore be greater than the wall clock time.

                  Warning

                  This value might wrap due to limitations in the underlying functionality -provided by the operating system that is used.

                  Example:

                  > statistics(runtime).
                  -{1690,1620}
                • statistics(scheduler_wall_time) ->
                  -  [{Id :: pos_integer,
                  -    ActiveTime :: non_neg_integer(),
                  -    TotalTime :: non_neg_integer()}] |
                  +provided by the operating system that is used.

                  Example:

                  > statistics(runtime).
                  +{1690,1620}
                • statistics(scheduler_wall_time) ->
                  +  [{Id :: pos_integer,
                  +    ActiveTime :: non_neg_integer(),
                  +    TotalTime :: non_neg_integer()}] |
                     undefined

                  Returns information describing how much time normal and dirty CPU schedulers in the @@ -17023,52 +17025,52 @@

                  statistics(Item)

                  This fact has to be taken under consideration when evaluating the result returned.

                  You can use scheduler_wall_time to calculate scheduler utilization. First you take a sample of the values returned by -erlang:statistics(scheduler_wall_time).

                  > erlang:system_flag(scheduler_wall_time, true).
                  +erlang:statistics(scheduler_wall_time).

                  > erlang:system_flag(scheduler_wall_time, true).
                   false
                  -> Ts0 = lists:sort(erlang:statistics(scheduler_wall_time)), ok.
                  +> Ts0 = lists:sort(erlang:statistics(scheduler_wall_time)), ok.
                   ok

                  Some time later the user takes another snapshot and calculates scheduler -utilization per scheduler, for example:

                  > Ts1 = lists:sort(erlang:statistics(scheduler_wall_time)), ok.
                  +utilization per scheduler, for example:

                  > Ts1 = lists:sort(erlang:statistics(scheduler_wall_time)), ok.
                   ok
                  -> lists:map(fun({{I, A0, T0}, {I, A1, T1}}) ->
                  -        {I, (A1 - A0)/(T1 - T0)} end, lists:zip(Ts0,Ts1)).
                  -[{1,0.9743474730177548},
                  - {2,0.9744843782751444},
                  - {3,0.9995902361669045},
                  - {4,0.9738012596572161},
                  - {5,0.9717956667018103},
                  - {6,0.9739235846420741},
                  - {7,0.973237033077876},
                  - {8,0.9741297293248656}]

                  Using the same snapshots to calculate a total scheduler utilization:

                  > {A, T} = lists:foldl(fun({{_, A0, T0}, {_, A1, T1}}, {Ai,Ti}) ->
                  -        {Ai + (A1 - A0), Ti + (T1 - T0)} end, {0, 0}, lists:zip(Ts0,Ts1)),
                  +> lists:map(fun({{I, A0, T0}, {I, A1, T1}}) ->
                  +        {I, (A1 - A0)/(T1 - T0)} end, lists:zip(Ts0,Ts1)).
                  +[{1,0.9743474730177548},
                  + {2,0.9744843782751444},
                  + {3,0.9995902361669045},
                  + {4,0.9738012596572161},
                  + {5,0.9717956667018103},
                  + {6,0.9739235846420741},
                  + {7,0.973237033077876},
                  + {8,0.9741297293248656}]

                  Using the same snapshots to calculate a total scheduler utilization:

                  > {A, T} = lists:foldl(fun({{_, A0, T0}, {_, A1, T1}}, {Ai,Ti}) ->
                  +        {Ai + (A1 - A0), Ti + (T1 - T0)} end, {0, 0}, lists:zip(Ts0,Ts1)),
                     TotalSchedulerUtilization = A/T.
                   0.9769136803764825

                  Total scheduler utilization will equal 1.0 when all schedulers have been active all the time between the two measurements.

                  Another (probably more) useful value is to calculate total scheduler utilization -weighted against maximum amount of available CPU time:

                  > WeightedSchedulerUtilization = (TotalSchedulerUtilization
                  -                                  * (erlang:system_info(schedulers)
                  -                                     + erlang:system_info(dirty_cpu_schedulers)))
                  -                                 / erlang:system_info(logical_processors_available).
                  +weighted against maximum amount of available CPU time:

                  > WeightedSchedulerUtilization = (TotalSchedulerUtilization
                  +                                  * (erlang:system_info(schedulers)
                  +                                     + erlang:system_info(dirty_cpu_schedulers)))
                  +                                 / erlang:system_info(logical_processors_available).
                   0.9769136803764825

                  This weighted scheduler utilization will reach 1.0 when schedulers are active the same amount of time as maximum available CPU time. If more schedulers exist than available logical processors, this value may be greater than 1.0.

                  As of ERTS version 9.0, the Erlang runtime system will as default have more schedulers than logical processors. This due to the dirty schedulers.

                  Note

                  scheduler_wall_time is by default disabled. To enable it, use -erlang:system_flag(scheduler_wall_time, true).

                  Available since OTP R15B01

                • statistics(scheduler_wall_time_all) ->
                  -  [{Id :: pos_integer,
                  -    ActiveTime :: non_neg_integer(),
                  -    TotalTime :: non_neg_integer()}] |
                  +erlang:system_flag(scheduler_wall_time, true).

                  Available since OTP R15B01

                • statistics(scheduler_wall_time_all) ->
                  +  [{Id :: pos_integer,
                  +    ActiveTime :: non_neg_integer(),
                  +    TotalTime :: non_neg_integer()}] |
                     undefined

                  Equivalent to statistics(scheduler_wall_time), except that it also include information about all dirty I/O schedulers.

                  Dirty IO schedulers will have scheduler identifiers in the range erlang:system_info(schedulers)+erlang:system_info(dirty_cpu_schedulers)< SchedulerId =< erlang:system_info(schedulers) + erlang:system_info(dirty_cpu_schedulers) +erlang:system_info(dirty_io_schedulers).

                  Note

                  Note that work executing on dirty I/O schedulers are expected to mainly wait for I/O. That is, when you get high scheduler utilization on dirty I/O -schedulers, CPU utilization is not expected to be high due to this work.

                  Available since OTP 20.0

                • statistics(total_active_tasks) -> non_neg_integer()

                  Equivalent to calling +schedulers, CPU utilization is not expected to be high due to this work.

                  Available since OTP 20.0

                • statistics(total_active_tasks) -> non_neg_integer()

                  Equivalent to calling lists:sum(statistics(active_tasks)), -but more efficient.

                  Available since OTP 18.3

                • statistics(total_active_tasks_all) -> non_neg_integer()

                  Equivalent to calling +but more efficient.

                  Available since OTP 18.3

                • statistics(total_active_tasks_all) -> non_neg_integer()

                  Equivalent to calling lists:sum(statistics(active_tasks_all)), -but more efficient.

                  Available since OTP 20.0

                • statistics(total_run_queue_lengths) -> non_neg_integer()

                  Equivalent to calling +but more efficient.

                  Available since OTP 20.0

                • statistics(total_run_queue_lengths) -> non_neg_integer()

                  Equivalent to calling lists:sum(statistics(run_queue_lengths)), -but more efficient.

                  Available since OTP 18.3

                • statistics(total_run_queue_lengths_all) -> non_neg_integer()

                  Equivalent to calling +but more efficient.

                  Available since OTP 18.3

                • statistics(total_run_queue_lengths_all) -> non_neg_integer()

                  Equivalent to calling lists:sum(statistics(run_queue_lengths_all)), -but more efficient.

                  Available since OTP 20.0

                • statistics(wall_clock) -> {Total :: non_neg_integer(), SinceLastCall :: non_neg_integer()}

                  Returns information about wall clock. wall_clock can be used in the same +but more efficient.

                  Available since OTP 20.0

                • statistics(wall_clock) -> {Total :: non_neg_integer(), SinceLastCall :: non_neg_integer()}

                  Returns information about wall clock. wall_clock can be used in the same manner as runtime, except that real time is measured as opposed to runtime or CPU time.

                @@ -17082,7 +17084,7 @@

                statistics(Item)

                system_flag(Flag, Value)

                - + View Source @@ -17142,9 +17144,9 @@

                system_flag(Flag, Value)

                -

                Sets a system flag to the given value.

                The possible flags to set are:

                • system_flag(backtrace_depths, non_neg_integer()) -> non_neg_integer()

                  Sets the maximum depth of call stack back-traces in the exit reason element of +

                  Sets a system flag to the given value.

                  The possible flags to set are:

                  • system_flag(backtrace_depths, non_neg_integer()) -> non_neg_integer()

                    Sets the maximum depth of call stack back-traces in the exit reason element of 'EXIT' tuples. The flag also limits the stacktrace depth returned by -process_info/2 item current_stacktrace.

                    Returns the old value of the flag.

                  • system_flag(cpu_topology, cpu_topology()) -> cpu_topology()

                    Warning

                    This argument is deprecated. Instead of using this argument, use +process_info/2 item current_stacktrace.

                    Returns the old value of the flag.

                  • system_flag(cpu_topology, cpu_topology()) -> cpu_topology()

                    Warning

                    This argument is deprecated. Instead of using this argument, use command-line argument +sct in erl.

                    When this argument is removed, a final CPU topology to use is determined at emulator boot time.

                    Sets the user-defined CpuTopology. The user-defined CPU topology overrides any automatically detected CPU topology. By passing undefined as CpuTopology, @@ -17156,7 +17158,7 @@

                    system_flag(Flag, Value)

                    +sct to erl.

                    For information on type CpuTopology and more, see erlang:system_info(cpu_topology) as well as command-line flags +sct and -+sbt in erl.

                  • system_flag(dirty_cpu_schedulers_online, pos_integer()) -> pos_integer()

                    Sets the number of dirty CPU schedulers online. Range is ++sbt in erl.

                  • system_flag(dirty_cpu_schedulers_online, pos_integer()) -> pos_integer()

                    Sets the number of dirty CPU schedulers online. Range is 1 <= DirtyCPUSchedulersOnline <= N, where N is the smallest of the return values of erlang:system_info(dirty_cpu_schedulers) and erlang:system_info(schedulers_online).

                    Returns the old value of the flag.

                    The number of dirty CPU schedulers online can change if the number of schedulers @@ -17168,31 +17170,31 @@

                    system_flag(Flag, Value)

                    of schedulers online.

                    For more information, see erlang:system_info(dirty_cpu_schedulers) and -erlang:system_info(dirty_cpu_schedulers_online).

                    Available since OTP 17.0

                  • system_flag(erts_alloc, {Alloc :: atom(), F :: atom(), V :: integer()}) ->
                    +erlang:system_info(dirty_cpu_schedulers_online).

                    Available since OTP 17.0

                  • system_flag(erts_alloc, {Alloc :: atom(), F :: atom(), V :: integer()}) ->
                       ok | notsup

                    Sets system flags for erts_alloc(3). Alloc is the allocator to affect, for example binary_alloc. F is the flag to change and V is the new value.

                    Only a subset of all erts_alloc flags can be changed at run time. This subset -is currently only the flag sbct.

                    Returns ok if the flag was set or notsup if not supported by erts_alloc.

                    Available since OTP 20.2.3

                  • system_flag(fullsweep_after, non_neg_integer()) -> non_neg_integer()

                    Sets system flag fullsweep_after. Number is a non-negative integer +is currently only the flag sbct.

                    Returns ok if the flag was set or notsup if not supported by erts_alloc.

                    Available since OTP 20.2.3

                  • system_flag(fullsweep_after, non_neg_integer()) -> non_neg_integer()

                    Sets system flag fullsweep_after. Number is a non-negative integer indicating how many times generational garbage collections can be done without forcing a fullsweep collection. The value applies to new processes, while processes already running are not affected.

                    Returns the old value of the flag.

                    In low-memory systems (especially without virtual memory), setting the value to 0 can help to conserve memory.

                    This value can also be set through (OS) environment variable -ERL_FULLSWEEP_AFTER.

                  • system_flag(microstate_accounting, true | false | reset) -> boolean()

                    Turns on/off microstate accounting measurements. When passing reset, all +ERL_FULLSWEEP_AFTER.

                  • system_flag(microstate_accounting, true | false | reset) -> boolean()

                    Turns on/off microstate accounting measurements. When passing reset, all counters are reset to 0.

                    For more information see -statistics(microstate_accounting).

                    Available since OTP 19.0

                  • system_flag(min_heap_size, non_neg_integer()) -> non_neg_integer()

                    Sets the default minimum heap size for processes. The size is specified in +statistics(microstate_accounting).

                    Available since OTP 19.0

                  • system_flag(min_heap_size, non_neg_integer()) -> non_neg_integer()

                    Sets the default minimum heap size for processes. The size is specified in words. The new min_heap_size effects only processes spawned after the change of min_heap_size has been made. min_heap_size can be set for individual -processes by using spawn_opt/4 or process_flag/2.

                    Returns the old value of the flag.

                  • system_flag(min_bin_vheap_size, non_neg_integer()) -> non_neg_integer()

                    Sets the default minimum binary virtual heap size for processes. The size is +processes by using spawn_opt/4 or process_flag/2.

                    Returns the old value of the flag.

                  • system_flag(min_bin_vheap_size, non_neg_integer()) -> non_neg_integer()

                    Sets the default minimum binary virtual heap size for processes. The size is specified in words. The new min_bin_vhheap_size effects only processes spawned after the change of min_bin_vheap_size has been made. min_bin_vheap_size can be set for individual processes by using spawn_opt/2,3,4 or -process_flag/2.

                    Returns the old value of the flag.

                    Available since OTP R13B04

                  • system_flag(max_heap_size, max_heap_size()) -> max_heap_size()

                    Sets the default maximum heap size settings for processes. The size is specified +process_flag/2.

                    Returns the old value of the flag.

                    Available since OTP R13B04

                  • system_flag(max_heap_size, max_heap_size()) -> max_heap_size()

                    Sets the default maximum heap size settings for processes. The size is specified in words. The new max_heap_size effects only processes spawned after the change has been made. max_heap_size can be set for individual processes using spawn_opt/2,3,4 or process_flag/2.

                    Returns the old value of the flag.

                    For details on how the heap grows, see Sizing the heap in the ERTS internal -documentation.

                    Available since OTP 19.0

                  • system_flag(multi_scheduling, BlockState) -> OldBlockState when
                    +documentation.

                    Available since OTP 19.0

                  • system_flag(multi_scheduling, BlockState) -> OldBlockState when
                       BlockState :: block | unblock | block_normal | unblock_normal,
                       OldBlockState :: blocked | disabled | enabled

                    If multi-scheduling is enabled, more than one scheduler thread is used by the emulator. Multi-scheduling can be blocked in two different ways. Either all @@ -17221,7 +17223,7 @@

                    system_flag(Flag, Value)

                    erlang:system_info(multi_scheduling), erlang:system_info(normal_multi_scheduling_blockers), erlang:system_info(multi_scheduling_blockers), -and erlang:system_info(schedulers).

                  • system_flag(outstanding_system_requests_limit, 1..134217727) -> 1..134217727

                    Sets a limit on the amount of outstanding requests made by a system process +and erlang:system_info(schedulers).

                  • system_flag(outstanding_system_requests_limit, 1..134217727) -> 1..134217727

                    Sets a limit on the amount of outstanding requests made by a system process orchestrating system wide changes. Currently there are two such processes:

                    • The Code Purger - The code purger orchestrates checking of references to old code before old code is removed from the system.

                    • The Literal Area Collector - The literal area collector orchestrates copying of references from old literal areas before removal of such areas from @@ -17232,8 +17234,8 @@

                      system_flag(Flag, Value)

                      quickly as possible at the same time as other work will be interleaved with this work. Currently used limit can be checked by calling erlang:system_info(outstanding_system_requests_limit).

                      This limit can also be set by passing the command line argument -+zosrl <Limit> to erl.

                      Available since OTP 24.2

                    • system_flag(scheduler_bind_type, scheduler_bind_type() | default_bind) ->
                      -  scheduler_bind_type()

                      Warning

                      This argument is deprecated. Instead of using this argument, use ++zosrl <Limit> to erl.

                      Available since OTP 24.2

                    • system_flag(scheduler_bind_type, scheduler_bind_type() | default_bind) ->
                      +  scheduler_bind_type()

                      Warning

                      This argument is deprecated. Instead of using this argument, use command-line argument +sbt in erl. When this argument is removed, a final scheduler bind type to use is determined at emulator boot time.

                      Controls if and how schedulers are bound to logical processors.

                      When erlang:system_flag(scheduler_bind_type, How) is called, an asynchronous @@ -17267,7 +17269,7 @@

                      system_flag(Flag, Value)

                      erlang:system_info(scheduler_bind_type), erlang:system_info(scheduler_bindings), as well as command-line flags +sbt and -+sct in erl.

                    • system_flag(scheduler_wall_time, boolean()) -> boolean()

                      Try enable or disable scheduler wall time measurements by passing Boolean as ++sct in erl.

                    • system_flag(scheduler_wall_time, boolean()) -> boolean()

                      Try enable or disable scheduler wall time measurements by passing Boolean as either true or false.

                      For more information about how to use scheduler wall time measurements, see statistics(scheduler_wall_time).

                      Scheduler wall time measurements has a node global state. It is either enabled for all processes on the node or disabled for all processes. Each process has a @@ -17279,7 +17281,7 @@

                      system_flag(Flag, Value)

                      counter will also disappear. To ensure scheduler_wall_time is kept enabled, the process that enabled it must therefore be kept alive.

                      Returns the old value of the node global state, true if scheduler wall time measurements were enabled, false if it were disabled.

                      Scheduler wall time measurements do consume some cpu overhead and should not be -left turned on unless used.

                      Available since OTP R15B01

                    • system_flag(schedulers_online, pos_integer()) -> pos_integer()

                      Sets the number of schedulers online. Range is +left turned on unless used.

                      Available since OTP R15B01

                    • system_flag(schedulers_online, pos_integer()) -> pos_integer()

                      Sets the number of schedulers online. Range is 1 <= SchedulersOnline <= erlang:system_info(schedulers).

                      Returns the old value of the flag.

                      If the emulator was built with support for dirty schedulers, changing the number of schedulers online can also change the number of dirty CPU @@ -17290,23 +17292,23 @@

                      system_flag(Flag, Value)

                      dirty CPU schedulers online increases proportionally to increases in the number of schedulers online.

                      For more information, see erlang:system_info(schedulers) and -erlang:system_info(schedulers_online).

                    • system_flag(system_logger, logger | undefined | pid()) -> logger | undefined | pid()

                      Sets the process that will receive the logging messages generated by ERTS. If +erlang:system_info(schedulers_online).

                    • system_flag(system_logger, logger | undefined | pid()) -> logger | undefined | pid()

                      Sets the process that will receive the logging messages generated by ERTS. If set to undefined, all logging messages generated by ERTS will be dropped. The -messages will be in the format:

                      {log,Level,Format,ArgList,Metadata} where
                      -
                      -Level = atom(),
                      -Format = string(),
                      -ArgList = list(term()),
                      -Metadata = #{ pid => pid(),
                      -   group_leader => pid(),
                      -   time := logger:timestamp(),
                      -   error_logger := #{ emulator := true, tag := atom() }

                      If the system_logger process dies, this flag will be reset to logger.

                      The default is the process named logger.

                      Returns the old value of the flag.

                      Note

                      This function is designed to be used by the KERNEL logger. Be careful if +messages will be in the format:

                      {log,Level,Format,ArgList,Metadata} where
                      +
                      +Level = atom(),
                      +Format = string(),
                      +ArgList = list(term()),
                      +Metadata = #{ pid => pid(),
                      +   group_leader => pid(),
                      +   time := logger:timestamp(),
                      +   error_logger := #{ emulator := true, tag := atom() }

                      If the system_logger process dies, this flag will be reset to logger.

                      The default is the process named logger.

                      Returns the old value of the flag.

                      Note

                      This function is designed to be used by the KERNEL logger. Be careful if you change it to something else as log messages may be lost. If you want to intercept emulator log messages, do it by adding a specialized handler to the -KERNEL logger.

                      Available since OTP 21.2

                    • system_flag(trace_control_word, non_neg_integer()) -> non_neg_integer()

                      Sets the value of the node trace control word to TCW, which is to be an +KERNEL logger.

                      Available since OTP 21.2

                    • system_flag(trace_control_word, non_neg_integer()) -> non_neg_integer()

                      Sets the value of the node trace control word to TCW, which is to be an unsigned integer. For more information, see function set_tcw in section "Match Specifications in Erlang" -in the User's Guide.

                      Returns the old value of the flag.

                    • system_flag(time_offset, finalize) -> preliminary | final | volatile

                      Finalizes the time offset when +in the User's Guide.

                      Returns the old value of the flag.

                    • system_flag(time_offset, finalize) -> preliminary | final | volatile

                      Finalizes the time offset when single time warp mode is used. If another time warp mode is used, the time offset state is left unchanged.

                      Returns the old state identifier, that is:

                      • If preliminary is returned, finalization was performed and the time offset is now final.
                      • If final is returned, the time offset was already in the final state. This @@ -17324,7 +17326,7 @@

                        system_flag(Flag, Value)

                        system_info(Item)

                        - + View Source @@ -17518,14 +17520,14 @@

                        system_info(Item)

                        allocated by the emulator. Some values are part of other values, and some memory areas are not part of the result. For information about the total amount of memory allocated by the emulator, see -erlang:memory/0,1.

                      • allocator - Returns

                        {Allocator :: undefined | glibc,
                        - Version :: [non_neg_integer()],
                        - Features :: [atom()],
                        - Settings :: [{Subsystem :: atom(),
                        -               [{Parameter :: atom(),
                        -                 Value :: term()}]
                        -               }]
                        -}

                        where

                        • allocator - Returns

                          {Allocator :: undefined | glibc,
                          + Version :: [non_neg_integer()],
                          + Features :: [atom()],
                          + Settings :: [{Subsystem :: atom(),
                          +               [{Parameter :: atom(),
                          +                 Value :: term()}]
                          +               }]
                          +}

                          where

                          • Allocator corresponds to the malloc() implementation used. If Allocator equals undefined, the malloc() implementation used cannot be identified. glibc can be identified.
                          • Version is a list of integers (but not a string) representing the version of the malloc() implementation used.
                          • Features is a list of atoms representing the allocation features used.
                          • Settings is a list of subsystems, their configurable parameters, and used @@ -18361,8 +18363,8 @@

                            date()

                            Returns the current date as {Year, Month, Day}.

                            The time zone and Daylight Saving Time correction depend on the underlying OS. The return value is based on the -OS System Time.

                            For example:

                            > date().
                            -{1995,2,19}
                            +OS System Time.

                            For example:

                            > date().
                            +{1995,2,19}
                            @@ -18391,8 +18393,8 @@

                            localtime()

                            Returns the current local date and time, -{{Year, Month, Day}, {Hour, Minute, Second}}.

                            For example:

                            > erlang:localtime().
                            -{{1996,11,6},{14,45,17}}

                            The time zone and Daylight Saving Time correction depend on the underlying OS. +{{Year, Month, Day}, {Hour, Minute, Second}}.

                            For example:

                            > erlang:localtime().
                            +{{1996,11,6},{14,45,17}}

                            The time zone and Daylight Saving Time correction depend on the underlying OS. The return value is based on the OS System Time.

                            @@ -18406,7 +18408,7 @@

                            localtime()

                            localtime_to_universaltime(Localtime)

                            - + View Source @@ -18427,8 +18429,8 @@

                            localtime_to_universaltime(Localtime)

                            Converts local date and time to Universal Time Coordinated (UTC), if supported by the underlying OS. Otherwise no conversion is done and Localtime is -returned.

                            For example:

                            > erlang:localtime_to_universaltime({{1996,11,6},{14,45,17}}).
                            -{{1996,11,6},{13,45,17}}

                            Failure: badarg if Localtime denotes an invalid date and time.

                            +returned.

                            For example:

                            > erlang:localtime_to_universaltime({{1996,11,6},{14,45,17}}).
                            +{{1996,11,6},{13,45,17}}

                            Failure: badarg if Localtime denotes an invalid date and time.

                            @@ -18465,12 +18467,12 @@

                            localtime_to_universaltime(Localtime, IsDst Time is active.

                            If IsDst == true, Localtime is during Daylight Saving Time, if IsDst == false it is not. If IsDst == undefined, the underlying OS can guess, which is the same as calling -erlang:localtime_to_universaltime(Localtime).

                            Examples:

                            > erlang:localtime_to_universaltime({{1996,11,6},{14,45,17}}, true).
                            -{{1996,11,6},{12,45,17}}
                            -> erlang:localtime_to_universaltime({{1996,11,6},{14,45,17}}, false).
                            -{{1996,11,6},{13,45,17}}
                            -> erlang:localtime_to_universaltime({{1996,11,6},{14,45,17}}, undefined).
                            -{{1996,11,6},{13,45,17}}

                            Failure: badarg if Localtime denotes an invalid date and time.

                            +erlang:localtime_to_universaltime(Localtime).

                            Examples:

                            > erlang:localtime_to_universaltime({{1996,11,6},{14,45,17}}, true).
                            +{{1996,11,6},{12,45,17}}
                            +> erlang:localtime_to_universaltime({{1996,11,6},{14,45,17}}, false).
                            +{{1996,11,6},{13,45,17}}
                            +> erlang:localtime_to_universaltime({{1996,11,6},{14,45,17}}, undefined).
                            +{{1996,11,6},{13,45,17}}

                            Failure: badarg if Localtime denotes an invalid date and time.

                            @@ -18901,8 +18903,8 @@

                            time()

                            Returns the current time as {Hour, Minute, Second}.

                            The time zone and Daylight Saving Time correction depend on the underlying OS. The return value is based on the -OS System Time.

                            For example:

                            > time().
                            -{9,42,44}
                            +OS System Time.

                            For example:

                            > time().
                            +{9,42,44}
                            @@ -19015,12 +19017,12 @@

                            timestamp()

                            The reason for the existence of erlang:timestamp() is purely to simplify use for existing code that assumes this time stamp format. Current Erlang system time can more efficiently be retrieved in the time unit of your choice using -erlang:system_time/1.

                            The erlang:timestamp() BIF is equivalent to:

                            timestamp() ->
                            -    ErlangSystemTime = erlang:system_time(microsecond),
                            +erlang:system_time/1.

                            The erlang:timestamp() BIF is equivalent to:

                            timestamp() ->
                            +    ErlangSystemTime = erlang:system_time(microsecond),
                                 MegaSecs = ErlangSystemTime div 1000_000_000_000,
                                 Secs = ErlangSystemTime div 1000_000 - MegaSecs*1000_000,
                                 MicroSecs = ErlangSystemTime rem 1000_000,
                            -    {MegaSecs, Secs, MicroSecs}.

                            It, however, uses a native implementation that does not build garbage on the + {MegaSecs, Secs, MicroSecs}.

                            It, however, uses a native implementation that does not build garbage on the heap and with slightly better performance.

                            Note

                            This time is not a monotonically increasing time in the general case. For more information, see the documentation of time warp modes in the User's Guide.

                            @@ -19055,8 +19057,8 @@

                            universaltime()

                            in the form {{Year, Month, Day}, {Hour, Minute, Second}} if supported by the underlying OS. Otherwise erlang:universaltime() is equivalent to erlang:localtime(). The return value is based on the -OS System Time.

                            For example:

                            > erlang:universaltime().
                            -{{1996,11,6},{14,18,43}}
                            +OS System Time.

                            For example:

                            > erlang:universaltime().
                            +{{1996,11,6},{14,18,43}}
                            @@ -19068,7 +19070,7 @@

                            universaltime()

                            universaltime_to_localtime(Universaltime)

                            - + View Source @@ -19089,8 +19091,8 @@

                            universaltime_to_localtime(Universaltime)Converts Universal Time Coordinated (UTC) date and time to local date and time in the form {{Year, Month, Day}, {Hour, Minute, Second}} if supported by the -underlying OS. Otherwise no conversion is done, and Universaltime is returned.

                            For example:

                            > erlang:universaltime_to_localtime({{1996,11,6},{14,18,43}}).
                            -{{1996,11,7},{15,18,43}}

                            Failure: badarg if Universaltime denotes an invalid date and time.

                            +underlying OS. Otherwise no conversion is done, and Universaltime is returned.

                            For example:

                            > erlang:universaltime_to_localtime({{1996,11,6},{14,18,43}}).
                            +{{1996,11,7},{15,18,43}}

                            Failure: badarg if Universaltime denotes an invalid date and time.

                            @@ -19250,7 +19252,7 @@

                            trace_info(PidPortFuncEvent, Item)

                            trace_pattern(MFA, MatchSpec)

                            - + View Source @@ -19283,7 +19285,7 @@

                            trace_pattern(MFA, MatchSpec)

                            trace_pattern(MFA, MatchSpec, FlagList)

                            - + View Source diff --git a/prs/9045/erts-15.1.2/doc/html/erlsrv_cmd.html b/prs/9045/erts-15.1.2/doc/html/erlsrv_cmd.html index e29eede8dee6..01ceea3b5edc 100644 --- a/prs/9045/erts-15.1.2/doc/html/erlsrv_cmd.html +++ b/prs/9045/erts-15.1.2/doc/html/erlsrv_cmd.html @@ -321,28 +321,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); - } -}

                + SetConsoleCtrlHandler(&service_aware_handler, TRUE); + } +}

                diff --git a/prs/9045/erts-15.1.2/doc/html/escript_cmd.html b/prs/9045/erts-15.1.2/doc/html/escript_cmd.html index b4d008d4e595..2a2fc2cd4942 100644 --- a/prs/9045/erts-15.1.2/doc/html/escript_cmd.html +++ b/prs/9045/erts-15.1.2/doc/html/escript_cmd.html @@ -137,7 +137,7 @@

                Synopsis

                -
                script-name [arg1 arg2...]

                +
                script-name [arg1 arg2...]

                @@ -149,24 +149,24 @@

                $ 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
                @@ -179,7 +179,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 @@ -198,7 +198,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. @@ -206,7 +206,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.

                diff --git a/prs/9045/erts-15.1.2/doc/html/garbagecollection.html b/prs/9045/erts-15.1.2/doc/html/garbagecollection.html index 7a61a445dd0a..b09237c6c327 100644 --- a/prs/9045/erts-15.1.2/doc/html/garbagecollection.html +++ b/prs/9045/erts-15.1.2/doc/html/garbagecollection.html @@ -143,25 +143,25 @@

                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!"}}}.
                +

                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 off 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.

                +

                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 off 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.

                @@ -185,11 +185,11 @@

                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)) {
                +

                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.

                +} 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.

                diff --git a/prs/9045/erts-15.1.2/doc/html/inet_cfg.html b/prs/9045/erts-15.1.2/doc/html/inet_cfg.html index f8c1dd8fc74b..0206f3dc37f5 100644 --- a/prs/9045/erts-15.1.2/doc/html/inet_cfg.html +++ b/prs/9045/erts-15.1.2/doc/html/inet_cfg.html @@ -171,11 +171,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 @@ -183,61 +183,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.

                  +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.

                @@ -252,19 +252,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"'
                diff --git a/prs/9045/erts-15.1.2/doc/html/init.html b/prs/9045/erts-15.1.2/doc/html/init.html index bf7c39865401..fe0659dcbe71 100644 --- a/prs/9045/erts-15.1.2/doc/html/init.html +++ b/prs/9045/erts-15.1.2/doc/html/init.html @@ -167,8 +167,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 @@ -222,13 +222,13 @@

              % 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

              @@ -530,12 +530,12 @@

              get_argument(Flag)

              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:

    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.

    diff --git a/prs/9045/erts-15.1.2/doc/html/match_spec.html b/prs/9045/erts-15.1.2/doc/html/match_spec.html index f03b30180dc3..13943ea1dcdf 100644 --- a/prs/9045/erts-15.1.2/doc/html/match_spec.html +++ b/prs/9045/erts-15.1.2/doc/html/match_spec.html @@ -377,70 +377,70 @@

    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 +

    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'],
    -  [],
    -  []},
    - {'_',[],[]}]

    +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 +'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.

    diff --git a/prs/9045/erts-15.1.2/doc/html/notes.html b/prs/9045/erts-15.1.2/doc/html/notes.html index 5bc08592e3fd..3ed2eb2e7b24 100644 --- a/prs/9045/erts-15.1.2/doc/html/notes.html +++ b/prs/9045/erts-15.1.2/doc/html/notes.html @@ -167,8 +167,8 @@

    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:

      {'GetOverlappedResult',
      -  '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

    +
    • 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:

      {'GetOverlappedResult',
      +  '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

    @@ -205,17 +205,17 @@

    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}).
      +
      • 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(#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

      • 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, @@ -3077,9 +3077,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 @@ -10794,12 +10794,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:
      diff --git a/prs/9045/erts-15.1.2/doc/html/persistent_term.html b/prs/9045/erts-15.1.2/doc/html/persistent_term.html
      index 1901e116aa9d..80ece7ef3709 100644
      --- a/prs/9045/erts-15.1.2/doc/html/persistent_term.html
      +++ b/prs/9045/erts-15.1.2/doc/html/persistent_term.html
      @@ -206,9 +206,9 @@ 

      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).

    diff --git a/prs/9045/erts-15.1.2/doc/html/search.html b/prs/9045/erts-15.1.2/doc/html/search.html index 648b0b317c5a..edd47a8842e6 100644 --- a/prs/9045/erts-15.1.2/doc/html/search.html +++ b/prs/9045/erts-15.1.2/doc/html/search.html @@ -128,7 +128,7 @@

    - +

    diff --git a/prs/9045/erts-15.1.2/doc/html/supercarrier.html b/prs/9045/erts-15.1.2/doc/html/supercarrier.html index 8f5db4aed59a..94315dd4ed30 100644 --- a/prs/9045/erts-15.1.2/doc/html/supercarrier.html +++ b/prs/9045/erts-15.1.2/doc/html/supercarrier.html @@ -235,12 +235,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. diff --git a/prs/9045/erts-15.1.2/doc/html/time_correction.html b/prs/9045/erts-15.1.2/doc/html/time_correction.html index fe5219289e08..de5eafbdf5e4 100644 --- a/prs/9045/erts-15.1.2/doc/html/time_correction.html +++ b/prs/9045/erts-15.1.2/doc/html/time_correction.html @@ -570,9 +570,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 diff --git a/prs/9045/erts-15.1.2/doc/html/tracing.html b/prs/9045/erts-15.1.2/doc/html/tracing.html index 4e716c4812c7..70fc3039d843 100644 --- a/prs/9045/erts-15.1.2/doc/html/tracing.html +++ b/prs/9045/erts-15.1.2/doc/html/tracing.html @@ -155,23 +155,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).

    +bar(N) -> + bar(N - 1).

    diff --git a/prs/9045/erts-15.1.2/doc/html/zlib.html b/prs/9045/erts-15.1.2/doc/html/zlib.html index 3c78149fc603..4fc136846468 100644 --- a/prs/9045/erts-15.1.2/doc/html/zlib.html +++ b/prs/9045/erts-15.1.2/doc/html/zlib.html @@ -139,18 +139,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(end_of_data, _Cont) -> [];
    -              (Data, Cont) ->
    -                 [zlib:deflate(Z, Data)|Cont(Read(),Cont)]
    +Compress = fun(end_of_data, _Cont) -> [];
    +              (Data, Cont) ->
    +                 [zlib:deflate(Z, Data)|Cont(Read(),Cont)]
                end,
    -Compressed = Compress(Read(),Compress),
    -Last = zlib:deflate(Z, [], finish),
    -ok = zlib:deflateEnd(Z),
    -zlib:close(Z),
    -list_to_binary([Compressed|Last])

    In all functions errors, {'EXIT',{Reason,Backtrace}}, can be thrown, where +Compressed = Compress(Read(),Compress), +Last = zlib:deflate(Z, [], finish), +ok = zlib:deflateEnd(Z), +zlib:close(Z), +list_to_binary([Compressed|Last])

    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 @@ -859,11 +859,11 @@

      deflate(Z, Data, Flush)

      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])
      @@ -1415,20 +1415,20 @@

      inflateSetDictionary(Z, Dictionary)

      {'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.
      @@ -1504,18 +1504,18 @@

      safeInflate(Z, Data)

      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).
      diff --git a/prs/9045/lib/asn1-5.3.1/doc/html/asn1.epub b/prs/9045/lib/asn1-5.3.1/doc/html/asn1.epub index 49150dd42b24..d349de4e2c68 100644 Binary files a/prs/9045/lib/asn1-5.3.1/doc/html/asn1.epub and b/prs/9045/lib/asn1-5.3.1/doc/html/asn1.epub differ diff --git a/prs/9045/lib/asn1-5.3.1/doc/html/asn1_getting_started.html b/prs/9045/lib/asn1-5.3.1/doc/html/asn1_getting_started.html index 9b821bd763e4..453cbbfe179e 100644 --- a/prs/9045/lib/asn1-5.3.1/doc/html/asn1_getting_started.html +++ b/prs/9045/lib/asn1-5.3.1/doc/html/asn1_getting_started.html @@ -149,37 +149,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}}

      +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}}

      @@ -277,16 +277,16 @@

      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

      @@ -297,7 +297,7 @@

      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),

      +{ok,Bytes} = MyModule:encode('Operational', Val),

      @@ -314,11 +314,11 @@

      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,
    @@ -365,7 +365,7 @@ 

    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 @@ -393,7 +393,7 @@

      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 @@ -414,11 +414,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 @@ -427,26 +427,26 @@

      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).
    +[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,
       181,208,189,209,140,208,186,208,184,208,185,32,208,147,
       208,...>>
    @@ -454,22 +454,22 @@ 

    <<208,156,208,190,208,185,32,208,188,208,176,208,187,208, 181,208,189,209,140,208,186,208,184,208,185,32,208,147, 208,...>> -4> Gs = unicode:characters_to_list(Gbin). -[1052,1086,1081,32,1084,1072,1083,1077,1085,1100,1082,1080, - 1081,32,1043,1085,1086,1084]

    For details, see the unicode module in STDLIB.

    In the following example, this ASN.1 specification is used:

    UTF DEFINITIONS AUTOMATIC TAGS ::=
    +4> Gs = unicode:characters_to_list(Gbin).
    +[1052,1086,1081,32,1084,1072,1083,1077,1085,1100,1082,1080,
    + 1081,32,1043,1085,1086,1084]

    For details, see the unicode module in STDLIB.

    In the following example, this ASN.1 specification is used:

    UTF DEFINITIONS AUTOMATIC TAGS ::=
     BEGIN
        UTF ::= UTF8String
    -END

    Encoding and decoding a string with Unicode characters:

    5> asn1ct:compile('UTF', [ber]).
    +END

    Encoding and decoding a string with Unicode characters:

    5> asn1ct:compile('UTF', [ber]).
     ok
    -6> {ok,Bytes1} = 'UTF':encode('UTF', <<"Гном"/utf8>>).
    -{ok,<<12,8,208,147,208,189,208,190,208,188>>}
    -7> {ok,Bin1} = 'UTF':decode('UTF', Bytes1).
    -{ok,<<208,147,208,189,208,190,208,188>>}
    -8> io:format("~ts\n", [Bin1]).
    +6> {ok,Bytes1} = 'UTF':encode('UTF', <<"Гном"/utf8>>).
    +{ok,<<12,8,208,147,208,189,208,190,208,188>>}
    +7> {ok,Bin1} = 'UTF':decode('UTF', Bytes1).
    +{ok,<<208,147,208,189,208,190,208,188>>}
    +8> io:format("~ts\n", [Bin1]).
     Гном
     ok
    -9> unicode:characters_to_list(Bin1).
    -[1043,1085,1086,1084]

    +9> unicode:characters_to_list(Bin1). +[1043,1085,1086,1084]

    @@ -505,15 +505,15 @@

    The structured types of ASN.1 are constructed from other types in a manner similar to the concepts of arrays and structs in C.

    A SEQUENCE in ASN.1 is comparable with a struct in C and a record in Erlang. A -SEQUENCE can be defined as follows:

    Pdu ::= SEQUENCE {
    +SEQUENCE can be defined as follows:

    Pdu ::= SEQUENCE {
        a INTEGER,
        b REAL,
        c OBJECT IDENTIFIER,
    -   d NULL }

    This is a 4-component structure called Pdu. By default, a SEQUENCE is + d NULL }

    This is a 4-component structure called Pdu. By default, a SEQUENCE is represented by a record in Erlang. It can also be represented as a map; see Map representation for SEQUENCE and SET. For each SEQUENCE and SET in an ASN.1 module an Erlang record declaration is -generated. For Pdu, a record like the following is defined:

    -record('Pdu', {a, b, c, d}).

    The record declarations for a module M are placed in a separate M.hrl file.

    Values can be assigned in Erlang as follows:

    MyPdu = #'Pdu'{a=22,b=77.99,c={0,1,2,3,4},d='NULL'}.

    The decode functions return a record as result when decoding a SEQUENCE or a +generated. For Pdu, a record like the following is defined:

    -record('Pdu', {a, b, c, d}).

    The record declarations for a module M are placed in a separate M.hrl file.

    Values can be assigned in Erlang as follows:

    MyPdu = #'Pdu'{a=22,b=77.99,c={0,1,2,3,4},d='NULL'}.

    The decode functions return a record as result when decoding a SEQUENCE or a SET.

    A SEQUENCE and a SET can contain a component with a DEFAULT keyword followed by the actual value, which is the default value. The DEFAULT keyword means that the application doing the encoding can omit encoding of the value, @@ -538,21 +538,21 @@

    Seq3 ::= SEQUENCE { bs BIT STRING {a(0), b(1), c(2)} DEFAULT {a, c} } -END

    Example where the BER encoder is able to omit encoding of the default values:

    1> asn1ct:compile('File', [ber]).
    +END

    Example where the BER encoder is able to omit encoding of the default values:

    1> asn1ct:compile('File', [ber]).
     ok
    -2> 'File':encode('Seq1', {'Seq1',asn1_DEFAULT,asn1_DEFAULT}).
    -{ok,<<48,0>>}
    -3> 'File':encode('Seq1', {'Seq1',1,{'Seq2',true,15}}).
    -{ok,<<48,0>>}

    Example with a named BIT STRING where the BER encoder does not omit the -encoding:

    4> 'File':encode('Seq3', {'Seq3',asn1_DEFAULT).
    -{ok,<<48,0>>}
    -5> 'File':encode('Seq3', {'Seq3',<<16#101:3>>).
    -{ok,<<48,4,128,2,5,160>>}

    The DER encoder omits the encoding for the same BIT STRING:

    6> asn1ct:compile('File', [ber,der]).
    +2> 'File':encode('Seq1', {'Seq1',asn1_DEFAULT,asn1_DEFAULT}).
    +{ok,<<48,0>>}
    +3> 'File':encode('Seq1', {'Seq1',1,{'Seq2',true,15}}).
    +{ok,<<48,0>>}

    Example with a named BIT STRING where the BER encoder does not omit the +encoding:

    4> 'File':encode('Seq3', {'Seq3',asn1_DEFAULT).
    +{ok,<<48,0>>}
    +5> 'File':encode('Seq3', {'Seq3',<<16#101:3>>).
    +{ok,<<48,4,128,2,5,160>>}

    The DER encoder omits the encoding for the same BIT STRING:

    6> asn1ct:compile('File', [ber,der]).
     ok
    -7> 'File':encode('Seq3', {'Seq3',asn1_DEFAULT).
    -{ok,<<48,0>>}
    -8> 'File':encode('Seq3', {'Seq3',<<16#101:3>>).
    -{ok,<<48,0>>}

    +7> 'File':encode('Seq3', {'Seq3',asn1_DEFAULT). +{ok,<<48,0>>} +8> 'File':encode('Seq3', {'Seq3',<<16#101:3>>). +{ok,<<48,0>>}

    @@ -588,14 +588,14 @@

    b BOOLEAN OPTIONAL, c IA5String } -END

    Optional fields are to be omitted from the map if they have no value:

    1> asn1ct:compile('File', [per,maps]).
    +END

    Optional fields are to be omitted from the map if they have no value:

    1> asn1ct:compile('File', [per,maps]).
     ok
    -2> {ok,E} = 'File':encode('Seq1', #{a=>0,c=>"string"}).
    -{ok,<<128,1,0,6,115,116,114,105,110,103>>}

    When decoding, optional fields will be omitted from the map:

    3> 'File':decode('Seq1', E).
    -{ok,#{a => 0,c => "string"}}

    Default values can be omitted from the map:

    4> {ok,E2} = 'File':encode('Seq1', #{c=>"string"}).
    -{ok,<<0,6,115,116,114,105,110,103>>}
    -5> 'File':decode('Seq1', E2).
    -{ok,#{a => 42,c => "string"}}

    Note

    It is not allowed to use the atoms asn1_VALUE and asn1_DEFAULT with maps.

    +2> {ok,E} = 'File':encode('Seq1', #{a=>0,c=>"string"}). +{ok,<<128,1,0,6,115,116,114,105,110,103>>}

    When decoding, optional fields will be omitted from the map:

    3> 'File':decode('Seq1', E).
    +{ok,#{a => 0,c => "string"}}

    Default values can be omitted from the map:

    4> {ok,E2} = 'File':encode('Seq1', #{c=>"string"}).
    +{ok,<<0,6,115,116,114,105,110,103>>}
    +5> 'File':decode('Seq1', E2).
    +{ok,#{a => 42,c => "string"}}

    Note

    It is not allowed to use the atoms asn1_VALUE and asn1_DEFAULT with maps.

    @@ -608,8 +608,8 @@

    x REAL, y INTEGER, z OBJECT IDENTIFIER } -END

    It is then possible to assign values as follows:

    TVal1 = {y,17},
    -TVal2 = {z,{0,1,2}},

    A CHOICE value is always represented as the tuple {ChoiceAlternative, Val} +END

    It is then possible to assign values as follows:

    TVal1 = {y,17},
    +TVal2 = {z,{0,1,2}},

    A CHOICE value is always represented as the tuple {ChoiceAlternative, Val} where ChoiceAlternative is an atom denoting the selected choice alternative.

    Extensible CHOICE

    When a CHOICE contains an extension marker and the decoder detects an unknown alternative of the CHOICE, the value is represented as follows:

    {asn1_ExtAlt, BytesForOpenType}

    Here BytesForOpenType is a list of bytes constituting the encoding of the "unknown" CHOICE alternative.

    @@ -675,8 +675,8 @@

    x REAL, y INTEGER, z OBJECT IDENTIFIER } - END

    SEQUENCE b can be encoded as follows in Erlang:

    1> 'EmbeddedExample':encode('B', {'B',[4,5,6,7,8],{x,"7.77"}}).
    -{ok,<<5,56,0,8,3,55,55,55,46,69,45,50>>}

    + END

    SEQUENCE b can be encoded as follows in Erlang:

    1> 'EmbeddedExample':encode('B', {'B',[4,5,6,7,8],{x,"7.77"}}).
    +{ok,<<5,56,0,8,3,55,55,55,46,69,45,50>>}

    @@ -702,10 +702,10 @@

    a INTEGER, b FooType } } -FooType ::= [3] VisibleString

    The following records are generated because of type Emb:

    -record('Emb,{a, b, c}).
    --record('Emb_b',{a, b = asn1_DEFAULT}). % the embedded SET type

    Values of type Emb can be assigned as follows:

    V = #'Emb'{a=["qqqq",[1,2,255]],
    -           b = #'Emb_b'{a=99},
    -           c ={b,"Can you see this"}}.

    For an embedded type of type SEQUENCE/SET in a SEQUENCE/SET, the record +FooType ::= [3] VisibleString

    The following records are generated because of type Emb:

    -record('Emb,{a, b, c}).
    +-record('Emb_b',{a, b = asn1_DEFAULT}). % the embedded SET type

    Values of type Emb can be assigned as follows:

    V = #'Emb'{a=["qqqq",[1,2,255]],
    +           b = #'Emb_b'{a=99},
    +           c ={b,"Can you see this"}}.

    For an embedded type of type SEQUENCE/SET in a SEQUENCE/SET, the record name is extended with an underscore and the component name. If the embedded structure is deeper with the SEQUENCE, SET, or CHOICE types in the line, each component name/alternative name is added to the record name.

    Example:

    Seq ::= SEQUENCE{
    @@ -714,7 +714,7 @@ 

    c INTEGER } } -}

    This results in the following record:

    -record('Seq_a_b',{c}).

    If the structured type has a component with an embedded SEQUENCE OF/SET OF +}

    This results in the following record:

    -record('Seq_a_b',{c}).

    If the structured type has a component with an embedded SEQUENCE OF/SET OF which embedded type in turn is a SEQUENCE/SET, it gives a record with the SEQUENCE OF/SET OF addition as in the following example:

    Seq ::= SEQUENCE {
         a SEQUENCE OF SEQUENCE {
    @@ -723,8 +723,8 @@ 

    c SET OF SEQUENCE { d } -}

    This results in the following records:

    -record('Seq_a_SEQOF'{b}).
    --record('Seq_c_SETOF'{d}).

    A parameterized type is to be considered as an embedded type. Each time such a +}

    This results in the following records:

    -record('Seq_a_SEQOF'{b}).
    +-record('Seq_c_SETOF'{d}).

    A parameterized type is to be considered as an embedded type. Each time such a type is referenced, an instance of it is defined. Thus, in the following example a record with name 'Seq_b' is generated in the .hrl file and is used to hold values:

    Seq ::= SEQUENCE {
    @@ -739,15 +739,15 @@ 

    Recursive Types

    -

    Types that refer to themselves are called recursive types. Example:

    Rec ::= CHOICE {
    +

    Types that refer to themselves are called recursive types. Example:

    Rec ::= CHOICE {
          nothing NULL,
    -     something SEQUENCE {
    +     something SEQUENCE {
               a INTEGER,
               b OCTET STRING,
    -          c Rec }}

    This is allowed in ASN.1 and the ASN.1-to-Erlang compiler supports this -recursive type. A value for this type is assigned in Erlang as follows:

    V = {something,#'Rec_something'{a = 77,
    +          c Rec }}

    This is allowed in ASN.1 and the ASN.1-to-Erlang compiler supports this +recursive type. A value for this type is assigned in Erlang as follows:

    V = {something,#'Rec_something'{a = 77,
                                     b = "some octets here",
    -                                c = {nothing,'NULL'}}}.

    + c = {nothing,'NULL'}}}.

    @@ -756,22 +756,22 @@

    Values can be assigned to an ASN.1 type within the ASN.1 code itself, as opposed to the actions in the previous section where a value was assigned to an ASN.1 type in Erlang. The full value syntax of ASN.1 is supported and X.680 describes -in detail how to assign values in ASN.1. A short example:

    TT ::= SEQUENCE {
    +in detail how to assign values in ASN.1. A short example:

    TT ::= SEQUENCE {
        a INTEGER,
    -   b SET OF OCTET STRING }
    +   b SET OF OCTET STRING }
     
    -tt TT ::= {a 77,b {"kalle","kula"}}

    The value defined here can be used in several ways. It can, for example, be used +tt TT ::= {a 77,b {"kalle","kula"}}

    The value defined here can be used in several ways. It can, for example, be used as the value in some DEFAULT component:

    SS ::= SET {
         s OBJECT IDENTIFIER,
         val TT DEFAULT tt }

    It can also be used from inside an Erlang program. If this ASN.1 code is defined in ASN.1 module Values, the ASN.1 value tt can be reached from Erlang as a -function call to 'Values':tt() as in the following example:

    1> Val = 'Values':tt().
    -{'TT',77,["kalle","kula"]}
    -2> {ok,Bytes} = 'Values':encode('TT',Val).
    -{ok,<<48,18,128,1,77,161,13,4,5,107,97,108,108,101,4,4,
    -      107,117,108,97>>}
    -4> 'Values':decode('TT',Bytes).
    -{ok,{'TT',77,["kalle","kula"]}}
    +function call to 'Values':tt() as in the following example:

    1> Val = 'Values':tt().
    +{'TT',77,["kalle","kula"]}
    +2> {ok,Bytes} = 'Values':encode('TT',Val).
    +{ok,<<48,18,128,1,77,161,13,4,5,107,97,108,108,101,4,4,
    +      107,117,108,97>>}
    +4> 'Values':decode('TT',Bytes).
    +{ok,{'TT',77,["kalle","kula"]}}
     5>

    This example shows that a function is generated by the compiler that returns a valid Erlang representation of the value, although the value is of a complex type.

    Furthermore, if the option maps is not used, a macro is generated for each @@ -824,10 +824,10 @@

    object1 | object2}

    You cannot encode a class, object, or object set, only refer to it when defining other ASN.1 entities. Typically you refer to a class as well as to object sets by table constraints and component relation constraints (X.682) in ASN.1 types, -as in the following:

    StartMessage  ::= SEQUENCE {
    -    msgId  GENERAL-PROCEDURE.&id  ({GENERAL-PROCEDURES}),
    -    content GENERAL-PROCEDURE.&Message ({GENERAL-PROCEDURES}{@msgId}),
    -    }

    In type StartMessage, the constraint following field content tells that in a +as in the following:

    StartMessage  ::= SEQUENCE {
    +    msgId  GENERAL-PROCEDURE.&id  ({GENERAL-PROCEDURES}),
    +    content GENERAL-PROCEDURE.&Message ({GENERAL-PROCEDURES}{@msgId}),
    +    }

    In type StartMessage, the constraint following field content tells that in a value of type StartMessage the value in field content must come from the same object that is chosen by field msgId.

    So, the value #'StartMessage'{msgId="home",content="Any Printable String"} is legal to encode as a StartMessage value. However, the value diff --git a/prs/9045/lib/asn1-5.3.1/doc/html/asn1_spec.html b/prs/9045/lib/asn1-5.3.1/doc/html/asn1_spec.html index 88172575f668..4f45bc7960a4 100644 --- a/prs/9045/lib/asn1-5.3.1/doc/html/asn1_spec.html +++ b/prs/9045/lib/asn1-5.3.1/doc/html/asn1_spec.html @@ -171,37 +171,37 @@

    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)

    +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}}.
    +

    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 @@ -267,78 +267,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).
    +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).
    +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).
    +        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,
    +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>>]},
    +                                                     <<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,
    +                                                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>>]},
    +                                                     <<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}}]}

    + 1,255>>}}} +14> 'GUI':decode_part(ChoiceKey, ChoiceUndec). +{possibleActions,[#'Action'{number = 16, + handle = #'Button'{number = 17,on = true}}]}

    @@ -375,23 +375,23 @@

    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]+
    +DecodeInstructions = [DecodeInstruction]+
     
    -DecodeInstruction = {SelectiveDecodeFunctionName,TypeList}
    +DecodeInstruction = {SelectiveDecodeFunctionName,TypeList}
     
    -SelectiveDecodeFunctionName = atom()
    +SelectiveDecodeFunctionName = atom()
     
    -TypeList = [TopType|ElementList]
    +TypeList = [TopType|ElementList]
     
     ElementList = Name|ListSelector
     
    -Name = atom()
    +Name = atom()
     
    -ListSelector = [integer()]

    The instruction must be a valid Erlang term terminated by a dot.

    • ModuleName is the same as the name of the ASN.1 specification, but without +ListSelector = [integer()]

    The instruction must be a valid Erlang term terminated by a dot.

    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}]
    diff --git a/prs/9045/lib/common_test-1.27.3/doc/html/ct_property_test_chapter.html b/prs/9045/lib/common_test-1.27.3/doc/html/ct_property_test_chapter.html index 6c44addfdfe3..2021c484a1c6 100644 --- a/prs/9045/lib/common_test-1.27.3/doc/html/ct_property_test_chapter.html +++ b/prs/9045/lib/common_test-1.27.3/doc/html/ct_property_test_chapter.html @@ -153,51 +153,51 @@

    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...
     
    @@ -227,13 +227,13 @@ 

    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 ***
    diff --git a/prs/9045/lib/common_test-1.27.3/doc/html/ct_run_cmd.html b/prs/9045/lib/common_test-1.27.3/doc/html/ct_run_cmd.html
    index 782fef164422..8743e5166f95 100644
    --- a/prs/9045/lib/common_test-1.27.3/doc/html/ct_run_cmd.html
    +++ b/prs/9045/lib/common_test-1.27.3/doc/html/ct_run_cmd.html
    @@ -257,10 +257,10 @@ 

    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]

    + [-config ConfigFile1 ConfigFile2 ... ConfigFileN] + [-userconfig CallbackModule1 ConfigString1 and CallbackModule2 + ConfigString2 and .. and CallbackModuleN ConfigStringN] + [-decrypt_key Key] | [-decrypt_file KeyFile]

    diff --git a/prs/9045/lib/common_test-1.27.3/doc/html/ct_snmp.html b/prs/9045/lib/common_test-1.27.3/doc/html/ct_snmp.html index b99d6e238cb8..06f52c59919c 100644 --- a/prs/9045/lib/common_test-1.27.3/doc/html/ct_snmp.html +++ b/prs/9045/lib/common_test-1.27.3/doc/html/ct_snmp.html @@ -156,15 +156,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 diff --git a/prs/9045/lib/common_test-1.27.3/doc/html/ct_ssh.html b/prs/9045/lib/common_test-1.27.3/doc/html/ct_ssh.html index 5308afc52373..186c28a63807 100644 --- a/prs/9045/lib/common_test-1.27.3/doc/html/ct_ssh.html +++ b/prs/9045/lib/common_test-1.27.3/doc/html/ct_ssh.html @@ -139,14 +139,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.

    diff --git a/prs/9045/lib/common_test-1.27.3/doc/html/ct_telnet.html b/prs/9045/lib/common_test-1.27.3/doc/html/ct_telnet.html index 1bece7379496..d059c5ab14ea 100644 --- a/prs/9045/lib/common_test-1.27.3/doc/html/ct_telnet.html +++ b/prs/9045/lib/common_test-1.27.3/doc/html/ct_telnet.html @@ -142,14 +142,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 = integer(), 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 = integer(), 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.

    @@ -164,8 +164,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 @@ -182,15 +182,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, []}]}].

    +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, []}]}].

    @@ -899,9 +899,9 @@

    expect(Connection, Patterns, Opts)

    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.

    diff --git a/prs/9045/lib/common_test-1.27.3/doc/html/dependencies_chapter.html b/prs/9045/lib/common_test-1.27.3/doc/html/dependencies_chapter.html index 26e85bbb4a3b..86db1386a410 100644 --- a/prs/9045/lib/common_test-1.27.3/doc/html/dependencies_chapter.html +++ b/prs/9045/lib/common_test-1.27.3/doc/html/dependencies_chapter.html @@ -167,65 +167,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.

    @@ -253,40 +253,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}.
    -
    -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 + 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 {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 @@ -306,22 +306,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 diff --git a/prs/9045/lib/common_test-1.27.3/doc/html/event_handler_chapter.html b/prs/9045/lib/common_test-1.27.3/doc/html/event_handler_chapter.html index 1ea1fad52d43..6e1451f11c82 100644 --- a/prs/9045/lib/common_test-1.27.3/doc/html/event_handler_chapter.html +++ b/prs/9045/lib/common_test-1.27.3/doc/html/event_handler_chapter.html @@ -174,12 +174,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 diff --git a/prs/9045/lib/common_test-1.27.3/doc/html/example_chapter.html b/prs/9045/lib/common_test-1.27.3/doc/html/example_chapter.html index 46441e4f89e1..68c75497b4f6 100644 --- a/prs/9045/lib/common_test-1.27.3/doc/html/example_chapter.html +++ b/prs/9045/lib/common_test-1.27.3/doc/html/example_chapter.html @@ -137,19 +137,19 @@

    Test Suite Example

    -

    The following example test suite shows some tests of a database server:

    -module(db_data_type_SUITE).
    +

    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
    @@ -164,8 +164,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 @@ -175,10 +175,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() @@ -188,9 +188,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. %%-------------------------------------------------------------------- @@ -203,10 +203,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. %%-------------------------------------------------------------------- @@ -219,10 +219,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. %%-------------------------------------------------------------------- @@ -237,28 +237,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.

    @@ -276,12 +276,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 @@ -299,8 +299,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) -> @@ -316,7 +316,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. %%-------------------------------------------------------------------- @@ -327,7 +327,7 @@

    %% %% Description: Cleanup after the suite. %%-------------------------------------------------------------------- -end_per_suite(_Config) -> +end_per_suite(_Config) -> ok. %%-------------------------------------------------------------------- @@ -343,7 +343,7 @@

    %% %% Description: Initialization before each test case group. %%-------------------------------------------------------------------- -init_per_group(_GroupName, Config) -> +init_per_group(_GroupName, Config) -> Config. %%-------------------------------------------------------------------- @@ -357,7 +357,7 @@

    %% %% Description: Cleanup after each test case group. %%-------------------------------------------------------------------- -end_per_group(_GroupName, _Config) -> +end_per_group(_GroupName, _Config) -> ok. %%-------------------------------------------------------------------- @@ -376,7 +376,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_testcase(_TestCase, Config) -> +init_per_testcase(_TestCase, Config) -> Config. %%-------------------------------------------------------------------- @@ -392,7 +392,7 @@

    %% %% Description: Cleanup after each test case. %%-------------------------------------------------------------------- -end_per_testcase(_TestCase, _Config) -> +end_per_testcase(_TestCase, _Config) -> ok. %%-------------------------------------------------------------------- @@ -416,8 +416,8 @@

    %% %% Description: Returns a list of test case group definitions. %%-------------------------------------------------------------------- -groups() -> - []. +groups() -> + []. %%-------------------------------------------------------------------- %% Function: all() -> GroupsAndTestCases | {skip,Reason} @@ -433,8 +433,8 @@

    %% Description: Returns the list of groups and test cases that %% are to be executed. %%-------------------------------------------------------------------- -all() -> - [my_test_case]. +all() -> + [my_test_case]. %%-------------------------------------------------------------------- @@ -453,8 +453,8 @@

    %% Note: This function is only meant to be used to return a list of %% values, not perform any other operations. %%-------------------------------------------------------------------- -my_test_case() -> - []. +my_test_case() -> + []. %%-------------------------------------------------------------------- %% Function: TestCase(Config0) -> @@ -472,7 +472,7 @@

    %% the all/0 list or in a test case group for the test case %% to be executed). %%-------------------------------------------------------------------- -my_test_case(_Config) -> +my_test_case(_Config) -> ok.

    Small Common Test Suite

    %%%-------------------------------------------------------------------
     %%% File    : example_SUITE.erl
     %%% Author  :
    @@ -480,18 +480,18 @@ 

    %%% %%% Created : %%%------------------------------------------------------------------- --module(example_SUITE). +-module(example_SUITE). --compile(export_all). +-compile(export_all). --include_lib("common_test/include/ct.hrl"). +-include_lib("common_test/include/ct.hrl"). %%-------------------------------------------------------------------- %% Function: suite() -> Info %% Info = [tuple()] %%-------------------------------------------------------------------- -suite() -> - [{timetrap,{seconds,30}}]. +suite() -> + [{timetrap,{seconds,30}}]. %%-------------------------------------------------------------------- %% Function: init_per_suite(Config0) -> @@ -499,14 +499,14 @@

    %% Config0 = Config1 = [tuple()] %% Reason = term() %%-------------------------------------------------------------------- -init_per_suite(Config) -> +init_per_suite(Config) -> Config. %%-------------------------------------------------------------------- %% Function: end_per_suite(Config0) -> term() | {save_config,Config1} %% Config0 = Config1 = [tuple()] %%-------------------------------------------------------------------- -end_per_suite(_Config) -> +end_per_suite(_Config) -> ok. %%-------------------------------------------------------------------- @@ -516,7 +516,7 @@

    %% Config0 = Config1 = [tuple()] %% Reason = term() %%-------------------------------------------------------------------- -init_per_group(_GroupName, Config) -> +init_per_group(_GroupName, Config) -> Config. %%-------------------------------------------------------------------- @@ -525,7 +525,7 @@

    %% GroupName = atom() %% Config0 = Config1 = [tuple()] %%-------------------------------------------------------------------- -end_per_group(_GroupName, _Config) -> +end_per_group(_GroupName, _Config) -> ok. %%-------------------------------------------------------------------- @@ -535,7 +535,7 @@

    %% Config0 = Config1 = [tuple()] %% Reason = term() %%-------------------------------------------------------------------- -init_per_testcase(_TestCase, Config) -> +init_per_testcase(_TestCase, Config) -> Config. %%-------------------------------------------------------------------- @@ -545,7 +545,7 @@

    %% Config0 = Config1 = [tuple()] %% Reason = term() %%-------------------------------------------------------------------- -end_per_testcase(_TestCase, _Config) -> +end_per_testcase(_TestCase, _Config) -> ok. %%-------------------------------------------------------------------- @@ -560,8 +560,8 @@

    %% repeat_until_any_ok | repeat_until_any_fail %% N = integer() | forever %%-------------------------------------------------------------------- -groups() -> - []. +groups() -> + []. %%-------------------------------------------------------------------- %% Function: all() -> GroupsAndTestCases | {skip,Reason} @@ -570,15 +570,15 @@

    %% TestCase = atom() %% Reason = term() %%-------------------------------------------------------------------- -all() -> - [my_test_case]. +all() -> + [my_test_case]. %%-------------------------------------------------------------------- %% Function: TestCase() -> Info %% Info = [tuple()] %%-------------------------------------------------------------------- -my_test_case() -> - []. +my_test_case() -> + []. %%-------------------------------------------------------------------- %% Function: TestCase(Config0) -> @@ -588,7 +588,7 @@

    %% Reason = term() %% Comment = term() %%-------------------------------------------------------------------- -my_test_case(_Config) -> +my_test_case(_Config) -> ok.

    diff --git a/prs/9045/lib/common_test-1.27.3/doc/html/getting_started_chapter.html b/prs/9045/lib/common_test-1.27.3/doc/html/getting_started_chapter.html index 5ba4f5a3d228..083153c1456e 100644 --- a/prs/9045/lib/common_test-1.27.3/doc/html/getting_started_chapter.html +++ b/prs/9045/lib/common_test-1.27.3/doc/html/getting_started_chapter.html @@ -175,14 +175,14 @@

    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.

    +mod_exists(_) -> + {module,mymod} = code:load_file(mymod).

    If the operation fails, a bad match error occurs that terminates the test case.

    @@ -195,33 +195,33 @@

    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

    diff --git a/prs/9045/lib/common_test-1.27.3/doc/html/run_test_chapter.html b/prs/9045/lib/common_test-1.27.3/doc/html/run_test_chapter.html index e28835f73b11..c31ef3cd40e1 100644 --- a/prs/9045/lib/common_test-1.27.3/doc/html/run_test_chapter.html +++ b/prs/9045/lib/common_test-1.27.3/doc/html/run_test_chapter.html @@ -286,7 +286,7 @@

    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 @@ -318,30 +318,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 @@ -369,12 +369,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. @@ -461,8 +461,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 @@ -524,154 +524,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}.
    +{event_handler, NodeRefs, EventHandlers}.
    +{event_handler, EventHandlers, InitArgs}.
    +{event_handler, NodeRefs, EventHandlers, InitArgs}.
     
    -{ct_hooks, CTHModules}.
    -{ct_hooks, NodeRefs, CTHModules}.
    +{ct_hooks, CTHModules}.
    +{ct_hooks, NodeRefs, CTHModules}.
     
    -{ct_hooks_order, CTHOrder}.
    +{ct_hooks_order, CTHOrder}.
     
    -{enable_builtin_hooks, Bool}.
    +{enable_builtin_hooks, Bool}.
     
    -{basic_html, Bool}.
    -{basic_html, NodeRefs, Bool}.
    +{basic_html, Bool}.
    +{basic_html, NodeRefs, Bool}.
     
    -{esc_chars, Bool}.
    -{esc_chars, NodeRefs, Bool}.
    +{esc_chars, Bool}.
    +{esc_chars, NodeRefs, Bool}.
     
    -{release_shell, Bool}.

    Test terms:

    {suites, Dir, Suites}.
    -{suites, NodeRefs, Dir, Suites}.
    +{release_shell, Bool}.

    Test terms:

    {suites, Dir, Suites}.
    +{suites, NodeRefs, Dir, Suites}.
     
    -{groups, Dir, Suite, Groups}.
    -{groups, NodeRefs, Dir, Suite, Groups}.
    +{groups, Dir, Suite, Groups}.
    +{groups, NodeRefs, Dir, Suite, Groups}.
     
    -{groups, Dir, Suite, Groups, {cases,Cases}}.
    -{groups, NodeRefs, Dir, Suite, Groups, {cases,Cases}}.
    +{groups, Dir, Suite, Groups, {cases,Cases}}.
    +{groups, NodeRefs, Dir, Suite, Groups, {cases,Cases}}.
     
    -{cases, Dir, Suite, Cases}.
    -{cases, NodeRefs, Dir, Suite, Cases}.
    +{cases, Dir, Suite, Cases}.
    +{cases, NodeRefs, Dir, Suite, Cases}.
     
    -{skip_suites, Dir, Suites, Comment}.
    -{skip_suites, NodeRefs, Dir, Suites, Comment}.
    +{skip_suites, Dir, Suites, Comment}.
    +{skip_suites, NodeRefs, Dir, Suites, Comment}.
     
    -{skip_groups, Dir, Suite, GroupNames, Comment}.
    -{skip_groups, NodeRefs, Dir, Suite, GroupNames, Comment}.
    +{skip_groups, Dir, Suite, GroupNames, Comment}.
    +{skip_groups, NodeRefs, Dir, Suite, GroupNames, Comment}.
     
    -{skip_cases, Dir, Suite, Cases, Comment}.
    -{skip_cases, NodeRefs, Dir, Suite, Cases, Comment}.

    Types:

    Bool            = true | false
    -Constant        = atom()
    -Value           = term()
    +{skip_cases, Dir, Suite, Cases, Comment}.
    +{skip_cases, NodeRefs, Dir, Suite, Cases, Comment}.

    Types:

    Bool            = true | false
    +Constant        = atom()
    +Value           = term()
     InclSpecsOption = join | separate
    -TestSpecs       = string() | [string()]
    -NodeAlias       = atom()
    -Node            = node()
    +TestSpecs       = string() | [string()]
    +NodeAlias       = atom()
    +Node            = node()
     NodeRef         = NodeAlias | Node | master
    -NodeRefs        = all_nodes | [NodeRef] | NodeRef
    -InitOptions     = term()
    -Label           = atom() | string()
    -VerbosityLevels = integer() | [{Category,integer()}]
    -Category        = atom()
    -CSSFile         = string()
    -ConnTypes       = all | [atom()]
    -N               = integer()
    -CoverSpecFile   = string()
    -IncludeDirs     = string() | [string()]
    -ConfigFiles     = string() | [string()]
    -ConfigDir       = string()
    -ConfigBaseNames = string() | [string()]
    -CallbackModule  = atom()
    -ConfigStrings   = string() | [string()]
    -LogDir          = string()
    -LogOpts         = [term()]
    +NodeRefs        = all_nodes | [NodeRef] | NodeRef
    +InitOptions     = term()
    +Label           = atom() | string()
    +VerbosityLevels = integer() | [{Category,integer()}]
    +Category        = atom()
    +CSSFile         = string()
    +ConnTypes       = all | [atom()]
    +N               = integer()
    +CoverSpecFile   = string()
    +IncludeDirs     = string() | [string()]
    +ConfigFiles     = string() | [string()]
    +ConfigDir       = string()
    +ConfigBaseNames = string() | [string()]
    +CallbackModule  = atom()
    +ConfigStrings   = string() | [string()]
    +LogDir          = string()
    +LogOpts         = [term()]
     PrivDirOption   = auto_per_run | auto_per_tc | manual_per_tc
    -EventHandlers   = atom() | [atom()]
    -InitArgs        = [term()]
    -CTHModules      = [CTHModule |
    -       	    {CTHModule, CTHInitArgs} |
    -       	    {CTHModule, CTHInitArgs, CTHPriority}]
    -CTHModule       = atom()
    -CTHInitArgs     = term()
    +EventHandlers   = atom() | [atom()]
    +InitArgs        = [term()]
    +CTHModules      = [CTHModule |
    +       	    {CTHModule, CTHInitArgs} |
    +       	    {CTHModule, CTHInitArgs, CTHPriority}]
    +CTHModule       = atom()
    +CTHInitArgs     = term()
     CTHOrder        = test | config
    -Dir             = string()
    -Suites          = atom() | [atom()] | all
    -Suite           = atom()
    -Groups          = GroupPath | GroupSpec | [GroupSpec] | all
    -GroupPath       = [[GroupSpec]]
    -GroupSpec       = GroupName | {GroupName,Properties} | {GroupName,Properties,[GroupSpec]}
    -GroupName       = atom()
    -GroupNames      = GroupName | [GroupName]
    -Cases           = atom() | [atom()] | all
    -Comment         = string() | ""

    The difference between the config terms above is that with ConfigDir, +Dir = string() +Suites = atom() | [atom()] | all +Suite = atom() +Groups = GroupPath | GroupSpec | [GroupSpec] | all +GroupPath = [[GroupSpec]] +GroupSpec = GroupName | {GroupName,Properties} | {GroupName,Properties,[GroupSpec]} +GroupName = atom() +GroupNames = GroupName | [GroupName] +Cases = atom() | [atom()] | all +Comment = string() | ""

    The difference between the config terms above is that with ConfigDir, ConfigBaseNames is a list of base names, that is, without directory paths. ConfigFiles must be full names, including paths. For example, the following -two terms have the same meaning:

    {config, ["/home/testuser/tests/config/nodeA.cfg",
    -          "/home/testuser/tests/config/nodeB.cfg"]}.
    +two terms have the same meaning:

    {config, ["/home/testuser/tests/config/nodeA.cfg",
    +          "/home/testuser/tests/config/nodeB.cfg"]}.
     
    -{config, "/home/testuser/tests/config", ["nodeA.cfg","nodeB.cfg"]}.

    Note

    Any relative paths, specified in the test specification, are relative to the +{config, "/home/testuser/tests/config", ["nodeA.cfg","nodeB.cfg"]}.

    Note

    Any relative paths, specified in the test specification, are relative to the directory containing the test specification file if ct_run -spec TestSpecFile ... or ct:run:test([{spec,TestSpecFile},...]) executes the test.

    The path is relative to the top-level log directory if @@ -691,36 +691,36 @@

    an uppercase letter, or a $, ?, or _. This means that it must always be single quoted (as the constant name is an atom, not text).

    The main benefit of constants is that they can be used to reduce the size (and avoid repetition) of long strings, such as file paths.

    Examples:

    %% 1a. no constant
    -{config, "/home/testuser/tests/config", ["nodeA.cfg","nodeB.cfg"]}.
    -{suites, "/home/testuser/tests/suites", all}.
    +{config, "/home/testuser/tests/config", ["nodeA.cfg","nodeB.cfg"]}.
    +{suites, "/home/testuser/tests/suites", all}.
     
     %% 1b. with constant
    -{define, 'TESTDIR', "/home/testuser/tests"}.
    -{config, "'TESTDIR'/config", ["nodeA.cfg","nodeB.cfg"]}.
    -{suites, "'TESTDIR'/suites", all}.
    +{define, 'TESTDIR', "/home/testuser/tests"}.
    +{config, "'TESTDIR'/config", ["nodeA.cfg","nodeB.cfg"]}.
    +{suites, "'TESTDIR'/suites", all}.
     
     %% 2a. no constants
    -{config, [testnode@host1, testnode@host2], "../config", ["nodeA.cfg","nodeB.cfg"]}.
    -{suites, [testnode@host1, testnode@host2], "../suites", [x_SUITE, y_SUITE]}.
    +{config, [testnode@host1, testnode@host2], "../config", ["nodeA.cfg","nodeB.cfg"]}.
    +{suites, [testnode@host1, testnode@host2], "../suites", [x_SUITE, y_SUITE]}.
     
     %% 2b. with constants
    -{define, 'NODE', testnode}.
    -{define, 'NODES', ['NODE'@host1, 'NODE'@host2]}.
    -{config, 'NODES', "../config", ["nodeA.cfg","nodeB.cfg"]}.
    -{suites, 'NODES', "../suites", [x_SUITE, y_SUITE]}.

    Constants make the test specification term alias, in previous versions of +{define, 'NODE', testnode}. +{define, 'NODES', ['NODE'@host1, 'NODE'@host2]}. +{config, 'NODES', "../config", ["nodeA.cfg","nodeB.cfg"]}. +{suites, 'NODES', "../suites", [x_SUITE, y_SUITE]}.

    Constants make the test specification term alias, in previous versions of Common Test, redundant. This term is deprecated but remains supported in upcoming Common Test releases. Replacing alias terms with define is strongly recommended though. An example of such replacement follows:

    %% using the old alias term
    -{config, "/home/testuser/tests/config/nodeA.cfg"}.
    -{alias, suite_dir, "/home/testuser/tests/suites"}.
    -{groups, suite_dir, x_SUITE, group1}.
    +{config, "/home/testuser/tests/config/nodeA.cfg"}.
    +{alias, suite_dir, "/home/testuser/tests/suites"}.
    +{groups, suite_dir, x_SUITE, group1}.
     
     %% replacing with constants
    -{define, 'TestDir', "/home/testuser/tests"}.
    -{define, 'CfgDir', "'TestDir'/config"}.
    -{define, 'SuiteDir', "'TestDir'/suites"}.
    -{config, 'CfgDir', "nodeA.cfg"}.
    -{groups, 'SuiteDir', x_SUITE, group1}.

    Constants can well replace term node also, but this still has a declarative +{define, 'TestDir', "/home/testuser/tests"}. +{define, 'CfgDir', "'TestDir'/config"}. +{define, 'SuiteDir', "'TestDir'/suites"}. +{config, 'CfgDir', "nodeA.cfg"}. +{groups, 'SuiteDir', x_SUITE, group1}.

    Constants can well replace term node also, but this still has a declarative value, mainly when used in combination with NodeRefs == all_nodes (see Types).

    @@ -728,25 +728,25 @@

    Example

    -

    Here follows a simple test specification example:

    {define, 'Top', "/home/test"}.
    -{define, 'T1', "'Top'/t1"}.
    -{define, 'T2', "'Top'/t2"}.
    -{define, 'T3', "'Top'/t3"}.
    -{define, 'CfgFile', "config.cfg"}.
    +

    Here follows a simple test specification example:

    {define, 'Top', "/home/test"}.
    +{define, 'T1', "'Top'/t1"}.
    +{define, 'T2', "'Top'/t2"}.
    +{define, 'T3', "'Top'/t3"}.
    +{define, 'CfgFile', "config.cfg"}.
     
    -{logdir, "'Top'/logs"}.
    +{logdir, "'Top'/logs"}.
     
    -{config, ["'T1'/'CfgFile'", "'T2'/'CfgFile'", "'T3'/'CfgFile'"]}.
    +{config, ["'T1'/'CfgFile'", "'T2'/'CfgFile'", "'T3'/'CfgFile'"]}.
     
    -{suites, 'T1', all}.
    -{skip_suites, 'T1', [t1B_SUITE,t1D_SUITE], "Not implemented"}.
    -{skip_cases, 'T1', t1A_SUITE, [test3,test4], "Irrelevant"}.
    -{skip_cases, 'T1', t1C_SUITE, [test1], "Ignore"}.
    +{suites, 'T1', all}.
    +{skip_suites, 'T1', [t1B_SUITE,t1D_SUITE], "Not implemented"}.
    +{skip_cases, 'T1', t1A_SUITE, [test3,test4], "Irrelevant"}.
    +{skip_cases, 'T1', t1C_SUITE, [test1], "Ignore"}.
     
    -{suites, 'T2', [t2B_SUITE,t2C_SUITE]}.
    -{cases, 'T2', t2A_SUITE, [test4,test1,test7]}.
    +{suites, 'T2', [t2B_SUITE,t2C_SUITE]}.
    +{cases, 'T2', t2A_SUITE, [test4,test1,test7]}.
     
    -{skip_suites, 'T3', all, "Not implemented"}.

    The example specifies the following:

    • The specified logdir directory is used for storing the HTML log files (in +{skip_suites, 'T3', all, "Not implemented"}.

    The example specifies the following:

    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"}]}
    -    ].

    +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"}]}
    +    ].

    @@ -308,14 +308,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"}
    -    ].

    +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"}
    +    ].

    @@ -337,20 +337,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 @@ -359,33 +359,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]}].
    -
    -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 +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}].
    +
    +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 @@ -411,13 +411,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 @@ -490,25 +490,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 simple as illustrated in the previous example, only the group name is stored in a tuple {group_result,GroupName}, which can be searched for in the status -lists.

    Example:

    end_per_group(group1, Config) ->
    -    Status = proplists:get_value(tc_group_result, Config),
    -    Failed = proplists:get_value(failed, Status),
    -    case lists:member({group_result,group2}, Failed) of
    +lists.

    Example:

    end_per_group(group1, Config) ->
    +    Status = proplists:get_value(tc_group_result, Config),
    +    Failed = proplists:get_value(failed, Status),
    +    case lists:member({group_result,group2}, Failed) of
               true ->
    -              {return_group_result,failed};
    +              {return_group_result,failed};
               false ->
    -              {return_group_result,ok}
    +              {return_group_result,ok}
         end;
     ...

    Note

    When a test case group is repeated, the configuration functions init_per_group/2 and end_per_group/2 are also always called with each @@ -540,9 +540,9 @@

    The test case group information function, group(GroupName), serves the same purpose as the suite- and test case information functions previously described. However, the scope for the group information function, is all test cases and -subgroups in the group in question (GroupName).

    Example:

    group(connection_tests) ->
    -   [{require,login_data},
    -    {timetrap,1000}].

    The group information properties override those set with the suite information +subgroups in the group in question (GroupName).

    Example:

    group(connection_tests) ->
    +   [{require,login_data},
    +    {timetrap,1000}].

    The group information properties override those set with the suite information function, and can in turn be overridden by test case information properties. For a list of valid information properties and more general information, see the Test Case Information Function.

    @@ -672,23 +672,23 @@

    (except from printouts made by Common Test itself).

    The general verbosity level is not associated with any particular category. This level sets the threshold for the standard I/O printouts, uncategorized ct:log/print/pal printouts, and printouts for categories with undefined -verbosity level.

    Examples:

    Some printouts during test case execution:

    io:format("1. Standard IO, importance = ~w~n", [?STD_IMPORTANCE]),
    -ct:log("2. Uncategorized, importance = ~w", [?STD_IMPORTANCE]),
    - ct:log(info, "3. Categorized info, importance = ~w", [?STD_IMPORTANCE]),
    - ct:log(info, ?LOW_IMPORTANCE, "4. Categorized info, importance = ~w", [?LOW_IMPORTANCE]),
    - ct:log(error, ?HI_IMPORTANCE, "5. Categorized error, importance = ~w", [?HI_IMPORTANCE]),
    - ct:log(error, ?MAX_IMPORTANCE, "6. Categorized error, importance = ~w", [?MAX_IMPORTANCE]),

    If starting the test with a general verbosity level of 50 (?STD_VERBOSITY):

    $ ct_run -verbosity 50

    the following is printed:

    1. Standard IO, importance = 50
    +verbosity level.

    Examples:

    Some printouts during test case execution:

    io:format("1. Standard IO, importance = ~w~n", [?STD_IMPORTANCE]),
    +ct:log("2. Uncategorized, importance = ~w", [?STD_IMPORTANCE]),
    + ct:log(info, "3. Categorized info, importance = ~w", [?STD_IMPORTANCE]),
    + ct:log(info, ?LOW_IMPORTANCE, "4. Categorized info, importance = ~w", [?LOW_IMPORTANCE]),
    + ct:log(error, ?HI_IMPORTANCE, "5. Categorized error, importance = ~w", [?HI_IMPORTANCE]),
    + ct:log(error, ?MAX_IMPORTANCE, "6. Categorized error, importance = ~w", [?MAX_IMPORTANCE]),

    If starting the test with a general verbosity level of 50 (?STD_VERBOSITY):

    $ ct_run -verbosity 50

    the following is printed:

    1. Standard IO, importance = 50
     2. Uncategorized, importance = 50
     3. Categorized info, importance = 50
     5. Categorized error, importance = 75
     6. Categorized error, importance = 99

    If starting the test with:

    $ ct_run -verbosity 1 and info 75

    the following is printed:

    3. Categorized info, importance = 50
     4. Categorized info, importance = 25
     6. Categorized error, importance = 99

    Note that the category argument is not required in order to only specify the -importance of a printout. Example:

    ct:pal(?LOW_IMPORTANCE, "Info report: ~p", [Info])

    Or perhaps in combination with constants:

    -define(INFO, ?LOW_IMPORTANCE).
    --define(ERROR, ?HI_IMPORTANCE).
    +importance of a printout. Example:

    ct:pal(?LOW_IMPORTANCE, "Info report: ~p", [Info])

    Or perhaps in combination with constants:

    -define(INFO, ?LOW_IMPORTANCE).
    +-define(ERROR, ?HI_IMPORTANCE).
     
    -ct:log(?INFO, "Info report: ~p", [Info])
    -ct:pal(?ERROR, "Error report: ~p", [Error])

    The functions ct:set_verbosity/2 and ct:get_verbosity/1 may be used to +ct:log(?INFO, "Info report: ~p", [Info]) +ct:pal(?ERROR, "Error report: ~p", [Error])

    The functions ct:set_verbosity/2 and ct:get_verbosity/1 may be used to modify and read verbosity levels during test execution.

    The arguments Format and FormatArgs in ct:log/print/pal are always passed on to the STDLIB function io:format/3 (For details, see the io manual page).

    ct:pal/4 and ct:log/5 add headers to strings being printed to the log file. diff --git a/prs/9045/lib/compiler-8.5.2/doc/html/beam_ssa.html b/prs/9045/lib/compiler-8.5.2/doc/html/beam_ssa.html index b9becff82f6a..0595b7268768 100644 --- a/prs/9045/lib/compiler-8.5.2/doc/html/beam_ssa.html +++ b/prs/9045/lib/compiler-8.5.2/doc/html/beam_ssa.html @@ -194,8 +194,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.

    @@ -240,7 +240,7 @@

    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 diff --git a/prs/9045/lib/compiler-8.5.2/doc/html/compile.html b/prs/9045/lib/compiler-8.5.2/doc/html/compile.html index da8ff3eeb26e..989848edc798 100644 --- a/prs/9045/lib/compiler-8.5.2/doc/html/compile.html +++ b/prs/9045/lib/compiler-8.5.2/doc/html/compile.html @@ -159,7 +159,7 @@

    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.

    @@ -183,14 +183,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}).

    +-compile(inline). +-compile({inline_size,100}).

    @@ -938,10 +938,10 @@

    file(File, Options)

    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 @@ -1007,7 +1007,7 @@

    file(File, Options)

    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 diff --git a/prs/9045/lib/compiler-8.5.2/doc/html/compiler.epub b/prs/9045/lib/compiler-8.5.2/doc/html/compiler.epub index cadd11380049..0ed08d85ac8b 100644 Binary files a/prs/9045/lib/compiler-8.5.2/doc/html/compiler.epub and b/prs/9045/lib/compiler-8.5.2/doc/html/compiler.epub differ diff --git a/prs/9045/lib/compiler-8.5.2/doc/html/notes.html b/prs/9045/lib/compiler-8.5.2/doc/html/notes.html index 8a248413bceb..1845ff8520cd 100644 --- a/prs/9045/lib/compiler-8.5.2/doc/html/notes.html +++ b/prs/9045/lib/compiler-8.5.2/doc/html/notes.html @@ -167,13 +167,13 @@

    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]).
      +
      • 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().
        +     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

      @@ -181,39 +181,39 @@

      Improvements and New Features

      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

  • diff --git a/prs/9045/lib/compiler-8.5.2/doc/html/ssa_checks.html b/prs/9045/lib/compiler-8.5.2/doc/html/ssa_checks.html index fc013a0a0b73..91fcd7d95dc8 100644 --- a/prs/9045/lib/compiler-8.5.2/doc/html/ssa_checks.html +++ b/prs/9045/lib/compiler-8.5.2/doc/html/ssa_checks.html @@ -148,32 +148,32 @@

    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} },
    @@ -181,9 +181,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}.

    + X = return_int(), + Y = return_tuple(), + {X, Y}.

    diff --git a/prs/9045/lib/crypto-5.5.1/doc/html/.build b/prs/9045/lib/crypto-5.5.1/doc/html/.build index 50ac2d6528cc..711563252480 100644 --- a/prs/9045/lib/crypto-5.5.1/doc/html/.build +++ b/prs/9045/lib/crypto-5.5.1/doc/html/.build @@ -21,7 +21,7 @@ dist/lato-latin-ext-300-normal-VPGGJKJL.woff2 dist/lato-latin-ext-400-normal-N27NCBWW.woff2 dist/lato-latin-ext-700-normal-Q2L5DVMW.woff2 dist/remixicon-NKANDIL5.woff2 -dist/search_data-44534696.js +dist/search_data-31A8E10D.js dist/sidebar_items-05B729E8.js engine_keys.html engine_load.html diff --git a/prs/9045/lib/crypto-5.5.1/doc/html/crypto.epub b/prs/9045/lib/crypto-5.5.1/doc/html/crypto.epub index 9f27126407f5..ab2c0af714e3 100644 Binary files a/prs/9045/lib/crypto-5.5.1/doc/html/crypto.epub and b/prs/9045/lib/crypto-5.5.1/doc/html/crypto.epub differ diff --git a/prs/9045/lib/crypto-5.5.1/doc/html/crypto.html b/prs/9045/lib/crypto-5.5.1/doc/html/crypto.html index 2eb9123ce2db..2f7f61bd28ac 100644 --- a/prs/9045/lib/crypto-5.5.1/doc/html/crypto.html +++ b/prs/9045/lib/crypto-5.5.1/doc/html/crypto.html @@ -601,7 +601,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 @@ -3137,7 +3137,7 @@

    rsa_params()

    -
    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 @@ -5554,9 +5554,9 @@

    rand_seed()

    BN_rand_range).

    Saves the state in the process dictionary before returning it as well. See also rand:seed/1 and rand_seed_s/0.

    When using the state object from this function the rand functions using it may raise exception error:low_entropy in case the random generator failed due -to lack of secure "randomness".

    Example

    _ = crypto:rand_seed(),
    -_IntegerValue = rand:uniform(42), % [1; 42]
    -_FloatValue = rand:uniform().     % [0.0; 1.0[
    +to lack of secure "randomness".

    Example

    _ = crypto:rand_seed(),
    +_IntegerValue = rand:uniform(42), % [1; 42]
    +_FloatValue = rand:uniform().     % [0.0; 1.0[
    @@ -5622,9 +5622,9 @@

    rand_seed_alg(Alg)

    generate cryptographically strong random numbers.

    Saves the state in the process dictionary before returning it as well. See also rand:seed/1 and rand_seed_alg_s/1.

    When using the state object from this function the rand functions using it may raise exception error:low_entropy in case the random generator failed due -to lack of secure "randomness".

    Example

    _ = crypto:rand_seed_alg(crypto_cache),
    -_IntegerValue = rand:uniform(42), % [1; 42]
    -_FloatValue = rand:uniform().     % [0.0; 1.0[
    +to lack of secure "randomness".

    Example

    _ = crypto:rand_seed_alg(crypto_cache),
    +_IntegerValue = rand:uniform(42), % [1; 42]
    +_FloatValue = rand:uniform().     % [0.0; 1.0[
    @@ -5656,12 +5656,12 @@

    rand_seed_alg(Alg, Seed)

    Creates a state object for random number generation, in order to generate cryptographically unpredictable random numbers.

    Saves the state in the process dictionary before returning it as well. See also -rand_seed_alg_s/2.

    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
    +rand_seed_alg_s/2.

    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
    @@ -6126,12 +6126,12 @@

    info()

    -

    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"}
    +  otp_crypto_version => "5.0.2"}
     2>

    More association types than documented may be present in the map.

    @@ -6199,8 +6199,8 @@

    info_lib()

    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.

    diff --git a/prs/9045/lib/crypto-5.5.1/doc/html/dist/search_data-31A8E10D.js b/prs/9045/lib/crypto-5.5.1/doc/html/dist/search_data-31A8E10D.js new file mode 100644 index 000000000000..1515a7995ca7 --- /dev/null +++ b/prs/9045/lib/crypto-5.5.1/doc/html/dist/search_data-31A8E10D.js @@ -0,0 +1 @@ +searchData={"items":[{"type":"module","doc":"Crypto Functions\n\nThis module provides a set of cryptographic functions.\n\n- **Hash functions** -\n\n - **SHA1, SHA2** - [Secure Hash Standard (FIPS PUB180-4)](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf)\n - **SHA3** - [SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions (FIPS PUB 202)](https://www.nist.gov/publications/sha-3-standard-permutation-based-hash-and-extendable-output-functions?pub_id=919061)\n\n - **BLAKE2** - [BLAKE2 — fast secure hashing](https://blake2.net/)\n\n - **SM3** - [The SM3 Hash Function (GM/T 0004-2012)](https://datatracker.ietf.org/doc/html/draft-sca-cfrg-sm3-02)\n\n - **MD5** - [The MD5 Message Digest Algorithm (RFC 1321)](http://www.ietf.org/rfc/rfc1321.txt)\n\n - **MD4** - [The MD4 Message Digest Algorithm (RFC 1320)](http://www.ietf.org/rfc/rfc1320.txt)\n\n- **MACs - Message Authentication Codes** -\n\n - **Hmac functions** - [Keyed-Hashing for Message Authentication (RFC 2104)](http://www.ietf.org/rfc/rfc2104.txt)\n\n - **Cmac functions** - [The AES-CMAC Algorithm (RFC 4493)](http://www.ietf.org/rfc/rfc4493.txt)\n\n - **POLY1305** - [ChaCha20 and Poly1305 for IETF Protocols (RFC 7539)](http://www.ietf.org/rfc/rfc7539.txt)\n\n- **Symmetric Ciphers** - \n\n - **DES, 3DES and AES** - [Block Cipher Techniques (NIST)](https://csrc.nist.gov/projects/block-cipher-techniques)\n\n - **Blowfish** -\n [Fast Software Encryption, Cambridge Security Workshop Proceedings (December 1993), Springer-Verlag, 1994, pp. 191-204.](https://www.schneier.com/academic/archives/1994/09/description_of_a_new.html)\n\n - **Chacha20** - [ChaCha20 and Poly1305 for IETF Protocols (RFC 7539)](http://www.ietf.org/rfc/rfc7539.txt)\n\n - **Chacha20_poly1305** - [ChaCha20 and Poly1305 for IETF Protocols (RFC 7539)](http://www.ietf.org/rfc/rfc7539.txt)\n\n - **SM4** - [The SM4 Block Cipher Algorithm](https://www.iso.org/standard/81564.html)\n\n- **Modes** -\n - **ECB, CBC, CFB, OFB and CTR** - [Recommendation for Block Cipher Modes of\n Operation: Methods and Techniques (NIST SP 800-38A)](https://csrc.nist.gov/publications/detail/sp/800-38a/final)\n\n - **GCM** - [Recommendation for Block Cipher Modes of Operation:\n Galois/Counter Mode (GCM) and GMAC (NIST SP 800-38D)](https://csrc.nist.gov/publications/detail/sp/800-38d/final)\n\n - **CCM** - [Recommendation for Block Cipher Modes of Operation: The CCM Mode\n for Authentication and Confidentiality (NIST SP 800-38C)](https://nvlpubs.nist.gov/nistpubs/legacy/sp/nistspecialpublication800-38c.pdf)\n\n- **Asymmetric Ciphers - Public Key Techniques** -\n\n - **RSA** - [PKCS #1: RSA Cryptography Specifications (RFC 3447)](http://www.ietf.org/rfc/rfc3447.txt)\n\n - **DSS** - [Digital Signature Standard (DSS) (FIPS 186-4)](https://csrc.nist.gov/publications/detail/fips/186/4/final)\n\n - **ECDSA** - [Elliptic Curve Digital Signature Algorithm (ECDSA)](http://csrc.nist.gov/groups/STM/cavp/documents/dss2/ecdsa2vs.pdf)\n\n - **SRP** - [The SRP Authentication and Key Exchange System (RFC 2945)](http://www.ietf.org/rfc/rfc2945.txt)\n\n> #### Note {: .info }\n>\n> The actual supported algorithms and features depends on their availability in\n> the actual libcrypto used. See the [crypto (App)](crypto_app.md) about\n> dependencies.\n>\n> Enabling FIPS mode will also disable algorithms and features.\n\nThe [CRYPTO User's Guide](index.html) has more information on FIPS, Engines and\nAlgorithm Details like key lengths.","title":"crypto","ref":"crypto.html"},{"type":"module","doc":"[](){: #error_old }","title":"Exceptions - crypto","ref":"crypto.html#module-exceptions"},{"type":"module","doc":"The exception `error:badarg` signifies that one or more arguments are of wrong\ndata type, or are otherwise badly formed.\n\nThe exception `error:notsup` signifies that the algorithm is known but is not\nsupported by current underlying libcrypto or explicitly disabled when building\nthat.\n\nFor a list of supported algorithms, see [supports(ciphers)](`supports/1`).\n\n[](){: #error_3tup }","title":"Atoms - the older style - crypto","ref":"crypto.html#module-atoms-the-older-style"},{"type":"module","doc":"The exception is:\n\n```text\nerror:{Tag, C_FileInfo, Description}\n\nTag = badarg | notsup | error\nC_FileInfo = term() % Usually only useful for the OTP maintainer\nDescription = string() % Clear text, sometimes only useful for the OTP maintainer\n```\n\nThe exception tags are:\n\n- **`badarg`** - Signifies that one or more arguments are of wrong data type or\n are otherwise badly formed.\n\n- **`notsup`** - Signifies that the algorithm is known but is not supported by\n current underlying libcrypto or explicitly disabled when building that one.\n\n- **`error`** - An error condition that should not occur, for example a memory\n allocation failed or the underlying cryptolib returned an error code, for\n example `\"Can't initialize context, step 1\"`. Those text usually needs\n searching the C-code to be understood.\n\nUsually there are more information in the call stack about which argument caused\nthe exception and what the values where.\n\nTo catch the exception, use for example:\n\n```text\ntry crypto:crypto_init(Ciph, Key, IV, true)\n catch\n error:{Tag, _C_FileInfo, Description} ->\n do_something(......)\n .....\nend\n```","title":"3-tuples - the new style - crypto","ref":"crypto.html#module-3-tuples-the-new-style"},{"type":"function","doc":"Convert binary representation, of an integer, to an Erlang integer.","title":"crypto.bytes_to_integer/1","ref":"crypto.html#bytes_to_integer/1"},{"type":"function","doc":"Get information about a cipher algorithm.\n\nReturns a map with information about block size, key length, IV length, aead\nsupport and possibly other properties of the cipher algorithm in question.\n\n> #### Note {: .info }\n>\n> The ciphers `aes_cbc`, `aes_cfb8`, `aes_cfb128`, `aes_ctr`, `aes_ecb`,\n> `aes_gcm` and `aes_ccm` has no keylength in the `Type` as opposed to for\n> example `aes_128_ctr`. They adapt to the length of the key provided in the\n> encrypt and decrypt function. Therefore it is impossible to return a valid\n> keylength in the map.\n>\n> Always use a `Type` with an explicit key length,\n\nFor a list of supported cipher algorithms, see\n[supports(ciphers)](`supports/1`).","title":"crypto.cipher_info/1","ref":"crypto.html#cipher_info/1"},{"type":"function","doc":"Compute the shared secret from the private key and the other party's public\nkey.\n\nSee also `public_key:compute_key/2`.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","title":"crypto.compute_key/4","ref":"crypto.html#compute_key/4"},{"type":"function","doc":"Finalize a streaming encryptions or decryptions operation and delivers the final\nbytes of the final block.\n\nThe data returned from this function may be empty if no padding was enabled in\n`crypto_init/3` or `crypto_init/4`.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","title":"crypto.crypto_final/1","ref":"crypto.html#crypto_final/1"},{"type":"function","doc":"Return information about a `t:crypto_state/0`.\n\nThe information returned is a map, which currently contains at least:\n\n- **`size`** - The number of bytes encrypted or decrypted so far.\n\n- **`padding_size`** - After a call to `crypto_final/1` it contains the number\n of bytes padded. Otherwise 0.\n\n- **`padding_type`** - The type of the padding as provided in the call to\n `crypto_init/3` or `crypto_init/4`.\n\n- **`encrypt`** - Is `true` if encryption is performed. It is `false` otherwise.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","title":"crypto.crypto_get_data/1","ref":"crypto.html#crypto_get_data/1"},{"type":"function","doc":"Initialize the state for a streaming encryption or decryption\noperation.\n\nEquivalent to the call\n[`crypto_init(Cipher, Key, <<>>, FlagOrOptions)`](`crypto_init/4`). It is\nintended for ciphers without an IV (nounce).\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","title":"crypto.crypto_init/3","ref":"crypto.html#crypto_init/3"},{"type":"function","doc":"Initialize the state for a streaming encryptions or decryptions operation.\n\nThe returned state should be used as argument to `crypto_update/2` and\n`crypto_final/1` to do the actual encryption or decryption.\n\nIf `IV = <<>>`, no IV is used. This is intended for ciphers without an IV\n(nounce). See `crypto_init/3`.\n\nFor encryption, set the `FlagOrOptions` to `true` or `[{encrypt,true}]`. For\ndecryption, set it to `false` or `[{encrypt,false}]`.\n\nPadding could be enabled with the option [\\{padding,Padding\\}](`t:padding/0`).\nThe [cryptolib_padding](`t:cryptolib_padding/0`) enables `pkcs_padding` or no\npadding (`none`). The paddings `zero` or `random` fills the last part of the\nlast block with zeroes or random bytes. If the last block is already full,\nnothing is added.\n\nIn decryption, the [cryptolib_padding](`t:cryptolib_padding/0`) removes such\npadding, if present. The [otp_padding](`t:otp_padding/0`) is not removed - it\nhas to be done elsewhere.\n\nIf padding is `{padding,none}` or not specified and the total data from all\nsubsequent [crypto_updates](`crypto_update/2`) does not fill the last block\nfully, that last data is lost. In case of `{padding,none}` there will be an\nerror in this case. If padding is not specified, the bytes of the unfilled block\nis silently discarded.\n\nThe actual padding is performed by `crypto_final/1`.\n\nFor blocksizes call `cipher_info/1`.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.\n\nSee\n[examples in the User's Guide.](new_api.md#examples-of-crypto_init-4-and-crypto_update-2)","title":"crypto.crypto_init/4","ref":"crypto.html#crypto_init/4"},{"type":"function","doc":"Do a complete encrypt or decrypt of the full text.\n\nAs `crypto_one_time/5` but for ciphers without IVs.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","title":"crypto.crypto_one_time/4","ref":"crypto.html#crypto_one_time/4"},{"type":"function","doc":"Do a complete encrypt or decrypt of the full text.\n\nArgument `Data` is the text to be encrypted or decrypted.\n\nFor encryption, set the `FlagOrOptions` to `true`. For decryption, set it to\n`false`. For setting other options, see `crypto_init/4`.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.\n\nSee [examples in the User's Guide.](new_api.md#example-of-crypto_one_time-5)","title":"crypto.crypto_one_time/5","ref":"crypto.html#crypto_one_time/5"},{"type":"function","doc":"","title":"crypto.crypto_one_time_aead/6","ref":"crypto.html#crypto_one_time_aead/6"},{"type":"function","doc":"Do a complete encrypt or decrypt with an AEAD cipher of the full text.\n\nFor encryption, set the `EncryptFlag` to `true` and set the `TagOrTagLength` to\nthe wanted size (in bytes) of the tag, that is, the tag length. If the default\nlength is wanted, the `crypto_one_time_aead/6` form may be used.\n\nFor decryption, set the `EncryptFlag` to `false` and put the tag to be checked\nin the argument `TagOrTagLength`.\n\nAdditional Authentication Data (AAD) is plaintext data that will not be\nencrypted, but will be covered by authenticity protection. It should be provided\nthrough the `AAD` argument, but can be an empty binary as well (`<<>>`) if not\nneeded. In that case, a plain AE (Authenticated Encryption) is performed instead\nof AEAD (Authenticated Encryption with Associated Data). This function only\nsupports ciphers that can be used both with and without AAD.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.\n\nSee\n[examples in the User's Guide.](new_api.md#example-of-crypto_one_time_aead-6)","title":"crypto.crypto_one_time_aead/7","ref":"crypto.html#crypto_one_time_aead/7"},{"type":"function","doc":"Add data to a streaming encryption or decryption operation.\n\nIf the part is less than a number of full blocks, only the full blocks (possibly\nnone) are encrypted or decrypted and the remaining bytes are saved to the next\n`crypto_update` operation. The `State` should be created with `crypto_init/3` or\n`crypto_init/4`.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.\n\nSee\n[examples in the User's Guide.](new_api.md#examples-of-crypto_init-4-and-crypto_update-2)","title":"crypto.crypto_update/2","ref":"crypto.html#crypto_update/2"},{"type":"function","doc":"Return the defining parameters of a elliptic curve.","title":"crypto.ec_curve/1","ref":"crypto.html#ec_curve/1"},{"type":"function","doc":"Return all supported named elliptic curves.","title":"crypto.ec_curves/0","ref":"crypto.html#ec_curves/0"},{"type":"function","doc":"Enable or disable FIPs mode.\n\nArgument `Enable` should be `true` to enable and `false` to disable FIPS mode.\nReturns `true` if the operation was successful or `false` otherwise.\n\nNote that to enable FIPS mode successfully, OTP must be built with the configure\noption `--enable-fips`, and the underlying libcrypto must also support FIPS.\n\nSee also `info_fips/0`.","title":"crypto.enable_fips_mode/1","ref":"crypto.html#enable_fips_mode/1"},{"type":"function","doc":"Add the engine to OpenSSL's internal list.\n\nThe function raises a `error:badarg` if the parameters are in wrong format. It\nmay also raise the exception `error:notsup` in case there is no engine support\nin the underlying OpenSSL implementation.","title":"crypto.engine_add/1","ref":"crypto.html#engine_add/1"},{"type":"function","doc":"Get a reference to an already loaded engine with `EngineId`. An error tuple is\nreturned if the engine can't be unloaded.\n\nThe function raises a `error:badarg` if the parameter is in wrong format. It may\nalso raise the exception `error:notsup` in case there is no engine support in\nthe underlying OpenSSL implementation.\n\nSee also the chapter [Engine Load](engine_load.md#engine_load) in the User's\nGuide.","title":"crypto.engine_by_id/1","ref":"crypto.html#engine_by_id/1"},{"type":"function","doc":"Send ctrl commands to an OpenSSL engine.\n\nThis function is the same as calling `engine_ctrl_cmd_string/4` with `Optional`\nset to `false`.\n\nThe function raises a `error:badarg` if the parameters are in wrong format. It\nmay also raise the exception `error:notsup` in case there is no engine support\nin the underlying OpenSSL implementation.","title":"crypto.engine_ctrl_cmd_string/3","ref":"crypto.html#engine_ctrl_cmd_string/3"},{"type":"function","doc":"Send ctrl commands to an OpenSSL engine.\n\n`Optional` is a\nboolean argument that can relax the semantics of the function. If set to `true`\nit will only return failure if the ENGINE supported the given command name but\nfailed while executing it, if the ENGINE doesn't support the command name it\nwill simply return success without doing anything. In this case we assume the\nuser is only supplying commands specific to the given ENGINE so we set this to\n`false`.\n\nThe function raises a `error:badarg` if the parameters are in wrong format. It\nmay also raise the exception `error:notsup` in case there is no engine support\nin the underlying OpenSSL implementation.","title":"crypto.engine_ctrl_cmd_string/4","ref":"crypto.html#engine_ctrl_cmd_string/4"},{"type":"function","doc":"Return a list of all possible engine methods.\n\nMay raise exception `error:notsup` in case there is no engine support in the\nunderlying OpenSSL implementation.\n\nSee also the chapter [Engine Load](engine_load.md#engine_load) in the User's\nGuide.","title":"crypto.engine_get_all_methods/0","ref":"crypto.html#engine_get_all_methods/0"},{"type":"function","doc":"Return the ID for the engine, or an empty binary if there is no id set.\n\nThe function raises a `error:badarg` if the parameters are in wrong format. It\nmay also raise the exception `error:notsup` in case there is no engine support\nin the underlying OpenSSL implementation.","title":"crypto.engine_get_id/1","ref":"crypto.html#engine_get_id/1"},{"type":"function","doc":"Return the name (eg a description) for the engine, or an empty binary if there\nis no name set.\n\nThe function raises a `error:badarg` if the parameters are in wrong format. It\nmay also raise the exception `error:notsup` in case there is no engine support\nin the underlying OpenSSL implementation.","title":"crypto.engine_get_name/1","ref":"crypto.html#engine_get_name/1"},{"type":"function","doc":"List the id's of all engines in OpenSSL's internal list.\n\nIt may also raise the exception `error:notsup` in case there is no engine\nsupport in the underlying OpenSSL implementation.\n\nSee also the chapter [Engine Load](engine_load.md#engine_load) in the User's\nGuide.\n\nMay raise exception `error:notsup` in case engine functionality is not supported\nby the underlying OpenSSL implementation.","title":"crypto.engine_list/0","ref":"crypto.html#engine_list/0"},{"type":"function","doc":"Load an OpenSSL engine.\n\nLoads the OpenSSL engine given by `EngineId` if it is available and intialize\nit. Returns `ok` and an engine handle, or if the engine can't be loaded an error\ntuple is returned.\n\nThe function raises a `error:badarg` if the parameters are in wrong format. It\nmay also raise the exception `error:notsup` in case there is no engine support\nin the underlying OpenSSL implementation.\n\nSee also the chapter [Engine Load](engine_load.md#engine_load) in the User's\nGuide.","title":"crypto.engine_load/3","ref":"crypto.html#engine_load/3"},{"type":"function","doc":"Register engine to handle some type of methods, for example\nengine_method_digests.\n\nThe function raises a `error:badarg` if the parameters are in wrong format. It\nmay also raise the exception `error:notsup` in case there is no engine support\nin the underlying OpenSSL implementation.","title":"crypto.engine_register/2","ref":"crypto.html#engine_register/2"},{"type":"function","doc":"Remove the engine from OpenSSL's internal list.\n\nThe function raises a `error:badarg` if the parameters are in wrong format. It\nmay also raise the exception `error:notsup` in case there is no engine support\nin the underlying OpenSSL implementation.","title":"crypto.engine_remove/1","ref":"crypto.html#engine_remove/1"},{"type":"function","doc":"Unload an OpenSSL engine.\n\nUnloads the OpenSSL engine given by `Engine`. An error tuple is returned if the\nengine can't be unloaded.\n\nThe function raises a `error:badarg` if the parameter is in wrong format. It may\nalso raise the exception `error:notsup` in case there is no engine support in\nthe underlying OpenSSL implementation.\n\nSee also the chapter [Engine Load](engine_load.md#engine_load) in the User's\nGuide.","title":"crypto.engine_unload/1","ref":"crypto.html#engine_unload/1"},{"type":"function","doc":"Unregister engine so it don't handle some type of methods.\n\nThe function raises a `error:badarg` if the parameters are in wrong format. It\nmay also raise the exception `error:notsup` in case there is no engine support\nin the underlying OpenSSL implementation.","title":"crypto.engine_unregister/2","ref":"crypto.html#engine_unregister/2"},{"type":"function","doc":"Load a dynamic engine if not already done.\n\nLoada the engine given by `EngineId` and the path to the dynamic library\nimplementing the engine. An error tuple is returned if the engine can't be\nloaded.\n\nThis function differs from the normal engine_load in the sense that it also add\nthe engine id to OpenSSL's internal engine list. The difference between the\nfirst call and the following is that the first loads the engine with the\ndynamical engine and the following calls fetch it from the OpenSSL's engine\nlist. All references that is returned are equal.\n\nUse [`engine_unload/1`](`engine_unload/1`) function to remove the references.\nBut remember that [`engine_unload/1`](`engine_unload/1`) just removes the\nreferences to the engine and not the tag in OpenSSL's engine list. That has to\nbe done with the [`engine_remove/1`](`engine_remove/1`) function when needed\n(just called once, from any of the references you got).\n\nThe function raises a `error:badarg` if the parameters are in wrong format. It\nmay also raise the exception `error:notsup` in case there is no engine support\nin the underlying OpenSSL implementation.\n\nSee also the chapter [Engine Load](engine_load.md#engine_load) in the User's\nGuide.","title":"crypto.ensure_engine_loaded/2","ref":"crypto.html#ensure_engine_loaded/2"},{"type":"function","doc":"Perform bit-wise XOR (exclusive or) on the data supplied.\n\nThe two byte sequences mus be of equal length.","title":"crypto.exor/2","ref":"crypto.html#exor/2"},{"type":"function","doc":"","title":"crypto.generate_key/2","ref":"crypto.html#generate_key/2"},{"type":"function","doc":"Generate a public key.\n\nSee also `public_key:generate_key/1`.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.\n\n> #### Note {: .info }\n>\n> If the linked version of cryptolib is OpenSSL 3.0\n>\n> - and the `Type` is `dh` (diffie-hellman)\n> - and the parameter `P` (in `t:dh_params/0`) is one of the MODP groups (see\n> [RFC 3526](https://tools.ietf.org/html/rfc3526))\n> - and the optional `PrivateKeyBitLength` parameter (in `t:dh_params/0`) is\n> present,\n>\n> then the optional key length parameter must be at least 224, 256, 302, 352 and\n> 400 for group sizes of 2048, 3072, 4096, 6144 and 8192, respectively.","title":"crypto.generate_key/3","ref":"crypto.html#generate_key/3"},{"type":"function","doc":"Compute a message digest.\n\nArgument `Type` is the digest type and argument `Data` is the full message.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","title":"crypto.hash/2","ref":"crypto.html#hash/2"},{"type":"function","doc":"Compare two binaries in constant time, such as results of HMAC computations.\n\nReturns true if the binaries are identical, false if they are of the same length\nbut not identical. The function raises an `error:badarg` exception if the\nbinaries are of different size.","title":"crypto.hash_equals/2","ref":"crypto.html#hash_equals/2"},{"type":"function","doc":"Finalize a streaming hash calculation.\n\nArgument `State` as returned from the last call to\n[hash_update](`hash_update/2`). The size of `Digest` is determined by\nthe type of hash function used to generate it.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","title":"crypto.hash_final/1","ref":"crypto.html#hash_final/1"},{"type":"function","doc":"Get information about a hash algorithm.\n\nReturns a map with information about block_size, size and possibly other\nproperties of the hash algorithm in question.\n\nFor a list of supported hash algorithms, see [supports(hashs)](`supports/1`).","title":"crypto.hash_info/1","ref":"crypto.html#hash_info/1"},{"type":"function","doc":"Initialize the state for a streaming hash digest calculation.\n\nArgument `Type` determines which digest to use. The returned state should be\nused as argument to `hash_update/2`.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","title":"crypto.hash_init/1","ref":"crypto.html#hash_init/1"},{"type":"function","doc":"Add data to a streaming digest calculation.\n\nUpdate the digest using the given `Data` of any length.\n\nArgument `State` must have been generated by [hash_init](`hash_init/1`) or a\nprevious call to this function.\n\nReturns `NewState` that must be passed into the next call to `hash_update/2` or\n`hash_final/1`.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","title":"crypto.hash_update/2","ref":"crypto.html#hash_update/2"},{"type":"function","doc":"Compute a message digest for an `xof_algorithm`.\n\nArgument `Type` is the type of digest, `Data` is the full text and `Length` is\nthe digest length in bits.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.\n\nMay raise exception `error:notsup` in case the chosen `Type` is not supported by\nthe underlying libcrypto implementation.","title":"crypto.hash_xof/3","ref":"crypto.html#hash_xof/3"},{"type":"function","doc":"Get information about crypto and the OpenSSL backend.\n\nReturns a map with information about the compilation and linking of crypto.\n\nExample:\n\n```erlang\n1> crypto:info().\n#{compile_type => normal,\n cryptolib_version_compiled => \"OpenSSL 3.0.0 7 sep 2021\",\n cryptolib_version_linked => \"OpenSSL 3.0.0 7 sep 2021\",\n link_type => dynamic,\n otp_crypto_version => \"5.0.2\"}\n2>\n```\n\nMore association types than documented may be present in the map.","title":"crypto.info/0","ref":"crypto.html#info/0"},{"type":"function","doc":"Get information about the operating status of FIPS.\n\nReturns the FIPS operating status of crypto and the underlying libcrypto\nlibrary. If crypto was built with FIPS support this can be either `enabled`\n(when running in FIPS mode) or `not_enabled`. For other builds\nthis value is always `not_supported`.\n\nSee configuration parameter [fips_mode](`e:crypto:crypto_app.md#fips_mode`)\nabout how to enable FIPS mode.\n\n> #### Warning {: .warning }\n>\n> In FIPS mode all non-FIPS compliant algorithms are disabled and raise\n> exception `error:notsup`. Check [supports(ciphers)](`supports/1`) that in FIPS\n> mode returns the restricted list of available algorithms.","title":"crypto.info_fips/0","ref":"crypto.html#info_fips/0"},{"type":"function","doc":"Get the name and version of the libraries used by crypto.\n\n`Name` is the name of the library. `VerNum` is the numeric version according to\nthe library's own versioning scheme. `VerStr` contains a text variant of the\nversion.\n\n```erlang\n> info_lib().\n[{<<\"OpenSSL\">>,269484095,<<\"OpenSSL 1.1.0c 10 Nov 2016\"\">>}]\n```\n\n> #### Note {: .info }\n>\n> From OTP R16 the _numeric version_ represents the version of the OpenSSL\n> _header files_ (`openssl/opensslv.h`) used when crypto was compiled. The text\n> variant represents the libcrypto library used at runtime. In earlier OTP\n> versions both numeric and text was taken from the library.","title":"crypto.info_lib/0","ref":"crypto.html#info_lib/0"},{"type":"function","doc":"Compute a `poly1305` MAC (Message Authentication Code).\n\nSame as [`mac(Type, undefined, Key, Data)`](`mac/4`).\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","title":"crypto.mac/3","ref":"crypto.html#mac/3"},{"type":"function","doc":"Compute a MAC (Message Authentication Code).\n\nArgument `Type` is the type of MAC and `Data` is the full message.\n\n`SubType` depends on the MAC `Type`:\n\n- For `hmac` it is a hash algorithm, see\n [Algorithm Details](algorithm_details.md#hmac) in the User's Guide.\n- For `cmac` it is a cipher suitable for cmac, see\n [Algorithm Details](algorithm_details.md#cmac) in the User's Guide.\n- For `poly1305` it should be set to `undefined` or the [mac/2](`mac_init/2`)\n function could be used instead, see\n [Algorithm Details](algorithm_details.md#poly1305) in the User's Guide.\n\n`Key` is the authentication key with a length according to the `Type` and\n`SubType`. The key length could be found with the `hash_info/1` (`hmac`) for and\n`cipher_info/1` (`cmac`) functions. For `poly1305` the key length is 32 bytes.\nNote that the cryptographic quality of the key is not checked.\n\nThe `Mac` result will have a default length depending on the `Type` and\n`SubType`. To set a shorter length, use `macN/4` or `macN/5` instead. The\ndefault length is documented in\n[Algorithm Details](algorithm_details.md#message-authentication-codes-macs) in\nthe User's Guide.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","title":"crypto.mac/4","ref":"crypto.html#mac/4"},{"type":"function","doc":"Finalize a streaming MAC operation.\n\nArgument `State` is the state as returned by the last call to `mac_update/2`.\n\nThe `Mac` result will have a default length depending on the `Type` and `SubType` in the\n[mac_init/2,3](`mac_init/3`) call. To set a shorter length, use `mac_finalN/2`\ninstead. The default length is documented in\n[Algorithm Details](algorithm_details.md#message-authentication-codes-macs) in\nthe User's Guide.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","title":"crypto.mac_final/1","ref":"crypto.html#mac_final/1"},{"type":"function","doc":"Finalize a MAC operation with a custom length.\n\nArgument `State` is the state as returned by the last call to `mac_update/2`.\n\n`Mac` will be a binary with at most `MacLength` bytes. Note that if `MacLength`\nis greater than the actual number of bytes returned from the underlying hash,\nthe returned hash will have that shorter length instead.\n\nThe max `MacLength` is documented in\n[Algorithm Details](algorithm_details.md#message-authentication-codes-macs) in\nthe User's Guide.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","title":"crypto.mac_finalN/2","ref":"crypto.html#mac_finalN/2"},{"type":"function","doc":"Initialize a state for streaming `poly1305` MAC calculation.\n\nSame as [`mac_init(Type, undefined, Key)`](`mac_init/3`).\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","title":"crypto.mac_init/2","ref":"crypto.html#mac_init/2"},{"type":"function","doc":"Initialize the state for streaming MAC calculation.\n\n`Type` determines which mac algorithm to use in the MAC operation.\n\n`SubType` depends on the MAC `Type`:\n\n- For `hmac` it is a hash algorithm, see\n [Algorithm Details](algorithm_details.md#hmac) in the User's Guide.\n- For `cmac` it is a cipher suitable for cmac, see\n [Algorithm Details](algorithm_details.md#cmac) in the User's Guide.\n- For `poly1305` it should be set to `undefined` or the [mac/2](`mac_init/2`)\n function could be used instead, see\n [Algorithm Details](algorithm_details.md#poly1305) in the User's Guide.\n\n`Key` is the authentication key with a length according to the `Type` and\n`SubType`. The key length could be found with the `hash_info/1` (`hmac`) for and\n`cipher_info/1` (`cmac`) functions. For `poly1305` the key length is 32 bytes.\nNote that the cryptographic quality of the key is not checked.\n\nThe returned `State` should be used in one or more subsequent calls to\n`mac_update/2`. The MAC value is finally returned by calling `mac_final/1` or\n`mac_finalN/2`.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.\n\nSee\n[examples in the User's Guide.](new_api.md#example-of-mac_init-mac_update-and-mac_final)","title":"crypto.mac_init/3","ref":"crypto.html#mac_init/3"},{"type":"function","doc":"Add data to a streaming MAC calculation.\n\nUpdate the MAC represented by `State0` using the given `Data` which could be of\nany length.\n\nThe `State0` is the State value originally from a MAC init function, that is\n`mac_init/2`, `mac_init/3` or the last call to `mac_update/2`. The value\n`State0` is returned unchanged by the function as a reference to a mutated\ninternal state. Hence, it is not possible to branch off a data stream by reusing\nold states.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","title":"crypto.mac_update/2","ref":"crypto.html#mac_update/2"},{"type":"function","doc":"Compute a `poly1305` MAC (Message Authentication Code) with a limited length.\n\nSame as [`macN(Type, undefined, Key, Data, MacLength)`](`macN/5`).\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","title":"crypto.macN/4","ref":"crypto.html#macN/4"},{"type":"function","doc":"Compute a MAC (Message Authentication Code) with a limited length.\n\nWorks like `mac/3` and `mac/4` but `MacLength` will limit the size of the\nresultant `Mac` to at most `MacLength` bytes. Note that if `MacLength` is\ngreater than the actual number of bytes returned from the underlying hash, the\nreturned hash will have that shorter length instead.\n\nThe max `MacLength` is documented in\n[Algorithm Details](algorithm_details.md#message-authentication-codes-macs) in\nthe User's Guide.","title":"crypto.macN/5","ref":"crypto.html#macN/5"},{"type":"function","doc":"Compute the function `N^P mod M`.","title":"crypto.mod_pow/3","ref":"crypto.html#mod_pow/3"},{"type":"function","doc":"PKCS #5 PBKDF2 (Password-Based Key Derivation Function 2) in combination with\nHMAC.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","title":"crypto.pbkdf2_hmac/5","ref":"crypto.html#pbkdf2_hmac/5"},{"type":"function","doc":"Decrypt using a private key.\n\nDecrypts the `CipherText`, encrypted with `public_encrypt/4` (or equivalent\nfunction) using the `PrivateKey`, and returns the plaintext (message digest).\nThis is a low level signature verification operation used for instance by older\nversions of the SSL protocol. See also\n[public_key:decrypt_private/2,3](`public_key:decrypt_private/2`)\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.\n\n> #### Warning {: .warning }\n>\n> This is a legacy function, for security reasons do not use with rsa_pkcs1_padding.","title":"crypto.private_decrypt/4","ref":"crypto.html#private_decrypt/4"},{"type":"function","doc":"Encrypt using a private key.\n\nEncrypts the `PlainText` using the `PrivateKey` and returns the ciphertext. This\nis a low level signature operation used for instance by older versions of the\nSSL protocol. See also\n[public_key:encrypt_private/2,3](`public_key:encrypt_private/2`)\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.\n\nPublic-key decryption using the private key. See also `crypto:private_decrypt/4`\n\n> #### Warning {: .warning }\n>\n> This is a legacy function, for security reasons do not use with rsa_pkcs1_padding.\n> For digital signatures use of [`sign/4`](`sign/4`) together\n> with [`verify/5`](`verify/5`) is the prefered solution.","title":"crypto.private_encrypt/4","ref":"crypto.html#private_encrypt/4"},{"type":"function","doc":"Fetch public key from a private key stored in an Engine.\n\nThe key must be of the type indicated by the Type parameter.","title":"crypto.privkey_to_pubkey/2","ref":"crypto.html#privkey_to_pubkey/2"},{"type":"function","doc":"Decrypt using a public key.\n\nDecrypts the `CipherText`, encrypted with `private_encrypt/4`(or equivalent\nfunction) using the `PublicKey`, and returns the plaintext (message digest).\nThis is a low level signature verification operation used for instance by older\nversions of the SSL protocol. See also\n[public_key:decrypt_public/2,3](`public_key:decrypt_public/2`)\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.\n\n> #### Warning {: .warning }\n>\n> This is a legacy function, for security reasons do not use with rsa_pkcs1_padding.\n> For digital signatures use of [`verify/5`](`verify/5`) together\n> with [`sign/4`](`sign/4`) is the prefered solution.","title":"crypto.public_decrypt/4","ref":"crypto.html#public_decrypt/4"},{"type":"function","doc":"Encrypt using a public key.\n\nEncrypts the `PlainText` (message digest) using the `PublicKey` and returns the\n`CipherText`. This is a low level signature operation used for instance by older\nversions of the SSL protocol. See also\n[public_key:encrypt_public/2,3](`public_key:encrypt_public/2`)\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.\n\n> #### Warning {: .warning }\n>\n> This is a legacy function, for security reasons do not use together with rsa_pkcs1_padding.","title":"crypto.public_encrypt/4","ref":"crypto.html#public_encrypt/4"},{"type":"function","doc":"Create a state object for [random number generation](`m:rand`), in order to\ngenerate cryptographically strong random numbers (based on OpenSSL's\n`BN_rand_range`).\n\nSaves the state in the process dictionary before returning it as\nwell. See also `rand:seed/1` and `rand_seed_s/0`.\n\nWhen using the state object from this function the `m:rand` functions using it\nmay raise exception `error:low_entropy` in case the random generator failed due\nto lack of secure \"randomness\".\n\n_Example_\n\n```erlang\n_ = crypto:rand_seed(),\n_IntegerValue = rand:uniform(42), % [1; 42]\n_FloatValue = rand:uniform(). % [0.0; 1.0[\n```","title":"crypto.rand_seed/0","ref":"crypto.html#rand_seed/0"},{"type":"function","doc":"Set the seed for PRNG to the given binary.\n\nThis calls the RAND_seed function from openssl. Only use this if the system you\nare running on does not have enough \"randomness\" built in. Normally this is when\n`strong_rand_bytes/1` raises `error:low_entropy`.","title":"crypto.rand_seed/1","ref":"crypto.html#rand_seed/1"},{"type":"function","doc":"Create a state object for [random number generation](`m:rand`), in order to\ngenerate cryptographically strong random numbers.\n\nSaves the state in the process dictionary before returning it as well. See also\n`rand:seed/1` and `rand_seed_alg_s/1`.\n\nWhen using the state object from this function the `m:rand` functions using it\nmay raise exception `error:low_entropy` in case the random generator failed due\nto lack of secure \"randomness\".\n\n_Example_\n\n```erlang\n_ = crypto:rand_seed_alg(crypto_cache),\n_IntegerValue = rand:uniform(42), % [1; 42]\n_FloatValue = rand:uniform(). % [0.0; 1.0[\n```","title":"crypto.rand_seed_alg/1","ref":"crypto.html#rand_seed_alg/1"},{"type":"function","doc":"Creates a state object for [random number generation](`m:rand`), in order to\ngenerate cryptographically unpredictable random numbers.\n\nSaves the state in the process dictionary before returning it as well. See also\n`rand_seed_alg_s/2`.\n\n_Example_\n\n```erlang\n_ = crypto:rand_seed_alg(crypto_aes, \"my seed\"),\nIntegerValue = rand:uniform(42), % [1; 42]\nFloatValue = rand:uniform(), % [0.0; 1.0[\n_ = crypto:rand_seed_alg(crypto_aes, \"my seed\"),\nIntegerValue = rand:uniform(42), % Same values\nFloatValue = rand:uniform(). % again\n```","title":"crypto.rand_seed_alg/2","ref":"crypto.html#rand_seed_alg/2"},{"type":"function","doc":"Create a state object for [random number generation](`m:rand`), in order to\ngenerate cryptographically strongly random numbers.\n\nSee also `rand:seed_s/1`.\n\nIf `Alg` is `crypto` this function behaves exactly like `rand_seed_s/0`.\n\nIf `Alg` is `crypto_cache` this function fetches random data with OpenSSL's\n`RAND_bytes` and caches it for speed using an internal word size of 56 bits that\nmakes calculations fast on 64 bit machines.\n\nWhen using the state object from this function the `m:rand` functions using it\nmay raise exception `error:low_entropy` in case the random generator failed due\nto lack of secure \"randomness\".\n\nThe cache size can be changed from its default value using the\n[crypto app's ](crypto_app.md)configuration parameter `rand_cache_size`.\n\n> #### Note {: .info }\n>\n> The state returned from this function cannot be used to get a reproducible\n> random sequence as from the other `m:rand` functions, since reproducibility\n> does not match cryptographically safe.\n>\n> In fact since random data is cached some numbers may get reproduced if you\n> try, but this is unpredictable.\n>\n> The only supported usage is to generate one distinct random sequence from this\n> start state.","title":"crypto.rand_seed_alg_s/1","ref":"crypto.html#rand_seed_alg_s/1"},{"type":"function","doc":"Create a state object for [random number generation](`m:rand`), in order to\ngenerate cryptographically unpredictable random numbers.\n\nSee also `rand_seed_alg/1`.\n\nTo get a long period the Xoroshiro928 generator from the `m:rand` module is used\nas a counter (with period 2^928 - 1) and the generator states are scrambled\nthrough AES to create 58-bit pseudo random values.\n\nThe result should be statistically completely unpredictable random values, since\nthe scrambling is cryptographically strong and the period is ridiculously long.\nBut the generated numbers are not to be regarded as cryptographically strong\nsince there is no re-keying schedule.\n\n- If you need cryptographically strong random numbers use `rand_seed_alg_s/1`\n with `Alg =:= crypto` or `Alg =:= crypto_cache`.\n- If you need to be able to repeat the sequence use this function.\n- If you do not need the statistical quality of this function, there are faster\n algorithms in the `m:rand` module.\n\nThanks to the used generator the state object supports the\n[`rand:jump/0,1`](`rand:jump/0`) function with distance 2^512.\n\nNumbers are generated in batches and cached for speed reasons. The cache size\ncan be changed from its default value using the\n[crypto app's ](crypto_app.md)configuration parameter `rand_cache_size`.","title":"crypto.rand_seed_alg_s/2","ref":"crypto.html#rand_seed_alg_s/2"},{"type":"function","doc":"Create a state object for [random number generation](`m:rand`), in order to\ngenerate cryptographically strongly random numbers (based on OpenSSL's\n`BN_rand_range`). See also `rand:seed_s/1`.\n\nWhen using the state object from this function the `m:rand` functions using it\nmay raise exception `error:low_entropy` in case the random generator failed due\nto lack of secure \"randomness\".\n\n> #### Note {: .info }\n>\n> The state returned from this function cannot be used to get a reproducible\n> random sequence as from the other `m:rand` functions, since reproducibility\n> does not match cryptographically safe.\n>\n> The only supported usage is to generate one distinct random sequence from this\n> start state.","title":"crypto.rand_seed_s/0","ref":"crypto.html#rand_seed_s/0"},{"type":"function","doc":"Generate a random integer number.\n\nThe interval is `From =< N < To`. Uses the `crypto` library\npseudo-random number generator. `To` must be larger than `From`.","title":"crypto.rand_uniform/2","ref":"crypto.html#rand_uniform/2"},{"type":"function","doc":"","title":"crypto.sign/4","ref":"crypto.html#sign/4"},{"type":"function","doc":"Create a digital signature.\n\nThe msg is either the binary \"cleartext\" data to be signed or it is the hashed\nvalue of \"cleartext\" i.e. the digest (plaintext).\n\nAlgorithm `dss` can only be used together with digest type `sha`.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.\n\nSee also `public_key:sign/3`.","title":"crypto.sign/5","ref":"crypto.html#sign/5"},{"type":"function","doc":"Use [`application:start(crypto)`](`application:start/1`) instead.\n\n> #### Warning {: .warning }\n>\n> This function does not work if FIPS mode is to be enabled. FIPS mode will be\n> disabled even if configuration parameter `fips_mode` is set to `true`. Use\n> [`application:start(crypto)`](`application:start/1`) instead.","title":"crypto.start/0","ref":"crypto.html#start/0"},{"type":"function","doc":"Use [`application:stop(crypto)`](`application:stop/1`) instead.","title":"crypto.stop/0","ref":"crypto.html#stop/0"},{"type":"function","doc":"Generate bytes with randomly uniform values 0..255.\n\nReturns the result in a binary with `N` bytes.\n\nUses a cryptographically secure PRNG seeded and periodically mixed with\noperating system provided entropy. By default this is the `RAND_bytes` method\nfrom OpenSSL.\n\nMay raise exception `error:low_entropy` in case the random generator failed due\nto lack of secure \"randomness\".","title":"crypto.strong_rand_bytes/1","ref":"crypto.html#strong_rand_bytes/1"},{"type":"function","doc":"Get which crypto algorithms that are supported by the underlying libcrypto\nlibrary.\n\nSee `hash_info/1` and `cipher_info/1` for information about the hash and cipher\nalgorithms.","title":"crypto.supports/1","ref":"crypto.html#supports/1"},{"type":"function","doc":"","title":"crypto.verify/5","ref":"crypto.html#verify/5"},{"type":"function","doc":"Verify a digital signature.\n\nThe msg is either the binary \"cleartext\" data to be signed or it is the hashed\nvalue of \"cleartext\" i.e. the digest (plaintext).\n\nAlgorithm `dss` can only be used together with digest type `sha`.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.\n\nSee also `public_key:verify/4`.","title":"crypto.verify/6","ref":"crypto.html#verify/6"},{"type":"type","doc":"","title":"crypto.blake2/0","ref":"crypto.html#t:blake2/0"},{"type":"type","doc":"","title":"crypto.cipher/0","ref":"crypto.html#t:cipher/0"},{"type":"type","doc":"Ciphers known by the CRYPTO application.\n\nNote that this list might be reduced if the underlying libcrypto does not\nsupport all of them.","title":"crypto.cipher_aead/0","ref":"crypto.html#t:cipher_aead/0"},{"type":"type","doc":"","title":"crypto.cipher_iv/0","ref":"crypto.html#t:cipher_iv/0"},{"type":"type","doc":"","title":"crypto.cipher_no_iv/0","ref":"crypto.html#t:cipher_no_iv/0"},{"type":"type","doc":"","title":"crypto.cmac_cipher_algorithm/0","ref":"crypto.html#t:cmac_cipher_algorithm/0"},{"type":"type","doc":"The `t:compatibility_only_hash/0` algorithms are recommended only for\ncompatibility with existing applications.","title":"crypto.compatibility_only_hash/0","ref":"crypto.html#t:compatibility_only_hash/0"},{"type":"type","doc":"","title":"crypto.crypto_integer/0","ref":"crypto.html#t:crypto_integer/0"},{"type":"type","doc":"Selects encryption (`{encrypt,true}`) or decryption (`{encrypt,false}`).","title":"crypto.crypto_opt/0","ref":"crypto.html#t:crypto_opt/0"},{"type":"type","doc":"","title":"crypto.crypto_opts/0","ref":"crypto.html#t:crypto_opts/0"},{"type":"opaque","doc":"","title":"crypto.crypto_state/0","ref":"crypto.html#t:crypto_state/0"},{"type":"type","doc":"The `cryptolib_padding` are paddings that may be present in the underlying\ncryptolib linked to the Erlang/OTP crypto app.\n\nFor OpenSSL, see the [OpenSSL documentation](https://openssl.org). and find\n`EVP_CIPHER_CTX_set_padding()` in cryptolib for your linked version.","title":"crypto.cryptolib_padding/0","ref":"crypto.html#t:cryptolib_padding/0"},{"type":"type","doc":"```text\ndh_params() = [P, G] | [P, G, PrivateKeyBitLength]\n```","title":"crypto.dh_params/0","ref":"crypto.html#t:dh_params/0"},{"type":"type","doc":"","title":"crypto.dh_private/0","ref":"crypto.html#t:dh_private/0"},{"type":"type","doc":"","title":"crypto.dh_public/0","ref":"crypto.html#t:dh_public/0"},{"type":"type","doc":"","title":"crypto.dss_digest_type/0","ref":"crypto.html#t:dss_digest_type/0"},{"type":"type","doc":"```text\ndss_public() = [P, Q, G, Y]\n```\n\nWhere P, Q and G are the dss parameters and Y is the public key.\n\n```text\ndss_private() = [P, Q, G, X]\n```\n\nWhere P, Q and G are the dss parameters and X is the private key.","title":"crypto.dss_private/0","ref":"crypto.html#t:dss_private/0"},{"type":"type","doc":"","title":"crypto.dss_public/0","ref":"crypto.html#t:dss_public/0"},{"type":"type","doc":"Curve definition details.","title":"crypto.ec_basis/0","ref":"crypto.html#t:ec_basis/0"},{"type":"type","doc":"","title":"crypto.ec_characteristic_two_field/0","ref":"crypto.html#t:ec_characteristic_two_field/0"},{"type":"type","doc":"Parametric curve definition.","title":"crypto.ec_curve/0","ref":"crypto.html#t:ec_curve/0"},{"type":"type","doc":"","title":"crypto.ec_explicit_curve/0","ref":"crypto.html#t:ec_explicit_curve/0"},{"type":"type","doc":"","title":"crypto.ec_field/0","ref":"crypto.html#t:ec_field/0"},{"type":"type","doc":"","title":"crypto.ec_named_curve/0","ref":"crypto.html#t:ec_named_curve/0"},{"type":"type","doc":"","title":"crypto.ec_prime_field/0","ref":"crypto.html#t:ec_prime_field/0"},{"type":"type","doc":"","title":"crypto.ecdh_params/0","ref":"crypto.html#t:ecdh_params/0"},{"type":"type","doc":"","title":"crypto.ecdh_private/0","ref":"crypto.html#t:ecdh_private/0"},{"type":"type","doc":"","title":"crypto.ecdh_public/0","ref":"crypto.html#t:ecdh_public/0"},{"type":"type","doc":"","title":"crypto.ecdsa_digest_type/0","ref":"crypto.html#t:ecdsa_digest_type/0"},{"type":"type","doc":"","title":"crypto.ecdsa_params/0","ref":"crypto.html#t:ecdsa_params/0"},{"type":"type","doc":"","title":"crypto.ecdsa_private/0","ref":"crypto.html#t:ecdsa_private/0"},{"type":"type","doc":"","title":"crypto.ecdsa_public/0","ref":"crypto.html#t:ecdsa_public/0"},{"type":"type","doc":"","title":"crypto.eddsa_params/0","ref":"crypto.html#t:eddsa_params/0"},{"type":"type","doc":"","title":"crypto.eddsa_private/0","ref":"crypto.html#t:eddsa_private/0"},{"type":"type","doc":"","title":"crypto.eddsa_public/0","ref":"crypto.html#t:eddsa_public/0"},{"type":"type","doc":"","title":"crypto.edwards_curve_dh/0","ref":"crypto.html#t:edwards_curve_dh/0"},{"type":"type","doc":"Note that some curves are disabled if FIPS is enabled.","title":"crypto.edwards_curve_ed/0","ref":"crypto.html#t:edwards_curve_ed/0"},{"type":"type","doc":"Pre and Post commands for [engine_load/3 and /4](`engine_load/3`).","title":"crypto.engine_cmnd/0","ref":"crypto.html#t:engine_cmnd/0"},{"type":"type","doc":"","title":"crypto.engine_key_ref/0","ref":"crypto.html#t:engine_key_ref/0"},{"type":"type","doc":"","title":"crypto.engine_method_type/0","ref":"crypto.html#t:engine_method_type/0"},{"type":"type","doc":"The result of a call to `engine_load/3`.","title":"crypto.engine_ref/0","ref":"crypto.html#t:engine_ref/0"},{"type":"type","doc":"","title":"crypto.hash_algorithm/0","ref":"crypto.html#t:hash_algorithm/0"},{"type":"opaque","doc":"","title":"crypto.hash_state/0","ref":"crypto.html#t:hash_state/0"},{"type":"type","doc":"","title":"crypto.hash_xof_algorithm/0","ref":"crypto.html#t:hash_xof_algorithm/0"},{"type":"type","doc":"","title":"crypto.hmac_hash_algorithm/0","ref":"crypto.html#t:hmac_hash_algorithm/0"},{"type":"type","doc":"Identifies the key to be used. The format depends on the loaded engine. It is\npassed to the `ENGINE_load_(private|public)_key` functions in libcrypto.","title":"crypto.key_id/0","ref":"crypto.html#t:key_id/0"},{"type":"type","doc":"Always `t:binary/0` when used as return value","title":"crypto.key_integer/0","ref":"crypto.html#t:key_integer/0"},{"type":"opaque","doc":"Contexts with an internal state that should not be manipulated but passed\nbetween function calls.","title":"crypto.mac_state/0","ref":"crypto.html#t:mac_state/0"},{"type":"type","doc":"Erlang/OTP adds a either padding of zeroes or padding with random bytes.","title":"crypto.otp_padding/0","ref":"crypto.html#t:otp_padding/0"},{"type":"type","doc":"This option handles padding in the last block. If not set, no padding is done\nand any bytes in the last unfilled block is silently discarded.","title":"crypto.padding/0","ref":"crypto.html#t:padding/0"},{"type":"type","doc":"The password of the key stored in an engine.","title":"crypto.password/0","ref":"crypto.html#t:password/0"},{"type":"type","doc":"Algorithms for public key encrypt/decrypt. Only RSA is supported.","title":"crypto.pk_encrypt_decrypt_algs/0","ref":"crypto.html#t:pk_encrypt_decrypt_algs/0"},{"type":"type","doc":"","title":"crypto.pk_encrypt_decrypt_opts/0","ref":"crypto.html#t:pk_encrypt_decrypt_opts/0"},{"type":"type","doc":"Algorithms for sign and verify.","title":"crypto.pk_sign_verify_algs/0","ref":"crypto.html#t:pk_sign_verify_algs/0"},{"type":"type","doc":"","title":"crypto.pk_sign_verify_opts/0","ref":"crypto.html#t:pk_sign_verify_opts/0"},{"type":"type","doc":"","title":"crypto.rand_cache_seed/0","ref":"crypto.html#t:rand_cache_seed/0"},{"type":"type","doc":"Those option forms are kept only for compatibility and should not be used in new\ncode.","title":"crypto.rsa_compat_opts/0","ref":"crypto.html#t:rsa_compat_opts/0"},{"type":"type","doc":"","title":"crypto.rsa_digest_type/0","ref":"crypto.html#t:rsa_digest_type/0"},{"type":"type","doc":"","title":"crypto.rsa_opt/0","ref":"crypto.html#t:rsa_opt/0"},{"type":"type","doc":"Options for public key encrypt/decrypt. Only RSA is supported.\n\n> #### Warning {: .warning }\n>\n> The RSA options are experimental.\n>\n> The exact set of options and there syntax _may_ be changed without prior\n> notice.","title":"crypto.rsa_padding/0","ref":"crypto.html#t:rsa_padding/0"},{"type":"type","doc":"```text\nrsa_public() = [E, N]\n```\n\n```erlang\nrsa_private() = [E, N, D] | [E, N, D, P1, P2, E1, E2, C]\n```\n\nWhere E is the public exponent, N is public modulus and D is the private\nexponent. The longer key format contains redundant information that will make\nthe calculation faster. P1 and P2 are first and second prime factors. E1 and E2\nare first and second exponents. C is the CRT coefficient. The terminology is\ntaken from [RFC 3447](http://www.ietf.org/rfc/rfc3447.txt).","title":"crypto.rsa_params/0","ref":"crypto.html#t:rsa_params/0"},{"type":"type","doc":"","title":"crypto.rsa_private/0","ref":"crypto.html#t:rsa_private/0"},{"type":"type","doc":"","title":"crypto.rsa_public/0","ref":"crypto.html#t:rsa_public/0"},{"type":"type","doc":"","title":"crypto.rsa_sign_verify_opt/0","ref":"crypto.html#t:rsa_sign_verify_opt/0"},{"type":"type","doc":"Options for sign and verify.\n\n> #### Warning {: .warning }\n>\n> The RSA options are experimental.\n>\n> The exact set of options and there syntax _may_ be changed without prior\n> notice.","title":"crypto.rsa_sign_verify_padding/0","ref":"crypto.html#t:rsa_sign_verify_padding/0"},{"type":"type","doc":"","title":"crypto.sha1/0","ref":"crypto.html#t:sha1/0"},{"type":"type","doc":"","title":"crypto.sha2/0","ref":"crypto.html#t:sha2/0"},{"type":"type","doc":"","title":"crypto.sha3/0","ref":"crypto.html#t:sha3/0"},{"type":"type","doc":"","title":"crypto.sha3_xof/0","ref":"crypto.html#t:sha3_xof/0"},{"type":"type","doc":"","title":"crypto.srp_comp_params/0","ref":"crypto.html#t:srp_comp_params/0"},{"type":"type","doc":"","title":"crypto.srp_gen_params/0","ref":"crypto.html#t:srp_gen_params/0"},{"type":"type","doc":"Where Verifier is `v`, Generator is `g` and Prime is` N`, DerivedKey is `X`, and\nScrambler is `u` (optional will be generated if not provided) from\n[SRP design](http://srp.stanford.edu/design.html) Version = '3' | '6' | '6a'","title":"crypto.srp_host_comp_params/0","ref":"crypto.html#t:srp_host_comp_params/0"},{"type":"type","doc":"","title":"crypto.srp_host_gen_params/0","ref":"crypto.html#t:srp_host_gen_params/0"},{"type":"type","doc":"```text\nsrp_public() = key_integer()\n```\n\nWhere is `A` or `B` from [SRP design](http://srp.stanford.edu/design.html)\n\n```text\nsrp_private() = key_integer()\n```\n\nWhere is `a` or `b` from [SRP design](http://srp.stanford.edu/design.html)","title":"crypto.srp_private/0","ref":"crypto.html#t:srp_private/0"},{"type":"type","doc":"","title":"crypto.srp_public/0","ref":"crypto.html#t:srp_public/0"},{"type":"type","doc":"","title":"crypto.srp_user_comp_params/0","ref":"crypto.html#t:srp_user_comp_params/0"},{"type":"type","doc":"","title":"crypto.srp_user_gen_params/0","ref":"crypto.html#t:srp_user_gen_params/0"},{"type":"extras","doc":"\n# Crypto Application","title":"Crypto Application","ref":"crypto_app.html"},{"type":"extras","doc":"The purpose of the Crypto application is to provide an Erlang API to\ncryptographic functions, see `m:crypto`. Note that the API is on a fairly low\nlevel and there are some corresponding API functions available in\n`m:public_key`, on a higher abstraction level, that uses the crypto application\nin its implementation.","title":"Description - Crypto Application","ref":"crypto_app.html#description"},{"type":"extras","doc":"The current crypto implementation uses nifs to interface OpenSSLs crypto library\nand may work with limited functionality with as old versions as _OpenSSL_\n0\\.9.8c. FIPS mode support requires at least version 1.0.1 and a FIPS capable\nOpenSSL installation. We recommend using a version that is officially supported\nby the OpenSSL project. API compatible backends like LibreSSL should also work.\n\nThe crypto app is tested daily with at least one version of each of the OpenSSL\n1.0.1, 1.0.2, 1.1.0, 1.1.1 and 3.0. FIPS mode is also tested for 1.0.1, 1.0.2\nand 3.0.\n\nUsing OpenSSL 3.0 with Engines is supported since OTP 26.2.\n\nSource releases of OpenSSL can be downloaded from the\n[OpenSSL](http://www.openssl.org) project home page, or mirror sites listed\nthere.","title":"DEPENDENCIES - Crypto Application","ref":"crypto_app.html#dependencies"},{"type":"extras","doc":"The following configuration parameters are defined for the crypto application.\nSee [`app(3)`](`e:kernel:app.md`) for more information about configuration\nparameters.\n\n[](){: #fips_mode }\n- **`fips_mode = boolean()`** - Specifies whether to run crypto in FIPS mode.\n This setting will take effect when the nif module is loaded. If FIPS mode is\n requested but not available at run time the nif module and thus the crypto\n module will fail to load. This mechanism prevents the accidental use of\n non-validated algorithms.\n\n- **`rand_cache_size = integer()`** - Sets the cache size in bytes to use by\n [`crypto:rand_seed_alg(crypto_cache)` ](`crypto:rand_seed_alg/1`)and\n [`crypto:rand_seed_alg_s(crypto_cache)` ](`crypto:rand_seed_alg_s/1`). This\n parameter is read when a seed function is called, and then kept in generators\n state object. It has a rather small default value that causes reads of strong\n random bytes about once per hundred calls for a random value. The set value is\n rounded up to an integral number of words of the size these seed functions\n use.","title":"CONFIGURATION - Crypto Application","ref":"crypto_app.html#configuration"},{"type":"extras","doc":"application(3)","title":"SEE ALSO - Crypto Application","ref":"crypto_app.html#see-also"},{"type":"extras","doc":"\n# Crypto Release Notes\n\nThis document describes the changes made to the Crypto application.","title":"Crypto Release Notes","ref":"notes.html"},{"type":"extras","doc":"","title":"Crypto 5.5.1 - Crypto Release Notes","ref":"notes.html#crypto-5-5-1"},{"type":"extras","doc":"- crypto built with `--enable-fips` will now accept an OpenSSL 3 lib without fips provider as long as fips mode is not enabled.\n\n Own Id: OTP-19212 Aux Id: [GH-8562]\n\n[GH-8562]: https://github.com/erlang/otp/issues/8562","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Added a warning in the documentation to avoid calling `crypto:start/0` as it does not work for FIPS mode. Use `application:start(crypto)` instead.\n\n Own Id: OTP-19143\n\n- Deprecation of RSA encryption functions has been reverted, as there still exists legitimate use cases with other padding modes than PKCS-1.\n \n While use PCKS-1 padding with some versions of cryptolib could be considered secure, we still recommend using other algorithms that are less sensitive to oracle attacks.\n\n Own Id: OTP-19163\n\n- Compiler warnings for some removed functions have been corrected to point out the correct replacement functions.\n\n Own Id: OTP-19186 Aux Id: [PR-8709]\n\n[PR-8709]: https://github.com/erlang/otp/pull/8709","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 5.5 - Crypto Release Notes","ref":"notes.html#crypto-5-5"},{"type":"extras","doc":"- The documentation has been migrated to use Markdown and ExDoc.\n\n Own Id: OTP-18955 Aux Id: [PR-8026]\n\n- Removed functions `crypto_dyn_iv_init/3` and `crypto_dyn_iv_update/3` which were marked as deprecated since OTP 25.\n\n Own Id: OTP-18973\n\n- Add support for sm3 hash and hmac.\n\n Own Id: OTP-18975 Aux Id: [PR-6658]\n\n- `OPENSSL_thread_stop` is called when `crypto` is purged to not leak thread specific data.\n\n Own Id: OTP-18978 Aux Id: [PR-7809]\n\n- Add SM4 block cipher implemented according to GB/T 32907-2016.\n\n Own Id: OTP-19005 Aux Id: [PR-8168]\n\n- The existing function `ssl:key_exporter_materials/4` is now documented and supported.\n\n *** POTENTIAL INCOMPATIBILITY ***\n\n Own Id: OTP-19016 Aux Id: [PR-8233]\n\n- Due to another attack on PKCS #1 v1.5 padding, known as the Marvin attack, about which we were alerted by Hubert Kario from Red Hat. You can find more details about the attack at\n https://people.redhat.com/~hkario/marvin/\n Functions that may be vulnerable are now deprecated. \n \n Note that you might mitigate the problem \n by using appropriate versions of OpenSSL together with our software, but we recommend not using them at all. \n \n Also avoid using TLS versions prior to TLS-1.2 (not supported by default) and\n do not enable RSA-key exchange cipher suites (not supported by default).\n\n *** POTENTIAL INCOMPATIBILITY ***\n\n Own Id: OTP-19075\n\n[PR-8026]: https://github.com/erlang/otp/pull/8026\n[PR-6658]: https://github.com/erlang/otp/pull/6658\n[PR-7809]: https://github.com/erlang/otp/pull/7809\n[PR-8168]: https://github.com/erlang/otp/pull/8168\n[PR-8233]: https://github.com/erlang/otp/pull/8233","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 5.4.2.3 - Crypto Release Notes","ref":"notes.html#crypto-5-4-2-3"},{"type":"extras","doc":"* Fixed bug that could cause blocking scheduler threads in `crypto:supports(curves)` if called the first time by more than one Erlang process. Bug exists only in OTP-26.2.5.4.\n\n Own Id: OTP-19316 Aux Id: GH-8971, PR-8979\n* Fixed `crypto:hash_final/1` for digest types `shake128` and `shake256` when using OpenSSL 3.4 or newer.\n\n Own Id: OTP-19329 Aux Id: GH-8997, PR-9002","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 5.4.2.2 - Crypto Release Notes","ref":"notes.html#crypto-5-4-2-2"},{"type":"extras","doc":"* crypto built with `--enable-fips` will now accept an OpenSSL 3 lib without fips provider as long as fips mode is not enabled.\n\n Own Id: OTP-19212 Aux Id: GH-8562, PR-8762\n* `crypto:strong_rand_bytes/2` fixed to work on Ubuntu pro with installed FIPS support.\n\n Own Id: OTP-19223 Aux Id: PR-8800, GH-8769","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 5.4.2.1 - Crypto Release Notes","ref":"notes.html#crypto-5-4-2-1"},{"type":"extras","doc":"* Add warning in documentation to avoid `crypto:start/0` as it does not work for FIPS mode. Use `application:start(crypto)` instead.\n\n Own Id: OTP-19143","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 5.4.2 - Crypto Release Notes","ref":"notes.html#crypto-5-4-2"},{"type":"extras","doc":"* Fix building with `--enable-fips` with OpenSSL 3 on MacOS.\n\n Own Id: OTP-19038 Aux Id: GH-8271, PR-8277","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 5.4.1 - Crypto Release Notes","ref":"notes.html#crypto-5-4-1"},{"type":"extras","doc":"* Fix compile error when OPENSSL_NO_DES is defined.\n\n Own Id: OTP-18921\n* The function `crypto:pbkdf2_hmac` will no longer block the main schedulers. If the iteration count or block size parameters are such that the function is likely to take a long time to execute, the function will be scheduled to run on a dirty CPU scheduler.\n\n Own Id: OTP-18996 Aux Id: PR-8173, PR-8174","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 5.4 - Crypto Release Notes","ref":"notes.html#crypto-5-4"},{"type":"extras","doc":"- Fixed some benign compile warnings on Windows.\n\n Own Id: OTP-18895","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Enable engine support for OpenSSL versions 3.\n\n Own Id: OTP-18832 Aux Id: PR-7763","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 5.3 - Crypto Release Notes","ref":"notes.html#crypto-5-3"},{"type":"extras","doc":"- Fix VM crash caused by `crypto being` purged and reloaded (by init:restart for\n example) on OS with musl libc (such as Alpine linux).\n\n Own Id: OTP-18670 Aux Id: GH-7436, PR-7450\n\n- Improved understanding of LibreSSL versions. Support chacha20 and\n chacha20_poly1305 for LibreSSL 3.7. Reflect removal of support for the DSS/DSA\n algorithm which was done in LibreSSL 2.6.1.\n\n Own Id: OTP-18758 Aux Id: PR-7209","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- FIPS supported by `crypto` for OpenSSL 3.0._ and 3.1._.\n\n Own Id: OTP-18666 Aux Id: PR-7392","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 5.2 - Crypto Release Notes","ref":"notes.html#crypto-5-2"},{"type":"extras","doc":"- Fix cmac_update aes_128_cbc for LibreSSL.\n\n Own Id: OTP-18571","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add support for SHAKE128 and SHAKE256.\n\n Own Id: OTP-18204 Aux Id: PR-6203\n\n- Make the `-DOPENSSL_API_COMPAT` flag work without warnings.\n\n Own Id: OTP-18206 Aux Id: PR-6167\n\n- Replace size/1 with either tuple_size/1 or byte_size/1\n\n The [`size/1`](`size/1`) BIF is not optimized by the JIT, and its use can\n result in worse types for Dialyzer.\n\n When one knows that the value being tested must be a tuple,\n [`tuple_size/1`](`tuple_size/1`) should always be preferred.\n\n When one knows that the value being tested must be a binary,\n [`byte_size/1`](`byte_size/1`) should be preferred. However,\n [`byte_size/1`](`byte_size/1`) also accepts a bitstring (rounding up size to a\n whole number of bytes), so one must make sure that the call to `byte_size/` is\n preceded by a call to [`is_binary/1`](`is_binary/1`) to ensure that bitstrings\n are rejected. Note that the compiler removes redundant calls to\n [`is_binary/1`](`is_binary/1`), so if one is not sure whether previous code\n had made sure that the argument is a binary, it does not harm to add an\n [`is_binary/1`](`is_binary/1`) test immediately before the call to\n [`byte_size/1`](`byte_size/1`).\n\n Own Id: OTP-18405 Aux Id:\n GH-6672,PR-6702,PR-6768,PR-6700,PR-6769,PR-6812,PR-6814\n\n- Handling of `on_load` modules during boot has been improved by adding an extra\n step in the boot order for embedded mode that runs all `on_load` handlers,\n instead of relying on explicit invocation of them, later, when the kernel\n supervision tree starts.\n\n This is mostly a code improvement and OTP internal simplification to avoid\n future bugs and to simplify code maintenance.\n\n Own Id: OTP-18447","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 5.1.4.3 - Crypto Release Notes","ref":"notes.html#crypto-5-1-4-3"},{"type":"extras","doc":"* Fix building with `--enable-fips` with OpenSSL 3 on MacOS.\n\n Own Id: OTP-19038 Aux Id: GH-8271, PR-8277","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 5.1.4.2 - Crypto Release Notes","ref":"notes.html#crypto-5-1-4-2"},{"type":"extras","doc":"* The function `crypto:pbkdf2_hmac` will no longer block the main schedulers. If the iteration count or block size parameters are such that the function is likely to take a long time to execute, the function will be scheduled to run on a dirty CPU scheduler.\n\n Own Id: OTP-18996 Aux Id: PR-8173, PR-8174","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 5.1.4.1 - Crypto Release Notes","ref":"notes.html#crypto-5-1-4-1"},{"type":"extras","doc":"- Fix VM crash caused by `crypto being` purged and reloaded (by init:restart for\n example) on OS with musl libc (such as Alpine linux).\n\n Own Id: OTP-18670 Aux Id: GH-7436, PR-7450","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 5.1.4 - Crypto Release Notes","ref":"notes.html#crypto-5-1-4"},{"type":"extras","doc":"- With this change, random errors are fixed for crypto:generate_key calls with\n OpenSSL 3.\n\n Own Id: OTP-18555","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 5.1.3 - Crypto Release Notes","ref":"notes.html#crypto-5-1-3"},{"type":"extras","doc":"- A user defined runtime library path configured using\n `--with-ssl-rpath= ` could fail to be enabled.\n\n Own Id: OTP-18384 Aux Id: PR-6596\n\n- Ensure that `configure` fails if a user defined runtime library path has been\n passed by the user, but cannot set.\n\n Own Id: OTP-18408","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 5.1.2 - Crypto Release Notes","ref":"notes.html#crypto-5-1-2"},{"type":"extras","doc":"- Fix configure with `--with-ssl` and `--disable-dynamic-ssl-lib` on Windows.\n\n Own Id: OTP-18147 Aux Id: GH-6024, PR-6056\n\n- Remove all references correctly in the garbage collection if an engine handle\n was not explicit unloaded.\n\n Own Id: OTP-18152\n\n- Changed the behaviour of the engine load/unload functions\n\n The engine load/unload functions have got changed semantics to get a more\n consistent behaviour and work correct when variables are garbage collected.\n\n The load functions now don't register the methods for the engine to replace.\n That will now be handled with the new functions\n engine_register/engine_unregister if needed.\n\n Some functions are removed from the documentation and therefor the API, but\n they are left in the code for compatibility.\n\n - engine_load/4: is now the same as engine_load/3\n - engine_unload/2: is now the same as engine_unload/1\n - ensure_engine_loaded/3: is now the same as ensure_engine_loaded/2\n - ensure_engine_unloaded/1, ensure_engine_unloaded/2: is now the same as\n engine_unload/1\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18172 Aux Id: ERIERL-826\n\n- Fixed a naming bug for AES-CFB and Blowfish-CFB/OFB when linked with OpenSSL\n 3.0 cryptolib.\n\n Own Id: OTP-18200\n\n- Sign/verify does now behave as in OTP-24 and earlier for eddsa.\n\n Own Id: OTP-18205 Aux Id: GH-6219","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Pass elliptic curve names from crypto.erl to crypto's nif.\n\n Own Id: OTP-18037\n\n- The configure option `--disable-deprecated-warnings` is removed. It was used\n for some releases when the support for OpenSSL 3.0 was not completed. It is\n not needed in OTP 25.\n\n Own Id: OTP-18133\n\n- Crypto is now considered to be usable with the OpenSSL 3.0 cryptolib for\n production code.\n\n ENGINE and FIPS are not yet fully functional.\n\n Own Id: OTP-18153\n\n- Do not exit if the legacy provider is missing in libcrypto 3.0.\n\n Own Id: OTP-18217","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 5.1.1 - Crypto Release Notes","ref":"notes.html#crypto-5-1-1"},{"type":"extras","doc":"- Note in the documentation that MODP (rfc3526) groups and OpenSSL 3.0 can give\n an error if a call to `crypto:generate_key/2` specifies a key length, and that\n length is to small.\n\n Own Id: OTP-18046","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The cmac now uses only the 3.0 API\n\n Own Id: OTP-18010\n\n- Documentation is now updated with which OpenSSL cryptolib versions that OTP\n currently is tested.\n\n Own Id: OTP-18132","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 5.1 - Crypto Release Notes","ref":"notes.html#crypto-5-1"},{"type":"extras","doc":"- Fix timing bug in ensure_engine_loaded\n\n When two ensure_engine_loaded() calls were done in parallel there was a\n possibility that a crypto lib function was called by both instead of just one\n of them which resulted in an error. This is solved by moving the\n implementation from erlang down into a NIF function that uses a mutex to\n protect the sensitive part.\n\n Own Id: OTP-17858 Aux Id: ERIERL-728\n\n- Remove faulty types `run_time_error()` and `descriptive_error()`.\n\n Own Id: OTP-17984","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Input for `configure` scripts adapted to `autoconf` 2\\.71.\n\n Own Id: OTP-17414 Aux Id: PR-4967\n\n- Add crypto:hash_equals/2\n\n Own Id: OTP-17471 Aux Id: PR-4750\n\n- Add /opt/homebrew/opt/openssl to standard locations to search for OpenSSL\n cryptolib.\n\n Own Id: OTP-17561\n\n- `crypto_dyn_iv_init/3` and `crypto_dyn_iv_update/3` are deprecated.\n\n Own Id: OTP-17870\n\n- The information in error messages are increased.\n\n Previously the error was signaled with en error class exception `badarg`,\n `notsup` or `error`, and also in some more ways like an other exception or a\n return value in a non-standardized format.\n\n Now it is an error-class exception\n `{notsup|badarg|error, InfoFromCfile, Description::string()}`.\n\n The `InfoFromCfile` is a term with name and line number of the C-file where\n the error was found. This is primarily intended for a crypto maintainer or an\n advanced user to find the cause of complicated errors - maybe in crypto\n itself. The contents of that term might be changed in the future.\n\n The `Description` is a clear text string that describes the error. In case of\n `badarg` and `notsup` the intention is that it should help the user to find\n the cause (\"Bad key size\" as an example). Specially for some `error` that are\n unlikely, the string may not be possible to understand without deep knowledge\n of the underlying cryptolib. Such messages are intended for a crypto\n maintainer.\n\n The first element on call stack (the `S` in\n `try ... catch error:E:S .... end`) gives more information like the actual\n argument list in the call of crypto and the argument number (if possible) in\n the call to the NIF inside crypto.\n\n The functions in crypto affected by this change are:\n\n sign/4, sign/5, verify/5, verify/6,\n\n generate_key/2, generate_key/3, compute_key/4,\n\n hash/2, hash/4, hash_init/1, hash_update/4, hash_final/1,\n\n mac/3,4, mac_init/3, mac_update/2, mac_final/2,\n\n pbkdf2_hmac/5,\n\n public_encrypt/4, private_decrypt/4, private_encrypt/4, public_decrypt/4\n\n This schema was introduced earlier in:\n\n crypto_init/3, crypto_init/4, crypto_update/2, crypto_final/1,\n crypto_get_data/1,\n\n crypto_one_time/4, crypto_one_time/5, crypto_one_time_aead/6,\n crypto_one_time_aead/7\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17965\n\n- Add Output Feedback mode (OFB) support for AES encryption / decryption for key\n sizes of 128, 192 and 256 bits.\n\n Own Id: OTP-18067 Aux Id: PR-5866\n\n- The cryptolib API deprecated in OpenSSL 3.0 is now no longer used with a few\n exceptions listed below.\n\n Although OpenSSL 3.0.x itself is stable, its usage in OTP/crypto should still\n not be considered suitable for production code.\n\n The use of ENGINEs is still disabled by default when using 3.0.\n\n Deprecated functions are still called in the otp_test_engine.c (only used in\n tests), in mac.c (EVP_PKEY_new_CMAC_key) and five function calls in ec.c\n (EVP_PKEY_assign, EC_KEY_get_conv_form, EVP_PKEY_get1_EC_KEY,\n EC_KEY_get0_group and EC_KEY_set_public_key).\n\n Own Id: OTP-18086 Aux Id: OTP-16282, OTP-16643, OTP-16644, OTP-17701,\n OTP-17702, OTP-17704","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 5.0.6.5 - Crypto Release Notes","ref":"notes.html#crypto-5-0-6-5"},{"type":"extras","doc":"* The function `crypto:pbkdf2_hmac` will no longer block the main schedulers. If the iteration count or block size parameters are such that the function is likely to take a long time to execute, the function will be scheduled to run on a dirty CPU scheduler.\n\n Own Id: OTP-18996 Aux Id: PR-8173, PR-8174","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 5.0.6.4 - Crypto Release Notes","ref":"notes.html#crypto-5-0-6-4"},{"type":"extras","doc":"- Fix VM crash caused by `crypto being` purged and reloaded (by init:restart for\n example) on OS with musl libc (such as Alpine linux).\n\n Own Id: OTP-18670 Aux Id: GH-7436, PR-7450","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 5.0.6.3 - Crypto Release Notes","ref":"notes.html#crypto-5-0-6-3"},{"type":"extras","doc":"- Changed the behaviour of the engine load/unload functions\n\n The engine load/unload functions have got changed semantics to get a more\n consistent behaviour and work correct when variables are garbage collected.\n\n The load functions now don't register the methods for the engine to replace.\n That will now be handled with the new functions\n engine_register/engine_unregister if needed.\n\n Some functions functions are removed from the documentation and therefor the\n API, but they are left in the code for compatibility.\n\n - engine_load/4: is now the same as engine_load/3\n - engine_unload/2: is now the same as engine_unload/1\n - ensure_engine_loaded/3: is now the same as ensure_engine_loaded/2\n - ensure_engine_unloaded/1, ensure_engine_unloaded/2: is now the same as\n engine_unload/1\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18172 Aux Id: ERIERL-826","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 5.0.6.2 - Crypto Release Notes","ref":"notes.html#crypto-5-0-6-2"},{"type":"extras","doc":"- Fix configure with `--with-ssl` and `--disable-dynamic-ssl-lib` on Windows.\n\n Own Id: OTP-18147 Aux Id: GH-6024, PR-6056","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 5.0.6.1 - Crypto Release Notes","ref":"notes.html#crypto-5-0-6-1"},{"type":"extras","doc":"- Fix timing bug in ensure_engine_loaded\n\n When two ensure_engine_loaded() calls were done in parallel there was a\n possibility that a crypto lib function was called by both instead of just one\n of them which resulted in an error. This is solved by moving the\n implementation from erlang down into a NIF function that uses a mutex to\n protect the sensitive part.\n\n Own Id: OTP-17858 Aux Id: ERIERL-728","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 5.0.6 - Crypto Release Notes","ref":"notes.html#crypto-5-0-6"},{"type":"extras","doc":"- The crypto app in OTP can since OTP-24.2 be compiled, linked and used with the\n new OpenSSL 3.0 cryptolib.\n\n The crypto app has 3.0 support has been improved, but is still \\*\\*not\n recommended\\*\\* for other usages than experiments and alpha testing. There are\n not yet any guaranties that it works, not even together with other OTP\n applications like for example SSL and SSH, although there are no known errors.\n\n Since the previous release, OTP-24.2, the following improvements have been\n done:\n\n \\- It has been tested during nearly every nightly test on the OTP lab\n\n \\- The hash algorithms `md4` and `ripemd160` have been enabled with OpenSSL\n 3.0.\n\n \\- The ciphers `blowfish_cbc`, `blowfish_ecb`, `des_cbc`, `des_cfb`,\n `des_ecb`, `rc2_cbc` and `rc4` have been enabled with OpenSSL 3.0.\n\n Disabled or unsupported with OpenSSL 3.0 are still:\n\n \\- ENGINE support\n\n \\- FIPS mode\n\n \\- Other providers than the built-in ones\n\n \\- Compiling and linking with OpenSSL 3.0 cryptolib in compatibility modes\n (for example to behave as 1.1.1)\n\n and, the ciphers `blowfish_cfb64` and `blowfish_ofb64` are not supported and\n will not be either.\n\n Deprecated functions in the OpenSSL 3.0 cryptolib must not be disabled as\n OTP/crypto still uses some of the deprecated API functions. The gcc flag\n `-Wno-deprecated-declarations` is set to prevent deprecation warnings to be\n printed when compiling.\n\n Own Id: OTP-17812 Aux Id: OTP-16646, OTP-16282\n\n- Crypto is adapted to LibreSSL 3.5.0 on OpenBSD.\n\n Own Id: OTP-17941 Aux Id: OTP-17942\n\n- New configure option ( `--disable-otp-test-engine`) to prohibit the build of\n the OTP test engine used in some test suites.\n\n The reason is that the test engine could be hard to compile on for instance\n LibreSSL 3.5.0. For that particular cryptolib version (or higher), this\n configure option is set automatically.\n\n Own Id: OTP-17942 Aux Id: OTP-17941","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 5.0.5 - Crypto Release Notes","ref":"notes.html#crypto-5-0-5"},{"type":"extras","doc":"- Fixed the C-warning \"implicit declaration of function 'OpenSSL_version_num'\"\n if compiling with an early LibreSSL version.\n\n Own Id: OTP-17637\n\n- FIPS availability was not checked correctly for AEAD ciphers.\n\n Own Id: OTP-17740\n\n- Fixed that cipher aliases (like aes_cbc etc) could be present even if the\n aliased cipher(s) (like aes_128_cbc, aes_256_cbc,... etc) was missing.\n\n Own Id: OTP-17741","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The crypto app in OTP can now be compiled, linked and used with the new\n OpenSSL 3.0 cryptolib.\n\n It has not yet been extensively tested and is in this release \\*\\*not\n recommended\\*\\* for other usages than experiments and alpha testing. There are\n not yet any guaranties that it works, not even together with other OTP\n applications like for example SSL and SSH, although there are no known errors.\n\n Compiling and linking with OpenSSL 3.0 cryptolib in compatibility modes (for\n example to behave as 1.1.1) are not tested. It is not tested with external\n providers.\n\n The support for FIPS mode does not yet work, and is disabled when compiled\n with OpenSSL 3.0.\n\n Deprecated functions in the OpenSSL 3.0 cryptolib must not be disabled as\n OTP/crypto still uses some of the deprecated API functions. The gcc flag\n `-Wno-deprecated-declarations` is set to prevent deprecation warnings to be\n printed when compiling.\n\n The hash algorithms `md4` and `ripemd160` are disabled temporarily when\n compiled with OpenSSL 3.0.\n\n The ciphers `blowfish_cbc`, `blowfish_cfb64`, `blowfish_ecb`,\n `blowfish_ofb64`, `des_cbc`, `des_cfb`, `des_ecb`, `rc2_cbc` and `rc4` are\n disabled temporarily when compiled with OpenSSL 3.0.\n\n Own Id: OTP-16646 Aux Id: OTP-16282\n\n- The error handling in crypto is partly refactored using the new error\n reporting support. Errors earlier propagated like exceptions are still so, but\n when the failing function is called from the terminal - for example during\n failure hunting - a more descriptive text is produced.\n\n Own Id: OTP-17241\n\n- A new function `crypto:info/0` which presents some data about the compilation\n and linkage of the crypto nif is added.\n\n Own Id: OTP-17603\n\n- Added the `pbkdf2_hmac/5` function to the crypto module.\n\n It calls the `PKCS5_PBKDF2_HMAC` function which implements PBKD2 with HMAC in\n an efficient way.\n\n Own Id: OTP-17808 Aux Id: PR-5421","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 5.0.4 - Crypto Release Notes","ref":"notes.html#crypto-5-0-4"},{"type":"extras","doc":"- Fixed minor memory leak at `crypto` module purge.\n\n Own Id: OTP-17668 Aux Id: PR-5245\n\n- Fix possible inconsistency in fips mode when linking with some cryptolibs.\n\n Own Id: OTP-17672","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 5.0.3 - Crypto Release Notes","ref":"notes.html#crypto-5-0-3"},{"type":"extras","doc":"- Fix bug in `crypto:ensure_engine_unloaded`. Also fixed minor memory leak\n related to engine unloading.\n\n Own Id: OTP-17593 Aux Id: ERIERL-679\n\n- Fixes that FIPS enable and disable (or vice versa) on Windows sometimes leads\n to core dump at the time of process exit.\n\n Own Id: OTP-17618 Aux Id: PR-5126, GH-4920","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Disable fips if cryptolib < 1.0.1 and OTP/crypto is configured with\n --enable-fips\n\n If not, there could be compiling or loading problems with antique OpenSSL\n versions.\n\n Own Id: OTP-17389","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 5.0.2 - Crypto Release Notes","ref":"notes.html#crypto-5-0-2"},{"type":"extras","doc":"- EC keys are now zero-padded to the expected length if needed.\n\n Own Id: OTP-17442 Aux Id: GH-4861","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 5.0.1 - Crypto Release Notes","ref":"notes.html#crypto-5-0-1"},{"type":"extras","doc":"- Removed a risk for coredump.\n\n Own Id: OTP-17391 Aux Id: GH-4810\n\n- Fixed and documented the `DED_LDFLAGS_CONFTEST` configuration variable in\n `$ERL_TOP/HOWTO/INSTALL.md`.\n\n Own Id: OTP-17419 Aux Id: GH-4821\n\n- Commit of generated `configure` script.\n\n Own Id: OTP-17420 Aux Id: OTP-17398, GH-4821","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 5.0 - Crypto Release Notes","ref":"notes.html#crypto-5-0"},{"type":"extras","doc":"- Add `/usr/local/opt/openssl` to the openssl configure search path. This path\n is where some tools on OS X place openssl.\n\n Own Id: OTP-16882\n\n- Fix compiler warnings produced by the clang compiler.\n\n Own Id: OTP-17105 Aux Id: PR-2872\n\n- The `configure` scripts in `crypto` and `erts` now fail if a requested feature\n cannot be enabled.\n\n Large parts of the `configure` script of `crypto` have been rewritten with\n various improvements and bug fixes. It is now better at finding usable OpenSSL\n libraries, but will in the following cases fail to detect OpenSSL libraries\n where it previously sometimes detected the libraries by chance:\n\n - OpenSSL installations with `include` directory and `lib` directory parts\n installed in different base directories. In order to detect such\n installations after this change, the user must explicitly specify the\n locations using the\n [`--with-ssl= `](`e:system:install.md#advanced-configuration-and-build-of-erlang-otp_configuring`)\n and the\n [`--with-ssl-incl= `](`e:system:install.md#advanced-configuration-and-build-of-erlang-otp_configuring`)\n `configure` command line arguments.\n - When building with old `gcc` compilers or other compilers on Debian\n derivatives with multiarch directories under the `lib` directory. In order\n to detect such installations after this change, the user must explicitly\n specify the multiarch directory name using the\n [`--with-ssl-lib-subdir=lib/ `](`e:system:install.md#advanced-configuration-and-build-of-erlang-otp_configuring`)\n `configure` command line argument.\n\n Own Id: OTP-17254 Aux Id: ERIERL-618, GH-4230\n\n- The value 'none' was missing in the specs of crypto:sign/4 and\n crypto:verify/6.\n\n Own Id: OTP-17312 Aux Id: PR-4723","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The functions and cipher names that were deprecated in OTP-23.0 are now\n removed.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-16656\n\n- Removed installed directory priv/obj/ containing superfluous object files.\n\n Own Id: OTP-17001 Aux Id: PR-2852\n\n- TLS connections now support EdDSA certificates.\n\n Own Id: OTP-17142 Aux Id: PR-4756, GH-4637, GH-4650\n\n- Add prop_aead attribute to map from crypto:cipher_info/1.\n\n Own Id: OTP-17313 Aux Id: PR-4686","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 4.9.0.4 - Crypto Release Notes","ref":"notes.html#crypto-4-9-0-4"},{"type":"extras","doc":"- Changed the behaviour of the engine load/unload functions\n\n The engine load/unload functions have got changed semantics to get a more\n consistent behaviour and work correct when variables are garbage collected.\n\n The load functions now don't register the methods for the engine to replace.\n That will now be handled with the new functions\n engine_register/engine_unregister if needed.\n\n Some functions functions are removed from the documentation and therefor the\n API, but they are left in the code for compatibility.\n\n - engine_load/4: is now the same as engine_load/3\n - engine_unload/2: is now the same as engine_unload/1\n - ensure_engine_loaded/3: is now the same as ensure_engine_loaded/2\n - ensure_engine_unloaded/1, ensure_engine_unloaded/2: is now the same as\n engine_unload/1\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18172 Aux Id: ERIERL-826","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 4.9.0.3 - Crypto Release Notes","ref":"notes.html#crypto-4-9-0-3"},{"type":"extras","doc":"- Fix timing bug in ensure_engine_loaded\n\n When two ensure_engine_loaded() calls were done in parallel there was a\n possibility that a crypto lib function was called by both instead of just one\n of them which resulted in an error. This is solved by moving the\n implementation from erlang down into a NIF function that uses a mutex to\n protect the sensitive part.\n\n Own Id: OTP-17858 Aux Id: ERIERL-728\n\n- Remove all references correctly in the garbage collection if an engine handle\n was not explicit unloaded.\n\n Own Id: OTP-18152","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 4.9.0.2 - Crypto Release Notes","ref":"notes.html#crypto-4-9-0-2"},{"type":"extras","doc":"- EC keys are now zero-padded to the expected length if needed.\n\n Own Id: OTP-17442 Aux Id: GH-4861","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 4.9.0.1 - Crypto Release Notes","ref":"notes.html#crypto-4-9-0-1"},{"type":"extras","doc":"- Removed a risk for coredump.\n\n Own Id: OTP-17391 Aux Id: GH-4810\n\n- Commit of generated `configure` script.\n\n Own Id: OTP-17420 Aux Id: OTP-17398, GH-4821","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 4.9 - Crypto Release Notes","ref":"notes.html#crypto-4-9"},{"type":"extras","doc":"- Fix minor memory leaks in crypto ENGINE and robustify the code.\n\n Own Id: OTP-17212\n\n- The otp_test_engine no longer fails if NO_EC\\* is set in the OpenSSL\n configuration.\n\n Own Id: OTP-17256 Aux Id: PR-4580, GH-4573","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Various address sanitizer support.\n\n Own Id: OTP-16959 Aux Id: PR-2965\n\n- EVP is now disabled for OpenSSL cryptolib versions up to and including 1.0.2\n\n Own Id: OTP-17116 Aux Id: PR-2972\n\n- Warning for unused C function removed\n\n Own Id: OTP-17145 Aux Id: OTP-17105, PR-2872","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 4.8.3 - Crypto Release Notes","ref":"notes.html#crypto-4-8-3"},{"type":"extras","doc":"- Adding missing flag in BN-calls in SRP.\n\n Own Id: OTP-17107","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 4.8.2 - Crypto Release Notes","ref":"notes.html#crypto-4-8-2"},{"type":"extras","doc":"- Fixed usage of `AC_CONFIG_AUX_DIRS()` macros in configure script sources.\n\n Own Id: OTP-17093 Aux Id: ERL-1447, PR-2948","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 4.8.1 - Crypto Release Notes","ref":"notes.html#crypto-4-8-1"},{"type":"extras","doc":"- Build the supported curves cache in the NIF when crypto is loaded, no matter\n how it is loaded.\n\n This prevents a possible problem with different processes starting the crypto\n application concurrently.\n\n Own Id: OTP-16819 Aux Id: PR-2720\n\n- It is now possible to build with crypto and openssl gprof-enabled and\n statically link them into the VM.\n\n Own Id: OTP-17029","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Fixed performance loss in HMAC when using older OpenSSL due to mutex issues.\n\n A workaround is implemented to allow fallback from using the EVP API for HMAC\n operations. On some architectures this may improve the performance, especially\n with old OpenSSL versions. This fallback to low-level functions is always\n enabled for openssl versions before 1.0.2.\n\n Own Id: OTP-17025 Aux Id: ERL-1400, PR-2877","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 4.8 - Crypto Release Notes","ref":"notes.html#crypto-4-8"},{"type":"extras","doc":"- Fix type spec bug in crypto for crypto_init and crypto:one_time\n\n Own Id: OTP-16658 Aux Id: OTP-15884, ERL-1257\n\n- The deprecation message for crypto:rand_uniform/2 indicated a non-existent\n function. The correct one (rand:uniform/1) is now suggested.\n\n Own Id: OTP-16846 Aux Id: PR-2741","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Implemented a workaround to allow fallback from using the EVP API for\n Diffie-Hellman key generation\n\n Own Id: OTP-16771 Aux Id: ERIERL-509\n\n- The internal Diffie-Hellman high level API for key generation was slow in old\n and by OpenSSL now unsupported cryptolib versions (1.0.1 and earlier).\n\n If such a cryptolib is used anyhow, the low-level API is used internally in\n the crypto application.\n\n Own Id: OTP-16774","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 4.7 - Crypto Release Notes","ref":"notes.html#crypto-4-7"},{"type":"extras","doc":"- Crypto reported unsupported elliptic curves as supported on e.g Fedora\n distros.\n\n Own Id: OTP-16579 Aux Id: ERL-825","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Support for ed25519 and ed448 added to `crypto:generate_key`.\n\n Own Id: OTP-15967 Aux Id: PR-2329\n\n- The [new crypto functions api](new_api.md#the-new-api) (crypto_init,\n crypto_update and crypto_one_time) has been updated.\n\n There is now a function [`crypto_final/1`](`crypto:crypto_final/1`) and a\n possibility to set options in [`crypto_init/3`](`crypto:crypto_init/3`) and\n [`crypto_init/4`](`crypto:crypto_init/4`). See the manual for details.\n\n Own Id: OTP-16160\n\n- As [announced](notes.md#crypto-4-5) in OTP 22.0, a New API was introduced in\n CRYPTO. See the [_New and Old API_](new_api.md) chapter in the CRYPTO User's\n Guide for more information and suggested replacement functions.\n\n [The Old API](new_api.md#the-old-api) is now deprecated in OTP-23.0 and will\n be removed in OTP-24.0.\n\n This deprecation includes cipher names. See the section\n [Retired cipher names](new_api.md#retired-cipher-names) in the crypto User's\n Guide, chapter [The Old API](new_api.md#the-old-api).\n\n Own Id: OTP-16232\n\n- Fix C-compilation without deprecated OpenSSL cryptolib APIs\n\n Own Id: OTP-16369 Aux Id: PR-2474\n\n- Refactored the internal handling of deprecated and removed functions.\n\n Own Id: OTP-16469\n\n- Added missing 'eddh' to [crypto:supports(public_keys)](`crypto:supports/1`).\n\n Own Id: OTP-16583","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 4.6.5.4 - Crypto Release Notes","ref":"notes.html#crypto-4-6-5-4"},{"type":"extras","doc":"- EC keys are now zero-padded to the expected length if needed.\n\n Own Id: OTP-17442 Aux Id: GH-4861","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 4.6.5.3 - Crypto Release Notes","ref":"notes.html#crypto-4-6-5-3"},{"type":"extras","doc":"- Removed a risk for coredump.\n\n Own Id: OTP-17391 Aux Id: GH-4810\n\n- Commit of generated `configure` script.\n\n Own Id: OTP-17420 Aux Id: OTP-17398, GH-4821","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 4.6.5.2 - Crypto Release Notes","ref":"notes.html#crypto-4-6-5-2"},{"type":"extras","doc":"- Adding missing flag in BN-calls in SRP.\n\n Own Id: OTP-17107","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 4.6.5.1 - Crypto Release Notes","ref":"notes.html#crypto-4-6-5-1"},{"type":"extras","doc":"- Implemented a workaround to allow fallback from using the EVP API for\n Diffie-Hellman key generation\n\n Own Id: OTP-16771 Aux Id: ERIERL-509","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 4.6.5 - Crypto Release Notes","ref":"notes.html#crypto-4-6-5"},{"type":"extras","doc":"- Fixed potential memory leaks involving calls to the crypto ng_api.\n\n Own Id: OTP-16428 Aux Id: PR-2511","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 4.6.4 - Crypto Release Notes","ref":"notes.html#crypto-4-6-4"},{"type":"extras","doc":"- Constant time comparisons added.\n\n Own Id: OTP-16376","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 4.6.3 - Crypto Release Notes","ref":"notes.html#crypto-4-6-3"},{"type":"extras","doc":"- The ciphers aes_cfb8 and aes_cfb128 are now using the EVP interface. The\n supported key lengths are 128, 192 and 256 bits.\n\n Own Id: OTP-16133 Aux Id: PR-2407\n\n- The ciphers aes_cfb8 and aes_cfb128 are now available in FIPS enabled mode.\n\n Own Id: OTP-16134 Aux Id: PR-2407","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 4.6.2 - Crypto Release Notes","ref":"notes.html#crypto-4-6-2"},{"type":"extras","doc":"- The AEAD tag was not previously checked on decrypt with chacha20_poly1305\n\n Own Id: OTP-16242 Aux Id: ERL-1078","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 4.6.1 - Crypto Release Notes","ref":"notes.html#crypto-4-6-1"},{"type":"extras","doc":"- FIxed a bug if the erlang emulator was linked with a very old cryptolib\n version (1.0.1 or earlier).\n\n The bug now fixed could have triggered a core dump if an unknown cipher name\n was used in crypto functions.\n\n Own Id: OTP-16202","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 4.6 - Crypto Release Notes","ref":"notes.html#crypto-4-6"},{"type":"extras","doc":"- The implementation of `crypto_one_time/4` is adjusted to match the type\n specification. The spec and the black-box behaviour of the function are\n unchanged.\n\n Some details: Both the spec and the implementation were correct seen\n separately. But with both of them combined simultaneously with\n `crypto_one_time/5` which was called by the implementation of\n `crypto_one_time/4`, an (obvious) error was detected by a Dialyzer with more\n thorough checking than usual.\n\n Own Id: OTP-15884 Aux Id: ERL-974\n\n- When using crypto with FIPS mode enabled, the digests were not correctly\n handled.\n\n Own Id: OTP-15911\n\n- A memory leak in error handling code in `ng_crypto_init_nif` is fixed.\n\n Own Id: OTP-15924\n\n- Fixed the broken static build of the crypto nifs\n\n Own Id: OTP-15928 Aux Id: PR-2296","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The Message Authentication Codes (MAC) CMAC, HMAC and Poly1305 are unified\n into common functions in the New Crypto API. See the manual for CRYPTO.\n\n Own Id: OTP-13872","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 4.5.1 - Crypto Release Notes","ref":"notes.html#crypto-4-5-1"},{"type":"extras","doc":"- The cipher aes-ctr was disabled by mistake in crypto:supports for cryptolibs\n before 1.0.1. It worked however in the encrypt and decrypt functions.\n\n Own Id: OTP-15829","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 4.5 - Crypto Release Notes","ref":"notes.html#crypto-4-5"},{"type":"extras","doc":"- Fixed a bug in error return for `crypto:poly1305/2`. It returned the atom\n `notsup` instead of the exception `notsup`.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15677\n\n- The cipher chacha20 was introduced in OpenSSL 1.1.0. However, it could in a\n very odd situation, fail for versions less than OpenSSL 1.1.0d. It is\n therefore disabled for those versions.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15678","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- A new `rand` module algorithm, `exro928ss` (Xoroshiro928\\*\\*), has been\n implemented. It has got a really long period and good statistical quality for\n all output bits, while still being only about 50% slower than the default\n algorithm.\n\n The same generator is also used as a long period counter in a new `crypto`\n plugin for the `rand` module, algorithm `crypto_aes`. This plugin uses AES-256\n to scramble the counter which buries any detectable statistical artifacts.\n Scrambling is done in chunks which are cached to get good amortized speed\n (about half of the default algorithm).\n\n Own Id: OTP-14461 Aux Id: PR-1857\n\n- Crypto's single C-file is split into multiple files. The different coding\n styles in the different parts are unified into a single style.\n\n Own Id: OTP-14732 Aux Id: PR-2068, PR-2095\n\n- Build configuration of the `crypto` application has been moved from the `erts`\n application into the `crypto` application.\n\n Own Id: OTP-15129\n\n- Adds two hash functions `blake2b` and `blake2s` (64 bit hash and 32 bit hash\n respectively). These are modern and standard hash functions used in\n blockchains and encrypted communication protocols. The hash functions are\n available in OpenSSL since version 1.1.1.\n\n Own Id: OTP-15564 Aux Id: PR-2129\n\n- A new API is implemented in crypto. See the CRYPTO user's guide, chapter _New\n and Old API_ for more information.\n\n The old api with the `crypto:block_*` and `crypto:stream_*` interfaces are\n kept for compatibility, but implemented with the new api. Please note that\n since the error checking is more thorough, there _might_ be arguments with for\n example faulty lengths that are no longer accepted.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15644 Aux Id: OTP-14732 , OTP-15451, PR-1857 , PR-2068, PR-2095\n\n- The new hash_info/1 and cipher_info/1 functions returns maps with information\n about the hash or cipher in the argument.\n\n Own Id: OTP-15655 Aux Id: PR-2173, ERL-864, PR-2186\n\n- Obey additional OpenSSL configure flags when compiling the C-part of the\n CRYPTO application: `no-bf`, `no-blake2`, `no-chacha`, `no-cmac`, `no-dh`,\n `no-dsa`, `no-md4`, `no-poly1305`, `no-rc2`, `no-rc4` and `no-rmd160`.\n\n Own Id: OTP-15683\n\n- A new function `crypto:supports/1` is introduced. The single argument takes an\n atom as argument: `hashes`, `public_keys`, `ciphers`, `macs`, `curves` or\n `rsa_opts`. The return value is a list of supported algorithms.\n\n The difference with the existing `crypto:supports/0` is, apart from the\n argument and the return value, that the old function reports what is supported\n by the old api, and the new function reports algorithms in the new api.\n\n Own Id: OTP-15771","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 4.4.2.3 - Crypto Release Notes","ref":"notes.html#crypto-4-4-2-3"},{"type":"extras","doc":"- Adding missing flag in BN-calls in SRP.\n\n Own Id: OTP-17107","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 4.4.2.2 - Crypto Release Notes","ref":"notes.html#crypto-4-4-2-2"},{"type":"extras","doc":"- Constant time comparisons added.\n\n Own Id: OTP-16376","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 4.4.2.1 - Crypto Release Notes","ref":"notes.html#crypto-4-4-2-1"},{"type":"extras","doc":"- The ciphers aes_cfb8 and aes_cfb128 are now using the EVP interface. The\n supported key lengths are 128, 192 and 256 bits.\n\n Own Id: OTP-16133 Aux Id: PR-2407\n\n- The ciphers aes_cfb8 and aes_cfb128 are now available in FIPS enabled mode.\n\n Own Id: OTP-16134 Aux Id: PR-2407","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 4.4.2 - Crypto Release Notes","ref":"notes.html#crypto-4-4-2"},{"type":"extras","doc":"- Fixed build link error on Windows. Unresolved symbol 'bcmp'.\n\n Own Id: OTP-15750 Aux Id: ERL-905","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 4.4.1 - Crypto Release Notes","ref":"notes.html#crypto-4-4-1"},{"type":"extras","doc":"- Fixes a bug that caused `crypto:sign` and `crypto:verify` to return the error\n message `badarg` instead of `notsup` in one case. That case was when signing\n or verifying with eddsa keys (that is, ed15519 or ed448), but only when FIPS\n was supported and enabled.\n\n Own Id: OTP-15634","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Added a crypto benchmark test suite.\n\n Own Id: OTP-15447","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 4.4 - Crypto Release Notes","ref":"notes.html#crypto-4-4"},{"type":"extras","doc":"- Updated the RSA options part in the crypto application's C-code, documentation\n and tests.\n\n Own Id: OTP-15302","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Added ed25519 and ed448 sign/verify.\n\n Requires OpenSSL 1.1.1 or higher as cryptolib under the OTP application\n `crypto`.\n\n Own Id: OTP-15419 Aux Id: OTP-15094\n\n- Fixed valgrind warnings.\n\n Own Id: OTP-15467","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 4.3.3 - Crypto Release Notes","ref":"notes.html#crypto-4-3-3"},{"type":"extras","doc":"- The RSA options `rsa_mgf1_md`, `rsa_oaep_md`, and `rsa_oaep_label` were always\n disabled. They will now be enabled when a suitable cryptolib is used.\n\n They are still experimental and may change without prior notice.\n\n Own Id: OTP-15212 Aux Id: ERL-675, PR1899, PR838\n\n- The ciphers `aes_ige256` and `blowfish_cbc` had naming issues in\n `crypto:next_iv/2`.\n\n Own Id: OTP-15283\n\n- the `RSA_SSLV23_PADDING` is disabled if LibreSSL is used as cryptlib. This is\n due to compilation problems.\n\n This will be investigated further in the future.\n\n Own Id: OTP-15303","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The supported named elliptic curves are now reported in `crypto:supports/0` in\n a new entry tagged by `'curves'`.\n\n The function `crypto:ec_curves/0` is kept for compatibility.\n\n Own Id: OTP-14717 Aux Id: OTP-15244\n\n- The typing in the CRYPTO and PUBLIC_KEY applications are reworked and a few\n mistakes are corrected.\n\n The documentation is now generated from the typing and some clarifications are\n made.\n\n A new chapter on Algorithm Details such as key sizes and availability is added\n to the CRYPTO User's Guide.\n\n Own Id: OTP-15134\n\n- Support for SHA3 both as a separate hash and in HMAC is now available if\n OpenSSL 1.1.1 or higher is used as cryptolib.\n\n Available lengths are reported in the `'hashs'` entry in `crypto:supports/0`\n as `sha3_*`.\n\n Own Id: OTP-15153\n\n- The mac algorithm `poly1305` and the cipher algorithm `chacha20` are now\n supported if OpenSSL 1.1.1 or higher is used as cryptolib.\n\n Own Id: OTP-15164 Aux Id: OTP-15209\n\n- The key exchange Edward curves `x25519` and `x448` are now supported if\n OpenSSL 1.1.1 or higher is used as cryptolib.\n\n Own Id: OTP-15240 Aux Id: OTP-15133\n\n- The supported RSA options for sign/verify and encrypt/decrypt are now reported\n in `crypto:supports/0` in a new entry tagged by '`rsa_opts`'.\n\n The exakt set is still experimental and may change without prior notice.\n\n Own Id: OTP-15260\n\n- The cipher `aes_ccm` is added.\n\n Own Id: OTP-15286","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 4.3.2 - Crypto Release Notes","ref":"notes.html#crypto-4-3-2"},{"type":"extras","doc":"- Update the crypto engine functions to handle multiple loads of an engine.\n\n `engine_load/3/4` is updated so it doesn't add the engine ID to OpenSSLs\n internal list of engines which makes it possible to run the engine_load more\n than once if it doesn't contain global data.\n\n Added `ensure_engine_loaded/2/3` which guarantees that the engine just is\n loaded once and the following calls just returns a reference to it. This is\n done by add the ID to the internal OpenSSL list and check if it is already\n registered when the function is called.\n\n Added `ensure_engine_unloaded/1/2` to unload engines loaded with\n ensure_engine_loaded.\n\n Then some more utility functions are added.\n\n `engine_add/1`, adds the engine to OpenSSL internal list\n\n `engine_remove/1`, remove the engine from OpenSSL internal list\n\n `engine_get_id/1`, fetch the engines id\n\n `engine_get_name/1`, fetch the engine name\n\n Own Id: OTP-15233","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 4.3.1 - Crypto Release Notes","ref":"notes.html#crypto-4-3-1"},{"type":"extras","doc":"- Fixed a node crash in `crypto:compute_key(ecdh, ...)` when passing a wrongly\n typed Others argument.\n\n Own Id: OTP-15194 Aux Id: ERL-673","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 4.3 - Crypto Release Notes","ref":"notes.html#crypto-4-3"},{"type":"extras","doc":"- Removed two undocumented and erroneous functions\n (`crypto:dh_generate_parameters/2` and `crypto:dh_check/1`).\n\n Own Id: OTP-14956 Aux Id: ERL-579\n\n- Fixed bug causing VM crash if doing runtime upgrade of a crypto module built\n against OpenSSL older than 0.9.8h. Bug exists since OTP-20.2.\n\n Own Id: OTP-15088","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- A new `rand` plugin algorithm has been implemented in `crypto`, that is:\n `crypto_cache`. It uses strong random bytes as randomness source and caches\n them to get good speed. See `crypto:rand_seed_alg/1`.\n\n Own Id: OTP-13370 Aux Id: PR-1573\n\n- Diffie-Hellman key functions are re-written with the EVP_PKEY api.\n\n Own Id: OTP-14864","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 4.2.2.4 - Crypto Release Notes","ref":"notes.html#crypto-4-2-2-4"},{"type":"extras","doc":"- Constant time comparisons added.\n\n Own Id: OTP-16376","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 4.2.2.3 - Crypto Release Notes","ref":"notes.html#crypto-4-2-2-3"},{"type":"extras","doc":"- The ciphers aes_cfb8 and aes_cfb128 are now using the EVP interface. The\n supported key lengths are 128, 192 and 256 bits.\n\n Own Id: OTP-16133 Aux Id: PR-2407","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 4.2.2.1 - Crypto Release Notes","ref":"notes.html#crypto-4-2-2-1"},{"type":"extras","doc":"- Fixed a node crash in `crypto:compute_key(ecdh, ...)` when passing a wrongly\n typed Others argument.\n\n Own Id: OTP-15194 Aux Id: ERL-673","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 4.2.2 - Crypto Release Notes","ref":"notes.html#crypto-4-2-2"},{"type":"extras","doc":"- If OPENSSL_NO_EC was set, the compilation of the crypto nifs failed.\n\n Own Id: OTP-15073\n\n- C-compile errors for LibreSSL 2.7.0 - 2.7.2 fixed\n\n Own Id: OTP-15074 Aux Id: ERL-618","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 4.2.1 - Crypto Release Notes","ref":"notes.html#crypto-4-2-1"},{"type":"extras","doc":"- Fix build error caused by removed RSA padding functions in LibreSSL >= 2.6.1\n\n Own Id: OTP-14873","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 4.2 - Crypto Release Notes","ref":"notes.html#crypto-4-2"},{"type":"extras","doc":"- The compatibility function `void HMAC_CTX_free` in `crypto.c` erroneously\n tried to return a value.\n\n Own Id: OTP-14720","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Rewrite public and private key encode/decode with EVP api. New RSA padding\n options added. This is a modified half of PR-838.\n\n Own Id: OTP-14446\n\n- The crypto API is extended to use private/public keys stored in an Engine for\n sign/verify or encrypt/decrypt operations.\n\n The ssl application provides an API to use this new engine concept in TLS.\n\n Own Id: OTP-14448\n\n- Add support to plug in alternative implementations for some or all of the\n cryptographic operations supported by the OpenSSL Engine API. When configured\n appropriately, OpenSSL calls the engine's implementation of these operations\n instead of its own.\n\n Own Id: OTP-14567\n\n- Replaced a call of the OpenSSL deprecated function `DH_generate_parameters` in\n `crypto.c`.\n\n Own Id: OTP-14639\n\n- Documentation added about how to use keys stored in an Engine.\n\n Own Id: OTP-14735 Aux Id: OTP-14448\n\n- Add engine\\_ ctrl_cmd_string/3,4 the OpenSSL Engine support in crypto.\n\n Own Id: OTP-14801","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 4.1 - Crypto Release Notes","ref":"notes.html#crypto-4-1"},{"type":"extras","doc":"- On macOS, `crypto` would crash if `observer` had been started before `crypto`.\n On the beta for macOS 10.13 (High Sierra), `crypto` would crash. Both of those\n bugs have been fixed.\n\n Own Id: OTP-14499 Aux Id: ERL-251 ERL-439","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Extend crypto:sign, crypto:verify, public_key:sign and public_key:verify with:\n\n \\* support for RSASSA-PS padding for signatures and for saltlength setting \n \\* X9.31 RSA padding. \n \\* sha, sha224, sha256, sha384, and sha512 for dss signatures as mentioned in\n NIST SP 800-57 Part 1. \n \\* ripemd160 to be used for rsa signatures.\n\n This is a manual merge of half of the pull request 838 by potatosalad from\n Sept 2015.\n\n Own Id: OTP-13704 Aux Id: PR838\n\n- A new tuple in `crypto:supports/0` reports supported MAC algorithms.\n\n Own Id: OTP-14504","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 4.0 - Crypto Release Notes","ref":"notes.html#crypto-4-0"},{"type":"extras","doc":"- LibreSSL can now be used by the modernized crypto app.\n\n Own Id: OTP-14247\n\n- Add compile option `-compile(no_native)` in modules with `on_load` directive\n which is not yet supported by HiPE.\n\n Own Id: OTP-14316 Aux Id: PR-1390\n\n- Fix a bug in aes cfb128 function introduced by the bug fix in GitHub pull\n request [\\#1393](https://github.com/erlang/otp/pull/1393).\n\n Own Id: OTP-14435 Aux Id: PR-1462, PR-1393, OTP-14313","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add basic support for CMAC\n\n Own Id: OTP-13779 Aux Id: ERL-82 PR-1138\n\n- Removed functions deprecated in crypto-3.0 first released in OTP-R16B01\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-13873\n\n- The `crypto` application now supports OpenSSL 1.1.\n\n Own Id: OTP-13900\n\n- Allow Erlang/OTP to use OpenSSL in FIPS-140 mode, in order to satisfy specific\n security requirements (mostly by different parts of the US federal\n government).\n\n See the new crypto users guide \"FIPS mode\" chapter about building and using\n the FIPS support which is disabled by default.\n\n (Thanks to dszoboszlay and legoscia)\n\n Own Id: OTP-13921 Aux Id: PR-1180\n\n- Crypto chacha20-poly1305 as in RFC 7539 enabled for OpenSSL >= 1.1.\n\n Thanks to mururu.\n\n Own Id: OTP-14092 Aux Id: PR-1291\n\n- RSA key generation added to `crypto:generate_key/2`. Thanks to wiml.\n\n An interface is also added to `public_key:generate_key/1`.\n\n Own Id: OTP-14140 Aux Id: ERL-165, PR-1299\n\n- Raised minimum requirement for OpenSSL version to OpenSSL-0.9.8.c although we\n recommend a much higher version, that is a version that is still maintained\n officially by the OpenSSL project. Note that using such an old version may\n restrict the crypto algorithms supported.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-14171\n\n- Deprecate crypto:rand_uniform/2 as it is not cryptographically strong\n\n Own Id: OTP-14274\n\n- The Crypto application now supports generation of cryptographically strong\n random numbers (floats < 1.0 and integer arbitrary ranges) as a plugin to the\n 'rand' module.\n\n Own Id: OTP-14317 Aux Id: PR-1372\n\n- This replaces the hard coded test values for AES, CMAC and GCM ciphers with\n the full validation set from NIST's CAVP program.\n\n Own Id: OTP-14436 Aux Id: PR-1396","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 3.7.4 - Crypto Release Notes","ref":"notes.html#crypto-3-7-4"},{"type":"extras","doc":"- Fix a bug with AES CFB 128 for 192 and 256 bit keys. Thanks to kellymclaughlin\n \\!\n\n Own Id: OTP-14313 Aux Id: PR-1393","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 3.7.3 - Crypto Release Notes","ref":"notes.html#crypto-3-7-3"},{"type":"extras","doc":"- The implementation of the key exchange algorithms\n diffie-hellman-group-exchange-sha\\* are optimized, up to a factor of 11 for\n the slowest ( = biggest and safest) group size.\n\n Own Id: OTP-14169 Aux Id: seq-13261","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 3.7.2 - Crypto Release Notes","ref":"notes.html#crypto-3-7-2"},{"type":"extras","doc":"- The crypto application has been fixed to not use RC2 against OpenSSL built\n with RC2 disabled.\n\n Own Id: OTP-13895 Aux Id: PR-1163\n\n- The crypto application has been fixed to not use RC4 against OpenSSL built\n with RC4 disabled.\n\n Own Id: OTP-13896 Aux Id: PR-1169","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- To ease troubleshooting, `erlang:load_nif/2` now includes the return value\n from a failed call to load/reload/upgrade in the text part of the error tuple.\n The `crypto` NIF makes use of this feature by returning the source line\n where/if the initialization fails.\n\n Own Id: OTP-13951","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 3.7.1 - Crypto Release Notes","ref":"notes.html#crypto-3-7-1"},{"type":"extras","doc":"- Crypto has been fixed to work against OpenSSL versions with disabled DES\n ciphers. Correct spelling of cipher algorithm 'des3_cfb' has been introduced;\n the previous misspeling still works.\n\n Own Id: OTP-13783 Aux Id: ERL-203\n\n- The size of an internal array in crypto has been fixed to not segfault when\n having all possible ciphers. Bug fix by Duncan Overbruck.\n\n Own Id: OTP-13789 Aux Id: PR-1140","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 3.7 - Crypto Release Notes","ref":"notes.html#crypto-3-7"},{"type":"extras","doc":"- Refactor `crypto` to use the EVP interface of OpenSSL, which is the\n recommended interface that also enables access to hardware acceleration for\n some operations.\n\n Own Id: OTP-12217\n\n- Add support for 192-bit keys for the `aes_cbc` cipher.\n\n Own Id: OTP-13206 Aux Id: pr 832\n\n- Add support for 192-bit keys for `aes_ecb`.\n\n Own Id: OTP-13207 Aux Id: pr829\n\n- Deprecate the function `crypto:rand_bytes` and make sure that\n `crypto:strong_rand_bytes` is used in all places that are cryptographically\n significant.\n\n Own Id: OTP-13214\n\n- Enable AES-GCM encryption/decryption to change the tag length between 1 to 16\n bytes.\n\n Own Id: OTP-13483 Aux Id: PR-998","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 3.6.3 - Crypto Release Notes","ref":"notes.html#crypto-3-6-3"},{"type":"extras","doc":"- Fix bug for `aes_ecb` block crypto when data is larger than 16 bytes.\n\n Own Id: OTP-13249\n\n- Improve portability of ECC tests in Crypto and SSL for \"exotic\" OpenSSL\n versions.\n\n Own Id: OTP-13311","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 3.6.2 - Crypto Release Notes","ref":"notes.html#crypto-3-6-2"},{"type":"extras","doc":"- Small documentation fixes\n\n Own Id: OTP-13017","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 3.6.1 - Crypto Release Notes","ref":"notes.html#crypto-3-6-1"},{"type":"extras","doc":"- Make `crypto:ec_curves/0` return empty list if elliptic curve is not supported\n at all.\n\n Own Id: OTP-12944","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 3.6 - Crypto Release Notes","ref":"notes.html#crypto-3-6"},{"type":"extras","doc":"- Enhance crypto:generate_key to calculate ECC public keys from private key.\n\n Own Id: OTP-12394\n\n- Fix bug in `crypto:generate_key` for `ecdh` that could cause VM crash for\n faulty input.\n\n Own Id: OTP-12733","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Use the EVP API for AES-CBC crypto to enables the use of hardware acceleration\n for AES-CBC crypto on newer Intel CPUs (AES-NI), among other platforms.\n\n Own Id: OTP-12380\n\n- Add AES ECB block encryption.\n\n Own Id: OTP-12403","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 3.5 - Crypto Release Notes","ref":"notes.html#crypto-3-5"},{"type":"extras","doc":"- Extend block_encrypt/decrypt for aes_cfb8 and aes_cfb128 to accept keys of\n length 128, 192 and 256 bits. Before only 128 bit keys were accepted.\n\n Own Id: OTP-12467","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 3.4.2 - Crypto Release Notes","ref":"notes.html#crypto-3-4-2"},{"type":"extras","doc":"- Add configure option --with-ssl-incl=PATH to support OpenSSL installations\n with headers and libraries at different places.\n\n Own Id: OTP-12215 Aux Id: seq12700\n\n- Add configure option --with-ssl-rpath to control which runtime library path to\n use for dynamic linkage toward OpenSSL.\n\n Own Id: OTP-12316 Aux Id: seq12753","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 3.4.1 - Crypto Release Notes","ref":"notes.html#crypto-3-4-1"},{"type":"extras","doc":"- Make `crypto` verify major version number of OpenSSL header files and runtime\n library. Loading of `crypto` will fail if there is a version mismatch.\n\n Own Id: OTP-12146 Aux Id: seq12700","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 3.4 - Crypto Release Notes","ref":"notes.html#crypto-3-4"},{"type":"extras","doc":"- Fix memory leak in `crypto:hmac_init/upgrade/final` functions for all data and\n in `crypto:hmac/3/4` for data larger than 20000 bytes. Bug exists since OTP\n 17.0.\n\n Own Id: OTP-11953\n\n- Fix memory leak in `crypto` for elliptic curve.\n\n Own Id: OTP-11999","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add `aes_cfb8` cypher to `crypto:block_encrypt` and `block_decrypt`.\n\n Own Id: OTP-11911","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 3.3 - Crypto Release Notes","ref":"notes.html#crypto-3-3"},{"type":"extras","doc":"- Fix memory leaks and invalid deallocations in `mod_pow`, `mod_exp` and\n `generate_key(srp,...)` when bad arguments are passed. (Thanks to Florian\n Zumbiehi)\n\n Own Id: OTP-11550\n\n- Correction of the word 'ChipherText' throughout the documentation (Thanks to\n Andrew Tunnell-Jones)\n\n Own Id: OTP-11609\n\n- Fix fatal bug when using a hmac context variable in more than one call to\n `hmac_update` or `hmac_final`. The reuse of hmac contexts has never worked as\n the underlying OpenSSL implementation does not support it. It is now\n documented as having undefined behaviour, but it does not crash or corrupt the\n VM anymore.\n\n Own Id: OTP-11724\n\n- Crypto handles out-of-memory with a controlled abort instead of\n crash/corruption. (Thanks to Florian Zumbiehi)\n\n Own Id: OTP-11725\n\n- Application upgrade (appup) files are corrected for the following\n applications:\n\n `asn1, common_test, compiler, crypto, debugger, dialyzer, edoc, eldap, erl_docgen, et, eunit, gs, hipe, inets, observer, odbc, os_mon, otp_mibs, parsetools, percept, public_key, reltool, runtime_tools, ssh, syntax_tools, test_server, tools, typer, webtool, wx, xmerl`\n\n A new test utility for testing appup files is added to test_server. This is\n now used by most applications in OTP.\n\n (Thanks to Tobias Schlager)\n\n Own Id: OTP-11744","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- By giving --enable-static-\\{nifs,drivers\\} to configure it is now possible to\n statically linking of nifs and drivers to the main Erlang VM binary. At the\n moment only the asn1 and crypto nifs of the Erlang/OTP nifs and drivers have\n been prepared to be statically linked. For more details see the Installation\n Guide in the System documentation.\n\n Own Id: OTP-11258\n\n- Add IGE mode for AES cipher in crypto (Thanks to Yura Beznos).\n\n Own Id: OTP-11522\n\n- Moved elliptic curve definition from the crypto NIF/OpenSSL into Erlang code,\n adds the RFC-5639 brainpool curves and makes TLS use them (RFC-7027).\n\n Thanks to Andreas Schultz\n\n Own Id: OTP-11578\n\n- Remove all obsolete application processes from crypto and make it into a pure\n library application.\n\n Own Id: OTP-11619","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 3.2 - Crypto Release Notes","ref":"notes.html#crypto-3-2"},{"type":"extras","doc":"- Fix uninitialized pointers in crypto (Thanks to Anthony Ramine)\n\n Own Id: OTP-11510","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 3.1 - Crypto Release Notes","ref":"notes.html#crypto-3-1"},{"type":"extras","doc":"- Refactor ecdsa cipher to simplify code and improve performance.\n\n Own Id: OTP-11320","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 3.0 - Crypto Release Notes","ref":"notes.html#crypto-3-0"},{"type":"extras","doc":"- Integrate elliptic curve contribution from Andreas Schultz\n\n In order to be able to support elliptic curve cipher suites in SSL/TLS,\n additions to handle elliptic curve infrastructure has been added to public_key\n and crypto.\n\n This also has resulted in a rewrite of the crypto API to gain consistency and\n remove unnecessary overhead. All OTP applications using crypto has been\n updated to use the new API.\n\n Impact: Elliptic curve cryptography (ECC) offers equivalent security with\n smaller key sizes than other public key algorithms. Smaller key sizes result\n in savings for power, memory, bandwidth, and computational cost that make ECC\n especially attractive for constrained environments.\n\n Own Id: OTP-11009\n\n- Fixed a spelling mistake in crypto docs. Thanks to Klaus Trainer\n\n Own Id: OTP-11058","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"- Make the crypto functions interruptible by chunking input when it is very\n large and bumping reductions in the nifs.\n\n Not yet implemented for block_encrypt|decrypt/4\n\n Impact: Individual calls to crypto functions may take longer time but over all\n system performance should improve as crypto calls will not become throughput\n bottlenecks.\n\n Own Id: OTP-11142","title":"Known Bugs and Problems - Crypto Release Notes","ref":"notes.html#known-bugs-and-problems"},{"type":"extras","doc":"","title":"Crypto 2.3 - Crypto Release Notes","ref":"notes.html#crypto-2-3"},{"type":"extras","doc":"- Enable runtime upgrade of crypto including the OpenSSL library used by crypto.\n\n Own Id: OTP-10596\n\n- Improve documentation and tests for hmac functions in crypto. Thanks to Daniel\n White\n\n Own Id: OTP-10640\n\n- Added ripemd160 support to crypto. Thanks to Michael Loftis\n\n Own Id: OTP-10667","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 2.2 - Crypto Release Notes","ref":"notes.html#crypto-2-2"},{"type":"extras","doc":"- Remove unnecessary dependency to libssl from crypto NIF library. This\n dependency was introduced by accident in R14B04.\n\n Own Id: OTP-10064","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add crypto and public_key support for the hash functions SHA224, SHA256,\n SHA384 and SHA512 and also hmac and rsa_sign/verify support using these hash\n functions. Thanks to Andreas Schultz for making a prototype.\n\n Own Id: OTP-9908\n\n- Optimize RSA private key handling in `crypto` and `public_key`.\n\n Own Id: OTP-10065\n\n- Make `crypto:aes_cfb_128_encrypt` and `crypto:aes_cfb_128_decrypt` handle data\n and cipher with arbitrary length. (Thanks to Stefan Zegenhagen)\n\n Own Id: OTP-10136","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 2.1 - Crypto Release Notes","ref":"notes.html#crypto-2-1"},{"type":"extras","doc":"- public_key, ssl and crypto now supports PKCS-8\n\n Own Id: OTP-9312\n\n- Erlang/OTP can now be built using parallel make if you limit the number of\n jobs, for instance using '`make -j6`' or '`make -j10`'. '`make -j`' does not\n work at the moment because of some missing dependencies.\n\n Own Id: OTP-9451\n\n- Add DES and Triple DES cipher feedback (CFB) mode functions to `crypto`.\n (Thanks to Paul Guyot)\n\n Own Id: OTP-9640\n\n- Add sha256, sha384 and sha512 support for `crypto:rsa_verify`.\n\n Own Id: OTP-9778","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 2.0.4 - Crypto Release Notes","ref":"notes.html#crypto-2-0-4"},{"type":"extras","doc":"- `crypto:rand_uniform` works correctly for negative integers. Fails with\n `badarg` exception for invalid ranges (when `Hi =< Lo`) instead of returning\n incorrect output.\n\n Own Id: OTP-9526\n\n- Fix win32 OpenSSL static linking (Thanks to Dave Cottlehuber)\n\n Own Id: OTP-9532","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 2.0.3 - Crypto Release Notes","ref":"notes.html#crypto-2-0-3"},{"type":"extras","doc":"- Various small documentation fixes (Thanks to Bernard Duggan)\n\n Own Id: OTP-9172","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- New `crypto` support for streaming of AES CTR and HMAC. (Thanks to Travis\n Jensen)\n\n Own Id: OTP-9275\n\n- Due to standard library DLL mismatches between versions of OpenSSL and\n Erlang/OTP, OpenSSL is now linked statically to the crypto driver on Windows.\n This fixes problems starting crypto when running Erlang as a service on all\n Windows versions.\n\n Own Id: OTP-9280","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 2.0.2.2 - Crypto Release Notes","ref":"notes.html#crypto-2-0-2-2"},{"type":"extras","doc":"- Strengthened random number generation. (Thanks to Geoff Cant)\n\n Own Id: OTP-9225","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 2.0.2.1 - Crypto Release Notes","ref":"notes.html#crypto-2-0-2-1"},{"type":"extras","doc":"- Misc. Updates.\n\n Own Id: OTP-9132","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 2.0.2 - Crypto Release Notes","ref":"notes.html#crypto-2-0-2"},{"type":"extras","doc":"- AES CTR encryption support in `crypto`.\n\n Own Id: OTP-8752 Aux Id: seq11642","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 2.0.1 - Crypto Release Notes","ref":"notes.html#crypto-2-0-1"},{"type":"extras","doc":"- Crypto dialyzer type error in md5_mac and sha_mac.\n\n Own Id: OTP-8718\n\n- RC4 stream cipher didn't work. This since the new NIF implementation of\n `crypto:rc4_encrypt_with_state/2` introduced in `crypto-2.0` didn't return an\n updated state. (Thanks to Paul Guyot)\n\n Own Id: OTP-8781\n\n- A number of memory leaks in the crypto NIF library have been fixed.\n\n Own Id: OTP-8810","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Added erlang:system_info(build_type) which makes it easier to chose drivers,\n NIF libraries, etc based on build type of the runtime system.\n\n The NIF library for crypto can now be built for valgrind and/or debug as\n separate NIF libraries that will be automatically loaded if the runtime system\n has been built with a matching build type.\n\n Own Id: OTP-8760","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 2.0 - Crypto Release Notes","ref":"notes.html#crypto-2-0"},{"type":"extras","doc":"- crypto application changed to use NIFs instead of driver.\n\n Own Id: OTP-8333\n\n- des_ecb_encrypt/2 and des_ecb_decrypt/2 has been added to the crypto module.\n The crypto:md4/1 function has been documented.\n\n Own Id: OTP-8551\n\n- The undocumented, unsupported, and deprecated function `lists:flat_length/1`\n has been removed.\n\n Own Id: OTP-8584\n\n- New variants of `crypto:dss_sign` and `crypto:dss_verify` with an extra\n argument to control how the digest is calculated.\n\n Own Id: OTP-8700","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 1.6.4 - Crypto Release Notes","ref":"notes.html#crypto-1-6-4"},{"type":"extras","doc":"- Cross compilation improvements and other build system improvements.\n\n Most notable:\n\n - Lots of cross compilation improvements. The old cross compilation support\n was more or less non-existing as well as broken. Please, note that the cross\n compilation support should still be considered as experimental. Also note\n that old cross compilation configurations cannot be used without\n modifications. For more information on cross compiling Erlang/OTP see the\n `$ERL_TOP/INSTALL-CROSS.md` file.\n - Support for staged install using\n [DESTDIR](http://www.gnu.org/prep/standards/html_node/DESTDIR.html). The old\n broken `INSTALL_PREFIX` has also been fixed. For more information see the\n `$ERL_TOP/INSTALL.md` file.\n - Documentation of the `release` target of the top `Makefile`. For more\n information see the `$ERL_TOP/INSTALL.md` file.\n - `make install` now by default creates relative symbolic links instead of\n absolute ones. For more information see the `$ERL_TOP/INSTALL.md` file.\n - `$ERL_TOP/configure --help=recursive` now works and prints help for all\n applications with `configure` scripts.\n - Doing `make install`, or `make release` directly after `make all` no longer\n triggers miscellaneous rebuilds.\n - Existing bootstrap system is now used when doing `make install`, or\n `make release` without a preceding `make all`.\n - The `crypto` and `ssl` applications use the same runtime library path when\n dynamically linking against `libssl.so` and `libcrypto.so`. The runtime\n library search path has also been extended.\n - The `configure` scripts of `erl_interface` and `odbc` now search for thread\n libraries and thread library quirks the same way as ERTS do.\n - The `configure` script of the `odbc` application now also looks for odbc\n libraries in `lib64` and `lib/64` directories when building on a 64-bit\n system.\n - The `config.h.in` file in the `erl_interface` application is now\n automatically generated in instead of statically updated which reduces the\n risk of `configure` tests without any effect.\n\n (Thanks to Henrik Riomar for suggestions and testing)\n\n (Thanks to Winston Smith for the AVR32-Linux cross configuration and testing)\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8323\n\n- The crypto module now supports Blowfish in ECB, CBC and OFB modes. (Thanks to\n Paul Oliver.)\n\n Own Id: OTP-8331\n\n- The documentation is now possible to build in an open source environment after\n a number of bugs are fixed and some features are added in the documentation\n build process.\n\n \\- The arity calculation is updated.\n\n \\- The module prefix used in the function names for bif's are removed in the\n generated links so the links will look like\n \"http://www.erlang.org/doc/man/erlang.html#append_element-2\" instead of\n \"http://www.erlang.org/doc/man/erlang.html#erlang:append_element-2\".\n\n \\- Enhanced the menu positioning in the html documentation when a new page is\n loaded.\n\n \\- A number of corrections in the generation of man pages (thanks to Sergei\n Golovan)\n\n \\- The legal notice is taken from the xml book file so OTP's build process can\n be used for non OTP applications.\n\n Own Id: OTP-8343","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 1.6.3 - Crypto Release Notes","ref":"notes.html#crypto-1-6-3"},{"type":"extras","doc":"- Suppressed false valgrind errors caused by libcrypto using uninitialized data\n as entropy.\n\n Own Id: OTP-8200","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The documentation is now built with open source tools (xsltproc and fop) that\n exists on most platforms. One visible change is that the frames are removed.\n\n Own Id: OTP-8201\n\n- When the crypto application failed to load the OpenSSL/LibEAY shared object,\n error indication was sparse. Now a more specific error message is sent to the\n error logger.\n\n Own Id: OTP-8281","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 1.6.2 - Crypto Release Notes","ref":"notes.html#crypto-1-6-2"},{"type":"extras","doc":"- Fixed emulator crash caused by crypto using an old openssl version that did\n not cope with large file descriptors.\n\n Own Id: OTP-8261 Aux Id: seq11434","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 1.6.1 - Crypto Release Notes","ref":"notes.html#crypto-1-6-1"},{"type":"extras","doc":"- `Makefile.in` has been updated to use the LDFLAGS environment variable (if\n set). (Thanks to Davide Pesavento.)\n\n Own Id: OTP-8157","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Support for Blowfish cfb64 added to `crypto`.\n\n Own Id: OTP-8096\n\n- New function `crypto:aes_cbc_ivec`\n\n Own Id: OTP-8141","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 1.6 - Crypto Release Notes","ref":"notes.html#crypto-1-6"},{"type":"extras","doc":"- The `dh_compute_key` sometimes returned a SharedSecret of incorrect size.\n\n Own Id: OTP-7674","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Optimization for drivers by creating small binaries direct on process heap.\n\n Own Id: OTP-7762","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 1.5.3 - Crypto Release Notes","ref":"notes.html#crypto-1-5-3"},{"type":"extras","doc":"- Added new functions: dss_verify/3, rsa_verify/3, rsa_verify/4, dss_sign/2,\n rsa_sign/2, rsa_sign/3, rsa_public_encrypt, rsa_private_decrypt/3,\n rsa_private_encrypt/3, rsa_public_decrypt/3, dh_generate_key/1,\n dh_generate_key/2, dh_compute_key/3.\n\n Own Id: OTP-7545","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 1.5.2.1 - Crypto Release Notes","ref":"notes.html#crypto-1-5-2-1"},{"type":"extras","doc":"- Minor performance optimization.\n\n Own Id: OTP-7521","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 1.5.2 - Crypto Release Notes","ref":"notes.html#crypto-1-5-2"},{"type":"extras","doc":"- ./configure has been improved to find 64-bit OpenSSL libraries.\n\n Own Id: OTP-7270","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- crypto and zlib drivers improved to allow concurrent smp access.\n\n Own Id: OTP-7262","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 1.5.1.1 - Crypto Release Notes","ref":"notes.html#crypto-1-5-1-1"},{"type":"extras","doc":"- The linked in driver for the crypto application is now linked statically\n against the OpenSSL libraries, to avoid installation and runtime problems in\n connection to the OpenSSL library locations.\n\n Own Id: OTP-6680\n\n- Minor Makefile changes.\n\n Own Id: OTP-6689","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 1.5 - Crypto Release Notes","ref":"notes.html#crypto-1-5"},{"type":"extras","doc":"- It is now explicitly checked at start-up that the crypto driver is properly\n loaded (Thanks to Claes Wikstrom).\n\n Own Id: OTP-6109","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 1.4 - Crypto Release Notes","ref":"notes.html#crypto-1-4"},{"type":"extras","doc":"- The previously undocumented and UNSUPPORTED `ssh` application has been updated\n and documented. This release of the `ssh` application is still considered to\n be a beta release and (if necessary) there could still be changes in its API\n before it reaches 1.0.\n\n Also, more cryptographic algorithms have been added to the `crypto`\n application.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-5631","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 1.3 - Crypto Release Notes","ref":"notes.html#crypto-1-3"},{"type":"extras","doc":"- Added support for RFC 3826 - The Advanced Encryption Standard (AES) Cipher\n Algorithm in the SNMP User-based Security Model. \n Martin Björklund","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 1.2.3 - Crypto Release Notes","ref":"notes.html#crypto-1-2-3"},{"type":"extras","doc":"- Linked in drivers in the crypto, and asn1 applications are now compiled with\n the -D_THREAD_SAFE and -D_REENTRANT switches on unix when the emulator has\n thread support enabled.\n\n Linked in drivers on MacOSX are not compiled with the undocumented -lbundle1.o\n switch anymore. Thanks to Sean Hinde who sent us a patch.\n\n Linked in driver in crypto, and port programs in ssl, now compiles on OSF1.\n\n Minor makefile improvements in runtime_tools.\n\n Own Id: OTP-5346","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 1.2.2 - Crypto Release Notes","ref":"notes.html#crypto-1-2-2"},{"type":"extras","doc":"- Corrected error handling. If the port to the driver that crypto uses is\n unexpectedly closed (which should not happen during normal operation of\n crypto), crypto will terminate immediately (rather than crashing the next time\n crypto is used). Also corrected build problems on Mac OS X.\n\n Own Id: OTP-5279","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 1.2.1 - Crypto Release Notes","ref":"notes.html#crypto-1-2-1"},{"type":"extras","doc":"- It was not possible in R9 to relink the crypto driver. The object file was\n missing as well as an example makefile. The crypto driver object file is now\n released with the application (installed in priv/obj). An example makefile has\n also been added to the priv/obj directory. The makefile serves as an example\n of how to relink the driver on Unix (crypto_drv.so) or Windows\n (crypto_drv.dll).\n\n Own Id: OTP-4828 Aux Id: seq8193","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 1.2 - Crypto Release Notes","ref":"notes.html#crypto-1-2"},{"type":"extras","doc":"- Previous versions of Crypto where delivered with statically linked binaries\n based on SSLeay. That is not longer the case. The current version of Crypto\n requires dynamically linked OpenSSL libraries that the user has to install.\n The library needed is `libcrypto.so` (Unix) or `libeay32.[lib|dll]` (Win32).\n For further details see the crypto(6) application manual page.\n- This version of Crypto uses the new DES interface of OpenSSL 0.9.7, which is\n not backward compatible with earlier versions of OpenSSL.\n- The functions `des_ede3_cbc_encrypt/5` and `des_ede3_cbc_decrypt/5` have been\n renamed to `des3_cbc_encrypt/5` and `des3_cbc_decrypt/5`, respectively. The\n old functions have been retained (they are deprecated and not listed in the\n crypto(3) manual page).","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"- The start of crypto failed on Windows, due to erroneous addition of a DES3\n algorithm.\n\n Own Id: OTP-4684 \n Aux Id: seq7864","title":"Reported Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#reported-fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 1.1.3 - Crypto Release Notes","ref":"notes.html#crypto-1-1-3"},{"type":"extras","doc":"- To obtain backward compatibility with the old SSLeay package, and with earlier\n versions of OpenSSL, the macro OPENSSL_DES_LIBDES_COMPATIBILITY has been added\n to `crypto_drv.c`. This is of importance only for the open source version of\n Crypto.","title":"Reported Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#reported-fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Crypto 1.1.2 - Crypto Release Notes","ref":"notes.html#crypto-1-1-2"},{"type":"extras","doc":"- In the manual page `m:crypto` the function names `md5_finish` and `sha_finish`\n have been changed to `md5_final` and `sha_final` to correctly document the\n implementation.\n\n Own Id: OTP-3409","title":"Reported Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#reported-fixed-bugs-and-malfunctions"},{"type":"extras","doc":"Code replacement in runtime is supported. Upgrade can be done from from version\n1.1 and downgrade to version 1.1.","title":"Crypto 1.1.1 - Crypto Release Notes","ref":"notes.html#crypto-1-1-1"},{"type":"extras","doc":"- The driver part of the Crypto application has been updated to use the\n erl_driver header file. Version 1.1.1 requires emulator version 4.9.1 or\n later.","title":"Improvements and New Features - Crypto Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Crypto 1.1 - Crypto Release Notes","ref":"notes.html#crypto-1-1"},{"type":"extras","doc":"- On Windows the crypto_drv was incorrectly linked to static run-time libraries\n instead of dynamic ones.\n\n Own Id: OTP-3240","title":"Reported Fixed Bugs and Malfunctions - Crypto Release Notes","ref":"notes.html#reported-fixed-bugs-and-malfunctions"},{"type":"extras","doc":"New application.","title":"Crypto 1.0 - Crypto Release Notes","ref":"notes.html#crypto-1-0"},{"type":"extras","doc":"\n# Licenses\n\n[](){: #licenses } This chapter contains in extenso versions of the OpenSSL and\nSSLeay licenses.","title":"Licenses","ref":"licenses.html"},{"type":"extras","doc":"```c\n/* ====================================================================\n * Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in\n * the documentation and/or other materials provided with the\n * distribution.\n *\n * 3. All advertising materials mentioning features or use of this\n * software must display the following acknowledgment:\n * \"This product includes software developed by the OpenSSL Project\n * for use in the OpenSSL Toolkit. (http://www.openssl.org/)\"\n *\n * 4. The names \"OpenSSL Toolkit\" and \"OpenSSL Project\" must not be used to\n * endorse or promote products derived from this software without\n * prior written permission. For written permission, please contact\n * openssl-core@openssl.org.\n *\n * 5. Products derived from this software may not be called \"OpenSSL\"\n * nor may \"OpenSSL\" appear in their names without prior written\n * permission of the OpenSSL Project.\n *\n * 6. Redistributions of any form whatsoever must retain the following\n * acknowledgment:\n * \"This product includes software developed by the OpenSSL Project\n * for use in the OpenSSL Toolkit (http://www.openssl.org/)\"\n *\n * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY\n * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR\n * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n * ====================================================================\n *\n * This product includes cryptographic software written by Eric Young\n * (eay@cryptsoft.com). This product includes software written by Tim\n * Hudson (tjh@cryptsoft.com).\n *\n */\n```","title":"OpenSSL License - Licenses","ref":"licenses.html#openssl-license"},{"type":"extras","doc":"```c\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are adhered to. The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code. The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n * notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n * must display the following acknowledgement:\n * \"This product includes cryptographic software written by\n * Eric Young (eay@cryptsoft.com)\"\n * The word 'cryptographic' can be left out if the routines from the library\n * being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n * the apps directory (application code) you must include an acknowledgement:\n * \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publicly available version or\n * derivative of this code cannot be changed. i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n```","title":"SSLeay License - Licenses","ref":"licenses.html#ssleay-license"},{"type":"extras","doc":"\n# FIPS mode\n\n[](){: #fips } This chapter describes FIPS mode support in the crypto\napplication.","title":"FIPS mode","ref":"fips.html"},{"type":"extras","doc":"OpenSSL can be built to provide FIPS 140-2 validated cryptographic services. It\nis not the OpenSSL application that is validated, but a special software\ncomponent called the OpenSSL FIPS Object Module. However applications do not use\nthis Object Module directly, but through the regular API of the OpenSSL library.\n\nThe crypto application supports using OpenSSL in FIPS mode. In this scenario\nonly the validated algorithms provided by the Object Module are accessible,\nother algorithms usually available in OpenSSL (like md5) or implemented in the\nErlang code (like SRP) are disabled.","title":"Background - FIPS mode","ref":"fips.html#background"},{"type":"extras","doc":"1. Build or install the FIPS Object Module and a FIPS enabled OpenSSL library.\n\nYou should read and precisely follow the instructions of the\n[Security Policy](http://csrc.nist.gov/groups/STM/cmvp/documents/140-1/140sp/140sp1747.pdf)\nand [User Guide](https://www.openssl.org/docs/fips/UserGuide-2.0.pdf).\n\n> #### Warning {: .warning }\n>\n> It is very easy to build a working OpenSSL FIPS Object Module and library from\n> the source. However it _does not_ qualify as FIPS 140-2 validated if the\n> numerous restrictions in the Security Policy are not properly followed.\n\n1. Configure and build Erlang/OTP with FIPS support:\n\n```text\n$ cd $ERL_TOP\n$ ./otp_build configure --enable-fips\n...\nchecking for FIPS_mode_set... yes\n...\n$ make\n```\n\nIf `FIPS_mode_set` returns `no` the OpenSSL library is not FIPS enabled and\ncrypto won't support FIPS mode either.\n\n1. Set the `fips_mode` configuration setting of the crypto application to `true`\n _before loading the crypto module_.\n\nThe best place is in the `sys.config` system configuration file of the release.\n\n1. Start and use the crypto application as usual. However take care to avoid the\n non-FIPS validated algorithms, they will all throw exception `not_supported`.\n\nEntering and leaving FIPS mode on a node already running crypto is not\nsupported. The reason is that OpenSSL is designed to prevent an application\nrequesting FIPS mode to end up accidentally running in non-FIPS mode. If\nentering FIPS mode fails (e.g. the Object Module is not found or is compromised)\nany subsequent use of the OpenSSL API would terminate the emulator.\n\nAn on-the-fly FIPS mode change would thus have to be performed in a critical\nsection protected from any concurrently running crypto operations. Furthermore\nin case of failure all crypto calls would have to be disabled from the Erlang or\nnif code. This would be too much effort put into this not too important feature.","title":"Enabling FIPS mode - FIPS mode","ref":"fips.html#enabling-fips-mode"},{"type":"extras","doc":"The Erlang API of the crypto application is identical regardless of building\nwith or without FIPS support. However the nif code internally uses a different\nOpenSSL API.\n\nThis means that the context (an opaque type) returned from streaming crypto\nfunctions (`hash_(init|update|final)`, `hmac_(init|update|final)` and\n`stream_(init|encrypt|decrypt)`) is different and incompatible with regular\nbuilds when compiling crypto with FIPS support.","title":"Incompatibilities with regular builds - FIPS mode","ref":"fips.html#incompatibilities-with-regular-builds"},{"type":"extras","doc":"In FIPS mode non-validated algorithms are disabled. This may cause some\nunexpected problems in application relying on crypto.\n\n> #### Warning {: .warning }\n>\n> Do not try to work around these problems by using alternative implementations\n> of the missing algorithms\\! An application can only claim to be using a FIPS\n> 140-2 validated cryptographic module if it uses it exclusively for every\n> cryptographic operation.","title":"Common caveats - FIPS mode","ref":"fips.html#common-caveats"},{"type":"extras","doc":"Although public key algorithms are supported in FIPS mode they can only be used\nwith secure key sizes. The Security Policy requires the following minimum\nvalues:\n\n- **RSA** - 1024 bit\n\n- **DSS** - 1024 bit\n\n- **EC algorithms** - 160 bit","title":"Restrictions on key sizes - FIPS mode","ref":"fips.html#restrictions-on-key-sizes"},{"type":"extras","doc":"The Erlang API allows using arbitrary curve parameters, but in FIPS mode only\nthose allowed by the Security Policy shall be used.","title":"Restrictions on elliptic curves - FIPS mode","ref":"fips.html#restrictions-on-elliptic-curves"},{"type":"extras","doc":"Md5 is a popular choice as a hash function, but it is not secure enough to be\nvalidated. Try to use sha instead wherever possible.\n\nFor exceptional, non-cryptographic use cases one may consider switching to\n`erlang:md5/1` as well.","title":"Avoid md5 for hashing - FIPS mode","ref":"fips.html#avoid-md5-for-hashing"},{"type":"extras","doc":"As md5 is not available in FIPS mode it is only possible to use certificates\nthat were signed using sha hashing. When validating an entire certificate chain\nall certificates (including the root CA's) must comply with this rule.\n\nFor similar dependency on the md5 and des algorithms most encrypted private keys\nin PEM format do not work either. However, the PBES2 encryption scheme allows\nthe use of stronger FIPS verified algorithms which is a viable alternative.","title":"Certificates and encrypted keys - FIPS mode","ref":"fips.html#certificates-and-encrypted-keys"},{"type":"extras","doc":"It is only possible to use `usmHMACSHAAuthProtocol` and `usmAesCfb128Protocol`\nfor authentication and privacy respectively in FIPS mode. The snmp application\nhowever won't restrict selecting disabled protocols in any way, and using them\nwould result in run time crashes.","title":"SNMP v3 limitations - FIPS mode","ref":"fips.html#snmp-v3-limitations"},{"type":"extras","doc":"All SSL and TLS versions prior to TLS 1.2 use a combination of md5 and sha1\nhashes in the handshake for various purposes:\n\n- Authenticating the integrity of the handshake messages.\n- In the exchange of DH parameters in cipher suites providing non-anonymous PFS\n (perfect forward secrecy).\n- In the PRF (pseud-random function) to generate keying materials in cipher\n suites not using PFS.\n\nOpenSSL handles these corner cases in FIPS mode, however the Erlang crypto and\nssl applications are not prepared for them and therefore you are limited to TLS\n1.2 in FIPS mode.\n\nOn the other hand it worth mentioning that at least all cipher suites that would\nrely on non-validated algorithms are automatically disabled in FIPS mode.\n\n> #### Note {: .info }\n>\n> Certificates using weak (md5) digests may also cause problems in TLS. Although\n> TLS 1.2 has an extension for specifying which type of signatures are accepted,\n> and in FIPS mode the ssl application will use it properly, most TLS\n> implementations ignore this extension and simply send whatever certificates\n> they were configured with.","title":"TLS 1.2 is required - FIPS mode","ref":"fips.html#tls-1-2-is-required"},{"type":"extras","doc":"\n# Engine Load\n\n[](){: #engine_load } This chapter describes the support for loading encryption\nengines in the crypto application.","title":"Engine Load","ref":"engine_load.html"},{"type":"extras","doc":"OpenSSL exposes an Engine API, which makes it possible to plug in alternative\nimplementations for some or all of the cryptographic operations implemented by\nOpenSSL. When configured appropriately, OpenSSL calls the engine's\nimplementation of these operations instead of its own.\n\nTypically, OpenSSL engines provide a hardware implementation of specific\ncryptographic operations. The hardware implementation usually offers improved\nperformance over its software-based counterpart, which is known as cryptographic\nacceleration.\n\n> #### Note {: .info }\n>\n> The file name requirement on the engine dynamic library can differ between SSL\n> versions.","title":"Background - Engine Load","ref":"engine_load.html#background"},{"type":"extras","doc":"","title":"Use Cases - Engine Load","ref":"engine_load.html#use-cases"},{"type":"extras","doc":"If the engine is located in the OpenSSL/LibreSSL installation `engines`\ndirectory.\n\n```erlang\n1> {ok, Engine} = crypto:engine_load(<<\"otp_test_engine\">>, [], []).\n {ok, #Ref}\n```","title":"Dynamically load an engine from default directory - Engine Load","ref":"engine_load.html#dynamically-load-an-engine-from-default-directory"},{"type":"extras","doc":"Load an engine with the help of the dynamic engine by giving the path to the\nlibrary.\n\n```erlang\n 2> {ok, Engine} = crypto:engine_load(<<\"dynamic\">>,\n [{<<\"SO_PATH\">>,\n <<\"/some/path/otp_test_engine.so\">>},\n {<<\"ID\">>, <<\"MD5\">>},\n <<\"LOAD\">>],\n []).\n {ok, #Ref}\n```","title":"Load an engine with the dynamic engine - Engine Load","ref":"engine_load.html#load-an-engine-with-the-dynamic-engine"},{"type":"extras","doc":"Load an engine with the help of the dynamic engine and just replace some engine\nmethods.\n\n```erlang\n 3> {ok, Engine} = crypto:engine_load(<<\"dynamic\">>,\n [{<<\"SO_PATH\">>,\n <<\"/some/path/otp_test_engine.so\">>},\n {<<\"ID\">>, <<\"MD5\">>},\n <<\"LOAD\">>],\n []).\n{ok, #Ref}\n4> ok = crypto:engine_register(Engine, [engine_method_digests]).\nok\n```","title":"Load an engine and replace some methods - Engine Load","ref":"engine_load.html#load-an-engine-and-replace-some-methods"},{"type":"extras","doc":"This function makes sure the engine is loaded just once and the ID is added to\nthe internal engine list of OpenSSL. The following calls to the function will\ncheck if the ID is loaded and then just get a new reference to the engine.\n\n```erlang\n 5> {ok, Engine} = crypto:ensure_engine_loaded(<<\"MD5\">>,\n <<\"/some/path/otp_test_engine.so\">>).\n {ok, #Ref}\n```\n\nTo remove the tag from the OpenSSL engine list use `crypto:engine_remove/1`.\n\n```erlang\n 6> crypto:engine_remove(Engine).\n ok\n```\n\nTo unload it use `crypto:engine_unload/1` which removes the references to the\nengine.\n\n```erlang\n 6> crypto:engine_unload(Engine).\n ok\n```","title":"Load with the ensure loaded function - Engine Load","ref":"engine_load.html#load-with-the-ensure-loaded-function"},{"type":"extras","doc":"```erlang\n 8> crypto:engine_list().\n[<<\"dynamic\">>, <<\"MD5\">>]\n```","title":"List all engines currently loaded - Engine Load","ref":"engine_load.html#list-all-engines-currently-loaded"},{"type":"extras","doc":"\n# Engine Stored Keys\n\n[](){: #engine_key } This chapter describes the support in the crypto\napplication for using public and private keys stored in encryption engines.","title":"Engine Stored Keys","ref":"engine_keys.html"},{"type":"extras","doc":"[OpenSSL](https://www.openssl.org/) exposes an Engine API, which makes it\npossible to plug in alternative implementations for some of the cryptographic\noperations implemented by OpenSSL. See the chapter\n[Engine Load](engine_load.md#engine_load) for details and how to load an Engine.\n\nAn engine could among other tasks provide a storage for private or public keys.\nSuch a storage could be made safer than the normal file system. Those techniques\nare not described in this User's Guide. Here we concentrate on how to use\nprivate or public keys stored in such an engine.\n\nThe storage engine must call `ENGINE_set_load_privkey_function` and\n`ENGINE_set_load_pubkey_function`. See the OpenSSL cryptolib's\n[manpages](https://www.openssl.org/docs/manpages.html).\n\nOTP/Crypto requires that the user provides two or three items of information\nabout the key. The application used by the user is usually on a higher level,\nfor example in [SSL](`t:ssl:key/0`). If using the crypto application directly,\nit is required that:\n\n- an Engine is loaded, see the chapter on\n [Engine Load](engine_load.md#engine_load) or the\n [Reference Manual](`crypto:engine_load/3`)\n- a reference to a key in the Engine is available. This should be an Erlang\n string or binary and depends on the Engine loaded\n- an Erlang map is constructed with the Engine reference, the key reference and\n possibly a key passphrase if needed by the Engine. See the\n [Reference Manual](`t:crypto:engine_key_ref/0`) for details of the map.","title":"Background - Engine Stored Keys","ref":"engine_keys.html#background"},{"type":"extras","doc":"","title":"Use Cases - Engine Stored Keys","ref":"engine_keys.html#use-cases"},{"type":"extras","doc":"This example shows how to construct a key reference that is used in a sign\noperation. The actual key is stored in the engine that is loaded at prompt 1.\n\n```erlang\n1> {ok, EngineRef} = crypto:engine_load(....).\n...\n{ok,#Ref<0.2399045421.3028942852.173962>}\n2> PrivKey = #{engine => EngineRef,\n key_id => \"id of the private key in Engine\"}.\n...\n3> Signature = crypto:sign(rsa, sha, <<\"The message\">>, PrivKey).\n<<65,6,125,254,54,233,84,77,83,63,168,28,169,214,121,76,\n 207,177,124,183,156,185,160,243,36,79,125,230,231,...>>\n```","title":"Sign with an engine stored private key - Engine Stored Keys","ref":"engine_keys.html#sign-with-an-engine-stored-private-key"},{"type":"extras","doc":"Here the signature and message in the last example is verifyed using the public\nkey. The public key is stored in an engine, only to exemplify that it is\npossible. The public key could of course be handled openly as usual.\n\n```erlang\n4> PublicKey = #{engine => EngineRef,\n key_id => \"id of the public key in Engine\"}.\n...\n5> crypto:verify(rsa, sha, <<\"The message\">>, Signature, PublicKey).\ntrue\n6>\n```","title":"Verify with an engine stored public key - Engine Stored Keys","ref":"engine_keys.html#verify-with-an-engine-stored-public-key"},{"type":"extras","doc":"The same example as the first sign example, except that a password protects the\nkey down in the Engine.\n\n```erlang\n6> PrivKeyPwd = #{engine => EngineRef,\n key_id => \"id of the pwd protected private key in Engine\",\n\t\t password => \"password\"}.\n...\n7> crypto:sign(rsa, sha, <<\"The message\">>, PrivKeyPwd).\n<<140,80,168,101,234,211,146,183,231,190,160,82,85,163,\n 175,106,77,241,141,120,72,149,181,181,194,154,175,76,\n 223,...>>\n8>\n```","title":"Using a password protected private key - Engine Stored Keys","ref":"engine_keys.html#using-a-password-protected-private-key"},{"type":"extras","doc":"\n# Algorithm Details\n\nThis chapter describes details of algorithms in the crypto application.\n\nThe tables only documents the supported cryptos and key lengths. The user should\nnot draw any conclusion on security from the supplied tables.","title":"Algorithm Details","ref":"algorithm_details.html"},{"type":"extras","doc":"A [cipher](`t:crypto:cipher/0`) in the [new api](new_api.md#the-new-api) is\ncategorized as either [cipher_no_iv()](`t:crypto:cipher_no_iv/0`),\n[cipher_iv()](`t:crypto:cipher_iv/0`) or\n[cipher_aead()](`t:crypto:cipher_aead/0`). The letters IV are short for\n_Initialization Vector_ and AEAD is an abbreviation of _Authenticated Encryption\nwith Associated Data_.\n\nDue to irregular naming conventions, some cipher names in the old api are\nsubstituted by new names in the new api. For a list of retired names, see\n[Retired cipher names](new_api.md#retired-cipher-names).\n\nTo dynamically check availability, check that the name in the _Cipher and Mode_\ncolumn is present in the list returned by\n[crypto:supports(ciphers)](`crypto:supports/1`).","title":"Ciphers - Algorithm Details","ref":"algorithm_details.html#ciphers"},{"type":"extras","doc":"To be used with:\n\n- [crypto_one_time/4](`crypto:crypto_one_time/4`)\n- [crypto_init/3](`crypto:crypto_init/3`)\n\nThe ciphers are:\n\n| **Cipher and Mode** | **Key length** **\\[bytes]** | **Block size** **\\[bytes]** |\n| ------------------- | --------------------------- | --------------------------- |\n| `aes_128_ecb` | 16 | 16 |\n| `aes_192_ecb` | 24 | 16 |\n| `aes_256_ecb` | 32 | 16 |\n| `blowfish_ecb` | 16 |  8 |\n| `des_ecb` |  8 |  8 |\n| `rc4` | 16 |  1 |\n| `sm4_ecb` | 16 | 16 |\n\n_Table: Ciphers without IV_","title":"Ciphers without an IV - cipher_no_iv() - Algorithm Details","ref":"algorithm_details.html#ciphers-without-an-iv-cipher_no_iv"},{"type":"extras","doc":"To be used with:\n\n- [crypto_one_time/5](`crypto:crypto_one_time/5`)\n- [crypto_init/4](`crypto:crypto_init/4`)\n\nThe ciphers are:\n\n| **Cipher and Mode** | **Key length** **\\[bytes]** | **IV length** **\\[bytes]** | **Block size** **\\[bytes]** | **Limited to** **OpenSSL versions** |\n| ------------------- | --------------------------- | -------------------------- | --------------------------- | ----------------------------------- |\n| `aes_128_cbc` | 16 | 16 | 16 | |\n| `aes_192_cbc` | 24 | 16 | 16 | |\n| `aes_256_cbc` | 32 | 16 | 16 | |\n| `aes_128_cfb8` | 16 | 16 |  1 | |\n| `aes_192_cfb8` | 24 | 16 |  1 | |\n| `aes_256_cfb8` | 32 | 16 |  1 | |\n| `aes_128_cfb128` | 16 | 16 |  1 | |\n| `aes_192_cfb128` | 24 | 16 |  1 | |\n| `aes_256_cfb128` | 32 | 16 |  1 | |\n| `aes_128_ctr` | 16 | 16 |  1 | |\n| `aes_192_ctr` | 24 | 16 |  1 | |\n| `aes_256_ctr` | 32 | 16 |  1 | |\n| `aes_128_ofb` | 16 | 16 |  1 | |\n| `aes_192_ofb` | 24 | 16 |  1 | |\n| `aes_256_ofb` | 32 | 16 |  1 | |\n| `blowfish_cbc` | 16 |  8 |  8 | |\n| `blowfish_cfb64` | 16 |  8 |  1 | |\n| `blowfish_ofb64` | 16 |  8 |  1 | |\n| `chacha20` | 32 | 16 |  1 | ≥1.1.0d |\n| `des_cbc` |  8 |  8 |  8 | |\n| `des_ede3_cbc` | 24 |  8 |  8 | |\n| `des_cfb` |  8 |  8 |  1 | |\n| `des_ede3_cfb` | 24 |  8 |  1 | |\n| `rc2_cbc` | 16 |  8 |  8 | |\n| `sm4_cbc` | 16 | 16 | 16 | ≥1.1.1 |\n| `sm4_cfb` | 16 | 16 | 16 | ≥1.1.1 |\n| `sm4_ofb` | 16 | 16 | 16 | ≥1.1.1 |\n| `sm4_ctr` | 16 | 16 | 16 | ≥1.1.1 |\n\n_Table: Ciphers with IV_","title":"Ciphers with an IV - cipher_iv() - Algorithm Details","ref":"algorithm_details.html#ciphers-with-an-iv-cipher_iv"},{"type":"extras","doc":"To be used with:\n\n- [crypto_one_time_aead/6](`crypto:crypto_one_time_aead/6`)\n- [crypto_one_time_aead/7](`crypto:crypto_one_time_aead/7`)\n\nThe ciphers are:\n\n| **Cipher and Mode** | **Key length** **\\[bytes]** | **IV length** **\\[bytes]** | **AAD length** **\\[bytes]** | **Tag length** **\\[bytes]** | **Block size** **\\[bytes]** | **Limited to** **OpenSSL versions** |\n| ------------------- | --------------------------- | -------------------------- | --------------------------- | --------------------------- | --------------------------- | ----------------------------------- |\n| `aes_128_ccm` | 16 | 7-13 | any | even 4-16 default: 12 | any | ≥1.0.1 |\n| `aes_192_ccm` | 24 | 7-13 | any | even 4-16 default: 12 | any | ≥1.0.1 |\n| `aes_256_ccm` | 32 | 7-13 | any | even 4-16 default: 12 | any | ≥1.0.1 |\n| `aes_128_gcm` | 16 | ≥1 | any | 1-16 default: 16 | any | ≥1.0.1 |\n| `aes_192_gcm` | 24 | ≥1 | any | 1-16 default: 16 | any | ≥1.0.1 |\n| `aes_256_gcm` | 32 | ≥1 | any | 1-16 default: 16 | any | ≥1.0.1 |\n| `chacha20_poly1305` | 32 | 1-16 | any | 16 | any | ≥1.1.0 |\n| `sm4_gcm` | 16 | 12 | any | 16 | any | ≥3.1.0 |\n| `sm4_ccm` | 16 | 12 | any | 16 | any | ≥3.1.0 |\n\n_Table: AEAD ciphers_","title":"Ciphers with AEAD - cipher_aead() - Algorithm Details","ref":"algorithm_details.html#ciphers-with-aead-cipher_aead"},{"type":"extras","doc":"To be used in [mac/4](`crypto:mac/4`) and\n[related functions](new_api.md#macs-message-authentication-codes).","title":"Message Authentication Codes (MACs) - Algorithm Details","ref":"algorithm_details.html#message-authentication-codes-macs"},{"type":"extras","doc":"CMAC with the following ciphers are available with OpenSSL 1.0.1 or later if not\ndisabled by configuration.\n\nTo dynamically check availability, check that the name `cmac` is present in the\nlist returned by [crypto:supports(macs)](`crypto:supports/1`). Also check that\nthe name in the _Cipher and Mode_ column is present in the list returned by\n[crypto:supports(ciphers)](`crypto:supports/1`).\n\n| **Cipher and Mode** | **Key length** **\\[bytes]** | **Max Mac Length** **(= default length)** **\\[bytes]** |\n| ------------------- | --------------------------- | ------------------------------------------------------ |\n| `aes_128_cbc` | 16 | 16 |\n| `aes_192_cbc` | 24 | 16 |\n| `aes_256_cbc` | 32 | 16 |\n| `aes_128_ecb` | 16 | 16 |\n| `aes_192_ecb` | 24 | 16 |\n| `aes_256_ecb` | 32 | 16 |\n| `blowfish_cbc` | 16 |  8 |\n| `blowfish_ecb` | 16 |  8 |\n| `des_cbc` |  8 |  8 |\n| `des_ecb` |  8 |  8 |\n| `des_ede3_cbc` | 24 |  8 |\n| `rc2_cbc` | 16 |  8 |\n\n_Table: CMAC cipher key lengths_","title":"CMAC - Algorithm Details","ref":"algorithm_details.html#cmac"},{"type":"extras","doc":"Available in all OpenSSL compatible with Erlang CRYPTO if not disabled by\nconfiguration.\n\nTo dynamically check availability, check that the name `hmac` is present in the\nlist returned by [crypto:supports(macs)](`crypto:supports/1`) and that the hash\nname is present in the list returned by\n[crypto:supports(hashs)](`crypto:supports/1`).\n\n| **Hash** | **Max Mac Length** **(= default length)** **\\[bytes]** |\n| ----------- | ------------------------------------------------------ |\n| `sha` | 20 |\n| `sha224` | 28 |\n| `sha256` | 32 |\n| `sha384` | 48 |\n| `sha512` | 64 |\n| `sha3_224` | 28 |\n| `sha3_256` | 32 |\n| `sha3_384` | 48 |\n| `sha3_512` | 64 |\n| `shake128` | 64 |\n| `shake256` | 64 |\n| `blake2b` | 64 |\n| `blake2s` | 32 |\n| `md4` | 16 |\n| `md5` | 16 |\n| `ripemd160` | 20 |\n\n_Table: HMAC output sizes_","title":"HMAC - Algorithm Details","ref":"algorithm_details.html#hmac"},{"type":"extras","doc":"POLY1305 is available with OpenSSL 1.1.1 or later if not disabled by\nconfiguration.\n\nTo dynamically check availability, check that the name `poly1305` is present in\nthe list returned by [crypto:supports(macs)](`crypto:supports/1`).\n\nThe poly1305 mac wants an 32 bytes key and produces a 16 byte MAC by default.","title":"POLY1305 - Algorithm Details","ref":"algorithm_details.html#poly1305"},{"type":"extras","doc":"To dynamically check availability, check that the wanted name in the _Names_\ncolumn is present in the list returned by\n[crypto:supports(hashs)](`crypto:supports/1`).\n\n| **Type** | **Names** | **Limited to** **OpenSSL versions** |\n| -------- | ---------------------------------------------------------- | ----------------------------------- |\n| SHA1 | sha | |\n| SHA2 | sha224, sha256, sha384, sha512 | |\n| SHA3 | sha3_224, sha3_256, sha3_384, sha3_512, shake128, shake256 | ≥1.1.1 |\n| SM3 | sm3 | ≥1.1.1 |\n| MD4 | md4 | |\n| MD5 | md5 | |\n| RIPEMD | ripemd160 | |","title":"Hash - Algorithm Details","ref":"algorithm_details.html#hash"},{"type":"extras","doc":"","title":"Public Key Cryptography - Algorithm Details","ref":"algorithm_details.html#public-key-cryptography"},{"type":"extras","doc":"RSA is available with all OpenSSL versions compatible with Erlang CRYPTO if not\ndisabled by configuration. To dynamically check availability, check that the\natom `rsa` is present in the list returned by\n[crypto:supports(public_keys)](`crypto:supports/1`).\n\n> #### Warning {: .warning }\n>\n> The RSA options are experimental.\n>\n> The exact set of options and there syntax _may_ be changed without prior\n> notice.\n\n| **Option** | **sign/verify** | **public encrypt** **private decrypt** | **private encrypt** **public decrypt** |\n| --------------------------------------------------------------------------------------------------------------------- | ----------------- | -------------------------------------- | -------------------------------------- |\n| \\{rsa_padding,rsa_x931_padding\\} | x | | x |\n| \\{rsa_padding,rsa_pkcs1_padding\\} | x | x | x |\n| \\{rsa_padding,rsa_pkcs1_pss_padding\\} \\{rsa_pss_saltlen, -2..\\} \\{rsa_mgf1_md, atom()\\} | x (2) x (2) x (2) | | |\n| \\{rsa_padding,rsa_pkcs1_oaep_padding\\} \\{rsa_mgf1_md, atom()\\} \\{rsa_oaep_label, binary()\\}\\} \\{rsa_oaep_md, atom()\\} | | x (2) x (2) x (3) x (3) | |\n| \\{rsa_padding,rsa_no_padding\\} | x (1) | | |\n\nNotes:\n\n1. (1) OpenSSL ≤ 1.0.0\n1. (2) OpenSSL ≥ 1.0.1\n1. (3) OpenSSL ≥ 1.1.0","title":"RSA - Algorithm Details","ref":"algorithm_details.html#rsa"},{"type":"extras","doc":"DSS is available with OpenSSL versions compatible with Erlang CRYPTO if not\ndisabled by configuration. To dynamically check availability, check that the\natom `dss` is present in the list returned by\n[crypto:supports(public_keys)](`crypto:supports/1`).","title":"DSS - Algorithm Details","ref":"algorithm_details.html#dss"},{"type":"extras","doc":"ECDSA is available with OpenSSL 0.9.8o or later if not disabled by\nconfiguration. To dynamically check availability, check that the atom `ecdsa` is\npresent in the list returned by\n[crypto:supports(public_keys)](`crypto:supports/1`). If the atom `ec_gf2m` also\nis present, the characteristic two field curves are available.\n\nThe actual supported named curves could be checked by examining the list\nreturned by [crypto:supports(curves)](`crypto:supports/1`).","title":"ECDSA - Algorithm Details","ref":"algorithm_details.html#ecdsa"},{"type":"extras","doc":"EdDSA is available with OpenSSL 1.1.1 or later if not disabled by configuration.\nTo dynamically check availability, check that the atom `eddsa` is present in the\nlist returned by [crypto:supports(public_keys)](`crypto:supports/1`).\n\nSupport for the curves ed25519 and ed448 is implemented. The actual supported\nnamed curves could be checked by examining the list with the list returned by\n[crypto:supports(curves)](`crypto:supports/1`).","title":"EdDSA - Algorithm Details","ref":"algorithm_details.html#eddsa"},{"type":"extras","doc":"Diffie-Hellman computations are available with OpenSSL versions compatible with\nErlang CRYPTO if not disabled by configuration. To dynamically check\navailability, check that the atom `dh` is present in the list returned by\n[crypto:supports(public_keys)](`crypto:supports/1`).","title":"Diffie-Hellman - Algorithm Details","ref":"algorithm_details.html#diffie-hellman"},{"type":"extras","doc":"Elliptic Curve Diffie-Hellman is available with OpenSSL 0.9.8o or later if not\ndisabled by configuration. To dynamically check availability, check that the\natom `ecdh` is present in the list returned by\n[crypto:supports(public_keys)](`crypto:supports/1`).\n\nThe Edward curves `x25519` and `x448` are supported with OpenSSL 1.1.1 or later\nif not disabled by configuration.\n\nThe actual supported named curves could be checked by examining the list\nreturned by [crypto:supports(curves)](`crypto:supports/1`).","title":"Elliptic Curve Diffie-Hellman - Algorithm Details","ref":"algorithm_details.html#elliptic-curve-diffie-hellman"},{"type":"extras","doc":"\n# New and Old API\n\nThis chapter describes the new api to encryption and decryption.","title":"New and Old API","ref":"new_api.html"},{"type":"extras","doc":"The CRYPTO app has evolved during its lifetime. Since also the OpenSSL cryptolib\nhas changed the API several times, there are parts of the CRYPTO app that uses a\nvery old one internally and other parts that uses the latest one. The internal\ndefinitions of e.g cipher names was a bit hard to maintain.\n\nIt turned out that using the old api in the new way (more about that later), and\nstill keep it backwards compatible, was not possible. Specially as more\nprecision in the error messages is desired it could not be combined with the old\nstandard.\n\nTherefore the old api (see next section) is kept for now but internally\nimplemented with new primitives.","title":"Background - New and Old API","ref":"new_api.html#background"},{"type":"extras","doc":"The old functions - deprecated from 23.0 and removed from OTP 24.0 - are for\nciphers:\n\n- `block_encrypt/3`\n- `block_encrypt/4`\n- `block_decrypt/3`\n- `block_decrypt/4`\n- `stream_init/2`\n- `stream_init/3`\n- `stream_encrypt/2`\n- `stream_decrypt/2`\n- `next_iv/2`\n- `next_iv/3`\n\nfor lists of supported algorithms:\n\n- `supports/0`\n\nand for MACs (Message Authentication Codes):\n\n- `cmac/3`\n- `cmac/4`\n- `hmac/3`\n- `hmac/4`\n- `hmac_init/2`\n- `hmac_update/2`\n- `hmac_final/1`\n- `hmac_final_n/2`\n- `poly1305/2`","title":"The old API - New and Old API","ref":"new_api.html#the-old-api"},{"type":"extras","doc":"","title":"The new API - New and Old API","ref":"new_api.html#the-new-api"},{"type":"extras","doc":"The new functions for encrypting or decrypting one single binary are:\n\n- [crypto_one_time/4](`crypto:crypto_one_time/4`)\n- [crypto_one_time/5](`crypto:crypto_one_time/5`)\n- [crypto_one_time_aead/6](`crypto:crypto_one_time_aead/6`)\n- [crypto_one_time_aead/7](`crypto:crypto_one_time_aead/7`)\n\nIn those functions the internal crypto state is first created and initialized\nwith the cipher type, the key and possibly other data. Then the single binary is\nencrypted or decrypted, the crypto state is de-allocated and the result of the\ncrypto operation is returned.\n\nThe `crypto_one_time_aead` functions are for the ciphers of mode `ccm` or `gcm`,\nand for the cipher `chacha20-poly1305`.\n\nFor repeated encryption or decryption of a text divided in parts, where the\ninternal crypto state is initialized once, and then many binaries are encrypted\nor decrypted with the same state, the functions are:\n\n- [crypto_init/4](`crypto:crypto_init/4`)\n- [crypto_init/3](`crypto:crypto_init/3`)\n- [crypto_update/2](`crypto:crypto_update/2`)\n- [crypto_final/1](`crypto:crypto_final/1`)\n\nThe `crypto_init` initialies an internal cipher state, and one or more calls of\n`crypto_update` does the actual encryption or decryption. Note that AEAD ciphers\ncan't be handled this way due to their nature.\n\nAn example of where those functions are needed, is when handling the TLS\nprotocol.\n\nIf padding was not enabled, the call to\n[crypto_final/1](`crypto:crypto_final/1`) may be excluded.\n\nFor information about available algorithms, use:\n\n- [supports/1](`crypto:supports/1`)\n- [hash_info/1](`crypto:hash_info/1`)\n- [cipher_info/1](`crypto:cipher_info/1`)\n\nThe `next_iv/2` and `next_iv/3` are not needed since the `crypto_init` and\n`crypto_update` includes this functionality.","title":"Encryption and decryption - New and Old API","ref":"new_api.html#encryption-and-decryption"},{"type":"extras","doc":"The new functions for calculating a MAC of a single piece of text are:\n\n- [mac/3](`crypto:mac/3`)\n- [mac/4](`crypto:mac/4`)\n- [macN/4](`crypto:macN/4`)\n- [macN/5](`crypto:macN/5`)\n\nFor calculating a MAC of a text divided in parts use:\n\n- [mac_init/2](`crypto:mac_init/2`)\n- [mac_init/3](`crypto:mac_init/3`)\n- [mac_update/2](`crypto:mac_update/2`)\n- [mac_final/1](`crypto:mac_final/1`)\n- [mac_finalN/2](`crypto:mac_finalN/2`)","title":"MACs (Message Authentication Codes) - New and Old API","ref":"new_api.html#macs-message-authentication-codes"},{"type":"extras","doc":"","title":"Examples of the new api - New and Old API","ref":"new_api.html#examples-of-the-new-api"},{"type":"extras","doc":"The functions [crypto_init/4](`crypto:crypto_init/4`) and\n[crypto_update/2](`crypto:crypto_update/2`) are intended to be used for\nencrypting or decrypting a sequence of blocks. First one call of `crypto_init/4`\ninitialises the crypto context. One or more calls `crypto_update/2` does the\nactual encryption or decryption for each block.\n\nThis example shows first the encryption of two blocks and then decryptions of\nthe cipher text, but divided into three blocks just to show that it is possible\nto divide the plain text and cipher text differently for some ciphers:\n\n```erlang\n\t1> application:start(crypto).\n\tok\n\t2> Key = <<1:128>>.\n\t<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>\n\t3> IV = <<0:128>>.\n\t<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>\n\t4> StateEnc = crypto:crypto_init(aes_128_ctr, Key, IV, true). % encrypt -> true\n\t#Ref<0.3768901617.1128660993.124047>\n\t5> crypto:crypto_update(StateEnc, <<\"First bytes\">>).\n\t<<67,44,216,166,25,130,203,5,66,6,162>>\n\t6> crypto:crypto_update(StateEnc, <<\"Second bytes\">>).\n\t<<16,79,94,115,234,197,94,253,16,144,151,41>>\n\t7>\n\t7> StateDec = crypto:crypto_init(aes_128_ctr, Key, IV, false). % decrypt -> false\n\t#Ref<0.3768901617.1128660994.124255>\n\t8> crypto:crypto_update(StateDec, <<67,44,216,166,25,130,203>>).\n\t<<\"First b\">>\n\t9> crypto:crypto_update(StateDec, <<5,66,6,162,16,79,94,115,234,197,\n 94,253,16,144,151>>).\n\t<<\"ytesSecond byte\">>\n\t10> crypto:crypto_update(StateDec, <<41>>).\n\t<<\"s\">>\n\t11>\n```\n\nNote that the internal data that the `StateEnc` and `StateDec` references are\ndestructivly updated by the calls to\n[crypto_update/2](`crypto:crypto_update/2`). This is to gain time in the calls\nof the nifs interfacing the cryptolib. In a loop where the state is saved in the\nloop's state, it also saves one update of the loop state per crypto operation.\n\nFor example, a simple server receiving text parts to encrypt and send the result\nback to the one who sent them (the `Requester`):\n\n```erlang\n\tencode(Crypto, Key, IV) ->\n\tcrypto_loop(crypto:crypto_init(Crypto, Key, IV, true)).\n\n\tcrypto_loop(State) ->\n\treceive\n {Text, Requester} ->\n Requester ! crypto:crypto_update(State, Text),\n\tloop(State)\n\tend.\n```","title":"Examples of crypto_init/4 and crypto_update/2 - New and Old API","ref":"new_api.html#examples-of-crypto_init-4-and-crypto_update-2"},{"type":"extras","doc":"The same example as in the\n[previous section](new_api.md#examples-of-crypto_init-4-and-crypto_update-2),\nbut now with one call to [crypto_one_time/5](`crypto:crypto_one_time/5`):\n\n```erlang\n\t1> Key = <<1:128>>.\n\t<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>\n\t2> IV = <<0:128>>.\n\t<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>\n\t3> Txt = [<<\"First bytes\">>,<<\"Second bytes\">>].\n\t[<<\"First bytes\">>,<<\"Second bytes\">>]\n\t4> crypto:crypto_one_time(aes_128_ctr, Key, IV, Txt, true).\n\t<<67,44,216,166,25,130,203,5,66,6,162,16,79,94,115,234,\n\t197,94,253,16,144,151,41>>\n\t5>\n```\n\nThe `[<<\"First bytes\">>,<<\"Second bytes\">>]` could of course have been one\nsingle binary: `<<\"First bytesSecond bytes\">>`.","title":"Example of crypto_one_time/5 - New and Old API","ref":"new_api.html#example-of-crypto_one_time-5"},{"type":"extras","doc":"The same example as in the\n[previous section](new_api.md#example-of-crypto_one_time-5), but now with one\ncall to [crypto_one_time_aead/6](`crypto:crypto_one_time_aead/6`):\n\n```erlang\n\t1> Key = <<1:128>>.\n\t<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>\n\t2> IV = <<0:128>>.\n\t<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>\n\t3> Txt = [<<\"First bytes\">>,<<\"Second bytes\">>].\n\t[<<\"First bytes\">>,<<\"Second bytes\">>]\n\t4> AAD = <<\"Some additional auth data\">>.\n\t<<\"Some additional auth data\">>\n\t5> crypto:crypto_one_time_aead(aes_128_gcm, Key, IV, Txt, AAD, true).\n\t{<<240,130,38,96,130,241,189,52,3,190,179,213,132,1,72,\n\t192,103,176,90,104,15,71,158>>,\n\t<<131,47,45,91,142,85,9,244,21,141,214,71,31,135,2,155>>}\n\t6>\n```\n\nThe `[<<\"First bytes\">>,<<\"Second bytes\">>]` could of course have been one\nsingle binary: `<<\"First bytesSecond bytes\">>`.","title":"Example of crypto_one_time_aead/6 - New and Old API","ref":"new_api.html#example-of-crypto_one_time_aead-6"},{"type":"extras","doc":"```erlang\n\t1> Key = <<1:128>>.\n\t<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>\n\t2> StateMac = crypto:mac_init(cmac, aes_128_cbc, Key).\n\t#Ref<0.2424664121.2781478916.232610>\n\t3> crypto:mac_update(StateMac, <<\"First bytes\">>).\n\t#Ref<0.2424664121.2781478916.232610>\n\t4> crypto:mac_update(StateMac, \" \").\n\t#Ref<0.2424664121.2781478916.232610>\n\t5> crypto:mac_update(StateMac, <<\"last bytes\">>).\n\t#Ref<0.2424664121.2781478916.232610>\n\t6> crypto:mac_final(StateMac).\n\t<<68,191,219,128,84,77,11,193,197,238,107,6,214,141,160,\n\t249>>\n\t7>\n```\n\nand compare the result with a single calculation just for this example:\n\n```erlang\n\t7> crypto:mac(cmac, aes_128_cbc, Key, \"First bytes last bytes\").\n\t<<68,191,219,128,84,77,11,193,197,238,107,6,214,141,160,\n\t249>>\n\t8> v(7) == v(6).\n\ttrue\n\t9>\n```","title":"Example of mac_init mac_update and mac_final - New and Old API","ref":"new_api.html#example-of-mac_init-mac_update-and-mac_final"},{"type":"extras","doc":"This table lists the retired cipher names in the first column and suggests names\nto replace them with in the second column.\n\nThe new names follows the OpenSSL libcrypto names. The format is\nALGORITM_KEYSIZE_MODE.\n\nExamples of algorithms are aes, chacha20 and des. The keysize is the number of\nbits and examples of the mode are cbc, ctr and gcm. The mode may be followed by\na number depending on the mode. An example is the ccm mode which has a variant\ncalled ccm8 where the so called tag has a length of eight bits.\n\nThe old names had by time lost any common naming convention which the new names\nnow introduces. The new names include the key length which improves the error\nchecking in the lower levels of the crypto application.\n\n| **Instead of:** | **Use:** |\n| --------------- | ------------------------------------------------ |\n| `aes_cbc128` | `aes_128_cbc` |\n| `aes_cbc256` | `aes_256_cbc` |\n| `aes_cbc` | `aes_128_cbc, aes_192_cbc, aes_256_cbc` |\n| `aes_ccm` | `aes_128_ccm, aes_192_ccm, aes_256_ccm` |\n| `aes_cfb128` | `aes_128_cfb128, aes_192_cfb128, aes_256_cfb128` |\n| `aes_cfb8` | `aes_128_cfb8, aes_192_cfb8, aes_256_cfb8` |\n| `aes_ctr` | `aes_128_ctr, aes_192_ctr, aes_256_ctr` |\n| `aes_gcm` | `aes_128_gcm, aes_192_gcm, aes_256_gcm` |\n| `des3_cbc` | `des_ede3_cbc` |\n| `des3_cbf` | `des_ede3_cfb` |\n| `des3_cfb` | `des_ede3_cfb` |\n| `des_ede3` | `des_ede3_cbc` |\n| `des_ede3_cbf` | `des_ede3_cfb` |","title":"Retired cipher names - New and Old API","ref":"new_api.html#retired-cipher-names"}],"content_type":"text/plain","producer":{"name":"ex_doc","version":[48,46,51,52,46,49]}} \ No newline at end of file diff --git a/prs/9045/lib/crypto-5.5.1/doc/html/dist/search_data-44534696.js b/prs/9045/lib/crypto-5.5.1/doc/html/dist/search_data-44534696.js deleted file mode 100644 index dc07b575d48b..000000000000 --- a/prs/9045/lib/crypto-5.5.1/doc/html/dist/search_data-44534696.js +++ /dev/null @@ -1 +0,0 @@ -searchData={"items":[{"type":"module","title":"crypto","doc":"Crypto Functions\n\nThis module provides a set of cryptographic functions.\n\n- **Hash functions** -\n\n - **SHA1, SHA2** - [Secure Hash Standard (FIPS PUB180-4)](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf)\n - **SHA3** - [SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions (FIPS PUB 202)](https://www.nist.gov/publications/sha-3-standard-permutation-based-hash-and-extendable-output-functions?pub_id=919061)\n\n - **BLAKE2** - [BLAKE2 — fast secure hashing](https://blake2.net/)\n\n - **SM3** - [The SM3 Hash Function (GM/T 0004-2012)](https://datatracker.ietf.org/doc/html/draft-sca-cfrg-sm3-02)\n\n - **MD5** - [The MD5 Message Digest Algorithm (RFC 1321)](http://www.ietf.org/rfc/rfc1321.txt)\n\n - **MD4** - [The MD4 Message Digest Algorithm (RFC 1320)](http://www.ietf.org/rfc/rfc1320.txt)\n\n- **MACs - Message Authentication Codes** -\n\n - **Hmac functions** - [Keyed-Hashing for Message Authentication (RFC 2104)](http://www.ietf.org/rfc/rfc2104.txt)\n\n - **Cmac functions** - [The AES-CMAC Algorithm (RFC 4493)](http://www.ietf.org/rfc/rfc4493.txt)\n\n - **POLY1305** - [ChaCha20 and Poly1305 for IETF Protocols (RFC 7539)](http://www.ietf.org/rfc/rfc7539.txt)\n\n- **Symmetric Ciphers** - \n\n - **DES, 3DES and AES** - [Block Cipher Techniques (NIST)](https://csrc.nist.gov/projects/block-cipher-techniques)\n\n - **Blowfish** -\n [Fast Software Encryption, Cambridge Security Workshop Proceedings (December 1993), Springer-Verlag, 1994, pp. 191-204.](https://www.schneier.com/academic/archives/1994/09/description_of_a_new.html)\n\n - **Chacha20** - [ChaCha20 and Poly1305 for IETF Protocols (RFC 7539)](http://www.ietf.org/rfc/rfc7539.txt)\n\n - **Chacha20_poly1305** - [ChaCha20 and Poly1305 for IETF Protocols (RFC 7539)](http://www.ietf.org/rfc/rfc7539.txt)\n\n - **SM4** - [The SM4 Block Cipher Algorithm](https://www.iso.org/standard/81564.html)\n\n- **Modes** -\n - **ECB, CBC, CFB, OFB and CTR** - [Recommendation for Block Cipher Modes of\n Operation: Methods and Techniques (NIST SP 800-38A)](https://csrc.nist.gov/publications/detail/sp/800-38a/final)\n\n - **GCM** - [Recommendation for Block Cipher Modes of Operation:\n Galois/Counter Mode (GCM) and GMAC (NIST SP 800-38D)](https://csrc.nist.gov/publications/detail/sp/800-38d/final)\n\n - **CCM** - [Recommendation for Block Cipher Modes of Operation: The CCM Mode\n for Authentication and Confidentiality (NIST SP 800-38C)](https://nvlpubs.nist.gov/nistpubs/legacy/sp/nistspecialpublication800-38c.pdf)\n\n- **Asymmetric Ciphers - Public Key Techniques** -\n\n - **RSA** - [PKCS #1: RSA Cryptography Specifications (RFC 3447)](http://www.ietf.org/rfc/rfc3447.txt)\n\n - **DSS** - [Digital Signature Standard (DSS) (FIPS 186-4)](https://csrc.nist.gov/publications/detail/fips/186/4/final)\n\n - **ECDSA** - [Elliptic Curve Digital Signature Algorithm (ECDSA)](http://csrc.nist.gov/groups/STM/cavp/documents/dss2/ecdsa2vs.pdf)\n\n - **SRP** - [The SRP Authentication and Key Exchange System (RFC 2945)](http://www.ietf.org/rfc/rfc2945.txt)\n\n> #### Note {: .info }\n>\n> The actual supported algorithms and features depends on their availability in\n> the actual libcrypto used. See the [crypto (App)](crypto_app.md) about\n> dependencies.\n>\n> Enabling FIPS mode will also disable algorithms and features.\n\nThe [CRYPTO User's Guide](index.html) has more information on FIPS, Engines and\nAlgorithm Details like key lengths.","ref":"crypto.html"},{"type":"module","title":"Exceptions - crypto","doc":"[](){: #error_old }","ref":"crypto.html#module-exceptions"},{"type":"module","title":"Atoms - the older style - crypto","doc":"The exception `error:badarg` signifies that one or more arguments are of wrong\ndata type, or are otherwise badly formed.\n\nThe exception `error:notsup` signifies that the algorithm is known but is not\nsupported by current underlying libcrypto or explicitly disabled when building\nthat.\n\nFor a list of supported algorithms, see [supports(ciphers)](`supports/1`).\n\n[](){: #error_3tup }","ref":"crypto.html#module-atoms-the-older-style"},{"type":"module","title":"3-tuples - the new style - crypto","doc":"The exception is:\n\n```text\nerror:{Tag, C_FileInfo, Description}\n\nTag = badarg | notsup | error\nC_FileInfo = term() % Usually only useful for the OTP maintainer\nDescription = string() % Clear text, sometimes only useful for the OTP maintainer\n```\n\nThe exception tags are:\n\n- **`badarg`** - Signifies that one or more arguments are of wrong data type or\n are otherwise badly formed.\n\n- **`notsup`** - Signifies that the algorithm is known but is not supported by\n current underlying libcrypto or explicitly disabled when building that one.\n\n- **`error`** - An error condition that should not occur, for example a memory\n allocation failed or the underlying cryptolib returned an error code, for\n example `\"Can't initialize context, step 1\"`. Those text usually needs\n searching the C-code to be understood.\n\nUsually there are more information in the call stack about which argument caused\nthe exception and what the values where.\n\nTo catch the exception, use for example:\n\n```text\ntry crypto:crypto_init(Ciph, Key, IV, true)\n catch\n error:{Tag, _C_FileInfo, Description} ->\n do_something(......)\n .....\nend\n```","ref":"crypto.html#module-3-tuples-the-new-style"},{"type":"function","title":"crypto.bytes_to_integer/1","doc":"Convert binary representation, of an integer, to an Erlang integer.","ref":"crypto.html#bytes_to_integer/1"},{"type":"function","title":"crypto.cipher_info/1","doc":"Get information about a cipher algorithm.\n\nReturns a map with information about block size, key length, IV length, aead\nsupport and possibly other properties of the cipher algorithm in question.\n\n> #### Note {: .info }\n>\n> The ciphers `aes_cbc`, `aes_cfb8`, `aes_cfb128`, `aes_ctr`, `aes_ecb`,\n> `aes_gcm` and `aes_ccm` has no keylength in the `Type` as opposed to for\n> example `aes_128_ctr`. They adapt to the length of the key provided in the\n> encrypt and decrypt function. Therefore it is impossible to return a valid\n> keylength in the map.\n>\n> Always use a `Type` with an explicit key length,\n\nFor a list of supported cipher algorithms, see\n[supports(ciphers)](`supports/1`).","ref":"crypto.html#cipher_info/1"},{"type":"function","title":"crypto.compute_key/4","doc":"Compute the shared secret from the private key and the other party's public\nkey.\n\nSee also `public_key:compute_key/2`.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","ref":"crypto.html#compute_key/4"},{"type":"function","title":"crypto.crypto_final/1","doc":"Finalize a streaming encryptions or decryptions operation and delivers the final\nbytes of the final block.\n\nThe data returned from this function may be empty if no padding was enabled in\n`crypto_init/3` or `crypto_init/4`.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","ref":"crypto.html#crypto_final/1"},{"type":"function","title":"crypto.crypto_get_data/1","doc":"Return information about a `t:crypto_state/0`.\n\nThe information returned is a map, which currently contains at least:\n\n- **`size`** - The number of bytes encrypted or decrypted so far.\n\n- **`padding_size`** - After a call to `crypto_final/1` it contains the number\n of bytes padded. Otherwise 0.\n\n- **`padding_type`** - The type of the padding as provided in the call to\n `crypto_init/3` or `crypto_init/4`.\n\n- **`encrypt`** - Is `true` if encryption is performed. It is `false` otherwise.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","ref":"crypto.html#crypto_get_data/1"},{"type":"function","title":"crypto.crypto_init/3","doc":"Initialize the state for a streaming encryption or decryption\noperation.\n\nEquivalent to the call\n[`crypto_init(Cipher, Key, <<>>, FlagOrOptions)`](`crypto_init/4`). It is\nintended for ciphers without an IV (nounce).\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","ref":"crypto.html#crypto_init/3"},{"type":"function","title":"crypto.crypto_init/4","doc":"Initialize the state for a streaming encryptions or decryptions operation.\n\nThe returned state should be used as argument to `crypto_update/2` and\n`crypto_final/1` to do the actual encryption or decryption.\n\nIf `IV = <<>>`, no IV is used. This is intended for ciphers without an IV\n(nounce). See `crypto_init/3`.\n\nFor encryption, set the `FlagOrOptions` to `true` or `[{encrypt,true}]`. For\ndecryption, set it to `false` or `[{encrypt,false}]`.\n\nPadding could be enabled with the option [\\{padding,Padding\\}](`t:padding/0`).\nThe [cryptolib_padding](`t:cryptolib_padding/0`) enables `pkcs_padding` or no\npadding (`none`). The paddings `zero` or `random` fills the last part of the\nlast block with zeroes or random bytes. If the last block is already full,\nnothing is added.\n\nIn decryption, the [cryptolib_padding](`t:cryptolib_padding/0`) removes such\npadding, if present. The [otp_padding](`t:otp_padding/0`) is not removed - it\nhas to be done elsewhere.\n\nIf padding is `{padding,none}` or not specified and the total data from all\nsubsequent [crypto_updates](`crypto_update/2`) does not fill the last block\nfully, that last data is lost. In case of `{padding,none}` there will be an\nerror in this case. If padding is not specified, the bytes of the unfilled block\nis silently discarded.\n\nThe actual padding is performed by `crypto_final/1`.\n\nFor blocksizes call `cipher_info/1`.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.\n\nSee\n[examples in the User's Guide.](new_api.md#examples-of-crypto_init-4-and-crypto_update-2)","ref":"crypto.html#crypto_init/4"},{"type":"function","title":"crypto.crypto_one_time/4","doc":"Do a complete encrypt or decrypt of the full text.\n\nAs `crypto_one_time/5` but for ciphers without IVs.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","ref":"crypto.html#crypto_one_time/4"},{"type":"function","title":"crypto.crypto_one_time/5","doc":"Do a complete encrypt or decrypt of the full text.\n\nArgument `Data` is the text to be encrypted or decrypted.\n\nFor encryption, set the `FlagOrOptions` to `true`. For decryption, set it to\n`false`. For setting other options, see `crypto_init/4`.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.\n\nSee [examples in the User's Guide.](new_api.md#example-of-crypto_one_time-5)","ref":"crypto.html#crypto_one_time/5"},{"type":"function","title":"crypto.crypto_one_time_aead/6","doc":"","ref":"crypto.html#crypto_one_time_aead/6"},{"type":"function","title":"crypto.crypto_one_time_aead/7","doc":"Do a complete encrypt or decrypt with an AEAD cipher of the full text.\n\nFor encryption, set the `EncryptFlag` to `true` and set the `TagOrTagLength` to\nthe wanted size (in bytes) of the tag, that is, the tag length. If the default\nlength is wanted, the `crypto_one_time_aead/6` form may be used.\n\nFor decryption, set the `EncryptFlag` to `false` and put the tag to be checked\nin the argument `TagOrTagLength`.\n\nAdditional Authentication Data (AAD) is plaintext data that will not be\nencrypted, but will be covered by authenticity protection. It should be provided\nthrough the `AAD` argument, but can be an empty binary as well (`<<>>`) if not\nneeded. In that case, a plain AE (Authenticated Encryption) is performed instead\nof AEAD (Authenticated Encryption with Associated Data). This function only\nsupports ciphers that can be used both with and without AAD.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.\n\nSee\n[examples in the User's Guide.](new_api.md#example-of-crypto_one_time_aead-6)","ref":"crypto.html#crypto_one_time_aead/7"},{"type":"function","title":"crypto.crypto_update/2","doc":"Add data to a streaming encryption or decryption operation.\n\nIf the part is less than a number of full blocks, only the full blocks (possibly\nnone) are encrypted or decrypted and the remaining bytes are saved to the next\n`crypto_update` operation. The `State` should be created with `crypto_init/3` or\n`crypto_init/4`.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.\n\nSee\n[examples in the User's Guide.](new_api.md#examples-of-crypto_init-4-and-crypto_update-2)","ref":"crypto.html#crypto_update/2"},{"type":"function","title":"crypto.ec_curve/1","doc":"Return the defining parameters of a elliptic curve.","ref":"crypto.html#ec_curve/1"},{"type":"function","title":"crypto.ec_curves/0","doc":"Return all supported named elliptic curves.","ref":"crypto.html#ec_curves/0"},{"type":"function","title":"crypto.enable_fips_mode/1","doc":"Enable or disable FIPs mode.\n\nArgument `Enable` should be `true` to enable and `false` to disable FIPS mode.\nReturns `true` if the operation was successful or `false` otherwise.\n\nNote that to enable FIPS mode successfully, OTP must be built with the configure\noption `--enable-fips`, and the underlying libcrypto must also support FIPS.\n\nSee also `info_fips/0`.","ref":"crypto.html#enable_fips_mode/1"},{"type":"function","title":"crypto.engine_add/1","doc":"Add the engine to OpenSSL's internal list.\n\nThe function raises a `error:badarg` if the parameters are in wrong format. It\nmay also raise the exception `error:notsup` in case there is no engine support\nin the underlying OpenSSL implementation.","ref":"crypto.html#engine_add/1"},{"type":"function","title":"crypto.engine_by_id/1","doc":"Get a reference to an already loaded engine with `EngineId`. An error tuple is\nreturned if the engine can't be unloaded.\n\nThe function raises a `error:badarg` if the parameter is in wrong format. It may\nalso raise the exception `error:notsup` in case there is no engine support in\nthe underlying OpenSSL implementation.\n\nSee also the chapter [Engine Load](engine_load.md#engine_load) in the User's\nGuide.","ref":"crypto.html#engine_by_id/1"},{"type":"function","title":"crypto.engine_ctrl_cmd_string/3","doc":"Send ctrl commands to an OpenSSL engine.\n\nThis function is the same as calling `engine_ctrl_cmd_string/4` with `Optional`\nset to `false`.\n\nThe function raises a `error:badarg` if the parameters are in wrong format. It\nmay also raise the exception `error:notsup` in case there is no engine support\nin the underlying OpenSSL implementation.","ref":"crypto.html#engine_ctrl_cmd_string/3"},{"type":"function","title":"crypto.engine_ctrl_cmd_string/4","doc":"Send ctrl commands to an OpenSSL engine.\n\n`Optional` is a\nboolean argument that can relax the semantics of the function. If set to `true`\nit will only return failure if the ENGINE supported the given command name but\nfailed while executing it, if the ENGINE doesn't support the command name it\nwill simply return success without doing anything. In this case we assume the\nuser is only supplying commands specific to the given ENGINE so we set this to\n`false`.\n\nThe function raises a `error:badarg` if the parameters are in wrong format. It\nmay also raise the exception `error:notsup` in case there is no engine support\nin the underlying OpenSSL implementation.","ref":"crypto.html#engine_ctrl_cmd_string/4"},{"type":"function","title":"crypto.engine_get_all_methods/0","doc":"Return a list of all possible engine methods.\n\nMay raise exception `error:notsup` in case there is no engine support in the\nunderlying OpenSSL implementation.\n\nSee also the chapter [Engine Load](engine_load.md#engine_load) in the User's\nGuide.","ref":"crypto.html#engine_get_all_methods/0"},{"type":"function","title":"crypto.engine_get_id/1","doc":"Return the ID for the engine, or an empty binary if there is no id set.\n\nThe function raises a `error:badarg` if the parameters are in wrong format. It\nmay also raise the exception `error:notsup` in case there is no engine support\nin the underlying OpenSSL implementation.","ref":"crypto.html#engine_get_id/1"},{"type":"function","title":"crypto.engine_get_name/1","doc":"Return the name (eg a description) for the engine, or an empty binary if there\nis no name set.\n\nThe function raises a `error:badarg` if the parameters are in wrong format. It\nmay also raise the exception `error:notsup` in case there is no engine support\nin the underlying OpenSSL implementation.","ref":"crypto.html#engine_get_name/1"},{"type":"function","title":"crypto.engine_list/0","doc":"List the id's of all engines in OpenSSL's internal list.\n\nIt may also raise the exception `error:notsup` in case there is no engine\nsupport in the underlying OpenSSL implementation.\n\nSee also the chapter [Engine Load](engine_load.md#engine_load) in the User's\nGuide.\n\nMay raise exception `error:notsup` in case engine functionality is not supported\nby the underlying OpenSSL implementation.","ref":"crypto.html#engine_list/0"},{"type":"function","title":"crypto.engine_load/3","doc":"Load an OpenSSL engine.\n\nLoads the OpenSSL engine given by `EngineId` if it is available and intialize\nit. Returns `ok` and an engine handle, or if the engine can't be loaded an error\ntuple is returned.\n\nThe function raises a `error:badarg` if the parameters are in wrong format. It\nmay also raise the exception `error:notsup` in case there is no engine support\nin the underlying OpenSSL implementation.\n\nSee also the chapter [Engine Load](engine_load.md#engine_load) in the User's\nGuide.","ref":"crypto.html#engine_load/3"},{"type":"function","title":"crypto.engine_register/2","doc":"Register engine to handle some type of methods, for example\nengine_method_digests.\n\nThe function raises a `error:badarg` if the parameters are in wrong format. It\nmay also raise the exception `error:notsup` in case there is no engine support\nin the underlying OpenSSL implementation.","ref":"crypto.html#engine_register/2"},{"type":"function","title":"crypto.engine_remove/1","doc":"Remove the engine from OpenSSL's internal list.\n\nThe function raises a `error:badarg` if the parameters are in wrong format. It\nmay also raise the exception `error:notsup` in case there is no engine support\nin the underlying OpenSSL implementation.","ref":"crypto.html#engine_remove/1"},{"type":"function","title":"crypto.engine_unload/1","doc":"Unload an OpenSSL engine.\n\nUnloads the OpenSSL engine given by `Engine`. An error tuple is returned if the\nengine can't be unloaded.\n\nThe function raises a `error:badarg` if the parameter is in wrong format. It may\nalso raise the exception `error:notsup` in case there is no engine support in\nthe underlying OpenSSL implementation.\n\nSee also the chapter [Engine Load](engine_load.md#engine_load) in the User's\nGuide.","ref":"crypto.html#engine_unload/1"},{"type":"function","title":"crypto.engine_unregister/2","doc":"Unregister engine so it don't handle some type of methods.\n\nThe function raises a `error:badarg` if the parameters are in wrong format. It\nmay also raise the exception `error:notsup` in case there is no engine support\nin the underlying OpenSSL implementation.","ref":"crypto.html#engine_unregister/2"},{"type":"function","title":"crypto.ensure_engine_loaded/2","doc":"Load a dynamic engine if not already done.\n\nLoada the engine given by `EngineId` and the path to the dynamic library\nimplementing the engine. An error tuple is returned if the engine can't be\nloaded.\n\nThis function differs from the normal engine_load in the sense that it also add\nthe engine id to OpenSSL's internal engine list. The difference between the\nfirst call and the following is that the first loads the engine with the\ndynamical engine and the following calls fetch it from the OpenSSL's engine\nlist. All references that is returned are equal.\n\nUse [`engine_unload/1`](`engine_unload/1`) function to remove the references.\nBut remember that [`engine_unload/1`](`engine_unload/1`) just removes the\nreferences to the engine and not the tag in OpenSSL's engine list. That has to\nbe done with the [`engine_remove/1`](`engine_remove/1`) function when needed\n(just called once, from any of the references you got).\n\nThe function raises a `error:badarg` if the parameters are in wrong format. It\nmay also raise the exception `error:notsup` in case there is no engine support\nin the underlying OpenSSL implementation.\n\nSee also the chapter [Engine Load](engine_load.md#engine_load) in the User's\nGuide.","ref":"crypto.html#ensure_engine_loaded/2"},{"type":"function","title":"crypto.exor/2","doc":"Perform bit-wise XOR (exclusive or) on the data supplied.\n\nThe two byte sequences mus be of equal length.","ref":"crypto.html#exor/2"},{"type":"function","title":"crypto.generate_key/2","doc":"","ref":"crypto.html#generate_key/2"},{"type":"function","title":"crypto.generate_key/3","doc":"Generate a public key.\n\nSee also `public_key:generate_key/1`.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.\n\n> #### Note {: .info }\n>\n> If the linked version of cryptolib is OpenSSL 3.0\n>\n> - and the `Type` is `dh` (diffie-hellman)\n> - and the parameter `P` (in `t:dh_params/0`) is one of the MODP groups (see\n> [RFC 3526](https://tools.ietf.org/html/rfc3526))\n> - and the optional `PrivateKeyBitLength` parameter (in `t:dh_params/0`) is\n> present,\n>\n> then the optional key length parameter must be at least 224, 256, 302, 352 and\n> 400 for group sizes of 2048, 3072, 4096, 6144 and 8192, respectively.","ref":"crypto.html#generate_key/3"},{"type":"function","title":"crypto.hash/2","doc":"Compute a message digest.\n\nArgument `Type` is the digest type and argument `Data` is the full message.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","ref":"crypto.html#hash/2"},{"type":"function","title":"crypto.hash_equals/2","doc":"Compare two binaries in constant time, such as results of HMAC computations.\n\nReturns true if the binaries are identical, false if they are of the same length\nbut not identical. The function raises an `error:badarg` exception if the\nbinaries are of different size.","ref":"crypto.html#hash_equals/2"},{"type":"function","title":"crypto.hash_final/1","doc":"Finalize a streaming hash calculation.\n\nArgument `State` as returned from the last call to\n[hash_update](`hash_update/2`). The size of `Digest` is determined by\nthe type of hash function used to generate it.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","ref":"crypto.html#hash_final/1"},{"type":"function","title":"crypto.hash_info/1","doc":"Get information about a hash algorithm.\n\nReturns a map with information about block_size, size and possibly other\nproperties of the hash algorithm in question.\n\nFor a list of supported hash algorithms, see [supports(hashs)](`supports/1`).","ref":"crypto.html#hash_info/1"},{"type":"function","title":"crypto.hash_init/1","doc":"Initialize the state for a streaming hash digest calculation.\n\nArgument `Type` determines which digest to use. The returned state should be\nused as argument to `hash_update/2`.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","ref":"crypto.html#hash_init/1"},{"type":"function","title":"crypto.hash_update/2","doc":"Add data to a streaming digest calculation.\n\nUpdate the digest using the given `Data` of any length.\n\nArgument `State` must have been generated by [hash_init](`hash_init/1`) or a\nprevious call to this function.\n\nReturns `NewState` that must be passed into the next call to `hash_update/2` or\n`hash_final/1`.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","ref":"crypto.html#hash_update/2"},{"type":"function","title":"crypto.hash_xof/3","doc":"Compute a message digest for an `xof_algorithm`.\n\nArgument `Type` is the type of digest, `Data` is the full text and `Length` is\nthe digest length in bits.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.\n\nMay raise exception `error:notsup` in case the chosen `Type` is not supported by\nthe underlying libcrypto implementation.","ref":"crypto.html#hash_xof/3"},{"type":"function","title":"crypto.info/0","doc":"Get information about crypto and the OpenSSL backend.\n\nReturns a map with information about the compilation and linking of crypto.\n\nExample:\n\n```erlang\n1> crypto:info().\n#{compile_type => normal,\n cryptolib_version_compiled => \"OpenSSL 3.0.0 7 sep 2021\",\n cryptolib_version_linked => \"OpenSSL 3.0.0 7 sep 2021\",\n link_type => dynamic,\n otp_crypto_version => \"5.0.2\"}\n2>\n```\n\nMore association types than documented may be present in the map.","ref":"crypto.html#info/0"},{"type":"function","title":"crypto.info_fips/0","doc":"Get information about the operating status of FIPS.\n\nReturns the FIPS operating status of crypto and the underlying libcrypto\nlibrary. If crypto was built with FIPS support this can be either `enabled`\n(when running in FIPS mode) or `not_enabled`. For other builds\nthis value is always `not_supported`.\n\nSee configuration parameter [fips_mode](`e:crypto:crypto_app.md#fips_mode`)\nabout how to enable FIPS mode.\n\n> #### Warning {: .warning }\n>\n> In FIPS mode all non-FIPS compliant algorithms are disabled and raise\n> exception `error:notsup`. Check [supports(ciphers)](`supports/1`) that in FIPS\n> mode returns the restricted list of available algorithms.","ref":"crypto.html#info_fips/0"},{"type":"function","title":"crypto.info_lib/0","doc":"Get the name and version of the libraries used by crypto.\n\n`Name` is the name of the library. `VerNum` is the numeric version according to\nthe library's own versioning scheme. `VerStr` contains a text variant of the\nversion.\n\n```erlang\n> info_lib().\n[{<<\"OpenSSL\">>,269484095,<<\"OpenSSL 1.1.0c 10 Nov 2016\"\">>}]\n```\n\n> #### Note {: .info }\n>\n> From OTP R16 the _numeric version_ represents the version of the OpenSSL\n> _header files_ (`openssl/opensslv.h`) used when crypto was compiled. The text\n> variant represents the libcrypto library used at runtime. In earlier OTP\n> versions both numeric and text was taken from the library.","ref":"crypto.html#info_lib/0"},{"type":"function","title":"crypto.mac/3","doc":"Compute a `poly1305` MAC (Message Authentication Code).\n\nSame as [`mac(Type, undefined, Key, Data)`](`mac/4`).\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","ref":"crypto.html#mac/3"},{"type":"function","title":"crypto.mac/4","doc":"Compute a MAC (Message Authentication Code).\n\nArgument `Type` is the type of MAC and `Data` is the full message.\n\n`SubType` depends on the MAC `Type`:\n\n- For `hmac` it is a hash algorithm, see\n [Algorithm Details](algorithm_details.md#hmac) in the User's Guide.\n- For `cmac` it is a cipher suitable for cmac, see\n [Algorithm Details](algorithm_details.md#cmac) in the User's Guide.\n- For `poly1305` it should be set to `undefined` or the [mac/2](`mac_init/2`)\n function could be used instead, see\n [Algorithm Details](algorithm_details.md#poly1305) in the User's Guide.\n\n`Key` is the authentication key with a length according to the `Type` and\n`SubType`. The key length could be found with the `hash_info/1` (`hmac`) for and\n`cipher_info/1` (`cmac`) functions. For `poly1305` the key length is 32 bytes.\nNote that the cryptographic quality of the key is not checked.\n\nThe `Mac` result will have a default length depending on the `Type` and\n`SubType`. To set a shorter length, use `macN/4` or `macN/5` instead. The\ndefault length is documented in\n[Algorithm Details](algorithm_details.md#message-authentication-codes-macs) in\nthe User's Guide.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","ref":"crypto.html#mac/4"},{"type":"function","title":"crypto.mac_final/1","doc":"Finalize a streaming MAC operation.\n\nArgument `State` is the state as returned by the last call to `mac_update/2`.\n\nThe `Mac` result will have a default length depending on the `Type` and `SubType` in the\n[mac_init/2,3](`mac_init/3`) call. To set a shorter length, use `mac_finalN/2`\ninstead. The default length is documented in\n[Algorithm Details](algorithm_details.md#message-authentication-codes-macs) in\nthe User's Guide.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","ref":"crypto.html#mac_final/1"},{"type":"function","title":"crypto.mac_finalN/2","doc":"Finalize a MAC operation with a custom length.\n\nArgument `State` is the state as returned by the last call to `mac_update/2`.\n\n`Mac` will be a binary with at most `MacLength` bytes. Note that if `MacLength`\nis greater than the actual number of bytes returned from the underlying hash,\nthe returned hash will have that shorter length instead.\n\nThe max `MacLength` is documented in\n[Algorithm Details](algorithm_details.md#message-authentication-codes-macs) in\nthe User's Guide.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","ref":"crypto.html#mac_finalN/2"},{"type":"function","title":"crypto.mac_init/2","doc":"Initialize a state for streaming `poly1305` MAC calculation.\n\nSame as [`mac_init(Type, undefined, Key)`](`mac_init/3`).\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","ref":"crypto.html#mac_init/2"},{"type":"function","title":"crypto.mac_init/3","doc":"Initialize the state for streaming MAC calculation.\n\n`Type` determines which mac algorithm to use in the MAC operation.\n\n`SubType` depends on the MAC `Type`:\n\n- For `hmac` it is a hash algorithm, see\n [Algorithm Details](algorithm_details.md#hmac) in the User's Guide.\n- For `cmac` it is a cipher suitable for cmac, see\n [Algorithm Details](algorithm_details.md#cmac) in the User's Guide.\n- For `poly1305` it should be set to `undefined` or the [mac/2](`mac_init/2`)\n function could be used instead, see\n [Algorithm Details](algorithm_details.md#poly1305) in the User's Guide.\n\n`Key` is the authentication key with a length according to the `Type` and\n`SubType`. The key length could be found with the `hash_info/1` (`hmac`) for and\n`cipher_info/1` (`cmac`) functions. For `poly1305` the key length is 32 bytes.\nNote that the cryptographic quality of the key is not checked.\n\nThe returned `State` should be used in one or more subsequent calls to\n`mac_update/2`. The MAC value is finally returned by calling `mac_final/1` or\n`mac_finalN/2`.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.\n\nSee\n[examples in the User's Guide.](new_api.md#example-of-mac_init-mac_update-and-mac_final)","ref":"crypto.html#mac_init/3"},{"type":"function","title":"crypto.mac_update/2","doc":"Add data to a streaming MAC calculation.\n\nUpdate the MAC represented by `State0` using the given `Data` which could be of\nany length.\n\nThe `State0` is the State value originally from a MAC init function, that is\n`mac_init/2`, `mac_init/3` or the last call to `mac_update/2`. The value\n`State0` is returned unchanged by the function as a reference to a mutated\ninternal state. Hence, it is not possible to branch off a data stream by reusing\nold states.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","ref":"crypto.html#mac_update/2"},{"type":"function","title":"crypto.macN/4","doc":"Compute a `poly1305` MAC (Message Authentication Code) with a limited length.\n\nSame as [`macN(Type, undefined, Key, Data, MacLength)`](`macN/5`).\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","ref":"crypto.html#macN/4"},{"type":"function","title":"crypto.macN/5","doc":"Compute a MAC (Message Authentication Code) with a limited length.\n\nWorks like `mac/3` and `mac/4` but `MacLength` will limit the size of the\nresultant `Mac` to at most `MacLength` bytes. Note that if `MacLength` is\ngreater than the actual number of bytes returned from the underlying hash, the\nreturned hash will have that shorter length instead.\n\nThe max `MacLength` is documented in\n[Algorithm Details](algorithm_details.md#message-authentication-codes-macs) in\nthe User's Guide.","ref":"crypto.html#macN/5"},{"type":"function","title":"crypto.mod_pow/3","doc":"Compute the function `N^P mod M`.","ref":"crypto.html#mod_pow/3"},{"type":"function","title":"crypto.pbkdf2_hmac/5","doc":"PKCS #5 PBKDF2 (Password-Based Key Derivation Function 2) in combination with\nHMAC.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.","ref":"crypto.html#pbkdf2_hmac/5"},{"type":"function","title":"crypto.private_decrypt/4","doc":"Decrypt using a private key.\n\nDecrypts the `CipherText`, encrypted with `public_encrypt/4` (or equivalent\nfunction) using the `PrivateKey`, and returns the plaintext (message digest).\nThis is a low level signature verification operation used for instance by older\nversions of the SSL protocol. See also\n[public_key:decrypt_private/2,3](`public_key:decrypt_private/2`)\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.\n\n> #### Warning {: .warning }\n>\n> This is a legacy function, for security reasons do not use with rsa_pkcs1_padding.","ref":"crypto.html#private_decrypt/4"},{"type":"function","title":"crypto.private_encrypt/4","doc":"Encrypt using a private key.\n\nEncrypts the `PlainText` using the `PrivateKey` and returns the ciphertext. This\nis a low level signature operation used for instance by older versions of the\nSSL protocol. See also\n[public_key:encrypt_private/2,3](`public_key:encrypt_private/2`)\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.\n\nPublic-key decryption using the private key. See also `crypto:private_decrypt/4`\n\n> #### Warning {: .warning }\n>\n> This is a legacy function, for security reasons do not use with rsa_pkcs1_padding.\n> For digital signatures use of [`sign/4`](`sign/4`) together\n> with [`verify/5`](`verify/5`) is the prefered solution.","ref":"crypto.html#private_encrypt/4"},{"type":"function","title":"crypto.privkey_to_pubkey/2","doc":"Fetch public key from a private key stored in an Engine.\n\nThe key must be of the type indicated by the Type parameter.","ref":"crypto.html#privkey_to_pubkey/2"},{"type":"function","title":"crypto.public_decrypt/4","doc":"Decrypt using a public key.\n\nDecrypts the `CipherText`, encrypted with `private_encrypt/4`(or equivalent\nfunction) using the `PublicKey`, and returns the plaintext (message digest).\nThis is a low level signature verification operation used for instance by older\nversions of the SSL protocol. See also\n[public_key:decrypt_public/2,3](`public_key:decrypt_public/2`)\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.\n\n> #### Warning {: .warning }\n>\n> This is a legacy function, for security reasons do not use with rsa_pkcs1_padding.\n> For digital signatures use of [`verify/5`](`verify/5`) together\n> with [`sign/4`](`sign/4`) is the prefered solution.","ref":"crypto.html#public_decrypt/4"},{"type":"function","title":"crypto.public_encrypt/4","doc":"Encrypt using a public key.\n\nEncrypts the `PlainText` (message digest) using the `PublicKey` and returns the\n`CipherText`. This is a low level signature operation used for instance by older\nversions of the SSL protocol. See also\n[public_key:encrypt_public/2,3](`public_key:encrypt_public/2`)\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.\n\n> #### Warning {: .warning }\n>\n> This is a legacy function, for security reasons do not use together with rsa_pkcs1_padding.","ref":"crypto.html#public_encrypt/4"},{"type":"function","title":"crypto.rand_seed/0","doc":"Create a state object for [random number generation](`m:rand`), in order to\ngenerate cryptographically strong random numbers (based on OpenSSL's\n`BN_rand_range`).\n\nSaves the state in the process dictionary before returning it as\nwell. See also `rand:seed/1` and `rand_seed_s/0`.\n\nWhen using the state object from this function the `m:rand` functions using it\nmay raise exception `error:low_entropy` in case the random generator failed due\nto lack of secure \"randomness\".\n\n_Example_\n\n```erlang\n_ = crypto:rand_seed(),\n_IntegerValue = rand:uniform(42), % [1; 42]\n_FloatValue = rand:uniform(). % [0.0; 1.0[\n```","ref":"crypto.html#rand_seed/0"},{"type":"function","title":"crypto.rand_seed/1","doc":"Set the seed for PRNG to the given binary.\n\nThis calls the RAND_seed function from openssl. Only use this if the system you\nare running on does not have enough \"randomness\" built in. Normally this is when\n`strong_rand_bytes/1` raises `error:low_entropy`.","ref":"crypto.html#rand_seed/1"},{"type":"function","title":"crypto.rand_seed_alg/1","doc":"Create a state object for [random number generation](`m:rand`), in order to\ngenerate cryptographically strong random numbers.\n\nSaves the state in the process dictionary before returning it as well. See also\n`rand:seed/1` and `rand_seed_alg_s/1`.\n\nWhen using the state object from this function the `m:rand` functions using it\nmay raise exception `error:low_entropy` in case the random generator failed due\nto lack of secure \"randomness\".\n\n_Example_\n\n```erlang\n_ = crypto:rand_seed_alg(crypto_cache),\n_IntegerValue = rand:uniform(42), % [1; 42]\n_FloatValue = rand:uniform(). % [0.0; 1.0[\n```","ref":"crypto.html#rand_seed_alg/1"},{"type":"function","title":"crypto.rand_seed_alg/2","doc":"Creates a state object for [random number generation](`m:rand`), in order to\ngenerate cryptographically unpredictable random numbers.\n\nSaves the state in the process dictionary before returning it as well. See also\n`rand_seed_alg_s/2`.\n\n_Example_\n\n```erlang\n_ = crypto:rand_seed_alg(crypto_aes, \"my seed\"),\nIntegerValue = rand:uniform(42), % [1; 42]\nFloatValue = rand:uniform(), % [0.0; 1.0[\n_ = crypto:rand_seed_alg(crypto_aes, \"my seed\"),\nIntegerValue = rand:uniform(42), % Same values\nFloatValue = rand:uniform(). % again\n```","ref":"crypto.html#rand_seed_alg/2"},{"type":"function","title":"crypto.rand_seed_alg_s/1","doc":"Create a state object for [random number generation](`m:rand`), in order to\ngenerate cryptographically strongly random numbers.\n\nSee also `rand:seed_s/1`.\n\nIf `Alg` is `crypto` this function behaves exactly like `rand_seed_s/0`.\n\nIf `Alg` is `crypto_cache` this function fetches random data with OpenSSL's\n`RAND_bytes` and caches it for speed using an internal word size of 56 bits that\nmakes calculations fast on 64 bit machines.\n\nWhen using the state object from this function the `m:rand` functions using it\nmay raise exception `error:low_entropy` in case the random generator failed due\nto lack of secure \"randomness\".\n\nThe cache size can be changed from its default value using the\n[crypto app's ](crypto_app.md)configuration parameter `rand_cache_size`.\n\n> #### Note {: .info }\n>\n> The state returned from this function cannot be used to get a reproducible\n> random sequence as from the other `m:rand` functions, since reproducibility\n> does not match cryptographically safe.\n>\n> In fact since random data is cached some numbers may get reproduced if you\n> try, but this is unpredictable.\n>\n> The only supported usage is to generate one distinct random sequence from this\n> start state.","ref":"crypto.html#rand_seed_alg_s/1"},{"type":"function","title":"crypto.rand_seed_alg_s/2","doc":"Create a state object for [random number generation](`m:rand`), in order to\ngenerate cryptographically unpredictable random numbers.\n\nSee also `rand_seed_alg/1`.\n\nTo get a long period the Xoroshiro928 generator from the `m:rand` module is used\nas a counter (with period 2^928 - 1) and the generator states are scrambled\nthrough AES to create 58-bit pseudo random values.\n\nThe result should be statistically completely unpredictable random values, since\nthe scrambling is cryptographically strong and the period is ridiculously long.\nBut the generated numbers are not to be regarded as cryptographically strong\nsince there is no re-keying schedule.\n\n- If you need cryptographically strong random numbers use `rand_seed_alg_s/1`\n with `Alg =:= crypto` or `Alg =:= crypto_cache`.\n- If you need to be able to repeat the sequence use this function.\n- If you do not need the statistical quality of this function, there are faster\n algorithms in the `m:rand` module.\n\nThanks to the used generator the state object supports the\n[`rand:jump/0,1`](`rand:jump/0`) function with distance 2^512.\n\nNumbers are generated in batches and cached for speed reasons. The cache size\ncan be changed from its default value using the\n[crypto app's ](crypto_app.md)configuration parameter `rand_cache_size`.","ref":"crypto.html#rand_seed_alg_s/2"},{"type":"function","title":"crypto.rand_seed_s/0","doc":"Create a state object for [random number generation](`m:rand`), in order to\ngenerate cryptographically strongly random numbers (based on OpenSSL's\n`BN_rand_range`). See also `rand:seed_s/1`.\n\nWhen using the state object from this function the `m:rand` functions using it\nmay raise exception `error:low_entropy` in case the random generator failed due\nto lack of secure \"randomness\".\n\n> #### Note {: .info }\n>\n> The state returned from this function cannot be used to get a reproducible\n> random sequence as from the other `m:rand` functions, since reproducibility\n> does not match cryptographically safe.\n>\n> The only supported usage is to generate one distinct random sequence from this\n> start state.","ref":"crypto.html#rand_seed_s/0"},{"type":"function","title":"crypto.rand_uniform/2","doc":"Generate a random integer number.\n\nThe interval is `From =< N < To`. Uses the `crypto` library\npseudo-random number generator. `To` must be larger than `From`.","ref":"crypto.html#rand_uniform/2"},{"type":"function","title":"crypto.sign/4","doc":"","ref":"crypto.html#sign/4"},{"type":"function","title":"crypto.sign/5","doc":"Create a digital signature.\n\nThe msg is either the binary \"cleartext\" data to be signed or it is the hashed\nvalue of \"cleartext\" i.e. the digest (plaintext).\n\nAlgorithm `dss` can only be used together with digest type `sha`.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.\n\nSee also `public_key:sign/3`.","ref":"crypto.html#sign/5"},{"type":"function","title":"crypto.start/0","doc":"Use [`application:start(crypto)`](`application:start/1`) instead.\n\n> #### Warning {: .warning }\n>\n> This function does not work if FIPS mode is to be enabled. FIPS mode will be\n> disabled even if configuration parameter `fips_mode` is set to `true`. Use\n> [`application:start(crypto)`](`application:start/1`) instead.","ref":"crypto.html#start/0"},{"type":"function","title":"crypto.stop/0","doc":"Use [`application:stop(crypto)`](`application:stop/1`) instead.","ref":"crypto.html#stop/0"},{"type":"function","title":"crypto.strong_rand_bytes/1","doc":"Generate bytes with randomly uniform values 0..255.\n\nReturns the result in a binary with `N` bytes.\n\nUses a cryptographically secure PRNG seeded and periodically mixed with\noperating system provided entropy. By default this is the `RAND_bytes` method\nfrom OpenSSL.\n\nMay raise exception `error:low_entropy` in case the random generator failed due\nto lack of secure \"randomness\".","ref":"crypto.html#strong_rand_bytes/1"},{"type":"function","title":"crypto.supports/1","doc":"Get which crypto algorithms that are supported by the underlying libcrypto\nlibrary.\n\nSee `hash_info/1` and `cipher_info/1` for information about the hash and cipher\nalgorithms.","ref":"crypto.html#supports/1"},{"type":"function","title":"crypto.verify/5","doc":"","ref":"crypto.html#verify/5"},{"type":"function","title":"crypto.verify/6","doc":"Verify a digital signature.\n\nThe msg is either the binary \"cleartext\" data to be signed or it is the hashed\nvalue of \"cleartext\" i.e. the digest (plaintext).\n\nAlgorithm `dss` can only be used together with digest type `sha`.\n\nUses the [3-tuple style](`m:crypto#error_3tup`) for error handling.\n\nSee also `public_key:verify/4`.","ref":"crypto.html#verify/6"},{"type":"type","title":"crypto.blake2/0","doc":"","ref":"crypto.html#t:blake2/0"},{"type":"type","title":"crypto.cipher/0","doc":"","ref":"crypto.html#t:cipher/0"},{"type":"type","title":"crypto.cipher_aead/0","doc":"Ciphers known by the CRYPTO application.\n\nNote that this list might be reduced if the underlying libcrypto does not\nsupport all of them.","ref":"crypto.html#t:cipher_aead/0"},{"type":"type","title":"crypto.cipher_iv/0","doc":"","ref":"crypto.html#t:cipher_iv/0"},{"type":"type","title":"crypto.cipher_no_iv/0","doc":"","ref":"crypto.html#t:cipher_no_iv/0"},{"type":"type","title":"crypto.cmac_cipher_algorithm/0","doc":"","ref":"crypto.html#t:cmac_cipher_algorithm/0"},{"type":"type","title":"crypto.compatibility_only_hash/0","doc":"The `t:compatibility_only_hash/0` algorithms are recommended only for\ncompatibility with existing applications.","ref":"crypto.html#t:compatibility_only_hash/0"},{"type":"type","title":"crypto.crypto_integer/0","doc":"","ref":"crypto.html#t:crypto_integer/0"},{"type":"type","title":"crypto.crypto_opt/0","doc":"Selects encryption (`{encrypt,true}`) or decryption (`{encrypt,false}`).","ref":"crypto.html#t:crypto_opt/0"},{"type":"type","title":"crypto.crypto_opts/0","doc":"","ref":"crypto.html#t:crypto_opts/0"},{"type":"opaque","title":"crypto.crypto_state/0","doc":"","ref":"crypto.html#t:crypto_state/0"},{"type":"type","title":"crypto.cryptolib_padding/0","doc":"The `cryptolib_padding` are paddings that may be present in the underlying\ncryptolib linked to the Erlang/OTP crypto app.\n\nFor OpenSSL, see the [OpenSSL documentation](https://openssl.org). and find\n`EVP_CIPHER_CTX_set_padding()` in cryptolib for your linked version.","ref":"crypto.html#t:cryptolib_padding/0"},{"type":"type","title":"crypto.dh_params/0","doc":"```text\ndh_params() = [P, G] | [P, G, PrivateKeyBitLength]\n```","ref":"crypto.html#t:dh_params/0"},{"type":"type","title":"crypto.dh_private/0","doc":"","ref":"crypto.html#t:dh_private/0"},{"type":"type","title":"crypto.dh_public/0","doc":"","ref":"crypto.html#t:dh_public/0"},{"type":"type","title":"crypto.dss_digest_type/0","doc":"","ref":"crypto.html#t:dss_digest_type/0"},{"type":"type","title":"crypto.dss_private/0","doc":"```text\ndss_public() = [P, Q, G, Y]\n```\n\nWhere P, Q and G are the dss parameters and Y is the public key.\n\n```text\ndss_private() = [P, Q, G, X]\n```\n\nWhere P, Q and G are the dss parameters and X is the private key.","ref":"crypto.html#t:dss_private/0"},{"type":"type","title":"crypto.dss_public/0","doc":"","ref":"crypto.html#t:dss_public/0"},{"type":"type","title":"crypto.ec_basis/0","doc":"Curve definition details.","ref":"crypto.html#t:ec_basis/0"},{"type":"type","title":"crypto.ec_characteristic_two_field/0","doc":"","ref":"crypto.html#t:ec_characteristic_two_field/0"},{"type":"type","title":"crypto.ec_curve/0","doc":"Parametric curve definition.","ref":"crypto.html#t:ec_curve/0"},{"type":"type","title":"crypto.ec_explicit_curve/0","doc":"","ref":"crypto.html#t:ec_explicit_curve/0"},{"type":"type","title":"crypto.ec_field/0","doc":"","ref":"crypto.html#t:ec_field/0"},{"type":"type","title":"crypto.ec_named_curve/0","doc":"","ref":"crypto.html#t:ec_named_curve/0"},{"type":"type","title":"crypto.ec_prime_field/0","doc":"","ref":"crypto.html#t:ec_prime_field/0"},{"type":"type","title":"crypto.ecdh_params/0","doc":"","ref":"crypto.html#t:ecdh_params/0"},{"type":"type","title":"crypto.ecdh_private/0","doc":"","ref":"crypto.html#t:ecdh_private/0"},{"type":"type","title":"crypto.ecdh_public/0","doc":"","ref":"crypto.html#t:ecdh_public/0"},{"type":"type","title":"crypto.ecdsa_digest_type/0","doc":"","ref":"crypto.html#t:ecdsa_digest_type/0"},{"type":"type","title":"crypto.ecdsa_params/0","doc":"","ref":"crypto.html#t:ecdsa_params/0"},{"type":"type","title":"crypto.ecdsa_private/0","doc":"","ref":"crypto.html#t:ecdsa_private/0"},{"type":"type","title":"crypto.ecdsa_public/0","doc":"","ref":"crypto.html#t:ecdsa_public/0"},{"type":"type","title":"crypto.eddsa_params/0","doc":"","ref":"crypto.html#t:eddsa_params/0"},{"type":"type","title":"crypto.eddsa_private/0","doc":"","ref":"crypto.html#t:eddsa_private/0"},{"type":"type","title":"crypto.eddsa_public/0","doc":"","ref":"crypto.html#t:eddsa_public/0"},{"type":"type","title":"crypto.edwards_curve_dh/0","doc":"","ref":"crypto.html#t:edwards_curve_dh/0"},{"type":"type","title":"crypto.edwards_curve_ed/0","doc":"Note that some curves are disabled if FIPS is enabled.","ref":"crypto.html#t:edwards_curve_ed/0"},{"type":"type","title":"crypto.engine_cmnd/0","doc":"Pre and Post commands for [engine_load/3 and /4](`engine_load/3`).","ref":"crypto.html#t:engine_cmnd/0"},{"type":"type","title":"crypto.engine_key_ref/0","doc":"","ref":"crypto.html#t:engine_key_ref/0"},{"type":"type","title":"crypto.engine_method_type/0","doc":"","ref":"crypto.html#t:engine_method_type/0"},{"type":"type","title":"crypto.engine_ref/0","doc":"The result of a call to `engine_load/3`.","ref":"crypto.html#t:engine_ref/0"},{"type":"type","title":"crypto.hash_algorithm/0","doc":"","ref":"crypto.html#t:hash_algorithm/0"},{"type":"opaque","title":"crypto.hash_state/0","doc":"","ref":"crypto.html#t:hash_state/0"},{"type":"type","title":"crypto.hash_xof_algorithm/0","doc":"","ref":"crypto.html#t:hash_xof_algorithm/0"},{"type":"type","title":"crypto.hmac_hash_algorithm/0","doc":"","ref":"crypto.html#t:hmac_hash_algorithm/0"},{"type":"type","title":"crypto.key_id/0","doc":"Identifies the key to be used. The format depends on the loaded engine. It is\npassed to the `ENGINE_load_(private|public)_key` functions in libcrypto.","ref":"crypto.html#t:key_id/0"},{"type":"type","title":"crypto.key_integer/0","doc":"Always `t:binary/0` when used as return value","ref":"crypto.html#t:key_integer/0"},{"type":"opaque","title":"crypto.mac_state/0","doc":"Contexts with an internal state that should not be manipulated but passed\nbetween function calls.","ref":"crypto.html#t:mac_state/0"},{"type":"type","title":"crypto.otp_padding/0","doc":"Erlang/OTP adds a either padding of zeroes or padding with random bytes.","ref":"crypto.html#t:otp_padding/0"},{"type":"type","title":"crypto.padding/0","doc":"This option handles padding in the last block. If not set, no padding is done\nand any bytes in the last unfilled block is silently discarded.","ref":"crypto.html#t:padding/0"},{"type":"type","title":"crypto.password/0","doc":"The password of the key stored in an engine.","ref":"crypto.html#t:password/0"},{"type":"type","title":"crypto.pk_encrypt_decrypt_algs/0","doc":"Algorithms for public key encrypt/decrypt. Only RSA is supported.","ref":"crypto.html#t:pk_encrypt_decrypt_algs/0"},{"type":"type","title":"crypto.pk_encrypt_decrypt_opts/0","doc":"","ref":"crypto.html#t:pk_encrypt_decrypt_opts/0"},{"type":"type","title":"crypto.pk_sign_verify_algs/0","doc":"Algorithms for sign and verify.","ref":"crypto.html#t:pk_sign_verify_algs/0"},{"type":"type","title":"crypto.pk_sign_verify_opts/0","doc":"","ref":"crypto.html#t:pk_sign_verify_opts/0"},{"type":"type","title":"crypto.rand_cache_seed/0","doc":"","ref":"crypto.html#t:rand_cache_seed/0"},{"type":"type","title":"crypto.rsa_compat_opts/0","doc":"Those option forms are kept only for compatibility and should not be used in new\ncode.","ref":"crypto.html#t:rsa_compat_opts/0"},{"type":"type","title":"crypto.rsa_digest_type/0","doc":"","ref":"crypto.html#t:rsa_digest_type/0"},{"type":"type","title":"crypto.rsa_opt/0","doc":"","ref":"crypto.html#t:rsa_opt/0"},{"type":"type","title":"crypto.rsa_padding/0","doc":"Options for public key encrypt/decrypt. Only RSA is supported.\n\n> #### Warning {: .warning }\n>\n> The RSA options are experimental.\n>\n> The exact set of options and there syntax _may_ be changed without prior\n> notice.","ref":"crypto.html#t:rsa_padding/0"},{"type":"type","title":"crypto.rsa_params/0","doc":"```text\nrsa_public() = [E, N]\n```\n\n```erlang\nrsa_private() = [E, N, D] | [E, N, D, P1, P2, E1, E2, C]\n```\n\nWhere E is the public exponent, N is public modulus and D is the private\nexponent. The longer key format contains redundant information that will make\nthe calculation faster. P1 and P2 are first and second prime factors. E1 and E2\nare first and second exponents. C is the CRT coefficient. The terminology is\ntaken from [RFC 3447](http://www.ietf.org/rfc/rfc3447.txt).","ref":"crypto.html#t:rsa_params/0"},{"type":"type","title":"crypto.rsa_private/0","doc":"","ref":"crypto.html#t:rsa_private/0"},{"type":"type","title":"crypto.rsa_public/0","doc":"","ref":"crypto.html#t:rsa_public/0"},{"type":"type","title":"crypto.rsa_sign_verify_opt/0","doc":"","ref":"crypto.html#t:rsa_sign_verify_opt/0"},{"type":"type","title":"crypto.rsa_sign_verify_padding/0","doc":"Options for sign and verify.\n\n> #### Warning {: .warning }\n>\n> The RSA options are experimental.\n>\n> The exact set of options and there syntax _may_ be changed without prior\n> notice.","ref":"crypto.html#t:rsa_sign_verify_padding/0"},{"type":"type","title":"crypto.sha1/0","doc":"","ref":"crypto.html#t:sha1/0"},{"type":"type","title":"crypto.sha2/0","doc":"","ref":"crypto.html#t:sha2/0"},{"type":"type","title":"crypto.sha3/0","doc":"","ref":"crypto.html#t:sha3/0"},{"type":"type","title":"crypto.sha3_xof/0","doc":"","ref":"crypto.html#t:sha3_xof/0"},{"type":"type","title":"crypto.srp_comp_params/0","doc":"","ref":"crypto.html#t:srp_comp_params/0"},{"type":"type","title":"crypto.srp_gen_params/0","doc":"","ref":"crypto.html#t:srp_gen_params/0"},{"type":"type","title":"crypto.srp_host_comp_params/0","doc":"Where Verifier is `v`, Generator is `g` and Prime is` N`, DerivedKey is `X`, and\nScrambler is `u` (optional will be generated if not provided) from\n[SRP design](http://srp.stanford.edu/design.html) Version = '3' | '6' | '6a'","ref":"crypto.html#t:srp_host_comp_params/0"},{"type":"type","title":"crypto.srp_host_gen_params/0","doc":"","ref":"crypto.html#t:srp_host_gen_params/0"},{"type":"type","title":"crypto.srp_private/0","doc":"```text\nsrp_public() = key_integer()\n```\n\nWhere is `A` or `B` from [SRP design](http://srp.stanford.edu/design.html)\n\n```text\nsrp_private() = key_integer()\n```\n\nWhere is `a` or `b` from [SRP design](http://srp.stanford.edu/design.html)","ref":"crypto.html#t:srp_private/0"},{"type":"type","title":"crypto.srp_public/0","doc":"","ref":"crypto.html#t:srp_public/0"},{"type":"type","title":"crypto.srp_user_comp_params/0","doc":"","ref":"crypto.html#t:srp_user_comp_params/0"},{"type":"type","title":"crypto.srp_user_gen_params/0","doc":"","ref":"crypto.html#t:srp_user_gen_params/0"},{"type":"extras","title":"Crypto Application","doc":"\n# Crypto Application","ref":"crypto_app.html"},{"type":"extras","title":"Description - Crypto Application","doc":"The purpose of the Crypto application is to provide an Erlang API to\ncryptographic functions, see `m:crypto`. Note that the API is on a fairly low\nlevel and there are some corresponding API functions available in\n`m:public_key`, on a higher abstraction level, that uses the crypto application\nin its implementation.","ref":"crypto_app.html#description"},{"type":"extras","title":"DEPENDENCIES - Crypto Application","doc":"The current crypto implementation uses nifs to interface OpenSSLs crypto library\nand may work with limited functionality with as old versions as _OpenSSL_\n0\\.9.8c. FIPS mode support requires at least version 1.0.1 and a FIPS capable\nOpenSSL installation. We recommend using a version that is officially supported\nby the OpenSSL project. API compatible backends like LibreSSL should also work.\n\nThe crypto app is tested daily with at least one version of each of the OpenSSL\n1.0.1, 1.0.2, 1.1.0, 1.1.1 and 3.0. FIPS mode is also tested for 1.0.1, 1.0.2\nand 3.0.\n\nUsing OpenSSL 3.0 with Engines is supported since OTP 26.2.\n\nSource releases of OpenSSL can be downloaded from the\n[OpenSSL](http://www.openssl.org) project home page, or mirror sites listed\nthere.","ref":"crypto_app.html#dependencies"},{"type":"extras","title":"CONFIGURATION - Crypto Application","doc":"The following configuration parameters are defined for the crypto application.\nSee [`app(3)`](`e:kernel:app.md`) for more information about configuration\nparameters.\n\n[](){: #fips_mode }\n- **`fips_mode = boolean()`** - Specifies whether to run crypto in FIPS mode.\n This setting will take effect when the nif module is loaded. If FIPS mode is\n requested but not available at run time the nif module and thus the crypto\n module will fail to load. This mechanism prevents the accidental use of\n non-validated algorithms.\n\n- **`rand_cache_size = integer()`** - Sets the cache size in bytes to use by\n [`crypto:rand_seed_alg(crypto_cache)` ](`crypto:rand_seed_alg/1`)and\n [`crypto:rand_seed_alg_s(crypto_cache)` ](`crypto:rand_seed_alg_s/1`). This\n parameter is read when a seed function is called, and then kept in generators\n state object. It has a rather small default value that causes reads of strong\n random bytes about once per hundred calls for a random value. The set value is\n rounded up to an integral number of words of the size these seed functions\n use.","ref":"crypto_app.html#configuration"},{"type":"extras","title":"SEE ALSO - Crypto Application","doc":"application(3)","ref":"crypto_app.html#see-also"},{"type":"extras","title":"Crypto Release Notes","doc":"\n# Crypto Release Notes\n\nThis document describes the changes made to the Crypto application.","ref":"notes.html"},{"type":"extras","title":"Crypto 5.5.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-5-5-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- crypto built with `--enable-fips` will now accept an OpenSSL 3 lib without fips provider as long as fips mode is not enabled.\n\n Own Id: OTP-19212 Aux Id: [GH-8562]\n\n[GH-8562]: https://github.com/erlang/otp/issues/8562","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Added a warning in the documentation to avoid calling `crypto:start/0` as it does not work for FIPS mode. Use `application:start(crypto)` instead.\n\n Own Id: OTP-19143\n\n- Deprecation of RSA encryption functions has been reverted, as there still exists legitimate use cases with other padding modes than PKCS-1.\n \n While use PCKS-1 padding with some versions of cryptolib could be considered secure, we still recommend using other algorithms that are less sensitive to oracle attacks.\n\n Own Id: OTP-19163\n\n- Compiler warnings for some removed functions have been corrected to point out the correct replacement functions.\n\n Own Id: OTP-19186 Aux Id: [PR-8709]\n\n[PR-8709]: https://github.com/erlang/otp/pull/8709","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 5.5 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-5-5"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- The documentation has been migrated to use Markdown and ExDoc.\n\n Own Id: OTP-18955 Aux Id: [PR-8026]\n\n- Removed functions `crypto_dyn_iv_init/3` and `crypto_dyn_iv_update/3` which were marked as deprecated since OTP 25.\n\n Own Id: OTP-18973\n\n- Add support for sm3 hash and hmac.\n\n Own Id: OTP-18975 Aux Id: [PR-6658]\n\n- `OPENSSL_thread_stop` is called when `crypto` is purged to not leak thread specific data.\n\n Own Id: OTP-18978 Aux Id: [PR-7809]\n\n- Add SM4 block cipher implemented according to GB/T 32907-2016.\n\n Own Id: OTP-19005 Aux Id: [PR-8168]\n\n- The existing function `ssl:key_exporter_materials/4` is now documented and supported.\n\n *** POTENTIAL INCOMPATIBILITY ***\n\n Own Id: OTP-19016 Aux Id: [PR-8233]\n\n- Due to another attack on PKCS #1 v1.5 padding, known as the Marvin attack, about which we were alerted by Hubert Kario from Red Hat. You can find more details about the attack at\n https://people.redhat.com/~hkario/marvin/\n Functions that may be vulnerable are now deprecated. \n \n Note that you might mitigate the problem \n by using appropriate versions of OpenSSL together with our software, but we recommend not using them at all. \n \n Also avoid using TLS versions prior to TLS-1.2 (not supported by default) and\n do not enable RSA-key exchange cipher suites (not supported by default).\n\n *** POTENTIAL INCOMPATIBILITY ***\n\n Own Id: OTP-19075\n\n[PR-8026]: https://github.com/erlang/otp/pull/8026\n[PR-6658]: https://github.com/erlang/otp/pull/6658\n[PR-7809]: https://github.com/erlang/otp/pull/7809\n[PR-8168]: https://github.com/erlang/otp/pull/8168\n[PR-8233]: https://github.com/erlang/otp/pull/8233","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 5.4.2.3 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-5-4-2-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"* Fixed bug that could cause blocking scheduler threads in `crypto:supports(curves)` if called the first time by more than one Erlang process. Bug exists only in OTP-26.2.5.4.\n\n Own Id: OTP-19316 Aux Id: GH-8971, PR-8979\n* Fixed `crypto:hash_final/1` for digest types `shake128` and `shake256` when using OpenSSL 3.4 or newer.\n\n Own Id: OTP-19329 Aux Id: GH-8997, PR-9002","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 5.4.2.2 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-5-4-2-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"* crypto built with `--enable-fips` will now accept an OpenSSL 3 lib without fips provider as long as fips mode is not enabled.\n\n Own Id: OTP-19212 Aux Id: GH-8562, PR-8762\n* `crypto:strong_rand_bytes/2` fixed to work on Ubuntu pro with installed FIPS support.\n\n Own Id: OTP-19223 Aux Id: PR-8800, GH-8769","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 5.4.2.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-5-4-2-1"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"* Add warning in documentation to avoid `crypto:start/0` as it does not work for FIPS mode. Use `application:start(crypto)` instead.\n\n Own Id: OTP-19143","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 5.4.2 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-5-4-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"* Fix building with `--enable-fips` with OpenSSL 3 on MacOS.\n\n Own Id: OTP-19038 Aux Id: GH-8271, PR-8277","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 5.4.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-5-4-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"* Fix compile error when OPENSSL_NO_DES is defined.\n\n Own Id: OTP-18921\n* The function `crypto:pbkdf2_hmac` will no longer block the main schedulers. If the iteration count or block size parameters are such that the function is likely to take a long time to execute, the function will be scheduled to run on a dirty CPU scheduler.\n\n Own Id: OTP-18996 Aux Id: PR-8173, PR-8174","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 5.4 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-5-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Fixed some benign compile warnings on Windows.\n\n Own Id: OTP-18895","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Enable engine support for OpenSSL versions 3.\n\n Own Id: OTP-18832 Aux Id: PR-7763","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 5.3 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-5-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Fix VM crash caused by `crypto being` purged and reloaded (by init:restart for\n example) on OS with musl libc (such as Alpine linux).\n\n Own Id: OTP-18670 Aux Id: GH-7436, PR-7450\n\n- Improved understanding of LibreSSL versions. Support chacha20 and\n chacha20_poly1305 for LibreSSL 3.7. Reflect removal of support for the DSS/DSA\n algorithm which was done in LibreSSL 2.6.1.\n\n Own Id: OTP-18758 Aux Id: PR-7209","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- FIPS supported by `crypto` for OpenSSL 3.0._ and 3.1._.\n\n Own Id: OTP-18666 Aux Id: PR-7392","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 5.2 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-5-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Fix cmac_update aes_128_cbc for LibreSSL.\n\n Own Id: OTP-18571","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Add support for SHAKE128 and SHAKE256.\n\n Own Id: OTP-18204 Aux Id: PR-6203\n\n- Make the `-DOPENSSL_API_COMPAT` flag work without warnings.\n\n Own Id: OTP-18206 Aux Id: PR-6167\n\n- Replace size/1 with either tuple_size/1 or byte_size/1\n\n The [`size/1`](`size/1`) BIF is not optimized by the JIT, and its use can\n result in worse types for Dialyzer.\n\n When one knows that the value being tested must be a tuple,\n [`tuple_size/1`](`tuple_size/1`) should always be preferred.\n\n When one knows that the value being tested must be a binary,\n [`byte_size/1`](`byte_size/1`) should be preferred. However,\n [`byte_size/1`](`byte_size/1`) also accepts a bitstring (rounding up size to a\n whole number of bytes), so one must make sure that the call to `byte_size/` is\n preceded by a call to [`is_binary/1`](`is_binary/1`) to ensure that bitstrings\n are rejected. Note that the compiler removes redundant calls to\n [`is_binary/1`](`is_binary/1`), so if one is not sure whether previous code\n had made sure that the argument is a binary, it does not harm to add an\n [`is_binary/1`](`is_binary/1`) test immediately before the call to\n [`byte_size/1`](`byte_size/1`).\n\n Own Id: OTP-18405 Aux Id:\n GH-6672,PR-6702,PR-6768,PR-6700,PR-6769,PR-6812,PR-6814\n\n- Handling of `on_load` modules during boot has been improved by adding an extra\n step in the boot order for embedded mode that runs all `on_load` handlers,\n instead of relying on explicit invocation of them, later, when the kernel\n supervision tree starts.\n\n This is mostly a code improvement and OTP internal simplification to avoid\n future bugs and to simplify code maintenance.\n\n Own Id: OTP-18447","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 5.1.4.3 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-5-1-4-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"* Fix building with `--enable-fips` with OpenSSL 3 on MacOS.\n\n Own Id: OTP-19038 Aux Id: GH-8271, PR-8277","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 5.1.4.2 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-5-1-4-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"* The function `crypto:pbkdf2_hmac` will no longer block the main schedulers. If the iteration count or block size parameters are such that the function is likely to take a long time to execute, the function will be scheduled to run on a dirty CPU scheduler.\n\n Own Id: OTP-18996 Aux Id: PR-8173, PR-8174","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 5.1.4.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-5-1-4-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Fix VM crash caused by `crypto being` purged and reloaded (by init:restart for\n example) on OS with musl libc (such as Alpine linux).\n\n Own Id: OTP-18670 Aux Id: GH-7436, PR-7450","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 5.1.4 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-5-1-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- With this change, random errors are fixed for crypto:generate_key calls with\n OpenSSL 3.\n\n Own Id: OTP-18555","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 5.1.3 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-5-1-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- A user defined runtime library path configured using\n `--with-ssl-rpath= ` could fail to be enabled.\n\n Own Id: OTP-18384 Aux Id: PR-6596\n\n- Ensure that `configure` fails if a user defined runtime library path has been\n passed by the user, but cannot set.\n\n Own Id: OTP-18408","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 5.1.2 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-5-1-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Fix configure with `--with-ssl` and `--disable-dynamic-ssl-lib` on Windows.\n\n Own Id: OTP-18147 Aux Id: GH-6024, PR-6056\n\n- Remove all references correctly in the garbage collection if an engine handle\n was not explicit unloaded.\n\n Own Id: OTP-18152\n\n- Changed the behaviour of the engine load/unload functions\n\n The engine load/unload functions have got changed semantics to get a more\n consistent behaviour and work correct when variables are garbage collected.\n\n The load functions now don't register the methods for the engine to replace.\n That will now be handled with the new functions\n engine_register/engine_unregister if needed.\n\n Some functions are removed from the documentation and therefor the API, but\n they are left in the code for compatibility.\n\n - engine_load/4: is now the same as engine_load/3\n - engine_unload/2: is now the same as engine_unload/1\n - ensure_engine_loaded/3: is now the same as ensure_engine_loaded/2\n - ensure_engine_unloaded/1, ensure_engine_unloaded/2: is now the same as\n engine_unload/1\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18172 Aux Id: ERIERL-826\n\n- Fixed a naming bug for AES-CFB and Blowfish-CFB/OFB when linked with OpenSSL\n 3.0 cryptolib.\n\n Own Id: OTP-18200\n\n- Sign/verify does now behave as in OTP-24 and earlier for eddsa.\n\n Own Id: OTP-18205 Aux Id: GH-6219","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Pass elliptic curve names from crypto.erl to crypto's nif.\n\n Own Id: OTP-18037\n\n- The configure option `--disable-deprecated-warnings` is removed. It was used\n for some releases when the support for OpenSSL 3.0 was not completed. It is\n not needed in OTP 25.\n\n Own Id: OTP-18133\n\n- Crypto is now considered to be usable with the OpenSSL 3.0 cryptolib for\n production code.\n\n ENGINE and FIPS are not yet fully functional.\n\n Own Id: OTP-18153\n\n- Do not exit if the legacy provider is missing in libcrypto 3.0.\n\n Own Id: OTP-18217","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 5.1.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-5-1-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Note in the documentation that MODP (rfc3526) groups and OpenSSL 3.0 can give\n an error if a call to `crypto:generate_key/2` specifies a key length, and that\n length is to small.\n\n Own Id: OTP-18046","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- The cmac now uses only the 3.0 API\n\n Own Id: OTP-18010\n\n- Documentation is now updated with which OpenSSL cryptolib versions that OTP\n currently is tested.\n\n Own Id: OTP-18132","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 5.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-5-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Fix timing bug in ensure_engine_loaded\n\n When two ensure_engine_loaded() calls were done in parallel there was a\n possibility that a crypto lib function was called by both instead of just one\n of them which resulted in an error. This is solved by moving the\n implementation from erlang down into a NIF function that uses a mutex to\n protect the sensitive part.\n\n Own Id: OTP-17858 Aux Id: ERIERL-728\n\n- Remove faulty types `run_time_error()` and `descriptive_error()`.\n\n Own Id: OTP-17984","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Input for `configure` scripts adapted to `autoconf` 2\\.71.\n\n Own Id: OTP-17414 Aux Id: PR-4967\n\n- Add crypto:hash_equals/2\n\n Own Id: OTP-17471 Aux Id: PR-4750\n\n- Add /opt/homebrew/opt/openssl to standard locations to search for OpenSSL\n cryptolib.\n\n Own Id: OTP-17561\n\n- `crypto_dyn_iv_init/3` and `crypto_dyn_iv_update/3` are deprecated.\n\n Own Id: OTP-17870\n\n- The information in error messages are increased.\n\n Previously the error was signaled with en error class exception `badarg`,\n `notsup` or `error`, and also in some more ways like an other exception or a\n return value in a non-standardized format.\n\n Now it is an error-class exception\n `{notsup|badarg|error, InfoFromCfile, Description::string()}`.\n\n The `InfoFromCfile` is a term with name and line number of the C-file where\n the error was found. This is primarily intended for a crypto maintainer or an\n advanced user to find the cause of complicated errors - maybe in crypto\n itself. The contents of that term might be changed in the future.\n\n The `Description` is a clear text string that describes the error. In case of\n `badarg` and `notsup` the intention is that it should help the user to find\n the cause (\"Bad key size\" as an example). Specially for some `error` that are\n unlikely, the string may not be possible to understand without deep knowledge\n of the underlying cryptolib. Such messages are intended for a crypto\n maintainer.\n\n The first element on call stack (the `S` in\n `try ... catch error:E:S .... end`) gives more information like the actual\n argument list in the call of crypto and the argument number (if possible) in\n the call to the NIF inside crypto.\n\n The functions in crypto affected by this change are:\n\n sign/4, sign/5, verify/5, verify/6,\n\n generate_key/2, generate_key/3, compute_key/4,\n\n hash/2, hash/4, hash_init/1, hash_update/4, hash_final/1,\n\n mac/3,4, mac_init/3, mac_update/2, mac_final/2,\n\n pbkdf2_hmac/5,\n\n public_encrypt/4, private_decrypt/4, private_encrypt/4, public_decrypt/4\n\n This schema was introduced earlier in:\n\n crypto_init/3, crypto_init/4, crypto_update/2, crypto_final/1,\n crypto_get_data/1,\n\n crypto_one_time/4, crypto_one_time/5, crypto_one_time_aead/6,\n crypto_one_time_aead/7\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17965\n\n- Add Output Feedback mode (OFB) support for AES encryption / decryption for key\n sizes of 128, 192 and 256 bits.\n\n Own Id: OTP-18067 Aux Id: PR-5866\n\n- The cryptolib API deprecated in OpenSSL 3.0 is now no longer used with a few\n exceptions listed below.\n\n Although OpenSSL 3.0.x itself is stable, its usage in OTP/crypto should still\n not be considered suitable for production code.\n\n The use of ENGINEs is still disabled by default when using 3.0.\n\n Deprecated functions are still called in the otp_test_engine.c (only used in\n tests), in mac.c (EVP_PKEY_new_CMAC_key) and five function calls in ec.c\n (EVP_PKEY_assign, EC_KEY_get_conv_form, EVP_PKEY_get1_EC_KEY,\n EC_KEY_get0_group and EC_KEY_set_public_key).\n\n Own Id: OTP-18086 Aux Id: OTP-16282, OTP-16643, OTP-16644, OTP-17701,\n OTP-17702, OTP-17704","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 5.0.6.5 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-5-0-6-5"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"* The function `crypto:pbkdf2_hmac` will no longer block the main schedulers. If the iteration count or block size parameters are such that the function is likely to take a long time to execute, the function will be scheduled to run on a dirty CPU scheduler.\n\n Own Id: OTP-18996 Aux Id: PR-8173, PR-8174","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 5.0.6.4 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-5-0-6-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Fix VM crash caused by `crypto being` purged and reloaded (by init:restart for\n example) on OS with musl libc (such as Alpine linux).\n\n Own Id: OTP-18670 Aux Id: GH-7436, PR-7450","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 5.0.6.3 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-5-0-6-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Changed the behaviour of the engine load/unload functions\n\n The engine load/unload functions have got changed semantics to get a more\n consistent behaviour and work correct when variables are garbage collected.\n\n The load functions now don't register the methods for the engine to replace.\n That will now be handled with the new functions\n engine_register/engine_unregister if needed.\n\n Some functions functions are removed from the documentation and therefor the\n API, but they are left in the code for compatibility.\n\n - engine_load/4: is now the same as engine_load/3\n - engine_unload/2: is now the same as engine_unload/1\n - ensure_engine_loaded/3: is now the same as ensure_engine_loaded/2\n - ensure_engine_unloaded/1, ensure_engine_unloaded/2: is now the same as\n engine_unload/1\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18172 Aux Id: ERIERL-826","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 5.0.6.2 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-5-0-6-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Fix configure with `--with-ssl` and `--disable-dynamic-ssl-lib` on Windows.\n\n Own Id: OTP-18147 Aux Id: GH-6024, PR-6056","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 5.0.6.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-5-0-6-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Fix timing bug in ensure_engine_loaded\n\n When two ensure_engine_loaded() calls were done in parallel there was a\n possibility that a crypto lib function was called by both instead of just one\n of them which resulted in an error. This is solved by moving the\n implementation from erlang down into a NIF function that uses a mutex to\n protect the sensitive part.\n\n Own Id: OTP-17858 Aux Id: ERIERL-728","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 5.0.6 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-5-0-6"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- The crypto app in OTP can since OTP-24.2 be compiled, linked and used with the\n new OpenSSL 3.0 cryptolib.\n\n The crypto app has 3.0 support has been improved, but is still \\*\\*not\n recommended\\*\\* for other usages than experiments and alpha testing. There are\n not yet any guaranties that it works, not even together with other OTP\n applications like for example SSL and SSH, although there are no known errors.\n\n Since the previous release, OTP-24.2, the following improvements have been\n done:\n\n \\- It has been tested during nearly every nightly test on the OTP lab\n\n \\- The hash algorithms `md4` and `ripemd160` have been enabled with OpenSSL\n 3.0.\n\n \\- The ciphers `blowfish_cbc`, `blowfish_ecb`, `des_cbc`, `des_cfb`,\n `des_ecb`, `rc2_cbc` and `rc4` have been enabled with OpenSSL 3.0.\n\n Disabled or unsupported with OpenSSL 3.0 are still:\n\n \\- ENGINE support\n\n \\- FIPS mode\n\n \\- Other providers than the built-in ones\n\n \\- Compiling and linking with OpenSSL 3.0 cryptolib in compatibility modes\n (for example to behave as 1.1.1)\n\n and, the ciphers `blowfish_cfb64` and `blowfish_ofb64` are not supported and\n will not be either.\n\n Deprecated functions in the OpenSSL 3.0 cryptolib must not be disabled as\n OTP/crypto still uses some of the deprecated API functions. The gcc flag\n `-Wno-deprecated-declarations` is set to prevent deprecation warnings to be\n printed when compiling.\n\n Own Id: OTP-17812 Aux Id: OTP-16646, OTP-16282\n\n- Crypto is adapted to LibreSSL 3.5.0 on OpenBSD.\n\n Own Id: OTP-17941 Aux Id: OTP-17942\n\n- New configure option ( `--disable-otp-test-engine`) to prohibit the build of\n the OTP test engine used in some test suites.\n\n The reason is that the test engine could be hard to compile on for instance\n LibreSSL 3.5.0. For that particular cryptolib version (or higher), this\n configure option is set automatically.\n\n Own Id: OTP-17942 Aux Id: OTP-17941","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 5.0.5 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-5-0-5"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Fixed the C-warning \"implicit declaration of function 'OpenSSL_version_num'\"\n if compiling with an early LibreSSL version.\n\n Own Id: OTP-17637\n\n- FIPS availability was not checked correctly for AEAD ciphers.\n\n Own Id: OTP-17740\n\n- Fixed that cipher aliases (like aes_cbc etc) could be present even if the\n aliased cipher(s) (like aes_128_cbc, aes_256_cbc,... etc) was missing.\n\n Own Id: OTP-17741","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- The crypto app in OTP can now be compiled, linked and used with the new\n OpenSSL 3.0 cryptolib.\n\n It has not yet been extensively tested and is in this release \\*\\*not\n recommended\\*\\* for other usages than experiments and alpha testing. There are\n not yet any guaranties that it works, not even together with other OTP\n applications like for example SSL and SSH, although there are no known errors.\n\n Compiling and linking with OpenSSL 3.0 cryptolib in compatibility modes (for\n example to behave as 1.1.1) are not tested. It is not tested with external\n providers.\n\n The support for FIPS mode does not yet work, and is disabled when compiled\n with OpenSSL 3.0.\n\n Deprecated functions in the OpenSSL 3.0 cryptolib must not be disabled as\n OTP/crypto still uses some of the deprecated API functions. The gcc flag\n `-Wno-deprecated-declarations` is set to prevent deprecation warnings to be\n printed when compiling.\n\n The hash algorithms `md4` and `ripemd160` are disabled temporarily when\n compiled with OpenSSL 3.0.\n\n The ciphers `blowfish_cbc`, `blowfish_cfb64`, `blowfish_ecb`,\n `blowfish_ofb64`, `des_cbc`, `des_cfb`, `des_ecb`, `rc2_cbc` and `rc4` are\n disabled temporarily when compiled with OpenSSL 3.0.\n\n Own Id: OTP-16646 Aux Id: OTP-16282\n\n- The error handling in crypto is partly refactored using the new error\n reporting support. Errors earlier propagated like exceptions are still so, but\n when the failing function is called from the terminal - for example during\n failure hunting - a more descriptive text is produced.\n\n Own Id: OTP-17241\n\n- A new function `crypto:info/0` which presents some data about the compilation\n and linkage of the crypto nif is added.\n\n Own Id: OTP-17603\n\n- Added the `pbkdf2_hmac/5` function to the crypto module.\n\n It calls the `PKCS5_PBKDF2_HMAC` function which implements PBKD2 with HMAC in\n an efficient way.\n\n Own Id: OTP-17808 Aux Id: PR-5421","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 5.0.4 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-5-0-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Fixed minor memory leak at `crypto` module purge.\n\n Own Id: OTP-17668 Aux Id: PR-5245\n\n- Fix possible inconsistency in fips mode when linking with some cryptolibs.\n\n Own Id: OTP-17672","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 5.0.3 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-5-0-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Fix bug in `crypto:ensure_engine_unloaded`. Also fixed minor memory leak\n related to engine unloading.\n\n Own Id: OTP-17593 Aux Id: ERIERL-679\n\n- Fixes that FIPS enable and disable (or vice versa) on Windows sometimes leads\n to core dump at the time of process exit.\n\n Own Id: OTP-17618 Aux Id: PR-5126, GH-4920","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Disable fips if cryptolib < 1.0.1 and OTP/crypto is configured with\n --enable-fips\n\n If not, there could be compiling or loading problems with antique OpenSSL\n versions.\n\n Own Id: OTP-17389","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 5.0.2 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-5-0-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- EC keys are now zero-padded to the expected length if needed.\n\n Own Id: OTP-17442 Aux Id: GH-4861","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 5.0.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-5-0-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Removed a risk for coredump.\n\n Own Id: OTP-17391 Aux Id: GH-4810\n\n- Fixed and documented the `DED_LDFLAGS_CONFTEST` configuration variable in\n `$ERL_TOP/HOWTO/INSTALL.md`.\n\n Own Id: OTP-17419 Aux Id: GH-4821\n\n- Commit of generated `configure` script.\n\n Own Id: OTP-17420 Aux Id: OTP-17398, GH-4821","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 5.0 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-5-0"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Add `/usr/local/opt/openssl` to the openssl configure search path. This path\n is where some tools on OS X place openssl.\n\n Own Id: OTP-16882\n\n- Fix compiler warnings produced by the clang compiler.\n\n Own Id: OTP-17105 Aux Id: PR-2872\n\n- The `configure` scripts in `crypto` and `erts` now fail if a requested feature\n cannot be enabled.\n\n Large parts of the `configure` script of `crypto` have been rewritten with\n various improvements and bug fixes. It is now better at finding usable OpenSSL\n libraries, but will in the following cases fail to detect OpenSSL libraries\n where it previously sometimes detected the libraries by chance:\n\n - OpenSSL installations with `include` directory and `lib` directory parts\n installed in different base directories. In order to detect such\n installations after this change, the user must explicitly specify the\n locations using the\n [`--with-ssl= `](`e:system:install.md#advanced-configuration-and-build-of-erlang-otp_configuring`)\n and the\n [`--with-ssl-incl= `](`e:system:install.md#advanced-configuration-and-build-of-erlang-otp_configuring`)\n `configure` command line arguments.\n - When building with old `gcc` compilers or other compilers on Debian\n derivatives with multiarch directories under the `lib` directory. In order\n to detect such installations after this change, the user must explicitly\n specify the multiarch directory name using the\n [`--with-ssl-lib-subdir=lib/ `](`e:system:install.md#advanced-configuration-and-build-of-erlang-otp_configuring`)\n `configure` command line argument.\n\n Own Id: OTP-17254 Aux Id: ERIERL-618, GH-4230\n\n- The value 'none' was missing in the specs of crypto:sign/4 and\n crypto:verify/6.\n\n Own Id: OTP-17312 Aux Id: PR-4723","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- The functions and cipher names that were deprecated in OTP-23.0 are now\n removed.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-16656\n\n- Removed installed directory priv/obj/ containing superfluous object files.\n\n Own Id: OTP-17001 Aux Id: PR-2852\n\n- TLS connections now support EdDSA certificates.\n\n Own Id: OTP-17142 Aux Id: PR-4756, GH-4637, GH-4650\n\n- Add prop_aead attribute to map from crypto:cipher_info/1.\n\n Own Id: OTP-17313 Aux Id: PR-4686","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 4.9.0.4 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-9-0-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Changed the behaviour of the engine load/unload functions\n\n The engine load/unload functions have got changed semantics to get a more\n consistent behaviour and work correct when variables are garbage collected.\n\n The load functions now don't register the methods for the engine to replace.\n That will now be handled with the new functions\n engine_register/engine_unregister if needed.\n\n Some functions functions are removed from the documentation and therefor the\n API, but they are left in the code for compatibility.\n\n - engine_load/4: is now the same as engine_load/3\n - engine_unload/2: is now the same as engine_unload/1\n - ensure_engine_loaded/3: is now the same as ensure_engine_loaded/2\n - ensure_engine_unloaded/1, ensure_engine_unloaded/2: is now the same as\n engine_unload/1\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18172 Aux Id: ERIERL-826","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 4.9.0.3 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-9-0-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Fix timing bug in ensure_engine_loaded\n\n When two ensure_engine_loaded() calls were done in parallel there was a\n possibility that a crypto lib function was called by both instead of just one\n of them which resulted in an error. This is solved by moving the\n implementation from erlang down into a NIF function that uses a mutex to\n protect the sensitive part.\n\n Own Id: OTP-17858 Aux Id: ERIERL-728\n\n- Remove all references correctly in the garbage collection if an engine handle\n was not explicit unloaded.\n\n Own Id: OTP-18152","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 4.9.0.2 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-9-0-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- EC keys are now zero-padded to the expected length if needed.\n\n Own Id: OTP-17442 Aux Id: GH-4861","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 4.9.0.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-9-0-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Removed a risk for coredump.\n\n Own Id: OTP-17391 Aux Id: GH-4810\n\n- Commit of generated `configure` script.\n\n Own Id: OTP-17420 Aux Id: OTP-17398, GH-4821","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 4.9 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-9"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Fix minor memory leaks in crypto ENGINE and robustify the code.\n\n Own Id: OTP-17212\n\n- The otp_test_engine no longer fails if NO_EC\\* is set in the OpenSSL\n configuration.\n\n Own Id: OTP-17256 Aux Id: PR-4580, GH-4573","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Various address sanitizer support.\n\n Own Id: OTP-16959 Aux Id: PR-2965\n\n- EVP is now disabled for OpenSSL cryptolib versions up to and including 1.0.2\n\n Own Id: OTP-17116 Aux Id: PR-2972\n\n- Warning for unused C function removed\n\n Own Id: OTP-17145 Aux Id: OTP-17105, PR-2872","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 4.8.3 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-8-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Adding missing flag in BN-calls in SRP.\n\n Own Id: OTP-17107","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 4.8.2 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-8-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Fixed usage of `AC_CONFIG_AUX_DIRS()` macros in configure script sources.\n\n Own Id: OTP-17093 Aux Id: ERL-1447, PR-2948","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 4.8.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-8-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Build the supported curves cache in the NIF when crypto is loaded, no matter\n how it is loaded.\n\n This prevents a possible problem with different processes starting the crypto\n application concurrently.\n\n Own Id: OTP-16819 Aux Id: PR-2720\n\n- It is now possible to build with crypto and openssl gprof-enabled and\n statically link them into the VM.\n\n Own Id: OTP-17029","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Fixed performance loss in HMAC when using older OpenSSL due to mutex issues.\n\n A workaround is implemented to allow fallback from using the EVP API for HMAC\n operations. On some architectures this may improve the performance, especially\n with old OpenSSL versions. This fallback to low-level functions is always\n enabled for openssl versions before 1.0.2.\n\n Own Id: OTP-17025 Aux Id: ERL-1400, PR-2877","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 4.8 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-8"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Fix type spec bug in crypto for crypto_init and crypto:one_time\n\n Own Id: OTP-16658 Aux Id: OTP-15884, ERL-1257\n\n- The deprecation message for crypto:rand_uniform/2 indicated a non-existent\n function. The correct one (rand:uniform/1) is now suggested.\n\n Own Id: OTP-16846 Aux Id: PR-2741","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Implemented a workaround to allow fallback from using the EVP API for\n Diffie-Hellman key generation\n\n Own Id: OTP-16771 Aux Id: ERIERL-509\n\n- The internal Diffie-Hellman high level API for key generation was slow in old\n and by OpenSSL now unsupported cryptolib versions (1.0.1 and earlier).\n\n If such a cryptolib is used anyhow, the low-level API is used internally in\n the crypto application.\n\n Own Id: OTP-16774","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 4.7 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-7"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Crypto reported unsupported elliptic curves as supported on e.g Fedora\n distros.\n\n Own Id: OTP-16579 Aux Id: ERL-825","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Support for ed25519 and ed448 added to `crypto:generate_key`.\n\n Own Id: OTP-15967 Aux Id: PR-2329\n\n- The [new crypto functions api](new_api.md#the-new-api) (crypto_init,\n crypto_update and crypto_one_time) has been updated.\n\n There is now a function [`crypto_final/1`](`crypto:crypto_final/1`) and a\n possibility to set options in [`crypto_init/3`](`crypto:crypto_init/3`) and\n [`crypto_init/4`](`crypto:crypto_init/4`). See the manual for details.\n\n Own Id: OTP-16160\n\n- As [announced](notes.md#crypto-4-5) in OTP 22.0, a New API was introduced in\n CRYPTO. See the [_New and Old API_](new_api.md) chapter in the CRYPTO User's\n Guide for more information and suggested replacement functions.\n\n [The Old API](new_api.md#the-old-api) is now deprecated in OTP-23.0 and will\n be removed in OTP-24.0.\n\n This deprecation includes cipher names. See the section\n [Retired cipher names](new_api.md#retired-cipher-names) in the crypto User's\n Guide, chapter [The Old API](new_api.md#the-old-api).\n\n Own Id: OTP-16232\n\n- Fix C-compilation without deprecated OpenSSL cryptolib APIs\n\n Own Id: OTP-16369 Aux Id: PR-2474\n\n- Refactored the internal handling of deprecated and removed functions.\n\n Own Id: OTP-16469\n\n- Added missing 'eddh' to [crypto:supports(public_keys)](`crypto:supports/1`).\n\n Own Id: OTP-16583","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 4.6.5.4 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-6-5-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- EC keys are now zero-padded to the expected length if needed.\n\n Own Id: OTP-17442 Aux Id: GH-4861","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 4.6.5.3 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-6-5-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Removed a risk for coredump.\n\n Own Id: OTP-17391 Aux Id: GH-4810\n\n- Commit of generated `configure` script.\n\n Own Id: OTP-17420 Aux Id: OTP-17398, GH-4821","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 4.6.5.2 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-6-5-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Adding missing flag in BN-calls in SRP.\n\n Own Id: OTP-17107","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 4.6.5.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-6-5-1"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Implemented a workaround to allow fallback from using the EVP API for\n Diffie-Hellman key generation\n\n Own Id: OTP-16771 Aux Id: ERIERL-509","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 4.6.5 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-6-5"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Fixed potential memory leaks involving calls to the crypto ng_api.\n\n Own Id: OTP-16428 Aux Id: PR-2511","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 4.6.4 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-6-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Constant time comparisons added.\n\n Own Id: OTP-16376","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 4.6.3 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-6-3"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- The ciphers aes_cfb8 and aes_cfb128 are now using the EVP interface. The\n supported key lengths are 128, 192 and 256 bits.\n\n Own Id: OTP-16133 Aux Id: PR-2407\n\n- The ciphers aes_cfb8 and aes_cfb128 are now available in FIPS enabled mode.\n\n Own Id: OTP-16134 Aux Id: PR-2407","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 4.6.2 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-6-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- The AEAD tag was not previously checked on decrypt with chacha20_poly1305\n\n Own Id: OTP-16242 Aux Id: ERL-1078","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 4.6.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-6-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- FIxed a bug if the erlang emulator was linked with a very old cryptolib\n version (1.0.1 or earlier).\n\n The bug now fixed could have triggered a core dump if an unknown cipher name\n was used in crypto functions.\n\n Own Id: OTP-16202","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 4.6 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-6"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- The implementation of `crypto_one_time/4` is adjusted to match the type\n specification. The spec and the black-box behaviour of the function are\n unchanged.\n\n Some details: Both the spec and the implementation were correct seen\n separately. But with both of them combined simultaneously with\n `crypto_one_time/5` which was called by the implementation of\n `crypto_one_time/4`, an (obvious) error was detected by a Dialyzer with more\n thorough checking than usual.\n\n Own Id: OTP-15884 Aux Id: ERL-974\n\n- When using crypto with FIPS mode enabled, the digests were not correctly\n handled.\n\n Own Id: OTP-15911\n\n- A memory leak in error handling code in `ng_crypto_init_nif` is fixed.\n\n Own Id: OTP-15924\n\n- Fixed the broken static build of the crypto nifs\n\n Own Id: OTP-15928 Aux Id: PR-2296","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- The Message Authentication Codes (MAC) CMAC, HMAC and Poly1305 are unified\n into common functions in the New Crypto API. See the manual for CRYPTO.\n\n Own Id: OTP-13872","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 4.5.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-5-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- The cipher aes-ctr was disabled by mistake in crypto:supports for cryptolibs\n before 1.0.1. It worked however in the encrypt and decrypt functions.\n\n Own Id: OTP-15829","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 4.5 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-5"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Fixed a bug in error return for `crypto:poly1305/2`. It returned the atom\n `notsup` instead of the exception `notsup`.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15677\n\n- The cipher chacha20 was introduced in OpenSSL 1.1.0. However, it could in a\n very odd situation, fail for versions less than OpenSSL 1.1.0d. It is\n therefore disabled for those versions.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15678","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- A new `rand` module algorithm, `exro928ss` (Xoroshiro928\\*\\*), has been\n implemented. It has got a really long period and good statistical quality for\n all output bits, while still being only about 50% slower than the default\n algorithm.\n\n The same generator is also used as a long period counter in a new `crypto`\n plugin for the `rand` module, algorithm `crypto_aes`. This plugin uses AES-256\n to scramble the counter which buries any detectable statistical artifacts.\n Scrambling is done in chunks which are cached to get good amortized speed\n (about half of the default algorithm).\n\n Own Id: OTP-14461 Aux Id: PR-1857\n\n- Crypto's single C-file is split into multiple files. The different coding\n styles in the different parts are unified into a single style.\n\n Own Id: OTP-14732 Aux Id: PR-2068, PR-2095\n\n- Build configuration of the `crypto` application has been moved from the `erts`\n application into the `crypto` application.\n\n Own Id: OTP-15129\n\n- Adds two hash functions `blake2b` and `blake2s` (64 bit hash and 32 bit hash\n respectively). These are modern and standard hash functions used in\n blockchains and encrypted communication protocols. The hash functions are\n available in OpenSSL since version 1.1.1.\n\n Own Id: OTP-15564 Aux Id: PR-2129\n\n- A new API is implemented in crypto. See the CRYPTO user's guide, chapter _New\n and Old API_ for more information.\n\n The old api with the `crypto:block_*` and `crypto:stream_*` interfaces are\n kept for compatibility, but implemented with the new api. Please note that\n since the error checking is more thorough, there _might_ be arguments with for\n example faulty lengths that are no longer accepted.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15644 Aux Id: OTP-14732 , OTP-15451, PR-1857 , PR-2068, PR-2095\n\n- The new hash_info/1 and cipher_info/1 functions returns maps with information\n about the hash or cipher in the argument.\n\n Own Id: OTP-15655 Aux Id: PR-2173, ERL-864, PR-2186\n\n- Obey additional OpenSSL configure flags when compiling the C-part of the\n CRYPTO application: `no-bf`, `no-blake2`, `no-chacha`, `no-cmac`, `no-dh`,\n `no-dsa`, `no-md4`, `no-poly1305`, `no-rc2`, `no-rc4` and `no-rmd160`.\n\n Own Id: OTP-15683\n\n- A new function `crypto:supports/1` is introduced. The single argument takes an\n atom as argument: `hashes`, `public_keys`, `ciphers`, `macs`, `curves` or\n `rsa_opts`. The return value is a list of supported algorithms.\n\n The difference with the existing `crypto:supports/0` is, apart from the\n argument and the return value, that the old function reports what is supported\n by the old api, and the new function reports algorithms in the new api.\n\n Own Id: OTP-15771","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 4.4.2.3 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-4-2-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Adding missing flag in BN-calls in SRP.\n\n Own Id: OTP-17107","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 4.4.2.2 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-4-2-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Constant time comparisons added.\n\n Own Id: OTP-16376","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 4.4.2.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-4-2-1"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- The ciphers aes_cfb8 and aes_cfb128 are now using the EVP interface. The\n supported key lengths are 128, 192 and 256 bits.\n\n Own Id: OTP-16133 Aux Id: PR-2407\n\n- The ciphers aes_cfb8 and aes_cfb128 are now available in FIPS enabled mode.\n\n Own Id: OTP-16134 Aux Id: PR-2407","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 4.4.2 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-4-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Fixed build link error on Windows. Unresolved symbol 'bcmp'.\n\n Own Id: OTP-15750 Aux Id: ERL-905","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 4.4.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-4-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Fixes a bug that caused `crypto:sign` and `crypto:verify` to return the error\n message `badarg` instead of `notsup` in one case. That case was when signing\n or verifying with eddsa keys (that is, ed15519 or ed448), but only when FIPS\n was supported and enabled.\n\n Own Id: OTP-15634","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Added a crypto benchmark test suite.\n\n Own Id: OTP-15447","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 4.4 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Updated the RSA options part in the crypto application's C-code, documentation\n and tests.\n\n Own Id: OTP-15302","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Added ed25519 and ed448 sign/verify.\n\n Requires OpenSSL 1.1.1 or higher as cryptolib under the OTP application\n `crypto`.\n\n Own Id: OTP-15419 Aux Id: OTP-15094\n\n- Fixed valgrind warnings.\n\n Own Id: OTP-15467","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 4.3.3 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-3-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- The RSA options `rsa_mgf1_md`, `rsa_oaep_md`, and `rsa_oaep_label` were always\n disabled. They will now be enabled when a suitable cryptolib is used.\n\n They are still experimental and may change without prior notice.\n\n Own Id: OTP-15212 Aux Id: ERL-675, PR1899, PR838\n\n- The ciphers `aes_ige256` and `blowfish_cbc` had naming issues in\n `crypto:next_iv/2`.\n\n Own Id: OTP-15283\n\n- the `RSA_SSLV23_PADDING` is disabled if LibreSSL is used as cryptlib. This is\n due to compilation problems.\n\n This will be investigated further in the future.\n\n Own Id: OTP-15303","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- The supported named elliptic curves are now reported in `crypto:supports/0` in\n a new entry tagged by `'curves'`.\n\n The function `crypto:ec_curves/0` is kept for compatibility.\n\n Own Id: OTP-14717 Aux Id: OTP-15244\n\n- The typing in the CRYPTO and PUBLIC_KEY applications are reworked and a few\n mistakes are corrected.\n\n The documentation is now generated from the typing and some clarifications are\n made.\n\n A new chapter on Algorithm Details such as key sizes and availability is added\n to the CRYPTO User's Guide.\n\n Own Id: OTP-15134\n\n- Support for SHA3 both as a separate hash and in HMAC is now available if\n OpenSSL 1.1.1 or higher is used as cryptolib.\n\n Available lengths are reported in the `'hashs'` entry in `crypto:supports/0`\n as `sha3_*`.\n\n Own Id: OTP-15153\n\n- The mac algorithm `poly1305` and the cipher algorithm `chacha20` are now\n supported if OpenSSL 1.1.1 or higher is used as cryptolib.\n\n Own Id: OTP-15164 Aux Id: OTP-15209\n\n- The key exchange Edward curves `x25519` and `x448` are now supported if\n OpenSSL 1.1.1 or higher is used as cryptolib.\n\n Own Id: OTP-15240 Aux Id: OTP-15133\n\n- The supported RSA options for sign/verify and encrypt/decrypt are now reported\n in `crypto:supports/0` in a new entry tagged by '`rsa_opts`'.\n\n The exakt set is still experimental and may change without prior notice.\n\n Own Id: OTP-15260\n\n- The cipher `aes_ccm` is added.\n\n Own Id: OTP-15286","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 4.3.2 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-3-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Update the crypto engine functions to handle multiple loads of an engine.\n\n `engine_load/3/4` is updated so it doesn't add the engine ID to OpenSSLs\n internal list of engines which makes it possible to run the engine_load more\n than once if it doesn't contain global data.\n\n Added `ensure_engine_loaded/2/3` which guarantees that the engine just is\n loaded once and the following calls just returns a reference to it. This is\n done by add the ID to the internal OpenSSL list and check if it is already\n registered when the function is called.\n\n Added `ensure_engine_unloaded/1/2` to unload engines loaded with\n ensure_engine_loaded.\n\n Then some more utility functions are added.\n\n `engine_add/1`, adds the engine to OpenSSL internal list\n\n `engine_remove/1`, remove the engine from OpenSSL internal list\n\n `engine_get_id/1`, fetch the engines id\n\n `engine_get_name/1`, fetch the engine name\n\n Own Id: OTP-15233","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 4.3.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-3-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Fixed a node crash in `crypto:compute_key(ecdh, ...)` when passing a wrongly\n typed Others argument.\n\n Own Id: OTP-15194 Aux Id: ERL-673","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 4.3 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Removed two undocumented and erroneous functions\n (`crypto:dh_generate_parameters/2` and `crypto:dh_check/1`).\n\n Own Id: OTP-14956 Aux Id: ERL-579\n\n- Fixed bug causing VM crash if doing runtime upgrade of a crypto module built\n against OpenSSL older than 0.9.8h. Bug exists since OTP-20.2.\n\n Own Id: OTP-15088","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- A new `rand` plugin algorithm has been implemented in `crypto`, that is:\n `crypto_cache`. It uses strong random bytes as randomness source and caches\n them to get good speed. See `crypto:rand_seed_alg/1`.\n\n Own Id: OTP-13370 Aux Id: PR-1573\n\n- Diffie-Hellman key functions are re-written with the EVP_PKEY api.\n\n Own Id: OTP-14864","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 4.2.2.4 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-2-2-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Constant time comparisons added.\n\n Own Id: OTP-16376","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 4.2.2.3 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-2-2-3"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- The ciphers aes_cfb8 and aes_cfb128 are now using the EVP interface. The\n supported key lengths are 128, 192 and 256 bits.\n\n Own Id: OTP-16133 Aux Id: PR-2407","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 4.2.2.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-2-2-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Fixed a node crash in `crypto:compute_key(ecdh, ...)` when passing a wrongly\n typed Others argument.\n\n Own Id: OTP-15194 Aux Id: ERL-673","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 4.2.2 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-2-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- If OPENSSL_NO_EC was set, the compilation of the crypto nifs failed.\n\n Own Id: OTP-15073\n\n- C-compile errors for LibreSSL 2.7.0 - 2.7.2 fixed\n\n Own Id: OTP-15074 Aux Id: ERL-618","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 4.2.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-2-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Fix build error caused by removed RSA padding functions in LibreSSL >= 2.6.1\n\n Own Id: OTP-14873","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 4.2 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- The compatibility function `void HMAC_CTX_free` in `crypto.c` erroneously\n tried to return a value.\n\n Own Id: OTP-14720","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Rewrite public and private key encode/decode with EVP api. New RSA padding\n options added. This is a modified half of PR-838.\n\n Own Id: OTP-14446\n\n- The crypto API is extended to use private/public keys stored in an Engine for\n sign/verify or encrypt/decrypt operations.\n\n The ssl application provides an API to use this new engine concept in TLS.\n\n Own Id: OTP-14448\n\n- Add support to plug in alternative implementations for some or all of the\n cryptographic operations supported by the OpenSSL Engine API. When configured\n appropriately, OpenSSL calls the engine's implementation of these operations\n instead of its own.\n\n Own Id: OTP-14567\n\n- Replaced a call of the OpenSSL deprecated function `DH_generate_parameters` in\n `crypto.c`.\n\n Own Id: OTP-14639\n\n- Documentation added about how to use keys stored in an Engine.\n\n Own Id: OTP-14735 Aux Id: OTP-14448\n\n- Add engine\\_ ctrl_cmd_string/3,4 the OpenSSL Engine support in crypto.\n\n Own Id: OTP-14801","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 4.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- On macOS, `crypto` would crash if `observer` had been started before `crypto`.\n On the beta for macOS 10.13 (High Sierra), `crypto` would crash. Both of those\n bugs have been fixed.\n\n Own Id: OTP-14499 Aux Id: ERL-251 ERL-439","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Extend crypto:sign, crypto:verify, public_key:sign and public_key:verify with:\n\n \\* support for RSASSA-PS padding for signatures and for saltlength setting \n \\* X9.31 RSA padding. \n \\* sha, sha224, sha256, sha384, and sha512 for dss signatures as mentioned in\n NIST SP 800-57 Part 1. \n \\* ripemd160 to be used for rsa signatures.\n\n This is a manual merge of half of the pull request 838 by potatosalad from\n Sept 2015.\n\n Own Id: OTP-13704 Aux Id: PR838\n\n- A new tuple in `crypto:supports/0` reports supported MAC algorithms.\n\n Own Id: OTP-14504","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 4.0 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-4-0"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- LibreSSL can now be used by the modernized crypto app.\n\n Own Id: OTP-14247\n\n- Add compile option `-compile(no_native)` in modules with `on_load` directive\n which is not yet supported by HiPE.\n\n Own Id: OTP-14316 Aux Id: PR-1390\n\n- Fix a bug in aes cfb128 function introduced by the bug fix in GitHub pull\n request [\\#1393](https://github.com/erlang/otp/pull/1393).\n\n Own Id: OTP-14435 Aux Id: PR-1462, PR-1393, OTP-14313","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Add basic support for CMAC\n\n Own Id: OTP-13779 Aux Id: ERL-82 PR-1138\n\n- Removed functions deprecated in crypto-3.0 first released in OTP-R16B01\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-13873\n\n- The `crypto` application now supports OpenSSL 1.1.\n\n Own Id: OTP-13900\n\n- Allow Erlang/OTP to use OpenSSL in FIPS-140 mode, in order to satisfy specific\n security requirements (mostly by different parts of the US federal\n government).\n\n See the new crypto users guide \"FIPS mode\" chapter about building and using\n the FIPS support which is disabled by default.\n\n (Thanks to dszoboszlay and legoscia)\n\n Own Id: OTP-13921 Aux Id: PR-1180\n\n- Crypto chacha20-poly1305 as in RFC 7539 enabled for OpenSSL >= 1.1.\n\n Thanks to mururu.\n\n Own Id: OTP-14092 Aux Id: PR-1291\n\n- RSA key generation added to `crypto:generate_key/2`. Thanks to wiml.\n\n An interface is also added to `public_key:generate_key/1`.\n\n Own Id: OTP-14140 Aux Id: ERL-165, PR-1299\n\n- Raised minimum requirement for OpenSSL version to OpenSSL-0.9.8.c although we\n recommend a much higher version, that is a version that is still maintained\n officially by the OpenSSL project. Note that using such an old version may\n restrict the crypto algorithms supported.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-14171\n\n- Deprecate crypto:rand_uniform/2 as it is not cryptographically strong\n\n Own Id: OTP-14274\n\n- The Crypto application now supports generation of cryptographically strong\n random numbers (floats < 1.0 and integer arbitrary ranges) as a plugin to the\n 'rand' module.\n\n Own Id: OTP-14317 Aux Id: PR-1372\n\n- This replaces the hard coded test values for AES, CMAC and GCM ciphers with\n the full validation set from NIST's CAVP program.\n\n Own Id: OTP-14436 Aux Id: PR-1396","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 3.7.4 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-3-7-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Fix a bug with AES CFB 128 for 192 and 256 bit keys. Thanks to kellymclaughlin\n \\!\n\n Own Id: OTP-14313 Aux Id: PR-1393","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 3.7.3 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-3-7-3"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- The implementation of the key exchange algorithms\n diffie-hellman-group-exchange-sha\\* are optimized, up to a factor of 11 for\n the slowest ( = biggest and safest) group size.\n\n Own Id: OTP-14169 Aux Id: seq-13261","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 3.7.2 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-3-7-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- The crypto application has been fixed to not use RC2 against OpenSSL built\n with RC2 disabled.\n\n Own Id: OTP-13895 Aux Id: PR-1163\n\n- The crypto application has been fixed to not use RC4 against OpenSSL built\n with RC4 disabled.\n\n Own Id: OTP-13896 Aux Id: PR-1169","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- To ease troubleshooting, `erlang:load_nif/2` now includes the return value\n from a failed call to load/reload/upgrade in the text part of the error tuple.\n The `crypto` NIF makes use of this feature by returning the source line\n where/if the initialization fails.\n\n Own Id: OTP-13951","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 3.7.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-3-7-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Crypto has been fixed to work against OpenSSL versions with disabled DES\n ciphers. Correct spelling of cipher algorithm 'des3_cfb' has been introduced;\n the previous misspeling still works.\n\n Own Id: OTP-13783 Aux Id: ERL-203\n\n- The size of an internal array in crypto has been fixed to not segfault when\n having all possible ciphers. Bug fix by Duncan Overbruck.\n\n Own Id: OTP-13789 Aux Id: PR-1140","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 3.7 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-3-7"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Refactor `crypto` to use the EVP interface of OpenSSL, which is the\n recommended interface that also enables access to hardware acceleration for\n some operations.\n\n Own Id: OTP-12217\n\n- Add support for 192-bit keys for the `aes_cbc` cipher.\n\n Own Id: OTP-13206 Aux Id: pr 832\n\n- Add support for 192-bit keys for `aes_ecb`.\n\n Own Id: OTP-13207 Aux Id: pr829\n\n- Deprecate the function `crypto:rand_bytes` and make sure that\n `crypto:strong_rand_bytes` is used in all places that are cryptographically\n significant.\n\n Own Id: OTP-13214\n\n- Enable AES-GCM encryption/decryption to change the tag length between 1 to 16\n bytes.\n\n Own Id: OTP-13483 Aux Id: PR-998","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 3.6.3 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-3-6-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Fix bug for `aes_ecb` block crypto when data is larger than 16 bytes.\n\n Own Id: OTP-13249\n\n- Improve portability of ECC tests in Crypto and SSL for \"exotic\" OpenSSL\n versions.\n\n Own Id: OTP-13311","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 3.6.2 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-3-6-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Small documentation fixes\n\n Own Id: OTP-13017","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 3.6.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-3-6-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Make `crypto:ec_curves/0` return empty list if elliptic curve is not supported\n at all.\n\n Own Id: OTP-12944","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 3.6 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-3-6"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Enhance crypto:generate_key to calculate ECC public keys from private key.\n\n Own Id: OTP-12394\n\n- Fix bug in `crypto:generate_key` for `ecdh` that could cause VM crash for\n faulty input.\n\n Own Id: OTP-12733","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Use the EVP API for AES-CBC crypto to enables the use of hardware acceleration\n for AES-CBC crypto on newer Intel CPUs (AES-NI), among other platforms.\n\n Own Id: OTP-12380\n\n- Add AES ECB block encryption.\n\n Own Id: OTP-12403","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 3.5 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-3-5"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Extend block_encrypt/decrypt for aes_cfb8 and aes_cfb128 to accept keys of\n length 128, 192 and 256 bits. Before only 128 bit keys were accepted.\n\n Own Id: OTP-12467","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 3.4.2 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-3-4-2"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Add configure option --with-ssl-incl=PATH to support OpenSSL installations\n with headers and libraries at different places.\n\n Own Id: OTP-12215 Aux Id: seq12700\n\n- Add configure option --with-ssl-rpath to control which runtime library path to\n use for dynamic linkage toward OpenSSL.\n\n Own Id: OTP-12316 Aux Id: seq12753","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 3.4.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-3-4-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Make `crypto` verify major version number of OpenSSL header files and runtime\n library. Loading of `crypto` will fail if there is a version mismatch.\n\n Own Id: OTP-12146 Aux Id: seq12700","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 3.4 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-3-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Fix memory leak in `crypto:hmac_init/upgrade/final` functions for all data and\n in `crypto:hmac/3/4` for data larger than 20000 bytes. Bug exists since OTP\n 17.0.\n\n Own Id: OTP-11953\n\n- Fix memory leak in `crypto` for elliptic curve.\n\n Own Id: OTP-11999","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Add `aes_cfb8` cypher to `crypto:block_encrypt` and `block_decrypt`.\n\n Own Id: OTP-11911","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 3.3 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-3-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Fix memory leaks and invalid deallocations in `mod_pow`, `mod_exp` and\n `generate_key(srp,...)` when bad arguments are passed. (Thanks to Florian\n Zumbiehi)\n\n Own Id: OTP-11550\n\n- Correction of the word 'ChipherText' throughout the documentation (Thanks to\n Andrew Tunnell-Jones)\n\n Own Id: OTP-11609\n\n- Fix fatal bug when using a hmac context variable in more than one call to\n `hmac_update` or `hmac_final`. The reuse of hmac contexts has never worked as\n the underlying OpenSSL implementation does not support it. It is now\n documented as having undefined behaviour, but it does not crash or corrupt the\n VM anymore.\n\n Own Id: OTP-11724\n\n- Crypto handles out-of-memory with a controlled abort instead of\n crash/corruption. (Thanks to Florian Zumbiehi)\n\n Own Id: OTP-11725\n\n- Application upgrade (appup) files are corrected for the following\n applications:\n\n `asn1, common_test, compiler, crypto, debugger, dialyzer, edoc, eldap, erl_docgen, et, eunit, gs, hipe, inets, observer, odbc, os_mon, otp_mibs, parsetools, percept, public_key, reltool, runtime_tools, ssh, syntax_tools, test_server, tools, typer, webtool, wx, xmerl`\n\n A new test utility for testing appup files is added to test_server. This is\n now used by most applications in OTP.\n\n (Thanks to Tobias Schlager)\n\n Own Id: OTP-11744","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- By giving --enable-static-\\{nifs,drivers\\} to configure it is now possible to\n statically linking of nifs and drivers to the main Erlang VM binary. At the\n moment only the asn1 and crypto nifs of the Erlang/OTP nifs and drivers have\n been prepared to be statically linked. For more details see the Installation\n Guide in the System documentation.\n\n Own Id: OTP-11258\n\n- Add IGE mode for AES cipher in crypto (Thanks to Yura Beznos).\n\n Own Id: OTP-11522\n\n- Moved elliptic curve definition from the crypto NIF/OpenSSL into Erlang code,\n adds the RFC-5639 brainpool curves and makes TLS use them (RFC-7027).\n\n Thanks to Andreas Schultz\n\n Own Id: OTP-11578\n\n- Remove all obsolete application processes from crypto and make it into a pure\n library application.\n\n Own Id: OTP-11619","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 3.2 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-3-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Fix uninitialized pointers in crypto (Thanks to Anthony Ramine)\n\n Own Id: OTP-11510","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 3.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-3-1"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Refactor ecdsa cipher to simplify code and improve performance.\n\n Own Id: OTP-11320","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 3.0 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-3-0"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Integrate elliptic curve contribution from Andreas Schultz\n\n In order to be able to support elliptic curve cipher suites in SSL/TLS,\n additions to handle elliptic curve infrastructure has been added to public_key\n and crypto.\n\n This also has resulted in a rewrite of the crypto API to gain consistency and\n remove unnecessary overhead. All OTP applications using crypto has been\n updated to use the new API.\n\n Impact: Elliptic curve cryptography (ECC) offers equivalent security with\n smaller key sizes than other public key algorithms. Smaller key sizes result\n in savings for power, memory, bandwidth, and computational cost that make ECC\n especially attractive for constrained environments.\n\n Own Id: OTP-11009\n\n- Fixed a spelling mistake in crypto docs. Thanks to Klaus Trainer\n\n Own Id: OTP-11058","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Known Bugs and Problems - Crypto Release Notes","doc":"- Make the crypto functions interruptible by chunking input when it is very\n large and bumping reductions in the nifs.\n\n Not yet implemented for block_encrypt|decrypt/4\n\n Impact: Individual calls to crypto functions may take longer time but over all\n system performance should improve as crypto calls will not become throughput\n bottlenecks.\n\n Own Id: OTP-11142","ref":"notes.html#known-bugs-and-problems"},{"type":"extras","title":"Crypto 2.3 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-2-3"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Enable runtime upgrade of crypto including the OpenSSL library used by crypto.\n\n Own Id: OTP-10596\n\n- Improve documentation and tests for hmac functions in crypto. Thanks to Daniel\n White\n\n Own Id: OTP-10640\n\n- Added ripemd160 support to crypto. Thanks to Michael Loftis\n\n Own Id: OTP-10667","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 2.2 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-2-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Remove unnecessary dependency to libssl from crypto NIF library. This\n dependency was introduced by accident in R14B04.\n\n Own Id: OTP-10064","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Add crypto and public_key support for the hash functions SHA224, SHA256,\n SHA384 and SHA512 and also hmac and rsa_sign/verify support using these hash\n functions. Thanks to Andreas Schultz for making a prototype.\n\n Own Id: OTP-9908\n\n- Optimize RSA private key handling in `crypto` and `public_key`.\n\n Own Id: OTP-10065\n\n- Make `crypto:aes_cfb_128_encrypt` and `crypto:aes_cfb_128_decrypt` handle data\n and cipher with arbitrary length. (Thanks to Stefan Zegenhagen)\n\n Own Id: OTP-10136","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 2.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-2-1"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- public_key, ssl and crypto now supports PKCS-8\n\n Own Id: OTP-9312\n\n- Erlang/OTP can now be built using parallel make if you limit the number of\n jobs, for instance using '`make -j6`' or '`make -j10`'. '`make -j`' does not\n work at the moment because of some missing dependencies.\n\n Own Id: OTP-9451\n\n- Add DES and Triple DES cipher feedback (CFB) mode functions to `crypto`.\n (Thanks to Paul Guyot)\n\n Own Id: OTP-9640\n\n- Add sha256, sha384 and sha512 support for `crypto:rsa_verify`.\n\n Own Id: OTP-9778","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 2.0.4 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-2-0-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- `crypto:rand_uniform` works correctly for negative integers. Fails with\n `badarg` exception for invalid ranges (when `Hi =< Lo`) instead of returning\n incorrect output.\n\n Own Id: OTP-9526\n\n- Fix win32 OpenSSL static linking (Thanks to Dave Cottlehuber)\n\n Own Id: OTP-9532","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 2.0.3 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-2-0-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Various small documentation fixes (Thanks to Bernard Duggan)\n\n Own Id: OTP-9172","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- New `crypto` support for streaming of AES CTR and HMAC. (Thanks to Travis\n Jensen)\n\n Own Id: OTP-9275\n\n- Due to standard library DLL mismatches between versions of OpenSSL and\n Erlang/OTP, OpenSSL is now linked statically to the crypto driver on Windows.\n This fixes problems starting crypto when running Erlang as a service on all\n Windows versions.\n\n Own Id: OTP-9280","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 2.0.2.2 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-2-0-2-2"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Strengthened random number generation. (Thanks to Geoff Cant)\n\n Own Id: OTP-9225","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 2.0.2.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-2-0-2-1"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Misc. Updates.\n\n Own Id: OTP-9132","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 2.0.2 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-2-0-2"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- AES CTR encryption support in `crypto`.\n\n Own Id: OTP-8752 Aux Id: seq11642","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 2.0.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-2-0-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Crypto dialyzer type error in md5_mac and sha_mac.\n\n Own Id: OTP-8718\n\n- RC4 stream cipher didn't work. This since the new NIF implementation of\n `crypto:rc4_encrypt_with_state/2` introduced in `crypto-2.0` didn't return an\n updated state. (Thanks to Paul Guyot)\n\n Own Id: OTP-8781\n\n- A number of memory leaks in the crypto NIF library have been fixed.\n\n Own Id: OTP-8810","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Added erlang:system_info(build_type) which makes it easier to chose drivers,\n NIF libraries, etc based on build type of the runtime system.\n\n The NIF library for crypto can now be built for valgrind and/or debug as\n separate NIF libraries that will be automatically loaded if the runtime system\n has been built with a matching build type.\n\n Own Id: OTP-8760","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 2.0 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-2-0"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- crypto application changed to use NIFs instead of driver.\n\n Own Id: OTP-8333\n\n- des_ecb_encrypt/2 and des_ecb_decrypt/2 has been added to the crypto module.\n The crypto:md4/1 function has been documented.\n\n Own Id: OTP-8551\n\n- The undocumented, unsupported, and deprecated function `lists:flat_length/1`\n has been removed.\n\n Own Id: OTP-8584\n\n- New variants of `crypto:dss_sign` and `crypto:dss_verify` with an extra\n argument to control how the digest is calculated.\n\n Own Id: OTP-8700","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 1.6.4 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-1-6-4"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Cross compilation improvements and other build system improvements.\n\n Most notable:\n\n - Lots of cross compilation improvements. The old cross compilation support\n was more or less non-existing as well as broken. Please, note that the cross\n compilation support should still be considered as experimental. Also note\n that old cross compilation configurations cannot be used without\n modifications. For more information on cross compiling Erlang/OTP see the\n `$ERL_TOP/INSTALL-CROSS.md` file.\n - Support for staged install using\n [DESTDIR](http://www.gnu.org/prep/standards/html_node/DESTDIR.html). The old\n broken `INSTALL_PREFIX` has also been fixed. For more information see the\n `$ERL_TOP/INSTALL.md` file.\n - Documentation of the `release` target of the top `Makefile`. For more\n information see the `$ERL_TOP/INSTALL.md` file.\n - `make install` now by default creates relative symbolic links instead of\n absolute ones. For more information see the `$ERL_TOP/INSTALL.md` file.\n - `$ERL_TOP/configure --help=recursive` now works and prints help for all\n applications with `configure` scripts.\n - Doing `make install`, or `make release` directly after `make all` no longer\n triggers miscellaneous rebuilds.\n - Existing bootstrap system is now used when doing `make install`, or\n `make release` without a preceding `make all`.\n - The `crypto` and `ssl` applications use the same runtime library path when\n dynamically linking against `libssl.so` and `libcrypto.so`. The runtime\n library search path has also been extended.\n - The `configure` scripts of `erl_interface` and `odbc` now search for thread\n libraries and thread library quirks the same way as ERTS do.\n - The `configure` script of the `odbc` application now also looks for odbc\n libraries in `lib64` and `lib/64` directories when building on a 64-bit\n system.\n - The `config.h.in` file in the `erl_interface` application is now\n automatically generated in instead of statically updated which reduces the\n risk of `configure` tests without any effect.\n\n (Thanks to Henrik Riomar for suggestions and testing)\n\n (Thanks to Winston Smith for the AVR32-Linux cross configuration and testing)\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8323\n\n- The crypto module now supports Blowfish in ECB, CBC and OFB modes. (Thanks to\n Paul Oliver.)\n\n Own Id: OTP-8331\n\n- The documentation is now possible to build in an open source environment after\n a number of bugs are fixed and some features are added in the documentation\n build process.\n\n \\- The arity calculation is updated.\n\n \\- The module prefix used in the function names for bif's are removed in the\n generated links so the links will look like\n \"http://www.erlang.org/doc/man/erlang.html#append_element-2\" instead of\n \"http://www.erlang.org/doc/man/erlang.html#erlang:append_element-2\".\n\n \\- Enhanced the menu positioning in the html documentation when a new page is\n loaded.\n\n \\- A number of corrections in the generation of man pages (thanks to Sergei\n Golovan)\n\n \\- The legal notice is taken from the xml book file so OTP's build process can\n be used for non OTP applications.\n\n Own Id: OTP-8343","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 1.6.3 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-1-6-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Suppressed false valgrind errors caused by libcrypto using uninitialized data\n as entropy.\n\n Own Id: OTP-8200","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- The documentation is now built with open source tools (xsltproc and fop) that\n exists on most platforms. One visible change is that the frames are removed.\n\n Own Id: OTP-8201\n\n- When the crypto application failed to load the OpenSSL/LibEAY shared object,\n error indication was sparse. Now a more specific error message is sent to the\n error logger.\n\n Own Id: OTP-8281","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 1.6.2 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-1-6-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Fixed emulator crash caused by crypto using an old openssl version that did\n not cope with large file descriptors.\n\n Own Id: OTP-8261 Aux Id: seq11434","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 1.6.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-1-6-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- `Makefile.in` has been updated to use the LDFLAGS environment variable (if\n set). (Thanks to Davide Pesavento.)\n\n Own Id: OTP-8157","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Support for Blowfish cfb64 added to `crypto`.\n\n Own Id: OTP-8096\n\n- New function `crypto:aes_cbc_ivec`\n\n Own Id: OTP-8141","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 1.6 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-1-6"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- The `dh_compute_key` sometimes returned a SharedSecret of incorrect size.\n\n Own Id: OTP-7674","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Optimization for drivers by creating small binaries direct on process heap.\n\n Own Id: OTP-7762","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 1.5.3 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-1-5-3"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Added new functions: dss_verify/3, rsa_verify/3, rsa_verify/4, dss_sign/2,\n rsa_sign/2, rsa_sign/3, rsa_public_encrypt, rsa_private_decrypt/3,\n rsa_private_encrypt/3, rsa_public_decrypt/3, dh_generate_key/1,\n dh_generate_key/2, dh_compute_key/3.\n\n Own Id: OTP-7545","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 1.5.2.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-1-5-2-1"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Minor performance optimization.\n\n Own Id: OTP-7521","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 1.5.2 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-1-5-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- ./configure has been improved to find 64-bit OpenSSL libraries.\n\n Own Id: OTP-7270","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- crypto and zlib drivers improved to allow concurrent smp access.\n\n Own Id: OTP-7262","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 1.5.1.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-1-5-1-1"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- The linked in driver for the crypto application is now linked statically\n against the OpenSSL libraries, to avoid installation and runtime problems in\n connection to the OpenSSL library locations.\n\n Own Id: OTP-6680\n\n- Minor Makefile changes.\n\n Own Id: OTP-6689","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 1.5 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-1-5"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- It is now explicitly checked at start-up that the crypto driver is properly\n loaded (Thanks to Claes Wikstrom).\n\n Own Id: OTP-6109","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 1.4 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-1-4"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- The previously undocumented and UNSUPPORTED `ssh` application has been updated\n and documented. This release of the `ssh` application is still considered to\n be a beta release and (if necessary) there could still be changes in its API\n before it reaches 1.0.\n\n Also, more cryptographic algorithms have been added to the `crypto`\n application.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-5631","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 1.3 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-1-3"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Added support for RFC 3826 - The Advanced Encryption Standard (AES) Cipher\n Algorithm in the SNMP User-based Security Model. \n Martin Björklund","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 1.2.3 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-1-2-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- Linked in drivers in the crypto, and asn1 applications are now compiled with\n the -D_THREAD_SAFE and -D_REENTRANT switches on unix when the emulator has\n thread support enabled.\n\n Linked in drivers on MacOSX are not compiled with the undocumented -lbundle1.o\n switch anymore. Thanks to Sean Hinde who sent us a patch.\n\n Linked in driver in crypto, and port programs in ssl, now compiles on OSF1.\n\n Minor makefile improvements in runtime_tools.\n\n Own Id: OTP-5346","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 1.2.2 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-1-2-2"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Corrected error handling. If the port to the driver that crypto uses is\n unexpectedly closed (which should not happen during normal operation of\n crypto), crypto will terminate immediately (rather than crashing the next time\n crypto is used). Also corrected build problems on Mac OS X.\n\n Own Id: OTP-5279","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 1.2.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-1-2-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- It was not possible in R9 to relink the crypto driver. The object file was\n missing as well as an example makefile. The crypto driver object file is now\n released with the application (installed in priv/obj). An example makefile has\n also been added to the priv/obj directory. The makefile serves as an example\n of how to relink the driver on Unix (crypto_drv.so) or Windows\n (crypto_drv.dll).\n\n Own Id: OTP-4828 Aux Id: seq8193","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 1.2 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-1-2"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- Previous versions of Crypto where delivered with statically linked binaries\n based on SSLeay. That is not longer the case. The current version of Crypto\n requires dynamically linked OpenSSL libraries that the user has to install.\n The library needed is `libcrypto.so` (Unix) or `libeay32.[lib|dll]` (Win32).\n For further details see the crypto(6) application manual page.\n- This version of Crypto uses the new DES interface of OpenSSL 0.9.7, which is\n not backward compatible with earlier versions of OpenSSL.\n- The functions `des_ede3_cbc_encrypt/5` and `des_ede3_cbc_decrypt/5` have been\n renamed to `des3_cbc_encrypt/5` and `des3_cbc_decrypt/5`, respectively. The\n old functions have been retained (they are deprecated and not listed in the\n crypto(3) manual page).","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Reported Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- The start of crypto failed on Windows, due to erroneous addition of a DES3\n algorithm.\n\n Own Id: OTP-4684 \n Aux Id: seq7864","ref":"notes.html#reported-fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 1.1.3 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-1-1-3"},{"type":"extras","title":"Reported Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- To obtain backward compatibility with the old SSLeay package, and with earlier\n versions of OpenSSL, the macro OPENSSL_DES_LIBDES_COMPATIBILITY has been added\n to `crypto_drv.c`. This is of importance only for the open source version of\n Crypto.","ref":"notes.html#reported-fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 1.1.2 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-1-1-2"},{"type":"extras","title":"Reported Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- In the manual page `m:crypto` the function names `md5_finish` and `sha_finish`\n have been changed to `md5_final` and `sha_final` to correctly document the\n implementation.\n\n Own Id: OTP-3409","ref":"notes.html#reported-fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 1.1.1 - Crypto Release Notes","doc":"Code replacement in runtime is supported. Upgrade can be done from from version\n1.1 and downgrade to version 1.1.","ref":"notes.html#crypto-1-1-1"},{"type":"extras","title":"Improvements and New Features - Crypto Release Notes","doc":"- The driver part of the Crypto application has been updated to use the\n erl_driver header file. Version 1.1.1 requires emulator version 4.9.1 or\n later.","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Crypto 1.1 - Crypto Release Notes","doc":"","ref":"notes.html#crypto-1-1"},{"type":"extras","title":"Reported Fixed Bugs and Malfunctions - Crypto Release Notes","doc":"- On Windows the crypto_drv was incorrectly linked to static run-time libraries\n instead of dynamic ones.\n\n Own Id: OTP-3240","ref":"notes.html#reported-fixed-bugs-and-malfunctions"},{"type":"extras","title":"Crypto 1.0 - Crypto Release Notes","doc":"New application.","ref":"notes.html#crypto-1-0"},{"type":"extras","title":"Licenses","doc":"\n# Licenses\n\n[](){: #licenses } This chapter contains in extenso versions of the OpenSSL and\nSSLeay licenses.","ref":"licenses.html"},{"type":"extras","title":"OpenSSL License - Licenses","doc":"```c\n/* ====================================================================\n * Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in\n * the documentation and/or other materials provided with the\n * distribution.\n *\n * 3. All advertising materials mentioning features or use of this\n * software must display the following acknowledgment:\n * \"This product includes software developed by the OpenSSL Project\n * for use in the OpenSSL Toolkit. (http://www.openssl.org/)\"\n *\n * 4. The names \"OpenSSL Toolkit\" and \"OpenSSL Project\" must not be used to\n * endorse or promote products derived from this software without\n * prior written permission. For written permission, please contact\n * openssl-core@openssl.org.\n *\n * 5. Products derived from this software may not be called \"OpenSSL\"\n * nor may \"OpenSSL\" appear in their names without prior written\n * permission of the OpenSSL Project.\n *\n * 6. Redistributions of any form whatsoever must retain the following\n * acknowledgment:\n * \"This product includes software developed by the OpenSSL Project\n * for use in the OpenSSL Toolkit (http://www.openssl.org/)\"\n *\n * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY\n * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR\n * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n * ====================================================================\n *\n * This product includes cryptographic software written by Eric Young\n * (eay@cryptsoft.com). This product includes software written by Tim\n * Hudson (tjh@cryptsoft.com).\n *\n */\n```","ref":"licenses.html#openssl-license"},{"type":"extras","title":"SSLeay License - Licenses","doc":"```c\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are adhered to. The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code. The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n * notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n * must display the following acknowledgement:\n * \"This product includes cryptographic software written by\n * Eric Young (eay@cryptsoft.com)\"\n * The word 'cryptographic' can be left out if the routines from the library\n * being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n * the apps directory (application code) you must include an acknowledgement:\n * \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publicly available version or\n * derivative of this code cannot be changed. i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n```","ref":"licenses.html#ssleay-license"},{"type":"extras","title":"FIPS mode","doc":"\n# FIPS mode\n\n[](){: #fips } This chapter describes FIPS mode support in the crypto\napplication.","ref":"fips.html"},{"type":"extras","title":"Background - FIPS mode","doc":"OpenSSL can be built to provide FIPS 140-2 validated cryptographic services. It\nis not the OpenSSL application that is validated, but a special software\ncomponent called the OpenSSL FIPS Object Module. However applications do not use\nthis Object Module directly, but through the regular API of the OpenSSL library.\n\nThe crypto application supports using OpenSSL in FIPS mode. In this scenario\nonly the validated algorithms provided by the Object Module are accessible,\nother algorithms usually available in OpenSSL (like md5) or implemented in the\nErlang code (like SRP) are disabled.","ref":"fips.html#background"},{"type":"extras","title":"Enabling FIPS mode - FIPS mode","doc":"1. Build or install the FIPS Object Module and a FIPS enabled OpenSSL library.\n\nYou should read and precisely follow the instructions of the\n[Security Policy](http://csrc.nist.gov/groups/STM/cmvp/documents/140-1/140sp/140sp1747.pdf)\nand [User Guide](https://www.openssl.org/docs/fips/UserGuide-2.0.pdf).\n\n> #### Warning {: .warning }\n>\n> It is very easy to build a working OpenSSL FIPS Object Module and library from\n> the source. However it _does not_ qualify as FIPS 140-2 validated if the\n> numerous restrictions in the Security Policy are not properly followed.\n\n1. Configure and build Erlang/OTP with FIPS support:\n\n```text\n$ cd $ERL_TOP\n$ ./otp_build configure --enable-fips\n...\nchecking for FIPS_mode_set... yes\n...\n$ make\n```\n\nIf `FIPS_mode_set` returns `no` the OpenSSL library is not FIPS enabled and\ncrypto won't support FIPS mode either.\n\n1. Set the `fips_mode` configuration setting of the crypto application to `true`\n _before loading the crypto module_.\n\nThe best place is in the `sys.config` system configuration file of the release.\n\n1. Start and use the crypto application as usual. However take care to avoid the\n non-FIPS validated algorithms, they will all throw exception `not_supported`.\n\nEntering and leaving FIPS mode on a node already running crypto is not\nsupported. The reason is that OpenSSL is designed to prevent an application\nrequesting FIPS mode to end up accidentally running in non-FIPS mode. If\nentering FIPS mode fails (e.g. the Object Module is not found or is compromised)\nany subsequent use of the OpenSSL API would terminate the emulator.\n\nAn on-the-fly FIPS mode change would thus have to be performed in a critical\nsection protected from any concurrently running crypto operations. Furthermore\nin case of failure all crypto calls would have to be disabled from the Erlang or\nnif code. This would be too much effort put into this not too important feature.","ref":"fips.html#enabling-fips-mode"},{"type":"extras","title":"Incompatibilities with regular builds - FIPS mode","doc":"The Erlang API of the crypto application is identical regardless of building\nwith or without FIPS support. However the nif code internally uses a different\nOpenSSL API.\n\nThis means that the context (an opaque type) returned from streaming crypto\nfunctions (`hash_(init|update|final)`, `hmac_(init|update|final)` and\n`stream_(init|encrypt|decrypt)`) is different and incompatible with regular\nbuilds when compiling crypto with FIPS support.","ref":"fips.html#incompatibilities-with-regular-builds"},{"type":"extras","title":"Common caveats - FIPS mode","doc":"In FIPS mode non-validated algorithms are disabled. This may cause some\nunexpected problems in application relying on crypto.\n\n> #### Warning {: .warning }\n>\n> Do not try to work around these problems by using alternative implementations\n> of the missing algorithms\\! An application can only claim to be using a FIPS\n> 140-2 validated cryptographic module if it uses it exclusively for every\n> cryptographic operation.","ref":"fips.html#common-caveats"},{"type":"extras","title":"Restrictions on key sizes - FIPS mode","doc":"Although public key algorithms are supported in FIPS mode they can only be used\nwith secure key sizes. The Security Policy requires the following minimum\nvalues:\n\n- **RSA** - 1024 bit\n\n- **DSS** - 1024 bit\n\n- **EC algorithms** - 160 bit","ref":"fips.html#restrictions-on-key-sizes"},{"type":"extras","title":"Restrictions on elliptic curves - FIPS mode","doc":"The Erlang API allows using arbitrary curve parameters, but in FIPS mode only\nthose allowed by the Security Policy shall be used.","ref":"fips.html#restrictions-on-elliptic-curves"},{"type":"extras","title":"Avoid md5 for hashing - FIPS mode","doc":"Md5 is a popular choice as a hash function, but it is not secure enough to be\nvalidated. Try to use sha instead wherever possible.\n\nFor exceptional, non-cryptographic use cases one may consider switching to\n`erlang:md5/1` as well.","ref":"fips.html#avoid-md5-for-hashing"},{"type":"extras","title":"Certificates and encrypted keys - FIPS mode","doc":"As md5 is not available in FIPS mode it is only possible to use certificates\nthat were signed using sha hashing. When validating an entire certificate chain\nall certificates (including the root CA's) must comply with this rule.\n\nFor similar dependency on the md5 and des algorithms most encrypted private keys\nin PEM format do not work either. However, the PBES2 encryption scheme allows\nthe use of stronger FIPS verified algorithms which is a viable alternative.","ref":"fips.html#certificates-and-encrypted-keys"},{"type":"extras","title":"SNMP v3 limitations - FIPS mode","doc":"It is only possible to use `usmHMACSHAAuthProtocol` and `usmAesCfb128Protocol`\nfor authentication and privacy respectively in FIPS mode. The snmp application\nhowever won't restrict selecting disabled protocols in any way, and using them\nwould result in run time crashes.","ref":"fips.html#snmp-v3-limitations"},{"type":"extras","title":"TLS 1.2 is required - FIPS mode","doc":"All SSL and TLS versions prior to TLS 1.2 use a combination of md5 and sha1\nhashes in the handshake for various purposes:\n\n- Authenticating the integrity of the handshake messages.\n- In the exchange of DH parameters in cipher suites providing non-anonymous PFS\n (perfect forward secrecy).\n- In the PRF (pseud-random function) to generate keying materials in cipher\n suites not using PFS.\n\nOpenSSL handles these corner cases in FIPS mode, however the Erlang crypto and\nssl applications are not prepared for them and therefore you are limited to TLS\n1.2 in FIPS mode.\n\nOn the other hand it worth mentioning that at least all cipher suites that would\nrely on non-validated algorithms are automatically disabled in FIPS mode.\n\n> #### Note {: .info }\n>\n> Certificates using weak (md5) digests may also cause problems in TLS. Although\n> TLS 1.2 has an extension for specifying which type of signatures are accepted,\n> and in FIPS mode the ssl application will use it properly, most TLS\n> implementations ignore this extension and simply send whatever certificates\n> they were configured with.","ref":"fips.html#tls-1-2-is-required"},{"type":"extras","title":"Engine Load","doc":"\n# Engine Load\n\n[](){: #engine_load } This chapter describes the support for loading encryption\nengines in the crypto application.","ref":"engine_load.html"},{"type":"extras","title":"Background - Engine Load","doc":"OpenSSL exposes an Engine API, which makes it possible to plug in alternative\nimplementations for some or all of the cryptographic operations implemented by\nOpenSSL. When configured appropriately, OpenSSL calls the engine's\nimplementation of these operations instead of its own.\n\nTypically, OpenSSL engines provide a hardware implementation of specific\ncryptographic operations. The hardware implementation usually offers improved\nperformance over its software-based counterpart, which is known as cryptographic\nacceleration.\n\n> #### Note {: .info }\n>\n> The file name requirement on the engine dynamic library can differ between SSL\n> versions.","ref":"engine_load.html#background"},{"type":"extras","title":"Use Cases - Engine Load","doc":"","ref":"engine_load.html#use-cases"},{"type":"extras","title":"Dynamically load an engine from default directory - Engine Load","doc":"If the engine is located in the OpenSSL/LibreSSL installation `engines`\ndirectory.\n\n```erlang\n1> {ok, Engine} = crypto:engine_load(<<\"otp_test_engine\">>, [], []).\n {ok, #Ref}\n```","ref":"engine_load.html#dynamically-load-an-engine-from-default-directory"},{"type":"extras","title":"Load an engine with the dynamic engine - Engine Load","doc":"Load an engine with the help of the dynamic engine by giving the path to the\nlibrary.\n\n```erlang\n 2> {ok, Engine} = crypto:engine_load(<<\"dynamic\">>,\n [{<<\"SO_PATH\">>,\n <<\"/some/path/otp_test_engine.so\">>},\n {<<\"ID\">>, <<\"MD5\">>},\n <<\"LOAD\">>],\n []).\n {ok, #Ref}\n```","ref":"engine_load.html#load-an-engine-with-the-dynamic-engine"},{"type":"extras","title":"Load an engine and replace some methods - Engine Load","doc":"Load an engine with the help of the dynamic engine and just replace some engine\nmethods.\n\n```erlang\n 3> {ok, Engine} = crypto:engine_load(<<\"dynamic\">>,\n [{<<\"SO_PATH\">>,\n <<\"/some/path/otp_test_engine.so\">>},\n {<<\"ID\">>, <<\"MD5\">>},\n <<\"LOAD\">>],\n []).\n{ok, #Ref}\n4> ok = crypto:engine_register(Engine, [engine_method_digests]).\nok\n```","ref":"engine_load.html#load-an-engine-and-replace-some-methods"},{"type":"extras","title":"Load with the ensure loaded function - Engine Load","doc":"This function makes sure the engine is loaded just once and the ID is added to\nthe internal engine list of OpenSSL. The following calls to the function will\ncheck if the ID is loaded and then just get a new reference to the engine.\n\n```erlang\n 5> {ok, Engine} = crypto:ensure_engine_loaded(<<\"MD5\">>,\n <<\"/some/path/otp_test_engine.so\">>).\n {ok, #Ref}\n```\n\nTo remove the tag from the OpenSSL engine list use `crypto:engine_remove/1`.\n\n```erlang\n 6> crypto:engine_remove(Engine).\n ok\n```\n\nTo unload it use `crypto:engine_unload/1` which removes the references to the\nengine.\n\n```erlang\n 6> crypto:engine_unload(Engine).\n ok\n```","ref":"engine_load.html#load-with-the-ensure-loaded-function"},{"type":"extras","title":"List all engines currently loaded - Engine Load","doc":"```erlang\n 8> crypto:engine_list().\n[<<\"dynamic\">>, <<\"MD5\">>]\n```","ref":"engine_load.html#list-all-engines-currently-loaded"},{"type":"extras","title":"Engine Stored Keys","doc":"\n# Engine Stored Keys\n\n[](){: #engine_key } This chapter describes the support in the crypto\napplication for using public and private keys stored in encryption engines.","ref":"engine_keys.html"},{"type":"extras","title":"Background - Engine Stored Keys","doc":"[OpenSSL](https://www.openssl.org/) exposes an Engine API, which makes it\npossible to plug in alternative implementations for some of the cryptographic\noperations implemented by OpenSSL. See the chapter\n[Engine Load](engine_load.md#engine_load) for details and how to load an Engine.\n\nAn engine could among other tasks provide a storage for private or public keys.\nSuch a storage could be made safer than the normal file system. Those techniques\nare not described in this User's Guide. Here we concentrate on how to use\nprivate or public keys stored in such an engine.\n\nThe storage engine must call `ENGINE_set_load_privkey_function` and\n`ENGINE_set_load_pubkey_function`. See the OpenSSL cryptolib's\n[manpages](https://www.openssl.org/docs/manpages.html).\n\nOTP/Crypto requires that the user provides two or three items of information\nabout the key. The application used by the user is usually on a higher level,\nfor example in [SSL](`t:ssl:key/0`). If using the crypto application directly,\nit is required that:\n\n- an Engine is loaded, see the chapter on\n [Engine Load](engine_load.md#engine_load) or the\n [Reference Manual](`crypto:engine_load/3`)\n- a reference to a key in the Engine is available. This should be an Erlang\n string or binary and depends on the Engine loaded\n- an Erlang map is constructed with the Engine reference, the key reference and\n possibly a key passphrase if needed by the Engine. See the\n [Reference Manual](`t:crypto:engine_key_ref/0`) for details of the map.","ref":"engine_keys.html#background"},{"type":"extras","title":"Use Cases - Engine Stored Keys","doc":"","ref":"engine_keys.html#use-cases"},{"type":"extras","title":"Sign with an engine stored private key - Engine Stored Keys","doc":"This example shows how to construct a key reference that is used in a sign\noperation. The actual key is stored in the engine that is loaded at prompt 1.\n\n```erlang\n1> {ok, EngineRef} = crypto:engine_load(....).\n...\n{ok,#Ref<0.2399045421.3028942852.173962>}\n2> PrivKey = #{engine => EngineRef,\n key_id => \"id of the private key in Engine\"}.\n...\n3> Signature = crypto:sign(rsa, sha, <<\"The message\">>, PrivKey).\n<<65,6,125,254,54,233,84,77,83,63,168,28,169,214,121,76,\n 207,177,124,183,156,185,160,243,36,79,125,230,231,...>>\n```","ref":"engine_keys.html#sign-with-an-engine-stored-private-key"},{"type":"extras","title":"Verify with an engine stored public key - Engine Stored Keys","doc":"Here the signature and message in the last example is verifyed using the public\nkey. The public key is stored in an engine, only to exemplify that it is\npossible. The public key could of course be handled openly as usual.\n\n```erlang\n4> PublicKey = #{engine => EngineRef,\n key_id => \"id of the public key in Engine\"}.\n...\n5> crypto:verify(rsa, sha, <<\"The message\">>, Signature, PublicKey).\ntrue\n6>\n```","ref":"engine_keys.html#verify-with-an-engine-stored-public-key"},{"type":"extras","title":"Using a password protected private key - Engine Stored Keys","doc":"The same example as the first sign example, except that a password protects the\nkey down in the Engine.\n\n```erlang\n6> PrivKeyPwd = #{engine => EngineRef,\n key_id => \"id of the pwd protected private key in Engine\",\n\t\t password => \"password\"}.\n...\n7> crypto:sign(rsa, sha, <<\"The message\">>, PrivKeyPwd).\n<<140,80,168,101,234,211,146,183,231,190,160,82,85,163,\n 175,106,77,241,141,120,72,149,181,181,194,154,175,76,\n 223,...>>\n8>\n```","ref":"engine_keys.html#using-a-password-protected-private-key"},{"type":"extras","title":"Algorithm Details","doc":"\n# Algorithm Details\n\nThis chapter describes details of algorithms in the crypto application.\n\nThe tables only documents the supported cryptos and key lengths. The user should\nnot draw any conclusion on security from the supplied tables.","ref":"algorithm_details.html"},{"type":"extras","title":"Ciphers - Algorithm Details","doc":"A [cipher](`t:crypto:cipher/0`) in the [new api](new_api.md#the-new-api) is\ncategorized as either [cipher_no_iv()](`t:crypto:cipher_no_iv/0`),\n[cipher_iv()](`t:crypto:cipher_iv/0`) or\n[cipher_aead()](`t:crypto:cipher_aead/0`). The letters IV are short for\n_Initialization Vector_ and AEAD is an abbreviation of _Authenticated Encryption\nwith Associated Data_.\n\nDue to irregular naming conventions, some cipher names in the old api are\nsubstituted by new names in the new api. For a list of retired names, see\n[Retired cipher names](new_api.md#retired-cipher-names).\n\nTo dynamically check availability, check that the name in the _Cipher and Mode_\ncolumn is present in the list returned by\n[crypto:supports(ciphers)](`crypto:supports/1`).","ref":"algorithm_details.html#ciphers"},{"type":"extras","title":"Ciphers without an IV - cipher_no_iv() - Algorithm Details","doc":"To be used with:\n\n- [crypto_one_time/4](`crypto:crypto_one_time/4`)\n- [crypto_init/3](`crypto:crypto_init/3`)\n\nThe ciphers are:\n\n| **Cipher and Mode** | **Key length** **\\[bytes]** | **Block size** **\\[bytes]** |\n| ------------------- | --------------------------- | --------------------------- |\n| `aes_128_ecb` | 16 | 16 |\n| `aes_192_ecb` | 24 | 16 |\n| `aes_256_ecb` | 32 | 16 |\n| `blowfish_ecb` | 16 |  8 |\n| `des_ecb` |  8 |  8 |\n| `rc4` | 16 |  1 |\n| `sm4_ecb` | 16 | 16 |\n\n_Table: Ciphers without IV_","ref":"algorithm_details.html#ciphers-without-an-iv-cipher_no_iv"},{"type":"extras","title":"Ciphers with an IV - cipher_iv() - Algorithm Details","doc":"To be used with:\n\n- [crypto_one_time/5](`crypto:crypto_one_time/5`)\n- [crypto_init/4](`crypto:crypto_init/4`)\n\nThe ciphers are:\n\n| **Cipher and Mode** | **Key length** **\\[bytes]** | **IV length** **\\[bytes]** | **Block size** **\\[bytes]** | **Limited to** **OpenSSL versions** |\n| ------------------- | --------------------------- | -------------------------- | --------------------------- | ----------------------------------- |\n| `aes_128_cbc` | 16 | 16 | 16 | |\n| `aes_192_cbc` | 24 | 16 | 16 | |\n| `aes_256_cbc` | 32 | 16 | 16 | |\n| `aes_128_cfb8` | 16 | 16 |  1 | |\n| `aes_192_cfb8` | 24 | 16 |  1 | |\n| `aes_256_cfb8` | 32 | 16 |  1 | |\n| `aes_128_cfb128` | 16 | 16 |  1 | |\n| `aes_192_cfb128` | 24 | 16 |  1 | |\n| `aes_256_cfb128` | 32 | 16 |  1 | |\n| `aes_128_ctr` | 16 | 16 |  1 | |\n| `aes_192_ctr` | 24 | 16 |  1 | |\n| `aes_256_ctr` | 32 | 16 |  1 | |\n| `aes_128_ofb` | 16 | 16 |  1 | |\n| `aes_192_ofb` | 24 | 16 |  1 | |\n| `aes_256_ofb` | 32 | 16 |  1 | |\n| `blowfish_cbc` | 16 |  8 |  8 | |\n| `blowfish_cfb64` | 16 |  8 |  1 | |\n| `blowfish_ofb64` | 16 |  8 |  1 | |\n| `chacha20` | 32 | 16 |  1 | ≥1.1.0d |\n| `des_cbc` |  8 |  8 |  8 | |\n| `des_ede3_cbc` | 24 |  8 |  8 | |\n| `des_cfb` |  8 |  8 |  1 | |\n| `des_ede3_cfb` | 24 |  8 |  1 | |\n| `rc2_cbc` | 16 |  8 |  8 | |\n| `sm4_cbc` | 16 | 16 | 16 | ≥1.1.1 |\n| `sm4_cfb` | 16 | 16 | 16 | ≥1.1.1 |\n| `sm4_ofb` | 16 | 16 | 16 | ≥1.1.1 |\n| `sm4_ctr` | 16 | 16 | 16 | ≥1.1.1 |\n\n_Table: Ciphers with IV_","ref":"algorithm_details.html#ciphers-with-an-iv-cipher_iv"},{"type":"extras","title":"Ciphers with AEAD - cipher_aead() - Algorithm Details","doc":"To be used with:\n\n- [crypto_one_time_aead/6](`crypto:crypto_one_time_aead/6`)\n- [crypto_one_time_aead/7](`crypto:crypto_one_time_aead/7`)\n\nThe ciphers are:\n\n| **Cipher and Mode** | **Key length** **\\[bytes]** | **IV length** **\\[bytes]** | **AAD length** **\\[bytes]** | **Tag length** **\\[bytes]** | **Block size** **\\[bytes]** | **Limited to** **OpenSSL versions** |\n| ------------------- | --------------------------- | -------------------------- | --------------------------- | --------------------------- | --------------------------- | ----------------------------------- |\n| `aes_128_ccm` | 16 | 7-13 | any | even 4-16 default: 12 | any | ≥1.0.1 |\n| `aes_192_ccm` | 24 | 7-13 | any | even 4-16 default: 12 | any | ≥1.0.1 |\n| `aes_256_ccm` | 32 | 7-13 | any | even 4-16 default: 12 | any | ≥1.0.1 |\n| `aes_128_gcm` | 16 | ≥1 | any | 1-16 default: 16 | any | ≥1.0.1 |\n| `aes_192_gcm` | 24 | ≥1 | any | 1-16 default: 16 | any | ≥1.0.1 |\n| `aes_256_gcm` | 32 | ≥1 | any | 1-16 default: 16 | any | ≥1.0.1 |\n| `chacha20_poly1305` | 32 | 1-16 | any | 16 | any | ≥1.1.0 |\n| `sm4_gcm` | 16 | 12 | any | 16 | any | ≥3.1.0 |\n| `sm4_ccm` | 16 | 12 | any | 16 | any | ≥3.1.0 |\n\n_Table: AEAD ciphers_","ref":"algorithm_details.html#ciphers-with-aead-cipher_aead"},{"type":"extras","title":"Message Authentication Codes (MACs) - Algorithm Details","doc":"To be used in [mac/4](`crypto:mac/4`) and\n[related functions](new_api.md#macs-message-authentication-codes).","ref":"algorithm_details.html#message-authentication-codes-macs"},{"type":"extras","title":"CMAC - Algorithm Details","doc":"CMAC with the following ciphers are available with OpenSSL 1.0.1 or later if not\ndisabled by configuration.\n\nTo dynamically check availability, check that the name `cmac` is present in the\nlist returned by [crypto:supports(macs)](`crypto:supports/1`). Also check that\nthe name in the _Cipher and Mode_ column is present in the list returned by\n[crypto:supports(ciphers)](`crypto:supports/1`).\n\n| **Cipher and Mode** | **Key length** **\\[bytes]** | **Max Mac Length** **(= default length)** **\\[bytes]** |\n| ------------------- | --------------------------- | ------------------------------------------------------ |\n| `aes_128_cbc` | 16 | 16 |\n| `aes_192_cbc` | 24 | 16 |\n| `aes_256_cbc` | 32 | 16 |\n| `aes_128_ecb` | 16 | 16 |\n| `aes_192_ecb` | 24 | 16 |\n| `aes_256_ecb` | 32 | 16 |\n| `blowfish_cbc` | 16 |  8 |\n| `blowfish_ecb` | 16 |  8 |\n| `des_cbc` |  8 |  8 |\n| `des_ecb` |  8 |  8 |\n| `des_ede3_cbc` | 24 |  8 |\n| `rc2_cbc` | 16 |  8 |\n\n_Table: CMAC cipher key lengths_","ref":"algorithm_details.html#cmac"},{"type":"extras","title":"HMAC - Algorithm Details","doc":"Available in all OpenSSL compatible with Erlang CRYPTO if not disabled by\nconfiguration.\n\nTo dynamically check availability, check that the name `hmac` is present in the\nlist returned by [crypto:supports(macs)](`crypto:supports/1`) and that the hash\nname is present in the list returned by\n[crypto:supports(hashs)](`crypto:supports/1`).\n\n| **Hash** | **Max Mac Length** **(= default length)** **\\[bytes]** |\n| ----------- | ------------------------------------------------------ |\n| `sha` | 20 |\n| `sha224` | 28 |\n| `sha256` | 32 |\n| `sha384` | 48 |\n| `sha512` | 64 |\n| `sha3_224` | 28 |\n| `sha3_256` | 32 |\n| `sha3_384` | 48 |\n| `sha3_512` | 64 |\n| `shake128` | 64 |\n| `shake256` | 64 |\n| `blake2b` | 64 |\n| `blake2s` | 32 |\n| `md4` | 16 |\n| `md5` | 16 |\n| `ripemd160` | 20 |\n\n_Table: HMAC output sizes_","ref":"algorithm_details.html#hmac"},{"type":"extras","title":"POLY1305 - Algorithm Details","doc":"POLY1305 is available with OpenSSL 1.1.1 or later if not disabled by\nconfiguration.\n\nTo dynamically check availability, check that the name `poly1305` is present in\nthe list returned by [crypto:supports(macs)](`crypto:supports/1`).\n\nThe poly1305 mac wants an 32 bytes key and produces a 16 byte MAC by default.","ref":"algorithm_details.html#poly1305"},{"type":"extras","title":"Hash - Algorithm Details","doc":"To dynamically check availability, check that the wanted name in the _Names_\ncolumn is present in the list returned by\n[crypto:supports(hashs)](`crypto:supports/1`).\n\n| **Type** | **Names** | **Limited to** **OpenSSL versions** |\n| -------- | ---------------------------------------------------------- | ----------------------------------- |\n| SHA1 | sha | |\n| SHA2 | sha224, sha256, sha384, sha512 | |\n| SHA3 | sha3_224, sha3_256, sha3_384, sha3_512, shake128, shake256 | ≥1.1.1 |\n| SM3 | sm3 | ≥1.1.1 |\n| MD4 | md4 | |\n| MD5 | md5 | |\n| RIPEMD | ripemd160 | |","ref":"algorithm_details.html#hash"},{"type":"extras","title":"Public Key Cryptography - Algorithm Details","doc":"","ref":"algorithm_details.html#public-key-cryptography"},{"type":"extras","title":"RSA - Algorithm Details","doc":"RSA is available with all OpenSSL versions compatible with Erlang CRYPTO if not\ndisabled by configuration. To dynamically check availability, check that the\natom `rsa` is present in the list returned by\n[crypto:supports(public_keys)](`crypto:supports/1`).\n\n> #### Warning {: .warning }\n>\n> The RSA options are experimental.\n>\n> The exact set of options and there syntax _may_ be changed without prior\n> notice.\n\n| **Option** | **sign/verify** | **public encrypt** **private decrypt** | **private encrypt** **public decrypt** |\n| --------------------------------------------------------------------------------------------------------------------- | ----------------- | -------------------------------------- | -------------------------------------- |\n| \\{rsa_padding,rsa_x931_padding\\} | x | | x |\n| \\{rsa_padding,rsa_pkcs1_padding\\} | x | x | x |\n| \\{rsa_padding,rsa_pkcs1_pss_padding\\} \\{rsa_pss_saltlen, -2..\\} \\{rsa_mgf1_md, atom()\\} | x (2) x (2) x (2) | | |\n| \\{rsa_padding,rsa_pkcs1_oaep_padding\\} \\{rsa_mgf1_md, atom()\\} \\{rsa_oaep_label, binary()\\}\\} \\{rsa_oaep_md, atom()\\} | | x (2) x (2) x (3) x (3) | |\n| \\{rsa_padding,rsa_no_padding\\} | x (1) | | |\n\nNotes:\n\n1. (1) OpenSSL ≤ 1.0.0\n1. (2) OpenSSL ≥ 1.0.1\n1. (3) OpenSSL ≥ 1.1.0","ref":"algorithm_details.html#rsa"},{"type":"extras","title":"DSS - Algorithm Details","doc":"DSS is available with OpenSSL versions compatible with Erlang CRYPTO if not\ndisabled by configuration. To dynamically check availability, check that the\natom `dss` is present in the list returned by\n[crypto:supports(public_keys)](`crypto:supports/1`).","ref":"algorithm_details.html#dss"},{"type":"extras","title":"ECDSA - Algorithm Details","doc":"ECDSA is available with OpenSSL 0.9.8o or later if not disabled by\nconfiguration. To dynamically check availability, check that the atom `ecdsa` is\npresent in the list returned by\n[crypto:supports(public_keys)](`crypto:supports/1`). If the atom `ec_gf2m` also\nis present, the characteristic two field curves are available.\n\nThe actual supported named curves could be checked by examining the list\nreturned by [crypto:supports(curves)](`crypto:supports/1`).","ref":"algorithm_details.html#ecdsa"},{"type":"extras","title":"EdDSA - Algorithm Details","doc":"EdDSA is available with OpenSSL 1.1.1 or later if not disabled by configuration.\nTo dynamically check availability, check that the atom `eddsa` is present in the\nlist returned by [crypto:supports(public_keys)](`crypto:supports/1`).\n\nSupport for the curves ed25519 and ed448 is implemented. The actual supported\nnamed curves could be checked by examining the list with the list returned by\n[crypto:supports(curves)](`crypto:supports/1`).","ref":"algorithm_details.html#eddsa"},{"type":"extras","title":"Diffie-Hellman - Algorithm Details","doc":"Diffie-Hellman computations are available with OpenSSL versions compatible with\nErlang CRYPTO if not disabled by configuration. To dynamically check\navailability, check that the atom `dh` is present in the list returned by\n[crypto:supports(public_keys)](`crypto:supports/1`).","ref":"algorithm_details.html#diffie-hellman"},{"type":"extras","title":"Elliptic Curve Diffie-Hellman - Algorithm Details","doc":"Elliptic Curve Diffie-Hellman is available with OpenSSL 0.9.8o or later if not\ndisabled by configuration. To dynamically check availability, check that the\natom `ecdh` is present in the list returned by\n[crypto:supports(public_keys)](`crypto:supports/1`).\n\nThe Edward curves `x25519` and `x448` are supported with OpenSSL 1.1.1 or later\nif not disabled by configuration.\n\nThe actual supported named curves could be checked by examining the list\nreturned by [crypto:supports(curves)](`crypto:supports/1`).","ref":"algorithm_details.html#elliptic-curve-diffie-hellman"},{"type":"extras","title":"New and Old API","doc":"\n# New and Old API\n\nThis chapter describes the new api to encryption and decryption.","ref":"new_api.html"},{"type":"extras","title":"Background - New and Old API","doc":"The CRYPTO app has evolved during its lifetime. Since also the OpenSSL cryptolib\nhas changed the API several times, there are parts of the CRYPTO app that uses a\nvery old one internally and other parts that uses the latest one. The internal\ndefinitions of e.g cipher names was a bit hard to maintain.\n\nIt turned out that using the old api in the new way (more about that later), and\nstill keep it backwards compatible, was not possible. Specially as more\nprecision in the error messages is desired it could not be combined with the old\nstandard.\n\nTherefore the old api (see next section) is kept for now but internally\nimplemented with new primitives.","ref":"new_api.html#background"},{"type":"extras","title":"The old API - New and Old API","doc":"The old functions - deprecated from 23.0 and removed from OTP 24.0 - are for\nciphers:\n\n- `block_encrypt/3`\n- `block_encrypt/4`\n- `block_decrypt/3`\n- `block_decrypt/4`\n- `stream_init/2`\n- `stream_init/3`\n- `stream_encrypt/2`\n- `stream_decrypt/2`\n- `next_iv/2`\n- `next_iv/3`\n\nfor lists of supported algorithms:\n\n- `supports/0`\n\nand for MACs (Message Authentication Codes):\n\n- `cmac/3`\n- `cmac/4`\n- `hmac/3`\n- `hmac/4`\n- `hmac_init/2`\n- `hmac_update/2`\n- `hmac_final/1`\n- `hmac_final_n/2`\n- `poly1305/2`","ref":"new_api.html#the-old-api"},{"type":"extras","title":"The new API - New and Old API","doc":"","ref":"new_api.html#the-new-api"},{"type":"extras","title":"Encryption and decryption - New and Old API","doc":"The new functions for encrypting or decrypting one single binary are:\n\n- [crypto_one_time/4](`crypto:crypto_one_time/4`)\n- [crypto_one_time/5](`crypto:crypto_one_time/5`)\n- [crypto_one_time_aead/6](`crypto:crypto_one_time_aead/6`)\n- [crypto_one_time_aead/7](`crypto:crypto_one_time_aead/7`)\n\nIn those functions the internal crypto state is first created and initialized\nwith the cipher type, the key and possibly other data. Then the single binary is\nencrypted or decrypted, the crypto state is de-allocated and the result of the\ncrypto operation is returned.\n\nThe `crypto_one_time_aead` functions are for the ciphers of mode `ccm` or `gcm`,\nand for the cipher `chacha20-poly1305`.\n\nFor repeated encryption or decryption of a text divided in parts, where the\ninternal crypto state is initialized once, and then many binaries are encrypted\nor decrypted with the same state, the functions are:\n\n- [crypto_init/4](`crypto:crypto_init/4`)\n- [crypto_init/3](`crypto:crypto_init/3`)\n- [crypto_update/2](`crypto:crypto_update/2`)\n- [crypto_final/1](`crypto:crypto_final/1`)\n\nThe `crypto_init` initialies an internal cipher state, and one or more calls of\n`crypto_update` does the actual encryption or decryption. Note that AEAD ciphers\ncan't be handled this way due to their nature.\n\nAn example of where those functions are needed, is when handling the TLS\nprotocol.\n\nIf padding was not enabled, the call to\n[crypto_final/1](`crypto:crypto_final/1`) may be excluded.\n\nFor information about available algorithms, use:\n\n- [supports/1](`crypto:supports/1`)\n- [hash_info/1](`crypto:hash_info/1`)\n- [cipher_info/1](`crypto:cipher_info/1`)\n\nThe `next_iv/2` and `next_iv/3` are not needed since the `crypto_init` and\n`crypto_update` includes this functionality.","ref":"new_api.html#encryption-and-decryption"},{"type":"extras","title":"MACs (Message Authentication Codes) - New and Old API","doc":"The new functions for calculating a MAC of a single piece of text are:\n\n- [mac/3](`crypto:mac/3`)\n- [mac/4](`crypto:mac/4`)\n- [macN/4](`crypto:macN/4`)\n- [macN/5](`crypto:macN/5`)\n\nFor calculating a MAC of a text divided in parts use:\n\n- [mac_init/2](`crypto:mac_init/2`)\n- [mac_init/3](`crypto:mac_init/3`)\n- [mac_update/2](`crypto:mac_update/2`)\n- [mac_final/1](`crypto:mac_final/1`)\n- [mac_finalN/2](`crypto:mac_finalN/2`)","ref":"new_api.html#macs-message-authentication-codes"},{"type":"extras","title":"Examples of the new api - New and Old API","doc":"","ref":"new_api.html#examples-of-the-new-api"},{"type":"extras","title":"Examples of crypto_init/4 and crypto_update/2 - New and Old API","doc":"The functions [crypto_init/4](`crypto:crypto_init/4`) and\n[crypto_update/2](`crypto:crypto_update/2`) are intended to be used for\nencrypting or decrypting a sequence of blocks. First one call of `crypto_init/4`\ninitialises the crypto context. One or more calls `crypto_update/2` does the\nactual encryption or decryption for each block.\n\nThis example shows first the encryption of two blocks and then decryptions of\nthe cipher text, but divided into three blocks just to show that it is possible\nto divide the plain text and cipher text differently for some ciphers:\n\n```erlang\n\t1> application:start(crypto).\n\tok\n\t2> Key = <<1:128>>.\n\t<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>\n\t3> IV = <<0:128>>.\n\t<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>\n\t4> StateEnc = crypto:crypto_init(aes_128_ctr, Key, IV, true). % encrypt -> true\n\t#Ref<0.3768901617.1128660993.124047>\n\t5> crypto:crypto_update(StateEnc, <<\"First bytes\">>).\n\t<<67,44,216,166,25,130,203,5,66,6,162>>\n\t6> crypto:crypto_update(StateEnc, <<\"Second bytes\">>).\n\t<<16,79,94,115,234,197,94,253,16,144,151,41>>\n\t7>\n\t7> StateDec = crypto:crypto_init(aes_128_ctr, Key, IV, false). % decrypt -> false\n\t#Ref<0.3768901617.1128660994.124255>\n\t8> crypto:crypto_update(StateDec, <<67,44,216,166,25,130,203>>).\n\t<<\"First b\">>\n\t9> crypto:crypto_update(StateDec, <<5,66,6,162,16,79,94,115,234,197,\n 94,253,16,144,151>>).\n\t<<\"ytesSecond byte\">>\n\t10> crypto:crypto_update(StateDec, <<41>>).\n\t<<\"s\">>\n\t11>\n```\n\nNote that the internal data that the `StateEnc` and `StateDec` references are\ndestructivly updated by the calls to\n[crypto_update/2](`crypto:crypto_update/2`). This is to gain time in the calls\nof the nifs interfacing the cryptolib. In a loop where the state is saved in the\nloop's state, it also saves one update of the loop state per crypto operation.\n\nFor example, a simple server receiving text parts to encrypt and send the result\nback to the one who sent them (the `Requester`):\n\n```erlang\n\tencode(Crypto, Key, IV) ->\n\tcrypto_loop(crypto:crypto_init(Crypto, Key, IV, true)).\n\n\tcrypto_loop(State) ->\n\treceive\n {Text, Requester} ->\n Requester ! crypto:crypto_update(State, Text),\n\tloop(State)\n\tend.\n```","ref":"new_api.html#examples-of-crypto_init-4-and-crypto_update-2"},{"type":"extras","title":"Example of crypto_one_time/5 - New and Old API","doc":"The same example as in the\n[previous section](new_api.md#examples-of-crypto_init-4-and-crypto_update-2),\nbut now with one call to [crypto_one_time/5](`crypto:crypto_one_time/5`):\n\n```erlang\n\t1> Key = <<1:128>>.\n\t<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>\n\t2> IV = <<0:128>>.\n\t<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>\n\t3> Txt = [<<\"First bytes\">>,<<\"Second bytes\">>].\n\t[<<\"First bytes\">>,<<\"Second bytes\">>]\n\t4> crypto:crypto_one_time(aes_128_ctr, Key, IV, Txt, true).\n\t<<67,44,216,166,25,130,203,5,66,6,162,16,79,94,115,234,\n\t197,94,253,16,144,151,41>>\n\t5>\n```\n\nThe `[<<\"First bytes\">>,<<\"Second bytes\">>]` could of course have been one\nsingle binary: `<<\"First bytesSecond bytes\">>`.","ref":"new_api.html#example-of-crypto_one_time-5"},{"type":"extras","title":"Example of crypto_one_time_aead/6 - New and Old API","doc":"The same example as in the\n[previous section](new_api.md#example-of-crypto_one_time-5), but now with one\ncall to [crypto_one_time_aead/6](`crypto:crypto_one_time_aead/6`):\n\n```erlang\n\t1> Key = <<1:128>>.\n\t<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>\n\t2> IV = <<0:128>>.\n\t<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>\n\t3> Txt = [<<\"First bytes\">>,<<\"Second bytes\">>].\n\t[<<\"First bytes\">>,<<\"Second bytes\">>]\n\t4> AAD = <<\"Some additional auth data\">>.\n\t<<\"Some additional auth data\">>\n\t5> crypto:crypto_one_time_aead(aes_128_gcm, Key, IV, Txt, AAD, true).\n\t{<<240,130,38,96,130,241,189,52,3,190,179,213,132,1,72,\n\t192,103,176,90,104,15,71,158>>,\n\t<<131,47,45,91,142,85,9,244,21,141,214,71,31,135,2,155>>}\n\t6>\n```\n\nThe `[<<\"First bytes\">>,<<\"Second bytes\">>]` could of course have been one\nsingle binary: `<<\"First bytesSecond bytes\">>`.","ref":"new_api.html#example-of-crypto_one_time_aead-6"},{"type":"extras","title":"Example of mac_init mac_update and mac_final - New and Old API","doc":"```erlang\n\t1> Key = <<1:128>>.\n\t<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>\n\t2> StateMac = crypto:mac_init(cmac, aes_128_cbc, Key).\n\t#Ref<0.2424664121.2781478916.232610>\n\t3> crypto:mac_update(StateMac, <<\"First bytes\">>).\n\t#Ref<0.2424664121.2781478916.232610>\n\t4> crypto:mac_update(StateMac, \" \").\n\t#Ref<0.2424664121.2781478916.232610>\n\t5> crypto:mac_update(StateMac, <<\"last bytes\">>).\n\t#Ref<0.2424664121.2781478916.232610>\n\t6> crypto:mac_final(StateMac).\n\t<<68,191,219,128,84,77,11,193,197,238,107,6,214,141,160,\n\t249>>\n\t7>\n```\n\nand compare the result with a single calculation just for this example:\n\n```erlang\n\t7> crypto:mac(cmac, aes_128_cbc, Key, \"First bytes last bytes\").\n\t<<68,191,219,128,84,77,11,193,197,238,107,6,214,141,160,\n\t249>>\n\t8> v(7) == v(6).\n\ttrue\n\t9>\n```","ref":"new_api.html#example-of-mac_init-mac_update-and-mac_final"},{"type":"extras","title":"Retired cipher names - New and Old API","doc":"This table lists the retired cipher names in the first column and suggests names\nto replace them with in the second column.\n\nThe new names follows the OpenSSL libcrypto names. The format is\nALGORITM_KEYSIZE_MODE.\n\nExamples of algorithms are aes, chacha20 and des. The keysize is the number of\nbits and examples of the mode are cbc, ctr and gcm. The mode may be followed by\na number depending on the mode. An example is the ccm mode which has a variant\ncalled ccm8 where the so called tag has a length of eight bits.\n\nThe old names had by time lost any common naming convention which the new names\nnow introduces. The new names include the key length which improves the error\nchecking in the lower levels of the crypto application.\n\n| **Instead of:** | **Use:** |\n| --------------- | ------------------------------------------------ |\n| `aes_cbc128` | `aes_128_cbc` |\n| `aes_cbc256` | `aes_256_cbc` |\n| `aes_cbc` | `aes_128_cbc, aes_192_cbc, aes_256_cbc` |\n| `aes_ccm` | `aes_128_ccm, aes_192_ccm, aes_256_ccm` |\n| `aes_cfb128` | `aes_128_cfb128, aes_192_cfb128, aes_256_cfb128` |\n| `aes_cfb8` | `aes_128_cfb8, aes_192_cfb8, aes_256_cfb8` |\n| `aes_ctr` | `aes_128_ctr, aes_192_ctr, aes_256_ctr` |\n| `aes_gcm` | `aes_128_gcm, aes_192_gcm, aes_256_gcm` |\n| `des3_cbc` | `des_ede3_cbc` |\n| `des3_cbf` | `des_ede3_cfb` |\n| `des3_cfb` | `des_ede3_cfb` |\n| `des_ede3` | `des_ede3_cbc` |\n| `des_ede3_cbf` | `des_ede3_cfb` |","ref":"new_api.html#retired-cipher-names"}],"content_type":"text/plain","producer":{"name":"ex_doc","version":[48,46,51,52,46,49]}} \ No newline at end of file diff --git a/prs/9045/lib/crypto-5.5.1/doc/html/engine_keys.html b/prs/9045/lib/crypto-5.5.1/doc/html/engine_keys.html index 0f3db7659edd..0931c85c1065 100644 --- a/prs/9045/lib/crypto-5.5.1/doc/html/engine_keys.html +++ b/prs/9045/lib/crypto-5.5.1/doc/html/engine_keys.html @@ -167,13 +167,13 @@

    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).
    +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,...>>

    @@ -183,10 +183,10 @@

    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>

    @@ -195,11 +195,11 @@

    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).
    +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,...>>
    diff --git a/prs/9045/lib/crypto-5.5.1/doc/html/engine_load.html b/prs/9045/lib/crypto-5.5.1/doc/html/engine_load.html
    index d50859f8f3cf..dc55cd9b9f47 100644
    --- a/prs/9045/lib/crypto-5.5.1/doc/html/engine_load.html
    +++ b/prs/9045/lib/crypto-5.5.1/doc/html/engine_load.html
    @@ -158,35 +158,35 @@ 

    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}

    +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}

    +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]).
    +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

    @@ -195,19 +195,19 @@

    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).
    +engine.

     6> crypto:engine_unload(Engine).
      ok

    List all engines currently loaded

    -
     8> crypto:engine_list().
    -[<<"dynamic">>, <<"MD5">>]
    +
     8> crypto:engine_list().
    +[<<"dynamic">>, <<"MD5">>]
    diff --git a/prs/9045/lib/crypto-5.5.1/doc/html/new_api.html b/prs/9045/lib/crypto-5.5.1/doc/html/new_api.html index 499c6b67e406..9f03ba7b90ce 100644 --- a/prs/9045/lib/crypto-5.5.1/doc/html/new_api.html +++ b/prs/9045/lib/crypto-5.5.1/doc/html/new_api.html @@ -198,41 +198,41 @@

    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
    +	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">>).
    +	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">>).
    +	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>>).
    +	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>>).
    +	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>>).
    +	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.

    @@ -245,9 +245,9 @@

    <<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). + 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 @@ -263,14 +263,14 @@

    <<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">>] + 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, + 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>>} + <<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">>.

    @@ -280,21 +280,21 @@

    	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).
    +	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).
    +	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").
    +	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).
    +	8> v(7) == v(6).
     	true
     	9>

    diff --git a/prs/9045/lib/crypto-5.5.1/doc/html/search.html b/prs/9045/lib/crypto-5.5.1/doc/html/search.html index 42f961d40dee..08ed3acdd645 100644 --- a/prs/9045/lib/crypto-5.5.1/doc/html/search.html +++ b/prs/9045/lib/crypto-5.5.1/doc/html/search.html @@ -128,7 +128,7 @@

    - +

    diff --git a/prs/9045/lib/debugger-5.4/doc/html/debugger.epub b/prs/9045/lib/debugger-5.4/doc/html/debugger.epub index ffd4a85ef70a..346d4cae93dc 100644 Binary files a/prs/9045/lib/debugger-5.4/doc/html/debugger.epub and b/prs/9045/lib/debugger-5.4/doc/html/debugger.epub differ diff --git a/prs/9045/lib/debugger-5.4/doc/html/debugger_chapter.html b/prs/9045/lib/debugger-5.4/doc/html/debugger_chapter.html index 939b12027d80..3fde1864ec4c 100644 --- a/prs/9045/lib/debugger-5.4/doc/html/debugger_chapter.html +++ b/prs/9045/lib/debugger-5.4/doc/html/debugger_chapter.html @@ -170,12 +170,12 @@

    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;
    @@ -214,13 +214,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
    @@ -241,12 +241,12 @@ 

    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 diff --git a/prs/9045/lib/debugger-5.4/doc/html/i.html b/prs/9045/lib/debugger-5.4/doc/html/i.html index 8c2de4a86cb0..b59bc55fa01c 100644 --- a/prs/9045/lib/debugger-5.4/doc/html/i.html +++ b/prs/9045/lib/debugger-5.4/doc/html/i.html @@ -140,9 +140,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
    diff --git a/prs/9045/lib/debugger-5.4/doc/html/int.html b/prs/9045/lib/debugger-5.4/doc/html/int.html index dbcdd3c2e871..e7617dee47fd 100644 --- a/prs/9045/lib/debugger-5.4/doc/html/int.html +++ b/prs/9045/lib/debugger-5.4/doc/html/int.html @@ -692,7 +692,7 @@

    auto_attach(Flags, Function)

    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.

    diff --git a/prs/9045/lib/dialyzer-5.2.1/doc/html/dialyzer.epub b/prs/9045/lib/dialyzer-5.2.1/doc/html/dialyzer.epub index 88836e61fe6c..0b5326493c43 100644 Binary files a/prs/9045/lib/dialyzer-5.2.1/doc/html/dialyzer.epub and b/prs/9045/lib/dialyzer-5.2.1/doc/html/dialyzer.epub differ diff --git a/prs/9045/lib/dialyzer-5.2.1/doc/html/dialyzer.html b/prs/9045/lib/dialyzer-5.2.1/doc/html/dialyzer.html index ccb1ea36f345..fb0888006e30 100644 --- a/prs/9045/lib/dialyzer-5.2.1/doc/html/dialyzer.html +++ b/prs/9045/lib/dialyzer-5.2.1/doc/html/dialyzer.html @@ -276,13 +276,13 @@

    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"]}.

    +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"]}.

    @@ -290,13 +290,13 @@

    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).
    diff --git a/prs/9045/lib/dialyzer-5.2.1/doc/html/dialyzer_chapter.html b/prs/9045/lib/dialyzer-5.2.1/doc/html/dialyzer_chapter.html index d0c56c3d47f8..85e3f485cbe6 100644 --- a/prs/9045/lib/dialyzer-5.2.1/doc/html/dialyzer_chapter.html +++ b/prs/9045/lib/dialyzer-5.2.1/doc/html/dialyzer_chapter.html @@ -215,29 +215,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) ->
    diff --git a/prs/9045/lib/diameter-2.4.1/doc/html/diameter.epub b/prs/9045/lib/diameter-2.4.1/doc/html/diameter.epub
    index 686d5d9aa7a2..afdeece05ade 100644
    Binary files a/prs/9045/lib/diameter-2.4.1/doc/html/diameter.epub and b/prs/9045/lib/diameter-2.4.1/doc/html/diameter.epub differ
    diff --git a/prs/9045/lib/diameter-2.4.1/doc/html/diameter.html b/prs/9045/lib/diameter-2.4.1/doc/html/diameter.html
    index 7a5a9976c673..c9dae71c2c11 100644
    --- a/prs/9045/lib/diameter-2.4.1/doc/html/diameter.html
    +++ b/prs/9045/lib/diameter-2.4.1/doc/html/diameter.html
    @@ -235,14 +235,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. @@ -285,10 +285,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 @@ -314,20 +314,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 @@ -575,10 +575,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 @@ -2565,13 +2565,13 @@

    remove_transport(SvcName, Pred)

    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.

    @@ -2615,52 +2615,52 @@

    service_info(SvcName, Option)

    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 the corresponding transport_opt() list passed to add_transport/2. The watchdog entry shows the state of a connection's RFC 3539 watchdog state machine. The peer entry identifies the @@ -2679,55 +2679,55 @@

    service_info(SvcName, Option)

    transport configuration.

    A listening transport presents its information slightly differently since there may be multiple accepted connections for the same transport_ref(). The transport info returned -by a server with a single client connection might look as follows.

    [[{ref,#Ref<0.0.0.61>},
    -  {type,listen},
    -  {options,[{transport_module,diameter_tcp},
    -            {transport_config,[{reuseaddr,true},
    -                               {ip,{127,0,0,1}},
    -                               {port,3868}]}]},
    -  {accept,[[{watchdog,{<0.56.0>,-576460739249514012,okay}},
    -            {peer,{<0.58.0>,-576460638229179167}},
    -            {apps,[{0,common}]},
    -            {caps,[{origin_host,{"server.example.com","client.example.com"}},
    -                   {origin_realm,{"example.com","example.com"}},
    -                   {host_ip_address,{[{127,0,0,1}],[{127,0,0,1}]}},
    -                   {vendor_id,{193,0}},
    -                   {product_name,{"Server","Client"}},
    -                   {origin_state_id,{[],[]}},
    -                   {supported_vendor_id,{[],[]}},
    -                   {auth_application_id,{[0],[0]}},
    -                   {inband_security_id,{[],[]}},
    -                   {acct_application_id,{[],[]}},
    -                   {vendor_specific_application_id,{[],[]}},
    -                   {firmware_revision,{[],[]}},
    -                   {avp,{[],[]}}]},
    -            {port,[{owner,<0.62.0>},
    -                   {module,diameter_tcp},
    -                   {socket,{{127,0,0,1},3868}},
    -                   {peer,{{127,0,0,1},48758}},
    -                   {statistics,[{recv_oct,1576},
    -                                {recv_cnt,16},
    -                                {recv_max,184},
    -                                {recv_avg,98},
    -                                {recv_dvi,26},
    -                                {send_oct,1396},
    -                                {send_cnt,16},
    -                                {send_max,148},
    -                                {send_avg,87},
    -                                {send_pend,0}]}]}],
    -           [{watchdog,{<0.72.0>,-576460638229717546,initial}}]]},
    -  {statistics,[{{{0,280,0},recv},7},
    -               {{{0,280,1},send},7},
    -               {{{0,280,0},recv,{'Result-Code',2001}},7},
    -               {{{0,258,1},recv},3},
    -               {{{0,258,0},send},3},
    -               {{{0,258,0},send,{'Result-Code',2001}},3},
    -               {{{0,280,1},recv},5},
    -               {{{0,280,0},send},5},
    -               {{{0,280,0},send,{'Result-Code',2001}},5},
    -               {{{0,257,1},recv},1},
    -               {{{0,257,0},send},1},
    -               {{{0,257,0},send,{'Result-Code',2001}},1}]}]]

    The information presented here is as in the connect case except that the +by a server with a single client connection might look as follows.

    [[{ref,#Ref<0.0.0.61>},
    +  {type,listen},
    +  {options,[{transport_module,diameter_tcp},
    +            {transport_config,[{reuseaddr,true},
    +                               {ip,{127,0,0,1}},
    +                               {port,3868}]}]},
    +  {accept,[[{watchdog,{<0.56.0>,-576460739249514012,okay}},
    +            {peer,{<0.58.0>,-576460638229179167}},
    +            {apps,[{0,common}]},
    +            {caps,[{origin_host,{"server.example.com","client.example.com"}},
    +                   {origin_realm,{"example.com","example.com"}},
    +                   {host_ip_address,{[{127,0,0,1}],[{127,0,0,1}]}},
    +                   {vendor_id,{193,0}},
    +                   {product_name,{"Server","Client"}},
    +                   {origin_state_id,{[],[]}},
    +                   {supported_vendor_id,{[],[]}},
    +                   {auth_application_id,{[0],[0]}},
    +                   {inband_security_id,{[],[]}},
    +                   {acct_application_id,{[],[]}},
    +                   {vendor_specific_application_id,{[],[]}},
    +                   {firmware_revision,{[],[]}},
    +                   {avp,{[],[]}}]},
    +            {port,[{owner,<0.62.0>},
    +                   {module,diameter_tcp},
    +                   {socket,{{127,0,0,1},3868}},
    +                   {peer,{{127,0,0,1},48758}},
    +                   {statistics,[{recv_oct,1576},
    +                                {recv_cnt,16},
    +                                {recv_max,184},
    +                                {recv_avg,98},
    +                                {recv_dvi,26},
    +                                {send_oct,1396},
    +                                {send_cnt,16},
    +                                {send_max,148},
    +                                {send_avg,87},
    +                                {send_pend,0}]}]}],
    +           [{watchdog,{<0.72.0>,-576460638229717546,initial}}]]},
    +  {statistics,[{{{0,280,0},recv},7},
    +               {{{0,280,1},send},7},
    +               {{{0,280,0},recv,{'Result-Code',2001}},7},
    +               {{{0,258,1},recv},3},
    +               {{{0,258,0},send},3},
    +               {{{0,258,0},send,{'Result-Code',2001}},3},
    +               {{{0,280,1},recv},5},
    +               {{{0,280,0},send},5},
    +               {{{0,280,0},send,{'Result-Code',2001}},5},
    +               {{{0,257,1},recv},1},
    +               {{{0,257,0},send},1},
    +               {{{0,257,0},send,{'Result-Code',2001}},1}]}]]

    The information presented here is as in the connect case except that the client connections are grouped under an accept tuple.

    Whether or not the transport_opt() pool_size has been configured affects the format of the listing in the case of a connecting transport, since a value greater than 1 implies multiple transport @@ -2738,54 +2738,54 @@

    service_info(SvcName, Option)

    This is a flat view of transport info which lists only active connections and for which Diameter-level statistics are accumulated only for the lifetime of the transport connection. A return value for the server above might look as -follows.

    [[{ref,#Ref<0.0.0.61>},
    -  {type,accept},
    -  {options,[{transport_module,diameter_tcp},
    -            {transport_config,[{reuseaddr,true},
    -                               {ip,{127,0,0,1}},
    -                               {port,3868}]}]},
    -  {watchdog,{<0.56.0>,-576460739249514012,okay}},
    -  {peer,{<0.58.0>,-576460638229179167}},
    -  {apps,[{0,common}]},
    -  {caps,[{origin_host,{"server.example.com","client.example.com"}},
    -         {origin_realm,{"example.com","example.com"}},
    -         {host_ip_address,{[{127,0,0,1}],[{127,0,0,1}]}},
    -         {vendor_id,{193,0}},
    -         {product_name,{"Server","Client"}},
    -         {origin_state_id,{[],[]}},
    -         {supported_vendor_id,{[],[]}},
    -         {auth_application_id,{[0],[0]}},
    -         {inband_security_id,{[],[]}},
    -         {acct_application_id,{[],[]}},
    -         {vendor_specific_application_id,{[],[]}},
    -         {firmware_revision,{[],[]}},
    -         {avp,{[],[]}}]},
    -  {port,[{owner,<0.62.0>},
    -         {module,diameter_tcp},
    -         {socket,{{127,0,0,1},3868}},
    -         {peer,{{127,0,0,1},48758}},
    -         {statistics,[{recv_oct,10124},
    -                      {recv_cnt,132},
    -                      {recv_max,184},
    -                      {recv_avg,76},
    -                      {recv_dvi,9},
    -                      {send_oct,10016},
    -                      {send_cnt,132},
    -                      {send_max,148},
    -                      {send_avg,75},
    -                      {send_pend,0}]}]},
    -  {statistics,[{{{0,280,0},recv},62},
    -               {{{0,280,1},send},62},
    -               {{{0,280,0},recv,{'Result-Code',2001}},62},
    -               {{{0,258,1},recv},3},
    -               {{{0,258,0},send},3},
    -               {{{0,258,0},send,{'Result-Code',2001}},3},
    -               {{{0,280,1},recv},66},
    -               {{{0,280,0},send},66},
    -               {{{0,280,0},send,{'Result-Code',2001}},66},
    -               {{{0,257,1},recv},1},
    -               {{{0,257,0},send},1},
    -               {{{0,257,0},send,{'Result-Code',2001}},1}]}]]

    Note that there may be multiple entries with the same ref, in contrast to +follows.

    [[{ref,#Ref<0.0.0.61>},
    +  {type,accept},
    +  {options,[{transport_module,diameter_tcp},
    +            {transport_config,[{reuseaddr,true},
    +                               {ip,{127,0,0,1}},
    +                               {port,3868}]}]},
    +  {watchdog,{<0.56.0>,-576460739249514012,okay}},
    +  {peer,{<0.58.0>,-576460638229179167}},
    +  {apps,[{0,common}]},
    +  {caps,[{origin_host,{"server.example.com","client.example.com"}},
    +         {origin_realm,{"example.com","example.com"}},
    +         {host_ip_address,{[{127,0,0,1}],[{127,0,0,1}]}},
    +         {vendor_id,{193,0}},
    +         {product_name,{"Server","Client"}},
    +         {origin_state_id,{[],[]}},
    +         {supported_vendor_id,{[],[]}},
    +         {auth_application_id,{[0],[0]}},
    +         {inband_security_id,{[],[]}},
    +         {acct_application_id,{[],[]}},
    +         {vendor_specific_application_id,{[],[]}},
    +         {firmware_revision,{[],[]}},
    +         {avp,{[],[]}}]},
    +  {port,[{owner,<0.62.0>},
    +         {module,diameter_tcp},
    +         {socket,{{127,0,0,1},3868}},
    +         {peer,{{127,0,0,1},48758}},
    +         {statistics,[{recv_oct,10124},
    +                      {recv_cnt,132},
    +                      {recv_max,184},
    +                      {recv_avg,76},
    +                      {recv_dvi,9},
    +                      {send_oct,10016},
    +                      {send_cnt,132},
    +                      {send_max,148},
    +                      {send_avg,75},
    +                      {send_pend,0}]}]},
    +  {statistics,[{{{0,280,0},recv},62},
    +               {{{0,280,1},send},62},
    +               {{{0,280,0},recv,{'Result-Code',2001}},62},
    +               {{{0,258,1},recv},3},
    +               {{{0,258,0},send},3},
    +               {{{0,258,0},send,{'Result-Code',2001}},3},
    +               {{{0,280,1},recv},66},
    +               {{{0,280,0},send},66},
    +               {{{0,280,0},send,{'Result-Code',2001}},66},
    +               {{{0,257,1},recv},1},
    +               {{{0,257,0},send},1},
    +               {{{0,257,0},send,{'Result-Code',2001}},1}]}]]

    Note that there may be multiple entries with the same ref, in contrast to transport info.

  • statistics - Return a {{Counter, Ref}, non_neg_integer()} list of counter values. Ref can be either a transport_ref() or a @@ -2797,12 +2797,12 @@

    service_info(SvcName, Option)

    configuration associated with a single peer, as passed to add_transport/2. The returned list is empty if the peer is unknown. Otherwise it contains the ref, type and options tuples as in transport and connections info -above. For example:

    [{ref,#Ref<0.0.0.61>},
    - {type,accept},
    - {options,[{transport_module,diameter_tcp},
    -           {transport_config,[{reuseaddr,true},
    -                              {ip,{127,0,0,1}},
    -                              {port,3868}]}]}]
  • +above. For example:

    [{ref,#Ref<0.0.0.61>},
    + {type,accept},
    + {options,[{transport_module,diameter_tcp},
    +           {transport_config,[{reuseaddr,true},
    +                              {ip,{127,0,0,1}},
    +                              {port,3868}]}]}]
    diff --git a/prs/9045/lib/diameter-2.4.1/doc/html/diameter_app.html b/prs/9045/lib/diameter-2.4.1/doc/html/diameter_app.html index d1cc039f678f..994a8f5c6bd9 100644 --- a/prs/9045/lib/diameter-2.4.1/doc/html/diameter_app.html +++ b/prs/9045/lib/diameter-2.4.1/doc/html/diameter_app.html @@ -725,12 +725,12 @@

    handle_request(Packet, SvcName, Peer)

    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 diff --git a/prs/9045/lib/diameter-2.4.1/doc/html/diameter_codec.html b/prs/9045/lib/diameter-2.4.1/doc/html/diameter_codec.html index 7c6eab45a5be..fefc1fc5d2d8 100644 --- a/prs/9045/lib/diameter-2.4.1/doc/html/diameter_codec.html +++ b/prs/9045/lib/diameter-2.4.1/doc/html/diameter_codec.html @@ -145,7 +145,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.

    diff --git a/prs/9045/lib/diameter-2.4.1/doc/html/diameter_dict.html b/prs/9045/lib/diameter-2.4.1/doc/html/diameter_dict.html index f276275da913..838c30a01324 100644 --- a/prs/9045/lib/diameter-2.4.1/doc/html/diameter_dict.html +++ b/prs/9045/lib/diameter-2.4.1/doc/html/diameter_dict.html @@ -315,14 +315,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()
    @@ -330,14 +330,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
    @@ -365,8 +365,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.

    +hrl file.

    IPFilterRule()  = OctetString()
    +QoSFilterRule() = OctetString()

    Values of these types are not currently parsed by diameter.

    diff --git a/prs/9045/lib/diameter-2.4.1/doc/html/diameterc_cmd.html b/prs/9045/lib/diameter-2.4.1/doc/html/diameterc_cmd.html index ab9d5ba0081d..e1372bd46411 100644 --- a/prs/9045/lib/diameter-2.4.1/doc/html/diameterc_cmd.html +++ b/prs/9045/lib/diameter-2.4.1/doc/html/diameterc_cmd.html @@ -137,7 +137,7 @@

    Synopsis

    -
    diameterc [<options>] <file>

    +
    diameterc [<options>] <file>

    diff --git a/prs/9045/lib/edoc-1.3.2/doc/html/edoc_doclet_markdown.html b/prs/9045/lib/edoc-1.3.2/doc/html/edoc_doclet_markdown.html index 3cc915c3120d..15b38aff3950 100644 --- a/prs/9045/lib/edoc-1.3.2/doc/html/edoc_doclet_markdown.html +++ b/prs/9045/lib/edoc-1.3.2/doc/html/edoc_doclet_markdown.html @@ -134,8 +134,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.

    diff --git a/prs/9045/lib/eldap-1.2.13/doc/html/eldap.epub b/prs/9045/lib/eldap-1.2.13/doc/html/eldap.epub index e2a5cc426e3d..ca80ae3385e9 100644 Binary files a/prs/9045/lib/eldap-1.2.13/doc/html/eldap.epub and b/prs/9045/lib/eldap-1.2.13/doc/html/eldap.epub differ diff --git a/prs/9045/lib/eldap-1.2.13/doc/html/eldap.html b/prs/9045/lib/eldap-1.2.13/doc/html/eldap.html index 7d3e771e23eb..81c33b17791d 100644 --- a/prs/9045/lib/eldap-1.2.13/doc/html/eldap.html +++ b/prs/9045/lib/eldap-1.2.13/doc/html/eldap.html @@ -981,13 +981,13 @@

    add(Handle, Dn, Attributes)

    -

    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"]}] + )
    @@ -1299,7 +1299,7 @@

    extensibleMatch(MatchValue, OptionalAttrs)< -

    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.

    @@ -1517,9 +1517,9 @@

    modify(Handle, Dn, ModifyOps)

    -

    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"]) ])
    @@ -1839,8 +1839,8 @@

    paged_result_control(PageSize)

    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]),
    @@ -1873,12 +1873,12 @@

    paged_result_control(PageSize, Cookie)

    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
    @@ -1998,8 +1998,8 @@

    search(Handle, SearchOptions)

    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.

    diff --git a/prs/9045/lib/erl_interface-5.5.2/doc/html/ei.html b/prs/9045/lib/erl_interface-5.5.2/doc/html/ei.html index 70f5edc71210..86d6e79cb42d 100644 --- a/prs/9045/lib/erl_interface-5.5.2/doc/html/ei.html +++ b/prs/9045/lib/erl_interface-5.5.2/doc/html/ei.html @@ -157,30 +157,30 @@

    Data Types

    -
    • ei_term

      typedef struct {
      +
      • 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 @@ -196,7 +196,7 @@

    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 +

    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

    @@ -205,7 +205,7 @@

    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 +

    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

    @@ -214,7 +214,7 @@

    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 +

    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

    @@ -222,15 +222,15 @@

    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 +

    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 +

    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, @@ -245,7 +245,7 @@

    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 +

    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.

    @@ -253,7 +253,7 @@

    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 +

    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().

    @@ -262,8 +262,8 @@

    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.

    • pp - Either NULL or *pp returns a pointer to the first byte of the +

      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.

      • pp - Either NULL or *pp returns a pointer to the first byte of the bit string. The returned bit string is readable as long as the buffer pointed to by buf is readable and not written to.

      • bitoffsp - Either NULL or *bitoffsp returns the number of unused bits in the first byte pointed to by *pp. The value of *bitoffsp is @@ -279,14 +279,14 @@

        ei_decode_boolean()

        -
        int ei_decode_boolean(const char *buf, int *index, int *p);

        Decodes a boolean value from the binary format. A boolean is actually an atom, +

        int ei_decode_boolean(const char *buf, int *index, int *p);

        Decodes a boolean value from the binary format. A boolean is actually an atom, true decodes 1 and false decodes 0.

        ei_decode_char()

        -
        int ei_decode_char(const char *buf, int *index, char *p);

        Decodes a char (8-bit) integer between 0-255 from the binary format. For +

        int ei_decode_char(const char *buf, int *index, char *p);

        Decodes a char (8-bit) integer between 0-255 from the binary format. For historical reasons the returned integer is of type char. Your C code is to consider the returned value to be of type unsigned char even if the C compilers and system can define char to be signed.

        @@ -295,14 +295,14 @@

        ei_decode_double()

        -
        int ei_decode_double(const char *buf, int *index, double *p);

        Decodes a double-precision (64-bit) floating point number from the binary +

        int ei_decode_double(const char *buf, int *index, double *p);

        Decodes a double-precision (64-bit) floating point number from the binary format.

        ei_decode_ei_term()

        -
        int ei_decode_ei_term(const char* buf, int* index, ei_term* term);

        Decodes any term, or at least tries to. If the term pointed at by *index in +

        int ei_decode_ei_term(const char* buf, int* index, ei_term* term);

        Decodes any term, or at least tries to. If the term pointed at by *index in buf fits in the term union, it is decoded, and the appropriate field in term->value is set, and *index is incremented by the term size.

        The function returns 1 on successful decoding, -1 on error, and 0 if the term seems alright, but does not fit in the term structure. If 1 is @@ -320,7 +320,7 @@

        free_fun()

        -
        int ei_decode_fun(const char *buf, int *index, erlang_fun *p);
        void free_fun(erlang_fun* f);

        Decodes a fun from the binary format. Parameter p is to be NULL or point to +

        int ei_decode_fun(const char *buf, int *index, erlang_fun *p);
        void free_fun(erlang_fun* f);

        Decodes a fun from the binary format. Parameter p is to be NULL or point to an erlang_fun structure. This is the only decode function that allocates memory. When the erlang_fun is no longer needed, it is to be freed with free_fun. (This has to do with the arbitrary size of the environment for a @@ -330,7 +330,7 @@

        ei_decode_iodata()

        -
        int ei_decode_iodata(const char *buf, int *index, int *size, char *outbuf);

        Decodes a term of the type iodata(). +

        int ei_decode_iodata(const char *buf, int *index, int *size, char *outbuf);

        Decodes a term of the type iodata(). The iodata/0 term will be flattened an written into the buffer pointed to by the outbuf argument. The byte size of the iodata is written into the integer variable pointed to by the size argument. Both size and outbuf can be set @@ -351,7 +351,7 @@

        ei_decode_list_header()

        -
        int ei_decode_list_header(const char *buf, int *index, int *arity);

        Decodes a list header from the binary format. The number of elements is returned +

        int ei_decode_list_header(const char *buf, int *index, int *arity);

        Decodes a list header from the binary format. The number of elements is returned in arity. The arity+1 elements follow (the last one is the tail of the list, normally an empty list). If arity is 0, it is an empty list.

        Notice that lists are encoded as strings if they consist entirely of integers in the range 0..255. This function do not decode such strings, use @@ -361,21 +361,21 @@

        ei_decode_long()

        -
        int ei_decode_long(const char *buf, int *index, long *p);

        Decodes a long integer from the binary format. If the code is 64 bits, the +

        int ei_decode_long(const char *buf, int *index, long *p);

        Decodes a long integer from the binary format. If the code is 64 bits, the function ei_decode_long() is the same as ei_decode_longlong().

        ei_decode_longlong()

        -
        int ei_decode_longlong(const char *buf, int *index, long long *p);

        Decodes a GCC long long or Visual C++ __int64 (64-bit) integer from the +

        int ei_decode_longlong(const char *buf, int *index, long long *p);

        Decodes a GCC long long or Visual C++ __int64 (64-bit) integer from the binary format.

        ei_decode_map_header()

        -
        int ei_decode_map_header(const char *buf, int *index, int *arity);

        Decodes a map header from the binary format. The number of key-value pairs is +

        int ei_decode_map_header(const char *buf, int *index, int *arity);

        Decodes a map header from the binary format. The number of key-value pairs is returned in *arity. Keys and values follow in this order: K1, V1, K2, V2, ..., Kn, Vn. This makes a total of arity*2 terms. If arity is zero, it is an empty map. A correctly encoded map does not have duplicate @@ -385,25 +385,25 @@

        ei_decode_pid()

        -
        int ei_decode_pid(const char *buf, int *index, erlang_pid *p);

        Decodes a process identifier (pid) from the binary format.

        +
        int ei_decode_pid(const char *buf, int *index, erlang_pid *p);

        Decodes a process identifier (pid) from the binary format.

        ei_decode_port()

        -
        int ei_decode_port(const char *buf, int *index, erlang_port *p);

        Decodes a port identifier from the binary format.

        +
        int ei_decode_port(const char *buf, int *index, erlang_port *p);

        Decodes a port identifier from the binary format.

        ei_decode_ref()

        -
        int ei_decode_ref(const char *buf, int *index, erlang_ref *p);

        Decodes a reference from the binary format.

        +
        int ei_decode_ref(const char *buf, int *index, erlang_ref *p);

        Decodes a reference from the binary format.

        ei_decode_string()

        -
        int ei_decode_string(const char *buf, int *index, char *p);

        Decodes a string from the binary format. A string in Erlang is a list of +

        int ei_decode_string(const char *buf, int *index, char *p);

        Decodes a string from the binary format. A string in Erlang is a list of integers between 0 and 255. Notice that as the string is just a list, sometimes lists are encoded as strings by term_to_binary/1, even if it was not intended.

        The string is copied to p, and enough space must be allocated. The returned @@ -414,34 +414,34 @@

        ei_decode_trace()

        -
        int ei_decode_trace(const char *buf, int *index, erlang_trace *p);

        Decodes an Erlang trace token from the binary format.

        +
        int ei_decode_trace(const char *buf, int *index, erlang_trace *p);

        Decodes an Erlang trace token from the binary format.

        ei_decode_tuple_header()

        -
        int ei_decode_tuple_header(const char *buf, int *index, int *arity);

        Decodes a tuple header, the number of elements is returned in arity. The tuple +

        int ei_decode_tuple_header(const char *buf, int *index, int *arity);

        Decodes a tuple header, the number of elements is returned in arity. The tuple elements follow in order in the buffer.

        ei_decode_ulong()

        -
        int ei_decode_ulong(const char *buf, int *index, unsigned long *p);

        Decodes an unsigned long integer from the binary format. If the code is 64 bits, +

        int ei_decode_ulong(const char *buf, int *index, unsigned long *p);

        Decodes an unsigned long integer from the binary format. If the code is 64 bits, the function ei_decode_ulong() is the same as ei_decode_ulonglong().

        ei_decode_ulonglong()

        -
        int ei_decode_ulonglong(const char *buf, int *index, unsigned long long *p);

        Decodes a GCC unsigned long long or Visual C++ unsigned __int64 (64-bit) +

        int ei_decode_ulonglong(const char *buf, int *index, unsigned long long *p);

        Decodes a GCC unsigned long long or Visual C++ unsigned __int64 (64-bit) integer from the binary format.

        ei_decode_version()

        -
        int ei_decode_version(const char *buf, int *index, int *version);

        Decodes the version magic number for the Erlang binary term format. It must be +

        int ei_decode_version(const char *buf, int *index, int *version);

        Decodes the version magic number for the Erlang binary term format. It must be the first token in a binary term.

        @@ -466,7 +466,7 @@

        ei_x_encode_atom_len()

        -
        int ei_encode_atom(char *buf, int *index, const char *p);
        int ei_encode_atom_len(char *buf, int *index, const char *p, int len);
        int ei_x_encode_atom(ei_x_buff* x, const char *p);
        int ei_x_encode_atom_len(ei_x_buff* x, const char *p, int len);

        Encodes an atom in the binary format. Parameter p is the name of the atom in +

        int ei_encode_atom(char *buf, int *index, const char *p);
        int ei_encode_atom_len(char *buf, int *index, const char *p, int len);
        int ei_x_encode_atom(ei_x_buff* x, const char *p);
        int ei_x_encode_atom_len(ei_x_buff* x, const char *p, int len);

        Encodes an atom in the binary format. Parameter p is the name of the atom in Latin-1 encoding. Only up to MAXATOMLEN-1 bytes are encoded. The name is to be NULL-terminated, except for the ei_x_encode_atom_len() function.

        @@ -492,11 +492,11 @@

        ei_x_encode_atom_len_as()

        -
        int ei_encode_atom_as(char *buf, int *index, const char *p,
        -  erlang_char_encoding from_enc, erlang_char_encoding to_enc);
        int ei_encode_atom_len_as(char *buf, int *index, const char *p, int len,
        -  erlang_char_encoding from_enc, erlang_char_encoding to_enc);
        int ei_x_encode_atom_as(ei_x_buff* x, const char *p,
        -  erlang_char_encoding from_enc, erlang_char_encoding to_enc);
        int ei_x_encode_atom_len_as(ei_x_buff* x, const char *p, int len,
        -  erlang_char_encoding from_enc, erlang_char_encoding to_enc);

        Encodes an atom in the binary format. Parameter p is the name of the atom with +

        int ei_encode_atom_as(char *buf, int *index, const char *p,
        +  erlang_char_encoding from_enc, erlang_char_encoding to_enc);
        int ei_encode_atom_len_as(char *buf, int *index, const char *p, int len,
        +  erlang_char_encoding from_enc, erlang_char_encoding to_enc);
        int ei_x_encode_atom_as(ei_x_buff* x, const char *p,
        +  erlang_char_encoding from_enc, erlang_char_encoding to_enc);
        int ei_x_encode_atom_len_as(ei_x_buff* x, const char *p, int len,
        +  erlang_char_encoding from_enc, erlang_char_encoding to_enc);

        Encodes an atom in the binary format. Parameter p is the name of the atom with character encoding from_enc (ASCII, Latin-1, or UTF-8). The name must either be NULL-terminated or a function variant with a len parameter must be used.

        The encoding fails if p is not a valid string in encoding from_enc.

        Argument to_enc is ignored. As from Erlang/OTP 20 the encoding is always done @@ -512,7 +512,7 @@

        ei_x_encode_bignum()

        -
        int ei_encode_bignum(char *buf, int *index, mpz_t obj);
        int ei_x_encode_bignum(ei_x_buff *x, mpz_t obj);

        Encodes a GMP mpz_t integer to binary format. To use this function, the ei +

        int ei_encode_bignum(char *buf, int *index, mpz_t obj);
        int ei_x_encode_bignum(ei_x_buff *x, mpz_t obj);

        Encodes a GMP mpz_t integer to binary format. To use this function, the ei library must be configured and compiled to use the GMP library.

        @@ -525,7 +525,7 @@

        ei_x_encode_binary()

        -
        int ei_encode_binary(char *buf, int *index, const void *p, long len);
        int ei_x_encode_binary(ei_x_buff* x, const void *p, long len);

        Encodes a binary in the binary format. The data is at p, of len bytes +

        int ei_encode_binary(char *buf, int *index, const void *p, long len);
        int ei_x_encode_binary(ei_x_buff* x, const void *p, long len);

        Encodes a binary in the binary format. The data is at p, of len bytes length.

        @@ -538,7 +538,7 @@

        ei_x_encode_bitstring()

        -
        int ei_encode_bitstring(char *buf, int *index, const char *p, size_t bitoffs, size_t nbits);
        int ei_x_encode_bitstring(ei_x_buff* x, const char *p, size_t bitoffs, size_t nbits);

        Encodes a bit string in the binary format.

        The data is at p. The length of the bit string is nbits bits. The first +

        int ei_encode_bitstring(char *buf, int *index, const char *p, size_t bitoffs, size_t nbits);
        int ei_x_encode_bitstring(ei_x_buff* x, const char *p, size_t bitoffs, size_t nbits);

        Encodes a bit string in the binary format.

        The data is at p. The length of the bit string is nbits bits. The first bitoffs bits of the data at p are unused. The first byte which is part of the bit string is p[bitoffs/8]. The bitoffs%8 most significant bits of the first byte p[bitoffs/8] are unused.

        The number of bytes which is part of the bit string is @@ -556,7 +556,7 @@

        ei_x_encode_boolean()

        -
        int ei_encode_boolean(char *buf, int *index, int p);
        int ei_x_encode_boolean(ei_x_buff* x, int p);

        Encodes a boolean value as the atom true if p is not zero, or false if p +

        int ei_encode_boolean(char *buf, int *index, int p);
        int ei_x_encode_boolean(ei_x_buff* x, int p);

        Encodes a boolean value as the atom true if p is not zero, or false if p is zero.

        @@ -569,7 +569,7 @@

        ei_x_encode_char()

        -
        int ei_encode_char(char *buf, int *index, char p);
        int ei_x_encode_char(ei_x_buff* x, char p);

        Encodes a char (8-bit) as an integer between 0-255 in the binary format. For +

        int ei_encode_char(char *buf, int *index, char p);
        int ei_x_encode_char(ei_x_buff* x, char p);

        Encodes a char (8-bit) as an integer between 0-255 in the binary format. For historical reasons the integer argument is of type char. Your C code is to consider the specified argument to be of type unsigned char even if the C compilers and system may define char to be signed.

        @@ -584,7 +584,7 @@

        ei_x_encode_double()

        -
        int ei_encode_double(char *buf, int *index, double p);
        int ei_x_encode_double(ei_x_buff* x, double p);

        Encodes a double-precision (64-bit) floating point number in the binary format.

        Returns -1 if the floating point number is not finite.

        +
        int ei_encode_double(char *buf, int *index, double p);
        int ei_x_encode_double(ei_x_buff* x, double p);

        Encodes a double-precision (64-bit) floating point number in the binary format.

        Returns -1 if the floating point number is not finite.

        @@ -596,7 +596,7 @@

        ei_x_encode_empty_list()

        -
        int ei_encode_empty_list(char* buf, int* index);
        int ei_x_encode_empty_list(ei_x_buff* x);

        Encodes an empty list. It is often used at the tail of a list.

        +
        int ei_encode_empty_list(char* buf, int* index);
        int ei_x_encode_empty_list(ei_x_buff* x);

        Encodes an empty list. It is often used at the tail of a list.

        @@ -608,7 +608,7 @@

        ei_x_encode_fun()

        -
        int ei_encode_fun(char *buf, int *index, const erlang_fun *p);
        int ei_x_encode_fun(ei_x_buff* x, const erlang_fun* fun);

        Encodes a fun in the binary format. Parameter p points to an erlang_fun +

        int ei_encode_fun(char *buf, int *index, const erlang_fun *p);
        int ei_x_encode_fun(ei_x_buff* x, const erlang_fun* fun);

        Encodes a fun in the binary format. Parameter p points to an erlang_fun structure. The erlang_fun is not freed automatically, the free_fun is to be called if the fun is not needed after encoding.

        @@ -622,23 +622,23 @@

        ei_x_encode_list_header()

        -
        int ei_encode_list_header(char *buf, int *index, int arity);
        int ei_x_encode_list_header(ei_x_buff* x, int arity);

        Encodes a list header, with a specified arity. The next arity+1 terms are the +

        int ei_encode_list_header(char *buf, int *index, int arity);
        int ei_x_encode_list_header(ei_x_buff* x, int arity);

        Encodes a list header, with a specified arity. The next arity+1 terms are the elements (actually its arity cons cells) and the tail of the list. Lists and tuples are encoded recursively, so that a list can contain another list or -tuple.

        For example, to encode the list [c, d, [e | f]]:

        ei_encode_list_header(buf, &i, 3);
        -ei_encode_atom(buf, &i, "c");
        -ei_encode_atom(buf, &i, "d");
        -ei_encode_list_header(buf, &i, 1);
        -ei_encode_atom(buf, &i, "e");
        -ei_encode_atom(buf, &i, "f");
        -ei_encode_empty_list(buf, &i);

        Note

        It may seem that there is no way to create a list without knowing the number +tuple.

        For example, to encode the list [c, d, [e | f]]:

        ei_encode_list_header(buf, &i, 3);
        +ei_encode_atom(buf, &i, "c");
        +ei_encode_atom(buf, &i, "d");
        +ei_encode_list_header(buf, &i, 1);
        +ei_encode_atom(buf, &i, "e");
        +ei_encode_atom(buf, &i, "f");
        +ei_encode_empty_list(buf, &i);

        Note

        It may seem that there is no way to create a list without knowing the number of elements in advance. But indeed there is a way. Notice that the list [a, b, c] can be written as [a | [b | [c]]]. Using this, a list can be -written as conses.

        To encode a list, without knowing the arity in advance:

        while (something()) {
        -    ei_x_encode_list_header(&x, 1);
        -    ei_x_encode_ulong(&x, i); /* just an example */
        -}
        -ei_x_encode_empty_list(&x);

        +written as conses.

        To encode a list, without knowing the arity in advance:

        while (something()) {
        +    ei_x_encode_list_header(&x, 1);
        +    ei_x_encode_ulong(&x, i); /* just an example */
        +}
        +ei_x_encode_empty_list(&x);

        @@ -650,7 +650,7 @@

        ei_x_encode_long()

        -
        int ei_encode_long(char *buf, int *index, long p);
        int ei_x_encode_long(ei_x_buff* x, long p);

        Encodes a long integer in the binary format. If the code is 64 bits, the +

        int ei_encode_long(char *buf, int *index, long p);
        int ei_x_encode_long(ei_x_buff* x, long p);

        Encodes a long integer in the binary format. If the code is 64 bits, the function ei_encode_long() is the same as ei_encode_longlong().

        @@ -663,7 +663,7 @@

        ei_x_encode_longlong()

        -
        int ei_encode_longlong(char *buf, int *index, long long p);
        int ei_x_encode_longlong(ei_x_buff* x, long long p);

        Encodes a GCC long long or Visual C++ __int64 (64-bit) integer in the binary +

        int ei_encode_longlong(char *buf, int *index, long long p);
        int ei_x_encode_longlong(ei_x_buff* x, long long p);

        Encodes a GCC long long or Visual C++ __int64 (64-bit) integer in the binary format.

        @@ -676,13 +676,13 @@

        ei_x_encode_map_header()

        -
        int ei_encode_map_header(char *buf, int *index, int arity);
        int ei_x_encode_map_header(ei_x_buff* x, int arity);

        Encodes a map header, with a specified arity. The next arity*2 terms encoded +

        int ei_encode_map_header(char *buf, int *index, int arity);
        int ei_x_encode_map_header(ei_x_buff* x, int arity);

        Encodes a map header, with a specified arity. The next arity*2 terms encoded will be the keys and values of the map encoded in the following order: -K1, V1, K2, V2, ..., Kn, Vn.

        For example, to encode the map #{a => "Apple", b => "Banana"}:

        ei_x_encode_map_header(&x, 2);
        -ei_x_encode_atom(&x, "a");
        -ei_x_encode_string(&x, "Apple");
        -ei_x_encode_atom(&x, "b");
        -ei_x_encode_string(&x, "Banana");

        A correctly encoded map cannot have duplicate keys.

        Available since OTP 17.0

        +K1, V1, K2, V2, ..., Kn, Vn.

        For example, to encode the map #{a => "Apple", b => "Banana"}:

        ei_x_encode_map_header(&x, 2);
        +ei_x_encode_atom(&x, "a");
        +ei_x_encode_string(&x, "Apple");
        +ei_x_encode_atom(&x, "b");
        +ei_x_encode_string(&x, "Banana");

        A correctly encoded map cannot have duplicate keys.

        Available since OTP 17.0

        @@ -694,7 +694,7 @@

        ei_x_encode_pid()

        -
        int ei_encode_pid(char *buf, int *index, const erlang_pid *p);
        int ei_x_encode_pid(ei_x_buff* x, const erlang_pid *p);

        Encodes an Erlang process identifier (pid) in the binary format. Parameter p +

        int ei_encode_pid(char *buf, int *index, const erlang_pid *p);
        int ei_x_encode_pid(ei_x_buff* x, const erlang_pid *p);

        Encodes an Erlang process identifier (pid) in the binary format. Parameter p points to an erlang_pid structure which should either have been obtained earlier with ei_decode_pid(), ei_self() or created by @@ -710,7 +710,7 @@

        ei_x_encode_port()

        -
        int ei_encode_port(char *buf, int *index, const erlang_port *p);
        int ei_x_encode_port(ei_x_buff* x, const erlang_port *p);

        Encodes an Erlang port in the binary format. Parameter p points to an +

        int ei_encode_port(char *buf, int *index, const erlang_port *p);
        int ei_x_encode_port(ei_x_buff* x, const erlang_port *p);

        Encodes an Erlang port in the binary format. Parameter p points to an erlang_port structure which should have been obtained earlier with ei_decode_port(),

        @@ -724,7 +724,7 @@

        ei_x_encode_ref()

        -
        int ei_encode_ref(char *buf, int *index, const erlang_ref *p);
        int ei_x_encode_ref(ei_x_buff* x, const erlang_ref *p);

        Encodes an Erlang reference in the binary format. Parameter p points to an +

        int ei_encode_ref(char *buf, int *index, const erlang_ref *p);
        int ei_x_encode_ref(ei_x_buff* x, const erlang_ref *p);

        Encodes an Erlang reference in the binary format. Parameter p points to an erlang_ref structure which either should have been obtained earlier with ei_decode_ref(), or created by ei_make_ref().

        @@ -751,7 +751,7 @@

        ei_x_encode_string_len()

        -
        int ei_encode_string(char *buf, int *index, const char *p);
        int ei_encode_string_len(char *buf, int *index, const char *p, int len);
        int ei_x_encode_string(ei_x_buff* x, const char *p);
        int ei_x_encode_string_len(ei_x_buff* x, const char* s, int len);

        Encodes a string in the binary format. (A string in Erlang is a list, but is +

        int ei_encode_string(char *buf, int *index, const char *p);
        int ei_encode_string_len(char *buf, int *index, const char *p, int len);
        int ei_x_encode_string(ei_x_buff* x, const char *p);
        int ei_x_encode_string_len(ei_x_buff* x, const char* s, int len);

        Encodes a string in the binary format. (A string in Erlang is a list, but is encoded as a character array in the binary format.) The string is to be NULL-terminated, except for the ei_x_encode_string_len() function.

        @@ -765,7 +765,7 @@

        ei_x_encode_trace()

        -
        int ei_encode_trace(char *buf, int *index, const erlang_trace *p);
        int ei_x_encode_trace(ei_x_buff* x, const erlang_trace *p);

        Encodes an Erlang trace token in the binary format. Parameter p points to a +

        int ei_encode_trace(char *buf, int *index, const erlang_trace *p);
        int ei_x_encode_trace(ei_x_buff* x, const erlang_trace *p);

        Encodes an Erlang trace token in the binary format. Parameter p points to a erlang_trace structure which should have been obtained earlier with ei_decode_trace().

        @@ -779,13 +779,13 @@

        ei_x_encode_tuple_header()

        -
        int ei_encode_tuple_header(char *buf, int *index, int arity);
        int ei_x_encode_tuple_header(ei_x_buff* x, int arity);

        Encodes a tuple header, with a specified arity. The next arity terms encoded +

        int ei_encode_tuple_header(char *buf, int *index, int arity);
        int ei_x_encode_tuple_header(ei_x_buff* x, int arity);

        Encodes a tuple header, with a specified arity. The next arity terms encoded will be the elements of the tuple. Tuples and lists are encoded recursively, so -that a tuple can contain another tuple or list.

        For example, to encode the tuple {a, {b, {}}}:

        ei_encode_tuple_header(buf, &i, 2);
        -ei_encode_atom(buf, &i, "a");
        -ei_encode_tuple_header(buf, &i, 2);
        -ei_encode_atom(buf, &i, "b");
        -ei_encode_tuple_header(buf, &i, 0);

        +that a tuple can contain another tuple or list.

        For example, to encode the tuple {a, {b, {}}}:

        ei_encode_tuple_header(buf, &i, 2);
        +ei_encode_atom(buf, &i, "a");
        +ei_encode_tuple_header(buf, &i, 2);
        +ei_encode_atom(buf, &i, "b");
        +ei_encode_tuple_header(buf, &i, 0);

        @@ -797,7 +797,7 @@

        ei_x_encode_ulong()

        -
        int ei_encode_ulong(char *buf, int *index, unsigned long p);
        int ei_x_encode_ulong(ei_x_buff* x, unsigned long p);

        Encodes an unsigned long integer in the binary format. If the code is 64 bits, +

        int ei_encode_ulong(char *buf, int *index, unsigned long p);
        int ei_x_encode_ulong(ei_x_buff* x, unsigned long p);

        Encodes an unsigned long integer in the binary format. If the code is 64 bits, the function ei_encode_ulong() is the same as ei_encode_ulonglong().

        @@ -810,7 +810,7 @@

        ei_x_encode_ulonglong()

        -
        int ei_encode_ulonglong(char *buf, int *index, unsigned long long p);
        int ei_x_encode_ulonglong(ei_x_buff* x, unsigned long long p);

        Encodes a GCC unsigned long long or Visual C++ unsigned __int64 (64-bit) +

        int ei_encode_ulonglong(char *buf, int *index, unsigned long long p);
        int ei_x_encode_ulonglong(ei_x_buff* x, unsigned long long p);

        Encodes a GCC unsigned long long or Visual C++ unsigned __int64 (64-bit) integer in the binary format.

        @@ -823,14 +823,14 @@

        ei_x_encode_version()

        -
        int ei_encode_version(char *buf, int *index);
        int ei_x_encode_version(ei_x_buff* x);

        Encodes a version magic number for the binary format. Must be the first token in +

        int ei_encode_version(char *buf, int *index);
        int ei_x_encode_version(ei_x_buff* x);

        Encodes a version magic number for the binary format. Must be the first token in a binary term.

        ei_get_type()

        -
        int ei_get_type(const char *buf, const int *index, int *type, int *size);

        Returns the type in *type and size in *size of the encoded term. For strings +

        int ei_get_type(const char *buf, const int *index, int *type, int *size);

        Returns the type in *type and size in *size of the encoded term. For strings and atoms, size is the number of characters not including the terminating NULL. For binaries and bitstrings, *size is the number of bytes. For lists, tuples and maps, *size is the arity of the object. For bignum integers, @@ -863,7 +863,7 @@

        ei_init()

        -
        int ei_init(void);

        Initialize the ei library. This function should be called once (and only once) +

        int ei_init(void);

        Initialize the ei library. This function should be called once (and only once) before calling any other functionality in the ei library.

        On success zero is returned. On failure a posix error code is returned.

        Available since OTP 21.3

        @@ -876,7 +876,7 @@

        ei_s_print_term()

        -
        int ei_print_term(FILE* fp, const char* buf, int* index);
        int ei_s_print_term(char** s, const char* buf, int* index);

        Prints a term, in clear text, to the file specified by fp, or the buffer +

        int ei_print_term(FILE* fp, const char* buf, int* index);
        int ei_s_print_term(char** s, const char* buf, int* index);

        Prints a term, in clear text, to the file specified by fp, or the buffer pointed to by s. It tries to resemble the term printing in the Erlang shell.

        In ei_s_print_term(), parameter s is to point to a dynamically (malloc) allocated string of BUFSIZ bytes or a NULL pointer. The string can be reallocated (and *s can be updated) by this function if the result is more @@ -889,7 +889,7 @@

        ei_set_compat_rel()

        -
        void ei_set_compat_rel(unsigned release_number);

        In general, the ei library is guaranteed to be compatible with other +

        void ei_set_compat_rel(unsigned release_number);

        In general, the ei library is guaranteed to be compatible with other Erlang/OTP components that are 2 major releases older or newer than the ei library itself.

        Sometimes an exception to the above rule has to be made to make new features (or even bug fixes) possible. A call to ei_set_compat_rel(release_number) sets the @@ -914,7 +914,7 @@

        ei_skip_term()

        -
        int ei_skip_term(const char* buf, int* index);

        Skips a term in the specified buffer; recursively skips elements of lists and +

        int ei_skip_term(const char* buf, int* index);

        Skips a term in the specified buffer; recursively skips elements of lists and tuples, so that a full term is skipped. This is a way to get the size of an Erlang term.

        buf is the buffer.

        index is updated to point right after the term in the buffer.

        Note

        This can be useful when you want to hold arbitrary terms: skip them and copy the binary term data to some buffer.

        Returns 0 on success, otherwise -1.

        @@ -929,7 +929,7 @@

        ei_x_append_buf()

        -
        int ei_x_append(ei_x_buff* x, const ei_x_buff* x2);
        int ei_x_append_buf(ei_x_buff* x, const char* buf, int len);

        Appends data at the end of buffer x.

        +
        int ei_x_append(ei_x_buff* x, const ei_x_buff* x2);
        int ei_x_append_buf(ei_x_buff* x, const char* buf, int len);

        Appends data at the end of buffer x.

        @@ -941,7 +941,7 @@

        ei_x_format_wo_ver()

        -
        int ei_x_format(ei_x_buff* x, const char* fmt, ...);
        int ei_x_format_wo_ver(ei_x_buff* x, const char *fmt, ... );

        Formats a term, given as a string, to a buffer. Works like a sprintf for Erlang +

        int ei_x_format(ei_x_buff* x, const char* fmt, ...);
        int ei_x_format_wo_ver(ei_x_buff* x, const char *fmt, ... );

        Formats a term, given as a string, to a buffer. Works like a sprintf for Erlang terms. fmt contains a format string, with arguments like ~d, to insert terms from variables. The following formats are supported (with the C types given):

        ~a  An atom, char*
         ~c  A character, char
        @@ -951,14 +951,14 @@ 

        ~u A unsigned long integer, unsigned long int ~f A float, float ~d A double float, double float -~p An Erlang pid, erlang_pid*

        For example, to encode a tuple with some stuff:

        ei_x_format("{~a,~i,~d}", "numbers", 12, 3.14159)
        -encodes the tuple {numbers,12,3.14159}

        ei_x_format_wo_ver() formats into a buffer, without the initial version byte.

        Change

        Since OTP 26.2 maps can be encoded with syntax like "#{k1 => v1, k2 => v2}".

        +~p An Erlang pid, erlang_pid*

    For example, to encode a tuple with some stuff:

    ei_x_format("{~a,~i,~d}", "numbers", 12, 3.14159)
    +encodes the tuple {numbers,12,3.14159}

    ei_x_format_wo_ver() formats into a buffer, without the initial version byte.

    Change

    Since OTP 26.2 maps can be encoded with syntax like "#{k1 => v1, k2 => v2}".

    ei_x_free()

    -
    int ei_x_free(ei_x_buff* x);

    Deallocates the dynamically allocated content of the buffer referred by x. +

    int ei_x_free(ei_x_buff* x);

    Deallocates the dynamically allocated content of the buffer referred by x. After deallocation, the buff field is set to NULL.

    @@ -971,7 +971,7 @@

    ei_x_new_with_version()

    -
    int ei_x_new(ei_x_buff* x);
    int ei_x_new_with_version(ei_x_buff* x);

    Initialize the dynamically realizable buffer referred to by x. The fields of +

    int ei_x_new(ei_x_buff* x);
    int ei_x_new_with_version(ei_x_buff* x);

    Initialize the dynamically realizable buffer referred to by x. The fields of the structure pointed to by parameter x is filled in, and a default buffer is allocated. ei_x_new_with_version() also puts an initial version byte, which is used in the binary format (so that ei_x_encode_version() will not be needed.)

    diff --git a/prs/9045/lib/erl_interface-5.5.2/doc/html/ei_connect.html b/prs/9045/lib/erl_interface-5.5.2/doc/html/ei_connect.html index 40e9694a4de2..546007d3fff3 100644 --- a/prs/9045/lib/erl_interface-5.5.2/doc/html/ei_connect.html +++ b/prs/9045/lib/erl_interface-5.5.2/doc/html/ei_connect.html @@ -247,36 +247,36 @@

    • ei_cnode - Opaque data type representing a C-node. A ei_cnode structure is initialized by calling -ei_connect_init() or friends.

    • ei_socket_callbacks

      typedef struct {
      +ei_connect_init() or friends.

    • ei_socket_callbacks

      typedef struct {
           int flags;
      -    int (*socket)(void **ctx, void *setup_ctx);
      -    int   (*close)(void *ctx);
      -    int (*listen)(void *ctx, void *addr, int *len, int backlog);
      -    int (*accept)(void **ctx, void *addr, int *len, unsigned tmo);
      -    int (*connect)(void *ctx, void *addr, int len, unsigned tmo);
      -    int (*writev)(void *ctx, const void *iov, int iovcnt, ssize_t *len, unsigned tmo);
      -    int (*write)(void *ctx, const char *buf, ssize_t *len, unsigned tmo);
      -    int (*read)(void *ctx, char *buf, ssize_t *len, unsigned tmo);
      -    int (*handshake_packet_header_size)(void *ctx, int *sz);
      -    int (*connect_handshake_complete)(void *ctx);
      -    int (*accept_handshake_complete)(void *ctx);
      -    int (*get_fd)(void *ctx, int *fd);
      -} ei_socket_callbacks;

      Callbacks functions for a + int (*socket)(void **ctx, void *setup_ctx); + int (*close)(void *ctx); + int (*listen)(void *ctx, void *addr, int *len, int backlog); + int (*accept)(void **ctx, void *addr, int *len, unsigned tmo); + int (*connect)(void *ctx, void *addr, int len, unsigned tmo); + int (*writev)(void *ctx, const void *iov, int iovcnt, ssize_t *len, unsigned tmo); + int (*write)(void *ctx, const char *buf, ssize_t *len, unsigned tmo); + int (*read)(void *ctx, char *buf, ssize_t *len, unsigned tmo); + int (*handshake_packet_header_size)(void *ctx, int *sz); + int (*connect_handshake_complete)(void *ctx); + int (*accept_handshake_complete)(void *ctx); + int (*get_fd)(void *ctx, int *fd); +} ei_socket_callbacks;

    Callbacks functions for a User Supplied Socket Implementation. Documentation of each field can be -found in the User Supplied Socket Implementation section above.

  • ErlConnect

    typedef struct {
    -    char ipadr[4]; /* Ip v4 address in network byte order */
    -    char nodename[MAXNODELEN];
    -} ErlConnect;

    IP v4 address and nodename.

  • Erl_IpAddr

    typedef struct {
    +found in the User Supplied Socket Implementation section above.

  • ErlConnect

    typedef struct {
    +    char ipadr[4]; /* Ip v4 address in network byte order */
    +    char nodename[MAXNODELEN];
    +} ErlConnect;

    IP v4 address and nodename.

  • Erl_IpAddr

    typedef struct {
         unsigned s_addr; /* Ip v4 address in network byte order */
    -} Erl_IpAddr;

    IP v4 address.

  • erlang_msg

    typedef struct {
    +} Erl_IpAddr;

    IP v4 address.

  • erlang_msg

    typedef struct {
         long msgtype;
         erlang_pid from;
         erlang_pid to;
    -    char toname[MAXATOMLEN+1];
    -    char cookie[MAXATOMLEN+1];
    +    char toname[MAXATOMLEN+1];
    +    char cookie[MAXATOMLEN+1];
         erlang_trace token;
    -} erlang_msg;

    Information about a message received via +} erlang_msg;

  • Information about a message received via ei_receive_msg() or friends.

    @@ -301,15 +301,15 @@

    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.

    +
    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.

    • ec is the C-node structure.
    • listensock is an open socket descriptor on which listen() has previously +
      int ei_accept(ei_cnode *ec, int listensock, ErlConnect *conp);

      Used by a server process to accept a connection from a client process.

      • ec is the C-node structure.
      • listensock is an open socket descriptor on which listen() has previously been called.
      • conp is a pointer to an ErlConnect struct.

      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.

      @@ -318,14 +318,14 @@

      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 +

      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

      +
      int ei_close_connection(int fd);

      Closes a previously opened connection or listen socket.

      Available since OTP 21.3

      @@ -349,7 +349,7 @@

      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 +

      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 @@ -365,12 +365,12 @@

      #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

    +addr.s_addr = inet_addr(IP_ADDR); +fd = ei_xconnect(&ec, &addr, ALIVE);

    Available since OTP 23.0

    @@ -394,11 +394,11 @@

    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,
    +
    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.

    • ec is a structure containing information about the C-node. It is used in @@ -421,20 +421,20 @@

      see the relevant system documentation.

      These functions return a negative value indicating that an error occurred.

      Example 1:

      unsigned n = 0;
       struct in_addr addr;
       ei_cnode ec;
      -addr.s_addr = inet_addr("150.236.14.75");
      -if (ei_connect_xinit(&ec,
      +addr.s_addr = inet_addr("150.236.14.75");
      +if (ei_connect_xinit(&ec,
                            "chivas",
                            "madonna",
                            "madonna@chivas.du.etx.ericsson.se",
                            &addr;
                            "cookie...",
      -                     n++) < 0) {
      -    fprintf(stderr,"ERROR when initializing: %d",erl_errno);
      -    exit(-1);
      -}

      Example 2:

      if (ei_connect_init(&ec, "madonna", "cookie...", n++) < 0) {
      -    fprintf(stderr,"ERROR when initializing: %d",erl_errno);
      -    exit(-1);
      -}

      Available since OTP 21.3

      + n++) < 0) { + fprintf(stderr,"ERROR when initializing: %d",erl_errno); + exit(-1); +}

    Example 2:

    if (ei_connect_init(&ec, "madonna", "cookie...", n++) < 0) {
    +    fprintf(stderr,"ERROR when initializing: %d",erl_errno);
    +    exit(-1);
    +}

    Available since OTP 21.3

    @@ -458,7 +458,7 @@

    ei_xconnect_host_port_tmo()

    -
    int ei_connect_tmo(ei_cnode* ec, char *nodename, unsigned timeout_ms);
    int ei_xconnect_tmo(ei_cnode* ec, Erl_IpAddr adr, char *alivename, unsigned timeout_ms);
    int ei_connect_host_port_tmo(ei_cnode* ec, char *hostname, int port, unsigned ms);
    int ei_xconnect_host_port_tmo(ei_cnode* ec, Erl_IpAddr adr, int port, unsigned ms);

    Equivalent to ei_connect, ei_xconnect, ei_connect_host_port and +

    int ei_connect_tmo(ei_cnode* ec, char *nodename, unsigned timeout_ms);
    int ei_xconnect_tmo(ei_cnode* ec, Erl_IpAddr adr, char *alivename, unsigned timeout_ms);
    int ei_connect_host_port_tmo(ei_cnode* ec, char *hostname, int port, unsigned ms);
    int ei_xconnect_host_port_tmo(ei_cnode* ec, Erl_IpAddr adr, int port, unsigned ms);

    Equivalent to ei_connect, ei_xconnect, ei_connect_host_port and ei_xconnect_host_port with an optional time-out argument, see the description at the beginning of this manual page.

    Available since OTP 23.0

    @@ -472,7 +472,7 @@

    ei_set_tracelevel()

    -
    int ei_get_tracelevel(void);
    void ei_set_tracelevel(int level);

    Used to set tracing on the distribution. The levels are different verbosity +

    int ei_get_tracelevel(void);
    void ei_set_tracelevel(int level);

    Used to set tracing on the distribution. The levels are different verbosity levels. A higher level means more information. See also section Debug Information.

    These functions are not thread safe.

    Available since OTP R13B04

    @@ -486,7 +486,7 @@

    ei_xlisten()

    -
    int ei_listen(ei_cnode *ec, int *port, int backlog);
    int ei_xlisten(ei_cnode *ec, Erl_IpAddr adr, int *port, int backlog);

    Used by a server process to setup a listen socket which later can be used for +

    int ei_listen(ei_cnode *ec, int *port, int backlog);
    int ei_xlisten(ei_cnode *ec, Erl_IpAddr adr, int *port, int backlog);

    Used by a server process to setup a listen socket which later can be used for accepting connections from client processes.

    • ec is the C-node structure.
    • adr is local interface to bind to.
    • port is a pointer to an integer containing the port number to bind to. If *port equals 0 when calling ei_listen(), the socket will be bound to an ephemeral port. On success, ei_listen() will update the value of *port to @@ -501,7 +501,7 @@

      ei_make_pid()

      -
      int ei_make_pid(ei_cnode *ec, erlang_pid *pid);

      Creates a new process identifier in the argument pid. This process identifier +

      int ei_make_pid(ei_cnode *ec, erlang_pid *pid);

      Creates a new process identifier in the argument pid. This process identifier refers to a conseptual process residing on the C-node identified by the argument ec. On success 0 is returned. On failure ERL_ERROR is returned and erl_errno is set.

      The C-node identified by ec must have been initialized and must have received @@ -514,7 +514,7 @@

      ei_make_ref()

      -
      int ei_make_ref(ei_cnode *ec, erlang_ref *ref);

      Creates a new reference in the argument ref. This reference originates from +

      int ei_make_ref(ei_cnode *ec, erlang_ref *ref);

      Creates a new reference in the argument ref. This reference originates from the C-node identified by the argument ec. On success 0 is returned. On failure ERL_ERROR is returned and erl_errno is set.

      The C-node identified by ec must have been initialized and must have received a name prior to the call to ei_make_ref(). Initialization of the C-node is @@ -526,7 +526,7 @@

      ei_publish()

      -
      int ei_publish(ei_cnode *ec, int port);

      Used by a server process to register with the local name server EPMD, thereby +

      int ei_publish(ei_cnode *ec, int port);

      Used by a server process to register with the local name server EPMD, thereby allowing other processes to send messages by using the registered name. Before calling either of these functions, the process should have called bind() and listen() on an open socket.

      • ec is the C-node structure.
      • port is the local name to register, and is to be the same as the port number @@ -539,14 +539,14 @@

        ei_publish_tmo()

        -
        int ei_publish_tmo(ei_cnode *ec, int port, unsigned timeout_ms);

        Equivalent to ei_publish with an optional time-out argument, see the +

        int ei_publish_tmo(ei_cnode *ec, int port, unsigned timeout_ms);

        Equivalent to ei_publish with an optional time-out argument, see the description at the beginning of this manual page.

        ei_receive()

        -
        int ei_receive(int fd, unsigned char* bufp, int bufsize);

        Receives a message consisting of a sequence of bytes in the Erlang external +

        int ei_receive(int fd, unsigned char* bufp, int bufsize);

        Receives a message consisting of a sequence of bytes in the Erlang external format.

        • fd is an open descriptor to an Erlang connection. It is obtained from a previous ei_connect or ei_accept.
        • bufp is a buffer large enough to hold the expected message.
        • bufsize indicates the size of bufp.

        If a tick occurs, that is, the Erlang node on the other end of the connection has polled this node to see if it is still alive, the function returns @@ -559,7 +559,7 @@

        ei_receive_encoded()

        -
        int ei_receive_encoded(int fd, char **mbufp, int *bufsz,  erlang_msg *msg, int *msglen);

        This function is retained for compatibility with code generated by the interface +

        int ei_receive_encoded(int fd, char **mbufp, int *bufsz,  erlang_msg *msg, int *msglen);

        This function is retained for compatibility with code generated by the interface compiler and with code following examples in the same application.

        In essence, the function performs the same operation as ei_xreceive_msg, but instead of using an ei_x_buff, the function expects a pointer to a character pointer (mbufp), where the character pointer is to point to a memory area @@ -575,8 +575,8 @@

        ei_receive_encoded_tmo()

        -
        int ei_receive_encoded_tmo(int fd, char **mbufp, int *bufsz,  erlang_msg *msg,
        -  int *msglen, unsigned timeout_ms);

        Equivalent to ei_receive_encoded with an optional time-out argument, see the +

        int ei_receive_encoded_tmo(int fd, char **mbufp, int *bufsz,  erlang_msg *msg,
        +  int *msglen, unsigned timeout_ms);

        Equivalent to ei_receive_encoded with an optional time-out argument, see the description at the beginning of this manual page.

        @@ -589,7 +589,7 @@

        ei_xreceive_msg()

        -
        int ei_receive_msg(int fd, erlang_msg* msg, ei_x_buff* x);
        int ei_xreceive_msg(int fd, erlang_msg* msg, ei_x_buff* x);

        Receives a message to the buffer in x. ei_xreceive_msg allows the buffer in +

        int ei_receive_msg(int fd, erlang_msg* msg, ei_x_buff* x);
        int ei_xreceive_msg(int fd, erlang_msg* msg, ei_x_buff* x);

        Receives a message to the buffer in x. ei_xreceive_msg allows the buffer in x to grow, but ei_receive_msg fails if the message is larger than the pre-allocated buffer in x.

        • fd is an open descriptor to an Erlang connection.
        • msg is a pointer to an erlang_msg structure and contains information on the message received.
        • x is buffer obtained from ei_x_new.

        On success, the functions return ERL_MSG and the @@ -609,33 +609,33 @@

        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 +

        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 +

        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.

        • fd is an open descriptor to an Erlang connection.
        • server_name is the registered name of the intended recipient.
        • buf is the buffer containing the term in binary format.
        • len is the length of the message in bytes.

        Returns 0 if successful, otherwise -1. In the latter case it sets +

        int ei_reg_send(ei_cnode* ec, int fd, char* server_name, char* buf, int len);

        Sends an Erlang term to a registered process.

        • fd is an open descriptor to an Erlang connection.
        • server_name is the registered name of the intended recipient.
        • buf is the buffer containing the term in binary format.
        • len is the length of the message in bytes.

        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");
        -if (ei_reg_send(&ec, fd, x.buff, x.index) < 0)
        -    handle_error();

        +ei_x_new_with_version(&x); +ei_x_encode_atom(&x, "ok"); +if (ei_reg_send(&ec, fd, x.buff, x.index) < 0) + handle_error();

    ei_reg_send_tmo()

    -
    int ei_reg_send_tmo(ei_cnode* ec, int fd, char* server_name, char* buf, int len,
    -  unsigned timeout_ms);

    Equivalent to ei_reg_send with an optional time-out argument, see the +

    int ei_reg_send_tmo(ei_cnode* ec, int fd, char* server_name, char* buf, int len,
    +  unsigned timeout_ms);

    Equivalent to ei_reg_send with an optional time-out argument, see the description at the beginning of this manual page.

    @@ -660,10 +660,10 @@

    ei_rpc_from()

    -
    int ei_rpc(ei_cnode *ec, int fd, char *mod, char *fun, const char *argbuf,
    -  int argbuflen, ei_x_buff *x);
    int ei_rpc_to(ei_cnode *ec, int fd, char *mod, char *fun, const char *argbuf,
    -  int argbuflen);
    int ei_xrpc_to(ei_cnode *ec, int fd, char *mod, char *fun, const char *argbuf,
    -  int argbuflen, int flags);
    int ei_rpc_from(ei_cnode *ec, int fd, int timeout, erlang_msg *msg, ei_x_buff *x);

    Supports calling Erlang functions on remote nodes. ei_rpc_to() sends an RPC +

    int ei_rpc(ei_cnode *ec, int fd, char *mod, char *fun, const char *argbuf,
    +  int argbuflen, ei_x_buff *x);
    int ei_rpc_to(ei_cnode *ec, int fd, char *mod, char *fun, const char *argbuf,
    +  int argbuflen);
    int ei_xrpc_to(ei_cnode *ec, int fd, char *mod, char *fun, const char *argbuf,
    +  int argbuflen, int flags);
    int ei_rpc_from(ei_cnode *ec, int fd, int timeout, erlang_msg *msg, ei_x_buff *x);

    Supports calling Erlang functions on remote nodes. ei_rpc_to() sends an RPC request to a remote node and ei_rpc_from() receives the results of such a call. ei_rpc() combines the functionality of these two functions by sending an RPC request and waiting for the results.

    The ei_xrpc_to() function is equivalent to ei_rpc_to() when its flags @@ -711,25 +711,25 @@

    functions set erl_errno to one of the following:

    • EIO - I/O error.

    • ETIMEDOUT - Time-out expired.

    • EAGAIN - Temporary error: Try again.

    Example:

    Check to see if an 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);
    +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_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();

    +if (ei_decode_version(result.buff, &index) < 0 + || ei_decode_bool(result.buff, &index, &is_alive) < 0) + handle_error();

    ei_self()

    -
    erlang_pid * ei_self(ei_cnode *ec);

    Retrieves a generic pid of the C-node. Every C-node has a (pseudo) pid used in +

    erlang_pid * ei_self(ei_cnode *ec);

    Retrieves a generic pid of the C-node. Every C-node has a (pseudo) pid used in ei_send_reg, ei_rpc(), and others. This is contained in a field in the ec structure. Do not modify this structure.

    On success a pointer to the process identifier is returned. On failure NULL is returned and erl_errno is set.

    The C-node identified by ec must have been initialized and must have received @@ -742,28 +742,28 @@

    ei_send()

    -
    int ei_send(int fd, erlang_pid* to, char* buf, int len);

    Sends an Erlang term to a process.

    • fd is an open descriptor to an Erlang connection.
    • to is the pid of the intended recipient of the message.
    • buf is the buffer containing the term in binary format.
    • len is the length of the message in bytes.

    Returns 0 if successful, otherwise -1. In the latter case it sets +

    int ei_send(int fd, erlang_pid* to, char* buf, int len);

    Sends an Erlang term to a process.

    • fd is an open descriptor to an Erlang connection.
    • to is the pid of the intended recipient of the message.
    • buf is the buffer containing the term in binary format.
    • len is the length of the message in bytes.

    Returns 0 if successful, otherwise -1. In the latter case it sets erl_errno to EIO.

    ei_send_encoded()

    -
    int ei_send_encoded(int fd, erlang_pid* to, char* buf, int len);

    Works exactly as ei_send, the alternative name is retained for backward +

    int ei_send_encoded(int fd, erlang_pid* to, char* buf, int len);

    Works exactly as ei_send, the alternative name is retained for backward compatibility. The function will not be removed without prior notice.

    ei_send_encoded_tmo()

    -
    int ei_send_encoded_tmo(int fd, erlang_pid* to, char* buf, int len, unsigned timeout_ms);

    Equivalent to ei_send_encoded with an optional time-out argument, see the +

    int ei_send_encoded_tmo(int fd, erlang_pid* to, char* buf, int len, unsigned timeout_ms);

    Equivalent to ei_send_encoded with an optional time-out argument, see the description at the beginning of this manual page.

    ei_send_reg_encoded()

    -
    int ei_send_reg_encoded(int fd, const erlang_pid *from, const char *to, const char *buf, int len);

    This function is retained for compatibility with code generated by the interface +

    int ei_send_reg_encoded(int fd, const erlang_pid *from, const char *to, const char *buf, int len);

    This function is retained for compatibility with code generated by the interface compiler and with code following examples in the same application.

    The function works as ei_reg_send with one exception. Instead of taking ei_cnode as first argument, it takes a second argument, an erlang_pid, which is to be the process identifier of the sending process (in the Erlang @@ -774,15 +774,15 @@

    ei_send_reg_encoded_tmo()

    -
    int ei_send_reg_encoded_tmo(int fd, const erlang_pid *from, const char *to, const char *buf,
    -  int len, unsigned timeout_ms);

    Equivalent to ei_send_reg_encoded with an optional time-out argument, see the +

    int ei_send_reg_encoded_tmo(int fd, const erlang_pid *from, const char *to, const char *buf,
    +  int len, unsigned timeout_ms);

    Equivalent to ei_send_reg_encoded with an optional time-out argument, see the description at the beginning of this manual page.

    ei_send_tmo()

    -
    int ei_send_tmo(int fd, erlang_pid* to, char* buf, int len, unsigned timeout_ms);

    Equivalent to ei_send with an optional time-out argument, see the description +

    int ei_send_tmo(int fd, erlang_pid* to, char* buf, int len, unsigned timeout_ms);

    Equivalent to ei_send with an optional time-out argument, see the description at the beginning of this manual page.

    @@ -801,7 +801,7 @@

    ei_thisalivename()

    -
    const char * ei_thisnodename(ei_cnode *ec);
    const char * ei_thishostname(ei_cnode *ec);
    const char * ei_thisalivename(ei_cnode *ec);

    Can be used to retrieve information about the C-node. These values are initially +

    const char * ei_thisnodename(ei_cnode *ec);
    const char * ei_thishostname(ei_cnode *ec);
    const char * ei_thisalivename(ei_cnode *ec);

    Can be used to retrieve information about the C-node. These values are initially set with ei_connect_init() or ei_connect_xinit().

    These function simply fetch the appropriate field from the ec structure. Read the field directly will probably be safe for a long time, so these functions are not really needed.

    @@ -810,7 +810,7 @@

    ei_unpublish()

    -
    int ei_unpublish(ei_cnode *ec);

    Can be called by a process to unregister a specified node from EPMD on the local +

    int ei_unpublish(ei_cnode *ec);

    Can be called by a process to unregister a specified node from EPMD on the local host. This is, however, usually not allowed, unless EPMD was started with flag -relaxed_command_check, which it normally is not.

    To unregister a node you have published, you should close the descriptor that was returned by ei_publish().

    Warning

    This function is deprecated and will be removed in a future release.

    ec is the node structure of the node to unregister.

    If the node was successfully unregistered from EPMD, the function returns 0. @@ -820,7 +820,7 @@

    ei_unpublish_tmo()

    -
    int ei_unpublish_tmo(ei_cnode *ec, unsigned timeout_ms);

    Equivalent to ei_unpublish with an optional time-out argument, see the +

    int ei_unpublish_tmo(ei_cnode *ec, unsigned timeout_ms);

    Equivalent to ei_unpublish with an optional time-out argument, see the description at the beginning of this manual page.

    diff --git a/prs/9045/lib/erl_interface-5.5.2/doc/html/ei_global.html b/prs/9045/lib/erl_interface-5.5.2/doc/html/ei_global.html index ff381329e78f..ed1a2a094c70 100644 --- a/prs/9045/lib/erl_interface-5.5.2/doc/html/ei_global.html +++ b/prs/9045/lib/erl_interface-5.5.2/doc/html/ei_global.html @@ -138,7 +138,7 @@

    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 +
      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 @@ -150,20 +150,20 @@

      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 +
        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

        +
        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 +

        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 diff --git a/prs/9045/lib/erl_interface-5.5.2/doc/html/ei_users_guide.html b/prs/9045/lib/erl_interface-5.5.2/doc/html/ei_users_guide.html index 07744a7b221c..921d0c6a4cab 100644 --- a/prs/9045/lib/erl_interface-5.5.2/doc/html/ei_users_guide.html +++ b/prs/9045/lib/erl_interface-5.5.2/doc/html/ei_users_guide.html @@ -186,11 +186,11 @@

        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.

        +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.

    @@ -199,18 +199,18 @@

    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.

    @@ -226,18 +226,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");

    +if ((sockfd = ei_connect(&ec, nodename)) < 0) + fprintf(stderr, "ERROR: ei_connect failed");

    @@ -252,7 +252,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 @@ -275,13 +275,13 @@

    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.

    @@ -295,24 +295,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, @@ -330,19 +330,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);
    +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_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 +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.

    @@ -359,32 +359,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 other nodes wishing to communicate with your service cannot find or connect to -your process.

    Create a name that Erlang processes can use to communicate with your service:

    ei_global_register(fd,servicename,ei_self(ec));

    After registering the name, use ei_accept to wait -for incoming connections.

    Note

    Remember to free pid later with ei_x_free.

    To unregister a name:

    ei_global_unregister(&ec,fd,servicename);
    +your process.

    Create a name that Erlang processes can use to communicate with your service:

    ei_global_register(fd,servicename,ei_self(ec));

    After registering the name, use ei_accept to wait +for incoming connections.

    Note

    Remember to free pid later with ei_x_free.

    To unregister a name:

    ei_global_unregister(&ec,fd,servicename);
    diff --git a/prs/9045/lib/erl_interface-5.5.2/doc/html/erl_call_cmd.html b/prs/9045/lib/erl_interface-5.5.2/doc/html/erl_call_cmd.html index 0645ccde07e4..7a26ad674581 100644 --- a/prs/9045/lib/erl_interface-5.5.2/doc/html/erl_call_cmd.html +++ b/prs/9045/lib/erl_interface-5.5.2/doc/html/erl_call_cmd.html @@ -257,8 +257,8 @@

    {<madonna@chivas.du.etx.ericsson.se,38,0>, []}]

    To forward standard output without printing the result term (again, the input ends with EOF (Control-D)):

    erl_call -s -e -sname madonna -fetch_stdout -no_result_term
    -io:format("Number of schedulers: ~p~n", [erlang:system_info(schedulers)]),
    -io:format("Number of logical cores: ~p~n", [erlang:system_info(logical_processors_available)]).
    +io:format("Number of schedulers: ~p~n", [erlang:system_info(schedulers)]),
    +io:format("Number of logical cores: ~p~n", [erlang:system_info(logical_processors_available)]).
     ^D
     Number of schedulers: 8
     Number of logical cores: 8
    diff --git a/prs/9045/lib/erl_interface-5.5.2/doc/html/erl_interface.epub b/prs/9045/lib/erl_interface-5.5.2/doc/html/erl_interface.epub index 2d1b1cba53f7..56b0026c992b 100644 Binary files a/prs/9045/lib/erl_interface-5.5.2/doc/html/erl_interface.epub and b/prs/9045/lib/erl_interface-5.5.2/doc/html/erl_interface.epub differ diff --git a/prs/9045/lib/et-1.7.1/doc/html/et.epub b/prs/9045/lib/et-1.7.1/doc/html/et.epub index 5125cbd838bf..dfc6ff85efe7 100644 Binary files a/prs/9045/lib/et-1.7.1/doc/html/et.epub and b/prs/9045/lib/et-1.7.1/doc/html/et.epub differ diff --git a/prs/9045/lib/et-1.7.1/doc/html/et_desc.html b/prs/9045/lib/et-1.7.1/doc/html/et_desc.html index 56cdb892342f..a3916e9b5bbc 100644 --- a/prs/9045/lib/et-1.7.1/doc/html/et_desc.html +++ b/prs/9045/lib/et-1.7.1/doc/html/et_desc.html @@ -144,33 +144,33 @@

    enable other types of Viewers. However in the following text we will focus on usage of the et_viewer.

    The main start function is et_viewer:start/1. By default it will start both an et_collector and an et_viewer:

    % erl -pa et/examples
    -Erlang R13B03 (erts-5.7.4) [64-bit] [smp:4:4] [rq:4] [async-threads:0] [kernel-poll:false]
    +Erlang R13B03 (erts-5.7.4) [64-bit] [smp:4:4] [rq:4] [async-threads:0] [kernel-poll:false]
     
    -Eshell V5.7.4  (abort with ^G)
    -1> {ok, Viewer} = et_viewer:start([]).
    -{ok,<0.40.0>}

    A Viewer gets trace Events from its Collector by polling it regularly for +Eshell V5.7.4 (abort with ^G) +1> {ok, Viewer} = et_viewer:start([]). +{ok,<0.40.0>}

    A Viewer gets trace Events from its Collector by polling it regularly for more Events to display. Events are for example reported to the Collector -with et_collector:report_event/6:

    2> Collector = et_viewer:get_collector_pid(Viewer).
    +with et_collector:report_event/6:

    2> Collector = et_viewer:get_collector_pid(Viewer).
     <0.39.0>
    -3> et_collector:report_event(Collector, 60, my_shell, mnesia_tm, start_outer,
    -3>                           "Start outer transaction"),
    -3> et_collector:report_event(Collector, 40, mnesia_tm, my_shell, new_tid,
    -3>                           "New transaction id is 4711"),
    -3> et_collector:report_event(Collector, 20, my_shell, mnesia_locker, try_write_lock,
    -3>                           "Acquire write lock for {my_tab, key}"),
    -3> et_collector:report_event(Collector, 10, mnesia_locker, my_shell, granted,
    -3>                           "You got the write lock for {my_tab, key}"),
    -3> et_collector:report_event(Collector, 60, my_shell, do_commit,
    -3>                           "Perform  transaction commit"),
    -3> et_collector:report_event(Collector, 40, my_shell, mnesia_locker, release_tid,
    -3>                           "Release all locks for transaction 4711"),
    -3> et_collector:report_event(Collector, 60, my_shell, mnesia_tm, delete_transaction,
    -3>                           "End of outer transaction"),
    -3> et_collector:report_event(Collector, 20, my_shell, end_outer,
    -3>                           "Transaction returned {atomic, ok}").
    -{ok,{table_handle,<0.39.0>,16402,trace_ts,
    -     #Fun<et_collector.0.62831470>}}

    This actually is a simulation of the process Events caused by a Mnesia -transaction that writes a record in a local table:

    mnesia:transaction(fun() -> mnesia:write({my_tab, key, val}) end).

    At this stage when we have a couple of Events, it is time to show how it looks +3> et_collector:report_event(Collector, 60, my_shell, mnesia_tm, start_outer, +3> "Start outer transaction"), +3> et_collector:report_event(Collector, 40, mnesia_tm, my_shell, new_tid, +3> "New transaction id is 4711"), +3> et_collector:report_event(Collector, 20, my_shell, mnesia_locker, try_write_lock, +3> "Acquire write lock for {my_tab, key}"), +3> et_collector:report_event(Collector, 10, mnesia_locker, my_shell, granted, +3> "You got the write lock for {my_tab, key}"), +3> et_collector:report_event(Collector, 60, my_shell, do_commit, +3> "Perform transaction commit"), +3> et_collector:report_event(Collector, 40, my_shell, mnesia_locker, release_tid, +3> "Release all locks for transaction 4711"), +3> et_collector:report_event(Collector, 60, my_shell, mnesia_tm, delete_transaction, +3> "End of outer transaction"), +3> et_collector:report_event(Collector, 20, my_shell, end_outer, +3> "Transaction returned {atomic, ok}"). +{ok,{table_handle,<0.39.0>,16402,trace_ts, + #Fun<et_collector.0.62831470>}}

    This actually is a simulation of the process Events caused by a Mnesia +transaction that writes a record in a local table:

    mnesia:transaction(fun() -> mnesia:write({my_tab, key, val}) end).

    At this stage when we have a couple of Events, it is time to show how it looks like in the graphical interface of et_viewer:

    A simulated Mnesia transaction which writes one record

    In the sequence chart, the actors (which symbolically has performed the Event) are shown as named vertical bars. The order of the actors may be altered by dragging (hold mouse button 1 pressed during the operation) the name tag of an @@ -187,11 +187,11 @@

    The Event Tracer (ET) uses named filters in various contexts. An Event Trace filter is an Erlang fun that takes some trace data as input and returns a -possibly modified version of it:

    filter(TraceData) -> false | true | {true, NewEvent}
    +possibly modified version of it:

    filter(TraceData) -> false | true | {true, NewEvent}
     
    -TraceData = Event | erlang_trace_data()
    -Event = #event{}
    -NewEvent = #event{}

    The interface of the filter function is the same as the the filter functions for +TraceData = Event | erlang_trace_data() +Event = #event{} +NewEvent = #event{}

    The interface of the filter function is the same as the the filter functions for the good old lists:filtermap/2. If the filter returns false it means that the trace data should silently be dropped. true means that the trace data data already is an Event Record and that it should be kept as it is. true means @@ -218,21 +218,21 @@

    in the viewer. The following filter in et/examples/et_demo.erl replaces the actor names mnesia_tm and mnesia_locker and leaves everything else in the record as it was:

    
    -mgr_actors(E) when is_record(E, event) ->
    -    Actor = fun(A) ->
    +mgr_actors(E) when is_record(E, event) ->
    +    Actor = fun(A) ->
                    case A of
                        mnesia_tm     -> trans_mgr;
                        mnesia_locker -> lock_mgr;
                        _             -> A
                    end
                 end,
    -    {true, E#event{from = Actor(E#event.from),
    -                   to = Actor(E#event.to),
    -                   contents = [{orig_from, E#event.from},
    -                               {orig_to,   E#event.to},
    -                               {orig_contents, E#event.contents}]}}.

    If we now add the filter to the running Collector:

    4> Fun = fun(E) -> et_demo:mgr_actors(E) end.
    +    {true, E#event{from = Actor(E#event.from),
    +                   to = Actor(E#event.to),
    +                   contents = [{orig_from, E#event.from},
    +                               {orig_to,   E#event.to},
    +                               {orig_contents, E#event.contents}]}}.

    If we now add the filter to the running Collector:

    4> Fun = fun(E) -> et_demo:mgr_actors(E) end.
     #Fun<erl_eval.6.13229925>
    -5> et_collector:dict_insert(Collector, {filter, mgr_actors}, Fun).
    +5> et_collector:dict_insert(Collector, {filter, mgr_actors}, Fun).
     ok

    you will see that the Filter menu in all viewers have got a new entry called mgr_actors. Select it, and a new Viewer window will pop up:

    The same trace data in a different view

    In order to see the nitty gritty details of an Event you may click on the Event in order to start a Contents Viewer for that Event. In the diff --git a/prs/9045/lib/et-1.7.1/doc/html/et_examples.html b/prs/9045/lib/et-1.7.1/doc/html/et_examples.html index 46f638129cb1..91a9cc697372 100644 --- a/prs/9045/lib/et-1.7.1/doc/html/et_examples.html +++ b/prs/9045/lib/et-1.7.1/doc/html/et_examples.html @@ -139,52 +139,52 @@

    The Erlang code for running the simulated Mnesia transaction example in the previous chapter is included in the et/examples/et_demo.erl file:

    
    -sim_trans() ->
    -    sim_trans([]).
    -
    -sim_trans(ExtraOptions) ->
    -    Options = [{dict_insert, {filter, mgr_actors}, fun mgr_actors/1}],
    -    {ok, Viewer} = et_viewer:start_link(Options ++ ExtraOptions),
    -    Collector = et_viewer:get_collector_pid(Viewer),
    -    et_collector:report_event(Collector, 60, my_shell, mnesia_tm, start_outer,
    -                              "Start outer transaction"),
    -    et_collector:report_event(Collector, 40, mnesia_tm, my_shell, new_tid,
    -                              "New transaction id is 4711"),
    -    et_collector:report_event(Collector, 20, my_shell, mnesia_locker, try_write_lock,
    -                              "Acquire write lock for {my_tab, key}"),
    -    et_collector:report_event(Collector, 10, mnesia_locker, my_shell, granted,
    -                              "You got the write lock for {my_tab, key}"),
    -    et_collector:report_event(Collector, 60, my_shell, do_commit,
    -                              "Perform  transaction commit"),
    -    et_collector:report_event(Collector, 40, my_shell, mnesia_locker, release_tid,
    -                              "Release all locks for transaction 4711"),
    -    et_collector:report_event(Collector, 60, my_shell, mnesia_tm, delete_transaction,
    -                              "End of outer transaction"),
    -    et_collector:report_event(Collector, 20, my_shell, end_outer,
    -                              "Transaction returned {atomic, ok}"),
    -    {collector, Collector}.
    
    -mgr_actors(E) when is_record(E, event) ->
    -    Actor = fun(A) ->
    +sim_trans() ->
    +    sim_trans([]).
    +
    +sim_trans(ExtraOptions) ->
    +    Options = [{dict_insert, {filter, mgr_actors}, fun mgr_actors/1}],
    +    {ok, Viewer} = et_viewer:start_link(Options ++ ExtraOptions),
    +    Collector = et_viewer:get_collector_pid(Viewer),
    +    et_collector:report_event(Collector, 60, my_shell, mnesia_tm, start_outer,
    +                              "Start outer transaction"),
    +    et_collector:report_event(Collector, 40, mnesia_tm, my_shell, new_tid,
    +                              "New transaction id is 4711"),
    +    et_collector:report_event(Collector, 20, my_shell, mnesia_locker, try_write_lock,
    +                              "Acquire write lock for {my_tab, key}"),
    +    et_collector:report_event(Collector, 10, mnesia_locker, my_shell, granted,
    +                              "You got the write lock for {my_tab, key}"),
    +    et_collector:report_event(Collector, 60, my_shell, do_commit,
    +                              "Perform  transaction commit"),
    +    et_collector:report_event(Collector, 40, my_shell, mnesia_locker, release_tid,
    +                              "Release all locks for transaction 4711"),
    +    et_collector:report_event(Collector, 60, my_shell, mnesia_tm, delete_transaction,
    +                              "End of outer transaction"),
    +    et_collector:report_event(Collector, 20, my_shell, end_outer,
    +                              "Transaction returned {atomic, ok}"),
    +    {collector, Collector}.
    
    +mgr_actors(E) when is_record(E, event) ->
    +    Actor = fun(A) ->
                    case A of
                        mnesia_tm     -> trans_mgr;
                        mnesia_locker -> lock_mgr;
                        _             -> A
                    end
                 end,
    -    {true, E#event{from = Actor(E#event.from),
    -                   to = Actor(E#event.to),
    -                   contents = [{orig_from, E#event.from},
    -                               {orig_to,   E#event.to},
    -                               {orig_contents, E#event.contents}]}}.

    If you invoke the et_demo:sim_trans() function, a Viewer window will pop up + {true, E#event{from = Actor(E#event.from), + to = Actor(E#event.to), + contents = [{orig_from, E#event.from}, + {orig_to, E#event.to}, + {orig_contents, E#event.contents}]}}.

    If you invoke the et_demo:sim_trans() function, a Viewer window will pop up and the sequence trace will be almost the same as if the following Mnesia -transaction would have been run:

    mnesia:transaction(fun() -> mnesia:write({my_tab, key, val}) end).

    And the viewer window will look like:

    Erlang R13B03 (erts-5.7.4) [64-bit] [smp:4:4] [rq:4] [async-threads:0] [kernel-poll:false]
    -
    -Eshell V5.7.4  (abort with ^G)
    -1> {ok, Viewer} = et_viewer:start([]).
    -{ok,<0.40.0>;}
    -2> et_demo:sim_trans().
    -{ok,{table_handle,<0.45.0>,24596,trace_ts,
    -     #Fun<et_collector.0.62831470>}}

    A simulated Mnesia transaction which writes one record

    +transaction would have been run:

    mnesia:transaction(fun() -> mnesia:write({my_tab, key, val}) end).

    And the viewer window will look like:

    Erlang R13B03 (erts-5.7.4) [64-bit] [smp:4:4] [rq:4] [async-threads:0] [kernel-poll:false]
    +
    +Eshell V5.7.4  (abort with ^G)
    +1> {ok, Viewer} = et_viewer:start([]).
    +{ok,<0.40.0>;}
    +2> et_demo:sim_trans().
    +{ok,{table_handle,<0.45.0>,24596,trace_ts,
    +     #Fun<et_collector.0.62831470>}}

    A simulated Mnesia transaction which writes one record

    @@ -196,20 +196,20 @@

    caller to the callee. The [{message, {caller}}, {return_trace}] options to dbg:tpl/2 function will imply the necessary information in the Erlang traces. Here follows the module_as_actor filter:

    
    -module_as_actor(E) when is_record(E, event) ->
    -    case lists:keysearch(mfa, 1, E#event.contents) of
    -        {value, {mfa, {M, F, _A}}} ->
    -            case lists:keysearch(pam_result, 1, E#event.contents) of
    -                {value, {pam_result, {M2, _F2, _A2}}} ->
    -                    {true, E#event{label = F, from = M2, to = M}};
    +module_as_actor(E) when is_record(E, event) ->
    +    case lists:keysearch(mfa, 1, E#event.contents) of
    +        {value, {mfa, {M, F, _A}}} ->
    +            case lists:keysearch(pam_result, 1, E#event.contents) of
    +                {value, {pam_result, {M2, _F2, _A2}}} ->
    +                    {true, E#event{label = F, from = M2, to = M}};
                     _ ->
    -                    {true, E#event{label = F, from = M, to = M}}
    +                    {true, E#event{label = F, from = M, to = M}}
                 end;
             _ ->
                 false
         end.

    The plain_process_info filter does not alter the Event Records. It merely ensures that the event not related to processes are skipped:

    
    -plain_process_info(E) when is_record(E, event) ->
    +plain_process_info(E) when is_record(E, event) ->
         case E#event.label of
             send                          -> true;
             send_to_non_existing_process  -> true;
    @@ -219,50 +219,50 @@ 

    link -> true; unlink -> true; getting_linked -> true; - {seq_send, _Label} -> true; - {seq_receive, _Label} -> true; - {seq_print, _Label} -> true; - {drop, _N} -> true; + {seq_send, _Label} -> true; + {seq_receive, _Label} -> true; + {seq_print, _Label} -> true; + {drop, _N} -> true; _ -> false end.

    The plain_process_info_nolink filter does not alter the Event Records. It do makes use of the plain_process_info , but do also ensure that the process info related to linking and unlinking is skipped:

    
    -plain_process_info_nolink(E) when is_record(E, event) ->
    -    (E#event.label /= link) and
    -    (E#event.label /= unlink) and
    -    (E#event.label /= getting_linked) and
    -    plain_process_info(E).

    In order to simplify the startup of an et_viewer process with the filters +plain_process_info_nolink(E) when is_record(E, event) -> + (E#event.label /= link) and + (E#event.label /= unlink) and + (E#event.label /= getting_linked) and + plain_process_info(E).

    In order to simplify the startup of an et_viewer process with the filters mentioned above, plus some others (that also are found in et/examples/et_demo.erl src/et_collector.erl the et_demo:start/0,1 functions can be used:

    
    -start() ->
    -    start([]).
    -
    -start(ExtraOptions) ->
    -    Options = [{trace_global, true},
    -               {parent_pid, undefined},
    -               {max_actors, infinity},
    -               {max_events, 1000},
    -               {active_filter, module_as_actor}],
    -    et_viewer:start_link(filters() ++ Options ++ ExtraOptions).

    A simple one-liner starts the tool:

              erl -pa ../examples -s et_demo

    The filters are included by the following parameters:

    
    -filters() ->
    -    [{dict_insert, {filter, module_as_actor},
    -                   fun module_as_actor/1},
    -     {dict_insert, {filter, plain_process_info},
    -                   fun plain_process_info/1},
    -     {dict_insert, {filter, plain_process_info_nolink},
    -                   fun plain_process_info_nolink/1},
    -     {dict_insert, {filter, named_process_info},
    -                   fun named_process_info/1},
    -     {dict_insert, {filter, named_process_info_nolink},
    -                   fun named_process_info_nolink/1},
    -     {dict_insert, {filter, node_process_info},
    -                   fun node_process_info/1},
    -     {dict_insert, {filter, node_process_info_nolink},
    -                   fun node_process_info_nolink/1},
    -     {dict_insert, {filter, application_as_actor},
    -                   fun application_as_actor/1}
    -    ].

    +start() -> + start([]). + +start(ExtraOptions) -> + Options = [{trace_global, true}, + {parent_pid, undefined}, + {max_actors, infinity}, + {max_events, 1000}, + {active_filter, module_as_actor}], + et_viewer:start_link(filters() ++ Options ++ ExtraOptions).

    A simple one-liner starts the tool:

              erl -pa ../examples -s et_demo

    The filters are included by the following parameters:

    
    +filters() ->
    +    [{dict_insert, {filter, module_as_actor},
    +                   fun module_as_actor/1},
    +     {dict_insert, {filter, plain_process_info},
    +                   fun plain_process_info/1},
    +     {dict_insert, {filter, plain_process_info_nolink},
    +                   fun plain_process_info_nolink/1},
    +     {dict_insert, {filter, named_process_info},
    +                   fun named_process_info/1},
    +     {dict_insert, {filter, named_process_info_nolink},
    +                   fun named_process_info_nolink/1},
    +     {dict_insert, {filter, node_process_info},
    +                   fun node_process_info/1},
    +     {dict_insert, {filter, node_process_info_nolink},
    +                   fun node_process_info_nolink/1},
    +     {dict_insert, {filter, application_as_actor},
    +                   fun application_as_actor/1}
    +    ].

    @@ -276,33 +276,33 @@

    processes plus the calling process (that is your shell). Please, observe that the whereis/1 call in the following code requires that both the traced Mnesia application and the et_viewer is running on the same node:

    
    -trace_mnesia() ->
    -    Modules = mnesia:ms(),
    -    Spec = [{message, {caller}}, {return_trace}],
    -    Flags = [send, 'receive', procs, timestamp],
    -    dbg:p(all, [call, timestamp]),
    -    [dbg:tpl(M, [{'_', [], Spec}]) || M <- Modules],
    -    LocallyRunningServers = [M || M <- Modules, whereis(M) /= undefined],
    -    [dbg:p(whereis(RS), Flags) || RS <- LocallyRunningServers],
    -    dbg:p(self(), Flags),
    +trace_mnesia() ->
    +    Modules = mnesia:ms(),
    +    Spec = [{message, {caller}}, {return_trace}],
    +    Flags = [send, 'receive', procs, timestamp],
    +    dbg:p(all, [call, timestamp]),
    +    [dbg:tpl(M, [{'_', [], Spec}]) || M <- Modules],
    +    LocallyRunningServers = [M || M <- Modules, whereis(M) /= undefined],
    +    [dbg:p(whereis(RS), Flags) || RS <- LocallyRunningServers],
    +    dbg:p(self(), Flags),
         LocallyRunningServers.

    The et_demo:live_trans/0 function starts the global Collector, starts a Viewer, starts Mnesia, creates a local table, activates tracing (as described above) and registers the shell process is as 'my_shell' for clarity. Finally a simple Mnesia transaction that writes a single record is run:

    
    -live_trans() ->
    -    live_trans([]).
    -
    -live_trans(ExtraOptions) ->
    -    Options = [{title, "Mnesia tracer"},
    -	       {hide_actions, true},
    -	       {active_filter, named_process_info_nolink}],
    -    et_demo:start(Options ++ ExtraOptions),
    -    mnesia:start(),
    -    mnesia:create_table(my_tab, [{ram_copies, [node()]}]),
    -    et_demo:trace_mnesia(),
    -    register(my_shell, self()),
    -
    -    mnesia:transaction(fun() -> mnesia:write({my_tab, key, val}) end).

    Now we run the et_demo:live_trans/0 function:

    erl -pa ../examples
    +live_trans() ->
    +    live_trans([]).
    +
    +live_trans(ExtraOptions) ->
    +    Options = [{title, "Mnesia tracer"},
    +	       {hide_actions, true},
    +	       {active_filter, named_process_info_nolink}],
    +    et_demo:start(Options ++ ExtraOptions),
    +    mnesia:start(),
    +    mnesia:create_table(my_tab, [{ram_copies, [node()]}]),
    +    et_demo:trace_mnesia(),
    +    register(my_shell, self()),
    +
    +    mnesia:transaction(fun() -> mnesia:write({my_tab, key, val}) end).

    Now we run the et_demo:live_trans/0 function:

    erl -pa ../examples
     Erlang R13B03 (erts-5.7.4) [64-bit] [smp:4:4] [rq:4]
                                [async-threads:0] [kernel-poll:false]
     
    @@ -322,113 +322,113 @@ 

    with calls to et:trace_me/5. For each call a detail level is given in order to enable dynamic control of the trace level in a simple manner.

    The megaco_filter module implements a customized filter for Megaco messages. It does also make use of trace_global combined with usage of the -trace_pattern:

    -module(megaco_filter).
    --export([start/0]).
    +trace_pattern:

    -module(megaco_filter).
    +-export([start/0]).
     
    -start() ->
    +start() ->
         Options =
    -        [{event_order, event_ts},
    -         {scale, 3},
    -         {max_actors, infinity},
    -         {trace_pattern, {megaco, max}},
    -         {trace_global, true},
    -         {dict_insert, {filter, megaco_filter}, fun filter/1},
    -         {active_filter, megaco_filter},
    -         {title, "Megaco tracer - Erlang/OTP"}],
    -    et_viewer:start(Options).

    First we start an Erlang node with a global Collector and its Viewer.

    erl -sname observer
    -Erlang R13B03 (erts-5.7.4) [64-bit] [smp:4:4] [rq:4] [async-threads:0] [kernel-poll:false]
    -
    -Eshell V5.7.4  (abort with ^G)
    -(observer@falco)1> megaco_filter:start().
    -{ok,<0.48.0>}

    Secondly we start another Erlang node which we connect the observer node, before + [{event_order, event_ts}, + {scale, 3}, + {max_actors, infinity}, + {trace_pattern, {megaco, max}}, + {trace_global, true}, + {dict_insert, {filter, megaco_filter}, fun filter/1}, + {active_filter, megaco_filter}, + {title, "Megaco tracer - Erlang/OTP"}], + et_viewer:start(Options).

    First we start an Erlang node with a global Collector and its Viewer.

    erl -sname observer
    +Erlang R13B03 (erts-5.7.4) [64-bit] [smp:4:4] [rq:4] [async-threads:0] [kernel-poll:false]
    +
    +Eshell V5.7.4  (abort with ^G)
    +(observer@falco)1> megaco_filter:start().
    +{ok,<0.48.0>}

    Secondly we start another Erlang node which we connect the observer node, before we start the application that we want to trace. In this case we start a Media Gateway Controller that listens for both TCP and UDP on the text and binary ports for Megaco:

    erl -sname mgc -pa ../../megaco/examples/simple
    -Erlang R13B03 (erts-5.7.4) [64-bit] [smp:4:4] [rq:4] [async-threads:0] [kernel-poll:false]
    +Erlang R13B03 (erts-5.7.4) [64-bit] [smp:4:4] [rq:4] [async-threads:0] [kernel-poll:false]
     
    -Eshell V5.7.4  (abort with ^G)
    -(mgc@falco)1> net:ping(observer@falco).
    +Eshell V5.7.4  (abort with ^G)
    +(mgc@falco)1> net:ping(observer@falco).
     pong
    -(mgc@falco)2> megaco:start().
    +(mgc@falco)2> megaco:start().
     ok
    -(mgc@falco)3> megaco_simple_mgc:start().
    -{ok,[{ok,2944,
    -         {megaco_receive_handle,{deviceName,"controller"},
    -                                megaco_pretty_text_encoder,[],megaco_tcp,dynamic}},
    -     {ok,2944,
    -         {megaco_receive_handle,{deviceName,"controller"},
    -                                megaco_pretty_text_encoder,[],megaco_udp,dynamic}},
    -     {ok,2945,
    -         {megaco_receive_handle,{deviceName,"controller"},
    -                                megaco_binary_encoder,[],megaco_tcp,dynamic}},
    -     {ok,2945,
    -         {megaco_receive_handle,{deviceName,"controller"},
    -                                megaco_binary_encoder,[],megaco_udp,dynamic}}]}

    And finally we start an Erlang node for the Media Gateways and connect to the +(mgc@falco)3> megaco_simple_mgc:start(). +{ok,[{ok,2944, + {megaco_receive_handle,{deviceName,"controller"}, + megaco_pretty_text_encoder,[],megaco_tcp,dynamic}}, + {ok,2944, + {megaco_receive_handle,{deviceName,"controller"}, + megaco_pretty_text_encoder,[],megaco_udp,dynamic}}, + {ok,2945, + {megaco_receive_handle,{deviceName,"controller"}, + megaco_binary_encoder,[],megaco_tcp,dynamic}}, + {ok,2945, + {megaco_receive_handle,{deviceName,"controller"}, + megaco_binary_encoder,[],megaco_udp,dynamic}}]}

    And finally we start an Erlang node for the Media Gateways and connect to the observer node. Each Media Gateway connects to the controller and sends an initial Service Change message. The controller accepts the gateways and sends a reply to each one using the same transport mechanism and message encoding according to the preference of each gateway. That is all combinations of TCP/IP -transport, UDP/IP transport, text encoding and ASN.1 BER encoding:

    Erlang R13B03 (erts-5.7.4) [64-bit] [smp:4:4] [rq:4] [async-threads:0] [kernel-poll:false]
    +transport, UDP/IP transport, text encoding and ASN.1 BER encoding:

    Erlang R13B03 (erts-5.7.4) [64-bit] [smp:4:4] [rq:4] [async-threads:0] [kernel-poll:false]
     
    -Eshell V5.7.4  (abort with ^G)
    -(mg@falco)1> net:ping(observer@falco).
    +Eshell V5.7.4  (abort with ^G)
    +(mg@falco)1> net:ping(observer@falco).
     pong
    -(mg@falco)2> megaco_simple_mg:start().
    -[{{deviceName,"gateway_tt"},
    -  {error,{start_user,megaco_not_started}}},
    - {{deviceName,"gateway_tb"},
    -  {error,{start_user,megaco_not_started}}},
    - {{deviceName,"gateway_ut"},
    -  {error,{start_user,megaco_not_started}}},
    - {{deviceName,"gateway_ub"},
    -  {error,{start_user,megaco_not_started}}}]
    -(mg@falco)3> megaco:start().
    +(mg@falco)2> megaco_simple_mg:start().
    +[{{deviceName,"gateway_tt"},
    +  {error,{start_user,megaco_not_started}}},
    + {{deviceName,"gateway_tb"},
    +  {error,{start_user,megaco_not_started}}},
    + {{deviceName,"gateway_ut"},
    +  {error,{start_user,megaco_not_started}}},
    + {{deviceName,"gateway_ub"},
    +  {error,{start_user,megaco_not_started}}}]
    +(mg@falco)3> megaco:start().
     ok
    -(mg@falco)4> megaco_simple_mg:start().
    -[{{deviceName,"gateway_tt"},
    -  {1,
    -   {ok,[{'ActionReply',0,asn1_NOVALUE,asn1_NOVALUE,
    -            [{serviceChangeReply,
    -                 {'ServiceChangeReply',
    -                     [{megaco_term_id,false,["root"]}],
    -                     {serviceChangeResParms,
    -                         {'ServiceChangeResParm',
    -                             {deviceName,"controller"},
    +(mg@falco)4> megaco_simple_mg:start().
    +[{{deviceName,"gateway_tt"},
    +  {1,
    +   {ok,[{'ActionReply',0,asn1_NOVALUE,asn1_NOVALUE,
    +            [{serviceChangeReply,
    +                 {'ServiceChangeReply',
    +                     [{megaco_term_id,false,["root"]}],
    +                     {serviceChangeResParms,
    +                         {'ServiceChangeResParm',
    +                             {deviceName,"controller"},
                                  asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,
    -                             asn1_NOVALUE}}}}]}]}}},
    - {{deviceName,"gateway_tb"},
    -  {1,
    -   {ok,[{'ActionReply',0,asn1_NOVALUE,asn1_NOVALUE,
    -            [{serviceChangeReply,
    -                 {'ServiceChangeReply',
    -                     [{megaco_term_id,false,["root"]}],
    -                     {serviceChangeResParms,
    -                         {'ServiceChangeResParm',
    -                             {deviceName,"controller"},
    +                             asn1_NOVALUE}}}}]}]}}},
    + {{deviceName,"gateway_tb"},
    +  {1,
    +   {ok,[{'ActionReply',0,asn1_NOVALUE,asn1_NOVALUE,
    +            [{serviceChangeReply,
    +                 {'ServiceChangeReply',
    +                     [{megaco_term_id,false,["root"]}],
    +                     {serviceChangeResParms,
    +                         {'ServiceChangeResParm',
    +                             {deviceName,"controller"},
                                  asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,
    -                             asn1_NOVALUE}}}}]}]}}},
    - {{deviceName,"gateway_ut"},
    -  {1,
    -   {ok,[{'ActionReply',0,asn1_NOVALUE,asn1_NOVALUE,
    -            [{serviceChangeReply,
    -                 {'ServiceChangeReply',
    -                     [{megaco_term_id,false,["root"]}],
    -                     {serviceChangeResParms,
    -                         {'ServiceChangeResParm',
    -                             {deviceName,"controller"},
    +                             asn1_NOVALUE}}}}]}]}}},
    + {{deviceName,"gateway_ut"},
    +  {1,
    +   {ok,[{'ActionReply',0,asn1_NOVALUE,asn1_NOVALUE,
    +            [{serviceChangeReply,
    +                 {'ServiceChangeReply',
    +                     [{megaco_term_id,false,["root"]}],
    +                     {serviceChangeResParms,
    +                         {'ServiceChangeResParm',
    +                             {deviceName,"controller"},
                                  asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,
    -                             asn1_NOVALUE}}}}]}]}}},
    - {{deviceName,"gateway_ub"},
    -  {1,
    -   {ok,[{'ActionReply',0,asn1_NOVALUE,asn1_NOVALUE,
    -            [{serviceChangeReply,
    -                 {'ServiceChangeReply',
    -                     [{megaco_term_id,false,["root"]}],
    -                     {serviceChangeResParms,
    -                         {'ServiceChangeResParm',
    -                             {deviceName,"controller"},
    +                             asn1_NOVALUE}}}}]}]}}},
    + {{deviceName,"gateway_ub"},
    +  {1,
    +   {ok,[{'ActionReply',0,asn1_NOVALUE,asn1_NOVALUE,
    +            [{serviceChangeReply,
    +                 {'ServiceChangeReply',
    +                     [{megaco_term_id,false,["root"]}],
    +                     {serviceChangeResParms,
    +                         {'ServiceChangeResParm',
    +                             {deviceName,"controller"},
                                  asn1_NOVALUE,asn1_NOVALUE,
    -                             asn1_NOVALUE,...}}}}]}]}}}]

    The Megaco adopted viewer looks like this, when we have clicked on the + asn1_NOVALUE,...}}}}]}]}}}]

    The Megaco adopted viewer looks like this, when we have clicked on the [gateway_tt] actor name in order to only display the events regarding that actor:

    The viewer adopted for Megaco

    A pretty printed Megaco message looks like this:

    A textual Megaco message

    And the corresponding internal form for the same Megaco message looks like this:

    The internal form of a Megaco message

    diff --git a/prs/9045/lib/et-1.7.1/doc/html/et_tutorial.html b/prs/9045/lib/et-1.7.1/doc/html/et_tutorial.html index e30555e25e1a..c6c080e43797 100644 --- a/prs/9045/lib/et-1.7.1/doc/html/et_tutorial.html +++ b/prs/9045/lib/et-1.7.1/doc/html/et_tutorial.html @@ -139,8 +139,8 @@

    The easiest way of using ET, is to just use it as a graphical tool for displaying message sequence charts. In order to do that you need to first start -a Viewer (which by default starts a Collector):

          {ok, ViewerPid} = et_viewer:start([{title,"Coffee Order"}]),
    -      CollectorPid = et_viewer:get_collector_pid(ViewerPid).

    Then you send events to the Collector with the function +a Viewer (which by default starts a Collector):

          {ok, ViewerPid} = et_viewer:start([{title,"Coffee Order"}]),
    +      CollectorPid = et_viewer:get_collector_pid(ViewerPid).

    Then you send events to the Collector with the function et_collector:report_event/6 like this:

          et_collector:report_event(CollectorPid,85,from,to,message,extra_stuff).

    The Viewer will automatically pull events from the Collector and display them on the screen.

    The number (in this case 85) is an integer from 1 to 100 that specifies the "detail level" of the message. The higher the number, the more important it is. @@ -150,30 +150,30 @@

    displayed next to the lifeline as an "action". The extra_stuffvalue is simply data that you can attach that will be displayed when someone actually clicks on the action or message in the Viewer window.

    The module et/examples/et_display_demo.erl illustrates how it can be used:

    
    --module(et_display_demo).
    +-module(et_display_demo).
     
    --export([test/0]).
    -
    -test() ->
    -    {ok, Viewer} = et_viewer:start([{title,"Coffee Order"}, {max_actors,10}]),
    -    Drink = {drink,iced_chai_latte},
    -    Size = {size,grande},
    -    Milk = {milk,whole},
    -    Flavor = {flavor,vanilla},
    -    C = et_viewer:get_collector_pid(Viewer),
    -    et_collector:report_event(C,99,customer,barrista1,place_order,[Drink,Size,Milk,Flavor]),
    -    et_collector:report_event(C,80,barrista1,register,enter_order,[Drink,Size,Flavor]),
    -    et_collector:report_event(C,80,register,barrista1,give_total,"$5"),
    -    et_collector:report_event(C,80,barrista1,barrista1,get_cup,[Drink,Size]),
    -    et_collector:report_event(C,80,barrista1,barrista2,give_cup,[]),
    -    et_collector:report_event(C,90,barrista1,customer,request_money,"$5"),
    -    et_collector:report_event(C,90,customer,barrista1,pay_money,"$5"),
    -    et_collector:report_event(C,80,barrista2,barrista2,get_chai_mix,[]),
    -    et_collector:report_event(C,80,barrista2,barrista2,add_flavor,[Flavor]),
    -    et_collector:report_event(C,80,barrista2,barrista2,add_milk,[Milk]),
    -    et_collector:report_event(C,80,barrista2,barrista2,add_ice,[]),
    -    et_collector:report_event(C,80,barrista2,barrista2,swirl,[]),
    -    et_collector:report_event(C,80,barrista2,customer,give_tasty_beverage,[Drink,Size]),
    +-export([test/0]).
    +
    +test() ->
    +    {ok, Viewer} = et_viewer:start([{title,"Coffee Order"}, {max_actors,10}]),
    +    Drink = {drink,iced_chai_latte},
    +    Size = {size,grande},
    +    Milk = {milk,whole},
    +    Flavor = {flavor,vanilla},
    +    C = et_viewer:get_collector_pid(Viewer),
    +    et_collector:report_event(C,99,customer,barrista1,place_order,[Drink,Size,Milk,Flavor]),
    +    et_collector:report_event(C,80,barrista1,register,enter_order,[Drink,Size,Flavor]),
    +    et_collector:report_event(C,80,register,barrista1,give_total,"$5"),
    +    et_collector:report_event(C,80,barrista1,barrista1,get_cup,[Drink,Size]),
    +    et_collector:report_event(C,80,barrista1,barrista2,give_cup,[]),
    +    et_collector:report_event(C,90,barrista1,customer,request_money,"$5"),
    +    et_collector:report_event(C,90,customer,barrista1,pay_money,"$5"),
    +    et_collector:report_event(C,80,barrista2,barrista2,get_chai_mix,[]),
    +    et_collector:report_event(C,80,barrista2,barrista2,add_flavor,[Flavor]),
    +    et_collector:report_event(C,80,barrista2,barrista2,add_milk,[Milk]),
    +    et_collector:report_event(C,80,barrista2,barrista2,add_ice,[]),
    +    et_collector:report_event(C,80,barrista2,barrista2,swirl,[]),
    +    et_collector:report_event(C,80,barrista2,customer,give_tasty_beverage,[Drink,Size]),
         ok.

    When you run the et_display_demo:test(). function in the example above, the Viewer window will look like this:

    Screenshot of the Viewer window

    @@ -205,7 +205,7 @@

    calls. The idea is that you should instrument your code with calls to et:trace_me/5 in strategic places where you have interesting information available in your program. Then you just start the Collector with global -tracing enabled:

          et_viewer:start([{trace_global, true}, {trace_pattern, {et,max}}]).

    This will start a Collector, a Viewer and also start the tracing of +tracing enabled:

          et_viewer:start([{trace_global, true}, {trace_pattern, {et,max}}]).

    This will start a Collector, a Viewer and also start the tracing of et:trace_me/5 function calls. The Raw Trace Data is collected by the Collector and a view of it is displayed on the screen by the Viewer. You can define your own "views" of the data by implementing your own Filter functions @@ -261,36 +261,36 @@

    all you have to do is enable them.

    For those people who want to do general tracing, consult the dbg module on how to trace whatever you're interested in and let it work its magic. If you just want et:trace_me/5 to work, do the following:

    1. Create a Collector
    2. Create a Viewer (this can do step #1 for you)
    3. Turn on and pare down debugging

    The module et/examples/et_trace_demo.erl achieves this.

    
    --module(et_trace_demo).
    +-module(et_trace_demo).
     
    --export([test/0]).
    -
    -test() ->
    -    et_viewer:start([
    -        {title,"Coffee Order"},
    -        {trace_global,true},
    -        {trace_pattern,{et,max}},
    -        {max_actors,10}
    -      ]),
    +-export([test/0]).
    +
    +test() ->
    +    et_viewer:start([
    +        {title,"Coffee Order"},
    +        {trace_global,true},
    +        {trace_pattern,{et,max}},
    +        {max_actors,10}
    +      ]),
           %% dbg:p(all,call),
           %% dbg:tpl(et, trace_me, 5, []),
    -      Drink = {drink,iced_chai_latte},
    -      Size = {size,grande},
    -      Milk = {milk,whole},
    -      Flavor = {flavor,vanilla},
    -      et:trace_me(99,customer,barrista1,place_order,[Drink,Size,Milk,Flavor]),
    -      et:trace_me(80,barrista1,register,enter_order,[Drink,Size,Flavor]),
    -      et:trace_me(80,register,barrista1,give_total,"$5"),
    -      et:trace_me(80,barrista1,barrista1,get_cup,[Drink,Size]),
    -      et:trace_me(80,barrista1,barrista2,give_cup,[]),
    -      et:trace_me(90,barrista1,customer,request_money,"$5"),
    -      et:trace_me(90,customer,barrista1,pay_money,"$5"),
    -      et:trace_me(80,barrista2,barrista2,get_chai_mix,[]),
    -      et:trace_me(80,barrista2,barrista2,add_flavor,[Flavor]),
    -      et:trace_me(80,barrista2,barrista2,add_milk,[Milk]),
    -      et:trace_me(80,barrista2,barrista2,add_ice,[]),
    -      et:trace_me(80,barrista2,barrista2,swirl,[]),
    -      et:trace_me(80,barrista2,customer,give_tasty_beverage,[Drink,Size]),
    +      Drink = {drink,iced_chai_latte},
    +      Size = {size,grande},
    +      Milk = {milk,whole},
    +      Flavor = {flavor,vanilla},
    +      et:trace_me(99,customer,barrista1,place_order,[Drink,Size,Milk,Flavor]),
    +      et:trace_me(80,barrista1,register,enter_order,[Drink,Size,Flavor]),
    +      et:trace_me(80,register,barrista1,give_total,"$5"),
    +      et:trace_me(80,barrista1,barrista1,get_cup,[Drink,Size]),
    +      et:trace_me(80,barrista1,barrista2,give_cup,[]),
    +      et:trace_me(90,barrista1,customer,request_money,"$5"),
    +      et:trace_me(90,customer,barrista1,pay_money,"$5"),
    +      et:trace_me(80,barrista2,barrista2,get_chai_mix,[]),
    +      et:trace_me(80,barrista2,barrista2,add_flavor,[Flavor]),
    +      et:trace_me(80,barrista2,barrista2,add_milk,[Milk]),
    +      et:trace_me(80,barrista2,barrista2,add_ice,[]),
    +      et:trace_me(80,barrista2,barrista2,swirl,[]),
    +      et:trace_me(80,barrista2,customer,give_tasty_beverage,[Drink,Size]),
           ok.

    Running through the above, the most important points are:

    • Turn on global tracing
    • Set a Trace Pattern
    • Tell dbg to trace function Calls
    • Tell it specifically to trace the et:trace_me/5 function

    When you run the et_trace_demo:test() function above, the Viewer window will look like this screenshot:

    Screenshot of the Viewer window

    diff --git a/prs/9045/lib/eunit-2.9.1/doc/html/eunit.epub b/prs/9045/lib/eunit-2.9.1/doc/html/eunit.epub index 3b6cce498a99..ade02c9fa631 100644 Binary files a/prs/9045/lib/eunit-2.9.1/doc/html/eunit.epub and b/prs/9045/lib/eunit-2.9.1/doc/html/eunit.epub differ diff --git a/prs/9045/lib/ftp-1.2.3/doc/html/.build b/prs/9045/lib/ftp-1.2.3/doc/html/.build index e7eb95003fdc..60174de3549e 100644 --- a/prs/9045/lib/ftp-1.2.3/doc/html/.build +++ b/prs/9045/lib/ftp-1.2.3/doc/html/.build @@ -18,7 +18,7 @@ dist/lato-latin-ext-300-normal-VPGGJKJL.woff2 dist/lato-latin-ext-400-normal-N27NCBWW.woff2 dist/lato-latin-ext-700-normal-Q2L5DVMW.woff2 dist/remixicon-NKANDIL5.woff2 -dist/search_data-8D0628B6.js +dist/search_data-3690279C.js dist/sidebar_items-B6B07F6E.js ftp.html ftp_client.html diff --git a/prs/9045/lib/ftp-1.2.3/doc/html/dist/search_data-3690279C.js b/prs/9045/lib/ftp-1.2.3/doc/html/dist/search_data-3690279C.js new file mode 100644 index 000000000000..2831eefe08ed --- /dev/null +++ b/prs/9045/lib/ftp-1.2.3/doc/html/dist/search_data-3690279C.js @@ -0,0 +1 @@ +searchData={"items":[{"type":"module","doc":"A File Transfer Protocol client.\n\nThis module implements a client for file transfer according to a subset of the\nFile Transfer Protocol (FTP), see [RFC 959](http://www.ietf.org/rfc/rfc959.txt).\n\nThe FTP client always tries to use passive FTP mode and only resort to active\nFTP mode if this fails. This default behavior can be changed by start option\n[mode](`m:ftp#mode`).\n\nFor a simple example of an FTP session, see [FTP User's Guide](ftp_client.md).\n\nThe return values of the following functions depend much on the implementation\nof the FTP server at the remote host. In particular, the results from `ls` and\n`nlist` varies. Often real errors are not reported as errors by `ls`, even if,\nfor example, a file or directory does not exist. `nlist` is usually more strict,\nbut some implementations have the peculiar behaviour of responding with an error\nif the request is a listing of the contents of a directory that exists but is\nempty.","title":"ftp","ref":"ftp.html"},{"type":"module","doc":"The possible error reasons and the corresponding diagnostic strings returned by\n[`formaterror/1`](`formaterror/1`) are as follows:\n\n- **`echunk`** - Synchronization error during chunk sending according to one of\n the following:\n\n - A call is made to [`send_chunk/2`](`send_chunk/2`) or\n [`send_chunk_end/1`](`send_chunk_end/1`) before a call to\n [`send_chunk_start/2`](`send_chunk_start/2`).\n - A call has been made to another transfer function during chunk sending, that\n is, before a call to [`send_chunk_end/1`](`send_chunk_end/1`).\n\n- **`eclosed`** - The session is closed.\n\n- **`econn`** - Connection to the remote server is prematurely closed.\n\n- **`ehost`** - Host is not found, FTP server is not found, or connection is\n rejected by FTP server.\n\n- **`elogin`** - User is not logged in.\n\n- **`enotbinary`** - Term is not a binary.\n\n- **`epath`** - No such file or directory, or directory already exists, or\n permission denied.\n\n- **`etype`** - No such type.\n\n- **`euser`** - Invalid username or password.\n\n- **`etnospc`** - Insufficient storage space in system \\[452].\n\n- **`epnospc`** - Exceeded storage allocation (for current directory or dataset)\n \\[552].\n\n- **`efnamena`** - Filename not allowed \\[553].","title":"Errors - ftp","ref":"ftp.html#module-errors"},{"type":"function","doc":"Sets the account for an operation, if needed.","title":"ftp.account/2","ref":"ftp.html#account/2"},{"type":"function","doc":"","title":"ftp.append/2","ref":"ftp.html#append/2"},{"type":"function","doc":"Transfers the file `LocalFile` to the remote server. If `RemoteFile` is\nspecified, the name of the remote file that the file is appended to is set to\n`RemoteFile`, otherwise to `LocalFile`. If the file does not exists, it is\ncreated.","title":"ftp.append/3","ref":"ftp.html#append/3"},{"type":"function","doc":"Transfers the binary `Bin` to the remote server and appends it to the file\n`RemoteFile`. If the file does not exist, it is created.","title":"ftp.append_bin/3","ref":"ftp.html#append_bin/3"},{"type":"function","doc":"Transfers the chunk `Bin` to the remote server, which appends it to the file\nspecified in the call to [`append_chunk_start/2`](`append_chunk_start/2`).\n\nFor some errors, for example, file system full, it is necessary to call\n`append_chunk_end` to get the proper reason.","title":"ftp.append_chunk/2","ref":"ftp.html#append_chunk/2"},{"type":"function","doc":"Stops transfer of chunks for appending to the remote server. The file at the\nremote server, specified in the call to\n[`append_chunk_start/2`](`append_chunk_start/2`), is closed by the server.","title":"ftp.append_chunk_end/1","ref":"ftp.html#append_chunk_end/1"},{"type":"function","doc":"Starts the transfer of chunks for appending to the file `RemoteFile` at the\nremote server. If the file does not exist, it is created.","title":"ftp.append_chunk_start/2","ref":"ftp.html#append_chunk_start/2"},{"type":"function","doc":"Changes the working directory at the remote server to `Dir`.","title":"ftp.cd/2","ref":"ftp.html#cd/2"},{"type":"function","doc":"Ends an FTP session, created using function [open](`open/2`).","title":"ftp.close/1","ref":"ftp.html#close/1"},{"type":"function","doc":"Deletes the file `File` at the remote server.","title":"ftp.delete/2","ref":"ftp.html#delete/2"},{"type":"function","doc":"Given an error return value `{error, AtomReason}`, this function returns a\nreadable string describing the error.","title":"ftp.formaterror/1","ref":"ftp.html#formaterror/1"},{"type":"function","doc":"Changes the working directory to `Dir` for the local client.","title":"ftp.lcd/2","ref":"ftp.html#lcd/2"},{"type":"function","doc":"Returns the current working directory at the local client.","title":"ftp.lpwd/1","ref":"ftp.html#lpwd/1"},{"type":"function","doc":"","title":"ftp.ls/1","ref":"ftp.html#ls/1"},{"type":"function","doc":"Returns a list of files in long format.\n\n`Dir` can be a directory or a file. The `Dir` string can contain wildcards.\n\n[`ls/1`](`ls/1`) implies the current remote directory of the user.\n\nThe format of `Listing` depends on the operating system. On UNIX, it is\ntypically produced from the output of the `ls -l` shell command.","title":"ftp.ls/2","ref":"ftp.html#ls/2"},{"type":"function","doc":"Creates the directory `Dir` at the remote server.","title":"ftp.mkdir/2","ref":"ftp.html#mkdir/2"},{"type":"function","doc":"","title":"ftp.nlist/1","ref":"ftp.html#nlist/1"},{"type":"function","doc":"Returns a list of files in short format.\n\n`Pathname` can be a directory or a file. The `Pathname` string can contain\nwildcards.\n\n[`nlist/1`](`nlist/1`) implies the current remote directory of the user.\n\nThe format of `Listing` is a stream of filenames where each filename is\nseparated by or . Contrary to function `ls`, the purpose of `nlist`\nis to enable a program to process filename information automatically.","title":"ftp.nlist/2","ref":"ftp.html#nlist/2"},{"type":"function","doc":"","title":"ftp.open/1","ref":"ftp.html#open/1"},{"type":"function","doc":"Starts a FTP client process and opens a session with the FTP server at `Host`.\n\nA session opened in this way is closed using function `close/1`.\n\nThe available configuration options are as follows:\n\n- **\\{host, Host\\}** - [](){: #host } Host = `string() | ip_address()`\n\n- **\\{port, Port\\}** - [](){: #port } Default is `0` which aliases to `21` or\n `990` when used with [`{tls_sec_method,ftps}`](`open/2`)).\n\n- **\\{mode, Mode\\}** - [](){: #mode } Default is `passive`.\n\n- **\\{verbose, Verbose\\}** - [](){: #verbose } Determines if the FTP\n communication is to be verbose or not.\n\n Default is `false`.\n\n- **\\{debug, Debug\\}** - [](){: #debug } Debugging using the dbg toolkit.\n\n Default is `disable`.\n\n- **\\{ipfamily, IpFamily\\}** - [](){: #ipfamily } With `inet6fb4` the client\n behaves as before, that is, tries to use IPv6, and only if that does not work\n it uses IPv4).\n\n Default is `inet` (IPv4).\n\n- **\\{timeout, Timeout\\}** - [](){: #timeout } Connection time-out.\n\n Default is `60000` (milliseconds).\n\n- **\\{dtimeout, DTimeout\\}** - [](){: #dtimeout } Data connect time-out. The\n time the client waits for the server to connect to the data socket.\n\n Default is `infinity`.\n\n- **\\{tls, TLSOptions\\}** - [](){: #tls_options } The FTP session is transported\n over `tls` (`ftps`, see [RFC 4217](http://www.ietf.org/rfc/rfc4217.txt)). The\n list `TLSOptions` can be empty. The function `ssl:connect/3` is used for\n securing both the control connection and the data sessions.\n\n- **\\{tls_sec_method, TLSSecMethod\\}** - [](){: #tls_sec_method } When set to\n `ftps` will connect immediately with SSL instead of upgrading with STARTTLS.\n This suboption is ignored unless the suboption `tls` is also set.\n\n Default is `ftpes`\n\n- **\\{tls_ctrl_session_reuse, boolean()\\}** - [](){: #tls_ctrl_session_reuse }\n When set to `true` the client will re-use the TLS session from the control\n channel on the data channel as enforced by many FTP servers as\n ([proposed and implemented first by vsftpd](https://scarybeastsecurity.blogspot.com/2009/02/vsftpd-210-released.html)).\n\n Default is `false`.\n\n- **\\{sock_ctrl, SocketCtrls :: \\[SocketControl :: gen_tcp:option()]\\}** -\n Passes options from `SocketCtrls` down to the underlying transport layer\n (tcp).\n\n `t:gen_tcp:option/0` except for `ipv6_v6only`, `active`, `packet`, `mode`,\n `packet_size` and `header`.\n\n Default value is `SocketCtrls = []`.\n\n- **\\{sock_data_act, \\[SocketControl]\\}** - Passes options from\n `[SocketControl]` down to the underlying transport layer (tcp).\n\n `sock_data_act` uses the value of `sock_ctrl` as default value.\n\n- **\\{sock_data_pass, \\[SocketControl]\\}** - Passes options from\n `[SocketControl]` down to the underlying transport layer (tcp).\n\n `sock_data_pass` uses the value of `sock_ctrl` as default value.\n\n- **\\{progress, Progress\\}** - [](){: #progress } Progress =\n `ignore | {Module, Function, InitialData}`\n\n `Module = atom()`, `Function = atom()`\n\n `InitialData = term()`\n\n Default is `ignore`.\n\n Option `progress` is intended to be used by applications that want to create\n some type of progress report, such as a progress bar in a GUI. Default for the\n progress option is `ignore`, that is, the option is not used. When the\n progress option is specified, the following happens when `ftp:send/[3,4]` or\n `ftp:recv/[3,4]` are called:\n\n - Before a file is transferred, the following call is made to indicate the\n start of the file transfer and how large the file is. The return value of\n the callback function is to be a new value for the `UserProgressTerm` that\n will be used as input the next time the callback function is called.\n\n `Module:Function(InitialData, File, {file_size, FileSize})`\n\n - Every time a chunk of bytes is transferred the following call is made:\n\n `Module:Function(UserProgressTerm, File, {transfer_size, TransferSize})`\n\n - At the end of the file the following call is made to indicate the end of the\n transfer:\n\n `Module:Function(UserProgressTerm, File, {transfer_size, 0})`\n\n The callback function is to be defined as follows:\n\n `Module:Function(UserProgressTerm, File, Size) -> UserProgressTerm`\n\n `UserProgressTerm = term()`\n\n `File = string()`\n\n `Size = {transfer_size, integer()} | {file_size, integer()} | {file_size, unknown}`\n\n For remote files, `ftp` cannot determine the file size in a platform\n independent way. In this case the size becomes `unknown` and it is left to the\n application to determine the size.\n\n > #### Note {: .info }\n >\n > The callback is made by a middleman process, hence the file transfer is not\n > affected by the code in the progress callback function. If the callback\n > crashes, this is detected by the FTP connection process, which then prints\n > an info-report and goes on as if the progress option was set to `ignore`.\n\n The file transfer type is set to the default of the FTP server when the\n session is opened. This is usually ASCII mode.\n\n The current local working directory (compare [`lpwd/1`](`lpwd/1`)) is set to\n the value reported by `file:get_cwd/1`, the wanted local directory.\n\n The return value `Pid` is used as a reference to the newly created FTP client\n in all other functions, and they are to be called by the process that created\n the connection. The FTP client process monitors the process that created it\n and terminates if that process terminates.","title":"ftp.open/2","ref":"ftp.html#open/2"},{"type":"function","doc":"Returns the current working directory at the remote server.","title":"ftp.pwd/1","ref":"ftp.html#pwd/1"},{"type":"function","doc":"> #### Note {: .info }\n>\n> The telnet end of line characters, from the FTP protocol definition, CRLF, for\n> example, \"\\\\\\\\r\\\\\\\\n\" has been removed.\n\nSends an arbitrary FTP command and returns verbatim a list of the lines sent\nback by the FTP server. This function is intended to give application accesses\nto FTP commands that are server-specific or that cannot be provided by this FTP\nclient.\n\n> #### Note {: .info }\n>\n> FTP commands requiring a data connection cannot be successfully issued with\n> this function.","title":"ftp.quote/2","ref":"ftp.html#quote/2"},{"type":"function","doc":"","title":"ftp.recv/2","ref":"ftp.html#recv/2"},{"type":"function","doc":"Transfers the file `RemoteFileName` from the remote server to the file system of\nthe local client. If `LocalFileName` is specified, the local file will be\n`LocalFileName`, otherwise `RemoteFileName`.\n\nIf the file write fails, the command is aborted and `{error, term()}` is\nreturned. However, the file is _not_ removed.","title":"ftp.recv/3","ref":"ftp.html#recv/3"},{"type":"function","doc":"Transfers the file `RemoteFile` from the remote server and receives it as a\nbinary.","title":"ftp.recv_bin/2","ref":"ftp.html#recv_bin/2"},{"type":"function","doc":"Receives a chunk of the remote file (`RemoteFile` of `recv_chunk_start`). The\nreturn values have the following meaning:\n\n- `ok` = the transfer is complete.\n- `{ok, Bin}` = just another chunk of the file.\n- `{error, Reason}` = transfer failed.","title":"ftp.recv_chunk/1","ref":"ftp.html#recv_chunk/1"},{"type":"function","doc":"Starts transfer of the file `RemoteFile` from the remote server.","title":"ftp.recv_chunk_start/2","ref":"ftp.html#recv_chunk_start/2"},{"type":"function","doc":"Renames `Old` to `New` at the remote server.","title":"ftp.rename/3","ref":"ftp.html#rename/3"},{"type":"function","doc":"Removes directory `Dir` at the remote server.","title":"ftp.rmdir/2","ref":"ftp.html#rmdir/2"},{"type":"function","doc":"","title":"ftp.send/2","ref":"ftp.html#send/2"},{"type":"function","doc":"Transfers the file `LocalFileName` to the remote server. If `RemoteFileName` is\nspecified, the name of the remote file is set to `RemoteFileName`, otherwise to\n`LocalFileName`.","title":"ftp.send/3","ref":"ftp.html#send/3"},{"type":"function","doc":"Transfers the binary `Bin` into the file `RemoteFile` at the remote server.","title":"ftp.send_bin/3","ref":"ftp.html#send_bin/3"},{"type":"function","doc":"Transfers the chunk `Bin` to the remote server, which writes it into the file\nspecified in the call to [`send_chunk_start/2`](`send_chunk_start/2`).\n\nFor some errors, for example, file system full, it is necessary to to call\n`send_chunk_end` to get the proper reason.","title":"ftp.send_chunk/2","ref":"ftp.html#send_chunk/2"},{"type":"function","doc":"Stops transfer of chunks to the remote server. The file at the remote server,\nspecified in the call to [`send_chunk_start/2`](`send_chunk_start/2`) is closed\nby the server.","title":"ftp.send_chunk_end/1","ref":"ftp.html#send_chunk_end/1"},{"type":"function","doc":"Starts transfer of chunks into the file `RemoteFile` at the remote server.","title":"ftp.send_chunk_start/2","ref":"ftp.html#send_chunk_start/2"},{"type":"function","doc":"Sets the file transfer type to `ascii` or `binary`. When an FTP session is\nopened, the default transfer type of the server is used, most often `ascii`,\nwhich is default according to [RFC 959](http://www.ietf.org/rfc/rfc959.txt).","title":"ftp.type/2","ref":"ftp.html#type/2"},{"type":"function","doc":"Performs login of `User` with `Pass`.","title":"ftp.user/3","ref":"ftp.html#user/3"},{"type":"function","doc":"Performs login of `User` with `Pass` to the account specified by `Account`.","title":"ftp.user/4","ref":"ftp.html#user/4"},{"type":"type","doc":"","title":"ftp.client/0","ref":"ftp.html#t:client/0"},{"type":"extras","doc":"\n# FTP Release Notes","title":"FTP Release Notes","ref":"notes.html"},{"type":"extras","doc":"","title":"Ftp 1.2.3 - FTP Release Notes","ref":"notes.html#ftp-1-2-3"},{"type":"extras","doc":"- Eliminated a race condition that sometimes resulted in `ftp:recv_bin/2` returning `ok` instead of `{ok, Data}`.\n\n Own Id: OTP-19119 Aux Id: [GH-8454] ,[PR-8543]\n\n[GH-8454]: https://github.com/erlang/otp/issues/8454\n[PR-8543]: https://github.com/erlang/otp/pull/8543","title":"Fixed Bugs and Malfunctions - FTP Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Ftp 1.2.2 - FTP Release Notes","ref":"notes.html#ftp-1-2-2"},{"type":"extras","doc":"- Dialyzer warnings due to type specs added in `m:dbg` have been eliminated.\n\n Own Id: OTP-18860","title":"Fixed Bugs and Malfunctions - FTP Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The documentation has been migrated to use Markdown and ExDoc.\n\n Own Id: OTP-18955 Aux Id: [PR-8026]\n\n[PR-8026]: https://github.com/erlang/otp/pull/8026","title":"Improvements and New Features - FTP Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Ftp 1.2.1.1 - FTP Release Notes","ref":"notes.html#ftp-1-2-1-1"},{"type":"extras","doc":"* Fix race condition that sometimes resulted in ftp:recv_bin/2 returning ok instead of \\{ok, Data\\}.\n\n Own Id: OTP-19119 Aux Id: GH-8454 ,PR-8543","title":"Fixed Bugs and Malfunctions - FTP Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Ftp 1.2.1 - FTP Release Notes","ref":"notes.html#ftp-1-2-1"},{"type":"extras","doc":"- Replaced unintentional Erlang Public License 1.1 headers in some files with\n the intended Apache License 2.0 header.\n\n Own Id: OTP-18815 Aux Id: PR-7780","title":"Fixed Bugs and Malfunctions - FTP Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Ftp 1.2 - FTP Release Notes","ref":"notes.html#ftp-1-2"},{"type":"extras","doc":"- Fixes the documentation for the `ftp` module and updates the typing of `ftp`\n functions that return errors.\n\n The documentation has been improved and the types of the functions are now\n read from source code, instead of being hard-coded in XML.\n\n Functions returning errors of the form `{error, Reason :: 'ehost' | ...}` are\n now similar to other modules, i.e., `{error, Reason :: term()}`. If one wants\n to understand the error, one must call the function\n `ftp:formaterror({error, Reason})`.\n\n Own Id: OTP-18359 Aux Id: PR-6545","title":"Fixed Bugs and Malfunctions - FTP Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Deprecates `dbg:stop_clear/0` because it is simply a function alias to\n `dbg:stop/0`\n\n Own Id: OTP-18478 Aux Id: GH-6903\n\n- Remove deprecated functions in OTP-26\n\n Own Id: OTP-18541","title":"Improvements and New Features - FTP Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Ftp 1.1.4 - FTP Release Notes","ref":"notes.html#ftp-1-1-4"},{"type":"extras","doc":"- Replace size/1 with either tuple_size/1 or byte_size/1\n\n The [`size/1`](`size/1`) BIF is not optimized by the JIT, and its use can\n result in worse types for Dialyzer.\n\n When one knows that the value being tested must be a tuple,\n [`tuple_size/1`](`tuple_size/1`) should always be preferred.\n\n When one knows that the value being tested must be a binary,\n [`byte_size/1`](`byte_size/1`) should be preferred. However,\n [`byte_size/1`](`byte_size/1`) also accepts a bitstring (rounding up size to a\n whole number of bytes), so one must make sure that the call to `byte_size/` is\n preceded by a call to [`is_binary/1`](`is_binary/1`) to ensure that bitstrings\n are rejected. Note that the compiler removes redundant calls to\n [`is_binary/1`](`is_binary/1`), so if one is not sure whether previous code\n had made sure that the argument is a binary, it does not harm to add an\n [`is_binary/1`](`is_binary/1`) test immediately before the call to\n [`byte_size/1`](`byte_size/1`).\n\n Own Id: OTP-18432 Aux Id:\n GH-6672,PR-6793,PR-6784,PR-6787,PR-6785,PR-6682,PR-6800,PR-6797,PR-6798,PR-6799,PR-6796,PR-6813,PR-6671,PR-6673,PR-6684,PR-6694,GH-6677,PR-6696,PR-6670,PR-6674","title":"Improvements and New Features - FTP Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Ftp 1.1.3 - FTP Release Notes","ref":"notes.html#ftp-1-1-3"},{"type":"extras","doc":"- Fixes calls to `ftp:nlist/2` returning `{error, epath}` when the file / folder\n exists\n\n Own Id: OTP-18409 Aux Id: PR-6721,ERIERL-908","title":"Fixed Bugs and Malfunctions - FTP Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Ftp 1.1.2 - FTP Release Notes","ref":"notes.html#ftp-1-1-2"},{"type":"extras","doc":"- fix unexpected result `ok` when calling `ftp:nlist` repeatedly\n\n Own Id: OTP-18252 Aux Id: GH-5823","title":"Fixed Bugs and Malfunctions - FTP Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Ftp 1.1.1 - FTP Release Notes","ref":"notes.html#ftp-1-1-1"},{"type":"extras","doc":"- An unexpected timeout message on the FTP control channel was observed in a\n real system and could not be associated with anything that was expected to\n happen, so we will ignore but info log such unexpected messages.\n\n Own Id: OTP-17989 Aux Id: ERIERL-767","title":"Fixed Bugs and Malfunctions - FTP Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Ftp 1.1 - FTP Release Notes","ref":"notes.html#ftp-1-1"},{"type":"extras","doc":"- Use OTP supervisor as intended, avoiding surprising behavior as the killing of\n the user's process. Also, FTP state handling logic is improved to avoid race\n conditions that could result in unexpected errors.\n\n Own Id: OTP-16926 Aux Id: ERL-1450, GH-4473\n\n- Missing runtime dependencies has been added to this application.\n\n Own Id: OTP-17243 Aux Id: PR-4557","title":"Fixed Bugs and Malfunctions - FTP Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add support for FTPES (explicit FTP over TLS).\n\n Own Id: OTP-15523 Aux Id: OTP-15352, PR-1968","title":"Improvements and New Features - FTP Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Ftp 1.0.5 - FTP Release Notes","ref":"notes.html#ftp-1-0-5"},{"type":"extras","doc":"- Avoid timing issue when setting active once on a socket that is being closed\n by the peer.\n\n Own Id: OTP-16734 Aux Id: OTP-16697, ERIERL-496","title":"Fixed Bugs and Malfunctions - FTP Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Ftp 1.0.4.1 - FTP Release Notes","ref":"notes.html#ftp-1-0-4-1"},{"type":"extras","doc":"- Avoid timing issue when setting active once on a socket that is being closed\n by the peer.\n\n Own Id: OTP-16734 Aux Id: OTP-16697, ERIERL-496","title":"Fixed Bugs and Malfunctions - FTP Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Ftp 1.0.4 - FTP Release Notes","ref":"notes.html#ftp-1-0-4"},{"type":"extras","doc":"- A possibly infinite loop is removed.\n\n Own Id: OTP-16243 Aux Id: PR-2436, OTP-16056","title":"Fixed Bugs and Malfunctions - FTP Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Removed compiler warnings.\n\n Own Id: OTP-16318 Aux Id: OTP-16183","title":"Improvements and New Features - FTP Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Ftp 1.0.3 - FTP Release Notes","ref":"notes.html#ftp-1-0-3"},{"type":"extras","doc":"- A possibly infinite loop when receiving messages divided in parts is removed.\n\n Own Id: OTP-16056","title":"Fixed Bugs and Malfunctions - FTP Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Ftp 1.0.2.2 - FTP Release Notes","ref":"notes.html#ftp-1-0-2-2"},{"type":"extras","doc":"- A possibly infinite loop is removed.\n\n Own Id: OTP-16243 Aux Id: PR-2436, OTP-16056","title":"Fixed Bugs and Malfunctions - FTP Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Ftp 1.0.2.1 - FTP Release Notes","ref":"notes.html#ftp-1-0-2-1"},{"type":"extras","doc":"- A possibly infinite loop when receiving messages divided in parts is removed.\n\n Own Id: OTP-16056","title":"Fixed Bugs and Malfunctions - FTP Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Ftp 1.0.2 - FTP Release Notes","ref":"notes.html#ftp-1-0-2"},{"type":"extras","doc":"- Fixed timing related bug that could make ftp functions behave badly.\n\n Own Id: OTP-15659 Aux Id: ERIERL-316","title":"Fixed Bugs and Malfunctions - FTP Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Ftp 1.0.1 - FTP Release Notes","ref":"notes.html#ftp-1-0-1"},{"type":"extras","doc":"- Improved documentation.\n\n Own Id: OTP-15190","title":"Fixed Bugs and Malfunctions - FTP Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"FTP 1.0 - FTP Release Notes","ref":"notes.html#ftp-1-0"},{"type":"extras","doc":"- Inets application was split into multiple smaller protocol specific\n applications. The FTP application is a standalone FTP client with the same\n functionality as FTP client in Inets.\n\n Own Id: OTP-14113","title":"First released version - FTP Release Notes","ref":"notes.html#first-released-version"},{"type":"extras","doc":"\n# FTP client introduction\n\nFTP clients are considered to be rather temporary. Thus, they are only started\nand stopped during runtime and cannot be started at application startup. The FTP\nclient API is designed to allow some functions to return intermediate results.\nThis implies that only the process that started the FTP client can access it\nwith preserved sane semantics. If the process that started the FTP session dies,\nthe FTP client process terminates.\n\nThe client supports IPv6 as long as the underlying mechanisms also do so.","title":"FTP client introduction","ref":"introduction.html"},{"type":"extras","doc":"\n# Examples \n\n\nThe following is a simple example of an FTP session, where the user `guest` with\npassword `password` logs on to the remote host `erlang.org`:\n\n```erlang\n 1> ftp:start().\n ok\n 2> {ok, Pid} = ftp:open([{host, \"erlang.org\"}]).\n {ok,<0.22.0>}\n 3> ftp:user(Pid, \"guest\", \"password\").\n ok\n 4> ftp:pwd(Pid).\n {ok, \"/home/guest\"}\n 5> ftp:cd(Pid, \"appl/examples\").\n ok\n 6> ftp:lpwd(Pid).\n {ok, \"/home/fred\"}.\n 7> ftp:lcd(Pid, \"/home/eproj/examples\").\n ok\n 8> ftp:recv(Pid, \"appl.erl\").\n ok\n 9> ftp:close(Pid).\n ok\n 10> ftp:stop().\n ok\n```\n\nThe file `appl.erl` is transferred from the remote to the local host. When the\nsession is opened, the current directory at the remote host is `/home/guest`,\nand `/home/fred` at the local host. Before transferring the file, the current\nlocal directory is changed to `/home/eproj/examples`, and the remote directory\nis set to `/home/guest/appl/examples`.","title":"Examples","ref":"ftp_client.html"}],"content_type":"text/plain","producer":{"name":"ex_doc","version":[48,46,51,52,46,49]}} \ No newline at end of file diff --git a/prs/9045/lib/ftp-1.2.3/doc/html/dist/search_data-8D0628B6.js b/prs/9045/lib/ftp-1.2.3/doc/html/dist/search_data-8D0628B6.js deleted file mode 100644 index 8f209d2ff41a..000000000000 --- a/prs/9045/lib/ftp-1.2.3/doc/html/dist/search_data-8D0628B6.js +++ /dev/null @@ -1 +0,0 @@ -searchData={"items":[{"type":"module","title":"ftp","doc":"A File Transfer Protocol client.\n\nThis module implements a client for file transfer according to a subset of the\nFile Transfer Protocol (FTP), see [RFC 959](http://www.ietf.org/rfc/rfc959.txt).\n\nThe FTP client always tries to use passive FTP mode and only resort to active\nFTP mode if this fails. This default behavior can be changed by start option\n[mode](`m:ftp#mode`).\n\nFor a simple example of an FTP session, see [FTP User's Guide](ftp_client.md).\n\nThe return values of the following functions depend much on the implementation\nof the FTP server at the remote host. In particular, the results from `ls` and\n`nlist` varies. Often real errors are not reported as errors by `ls`, even if,\nfor example, a file or directory does not exist. `nlist` is usually more strict,\nbut some implementations have the peculiar behaviour of responding with an error\nif the request is a listing of the contents of a directory that exists but is\nempty.","ref":"ftp.html"},{"type":"module","title":"Errors - ftp","doc":"The possible error reasons and the corresponding diagnostic strings returned by\n[`formaterror/1`](`formaterror/1`) are as follows:\n\n- **`echunk`** - Synchronization error during chunk sending according to one of\n the following:\n\n - A call is made to [`send_chunk/2`](`send_chunk/2`) or\n [`send_chunk_end/1`](`send_chunk_end/1`) before a call to\n [`send_chunk_start/2`](`send_chunk_start/2`).\n - A call has been made to another transfer function during chunk sending, that\n is, before a call to [`send_chunk_end/1`](`send_chunk_end/1`).\n\n- **`eclosed`** - The session is closed.\n\n- **`econn`** - Connection to the remote server is prematurely closed.\n\n- **`ehost`** - Host is not found, FTP server is not found, or connection is\n rejected by FTP server.\n\n- **`elogin`** - User is not logged in.\n\n- **`enotbinary`** - Term is not a binary.\n\n- **`epath`** - No such file or directory, or directory already exists, or\n permission denied.\n\n- **`etype`** - No such type.\n\n- **`euser`** - Invalid username or password.\n\n- **`etnospc`** - Insufficient storage space in system \\[452].\n\n- **`epnospc`** - Exceeded storage allocation (for current directory or dataset)\n \\[552].\n\n- **`efnamena`** - Filename not allowed \\[553].","ref":"ftp.html#module-errors"},{"type":"function","title":"ftp.account/2","doc":"Sets the account for an operation, if needed.","ref":"ftp.html#account/2"},{"type":"function","title":"ftp.append/2","doc":"","ref":"ftp.html#append/2"},{"type":"function","title":"ftp.append/3","doc":"Transfers the file `LocalFile` to the remote server. If `RemoteFile` is\nspecified, the name of the remote file that the file is appended to is set to\n`RemoteFile`, otherwise to `LocalFile`. If the file does not exists, it is\ncreated.","ref":"ftp.html#append/3"},{"type":"function","title":"ftp.append_bin/3","doc":"Transfers the binary `Bin` to the remote server and appends it to the file\n`RemoteFile`. If the file does not exist, it is created.","ref":"ftp.html#append_bin/3"},{"type":"function","title":"ftp.append_chunk/2","doc":"Transfers the chunk `Bin` to the remote server, which appends it to the file\nspecified in the call to [`append_chunk_start/2`](`append_chunk_start/2`).\n\nFor some errors, for example, file system full, it is necessary to call\n`append_chunk_end` to get the proper reason.","ref":"ftp.html#append_chunk/2"},{"type":"function","title":"ftp.append_chunk_end/1","doc":"Stops transfer of chunks for appending to the remote server. The file at the\nremote server, specified in the call to\n[`append_chunk_start/2`](`append_chunk_start/2`), is closed by the server.","ref":"ftp.html#append_chunk_end/1"},{"type":"function","title":"ftp.append_chunk_start/2","doc":"Starts the transfer of chunks for appending to the file `RemoteFile` at the\nremote server. If the file does not exist, it is created.","ref":"ftp.html#append_chunk_start/2"},{"type":"function","title":"ftp.cd/2","doc":"Changes the working directory at the remote server to `Dir`.","ref":"ftp.html#cd/2"},{"type":"function","title":"ftp.close/1","doc":"Ends an FTP session, created using function [open](`open/2`).","ref":"ftp.html#close/1"},{"type":"function","title":"ftp.delete/2","doc":"Deletes the file `File` at the remote server.","ref":"ftp.html#delete/2"},{"type":"function","title":"ftp.formaterror/1","doc":"Given an error return value `{error, AtomReason}`, this function returns a\nreadable string describing the error.","ref":"ftp.html#formaterror/1"},{"type":"function","title":"ftp.lcd/2","doc":"Changes the working directory to `Dir` for the local client.","ref":"ftp.html#lcd/2"},{"type":"function","title":"ftp.lpwd/1","doc":"Returns the current working directory at the local client.","ref":"ftp.html#lpwd/1"},{"type":"function","title":"ftp.ls/1","doc":"","ref":"ftp.html#ls/1"},{"type":"function","title":"ftp.ls/2","doc":"Returns a list of files in long format.\n\n`Dir` can be a directory or a file. The `Dir` string can contain wildcards.\n\n[`ls/1`](`ls/1`) implies the current remote directory of the user.\n\nThe format of `Listing` depends on the operating system. On UNIX, it is\ntypically produced from the output of the `ls -l` shell command.","ref":"ftp.html#ls/2"},{"type":"function","title":"ftp.mkdir/2","doc":"Creates the directory `Dir` at the remote server.","ref":"ftp.html#mkdir/2"},{"type":"function","title":"ftp.nlist/1","doc":"","ref":"ftp.html#nlist/1"},{"type":"function","title":"ftp.nlist/2","doc":"Returns a list of files in short format.\n\n`Pathname` can be a directory or a file. The `Pathname` string can contain\nwildcards.\n\n[`nlist/1`](`nlist/1`) implies the current remote directory of the user.\n\nThe format of `Listing` is a stream of filenames where each filename is\nseparated by or . Contrary to function `ls`, the purpose of `nlist`\nis to enable a program to process filename information automatically.","ref":"ftp.html#nlist/2"},{"type":"function","title":"ftp.open/1","doc":"","ref":"ftp.html#open/1"},{"type":"function","title":"ftp.open/2","doc":"Starts a FTP client process and opens a session with the FTP server at `Host`.\n\nA session opened in this way is closed using function `close/1`.\n\nThe available configuration options are as follows:\n\n- **\\{host, Host\\}** - [](){: #host } Host = `string() | ip_address()`\n\n- **\\{port, Port\\}** - [](){: #port } Default is `0` which aliases to `21` or\n `990` when used with [`{tls_sec_method,ftps}`](`open/2`)).\n\n- **\\{mode, Mode\\}** - [](){: #mode } Default is `passive`.\n\n- **\\{verbose, Verbose\\}** - [](){: #verbose } Determines if the FTP\n communication is to be verbose or not.\n\n Default is `false`.\n\n- **\\{debug, Debug\\}** - [](){: #debug } Debugging using the dbg toolkit.\n\n Default is `disable`.\n\n- **\\{ipfamily, IpFamily\\}** - [](){: #ipfamily } With `inet6fb4` the client\n behaves as before, that is, tries to use IPv6, and only if that does not work\n it uses IPv4).\n\n Default is `inet` (IPv4).\n\n- **\\{timeout, Timeout\\}** - [](){: #timeout } Connection time-out.\n\n Default is `60000` (milliseconds).\n\n- **\\{dtimeout, DTimeout\\}** - [](){: #dtimeout } Data connect time-out. The\n time the client waits for the server to connect to the data socket.\n\n Default is `infinity`.\n\n- **\\{tls, TLSOptions\\}** - [](){: #tls_options } The FTP session is transported\n over `tls` (`ftps`, see [RFC 4217](http://www.ietf.org/rfc/rfc4217.txt)). The\n list `TLSOptions` can be empty. The function `ssl:connect/3` is used for\n securing both the control connection and the data sessions.\n\n- **\\{tls_sec_method, TLSSecMethod\\}** - [](){: #tls_sec_method } When set to\n `ftps` will connect immediately with SSL instead of upgrading with STARTTLS.\n This suboption is ignored unless the suboption `tls` is also set.\n\n Default is `ftpes`\n\n- **\\{tls_ctrl_session_reuse, boolean()\\}** - [](){: #tls_ctrl_session_reuse }\n When set to `true` the client will re-use the TLS session from the control\n channel on the data channel as enforced by many FTP servers as\n ([proposed and implemented first by vsftpd](https://scarybeastsecurity.blogspot.com/2009/02/vsftpd-210-released.html)).\n\n Default is `false`.\n\n- **\\{sock_ctrl, SocketCtrls :: \\[SocketControl :: gen_tcp:option()]\\}** -\n Passes options from `SocketCtrls` down to the underlying transport layer\n (tcp).\n\n `t:gen_tcp:option/0` except for `ipv6_v6only`, `active`, `packet`, `mode`,\n `packet_size` and `header`.\n\n Default value is `SocketCtrls = []`.\n\n- **\\{sock_data_act, \\[SocketControl]\\}** - Passes options from\n `[SocketControl]` down to the underlying transport layer (tcp).\n\n `sock_data_act` uses the value of `sock_ctrl` as default value.\n\n- **\\{sock_data_pass, \\[SocketControl]\\}** - Passes options from\n `[SocketControl]` down to the underlying transport layer (tcp).\n\n `sock_data_pass` uses the value of `sock_ctrl` as default value.\n\n- **\\{progress, Progress\\}** - [](){: #progress } Progress =\n `ignore | {Module, Function, InitialData}`\n\n `Module = atom()`, `Function = atom()`\n\n `InitialData = term()`\n\n Default is `ignore`.\n\n Option `progress` is intended to be used by applications that want to create\n some type of progress report, such as a progress bar in a GUI. Default for the\n progress option is `ignore`, that is, the option is not used. When the\n progress option is specified, the following happens when `ftp:send/[3,4]` or\n `ftp:recv/[3,4]` are called:\n\n - Before a file is transferred, the following call is made to indicate the\n start of the file transfer and how large the file is. The return value of\n the callback function is to be a new value for the `UserProgressTerm` that\n will be used as input the next time the callback function is called.\n\n `Module:Function(InitialData, File, {file_size, FileSize})`\n\n - Every time a chunk of bytes is transferred the following call is made:\n\n `Module:Function(UserProgressTerm, File, {transfer_size, TransferSize})`\n\n - At the end of the file the following call is made to indicate the end of the\n transfer:\n\n `Module:Function(UserProgressTerm, File, {transfer_size, 0})`\n\n The callback function is to be defined as follows:\n\n `Module:Function(UserProgressTerm, File, Size) -> UserProgressTerm`\n\n `UserProgressTerm = term()`\n\n `File = string()`\n\n `Size = {transfer_size, integer()} | {file_size, integer()} | {file_size, unknown}`\n\n For remote files, `ftp` cannot determine the file size in a platform\n independent way. In this case the size becomes `unknown` and it is left to the\n application to determine the size.\n\n > #### Note {: .info }\n >\n > The callback is made by a middleman process, hence the file transfer is not\n > affected by the code in the progress callback function. If the callback\n > crashes, this is detected by the FTP connection process, which then prints\n > an info-report and goes on as if the progress option was set to `ignore`.\n\n The file transfer type is set to the default of the FTP server when the\n session is opened. This is usually ASCII mode.\n\n The current local working directory (compare [`lpwd/1`](`lpwd/1`)) is set to\n the value reported by `file:get_cwd/1`, the wanted local directory.\n\n The return value `Pid` is used as a reference to the newly created FTP client\n in all other functions, and they are to be called by the process that created\n the connection. The FTP client process monitors the process that created it\n and terminates if that process terminates.","ref":"ftp.html#open/2"},{"type":"function","title":"ftp.pwd/1","doc":"Returns the current working directory at the remote server.","ref":"ftp.html#pwd/1"},{"type":"function","title":"ftp.quote/2","doc":"> #### Note {: .info }\n>\n> The telnet end of line characters, from the FTP protocol definition, CRLF, for\n> example, \"\\\\\\\\r\\\\\\\\n\" has been removed.\n\nSends an arbitrary FTP command and returns verbatim a list of the lines sent\nback by the FTP server. This function is intended to give application accesses\nto FTP commands that are server-specific or that cannot be provided by this FTP\nclient.\n\n> #### Note {: .info }\n>\n> FTP commands requiring a data connection cannot be successfully issued with\n> this function.","ref":"ftp.html#quote/2"},{"type":"function","title":"ftp.recv/2","doc":"","ref":"ftp.html#recv/2"},{"type":"function","title":"ftp.recv/3","doc":"Transfers the file `RemoteFileName` from the remote server to the file system of\nthe local client. If `LocalFileName` is specified, the local file will be\n`LocalFileName`, otherwise `RemoteFileName`.\n\nIf the file write fails, the command is aborted and `{error, term()}` is\nreturned. However, the file is _not_ removed.","ref":"ftp.html#recv/3"},{"type":"function","title":"ftp.recv_bin/2","doc":"Transfers the file `RemoteFile` from the remote server and receives it as a\nbinary.","ref":"ftp.html#recv_bin/2"},{"type":"function","title":"ftp.recv_chunk/1","doc":"Receives a chunk of the remote file (`RemoteFile` of `recv_chunk_start`). The\nreturn values have the following meaning:\n\n- `ok` = the transfer is complete.\n- `{ok, Bin}` = just another chunk of the file.\n- `{error, Reason}` = transfer failed.","ref":"ftp.html#recv_chunk/1"},{"type":"function","title":"ftp.recv_chunk_start/2","doc":"Starts transfer of the file `RemoteFile` from the remote server.","ref":"ftp.html#recv_chunk_start/2"},{"type":"function","title":"ftp.rename/3","doc":"Renames `Old` to `New` at the remote server.","ref":"ftp.html#rename/3"},{"type":"function","title":"ftp.rmdir/2","doc":"Removes directory `Dir` at the remote server.","ref":"ftp.html#rmdir/2"},{"type":"function","title":"ftp.send/2","doc":"","ref":"ftp.html#send/2"},{"type":"function","title":"ftp.send/3","doc":"Transfers the file `LocalFileName` to the remote server. If `RemoteFileName` is\nspecified, the name of the remote file is set to `RemoteFileName`, otherwise to\n`LocalFileName`.","ref":"ftp.html#send/3"},{"type":"function","title":"ftp.send_bin/3","doc":"Transfers the binary `Bin` into the file `RemoteFile` at the remote server.","ref":"ftp.html#send_bin/3"},{"type":"function","title":"ftp.send_chunk/2","doc":"Transfers the chunk `Bin` to the remote server, which writes it into the file\nspecified in the call to [`send_chunk_start/2`](`send_chunk_start/2`).\n\nFor some errors, for example, file system full, it is necessary to to call\n`send_chunk_end` to get the proper reason.","ref":"ftp.html#send_chunk/2"},{"type":"function","title":"ftp.send_chunk_end/1","doc":"Stops transfer of chunks to the remote server. The file at the remote server,\nspecified in the call to [`send_chunk_start/2`](`send_chunk_start/2`) is closed\nby the server.","ref":"ftp.html#send_chunk_end/1"},{"type":"function","title":"ftp.send_chunk_start/2","doc":"Starts transfer of chunks into the file `RemoteFile` at the remote server.","ref":"ftp.html#send_chunk_start/2"},{"type":"function","title":"ftp.type/2","doc":"Sets the file transfer type to `ascii` or `binary`. When an FTP session is\nopened, the default transfer type of the server is used, most often `ascii`,\nwhich is default according to [RFC 959](http://www.ietf.org/rfc/rfc959.txt).","ref":"ftp.html#type/2"},{"type":"function","title":"ftp.user/3","doc":"Performs login of `User` with `Pass`.","ref":"ftp.html#user/3"},{"type":"function","title":"ftp.user/4","doc":"Performs login of `User` with `Pass` to the account specified by `Account`.","ref":"ftp.html#user/4"},{"type":"type","title":"ftp.client/0","doc":"","ref":"ftp.html#t:client/0"},{"type":"extras","title":"FTP Release Notes","doc":"\n# FTP Release Notes","ref":"notes.html"},{"type":"extras","title":"Ftp 1.2.3 - FTP Release Notes","doc":"","ref":"notes.html#ftp-1-2-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - FTP Release Notes","doc":"- Eliminated a race condition that sometimes resulted in `ftp:recv_bin/2` returning `ok` instead of `{ok, Data}`.\n\n Own Id: OTP-19119 Aux Id: [GH-8454] ,[PR-8543]\n\n[GH-8454]: https://github.com/erlang/otp/issues/8454\n[PR-8543]: https://github.com/erlang/otp/pull/8543","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Ftp 1.2.2 - FTP Release Notes","doc":"","ref":"notes.html#ftp-1-2-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - FTP Release Notes","doc":"- Dialyzer warnings due to type specs added in `m:dbg` have been eliminated.\n\n Own Id: OTP-18860","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - FTP Release Notes","doc":"- The documentation has been migrated to use Markdown and ExDoc.\n\n Own Id: OTP-18955 Aux Id: [PR-8026]\n\n[PR-8026]: https://github.com/erlang/otp/pull/8026","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Ftp 1.2.1.1 - FTP Release Notes","doc":"","ref":"notes.html#ftp-1-2-1-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - FTP Release Notes","doc":"* Fix race condition that sometimes resulted in ftp:recv_bin/2 returning ok instead of \\{ok, Data\\}.\n\n Own Id: OTP-19119 Aux Id: GH-8454 ,PR-8543","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Ftp 1.2.1 - FTP Release Notes","doc":"","ref":"notes.html#ftp-1-2-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - FTP Release Notes","doc":"- Replaced unintentional Erlang Public License 1.1 headers in some files with\n the intended Apache License 2.0 header.\n\n Own Id: OTP-18815 Aux Id: PR-7780","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Ftp 1.2 - FTP Release Notes","doc":"","ref":"notes.html#ftp-1-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - FTP Release Notes","doc":"- Fixes the documentation for the `ftp` module and updates the typing of `ftp`\n functions that return errors.\n\n The documentation has been improved and the types of the functions are now\n read from source code, instead of being hard-coded in XML.\n\n Functions returning errors of the form `{error, Reason :: 'ehost' | ...}` are\n now similar to other modules, i.e., `{error, Reason :: term()}`. If one wants\n to understand the error, one must call the function\n `ftp:formaterror({error, Reason})`.\n\n Own Id: OTP-18359 Aux Id: PR-6545","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - FTP Release Notes","doc":"- Deprecates `dbg:stop_clear/0` because it is simply a function alias to\n `dbg:stop/0`\n\n Own Id: OTP-18478 Aux Id: GH-6903\n\n- Remove deprecated functions in OTP-26\n\n Own Id: OTP-18541","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Ftp 1.1.4 - FTP Release Notes","doc":"","ref":"notes.html#ftp-1-1-4"},{"type":"extras","title":"Improvements and New Features - FTP Release Notes","doc":"- Replace size/1 with either tuple_size/1 or byte_size/1\n\n The [`size/1`](`size/1`) BIF is not optimized by the JIT, and its use can\n result in worse types for Dialyzer.\n\n When one knows that the value being tested must be a tuple,\n [`tuple_size/1`](`tuple_size/1`) should always be preferred.\n\n When one knows that the value being tested must be a binary,\n [`byte_size/1`](`byte_size/1`) should be preferred. However,\n [`byte_size/1`](`byte_size/1`) also accepts a bitstring (rounding up size to a\n whole number of bytes), so one must make sure that the call to `byte_size/` is\n preceded by a call to [`is_binary/1`](`is_binary/1`) to ensure that bitstrings\n are rejected. Note that the compiler removes redundant calls to\n [`is_binary/1`](`is_binary/1`), so if one is not sure whether previous code\n had made sure that the argument is a binary, it does not harm to add an\n [`is_binary/1`](`is_binary/1`) test immediately before the call to\n [`byte_size/1`](`byte_size/1`).\n\n Own Id: OTP-18432 Aux Id:\n GH-6672,PR-6793,PR-6784,PR-6787,PR-6785,PR-6682,PR-6800,PR-6797,PR-6798,PR-6799,PR-6796,PR-6813,PR-6671,PR-6673,PR-6684,PR-6694,GH-6677,PR-6696,PR-6670,PR-6674","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Ftp 1.1.3 - FTP Release Notes","doc":"","ref":"notes.html#ftp-1-1-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - FTP Release Notes","doc":"- Fixes calls to `ftp:nlist/2` returning `{error, epath}` when the file / folder\n exists\n\n Own Id: OTP-18409 Aux Id: PR-6721,ERIERL-908","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Ftp 1.1.2 - FTP Release Notes","doc":"","ref":"notes.html#ftp-1-1-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - FTP Release Notes","doc":"- fix unexpected result `ok` when calling `ftp:nlist` repeatedly\n\n Own Id: OTP-18252 Aux Id: GH-5823","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Ftp 1.1.1 - FTP Release Notes","doc":"","ref":"notes.html#ftp-1-1-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - FTP Release Notes","doc":"- An unexpected timeout message on the FTP control channel was observed in a\n real system and could not be associated with anything that was expected to\n happen, so we will ignore but info log such unexpected messages.\n\n Own Id: OTP-17989 Aux Id: ERIERL-767","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Ftp 1.1 - FTP Release Notes","doc":"","ref":"notes.html#ftp-1-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - FTP Release Notes","doc":"- Use OTP supervisor as intended, avoiding surprising behavior as the killing of\n the user's process. Also, FTP state handling logic is improved to avoid race\n conditions that could result in unexpected errors.\n\n Own Id: OTP-16926 Aux Id: ERL-1450, GH-4473\n\n- Missing runtime dependencies has been added to this application.\n\n Own Id: OTP-17243 Aux Id: PR-4557","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - FTP Release Notes","doc":"- Add support for FTPES (explicit FTP over TLS).\n\n Own Id: OTP-15523 Aux Id: OTP-15352, PR-1968","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Ftp 1.0.5 - FTP Release Notes","doc":"","ref":"notes.html#ftp-1-0-5"},{"type":"extras","title":"Fixed Bugs and Malfunctions - FTP Release Notes","doc":"- Avoid timing issue when setting active once on a socket that is being closed\n by the peer.\n\n Own Id: OTP-16734 Aux Id: OTP-16697, ERIERL-496","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Ftp 1.0.4.1 - FTP Release Notes","doc":"","ref":"notes.html#ftp-1-0-4-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - FTP Release Notes","doc":"- Avoid timing issue when setting active once on a socket that is being closed\n by the peer.\n\n Own Id: OTP-16734 Aux Id: OTP-16697, ERIERL-496","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Ftp 1.0.4 - FTP Release Notes","doc":"","ref":"notes.html#ftp-1-0-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - FTP Release Notes","doc":"- A possibly infinite loop is removed.\n\n Own Id: OTP-16243 Aux Id: PR-2436, OTP-16056","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - FTP Release Notes","doc":"- Removed compiler warnings.\n\n Own Id: OTP-16318 Aux Id: OTP-16183","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Ftp 1.0.3 - FTP Release Notes","doc":"","ref":"notes.html#ftp-1-0-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - FTP Release Notes","doc":"- A possibly infinite loop when receiving messages divided in parts is removed.\n\n Own Id: OTP-16056","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Ftp 1.0.2.2 - FTP Release Notes","doc":"","ref":"notes.html#ftp-1-0-2-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - FTP Release Notes","doc":"- A possibly infinite loop is removed.\n\n Own Id: OTP-16243 Aux Id: PR-2436, OTP-16056","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Ftp 1.0.2.1 - FTP Release Notes","doc":"","ref":"notes.html#ftp-1-0-2-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - FTP Release Notes","doc":"- A possibly infinite loop when receiving messages divided in parts is removed.\n\n Own Id: OTP-16056","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Ftp 1.0.2 - FTP Release Notes","doc":"","ref":"notes.html#ftp-1-0-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - FTP Release Notes","doc":"- Fixed timing related bug that could make ftp functions behave badly.\n\n Own Id: OTP-15659 Aux Id: ERIERL-316","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Ftp 1.0.1 - FTP Release Notes","doc":"","ref":"notes.html#ftp-1-0-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - FTP Release Notes","doc":"- Improved documentation.\n\n Own Id: OTP-15190","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"FTP 1.0 - FTP Release Notes","doc":"","ref":"notes.html#ftp-1-0"},{"type":"extras","title":"First released version - FTP Release Notes","doc":"- Inets application was split into multiple smaller protocol specific\n applications. The FTP application is a standalone FTP client with the same\n functionality as FTP client in Inets.\n\n Own Id: OTP-14113","ref":"notes.html#first-released-version"},{"type":"extras","title":"FTP client introduction","doc":"\n# FTP client introduction\n\nFTP clients are considered to be rather temporary. Thus, they are only started\nand stopped during runtime and cannot be started at application startup. The FTP\nclient API is designed to allow some functions to return intermediate results.\nThis implies that only the process that started the FTP client can access it\nwith preserved sane semantics. If the process that started the FTP session dies,\nthe FTP client process terminates.\n\nThe client supports IPv6 as long as the underlying mechanisms also do so.","ref":"introduction.html"},{"type":"extras","title":"Examples","doc":"\n# Examples \n\n\nThe following is a simple example of an FTP session, where the user `guest` with\npassword `password` logs on to the remote host `erlang.org`:\n\n```erlang\n 1> ftp:start().\n ok\n 2> {ok, Pid} = ftp:open([{host, \"erlang.org\"}]).\n {ok,<0.22.0>}\n 3> ftp:user(Pid, \"guest\", \"password\").\n ok\n 4> ftp:pwd(Pid).\n {ok, \"/home/guest\"}\n 5> ftp:cd(Pid, \"appl/examples\").\n ok\n 6> ftp:lpwd(Pid).\n {ok, \"/home/fred\"}.\n 7> ftp:lcd(Pid, \"/home/eproj/examples\").\n ok\n 8> ftp:recv(Pid, \"appl.erl\").\n ok\n 9> ftp:close(Pid).\n ok\n 10> ftp:stop().\n ok\n```\n\nThe file `appl.erl` is transferred from the remote to the local host. When the\nsession is opened, the current directory at the remote host is `/home/guest`,\nand `/home/fred` at the local host. Before transferring the file, the current\nlocal directory is changed to `/home/eproj/examples`, and the remote directory\nis set to `/home/guest/appl/examples`.","ref":"ftp_client.html"}],"content_type":"text/plain","producer":{"name":"ex_doc","version":[48,46,51,52,46,49]}} \ No newline at end of file diff --git a/prs/9045/lib/ftp-1.2.3/doc/html/ftp.epub b/prs/9045/lib/ftp-1.2.3/doc/html/ftp.epub index 34340c1b777c..944efb276af7 100644 Binary files a/prs/9045/lib/ftp-1.2.3/doc/html/ftp.epub and b/prs/9045/lib/ftp-1.2.3/doc/html/ftp.epub differ diff --git a/prs/9045/lib/ftp-1.2.3/doc/html/ftp_client.html b/prs/9045/lib/ftp-1.2.3/doc/html/ftp_client.html index 07f1d6ff6b40..5b73b80b0235 100644 --- a/prs/9045/lib/ftp-1.2.3/doc/html/ftp_client.html +++ b/prs/9045/lib/ftp-1.2.3/doc/html/ftp_client.html @@ -132,25 +132,25 @@

    The following is a simple example of an FTP session, where the user guest with -password password logs on to the remote host erlang.org:

          1> ftp:start().
    +password password logs on to the remote host erlang.org:

          1> ftp:start().
           ok
    -      2> {ok, Pid} = ftp:open([{host, "erlang.org"}]).
    -      {ok,<0.22.0>}
    -      3> ftp:user(Pid, "guest", "password").
    +      2> {ok, Pid} = ftp:open([{host, "erlang.org"}]).
    +      {ok,<0.22.0>}
    +      3> ftp:user(Pid, "guest", "password").
           ok
    -      4> ftp:pwd(Pid).
    -      {ok, "/home/guest"}
    -      5> ftp:cd(Pid, "appl/examples").
    +      4> ftp:pwd(Pid).
    +      {ok, "/home/guest"}
    +      5> ftp:cd(Pid, "appl/examples").
           ok
    -      6> ftp:lpwd(Pid).
    -      {ok, "/home/fred"}.
    -      7> ftp:lcd(Pid, "/home/eproj/examples").
    +      6> ftp:lpwd(Pid).
    +      {ok, "/home/fred"}.
    +      7> ftp:lcd(Pid, "/home/eproj/examples").
           ok
    -      8> ftp:recv(Pid, "appl.erl").
    +      8> ftp:recv(Pid, "appl.erl").
           ok
    -      9> ftp:close(Pid).
    +      9> ftp:close(Pid).
           ok
    -      10> ftp:stop().
    +      10> ftp:stop().
           ok

    The file appl.erl is transferred from the remote to the local host. When the session is opened, the current directory at the remote host is /home/guest, and /home/fred at the local host. Before transferring the file, the current diff --git a/prs/9045/lib/ftp-1.2.3/doc/html/search.html b/prs/9045/lib/ftp-1.2.3/doc/html/search.html index 33682282d93e..cdc7916d26ed 100644 --- a/prs/9045/lib/ftp-1.2.3/doc/html/search.html +++ b/prs/9045/lib/ftp-1.2.3/doc/html/search.html @@ -128,7 +128,7 @@

    - +

    diff --git a/prs/9045/lib/inets-9.3/doc/html/http_client.html b/prs/9045/lib/inets-9.3/doc/html/http_client.html index bd599cd9013f..024719b333d2 100644 --- a/prs/9045/lib/inets-9.3/doc/html/http_client.html +++ b/prs/9045/lib/inets-9.3/doc/html/http_client.html @@ -144,32 +144,32 @@

    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.

    +start a profile at application startup:

    [{inets, [{services, [{httpc, PropertyList}]}]}]

    For valid properties, see httpc.

    Getting Started

    -

    Start Inets:

    1> inets:start().
    +

    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
    diff --git a/prs/9045/lib/inets-9.3/doc/html/http_server.html b/prs/9045/lib/inets-9.3/doc/html/http_server.html index 3a5468fd1ed0..41c93b1e2a5b 100644 --- a/prs/9045/lib/inets-9.3/doc/html/http_server.html +++ b/prs/9045/lib/inets-9.3/doc/html/http_server.html @@ -147,20 +147,20 @@

    server API, which is described in the Erlang Web Server API. This API can be used to enhance the core server functionality, for example with custom logging and authentication.

    The following is to be put in the Erlang node application configuration file to -start an HTTP server at application startup:

    [{inets, [{services, [{httpd, [{proplist_file,
    -           "/var/tmp/server_root/conf/8888_props.conf"}]},
    -          {httpd, [{proplist_file,
    -           "/var/tmp/server_root/conf/8080_props.conf"}]}]}]}].

    The server is configured using an Erlang property list. For the available -properties, see httpd.

    The available configuration properties are as follows:

    httpd_service() -> {httpd, httpd()}
    -httpd()         -> [httpd_config()]
    -httpd_config()  -> {proplist_file, file()}
    -                   {debug, debug()} |
    -                   {accept_timeout, integer()}
    -debug()         -> disable | [debug_options()]
    -debug_options() -> {all_functions, modules()} |
    -                   {exported_functions, modules()} |
    -                   {disable, modules()}
    -modules()       -> [atom()]

    Here:

    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.

  • diff --git a/prs/9045/lib/inets-9.3/doc/html/httpd.html b/prs/9045/lib/inets-9.3/doc/html/httpd.html index 8d81e918ab33..833ba67b8353 100644 --- a/prs/9045/lib/inets-9.3/doc/html/httpd.html +++ b/prs/9045/lib/inets-9.3/doc/html/httpd.html @@ -242,36 +242,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 @@ -281,7 +281,7 @@

      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.

    +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.

  • @@ -290,15 +290,15 @@

    • {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.

    @@ -326,7 +326,7 @@

    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"}}

    +PATH_TRANSLATED environment variables.

    Example:

    {script, {"PUT", "/cgi-bin/put"}}

    @@ -334,7 +334,7 @@

    • {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 @@ -384,7 +384,7 @@

      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 +

        {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 @@ -419,7 +419,7 @@

          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 +

            {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 @@ -436,10 +436,10 @@

              Web server API data types

              -

              The Erlang web server API data types are as follows:

              ModData = #mod{}
              +

              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,
              @@ -448,10 +448,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 diff --git a/prs/9045/lib/inets-9.3/doc/html/inets.epub b/prs/9045/lib/inets-9.3/doc/html/inets.epub index f33f83128eb5..d04117061732 100644 Binary files a/prs/9045/lib/inets-9.3/doc/html/inets.epub and b/prs/9045/lib/inets-9.3/doc/html/inets.epub differ diff --git a/prs/9045/lib/inets-9.3/doc/html/inets_services.html b/prs/9045/lib/inets-9.3/doc/html/inets_services.html index f7c295422aad..79212de49528 100644 --- a/prs/9045/lib/inets-9.3/doc/html/inets_services.html +++ b/prs/9045/lib/inets-9.3/doc/html/inets_services.html @@ -147,7 +147,7 @@

                unless the service is started with the standalone option. In this case the service is linked to the calling process and all OTP application features, such as soft upgrade, are lost.

                Services to be configured for startup at application startup are to be put into -the Erlang node configuration file on the following form:

                [{inets, [{services, ListofConfiguredServices}]}].

                For details of what to put in the list of configured services, see the +the Erlang node configuration file on the following form:

                [{inets, [{services, ListofConfiguredServices}]}].

                For details of what to put in the list of configured services, see the documentation for the services to be configured.

                diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/allclasses-index.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/allclasses-index.html index e050fa7f1bba..9fe501897ffc 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/allclasses-index.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/allclasses-index.html @@ -2,10 +2,10 @@ - + All Classes (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/allclasses.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/allclasses.html index f27b73ccc11b..bb203651fa77 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/allclasses.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/allclasses.html @@ -2,10 +2,10 @@ - + All Classes (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/allpackages-index.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/allpackages-index.html index 82473dcb9088..6fb3123fd85d 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/allpackages-index.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/allpackages-index.html @@ -2,10 +2,10 @@ - + All Packages (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/AbstractConnection.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/AbstractConnection.html index 1ce41444df76..00f09dd115b5 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/AbstractConnection.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/AbstractConnection.html @@ -2,10 +2,10 @@ - + AbstractConnection (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/AbstractNode.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/AbstractNode.html index 58fac0c56332..591d420e9423 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/AbstractNode.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/AbstractNode.html @@ -2,10 +2,10 @@ - + AbstractNode (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/GenericQueue.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/GenericQueue.html index c983986e598b..e7e6d5618090 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/GenericQueue.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/GenericQueue.html @@ -2,10 +2,10 @@ - + GenericQueue (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpAuthException.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpAuthException.html index 57fb2ffb4104..c3a55b5f62d6 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpAuthException.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpAuthException.html @@ -2,10 +2,10 @@ - + OtpAuthException (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpConnection.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpConnection.html index a9a7b1c0e83c..58b2a0626d01 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpConnection.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpConnection.html @@ -2,10 +2,10 @@ - + OtpConnection (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpCookedConnection.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpCookedConnection.html index 3fcaaa70c8b9..bb7886777a97 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpCookedConnection.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpCookedConnection.html @@ -2,10 +2,10 @@ - + OtpCookedConnection (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpEpmd.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpEpmd.html index cb2b5395036c..2240e23ba900 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpEpmd.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpEpmd.html @@ -2,10 +2,10 @@ - + OtpEpmd (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangAtom.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangAtom.html index ba4eb1cb0a78..258954f265a3 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangAtom.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangAtom.html @@ -2,10 +2,10 @@ - + OtpErlangAtom (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangBinary.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangBinary.html index 065249e9278b..f2864d2bbc1f 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangBinary.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangBinary.html @@ -2,10 +2,10 @@ - + OtpErlangBinary (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangBitstr.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangBitstr.html index 740682bd9df5..5257f9d0a68a 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangBitstr.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangBitstr.html @@ -2,10 +2,10 @@ - + OtpErlangBitstr (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangBoolean.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangBoolean.html index 90cf7299b6a2..f75c3061fbaa 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangBoolean.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangBoolean.html @@ -2,10 +2,10 @@ - + OtpErlangBoolean (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangByte.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangByte.html index 7f7b4b376cae..aa5daeeab0f7 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangByte.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangByte.html @@ -2,10 +2,10 @@ - + OtpErlangByte (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangChar.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangChar.html index 1b7101d83299..197e190058cf 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangChar.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangChar.html @@ -2,10 +2,10 @@ - + OtpErlangChar (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangDecodeException.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangDecodeException.html index ce987b949acc..d92a067680aa 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangDecodeException.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangDecodeException.html @@ -2,10 +2,10 @@ - + OtpErlangDecodeException (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangDouble.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangDouble.html index b0974ac276ab..ed1883a75407 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangDouble.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangDouble.html @@ -2,10 +2,10 @@ - + OtpErlangDouble (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangException.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangException.html index 51ff2fe3ec35..c1f2395043f9 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangException.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangException.html @@ -2,10 +2,10 @@ - + OtpErlangException (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangExit.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangExit.html index ae37681fb258..4ed4ecf98efa 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangExit.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangExit.html @@ -2,10 +2,10 @@ - + OtpErlangExit (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangExternalFun.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangExternalFun.html index f3d1bb1c91c5..1849d7b384cb 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangExternalFun.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangExternalFun.html @@ -2,10 +2,10 @@ - + OtpErlangExternalFun (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangFloat.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangFloat.html index 6158a8d09876..d3480f7f19a9 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangFloat.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangFloat.html @@ -2,10 +2,10 @@ - + OtpErlangFloat (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangFun.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangFun.html index 13577a2c6372..e06a348bc9e8 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangFun.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangFun.html @@ -2,10 +2,10 @@ - + OtpErlangFun (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangInt.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangInt.html index 12395e9993b3..6c33a2ad57b1 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangInt.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangInt.html @@ -2,10 +2,10 @@ - + OtpErlangInt (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangList.SubList.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangList.SubList.html index fed135340764..a5646cb87e08 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangList.SubList.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangList.SubList.html @@ -2,10 +2,10 @@ - + OtpErlangList.SubList (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangList.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangList.html index 82b563fcc747..786ece3b45e7 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangList.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangList.html @@ -2,10 +2,10 @@ - + OtpErlangList (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangLong.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangLong.html index 15eb2d8c455f..b533f87d38c6 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangLong.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangLong.html @@ -2,10 +2,10 @@ - + OtpErlangLong (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangMap.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangMap.html index 07aecc97dc97..d6f98faeaaa2 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangMap.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangMap.html @@ -2,10 +2,10 @@ - + OtpErlangMap (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangObject.Hash.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangObject.Hash.html index e2f9279df551..b03e01f0ad0e 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangObject.Hash.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangObject.Hash.html @@ -2,10 +2,10 @@ - + OtpErlangObject.Hash (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangObject.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangObject.html index 7c6e3e52d665..1aed11b1e3e1 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangObject.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangObject.html @@ -2,10 +2,10 @@ - + OtpErlangObject (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangPid.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangPid.html index 2956856b9a94..cb72b388a13f 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangPid.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangPid.html @@ -2,10 +2,10 @@ - + OtpErlangPid (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangPort.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangPort.html index 3046e39b3799..7434c7326b6c 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangPort.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangPort.html @@ -2,10 +2,10 @@ - + OtpErlangPort (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangRangeException.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangRangeException.html index b253f2b3f065..d917bf7367af 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangRangeException.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangRangeException.html @@ -2,10 +2,10 @@ - + OtpErlangRangeException (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangRef.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangRef.html index a4050772e74c..1d7b900a1af1 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangRef.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangRef.html @@ -2,10 +2,10 @@ - + OtpErlangRef (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangShort.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangShort.html index f150dc728fd4..8538e7dc87b1 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangShort.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangShort.html @@ -2,10 +2,10 @@ - + OtpErlangShort (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangString.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangString.html index e95419ff676c..a2e32e351dca 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangString.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangString.html @@ -2,10 +2,10 @@ - + OtpErlangString (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangTuple.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangTuple.html index 6d2c8c7afd41..0fa85e5005f2 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangTuple.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangTuple.html @@ -2,10 +2,10 @@ - + OtpErlangTuple (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangUInt.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangUInt.html index 9dced352c552..04c4f0ba0023 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangUInt.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangUInt.html @@ -2,10 +2,10 @@ - + OtpErlangUInt (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangUShort.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangUShort.html index f28d7bbfa2ec..10ced1a92478 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangUShort.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangUShort.html @@ -2,10 +2,10 @@ - + OtpErlangUShort (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpException.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpException.html index ae3a0093e66e..50525c3972d2 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpException.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpException.html @@ -2,10 +2,10 @@ - + OtpException (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpExternal.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpExternal.html index c0dec0e8d01f..de94899c2f48 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpExternal.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpExternal.html @@ -2,10 +2,10 @@ - + OtpExternal (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpGenericTransportFactory.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpGenericTransportFactory.html index 46707117242c..586db74cb6fb 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpGenericTransportFactory.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpGenericTransportFactory.html @@ -2,10 +2,10 @@ - + OtpGenericTransportFactory (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpInputStream.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpInputStream.html index 23910206386c..1816fca48959 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpInputStream.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpInputStream.html @@ -2,10 +2,10 @@ - + OtpInputStream (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpLocalNode.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpLocalNode.html index f813eabe4628..a844af083faa 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpLocalNode.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpLocalNode.html @@ -2,10 +2,10 @@ - + OtpLocalNode (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpMbox.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpMbox.html index 9c64bd2ff2fe..66207923ee73 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpMbox.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpMbox.html @@ -2,10 +2,10 @@ - + OtpMbox (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpMsg.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpMsg.html index 35c1cd108b52..e9ade8c3d567 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpMsg.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpMsg.html @@ -2,10 +2,10 @@ - + OtpMsg (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpNode.Acceptor.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpNode.Acceptor.html index c078b854b058..4189e8e15948 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpNode.Acceptor.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpNode.Acceptor.html @@ -2,10 +2,10 @@ - + OtpNode.Acceptor (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpNode.Mailboxes.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpNode.Mailboxes.html index a7c7e52b6cd3..a5d68ccf5050 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpNode.Mailboxes.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpNode.Mailboxes.html @@ -2,10 +2,10 @@ - + OtpNode.Mailboxes (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpNode.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpNode.html index cf37b6a5d7bb..ab2b6955a4bb 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpNode.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpNode.html @@ -2,10 +2,10 @@ - + OtpNode (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpNodeStatus.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpNodeStatus.html index 6796230f8981..8d50d9338339 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpNodeStatus.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpNodeStatus.html @@ -2,10 +2,10 @@ - + OtpNodeStatus (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpOutputStream.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpOutputStream.html index 8aa37455c98e..341f99a9a65e 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpOutputStream.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpOutputStream.html @@ -2,10 +2,10 @@ - + OtpOutputStream (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpPeer.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpPeer.html index 3bd40066b790..35cbd1e04877 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpPeer.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpPeer.html @@ -2,10 +2,10 @@ - + OtpPeer (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpSelf.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpSelf.html index 5e06104f7063..2df7f12af29a 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpSelf.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpSelf.html @@ -2,10 +2,10 @@ - + OtpSelf (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpServer.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpServer.html index dc3b0ca02e8b..265a897b1dae 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpServer.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpServer.html @@ -2,10 +2,10 @@ - + OtpServer (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpServerSocketTransport.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpServerSocketTransport.html index c4eb3a52b26c..472bd37573f6 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpServerSocketTransport.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpServerSocketTransport.html @@ -2,10 +2,10 @@ - + OtpServerSocketTransport (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpServerTransport.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpServerTransport.html index 32caef0b538c..c6613b361337 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpServerTransport.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpServerTransport.html @@ -2,10 +2,10 @@ - + OtpServerTransport (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpSocketTransport.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpSocketTransport.html index 447be394ed9f..47e835a28e99 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpSocketTransport.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpSocketTransport.html @@ -2,10 +2,10 @@ - + OtpSocketTransport (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpSocketTransportFactory.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpSocketTransportFactory.html index f5181726b4b0..9e032f5d4d4d 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpSocketTransportFactory.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpSocketTransportFactory.html @@ -2,10 +2,10 @@ - + OtpSocketTransportFactory (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpTransport.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpTransport.html index 39eef5e7dc26..afed346cff1f 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpTransport.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpTransport.html @@ -2,10 +2,10 @@ - + OtpTransport (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpTransportFactory.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpTransportFactory.html index abd65694f339..52df3ad4b0a7 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpTransportFactory.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/OtpTransportFactory.html @@ -2,10 +2,10 @@ - + OtpTransportFactory (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/package-summary.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/package-summary.html index bc29b295ec12..6c30a207b3f3 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/package-summary.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/package-summary.html @@ -2,10 +2,10 @@ - + com.ericsson.otp.erlang (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/package-tree.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/package-tree.html index 3b8a1add319c..42efd690fa7d 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/package-tree.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/com/ericsson/otp/erlang/package-tree.html @@ -2,10 +2,10 @@ - + com.ericsson.otp.erlang Class Hierarchy (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/constant-values.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/constant-values.html index 04db5875daa3..45df4d3d22b3 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/constant-values.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/constant-values.html @@ -2,10 +2,10 @@ - + Constant Field Values (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/deprecated-list.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/deprecated-list.html index c805460ad7d6..25ac2bed5684 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/deprecated-list.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/deprecated-list.html @@ -2,10 +2,10 @@ - + Deprecated List (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/help-doc.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/help-doc.html index 8eb2d27bb115..d83ec25bc2bd 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/help-doc.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/help-doc.html @@ -2,10 +2,10 @@ - + API Help (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/index-all.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/index-all.html index 3bc20b029cc2..dd1a54950f24 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/index-all.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/index-all.html @@ -2,10 +2,10 @@ - + Index (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/index.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/index.html index ec19f960caa5..81c31ec89754 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/index.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/index.html @@ -2,7 +2,7 @@ - + Java-Erlang Interface Library diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/member-search-index.zip b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/member-search-index.zip index e8c88403a968..bf0a258874f0 100644 Binary files a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/member-search-index.zip and b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/member-search-index.zip differ diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/overview-tree.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/overview-tree.html index cd1daf06283a..fd43db1b17c3 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/overview-tree.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/overview-tree.html @@ -2,10 +2,10 @@ - + Class Hierarchy (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/package-search-index.zip b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/package-search-index.zip index 863938e3c85f..6ffe8e69d9d9 100644 Binary files a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/package-search-index.zip and b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/package-search-index.zip differ diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/serialized-form.html b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/serialized-form.html index 185e5474874f..0b517a147335 100644 --- a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/serialized-form.html +++ b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/serialized-form.html @@ -2,10 +2,10 @@ - + Serialized Form (Java-Erlang Interface Library) - + diff --git a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/type-search-index.zip b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/type-search-index.zip index d258bb29cf07..e87acdcf4656 100644 Binary files a/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/type-search-index.zip and b/prs/9045/lib/jinterface-1.14.1/doc/html/assets/java/type-search-index.zip differ diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/.build b/prs/9045/lib/kernel-10.1.1/doc/html/.build index 35516069bb49..4209e4ace3bd 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/.build +++ b/prs/9045/lib/kernel-10.1.1/doc/html/.build @@ -24,7 +24,7 @@ dist/lato-latin-ext-300-normal-VPGGJKJL.woff2 dist/lato-latin-ext-400-normal-N27NCBWW.woff2 dist/lato-latin-ext-700-normal-Q2L5DVMW.woff2 dist/remixicon-NKANDIL5.woff2 -dist/search_data-9B590B76.js +dist/search_data-3E9A2FC2.js dist/sidebar_items-3BEC7028.js eep48_chapter.html erl_boot_server.html diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/app.html b/prs/9045/lib/kernel-10.1.1/doc/html/app.html index b83fb07a992c..5ee1f1ac5d8c 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/app.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/app.html @@ -150,41 +150,41 @@

                The application resource file is to be called Application.app, where Application is the application name. The file is to be located in directory ebin for the application.

                The file must contain a single Erlang term, which is called an application -specification:

                {application, Application,
                -  [{description,  Description},
                -   {id,           Id},
                -   {vsn,          Vsn},
                -   {modules,      Modules},
                -   {maxP,         MaxP},
                -   {maxT,         MaxT},
                -   {registered,   Names},
                -   {included_applications, Apps},
                -   {optional_applications, Apps},
                -   {applications, Apps},
                -   {env,          Env},
                -   {mod,          Start},
                -   {start_phases, Phases},
                -   {runtime_dependencies, RTDeps}]}.
                +specification:

                {application, Application,
                +  [{description,  Description},
                +   {id,           Id},
                +   {vsn,          Vsn},
                +   {modules,      Modules},
                +   {maxP,         MaxP},
                +   {maxT,         MaxT},
                +   {registered,   Names},
                +   {included_applications, Apps},
                +   {optional_applications, Apps},
                +   {applications, Apps},
                +   {env,          Env},
                +   {mod,          Start},
                +   {start_phases, Phases},
                +   {runtime_dependencies, RTDeps}]}.
                 
                              Value                Default
                              -----                -------
                -Application  atom()               -
                -Description  string()             ""
                -Id           string()             ""
                -Vsn          string()             ""
                -Modules      [Module]             []
                -MaxP         int()                infinity
                -MaxT         int()                infinity
                -Names        [Name]               []
                -Apps         [App]                []
                -Env          [{Par,Val}]          []
                -Start        {Module,StartArgs}   []
                -Phases       [{Phase,PhaseArgs}]  undefined
                -RTDeps       [ApplicationVersion] []
                -
                -Module = Name = App = Par = Phase = atom()
                -Val = StartArgs = PhaseArgs = term()
                -ApplicationVersion = string()
                • Application - Application name.

                For the application controller, all keys are optional. The respective default +Application atom() - +Description string() "" +Id string() "" +Vsn string() "" +Modules [Module] [] +MaxP int() infinity +MaxT int() infinity +Names [Name] [] +Apps [App] [] +Env [{Par,Val}] [] +Start {Module,StartArgs} [] +Phases [{Phase,PhaseArgs}] undefined +RTDeps [ApplicationVersion] [] + +Module = Name = App = Par = Phase = atom() +Val = StartArgs = PhaseArgs = term() +ApplicationVersion = string()

                • Application - Application name.

                For the application controller, all keys are optional. The respective default values are used for any omitted keys.

                The functions in systools require more information. If they are used, the following keys are mandatory:

                • description
                • vsn
                • modules
                • registered
                • applications

                The other keys are ignored by systools.

                • description - A one-line description of the application.

                • id - Product identification, or similar.

                • vsn - Version of the application.

                • modules - All modules introduced by this application. systools uses this list when generating start scripts and tar files. A module can only be @@ -217,7 +217,7 @@

                  Module:start_phase(Phase,Type,PhaseArgs) for each start phase defined by key start_phases. Only after this extended start procedure, application:start(Application) returns.

                  Start phases can be used to synchronize startup of an application and its -included applications. In this case, key mod must be specified as follows:

                  {mod, {application_starter,[Module,StartArgs]}}

                  The application master then calls Module:start/2 for the primary +included applications. In this case, key mod must be specified as follows:

                  {mod, {application_starter,[Module,StartArgs]}}

                  The application master then calls Module:start/2 for the primary application, followed by calls to Module:start_phase/3 for each start phase (as defined for the primary application), both for the primary application and for each of its included applications, for which the start phase is defined.

                  This implies that for an included application, the set of start phases must be diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/application.html b/prs/9045/lib/kernel-10.1.1/doc/html/application.html index fec28b57a52c..c3d89efac3d1 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/application.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/application.html @@ -1659,7 +1659,7 @@

                  load(AppDescr, Distributed)

                  restart the application on another node. If Time is not specified, it defaults to 0 and the application is restarted immediately.

                  Nodes is a list of node names where the application can run, in priority from left to right. Node names can be grouped using tuples to indicate that they have -the same priority.

                  Example:

                  Nodes = [cp1@cave, {cp2@cave, cp3@cave}]

                  This means that the application is preferably to be started at cp1@cave. If +the same priority.

                  Example:

                  Nodes = [cp1@cave, {cp2@cave, cp3@cave}]

                  This means that the application is preferably to be started at cp1@cave. If cp1@cave is down, the application is to be started at cp2@cave or cp3@cave.

                  If Distributed == default, the value for the application in the Kernel configuration parameter distributed is used.

                  diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/code.html b/prs/9045/lib/kernel-10.1.1/doc/html/code.html index e2877b991a59..0eb05effa28f 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/code.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/code.html @@ -199,11 +199,11 @@

                  mnesia-4.4.7, the archive file must be named mnesia-4.4.7.ez and it must contain a top directory named mnesia-4.4.7. If the version part of the name is omitted, it must also be omitted in the archive. That is, a mnesia.ez archive -must contain a mnesia top directory.

                  An archive file for an application can, for example, be created like this:

                  zip:create("mnesia-4.4.7.ez",
                  -	["mnesia-4.4.7"],
                  -	[{cwd, code:lib_dir()},
                  -	 {compress, all},
                  -	 {uncompress,[".beam",".app"]}]).

                  Any file in the archive can be compressed, but to speed up the access of +must contain a mnesia top directory.

                  An archive file for an application can, for example, be created like this:

                  zip:create("mnesia-4.4.7.ez",
                  +	["mnesia-4.4.7"],
                  +	[{cwd, code:lib_dir()},
                  +	 {compress, all},
                  +	 {uncompress,[".beam",".app"]}]).

                  Any file in the archive can be compressed, but to speed up the access of frequently read files, it can be a good idea to store beam and app files uncompressed in the archive.

                  Normally the top directory of an application is located in library directory $OTPROOT/lib or in a directory referred to by environment variable ERL_LIBS. @@ -1881,10 +1881,10 @@

                  atomic_load(Modules)

                  the code already exists.

                • sticky_directory - The object code resides in a sticky directory.

                • pending_on_load - A previously loaded module contains an -on_load function that never finished.

                If it is important to minimize the time that an application is inactive while changing code, use prepare_loading/1 and finish_loading/1 instead of -atomic_load/1. Here is an example:

                {ok,Prepared} = code:prepare_loading(Modules),
                +atomic_load/1. Here is an example:

                {ok,Prepared} = code:prepare_loading(Modules),
                 %% Put the application into an inactive state or do any
                 %% other preparation needed before changing the code.
                -ok = code:finish_loading(Prepared),
                +ok = code:finish_loading(Prepared),
                 %% Resume the application.
                @@ -2437,8 +2437,8 @@

                get_object_code(Module)

                code for the module. This is useful if code is to be loaded on a remote node in a distributed system. For example, loading module Module on a node Node is done as follows:

                ...
                -{_Module, Binary, Filename} = code:get_object_code(Module),
                -erpc:call(Node, code, load_binary, [Module, Filename, Binary]),
                +{_Module, Binary, Filename} = code:get_object_code(Module),
                +erpc:call(Node, code, load_binary, [Module, Filename, Binary]),
                 ...
                @@ -2557,7 +2557,7 @@

                lib_dir()

                Returns the library directory, $OTPROOT/lib, where $OTPROOT is the root -directory of Erlang/OTP.

                Example:

                1> code:lib_dir().
                +directory of Erlang/OTP.

                Example:

                1> code:lib_dir().
                 "/usr/local/otp/lib"
                @@ -2596,7 +2596,7 @@

                lib_dir(Name)

                /usr/local/otp/lib/mnesia-4.2.2/ebin is returned. This means that the library directory for an application is the same, regardless if the application resides in an archive or not.

                Warning

                Archives are experimental. In a future release, they can be removed or -their behavior can change.

                Example:

                > code:lib_dir(mnesia).
                +their behavior can change.

                Example:

                > code:lib_dir(mnesia).
                 "/usr/local/otp/lib/mnesia-4.23"

                Returns {error, bad_name} if Name is not the name of an application under $OTPROOT/lib or on a directory referred to through environment variable ERL_LIBS. Fails with an exception if Name has the wrong type.

                Warning

                For backward compatibility, Name is also allowed to be a string. That will @@ -2639,7 +2639,7 @@

                lib_dir(Name, SubDir)

                situation is different. Some of the subdirectories can reside as regular directories while others reside in an archive file. It is not checked whether this directory exists.

                Instead of using this function, use code:lib_dir/1 -and filename:join/2.

                Example:

                1> filename:join(code:lib_dir(megaco), "priv").
                +and filename:join/2.

                Example:

                1> filename:join(code:lib_dir(megaco), "priv").
                 "/usr/local/otp/lib/megaco-3.9.1.1/priv"

                Fails with an exception if Name or SubDir has the wrong type.

                @@ -3098,7 +3098,7 @@

                root_dir()

                Returns the root directory of Erlang/OTP, which is the directory where it is -installed.

                Example:

                1> code:root_dir().
                +installed.

                Example:

                1> code:root_dir().
                 "/usr/local/otp"
                diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/config.html b/prs/9045/lib/kernel-10.1.1/doc/html/config.html index 1aeda7450e4d..118ac119443f 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/config.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/config.html @@ -158,9 +158,9 @@

                File Syntax

                -

                The configuration file is to be called Name.config, where Name is any name.

                File .config contains a single Erlang term and has the following syntax:

                [{Application1, [{Par11, Val11}, ...]},
                +

                The configuration file is to be called Name.config, where Name is any name.

                File .config contains a single Erlang term and has the following syntax:

                [{Application1, [{Par11, Val11}, ...]},
                  ...
                - {ApplicationN, [{ParN1, ValN1}, ...]}].
                • Application = atom() - Application name.

                • Par = atom() - Name of a configuration parameter.

                • Val = term() - Value of a configuration parameter.

                + {ApplicationN, [{ParN1, ValN1}, ...]}].

                • Application = atom() - Application name.

                • Par = atom() - Name of a configuration parameter.

                • Val = term() - Value of a configuration parameter.

                diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/dist/search_data-3E9A2FC2.js b/prs/9045/lib/kernel-10.1.1/doc/html/dist/search_data-3E9A2FC2.js new file mode 100644 index 000000000000..ef6de159bf69 --- /dev/null +++ b/prs/9045/lib/kernel-10.1.1/doc/html/dist/search_data-3E9A2FC2.js @@ -0,0 +1 @@ +searchData={"items":[{"type":"behaviour","title":"application","doc":"Generic OTP application functions\n\nIn OTP, _application_ denotes a component implementing some specific\nfunctionality, that can be started and stopped as a unit, and that can be reused\nin other systems. This module interacts with _application controller_, a process\nstarted at every Erlang runtime system. This module contains functions for\ncontrolling applications (for example, starting and stopping applications), and\nfunctions to access information about applications (for example, configuration\nparameters).\n\nAn application is defined by an _application specification_. The specification\nis normally located in an _application resource file_ named `Application.app`,\nwhere `Application` is the application name. For details about the application\nspecification, see [`app`](app.md).\n\nThis module can also be viewed as a behaviour for an application implemented\naccording to the OTP design principles as a supervision tree. The definition of\nhow to start and stop the tree is to be located in an _application callback\nmodule_, exporting a predefined set of functions.\n\nFor details about applications and behaviours, see\n[OTP Design Principles](`e:system:design_principles.md`).","ref":"application.html"},{"type":"behaviour","title":"See Also - application","doc":"[OTP Design Principles](`e:system:design_principles.md`),\n[kernel](kernel_app.md), [app](app.md)","ref":"application.html#module-see-also"},{"type":"callback","title":"application.config_change/3","doc":"This function is called by an application after a code replacement, if the\nconfiguration parameters have changed.\n\n`Changed` is a list of parameter-value tuples including all configuration\nparameters with changed values.\n\n`New` is a list of parameter-value tuples including all added configuration\nparameters.\n\n`Removed` is a list of all removed parameters.","ref":"application.html#c:config_change/3"},{"type":"function","title":"application.ensure_all_started/1","doc":"","ref":"application.html#ensure_all_started/1"},{"type":"function","title":"application.ensure_all_started/2","doc":"","ref":"application.html#ensure_all_started/2"},{"type":"function","title":"application.ensure_all_started/3","doc":"`Applications` is either an an `t:atom/0` or a list of `t:atom/0` representing\nmultiple applications.\n\nThis function is equivalent to calling [`start/1,2`](`start/1`) repeatedly on\nall dependencies that are not yet started of each application. Optional\ndependencies will also be loaded and started if they are available.\n\nThe `Mode` argument controls if the applications should be started in `serial`\nmode (one at a time) or `concurrent` mode. In concurrent mode, a dependency\ngraph is built and the leaves of the graph are started concurrently and\nrecursively. In both modes, no assertion can be made about the order the\napplications are started. If not supplied, it defaults to `serial`.\n\nReturns `{ok, AppNames}` for a successful start or for an already started\napplication (which is, however, omitted from the `AppNames` list).\n\nThe function reports `{error, {AppName,Reason}}` for errors, where `Reason` is\nany possible reason returned by [`start/1,2`](`start/1`) when starting a\nspecific dependency.\n\nIf an error occurs, the applications started by the function are stopped to\nbring the set of running applications back to its initial state.","ref":"application.html#ensure_all_started/3"},{"type":"function","title":"application.ensure_started/1","doc":"Equivalent to [`start(Application)`](`start/1`) except it returns `ok` for\nalready started applications.","ref":"application.html#ensure_started/1"},{"type":"function","title":"application.ensure_started/2","doc":"Equivalent to [`start(Application, Type)`](`start/2`) except it returns `ok` for\nalready started applications.","ref":"application.html#ensure_started/2"},{"type":"function","title":"application.get_all_env/0","doc":"","ref":"application.html#get_all_env/0"},{"type":"function","title":"application.get_all_env/1","doc":"Returns the configuration parameters and their values for `Application`.\n\nIf the specified application is not loaded, or if the process executing the call\ndoes not belong to any application, the function returns `[]`.","ref":"application.html#get_all_env/1"},{"type":"function","title":"application.get_all_key/0","doc":"","ref":"application.html#get_all_key/0"},{"type":"function","title":"application.get_all_key/1","doc":"Returns the application specification keys and their values for `Application`.\nIf the argument is omitted, it defaults to the application of the calling\nprocess.\n\nIf the specified application is not loaded, the function returns `undefined`. If\nthe process executing the call does not belong to any application, the function\nreturns `[]`.","ref":"application.html#get_all_key/1"},{"type":"function","title":"application.get_application/0","doc":"","ref":"application.html#get_application/0"},{"type":"function","title":"application.get_application/1","doc":"Returns the name of the application to which the process `Pid` or the module\n`Module` belongs.\n\nIf the specified process does not belong to any application, or if the specified\nprocess or module does not exist, the function returns `undefined`.","ref":"application.html#get_application/1"},{"type":"function","title":"application.get_env/1","doc":"","ref":"application.html#get_env/1"},{"type":"function","title":"application.get_env/2","doc":"Returns the value of configuration parameter `Par` for `Application`.\n\nReturns `undefined` if any of the following applies:\n\n- The specified application is not loaded.\n- The configuration parameter does not exist.\n- The process executing the call does not belong to any application.","ref":"application.html#get_env/2"},{"type":"function","title":"application.get_env/3","doc":"Works like `get_env/2` but returns value `Def` when configuration parameter\n`Par` does not exist.","ref":"application.html#get_env/3"},{"type":"function","title":"application.get_key/1","doc":"","ref":"application.html#get_key/1"},{"type":"function","title":"application.get_key/2","doc":"Returns the value of the application specification key `Key` for `Application`.\n\nReturns `undefined` if any of the following applies:\n\n- The specified application is not loaded.\n- The specification key does not exist.\n- The process executing the call does not belong to any application.","ref":"application.html#get_key/2"},{"type":"function","title":"application.get_supervisor/1","doc":"Returns the `Pid` of the supervisor running at the root of `Application`.\n\nIf the specified application does not exist or does not define a callback\nmodule, the function returns `undefined`.","ref":"application.html#get_supervisor/1"},{"type":"function","title":"application.load/1","doc":"","ref":"application.html#load/1"},{"type":"function","title":"application.load/2","doc":"Loads the application specification for an application into the application\ncontroller. It also loads the application specifications for any included\napplications. Notice that the function does not load the Erlang object code.\n\nThe application can be specified by its name `Application`. In this case, the\napplication controller searches the code path for the application resource file\n`Application.app` and loads the specification it contains.\n\nThe application specification can also be specified directly as a tuple\n`AppSpec`, having the format and contents as described in [`app`](app.md).\n\nIf `Distributed == {Application,[Time,]Nodes}`, the application becomes\ndistributed. The argument overrides the value for the application in the Kernel\nconfiguration parameter `distributed`. `Application` must be the application\nname (same as in the first argument). If a node crashes and `Time` is specified,\nthe application controller waits for `Time` milliseconds before attempting to\nrestart the application on another node. If `Time` is not specified, it defaults\nto `0` and the application is restarted immediately.\n\n`Nodes` is a list of node names where the application can run, in priority from\nleft to right. Node names can be grouped using tuples to indicate that they have\nthe same priority.\n\n_Example:_\n\n```erlang\nNodes = [cp1@cave, {cp2@cave, cp3@cave}]\n```\n\nThis means that the application is preferably to be started at `cp1@cave`. If\n`cp1@cave` is down, the application is to be started at `cp2@cave` or\n`cp3@cave`.\n\nIf `Distributed == default`, the value for the application in the Kernel\nconfiguration parameter `distributed` is used.","ref":"application.html#load/2"},{"type":"function","title":"application.loaded_applications/0","doc":"Returns a list with information about the applications, and included\napplications, which are loaded using `load/1,2`. `Application` is the\napplication name. `Description` and `Vsn` are the values of their `description`\nand `vsn` application specification keys, respectively.","ref":"application.html#loaded_applications/0"},{"type":"function","title":"application.permit/2","doc":"Changes the permission for `Application` to run at the current node. The\napplication must be loaded using `load/1,2` for the function to have effect.\n\nIf the permission of a loaded, but not started, application is set to `false`,\n`start` returns `ok` but the application is not started until the permission is\nset to `true`.\n\nIf the permission of a running application is set to `false`, the application is\nstopped. If the permission later is set to `true`, it is restarted.\n\nIf the application is distributed, setting the permission to `false` means that\nthe application will be started at, or moved to, another node according to how\nits distribution is configured (see `load/2`).\n\nThe function does not return until the application is started, stopped, or\nsuccessfully moved to another node. However, in some cases where permission is\nset to `true`, the function returns `ok` even though the application is not\nstarted. This is true when an application cannot start because of dependencies\nto other applications that are not yet started. When they are started,\n`Application` is started as well.\n\nBy default, all applications are loaded with permission `true` on all nodes. The\npermission can be configured using the Kernel configuration parameter\n`permissions`.","ref":"application.html#permit/2"},{"type":"callback","title":"application.prep_stop/1","doc":"This function is called when an application is about to be stopped, before\nshutting down the processes of the application.\n\n`State` is the state returned from [`Module:start/2`](`c:start/2`), or `[]` if\nno state was returned. `NewState` is any term and is passed to\n[`Module:stop/1`](`c:stop/1`).\n\nThe function is optional. If it is not defined, the processes are terminated and\nthen [`Module:stop(State)`](`c:stop/1`) is called.","ref":"application.html#c:prep_stop/1"},{"type":"function","title":"application.set_env/1","doc":"","ref":"application.html#set_env/1"},{"type":"function","title":"application.set_env/2","doc":"Sets the configuration `Config` for multiple applications.\n\nIt is equivalent to calling [`set_env/4`](`set_env/4`) on each application\nindividually, except it is more efficient. The given `Config` is validated before\nthe configuration is set.\n\n[`set_env/2`](`set_env/2`) uses the standard `gen_server` time-out value (5000\nms). Option `timeout` can be specified if another time-out value is useful, for\nexample, in situations where the application controller is heavily loaded.\n\nOption `persistent` can be set to `true` to guarantee that parameters set with\n[`set_env/2`](`set_env/2`) are not overridden by those defined in the\napplication resource file on load. This means that persistent values will stick\nafter the application is loaded and also on application reload.\n\nIf an application is given more than once or if an application has the same key\ngiven more than once, the behaviour is undefined and a warning message will be\nlogged. In future releases, an error will be raised.\n\n> #### Warning {: .warning }\n>\n> Use this function only if you know what you are doing, that is, on your own\n> applications. It is very application-dependent and configuration\n> parameter-dependent when and how often the value is read by the application.\n> Careless use of this function can put the application in a weird,\n> inconsistent, and malfunctioning state.","ref":"application.html#set_env/2"},{"type":"function","title":"application.set_env/3","doc":"","ref":"application.html#set_env/3"},{"type":"function","title":"application.set_env/4","doc":"Sets the value of configuration parameter `Par` for `Application`.\n\n[`set_env/4`](`set_env/4`) uses the standard `gen_server` time-out value (5000\nms). Option `timeout` can be specified if another time-out value is useful, for\nexample, in situations where the application controller is heavily loaded.\n\nIf [`set_env/4`](`set_env/4`) is called before the application is loaded, the\napplication environment values specified in file `Application.app` override the\nones previously set. This is also true for application reloads.\n\nOption `persistent` can be set to `true` to guarantee that parameters set with\n[`set_env/4`](`set_env/4`) are not overridden by those defined in the\napplication resource file on load. This means that persistent values will stick\nafter the application is loaded and also on application reload.\n\n> #### Warning {: .warning }\n>\n> Use this function only if you know what you are doing, that is, on your own\n> applications. It is very application-dependent and configuration\n> parameter-dependent when and how often the value is read by the application.\n> Careless use of this function can put the application in a weird,\n> inconsistent, and malfunctioning state.","ref":"application.html#set_env/4"},{"type":"function","title":"application.start/1","doc":"","ref":"application.html#start/1"},{"type":"function","title":"application.start/2","doc":"Starts `Application`. If it is not loaded, the application controller first\nloads it using [`load/1`](`load/1`). It ensures that any included applications\nare loaded, but does not start them. That is assumed to be taken care of in the\ncode for `Application`.\n\nThe application controller checks the value of the application specification key\n`applications`, to ensure that all applications needed to be started before this\napplication are running. If an application is missing and the application is not\nmarked as optional, `{error,{not_started,App}}` is returned, where `App` is the\nname of the missing application. Note this function makes no attempt to start\nany of the applications listed in `applications`, not even optional ones. See\n[`ensure_all_started/1,2`](`ensure_all_started/1`) for recursively starting the\ncurrent application and its dependencies.\n\nOnce validated, the application controller then creates an _application master_\nfor the application. The application master becomes the group leader of all the\nprocesses in the application. I/O is forwarded to the previous group leader,\nthough, this is just a way to identify processes that belong to the application.\nUsed for example to find itself from any process, or, reciprocally, to kill them\nall when it terminates.\n\nThe application master starts the application by calling the application\ncallback function [`Module:start/2`](`c:start/2`) as defined by the application\nspecification key `mod`.\n\nArgument `Type` specifies the type of the application. If omitted, it defaults\nto `temporary`.\n\n- If a permanent application terminates, all other applications and the entire\n Erlang node are also terminated.\n- If a transient application terminates:\n - with `Reason == normal`, this is reported but no other applications are\n terminated.\n - abnormally, all other applications and the entire Erlang node are also\n terminated.\n- If a temporary application terminates, this is reported but no other\n applications are terminated.\n\nNotice that an application can always be stopped explicitly by calling\n[`stop/1`](`stop/1`). Regardless of the type of the application, no other\napplications are affected.\n\nNotice also that the transient type is of little practical use, because when a\nsupervision tree terminates, the reason is set to `shutdown`, not `normal`.","ref":"application.html#start/2"},{"type":"callback","title":"application.start/2","doc":"This function is called whenever an application is started using `start/1,2`,\nand is to start the processes of the application. If the application is\nstructured according to the OTP design principles as a supervision tree, this\nmeans starting the top supervisor of the tree.\n\n`StartType`{: #start_type } defines the type of start:\n\n- `normal` if it is a normal startup.\n- `normal` also if the application is distributed and started at the current\n node because of a failover from another node, and the application\n specification key `start_phases == undefined`.\n- `{takeover,Node}` if the application is distributed and started at the current\n node because of a takeover from `Node`, either because\n [`takeover/2`](`takeover/2`) has been called or because the current node has\n higher priority than `Node`.\n- `{failover,Node}` if the application is distributed and started at the current\n node because of a failover from `Node`, and the application specification key\n `start_phases /= undefined`.\n\n`StartArgs` is the `StartArgs` argument defined by the application specification\nkey `mod`.\n\nThe function is to return `{ok,Pid}` or `{ok,Pid,State}`, where `Pid` is the pid\nof the top supervisor and `State` is any term. If omitted, `State` defaults to\n`[]`. If the application is stopped later, `State` is passed to\n[`Module:prep_stop/1`](`c:prep_stop/1`).","ref":"application.html#c:start/2"},{"type":"callback","title":"application.start_phase/3","doc":"Starts an application with included applications, when synchronization is needed\nbetween processes in the different applications during startup.\n\nThe start phases are defined by the application specification key\n`start_phases == [{Phase,PhaseArgs}]`. For included applications, the set of\nphases must be a subset of the set of phases defined for the including\napplication.\n\nThe function is called for each start phase (as defined for the primary\napplication) for the primary application and all included applications, for\nwhich the start phase is defined.\n\nFor a description of `StartType`, see [`Module:start/2`](`c:start/2`).","ref":"application.html#c:start_phase/3"},{"type":"function","title":"application.start_type/0","doc":"This function is intended to be called by a process belonging to an application,\nwhen the application is started, to determine the start type, which is\n`StartType` or `local`.\n\nFor a description of `StartType`, see\n[`Module:start/2`](`m:application#start_type`).\n\n`local` is returned if only parts of the application are restarted (by a\nsupervisor), or if the function is called outside a startup.\n\nIf the process executing the call does not belong to any application, the\nfunction returns `undefined`.","ref":"application.html#start_type/0"},{"type":"function","title":"application.stop/1","doc":"Stops `Application`. The application master calls\n[`Module:prep_stop/1`](`c:prep_stop/1`), if such a function is defined, and then\ntells the top supervisor of the application to shut down (see `m:supervisor`).\n\nThis means that the entire supervision tree, including included applications, is\nterminated in reversed start order. After the shutdown, the application master\ncalls [`Module:stop/1`](`c:stop/1`). `Module` is the callback module as defined\nby the application specification key `mod`.\n\nLast, the application master terminates. Notice that all processes with the\napplication master as group leader, that is, processes spawned from a process\nbelonging to the application, are also terminated.\n\nWhen stopped, the application is still loaded.\n\nTo stop a distributed application, [`stop/1`](`stop/1`) must be called on all\nnodes where it can execute (that is, on all nodes where it has been started).\nThe call to [`stop/1`](`stop/1`) on the node where the application currently\nexecutes stops its execution. The application is not moved between nodes, as\n[`stop/1`](`stop/1`) is called on the node where the application currently\nexecutes before [`stop/1`](`stop/1`) is called on the other nodes.","ref":"application.html#stop/1"},{"type":"callback","title":"application.stop/1","doc":"This function is called whenever an application has stopped. It is intended to\nbe the opposite of [`Module:start/2`](`c:start/2`) and is to do any necessary\ncleaning up. The return value is ignored.\n\n`State` is the return value of [`Module:prep_stop/1`](`c:prep_stop/1`), if such\na function exists. Otherwise `State` is taken from the return value of\n[`Module:start/2`](`c:start/2`).","ref":"application.html#c:stop/1"},{"type":"function","title":"application.takeover/2","doc":"Takes over the distributed application `Application`, which executes at another\nnode `Node`.\n\nAt the current node, the application is restarted by calling\n[`Module:start({takeover,Node},StartArgs)`](`c:start/2`). `Module` and\n`StartArgs` are retrieved from the loaded application specification. The\napplication at the other node is not stopped until the startup is completed,\nthat is, when [`Module:start/2`](`c:start/2`) and any calls to\n[`Module:start_phase/3`](`c:start_phase/3`) have returned.\n\nThus, two instances of the application run simultaneously during the takeover,\nso that data can be transferred from the old to the new instance. If this is not\nan acceptable behavior, parts of the old instance can be shut down when the new\ninstance is started. However, the application cannot be stopped entirely, at\nleast the top supervisor must remain alive.\n\nFor a description of `Type`, see [`start/1,2`](`start/1`).","ref":"application.html#takeover/2"},{"type":"function","title":"application.unload/1","doc":"Unloads the application specification for `Application` from the application\ncontroller. It also unloads the application specifications for any included\napplications. Notice that the function does not purge the Erlang object code.","ref":"application.html#unload/1"},{"type":"function","title":"application.unset_env/2","doc":"","ref":"application.html#unset_env/2"},{"type":"function","title":"application.unset_env/3","doc":"Removes the configuration parameter `Par` and its value for `Application`.\n\n[`unset_env/3`](`unset_env/3`) uses the standard `gen_server` time-out value\n(5000 ms). Option `timeout` can be specified if another time-out value is\nuseful, for example, in situations where the application controller is heavily\nloaded.\n\n[`unset_env/3`](`unset_env/3`) also allows the persistent option to be passed\n(see `set_env/4`).\n\n> #### Warning {: .warning }\n>\n> Use this function only if you know what you are doing, that is, on your own\n> applications. It is very application-dependent and configuration\n> parameter-dependent when and how often the value is read by the application.\n> Careless use of this function can put the application in a weird,\n> inconsistent, and malfunctioning state.","ref":"application.html#unset_env/3"},{"type":"function","title":"application.which_applications/0","doc":"","ref":"application.html#which_applications/0"},{"type":"function","title":"application.which_applications/1","doc":"Returns a list with information about the applications that are currently\nrunning.\n\n`Application` is the application name. `Description` and `Vsn` are the\nvalues of their `description` and `vsn` application specification keys,\nrespectively.\n\nA `Timeout` argument can be specified in situations where the application\ncontroller is heavily loaded.","ref":"application.html#which_applications/1"},{"type":"type","title":"application.application_opt/0","doc":"The built-in options available to an application.\n\nSee [app](app.md) for descriptions of the options.","ref":"application.html#t:application_opt/0"},{"type":"type","title":"application.application_spec/0","doc":"An application specification.","ref":"application.html#t:application_spec/0"},{"type":"type","title":"application.restart_type/0","doc":"The type of restart behaviour an application should have.","ref":"application.html#t:restart_type/0"},{"type":"type","title":"application.start_type/0","doc":"The reason for the application to be started on the current node.","ref":"application.html#t:start_type/0"},{"type":"type","title":"application.tuple_of/1","doc":"A tuple where the elements are of type `T`.","ref":"application.html#t:tuple_of/1"},{"type":"module","title":"code","doc":"Interface to the Erlang code server process.\n\nThis module contains the interface to the Erlang _code server_, which deals with\nthe loading of compiled code into a running Erlang runtime system.\n\nThe runtime system can be started in _interactive_ or _embedded_ mode. Which one\nis decided by the command-line flag `-mode`:\n\n```bash\n% erl -mode embedded\n```\n\nThe modes are as follows:\n\n- In _interactive_ mode, which is default, only the modules needed by\n the runtime system are loaded during system startup. Other code is\n dynamically loaded when first referenced. When a call to a function\n in a certain module is made, and that module is not loaded, the code\n server searches for and tries to load that module.\n\n- In _embedded_ mode, modules are not auto-loaded. Trying to use a\n module that has not been loaded results in an error. This mode is\n recommended when the boot script loads all modules, as it is\n typically done in OTP releases. (Code can still be loaded later by\n explicitly ordering the code server to do so).\n\nTo prevent accidentally reloading of modules affecting the Erlang runtime\nsystem, directories `kernel`, `stdlib`, and `compiler` are considered _sticky_.\nThis means that the system issues a warning and rejects the request if a user\ntries to reload a module residing in any of them. The feature can be disabled by\nusing command-line flag `-nostick`.","ref":"code.html"},{"type":"module","title":"Code Path - code","doc":"In interactive mode, the code server maintains a _code path_,\nconsisting of a list of directories, which it searches sequentially\nwhen trying to load a module.\n\nInitially, the code path consists of the current working directory and all\nErlang object code directories under library directory `$OTPROOT/lib`, where\n`$OTPROOT` is the installation directory of Erlang/OTP, `code:root_dir()`.\nDirectories can be named `Name[-Vsn]` and the code server, by default, chooses\nthe directory with the highest version number among those having the same\n`Name`. Suffix `-Vsn` is optional. If an `ebin` directory exists under\n`Name[-Vsn]`, this directory is added to the code path.\n\nEnvironment variable `ERL_LIBS` (defined in the operating system) can be used to\ndefine more library directories to be handled in the same way as the standard\nOTP library directory described above, except that directories without an `ebin`\ndirectory are ignored.\n\nAll application directories found in the additional directories appear before\nthe standard OTP applications, except for the Kernel and STDLIB applications,\nwhich are placed before any additional applications. In other words, modules\nfound in any of the additional library directories override modules with the\nsame name in OTP, except for modules in Kernel and STDLIB.\n\nEnvironment variable `ERL_LIBS` (if defined) is to contain a colon-separated\n(for Unix-like systems) or semicolon-separated (for Windows) list of additional\nlibraries.\n\n_Example:_\n\nOn a Unix-like system, `ERL_LIBS` can be set to the following:\n\n```text\n/usr/local/jungerl:/home/some_user/my_erlang_lib\n```\n\nThe code paths specified by `$OTPROOT`, `ERL_LIBS`, and boot scripts have their\nlistings cached by default (except for `\".\"`) The code server will\nlookup the contents in their directories once and avoid future file system\ntraversals. Therefore, modules added to such directories after the Erlang VM\nboots will not be picked up. This behaviour can be disabled by setting\n`-cache_boot_paths false` or by calling `code:set_path(code:get_path())`.\n\n> #### Change {: .info }\n>\n> The support for caching directories in the code path was added\n> in Erlang/OTP 26.\n\nDirectories given by the command line options `-pa` and `-pz` are not\ncached by default. Many of the functions that manipulate the code path\naccept the `cache` atom as an optional argument to enable caching\nselectively.","ref":"code.html#module-code-path"},{"type":"module","title":"Loading of Code From Archive Files - code","doc":"> #### Change {: .info }\n>\n> The existing experimental support for archive files will be changed\n> in a future release. As of Erlang/OTP 27, the function `code:lib_dir/2`,\n> the `-code_path_choice` flag, and using `m:erl_prim_loader` for\n> reading files from an archive are deprecated.\n>\n> `escript` scripts that use archive files should use\n> `escript:extract/2` to read data files from its archive instead of using\n> `code:lib_dir/2` and `m:erl_prim_loader`.\n\nThe Erlang archives are `ZIP` files with extension `.ez`. Erlang archives can\nalso be [enclosed in `escript`](`m:escript`) files whose file extension is arbitrary.\n\nErlang archive files can contain entire Erlang applications or parts of\napplications. The structure in an archive file is the same as the directory\nstructure for an application. If you, for example, create an archive of\n`mnesia-4.4.7`, the archive file must be named `mnesia-4.4.7.ez` and it must\ncontain a top directory named `mnesia-4.4.7`. If the version part of the name is\nomitted, it must also be omitted in the archive. That is, a `mnesia.ez` archive\nmust contain a `mnesia` top directory.\n\nAn archive file for an application can, for example, be created like this:\n\n```erlang\nzip:create(\"mnesia-4.4.7.ez\",\n\t[\"mnesia-4.4.7\"],\n\t[{cwd, code:lib_dir()},\n\t {compress, all},\n\t {uncompress,[\".beam\",\".app\"]}]).\n```\n\nAny file in the archive can be compressed, but to speed up the access of\nfrequently read files, it can be a good idea to store `beam` and `app` files\nuncompressed in the archive.\n\nNormally the top directory of an application is located in library directory\n`$OTPROOT/lib` or in a directory referred to by environment variable `ERL_LIBS`.\nAt startup, when the initial code path is computed, the code server also looks\nfor archive files in these directories and possibly adds `ebin` directories in\narchives to the code path. The code path then contains paths to directories that\nlook like `$OTPROOT/lib/mnesia.ez/mnesia/ebin` or\n`$OTPROOT/lib/mnesia-4.4.7.ez/mnesia-4.4.7/ebin`.\n\nThe code server uses module `erl_prim_loader` in ERTS (possibly through\n`erl_boot_server`) to read code files from archives. However, the functions in\n`erl_prim_loader` can also be used by other applications to read files from\narchives. For example, the call\n`erl_prim_loader:list_dir( \"/otp/root/lib/mnesia-4.4.7.ez/mnesia-4.4.7/examples/bench)\"`\nwould list the contents of a directory inside an archive. See\n`m:erl_prim_loader`.\n\nAn application archive file and a regular application directory can coexist.\nThis can be useful when it is needed to have parts of the application as regular\nfiles. A typical case is the `priv` directory, which must reside as a regular\ndirectory to link in drivers dynamically and start port programs. For other\napplications that do not need this, directory `priv` can reside in the archive\nand the files under the directory `priv` can be read through `erl_prim_loader`.\n\nWhen a directory is added to the code path and when the entire code path is\n(re)set, the code server decides which subdirectories in an application that are\nto be read from the archive and which that are to be read as regular files. If\ndirectories are added or removed afterwards, the file access can fail if the\ncode path is not updated (possibly to the same path as before, to trigger the\ndirectory resolution update).\n\nFor each directory on the second level in the application archive (`ebin`,\n`priv`, `src`, and so on), the code server first chooses the regular directory\nif it exists and second from the archive. Function `code:lib_dir/2` returns the\npath to the subdirectory. For example, `code:lib_dir(megaco, ebin)` can return\n`/otp/root/lib/megaco-3.9.1.1.ez/megaco-3.9.1.1/ebin` while\n`code:lib_dir(megaco, priv)` can return `/otp/root/lib/megaco-3.9.1.1/priv`.\n\nWhen an `escript` file contains an archive, there are no restrictions on the\nname of the `escript` and no restrictions on how many applications that can be\nstored in the embedded archive. Single Beam files can also reside on the top\nlevel in the archive. At startup, the top directory in the embedded archive and\nall (second level) `ebin` directories in the embedded archive are added to the\ncode path. See [`escript`](`e:erts:escript_cmd.md`).\n\nA future-proof way for `escript` scripts to read data files from the archive is\nto use the `escript:extract/2` function.\n\nWhen the choice of directories in the code path is `strict` (which is\nthe default as of Erlang/OTP 27), the directory that ends up in the\ncode path is exactly the stated one. This means that if, for example,\nthe directory `$OTPROOT/lib/mnesia-4.4.7/ebin` is explicitly added to\nthe code path, the code server does not load files from\n`$OTPROOT/lib/mnesia-4.4.7.ez/mnesia-4.4.7/ebin`.\n\nThis behavior can be controlled through command-line flag\n`-code_path_choice Choice`. If the flag is set to `relaxed`, the code server\ninstead chooses a suitable directory depending on the actual file structure. If\na regular application `ebin` directory exists, it is chosen. Otherwise, the\ndirectory `ebin` in the archive is chosen if it exists. If neither of them\nexists, the original directory is chosen.\n\nCommand-line flag `-code_path_choice Choice` also affects how module `init`\ninterprets the `boot script`. The interpretation of the explicit code paths in\nthe `boot script` can be `strict` or `relaxed`. It is particularly useful to set\nthe flag to `relaxed` when elaborating with code loading from archives without\nediting the `boot script`. The default has changed to `strict` in OTP 27 and the\noption is scheduled for removal in OTP 28. See module `m:init` in the\nErts application.","ref":"code.html#module-loading-of-code-from-archive-files"},{"type":"module","title":"Current and Old Code - code","doc":"The code for a module can exist in two variants in a system: _current code_ and\n_old code_. When a module is loaded into the system for the first time, the\nmodule code becomes *current* and the global _export table_ is updated with\nreferences to all functions exported from the module.\n\nWhen a new instance of the module is loaded, the code of the previous\ninstance becomes *old*, and all export entries referring to the\nprevious instance are removed. After that, the new instance is loaded\nas for the first time, and becomes current.\n\nBoth old and current code for a module are valid, and can even be executed\nconcurrently. The difference is that exported functions in old code are\nunavailable. Hence, a global call cannot be made to an exported function in old\ncode, but old code can still be executed because of processes lingering in it.\n\nIf a third instance of the module is loaded, the code server removes (purges)\nthe old code and any processes lingering in it are terminated. Then the third\ninstance becomes current and the previously current code becomes old.\n\nFor more information about old and current code, and how to make a process\nswitch from old to current code, see section Compilation and Code Loading in the\n[Erlang Reference Manual](`e:system:code_loading.md`).","ref":"code.html#module-current-and-old-code"},{"type":"module","title":"Native Coverage Support - code","doc":"In runtime systems that use the JIT, native coverage is a light-weight\nway to find out which functions or lines that have been executed, or\nhow many times each function or line has been executed.\n\n> #### Change {: .info }\n>\n> The support for native coverage was added in Erlang/OTP 27.\n\nNative coverage works by instrumenting code at load-time. When a\nmodule has been instrumented for native coverage collection it is not\npossible to later disable the coverage collection, except by reloading\nthe module. However, the overhead for keeping coverage collection\nrunning is often neligible, especially for [coverage\nmode](`t:coverage_mode/0`) `function` that only keeps track of which\nfunctions that have been executed.\n\nThe `m:cover` tool in the Tools application will automatically use the\nnative coverage support if the runtime system supports it.\n\nIt is only necessary to use the functionality described next if\n`m:cover` is not sufficient, for example:\n\n* If one wants to collect coverage information for the code that runs\n when the runtime system is starting (module `m:init` and so on).\n `m:cover` can only be used when the Erlang system has started, and\n it will reload every module that is to be analyzed.\n\n* If it is necessary to collect coverage information with the absolute\n minimum disturbance of the test system. `m:cover` always counts how\n many times each line is executed (coverage mode `line_counters`),\n but by using native coverage one can use a less expensive coverage\n mode such as `function`, which has almost negligible overhead.","ref":"code.html#module-native-coverage-support"},{"type":"module","title":"Short summary of using native coverage - code","doc":"If the `line` or `line_counters` coverage mode is to be used,\nthe code to be tested must be compiled with option\n[`line_coverage`](`e:compiler:compile#line_coverage`).\n\nUse [set_coverage_mode(Mode)](`set_coverage_mode/1`) to set a\n[coverage mode](`t:coverage_mode/0`) for all code subsequently\nloaded, or set it with option [\\+JPcover](`e:erts:erl_cmd.md#%2BJPcover`)\nfor `erl`.\n\nOptionally reset coverage information for all\nmodules that are to be tested by calling\n[reset_coverage(Module)](`reset_coverage/1`).\n\nRun the code whose coverage information is to be collected.\n\nRead out the counters for all interesting modules by calling\n[get_coverage(Level, Module)](`get_coverage/2`), where `Level`\nis either `function` or `line`.","ref":"code.html#module-short-summary-of-using-native-coverage"},{"type":"module","title":"The other native coverage BIFs - code","doc":"The following BIFs are sometimes useful, for example to fail gracefully\nif the runtime system does not support native coverage:\n\n* [coverage_support()](`coverage_support/0`) - check whether\n the runtime system supports native coverage\n\n* [get_coverage_mode()](`get_coverage_mode/0`) - get the current\n coverage mode\n\n* [get_coverage_mode(Module)](`get_coverage_mode/1`) - get the coverage\n mode for module `Module`","ref":"code.html#module-the-other-native-coverage-bifs"},{"type":"module","title":"Argument Types and Invalid Arguments - code","doc":"Module and application names are atoms, while file and directory names are\nstrings. For backward compatibility reasons, some functions accept both strings\nand atoms, but a future release will probably only allow the arguments that are\ndocumented.\n\nFunctions in this module generally fail with an exception if they are passed an\nincorrect type (for example, an integer or a tuple where an atom is expected).\nAn error tuple is returned if the argument type is correct, but there are some\nother errors (for example, a non-existing directory is specified to\n[`set_path/1`](`set_path/1`)).\n\n[](){: #error_reasons }","ref":"code.html#module-argument-types-and-invalid-arguments"},{"type":"module","title":"Error Reasons for Code-Loading Functions - code","doc":"Functions that load code (such as [`load_file/1`](`load_file/1`)) will return\n`{error,Reason}` if the load operation fails. Here follows a description of the\ncommon reasons.\n\n- **`badfile`** - The object code has an incorrect format or the module name in\n the object code is not the expected module name.\n\n- **`nofile`** - No file with object code was found.\n\n- **`not_purged`** - The object code could not be loaded because an old version\n of the code already existed.\n\n- **`on_load_failure`** - The module has an\n [\\-on_load function](`e:system:code_loading.md#on_load`) that failed when it\n was called.\n\n- **`sticky_directory`** - The object code resides in a sticky directory.","ref":"code.html#module-error-reasons-for-code-loading-functions"},{"type":"function","title":"code.add_path/1","doc":"","ref":"code.html#add_path/1"},{"type":"function","title":"code.add_path/2","doc":"","ref":"code.html#add_path/2"},{"type":"function","title":"code.add_patha/1","doc":"","ref":"code.html#add_patha/1"},{"type":"function","title":"code.add_patha/2","doc":"Adds `Dir` to the beginning of the code path.\n\nIf `Dir` exists, it is removed from the old position in the code path.\n\nArgument `Cache` controls whether the content of the directory\nshould be cached on first traversal. If `Cache` is `cache` the directory\ncontents will be cached; if `Cache` is `nocache` it will not be cached.\n\nReturns `true` if successful, or `{error, bad_directory}` if `Dir` is\nnot the name of a directory.","ref":"code.html#add_patha/2"},{"type":"function","title":"code.add_paths/1","doc":"","ref":"code.html#add_paths/1"},{"type":"function","title":"code.add_paths/2","doc":"","ref":"code.html#add_paths/2"},{"type":"function","title":"code.add_pathsa/1","doc":"","ref":"code.html#add_pathsa/1"},{"type":"function","title":"code.add_pathsa/2","doc":"Traverses `Dirs` and adds each `Dir` to the beginning of the code path.\n\nThis means that the order of `Dirs` is reversed in the resulting code\npath. For example, if `Dirs` is `[Dir1,Dir2]`, the resulting path will\nbe `[Dir2,Dir1|OldCodePath]`.\n\nIf a `Dir` already exists in the code path, it is removed from the old position.\n\nArgument `Cache` controls whether the content of the directory\nshould be cached on first traversal. If `Cache` is `cache` the directory\ncontents will be cached; if `Cache` is `nocache` it will not be cached.\n\nAlways returns `ok`, regardless of the validity of each individual `Dir`.","ref":"code.html#add_pathsa/2"},{"type":"function","title":"code.add_pathsz/1","doc":"","ref":"code.html#add_pathsz/1"},{"type":"function","title":"code.add_pathsz/2","doc":"Adds the directories in `Dirs` to the end of the code path.\n\nDirectories that are already present in the path will not be added.\n\nArgument `Cache` controls whether the content of the directory\nshould be cached on first traversal. If `Cache` is `cache` the directory\ncontents will be cached; if `Cache` is `nocache` it will not be cached.\n\nAlways returns `ok`, regardless of the validity of each individual `Dir`.","ref":"code.html#add_pathsz/2"},{"type":"function","title":"code.add_pathz/1","doc":"","ref":"code.html#add_pathz/1"},{"type":"function","title":"code.add_pathz/2","doc":"Adds `Dir` as the directory last in the code path.\n\nIf `Dir` already exists in the path, it is not added.\n\nArgument `Cache` controls whether the content of the directory\nshould be cached on first traversal. If `Cache` is `cache` the directory\ncontents will be cached; if `Cache` is `nocache` it will not be cached.\n\nReturns `true` if successful, or `{error, bad_directory}` if `Dir` is\nnot the name of a directory.","ref":"code.html#add_pathz/2"},{"type":"function","title":"code.all_available/0","doc":"Returns a list of tuples `{Module, Filename, Loaded}` for all available modules.\n\nA module is considered to be available if it either is loaded or would be loaded\nif called. `Filename` is normally the absolute filename, as described for\n`is_loaded/1`.","ref":"code.html#all_available/0"},{"type":"function","title":"code.all_loaded/0","doc":"Returns a list of tuples `{Module, Loaded}` for all loaded modules.\n\n`Loaded` is normally the absolute filename, as described for `is_loaded/1`.","ref":"code.html#all_loaded/0"},{"type":"function","title":"code.atomic_load/1","doc":"Tries to load all of the modules in the list `Modules` atomically.\n\nThat means that either all modules are loaded at the same time, or\nnone of the modules are loaded if there is a problem with any of the\nmodules.\n\nLoading can fail for one the following reasons:\n\n- **`badfile`** - The object code has an incorrect format or the module name in\n the object code is not the expected module name.\n\n- **`nofile`** - No file with object code exists.\n\n- **`on_load_not_allowed`** - A module contains an\n [\\-on_load function](`e:system:code_loading.md#on_load`).\n\n- **`duplicated`** - A module is included more than once in `Modules`.\n\n- **`not_purged`** - The object code cannot be loaded because an old version of\n the code already exists.\n\n- **`sticky_directory`** - The object code resides in a sticky directory.\n\n- **`pending_on_load`** - A previously loaded module contains an `-on_load`\n function that never finished.\n\nIf it is important to minimize the time that an application is inactive while\nchanging code, use `prepare_loading/1` and `finish_loading/1` instead of\n[`atomic_load/1`](`atomic_load/1`). Here is an example:\n\n```erlang\n{ok,Prepared} = code:prepare_loading(Modules),\n%% Put the application into an inactive state or do any\n%% other preparation needed before changing the code.\nok = code:finish_loading(Prepared),\n%% Resume the application.\n```","ref":"code.html#atomic_load/1"},{"type":"function","title":"code.clash/0","doc":"Searches all directories in the code path for module names with identical names\nand writes a report to `stdout`.","ref":"code.html#clash/0"},{"type":"function","title":"code.clear_cache/0","doc":"Clears the code path cache.\n\nIf a directory is cached, its cache is cleared once and then it will\nbe recalculated and cached once more in a future traversal.\n\nTo clear the cache for a single path, either re-add it to the code\npath (with [`add_path/2`](`add_path/2`)) or replace it (with\n[`replace_path/3`](`replace_path/3`)). To disable all caching, reset\nthe code path with `code:set_path(code:get_path())`.\n\nAlways returns `ok`.","ref":"code.html#clear_cache/0"},{"type":"function","title":"code.compiler_dir/0","doc":"Returns the compiler library directory.\n\nEquivalent to [`code:lib_dir(compiler)`](`code:lib_dir/1`).","ref":"code.html#compiler_dir/0"},{"type":"function","title":"code.coverage_support/0","doc":"Returns `true` if the system supports coverage and `false` otherwise.\n\n_See also:_ [Native Coverage Support](#module-native-coverage-support)","ref":"code.html#coverage_support/0"},{"type":"function","title":"code.del_path/1","doc":"Deletes a directory from the code path.\n\nThe argument can be an atom `Name`, in which case the directory with\nthe name `.../Name[-Vsn][/ebin]` is deleted from the code path. Also,\nthe complete directory name `Dir` can be specified as argument.\n\nReturns:\n\n- **`true`** - If successful\n\n- **`false`** - If the directory is not found\n\n- **`{error, bad_name}`** - If the argument is invalid","ref":"code.html#del_path/1"},{"type":"function","title":"code.del_paths/1","doc":"Deletes directories from the code path.\n\nThe argument is a list of either atoms or complete directory names. If\n`Name` is an atom, the directory with the name `.../Name[-Vsn][/ebin]` is\ndeleted from the code path.\n\nAlways returns `ok`, regardless of the validity of each individual\n`NamesOrDirs`.","ref":"code.html#del_paths/1"},{"type":"function","title":"code.delete/1","doc":"Removes the current code for `Module`, that is, the current code for `Module` is\nmade old.\n\nThis means that processes can continue to execute the code in the\nmodule, but no external function calls can be made to it.\n\nReturns `true` if successful, or `false` if there is old code for `Module` that\nmust be purged first, or if `Module` is not a (loaded) module.","ref":"code.html#delete/1"},{"type":"function","title":"code.ensure_loaded/1","doc":"Tries to load a module in the same way as `load_file/1`, unless the module is\nalready loaded.\n\nIf called concurrently, this function ensures that only one process\nattempts to load said module at a given time.\n\nIn embedded mode, it does not load a module that is not already loaded, but\nreturns `{error, embedded}` instead. See\n[Error Reasons for Code-Loading Functions](`m:code#error_reasons`) for a\ndescription of other possible error reasons.","ref":"code.html#ensure_loaded/1"},{"type":"function","title":"code.ensure_modules_loaded/1","doc":"Tries to load any modules not already loaded in the list `Modules` in the same\nway as `load_file/1`.\n\nUnlike `ensure_loaded/1`, modules are loaded even in `embedded` mode.\n\nReturns `ok` if successful, or `{error,[{Module,Reason}]}` if loading of some\nmodules fails. See\n[Error Reasons for Code-Loading Functions](`m:code#error_reasons`) for a\ndescription of other possible error reasons.","ref":"code.html#ensure_modules_loaded/1"},{"type":"function","title":"code.finish_loading/1","doc":"Tries to load code for all modules that have been previously prepared by\n`prepare_loading/1`.\n\nThe loading occurs atomically, meaning that either all modules are\nloaded at the same time, or none of the modules are loaded.\n\nThis function can fail with one of the following error reasons:\n\n- **`not_purged`** - The object code cannot be loaded because an old version of\n the code already exists.\n\n- **`sticky_directory`** - The object code resides in a sticky directory.\n\n- **`pending_on_load`** - A previously loaded module contains an `-on_load`\n function that never finished.","ref":"code.html#finish_loading/1"},{"type":"function","title":"code.get_coverage/2","doc":"Return either `function` or `line` coverage data for module `Module`.\n\nIf Level is `function`, returns function coverage for the given module\naccording to its [coverage mode](`t:coverage_mode/0`):\n\n- **`function`** - For each function in module Module, a boolean indicating\n whether that function has been executed at least once is returned.\n\n- **`function_counters`** - For each function in module Module, an integer\n giving the number of times that line has been executed is returned.\n\n- **`line`** - For each function in module Module, a boolean indicating whether\n that function has been executed at least once is returned.\n\n- **`line_counters`** - For each function in module Module, a boolean indicating\n whether that function has been executed at least once is returned (note that\n in this mode, counters for the number of times each function has been executed\n **cannot** be retrieved).\n\nIf Level is `line`, returns line coverage for the given module according to its\ncoverage mode:\n\n- **`line`** - For each executable line in the module, a boolean indicating\n whether that line has been executed at least once is returned.\n\n- **`line_counters`** - For each executable line in the module, an integer\n giving the number of times that line was executed is returned.\n\nLevel `cover_id_line` is used by the `m:cover` tool.\n\nFailures:\n\n- **`badarg`** - If `Level` is not `function` or `line`.\n\n- **`badarg`** - If `Module` is not an atom.\n\n- **`badarg`** - If `Module` does not refer to a loaded module.\n\n- **`badarg`** - If `Module` was not loaded in another coverage mode than\n `none`.\n\n- **`badarg`** - If Level is `line` and `Module` has not been loaded with either\n `line` or `line_counters` enabled.\n\n- **`badarg`** - If the runtime system does not support coverage.\n\n_See also:_ [Native Coverage Support](#module-native-coverage-support)","ref":"code.html#get_coverage/2"},{"type":"function","title":"code.get_coverage_mode/0","doc":"Returns the coverage mode as set by option\n[\\+JPcover](`e:erts:erl_cmd.md#%2BJPcover`) for `erl` or `set_coverage_mode/1`.\n\nFailure:\n\n- **`badarg`** - If the runtime system does not support coverage.\n\n_See also:_ [Native Coverage Support](#module-native-coverage-support)","ref":"code.html#get_coverage_mode/0"},{"type":"function","title":"code.get_coverage_mode/1","doc":"Get coverage mode for the given module.\n\nFailures:\n\n- **`badarg`** - If `Module` is not an atom.\n\n- **`badarg`** - If `Module` does not refer to a loaded module.\n\n- **`badarg`** - If the runtime system does not support coverage.\n\n_See also:_ [Native Coverage Support](#module-native-coverage-support)","ref":"code.html#get_coverage_mode/1"},{"type":"function","title":"code.get_doc/1","doc":"Returns [EEP 48](https://www.erlang.org/eeps/eep-0048.html) style\ndocumentation for `Module` if available.\n\nIf `Module` is not found in the code path, this function returns\n`{error,non_existing}`.\n\nIf no documentation can be found this function attempts to generate\ndocumentation from the debug information in the module. If no debug\ninformation is available, this function returns `{error,missing}`.\n\nFor more information about the documentation chunk see\n[Documentation Storage and Format](eep48_chapter.md) in\nKernel's User's Guide.","ref":"code.html#get_doc/1"},{"type":"function","title":"code.get_mode/0","doc":"Returns an atom describing the mode of the code server: `interactive` or\n`embedded`.\n\nThis information is useful when an external entity (for example, an IDE)\nprovides additional code for a running node. If the code server is in\ninteractive mode, it only has to add the path to the code. If the code server is\nin embedded mode, the code must be loaded with `load_binary/3`.","ref":"code.html#get_mode/0"},{"type":"function","title":"code.get_object_code/1","doc":"Returns the object code for module `Module` if found in the code path.\n\nReturns `{Module, Binary, Filename}` if successful, otherwise\n`error`. `Binary` is a binary data object, which contains the object\ncode for the module. This is useful if code is to be loaded on a\nremote node in a distributed system. For example, loading module\n`Module` on a node `Node` is done as follows:\n\n```erlang\n...\n{_Module, Binary, Filename} = code:get_object_code(Module),\nerpc:call(Node, code, load_binary, [Module, Filename, Binary]),\n...\n```","ref":"code.html#get_object_code/1"},{"type":"function","title":"code.get_path/0","doc":"Returns the code path.","ref":"code.html#get_path/0"},{"type":"function","title":"code.is_loaded/1","doc":"Checks whether `Module` is loaded.\n\nIf it is, `{file, Loaded}` is returned, otherwise `false`.\n\nNormally, `Loaded` is the absolute filename `Filename` from which the code is\nobtained. If the module is preloaded (see [`script(4)`](`e:sasl:script.md`)),\n`Loaded =:= preloaded`. If the module is Cover-compiled (see `m:cover`),\n`Loaded =:= cover_compiled`.","ref":"code.html#is_loaded/1"},{"type":"function","title":"code.is_sticky/1","doc":"Returns `true` if `Module` is the name of a module that has been loaded from a\nsticky directory (in other words: an attempt to reload the module will fail), or\n`false` if `Module` is not a loaded module or is not sticky.","ref":"code.html#is_sticky/1"},{"type":"function","title":"code.lib_dir/0","doc":"Returns the library directory, `$OTPROOT/lib`, where `$OTPROOT` is the root\ndirectory of Erlang/OTP.\n\n_Example:_\n\n```erlang\n1> code:lib_dir().\n\"/usr/local/otp/lib\"\n```","ref":"code.html#lib_dir/0"},{"type":"function","title":"code.lib_dir/1","doc":"Returns the path for the *library directory*, the top directory, for an\napplication `Name` located under `$OTPROOT/lib` or in a directory referred to\nwith environment variable `ERL_LIBS`.\n\nIf a regular directory called `Name` or `Name-Vsn` exists in the code path with\nan `ebin` subdirectory, the path to this directory is returned (not the `ebin`\ndirectory).\n\nIf the directory refers to a directory in an archive, the archive name is\nstripped away before the path is returned. For example, if directory\n`/usr/local/otp/lib/mnesia-4.2.2.ez/mnesia-4.2.2/ebin` is in the path,\n`/usr/local/otp/lib/mnesia-4.2.2/ebin` is returned. This means that the library\ndirectory for an application is the same, regardless if the application resides\nin an archive or not.\n\n> #### Warning {: .info }\n>\n> Archives are experimental. In a future release, they can be removed or\n> their behavior can change.\n\n_Example:_\n\n```erlang\n> code:lib_dir(mnesia).\n\"/usr/local/otp/lib/mnesia-4.23\"\n```\n\nReturns `{error, bad_name}` if `Name` is not the name of an application under\n`$OTPROOT/lib` or on a directory referred to through environment variable\n`ERL_LIBS`. Fails with an exception if `Name` has the wrong type.\n\n> #### Warning {: .warning }\n>\n> For backward compatibility, `Name` is also allowed to be a string. That will\n> probably change in a future release.","ref":"code.html#lib_dir/1"},{"type":"function","title":"code.lib_dir/2","doc":"Returns the path to a subdirectory directly under the top directory of an\napplication.\n\n> #### Change {: .info }\n>\n> This function is part of the archive support, which is an experimental\n> feature that will be changed or removed in a future release.\n\nNormally the subdirectories reside under the top directory for the\napplication, but when applications at least partly reside in an archive, the\nsituation is different. Some of the subdirectories can reside as regular\ndirectories while others reside in an archive file. It is not checked whether\nthis directory exists.\n\nInstead of using this function, use [`code:lib_dir/1`](`code:lib_dir/1`)\nand `filename:join/2`.\n\n_Example:_\n\n```erlang\n1> filename:join(code:lib_dir(megaco), \"priv\").\n\"/usr/local/otp/lib/megaco-3.9.1.1/priv\"\n```\n\nFails with an exception if `Name` or `SubDir` has the wrong type.","ref":"code.html#lib_dir/2"},{"type":"function","title":"code.load_abs/1","doc":"Equivalent to [`load_file(Module)`](`load_file/1`), except that `Filename` is\nan absolute or relative filename.\n\nThe code path is not searched. It returns a value in the same way as\n`load_file/1`. Notice that `Filename` must not contain the extension\n(for example, `.beam`) because [`load_abs/1`](`load_abs/1`) adds the\ncorrect extension.","ref":"code.html#load_abs/1"},{"type":"function","title":"code.load_binary/3","doc":"Loads object code from a binary.\n\nThis function can be used to load object code on remote Erlang nodes. Argument\n`Binary` must contain object code for `Module`. `Filename` is only used by the\ncode server to keep a record of from which file the object code for `Module`\noriginates. Thus, `Filename` is not opened and read by the code server.\n\nReturns `{module, Module}` if successful, or `{error, Reason}` if loading fails.\nSee [Error Reasons for Code-Loading Functions](`m:code#error_reasons`) for a\ndescription of the possible error reasons.","ref":"code.html#load_binary/3"},{"type":"function","title":"code.load_file/1","doc":"Tries to load the Erlang module `Module` using the code path.\n\nIt looks for the object code file with an extension corresponding to\nthe Erlang machine used, for example, `Module.beam`. The loading fails\nif the module name found in the object code differs from the name\n`Module`. Use `load_binary/3` to load object code with a module name\nthat is different from the file name.\n\nReturns `{module, Module}` if successful, or `{error, Reason}` if loading fails.\nSee [Error Reasons for Code-Loading Functions](`m:code#error_reasons`) for a\ndescription of the possible error reasons.","ref":"code.html#load_file/1"},{"type":"function","title":"code.modified_modules/0","doc":"Returns the list of all currently loaded modules for which `module_status/1`\nreturns `modified`.\n\nSee also `all_loaded/0`.","ref":"code.html#modified_modules/0"},{"type":"function","title":"code.module_status/0","doc":"See `module_status/1` and `all_loaded/0` for details.","ref":"code.html#module_status/0"},{"type":"function","title":"code.module_status/1","doc":"Returns the status of `Module` in relation to object file on disk.\n\nThe status of a module can be one of:\n\n- **`not_loaded`** - If `Module` is not currently loaded.\n\n- **`loaded`** - If `Module` is loaded, and the object file exists and contains\n the same code.\n\n- **`removed`** - If `Module` is loaded, but no corresponding object file can be\n found in the code path.\n\n- **`modified`** - If `Module` is loaded, but the object file contains code with\n a different MD5 checksum.\n\nPreloaded modules are always reported as `loaded`, without inspecting the\ncontents on disk. Cover-compiled modules will always be reported as `modified`\nif an object file exists, or as `removed` otherwise. Modules whose load path is\nan empty string (which is the convention for auto-generated code) will only be\nreported as `loaded` or `not_loaded`.\n\nSee also `modified_modules/0`.","ref":"code.html#module_status/1"},{"type":"function","title":"code.objfile_extension/0","doc":"Returns the object code file extension corresponding to the Erlang machine used.\n\nFor the official Erlang/OTP release, the return value is always `.beam`.","ref":"code.html#objfile_extension/0"},{"type":"function","title":"code.prepare_loading/1","doc":"Prepares to load the modules in the list `Modules`.\n\nFinish the loading by calling\n[finish_loading(Prepared)](`finish_loading/1`).\n\nThis function can fail with one of the following error reasons:\n\n- **`badfile`** - The object code has an incorrect format or the module name in\n the object code is not the expected module name.\n\n- **`nofile`** - No file with object code exists.\n\n- **`on_load_not_allowed`** - A module contains an\n [\\-on_load function](`e:system:code_loading.md#on_load`).\n\n- **`duplicated`** - A module is included more than once in `Modules`.","ref":"code.html#prepare_loading/1"},{"type":"function","title":"code.priv_dir/1","doc":"Returns the path to the `priv` directory in an application.\n\n> #### Warning {: .warning }\n>\n> For backward compatibility, `Name` is also allowed to be a string. That will\n> probably change in a future release.","ref":"code.html#priv_dir/1"},{"type":"function","title":"code.purge/1","doc":"Purges the code for `Module`, that is, removes code marked as old.\n\nIf some processes still linger in the old code, these processes are\nkilled before the code is removed.\n\n> #### Change {: .info }\n>\n> As of Erlang/OTP 20.0, a process is only considered to be lingering in the\n> code if it has direct references to the code. For more information see\n> documentation of `erlang:check_process_code/3`, which is used in order to\n> determine whether a process is lingering.\n\nReturns `true` if successful and any process is needed to be killed, otherwise\n`false`.","ref":"code.html#purge/1"},{"type":"function","title":"code.replace_path/2","doc":"","ref":"code.html#replace_path/2"},{"type":"function","title":"code.replace_path/3","doc":"Replaces an old occurrence of a directory named `.../Name[-Vsn][/ebin]` in the\ncode path, with `Dir`.\n\nIf `Name` does not exist, it adds the new directory `Dir` last in the\ncode path. The new directory must also be named\n`.../Name[-Vsn][/ebin]`. This function is to be used if a new version\nof the directory (library) is added to a running system.\n\nArgument `Cache` controls whether the content of the directory\nshould be cached on first traversal. If `Cache` is `cache` the directory\ncontents will be cached; if `Cache` is `nocache` it will not be cached.\n\nReturns:\n\n- **`true`** - If successful\n\n- **`{error, bad_name}`** - If `Name` is not found\n\n- **`{error, bad_directory}`** - If `Dir` does not exist\n\n- **`{error, {badarg, [Name, Dir]}}`** - If `Name` or `Dir` is invalid","ref":"code.html#replace_path/3"},{"type":"function","title":"code.reset_coverage/1","doc":"Resets coverage information for module `Module`.\n\nIf the [coverage mode](`t:coverage_mode/0`) is either `function` or\n`line`, all booleans for `Module` keeping track of executed functions\nor lines are set to `false`.\n\nIf the coverage mode is either `function_counters` or\n`line_counters`, all counters for `Module` are reset to zero.\n\nFailures:\n\n- **`badarg`** - If `Module` is not an atom.\n\n- **`badarg`** - If `Module` does not refer to a loaded module.\n\n- **`badarg`** - If `Module` was not loaded with coverage enabled.\n\n- **`badarg`** - If the runtime system does not support coverage.\n\n_See also:_ [Native Coverage Support](#module-native-coverage-support)","ref":"code.html#reset_coverage/1"},{"type":"function","title":"code.root_dir/0","doc":"Returns the root directory of Erlang/OTP, which is the directory where it is\ninstalled.\n\n_Example:_\n\n```erlang\n1> code:root_dir().\n\"/usr/local/otp\"\n```","ref":"code.html#root_dir/0"},{"type":"function","title":"code.set_coverage_mode/1","doc":"Sets the coverage mode for modules that are subsequently loaded, similar to\noption [\\+JPcover](`e:erts:erl_cmd.md#%2BJPcover`) for `erl`.\n\nThe coverage mode will have the following effect on code that is\nloaded following this call:\n\n- **`function`** - All modules that are loaded will be instrumented to keep\n track of which functions are executed. Information about which functions that\n have been executed can be retrieved by calling\n [`get_coverage(function, Module)`](`get_coverage/2`).\n\n- **`function_counters`** - All modules that are loaded will be instrumented to\n count how many times each function is executed. Information about how many\n times each function has been executed can be retrieved by calling\n [`get_coverage(function, Module)`](`get_coverage/2`).\n\n- **`line`** - When modules that have been compiled with the\n [`line_coverage`](`m:compile#line_coverage`) option are loaded, they will be\n instrumented to keep track of which lines have been executed. Information\n about which lines have been executed can be retrieved by calling\n [`get_coverage(line, Module)`](`get_coverage/2`), and information about which\n functions that have been executed can be retrieved by calling\n [`get_coverage(function, Module)`](`get_coverage/2`).\n\n- **`line_counters`** - When modules that have been compiled with the\n [`line_coverage`](`m:compile#line_coverage`) option are loaded, they will be\n instrumented to count the number of times each line is executed. Information\n about how many times each line has been executed can be retrieved by calling\n [`get_coverage(line, Module)`](`get_coverage/2`), and information about which\n functions that have been executed can be retrieved by calling\n [`get_coverage(function, Module)`](`get_coverage/2`) (note that in this mode,\n counters for the number of times each function has been executed **cannot** be\n retrieved).\n\n- **`none`** - Modules will be loaded without coverage instrumentation.\n\nReturns the previous coverage mode.\n\nFailures:\n\n- **`badarg`** - If `Mode` is not a valid coverage mode.\n\n- **`badarg`** - If the runtime system does not support coverage.\n\n_See also:_ [Native Coverage Support](#module-native-coverage-support)","ref":"code.html#set_coverage_mode/1"},{"type":"function","title":"code.set_path/1","doc":"","ref":"code.html#set_path/1"},{"type":"function","title":"code.set_path/2","doc":"Sets the code path to the list of directories `Path`.\n\nArgument `Cache` controls whether the content of the directory\nshould be cached on first traversal. If `Cache` is `cache` the directory\ncontents will be cached; if `Cache` is `nocache` it will not be cached.\n\nReturns:\n\n- **`true`** - If successful\n\n- **`{error, bad_directory}`** - If any `Dir` is not a directory name","ref":"code.html#set_path/2"},{"type":"function","title":"code.soft_purge/1","doc":"Purges the code for `Module`, that is, removes code marked as old, but only if\nno processes linger in it.\n\n> #### Change {: .info }\n>\n> As of Erlang/OTP 20.0, a process is only considered to be lingering in the\n> code if it has direct references to the code. For more information see\n> documentation of `erlang:check_process_code/3`, which is used in order to\n> determine whether a process is lingering.\n\nReturns `false` if the module cannot be purged because of processes lingering in\nold code, otherwise `true`.","ref":"code.html#soft_purge/1"},{"type":"function","title":"code.stick_dir/1","doc":"Marks `Dir` as sticky.\n\nReturns `ok` if successful, otherwise `error`.","ref":"code.html#stick_dir/1"},{"type":"function","title":"code.unstick_dir/1","doc":"Unsticks a directory that is marked as sticky.\n\nReturns `ok` if successful, otherwise `error`.","ref":"code.html#unstick_dir/1"},{"type":"function","title":"code.where_is_file/1","doc":"Searches the code path for `Filename`, which is a file of arbitrary type.\n\nIf found, the full name is returned. `non_existing` is returned if the\nfile cannot be found. The function can be useful, for example, to\nlocate application resource files.","ref":"code.html#where_is_file/1"},{"type":"function","title":"code.which/1","doc":"If the module is not loaded, this function searches the code path for the first\nfile containing object code for `Module` and returns the absolute filename.\n\n- If the module is loaded, it returns the name of the file containing the loaded\n object code.\n\n- If the module is preloaded, `preloaded` is returned.\n\n- If the module is Cover-compiled, `cover_compiled` is returned.\n\n- If the module cannot be found, `non_existing` is returned.","ref":"code.html#which/1"},{"type":"type","title":"code.add_path_ret/0","doc":"","ref":"code.html#t:add_path_ret/0"},{"type":"type","title":"code.cache/0","doc":"","ref":"code.html#t:cache/0"},{"type":"type","title":"code.coverage_mode/0","doc":"","ref":"code.html#t:coverage_mode/0"},{"type":"type","title":"code.load_error_rsn/0","doc":"","ref":"code.html#t:load_error_rsn/0"},{"type":"type","title":"code.load_ret/0","doc":"","ref":"code.html#t:load_ret/0"},{"type":"type","title":"code.loaded_filename/0","doc":"","ref":"code.html#t:loaded_filename/0"},{"type":"type","title":"code.loaded_ret_atoms/0","doc":"","ref":"code.html#t:loaded_ret_atoms/0"},{"type":"type","title":"code.module_status/0","doc":"","ref":"code.html#t:module_status/0"},{"type":"opaque","title":"code.prepared_code/0","doc":"An opaque term holding prepared code.","ref":"code.html#t:prepared_code/0"},{"type":"type","title":"code.replace_path_ret/0","doc":"","ref":"code.html#t:replace_path_ret/0"},{"type":"type","title":"code.set_path_ret/0","doc":"","ref":"code.html#t:set_path_ret/0"},{"type":"module","title":"erl_ddll","doc":"Dynamic driver loader and linker.\n\nThis module provides an interface for loading and unloading _Erlang linked-in\ndrivers_ in runtime.\n\n> #### Note {: .info }\n>\n> This is a large reference document. For casual use of this module, and for\n> most real world applications, the descriptions of functions `load/2` and\n> `unload/1` are enough to getting started.\n\nThe driver is to be provided as a dynamically linked library in an object code\nformat specific for the platform in use, that is, `.so` files on most Unix\nsystems and `.ddl` files on Windows. An Erlang linked-in driver must provide\nspecific interfaces to the emulator, so this module is not designed for loading\narbitrary dynamic libraries. For more information about Erlang drivers, see\n[`erl_driver`](`e:erts:erl_driver.md`) .\n\n[](){: #users }\n\nWhen describing a set of functions (that is, a module, a part of a module, or an\napplication), executing in a process and wanting to use a ddll-driver, we use\nthe term _user_. A process can have many users (different modules needing the\nsame driver) and many processes running the same code, making up many _users_ of\na driver.\n\nIn the basic scenario, each user loads the driver before starting to use it and\nunloads the driver when done. The reference counting keeps track of processes\nand the number of loads by each process. This way the driver is only unloaded\nwhen no one wants it (it has no user). The driver also keeps track of ports that\nare opened to it. This enables delay of unloading until all ports are closed, or\nkilling of all ports that use the driver when it is unloaded.\n\n[](){: #scenarios }\n\nThe interface supports two basic scenarios of loading and unloading. Each\nscenario can also have the option of either killing ports when the driver is\nunloading, or waiting for the ports to close themselves. The scenarios are as\nfollows:\n\n- **_Load and Unload on a \"When Needed Basis\"_** - This (most common) scenario\n simply supports that each [user](`m:erl_ddll#users`) of the driver loads it\n when needed and unloads it when no longer needed. The driver is always\n reference counted and as long as a process keeping the driver loaded is still\n alive, the driver is present in the system.\n\n Each [user](`m:erl_ddll#users`) of the driver use _literally_ the same\n pathname for the driver when demanding load, but the\n [users](`m:erl_ddll#users`) are not concerned with if the driver is already\n loaded from the file system or if the object code must be loaded from file\n system.\n\n The following two pairs of functions support this scenario:\n\n - **_load/2 and unload/1_** - When using the `load/unload` interfaces, the\n driver is not unloaded until the _last port_ using the driver is closed.\n Function [`unload/1`](`unload/1`) can return immediately, as the\n [users](`m:erl_ddll#users`) have no interest in when the unloading occurs.\n The driver is unloaded when no one needs it any longer.\n\n If a process having the driver loaded dies, it has the same effect as if\n unloading is done.\n\n When loading, function [`load/2`](`load/2`) returns `ok` when any instance\n of the driver is present. Thus, if a driver is waiting to get unloaded\n (because of open ports), it simply changes state to no longer need\n unloading.\n\n - **_load_driver/2 and unload_driver/1_** - These interfaces are intended to\n be used when it is considered an error that ports are open to a driver that\n no [user](`m:erl_ddll#users`) has loaded. The ports that are still open when\n the last [user](`m:erl_ddll#users`) calls\n [`unload_driver/1`](`unload_driver/1`) or when the last process having the\n driver loaded dies, are killed with reason `driver_unloaded`.\n\n The function names `load_driver` and `unload_driver` are kept for backward\n compatibility.\n\n- **_Loading and Reloading for Code Replacement_** - This scenario can occur if\n the driver code needs replacement during operation of the Erlang emulator.\n Implementing driver code replacement is a little more tedious than Beam code\n replacement, as one driver cannot be loaded as both \"old\" and \"new\" code. All\n [users](`m:erl_ddll#users`) of a driver must have it closed (no open ports)\n before the old code can be unloaded and the new code can be loaded.\n\n The unloading/loading is done as one atomic operation, blocking all processes\n in the system from using the driver in question while in progress.\n\n The preferred way to do driver code replacement is to let _one single process_\n keep track of the driver. When the process starts, the driver is loaded. When\n replacement is required, the driver is reloaded. Unload is probably never\n done, or done when the process exits. If more than one\n [user](`m:erl_ddll#users`) has a driver loaded when code replacement is\n demanded, the replacement cannot occur until the last \"other\"\n [user](`m:erl_ddll#users`) has unloaded the driver.\n\n Demanding reload when a reload is already in progress is always an error.\n Using the high-level functions, it is also an error to demand reloading when\n more than one [user](`m:erl_ddll#users`) has the driver loaded.\n\n To simplify driver replacement, avoid designing your system so that more than\n one [user](`m:erl_ddll#users`) has the driver loaded.\n\n The two functions for reloading drivers are to be used together with\n corresponding load functions to support the two different behaviors concerning\n open ports:\n\n - **_load/2 and reload/2_** - This pair of functions is used when reloading is\n to be done after the last open port to the driver is closed.\n\n As [`reload/2`](`reload/2`) waits for the reloading to occur, a misbehaving\n process keeping open ports to the driver (or keeping the driver loaded) can\n cause infinite waiting for reload. Time-outs must be provided outside of the\n process demanding the reload or by using the low-level interface\n `try_load/3` in combination with driver monitors.\n\n - **_load_driver/2 and reload_driver/2_** - This pair of functions are used\n when open ports to the driver are to be killed with reason `driver_unloaded`\n to allow for new driver code to get loaded.\n\n However, if another process has the driver loaded, calling `reload_driver`\n returns error code `pending_process`. As stated earlier, the recommended\n design is to not allow other [users](`m:erl_ddll#users`) than the \"driver\n reloader\" to demand loading of the driver in question.","ref":"erl_ddll.html"},{"type":"module","title":"See Also - erl_ddll","doc":"[`erl_driver(4)`](`e:erts:erl_driver.md`), [`driver_entry(4)`](`e:erts:driver_entry.md`)","ref":"erl_ddll.html#module-see-also"},{"type":"function","title":"erl_ddll.demonitor/1","doc":"Removes a driver monitor in much the same way as `erlang:demonitor/1` in ERTS\ndoes with process monitors.\n\nFor details about how to create driver monitors, see `monitor/2`,\n`try_load/3`, and `try_unload/2`.\n\nThe function throws a `badarg` exception if the parameter is not a\n`t:reference/0`.","ref":"erl_ddll.html#demonitor/1"},{"type":"function","title":"erl_ddll.format_error/1","doc":"Takes an `ErrorDesc` returned by load, unload, or reload functions and returns a\nstring that describes the error or warning.\n\n> #### Note {: .info }\n>\n> Because of peculiarities in the dynamic loading interfaces on different\n> platforms, the returned string is only guaranteed to describe the correct\n> error _if format_error/1 is called in the same instance of the Erlang virtual\n> machine as the error appeared in_ (meaning the same operating system process).","ref":"erl_ddll.html#format_error/1"},{"type":"function","title":"erl_ddll.info/0","doc":"Returns a list of tuples `{DriverName, InfoList}`, where `InfoList` is the\nresult of calling `info/1` for that `DriverName`. Only dynamically linked-in\ndrivers are included in the list.","ref":"erl_ddll.html#info/0"},{"type":"function","title":"erl_ddll.info/1","doc":"Returns a list of tuples `{Tag, Value}`, where `Tag` is the information item and\n`Value` is the result of calling `info/2` with this driver name and this tag.\nThe result is a tuple list containing all information available about a driver.\n\nThe following tags appears in the list:\n\n- `processes`\n- `driver_options`\n- `port_count`\n- `linked_in_driver`\n- `permanent`\n- `awaiting_load`\n- `awaiting_unload`\n\nFor a detailed description of each value, see `info/2`.\n\nThe function throws a `badarg` exception if the driver is not present in the\nsystem.","ref":"erl_ddll.html#info/1"},{"type":"function","title":"erl_ddll.info/2","doc":"Returns specific information about one aspect of a driver. Parameter `Tag`\nspecifies which aspect to get information about. The return `Value` differs\nbetween different tags:\n\n- **`processes`** - Returns all processes containing [users](`m:erl_ddll#users`)\n of the specific drivers as a list of tuples `{pid(),integer() >= 0}`, where\n `t:integer/0` denotes the number of users in process `t:pid/0`.\n\n- **`driver_options`** - Returns a list of the driver options provided when\n loading, and any options set by the driver during initialization. The only\n valid option is `kill_ports`.\n\n- **`port_count`** - Returns the number of ports (an `integer() >= 0`) using the\n driver.\n\n- **`linked_in_driver`** - Returns a `t:boolean/0`, which is `true` if the\n driver is a statically linked-in one, otherwise `false`.\n\n- **`permanent`** - Returns a `t:boolean/0`, which is `true` if the driver has\n made itself permanent (and is _not_ a statically linked-in driver), otherwise\n `false`.\n\n- **`awaiting_load`** - Returns a list of all processes having monitors for\n `loading` active. Each process is returned as `{pid(),integer() >= 0}`, where\n `t:integer/0` is the number of monitors held by process `t:pid/0`.\n\n- **`awaiting_unload`** - Returns a list of all processes having monitors for\n `unloading` active. Each process is returned as `{pid(),integer() >= 0}`,\n where `t:integer/0` is the number of monitors held by process `t:pid/0`.\n\nIf option `linked_in_driver` or `permanent` returns `true`, all other options\nreturn `linked_in_driver` or `permanent`, respectively.\n\nThe function throws a `badarg` exception if the driver is not present in the\nsystem or if the tag is not supported.","ref":"erl_ddll.html#info/2"},{"type":"function","title":"erl_ddll.load/2","doc":"Loads and links the dynamic driver `Name`. `Path` is a file path to the\ndirectory containing the driver. `Name` must be a shareable object/dynamic\nlibrary. Two drivers with different `Path` parameters cannot be loaded under the\nsame name. `Name` is a string or atom containing at least one character.\n\nThe `Name` specified is to correspond to the filename of the dynamically\nloadable object file residing in the directory specified as `Path`, but\n_without_ the extension (that is, `.so`). The driver name provided in the driver\ninitialization routine must correspond with the filename, in much the same way\nas Erlang module names correspond to the names of the `.beam` files.\n\nIf the driver was previously unloaded, but is still present because of open\nports to it, a call to [`load/2`](`load/2`) stops the unloading and keeps the\ndriver (as long as `Path` is the same), and `ok` is returned. If you really want\nthe object code to be reloaded, use `reload/2` or the low-level interface\n`try_load/3` instead. See also the description of\n[`different scenarios`](`m:erl_ddll#scenarios`) for loading/unloading in the\nintroduction.\n\nIf more than one process tries to load an already loaded driver with the same\n`Path`, or if the same process tries to load it many times, the function returns\n`ok`. The emulator keeps track of the [`load/2`](`load/2`) calls, so that a\ncorresponding number of `unload/2` calls must be done from the same process\nbefore the driver gets unloaded. It is therefore safe for an application to load\na driver that is shared between processes or applications when needed. It can\nsafely be unloaded without causing trouble for other parts of the system.\n\nIt is not allowed to load multiple drivers with the same name but with different\n`Path` parameters.\n\n> #### Note {: .info }\n>\n> `Path` is interpreted literally, so that all loaders of the same driver must\n> specify the same _literal_ `Path` string, although different paths can point\n> out the same directory in the file system (because of use of relative paths\n> and links).\n\nOn success, the function returns `ok`. On failure, the return value is\n`{error,ErrorDesc}`, where `ErrorDesc` is an opaque term to be translated into\nhuman readable form by function `format_error/1`.\n\nFor more control over the error handling, use the `try_load/3` interface\ninstead.\n\nThe function throws a `badarg` exception if the parameters are not specified as\ndescribed here.","ref":"erl_ddll.html#load/2"},{"type":"function","title":"erl_ddll.load_driver/2","doc":"Works essentially as [`load/2`](`load/2`), but loads the driver with other\noptions. All ports using the driver are killed with reason `driver_unloaded`\nwhen the driver is to be unloaded.\n\nThe number of loads and unloads by different [users](`m:erl_ddll#users`)\ninfluences the loading and unloading of a driver file. The port killing\ntherefore only occurs when the _last_ [user](`m:erl_ddll#users`) unloads the\ndriver, or when the last process having loaded the driver exits.\n\nThis interface (or at least the name of the functions) is kept for backward\ncompatibility. Using `try_load/3` with `{driver_options,[kill_ports]}` in the\noption list gives the same effect regarding the port killing.\n\nThe function throws a `badarg` exception if the parameters are not specified as\ndescribed here.","ref":"erl_ddll.html#load_driver/2"},{"type":"function","title":"erl_ddll.loaded_drivers/0","doc":"Returns a list of all the available drivers, both (statically) linked-in and\ndynamically loaded ones.\n\nThe driver names are returned as a list of strings rather than a list of atoms\nfor historical reasons.\n\nFor more information about drivers, see [`info`](`info/0`).","ref":"erl_ddll.html#loaded_drivers/0"},{"type":"function","title":"erl_ddll.monitor/2","doc":"Creates a driver monitor and works in many ways as `erlang:monitor/2` in ERTS,\ndoes for processes. When a driver changes state, the monitor results in a\nmonitor message that is sent to the calling process. `MonitorRef` returned by\nthis function is included in the message sent.\n\nAs with process monitors, each driver monitor set only generates _one single\nmessage_. The monitor is \"destroyed\" after the message is sent, so it is then\nnot needed to call `demonitor/1`.\n\n`MonitorRef` can also be used in subsequent calls to `demonitor/1` to remove a\nmonitor.\n\nThe function accepts the following parameters:\n\n- **`Tag`** - The monitor tag is always `driver`, as this function can only be\n used to create driver monitors. In the future, driver monitors will be\n integrated with process monitors, why this parameter has to be specified for\n consistence.\n\n- **`Item`** - Parameter `Item` specifies which driver to monitor (the driver\n name) and which state change to monitor. The parameter is a tuple of arity two\n whose first element is the driver name and second element is one of the\n following:\n\n - **`loaded`** - Notifies when the driver is reloaded (or loaded if loading is\n underway). It only makes sense to monitor drivers that are in the process of\n being loaded or reloaded. A future driver name for loading cannot be\n monitored. That only results in a `DOWN` message sent immediately.\n Monitoring for loading is therefore most useful when triggered by function\n `try_load/3`, where the monitor is created _because_ the driver is in such a\n pending state.\n\n Setting a driver monitor for `loading` eventually leads to one of the\n following messages being sent:\n\n - **`{'UP', reference(), driver, Name, loaded}`** - This message is sent\n either immediately if the driver is already loaded and no reloading is\n pending, or when reloading is executed if reloading is pending.\n\n The [user](`m:erl_ddll#users`) is expected to know if reloading is\n demanded before creating a monitor for loading.\n\n - **`{'UP', reference(), driver, Name, permanent}`** - This message is sent\n if reloading was expected, but the (old) driver made itself permanent\n before reloading. It is also sent if the driver was permanent or\n statically linked-in when trying to create the monitor.\n\n - **`{'DOWN', reference(), driver, Name, load_cancelled}`** - This message\n arrives if reloading was underway, but the requesting\n [user](`m:erl_ddll#users`) cancelled it by dying or calling `try_unload/2`\n (or [`unload/1`](`unload/1`)/[`unload_driver/1`](`unload_driver/1`)) again\n before it was reloaded.\n\n - **`{'DOWN', reference(), driver, Name, {load_failure, Failure}}`** - This\n message arrives if reloading was underway but the loading for some reason\n failed. The `Failure` term is one of the errors that can be returned from\n `try_load/3`. The error term can be passed to `format_error/1` for\n translation into human readable form. Notice that the translation must be\n done in the same running Erlang virtual machine as the error was detected\n in.\n\n - **`unloaded`** - Monitors when a driver gets unloaded. If one monitors a\n driver that is not present in the system, one immediately gets notified that\n the driver got unloaded. There is no guarantee that the driver was ever\n loaded.\n\n A driver monitor for unload eventually results in one of the following\n messages being sent:\n\n - **`{'DOWN', reference(), driver, Name, unloaded}`** - The monitored driver\n instance is now unloaded. As the unload can be a result of a\n [`reload/2`](`reload/2`) request, the driver can once again have been\n loaded when this message arrives.\n\n - **`{'UP', reference(), driver, Name, unload_cancelled}`** - This message\n is sent if unloading was expected, but while the driver was waiting for\n all ports to get closed, a new [user](`m:erl_ddll#users`) of the driver\n appeared, and the unloading was cancelled.\n\n This message appears if `{ok, pending_driver}` was returned from\n `try_unload/2` for the last [user](`m:erl_ddll#users`) of the driver, and\n then `{ok, already_loaded}` is returned from a call to `try_load/3`.\n\n If one _really_ wants to monitor when the driver gets unloaded, this\n message distorts the picture, because no unloading was done. Option\n `unloaded_only` creates a monitor similar to an `unloaded` monitor, but\n never results in this message.\n\n - **`{'UP', reference(), driver, Name, permanent}`** - This message is sent\n if unloading was expected, but the driver made itself permanent before\n unloading. It is also sent if trying to monitor a permanent or statically\n linked-in driver.\n\n - **`unloaded_only`** - A monitor created as `unloaded_only` behaves exactly\n as one created as `unloaded` except that the\n `{'UP', reference(), driver, Name, unload_cancelled}` message is never sent,\n but the monitor instead persists until the driver _really_ gets unloaded.\n\nThe function throws a `badarg` exception if the parameters are not specified as\ndescribed here.","ref":"erl_ddll.html#monitor/2"},{"type":"function","title":"erl_ddll.reload/2","doc":"Reloads the driver named `Name` from a possibly different `Path` than previously\nused. This function is used in the code change\n[`scenario`](`m:erl_ddll#scenarios`) described in the introduction.\n\nIf there are other [users](`m:erl_ddll#users`) of this driver, the function\nreturns `{error, pending_process}`, but if there are no other users, the\nfunction call hangs until all open ports are closed.\n\n> #### Note {: .info }\n>\n> Avoid mixing multiple [users](`m:erl_ddll#users`) with driver reload requests.\n\nTo avoid hanging on open ports, use function `try_load/3` instead.\n\nThe `Name` and `Path` parameters have exactly the same meaning as when calling\nthe plain function `load/2`.\n\nOn success, the function returns `ok`. On failure, the function returns an\nopaque error, except the `pending_process` error described earlier. The opaque\nerrors are to be translated into human readable form by function\n`format_error/1`.\n\nFor more control over the error handling, use the `try_load/3` interface\ninstead.\n\nThe function throws a `badarg` exception if the parameters are not specified as\ndescribed here.","ref":"erl_ddll.html#reload/2"},{"type":"function","title":"erl_ddll.reload_driver/2","doc":"Works exactly as `reload/2`, but for drivers loaded with the `load_driver/2`\ninterface.\n\nAs this interface implies that ports are killed when the last user disappears,\nthe function does not hang waiting for ports to get closed.\n\nFor more details, see [`scenarios`](`m:erl_ddll#scenarios`) in this module\ndescription and the function description for `reload/2`.\n\nThe function throws a `badarg` exception if the parameters are not specified as\ndescribed here.","ref":"erl_ddll.html#reload_driver/2"},{"type":"function","title":"erl_ddll.try_load/3","doc":"Provides more control than the [`load/2`](`load/2`)/[`reload/2`](`reload/2`) and\n[`load_driver/2`](`load_driver/2`)/[`reload_driver/2`](`reload_driver/2`)\ninterfaces. It never waits for completion of other operations related to the\ndriver, but immediately returns the status of the driver as one of the\nfollowing:\n\n- **`{ok, loaded}`** - The driver was loaded and is immediately usable.\n\n- **`{ok, already_loaded}`** - The driver was already loaded by another process\n or is in use by a living port, or both. The load by you is registered and a\n corresponding `try_unload` is expected sometime in the future.\n\n- **`{ok, pending_driver}`or `{ok, pending_driver, reference()}`** - The load\n request is registered, but the loading is delayed because an earlier instance\n of the driver is still waiting to get unloaded (open ports use it). Still,\n unload is expected when you are done with the driver. This return value\n _mostly_ occurs when options `{reload,pending_driver}` or `{reload,pending}`\n are used, but _can_ occur when another [user](`m:erl_ddll#users`) is unloading\n a driver in parallel and driver option `kill_ports` is set. In other words,\n this return value always needs to be handled.\n\n- **`{ok, pending_process}`or `{ok, pending_process, reference()}`** - The load\n request is registered, but the loading is delayed because an earlier instance\n of the driver is still waiting to get unloaded by another\n [user](`m:erl_ddll#users`) (not only by a port, in which case\n `{ok,pending_driver}` would have been returned). Still, unload is expected\n when you are done with the driver. This return value _only_ occurs when option\n `{reload,pending}` is used.\n\nWhen the function returns `{ok, pending_driver}` or `{ok, pending_process}`, one\ncan get information about when the driver is _actually_ loaded by using option\n`{monitor, MonitorOption}`.\n\nWhen monitoring is requested, and a corresponding `{ok, pending_driver}` or\n`{ok, pending_process}` would be returned, the function instead returns a tuple\n`{ok, PendingStatus, reference()}` and the process then gets a monitor message\nlater, when the driver gets loaded. The monitor message to expect is described\nin the function description of `monitor/2`.\n\n> #### Note {: .info }\n>\n> In case of loading, monitoring can _not_ only get triggered by using option\n> `{reload, ReloadOption}`, but also in special cases where the load error is\n> transient. Thus, `{monitor, pending_driver}` is to be used under basically\n> _all_ real world circumstances.\n\nThe function accepts the following parameters:\n\n- **`Path`** - The file system path to the directory where the driver object\n file is located. The filename of the object file (minus extension) must\n correspond to the driver name (used in parameter `Name`) and the driver must\n identify itself with the same name. `Path` can be provided as an _iolist()_,\n meaning it can be a list of other `t:iolist/0`s, characters (8-bit integers),\n or binaries, all to be flattened into a sequence of characters.\n\n The (possibly flattened) `Path` parameter must be consistent throughout the\n system. A driver is to, by all [users](`m:erl_ddll#users`), be loaded using\n the same _literal_ `Path`. The exception is when _reloading_ is requested, in\n which case `Path` can be specified differently. Notice that all\n [users](`m:erl_ddll#users`) trying to load the driver later need to use the\n _new_ `Path` if `Path` is changed using a `reload` option. This is yet another\n reason to have _only one loader_ of a driver one wants to upgrade in a running\n system.\n\n- **`Name`** - This parameter is the name of the driver to be used in subsequent\n calls to function [`erlang:open_port`](`erlang:open_port/2`) in ERTS. The name\n can be specified as an `t:iolist/0` or an `t:atom/0`. The name specified when\n loading is used to find the object file (with the help of `Path` and the\n system-implied extension suffix, that is, `.so`). The name by which the driver\n identifies itself must also be consistent with this `Name` parameter, much as\n the module name of a Beam file much corresponds to its filename.\n\n- **`OptionList`** - Some options can be specified to control the loading\n operation. The options are specified as a list of two-tuples. The tuples have\n the following values and meanings:\n\n - **`{driver_options, DriverOptionList}`** - This is to provide options that\n changes its general behavior and \"sticks\" to the driver throughout its\n lifespan.\n\n The driver options for a specified driver name need always to be consistent,\n _even when the driver is reloaded_, meaning that they are as much a part of\n the driver as the name.\n\n The only allowed driver option is `kill_ports`, which means that all ports\n opened to the driver are killed with exit reason `driver_unloaded` when no\n process any longer has the driver loaded. This situation arises either when\n the last [user](`m:erl_ddll#users`) calls `try_unload/2`, or when the last\n process having loaded the driver exits.\n\n - **`{monitor, MonitorOption}`** - A `MonitorOption` tells\n [`try_load/3`](`try_load/3`) to trigger a driver monitor under certain\n conditions. When the monitor is triggered, the function returns a\n three-tuple `{ok, PendingStatus, reference()}`, where `t:reference/0` is the\n monitor reference for the driver monitor.\n\n Only one `MonitorOption` can be specified. It is one of the following:\n\n - The atom `pending`, which means that a monitor is to be created whenever a\n load operation is delayed,\n - The atom `pending_driver`, in which a monitor is created whenever the\n operation is delayed because of open ports to an otherwise unused driver.\n\n Option `pending_driver` is of little use, but is present for completeness,\n as it is well defined which reload options that can give rise to which\n delays. However, it can be a good idea to use the same `MonitorOption` as\n the `ReloadOption`, if present.\n\n If reloading is not requested, it can still be useful to specify option\n `monitor`, as forced unloads (driver option `kill_ports` or option\n `kill_ports` to `try_unload/2`) trigger a transient state where driver\n loading cannot be performed until all closing ports are closed. Thus, as\n `try_unload` can, in almost all situations, return `{ok, pending_driver}`,\n always specify at least `{monitor, pending_driver}` in production code (see\n the monitor discussion earlier).\n\n - **`{reload, ReloadOption}`** - This option is used to _reload_ a driver from\n disk, most often in a code upgrade scenario. Having a `reload` option also\n implies that parameter `Path` does _not_ need to be consistent with earlier\n loads of the driver.\n\n To reload a driver, the process must have loaded the driver before, that is,\n there must be an active [user](`m:erl_ddll#users`) of the driver in the\n process.\n\n The `reload` option can be either of the following:\n\n - **`pending`** - With the atom `pending`, reloading is requested for any\n driver and is effectuated when _all_ ports opened to the driver are\n closed. The driver replacement in this case takes place regardless if\n there are still pending [users](`m:erl_ddll#users`) having the driver\n loaded.\n\n The option also triggers port-killing (if driver option `kill_ports` is\n used) although there are pending users, making it usable for forced driver\n replacement, but laying much responsibility on the driver\n [users](`m:erl_ddll#users`). The pending option is seldom used as one does\n not want other [users](`m:erl_ddll#users`) to have loaded the driver when\n code change is underway.\n\n - **`pending_driver`** - This option is more useful. Here, reloading is\n queued if the driver is _not_ loaded by any other\n [users](`m:erl_ddll#users`), but the driver has opened ports, in which\n case `{ok, pending_driver}` is returned (a `monitor` option is\n recommended).\n\n If the driver is unloaded (not present in the system), error code\n `not_loaded` is returned. Option `reload` is intended for when the user has\n already loaded the driver in advance.\n\nThe function can return numerous errors, some can only be returned given a\ncertain combination of options.\n\nSome errors are opaque and can only be interpreted by passing them to function\n`format_error/1`, but some can be interpreted directly:\n\n- **`{error,linked_in_driver}`** - The driver with the specified name is an\n Erlang statically linked-in driver, which cannot be manipulated with this API.\n\n- **`{error,inconsistent}`** - The driver is already loaded with other\n `DriverOptionList` or a different _literal_ `Path` argument.\n\n This can occur even if a `reload` option is specified, if `DriverOptionList`\n differs from the current.\n\n- **`{error, permanent}`** - The driver has requested itself to be permanent,\n making it behave like an Erlang linked-in driver and can no longer be\n manipulated with this API.\n\n- **`{error, pending_process}`** - The driver is loaded by other\n [users](`m:erl_ddll#users`) when option `{reload, pending_driver}` was\n specified.\n\n- **`{error, pending_reload}`** - Driver reload is already requested by another\n [user](`m:erl_ddll#users`) when option `{reload, ReloadOption}` was specified.\n\n- **`{error, not_loaded_by_this_process}`** - Appears when option `reload` is\n specified. The driver `Name` is present in the system, but there is no\n [user](`m:erl_ddll#users`) of it in this process.\n\n- **`{error, not_loaded}`** - Appears when option `reload` is specified. The\n driver `Name` is not in the system. Only drivers loaded by this process can be\n reloaded.\n\nAll other error codes are to be translated by function `format_error/1`. Notice\nthat calls to `format_error` are to be performed from the same running instance\nof the Erlang virtual machine as the error is detected in, because of\nsystem-dependent behavior concerning error values.\n\nIf the arguments or options are malformed, the function throws a `badarg`\nexception.","ref":"erl_ddll.html#try_load/3"},{"type":"function","title":"erl_ddll.try_unload/2","doc":"This is the low-level function to unload (or decrement reference counts of) a\ndriver. It can be used to force port killing, in much the same way as the driver\noption `kill_ports` implicitly does. Also, it can trigger a monitor either\nbecause other [users](`m:erl_ddll#users`) still have the driver loaded or\nbecause open ports use the driver.\n\nUnloading can be described as the process of telling the emulator that this\nparticular part of the code in this particular process (that is, this\n[user](`m:erl_ddll#users`)) no longer needs the driver. That can, if there are\nno other users, trigger unloading of the driver, in which case the driver name\ndisappears from the system and (if possible) the memory occupied by the driver\nexecutable code is reclaimed.\n\nIf the driver has option `kill_ports` set, or if `kill_ports` is specified as an\noption to this function, all pending ports using this driver are killed when\nunloading is done by the last [user](`m:erl_ddll#users`). If no port-killing is\ninvolved and there are open ports, the unloading is delayed until no more open\nports use the driver. If, in this case, another [user](`m:erl_ddll#users`) (or\neven this user) loads the driver again before the driver is unloaded, the\nunloading never takes place.\n\nTo allow the [user](`m:erl_ddll#users`) to _request unloading_ to wait for\n_actual unloading_, `monitor` triggers can be specified in much the same way as\nwhen loading. However, as [users](`m:erl_ddll#users`) of this function seldom\nare interested in more than decrementing the reference counts, monitoring is\nseldom needed.\n\n> #### Note {: .info }\n>\n> If option `kill_ports` is used, monitor trigging is crucial, as the ports are\n> not guaranteed to be killed until the driver is unloaded. Thus, a monitor must\n> be triggered for at least the `pending_driver` case.\n\nThe possible monitor messages to expect are the same as when using option\n`unloaded` to function `monitor/2`.\n\nThe function returns one of the following statuses upon success:\n\n- **`{ok, unloaded}`** - The driver was immediately unloaded, meaning that the\n driver name is now free to use by other drivers and, if the underlying OS\n permits it, the memory occupied by the driver object code is now reclaimed.\n\n The driver can only be unloaded when there are no open ports using it and no\n more [users](`m:erl_ddll#users`) require it to be loaded.\n\n- **`{ok, pending_driver}`or `{ok, pending_driver, reference()}`** - Indicates\n that this call removed the last [user](`m:erl_ddll#users`) from the driver,\n but there are still open ports using it. When all ports are closed and no new\n [users](`m:erl_ddll#users`) have arrived, the driver is reloaded and the name\n and memory reclaimed.\n\n This return value is valid even if option `kill_ports` was used, as killing\n ports can be a process that does not complete immediately. However, the\n condition is in that case transient. Monitors are always useful to detect when\n the driver is really unloaded.\n\n- **`{ok, pending_process}`or `{ok, pending_process, reference()}`** - The\n unload request is registered, but other [users](`m:erl_ddll#users`) still hold\n the driver. Notice that the term `pending_process` can refer to the running\n process; there can be more than one [user](`m:erl_ddll#users`) in the same\n process.\n\n This is a normal, healthy, return value if the call was just placed to inform\n the emulator that you have no further use of the driver. It is the most common\n return value in the most common [`scenario`](`m:erl_ddll#scenarios`) described\n in the introduction.\n\nThe function accepts the following parameters:\n\n- **`Name`** - `Name` is the name of the driver to be unloaded. The name can be\n specified as an `t:iolist/0` or as an `t:atom/0`.\n\n- **`OptionList`** - Argument `OptionList` can be used to specify certain\n behavior regarding ports and triggering monitors under certain conditions:\n\n - **`kill_ports`** - Forces killing of all ports opened using this driver,\n with exit reason `driver_unloaded`, if you are the _last_\n [user](`m:erl_ddll#users`) of the driver.\n\n If other [users](`m:erl_ddll#users`) have the driver loaded, this option has\n no effect.\n\n To get the consistent behavior of killing ports when the last\n [user](`m:erl_ddll#users`) unloads, use driver option `kill_ports` when\n loading the driver instead.\n\n - **`{monitor, MonitorOption}`** - Creates a driver monitor if the condition\n specified in `MonitorOption` is true. The valid options are:\n\n - **`pending_driver`** - Creates a driver monitor if the return value is to\n be `{ok, pending_driver}`.\n\n - **`pending`** - Creates a monitor if the return value is\n `{ok, pending_driver}` or `{ok, pending_process}`.\n\n The `pending_driver` `MonitorOption` is by far the most useful. It must be\n used to ensure that the driver really is unloaded and the ports closed\n whenever option `kill_ports` is used, or the driver can have been loaded\n with driver option `kill_ports`.\n\n Using the monitor triggers in the call to `try_unload` ensures that the\n monitor is added before the unloading is executed, meaning that the monitor\n is always properly triggered, which is not the case if\n [`monitor/2`](`monitor/2`) is called separately.\n\nThe function can return the following error conditions, all well specified (no\nopaque values):\n\n- **`{error, linked_in_driver}`** - You were trying to unload an Erlang\n statically linked-in driver, which cannot be manipulated with this interface\n (and cannot be unloaded at all).\n\n- **`{error, not_loaded}`** - The driver `Name` is not present in the system.\n\n- **`{error, not_loaded_by_this_process}`** - The driver `Name` is present in\n the system, but there is no [user](`m:erl_ddll#users`) of it in this process.\n\n As a special case, drivers can be unloaded from processes that have done no\n corresponding call to [`try_load/3`](`try_load/3`) if, and only if, there are\n _no users of the driver at all_, which can occur if the process containing the\n last user dies.\n\n- **`{error, permanent}`** - The driver has made itself permanent, in which case\n it can no longer be manipulated by this interface (much like a statically\n linked-in driver).\n\nThe function throws a `badarg` exception if the parameters are not specified as\ndescribed here.","ref":"erl_ddll.html#try_unload/2"},{"type":"function","title":"erl_ddll.unload/1","doc":"Unloads, or at least dereferences the driver named `Name`. If the caller is the\nlast [user](`m:erl_ddll#users`) of the driver, and no more open ports use the\ndriver, the driver gets unloaded. Otherwise, unloading is delayed until all\nports are closed and no [users](`m:erl_ddll#users`) remain.\n\nIf there are other [users](`m:erl_ddll#users`) of the driver, the reference\ncounts of the driver is merely decreased, so that the caller is no longer\nconsidered a [user](`m:erl_ddll#users`) of the driver. For use scenarios, see\nthe [`description`](`m:erl_ddll#scenarios`) in the beginning of this module.\n\nThe `ErrorDesc` returned is an opaque value to be passed further on to function\n`format_error/1`. For more control over the operation, use the `try_unload/2`\ninterface.\n\nThe function throws a `badarg` exception if the parameters are not specified as\ndescribed here.","ref":"erl_ddll.html#unload/1"},{"type":"function","title":"erl_ddll.unload_driver/1","doc":"Unloads, or at least dereferences the driver named `Name`. If the caller is the\nlast [user](`m:erl_ddll#users`) of the driver, all remaining open ports using\nthe driver are killed with reason `driver_unloaded` and the driver eventually\ngets unloaded.\n\nIf there are other [users](`m:erl_ddll#users`) of the driver, the reference\ncounts of the driver is merely decreased, so that the caller is no longer\nconsidered a [user](`m:erl_ddll#users`). For use scenarios, see the\n[`description`](`m:erl_ddll#scenarios`) in the beginning of this module.\n\nThe `ErrorDesc` returned is an opaque value to be passed further on to function\n`format_error/1`. For more control over the operation, use the `try_unload/2`\ninterface.\n\nThe function throws a `badarg` exception if the parameters are not specified as\ndescribed here.","ref":"erl_ddll.html#unload_driver/1"},{"type":"type","title":"erl_ddll.driver/0","doc":"","ref":"erl_ddll.html#t:driver/0"},{"type":"type","title":"erl_ddll.path/0","doc":"","ref":"erl_ddll.html#t:path/0"},{"type":"module","title":"error_handler","doc":"Default system error handler.\n\nThis module defines what happens when certain types of errors occur.\n\nYou can change the error handler of a process by calling\n[`erlang:process_flag(error_handler, NewErrorHandler)`](`erlang#process_flag_error_handler`).","ref":"error_handler.html"},{"type":"module","title":"Notes - error_handler","doc":"The code in `error_handler` is complex. Do not change it without fully\nunderstanding the interaction between the error handler, the `init` process of\nthe code server, and the I/O mechanism of the code.\n\nCode changes that seem small can cause a deadlock, as unforeseen consequences\ncan occur. The use of `input` is dangerous in this type of code.","ref":"error_handler.html#module-notes"},{"type":"function","title":"error_handler.raise_undef_exception/3","doc":"Raises an `undef` exception with a stacktrace, indicating that\n`Module:Function/N` is undefined.","ref":"error_handler.html#raise_undef_exception/3"},{"type":"function","title":"error_handler.undefined_function/3","doc":"This function is called by the runtime system if a call is made to\n`Module:Function(Arg1,.., ArgN)` and `Module:Function/N` is undefined. Notice\nthat this function is evaluated inside the process making the original call.\n\nThis function first attempts to autoload `Module`. If that is not possible, an\n`undef` exception is raised.\n\nIf it is possible to load `Module` and function `Function/N` is exported, it is\ncalled.\n\nOtherwise, if function `'$handle_undefined_function'/2` is exported, it is\ncalled as `'$handle_undefined_function'(`Function, Args).\n\n> #### Warning {: .warning }\n>\n> Defining `'$handle_undefined_function'/2` in ordinary application code is\n> highly discouraged. It is very easy to make subtle errors that can take a long\n> time to debug. Furthermore, none of the tools for static code analysis (such\n> as Dialyzer and Xref) supports the use of `'$handle_undefined_function'/2` and\n> no such support will be added. Only use this function after having carefully\n> considered other, less dangerous, solutions. One example of potential\n> legitimate use is creating stubs for other sub-systems during testing and\n> debugging.\n\nOtherwise an `undef` exception is raised.","ref":"error_handler.html#undefined_function/3"},{"type":"function","title":"error_handler.undefined_lambda/3","doc":"This function is evaluated if a call is made to `Fun(Arg1,.., ArgN)` when the\nmodule defining the fun is not loaded. The function is evaluated inside the\nprocess making the original call.\n\nIf `Module` is interpreted, the interpreter is invoked and the return value of\nthe interpreted `Fun(Arg1,.., ArgN)` call is returned.\n\nOtherwise, it returns, if possible, the value of [`apply(Fun, Args)`](`apply/2`)\nafter an attempt is made to autoload `Module`. If this is not possible, the call\nfails with exit reason `undef`.","ref":"error_handler.html#undefined_lambda/3"},{"type":"module","title":"heart","doc":"Heartbeat monitoring of an Erlang runtime system.\n\nThis modules contains the interface to the `heart` process. `heart` sends\nperiodic heartbeats to an external port program, which is also named `heart`.\nThe purpose of the `heart` port program is to check that the Erlang runtime\nsystem it is supervising is still running. If the port program has not received\nany heartbeats within `HEART_BEAT_TIMEOUT` seconds (defaults to 60 seconds), the\nsystem can be rebooted.\n\nAn Erlang runtime system to be monitored by a heart program is to be started\nwith command-line flag `-heart` (see also [`erl(1)`](`e:erts:erl_cmd.md`)). The\n`heart` process is then started automatically:\n\n```text\n% erl -heart ...\n```\n\nIf the system is to be rebooted because of missing heartbeats, or a terminated\nErlang runtime system, environment variable `HEART_COMMAND` must be set before\nthe system is started. If this variable is not set, a warning text is printed\nbut the system does not reboot.\n\nTo reboot on Windows, `HEART_COMMAND` can be set to `heart -shutdown` (included\nin the Erlang delivery) or to any other suitable program that can activate a\nreboot.\n\nThe environment variable `HEART_BEAT_TIMEOUT` can be used to configure the heart\ntime-outs; it can be set in the operating system shell before Erlang is started\nor be specified at the command line:\n\n```text\n% erl -heart -env HEART_BEAT_TIMEOUT 30 ...\n```\n\nThe value (in seconds) must be in the range `10 < X <= 65535`.\n\nWhen running on OSs lacking support for monotonic time, `heart` is susceptible\nto system clock adjustments of more than `HEART_BEAT_TIMEOUT` seconds. When this\nhappens, `heart` times out and tries to reboot the system. This can occur, for\nexample, if the system clock is adjusted automatically by use of the Network\nTime Protocol (NTP).\n\nIf a crash occurs, an `erl_crash.dump` is _not_ written unless environment\nvariable `ERL_CRASH_DUMP_SECONDS` is set:\n\n```text\n% erl -heart -env ERL_CRASH_DUMP_SECONDS 10 ...\n```\n\nIf a regular core dump is wanted, let `heart` know by setting the kill signal to\nabort using environment variable `HEART_KILL_SIGNAL=SIGABRT`. If unset, or not\nset to `SIGABRT`, the default behavior is a kill signal using `SIGKILL`:\n\n```text\n% erl -heart -env HEART_KILL_SIGNAL SIGABRT ...\n```\n\nIf heart should _not_ kill the Erlang runtime system, this can be indicated\nusing the environment variable `HEART_NO_KILL=TRUE`. This can be useful if the\ncommand executed by heart takes care of this, for example as part of a specific\ncleanup sequence. If unset, or not set to `TRUE`, the default behaviour will be\nto kill as described above.\n\n```text\n% erl -heart -env HEART_NO_KILL 1 ...\n```\n\nFurthermore, `ERL_CRASH_DUMP_SECONDS` has the following behavior on `heart`:\n\n- **`ERL_CRASH_DUMP_SECONDS=0`** - Suppresses the writing of a crash dump file\n entirely, thus rebooting the runtime system immediately. This is the same as\n not setting the environment variable.\n\n- **`ERL_CRASH_DUMP_SECONDS=-1`** - Setting the environment variable to a\n negative value does not reboot the runtime system until the crash dump file is\n completely written.\n\n- **`ERL_CRASH_DUMP_SECONDS=S`** - `heart` waits for `S` seconds to let the\n crash dump file be written. After `S` seconds, `heart` reboots the runtime\n system, whether the crash dump file is written or not.\n\nIn the following descriptions, all functions fail with reason `badarg` if\n`heart` is not started.","ref":"heart.html"},{"type":"function","title":"heart.clear_callback/0","doc":"Removes the validation callback call before heartbeats.","ref":"heart.html#clear_callback/0"},{"type":"function","title":"heart.clear_cmd/0","doc":"Clears the temporary boot command. If the system terminates, the normal\n`HEART_COMMAND` is used to reboot.","ref":"heart.html#clear_cmd/0"},{"type":"function","title":"heart.get_callback/0","doc":"Get the validation callback. If the callback is cleared, `none` will be\nreturned.","ref":"heart.html#get_callback/0"},{"type":"function","title":"heart.get_cmd/0","doc":"Gets the temporary reboot command. If the command is cleared, the empty string\nis returned.","ref":"heart.html#get_cmd/0"},{"type":"function","title":"heart.get_options/0","doc":"Returns `{ok, Options}` where `Options` is a list of current options enabled for\nheart. If the callback is cleared, `none` will be returned.","ref":"heart.html#get_options/0"},{"type":"function","title":"heart.set_callback/2","doc":"This validation callback will be executed before any heartbeat is sent to the\nport program. For the validation to succeed it needs to return with the value\n`ok`.\n\nAn exception within the callback will be treated as a validation failure.\n\nThe callback will be removed if the system reboots.","ref":"heart.html#set_callback/2"},{"type":"function","title":"heart.set_cmd/1","doc":"Sets a temporary reboot command. This command is used if a `HEART_COMMAND` other\nthan the one specified with the environment variable is to be used to reboot the\nsystem. The new Erlang runtime system uses (if it misbehaves) environment\nvariable `HEART_COMMAND` to reboot.\n\nLimitations: Command string `Cmd` is sent to the `heart` program as an ISO\nLatin-1 or UTF-8 encoded binary, depending on the filename encoding mode of the\nemulator (see `file:native_name_encoding/0`). The size of the encoded binary\nmust be less than 2047 bytes.","ref":"heart.html#set_cmd/1"},{"type":"function","title":"heart.set_options/1","doc":"Valid options `set_options` are:\n\n- **`check_schedulers`** - If enabled, a signal will be sent to each scheduler\n to check its responsiveness. The system check occurs before any heartbeat sent\n to the port program. If any scheduler is not responsive enough the heart\n program will not receive its heartbeat and thus eventually terminate the node.\n\nReturns with the value `ok` if the options are valid.","ref":"heart.html#set_options/1"},{"type":"type","title":"heart.heart_option/0","doc":"","ref":"heart.html#t:heart_option/0"},{"type":"module","title":"os","doc":"Operating system-specific functions.\n\nThe functions in this module are operating system-specific. Careless use of\nthese functions results in programs that will only run on a specific platform.\nOn the other hand, with careful use, these functions can be of help in enabling\na program to run on most platforms.\n\n> #### Note {: .info }\n>\n> The functions in this module will raise a `badarg` exception if their\n> arguments contain invalid characters according to the description in the \"Data\n> Types\" section.","ref":"os.html"},{"type":"function","title":"os.cmd/1","doc":"","ref":"os.html#cmd/1"},{"type":"function","title":"os.cmd/2","doc":"Executes `Command` in a command shell of the target OS, captures the standard\noutput and standard error of the command, and returns this result as a string.\n\nThe command shell can be set using the\n[kernel configuration parameter](kernel_app.md#os_cmd_shell), by default the\nshell is detected upon system startup.\n\n_Examples:_\n\n```erlang\nLsOut = os:cmd(\"ls\"), % on unix platform\nDirOut = os:cmd(\"dir\"), % on Win32 platform\n```\n\nNotice that in some cases, standard output of a command when called from another\nprogram can differ, compared with the standard output of the command when called\ndirectly from an OS command shell.\n\nThe possible options are:\n\n- **`max_size`** - The maximum size of the data returned by the `os:cmd` call.\n This option is a safety feature that should be used when the command executed\n can return a very large, possibly infinite, result.\n\n ```erlang\n > os:cmd(\"cat /dev/zero\", #{ max_size => 20 }).\n [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]\n ```","ref":"os.html#cmd/2"},{"type":"function","title":"os.env/0","doc":"Returns a list of all environment variables. Each environment variable is\nexpressed as a tuple `{VarName,Value}`, where `VarName` is the name of the\nvariable and `Value` its value.\n\nIf Unicode filename encoding is in effect (see the\n[`erl` manual page](`e:erts:erl_cmd.md#file_name_encoding`)), the strings can\ncontain characters with codepoints > 255.","ref":"os.html#env/0"},{"type":"function","title":"os.find_executable/1","doc":"Equivalent to [`find_executable(Name, Path)`](`find_executable/2`) where\n`Path` is the current execution path (that is, the environment variable `PATH`\non Unix and Windows).","ref":"os.html#find_executable/1"},{"type":"function","title":"os.find_executable/2","doc":"Look up an executable program, with the specified name and a search path, in the\nsame way as the underlying OS.\n\n`Path` is to conform to the syntax of execution paths on the OS.\nReturns the absolute filename of the executable program `Name`, or `false` if\nthe program is not found.","ref":"os.html#find_executable/2"},{"type":"function","title":"os.getenv/0","doc":"Returns a list of all environment variables. Each environment variable is\nexpressed as a single string on the format `\"VarName=Value\"`, where `VarName` is\nthe name of the variable and `Value` its value.\n\nIf Unicode filename encoding is in effect (see the\n[`erl` manual page](`e:erts:erl_cmd.md#file_name_encoding`)), the strings can\ncontain characters with codepoints > 255.\n\nConsider using `env/0` for a nicer 2-tuple format.","ref":"os.html#getenv/0"},{"type":"function","title":"os.getenv/1","doc":"Returns the `Value` of the environment variable `VarName`, or `false` if the\nenvironment variable is undefined.\n\nIf Unicode filename encoding is in effect (see the\n[`erl` manual page](`e:erts:erl_cmd.md#file_name_encoding`)), the strings\n`VarName` and `Value` can contain characters with codepoints > 255.","ref":"os.html#getenv/1"},{"type":"function","title":"os.getenv/2","doc":"Returns the `Value` of the environment variable `VarName`, or `DefaultValue` if\nthe environment variable is undefined.\n\nIf Unicode filename encoding is in effect (see the\n[`erl` manual page](`e:erts:erl_cmd.md#file_name_encoding`)), the strings\n`VarName` and `Value` can contain characters with codepoints > 255.","ref":"os.html#getenv/2"},{"type":"function","title":"os.getpid/0","doc":"Returns the process identifier of the current Erlang emulator in the format most\ncommonly used by the OS environment.\n\nReturns `Value` as a string containing the (usually) numerical identifier for a process.\n\n- On Unix, this is typically the return value of the `getpid/0` system call.\n- On Windows, the process id as returned by the `GetCurrentProcessId()` system call\n is used.","ref":"os.html#getpid/0"},{"type":"function","title":"os.perf_counter/0","doc":"Returns the current performance counter value in `perf_counter`\n[time unit](`t:erlang:time_unit/0`). This is a highly optimized call that\nmight not be traceable.","ref":"os.html#perf_counter/0"},{"type":"function","title":"os.perf_counter/1","doc":"Returns a performance counter that can be used as a very fast and high\nresolution timestamp.\n\nThis counter is read directly from the hardware or operating system with the\nsame guarantees. This means that two consecutive calls to the function are not\nguaranteed to be monotonic, though it most likely will be. The performance\ncounter will be converted to the resolution passed as an argument.\n\n```erlang\n1> T1 = os:perf_counter(1000),receive after 10000 -> ok end,T2 = os:perf_counter(1000).\n176525861\n2> T2 - T1.\n10004\n```","ref":"os.html#perf_counter/1"},{"type":"function","title":"os.putenv/2","doc":"Sets a new `Value` for environment variable `VarName`.\n\nIf Unicode filename encoding is in effect (see the\n[`erl` manual page](`e:erts:erl_cmd.md#file_name_encoding`)), the strings\n`VarName` and `Value` can contain characters with codepoints > 255.\n\nOn Unix platforms, the environment is set using UTF-8 encoding if Unicode\nfilename translation is in effect. On Windows, the environment is set using wide\ncharacter interfaces.","ref":"os.html#putenv/2"},{"type":"function","title":"os.set_signal/2","doc":"Enables or disables OS signals.\n\nEach signal my be set to one of the following options:\n\n- **`ignore`** - This signal will be ignored.\n\n- **`default`** - This signal will use the default signal handler for the\n operating system.\n\n- **`handle`** - This signal will notify\n [`erl_signal_server`](kernel_app.md#erl_signal_server) when it is received by\n the Erlang runtime system.","ref":"os.html#set_signal/2"},{"type":"function","title":"os.system_time/0","doc":"Returns the current [OS system time](`e:erts:time_correction.md#os-system-time`)\nin `native` [time unit](`t:erlang:time_unit/0`).\n\n> #### Note {: .info }\n>\n> This time is _not_ a monotonically increasing time.","ref":"os.html#system_time/0"},{"type":"function","title":"os.system_time/1","doc":"Returns the current [OS system time](`e:erts:time_correction.md#os-system-time`)\nconverted into the `Unit` passed as argument.\n\nCalling `os:system_time(Unit)` is equivalent to\n[`erlang:convert_time_unit`](`erlang:convert_time_unit/3`)([`os:system_time()`](`system_time/0`)`, native, Unit)`.\n\n> #### Note {: .info }\n>\n> This time is _not_ a monotonically increasing time.","ref":"os.html#system_time/1"},{"type":"function","title":"os.timestamp/0","doc":"Returns the current [OS system time](`e:erts:time_correction.md#os-system-time`)\nin the same format as `erlang:timestamp/0`.\n\nThe tuple can be used together with function `calendar:now_to_universal_time/1`\nor `calendar:now_to_local_time/1` to get calendar time. Using the calendar time,\ntogether with the `MicroSecs` part of the return tuple from this function,\nallows you to log time stamps in high resolution and consistent with the time in\n the rest of the OS.\n\nExample of code formatting a string in format \"DD Mon YYYY HH:MM:SS.mmmmmm\",\nwhere DD is the day of month, Mon is the textual month name, YYYY is the year,\nHH:MM:SS is the time, and mmmmmm is the microseconds in six positions:\n\n```erlang\n-module(print_time).\n-export([format_utc_timestamp/0]).\nformat_utc_timestamp() ->\n TS = {_,_,Micro} = os:timestamp(),\n {{Year,Month,Day},{Hour,Minute,Second}} =\ncalendar:now_to_universal_time(TS),\n Mstr = element(Month,{\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\n \"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"}),\n io_lib:format(\"~2w ~s ~4w ~2w:~2..0w:~2..0w.~6..0w\",\n [Day,Mstr,Year,Hour,Minute,Second,Micro]).\n```\n\nThis module can be used as follows:\n\n```erlang\n1> io:format(\"~s~n\",[print_time:format_utc_timestamp()]).\n29 Apr 2009 9:55:30.051711\n```\n\nOS system time can also be retrieved by `system_time/0` and `system_time/1`.","ref":"os.html#timestamp/0"},{"type":"function","title":"os.type/0","doc":"Returns the `Osfamily` and, in some cases, the `Osname` of the current OS.\n\nOn Unix, `Osname` has the same value as `uname -s` returns, but in lower case.\nFor example, on Solaris 1 and 2, it is `sunos`.\n\nOn Windows, `Osname` is `nt`.\n\n> #### Note {: .info }\n>\n> Think twice before using this function. Use module `m:filename` if you want to\n> inspect or build filenames in a portable way. Avoid matching on atom `Osname`.","ref":"os.html#type/0"},{"type":"function","title":"os.unsetenv/1","doc":"Deletes the environment variable `VarName`.\n\nIf Unicode filename encoding is in effect (see the\n[`erl` manual page](`e:erts:erl_cmd.md#file_name_encoding`)), the string\n`VarName` can contain characters with codepoints > 255.","ref":"os.html#unsetenv/1"},{"type":"function","title":"os.version/0","doc":"Returns the OS version. On most systems, this function returns a tuple, but a\nstring is returned instead if the system has versions that cannot be expressed\nas three numbers.\n\n> #### Note {: .info }\n>\n> Think twice before using this function. If you still need to use it, always\n> `call os:type()` first.","ref":"os.html#version/0"},{"type":"type","title":"os.env_var_name/0","doc":"A string containing valid characters on the specific OS for environment variable\nnames using [`file:native_name_encoding()`](`file:native_name_encoding/0`)\nencoding.\n\nNull characters (integer value zero) are not allowed. On Unix, `=`\ncharacters are not allowed. On Windows, a `=` character is only allowed as the\nvery first character in the string.","ref":"os.html#t:env_var_name/0"},{"type":"type","title":"os.env_var_name_value/0","doc":"Assuming that environment variables has been correctly set, a strings containing\nvalid characters on the specific OS for environment variable names and values\nusing [`file:native_name_encoding()`](`file:native_name_encoding/0`) encoding.\n\nThe first `=` characters appearing in the string separates environment variable\nname (on the left) from environment variable value (on the right).","ref":"os.html#t:env_var_name_value/0"},{"type":"type","title":"os.env_var_value/0","doc":"A string containing valid characters on the specific OS for environment variable\nvalues using [`file:native_name_encoding()`](`file:native_name_encoding/0`)\nencoding.\n\nNull characters (integer value zero) are not allowed.","ref":"os.html#t:env_var_value/0"},{"type":"type","title":"os.os_command/0","doc":"All characters needs to be valid characters on the specific OS using\n[`file:native_name_encoding()`](`file:native_name_encoding/0`) encoding. Null\ncharacters (integer value zero) are not allowed.","ref":"os.html#t:os_command/0"},{"type":"type","title":"os.os_command_opts/0","doc":"Options for [`os:cmd/2`](`cmd/2`).\n\n- **`max_size`** - The maximum size of the data returned by the `os:cmd/2` call.\n See the [`os:cmd/2`](`cmd/2`) documentation for more details.","ref":"os.html#t:os_command_opts/0"},{"type":"module","title":"auth","doc":"Erlang network authentication server.\n\nFor a description of the Magic Cookie system, refer\nto [Distributed Erlang](`e:system:distributed.md`) in the Erlang Reference\nManual.","ref":"auth.html"},{"type":"function","title":"auth.cookie/0","doc":"Use [`erlang:get_cookie()`](`erlang:get_cookie/0`) in ERTS instead.","ref":"auth.html#cookie/0"},{"type":"function","title":"auth.cookie/1","doc":"Use [`erlang:set_cookie(node(), Cookie)` in ERTS](`erlang:set_cookie/2`)\ninstead.","ref":"auth.html#cookie/1"},{"type":"function","title":"auth.is_auth/1","doc":"Returns `yes` if communication with `Node` is authorized.\n\nUse [`net_adm:ping(Node)`](`net_adm:ping/1`) instead.\n\nNotice that a connection to `Node` is established in this case. Returns `no` if\n`Node` does not exist or communication is not authorized (it has another cookie\nthan `auth` thinks it has).","ref":"auth.html#is_auth/1"},{"type":"function","title":"auth.node_cookie/1","doc":"Equivalent to [`node_cookie(Node, Cookie)`](`node_cookie/2`).","ref":"auth.html#node_cookie/1"},{"type":"function","title":"auth.node_cookie/2","doc":"Sets the magic cookie of `Node` to `Cookie` and verifies the status of the\nauthorization.\n\nEquivalent to calling [`erlang:set_cookie(Node, Cookie)`](`erlang:set_cookie/2`),\nfollowed by [`auth:is_auth(Node)`](`is_auth/1`).","ref":"auth.html#node_cookie/2"},{"type":"type","title":"auth.cookie/0","doc":"","ref":"auth.html#t:cookie/0"},{"type":"module","title":"erl_boot_server","doc":"Boot server for other Erlang machines.\n\nThis server is used to assist diskless Erlang nodes that fetch all Erlang code\nfrom another machine.\n\nThis server is used to fetch all code, including the start script, if an Erlang\nruntime system is started with command-line flag `-loader inet`. All hosts\nspecified with command-line flag `-hosts Host` must have one instance of this\nserver running.\n\nThis server can be started with the Kernel configuration parameter\n`start_boot_server`.\n\nThe `erl_boot_server` can read regular files and files in archives. See `m:code`\nand `m:erl_prim_loader` in ERTS.\n\n> #### Warning {: .warning }\n>\n> The support for loading code from archive files is experimental. It is\n> released before it is ready to obtain early feedback. The file format,\n> semantics, interfaces, and so on, can be changed in a future release.","ref":"erl_boot_server.html"},{"type":"module","title":"SEE ALSO - erl_boot_server","doc":"[`erts:init`](`m:init`), [`erts:erl_prim_loader`](`m:erl_prim_loader`)","ref":"erl_boot_server.html#module-see-also"},{"type":"function","title":"erl_boot_server.add_slave/1","doc":"Adds a `Slave` node to the list of allowed slave hosts.","ref":"erl_boot_server.html#add_slave/1"},{"type":"function","title":"erl_boot_server.delete_slave/1","doc":"Deletes a `Slave` node from the list of allowed slave hosts.","ref":"erl_boot_server.html#delete_slave/1"},{"type":"function","title":"erl_boot_server.start/1","doc":"Starts the boot server. `Slaves` is a list of IP addresses for hosts, which are\nallowed to use this server as a boot server.","ref":"erl_boot_server.html#start/1"},{"type":"function","title":"erl_boot_server.start_link/1","doc":"Starts the boot server and links to the caller. This function is used to start\nthe server if it is included in a supervision tree.","ref":"erl_boot_server.html#start_link/1"},{"type":"function","title":"erl_boot_server.which_slaves/0","doc":"Returns the current list of allowed slave hosts.","ref":"erl_boot_server.html#which_slaves/0"},{"type":"module","title":"erl_epmd","doc":"Erlang interface towards epmd\n\nThis module communicates with the EPMD daemon, see [epmd](`e:erts:epmd_cmd.md`).\nTo implement your own epmd module please see\n[ERTS User's Guide: How to Implement an Alternative Node Discovery for Erlang Distribution](`e:erts:alt_disco.md`)","ref":"erl_epmd.html"},{"type":"function","title":"erl_epmd.address_please/3","doc":"Called by the distribution module to resolves the `Host` to an IP address of a\nremote node.\n\nAs an optimization this function may also return the port and version of the\nremote node. If port and version are returned `port_please/3` will not be\ncalled.","ref":"erl_epmd.html#address_please/3"},{"type":"function","title":"erl_epmd.listen_port_please/2","doc":"Called by the distribution module to get which port the local node should listen\nto when accepting new distribution requests.","ref":"erl_epmd.html#listen_port_please/2"},{"type":"function","title":"erl_epmd.names/1","doc":"Called by [`net_adm:names/0`](`m:net_adm`). `Host` defaults to the localhost.\nReturns the names and associated port numbers of the Erlang nodes that `epmd`\nregistered at the specified host. Returns `{error, address}` if `epmd` is not\noperational.\n\n_Example:_\n\n```erlang\n(arne@dunn)1> erl_epmd:names(localhost).\n{ok,[{\"arne\",40262}]}\n```","ref":"erl_epmd.html#names/1"},{"type":"function","title":"erl_epmd.port_please/2","doc":"","ref":"erl_epmd.html#port_please/2"},{"type":"function","title":"erl_epmd.port_please/3","doc":"Requests the distribution port for the given node of an EPMD instance. Together\nwith the port it returns a distribution protocol version which has been 5 since\nErlang/OTP R6.","ref":"erl_epmd.html#port_please/3"},{"type":"function","title":"erl_epmd.register_node/2","doc":"","ref":"erl_epmd.html#register_node/2"},{"type":"function","title":"erl_epmd.register_node/3","doc":"Registers the node with `epmd` and tells epmd what port will be used for the\ncurrent node. It returns a creation number. This number is incremented on each\nregister to help differentiate a new node instance connecting to epmd with the\nsame name.\n\nAfter the node has successfully registered with epmd it will automatically\nattempt reconnect to the daemon if the connection is broken.","ref":"erl_epmd.html#register_node/3"},{"type":"function","title":"erl_epmd.start_link/0","doc":"This function is invoked as this module is added as a child of the\n`erl_distribution` supervisor.","ref":"erl_epmd.html#start_link/0"},{"type":"module","title":"erpc","doc":"Enhanced Remote Procedure Call\n\nThis module provide services similar to Remote Procedure Calls. A remote\nprocedure call is a method to call a function on a remote node and collect the\nanswer. It is used for collecting information on a remote node, or for running a\nfunction with some specific side effects on the remote node.\n\nThis is an enhanced subset of the operations provided by the `m:rpc` module.\nEnhanced in the sense that it makes it possible to distinguish between returned\nvalue, raised exceptions, and other errors. `erpc` also has better performance\nand scalability than the original `rpc` implementation. However, current `rpc`\nmodule will utilize `erpc` in order to also provide these properties when\npossible.\n\nIn order for an `erpc` operation to succeed, the remote node also needs to\nsupport `erpc`. Typically only ordinary Erlang nodes as of OTP 23 have `erpc`\nsupport.\n\nNote that it is up to the user to ensure that correct code to execute via `erpc`\nis available on the involved nodes.\n\n> #### Note {: .info }\n>\n> For some important information about distributed signals, see the\n> [Blocking Signaling Over Distribution](`e:system:ref_man_processes.md#blocking-signaling-over-distribution`)\n> section in the _Processes_ chapter of the _Erlang Reference Manual_. Blocking\n> signaling can, for example, cause timeouts in `erpc` to be significantly\n> delayed.","ref":"erpc.html"},{"type":"function","title":"erpc.call/2","doc":"","ref":"erpc.html#call/2"},{"type":"function","title":"erpc.call/3","doc":"Equivalent to\n[`erpc:call(Node, erlang, apply, [Fun,[]], #{timeout => Timeout})`](`call/5`).\n\nMay raise all the same exceptions as [`call/5`](`call/5`) plus an `{erpc, badarg}`\n`error` exception if `Fun` is not a fun of zero arity.","ref":"erpc.html#call/3"},{"type":"function","title":"erpc.call/4","doc":"","ref":"erpc.html#call/4"},{"type":"function","title":"erpc.call/5","doc":"Evaluates [`apply(Module, Function, Args)`](`apply/3`) on node `Node` and\nreturns the corresponding value `Result`.\n\n`TimeoutOrOptions` can be either a [`timeout time`](`t:timeout_time/0`) or a\n[`call options`](`t:call_options/0`) map (since OTP 28.0).\n\nThe `call()` function only returns if the applied function successfully returned\nwithout raising any uncaught exceptions, the operation did not time out, and no\nfailures occurred. In all other cases an exception is raised. The following\nexceptions, listed by exception class, can currently be raised by `call()`:\n\n- **`throw`** - The applied function called [`throw(Value)`](`throw/1`) and did\n not catch this exception. The exception reason `Value` equals the argument\n passed to [`throw/1`](`throw/1`).\n\n- **`exit`** - Exception reason:\n\n - **`{exception, ExitReason}`** - The applied function called\n [`exit(ExitReason)`](`exit/1`) and did not catch this exception. The exit\n reason `ExitReason` equals the argument passed to [`exit/1`](`exit/1`).\n\n - **`{signal, ExitReason}`** - The process that applied the function received\n an exit signal and terminated due to this signal. The process terminated\n with exit reason `ExitReason`.\n\n- **`error`** - Exception reason:\n\n - **`{exception, ErrorReason, StackTrace}`** - A runtime error occurred which\n raised an error exception while applying the function, and the applied\n function did not catch the exception. The error reason `ErrorReason`\n indicates the type of error that occurred. `StackTrace` is formatted as when\n caught in a `try/catch` construct. The `StackTrace` is limited to the\n applied function and functions called by it.\n\n - **`{erpc, ERpcErrorReason}`** - The `erpc` operation failed. The following\n `ERpcErrorReason`s are the most common ones:\n\n - **`badarg`** - If any one of these are true:\n\n - `Node` is not an atom.\n - `Module` is not an atom.\n - `Function` is not an atom.\n - `Args` is not a list. Note that the list is not verified to be a proper\n list at the client side.\n - `Timeout` is invalid.\n\n - **`noconnection`** - The connection to `Node` was lost or could not be\n established. The function may or may not be applied.\n\n - **`system_limit`** - The `erpc` operation failed due to some system limit\n being reached. This typically due to failure to create a process on the\n remote node `Node`, but can be other things as well.\n\n - **`timeout`** - The `erpc` operation timed out. The function may or may\n not be applied.\n\n - **`notsup`** - The remote node `Node` does not support this `erpc`\n operation.\n\nIf the `erpc` operation fails, but it is unknown if the function is/will be\napplied (that is, a timeout or a connection loss), the caller will not receive\nany further information about the result if/when the applied function completes.\nIf the applied function explicitly communicates with the calling process, such\ncommunication may, of course, reach the calling process.\n\n> #### Note {: .info }\n>\n> If the `always_spawn` option is `false` (which is the default), you cannot make\n> _any_ assumptions about the process that will perform the `apply()`. It may be\n> the calling process itself, or a freshly spawned process.","ref":"erpc.html#call/5"},{"type":"function","title":"erpc.cast/2","doc":"Equivalent to [`erpc:cast(Node,erlang,apply,[Fun,[]])`](`cast/4`).\n\n[`cast/2`](`cast/2`) fails with an `{erpc, badarg}` `error` exception if:\n\n- `Node` is not an atom.\n- `Fun` is not a a fun of zero arity.","ref":"erpc.html#cast/2"},{"type":"function","title":"erpc.cast/4","doc":"Evaluates [`apply(Module, Function, Args)`](`apply/3`) on node `Node`. No\nresponse is delivered to the calling process. `cast()` returns immediately after\nthe cast request has been sent. Any failures beside bad arguments are silently\nignored.\n\n[`cast/4`](`cast/4`) fails with an `{erpc, badarg}` `error` exception if:\n\n- `Node` is not an atom.\n- `Module` is not an atom.\n- `Function` is not an atom.\n- `Args` is not a list. Note that the list is not verified to be a proper list\n at the client side.","ref":"erpc.html#cast/4"},{"type":"function","title":"erpc.check_response/2","doc":"Check if a message is a response to a `call` request previously made by the\ncalling process using `send_request/4`.\n\n`RequestId` should be the value returned from the previously made\n[`send_request/4`](`send_request/4`) call, and the\ncorresponding response should not already have been received and handled to\ncompletion by [`check_response/2`](`check_response/2`), `receive_response/2`, or\n`wait_response/2`. `Message` is the message to check.\n\nIf `Message` does not correspond to the response, the atom `no_response` is\nreturned. If `Message` corresponds to the response, the `call` operation is\ncompleted and either the result is returned as `{response, Result}` where\n`Result` corresponds to the value returned from the applied function or an\nexception is raised. The exceptions that can be raised corresponds to the same\nexceptions as can be raised by `call/4`. That is, no `{erpc, timeout}` `error`\nexception can be raised. `check_response()` will fail with an `{erpc, badarg}`\nexception if/when an invalid `RequestId` is detected.\n\nIf the `erpc` operation fails, but it is unknown if the function is/will be\napplied (that is, a connection loss), the caller will not receive any further\ninformation about the result if/when the applied function completes. If the\napplied function explicitly communicates with the calling process, such\ncommunication may, of course, reach the calling process.","ref":"erpc.html#check_response/2"},{"type":"function","title":"erpc.check_response/3","doc":"Check if a message is a response to a `call` request corresponding to a request\nidentifier saved in `RequestIdCollection`. All request identifiers of\n`RequestIdCollection` must correspond to requests that have been made using\n`send_request/4` or `send_request/6`, and all requests must have been made by\nthe process calling this function.\n\n`Label` is the label associated with the request identifier of the request that\nthe response corresponds to. A request identifier is associated with a label\nwhen [adding a request identifier](`reqids_add/3`) in a\n[request identifier collection](`t:request_id_collection/0`), or when sending\nthe request using `send_request/6`.\n\nCompared to `check_response/2`, the returned result associated with a specific\nrequest identifier or an exception associated with a specific request identifier\nwill be wrapped in a 3-tuple. The first element of this tuple equals the value\nthat would have been produced by [`check_response/2`](`check_response/2`), the\nsecond element equals the `Label` associated with the specific request\nidentifier, and the third element `NewRequestIdCollection` is a possibly\nmodified request identifier collection. The `error` exception `{erpc, badarg}`\nis not associated with any specific request identifier, and will hence not be\nwrapped.\n\nIf `RequestIdCollection` is empty, the atom `no_request` will be returned. If\n`Message` does not correspond to any of the request identifiers in\n`RequestIdCollection`, the atom `no_response` is returned.\n\nIf `Delete` equals `true`, the association with `Label` will have been deleted\nfrom `RequestIdCollection` in the resulting `NewRequestIdCollection`. If\n`Delete` equals `false`, `NewRequestIdCollection` will equal\n`RequestIdCollection`. Note that deleting an association is not for free and\nthat a collection containing already handled requests can still be used by\nsubsequent calls to [`check_response/3`](`check_response/3`),\n`receive_response/3`, and `wait_response/3`. However, without deleting handled\nassociations, the above calls will not be able to detect when there are no more\noutstanding requests to handle, so you will have to keep track of this some\nother way than relying on a `no_request` return. Note that if you pass a\ncollection only containing associations of already handled or abandoned requests\nto [`check_response/3`](`check_response/3`), it will always return\n`no_response`.\n\nNote that a response might have been consumed uppon an `{erpc, badarg}`\nexception and if so, will be lost for ever.","ref":"erpc.html#check_response/3"},{"type":"function","title":"erpc.multicall/2","doc":"","ref":"erpc.html#multicall/2"},{"type":"function","title":"erpc.multicall/3","doc":"Equivalent to\n[`erpc:multicall(Nodes, erlang, apply, [Fun,[]], #{timeout => Timeout})`](`multicall/5`).\n\nMay raise all the same exceptions as [`multicall/5`](`multicall/5`) plus an\n`{erpc, badarg}` `error` exception if `Fun` is not a fun of zero arity.","ref":"erpc.html#multicall/3"},{"type":"function","title":"erpc.multicall/4","doc":"","ref":"erpc.html#multicall/4"},{"type":"function","title":"erpc.multicall/5","doc":"Performs multiple `call` operations in parallel on multiple nodes.\n\nThat is, evaluates [`apply(Module, Function, Args)`](`apply/3`) on the nodes `Nodes` in\nparallel.\n\n`TimeoutOrOptions` can be either a [`timeout time`](`t:timeout_time/0`) or a\n[`call options`](`t:call_options/0`) map (since OTP 28.0).\n\nThe result is returned as a list where the result from each node is\nplaced at the same position as the node name is placed in `Nodes`. Each item in\nthe resulting list is formatted as either:\n\n- **`{ok, Result}`** - The `call` operation for this specific node returned\n `Result`.\n\n- **`{Class, ExceptionReason}`** - The `call` operation for this specific node\n raised an exception of class `Class` with exception reason `ExceptionReason`.\n These correspond to the exceptions that `call/5` can raise.\n\n[`multicall/5`](`multicall/5`) fails with an `{erpc, badarg}` `error` exception\nif:\n\n- `Nodes` is not a proper list of atoms. Note that some requests may already\n have been sent when the failure occurs. That is, the function may or may not\n be applied on some nodes.\n- `Module` is not an atom.\n- `Function` is not an atom.\n- `Args` is not a list. Note that the list is not verified to be a proper list\n at the client side.\n\nThe call `erpc:multicall(Nodes, Module, Function, Args)` is equivalent to the\ncall `erpc:multicall(Nodes, Module, Function, Args, infinity)`. These calls are\nalso equivalent to calling `my_multicall(Nodes, Module, Function, Args)` below\nif one disregard performance and failure behavior. `multicall()` can utilize a\nselective receive optimization which removes the need to scan the message queue\nfrom the beginning in order to find a matching message. The\n`send_request()/receive_response()` combination can, however, not utilize this\noptimization.\n\n```erlang\nmy_multicall(Nodes, Module, Function, Args) ->\n ReqIds = lists:map(fun (Node) ->\n erpc:send_request(Node, Module, Function, Args)\n end,\n Nodes),\n lists:map(fun (ReqId) ->\n try\n {ok, erpc:receive_response(ReqId, infinity)}\n catch\n Class:Reason ->\n {Class, Reason}\n end\n end,\n ReqIds).\n```\n\nIf an `erpc` operation fails, but it is unknown if the function is/will be\napplied (that is, a timeout, connection loss, or an improper `Nodes` list), the\ncaller will not receive any further information about the result if/when the\napplied function completes. If the applied function communicates with the\ncalling process, such communication may, of course, reach the calling process.\n\n> #### Note {: .info }\n>\n> If the `always_spawn` option is `false` (which is the default), you cannot make\n> _any_ assumptions about the processes that will perform the `apply()`s. It may be\n> the calling process itself, or freshly spawned processes, or a mix of both.","ref":"erpc.html#multicall/5"},{"type":"function","title":"erpc.multicast/2","doc":"Equivalent to\n[`erpc:multicast(Nodes,erlang,apply,[Fun,[]])`](`multicast/4`).\n\n[`multicast/2`](`multicast/2`) fails with an `{erpc, badarg}` `error` exception\nif:\n\n- `Nodes` is not a proper list of atoms.\n- `Fun` is not a a fun of zero arity.","ref":"erpc.html#multicast/2"},{"type":"function","title":"erpc.multicast/4","doc":"Evaluates [`apply(Module, Function, Args)`](`apply/3`) on the nodes `Nodes`. No\nresponse is delivered to the calling process. `multicast()` returns immediately\nafter the cast requests have been sent. Any failures beside bad arguments are\nsilently ignored.\n\n[`multicast/4`](`multicast/4`) fails with an `{erpc, badarg}` `error` exception\nif:\n\n- `Nodes` is not a proper list of atoms. Note that some requests may already\n have been sent when the failure occurs. That is, the function may or may not\n be applied on some nodes.\n- `Module` is not an atom.\n- `Function` is not an atom.\n- `Args` is not a list. Note that the list is not verified to be a proper list\n at the client side.","ref":"erpc.html#multicast/4"},{"type":"function","title":"erpc.receive_response/1","doc":"","ref":"erpc.html#receive_response/1"},{"type":"function","title":"erpc.receive_response/2","doc":"Receive a response to a `call` request previously made by the calling process\nusing `send_request/4`.\n\n`RequestId` should be the value returned from the\npreviously made [`send_request/4`](`send_request/4`) call, and the corresponding\nresponse should not already have been received and handled to completion by\n`receive_response()`, [`check_response/4`](`check_response/2`), or\n[`wait_response/4`](`wait_response/2`).\n\n`Timeout` sets an upper time limit on how long to wait for a response. If the\noperation times out, the request identified by `RequestId` will be abandoned,\nthen an `{erpc, timeout}` `error` exception will be raised. That is, no response\ncorresponding to the request will ever be received after a timeout. If a\nresponse is received, the `call` operation is completed and either the result is\nreturned or an exception is raised. The exceptions that can be raised\ncorresponds to the same exceptions as can be raised by `call/5`.\n[`receive_response/2`](`receive_response/2`) will fail with an `{erpc, badarg}`\nexception if/when an invalid `RequestId` is detected or if an invalid `Timeout`\nis passed.\n\nA call to the function `my_call(Node, Module, Function, Args, Timeout)` below is\nequivalent to the call\n[`erpc:call(Node, Module, Function, Args, Timeout)`](`call/5`) if one disregards\nperformance. `call()` can utilize a selective receive optimization which removes\nthe need to scan the message queue from the beginning in order to find a\nmatching message. The `send_request()/receive_response()` combination can,\nhowever, not utilize this optimization.\n\n```erlang\nmy_call(Node, Module, Function, Args, Timeout) ->\n RequestId = erpc:send_request(Node, Module, Function, Args),\n erpc:receive_response(RequestId, Timeout).\n```\n\nIf the `erpc` operation fails, but it is unknown if the function is/will be\napplied (that is, a timeout, or a connection loss), the caller will not receive\nany further information about the result if/when the applied function completes.\nIf the applied function explicitly communicates with the calling process, such\ncommunication may, of course, reach the calling process.","ref":"erpc.html#receive_response/2"},{"type":"function","title":"erpc.receive_response/3","doc":"Receive a response to a `call` request corresponding to a request identifier\nsaved in `RequestIdCollection`. All request identifiers of `RequestIdCollection`\nmust correspond to requests that have been made using `send_request/4` or\n`send_request/6`, and all requests must have been made by the process calling\nthis function.\n\n`Label` is the label associated with the request identifier of the request that\nthe response corresponds to. A request identifier is associated with a label\nwhen [adding a request identifier](`reqids_add/3`) in a\n[request identifier collection](`t:request_id_collection/0`), or when sending\nthe request using `send_request/6`.\n\nCompared to `receive_response/2`, the returned result associated with a specific\nrequest identifier or an exception associated with a specific request identifier\nwill be wrapped in a 3-tuple. The first element of this tuple equals the value\nthat would have been produced by [`receive_response/2`](`receive_response/2`),\nthe second element equals the `Label` associated with the specific request\nidentifier, and the third element `NewRequestIdCollection` is a possibly\nmodified request identifier collection. The `error` exceptions `{erpc, badarg}`\nand `{erpc, timeout}` are not associated with any specific request identifiers,\nand will hence not be wrapped.\n\nIf `RequestIdCollection` is empty, the atom `no_request` will be returned.\n\nIf the operation times out, all requests identified by `RequestIdCollection`\nwill be abandoned, then an `{erpc, timeout}` `error` exception will be raised.\nThat is, no responses corresponding to any of the request identifiers in\n`RequestIdCollection` will ever be received after a timeout. The difference\nbetween [`receive_response/3`](`receive_response/3`) and `wait_response/3` is\nthat [`receive_response/3`](`receive_response/3`) abandons the requests at\ntimeout so that any potential future responses are ignored, while\n[`wait_response/3`](`wait_response/3`) does not.\n\nIf `Delete` equals `true`, the association with `Label` will have been deleted\nfrom `RequestIdCollection` in the resulting `NewRequestIdCollection`. If\n`Delete` equals `false`, `NewRequestIdCollection` will equal\n`RequestIdCollection`. Note that deleting an association is not for free and\nthat a collection containing already handled requests can still be used by\nsubsequent calls to [`receive_response/3`](`receive_response/3`),\n`check_response/3`, and `wait_response/3`. However, without deleting handled\nassociations, the above calls will not be able to detect when there are no more\noutstanding requests to handle, so you will have to keep track of this some\nother way than relying on a `no_request` return. Note that if you pass a\ncollection only containing associations of already handled or abandoned requests\nto [`receive_response/3`](`receive_response/3`), it will always block until a\ntimeout determined by `Timeout` is triggered.\n\nNote that a response might have been consumed uppon an `{erpc, badarg}`\nexception and if so, will be lost for ever.","ref":"erpc.html#receive_response/3"},{"type":"function","title":"erpc.reqids_add/3","doc":"Saves `RequestId` and associates a `Label` with the request identifier by adding\nthis information to `RequestIdCollection` and returning the resulting request\nidentifier collection.","ref":"erpc.html#reqids_add/3"},{"type":"function","title":"erpc.reqids_new/0","doc":"Returns a new empty request identifier collection. A request identifier\ncollection can be utilized in order the handle multiple outstanding requests.\n\nRequest identifiers of requests made by `send_request/4` can be saved in a\nrequest identifier collection using `reqids_add/3`. Such a collection of request\nidentifiers can later be used in order to get one response corresponding to a\nrequest in the collection by passing the collection as argument to\n`check_response/3`, `receive_response/3`, and `wait_response/3`.\n\n`reqids_size/1` can be used to determine the amount of request identifiers in a\nrequest identifier collection.","ref":"erpc.html#reqids_new/0"},{"type":"function","title":"erpc.reqids_size/1","doc":"Returns the amount of request identifiers saved in `RequestIdCollection`.","ref":"erpc.html#reqids_size/1"},{"type":"function","title":"erpc.reqids_to_list/1","doc":"Returns a list of `{RequestId, Label}` tuples which corresponds to all request\nidentifiers with their associated labels present in the `RequestIdCollection`\ncollection.","ref":"erpc.html#reqids_to_list/1"},{"type":"function","title":"erpc.send_request/2","doc":"Equivalent to\n[`erpc:send_request(Node, erlang, apply, [Fun, []])`](`send_request/4`).\n\nFails with an `{erpc, badarg}` `error` exception if:\n\n- `Node` is not an atom.\n- `Fun` is not a fun of zero arity.","ref":"erpc.html#send_request/2"},{"type":"function","title":"erpc.send_request/4","doc":"Send an asynchronous `call` request to the node `Node`.\n\n[`send_request/4`](`send_request/4`) returns a request identifier that later is\nto be passed to either `receive_response/2`, `wait_response/2`, or,\n`check_response/2` in order to get the response of the call request. Besides\npassing the request identifier directly to these functions, it can also be added\nin a request identifier collection using `reqids_add/3`. Such a collection of\nrequest identifiers can later be used in order to get one response corresponding\nto a request in the collection by passing the collection as argument to\n`receive_response/3`, `wait_response/3`, or, `check_response/3`. If you are\nabout to save the request identifier in a request identifier collection, you may\nwant to consider using `send_request/6` instead.\n\nA call to the function `my_call(Node, Module, Function, Args, Timeout)` below is\nequivalent to the call\n[`erpc:call(Node, Module, Function, Args, Timeout)`](`call/5`) if one disregards\nperformance. `call()` can utilize a selective receive optimization which removes\nthe need to scan the message queue from the beginning in order to find a\nmatching message. The `send_request()/receive_response()` combination can,\nhowever, not utilize this optimization.\n\n```erlang\nmy_call(Node, Module, Function, Args, Timeout) ->\n RequestId = erpc:send_request(Node, Module, Function, Args),\n erpc:receive_response(RequestId, Timeout).\n```\n\nFails with an `{erpc, badarg}` `error` exception if:\n\n- `Node` is not an atom.\n- `Module` is not an atom.\n- `Function` is not an atom.\n- `Args` is not a list. Note that the list is not verified to be a proper list\n at the client side.\n\nEquivalent to\n[`erpc:send_request(Node, erlang, apply, [Fun,[]]), Label, RequestIdCollection)`](`send_request/6`).\n\nFails with an `{erpc, badarg}` `error` exception if:\n\n- `Node` is not an atom.\n- `Fun` is not a fun of zero arity.\n- `RequestIdCollection` is detected not to be request identifier collection.","ref":"erpc.html#send_request/4"},{"type":"function","title":"erpc.send_request/6","doc":"Send an asynchronous `call` request to the node `Node`. The `Label` will be\nassociated with the request identifier of the operation and added to the\nreturned request identifier collection `NewRequestIdCollection`. The collection\ncan later be used in order to get one response corresponding to a request in the\ncollection by passing the collection as argument to `receive_response/3`,\n`wait_response/3`, or, `check_response/3`.\n\nEquivalent to\n[`erpc:reqids_add`](`reqids_add/3`)([`erpc:send_request`](`send_request/4`)`(Node, Module, Function, Args), Label, RequestIdCollection)`,\nbut calling [`send_request/6`](`send_request/6`) is slightly more efficient.\n\nFails with an `{erpc, badarg}` `error` exception if:\n\n- `Node` is not an atom.\n- `Module` is not an atom.\n- `Function` is not an atom.\n- `Args` is not a list. Note that the list is not verified to be a proper list\n at the client side.\n- `RequestIdCollection` is detected not to be request identifier collection.","ref":"erpc.html#send_request/6"},{"type":"function","title":"erpc.wait_response/1","doc":"Equivalent to [`erpc:wait_response(RequestId, 0)`](`wait_response/2`).\nThat is, poll for a response message to a `call` request previously made by the\ncalling process.","ref":"erpc.html#wait_response/1"},{"type":"function","title":"erpc.wait_response/2","doc":"Wait or poll for a response message to a `call` request previously made by the\ncalling process using `send_request/4`.\n\n`RequestId` should be the value returned from the previously made `send_request()`\ncall, and the corresponding response should not already have been received and\nhandled to completion by `check_response/2`, `receive_response/2`, or `wait_response()`.\n\n`WaitTime` sets an upper time limit on how long to wait for a response. If no\nresponse is received before the `WaitTime` timeout has triggered, the atom\n`no_response` is returned. It is valid to continue waiting for a response as\nmany times as needed up until a response has been received and completed by\n`check_response()`, `receive_response()`, or `wait_response()`. If a response is\nreceived, the `call` operation is completed and either the result is returned as\n`{response, Result}` where `Result` corresponds to the value returned from the\napplied function or an exception is raised. The exceptions that can be raised\ncorresponds to the same exceptions as can be raised by `call/4`. That is, no\n`{erpc, timeout}` `error` exception can be raised.\n[`wait_response/2`](`wait_response/2`) will fail with an `{erpc, badarg}`\nexception if/when an invalid `RequestId` is detected or if an invalid `WaitTime`\nis passed.\n\nIf the `erpc` operation fails, but it is unknown if the function is/will be\napplied (that is, a too large wait time value, or a connection loss), the caller\nwill not receive any further information about the result if/when the applied\nfunction completes. If the applied function explicitly communicates with the\ncalling process, such communication may, of course, reach the calling process.","ref":"erpc.html#wait_response/2"},{"type":"function","title":"erpc.wait_response/3","doc":"Wait or poll for a response to a `call` request corresponding to a request\nidentifier saved in `RequestIdCollection`. All request identifiers of\n`RequestIdCollection` must correspond to requests that have been made using\n`send_request/4` or `send_request/6`, and all requests must have been made by\nthe process calling this function.\n\n`Label` is the label associated with the request identifier of the request that\nthe response corresponds to. A request identifier is associated with a label\nwhen [adding a request identifier](`reqids_add/3`) in a\n[request identifier collection](`t:request_id_collection/0`), or when sending\nthe request using `send_request/6`.\n\nCompared to `wait_response/2`, the returned result associated with a specific\nrequest identifier or an exception associated with a specific request identifier\nwill be wrapped in a 3-tuple. The first element of this tuple equals the value\nthat would have been produced by [`wait_response/2`](`wait_response/2`), the\nsecond element equals the `Label` associated with the specific request\nidentifier, and the third element `NewRequestIdCollection` is a possibly\nmodified request identifier collection. The `error` exception `{erpc, badarg}`\nis not associated with any specific request identifier, and will hence not be\nwrapped.\n\nIf `RequestIdCollection` is empty, `no_request` will be returned. If no response\nis received before the `WaitTime` timeout has triggered, the atom `no_response`\nis returned. It is valid to continue waiting for a response as many times as\nneeded up until a response has been received and completed by\n`check_response()`, `receive_response()`, or `wait_response()`. The difference\nbetween `receive_response/3` and [`wait_response/3`](`wait_response/3`) is that\n[`receive_response/3`](`receive_response/3`) abandons requests at timeout so\nthat any potential future responses are ignored, while\n[`wait_response/3`](`wait_response/3`) does not.\n\nIf `Delete` equals `true`, the association with `Label` will have been deleted\nfrom `RequestIdCollection` in the resulting `NewRequestIdCollection`. If\n`Delete` equals `false`, `NewRequestIdCollection` will equal\n`RequestIdCollection`. Note that deleting an association is not for free and\nthat a collection containing already handled requests can still be used by\nsubsequent calls to [`wait_response/3`](`wait_response/3`), `check_response/3`,\nand `receive_response/3`. However, without deleting handled associations, the\nabove calls will not be able to detect when there are no more outstanding\nrequests to handle, so you will have to keep track of this some other way than\nrelying on a `no_request` return. Note that if you pass a collection only\ncontaining associations of already handled or abandoned requests to\n[`wait_response/3`](`wait_response/3`), it will always block until a timeout\ndetermined by `WaitTime` is triggered and then return `no_response`.\n\nNote that a response might have been consumed uppon an `{erpc, badarg}`\nexception and if so, will be lost for ever.","ref":"erpc.html#wait_response/3"},{"type":"type","title":"erpc.call_options/0","doc":"Options to be used in [`call/3,5`](`call/5`) and\n[`multicall/3,5`](`multicall/5`) functions.\n\n- **`timeout`** - Upper time limit for call operations to complete, see\n `t:timeout_time/0`. Default: `infinity`.\n\n- **`always_spawn`** - If `true`, the `apply()` will _always_ be performed\n in a freshly spawned process. If `false`, the calling process _may_ be\n used instead, if possible. Default: `false`.","ref":"erpc.html#t:call_options/0"},{"type":"type","title":"erpc.caught_call_exception/0","doc":"","ref":"erpc.html#t:caught_call_exception/0"},{"type":"opaque","title":"erpc.request_id/0","doc":"An opaque request identifier. For more information see `send_request/4`.","ref":"erpc.html#t:request_id/0"},{"type":"opaque","title":"erpc.request_id_collection/0","doc":"An opaque collection of request identifiers (`t:request_id/0`) where each\nrequest identifier can be associated with a label chosen by the user. For more\ninformation see `reqids_new/0`.","ref":"erpc.html#t:request_id_collection/0"},{"type":"type","title":"erpc.stack_item/0","doc":"","ref":"erpc.html#t:stack_item/0"},{"type":"type","title":"erpc.timeout_time/0","doc":"The timeout time used by erpc functions.\n\nThe value can be:\n\n- **`0..4294967295`** - Timeout relative to current time in milliseconds.\n\n- **`infinity`** - Infinite timeout. That is, the operation will never time out.\n\n- **`{abs, Timeout}`** - An absolute\n [Erlang monotonic time](`erlang:monotonic_time/1`) timeout in milliseconds.\n That is, the operation will time out when\n [`erlang:monotonic_time(millisecond)`](`erlang:monotonic_time/1`) returns a\n value larger than or equal to `Timeout`. `Timeout` is not allowed to identify\n a time further into the future than `4294967295` milliseconds. Identifying the\n timeout using an absolute timeout value is especially handy when you have a\n deadline for responses corresponding to a complete collection of requests\n (`t:request_id_collection/0`), since you do not have to recalculate the\n relative time until the deadline over and over again.","ref":"erpc.html#t:timeout_time/0"},{"type":"module","title":"global","doc":"A global name registration facility.\n\nThis module consists of the following services:\n\n- Registration of global names\n- Global locks\n- Maintenance of the fully connected network\n\n[](){: #prevent_overlapping_partitions }\n\nAs of OTP 25, `global` will by default prevent overlapping partitions due to\nnetwork issues by actively disconnecting from nodes that reports that they have\nlost connections to other nodes. This will cause fully connected partitions to\nform instead of leaving the network in a state with overlapping partitions.\n\n> #### Warning {: .warning }\n>\n> Prevention of overlapping partitions can be disabled using the\n> [`prevent_overlapping_partitions`](kernel_app.md#prevent_overlapping_partitions)\n> Kernel parameter, making `global` behave like it used to do. This is,\n> however, problematic for all applications expecting a fully connected network\n> to be provided, such as for example `mnesia`, but also for `global` itself. A\n> network of overlapping partitions might cause the internal state of `global`\n> to become inconsistent. Such an inconsistency can remain even after such\n> partitions have been brought together to form a fully connected network again.\n> The effect on other applications that expects that a fully connected network\n> is maintained may vary, but they might misbehave in very subtle hard to detect\n> ways during such a partitioning. Since you might get hard to detect issues\n> without this fix, you are _strongly_ advised _not_ to disable this fix. Also\n> note that this fix _has_ to be enabled on _all_ nodes in the network in order\n> to work properly.\n\n> #### Note {: .info }\n>\n> None of the above services will be reliably delivered unless both of the\n> kernel parameters [`connect_all`](kernel_app.md#connect_all) and\n> [`prevent_overlapping_partitions`](kernel_app.md#prevent_overlapping_partitions)\n> are enabled. Calls to the `global` API will, however, _not_ fail even though\n> one or both of them are disabled. You will just get unreliable results.\n\nThese services are controlled through the process `global_name_server` that\nexists on every node. The global name server starts automatically when a node is\nstarted. With the term _global_ is meant over a system consisting of many Erlang\nnodes.\n\nThe ability to globally register names is a central concept in the programming\nof distributed Erlang systems. In this module, the equivalent of the\n[`register/2`](`register/2`) and [`whereis/1`](`whereis/1`) BIFs (for local name\nregistration) are provided, but for a network of Erlang nodes. A registered name\nis an alias for a process identifier (pid). The global name server monitors\nglobally registered pids. If a process terminates, the name is also globally\nunregistered.\n\nThe registered names are stored in replica global name tables on every node.\nThere is no central storage point. Thus, the translation of a name to a pid is\nfast, as it is always done locally. For any action resulting in a change to the\nglobal name table, all tables on other nodes are automatically updated.\n\nGlobal locks have lock identities and are set on a specific resource. For\nexample, the specified resource can be a pid. When a global lock is set, access\nto the locked resource is denied for all resources other than the lock\nrequester.\n\nBoth the registration and lock services are atomic. All nodes involved in these\nactions have the same view of the information.\n\nThe global name server also performs the critical task of continuously\nmonitoring changes in node configuration. If a node that runs a globally\nregistered process goes down, the name is globally unregistered. To this end,\nthe global name server subscribes to `nodeup` and `nodedown` messages sent from\nmodule `net_kernel`. Relevant Kernel application variables in this context are\n[`net_setuptime`](kernel_app.md#net_setuptime), [`net_ticktime`](kernel_app.md#net_ticktime),\nand [`dist_auto_connect`](kernel_app.md#dist_auto_connect).\n\nThe name server also maintains a fully connected network. For example, if node\n`N1` connects to node `N2` (which is already connected to `N3`), the global name\nservers on the nodes `N1` and `N3` ensure that also `N1` and `N3` are connected.\nIn this case, the name registration service cannot be used, but the lock\nmechanism still works.\n\nIf the global name server fails to connect nodes (`N1` and `N3` in the example),\na warning event is sent to the error logger. The presence of such an event does\nnot exclude the nodes to connect later (you can, for example, try command\n`rpc:call(N1, net_adm, ping, [N2])` in the Erlang shell), but it indicates a\nnetwork problem.\n\n> #### Note {: .info }\n>\n> If the fully connected network is not set up properly, try first to increase\n> the value of `net_setuptime`.","ref":"global.html"},{"type":"module","title":"See Also - global","doc":"`m:global_group`, `m:net_kernel`","ref":"global.html#module-see-also"},{"type":"function","title":"global.del_lock/1","doc":"","ref":"global.html#del_lock/1"},{"type":"function","title":"global.del_lock/2","doc":"Deletes the lock `Id` synchronously.","ref":"global.html#del_lock/2"},{"type":"function","title":"global.disconnect/0","doc":"Disconnect from all other nodes known to `global`.\n\nA list of node names (in an unspecified order) is returned which corresponds to\nthe nodes that were disconnected. All disconnect operations performed have completed when\n`global:disconnect/0` returns.\n\nThe disconnects will be made in such a way that only the current node will be\nremoved from the cluster of `global` nodes. If\n[`prevent_overlapping_partitions`] is\nenabled and you disconnect, from other nodes in the cluster of `global` nodes,\nby other means, `global` on the other nodes may partition the remaining nodes in\norder to ensure that no overlapping partitions appear. Even if\n[`prevent_overlapping_partitions`] is disabled, you should preferably use\n`global:disconnect/0` in order to remove current node from a cluster of `global`\nnodes, since you otherwise likely _will_ create overlapping partitions which\nmight [cause problems](`m:global#prevent_overlapping_partitions`).\n\nNote that if the node is going to be halted, there is _no_ need to remove it\nfrom a cluster of `global` nodes explicitly by calling `global:disconnect/0`\nbefore halting it. The removal from the cluster is taken care of automatically\nwhen the node halts regardless of whether [`prevent_overlapping_partitions`] is\nenabled or not.\n\nIf current node has been configured to be part of a\n[_global group_](`m:global_group`), only connected and/or synchronized nodes in\nthat group are known to `global`, so `global:disconnect/0` will _only_\ndisconnect from those nodes. If current node is _not_ part of a _global group_,\nall [connected visible nodes](`erlang:nodes/0`) will be known to `global`, so\n`global:disconnect/0` will disconnect from all those nodes.\n\nNote that information about connected nodes does not instantaneously reach\n`global`, so the caller might see a node part of the result returned by\n[`nodes()`](`erlang:nodes/0`) while it still is not known to `global`. The\ndisconnect operation will, however, still not cause any overlapping partitions\nwhen [`prevent_overlapping_partitions`] is enabled. If\n[`prevent_overlapping_partitions`] is disabled, overlapping partitions might form\nin this case.\n\nNote that when [`prevent_overlapping_partitions`] is enabled, you may see warning\nreports on other nodes when they detect that current node has disconnected.\nThese are in this case completely harmless and can be ignored.\n\n[`prevent_overlapping_partitions`]: kernel_app.md#prevent_overlapping_partitions","ref":"global.html#disconnect/0"},{"type":"function","title":"global.notify_all_name/3","doc":"The function unregisters both pids and sends the message\n`{global_name_conflict, Name, OtherPid}` to both processes.\n\nCan be used as a name resolving function for `register_name/3` and\n`re_register_name/3`.","ref":"global.html#notify_all_name/3"},{"type":"function","title":"global.random_exit_name/3","doc":"The function randomly selects one of the pids for registration and kills the\nother one.\n\nCan be used as a name resolving function for `register_name/3` and\n`re_register_name/3`.","ref":"global.html#random_exit_name/3"},{"type":"function","title":"global.random_notify_name/3","doc":"The function randomly selects one of the pids for registration, and sends the\nmessage `{global_name_conflict, Name}` to the other pid.\n\nCan be used as a name resolving function for `register_name/3` and\n`re_register_name/3`.","ref":"global.html#random_notify_name/3"},{"type":"function","title":"global.re_register_name/2","doc":"","ref":"global.html#re_register_name/2"},{"type":"function","title":"global.re_register_name/3","doc":"Atomically changes the registered name `Name` on all nodes to refer to `Pid`.\n\nFunction `Resolve` has the same behavior as in\n[`register_name/2,3`](`register_name/2`).","ref":"global.html#re_register_name/3"},{"type":"function","title":"global.register_name/2","doc":"","ref":"global.html#register_name/2"},{"type":"function","title":"global.register_name/3","doc":"Globally associates name `Name` with a pid, that is, globally notifies all nodes\nof a new global name in a network of Erlang nodes.\n\nWhen new nodes are added to the network, they are informed of the globally\nregistered names that already exist. The network is also informed of any global\nnames in newly connected nodes. If any name clashes are discovered, function\n`Resolve` is called. Its purpose is to decide which pid is correct. If the\nfunction crashes, or returns anything other than one of the pids, the name is\nunregistered. This function is called once for each name clash.\n\n> #### Warning {: .warning }\n>\n> If you plan to change code without restarting your system, you must use an\n> external fun (`fun Module:Function/Arity`) as function `Resolve`. If you use a\n> local fun, you can never replace the code for the module that the fun belongs\n> to.\n\nThree predefined resolve functions exist:\n[`random_exit_name/3`](`random_exit_name/3`),\n[`random_notify_name/3`](`random_notify_name/3`), and\n[`notify_all_name/3`](`notify_all_name/3`).\n\nThis function is completely synchronous, that is, when this function returns,\nthe name is either registered on all nodes or none.\n\nThe function returns `yes` if successful, `no` if it fails. For example, `no` is\nreturned if an attempt is made to register an already registered process or to\nregister a process with a name that is already in use.\n\n> #### Note {: .info }\n>\n> Releases up to and including Erlang/OTP R10 did not check if the process was\n> already registered. The global name table could therefore become inconsistent.\n> The old (buggy) behavior can be chosen by giving the Kernel application\n> variable `global_multi_name_action` the value `allow`.\n\nIf a process with a registered name dies, or the node goes down, the name is\nunregistered on all nodes.","ref":"global.html#register_name/3"},{"type":"function","title":"global.registered_names/0","doc":"Returns a list of all globally registered names.","ref":"global.html#registered_names/0"},{"type":"function","title":"global.send/2","doc":"Sends message `Msg` to the pid globally registered as `Name`.\n\nIf `Name` is not a globally registered name, the calling function exits with\nreason `{badarg, {Name, Msg}}`.","ref":"global.html#send/2"},{"type":"function","title":"global.set_lock/1","doc":"","ref":"global.html#set_lock/1"},{"type":"function","title":"global.set_lock/2","doc":"","ref":"global.html#set_lock/2"},{"type":"function","title":"global.set_lock/3","doc":"Sets a lock on the specified nodes on using `t:id/0`.\n\nIf a lock already exists on `ResourceId` for another requester than `LockRequesterId`,\nand `Retries` is not equal to `0`, the process sleeps for a while and tries to\nexecute the action later. When `Retries` attempts have been made, `false` is\nreturned, otherwise `true`. If `Retries` is `infinity`, `true` is eventually\nreturned (unless the lock is never released).\n\nThis function is completely synchronous.\n\nIf a process that holds a lock dies, or the node goes down, the locks held by\nthe process are deleted.\n\nThe global name server keeps track of all processes sharing the same lock, that\nis, if two processes set the same lock, both processes must delete the lock.\n\nThis function does not address the problem of a deadlock. A deadlock can never\noccur as long as processes only lock one resource at a time. A deadlock can\noccur if some processes try to lock two or more resources. It is up to the\napplication to detect and rectify a deadlock.\n\n> #### Note {: .info }\n>\n> Avoid the following values of `ResourceId`, otherwise Erlang/OTP does not work\n> properly:\n>\n> - `dist_ac`\n> - `global`\n> - `mnesia_adjust_log_writes`\n> - `mnesia_table_lock`","ref":"global.html#set_lock/3"},{"type":"function","title":"global.sync/0","doc":"Synchronizes the global name server with all nodes known to this node.\n\nThese are the nodes that are returned from [`nodes()`](`erlang:nodes/0`). When\nthis function returns, the global name server receives global information from\nall nodes. This function can be called when new nodes are added to the network.\n\nThe only possible error reason `Reason` is\n`{\"global_groups definition error\", Error}`.","ref":"global.html#sync/0"},{"type":"function","title":"global.trans/2","doc":"","ref":"global.html#trans/2"},{"type":"function","title":"global.trans/3","doc":"","ref":"global.html#trans/3"},{"type":"function","title":"global.trans/4","doc":"Sets a lock on `Id` (using `set_lock/3`).\n\nIf this succeeds, `Fun()` is evaluated and the result `Res` is returned.\nReturns `aborted` if the lock attempt fails. If `Retries` is set to `infinity`,\nthe transaction does not abort.\n\n`infinity` is the default setting and is used if no value is specified for\n`Retries`.","ref":"global.html#trans/4"},{"type":"function","title":"global.unregister_name/1","doc":"Removes the globally registered name `Name` from the network of Erlang nodes.","ref":"global.html#unregister_name/1"},{"type":"function","title":"global.whereis_name/1","doc":"Returns the pid with the globally registered name `Name`. Returns `undefined` if\nthe name is not globally registered.","ref":"global.html#whereis_name/1"},{"type":"type","title":"global.id/0","doc":"A lock id used to set or delete lock `ResourceId` on behalf of `LockRequesterId`.","ref":"global.html#t:id/0"},{"type":"type","title":"global.method/0","doc":"","ref":"global.html#t:method/0"},{"type":"type","title":"global.retries/0","doc":"","ref":"global.html#t:retries/0"},{"type":"type","title":"global.trans_fun/0","doc":"","ref":"global.html#t:trans_fun/0"},{"type":"module","title":"global_group","doc":"Grouping nodes to global name registration groups.\n\nThis module makes it possible to partition the nodes of a system into _global\ngroups_. Each global group has its own global namespace, see `m:global`.\n\nThe main advantage of dividing systems into global groups is that the background\nload decreases while the number of nodes to be updated is reduced when\nmanipulating globally registered names.\n\nThe Kernel configuration parameter [`global_groups`](kernel_app.md#global_groups)\ndefines the global groups:\n\n```erlang\n{global_groups, [GroupTuple :: group_tuple()]}\n```\n\nFor the processes and nodes to run smoothly using the global group\nfunctionality, the following criteria must be met:\n\n- An instance of the global group server, `global_group`, must be running on\n each node. The processes are automatically started and synchronized when a\n node is started.\n- All involved nodes must agree on the global group definition, otherwise the\n behavior of the system is undefined.\n- _All_ nodes in the system must belong to exactly one global group.\n\nIn the following descriptions, a _group node_ is a node belonging to the same\nglobal group as the local node.","ref":"global_group.html"},{"type":"module","title":"Notes - global_group","doc":"- In the situation where a node has lost its connections to other nodes in its\n global group, but has connections to nodes in other global groups, a request\n from another global group can produce an incorrect or misleading result. For\n example, the isolated node can have inaccurate information about registered\n names in its global group.\n- Function [`send/2,3`](`send/2`) is not secure.\n- Distribution of applications is highly dependent of the global group\n definitions. It is not recommended that an application is distributed over\n many global groups, as the registered names can be moved to another global\n group at failover/takeover. Nothing prevents this to be done, but the\n application code must then handle the situation.","ref":"global_group.html#module-notes"},{"type":"module","title":"See Also - global_group","doc":"`m:global`, [`erl`](`e:erts:erl_cmd.md`)","ref":"global_group.html#module-see-also"},{"type":"function","title":"global_group.global_groups/0","doc":"Returns a tuple containing the name of the global group that the local node\nbelongs to, and the list of all other known group names.\n\nReturns `undefined` if no global groups are defined.","ref":"global_group.html#global_groups/0"},{"type":"function","title":"global_group.info/0","doc":"Returns a list containing information about the global groups. Each list element\nis a tuple. The order of the tuples is undefined.\n\n- **`{state, State}`** - If the local node is part of a global group, `State` is\n equal to `synced`. If no global groups are defined, `State` is equal to\n `no_conf`.\n\n- **`{own_group_name, GroupName}`** - The name (atom) of the group that the\n local node belongs to.\n\n- **`{own_group_nodes, Nodes}`** - A list of node names (atoms), the group\n nodes.\n\n- **`{synced_nodes, Nodes}`** - A list of node names, the group nodes currently\n synchronized with the local node.\n\n- **`{sync_error, Nodes}`** - A list of node names, the group nodes with which\n the local node has failed to synchronize.\n\n- **`{no_contact, Nodes}`** - A list of node names, the group nodes to which\n there are currently no connections.\n\n- **`{other_groups, Groups}`** - `Groups` is a list of tuples\n `{GroupName, Nodes}`, specifying the name and nodes of the other global\n groups.\n\n- **`{monitoring, Pids}`** - A list of pids, specifying the processes that have\n subscribed to `nodeup` and `nodedown` messages.","ref":"global_group.html#info/0"},{"type":"function","title":"global_group.monitor_nodes/1","doc":"Alter the calling process' subscription of node status change messages.\n\nIf `Flag` is equal to `true` the calling process starts subscribing to\nnode status change messages. If equal to `false` it stops subscribing.\n\nA process that has subscribed receives the messages `{nodeup, Node}` and\n`{nodedown, Node}` when a group node connects or disconnects, respectively.","ref":"global_group.html#monitor_nodes/1"},{"type":"function","title":"global_group.own_nodes/0","doc":"Returns the names of all group nodes, regardless of their current status.","ref":"global_group.html#own_nodes/0"},{"type":"function","title":"global_group.registered_names/1","doc":"Returns a list of all names that are globally registered on the specified node\nor in the specified global group.","ref":"global_group.html#registered_names/1"},{"type":"function","title":"global_group.send/2","doc":"Sends `Msg` to the pid represented by the globally registered name `Name`.\n\n`send/2` searches for `Name` any any global group. The global groups are searched\nin the order that they appear in the value of configuration parameter\n[`global_groups`](kernel_app.md#global_groups).\n\nIf `Name` is found, message `Msg` is sent to the corresponding pid. The pid is\nalso the return value of the function. If the name is not found, the function\nreturns `{badarg, {Name, Msg}}`.","ref":"global_group.html#send/2"},{"type":"function","title":"global_group.send/3","doc":"Equivalent to [`send(Name, Msg)`](`send/2`) except that he search is limited\nto the node or global group specified by `Where`.","ref":"global_group.html#send/3"},{"type":"function","title":"global_group.sync/0","doc":"Synchronizes the group nodes, that is, the global name servers on the group\nnodes. Also checks the names globally registered in the current global group and\nunregisters them on any known node not part of the group.\n\nIf synchronization is not possible, an error report is sent to the error logger\n(see also `m:error_logger`.\n\nReturns `{error, {'invalid global_groups definition', Bad}}` if configuration\nparameter `global_groups` has an invalid value `Bad`.","ref":"global_group.html#sync/0"},{"type":"function","title":"global_group.whereis_name/1","doc":"Searched for `Name` in any global group.\n\nThe global groups are searched in the order that they appear in the value\nof configuration parameter `global_groups`.\n\nIf `Name` is found, the corresponding pid is returned. If the name is not found,\nthe function returns `undefined`.","ref":"global_group.html#whereis_name/1"},{"type":"function","title":"global_group.whereis_name/2","doc":"Equivalent to [`whereis_name(Name)`](`whereis_name/1`) except that he search is limited\nto the node or global group specified by `Where`.","ref":"global_group.html#whereis_name/2"},{"type":"type","title":"global_group.group_name/0","doc":"","ref":"global_group.html#t:group_name/0"},{"type":"type","title":"global_group.group_tuple/0","doc":"A `GroupTuple` without `PublishType` is the same as a `GroupTuple` with\n`PublishType` equal to `normal`.","ref":"global_group.html#t:group_tuple/0"},{"type":"type","title":"global_group.info_item/0","doc":"","ref":"global_group.html#t:info_item/0"},{"type":"type","title":"global_group.name/0","doc":"A registered name.","ref":"global_group.html#t:name/0"},{"type":"type","title":"global_group.publish_type/0","doc":"A node started with command-line flag `-hidden` (see\n[`erl`](`e:erts:erl_cmd.md`)) is said to be a _hidden_ node. A hidden node\nestablishes hidden connections to nodes not part of the same global group, but\nnormal (visible) connections to nodes part of the same global group.\n\nA global group defined with `PublishType` equal to `hidden` is said to be a\nhidden global group. All nodes in a hidden global group are hidden nodes,\nwhether they are started with command-line flag `-hidden` or not.","ref":"global_group.html#t:publish_type/0"},{"type":"type","title":"global_group.sync_state/0","doc":"","ref":"global_group.html#t:sync_state/0"},{"type":"type","title":"global_group.where/0","doc":"","ref":"global_group.html#t:where/0"},{"type":"module","title":"net_adm","doc":"Various Erlang net administration routines.\n\nThis module contains various network utility functions.","ref":"net_adm.html"},{"type":"module","title":"Files - net_adm","doc":"File `.hosts.erlang` consists of a number of host names written as Erlang terms.\nIt is looked for in the current work directory, the user's home directory, and\n`$OTPROOT` (the root directory of Erlang/OTP), in that order.\n\nThe format of file `.hosts.erlang` must be one host name per line. The host\nnames must be within quotes.\n\n_Example:_\n\n```text\n'super.eua.ericsson.se'.\n'renat.eua.ericsson.se'.\n'grouse.eua.ericsson.se'.\n'gauffin1.eua.ericsson.se'.\n^ (new line)\n```","ref":"net_adm.html#module-files"},{"type":"function","title":"net_adm.dns_hostname/1","doc":"Returns the official name of `Host`, or `{error, Host}` if no such name is\nfound. See also `m:inet`.","ref":"net_adm.html#dns_hostname/1"},{"type":"function","title":"net_adm.host_file/0","doc":"Reads file `.hosts.erlang`, see section [Files](`m:net_adm#module-files`). Returns the\nhosts in this file as a list. Returns `{error, Reason}` if the file cannot be\nread or the Erlang terms on the file cannot be interpreted.","ref":"net_adm.html#host_file/0"},{"type":"function","title":"net_adm.localhost/0","doc":"Returns the name of the local host. If Erlang was started with command-line flag\n`-name`, `Name` is the fully qualified name.","ref":"net_adm.html#localhost/0"},{"type":"function","title":"net_adm.names/0","doc":"","ref":"net_adm.html#names/0"},{"type":"function","title":"net_adm.names/1","doc":"Returns the names and associated port numbers of the Erlang nodes that `epmd`\nregistered at the specified host.\n\nSimilar to `epmd -names`, see [`erts:epmd`](`e:erts:epmd_cmd.md`).\n\nReturns `{error, address}` if `epmd` is not operational.\n\n_Example:_\n\n```erlang\n(arne@dunn)1> net_adm:names().\n{ok,[{\"arne\",40262}]}\n```","ref":"net_adm.html#names/1"},{"type":"function","title":"net_adm.ping/1","doc":"Sets up a connection to `Node`. Returns `pong` if it is successful, otherwise\n`pang`.","ref":"net_adm.html#ping/1"},{"type":"function","title":"net_adm.world/0","doc":"","ref":"net_adm.html#world/0"},{"type":"function","title":"net_adm.world/1","doc":"Calls [`names(Host)`](`names/1`) for all hosts that are specified in the Erlang\nhost file `.hosts.erlang`, collects the replies, and then evaluates\n[`ping(Node)`](`ping/1`) on all those nodes. Returns the list of all nodes that\nare successfully pinged.\n\nIf `Arg == verbose`, the function writes information about which nodes it is\npinging to `stdout`.\n\nThis function can be useful when a node is started, and the names of the other\nnetwork nodes are not initially known.\n\nReturns `{error, Reason}` if `host_file/0` returns `{error, Reason}`.","ref":"net_adm.html#world/1"},{"type":"function","title":"net_adm.world_list/1","doc":"","ref":"net_adm.html#world_list/1"},{"type":"function","title":"net_adm.world_list/2","doc":"Same as [`world/0,1`](`world/1`), but the hosts are specified as argument\ninstead of being read from `.hosts.erlang`.","ref":"net_adm.html#world_list/2"},{"type":"type","title":"net_adm.verbosity/0","doc":"","ref":"net_adm.html#t:verbosity/0"},{"type":"module","title":"net_kernel","doc":"Erlang networking kernel.\n\nThe net kernel is a system process, registered as `net_kernel`, which must be\noperational for distributed Erlang to work. The purpose of this process is to\nimplement parts of the BIFs [`spawn/4`](`spawn/4`) and\n[`spawn_link/4`](`spawn_link/4`), and to provide monitoring of the network.\n\nAn Erlang node is started using command-line flag `-name` or `-sname`:\n\n```text\n$ erl -sname foobar\n```\n\nIt is also possible to call [`net_kernel:start(foobar, #{})`](`start/2`)\ndirectly from the normal Erlang shell prompt:\n\n```erlang\n1> net_kernel:start(foobar, #{name_domain => shortnames}).\n{ok,<0.64.0>}\n(foobar@gringotts)2>\n```\n\nIf the node is started with command-line flag `-sname`, the node name is\n`foobar@Host`, where `Host` is the short name of the host (not the fully\nqualified domain name). If started with flag `-name`, the node name is\n`foobar@Host`, where `Host` is the fully qualified domain name. For more\ninformation, see [`erl`](`e:erts:erl_cmd.md`).\n\nNormally, connections are established automatically when another node is\nreferenced. This functionality can be disabled by setting Kernel configuration\nparameter `dist_auto_connect` to `never`, see [`kernel(6)`](kernel_app.md). In\nthis case, connections must be established explicitly by calling\n`connect_node/1`.\n\nWhich nodes that are allowed to communicate with each other is handled by the\nmagic cookie system, see section [Distributed Erlang](`e:system:distributed.md`)\nin the Erlang Reference Manual.\n\n> #### Warning {: .warning }\n>\n> Starting a distributed node without also specifying\n> [`-proto_dist inet_tls`](`e:erts:erl_cmd.md#proto_dist`) will expose the node\n> to attacks that may give the attacker complete access to the node and in\n> extension the cluster. When using un-secure distributed nodes, make sure that\n> the network is configured to keep potential attackers out. See the\n> [Using SSL for Erlang Distribution](`e:ssl:ssl_distribution.md`) User's Guide\n> for details on how to setup a secure distributed node.","ref":"net_kernel.html"},{"type":"function","title":"net_kernel.allow/1","doc":"Permits access to the specified set of nodes.\n\nBefore the first call to [`allow/1`](`allow/1`), any node with the correct\ncookie can be connected. When [`allow/1`](`allow/1`) is called, a list of\nallowed nodes is established. Any access attempts made from (or to) nodes not in\nthat list will be rejected.\n\nSubsequent calls to [`allow/1`](`allow/1`) will add the specified nodes to the\nlist of allowed nodes. It is not possible to remove nodes from the list.\n\nDisallowing an already connected node will not cause it to be disconnected. It\nwill, however, prevent any future reconnection attempts.\n\nPassing `Nodes` as an empty list has never any affect at all.\n\nReturns `error` if any element in `Nodes` is not an atom, and `ignored` if the\nlocal node is not alive.","ref":"net_kernel.html#allow/1"},{"type":"function","title":"net_kernel.allowed/0","doc":"Returns a list of nodes that are explicitly allowed to connect to the node by calling\n[`allow/1`](`allow/1`). If empty list is returned, it means that any node using the\nsame cookie will be able to connect.","ref":"net_kernel.html#allowed/0"},{"type":"function","title":"net_kernel.connect_node/1","doc":"Establishes a connection to `Node`.\n\nReturns `true` if a connection was established or was already established or if\n`Node` is the local node itself. Returns `false` if the connection attempt failed,\nand `ignored` if the local node is not alive.","ref":"net_kernel.html#connect_node/1"},{"type":"function","title":"net_kernel.get_net_ticktime/0","doc":"Returns currently used net tick time in seconds.\n\nFor more information see the [`net_ticktime`](kernel_app.md#net_ticktime)\n`Kernel` parameter.\n\nDefined return values (`Res`):\n\n- **`NetTicktime`** - `net_ticktime` is `NetTicktime` seconds.\n\n- **`{ongoing_change_to, NetTicktime}`** - `net_kernel` is currently changing\n `net_ticktime` to `NetTicktime` seconds.\n\n- **`ignored`** - The local node is not alive.","ref":"net_kernel.html#get_net_ticktime/0"},{"type":"function","title":"net_kernel.get_state/0","doc":"Get the current state of the distribution for the local node.\n\nReturns a map with (at least) the following key-value pairs:\n\n- **`started => Started`** - Valid values for `Started`:\n\n - **`no`** - The distribution is not started. In this state none of the other\n keys below are present in the map.\n\n - **`static`** - The distribution was started with command line arguments\n [`-name`](`e:erts:erl_cmd.md#name`) or\n [`-sname`](`e:erts:erl_cmd.md#sname`).\n\n - **`dynamic`** - The distribution was started with\n [`net_kernel:start/1`](`start/1`) and can be stopped with\n [`net_kernel:stop/0`](`start/1`).\n\n- **`name => Name`** - The name of the node. Same as returned by `erlang:node/0`\n except when `name_type` is `dynamic` in which case `Name` may be `undefined`\n (instead of `nonode@nohost`).\n\n- **`name_type => NameType`** - Valid values for `NameType`:\n\n - **`static`** - The node has a static node name set by the node itself.\n\n - **`dynamic`** - The distribution was started in\n [dynamic node name](`e:system:distributed.md#dyn_node_name`) mode, and will\n get its node name assigned from the first node it connects to. If key `name`\n has value `undefined` that has not happened yet.\n\n- **`name_domain => NameDomain`** - Valid values for `NameDomain`:\n\n - **`shortnames`** - The distribution was started to use node names with a\n short host portion (not fully qualified).\n\n - **`longnames`** - The distribution was started to use node names with a long\n fully qualified host portion.","ref":"net_kernel.html#get_state/0"},{"type":"function","title":"net_kernel.getopts/2","doc":"Get one or more options for the distribution socket connected to `Node`.\n\nIf `Node` is a connected node the return value is the same as from\n[`inet:getopts(Sock, Options)`](`inet:getopts/2`) where `Sock` is the\ndistribution socket for `Node`.\n\nReturns `ignored` if the local node is not alive or `{error, noconnection}` if\n`Node` is not connected.","ref":"net_kernel.html#getopts/2"},{"type":"function","title":"net_kernel.monitor_nodes/1","doc":"","ref":"net_kernel.html#monitor_nodes/1"},{"type":"function","title":"net_kernel.monitor_nodes/2","doc":"The calling process subscribes or unsubscribes to node status change messages. A\n`nodeup` message is delivered to all subscribing processes when a new node is\nconnected, and a `nodedown` message is delivered when a node is disconnected.\n\nIf `Flag` is `true`, a new subscription is started. If `Flag` is `false`, all\nprevious subscriptions started with the same `Options` are stopped. Two option\nlists are considered the same if they contain the same set of options.\n\nDelivery guarantees of `nodeup`/`nodedown` messages:\n\n- `nodeup` messages are delivered before delivery of any signals from the remote\n node through the newly established connection.\n- `nodedown` messages are delivered after all the signals from the remote node\n over the connection have been delivered.\n- `nodeup` messages are delivered after the corresponding node appears in\n results from `erlang:nodes()`.\n- `nodedown` messages are delivered after the corresponding node has disappeared\n in results from `erlang:nodes()`.\n- As of OTP 23.0, a `nodedown` message for a connection being taken down will be\n delivered before a `nodeup` message due to a new connection to the same node.\n Prior to OTP 23.0, this was not guaranteed to be the case.\n\nThe format of the node status change messages depends on `Options`. If `Options`\nis the empty list or if `net_kernel:monitor_nodes/1` is called, the format is as\nfollows:\n\n```erlang\n{nodeup, Node} | {nodedown, Node}\n Node = node()\n```\n\nWhen `Options` is the empty map or empty list, the caller will only subscribe\nfor status change messages for visible nodes. That is, only nodes that appear in\nthe result of `erlang:nodes/0`.\n\nIf `Options` equals anything other than the empty list, the format of the status\nchange messages is as follows:\n\n```erlang\n{nodeup, Node, Info} | {nodedown, Node, Info}\n Node = node()\n Info = #{Tag => Val} | [{Tag, Val}]\n```\n\n`Info` is either a map or a list of 2-tuples. Its content depends on `Options`.\nIf `Options` is a map, `Info` will also be a map. If `Options` is a list, `Info`\nwill also be a list.\n\nWhen `Options` is a map, currently the following associations are allowed:\n\n- **`connection_id => boolean()`** - If the value of the association equals\n `true`, a `connection_id => ConnectionId` association will be included in the\n `Info` map where `ConnectionId` is the connection identifier of the connection\n coming up or going down. For more info about this connection identifier see\n the documentation of [erlang:nodes/2](`m:erlang#connection_id`).\n\n- **`node_type => NodeType`** - Valid values for `NodeType`:\n\n - **`visible`** - Subscribe to node status change messages for visible nodes\n only. The association `node_type => visible` will be included in the `Info`\n map.\n\n - **`hidden`** - Subscribe to node status change messages for hidden nodes\n only. The association `node_type => hidden` will be included in the `Info`\n map.\n\n - **`all`** - Subscribe to node status change messages for both visible and\n hidden nodes. The association `node_type => visible | hidden` will be\n included in the `Info` map.\n\n If no `node_type => NodeType` association is included in the `Options` map,\n the caller will subscribe for status change messages for visible nodes only,\n but _no_ `node_type => visible` association will be included in the `Info`\n map.\n\n- **`nodedown_reason => boolean()`** - If the value of the association equals\n `true`, a `nodedown_reason => Reason` association will be included in the\n `Info` map for `nodedown` messages.\n\n [](){: #nodedown_reasons } `Reason` can, depending on which distribution\n module or process that is used, be any term, but for the standard TCP\n distribution module it is one of the following:\n\n - **`connection_setup_failed`** - The connection setup failed (after `nodeup`\n messages were sent).\n\n - **`no_network`** - No network is available.\n\n - **`net_kernel_terminated`** - The `net_kernel` process terminated.\n\n - **`shutdown`** - Unspecified connection shutdown.\n\n - **`connection_closed`** - The connection was closed.\n\n - **`disconnect`** - The connection was disconnected (forced from the current\n node).\n\n - **`net_tick_timeout`** - Net tick time-out.\n\n - **`send_net_tick_failed`** - Failed to send net tick over the connection.\n\n - **`get_status_failed`** - Status information retrieval from the `Port`\n holding the connection failed.\n\nWhen `Options` is a list, currently `ListOption` can be one of the following:\n\n- **`connection_id`** - A `{connection_id, ConnectionId}` tuple will be included\n in `Info` where `ConnectionId` is the connection identifier of the connection\n coming up or going down. For more info about this connection identifier see\n the documentation of [erlang:nodes/2](`m:erlang#connection_id`).\n\n- **`{node_type, NodeType}`** - Valid values for `NodeType`:\n\n - **`visible`** - Subscribe to node status change messages for visible nodes\n only. The tuple `{node_type, visible}` will be included in the `Info` list.\n\n - **`hidden`** - Subscribe to node status change messages for hidden nodes\n only. The tuple `{node_type, hidden}` will be included in the `Info` list.\n\n - **`all`** - Subscribe to node status change messages for both visible and\n hidden nodes. The tuple `{node_type, visible | hidden}` will be included in\n the `Info` list.\n\n If no `{node_type, NodeType}` option has been given. The caller will subscribe\n for status change messages for visible nodes only, but _no_\n `{node_type, visible}` tuple will be included in the `Info` list.\n\n- **`nodedown_reason`** - The tuple `{nodedown_reason, Reason}` will be included\n in the `Info` list for `nodedown` messages.\n\n See the documentation of the\n [`nodedown_reason => boolean()`](`m:net_kernel#nodedown_reasons`) association\n above for information about possible `Reason` values.\n\nExample:\n\n```erlang\n(a@localhost)1> net_kernel:monitor_nodes(true, #{connection_id=>true, node_type=>all, nodedown_reason=>true}).\nok\n(a@localhost)2> flush().\nShell got {nodeup,b@localhost,\n #{connection_id => 3067552,node_type => visible}}\nShell got {nodeup,c@localhost,\n #{connection_id => 13892107,node_type => hidden}}\nShell got {nodedown,b@localhost,\n #{connection_id => 3067552,node_type => visible,\n nodedown_reason => connection_closed}}\nShell got {nodedown,c@localhost,\n #{connection_id => 13892107,node_type => hidden,\n nodedown_reason => net_tick_timeout}}\nShell got {nodeup,b@localhost,\n #{connection_id => 3067553,node_type => visible}}\nok\n(a@localhost)3>\n```","ref":"net_kernel.html#monitor_nodes/2"},{"type":"function","title":"net_kernel.set_net_ticktime/1","doc":"","ref":"net_kernel.html#set_net_ticktime/1"},{"type":"function","title":"net_kernel.set_net_ticktime/2","doc":"Sets `net_ticktime` (see [`kernel(6)`](kernel_app.md)) to `NetTicktime` seconds.\n`TransitionPeriod` defaults to `60`.\n\nSome definitions:\n\n- **Minimum transition traffic interval (`MTTI`)** -\n `minimum(NetTicktime, PreviousNetTicktime)*1000 div 4` milliseconds.\n\n- **Transition period** - The time of the least number of consecutive `MTTI`s to\n cover `TransitionPeriod` seconds following the call to\n [`set_net_ticktime/2`](`set_net_ticktime/2`) (that is,\n ((`TransitionPeriod*1000 - 1) div MTTI + 1)*MTTI` milliseconds).\n\nIf `NetTicktime #### Note {: .info }\n>\n> The `net_ticktime` changes must be initiated on all nodes in the network (with\n> the same `NetTicktime`) before the end of any transition period on any node;\n> otherwise connections can erroneously be disconnected.\n\nReturns one of the following:\n\n- **`unchanged`** - `net_ticktime` already has the value of `NetTicktime` and is\n left unchanged.\n\n- **`change_initiated`** - `net_kernel` initiated the change of `net_ticktime`\n to `NetTicktime` seconds.\n\n- **`{ongoing_change_to, NewNetTicktime}`** - The request is _ignored_ because\n `net_kernel` is busy changing `net_ticktime` to `NewNetTicktime` seconds.","ref":"net_kernel.html#set_net_ticktime/2"},{"type":"function","title":"net_kernel.setopts/2","doc":"Set one or more options for distribution sockets. Argument `Node` can be either\none node name or the atom `new` to affect the distribution sockets of all future\nconnected nodes.\n\nThe return value is the same as from `inet:setopts/2` or `{error, noconnection}`\nif `Node` is not a connected node or `new`.\n\nIf `Node` is `new` the `Options` will then also be added to kernel configuration\nparameters [inet_dist_listen_options](kernel_app.md#inet_dist_listen_options)\nand [inet_dist_connect_options](kernel_app.md#inet_dist_connect_options).\n\nReturns `ignored` if the local node is not alive.","ref":"net_kernel.html#setopts/2"},{"type":"function","title":"net_kernel.start/1","doc":"Turns a non-distributed node into a distributed node by starting `net_kernel`\nand other necessary processes.\n\n`Options` list can only be exactly one of the following lists (order is\nimporant):\n\n- **`[Name]`** - The same as `net_kernel:start([Name, longnames, 15000])`.\n\n- **`[Name, NameDomain]`** - The same as\n `net_kernel:start([Name, NameDomain, 15000])`.\n\n- **`[Name, NameDomain, TickTime]`** - The same as\n [`net_kernel:start(Name, #{name_domain => NameDomain, net_ticktime => ((TickTime*4-1) div 1000) + 1, net_tickintensity => 4})`](`start/2`).\n Note that `TickTime` is _not_ the same as net tick time expressed in\n milliseconds. `TickTime` is the time between ticks when net tick intensity\n equals `4`.","ref":"net_kernel.html#start/1"},{"type":"function","title":"net_kernel.start/2","doc":"Turns a non-distributed node into a distributed node by starting `net_kernel`\nand other necessary processes.\n\nIf `Name` is set to _`undefined`_ the distribution will be started to request a\ndynamic node name from the first node it connects to. See\n[Dynamic Node Name](`e:system:distributed.md#dyn_node_name`). Setting `Name` to\n`undefined` implies options `dist_listen => false` and `hidden => true`.\n\nCurrently supported options:\n\n- **`name_domain => NameDomain`** - Determines the host name part of the node\n name. If `NameDomain` equals `longnames`, fully qualified domain names will be\n used which also is the default. If `NameDomain` equals `shortnames`, only the\n short name of the host will be used.\n\n- **`net_ticktime => NetTickTime`** - _Net tick time_ to use in seconds.\n Defaults to the value of the [`net_ticktime`](kernel_app.md#net_ticktime)\n `kernel(6)` parameter. For more information about _net tick time_, see the\n `kernel` parameter. However, note that if the value of the `kernel` parameter\n is invalid, it will silently be replaced by a valid value, but if an invalid\n `NetTickTime` value is passed as option value to this function, the call will\n fail.\n\n- **`net_tickintensity => NetTickIntensity`** - _Net tick intensity_ to use.\n Defaults to the value of the\n [`net_tickintensity`](kernel_app.md#net_tickintensity) `kernel(6)` parameter.\n For more information about _net tick intensity_, see the `kernel` parameter.\n However, note that if the value of the `kernel` parameter is invalid, it will\n silently be replaced by a valid value, but if an invalid `NetTickIntensity`\n value is passed as option value to this function, the call will fail.\n\n- **`dist_listen => boolean()`** - Enable or disable listening for incoming\n connections. Defaults to the value of the\n [`-dist_listen`](`e:erts:erl_cmd.md#dist_listen`) `erl` command line argument.\n Note that `dist_listen => false` implies `hidden => true`.\n\n If `undefined` has been passed as `Name`, the `dist_listen` option will be\n overridden with `dist_listen => false`.\n\n- **`hidden => boolean()`** - Enable or disable hidden node. Defaults to `true`\n if the [`-hidden`](`e:erts:erl_cmd.md#hidden`) `erl` command line argument has\n been passed; otherwise `false`.\n\n If `undefined` has been passed as `Name`, or the option `dist_listen` equals\n `false`, the `hidden` option will be overridden with `hidden => true`.","ref":"net_kernel.html#start/2"},{"type":"function","title":"net_kernel.stop/0","doc":"Turns a distributed node into a non-distributed node.\n\nFor other nodes in the network, this is the same as the node going down.\nOnly possible when the net kernel was started using `start/2`, otherwise\n`{error, not_allowed}` is returned. Returns `{error, not_found}` if the local\nnode is not alive.","ref":"net_kernel.html#stop/0"},{"type":"type","title":"net_kernel.connection_state/0","doc":"","ref":"net_kernel.html#t:connection_state/0"},{"type":"type","title":"net_kernel.connection_type/0","doc":"","ref":"net_kernel.html#t:connection_type/0"},{"type":"module","title":"pg","doc":"Distributed named process groups.\n\nThis module implements process groups. A message can be sent to one, some, or\nall group members.\n\nUp until OTP 17 there used to exist an experimental `pg` module in `stdlib`.\nThis `pg` module is not the same module as that experimental `pg` module, and\nonly share the same module name.\n\nA group of processes can be accessed by a common name. For example, if there is\na group named `foobar`, there can be a set of processes (which can be located on\ndifferent nodes) that are all members of the group `foobar`. There are no\nspecial functions for sending a message to the group. Instead, client functions\nare to be written with the functions `get_members/1` and `get_local_members/1`\nto determine which processes are members of the group. Then the message can be\nsent to one or more group members.\n\nIf a member terminates, it is automatically removed from the group.\n\nA process may join multiple groups. It may join the same group multiple times.\nIt is only allowed to join processes running on local node.\n\nProcess Groups implement strong eventual consistency. Process Groups membership\nview may temporarily diverge. For example, when processes on `node1` and `node2`\njoin concurrently, `node3` and `node4` may receive updates in a different order.\n\nMembership view is not transitive. If `node1` is not directly connected to\n`node2`, they will not see each other groups. But if both are connected to\n`node3`, `node3` will have the full view.\n\nGroups are automatically created when any process joins, and are removed when\nall processes leave the group. Non-existing group is considered empty\n(containing no processes).\n\nProcess groups can be organised into multiple scopes. Scopes are completely\nindependent of each other. A process may join any number of groups in any number\nof scopes. Scopes are designed to decouple single mesh into a set of overlay\nnetworks, reducing amount of traffic required to propagate group membership\ninformation. Default scope `pg` is started automatically when\n[Kernel](kernel_app.md#start_pg) is configured to do so.\n\n> #### Note {: .info }\n>\n> Scope name is used to register process locally, and to name an ETS table. If\n> there is another process registered under this name, or another ETS table\n> exists, scope fails to start.\n>\n> Local membership is not preserved if scope process exits and restarts.\n>\n> A scope can be kept local-only by using a scope name that is unique\n> cluster-wide, e.g. the node name: `pg:start_link(node()).`","ref":"pg.html"},{"type":"module","title":"See Also - pg","doc":"[Kernel](kernel_app.md)","ref":"pg.html#module-see-also"},{"type":"function","title":"pg.demonitor/1","doc":"","ref":"pg.html#demonitor/1"},{"type":"function","title":"pg.demonitor/2","doc":"Unsubscribes the caller from updates (scope or group). Flushes all outstanding\nupdates that were already in the message queue of the calling process.","ref":"pg.html#demonitor/2"},{"type":"function","title":"pg.get_local_members/1","doc":"","ref":"pg.html#get_local_members/1"},{"type":"function","title":"pg.get_local_members/2","doc":"Returns all processes running on the local node in the group `Group`. Processes\nare returned in no specific order. This function is optimised for speed.","ref":"pg.html#get_local_members/2"},{"type":"function","title":"pg.get_members/1","doc":"","ref":"pg.html#get_members/1"},{"type":"function","title":"pg.get_members/2","doc":"Returns all processes in the group `Group`. Processes are returned in no\nspecific order. This function is optimised for speed.","ref":"pg.html#get_members/2"},{"type":"function","title":"pg.join/2","doc":"","ref":"pg.html#join/2"},{"type":"function","title":"pg.join/3","doc":"Joins single process or multiple processes to the group `Group`. A process can\njoin a group many times and must then leave the group the same number of times.\n\n`PidOrPids` may contain the same process multiple times.","ref":"pg.html#join/3"},{"type":"function","title":"pg.leave/2","doc":"","ref":"pg.html#leave/2"},{"type":"function","title":"pg.leave/3","doc":"Makes the process `PidOrPids` leave the group `Group`. If the process is not a\nmember of the group, `not_joined` is returned.\n\nWhen list of processes is passed as `PidOrPids`, function returns `not_joined`\nonly when all processes of the list are not joined.","ref":"pg.html#leave/3"},{"type":"function","title":"pg.monitor/1","doc":"","ref":"pg.html#monitor/1"},{"type":"function","title":"pg.monitor/2","doc":"Subscribes the caller to updates for the specified group.\n\nReturns list of processes currently in the group, and a reference to match the\nupcoming notifications.\n\nSee `monitor_scope/0` for the update message structure.","ref":"pg.html#monitor/2"},{"type":"function","title":"pg.monitor_scope/0","doc":"","ref":"pg.html#monitor_scope/0"},{"type":"function","title":"pg.monitor_scope/1","doc":"Subscribes the caller to updates from the specified scope.\n\nReturns content of the entire scope and a reference to match the upcoming\nnotifications.\n\nWhenever any group membership changes, an update message is sent to the\nsubscriber:\n\n```erlang\n{Ref, join, Group, [JoinPid1, JoinPid2]}\n```\n\n```erlang\n{Ref, leave, Group, [LeavePid1]}\n```","ref":"pg.html#monitor_scope/1"},{"type":"function","title":"pg.start/1","doc":"Starts additional scope.","ref":"pg.html#start/1"},{"type":"function","title":"pg.start_link/0","doc":"Starts the default `pg` scope within supervision tree.\n\nKernel may be configured to do it automatically by setting\nthe Kernel configuration parameter [`start_pg`](kernel_app.md#start_pg).","ref":"pg.html#start_link/0"},{"type":"function","title":"pg.start_link/1","doc":"Equivalent to [`start(Scope)`](`start/1`), except that it also creates\na `link/1` with the calling process.","ref":"pg.html#start_link/1"},{"type":"function","title":"pg.which_groups/0","doc":"","ref":"pg.html#which_groups/0"},{"type":"function","title":"pg.which_groups/1","doc":"Returns a list of all known groups.","ref":"pg.html#which_groups/1"},{"type":"type","title":"pg.group/0","doc":"The identifier of a process group.","ref":"pg.html#t:group/0"},{"type":"module","title":"rpc","doc":"Remote Procedure Call services.\n\nThis module contains services similar to Remote Procedure Calls. It also\ncontains broadcast facilities and parallel evaluators. A remote procedure call\nis a method to call a function on a remote node and collect the answer. It is\nused for collecting information on a remote node, or for running a function with\nsome specific side effects on the remote node.\n\n> #### Note {: .info }\n>\n> `rpc:call/4` and friends makes it quite hard to distinguish between successful\n> results, raised exceptions, and other errors. This cannot be changed due to\n> compatibility reasons. As of OTP 23, a new module `m:erpc` was introduced in\n> order to provide an API that makes it possible to distinguish between the\n> different results. The `erpc` module provides a subset (however, the central\n> subset) of the functionality available in the `rpc` module. The `erpc`\n> implementation also provides a more scalable implementation with better\n> performance than the original `rpc` implementation. However, since the\n> introduction of `erpc`, the `rpc` module implements large parts of its central\n> functionality using `erpc`, so the `rpc` module won't not suffer scalability\n> wise and performance wise compared to `erpc`.\n\n> #### Note {: .info }\n>\n> For some important information about distributed signals, see the\n> [Blocking Signaling Over Distribution](`e:system:ref_man_processes.md#blocking-signaling-over-distribution`)\n> section in the _Processes_ chapter of the _Erlang Reference Manual_. Blocking\n> signaling can, for example, cause timeouts in `rpc` to be significantly\n> delayed.","ref":"rpc.html"},{"type":"function","title":"rpc.abcast/2","doc":"Equivalent to [`abcast([node()|nodes()], Name, Msg)`](`abcast/3`).","ref":"rpc.html#abcast/2"},{"type":"function","title":"rpc.abcast/3","doc":"Broadcasts the message `Msg` asynchronously to the registered process `Name` on\nthe specified nodes.","ref":"rpc.html#abcast/3"},{"type":"function","title":"rpc.async_call/4","doc":"Implements _call streams with promises_, a type of RPC that does not suspend the\ncaller until the result is finished. Instead, a key is returned, which can be\nused later to collect the value. The key can be viewed as a promise to deliver\nthe answer.\n\nIn this case, the key `Key` is returned, which can be used in a subsequent call\nto `yield/1` or [`nb_yield/1,2`](`nb_yield/1`) to retrieve the value of\nevaluating [`apply(Module, Function, Args)`](`apply/3`) on node `Node`.\n\n> #### Note {: .info }\n>\n> If you want the ability to distinguish between results, you may want to\n> consider using the [`erpc:send_request()`](`erpc:send_request/4`) function\n> from the `erpc` module instead. This also gives you the ability retrieve the\n> results in other useful ways.\n\n> #### Note {: .info }\n>\n> `yield/1` and [`nb_yield/1,2`](`nb_yield/1`) must be called by the same\n> process from which this function was made otherwise they will never yield\n> correctly.\n\n> #### Note {: .info }\n>\n> You cannot make _any_ assumptions about the process that will perform the\n> `apply()`. It may be an `rpc` server, another server, or a freshly spawned\n> process.","ref":"rpc.html#async_call/4"},{"type":"function","title":"rpc.block_call/4","doc":"The same as calling\n[`rpc:block_call(Node, Module, Function, Args, infinity)`](`block_call/5`).","ref":"rpc.html#block_call/4"},{"type":"function","title":"rpc.block_call/5","doc":"The same as calling\n[`rpc:call(Node, Module, Function, Args, Timeout)`](`call/5`) with the exception\nthat it also blocks other `rpc:block_call/5` operations from executing\nconcurrently on the node `Node`.\n\n> #### Warning {: .warning }\n>\n> Note that it also blocks other operations than just `rpc:block_call/5`\n> operations, so use it with care.","ref":"rpc.html#block_call/5"},{"type":"function","title":"rpc.call/4","doc":"Evaluates [`apply(Module, Function, Args)`](`apply/3`) on node `Node` and\nreturns the corresponding value `Res`, or `{badrpc, Reason}` if the call fails.\nThe same as calling\n[`rpc:call(Node, Module, Function, Args, infinity)`](`call/5`).","ref":"rpc.html#call/4"},{"type":"function","title":"rpc.call/5","doc":"Evaluates [`apply(Module, Function, Args)`](`apply/3`) on node `Node` and\nreturns the corresponding value `Res`, or `{badrpc, Reason}` if the call fails.\n`Timeout` is a time-out value in milliseconds. If the call times out, `Reason`\nis `timeout`.\n\nIf the reply arrives after the call times out, no message contaminates the\ncaller's message queue.\n\n> #### Note {: .info }\n>\n> If you want the ability to distinguish between results, you may want to\n> consider using the [`erpc:call()`](`erpc:call/4`) function from the `erpc`\n> module instead.\n\n> #### Note {: .info }\n>\n> Here follows the details of what exactly is returned.\n>\n> `{badrpc, Reason}` will be returned in the following circumstances:\n>\n> - The called function fails with an `exit` exception.\n> - The called function fails with an `error` exception.\n> - The called function returns a term that matches `{'EXIT', _}`.\n> - The called function `throws` a term that matches `{'EXIT', _}`.\n>\n> `Res` is returned in the following circumstances:\n>\n> - The called function returns normally with a term that does **not** match\n> `{'EXIT',_}`.\n> - The called function `throw`s a term that does **not** match `{'EXIT',_}`.\n\n> #### Note {: .info }\n>\n> You cannot make _any_ assumptions about the process that will perform the\n> `apply()`. It may be the calling process itself, an `rpc` server, another\n> server, or a freshly spawned process.","ref":"rpc.html#call/5"},{"type":"function","title":"rpc.cast/4","doc":"Evaluates [`apply(Module, Function, Args)`](`apply/3`) on node `Node`. No\nresponse is delivered and the calling process is not suspended until the\nevaluation is complete, as is the case with [`call/4,5`](`call/4`).\n\n> #### Note {: .info }\n>\n> You cannot make _any_ assumptions about the process that will perform the\n> `apply()`. It may be an `rpc` server, another server, or a freshly spawned\n> process.","ref":"rpc.html#cast/4"},{"type":"function","title":"rpc.eval_everywhere/3","doc":"Equivalent to\n[`eval_everywhere([node()|nodes()], Module, Function, Args)`](`eval_everywhere/4`).","ref":"rpc.html#eval_everywhere/3"},{"type":"function","title":"rpc.eval_everywhere/4","doc":"Evaluates [`apply(Module, Function, Args)`](`apply/3`) on the specified nodes.\nNo answers are collected.","ref":"rpc.html#eval_everywhere/4"},{"type":"function","title":"rpc.multi_server_call/2","doc":"Equivalent to\n[`multi_server_call([node()|nodes()], Name, Msg)`](`multi_server_call/3`).","ref":"rpc.html#multi_server_call/2"},{"type":"function","title":"rpc.multi_server_call/3","doc":"Can be used when interacting with servers called `Name` on the specified nodes.\nIt is assumed that the servers receive messages in the format `{From, Msg}` and\nreply using `From ! {Name, Node, Reply}`, where `Node` is the name of the node\nwhere the server is located. The function returns `{Replies, BadNodes}`, where\n`Replies` is a list of all `Reply` values, and `BadNodes` is one of the\nfollowing:\n\n- A list of the nodes that do not exist\n- A list of the nodes where the server does not exist\n- A list of the nodes where the server terminated before sending any reply.","ref":"rpc.html#multi_server_call/3"},{"type":"function","title":"rpc.multicall/3","doc":"Equivalent to\n[`multicall([node()|nodes()], Module, Function, Args, infinity)`](`multicall/5`).","ref":"rpc.html#multicall/3"},{"type":"function","title":"rpc.multicall/4","doc":"Equivalent to\n[`multicall(Nodes, Module, Function, Args, infinity)`](`multicall/5`).\n\nEquivalent to\n[`multicall([node()|nodes()], Module, Function, Args, Timeout)`](`multicall/5`).","ref":"rpc.html#multicall/4"},{"type":"function","title":"rpc.multicall/5","doc":"In contrast to an RPC, a multicall is an RPC that is sent concurrently from one\nclient to multiple servers. This is useful for collecting information from a set\nof nodes, or for calling a function on a set of nodes to achieve some side\neffects. It is semantically the same as iteratively making a series of RPCs on\nall the nodes, but the multicall is faster, as all the requests are sent at the\nsame time and are collected one by one as they come back.\n\nThe function evaluates [`apply(Module, Function, Args)`](`apply/3`) on the\nspecified nodes and collects the answers. It returns `{ResL, BadNodes}`, where\n`BadNodes` is a list of the nodes that do not exist, and `ResL` is a list of the\nreturn values, or `{badrpc, Reason}` for failing calls. `Timeout` is a time\n(integer) in milliseconds, or `infinity`.\n\nThe following example is useful when new object code is to be loaded on all\nnodes in the network, and indicates some side effects that RPCs can produce:\n\n```erlang\n%% Find object code for module Mod\n{Mod, Bin, File} = code:get_object_code(Mod),\n\n%% and load it on all nodes including this one\n{ResL, _} = rpc:multicall(code, load_binary, [Mod, File, Bin]),\n\n%% and then maybe check the ResL list.\n```\n\n> #### Note {: .info }\n>\n> If you want the ability to distinguish between results, you may want to\n> consider using the [`erpc:multicall()`](`erpc:multicall/4`) function from the\n> `erpc` module instead.\n\n> #### Note {: .info }\n>\n> You cannot make _any_ assumptions about the process that will perform the\n> `apply()`. It may be the calling process itself, an `rpc` server, another\n> server, or a freshly spawned process.","ref":"rpc.html#multicall/5"},{"type":"function","title":"rpc.nb_yield/1","doc":"Equivalent to [`nb_yield(Key, 0)`](`nb_yield/2`).","ref":"rpc.html#nb_yield/1"},{"type":"function","title":"rpc.nb_yield/2","doc":"Non-blocking version of `yield/1`. It returns the tuple `{value, Val}` when the\ncomputation is finished, or `timeout` when `Timeout` milliseconds has elapsed.\n\nSee the note in `call/4` for more details of Val.\n\n> #### Note {: .info }\n>\n> This function must be called by the same process from which `async_call/4` was\n> made otherwise it will only return `timeout`.","ref":"rpc.html#nb_yield/2"},{"type":"function","title":"rpc.parallel_eval/1","doc":"Evaluates, for every tuple in `FuncCalls`,\n[`apply(Module, Function, Args)`](`apply/3`) on some node in the network.\nReturns the list of return values, in the same order as in `FuncCalls`.","ref":"rpc.html#parallel_eval/1"},{"type":"function","title":"rpc.pinfo/1","doc":"Location transparent version of the BIF `erlang:process_info/1` in ERTS.","ref":"rpc.html#pinfo/1"},{"type":"function","title":"rpc.pinfo/2","doc":"Location transparent version of the BIF `erlang:process_info/2` in ERTS.","ref":"rpc.html#pinfo/2"},{"type":"function","title":"rpc.pmap/3","doc":"Evaluates [`apply(Module, Function, [Elem|ExtraArgs])`](`apply/3`) for every\nelement `Elem` in `List1`, in parallel. Returns the list of return values, in\nthe same order as in `List1`.","ref":"rpc.html#pmap/3"},{"type":"function","title":"rpc.sbcast/2","doc":"Equivalent to [`sbcast([node()|nodes()], Name, Msg)`](`sbcast/3`).","ref":"rpc.html#sbcast/2"},{"type":"function","title":"rpc.sbcast/3","doc":"Broadcasts the message `Msg` synchronously to the registered process `Name` on\nthe specified nodes.\n\nReturns `{GoodNodes, BadNodes}`, where `GoodNodes` is the list of nodes that\nhave `Name` as a registered process.\n\nThe function is synchronous in the sense that it is known that all servers have\nreceived the message when the call returns. It is not possible to know that the\nservers have processed the message.\n\nAny further messages sent to the servers, after this function has returned, are\nreceived by all servers after this message.","ref":"rpc.html#sbcast/3"},{"type":"function","title":"rpc.server_call/4","doc":"Can be used when interacting with a server called `Name` on node `Node`. It is\nassumed that the server receives messages in the format `{From, Msg}` and\nreplies using `From ! {ReplyWrapper, Node, Reply}`. This function makes such a\nserver call and ensures that the entire call is packed into an atomic\ntransaction, which either succeeds or fails. It never hangs, unless the server\nitself hangs.\n\nThe function returns the answer `Reply` as produced by the server `Name`, or\n`{error, Reason}`.","ref":"rpc.html#server_call/4"},{"type":"function","title":"rpc.yield/1","doc":"Returns the promised answer from a previous `async_call/4`. If the answer is\navailable, it is returned immediately. Otherwise, the calling process is\nsuspended until the answer arrives from `Node`.\n\n> #### Note {: .info }\n>\n> This function must be called by the same process from which `async_call/4` was\n> made otherwise it will never return.\n\nSee the note in `call/4` for more details of the return value.","ref":"rpc.html#yield/1"},{"type":"opaque","title":"rpc.key/0","doc":"Opaque value returned by `async_call/4`.","ref":"rpc.html#t:key/0"},{"type":"module","title":"file","doc":"File interface module.\n\nThis module provides an interface to the file system.\n\n> #### Warning {: .warning }\n>\n> File operations are only guaranteed to appear atomic when going through the\n> same file server. A NIF or other OS process may observe intermediate steps on\n> certain operations on some operating systems, eg. renaming an existing file on\n> Windows, or [`write_file_info/2`](`write_file_info/2`) on any OS at the time\n> of writing.\n\nRegarding filename encoding, the Erlang VM can operate in two modes. The current\nmode can be queried using function `native_name_encoding/0`. It returns `latin1`\nor `utf8`.\n\nIn `latin1` mode, the Erlang VM does not change the encoding of filenames. In\n`utf8` mode, filenames can contain Unicode characters greater than 255 and the\nVM converts filenames back and forth to the native filename encoding (usually\nUTF-8, but UTF-16 on Windows).\n\nThe default mode depends on the operating system. Windows, MacOS X and Android\nenforce consistent filename encoding and therefore the VM uses `utf8` mode.\n\nOn operating systems with transparent naming (for example, all Unix systems\nexcept MacOS X), default is `utf8` if the terminal supports UTF-8, otherwise\n`latin1`. The default can be overridden using `+fnl` (to force `latin1` mode) or\n`+fnu` (to force `utf8` mode) when starting [`erl`](`e:erts:erl_cmd.md`).\n\nOn operating systems with transparent naming, files can be inconsistently named,\nfor example, some files are encoded in UTF-8 while others are encoded in ISO\nLatin-1. The concept of _raw filenames_ is introduced to handle file systems\nwith inconsistent naming when running in `utf8` mode.\n\nA _raw filename_ is a filename specified as a binary. The Erlang VM does not\ntranslate a filename specified as a binary on systems with transparent naming.\n\nWhen running in `utf8` mode, functions `list_dir/1` and `read_link/1` never\nreturn raw filenames. To return all filenames including raw filenames, use\nfunctions [`list_dir_all/1`](`m:file#list_dir_all`) and\n[`read_link_all/1`](`m:file#read_link_all`).\n\nSee also section\n[Notes About Raw Filenames](`e:stdlib:unicode_usage.md#notes-about-raw-filenames`)\nin the STDLIB User's Guide.\n\n> #### Note {: .info }\n>\n> File operations used to accept filenames containing null characters (integer\n> value zero). This caused the name to be truncated and in some cases arguments\n> to primitive operations to be mixed up. Filenames containing null characters\n> inside the filename are now _rejected_ and will cause primitive file\n> operations fail.","ref":"file.html"},{"type":"module","title":"POSIX Error Codes - file","doc":"- `eacces` \\- Permission denied\n- `eagain` \\- Resource temporarily unavailable\n- `ebadf` \\- Bad file number\n- `ebusy` \\- File busy\n- `edquot` \\- Disk quota exceeded\n- `eexist` \\- File already exists\n- `efault` \\- Bad address in system call argument\n- `efbig` \\- File too large\n- `eintr` \\- Interrupted system call\n- `einval` \\- Invalid argument\n- `eio` \\- I/O error\n- `eisdir` \\- Illegal operation on a directory\n- `eloop` \\- Too many levels of symbolic links\n- `emfile` \\- Too many open files\n- `emlink` \\- Too many links\n- `enametoolong` \\- Filename too long\n- `enfile` \\- File table overflow\n- `enodev` \\- No such device\n- `enoent` \\- No such file or directory\n- `enomem` \\- Not enough memory\n- `enospc` \\- No space left on device\n- `enotblk` \\- Block device required\n- `enotdir` \\- Not a directory\n- `enotsup` \\- Operation not supported\n- `enxio` \\- No such device or address\n- `eperm` \\- Not owner\n- `epipe` \\- Broken pipe\n- `erofs` \\- Read-only file system\n- `espipe` \\- Invalid seek\n- `esrch` \\- No such process\n- `estale` \\- Stale remote file handle\n- `exdev` \\- Cross-device link","ref":"file.html#module-posix-error-codes"},{"type":"module","title":"Performance - file","doc":"For increased performance, raw files are recommended.\n\nA normal file is really a process so it can be used as an I/O device (see\n`m:io`). Therefore, when data is written to a normal file, the sending of the\ndata to the file process, copies all data that are not binaries. Opening the\nfile in binary mode and writing binaries is therefore recommended. If the file\nis opened on another node, or if the file server runs as slave to the file\nserver of another node, also binaries are copied.\n\n> #### Note {: .info }\n>\n> Raw files use the file system of the host machine of the node. For normal\n> files (non-raw), the file server is used to find the files, and if the node is\n> running its file server as slave to the file server of another node, and the\n> other node runs on some other host machine, they can have different file\n> systems. However, this is seldom a problem.\n\n`open/2` can be given the options `delayed_write` and `read_ahead` to turn on\ncaching, which will reduce the number of operating system calls and greatly\nimprove performance for small reads and writes. However, the overhead won't\ndisappear completely and it's best to keep the number of file operations to a\nminimum. As a contrived example, the following function writes 4MB in 2.5\nseconds when tested:\n\n```erlang\ncreate_file_slow(Name) ->\n {ok, Fd} = file:open(Name, [raw, write, delayed_write, binary]),\n create_file_slow_1(Fd, 4 bsl 20),\n file:close(Fd).\n\ncreate_file_slow_1(_Fd, 0) ->\n ok;\ncreate_file_slow_1(Fd, M) ->\n ok = file:write(Fd, <<0>>),\n create_file_slow_1(Fd, M - 1).\n```\n\nThe following functionally equivalent code writes 128 bytes per call to\n`write/2` and so does the same work in 0.08 seconds, which is roughly 30 times\nfaster:\n\n```erlang\ncreate_file(Name) ->\n {ok, Fd} = file:open(Name, [raw, write, delayed_write, binary]),\n create_file_1(Fd, 4 bsl 20),\n file:close(Fd),\n ok.\n\ncreate_file_1(_Fd, 0) ->\n ok;\ncreate_file_1(Fd, M) when M >= 128 ->\n ok = file:write(Fd, <<0:(128)/unit:8>>),\n create_file_1(Fd, M - 128);\ncreate_file_1(Fd, M) ->\n ok = file:write(Fd, <<0:(M)/unit:8>>),\n create_file_1(Fd, M - 1).\n```\n\nWhen writing data it's generally more efficient to write a list of binaries\nrather than a list of integers. It is not needed to flatten a deep list before\nwriting. On Unix hosts, scatter output, which writes a set of buffers in one\noperation, is used when possible. In this way\n[`write(FD, [Bin1, Bin2 | Bin3])`](`write/2`) writes the contents of the\nbinaries without copying the data at all, except for perhaps deep down in the\noperating system kernel.\n\n> #### Warning {: .warning }\n>\n> If an error occurs when accessing an open file with module `m:io`, the process\n> handling the file exits. The dead file process can hang if a process tries to\n> access it later. This will be fixed in a future release.","ref":"file.html#module-performance"},{"type":"module","title":"See Also - file","doc":"`m:filename`","ref":"file.html#module-see-also"},{"type":"function","title":"file.advise/4","doc":"[`advise/4`](`advise/4`) can be used to announce an intention to access file\ndata in a specific pattern in the future, thus allowing the operating system to\nperform appropriate optimizations.\n\nOn some platforms, this function might have no effect.","ref":"file.html#advise/4"},{"type":"function","title":"file.allocate/3","doc":"[`allocate/3`](`allocate/3`) can be used to preallocate space for a file.\n\nThis function only succeeds in platforms that provide this feature.","ref":"file.html#allocate/3"},{"type":"function","title":"file.change_group/2","doc":"Changes group of a file. See `write_file_info/2`.","ref":"file.html#change_group/2"},{"type":"function","title":"file.change_mode/2","doc":"Changes permissions of a file. See `write_file_info/2`.","ref":"file.html#change_mode/2"},{"type":"function","title":"file.change_owner/2","doc":"Changes owner of a file. See `write_file_info/2`.","ref":"file.html#change_owner/2"},{"type":"function","title":"file.change_owner/3","doc":"Changes owner and group of a file. See `write_file_info/2`.","ref":"file.html#change_owner/3"},{"type":"function","title":"file.change_time/2","doc":"Changes the modification and access times of a file. See `write_file_info/2`.","ref":"file.html#change_time/2"},{"type":"function","title":"file.change_time/3","doc":"Changes the modification and last access times of a file. See\n`write_file_info/2`.","ref":"file.html#change_time/3"},{"type":"function","title":"file.close/1","doc":"Closes the file referenced by `IoDevice`. It mostly returns `ok`, except for\nsome severe errors such as out of memory.\n\nNotice that if option `delayed_write` was used when opening the file,\n[`close/1`](`close/1`) can return an old write error and not even try to close\nthe file. See `open/2`.","ref":"file.html#close/1"},{"type":"function","title":"file.consult/1","doc":"Reads Erlang terms, separated by `.`, from `Filename`. Returns one of the\nfollowing:\n\n- **`{ok, Terms}`** - The file was successfully read.\n\n- **`{error, atom()}`** - An error occurred when opening the file or reading it.\n For a list of typical error codes, see `open/2`.\n\n- **`{error, {Line, Mod, Term}}`** - An error occurred when interpreting the\n Erlang terms in the file. To convert the three-element tuple to an English\n description of the error, use `format_error/1`.\n\n_Example:_\n\n```text\nf.txt: {person, \"kalle\", 25}.\n {person, \"pelle\", 30}.\n```\n\n```erlang\n1> file:consult(\"f.txt\").\n{ok,[{person,\"kalle\",25},{person,\"pelle\",30}]}\n```\n\nThe encoding of `Filename` can be set by a comment, as described in\n[`epp`](`m:epp#encoding`).","ref":"file.html#consult/1"},{"type":"function","title":"file.copy/2","doc":"","ref":"file.html#copy/2"},{"type":"function","title":"file.copy/3","doc":"Copies `ByteCount` bytes from `Source` to `Destination`. `Source` and\n`Destination` refer to either filenames or IO devices from, for example,\n[`open/2`](`open/2`).\n\nArgument `Modes` is a list of possible modes, see `open/2`, and defaults to\n`[]`.\n\nIf both `Source` and `Destination` refer to filenames, the files are opened with\n`[read, binary]` and `[write, binary]` prepended to their mode lists,\nrespectively, to optimize the copy.\n\nIf `Source` refers to a filename, it is opened with `read` mode prepended to the\nmode list before the copy, and closed when done.\n\nIf `Destination` refers to a filename, it is opened with `write` mode prepended\nto the mode list before the copy, and closed when done.\n\nReturns `{ok, BytesCopied}`, where `BytesCopied` is the number of bytes that was\ncopied, which can be less than `ByteCount` if end of file was encountered on the\nsource. If the operation fails, `{error, Reason}` is returned.\n\nTypical error reasons: as for `open/2` if a file had to be opened, and as for\n`read/2` and `write/2`.","ref":"file.html#copy/3"},{"type":"function","title":"file.datasync/1","doc":"Ensures that any buffers kept by the operating system (not by the Erlang runtime\nsystem) are written to disk. In many ways it resembles `fsync` but it does not\nupdate some of the metadata of the file, such as the access time. On some\nplatforms this function has no effect.\n\nApplications that access databases or log files often write a tiny data fragment\n(for example, one line in a log file) and then call `fsync()` immediately to\nensure that the written data is physically stored on the hard disk.\nUnfortunately, `fsync()` always initiates two write operations: one for the\nnewly written data and another one to update the modification time stored in the\n`inode`. If the modification time is not a part of the transaction concept,\n`fdatasync()` can be used to avoid unnecessary `inode` disk write operations.\n\nAvailable only in some POSIX systems, this call results in a call to `fsync()`,\nor has no effect in systems not providing the `fdatasync()` syscall.","ref":"file.html#datasync/1"},{"type":"function","title":"file.del_dir/1","doc":"Tries to delete directory `Dir`. The directory must be empty before it can be\ndeleted. Returns `ok` if successful.\n\nTypical error reasons:\n\n- **`eacces`** - Missing search or write permissions for the parent directories\n of `Dir`.\n\n- **`eexist`** - The directory is not empty.\n\n- **`enoent`** - The directory does not exist.\n\n- **`enotdir`** - A component of `Dir` is not a directory. On some platforms,\n `enoent` is returned instead.\n\n- **`einval`** - Attempt to delete the current directory. On some platforms,\n `eacces` is returned instead.","ref":"file.html#del_dir/1"},{"type":"function","title":"file.del_dir_r/1","doc":"Deletes file or directory `File`. If `File` is a directory, its contents is\nfirst recursively deleted. Returns:\n\n- **`ok`** - The operation completed without errors.\n\n- **`{error, posix()}`** - An error occurred when accessing or deleting `File`.\n If some file or directory under `File` could not be deleted, `File` cannot be\n deleted as it is non-empty, and `{error, eexist}` is returned.","ref":"file.html#del_dir_r/1"},{"type":"function","title":"file.delete/1","doc":"","ref":"file.html#delete/1"},{"type":"function","title":"file.delete/2","doc":"Tries to delete file `Filename`. Returns `ok` if successful.\n\nIf the option `raw` is set, the file server is not called. This can be useful in\nparticular during the early boot stage when the file server is not yet\nregistered, to still be able to delete local files.\n\nTypical error reasons:\n\n- **`enoent`** - The file does not exist.\n\n- **`eacces`** - Missing permission for the file or one of its parents.\n\n- **`eperm`** - The file is a directory and the user is not superuser.\n\n- **`enotdir`** - A component of the filename is not a directory. On some\n platforms, `enoent` is returned instead.\n\n- **`einval`** - `Filename` has an improper type, such as tuple.\n\n> #### Warning {: .warning }\n>\n> In a future release, a bad type for argument `Filename` will probably generate\n> an exception.","ref":"file.html#delete/2"},{"type":"function","title":"file.eval/1","doc":"Reads and evaluates Erlang expressions, separated by `.` (or `,`, a sequence of\nexpressions is also an expression) from `Filename`. The result of the evaluation\nis not returned; any expression sequence in the file must be there for its side\neffect.\n\nReturns one of the following:\n\n- **`ok`** - The file was read and evaluated.\n\n- **`{error, atom()}`** - An error occurred when opening the file or reading it.\n For a list of typical error codes, see `open/2`.\n\n- **`{error, {Line, Mod, Term}}`** - An error occurred when interpreting the\n Erlang expressions in the file. To convert the three-element tuple to an\n English description of the error, use `format_error/1`.\n\nThe encoding of `Filename` can be set by a comment, as described in\n[`epp`](`m:epp#encoding`).","ref":"file.html#eval/1"},{"type":"function","title":"file.eval/2","doc":"The same as [`eval/1`](`eval/1`), but the variable bindings `Bindings` are used\nin the evaluation. For information about the variable bindings, see\n`m:erl_eval`.","ref":"file.html#eval/2"},{"type":"function","title":"file.format_error/1","doc":"Given the error reason returned by any function in this module, returns a\ndescriptive string of the error in English.","ref":"file.html#format_error/1"},{"type":"function","title":"file.get_cwd/0","doc":"Returns `{ok, Dir}`, where `Dir` is the current working directory of the file\nserver.\n\n> #### Note {: .info }\n>\n> In rare circumstances, this function can fail on Unix. It can occur if read\n> permission does not exist for the parent directories of the current directory.\n\nA typical error reason:\n\n- **`eacces`** - Missing read permission for one of the parents of the current\n directory.","ref":"file.html#get_cwd/0"},{"type":"function","title":"file.get_cwd/1","doc":"Returns `{ok, Dir}` or `{error, Reason}`, where `Dir` is the current working\ndirectory of the specified drive.\n\n`Drive` is to be of the form `Letter:`, for example, `c:`.\n\nReturns `{error, enotsup}` on platforms that have no concept of current drive\n(Unix, for example).\n\nTypical error reasons:\n\n- **`enotsup`** - The operating system has no concept of drives.\n\n- **`eacces`** - The drive does not exist.\n\n- **`einval`** - The format of `Drive` is invalid.","ref":"file.html#get_cwd/1"},{"type":"function","title":"file.list_dir/1","doc":"Lists all files in a directory, _except_ files with raw filenames. Returns\n`{ok, Filenames}` if successful, otherwise `{error, Reason}`. `Filenames` is a\nlist of the names of all the files in the directory. The names are not sorted.\n\nTypical error reasons:\n\n- **`eacces`** - Missing search or write permissions for `Dir` or one of its\n parent directories.\n\n- **`enoent`** - The directory does not exist.\n\n- **`{no_translation, Filename}`** - `Filename` is a `t:binary/0` with\n characters coded in ISO Latin-1 and the VM was started with parameter `+fnue`.","ref":"file.html#list_dir/1"},{"type":"function","title":"file.list_dir_all/1","doc":"[](){: #list_dir_all } Lists all the files in a directory, including files with\nraw filenames. Returns `{ok, Filenames}` if successful, otherwise\n`{error, Reason}`. `Filenames` is a list of the names of all the files in the\ndirectory. The names are not sorted.\n\nTypical error reasons:\n\n- **`eacces`** - Missing search or write permissions for `Dir` or one of its\n parent directories.\n\n- **`enoent`** - The directory does not exist.","ref":"file.html#list_dir_all/1"},{"type":"function","title":"file.make_dir/1","doc":"Tries to create directory `Dir`. Missing parent directories are _not_ created.\nReturns `ok` if successful.\n\nTypical error reasons:\n\n- **`eacces`** - Missing search or write permissions for the parent directories\n of `Dir`.\n\n- **`eexist`** - A file or directory named `Dir` exists already.\n\n- **`enoent`** - A component of `Dir` does not exist.\n\n- **`enospc`** - No space is left on the device.\n\n- **`enotdir`** - A component of `Dir` is not a directory. On some platforms,\n `enoent` is returned instead.","ref":"file.html#make_dir/1"},{"type":"function","title":"file.make_link/2","doc":"Makes a hard link from `Existing` to `New` on platforms supporting links (Unix\nand Windows). This function returns `ok` if the link was successfully created,\notherwise `{error, Reason}`. On platforms not supporting links,\n`{error,enotsup}` is returned.\n\nTypical error reasons:\n\n- **`eacces`** - Missing read or write permissions for the parent directories of\n `Existing` or `New`.\n\n- **`eexist`** - `New` already exists.\n\n- **`enotsup`** - Hard links are not supported on this platform.","ref":"file.html#make_link/2"},{"type":"function","title":"file.make_symlink/2","doc":"Creates a symbolic link `New` to the file or directory `Existing` on platforms\nsupporting symbolic links (most Unix systems and Windows, beginning with Vista).\n`Existing` does not need to exist. Returns `ok` if the link is successfully\ncreated, otherwise `{error, Reason}`. On platforms not supporting symbolic\nlinks, `{error, enotsup}` is returned.\n\nTypical error reasons:\n\n- **`eacces`** - Missing read or write permissions for the parent directories of\n `Existing` or `New`.\n\n- **`eexist`** - `New` already exists.\n\n- **`enotsup`** - Symbolic links are not supported on this platform.\n\n- **`eperm`** - User does not have privileges to create symbolic links\n (`SeCreateSymbolicLinkPrivilege` on Windows).","ref":"file.html#make_symlink/2"},{"type":"function","title":"file.native_name_encoding/0","doc":"[](){: #native_name_encoding } Returns the filename encoding mode. If it is\n`latin1`, the system translates no filenames. If it is `utf8`, filenames are\nconverted back and forth to the native filename encoding (usually UTF-8, but\nUTF-16 on Windows).","ref":"file.html#native_name_encoding/0"},{"type":"function","title":"file.open/2","doc":"Opens file `File` in the mode determined by `Modes`, which can contain one or\nmore of the following options:\n\n- **`read`** - The file, which must exist, is opened for reading.\n\n- **`write`** - The file is opened for writing. It is created if it does not\n exist. If the file exists and `write` is not combined with `read`, the file is\n truncated.\n\n- **`append`** - The file is opened for writing. It is created if it does not\n exist. Every write operation to a file opened with `append` takes place at the\n end of the file.\n\n- **`exclusive`** - The file is opened for writing. It is created if it does not\n exist. If the file exists, `{error, eexist}` is returned.\n\n > #### Warning {: .warning }\n >\n > This option does not guarantee exclusiveness on file systems not supporting\n > `O_EXCL` properly, such as NFS. Do not depend on this option unless you know\n > that the file system supports it (in general, local file systems are safe).\n\n- **`raw`** - [](){: #raw } Allows faster access to a file, as no Erlang process\n is needed to handle the file. However, a file opened in this way has the\n following limitations:\n\n - The functions in the `io` module cannot be used, as they can only talk to an\n Erlang process. Instead, use functions `read/2`, `read_line/1`, and\n `write/2`.\n - Especially if [`read_line/1`](`read_line/1`) is to be used on a `raw` file,\n it is recommended to combine this option with option `{read_ahead, Size}` as\n line-oriented I/O is inefficient without buffering.\n - Only the Erlang process that opened the file can use it.\n - A remote Erlang file server cannot be used. The computer on which the Erlang\n node is running must have access to the file system (directly or through\n NFS).\n\n- **`binary`** - Read operations on the file return binaries rather than lists.\n\n- **`{delayed_write, Size, Delay}`** - Data in subsequent [`write/2`](`write/2`)\n calls is buffered until at least `Size` bytes are buffered, or until the\n oldest buffered data is `Delay` milliseconds old. Then all buffered data is\n written in one operating system call. The buffered data is also flushed before\n some other file operation than [`write/2`](`write/2`) is executed.\n\n The purpose of this option is to increase performance by reducing the number\n of operating system calls. Thus, the [`write/2`](`write/2`) calls must be for\n sizes significantly less than `Size`, and not interspersed by too many other\n file operations.\n\n When this option is used, the result of [`write/2`](`write/2`) calls can\n prematurely be reported as successful, and if a write error occurs, the error\n is reported as the result of the next file operation, which is not executed.\n\n For example, when `delayed_write` is used, after a number of\n [`write/2`](`write/2`) calls, [`close/1`](`close/1`) can return\n `{error, enospc}`, as there is not enough space on the disc for previously\n written data. [`close/1`](`close/1`) must probably be called again, as the\n file is still open.\n\n- **`delayed_write`** - The same as `{delayed_write, Size, Delay}` with\n reasonable default values for `Size` and `Delay` (roughly some 64 KB, 2\n seconds).\n\n- **`{read_ahead, Size}`** - Activates read data buffering. If\n [`read/2`](`read/2`) calls are for significantly less than `Size` bytes, read\n operations to the operating system are still performed for blocks of `Size`\n bytes. The extra data is buffered and returned in subsequent\n [`read/2`](`read/2`) calls, giving a performance gain as the number of\n operating system calls is reduced.\n\n The `read_ahead` buffer is also highly used by function\n [`read_line/1`](`read_line/1`) in `raw` mode, therefore this option is\n recommended (for performance reasons) when accessing raw files using that\n function.\n\n If [`read/2`](`read/2`) calls are for sizes not significantly less than, or\n even greater than `Size` bytes, no performance gain can be expected.\n\n- **`read_ahead`** - The same as `{read_ahead, Size}` with a reasonable default\n value for `Size` (roughly some 64 KB).\n\n- **`compressed`** - Makes it possible to read or write gzip compressed files.\n Option `compressed` must be combined with `read` or `write`, but not both.\n Notice that the file size obtained with `read_file_info/1` does probably not\n match the number of bytes that can be read from a compressed file.\n\n- **`compressed_one`** - Read one member of a gzip compressed file. Option\n `compressed_one` can only be combined with `read`.\n\n- **`{encoding, Encoding}`** - Makes the file perform automatic translation of\n characters to and from a specific (Unicode) encoding. Notice that the data\n supplied to `write/2` or returned by `read/2` still is byte-oriented; this\n option denotes only how data is stored in the disk file.\n\n Depending on the encoding, different methods of reading and writing data is\n preferred. The default encoding of `latin1` implies using this module (`file`)\n for reading and writing data as the interfaces provided here work with\n byte-oriented data. Using other (Unicode) encodings makes the `m:io` functions\n `get_chars`, `get_line`, and `put_chars` more suitable, as they can work with\n the full Unicode range.\n\n If data is sent to an `t:io_device/0` in a format that cannot be converted to\n the specified encoding, or if data is read by a function that returns data in\n a format that cannot cope with the character range of the data, an error\n occurs and the file is closed.\n\n Allowed values for `Encoding`:\n\n - **`latin1`** - The default encoding. Bytes supplied to the file, that is,\n `write/2` are written \"as is\" on the file. Likewise, bytes read from the\n file, that is, `read/2` are returned \"as is\". If module `m:io` is used for\n writing, the file can only cope with Unicode characters up to code point 255\n (the ISO Latin-1 range).\n\n - **`unicode or utf8`** - Characters are translated to and from UTF-8 encoding\n before they are written to or read from the file. A file opened in this way\n can be readable using function `read/2`, as long as no data stored on the\n file lies beyond the ISO Latin-1 range (0..255), but failure occurs if the\n data contains Unicode code points beyond that range. The file is best read\n with the functions in the Unicode aware module `m:io`.\n\n Bytes written to the file by any means are translated to UTF-8 encoding\n before being stored on the disk file.\n\n - **`utf16 or {utf16,big}`** - Works like `unicode`, but translation is done\n to and from big endian UTF-16 instead of UTF-8.\n\n - **`{utf16,little}`** - Works like `unicode`, but translation is done to and\n from little endian UTF-16 instead of UTF-8.\n\n - **`utf32 or {utf32,big}`** - Works like `unicode`, but translation is done\n to and from big endian UTF-32 instead of UTF-8.\n\n - **`{utf32,little}`** - Works like `unicode`, but translation is done to and\n from little endian UTF-32 instead of UTF-8.\n\n The Encoding can be changed for a file \"on the fly\" by using function\n `io:setopts/2`. So a file can be analyzed in latin1 encoding for, for example,\n a BOM, positioned beyond the BOM and then be set for the right encoding before\n further reading. For functions identifying BOMs, see module `m:unicode`.\n\n This option is not allowed on `raw` files.\n\n- **`ram`** - `File` must be `t:iodata/0`. Returns an `t:fd/0`, which lets\n module `file` operate on the data in-memory as if it is a file.\n\n- **`sync`** - On platforms supporting it, enables the POSIX `O_SYNC`\n synchronous I/O flag or its platform-dependent equivalent (for example,\n `FILE_FLAG_WRITE_THROUGH` on Windows) so that writes to the file block until\n the data is physically written to disk. However, be aware that the exact\n semantics of this flag differ from platform to platform. For example, none of\n Linux or Windows guarantees that all file metadata are also written before the\n call returns. For precise semantics, check the details of your platform\n documentation. On platforms with no support for POSIX `O_SYNC` or equivalent,\n use of the `sync` flag causes `open` to return `{error, enotsup}`.\n\n- **`directory`** - Allows `open` to work on directories.\n\nReturns:\n\n- **`{ok, IoDevice}`** - The file is opened in the requested mode. `IoDevice` is\n a reference to the file.\n\n- **`{error, Reason}`** - The file cannot be opened.\n\n`IoDevice` is really the pid of the process that handles the file. This process\nmonitors the process that originally opened the file (the owner process). If the\nowner process terminates, the file is closed and the process itself terminates\ntoo. An `IoDevice` returned from this call can be used as an argument to the I/O\nfunctions (see `m:io`).\n\n> #### Warning {: .warning }\n>\n> While this function can be used to open any file, we recommend against using\n> it for NFS-mounted files, FIFOs, devices, or similar since they can cause IO\n> threads to hang forever.\n>\n> If your application needs to interact with these kinds of files we recommend\n> breaking out those parts to a port program instead.\n\n> #### Note {: .info }\n>\n> In previous versions of `file`, modes were specified as one of the atoms\n> `read`, `write`, or `read_write` instead of a list. This is still allowed for\n> reasons of backwards compatibility, but is not to be used for new code. Also\n> note that `read_write` is not allowed in a mode list.\n\nTypical error reasons:\n\n- **`enoent`** - The file does not exist.\n\n- **`eacces`** - Missing permission for reading the file or searching one of the\n parent directories.\n\n- **`eisdir`** - The named file is a directory.\n\n- **`enotdir`** - A component of the filename is not a directory, or the\n filename itself is not a directory if `directory` mode was specified. On some\n platforms, `enoent` is returned instead.\n\n- **`enospc`** - There is no space left on the device (if `write` access was\n specified).","ref":"file.html#open/2"},{"type":"function","title":"file.path_consult/2","doc":"Searches the path `Path` (a list of directory names) until the file `Filename`\nis found. If `Filename` is an absolute filename, `Path` is ignored. Then reads\nErlang terms, separated by `.`, from the file.\n\nReturns one of the following:\n\n- **`{ok, Terms, FullName}`** - The file is successfully read. `FullName` is the\n full name of the file.\n\n- **`{error, enoent}`** - The file cannot be found in any of the directories in\n `Path`.\n\n- **`{error, atom()}`** - An error occurred when opening the file or reading it.\n For a list of typical error codes, see `open/2`.\n\n- **`{error, {Line, Mod, Term}}`** - An error occurred when interpreting the\n Erlang terms in the file. Use `format_error/1` to convert the three-element\n tuple to an English description of the error.\n\nThe encoding of `Filename` can be set by a comment as described in\n[`epp`](`m:epp#encoding`).","ref":"file.html#path_consult/2"},{"type":"function","title":"file.path_eval/2","doc":"Searches the path `Path` (a list of directory names) until the file `Filename`\nis found. If `Filename` is an absolute filename, `Path` is ignored. Then reads\nand evaluates Erlang expressions, separated by `.` (or `,`, a sequence of\nexpressions is also an expression), from the file. The result of evaluation is\nnot returned; any expression sequence in the file must be there for its side\neffect.\n\nReturns one of the following:\n\n- **`{ok, FullName}`** - The file is read and evaluated. `FullName` is the full\n name of the file.\n\n- **`{error, enoent}`** - The file cannot be found in any of the directories in\n `Path`.\n\n- **`{error, atom()}`** - An error occurred when opening the file or reading it.\n For a list of typical error codes, see `open/2`.\n\n- **`{error, {Line, Mod, Term}}`** - An error occurred when interpreting the\n Erlang expressions in the file. Use `format_error/1` to convert the\n three-element tuple to an English description of the error.\n\nThe encoding of `Filename` can be set by a comment as described in\n[`epp`](`m:epp#encoding`).","ref":"file.html#path_eval/2"},{"type":"function","title":"file.path_open/3","doc":"Searches the path `Path` (a list of directory names) until the file `Filename`\nis found. If `Filename` is an absolute filename, `Path` is ignored. Then opens\nthe file in the mode determined by `Modes`.\n\nReturns one of the following:\n\n- **`{ok, IoDevice, FullName}`** - The file is opened in the requested mode.\n `IoDevice` is a reference to the file and `FullName` is the full name of the\n file.\n\n- **`{error, enoent}`** - The file cannot be found in any of the directories in\n `Path`.\n\n- **`{error, atom()}`** - The file cannot be opened.","ref":"file.html#path_open/3"},{"type":"function","title":"file.path_script/2","doc":"Searches the path `Path` (a list of directory names) until the file `Filename`\nis found. If `Filename` is an absolute filename, `Path` is ignored. Then reads\nand evaluates Erlang expressions, separated by `.` (or `,`, a sequence of\nexpressions is also an expression), from the file.\n\nReturns one of the following:\n\n- **`{ok, Value, FullName}`** - The file is read and evaluated. `FullName` is\n the full name of the file and `Value` the value of the last expression.\n\n- **`{error, enoent}`** - The file cannot be found in any of the directories in\n `Path`.\n\n- **`{error, atom()}`** - An error occurred when opening the file or reading it.\n For a list of typical error codes, see `open/2`.\n\n- **`{error, {Line, Mod, Term}}`** - An error occurred when interpreting the\n Erlang expressions in the file. Use `format_error/1` to convert the\n three-element tuple to an English description of the error.\n\nThe encoding of `Filename` can be set by a comment as described in\n[`epp`](`m:epp#encoding`).","ref":"file.html#path_script/2"},{"type":"function","title":"file.path_script/3","doc":"The same as [`path_script/2`](`path_script/2`) but the variable bindings\n`Bindings` are used in the evaluation. See `m:erl_eval` about variable bindings.","ref":"file.html#path_script/3"},{"type":"function","title":"file.position/2","doc":"Sets the position of the file referenced by `IoDevice` to `Location`. Returns\n`{ok, NewPosition}` (as absolute offset) if successful, otherwise\n`{error, Reason}`. `Location` is one of the following:\n\n- **`Offset`** - The same as `{bof, Offset}`.\n\n- **`{bof, Offset}`** - Absolute offset.\n\n- **`{cur, Offset}`** - Offset from the current position.\n\n- **`{eof, Offset}`** - Offset from the end of file.\n\n- **`bof | cur | eof`** - The same as above with `Offset` 0.\n\nNotice that offsets are counted in bytes, not in characters. If the file is\nopened using some other `encoding` than `latin1`, one byte does not correspond\nto one character. Positioning in such a file can only be done to known character\nboundaries. That is, to a position earlier retrieved by getting a current\nposition, to the beginning/end of the file or to some other position _known_ to\nbe on a correct character boundary by some other means (typically beyond a byte\norder mark in the file, which has a known byte-size).\n\nA typical error reason is:\n\n- **`einval`** - Either `Location` is illegal, or it is evaluated to a negative\n offset in the file. Notice that if the resulting position is a negative value,\n the result is an error, and after the call the file position is undefined.","ref":"file.html#position/2"},{"type":"function","title":"file.pread/2","doc":"Performs a sequence of [`pread/3`](`pread/3`) in one operation, which is more\nefficient than calling them one at a time. Returns `{ok, [Data, ...]}` or\n`{error, Reason}`, where each `Data`, the result of the corresponding `pread`,\nis either a list or a binary depending on the mode of the file, or `eof` if the\nrequested position is beyond end of file.\n\nAs the position is specified as a byte-offset, take special caution when working\nwith files where `encoding` is set to something else than `latin1`, as not every\nbyte position is a valid character boundary on such a file.","ref":"file.html#pread/2"},{"type":"function","title":"file.pread/3","doc":"Combines [`position/2`](`position/2`) and [`read/2`](`read/2`) in one operation,\nwhich is more efficient than calling them one at a time.\n\n`Location` is only allowed to be an integer for `raw` and `ram` modes.\n\nThe current position of the file after the operation is undefined for `raw` mode\nand unchanged for `ram` mode.\n\nAs the position is specified as a byte-offset, take special caution when working\nwith files where `encoding` is set to something else than `latin1`, as not every\nbyte position is a valid character boundary on such a file.","ref":"file.html#pread/3"},{"type":"function","title":"file.pwrite/2","doc":"Performs a sequence of [`pwrite/3`](`pwrite/3`) in one operation, which is more\nefficient than calling them one at a time. Returns `ok` or\n`{error, {N, Reason}}`, where `N` is the number of successful writes done before\nthe failure.\n\nWhen positioning in a file with other `encoding` than `latin1`, caution must be\ntaken to set the position on a correct character boundary. For details, see\n`position/2`.","ref":"file.html#pwrite/2"},{"type":"function","title":"file.pwrite/3","doc":"Combines [`position/2`](`position/2`) and [`write/2`](`write/2`) in one\noperation, which is more efficient than calling them one at a time.\n\n`Location` is only allowed to be an integer for `raw` and `ram` modes.\n\nThe current position of the file after the operation is undefined for `raw` mode\nand unchanged for `ram` mode.\n\nWhen positioning in a file with other `encoding` than `latin1`, caution must be\ntaken to set the position on a correct character boundary. For details, see\n`position/2`.","ref":"file.html#pwrite/3"},{"type":"function","title":"file.read/2","doc":"Reads `Number` bytes/characters from the file referenced by `IoDevice`.\n\nThe functions `read/2`, `pread/3`, and `read_line/1` are the only ways to read from\na file opened in `raw` mode (although they work for normally opened files, too).\n\nFor files where `encoding` is set to something else than `latin1`, one character\ncan be represented by more than one byte on the file. The parameter `Number`\nalways denotes the number of _characters_ read from the file, while the position\nin the file can be moved much more than this number when reading a Unicode file.\n\nAlso, if `encoding` is set to something else than `latin1`, the\n[`read/2`](`read/2`) call fails if the data contains characters larger than 255,\nwhich is why `io:get_chars/3` is to be preferred when reading such a file.\n\nThe function returns:\n\n- **`{ok, Data}`** - If the file was opened in binary mode, the read bytes are\n returned in a binary, otherwise in a list. The list or binary is shorter than\n the number of bytes requested if end of file was reached.\n\n- **`eof`** - Returned if `Number>0` and end of file was reached before anything\n at all could be read.\n\n- **`{error, Reason}`** - An error occurred.\n\nTypical error reasons:\n\n- **`ebadf`** - The file is not opened for reading.\n\n- **`{no_translation, unicode, latin1}`** - The file is opened with another\n `encoding` than `latin1` and the data in the file cannot be translated to the\n byte-oriented data that this function returns.","ref":"file.html#read/2"},{"type":"function","title":"file.read_file/1","doc":"","ref":"file.html#read_file/1"},{"type":"function","title":"file.read_file/2","doc":"Returns `{ok, Binary}`, where `Binary` is a binary data object that contains the\ncontents of `Filename`, or `{error, Reason}` if an error occurs.\n\nIf the option `raw` is set, the file server is not called.\n\nTypical error reasons:\n\n- **`enoent`** - The file does not exist.\n\n- **`eacces`** - Missing permission for reading the file, or for searching one\n of the parent directories.\n\n- **`eisdir`** - The named file is a directory.\n\n- **`enotdir`** - A component of the filename is not a directory. On some\n platforms, `enoent` is returned instead.\n\n- **`enomem`** - There is not enough memory for the contents of the file.","ref":"file.html#read_file/2"},{"type":"function","title":"file.read_file_info/1","doc":"","ref":"file.html#read_file_info/1"},{"type":"function","title":"file.read_file_info/2","doc":"Retrieves information about a file. Returns `{ok, FileInfo}` if successful,\notherwise `{error, Reason}`.\n\n`FileInfo` is a record `file_info`, defined in the Kernel include file `file.hrl`.\nInclude the following directive in the module from which the function is called:\n\n```erlang\n-include_lib(\"kernel/include/file.hrl\").\n```\n\nThe time type returned in `atime`, `mtime`, and `ctime` is dependent on the time\ntype set in `Opts :: {time, Type}` as follows:\n\n- **`local`** - Returns local time.\n\n- **`universal`** - Returns universal time.\n\n- **`posix`** - Returns seconds since or before Unix time epoch, which is\n 1970-01-01 00:00 UTC.\n\nDefault is `{time, local}`.\n\nIf the option `raw` is set, the file server is not called and only information\nabout local files is returned. Note that this will break this module's atomicity\nguarantees as it can race with a concurrent call to\n[`write_file_info/1,2` ](`write_file_info/2`).\n\nThis option has no effect when the function is given an I/O device instead of a\nfile name. Use `open/2` with the `raw` mode to obtain a file descriptor first.\n\n> #### Note {: .info }\n>\n> As file times are stored in POSIX time on most OS, it is faster to query file\n> information with option `posix`.\n\nThe record `file_info` contains the following fields:\n\n- **`size = ` `t:non_neg_integer/0`** - Size of file in bytes.\n\n- **`type = device | directory | other | regular`** - The type of the file. Can\n also contain `symlink` when returned from\n [read_link_info/1,2](`read_link_info/1`).\n\n- **`access = read | write | read_write | none`** - The current system access to\n the file.\n\n- **`atime = ` `t:date_time/0` ` | ` `t:non_neg_integer/0`** - The last time the file was\n read.\n\n- **`mtime = ` `t:date_time/0` ` | ` `t:non_neg_integer/0`** - The last time the file was\n written.\n\n- **`ctime = ` `t:date_time/0` ` | ` `t:non_neg_integer/0`** - The interpretation of this\n time field depends on the operating system. On Unix, it is the last time the\n file or the `inode` was changed. In Windows, it is the create time.\n\n- **`mode = ` `t:non_neg_integer/0`** - The file permissions as the sum of the following\n bit values:\n\n - **`8#00400`** - read permission: owner\n\n - **`8#00200`** - write permission: owner\n\n - **`8#00100`** - execute permission: owner\n\n - **`8#00040`** - read permission: group\n\n - **`8#00020`** - write permission: group\n\n - **`8#00010`** - execute permission: group\n\n - **`8#00004`** - read permission: other\n\n - **`8#00002`** - write permission: other\n\n - **`8#00001`** - execute permission: other\n\n - **`16#800`** - set user id on execution\n\n - **`16#400`** - set group id on execution\n\n On Unix platforms, other bits than those listed above may be set.\n\n- **`links = ` `t:non_neg_integer/0`** - Number of links to the file (this is always 1\n for file systems that have no concept of links).\n\n- **`major_device = ` `t:non_neg_integer/0`** - Identifies the file system where the\n file is located. In Windows, the number indicates a drive as follows: 0 means\n A:, 1 means B:, and so on.\n\n- **`minor_device = ` `t:non_neg_integer/0`** - Only valid for character devices on\n Unix. In all other cases, this field is zero.\n\n- **`inode = ` `t:non_neg_integer/0`** - Gives the `inode` number. On non-Unix file\n systems, this field is zero.\n\n- **`uid = ` `t:non_neg_integer/0`** - Indicates the owner of the file. On non-Unix file\n systems, this field is zero.\n\n- **`gid = ` `t:non_neg_integer/0`** - Gives the group that the owner of the file\n belongs to. On non-Unix file systems, this field is zero.\n\nTypical error reasons:\n\n- **`eacces`** - Missing search permission for one of the parent directories of\n the file.\n\n- **`enoent`** - The file does not exist.\n\n- **`enotdir`** - A component of the filename is not a directory. On some\n platforms, `enoent` is returned instead.","ref":"file.html#read_file_info/2"},{"type":"function","title":"file.read_line/1","doc":"Reads a line of bytes/characters from the file referenced by `IoDevice`.\n\nLines are defined to be delimited by the linefeed (LF, `\\n`) character, but any\ncarriage return (CR, `\\r`) followed by a newline is also treated as a single LF\ncharacter (the carriage return is silently ignored). The line is returned\n_including_ the LF, but excluding any CR immediately followed by an LF. This\nbehaviour is consistent with the behaviour of `io:get_line/2`. If end of file is\nreached without any LF ending the last line, a line with no trailing LF is\nreturned.\n\nThe function can be used on files opened in `raw` mode. However, it is\ninefficient to use it on `raw` files if the file is not opened with option\n`{read_ahead, Size}` specified. Thus, combining `raw` and `{read_ahead, Size}`\nis highly recommended when opening a text file for raw line-oriented reading.\n\nIf `encoding` is set to something else than `latin1`, the\n[`read_line/1`](`read_line/1`) call fails if the data contains characters larger\nthan 255, why `io:get_line/2` is to be preferred when reading such a file.\n\nThe function returns:\n\n- **`{ok, Data}`** - One line from the file is returned, including the trailing\n LF, but with CRLF sequences replaced by a single LF (see above).\n\n If the file is opened in binary mode, the read bytes are returned in a binary,\n otherwise in a list.\n\n- **`eof`** - Returned if end of file was reached before anything at all could\n be read.\n\n- **`{error, Reason}`** - An error occurred.\n\nTypical error reasons:\n\n- **`ebadf`** - The file is not opened for reading.\n\n- **`{no_translation, unicode, latin1}`** - The file is opened with another\n `encoding` than `latin1` and the data on the file cannot be translated to the\n byte-oriented data that this function returns.","ref":"file.html#read_line/1"},{"type":"function","title":"file.read_link/1","doc":"[](){: #read_link_all } Returns `{ok, Filename}` if `Name` refers to a symbolic\nlink that is not a raw filename, or `{error, Reason}` otherwise. On platforms\nthat do not support symbolic links, the return value is `{error,enotsup}`.\n\nTypical error reasons:\n\n- **`einval`** - `Name` does not refer to a symbolic link or the name of the\n file that it refers to does not conform to the expected encoding.\n\n- **`enoent`** - The file does not exist.\n\n- **`enotsup`** - Symbolic links are not supported on this platform.","ref":"file.html#read_link/1"},{"type":"function","title":"file.read_link_all/1","doc":"Returns `{ok, Filename}` if `Name` refers to a symbolic link or\n`{error, Reason}` otherwise. On platforms that do not support symbolic links,\nthe return value is `{error,enotsup}`.\n\nNotice that `Filename` can be either a list or a binary.\n\nTypical error reasons:\n\n- **`einval`** - `Name` does not refer to a symbolic link.\n\n- **`enoent`** - The file does not exist.\n\n- **`enotsup`** - Symbolic links are not supported on this platform.","ref":"file.html#read_link_all/1"},{"type":"function","title":"file.read_link_info/1","doc":"","ref":"file.html#read_link_info/1"},{"type":"function","title":"file.read_link_info/2","doc":"Works like [`read_file_info/1,2`](`read_file_info/2`) except that if `Name` is a\nsymbolic link, information about the link is returned in the `file_info` record\nand the `type` field of the record is set to `symlink`.\n\nIf the option `raw` is set, the file server is not called and only information\nabout local files is returned. Note that this will break this module's atomicity\nguarantees as it can race with a concurrent call to\n[`write_file_info/1,2`](`write_file_info/2`)\n\nIf `Name` is not a symbolic link, this function returns the same result as\n[`read_file_info/1`](`read_file_info/1`). On platforms that do not support\nsymbolic links, this function is always equivalent to\n[`read_file_info/1`](`read_file_info/1`).","ref":"file.html#read_link_info/2"},{"type":"function","title":"file.rename/2","doc":"Tries to rename the file `Source` to `Destination`. It can be used to move files\n(and directories) between directories, but it is not sufficient to specify the\ndestination only. The destination filename must also be specified. For example,\nif `bar` is a normal file and `foo` and `baz` are directories,\n[`rename(\"foo/bar\", \"baz\")`](`rename/2`) returns an error, but\n[`rename(\"foo/bar\", \"baz/bar\")`](`rename/2`) succeeds. Returns `ok` if it is\nsuccessful.\n\n> #### Note {: .info }\n>\n> Renaming of open files is not allowed on most platforms (see `eacces` below).\n\nTypical error reasons:\n\n- **`eacces`** - Missing read or write permissions for the parent directories of\n `Source` or `Destination`. On some platforms, this error is given if either\n `Source` or `Destination` is open.\n\n- **`eexist`** - `Destination` is not an empty directory. On some platforms,\n also given when `Source` and `Destination` are not of the same type.\n\n- **`einval`** - `Source` is a root directory, or `Destination` is a\n subdirectory of `Source`.\n\n- **`eisdir`** - `Destination` is a directory, but `Source` is not.\n\n- **`enoent`** - `Source` does not exist.\n\n- **`enotdir`** - `Source` is a directory, but `Destination` is not.\n\n- **`exdev`** - `Source` and `Destination` are on different file systems.","ref":"file.html#rename/2"},{"type":"function","title":"file.script/1","doc":"Reads and evaluates Erlang expressions, separated by `.` (or `,`, a sequence of\nexpressions is also an expression), from the file.\n\nReturns one of the following:\n\n- **`{ok, Value}`** - The file is read and evaluated. `Value` is the value of\n the last expression.\n\n- **`{error, atom()}`** - An error occurred when opening the file or reading it.\n For a list of typical error codes, see `open/2`.\n\n- **`{error, {Line, Mod, Term}}`** - An error occurred when interpreting the\n Erlang expressions in the file. Use `format_error/1` to convert the\n three-element tuple to an English description of the error.\n\nThe encoding of `Filename` can be set by a comment as described in\n[`epp`](`m:epp#encoding`).","ref":"file.html#script/1"},{"type":"function","title":"file.script/2","doc":"The same as [`script/1`](`script/1`) but the variable bindings `Bindings` are\nused in the evaluation. See `m:erl_eval` about variable bindings.","ref":"file.html#script/2"},{"type":"function","title":"file.sendfile/2","doc":"Sends the file `Filename` to `Socket`. Returns `{ok, BytesSent}` if successful,\notherwise `{error, Reason}`.","ref":"file.html#sendfile/2"},{"type":"function","title":"file.sendfile/5","doc":"Sends `Bytes` from the file referenced by `RawFile` beginning at `Offset` to\n`Socket`. Returns `{ok, BytesSent}` if successful, otherwise `{error, Reason}`.\nIf `Bytes` is set to `0` all data after the specified `Offset` is sent.\n\nThe file used must be opened using the `raw` flag, and the process calling\n`sendfile` must be the controlling process of the socket. See\n`gen_tcp:controlling_process/2` or module [`socket`'s](`socket:setopt/3`)\n[level `otp` socket option ](`t:socket:otp_socket_option/0`)`controlling_process`.\n\nIf the OS used does not support non-blocking `sendfile`, an Erlang fallback\nusing `read/2` and `gen_tcp:send/2` is used.\n\nThe option list can contain the following options:\n\n- **`chunk_size`** - The chunk size used by the Erlang fallback to send data. If\n using the fallback, set this to a value that comfortably fits in the systems\n memory. Default is 20 MB.","ref":"file.html#sendfile/5"},{"type":"function","title":"file.set_cwd/1","doc":"Sets the current working directory of the file server to `Dir`. Returns `ok` if\nsuccessful.\n\nThe functions in the module `file` usually treat binaries as raw filenames, that\nis, they are passed \"as is\" even when the encoding of the binary does not agree\nwith [`native_name_encoding()`](`native_name_encoding/0`). However, this\nfunction expects binaries to be encoded according to the value returned by\n`native_name_encoding/0`.\n\nTypical error reasons are:\n\n- **`enoent`** - The directory does not exist.\n\n- **`enotdir`** - A component of `Dir` is not a directory. On some platforms,\n `enoent` is returned.\n\n- **`eacces`** - Missing permission for the directory or one of its parents.\n\n- **`badarg`** - `Dir` has an improper type, such as tuple.\n\n- **`no_translation`** - `Dir` is a `t:binary/0` with characters coded in\n ISO-latin-1 and the VM is operating with unicode filename encoding.\n\n> #### Warning {: .warning }\n>\n> In a future release, a bad type for argument `Dir` will probably generate an\n> exception.","ref":"file.html#set_cwd/1"},{"type":"function","title":"file.sync/1","doc":"Ensures that any buffers kept by the operating system (not by the Erlang runtime\nsystem) are written to disk. On some platforms, this function might have no\neffect.\n\nA typical error reason is:\n\n- **`enospc`** - Not enough space left to write the file.","ref":"file.html#sync/1"},{"type":"function","title":"file.truncate/1","doc":"Truncates the file referenced by `IoDevice` at the current position. Returns\n`ok` if successful, otherwise `{error, Reason}`.","ref":"file.html#truncate/1"},{"type":"function","title":"file.write/2","doc":"Writes `Bytes` to the file referenced by `IoDevice`. This function is the only\nway to write to a file opened in `raw` mode (although it works for normally\nopened files too). Returns `ok` if successful, and `{error, Reason}` otherwise.\n\nIf the file is opened with `encoding` set to something else than `latin1`, each\nbyte written can result in many bytes being written to the file, as the byte\nrange 0..255 can represent anything between one and four bytes depending on\nvalue and UTF encoding type. If you want to write `t:unicode:chardata/0` to the\n`IoDevice` you should use `io:put_chars/2` instead.\n\nTypical error reasons:\n\n- **`ebadf`** - The file is not opened for writing.\n\n- **`enospc`** - No space is left on the device.","ref":"file.html#write/2"},{"type":"function","title":"file.write_file/2","doc":"Writes the contents of the `iodata` term `Bytes` to file `Filename`. The file is\ncreated if it does not exist. If it exists, the previous contents are\noverwritten. Returns `ok` if successful, otherwise `{error, Reason}`.\n\nTypical error reasons:\n\n- **`enoent`** - A component of the filename does not exist.\n\n- **`enotdir`** - A component of the filename is not a directory. On some\n platforms, `enoent` is returned instead.\n\n- **`enospc`** - No space is left on the device.\n\n- **`eacces`** - Missing permission for writing the file or searching one of the\n parent directories.\n\n- **`eisdir`** - The named file is a directory.","ref":"file.html#write_file/2"},{"type":"function","title":"file.write_file/3","doc":"Same as [`write_file/2`](`write_file/2`), but takes a third argument `Modes`, a\nlist of possible modes, see `open/2`. The mode flags `binary` and `write` are\nimplicit, so they are not to be used.","ref":"file.html#write_file/3"},{"type":"function","title":"file.write_file_info/2","doc":"","ref":"file.html#write_file_info/2"},{"type":"function","title":"file.write_file_info/3","doc":"Changes file information. Returns `ok` if successful, otherwise\n`{error, Reason}`.\n\n`FileInfo` is a record `file_info`, defined in the Kernel\ninclude file `file.hrl`. Include the following directive in the module from\nwhich the function is called:\n\n```erlang\n-include_lib(\"kernel/include/file.hrl\").\n```\n\nThe time type set in `atime`, `mtime`, and `ctime` depends on the time type set\nin `Opts :: {time, Type}` as follows:\n\n- **`local`** - Interprets the time set as local.\n\n- **`universal`** - Interprets it as universal time.\n\n- **`posix`** - Must be seconds since or before Unix time epoch, which is\n 1970-01-01 00:00 UTC.\n\nDefault is `{time, local}`.\n\nIf the option `raw` is set, the file server is not called and only information\nabout local files is returned.\n\nThe following fields are used from the record, if they are specified:\n\n- **`atime = ` `t:date_time/0` ` | ` `t:non_neg_integer/0`** - The last time the file was\n read.\n\n- **`mtime = ` `t:date_time/0` ` | ` `t:non_neg_integer/0`** - The last time the file was\n written.\n\n- **`ctime = ` `t:date_time/0` ` | ` `t:non_neg_integer/0`** - On Unix, any value\n specified for this field is ignored (the \"ctime\" for the file is set to the\n current time). On Windows, this field is the new creation time to set for the\n file.\n\n- **`mode = ` `t:non_neg_integer/0`** - The file permissions as the sum of the following\n bit values:\n\n - **`8#00400`** - Read permission: owner\n\n - **`8#00200`** - Write permission: owner\n\n - **`8#00100`** - Execute permission: owner\n\n - **`8#00040`** - Read permission: group\n\n - **`8#00020`** - Write permission: group\n\n - **`8#00010`** - Execute permission: group\n\n - **`8#00004`** - Read permission: other\n\n - **`8#00002`** - Write permission: other\n\n - **`8#00001`** - Execute permission: other\n\n - **`16#800`** - Set user id on execution\n\n - **`16#400`** - Set group id on execution\n\n On Unix platforms, other bits than those listed above may be set.\n\n- **`uid = ` `t:non_neg_integer/0`** - Indicates the file owner. Ignored for non-Unix\n file systems.\n\n- **`gid = ` `t:non_neg_integer/0`** - Gives the group that the file owner belongs to.\n Ignored for non-Unix file systems.\n\nTypical error reasons:\n\n- **`eacces`** - Missing search permission for one of the parent directories of\n the file.\n\n- **`enoent`** - The file does not exist.\n\n- **`enotdir`** - A component of the filename is not a directory. On some\n platforms, `enoent` is returned instead.","ref":"file.html#write_file_info/3"},{"type":"type","title":"file.date_time/0","doc":"Must denote a valid date and time.","ref":"file.html#t:date_time/0"},{"type":"type","title":"file.deep_list/0","doc":"","ref":"file.html#t:deep_list/0"},{"type":"type","title":"file.delete_option/0","doc":"","ref":"file.html#t:delete_option/0"},{"type":"type","title":"file.fd/0","doc":"A file descriptor representing a file opened in [`raw`](`m:file#raw`) mode.","ref":"file.html#t:fd/0"},{"type":"type","title":"file.file_info/0","doc":"","ref":"file.html#t:file_info/0"},{"type":"type","title":"file.file_info_option/0","doc":"","ref":"file.html#t:file_info_option/0"},{"type":"type","title":"file.filename/0","doc":"A file name as returned from `m:file` API functions.\n\nSee the documentation of the `t:name_all/0` type.","ref":"file.html#t:filename/0"},{"type":"type","title":"file.filename_all/0","doc":"A file name as returned from `m:file` API functions.\n\nSee the documentation of the `t:name_all/0` type.","ref":"file.html#t:filename_all/0"},{"type":"type","title":"file.io_device/0","doc":"An IO device as returned by `open/2`.\n\n`t:io_server/0` is returned by default and `t:fd/0` is returned if the `raw` option is given.","ref":"file.html#t:io_device/0"},{"type":"type","title":"file.io_server/0","doc":"A process handling the I/O protocol.","ref":"file.html#t:io_server/0"},{"type":"type","title":"file.location/0","doc":"","ref":"file.html#t:location/0"},{"type":"type","title":"file.mode/0","doc":"","ref":"file.html#t:mode/0"},{"type":"type","title":"file.name/0","doc":"A restricted file name used as input into `m:file` API functions.\n\nIf VM is in Unicode filename mode, `t:string/0` and `t:char/0` are allowed to\nbe > 255. See also the documentation of the `t:name_all/0` type.","ref":"file.html#t:name/0"},{"type":"type","title":"file.name_all/0","doc":"A file name used as input into `m:file` API functions.\n\nIf VM is in Unicode filename mode, characters are allowed to be > 255.\n`RawFilename` is a filename not subject to Unicode translation, meaning that it\ncan contain characters not conforming to the Unicode encoding expected from the\nfile system (that is, non-UTF-8 characters although the VM is started in Unicode\nfilename mode). Null characters (integer value zero) are _not_ allowed in\nfilenames (not even at the end).","ref":"file.html#t:name_all/0"},{"type":"type","title":"file.posix/0","doc":"An atom that is named from the POSIX error codes used in Unix, and in the\nruntime libraries of most C compilers.","ref":"file.html#t:posix/0"},{"type":"type","title":"file.posix_file_advise/0","doc":"","ref":"file.html#t:posix_file_advise/0"},{"type":"type","title":"file.read_file_option/0","doc":"","ref":"file.html#t:read_file_option/0"},{"type":"type","title":"file.sendfile_option/0","doc":"","ref":"file.html#t:sendfile_option/0"},{"type":"module","title":"gen_sctp","doc":"Interface to SCTP sockets.\n\nThis module provides functions for communicating over SCTP sockets.\nThe implementation assumes that the OS kernel supports SCTP\n[(RFC 2960)](http://www.rfc-archive.org/getrfc.php?rfc=2960)\nthrough the user-level\n[Sockets API Extensions](http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13).\n\nDuring development, this implementation was tested on:\n\n- Linux Fedora Core 5.0 (kernel 2.6.15-2054 or later is needed)\n- Solaris 10, 11\n\nDuring OTP adaptation it was tested on:\n\n- SUSE Linux Enterprise Server 10 (x86_64) kernel 2.6.16.27-0.6-smp, with\n lksctp-tools-1.0.6\n- Briefly on Solaris 10\n- SUSE Linux Enterprise Server 10 Service Pack 1 (x86_64) kernel\n 2.6.16.54-0.2.3-smp with lksctp-tools-1.0.7\n- FreeBSD 8.2\n\nThis module was written for one-to-many style sockets (type `seqpacket`).\nWith the addition of `peeloff/2`, one-to-one style sockets (type `stream`)\nwere introduced.\n\nRecord definitions for this module can be found using:\n\n```erlang\n-include_lib(\"kernel/include/inet_sctp.hrl\").\n```\n\nThese record definitions use the \"new\" spelling 'adaptation',\nnot the deprecated 'adaption', regardless of which spelling\nthe underlying C API uses.\n\n[](){: #options } SCTP Socket Options\n-------------------------------------\n\nThe set of admissible SCTP socket options is by construction orthogonal\nto the sets of TCP, UDP, and generic `inet` options. Here are only\noptions listed that are allowed for SCTP sockets.\n\nOptions can be set on the socket when calling [`open/1,2`](`open/1`),\nand changed when calling [`connect/4,5`](`connect/4`) or\nby calling `inet:setopts/2`. They can be retrieved using `inet:getopts/2`.\n\n- **`{mode, list|binary} | list | binary`** [](){: #option-binary } [](){: #option-list } -\n Determines the type of data returned from [`recv/1,2`](`recv/1`)\n or in _active mode_ data messages.\n\n- **`{active, false|true|once|N}`** [](){: #option-active }\n\n - If `false` (_passive mode_, the default), the caller must do an explicit\n [`recv`](`recv/1`) call to retrieve the available data from the socket.\n\n - If `true|once|N` (_active modes_) received data or events are sent\n to the owning process. See [`open/0..2`](`open/0`) for the message format.\n\n - If `true` (fully _active mode_) there is no flow control.\n\n > #### Note {: .info }\n >\n > Note that this can cause the message queue to overflow\n > causing for example the virtual machine to run out of memory and crash.\n\n - If `once`, only one message is automatically placed in the message queue,\n and the mode resets to passive. This provides flow control\n and the possibility for the receiver to listen for incoming\n SCTP data interleaved with other inter-process messages.\n\n - If `active` is specified as an integer `N` in the range -32768 to 32767\n (inclusive), that number is added to the socket's data messages counter.\n If the result of the addition is negative, the counter is set to `0`.\n Once the counter reaches `0`, either through the delivery of messages\n or by being explicitly set with `inet:setopts/2`, the socket mode\n resets to passive (`{active, false}`). When a socket in `{active, N}`\n mode transitions to passive mode, the message `{sctp_passive, Socket}`\n is sent to the controlling process to notify that if it wants to receive\n more data messages from the socket, it must call `inet:setopts/2`\n to set the socket back into an active mode.\n\n- **`{tos, integer()}`** - Sets the Type-Of-Service field on the IP datagrams\n that are sent, to the specified value. This effectively determines a\n prioritization policy for the outbound packets. The acceptable values are\n system-dependent.\n\n- **`{priority, integer()}`** - A protocol-independent equivalent of `tos`\n above. Setting priority implies setting `tos` as well.\n\n- **`{dontroute, true|false}`** - Defaults to `false`.\n If `true`, the kernel does not send packets through any gateway,\n but only sends them to directly connected hosts.\n\n- **`{reuseaddr, true|false}`** - Defaults to `false`.\n If `true`, the local binding address `{IP,Port}` of the socket can be\n reused immediately. No waiting in state `CLOSE_WAIT` is performed\n (can be required for some types of servers).\n\n- **`{sndbuf, integer()}`** - The size, in bytes, of the OS kernel send buffer\n for this socket. Sending errors would occur for datagrams larger than\n `val(sndbuf)`. Setting this option also adjusts the size of\n the driver buffer (see `buffer` above).\n\n- **`{recbuf, integer()}`** - The size, in bytes, of the OS kernel receive\n buffer for this socket. Sending errors would occur for datagrams\n larger than `val(recbuf)`. Setting this option also adjusts the size\n of the driver buffer (see `buffer` above).\n\n### [](){: #option_non_block_send }\n\n- **`{non_block_send, boolean()}`** - A send call that would otherwise block (hang),\n will instead immediately return with e.g. `{error, eagain}`\n *if* this option has been set to `true`.\n Defaults to `false`.\n\n- **`{sctp_module, module()}`** - Overrides which callback module is used.\nDefaults to `inet_sctp` for IPv4 and `inet6_sctp` for IPv6.\n\n- **`{sctp_rtoinfo, #sctp_rtoinfo{}}`**\n\n ```erlang\n #sctp_rtoinfo{\n assoc_id = assoc_id(),\n initial = integer(),\n max = integer(),\n min = integer()\n }\n ```\n\n Determines retransmission time-out parameters, in milliseconds, for the\n association(s) specified by `assoc_id`.\n\n `assoc_id = 0` (default) indicates the whole endpoint. See\n [RFC 2960](http://www.rfc-archive.org/getrfc.php?rfc=2960) and\n [Sockets API Extensions for SCTP](http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13)\n for the exact semantics of the field values.\n\n- **`{sctp_associnfo, #sctp_assocparams{}}`**\n\n ```erlang\n #sctp_assocparams{\n assoc_id = assoc_id(),\n asocmaxrxt = integer(),\n number_peer_destinations = integer(),\n peer_rwnd = integer(),\n local_rwnd = integer(),\n cookie_life = integer()\n }\n ```\n\n Determines association parameters for the association(s) specified by\n `assoc_id`.\n\n `assoc_id = 0` (default) indicates the whole endpoint. See\n [Sockets API Extensions for SCTP](http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13)\n for the discussion of their semantics. Rarely used.\n\n- **`{sctp_initmsg, #sctp_initmsg{}}`**\n\n ```erlang\n #sctp_initmsg{\n num_ostreams = integer(),\n max_instreams = integer(),\n max_attempts = integer(),\n max_init_timeo = integer()\n }\n ```\n\n Determines the default parameters that this socket tries to negotiate\n with its peer while establishing an association with it. Is to be set after\n [`open/*`](`open/1`) but before the first [`connect/*`](`connect/4`).\n `#sctp_initmsg{}` can also be used as ancillary data with the first call of\n [`send/*`](`send/3`) to a new peer (when a new association is created).\n\n - **`num_ostreams`** - Number of outbound streams\n\n - **`max_instreams`** - Maximum number of inbound streams\n\n - **`max_attempts`** - Maximum retransmissions while establishing an\n association\n\n - **`max_init_timeo`** - Time-out, in milliseconds, for establishing an\n association\n\n- **`{sctp_autoclose, integer() >= 0}`** - Determines the time, in seconds,\n after which an idle association is automatically closed. `0` means that the\n association is never automatically closed.\n\n- **`{sctp_nodelay, true|false}`** - Turns on|off the Nagle algorithm for\n merging small packets into larger ones. This improves throughput at the\n expense of latency.\n\n- **`{sctp_disable_fragments, true|false}`** - If `true`, induces an error on an\n attempt to send a message larger than the current PMTU size (which would\n require fragmentation/reassembling). Notice that message fragmentation does\n not affect the logical atomicity of its delivery; this option is provided for\n performance reasons only.\n\n- **`{sctp_i_want_mapped_v4_addr, true|false}`** - Turns on|off automatic\n mapping of IPv4 addresses into IPv6 ones (if the socket address family is\n `AF_INET6`).\n\n- **`{sctp_maxseg, integer()}`** - Determines the maximum chunk size if message\n fragmentation is used. If `0`, the chunk size is limited by the Path MTU only.\n\n- **`{sctp_primary_addr, #sctp_prim{}}`**\n\n ```erlang\n #sctp_prim{\n assoc_id = assoc_id(),\n addr = {IP, Port}\n }\n IP = ip_address()\n Port = port_number()\n ```\n\n For the association specified by `assoc_id`, `{IP,Port}` must be one of the\n peer addresses. This option determines that the specified address is treated\n by the local SCTP stack as the primary address of the peer.\n\n- **`{sctp_set_peer_primary_addr, #sctp_setpeerprim{}}`**\n\n ```erlang\n #sctp_setpeerprim{\n assoc_id = assoc_id(),\n addr = {IP, Port}\n }\n IP = ip_address()\n Port = port_number()\n ```\n\n When set, informs the peer to use `{IP, Port}` as the primary address of the\n local endpoint for the association specified by `assoc_id`.\n\n\n- **`{sctp_adaptation_layer, #sctp_setadaptation{}}`** [](){: #option-sctp_adaptation_layer }\n\n ```erlang\n #sctp_setadaptation{\n adaptation_ind = integer()\n }\n ```\n\n When set, requests that the local endpoint uses the value specified by\n `adaptation_ind` as the Adaptation Indication parameter for establishing\n new associations. For details, see\n [RFC 2960](http://www.rfc-archive.org/getrfc.php?rfc=2960) and\n [Sockets API Extensions for SCTP](http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13).\n\n- **`{sctp_peer_addr_params, #sctp_paddrparams{}}`**\n\n ```erlang\n #sctp_paddrparams{\n assoc_id = assoc_id(),\n address = {IP, Port},\n hbinterval = integer(),\n pathmaxrxt = integer(),\n pathmtu = integer(),\n sackdelay = integer(),\n flags = list()\n }\n IP = ip_address()\n Port = port_number()\n ```\n\n Determines various per-address parameters for the association specified by\n `assoc_id` and the peer address `address` (the SCTP protocol supports\n multi-homing, so more than one address can correspond to a specified\n association).\n\n - **`hbinterval`** - Heartbeat interval, in milliseconds\n\n - **`pathmaxrxt`** - Maximum number of retransmissions before this address is\n considered unreachable (and an alternative address is selected)\n\n - **`pathmtu`** - Fixed Path MTU, if automatic discovery is disabled (see\n `flags` below)\n\n - **`sackdelay`** - Delay, in milliseconds, for SAC messages (if the delay is\n enabled, see `flags` below)\n\n - **`flags`** - The following flags are available:\n\n - **`hb_enable`** - Enables heartbeat\n\n - **`hb_disable`** - Disables heartbeat\n\n - **`hb_demand`** - Initiates heartbeat immediately\n\n - **`pmtud_enable`** - Enables automatic Path MTU discovery\n\n - **`pmtud_disable`** - Disables automatic Path MTU discovery\n\n - **`sackdelay_enable`** - Enables SAC delay\n\n - **`sackdelay_disable`** - Disables SAC delay\n\n- **`{sctp_default_send_param, #sctp_sndrcvinfo{}}`**\n\n [](){: #record-sctp_sndrcvinfo }\n ```erlang\n #sctp_sndrcvinfo{\n stream = integer(),\n ssn = integer(),\n flags = list(),\n ppid = integer(),\n context = integer(),\n timetolive = integer(),\n tsn = integer(),\n cumtsn = integer(),\n assoc_id = assoc_id()\n }\n ```\n\n `#sctp_sndrcvinfo{}` is used both in this socket option, and as\n ancillary data while sending or receiving SCTP messages. When set\n as an option, it provides default values for subsequent\n [`send`](`send/3`) calls on the association specified by `assoc_id`.\n\n `assoc_id = 0` (default) indicates the whole endpoint.\n\n The following fields typically must be specified by the sender:\n\n - **`sinfo_stream`** - Stream number (0-base) within the association to send\n the messages through;\n\n - **`sinfo_flags`** - The following flags are recognised:\n\n - **`unordered`** - The message is to be sent unordered\n\n - **`addr_over`** - The address specified in [`send`](`send/3`) overwrites\n the primary peer address\n\n - **`abort`** - Aborts the current association without flushing any unsent\n data\n\n - **`eof`** - Gracefully shuts down the current association, with flushing\n of unsent data\n\n Other fields are rarely used. For complete information, see\n [RFC 2960](http://www.rfc-archive.org/getrfc.php?rfc=2960) and\n [Sockets API Extensions for SCTP](http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13).\n\n- **`{sctp_events, #sctp_event_subscribe{}}`** [](){: #option-sctp_events }\n\n ```erlang\n #sctp_event_subscribe{\n data_io_event = true | false,\n association_event = true | false,\n address_event = true | false,\n send_failure_event = true | false,\n peer_error_event = true | false,\n shutdown_event = true | false,\n partial_delivery_event = true | false,\n adaptation_layer_event = true | false\n }\n ```\n\n This option determines which [SCTP Events](#sctp-events) that are to be\n received (through [`recv/*`](`recv/1`)) along with the data. The only\n exception is `data_io_event`, which enables or disables receiving of\n [`#sctp_sndrcvinfo{}`](#record-sctp_sndrcvinfo) ancillary data,\n not events. By default, all flags except `adaptation_layer_event` are enabled,\n although `sctp_data_io_event` and `association_event` are used by the driver\n itself and not exported to the user level.\n\n- **`{sctp_delayed_ack_time, #sctp_assoc_value{}}`**\n\n ```erlang\n #sctp_assoc_value{\n assoc_id = assoc_id(),\n assoc_value = integer()\n }\n ```\n\n Rarely used. Determines the ACK time (specified by `assoc_value`, in\n milliseconds) for the specified association or the whole endpoint if\n `assoc_value = 0` (default).\n\n- **`{sctp_status, #sctp_status{}}`**\n\n ```erlang\n #sctp_status{\n assoc_id = assoc_id(),\n state = atom(),\n rwnd = integer(),\n unackdata = integer(),\n penddata = integer(),\n instrms = integer(),\n outstrms = integer(),\n fragmentation_point = integer(),\n primary = #sctp_paddrinfo{}\n }\n ```\n\n This option is read-only. It determines the status of the SCTP association\n specified by `assoc_id`. The following are the possible values of `state`\n (the state designations are mostly self-explanatory):\n\n - **`sctp_state_empty`** - Default. Means that no other state is active.\n\n - **`sctp_state_closed`**\n\n - **`sctp_state_cookie_wait`**\n\n - **`sctp_state_cookie_echoed`**\n\n - **`sctp_state_established`**\n\n - **`sctp_state_shutdown_pending`**\n\n - **`sctp_state_shutdown_sent`**\n\n - **`sctp_state_shutdown_received`**\n\n - **`sctp_state_shutdown_ack_sent`**\n\n Semantics of the other fields:\n\n - **`sstat_rwnd`** - Current receiver window size of the association\n\n - **`sstat_unackdata`** - Number of unacked data chunks\n\n - **`sstat_penddata`** - Number of data chunks pending receipt\n\n - **`sstat_instrms`** - Number of inbound streams\n\n - **`sstat_outstrms`** - Number of outbound streams\n\n - **`sstat_fragmentation_point`** - Message size at which SCTP fragmentation\n occurs\n\n - **`sstat_primary`** - Information on the current primary peer address (see\n below for the format of `#sctp_paddrinfo{}`)\n\n\n- **`{sctp_get_peer_addr_info, #sctp_paddrinfo{}}`** [](){: #option-sctp_get_peer_addr_info }\n\n ```erlang\n #sctp_paddrinfo{\n assoc_id = assoc_id(),\n address = {IP, Port},\n state = inactive | active | unconfirmed,\n cwnd = integer(),\n srtt = integer(),\n rto = integer(),\n mtu = integer()\n }\n IP = ip_address()\n Port = port_number()\n ```\n\n This option is read-only. It determines the parameters specific to\n the peer address specified by `address` within the association specified\n by `assoc_id`. Field `address` fmust be set by the caller; all other fields\n are filled in on return. If `assoc_id = 0` (default), the `address`\n is automatically translated into the corresponding association ID.\n This option is rarely used. For the semantics of all fields, see\n [RFC 2960](http://www.rfc-archive.org/getrfc.php?rfc=2960) and\n [Sockets API Extensions for SCTP](http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13).\n\n[](){: #examples } SCTP Examples\n--------------------------------\n\nExample of an Erlang SCTP server that receives SCTP messages\nand prints them on the standard output:\n\n```erlang\n-module(sctp_server).\n\n-export([server/0,server/1,server/2]).\n-include_lib(\"kernel/include/inet.hrl\").\n-include_lib(\"kernel/include/inet_sctp.hrl\").\n\nserver() ->\n server(any, 2006).\n\nserver([Host,Port]) when is_list(Host), is_list(Port) ->\n {ok, #hostent{h_addr_list = [IP|_]}} = inet:gethostbyname(Host),\n io:format(\"~w -> ~w~n\", [Host, IP]),\n server([IP, list_to_integer(Port)]).\n\nserver(IP, Port) when is_tuple(IP) orelse IP == any orelse IP == loopback,\n is_integer(Port) ->\n {ok,S} = gen_sctp:open(Port, [{recbuf,65536}, {ip,IP}]),\n io:format(\"Listening on ~w:~w. ~w~n\", [IP,Port,S]),\n ok = gen_sctp:listen(S, true),\n server_loop(S).\n\nserver_loop(S) ->\n case gen_sctp:recv(S) of\n {error, Error} ->\n io:format(\"SCTP RECV ERROR: ~p~n\", [Error]);\n Data ->\n io:format(\"Received: ~p~n\", [Data])\n end,\n server_loop(S).\n```\n\nExample of an Erlang SCTP client interacting with the above server.\nNote that in this example the client creates an association with\nthe server with 5 outbound streams. Therefore, sending of `\"Test 0\"`\nover stream 0 succeeds, but sending of `\"Test 5\"` over stream 5 fails.\nThe client then `abort`s the association, which results in that\nthe corresponding event is received on the server side.\n\n```erlang\n-module(sctp_client).\n\n-export([client/0, client/1, client/2]).\n-include_lib(\"kernel/include/inet.hrl\").\n-include_lib(\"kernel/include/inet_sctp.hrl\").\n\nclient() ->\n client([localhost]).\n\nclient([Host]) ->\n client(Host, 2006);\n\nclient([Host, Port]) when is_list(Host), is_list(Port) ->\n client(Host,list_to_integer(Port)),\n init:stop().\n\nclient(Host, Port) when is_integer(Port) ->\n {ok,S} = gen_sctp:open(),\n {ok,Assoc} = gen_sctp:connect\n (S, Host, Port, [{sctp_initmsg,#sctp_initmsg{num_ostreams=5}}]),\n io:format(\"Connection Successful, Assoc=~p~n\", [Assoc]),\n\n io:write(gen_sctp:send(S, Assoc, 0, <<\"Test 0\">>)),\n io:nl(),\n timer:sleep(10000),\n io:write(gen_sctp:send(S, Assoc, 5, <<\"Test 5\">>)),\n io:nl(),\n timer:sleep(10000),\n io:write(gen_sctp:abort(S, Assoc)),\n io:nl(),\n\n timer:sleep(1000),\n gen_sctp:close(S).\n```\n\nA simple Erlang SCTP client that uses the `connect_init` API:\n\n```erlang\n-module(ex3).\n\n-export([client/4]).\n-include_lib(\"kernel/include/inet.hrl\").\n-include_lib(\"kernel/include/inet_sctp.hrl\").\n\nclient(Peer1, Port1, Peer2, Port2)\n when is_tuple(Peer1), is_integer(Port1), is_tuple(Peer2), is_integer(Port2) ->\n {ok,S} = gen_sctp:open(),\n SctpInitMsgOpt = {sctp_initmsg,#sctp_initmsg{num_ostreams=5}},\n ActiveOpt = {active, true},\n Opts = [SctpInitMsgOpt, ActiveOpt],\n ok = gen_sctp:connect(S, Peer1, Port1, Opts),\n ok = gen_sctp:connect(S, Peer2, Port2, Opts),\n io:format(\"Connections initiated~n\", []),\n client_loop(S, Peer1, Port1, undefined, Peer2, Port2, undefined).\n\nclient_loop(S, Peer1, Port1, AssocId1, Peer2, Port2, AssocId2) ->\n receive\n {sctp, S, Peer1, Port1, {_Anc, SAC}}\n when is_record(SAC, sctp_assoc_change), AssocId1 == undefined ->\n io:format(\"Association 1 connect result: ~p. AssocId: ~p~n\",\n [SAC#sctp_assoc_change.state,\n SAC#sctp_assoc_change.assoc_id]),\n client_loop(S, Peer1, Port1, SAC#sctp_assoc_change.assoc_id,\n Peer2, Port2, AssocId2);\n\n {sctp, S, Peer2, Port2, {_Anc, SAC}}\n when is_record(SAC, sctp_assoc_change), AssocId2 == undefined ->\n io:format(\"Association 2 connect result: ~p. AssocId: ~p~n\",\n [SAC#sctp_assoc_change.state, SAC#sctp_assoc_change.assoc_id]),\n client_loop(S, Peer1, Port1, AssocId1, Peer2, Port2,\n SAC#sctp_assoc_change.assoc_id);\n\n {sctp, S, Peer1, Port1, Data} ->\n io:format(\"Association 1: received ~p~n\", [Data]),\n client_loop(S, Peer1, Port1, AssocId1,\n Peer2, Port2, AssocId2);\n\n {sctp, S, Peer2, Port2, Data} ->\n io:format(\"Association 2: received ~p~n\", [Data]),\n client_loop(S, Peer1, Port1, AssocId1,\n Peer2, Port2, AssocId2);\n\n Other ->\n io:format(\"Other ~p~n\", [Other]),\n client_loop(S, Peer1, Port1, AssocId1,\n Peer2, Port2, AssocId2)\n\n after 5000 ->\n ok\n end.\n```\n\n[](){: #seealso } See Also\n--------------------------\n\n`m:gen_tcp`, `m:gen_udp`, `m:inet`,\n[RFC 2960](http://www.rfc-archive.org/getrfc.php?rfc=2960) (Stream Control\nTransmission Protocol),\n[Sockets API Extensions for SCTP](http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13)","ref":"gen_sctp.html"},{"type":"function","title":"gen_sctp.abort/2","doc":"Abort an association.\n\nAbnormally terminates the association specified by `Assoc`,\nwithout flushing unsent data. The socket itself remains open.\nOther associations opened on this socket are still valid,\nand the socket can be used in new associations.","ref":"gen_sctp.html#abort/2"},{"type":"function","title":"gen_sctp.close/1","doc":"Close an SCTP socket.\n\nCloses the socket and all associations on it. The unsent data is flushed\nas for `eof/2`. The [`close/1`](`close/1`) call is blocking\ndepending of the value of the [`linger`](`m:inet#option-linger`)\nsocket [option]. If it is `false` or the linger time-out expires,\nthe call returns and unsent data is flushed in the background.","ref":"gen_sctp.html#close/1"},{"type":"function","title":"gen_sctp.connect/3","doc":"","ref":"gen_sctp.html#connect/3"},{"type":"function","title":"gen_sctp.connect/4","doc":"Establish an association with a peer.\n\nWith arguments `Addr` and `Port`, equivalent to\n[`connect(Socket, Addr, Port, Opts, infinity)`](`connect/5`).\n\nWith arguments `SockAddr` and `Opts` _(since OTP 24.3)_, equivalent to\n[`connect(Socket, Addr, Port, Opts, Timeout)`](`connect/5`)\nwhere `Addr` and `Port` are extracted from `SockAddr`.","ref":"gen_sctp.html#connect/4"},{"type":"function","title":"gen_sctp.connect/5","doc":"Establish an association with a peer.\n\nEstablishes a new association for socket `Socket`, with the peer\n(SCTP server socket) specified by `Addr` and `Port`.\n`Timeout`, is expressed in milliseconds.\nA socket can be associated with multiple peers.\nThe socket has to be of type `seqpacket`.\n\n> #### Warning {: .warning }\n>\n> Using a value of `Timeout` less than the maximum time taken by the OS to\n> establish an association (around 4.5 minutes if the default values from\n> [RFC 4960](https://tools.ietf.org/html/rfc4960) are used), can result in\n> inconsistent or incorrect return values. This is especially relevant for\n> associations sharing the same `Socket` (that is, source address and port), as\n> the controlling process blocks until `connect/*` returns.\n> [`connect_init/*`](`connect_init/4`) provides an alternative without this\n> limitation.\n\n### [](){: #record-sctp_assoc_change } `#sctp_assoc_change{}`\n\nThe result of `connect/*` is an `#sctp_assoc_change{}` event that contains,\nin particular, the new [Association ID](`t:assoc_id/0`):\nl\n```erlang\n#sctp_assoc_change{\n state = atom(),\n error = integer(),\n outbound_streams = integer(),\n inbound_streams = integer(),\n assoc_id = assoc_id()\n}\n```\n\nThe number of outbound and inbound streams for the association\ncan be set by giving an `sctp_initmsg` option to `connect` as in:\n\n```erlang\nconnect(Socket, Ip, Port>,\n [{sctp_initmsg,#sctp_initmsg{num_ostreams=OutStreams,\n max_instreams=MaxInStreams}}])\n```\n\nAll options `Opt` are set on the socket before the association is attempted.\nIf an option record has undefined field values, the options record\nis first read from the socket for those values. In effect,\n`Opt` option records only need to define field values to change\nbefore connecting.\n\nThe returned `outbound_streams` and `inbound_streams` are the number of\nstream on the socket. These can be different from the requested values\n(`OutStreams` and `MaxInStreams`, respectively), if the peer\nrequires lower values.\n\n`state` can have the following values:\n\n- **`comm_up`** - Association is successfully established. This indicates\n a successful completion of `connect`.\n\n- **`cant_assoc`** - The association cannot be established\n (`connect/*` failure).\n\nOther states do not normally occur in the output from `connect/*`.\nRather, they can occur in `#sctp_assoc_change{}` events received\ninstead of data from [`recv/*`](`recv/1`) calls or socket messages.\nAll of them indicate losing the association because of various\nerror conditions, and are listed here for the sake of completeness:\n\n- **`comm_lost`**\n\n- **`restart`**\n\n- **`shutdown_comp`**\n\nThe field `error` can provide more detailed diagnostics. Its value\ncan be converted into a string using `error_string/1`.","ref":"gen_sctp.html#connect/5"},{"type":"function","title":"gen_sctp.connect_init/3","doc":"","ref":"gen_sctp.html#connect_init/3"},{"type":"function","title":"gen_sctp.connect_init/4","doc":"Start establishing an association with a peer.\n\nWith arguments `Addr` and `Port`, equivalent to\n[`connect_init(Socket, Addr, Port, Opts, infinity)`](`connect/5`).\n\nWith arguments `SockAddr` and `Opts` _(since OTP 24.3)_, equivalent to\n[`connect_init(Socket, Addr, Port, Opts, Timeout)`](`connect/5`)\nwhere `Addr` and `Port` are extracted from `SockAddr`.","ref":"gen_sctp.html#connect_init/4"},{"type":"function","title":"gen_sctp.connect_init/5","doc":"Start establishing an association with a peer.\n\nInitiates a new association for socket `Socket`, with the peer\n(SCTP server socket) specified by `Addr` and `Port`.\n\nThe fundamental difference between this API and `connect/*` is that\nthe return value is that of the underlying OS `connect(2)` system call.\nIf `ok` is returned, the operation has been succesfully initiated,\nand the final result result of the association establishment\nis sent to the socket owner (controlling process) as an\n[`#sctp_assoc_change{}`](#record-sctp_assoc_change) event.\nThe socket owner must be prepared to receive this, the\n[`recv/*`](`recv/1`) call has to be polled, depending on the value\nof the [active option](#option-active).\n\nThe parameters are as described for [`connect/*`](`connect/5`),\nexcept the `Timeout` value since for this function, the time-out only\napplies to the name resolving of `Addr` when it is a `t:inet:hostname/0`.","ref":"gen_sctp.html#connect_init/5"},{"type":"function","title":"gen_sctp.connectx_init/3","doc":"Start establishing an association with a peer (multiple addresses).\n\nSimilar to `connectx_init/5` except using socket addresses, and not having a\n`Timeout`. Since the addresses do not need lookup and the connect is\nnon-blocking this call returns immediately.\n\nThe value of each socket address `port` must be the same or zero.\nAt least one socket address must have a non-zero `port`","ref":"gen_sctp.html#connectx_init/3"},{"type":"function","title":"gen_sctp.connectx_init/4","doc":"","ref":"gen_sctp.html#connectx_init/4"},{"type":"function","title":"gen_sctp.connectx_init/5","doc":"Start establishing an association with a peer (multiple addresses).\n\nInitiates a new association for socket `Socket`, with the peer\n(SCTP server socket) specified by `Addrs` and `Port`.\n\nThis API is similar to `connect_init/*` except the underlying OS\n`sctp_connectx(3)` system call is used, that accepts multiple\ndestination addresses.\n\nIf successful, the association ID is returned which will be received in a\nsubsequent [`#sctp_assoc_change{}`](#record-sctp_assoc_change)\nevent.\n\nThe parameters are as described in `connect_init/5`\n\n> #### Note {: .info }\n> This API allows the OS to use all Addrs when establishing an association,\n> but does not guarantee it will. Therefore, if the connection fails,\n> the user may want to rotate the order of addresses for a subsequent call.","ref":"gen_sctp.html#connectx_init/5"},{"type":"function","title":"gen_sctp.controlling_process/2","doc":"Change the controlling process (owner) of a socket.\n\nAssigns a new controlling process `Pid` to `Socket`.\nSee `gen_udp:controlling_process/2`.","ref":"gen_sctp.html#controlling_process/2"},{"type":"function","title":"gen_sctp.eof/2","doc":"Terminate an association gracefully.\n\nGracefully terminates the association specified by `Assoc`, flushing\nall unsent data. The socket itself remains open. Other associations\nopened on this socket are still valid. The socket can be used\nin new associations.","ref":"gen_sctp.html#eof/2"},{"type":"function","title":"gen_sctp.error_string/1","doc":"Translate an error number into a string or atom.\n\nTranslates an SCTP error number from, for example, `#sctp_remote_error{}`\nor `#sctp_send_failed{}` into an explanatory string, or into\none of the atoms `ok` for no error, or `unknown_error`\nfor an unrecognized integer.","ref":"gen_sctp.html#error_string/1"},{"type":"function","title":"gen_sctp.listen/2","doc":"Make an SCTP socket listen to incoming associations.\n\nThe socket will listen on the IP address(es) and port number it is bound to.\n\nFor type `seqpacket`, sockets (the default), the argument`IsServer`\nmust be a `t:boolean/0`. In contrast to `stream` sockets, there is\nno listening queue length. If `IsServer` is `true`, the socket accepts\nnew associations, that is, it becomes an SCTP server socket.\n\nFor type `stream` sockets, the argument `Backlog` sets\nthe backlog queue length just like for TCP.","ref":"gen_sctp.html#listen/2"},{"type":"function","title":"gen_sctp.open/0","doc":"","ref":"gen_sctp.html#open/0"},{"type":"function","title":"gen_sctp.open/1","doc":"Create an SCTP socket.\n\nWith argument [`Port`](`t:inet:port_number/0`),\nequivalent to`open([{port, Port}]`.\n\nCreates an SCTP socket and binds it to the local addresses specified by all\n`{ip,IP}` (or synonymously `{ifaddr,IP}`) options (this feature is called\nSCTP multi-homing). The default `IP` and `Port` are `any` and `0`,\nmeaning bind to all local addresses on any free port.\n\nIt is also possible to use `{ifaddr, SockAddr}`, in which case it takes\nprecedence over the `ip` and `port` options. These options can however\nbe used to update the address and port of ifaddr (if they occur\nafter ifaddr in the options list), although this is not recommended.\n\nOther options:\n\n- **`inet6`** - Sets up the socket for IPv6.\n\n- **`inet`** - Sets up the socket for IPv4. This is the default.\n\nA default set of socket [options](#options) is used.\nIn particular, the socket is opened in [binary](#option-binary)\nand [passive](#option-active) mode, with SockType `seqpacket`,\nand with reasonably large [kernel](`m:inet#option-sndbuf`) and driver\n[buffers](`m:inet#option-buffer`).\n\nWhen the socket is in [passive](#option-active) mode,\ndata can be received through the [`recv/1,2`](`recv/1`) calls.\n\nWhen the socket is in [active](#option-active) mode,\ndata received data is delivered to the controlling process as messages:\n\n```erlang\n{sctp, Socket, FromIP, FromPort, {AncData, Data}}\n```\n\nSee [`recv/1,2`](`recv/1`) for a description of the message fields.\n\n> #### Note {: .info }\n>\n> This message format unfortunately differs slightly from the\n> [`gen_udp`](`gen_udp:open/1`) message format with ancillary data,\n> and from the [`recv/1,2`](`recv/1`) return tuple format.","ref":"gen_sctp.html#open/1"},{"type":"function","title":"gen_sctp.open/2","doc":"","ref":"gen_sctp.html#open/2"},{"type":"function","title":"gen_sctp.peeloff/2","doc":"Branch off an association into a new socket of type `stream`.\n\nThe existing association `Assoc` in the socket `Socket` (that has to\nbe of type `seqpacket`; one-to-many style) is branched off into\na new socket `NewSocket` of type `stream` (one-to-one style).\n\nThe existing association argument `Assoc` can be a\n[`#sctp_assoc_change{}`](#record-sctp_assoc_change) record as\nreturned from, for example, [`recv/*`](`recv/2`), [`connect/*`](`connect/5`),\nor from a listening socket in active mode.\nIt can also be just the field `assoc_id` `t:integer/0` from such a record.","ref":"gen_sctp.html#peeloff/2"},{"type":"function","title":"gen_sctp.recv/1","doc":"","ref":"gen_sctp.html#recv/1"},{"type":"function","title":"gen_sctp.recv/2","doc":"Receive a `Data` message.\n\nReceives the `Data` message from any association of the socket.\nIf the receive times out, `{error,timeout}` is returned. The default\ntime-out is `infinity`. `FromIP` and `FromPort` indicate the address\nof the sender.\n\n`AncData` is a list of ancillary data items received with the main `Data`.\nThis list can be empty, or contain a single\n[`#sctp_sndrcvinfo{}`](#record-sctp_sndrcvinfo) record,\nif receiving ancillary data is enabled\n(see option [`sctp_events`](#option-sctp_events)).\nPer default, it is enabled, as such ancillary data provides an easy way\nto determine the association and stream over which the message was received.\n(An alternative way is to get the association ID from `FromIP` and `FromPort`\nusing socket option\n[`sctp_get_peer_addr_info`](#option-sctp_get_peer_addr_info),\nbut this does still not give the stream number).\n\n`AncData` may also contain [ancillary data](`t:inet:ancillary_data/0`)\nfrom the socket [options](#options)\n[`recvtos`](`m:inet#option-recvtos`),\n[`recvtclass`](`m:inet#option-recvtclass`) or\n[`recvttl`](`m:inet#option-recvttl`), if that is supported for the socket\nby the platform.\n\nThe `Data` received can, depending on the socket [mode](#option-binary)\nbe a `t:binary/0` or a `t:list/0` of bytes (integers in the range\n`0` through `255`), or it can be an SCTP event.\n\n### [](){: #sctp-events } Possible SCTP events\n\n- [`#sctp_sndrcvinfo{}`](#record-sctp_sndrcvinfo)\n- [`#sctp_assoc_change{}`](#record-sctp_assoc_change)\n- ```erlang\n #sctp_paddr_change{\n addr = {ip_address(),port()},\n state = atom(),\n error = integer(),\n assoc_id = assoc_id()\n }\n ```\n\n Indicates change of the status of the IP address of the peer specified by\n `addr` within association `assoc_id`. Possible values of `state` (mostly\n self-explanatory) include:\n\n - **`addr_unreachable`**\n\n - **`addr_available`**\n\n - **`addr_removed`**\n\n - **`addr_added`**\n\n - **`addr_made_prim`**\n\n - **`addr_confirmed`**\n\n In case of an error (for example, `addr_unreachable`), the field `error`\n provides more diagnostics. In such cases, event `#sctp_paddr_change{}`\n is automatically converted into an `error` term returned by\n [`recv`](`recv/1`). The `error` field value can be converted\n into a string using `error_string/1`.\n\n- ```erlang\n #sctp_send_failed{\n flags = true | false,\n error = integer(),\n info = #sctp_sndrcvinfo{},\n assoc_id = assoc_id()\n data = binary()\n }\n ```\n\n The sender can receive this event if a send operation fails.\n\n - **`flags`** - A Boolean specifying if the data has been transmitted\n over the wire.\n\n - **`error`** - Provides extended diagnostics, use\n [`error_string/1`.](`error_string/1`)\n\n - **`info`** - The original\n [`#sctp_sndrcvinfo{}`](#record-sctp_sndrcvinfo) record\n used in the failed [`send/*`.](`send/3`)\n\n - **`data`** - The whole original data chunk attempted to be sent.\n\n In the current implementation of the Erlang/SCTP binding, this event is\n internally converted into an `error` term returned by [`recv/*`](`recv/1`).\n\n- ```erlang\n #sctp_adaptation_event{\n adaptation_ind = integer(),\n assoc_id = assoc_id()\n }\n ```\n\n Delivered when a peer sends an adaptation layer indication parameter\n (configured through option\n [`sctp_adaptation_layer`](#option-sctp_adaptation_layer)).\n Notie that with the current implementation of the Erlang/SCTP binding,\n this event is disabled by default.\n\n- ```erlang\n #sctp_pdapi_event{\n indication = sctp_partial_delivery_aborted,\n assoc_id = assoc_id()\n }\n ```\n\n A partial delivery failure. In the current implementation\n of the Erlang/SCTP binding, this event is internally converted\n into an `error` term returned by [`recv/*`](`recv/1`).","ref":"gen_sctp.html#recv/2"},{"type":"function","title":"gen_sctp.send/3","doc":"Send a `Data` message, full-featured.\n\nSends the `Data` message with all sending parameters from a\n[`#sctp_sndrcvinfo{}`](#record-sctp_sndrcvinfo) record.\nThis way, the user can specify the PPID (passed to the remote end)\nand context (passed to the local SCTP layer), which can be used,\nfor example, for error identification. However, such a fine grained\nuser control is rarely required. The function [`send/4`](`send/4`)\nis sufficient for most applications.\n\n> #### Note {: .info }\n>\n> Send is normally blocking, but if the socket option\n> [`non_block_send`](#option_non_block_send) is set to true,\n> the function will return with e.g. {error, eagain}\n> in the case when the function would otherwise block.\n> It is then up to the user to try again later.","ref":"gen_sctp.html#send/3"},{"type":"function","title":"gen_sctp.send/4","doc":"Send a data message.\n\nSends a `Data` message on the association `Assoc` and `Stream`.\n\n`Assoc` can be specified with a\n[`#sctp_assoc_change{}`](#record-sctp_assoc_change) record\nfrom an association establishment, or as the `t:assoc_id/0`\n`t:integer/0` field value.\n\n> #### Note {: .info }\n>\n> Send is normally blocking, but if the socket option\n> [`non_block_send`](#option_non_block_send) is set to true,\n> the function will return with e.g. {error, eagain}\n> in the case when the function would otherwise block.\n> It is then up to the user to try again later.","ref":"gen_sctp.html#send/4"},{"type":"type","title":"gen_sctp.assoc_id/0","doc":"Association ID.\n\nAn opaque term returned in, for example, `#sctp_paddr_change{}`, which\nidentifies an association for an SCTP socket. The term is opaque except for the\nspecial value `0`, which has a meaning such as \"the whole endpoint\" or \"all\nfuture associations\".","ref":"gen_sctp.html#t:assoc_id/0"},{"type":"type","title":"gen_sctp.elementary_option/0","doc":"","ref":"gen_sctp.html#t:elementary_option/0"},{"type":"type","title":"gen_sctp.elementary_option_name/0","doc":"","ref":"gen_sctp.html#t:elementary_option_name/0"},{"type":"type","title":"gen_sctp.option/0","doc":"[SCTP Socket Option](#options) name and value, to set.","ref":"gen_sctp.html#t:option/0"},{"type":"type","title":"gen_sctp.option_name/0","doc":"[SCTP Socket Option](#options) name, to get.","ref":"gen_sctp.html#t:option_name/0"},{"type":"type","title":"gen_sctp.option_value/0","doc":"[SCTP Socket Option](#options) name and value, what you get.","ref":"gen_sctp.html#t:option_value/0"},{"type":"type","title":"gen_sctp.record_option/0","doc":"","ref":"gen_sctp.html#t:record_option/0"},{"type":"type","title":"gen_sctp.ro_option/0","doc":"","ref":"gen_sctp.html#t:ro_option/0"},{"type":"type","title":"gen_sctp.sctp_socket/0","doc":"Socket identifier returned from [`open/*`](`open/0`).","ref":"gen_sctp.html#t:sctp_socket/0"},{"type":"module","title":"gen_tcp","doc":"Interface to TCP/IP sockets.\n\nThis module provides functions for communicating over TCP/IP\nprotocol sockets.\n\nThe following code fragment is a simple example of a client connecting to a\nserver at port 5678, transferring a binary, and closing the connection:\n\n```erlang\nclient() ->\n SomeHostInNet = \"localhost\", % to make it runnable on one machine\n {ok, Sock} = gen_tcp:connect(SomeHostInNet, 5678,\n [binary, {packet, 0}]),\n ok = gen_tcp:send(Sock, \"Some Data\"),\n ok = gen_tcp:close(Sock).\n```\n\nAt the other end, a server is listening on port 5678, accepts the connection,\nand receives the binary:\n\n```erlang\nserver() ->\n {ok, LSock} = gen_tcp:listen(5678, [binary, {packet, 0},\n {active, false}]),\n {ok, Sock} = gen_tcp:accept(LSock),\n {ok, Bin} = do_recv(Sock, []),\n ok = gen_tcp:close(Sock),\n ok = gen_tcp:close(LSock),\n Bin.\n\ndo_recv(Sock, Bs) ->\n case gen_tcp:recv(Sock, 0) of\n {ok, B} ->\n do_recv(Sock, [Bs, B]);\n {error, closed} ->\n {ok, list_to_binary(Bs)}\n end.\n```\n\nFor more examples, see section [Examples](#module-examples).\n\n> #### Note {: .info }\n>\n> Functions that create sockets can take an optional option;\n> `{inet_backend, Backend}` that, if specified, has to be the first option. This\n> selects the implementation backend towards the platform's socket API.\n>\n> This is a _temporary_ option that will be ignored in a future release.\n>\n> The default is `Backend = inet` that selects the traditional `inet_drv.c`\n> driver. The other choice is `Backend = socket` that selects the new `m:socket`\n> module and its NIF implementation.\n>\n> The system default can be changed when the node is started with the\n> application `kernel`'s configuration variable `inet_backend`.\n>\n> For `gen_tcp` with `inet_backend = socket` we have tried to be as \"compatible\"\n> as possible which has sometimes been impossible. Here is a list of cases when\n> the behaviour of inet-backend `inet` (default) and `socket` are different:\n>\n> - [Non-blocking send](#non_blocking_send)\n>\n> If a user calling [`gen_tcp:send/2`](`send/2`) with `inet_backend = inet`,\n> tries to send more data than there is room for in the OS buffers, the \"rest\n> data\" is buffered by the inet driver (and later sent in the background). The\n> effect for the user is that the call is non-blocking.\n>\n> This is _not_ the effect when `inet_backend = socket`, since there is no\n> buffering. Instead the user hangs either until all data has been sent or the\n> `send_timeout` timeout has been reached.\n>\n> - `shutdown/2` may hide errors\n>\n> The call does not involve the receive process state, and is done\n> right on the underlying socket. On for example Linux, it is a known\n> misbehaviour that it skips some checks so doing shutdown on a\n> listen socket returns `ok` while the logical result should have been\n> `{error, enotconn}`. The `inet_drv.c` driver did an extra check\n> and simulated the correct error, but with `Backend = socket`\n> it would introduce overhead to involve the receive process.\n>\n> - The option [nodelay](`m:inet#option-nodelay`) is a TCP specific option that\n> is _not_ compatible with `domain = local`.\n>\n> When using `inet_backend = socket`, trying to create a socket (via listen or\n> connect) with `domain = local` (for example with option \\{ifaddr,\n> \\{local,\"/tmp/test\"\\}\\}) _will fail_ with `{error, enotsup}`.\n>\n> This does not actually work for `inet_backend = inet` either, but in that\n> case the error is simply _ignored_, which is a _bad_ idea. We have chosen to\n> _not_ ignore this error for `inet_backend = socket`.\n>\n> - [Async shutdown write](#async_shutdown_write)\n>\n> Calling [gen_tcp:shutdown(Socket, write | read_write)](`shutdown/2`) on a\n> socket created with `inet_backend = socket` will take _immediate_ effect,\n> unlike for a socket created with `inet_backend = inet`.\n>\n> See [async shutdown write](#async_shutdown_write) for more info.\n>\n> - Windows require sockets (domain = `inet | inet6`) to be bound.\n>\n> _Currently_ all sockets created on Windows with `inet_backend = socket` will\n> be bound. If the user does not provide an address, gen_tcp will try to\n> 'figure out' an address itself.","ref":"gen_tcp.html"},{"type":"module","title":"Examples - gen_tcp","doc":"The following example illustrates use of option `{active,once}` and multiple\naccepts by implementing a server as a number of worker processes doing accept on\na single listening socket. Function `start/2` takes the number of worker\nprocesses and the port number on which to listen for incoming connections. If\n`LPort` is specified as `0`, an ephemeral port number is used, which is why the\nstart function returns the actual port number allocated:\n\n```erlang\nstart(Num,LPort) ->\n case gen_tcp:listen(LPort,[{active, false},{packet,2}]) of\n {ok, ListenSock} ->\n start_servers(Num,ListenSock),\n {ok, Port} = inet:port(ListenSock),\n Port;\n {error,Reason} ->\n {error,Reason}\n end.\n\nstart_servers(0,_) ->\n ok;\nstart_servers(Num,LS) ->\n spawn(?MODULE,server,[LS]),\n start_servers(Num-1,LS).\n\nserver(LS) ->\n case gen_tcp:accept(LS) of\n {ok,S} ->\n loop(S),\n server(LS);\n Other ->\n io:format(\"accept returned ~w - goodbye!~n\",[Other]),\n ok\n end.\n\nloop(S) ->\n inet:setopts(S,[{active,once}]),\n receive\n {tcp,S,Data} ->\n Answer = process(Data), % Not implemented in this example\n gen_tcp:send(S,Answer),\n loop(S);\n {tcp_closed,S} ->\n io:format(\"Socket ~w closed [~w]~n\",[S,self()]),\n ok\n end.\n```\n\nExample of a simple client:\n\n```erlang\nclient(PortNo,Message) ->\n {ok,Sock} = gen_tcp:connect(\"localhost\",PortNo,[{active,false},\n {packet,2}]),\n gen_tcp:send(Sock,Message),\n A = gen_tcp:recv(Sock,0),\n gen_tcp:close(Sock),\n A.\n```\n\nThe `send` call does not accept a time-out option because time-outs on send is\nhandled through socket option `send_timeout`. The behavior of a send operation\nwith no receiver is mainly defined by the underlying TCP stack and the network\ninfrastructure. To write code that handles a hanging receiver that can\neventually cause the sender to hang on a `send` do like the following.\n\nConsider a process that receives data from a client process to be forwarded to a\nserver on the network. The process is connected to the server through TCP/IP and\ndoes not get any acknowledge for each message it sends, but has to rely on the\nsend time-out option to detect that the other end is unresponsive. Option\n`send_timeout` can be used when connecting:\n\n```erlang\n...\n{ok,Sock} = gen_tcp:connect(HostAddress, Port,\n [{active,false},\n {send_timeout, 5000},\n {packet,2}]),\n loop(Sock), % See below\n...\n```\n\nIn the loop where requests are handled, send time-outs can now be detected:\n\n```erlang\nloop(Sock) ->\n receive\n {Client, send_data, Binary} ->\n case gen_tcp:send(Sock,[Binary]) of\n {error, timeout} ->\n io:format(\"Send timeout, closing!~n\",\n []),\n handle_send_timeout(), % Not implemented here\n Client ! {self(),{error_sending, timeout}},\n %% Usually, it's a good idea to give up in case of a\n %% send timeout, as you never know how much actually\n %% reached the server, maybe only a packet header?!\n gen_tcp:close(Sock);\n {error, OtherSendError} ->\n io:format(\"Some other error on socket (~p), closing\",\n [OtherSendError]),\n Client ! {self(),{error_sending, OtherSendError}},\n gen_tcp:close(Sock);\n ok ->\n Client ! {self(), data_sent},\n loop(Sock)\n end\n end.\n```\n\nUsually it suffices to detect time-outs on receive, as most protocols include\nsome sort of acknowledgment from the server, but if the protocol is strictly one\nway, option `send_timeout` comes in handy.","ref":"gen_tcp.html#module-examples"},{"type":"function","title":"gen_tcp.accept/1","doc":"","ref":"gen_tcp.html#accept/1"},{"type":"function","title":"gen_tcp.accept/2","doc":"Accept an incoming connection request on a listen socket.\n\n`Socket` must be a socket returned from `listen/2`. `Timeout` specifies\na time-out value in milliseconds. Defaults to `infinity`.\n\nReturns:\n\n- `{ok, Socket}` if a connection is established\n- `{error, closed}` if `ListenSocket` is closed\n- `{error, timeout}` if no connection is established within `Timeout`\n- `{error, system_limit}` if all available ports in the Erlang emulator\n are in use\n- A POSIX error value if something else goes wrong, see `m:inet`\n about possible values\n\nTo send packets (outbound) on the returned `Socket`, use `send/2`.\nPackets sent from the peer (inbound) are delivered as messages\nto the socket owner; the process that created the socket.\nUnless `{active, false}` is specified in the option list when creating\nthe [listening socket](`listen/2`).\n\nSee `connect/4` about _active mode_ socket messages and _passive mode_.\n\n> #### Note {: .info }\n>\n> The `accept` call _doesn't have to be_ issued from the socket owner process.\n> Using version 5.5.3 and higher of the emulator, multiple simultaneous accept\n> calls can be issued from different processes, which allows for a pool of\n> acceptor processes handling incoming connections.","ref":"gen_tcp.html#accept/2"},{"type":"function","title":"gen_tcp.close/1","doc":"Close a TCP socket.\n\nNote that in most implementations of TCP, doing a `close` does not guarantee\nthat the data sent is delivered to the recipient. It is guaranteed that\nthe recepient will see all sent data before getting the close, but the\nsender gets no indication of that.\n\nIf the sender needs to know that the recepient has received all data\nthere are two common ways to achieve this:\n\n1. Use [`gen_tcp:shutdown(Sock, write)`](`shutdown/2`) to signal that no more\n data is to be sent and wait for the other side to acknowledge seeing\n its read side being closed, by closing its write side, which shows\n as a socket close on this side.\n2. Implement an acknowledgement in the protocol on top of TCP\n that both connection ends adhere to, indicating that all data\n has been seen. The socket option [`{packet, N}`](`m:inet#option-packet`)\n may be useful.","ref":"gen_tcp.html#close/1"},{"type":"function","title":"gen_tcp.connect/2","doc":"Equivalent to [`connect(SockAddr, Opts, infinity)`](`connect/3`).","ref":"gen_tcp.html#connect/2"},{"type":"function","title":"gen_tcp.connect/3","doc":"Create a socket connected to the specified address.","ref":"gen_tcp.html#connect/3"},{"type":"function","title":"With arguments `Address` and `Port` - gen_tcp.connect/3","doc":"Equivalent to [`connect(Address, Port, Opts, infinity)`](`connect/4`).","ref":"gen_tcp.html#connect/3-with-arguments-address-and-port"},{"type":"function","title":"With argument `SockAddr` **(since OTP 24.3)** - gen_tcp.connect/3","doc":"Connects to a remote listen socket specified by `SockAddr`\nwhere `t:socket:sockaddr_in6/0` for example allows specifying\nthe `scope_id` for link local IPv6 addresses.\n\n[IPv4 addresses](`t:socket:sockaddr_in/0`) on the same\n`t:map/0` format is also allowed.\n\nEquivalent to `connect/4`, besides the format of the destination address.","ref":"gen_tcp.html#connect/3-with-argument-sockaddr-since-otp-24-3"},{"type":"function","title":"gen_tcp.connect/4","doc":"Create a socket connected to the specified address.\n\nCreates a socket and connects it to a server on TCP port `Port`\non the host with IP address `Address`, that may also be a hostname.\n\n### `Opts` (connect options)\n\n- **`{ip, Address}`** - If the local host has many IP addresses,\n this option specifies which one to use.\n\n- **`{ifaddr, Address}`** - Same as `{ip, Address}`.\n\n However, if `Address` instead is a `t:socket:sockaddr_in/0` or\n `t:socket:sockaddr_in6/0` this takes precedence over any value\n previously set with the `ip` and `port` options. If these options\n (`ip` or/and `port`) however comes _after_ this option,\n they may be used to _update_ the corresponding fields of this option\n (for `ip`, the `addr` field, and for `port`, the `port` field).\n\n- **`{fd, integer() >= 0}`** - If a socket has somehow been connected without\n using `gen_tcp`, use this option to pass the file descriptor for it.\n If `{ip, Address}` and/or `{port, port_number()}` is combined\n with this option, the `fd` is bound to the specified interface\n and port before connecting. If these options are not specified,\n it is assumed that the `fd` is already bound appropriately.\n\n- **`inet`** - Sets up the socket for IPv4.\n\n- **`inet6`** - Sets up the socket for IPv6.\n\n- **`local`** - Sets up a Unix Domain Socket. See `t:inet:local_address/0`\n\n- **`{port, Port}`** - Specifies which local port number to use.\n\n- **`{tcp_module, module()}`** - Overrides which callback module is used.\n Defaults to `inet_tcp` for IPv4 and `inet6_tcp` for IPv6.\n\n- **`t:option/0`** - See `inet:setopts/2`.","ref":"gen_tcp.html#connect/4"},{"type":"function","title":"Socket Data - gen_tcp.connect/4","doc":"Packets can be sent to the peer (outbound) with\n[`send(Socket, Packet)`](`send/2`). Packets sent from the peer\n(inbound) are delivered as messages to the socket owner;\nthe process that created the socket, unless `{active, false}`\nis specified in the `Options` list.\n\n#### Active mode socket messages\n\n- **`{tcp, Socket, Data}`** - Inbound data from the socket.\n\n- **`{tcp_passive, Socket}`** -\n The socket was in `{active, N}` mode (see `inet:setopts/2` for details)\n and its message counter reached `0`, indicating that\n the socket has transitioned to passive (`{active, false}`) mode.\n\n\n- **`{tcp_closed, Socket}`** - The socket was closed.\n\n- **`{tcp_error, Socket, Reason}`** A socket error occurred.\n\n#### Passive mode\n\nIf `{active, false}` is specified in the option list for the socket,\npackets and errors are retrieved by calling [`recv/2,3`](`recv/3`)\n(`send/2` may also return errors).\n\n#### Timeout\n\nThe optional `Timeout` parameter specifies a connect time-out in milliseconds.\nDefaults to `infinity`.\n\n> #### Note {: .info }\n>\n> Keep in mind that if the underlying OS `connect()` call returns a timeout,\n> `gen_tcp:connect` will also return a timeout (i.e. `{error, etimedout}`),\n> even if a larger `Timeout` was specified (for example `infinity`).\n\n> #### Note {: .info }\n>\n> The default values for options specified to `connect` can be affected by the\n> Kernel configuration parameter `inet_default_connect_options`.\n> For details, see `m:inet`.","ref":"gen_tcp.html#connect/4-socket-data"},{"type":"function","title":"gen_tcp.controlling_process/2","doc":"Change the controlling process (owner) of a socket.\n\nAssigns a new controlling process `Pid` to `Socket`. The controlling process\nis the process that the socket sends messages to. If this function\nis called from any other process than the current controlling process,\n`{error, not_owner}` is returned.\n\nIf the process identified by `Pid` is not an existing local `t:pid/0`,\n`{error, badarg}` is returned. `{error, badarg}` may also be returned\nin some cases when `Socket` is closed during the execution of this function.\n\nIf the socket is in _active mode_, this function will transfer any messages\nfrom the socket in the mailbox of the caller to the new controlling process.\n\nIf any other process is interacting with the socket during the transfer,\nit may not work correctly and messages may remain in the caller's mailbox.\nFor instance, changing the sockets active mode during the transfer\ncould cause this.","ref":"gen_tcp.html#controlling_process/2"},{"type":"function","title":"gen_tcp.listen/2","doc":"Create a listen socket.\n\nCreates a socket and sets it to listen on port `Port` on the local host.\n\nIf `Port == 0`, the underlying OS assigns an available (ephemeral)\nport number, use `inet:port/1` to retrieve it.\n\nThe following options are available:\n\n- **`list`** - Received `Packet`s are delivered as lists of bytes,\n `[`[`byte/0`](`t:byte/0`)`]`.\n\n- **`binary`** - Received `Packet`s are delivered as `t:binary/0`s.\n\n- **`{backlog, B}`** - `B ::` `t:non_neg_integer/0`. The backlog value\n defines the maximum length that the queue of pending connections\n can grow to. Defaults to `5`.\n\n- **`inet6`** - Sets up the socket for IPv6.\n\n- **`inet`** - Sets up the socket for IPv4.\n\n- **`{fd, Fd}`** - If a socket has somehow been created without using\n `gen_tcp`, use this option to pass the file descriptor for it.\n\n- **`{ip, Address}`** - If the host has many IP addresses, this option\n specifies which one to listen on.\n\n- **`{port, Port}`** - Specifies which local port number to use.\n\n- **`{ifaddr, Address}`** - Same as `{ip, Address}`.\n\n However, if this instead is an `t:socket:sockaddr_in/0` or\n `t:socket:sockaddr_in6/0` this takes precedence over any value\n previously set with the `ip` and `port` options. If these options\n (`ip` or/and `port`) however comes _after_ this option,\n they may be used to _update_ their corresponding fields of this option\n (for `ip`, the `addr` field, and for `port`, the `port` field).\n\n- **`{tcp_module, module()}`** - Overrides which callback module is used.\n Defaults to `inet_tcp` for IPv4 and `inet6_tcp` for IPv6.\n\n- **`t:option/0`** - See `inet:setopts/2`.\n\nThe returned socket `ListenSocket` should be used when calling\n[`accept/1,2`](`accept/1`) to accept an incoming connection request.\n\n> #### Note {: .info }\n>\n> The default values for options specified to `listen` can be affected by the\n> Kernel configuration parameter `inet_default_listen_options`. For details, see\n> `m:inet`.","ref":"gen_tcp.html#listen/2"},{"type":"function","title":"gen_tcp.recv/2","doc":"","ref":"gen_tcp.html#recv/2"},{"type":"function","title":"gen_tcp.recv/3","doc":"Receive a packet, from a socket in _passive mode_.\n\nA closed socket is indicated by the return value `{error, closed}`.\nIf the socket is not in passive mode, the return value is `{error, einval}`.\n\nArgument `Length` is only meaningful when the socket is in `raw` mode and\ndenotes the number of bytes to read. If `Length` is `0`, all available\nbytes are returned. If `Length > 0`, exactly `Length` bytes are returned,\nor an error; except if the socket is closed from the other side,\nthen the last read before the one returning `{error, closed}`\nmay return less than `Length` bytes of data.\n\nThe optional `Timeout` parameter specifies a time-out in milliseconds.\nDefaults to `infinity`.\n\nAny process can receive data from a passive socket, even if that process is not\nthe controlling process of the socket. However, only one process can call this\nfunction on a socket at any given time. Using simultaneous calls to `recv` is\nnot recommended as the behavior depends on the socket implementation,\nand could return errors such as `{error, ealready}`.","ref":"gen_tcp.html#recv/3"},{"type":"function","title":"gen_tcp.send/2","doc":"Send a packet on a socket.\n\nThere is no `send/2` call with a time-out option; use socket option\n`send_timeout` if time-outs are desired. See section\n[Examples](#module-examples).\n\nThe return value `{error, {timeout, RestData}}` can only be returned when\n`inet_backend = socket`.\n\n[](){: #non_blocking_send }\n\n> #### Note {: .info }\n>\n> #### Non-blocking send.\n>\n> If the user tries to send more data than there is room for in the OS send\n> buffers, the 'rest data' is stored in (inet driver) internal buffers and later\n> sent in the background. The function immediately returns ok (_not_ informing\n> the caller that some date isn'nt sent yet). Any issue while\n> sending the 'rest data' may be returned later.\n>\n> When using `inet_backend = socket`, the behaviour is different. There is\n> _no_ buffering, instead the caller will \"hang\" until all of the data\n> has been sent or the send timeout (as specified by the `send_timeout`\n> option) expires (the function can \"hang\" even when using the `inet`\n> backend if the internal buffers are full).\n>\n> If this happens when using `packet =/= raw`, a partial package has been\n> written. A new package therefore _mustn't_ be written at this point,\n> as there is no way for the peer to distinguish this from data in\n> the current package. Instead, set package to raw, send the rest data\n> (as raw data) and then set package to the correct package type again.","ref":"gen_tcp.html#send/2"},{"type":"function","title":"gen_tcp.shutdown/2","doc":"Close the socket in one or both directions.\n\n`How == write` means closing the socket for writing, reading from it is still\npossible.\n\nIf `How == read` or there is no outgoing data buffered in the `Socket` port, the\nshutdown is performed immediately and any error encountered is returned in\n`Reason`.\n\nIf there is data buffered in the socket port, shutdown isn't performed\non the socket until that buffered data has been written to the OS\nprotocol stack. If any errors are encountered, the socket is closed\nand `{error, closed}` is returned by the next `recv/2` or `send/2` call.\n\nOption `{exit_on_close, false}` is useful if the peer performs a shurdown\nof its write side. Then the socket stays open for writing after\nreceive has indicated that the socket was closed.\n\n[](){: #async_shutdown_write }\n\n> #### Note {: .info }\n>\n> Async shutdown write (`How :: write | read_write`).\n>\n> If the shutdown attempt is made while the inet driver is sending\n> buffered data in the background, the shutdown is postponed until\n> all buffered data has been sent. This function immediately returns `ok`,\n> and the caller _isn't_ informed (that the shutdown has been postponed).\n>\n> When using `inet_backend = socket`, the behaviour is different. A shutdown\n> with `How :: write | read_write` will always be performed _immediately_.","ref":"gen_tcp.html#shutdown/2"},{"type":"type","title":"gen_tcp.connect_option/0","doc":"","ref":"gen_tcp.html#t:connect_option/0"},{"type":"type","title":"gen_tcp.listen_option/0","doc":"","ref":"gen_tcp.html#t:listen_option/0"},{"type":"type","title":"gen_tcp.option/0","doc":"","ref":"gen_tcp.html#t:option/0"},{"type":"type","title":"gen_tcp.option_name/0","doc":"","ref":"gen_tcp.html#t:option_name/0"},{"type":"type","title":"gen_tcp.pktoptions_value/0","doc":"Value from socket option [`pktoptions`](`t:option_name/0`).\n\nIf the platform implements the IPv4 option `IP_PKTOPTIONS`,\nor the IPv6 option `IPV6_PKTOPTIONS` or `IPV6_2292PKTOPTIONS` for the socket;\nthis value is returned from `inet:getopts/2` when called with the option name\n[`pktoptions`](`t:option_name/0`).\n\n> #### Note {: .info }\n>\n> This option appears to be VERY Linux specific, and its existence in future\n> Linux kernel versions is also worrying since the option is part of RFC 2292\n> which is since long (2003) obsoleted by RFC 3542 that _explicitly_ removes\n> this possibility to get packet information from a stream socket. For\n> comparison: it has existed in FreeBSD but is now removed, at least since\n> FreeBSD 10.","ref":"gen_tcp.html#t:pktoptions_value/0"},{"type":"type","title":"gen_tcp.socket/0","doc":"As returned by [`accept/1,2`](`accept/1`) and [`connect/3,4`](`connect/3`).","ref":"gen_tcp.html#t:socket/0"},{"type":"module","title":"gen_udp","doc":"Interface to UDP sockets.\n\nThis module provides functions for communicating over UDP\nprotocol sockets.\n\n> #### Note {: .info }\n>\n> Functions that create sockets can take an optional option;\n> `{inet_backend, Backend}` that, if specified, has to be the first option. This\n> selects the implementation backend towards the platform's socket API.\n>\n> This is a _temporary_ option that will be ignored in a future release.\n>\n> The default is `Backend = inet` that selects the traditional `inet_drv.c`\n> driver. The other choice is `Backend = socket` that selects the new `m:socket`\n> module and its NIF implementation.\n>\n> The system default can be changed when the node is started with the\n> application `kernel`'s configuration variable `inet_backend`.\n>\n> For `gen_udp` with `inet_backend = socket` we have tried to be as \"compatible\"\n> as possible which has sometimes been impossible. Here is a list of cases when\n> the behaviour of inet-backend `inet` (default) and `socket` are different:\n>\n> - The option [read_packets](`m:inet#option-read_packets`) is currently\n> _ignored_.\n> - Windows require sockets (domain = `inet | inet6`) to be bound.\n>\n> _Currently_ all sockets created on Windows with `inet_backend = socket` will\n> be bound. If the user does not provide an address, gen_udp will try to\n> 'figure out' an address itself.","ref":"gen_udp.html"},{"type":"function","title":"gen_udp.close/1","doc":"Closes a UDP socket.","ref":"gen_udp.html#close/1"},{"type":"function","title":"gen_udp.connect/2","doc":"Connect a UDP socket.\n\nConnecting a UDP socket only means storing the specified (destination) socket\naddress, as specified by `SockAddr`, so that the system knows where to send\ndata.\n\nWhen the socket is \"connected\" it is not necessary to specify\nthe destination address when sending a datagram.\nThat is; `send/2` may be used.\n\nIt also means that the socket will only receive data from\nthe connected address. Other messages are discarded on arrival\nby the OS protocol stack.","ref":"gen_udp.html#connect/2"},{"type":"function","title":"gen_udp.connect/3","doc":"Connect a UDP socket.\n\nSee `connect/2`.\n\nWith this function the destination is specified\nwith separate `Address` and `Port` arguments where `Address` may be\nan [IP address](`t:inet:socket_address/0`)\nor a [host name](`t:inet:hostname/0`).","ref":"gen_udp.html#connect/3"},{"type":"function","title":"gen_udp.controlling_process/2","doc":"Change the controlling process (owner) of a socket.\n\nAssigns a new controlling process `Pid` to `Socket`. The controlling process\nis the process that the socket sends messages to. If this function\nis called from any other process than the current controlling process,\n`{error, not_owner}` is returned.\n\nIf the process identified by `Pid` is not an existing local `t:pid/0`,\n`{error, badarg}` is returned. `{error, badarg}` may also be returned\nin some cases when `Socket` is closed during the execution of this function.\n\nIf the socket is in _active mode_, this function will transfer any messages\nfrom the socket in the mailbox of the caller to the new controlling process.\n\nIf any other process is interacting with the socket during the transfer,\nit may not work correctly and messages may remain in the caller's mailbox.\nFor instance, changing the sockets active mode during the transfer\ncould cause this.","ref":"gen_udp.html#controlling_process/2"},{"type":"function","title":"gen_udp.open/1","doc":"","ref":"gen_udp.html#open/1"},{"type":"function","title":"gen_udp.open/2","doc":"Open a UDP socket.\n\nThe created socket is bound to the UDP port number `Port`.\nIf `Port == 0`, the underlying OS assigns a free (ephemeral) UDP port;\nuse `inet:port/1` to retrieve it.\n\nThe process that calls this function becomes the `Socket`'s\ncontrolling process (socket owner).","ref":"gen_udp.html#open/2"},{"type":"function","title":"UDP socket options - gen_udp.open/2","doc":"- **`list`** - Received `Packet` is delivered as a list.\n\n- **`binary`** - Received `Packet` is delivered as a binary.\n\n- **`{ip, Address}`** - If the local host has many IP addresses,\n this option specifies which one to use.\n\n- **`{ifaddr, Address}`** - Same as `{ip, Address}`.\n\n However, if this instead is a `t:socket:sockaddr_in/0` or\n `t:socket:sockaddr_in6/0` this takes precedence over any value\n previously set with the `ip` options. If the `ip` option comes\n _after_ the `ifaddr` option, it may be used to _update_ its corresponding\n field of the `ifaddr` option (the `addr` field).\n\n- **`{fd, integer() >= 0}`** - If a socket has somehow been opened without\n using `gen_udp`, use this option to pass the file descriptor for it.\n If `Port` is not set to `0` and/or `{ip, ip_address()}` is combined\n with this option, the `fd` is bound to the specified interface\n and port after it is being opened. If these options are not specified,\n it is assumed that the `fd` is already bound appropriately.\n\n- **`inet6`** - Sets up the socket for IPv6.\n\n- **`inet`** - Sets up the socket for IPv4.\n\n- **`local`** - Sets up a Unix Domain Socket. See `t:inet:local_address/0`\n\n- **`{udp_module, module()}`** - Overrides which callback module is used.\n Defaults to `inet_udp` for IPv4 and `inet6_udp` for IPv6.\n\n- **`{multicast_if, Address}`** - Sets the local device for a multicast socket.\n\n- **`{multicast_loop, true | false}`** - When `true`, sent multicast packets\n are looped back to the local sockets.\n\n- **`{multicast_ttl, Integer}`** - Option `multicast_ttl` changes the\n time-to-live (TTL) for outgoing multicast datagrams to control the scope of\n the multicasts.\n\n Datagrams with a TTL of 1 are not forwarded beyond the local network.\n Defaults to `1`.\n\n- **`{add_membership, {MultiAddress, InterfaceAddress}}`** -\n Joins a multicast group.\n\n- **`{drop_membership, {MultiAddress, InterfaceAddress}}`** -\n Leaves a multicast group.\n\n- **`t:option/0`** - See `inet:setopts/2`.\n\nUDP packets are sent with this socket using [`send(Socket, ...)`](`send/3`).\nWhen UDP packets arrive to the `Socket`'s UDP port, and the socket is in\nan _active mode_, the packets are delivered as messages to the\ncontrolling process (socket owner):\n\n```erlang\n{udp, Socket, PeerIP, PeerPort, Packet} % Without ancillary data\n{udp, Socket, PeerIP, PeerPort, AncData, Packet} % With ancillary data\n```\n\n`PeerIP` and `PeerPort` are the address from which `Packet` was sent.\n`Packet` is a list of bytes (`[`[`byte/0`](`t:byte/0`)`]` if option `list`\nis active and a `t:binary/0` if option `binary`is active\n(they are mutually exclusive).\n\nThe message contains an `AncData` field only if any of the socket\n[options](`t:option/0`) [`recvtos`](`m:inet#option-recvtos`),\n[`recvtclass`](`m:inet#option-recvtclass`) or\n[`recvttl`](`m:inet#option-recvttl`) are active.\n\nWhen a socket in `{active, N}` mode (see `inet:setopts/2` for details),\ntransitions to passive (`{active, false}`) mode (`N` counts down to `0`),\nthe controlling process is notified by a message on this form:\n\n```erlang\n{udp_passive, Socket}\n```\n\nIf the OS protocol stack reports an error for the socket, the following\nmessage is sent to the controlling process:\n\n```erlang\n{udp_error, Socket, Reason}\n```\n`Reason` is mostly a [POSIX Error Code](`m:inet#posix-error-codes`).\n\nIf the socket is in _passive mode_ (not in an _active mode_), received data\ncan be retrieved with the`recv/2,3`](`recv/2`) calls. Note that incoming\nUDP packets that are longer than the receive buffer option specifies\ncan be truncated without warning.\n\nThe default value for the receive buffer option is `{recbuf, 8192}`.","ref":"gen_udp.html#open/2-udp-socket-options"},{"type":"function","title":"gen_udp.recv/2","doc":"","ref":"gen_udp.html#recv/2"},{"type":"function","title":"gen_udp.recv/3","doc":"Receive a packet from a socket in _passive mode_.\n\n`Timeout` specifies a time-out in milliseconds.\n\nIf any of the socket [options](`t:option/0`)\n[`recvtos`](`m:inet#option-recvtos`),\n[`recvtclass`](`m:inet#option-recvtclass`)\nor [`recvttl`](`m:inet#option-recvttl`) are active,\nthe `RecvData` tuple contains an `AncData` field,\notherwise it doesn't.","ref":"gen_udp.html#recv/3"},{"type":"function","title":"gen_udp.send/2","doc":"Send a packet on a connected UDP socket.\n\nTo connect a UDP socket, use `connect/2` or `connect/3`.","ref":"gen_udp.html#send/2"},{"type":"function","title":"gen_udp.send/3","doc":"Equivalent to [`send(Socket, Destination, [], Packet)`](#send-4-AncData).","ref":"gen_udp.html#send/3"},{"type":"function","title":"gen_udp.send/4","doc":"Send a UDP packet to the specified destination.","ref":"gen_udp.html#send/4"},{"type":"function","title":"With arguments `Host` and `Port` - gen_udp.send/4","doc":"Argument `Host` can be a hostname or a socket address, and `Port`\ncan be a port number or a service name atom. These are resolved to\na `Destination` and then this function is equivalent to\n[`send(Socket, Destination, [], Packet)`](#send-4-AncData)\njust below.\n\n### [](){: #send-4-AncData } With arguments `Destination` and `AncData` _(since OTP 22.1)_\n\nSends a packet to the specified `Destination` with ancillary data `AncData`.\n\n> #### Note {: .info }\n>\n> The ancillary data `AncData` contains options that for this single message\n> override the default options for the socket, an operation that may not be\n> supported on all platforms, and if so return `{error, einval}`. Using more\n> than one of an ancillary data item type may also not be supported.\n> `AncData =:= []` is always supported.","ref":"gen_udp.html#send/4-with-arguments-host-and-port"},{"type":"function","title":"With arguments `Destination` and `PortZero` _(since OTP 22.1)_ - gen_udp.send/4","doc":"Sends a packet to the specified `Destination`. Since `Destination`\nis a complete address, `PortZero` is redundant and has to be `0`.\n\nThis is a legacy clause mostly for `Destination = {local, Binary}`\nwhere `PortZero` is superfluous. Equivalent to\n[`send(Socket, Destination, [], Packet)`](#send-4-AncData), right above here.","ref":"gen_udp.html#send/4-with-arguments-destination-and-portzero-_-since-otp-22-1-_"},{"type":"function","title":"gen_udp.send/5","doc":"Send a packet to the specified destination, with ancillary data.\n\nEquvalent to [`send(Socket, Host, Port, Packet)`](`send/4`)\nregarding `Host` and `Port` and also equivalent to\n[`send(Socket, Destination, AncData, Packet)`](#send-4-AncData)\nregarding the ancillary data: `AncData`.","ref":"gen_udp.html#send/5"},{"type":"type","title":"gen_udp.ip6_membership/0","doc":"","ref":"gen_udp.html#t:ip6_membership/0"},{"type":"type","title":"gen_udp.ip6_multicast_if/0","doc":"IPv6 this multicast interface index (an integer).","ref":"gen_udp.html#t:ip6_multicast_if/0"},{"type":"type","title":"gen_udp.ip_membership/0","doc":"IP multicast membership.\n\nThe 3-tuple form _isn't_ supported on all platforms.\n'ifindex' defaults to zero (0) on platforms that supports the 3-tuple variant.","ref":"gen_udp.html#t:ip_membership/0"},{"type":"type","title":"gen_udp.ip_multicast_if/0","doc":"","ref":"gen_udp.html#t:ip_multicast_if/0"},{"type":"type","title":"gen_udp.membership/0","doc":"","ref":"gen_udp.html#t:membership/0"},{"type":"type","title":"gen_udp.multicast_if/0","doc":"","ref":"gen_udp.html#t:multicast_if/0"},{"type":"type","title":"gen_udp.open_option/0","doc":"","ref":"gen_udp.html#t:open_option/0"},{"type":"type","title":"gen_udp.option/0","doc":"","ref":"gen_udp.html#t:option/0"},{"type":"type","title":"gen_udp.option_name/0","doc":"","ref":"gen_udp.html#t:option_name/0"},{"type":"type","title":"gen_udp.socket/0","doc":"A socket as returned by [`open/1,2`](`open/1`).","ref":"gen_udp.html#t:socket/0"},{"type":"module","title":"inet","doc":"Access to Network protocols.\n\nThis module, together with `m:gen_tcp`, `m:gen_udp` and `m:gen_sctp`\nprovides access to the Network protocols TCP, SCTP and UDP over IP,\nas well as stream and datagram protocols over the local (unix)\naddress domain / protocol domain.\n\nSee also [ERTS User's Guide: Inet Configuration](`e:erts:inet_cfg.md`)\nor more information about how to configure an Erlang runtime system\nfor IP communication.\n\nThe following two Kernel configuration parameters affect the behavior of all\n`m:gen_tcp` sockets opened on an Erlang node:\n\n- `inet_default_connect_options` can contain a list of\n default options used for all sockets created by\n a `gen_tcp:connect/2,3,4`](`gen_tcp:connect/2`) call.\n- `inet_default_listen_options` can contain a list of default options\n used for sockets created by a `gen_tcp:listen/2` call.\n\nFor the [`gen_tcp:accept/1,2`](`gen_tcp:accept/1`) call,\nthe values of the listening socket options are inherited.\nTherefore there is no corresponding application variable for `accept`.\n\nUsing the Kernel configuration parameters above, one can set default options\nfor all TCP sockets on a node, but use this with care. Options such as\n`{delay_send,true}` can be specified in this way. The following is an example\nof starting an Erlang node with all sockets using delayed send:\n\n```text\n$ erl -sname test -kernel \\\ninet_default_connect_options '[{delay_send,true}]' \\\ninet_default_listen_options '[{delay_send,true}]'\n```\n\n**Please note** that the default option `{active, true}` cannot be changed,\nfor internal implementation reasons.\n\nAddresses as inputs to functions can be either a string or a tuple.\nFor example, the IP address 150.236.20.73 can be passed to\n`gethostbyaddr/1`, either as a string `\"150.236.20.73\"`\nor as a tuple `{150, 236, 20, 73}`.\n\n_IPv4 address examples:_\n\n```text\nAddress ip_address()\n------- ------------\n127.0.0.1 {127,0,0,1}\n192.168.42.2 {192,168,42,2}\n```\n\n_IPv6 address examples:_\n\n```erlang\nAddress ip_address()\n------- ------------\n::1 {0,0,0,0,0,0,0,1}\n::192.168.42.2 {0,0,0,0,0,0,(192 bsl 8) bor 168,(42 bsl 8) bor 2}\n::FFFF:192.168.42.2\n {0,0,0,0,0,16#FFFF,(192 bsl 8) bor 168,(42 bsl 8) bor 2}\n3ffe:b80:1f8d:2:204:acff:fe17:bf38\n {16#3ffe,16#b80,16#1f8d,16#2,16#204,16#acff,16#fe17,16#bf38}\nfe80::204:acff:fe17:bf38\n {16#fe80,0,0,0,16#204,16#acff,16#fe17,16#bf38}\n```\n\nFunction `parse_address/1` can be useful:\n\n```erlang\n1> inet:parse_address(\"192.168.42.2\").\n{ok,{192,168,42,2}}\n2> inet:parse_address(\"::FFFF:192.168.42.2\").\n{ok,{0,0,0,0,0,65535,49320,10754}}\n```\n\n[](){: #posix-error-codes } POSIX Error Codes\n---------------------------------------------\n\n- `e2big` - Too long argument list\n- `eacces` - Permission denied\n- `eaddrinuse` - Address already in use\n- `eaddrnotavail` - Cannot assign requested address\n- `eadv` - Advertise error\n- `eafnosupport` - Address family not supported by protocol family\n- `eagain` - Resource temporarily unavailable\n- `ealign` - EALIGN\n- `ealready` - Operation already in progress\n- `ebade` - Bad exchange descriptor\n- `ebadf` - Bad file number\n- `ebadfd` - File descriptor in bad state\n- `ebadmsg` - Not a data message\n- `ebadr` - Bad request descriptor\n- `ebadrpc` - Bad RPC structure\n- `ebadrqc` - Bad request code\n- `ebadslt` - Invalid slot\n- `ebfont` - Bad font file format\n- `ebusy` - File busy\n- `echild` - No children\n- `echrng` - Channel number out of range\n- `ecomm` - Communication error on send\n- `econnaborted` - Software caused connection abort\n- `econnrefused` - Connection refused\n- `econnreset` - Connection reset by peer\n- `edeadlk` - Resource deadlock avoided\n- `edeadlock` - Resource deadlock avoided\n- `edestaddrreq` - Destination address required\n- `edirty` - Mounting a dirty fs without force\n- `edom` - Math argument out of range\n- `edotdot` - Cross mount point\n- `edquot` - Disk quota exceeded\n- `eduppkg` - Duplicate package name\n- `eexist` - File already exists\n- `efault` - Bad address in system call argument\n- `efbig` - File too large\n- `ehostdown` - Host is down\n- `ehostunreach` - Host is unreachable\n- `eidrm` - Identifier removed\n- `einit` - Initialization error\n- `einprogress` - Operation now in progress\n- `eintr` - Interrupted system call\n- `einval` - Invalid argument\n- `eio` - I/O error\n- `eisconn` - Socket is already connected\n- `eisdir` - Illegal operation on a directory\n- `eisnam` - Is a named file\n- `el2hlt` - Level 2 halted\n- `el2nsync` - Level 2 not synchronized\n- `el3hlt` - Level 3 halted\n- `el3rst` - Level 3 reset\n- `elbin` - ELBIN\n- `elibacc` - Cannot access a needed shared library\n- `elibbad` - Accessing a corrupted shared library\n- `elibexec` - Cannot exec a shared library directly\n- `elibmax` - Attempting to link in more shared libraries than system limit\n- `elibscn` - `.lib` section in `a.out` corrupted\n- `elnrng` - Link number out of range\n- `eloop` - Too many levels of symbolic links\n- `emfile` - Too many open files\n- `emlink` - Too many links\n- `emsgsize` - Message too long\n- `emultihop` - Multihop attempted\n- `enametoolong` - Filename too long\n- `enavail` - Unavailable\n- `enet` - ENET\n- `enetdown` - Network is down\n- `enetreset` - Network dropped connection on reset\n- `enetunreach` - Network is unreachable\n- `enfile` - File table overflow\n- `enoano` - Anode table overflow\n- `enobufs` - No buffer space available\n- `enocsi` - No CSI structure available\n- `enodata` - No data available\n- `enodev` - No such device\n- `enoent` - No such file or directory\n- `enoexec` - Exec format error\n- `enolck` - No locks available\n- `enolink` - Link has been severed\n- `enomem` - Not enough memory\n- `enomsg` - No message of desired type\n- `enonet` - Machine is not on the network\n- `enopkg` - Package not installed\n- `enoprotoopt` - Bad protocol option\n- `enospc` - No space left on device\n- `enosr` - Out of stream resources or not a stream device\n- `enosym` - Unresolved symbol name\n- `enosys` - Function not implemented\n- `enotblk` - Block device required\n- `enotconn` - Socket is not connected\n- `enotdir` - Not a directory\n- `enotempty` - Directory not empty\n- `enotnam` - Not a named file\n- `enotsock` - Socket operation on non-socket\n- `enotsup` - Operation not supported\n- `enotty` - Inappropriate device for `ioctl`\n- `enotuniq` - Name not unique on network\n- `enxio` - No such device or address\n- `eopnotsupp` - Operation not supported on socket\n- `eperm` - Not owner\n- `epfnosupport` - Protocol family not supported\n- `epipe` - Broken pipe\n- `eproclim` - Too many processes\n- `eprocunavail` - Bad procedure for program\n- `eprogmismatch` - Wrong program version\n- `eprogunavail` - RPC program unavailable\n- `eproto` - Protocol error\n- `eprotonosupport` - Protocol not supported\n- `eprototype` - Wrong protocol type for socket\n- `erange` - Math result unrepresentable\n- `erefused` - EREFUSED\n- `eremchg` - Remote address changed\n- `eremdev` - Remote device\n- `eremote` - Pathname hit remote filesystem\n- `eremoteio` - Remote I/O error\n- `eremoterelease` - EREMOTERELEASE\n- `erofs` - Read-only filesystem\n- `erpcmismatch` - Wrong RPC version\n- `erremote` - Object is remote\n- `eshutdown` - Cannot send after socket shutdown\n- `esocktnosupport` - Socket type not supported\n- `espipe` - Invalid seek\n- `esrch` - No such process\n- `esrmnt` - Srmount error\n- `estale` - Stale remote file handle\n- `esuccess` - Error 0\n- `etime` - Timer expired\n- `etimedout` - Connection timed out\n- `etoomanyrefs` - Too many references\n- `etxtbsy` - Text file or pseudo-device busy\n- `euclean` - Structure needs cleaning\n- `eunatch` - Protocol driver not attached\n- `eusers` - Too many users\n- `eversion` - Version mismatch\n- `ewouldblock` - Operation would block\n- `exdev` - Cross-device link\n- `exfull` - Message tables full\n- `nxdomain` - Hostname or domain name cannot be found","ref":"inet.html"},{"type":"function","title":"inet.cancel_monitor/1","doc":"Cancel a socket monitor.\n\nIf `MRef` is a reference that the calling process obtained by calling\n`monitor/1`, this monitor is removed. If the monitoring is already removed,\nnothing happens.\n\nThe returned value is one of the following:\n\n- **`true`** - The monitor was found and removed. In this case, no `'DOWN'`\n message corresponding to this monitor has been delivered and will not be\n delivered.\n\n- **`false`** - The monitor was not found and couldn't be removed.\n Probably because the monitor has already triggered and there is\n a corresponding `'DOWN'` message in the caller message queue.","ref":"inet.html#cancel_monitor/1"},{"type":"function","title":"inet.close/1","doc":"Close a socket of any type.","ref":"inet.html#close/1"},{"type":"function","title":"inet.format_error/1","doc":"Format an error code into a `t:string/0`.\n\nReturns a diagnostic error string. For possible POSIX values\nand corresponding strings, see section\n[POSIX Error Codes](#posix-error-codes).","ref":"inet.html#format_error/1"},{"type":"function","title":"inet.get_rc/0","doc":"Get the `inet` configuration.\n\nReturns the state of the `inet` configuration database in form of\na list of recorded configuration parameters. For more information, see\n[ERTS User's Guide: Inet Configuration](`e:erts:inet_cfg.md`).\n\nOnly actual parameters with other than default values are returned,\nfor example not directives that specify other sources for configuration\nparameters nor directives that clear parameters.","ref":"inet.html#get_rc/0"},{"type":"function","title":"inet.getaddr/2","doc":"Resolve a host to an address, in a specific addresss family.\n\nReturns the [IP address](`t:ip_address/0`) for `Host` as a tuple of integers.\n`Host` can be an [IP address](`t:ip_address/0`), a single `t:hostname/0`,\nor a fully qualified `t:hostname/0`.","ref":"inet.html#getaddr/2"},{"type":"function","title":"inet.getaddrs/2","doc":"Resolve a host to a list of addresses, in a specific address family.\n\nReturns a list of all IP addresses for `Host`.\n`Host` can be an [IP address](`t:ip_address/0`),\na single `t:hostname/0`, or a fully qualified `t:hostname/0`.","ref":"inet.html#getaddrs/2"},{"type":"function","title":"inet.gethostbyaddr/1","doc":"Resolve (reverse) an address to a [`#hostent{}`](`t:hostent/0`) record.\n\nReturns a [`#hostent{}`](`t:hostent/0`) record for the host\nwith the specified address.","ref":"inet.html#gethostbyaddr/1"},{"type":"function","title":"inet.gethostbyname/1","doc":"Resolve a hostname to a [`#hostent{}`](`t:hostent/0`) record.\n\nReturns a [`#hostent{}`](`t:hostent/0`) record for the host\nwith the specified `Hostname`.\n\nThis function uses the resolver, which is often the native (OS) resolver.\n\nIf resolver option `inet6` is `true`, an IPv6 address is looked up.\n\nSee [ERTS User's Guide: Inet Configuration](`e:erts:inet_cfg.md`) for\ninformation about the resolver configuration.\n\nA quirk of many resolvers is that an integer string is interpreted\nas an IP address. For instance, the integer string \"3232235521\"\nand the string \"192.168.0.1\" are both translated\nto the IP address `{192,168,0,1}`.","ref":"inet.html#gethostbyname/1"},{"type":"function","title":"inet.gethostbyname/2","doc":"Resolve a hostname to a [`#hostent{}`](`t:hostent/0`) record,\nin a specific address family.\n\nReturns a [`#hostent{}`](`t:hostent/0`) record for the host\nwith the specified `Hostname`, restricted to the specified address `Family`.\n\nSee also `gethostbyname/1`.","ref":"inet.html#gethostbyname/2"},{"type":"function","title":"inet.gethostname/0","doc":"Get the local hostname.\n\nReturns the local hostname. Never fails.","ref":"inet.html#gethostname/0"},{"type":"function","title":"inet.getifaddrs/0","doc":"Get interface names and addresses.\n\nReturns a list of 2-tuples containing interface names and the interfaces'\naddresses. `Ifname` is a Unicode string and `Ifopts` is a list of interface\naddress description tuples.\n\nThe interface address description tuples are documented under\nthe type of the [`Ifopts`](`t:getifaddrs_ifopts/0`) value.","ref":"inet.html#getifaddrs/0"},{"type":"function","title":"inet.getifaddrs/1","doc":"Get interface names and addresses, in a specific namespace.\n\nEquivalent to `getifaddrs/0`, but accepts an `Option`\n`{netns, Namespace}` that, on platforms that support the feature (Linux),\nsets a network namespace for the OS call.\nAlso,\nIf the option 'inet_backend' is *first* in the options list,\nthe specified backend will be used (for 'inet', inet and\nfor 'socket' the equivalent net functions will be used).\n \n\nSee the socket option [`{netns, Namespace}`](#option-netns)\nunder `setopts/2`.","ref":"inet.html#getifaddrs/1"},{"type":"function","title":"inet.getopts/2","doc":"Get one or more options for a socket.\n\nGets all options in the list `Options` from `Socket`.\nSee `setopts/2` for a list of available options. See also\nthe descriptions of protocol specific types referenced by\n[`socket_optval()` ](`t:socket_optval/0`).\n\nThe number of elements in the returned `OptionValues` list does not necessarily\ncorrespond to the number of options asked for. If the operating system fails to\nsupport an option, it is left out in the returned list. An error tuple is\nreturned only when getting options for the socket is impossible (that is, the\nsocket is closed or the buffer size in a raw request is too large). This\nbehavior is kept for backward compatibility reasons.\n\nA raw option request `RawOptReq = {raw, Protocol, OptionNum, ValueSpec}` can be\nused to get information about socket options not (explicitly) supported by the\nemulator. The use of raw socket options makes the code non-portable, but allows\nthe Erlang programmer to take advantage of unusual features present on a\nparticular platform.\n\n`RawOptReq` consists of tag `raw` followed by the protocol level, the option\nnumber, and either a binary or the size, in bytes, of the buffer in which the\noption value is to be stored. A binary is to be used when the underlying\n`getsockopt` requires _input_ in the argument field. In this case, the binary\nsize shall correspond to the required buffer size of the return value. The\nsupplied values in a `RawOptReq` correspond to the second, third, and\nfourth/fifth parameters to the `getsockopt` call in the C socket API. The value\nstored in the buffer is returned as a binary `ValueBin`, where all values are\ncoded in native endianness.\n\nAsking for and inspecting raw socket options require low-level information about\nthe current operating system and TCP stack.\n\n_Example:_\n\nConsider a Linux machine where option `TCP_INFO` can be used to collect TCP\nstatistics for a socket. Assume you are interested in field `tcpi_sacked` of\n`struct tcp_info` filled in when asking for `TCP_INFO`. To be able to access\nthis information, you need to know the following:\n\n- The numeric value of protocol level `IPPROTO_TCP`\n- The numeric value of option `TCP_INFO`\n- The size of `struct tcp_info`\n- The size and offset of the specific field\n\nBy inspecting the headers or writing a small C program, it is found that\n`IPPROTO_TCP` is 6, `TCP_INFO` is 11, the structure size is 92 (bytes), the\noffset of `tcpi_sacked` is 28 bytes, and the value is a 32-bit integer. The\nfollowing code can be used to retrieve the value:\n\n```erlang\nget_tcpi_sacked(Sock) ->\n {ok,[{raw,_,_,Info}]} = inet:getopts(Sock,[{raw,6,11,92}]),\n <<_:28/binary,TcpiSacked:32/native,_/binary>> = Info,\n TcpiSacked.\n```\n\nPreferably, you would check the machine type, the operating system, and the\nKernel version before executing anything similar to this code.","ref":"inet.html#getopts/2"},{"type":"function","title":"inet.getstat/1","doc":"","ref":"inet.html#getstat/1"},{"type":"function","title":"inet.getstat/2","doc":"Get one or more statistics options for a socket.\n\n[`getstat(Socket)`](`getstat/1`) is equivalent to\n[`getstat(Socket, [recv_avg, recv_cnt, recv_dvi, recv_max, recv_oct, send_avg, send_cnt, send_pend, send_max, send_oct])`](`getstat/2`).\n\nThe following options are available:\n\n- **`recv_avg`** - Average size of packets, in bytes, received by the socket.\n\n- **`recv_cnt`** - Number of packets received by the socket.\n\n- **`recv_dvi`** - Average packet size deviation, in bytes, received by the\n socket.\n\n- **`recv_max`** - Size of the largest packet, in bytes, received by the socket.\n\n- **`recv_oct`** - Number of bytes received by the socket.\n\n- **`send_avg`** - Average size of packets, in bytes, sent from the socket.\n\n- **`send_cnt`** - Number of packets sent from the socket.\n\n- **`send_pend`** - Number of bytes waiting to be sent by the socket.\n\n- **`send_max`** - Size of the largest packet, in bytes, sent from the socket.\n\n- **`send_oct`** - Number of bytes sent from the socket.","ref":"inet.html#getstat/2"},{"type":"function","title":"inet.i/0","doc":"Equivalent to `i/1` for the protocols `tcp`, `udp`, and `sctp`","ref":"inet.html#i/0"},{"type":"function","title":"inet.i/1","doc":"List network sockets.\n\nWith argument `Proto` equivalent to [`i(Proto, Options)`](`i/2`)\nwhere `Options` is a list of all `t:atom/0`s in `t:i_option/0`.\n\nWith argument `Options`, equivalent to [`i(Proto, Options)](`i/2`)\nfor `Proto`: `tcp`, `udp`, and `sctp`.\n\nWith argument `show_ports` **(since OTP 27.0)** equivalent to\n[`i(Proto, Options)](`i/2`) where `Option` is a list of all\noptions in `t:i_option/0` with `ShowPorts = true`.","ref":"inet.html#i/1"},{"type":"function","title":"inet.i/2","doc":"List network sockets.\n\nLists all TCP, UDP and SCTP sockets on the terminal, those created by\nthe Erlang runtime system as well as by the application.\n\nThe following options are available:\n\n- **`port`** - An internal index of the port.\n\n- **`module`** - The callback module of the socket.\n\n- **`recv`** - Number of bytes received by the socket.\n\n- **`sent`** - Number of bytes sent from the socket.\n\n- **`owner`** - The socket owner process.\n\n- **`local_address`** - The local address of the socket.\n\n- **`foreign_address`** - The address and port of the other end of the\n connection.\n\n- **`state`** - The connection state.\n\n- **`type`** - STREAM or DGRAM or SEQPACKET.\n\nThe `Options` argument may also be **(since OTP 27.0)**:\n\n- **`show_ports`** - Do *not* translate the port numbers\n (of 'local_address' and 'foreign_address') to service name(s).","ref":"inet.html#i/2"},{"type":"function","title":"inet.info/1","doc":"Get information about a socket.\n\nReturns a term containing miscellaneous information about a socket.","ref":"inet.html#info/1"},{"type":"function","title":"inet.ipv4_mapped_ipv6_address/1","doc":"Convert between an IPv4 address and an IPv4-mapped IPv6 address.\n\nConvert an IPv4 address to an IPv4-mapped IPv6 address or the reverse.\nWhen converting from an IPv6 address all but the 2 low words are ignored\nso this function also works on some other types of IPv6 addresses\nthan IPv4-mapped.","ref":"inet.html#ipv4_mapped_ipv6_address/1"},{"type":"function","title":"inet.is_ip_address/1","doc":"Test for an IP address.\n\nTests if the argument `IPAddress` is an `t:ip_address/0`\nand if so returns `true`, otherwise `false`.","ref":"inet.html#is_ip_address/1"},{"type":"function","title":"inet.is_ipv4_address/1","doc":"Test for an IPv4 address.\n\nTests if the argument `IPv4Address` is an `t:ip4_address/0`\nand if so returns `true`, otherwise `false`.","ref":"inet.html#is_ipv4_address/1"},{"type":"function","title":"inet.is_ipv6_address/1","doc":"Test for an IPv6 address.\n\nTests if the argument `IPv6Address` is an `t:ip6_address/0`\nand if so returns `true`, otherwise `false`.","ref":"inet.html#is_ipv6_address/1"},{"type":"function","title":"inet.monitor/1","doc":"Start a socket monitor.\n\nIf the `Socket` to monitor doesn't exist or when the monitor is triggered,\na `'DOWN'` message is sent that has the following pattern:\n\n```erlang\n\t {'DOWN', MonitorRef, Type, Object, Info}\n```\n\n- **`MonitorRef`** - The return value from this function.\n\n- **`Type`** - The type of socket, can be one of the following\n `t:atom/0`s: `port` or `socket`.\n\n- **`Object`** - The monitored entity, the socket, which triggered the event.\n\n- **`Info`** - Either the termination reason of the socket or `nosock`\n (the `Socket` did not exist when this function was called).\n\nMaking several calls to `inet:monitor/1` for the same `Socket`\nis not an error; one monitor is created per call.\n\nThe monitor is triggered when the socket is closed in any way such as\nan API call, remote end close, closed by signal when owner exits, ...","ref":"inet.html#monitor/1"},{"type":"function","title":"inet.ntoa/1","doc":"Parse an `t:ip_address/0` to an IPv4 or IPv6 address string.","ref":"inet.html#ntoa/1"},{"type":"function","title":"inet.parse_address/1","doc":"Parse an IP address string to an `t:ip_address/0`.\n\nReturns an `t:ip4_address/0` or an `t:ip6_address/0` depending\non which parsing that succeeds.\n\nAccepts a short form IPv4 address string like `parse_ipv4_address/1`.","ref":"inet.html#parse_address/1"},{"type":"function","title":"inet.parse_ipv4_address/1","doc":"Parse (relaxed) an IPv4 address string to an `t:ip4_address/0`.\n\nAccepts a short form IPv4 address string (less than 4 fields)\nsuch as `\"127.1\"` or `\"0x7f000001\"`.","ref":"inet.html#parse_ipv4_address/1"},{"type":"function","title":"inet.parse_ipv4strict_address/1","doc":"Parse an IPv4 address string to an `t:ip4_address/0`.\n\nRequires an IPv4 address string containing four fields,\nthat is; _not_ a short form address string.","ref":"inet.html#parse_ipv4strict_address/1"},{"type":"function","title":"inet.parse_ipv6_address/1","doc":"Parse (relaxed) an IPv6 address string to an `t:ip6_address/0`.\n\nAlso accepts a (relaxed) IPv4 address string like `parse_ipv4_address/1`\nand returns an IPv4-mapped IPv6 address.","ref":"inet.html#parse_ipv6_address/1"},{"type":"function","title":"inet.parse_ipv6strict_address/1","doc":"Parse an IPv6 address string to an `t:ip6_address/0`.\n\n_Doesn't_ accept an IPv4 address string. An IPv6 address string, though,\nallows an IPv4 tail like this: `\"::127.0.0.1\"`\n(which is the same as `\"::7f00:0001\"`).","ref":"inet.html#parse_ipv6strict_address/1"},{"type":"function","title":"inet.parse_strict_address/1","doc":"Parse an IP address string to an `t:ip_address/0`.\n\nLike `parse_address/1` but _doesn't_ accept a short form IPv4 address string.","ref":"inet.html#parse_strict_address/1"},{"type":"function","title":"inet.peername/1","doc":"Return the address of the socket's remote end.\n\nReturns the address and port for the other end of a connection.\n\nNotice that for SCTP sockets, this function returns only one of\nthe peer addresses of the socket. Function [`peernames/1,2`](`peernames/1`)\nreturns all.","ref":"inet.html#peername/1"},{"type":"function","title":"inet.peernames/1","doc":"Equivalent to [`peernames(Socket, 0)`](`peernames/2`).\n\nNotice that the behavior of this function for an SCTP one-to-many style socket\nis not defined by the\n[SCTP Sockets API Extensions](http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13).","ref":"inet.html#peernames/1"},{"type":"function","title":"inet.peernames/2","doc":"Return the addresses of all remote ends of a socket.\n\nReturns a list of all address/port number pairs for the remote end of an\nassociation `Assoc` of a socket.\n\nThis function can return multiple addresses for multihomed sockets,\nsuch as SCTP sockets. For other sockets it returns a one-element list.\n\nNotice that parameter `Assoc` is by the\n[SCTP Sockets API Extensions](http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13)\ndefined to be ignored for one-to-one style sockets.\nWhat the special value `0` means, is unfortunately undefined,\nand hence the behavior for one-to-many style sockets.","ref":"inet.html#peernames/2"},{"type":"function","title":"inet.port/1","doc":"Return the local port number for a socket.","ref":"inet.html#port/1"},{"type":"function","title":"inet.setopts/2","doc":"Set one or more options for a socket.\n\nSets the list of `Options` on `Socket`.\n\nThe following options are available:\n\n- **`{active, true | false | once | N}`** [](){: #option-active } -\n If the value is `true`, which is the default, everything received\n from the socket is sent as messages to the receiving process.\n\n If the value is `false` (passive mode), the process must explicitly receive\n incoming data by calling [`gen_tcp:recv/2,3`](`gen_tcp:recv/2`),\n [`gen_udp:recv/2,3`](`gen_udp:recv/2`), or\n [`gen_sctp:recv/1,2`](`gen_sctp:recv/1`) (depending on the type of socket).\n\n If the value is `once` (`{active, once}`), _one_ data message from the socket\n is sent to the process. To receive one more message,\n [`setopts/2`](`setopts/2`) must be called again with option `{active, once}`.\n\n If the value is an integer `N` in the range -32768 to 32767 (inclusive), the\n value is added to the socket's count of data messages sent to the controlling\n process. A socket's default message count is `0`. If a negative value is\n specified, and its magnitude is equal to or greater than the socket's current\n message count, the socket's message count is set to `0`. Once the socket's\n message count reaches `0`, either because of sending received data messages to\n the process or by being explicitly set, the process is then notified by a\n special message, specific to the type of socket, that the socket has entered\n passive mode. Once the socket enters passive mode, to receive more messages\n [`setopts/2`](`setopts/2`) must be called again to set the socket back into an\n active mode.\n\n When using `{active, once}` or `{active, N}`, the socket changes behavior\n automatically when data is received. This can be confusing in combination with\n connection-oriented sockets (that is, `gen_tcp`), as a socket with\n `{active, false}` behavior reports closing differently than a socket with\n `{active, true}` behavior. To simplify programming, a socket where the peer\n closed, and this is detected while in `{active, false}` mode, still generates\n message `{tcp_closed, Socket}` when set to `{active, once}`, `{active, true}`,\n or `{active, N}` mode. It is therefore safe to assume that message\n `{tcp_closed, Socket}`, possibly followed by socket port termination (depending\n on option `exit_on_close`) eventually appears when a socket changes back and\n forth between `{active, true}` and `{active, false}` mode. However, _when_\n peer closing is detected it is all up to the underlying TCP/IP stack and\n protocol.\n\n Notice that `{active, true}` mode provides no flow control; a fast sender can\n easily overflow the receiver with incoming messages. The same is true for\n `{active, N}` mode, while the message count is greater than zero.\n\n Use active mode only if your high-level protocol provides its own flow control\n (for example, acknowledging received messages) or the amount of data exchanged\n is small. `{active, false}` mode, use of the `{active, once}` mode, or\n `{active, N}` mode with values of `N` appropriate for the application\n to provide flow control. The other side cannot send faster than\n the receiver can read.\n\n- **`{broadcast, Boolean}` (UDP sockets)** [](){: #option-broadcast } -\n Enables/disables permission to send broadcasts.\n\n- **`{buffer, Size}`** [](){: #option-buffer } -\n The size of the user-level buffer used by the driver. Not to be confused\n with options `sndbuf` and `recbuf`, which correspond to the\n Kernel socket buffers. For TCP it is recommended to have\n `val(buffer) >= val(recbuf)` to avoid performance issues because of\n unnecessary copying. For UDP the same recommendation applies, but the max\n should not be larger than the MTU of the network path. `val(buffer)` is\n automatically set to the above maximum when `recbuf` is set. However, as the\n size set for `recbuf` usually become larger, you are encouraged to use\n `getopts/2` to analyze the behavior of your operating system.\n\n Note that this is also the maximum amount of data that can be received from a\n single recv call. If you are using higher than normal MTU consider setting\n buffer higher.\n\n- **`{delay_send, Boolean}`** - Normally, when an Erlang process sends to a\n socket, the driver tries to send the data immediately. If that fails, the\n driver uses any means available to queue up the message to be sent whenever\n the operating system says it can handle it. Setting `{delay_send, true}` makes\n _all_ messages queue up. The messages sent to the network are then larger but\n fewer. The option affects the scheduling of send requests versus Erlang\n processes instead of changing any real property of the socket. The option is\n implementation-specific. Defaults to `false`.\n\n- **`{deliver, port | term}`** - When `{active, true}`, data is delivered on the\n form `port` : `{S, {data, [H1,..Hsz | Data]}}`\n or `term` : `{tcp, S, [H1..Hsz | Data]}`.\n\n- **`{dontroute, Boolean}`** - Enables/disables routing bypass for outgoing\n messages.\n\n- **`{exit_on_close, Boolean}`** - This option is set to `true` by default.\n\n The only reason to set it to `false` is if you want to continue sending data\n to the socket after a close is detected, for example, if the peer uses\n `gen_tcp:shutdown/2` to shut down the write side.\n\n- **`{exclusiveaddruse, Boolean}`** [](){: #option-exclusiveaddruse } -\n Enables/disables exclusive address/port usage on Windows. That is, by enabling\n this option you can prevent other sockets from binding to the same\n address/port. By default this option is disabled. That is, other sockets\n may use the same address/port by setting\n [`{reuseaddr, true}`](#option-reuseaddr) in combination with\n [`{reuseport, true}`](#option-reuseport) unless\n `{exclusiveaddruse, true}` has been set on `Socket`. On non-Windows systems\n this option is silently ignored.\n\n > #### Note {: .info }\n >\n > This option is _currently_ not supported for socket created with\n > `inet_backend = socket`\n\n- **`{header, Size}`** - This option is only meaningful if option `binary` was\n specified when the socket was created. If option `header` is specified, the\n first `Size` number bytes of data received from the socket are elements of a\n list, and the remaining data is a binary specified as the tail of the same\n list. For example, if `Size == 2`, the data received matches\n `[Byte1, Byte2 | Binary]`.\n\n- **`{high_msgq_watermark, Size}`** - The socket message queue is set to a busy\n state when the amount of data on the message queue reaches this limit. Notice\n that this limit only concerns data that has not yet reached the ERTS internal\n socket implementation. Defaults to 8 kB.\n\n Senders of data to the socket are suspended if either the socket message queue\n is busy or the socket itself is busy.\n\n For more information, see options `low_msgq_watermark`, `high_watermark`, and\n `low_watermark`.\n\n Notice that distribution sockets disable the use of `high_msgq_watermark` and\n `low_msgq_watermark`. Instead use the\n [distribution buffer busy limit](`m:erlang#system_info_dist_buf_busy_limit`),\n which is a similar feature.\n\n- **`{high_watermark, Size}` (TCP/IP sockets)** - The socket is set to a busy\n state when the amount of data queued internally by the ERTS socket\n implementation reaches this limit. Defaults to 8 kB.\n\n Senders of data to the socket are suspended if either the socket message queue\n is busy or the socket itself is busy.\n\n For more information, see options `low_watermark`, `high_msgq_watermark`, and\n `low_msqg_watermark`.\n\n- **`{ipv6_v6only, Boolean}`** - Restricts the socket to use only IPv6,\n prohibiting any IPv4 connections. This is only applicable for IPv6 sockets\n (option `inet6`).\n\n On most platforms this option must be set on the socket before associating it\n to an address. It is therefore only reasonable to specify it when creating the\n socket and not to use it when calling function (`setopts/2`) containing this\n description.\n\n The behavior of a socket with this option set to `true` is the only portable\n one. The original idea when IPv6 was new of using IPv6 for all traffic is now\n not recommended by FreeBSD (you can use `{ipv6_v6only,false}` to override the\n recommended system default value), forbidden by OpenBSD (the supported GENERIC\n kernel), and impossible on Windows (which has separate IPv4 and IPv6 protocol\n stacks). Most Linux distros still have a system default value of `false`. This\n policy shift among operating systems to separate IPv6 from IPv4 traffic has\n evolved, as it gradually proved hard and complicated to get a dual stack\n implementation correct and secure.\n\n On some platforms, the only allowed value for this option is `true`, for\n example, OpenBSD and Windows. Trying to set this option to `false`, when\n creating the socket, fails in this case.\n\n Setting this option on platforms where it does not exist is ignored. Getting\n this option with `getopts/2` returns no value, that is, the returned list does\n not contain an `{ipv6_v6only,_}` tuple. On Windows, the option does not exist,\n but it is emulated as a read-only option with value `true`.\n\n Therefore, setting this option to `true` when creating a socket never fails,\n except possibly on a platform where you have customized the kernel to only\n allow `false`, which can be doable (but awkward) on, for example, OpenBSD.\n\n If you read back the option value using `getopts/2` and get no value, the\n option does not exist in the host operating system. The behavior of both an\n IPv6 and an IPv4 socket listening on the same port, and for an IPv6 socket\n getting IPv4 traffic is then no longer predictable.\n\n- **`{keepalive, Boolean}` (TCP/IP sockets)** - Enables/disables periodic\n transmission on a connected socket when no other data is exchanged. If the\n other end does not respond, the connection is considered broken and an error\n message is sent to the controlling process. Defaults to `false`.\n\n- **`{linger, {true|false, Seconds}}`** [](){: #option-linger } -\n Determines the time-out, in seconds, for flushing unsent data\n in the [`close/1`](`close/1`) socket call.\n\n The first component is if linger is enabled, the second component is the\n flushing time-out, in seconds. There are 3 alternatives:\n\n - **`{false, _}`** - close/1 or shutdown/2 returns immediately, not waiting\n for data to be flushed, with closing happening in the background.\n\n - **`{true, 0}`** - Aborts the connection when it is closed. Discards any data\n still remaining in the send buffers and sends RST to the peer.\n\n This avoids TCP's TIME_WAIT state, but leaves open the possibility that\n another \"incarnation\" of this connection being created.\n\n - **`{true, Time} when Time > 0`** - close/1 or shutdown/2 will not return\n until all queued messages for the socket have been successfully sent or the\n linger timeout (Time) has been reached.\n\n- **`{low_msgq_watermark, Size}`** - If the socket message queue is in a busy\n state, the socket message queue is set in a not busy state when the amount of\n data queued in the message queue falls below this limit. Notice that this\n limit only concerns data that has not yet reached the ERTS internal socket\n implementation. Defaults to 4 kB.\n\n Senders that are suspended because of either a busy message queue or a busy\n socket are resumed when the socket message queue and the socket are not busy.\n\n For more information, see options `high_msgq_watermark`, `high_watermark`, and\n `low_watermark`.\n\n Notice that distribution sockets disable the use of `high_msgq_watermark` and\n `low_msgq_watermark`. Instead they use the\n [distribution buffer busy limit](`m:erlang#system_info_dist_buf_busy_limit`),\n which is a similar feature.\n\n- **`{low_watermark, Size}` (TCP/IP sockets)** - If the socket is in a busy\n state, the socket is set in a not busy state when the amount of data queued\n internally by the ERTS socket implementation falls below this limit. Defaults\n to 4 kB.\n\n Senders that are suspended because of a busy message queue or a busy socket\n are resumed when the socket message queue and the socket are not busy.\n\n For more information, see options `high_watermark`, `high_msgq_watermark`, and\n `low_msgq_watermark`.\n\n- **`{mode, Mode :: binary | list}`** - Received `Packet` is delivered as\n defined by `Mode`.\n\n- **`{netns, Namespace :: file:filename_all()}`{: #option-netns }** - Sets a\n network namespace for the socket. Parameter `Namespace` is a filename defining\n the namespace, for example, `\"/var/run/netns/example\"`, typically created by\n command `ip netns add example`. This option must be used in a function call\n that creates a socket, that is, [`gen_tcp:connect/3,4`](`gen_tcp:connect/3`),\n `gen_tcp:listen/2`, [`gen_udp:open/1,2`](`gen_udp:open/1`) or\n [`gen_sctp:open/0,1,2`](`gen_sctp:open/0`), and also `getifaddrs/1`.\n\n This option uses the Linux-specific syscall `setns()`, such as in Linux kernel\n 3.0 or later, and therefore only exists when the runtime system is compiled\n for such an operating system.\n\n The virtual machine also needs elevated privileges, either running as\n superuser or (for Linux) having capability `CAP_SYS_ADMIN` according to the\n documentation for `setns(2)`. However, during testing also `CAP_SYS_PTRACE`\n and `CAP_DAC_READ_SEARCH` have proven to be necessary.\n\n _Example:_\n\n ```text\n setcap cap_sys_admin,cap_sys_ptrace,cap_dac_read_search+epi beam.smp\n ```\n\n Notice that the filesystem containing the virtual machine executable\n (`beam.smp` in the example) must be local, mounted without flag `nosetuid`,\n support extended attributes, and the kernel must support file capabilities.\n All this runs out of the box on at least Ubuntu 12.04 LTS, except that SCTP\n sockets appear to not support network namespaces.\n\n `Namespace` is a filename and is encoded and decoded as discussed in module\n `m:file`, with the following exceptions:\n\n - Emulator flag `+fnu` is ignored.\n - `getopts/2` for this option returns a binary for the filename if the stored\n filename cannot be decoded. This is only to occur if you set the option\n using a binary that cannot be decoded with the emulator's filename encoding:\n `file:native_name_encoding/0`.\n\n- **`{bind_to_device, Ifname :: binary()}`** - Binds a socket to a specific\n network interface. This option must be used in a function call that creates a\n socket, that is, [`gen_tcp:connect/3,4`](`gen_tcp:connect/3`),\n `gen_tcp:listen/2`, [`gen_udp:open/1,2`](`gen_udp:open/1`), or\n [`gen_sctp:open/0,1,2`](`gen_sctp:open/0`).\n\n Unlike `getifaddrs/0`, Ifname is encoded a binary. In the unlikely case that a\n system is using non-7-bit-ASCII characters in network device names, special\n care has to be taken when encoding this argument.\n\n This option uses the Linux-specific socket option `SO_BINDTODEVICE`, such as\n in Linux kernel 2.0.30 or later, and therefore only exists when the runtime\n system is compiled for such an operating system.\n\n Before Linux 3.8, this socket option could be set, but could not retrieved\n with `getopts/2`. Since Linux 3.8, it is readable.\n\n The virtual machine also needs elevated privileges, either running as\n superuser or (for Linux) having capability `CAP_NET_RAW`.\n\n The primary use case for this option is to bind sockets into\n [Linux VRF instances](http://www.kernel.org/doc/Documentation/networking/vrf.txt).\n\n- **`list`** - Received `Packet` is delivered as a list.\n\n- **`binary`** - Received `Packet` is delivered as a binary.\n\n- **`{nodelay, Boolean}` (TCP/IP sockets)** [](){: #option-nodelay } -\n If `Boolean == true`, option `TCP_NODELAY` is turned on for the socket,\n which means that also small amounts of data are sent immediately.\n\n This option is _not_ supported for `domain = local`, but if\n `inet_backend =/= socket` this error will be _ignored_.\n\n- **`{nopush, Boolean}` (TCP/IP sockets)** - This translates to `TCP_NOPUSH` on\n BSD and to `TCP_CORK` on Linux.\n\n If `Boolean == true`, the corresponding option is turned on for the socket,\n which means that small amounts of data are accumulated until a full MSS-worth\n of data is available or this option is turned off.\n\n Note that while `TCP_NOPUSH` socket option is available on OSX, its semantics\n is very different (e.g., unsetting it does not cause immediate send of\n accumulated data). Hence, `nopush` option is intentionally ignored on OSX.\n\n- **`{packet, PacketType}` (TCP/IP sockets)** [](){: #option-packet } -\n Defines the type of packets to use for a socket. Possible values:\n\n - **`raw | 0`** - No packaging is done.\n\n - **`1 | 2 | 4`** - Packets consist of a header specifying the number of bytes\n in the packet, followed by that number of bytes. The header length can be\n one, two, or four bytes, and containing an unsigned integer in big-endian\n byte order. Each send operation generates the header, and the header is\n stripped off on each receive operation.\n\n The 4-byte header is limited to 2Gb.\n\n - **`asn1 | cdr | sunrm | fcgi | tpkt | line`** - These packet types only have\n effect on receiving. When sending a packet, it is the responsibility of the\n application to supply a correct header. On receiving, however, one message\n is sent to the controlling process for each complete packet received, and,\n similarly, each call to `gen_tcp:recv/2,3` returns one complete packet. The\n header is _not_ stripped off.\n\n The meanings of the packet types are as follows:\n\n - `asn1` - ASN.1 BER\n - `sunrm` - Sun's RPC encoding\n - `cdr` - CORBA (GIOP 1.1)\n - `fcgi` - Fast CGI\n - `tpkt` - TPKT format \\[RFC1006]\n - `line` - Line mode, a packet is a line-terminated with newline, lines\n longer than the receive buffer are truncated\n\n - **`http | http_bin`** - The Hypertext Transfer Protocol. The packets are\n returned with the format according to `HttpPacket` described in\n `erlang:decode_packet/3` in ERTS. A socket in passive mode returns\n `{ok, HttpPacket}` from `gen_tcp:recv` while an active socket sends messages\n like `{http, Socket, HttpPacket}`.\n\n - **`httph | httph_bin`** - These two types are often not needed, as the\n socket automatically switches from `http`/`http_bin` to `httph`/`httph_bin`\n internally after the first line is read. However, there can be occasions\n when they are useful, such as parsing trailers from chunked encoding.\n\n- **`{packet_size, Integer}`(TCP/IP sockets)** - Sets the maximum allowed length\n of the packet body. If the packet header indicates that the length of the\n packet is longer than the maximum allowed length, the packet is considered\n invalid. The same occurs if the packet header is too large for the socket\n receive buffer.\n\n For line-oriented protocols (`line`, `http*`), option `packet_size` also\n guarantees that lines up to the indicated length are accepted and not\n considered invalid because of internal buffer limitations.\n\n- **`{line_delimiter, Char}` (TCP/IP sockets)**\n [](){: #option-line_delimiter } -\n Sets the line delimiting character for line-oriented protocols (`line`).\n Defaults to `$\\n`.\n\n- **`{raw, Protocol, OptionNum, ValueBin}`** - See below.\n\n- **`{read_ahead, Boolean}`** [](){: #option-read_ahead } -\n If set to `false` avoids reading ahead from the OS socket layer.\n The default for this option is `true` which speeds up packet header parsing.\n Setting `false` has a performance penalty because the packet header\n has to be read first, to know exactly how many bytes to read for the body,\n which roughly doubles the number of read operations.\n\n The use of this option is essential for example before switching to kTLS\n which activates OS socket layer encryption and decryption by setting\n special (raw) socket options. So if the Erlang socket layer has read ahead,\n it has read bytes that was for the OS socket layer to decrypt,\n which makes packet decryption derail for the connection.\n\n > #### Warning {: .warning }\n >\n > For packet modes that doesn't have the packet length at a fixed location\n > in a packet header, such as `line` or `asn1`, not reading ahead\n > can become very inefficient since sometimes the only way to accomplish\n > this is to read one byte at the time until the length\n > or packet end is found.\n\n- **`{read_packets, Integer}` (UDP sockets)** [](){: #option-read_packets } -\n Sets the maximum number of UDP packets to read without intervention\n from the socket when data is available. When this many packets\n have been read and delivered to the destination process,\n new packets are not read until a new notification of available data\n has arrived. Defaults to `5`. If this parameter is set too high, the system\n can become unresponsive because of UDP packet flooding.\n\n- **`{recbuf, Size}`** [](){: #option-recbuf } -\n The minimum size of the receive buffer to use for the socket.\n You are encouraged to use `getopts/2` to retrieve the size\n set by your operating system.\n\n- **`{recvtclass, Boolean}`** [](){: #option-recvtclass } -\n If set to `true` activates returning the received `TCLASS` value\n on platforms that implements the protocol `IPPROTO_IPV6` option\n `IPV6_RECVTCLASS` or `IPV6_2292RECVTCLASS` for the socket.\n The value is returned as a `{tclass,TCLASS}` tuple regardless of if\n the platform returns an `IPV6_TCLASS` or an `IPV6_RECVTCLASS` CMSG value.\n\n For packet oriented sockets that supports receiving ancillary data with the\n payload data (`gen_udp` and `gen_sctp`), the `TCLASS` value is returned in an\n extended return tuple contained in an\n [ancillary data](`t:ancillary_data/0`) list. For stream oriented sockets\n (`gen_tcp`) the only way to get the `TCLASS` value is if the platform supports\n the [`pktoptions`](`t:gen_tcp:pktoptions_value/0`) option.\n\n- **`{recvtos, Boolean}`** [](){: #option-recvtos } -\n If set to `true` activates returning the received `TOS` value\n on platforms that implements the protocol `IPPROTO_IP` option\n `IP_RECVTOS` for the socket. The value is returned as a `{tos,TOS}` tuple\n regardless of if the platform returns an `IP_TOS` or an `IP_RECVTOS` CMSG\n value.\n\n For packet oriented sockets that supports receiving ancillary data with the\n payload data (`gen_udp` and `gen_sctp`), the `TOS` value is returned in an\n extended return tuple contained in an\n [ancillary data](`t:ancillary_data/0`) list. For stream oriented sockets\n (`gen_tcp`) the only way to get the `TOS` value is if the platform supports\n the [`pktoptions`](`t:gen_tcp:pktoptions_value/0`) option.\n\n- **`{recvttl, Boolean}`** [](){: #option-recvttl } -\n If set to `true` activates returning the received `TTL` value\n on platforms that implements the protocol `IPPROTO_IP` option `IP_RECVTTL`\n for the socket. The value is returned as a `{ttl,TTL}` tuple\n regardless of if the platform returns an `IP_TTL` or an `IP_RECVTTL` CMSG\n value.\n\n For packet oriented sockets that supports receiving ancillary data with the\n payload data (`gen_udp` and `gen_sctp`), the `TTL` value is returned in an\n extended return tuple contained in an\n [ancillary data](`t:ancillary_data/0`) list. For stream oriented sockets\n (`gen_tcp`) the only way to get the `TTL` value is if the platform supports\n the [`pktoptions`](`t:gen_tcp:pktoptions_value/0`) option.\n\n- **`{reuseaddr, Boolean}`[](){: #option-reuseaddr }** -\n Allows or disallows reuse of local address. By default, reuse is disallowed.\n\n > #### Note {: .info }\n >\n > On windows `{reuseaddr, true}` will have no effect unless also\n > [`{reuseport, true}`](#option-reuseport) is set. If both are set,\n > the `SO_REUSEADDR` Windows socket option will be enabled. This since setting\n > `SO_REUSEADDR` on Windows more or less has the same behavior as setting both\n > `SO_REUSEADDR` and `SO_REUSEPORT` on BSD. This behavior was introduced as of\n > OTP 26.0.\n >\n > > #### Change {: .info }\n > >\n > > Previous behavior on Windows:\n > >\n > > - Prior to OTP 25.0, the `{reuseaddr, true}` option was silently ignored.\n > > - Between OTP 25.0 and up to the predecessor of OTP 25.2, the underlying\n > > `SO_REUSEADDR` socket option was set if `{reuseaddr, true}` was set.\n > > - Between OTP 25.2 and up to the predecessor of OTP 26.0, the underlying\n > > `SO_REUSEADDR` socket option was only set on UDP sockets if\n > > `{reuseaddr, true}` was set, and silently ignored on other sockets.\n >\n > See also the [`exclusiveaddruse`](#option-exclusiveaddruse) option.\n\n- **`{reuseport, Boolean}`[](){: #option-reuseport }** -\n Allows or disallows reuse of local port which _may or may not_\n have load balancing depending on the underlying OS. By default,\n reuse is disallowed. See also [`reuseport_lb`](#option-reuseport_lb).\n\n > #### Note {: .info }\n >\n > On windows `{reuseport, true}` will have no effect unless also\n > [`{reuseaddr, true}`](#option-reuseaddr) is set. If both are set,\n > the `SO_REUSEADDR` Windows socket option will be enabled. This since setting\n > `SO_REUSEADDR` on Windows more or less has the same behavior as setting both\n > `SO_REUSEADDR` and `SO_REUSEPORT` on BSD. The `reuseport` option was\n > introduced as of OTP 26.0.\n >\n > See also the [`exclusiveaddruse`](#option-exclusiveaddruse) option.\n\n > #### Note {: .info }\n >\n > `reuseport` _may or may not_ be the same underlying option as\n > [`reuseport_lb`](#option-reuseport_lb) depending on the underlying\n > OS. They, for example, are on Linux. When they are the same underlying\n > option, operating on both may cause them to interact in surprising ways. For\n > example, by enabling `reuseport` and then disabling `reuseport_lb` both will\n > end up being disabled.\n\n > #### Note {: .info }\n >\n > This option is _currently_ not supported for socket created with\n > `inet_backend = socket`\n\n- **`{reuseport_lb, Boolean}`[](){: #option-reuseport_lb }** -\n Allows or disallows reuse of local port _with_ load balancing.\n By default, reuse is disallowed. See also [`reuseport`](#option-reuseport).\n\n > #### Note {: .info }\n >\n > `reuseport_lb` _may or may not_ be the same underlying option as\n > [`reuseport`](#option-reuseport) depending on the underlying OS.\n > On Linux, for example, they are. And when they are the same\n > underlying option, operating on both may cause them to interact\n > in surprising ways. For example, by enabling `reuseport_lb`,\n > and then disabling `reuseport`, both will end up being disabled.\n\n > #### Note {: .info }\n >\n > This option is _currently_ not supported for socket created with\n > `inet_backend = socket`\n\n- **`{send_timeout, Integer}`** - Only allowed for connection-oriented sockets.\n\n Specifies a longest time to wait for a send operation to be accepted by the\n underlying TCP stack. When the limit is exceeded, the send operation returns\n `{error, timeout}`. How much of a packet that got sent is unknown; the socket\n is therefore to be closed whenever a time-out has occurred (see\n `send_timeout_close` below). Defaults to `infinity`.\n\n- **`{send_timeout_close, Boolean}`** - Only allowed for connection-oriented\n sockets.\n\n Used together with `send_timeout` to specify whether the socket is to be\n automatically closed when the send operation returns `{error, timeout}`. The\n recommended setting is `true`, which automatically closes the socket. Defaults\n to `false` because of backward compatibility.\n\n- **`{show_econnreset, Boolean}` (TCP/IP sockets)**\n [](){: #option-show_econnreset } -\n When this option is set to `false`, which is default, an RST\n received from the TCP peer is treated as a normal close\n (as though an FIN was sent). A caller to `gen_tcp:recv/2` gets\n `{error, closed}`. In active mode, the controlling process receives a\n `{tcp_closed, Socket}` message, indicating that the peer has closed the\n connection.\n\n Setting this option to `true` allows you to distinguish between a connection\n that was closed normally, and one that was aborted (intentionally or\n unintentionally) by the TCP peer. A call to `gen_tcp:recv/2` returns\n `{error, econnreset}`. In active mode, the controlling process receives a\n `{tcp_error, Socket, econnreset}` message before the usual\n `{tcp_closed, Socket}`, as is the case for any other socket error. Calls to\n `gen_tcp:send/2` also returns `{error, econnreset}` when it is detected that a\n TCP peer has sent an RST.\n\n A connected socket returned from `gen_tcp:accept/1` inherits the\n `show_econnreset` setting from the listening socket.\n\n- **`{sndbuf, Size}`** [](){: #option-sndbuf } -\n The minimum size of the send buffer to use for the socket.\n You are encouraged to use `getopts/2`, to retrieve the size\n set by your operating system.\n\n- **`{priority, Integer}`** - Sets the `SO_PRIORITY` socket level option on\n platforms where this is implemented. The behavior and allowed range varies\n between different systems. The option is ignored on platforms where it is not\n implemented. Use with caution.\n\n- **`{tos, Integer}`** - Sets `IP_TOS IP` level options on platforms where this\n is implemented. The behavior and allowed range varies between different\n systems. The option is ignored on platforms where it is not implemented. Use\n with caution.\n\n- **`{tclass, Integer}`** - Sets `IPV6_TCLASS IP` level options on platforms\n where this is implemented. The behavior and allowed range varies between\n different systems. The option is ignored on platforms where it is not\n implemented. Use with caution.\n\nIn addition to these options, _raw_ option specifications can be used. The raw\noptions are specified as a tuple of arity four, beginning with tag `raw`,\nfollowed by the protocol level, the option number, and the option value\nspecified as a binary. This corresponds to the second, third, and fourth\narguments to the `setsockopt` call in the C socket API. The option value must be\ncoded in the native endianness of the platform and, if a structure is required,\nmust follow the structure alignment conventions on the specific platform.\n\nUsing raw socket options requires detailed knowledge about the current operating\nsystem and TCP stack.\n\n_Example:_\n\nThis example concerns the use of raw options. Consider a Linux system where you\nwant to set option `TCP_LINGER2` on protocol level `IPPROTO_TCP` in the stack.\nYou know that on this particular system it defaults to 60 (seconds), but you\nwant to lower it to 30 for a particular socket. Option `TCP_LINGER2` is not\nexplicitly supported by `inet`, but you know that the protocol level translates\nto number 6, the option number to number 8, and the value is to be specified as\na 32-bit integer. You can use this code line to set the option for the socket\nnamed `Sock`:\n\n```text\ninet:setopts(Sock, [{raw,6,8,<<30:32/native>>}]),\n```\n\nAs many options are silently discarded by the stack if they are specified out of\nrange; it can be a good idea to check that a raw option is accepted. The\nfollowing code places the value in variable `TcpLinger2:`\n\n```text\n{ok,[{raw,6,8,< >}]}=inet:getopts(Sock,[{raw,6,8,4}]),\n```\n\nCode such as these examples is inherently non-portable, even different versions\nof the same OS on the same platform can respond differently to this kind of\noption manipulation. Use with care.\n\nNotice that the default options for TCP/IP sockets can be changed with the\nKernel configuration parameters mentioned in the beginning of this manual page.","ref":"inet.html#setopts/2"},{"type":"function","title":"inet.sockname/1","doc":"Return the local address and port number for a socket.\n\nNotice that for SCTP sockets this function returns only one of the socket\naddresses. Function [`socknames/1,2`](`socknames/1`) returns all.","ref":"inet.html#sockname/1"},{"type":"function","title":"inet.socknames/1","doc":"Equivalent to [`socknames(Socket, 0)`](`socknames/2`).","ref":"inet.html#socknames/1"},{"type":"function","title":"inet.socknames/2","doc":"Return all localaddresses for a socket.\n\nReturns a list of all local address/port number pairs for a socket,\nfor the specified association `Assoc`.\n\nThis function can return multiple addresses for multihomed sockets,\nsuch as SCTP sockets. For other sockets it returns a one-element list.\n\nNotice that parameter `Assoc` is by the\n[SCTP Sockets API Extensions](http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13)\ndefined to be ignored for one-to-one style sockets. For one-to-many style\nsockets, the special value `0` is defined to mean that the returned addresses\nmust be without any particular association. How different SCTP implementations\ninterpret this varies somewhat.","ref":"inet.html#socknames/2"},{"type":"type","title":"inet.address_family/0","doc":"","ref":"inet.html#t:address_family/0"},{"type":"type","title":"inet.ancillary_data/0","doc":"Ancillary data / control messages.\n\nAncillary data received with a data packet, read with the socket option\n[`pktoptions`](`t:gen_tcp:pktoptions_value/0`) from a TCP socket,\nor to set in a call to [`gen_udp:send/4`](`m:gen_udp#send-4-AncData`)\nor `gen_udp:send/5`.\n\nThe value(s) correspond to the currently active socket\n[options](`t:socket_setopt/0`) [`recvtos`](#option-recvtos),\n[`recvtclass`](#option-recvtclass) and [`recvttl`](#option-recvttl),\nor for a single send operation the option(s) to override\nthe currently active socket option(s).","ref":"inet.html#t:ancillary_data/0"},{"type":"type","title":"inet.ether_address/0","doc":"","ref":"inet.html#t:ether_address/0"},{"type":"type","title":"inet.family_address/0","doc":"A general network address.\n\nA general network address format on the form `{Family, Destination}`\nwhere `Family` is an atom such as `local` and the format of `Destination`\ndepends on `Family`. `Destination` is a complete address (for example\nan IP address with port number).","ref":"inet.html#t:family_address/0"},{"type":"type","title":"inet.getifaddrs_ifopts/0","doc":"Interface address description list.\n\nA list returned from [`getifaddrs/0,1`](`getifaddrs/0`)\nfor a named interface, translated from the\nreturned data of the POSIX API function `getaddrinfo()`.\n\n`Hwaddr` is hardware dependent, for example, on Ethernet interfaces it is the\n6-byte Ethernet address (MAC address (EUI-48 address)).\n\nThe tuples `{addr,Addr}`, `{netmask,Netmask}`, and possibly\n`{broadaddr,Broadaddr}` or `{dstaddr,Dstaddr}` are repeated in the list\nif the interface has got multiple addresses. An interface may have multiple\n`{flag,_}` tuples for example if it has different flags for different\naddress families.\n\nMultiple `{hwaddr,Hwaddr}` tuples is hard to say anything definite about,\nthough. The tuple `{flag,Flags}` is mandatory, all others are optional.\n\nDo not rely too much on the order of `Flags` atoms or the `Ifopt` tuples.\nThere are however some rules:\n\n- A `{flag,_}` tuple applies to all other tuples that follow.\n- Immediately after `{addr,_}` follows `{netmask,_}`.\n- Immediately thereafter may `{broadaddr,_}` follow if `broadcast`\n is member of `Flags`, or `{dstaddr,_}` if `pointtopoint`\n is member of `Flags`. Both `{dstaddr,_}` and `{broadaddr,_}` doesn't\n occur for the same `{addr,_}`.\n- Any `{netmask,_}`, `{broadaddr,_}`, or `{dstaddr,_}` tuples that follow an\n `{addr,Addr}` tuple concerns the address `Addr`.\n\nThe tuple `{hwaddr,_}` is not returned on Solaris, as the hardware address\nhistorically belongs to the link layer and it is not returned\nby the Solaris API function `getaddrinfo()`.\n\n> #### Warning {: .warning }\n>\n> On Windows, the data is fetched from different OS API functions, so the\n> `Netmask` and `Broadaddr` values may be calculated, just as some `Flags`\n> values.","ref":"inet.html#t:getifaddrs_ifopts/0"},{"type":"type","title":"inet.hostent/0","doc":"A record describing a host; name and address.\n\nCorresponds to the `C`: `struct hostent` as returned by for example\n`gethostbyname(3)`.\n\nThe record is defined in the Kernel include file `\"inet.hrl\"`.\n\nAdd the following directive to the module:\n\n```erlang\n-include_lib(\"kernel/include/inet.hrl\").\n```","ref":"inet.html#t:hostent/0"},{"type":"type","title":"inet.hostname/0","doc":"","ref":"inet.html#t:hostname/0"},{"type":"type","title":"inet.i_option/0","doc":"Options for selecting statistics items.\n\nRegarding `ShowPorts`, see `show_ports` as described in the `i/2` function,\ndefaults to `false`.","ref":"inet.html#t:i_option/0"},{"type":"type","title":"inet.inet6_address/0","doc":"A network address for the `inet6` family (`AF_INET6`, IPv6)\n> #### Warning {: .warning }\n>\n> This address format is currently experimental and for completeness\n> to make all address families have a `{Family, Destination}` representation.","ref":"inet.html#t:inet6_address/0"},{"type":"type","title":"inet.inet_address/0","doc":"A network address for the `inet` family (`AF_INET`, IPv4)\n> #### Warning {: .warning }\n>\n> This address format is currently experimental and for completeness\n> to make all address families have a `{Family, Destination}` representation.","ref":"inet.html#t:inet_address/0"},{"type":"type","title":"inet.inet_backend/0","doc":"Implementation backend selector for `t:socket/0`.\n\nSelects the implementation backend for [sockets](`t:socket/0`.\nThe current default is `inet` which uses `inet_drv.c` to call\nthe platform's socket API. The value `socket` instead uses\nthe `m:socket` module and its NIF implementation.\n\nThis is a _temporary_ option that will be ignored in a future release.","ref":"inet.html#t:inet_backend/0"},{"type":"type","title":"inet.ip4_address/0","doc":"","ref":"inet.html#t:ip4_address/0"},{"type":"type","title":"inet.ip6_address/0","doc":"","ref":"inet.html#t:ip6_address/0"},{"type":"type","title":"inet.ip_address/0","doc":"","ref":"inet.html#t:ip_address/0"},{"type":"type","title":"inet.local_address/0","doc":"A network address for the `local` family (`AF_LOCAL | AF_UNIX`)\n\nThis address family, also known as \"Unix domain sockets\" only works\non Unix-like systems.\n\n`File` is normally a file pathname in a local filesystem. It is limited in\nlength by the operating system, traditionally to 108 bytes.\n\nA `t:binary/0` is passed as is to the operating system,\nbut a `t:string/0` is encoded according to the\n[system filename encoding mode.](`file:native_name_encoding/0`)\n\nOther addresses are possible, for example Linux implements\n\"Abstract Addresses\". See the documentation for Unix Domain Sockets\non your system, normally `unix` in manual section 7.\n\nIn most API functions where you can use this address family\nthe port number must be `0`.","ref":"inet.html#t:local_address/0"},{"type":"type","title":"inet.module_socket/0","doc":"","ref":"inet.html#t:module_socket/0"},{"type":"type","title":"inet.port_number/0","doc":"","ref":"inet.html#t:port_number/0"},{"type":"type","title":"inet.posix/0","doc":"POSIX Error Code `t:atom/0`.\n\nAn atom that is named from the POSIX error codes used in Unix,\nand in the runtime libraries of most C compilers.\nSee section [POSIX Error Codes](#posix-error-codes).","ref":"inet.html#t:posix/0"},{"type":"type","title":"inet.returned_non_ip_address/0","doc":"a non-IP network address.\n\nAddresses besides `t:ip_address/0` ones that are returned from\nsocket API functions. See in particular `t:local_address/0`.\nThe `unspec` family corresponds to `AF_UNSPEC` and can occur\nif the other side has no socket address. The `undefined`\nfamily can only occur in the unlikely event of an address family\nthat the VM doesn't recognize.","ref":"inet.html#t:returned_non_ip_address/0"},{"type":"type","title":"inet.socket/0","doc":"A socket recognized by this module and its siblings.\n\nSee `t:gen_tcp:socket/0` and `t:gen_udp:socket/0`.","ref":"inet.html#t:socket/0"},{"type":"type","title":"inet.socket_address/0","doc":"","ref":"inet.html#t:socket_address/0"},{"type":"type","title":"inet.socket_getopt/0","doc":"","ref":"inet.html#t:socket_getopt/0"},{"type":"type","title":"inet.socket_optval/0","doc":"","ref":"inet.html#t:socket_optval/0"},{"type":"type","title":"inet.socket_protocol/0","doc":"","ref":"inet.html#t:socket_protocol/0"},{"type":"type","title":"inet.socket_setopt/0","doc":"","ref":"inet.html#t:socket_setopt/0"},{"type":"type","title":"inet.stat_option/0","doc":"","ref":"inet.html#t:stat_option/0"},{"type":"module","title":"inet_res","doc":"A rudimentary DNS client.\n\nThis module performs DNS name resolving towards recursive name servers.\n\nSee also [ERTS User's Guide: Inet Configuration](`e:erts:inet_cfg.md`)\nor more information about how to configure an Erlang runtime system for IP\ncommunication, and how to enable this DNS client by defining `'dns'`\nas a lookup method. The DNS client then acts as a backend for\nthe resolving functions in `m:inet`.\n\nThis DNS client can resolve DNS records even if it is not used\nfor normal name resolving in the node.\n\nThis is not a full-fledged resolver, only a DNS client that relies on asking\ntrusted recursive name servers.","ref":"inet_res.html"},{"type":"module","title":"Name Resolving - inet_res","doc":"UDP queries are used unless resolver option `usevc` is `true`,\nwhich forces TCP queries. If the query is too large for UDP,\nTCP is used instead. For regular DNS queries, 512 bytes is the size limit.\n\nWhen EDNS is enabled (resolver option `edns` is set to the EDNS version\n(that is; `0` instead of `false`), resolver option `udp_payload_size`\nsets the payload size limit. If a name server replies with the TC bit set\n(truncation), indicating that the answer is incomplete, the query is retried\ntowards the same name server using TCP. Resolver option `udp_payload_size`\nalso sets the advertised size for the maximum allowed reply size,\nif EDNS is enabled, otherwise the name server uses the limit 512 bytes.\nIf the reply is larger, it gets truncated, forcing a TCP requery.\n\nFor UDP queries, resolver options `timeout` and `retry` control\nretransmission. Each name server in the `nameservers` list is tried\nwith a time-out of `timeout`/`retry`. Then all name servers are tried again,\ndoubling the time-out, for a total of `retry` times.\n\n[](){: #servfail_retry_timeout }\n\nBut before all name servers are tried again, there is a (user configurable)\ntime-out, `servfail_retry_timeout`. The point of this is to prevent\nthe new query to be handled by a server's servfail cache (a client\nthat is too eager will actually only get what is in the servfail cache).\nIf there is too little time left of the resolver call's time-out\nto do a retry, the resolver call may return before the call's time-out\nhas expired.\n\nFor queries not using the `search` list, if the query to all `nameservers`\nresults in `{error,nxdomain}` or an empty answer, the same query is tried for\n`alt_nameservers`.","ref":"inet_res.html#module-name-resolving"},{"type":"module","title":"Resolver Types - inet_res","doc":"The following data types concern the resolver:","ref":"inet_res.html#module-resolver-types"},{"type":"module","title":"DNS Types - inet_res","doc":"The following data types concern the DNS client:","ref":"inet_res.html#module-dns-types"},{"type":"module","title":"Example - inet_res","doc":"This access functions example shows how `lookup/3` can be implemented using\n`resolve/3` from outside the module:\n\n```erlang\nexample_lookup(Name, Class, Type) ->\n case inet_res:resolve(Name, Class, Type) of\n {ok,Msg} ->\n [inet_dns:rr(RR, data)\n || RR <- inet_dns:msg(Msg, anlist),\n inet_dns:rr(RR, type) =:= Type,\n inet_dns:rr(RR, class) =:= Class];\n {error,_} ->\n []\n end.\n```","ref":"inet_res.html#module-example"},{"type":"function","title":"inet_res.getbyname/2","doc":"","ref":"inet_res.html#getbyname/2"},{"type":"function","title":"inet_res.getbyname/3","doc":"Resolve a DNS query.\n\nResolves a DNS query of the specified `Type` for the specified host,\nof class`in`. Returns, on success, when resolving a `Type = a|aaaa`\nDNS record, a `#hostent{}` record with `#hostent.h_addrtype = inet|inet6`,\nrespectively; see `t:inet:hostent/0`.\n\nWhen resolving other `Type = dns_rr_type()`:s (of class `in`), also returns\na `#hostent{}` record but with `t:dns_rr_type/0` in `#hostent.h_addrtype`,\nand the resolved `t:dns_data/0` in `#hostent.h_addr_list`; see `t:hostent/0`.\n\nThis function uses resolver option `search` that is a list of domain names.\nIf the name to resolve contains no dots, it is prepended to each domain\nname in the search list, and they are tried in order. If the name\ncontains dots, it is first tried as an absolute name and if that fails,\nthe search list is used. If the name has a trailing dot, it is supposed\nto be an absolute name and the search list is not used.","ref":"inet_res.html#getbyname/3"},{"type":"function","title":"inet_res.gethostbyaddr/1","doc":"","ref":"inet_res.html#gethostbyaddr/1"},{"type":"function","title":"inet_res.gethostbyaddr/2","doc":"Backend function used by `inet:gethostbyaddr/1`.","ref":"inet_res.html#gethostbyaddr/2"},{"type":"function","title":"inet_res.gethostbyname/1","doc":"Backend functions used by [`inet:gethostbyname/1,2`](`inet:gethostbyname/1`).\n\nIf resolver option `inet6` is `true`, equivalent to\n[`gethostbyname(Name, inet6, infinity)`](`gethostbyname/3`),\notherwise [`gethostbyname(Name, inet, infinity)`](`gethostbyname/3`).","ref":"inet_res.html#gethostbyname/1"},{"type":"function","title":"inet_res.gethostbyname/2","doc":"","ref":"inet_res.html#gethostbyname/2"},{"type":"function","title":"inet_res.gethostbyname/3","doc":"Backend functions used by [`inet:gethostbyname/1,2`](`inet:gethostbyname/1`).\n\nThis function uses resolver option `search` just like\n[`getbyname/2,3`](`getbyname/2`).","ref":"inet_res.html#gethostbyname/3"},{"type":"function","title":"inet_res.lookup/3","doc":"","ref":"inet_res.html#lookup/3"},{"type":"function","title":"inet_res.lookup/4","doc":"","ref":"inet_res.html#lookup/4"},{"type":"function","title":"inet_res.lookup/5","doc":"Look up DNS data.\n\nResolves the DNS data for the record `Name` of the specified\n`Type` and `Class`. On success, filters out the answer records\nwith the correct `Class` and `Type`, and returns a list of their data fields.\nSo, a lookup for type `any` gives an empty answer, as the answer records\nhave specific types that are not `any`. An empty answer or a failed lookup\nreturns an empty list.\n\nCalls [`resolve/*`](`resolve/3`) with the same arguments and filters the result,\nso `Opts` is described for those functions.","ref":"inet_res.html#lookup/5"},{"type":"function","title":"inet_res.nnslookup/4","doc":"","ref":"inet_res.html#nnslookup/4"},{"type":"function","title":"inet_res.nnslookup/5","doc":"Resolve a DNS query.\n\nLike `nslookup/4` but calls `resolve/5` with both the arguments\n`Opts = [{nameservers, Nameservers}]` and `Timeout`.","ref":"inet_res.html#nnslookup/5"},{"type":"function","title":"inet_res.nslookup/3","doc":"","ref":"inet_res.html#nslookup/3"},{"type":"function","title":"inet_res.nslookup/4","doc":"Resolve a DNS query.\n\nThis function is a legacy wrapper to `resolve/5` that simplifies\nerrors matching `{error, {Reason, _}}` into `{error, Reason}`\nor `{error, einval}`.\n\nWith argument `Timeout` calls `resolve/5` with `Opts = []`.\n\nWith argument `Nameservers` calls `resolve/5` with\n`Opts = [{nameservers, Nameservers}]` and `Timeout = infinity`.","ref":"inet_res.html#nslookup/4"},{"type":"function","title":"inet_res.resolve/3","doc":"","ref":"inet_res.html#resolve/3"},{"type":"function","title":"inet_res.resolve/4","doc":"","ref":"inet_res.html#resolve/4"},{"type":"function","title":"inet_res.resolve/5","doc":"Resolve a DNS query.\n\nResolves a DNS query for the specified `Type`, `Class`, and `Name`,\ninto a DNS message possibly containing Resource Records.\nThe returned `t:dns_msg/0` can be examined using access functions\nin `inet_db`, as described in section in [DNS Types](#module-dns-types).\n\nIf `Name` is an `ip_address()`, the domain name to query about is generated\nas the standard reverse `\".IN-ADDR.ARPA.\"` name for an IPv4 address, or the\n`\".IP6.ARPA.\"` name for an IPv6 address. In this case, you most probably\nwant to use `Class = in` and `Type = ptr`, but it is not done automatically.\n\n`Opts` overrides the corresponding resolver options. If option `nameservers`\nis specified, it is assumed that it is the complete list of name serves,\nso resolver option `alt_nameserves` is ignored. However, if option\n`alt_nameserves` is also specified to this function, it is used.\n\nOption `verbose` (or rather `{verbose,true}`) causes diagnostics printout\nthrough [`io:format/2`](`io:format/3`) of queries, replies, retransmissions,\nand so on, similar to utilities such as `dig` and `nslookup`.\n\nOption `nxdomain_reply` (or rather `{nxdomain_reply, true}`) causes NXDOMAIN\nerrors from DNS servers to be returned as `{error, {nxdomain, dns_msg()}}`.\n`t:dns_msg/0` contains the additional sections that where included by the\nanswering server. This is mainly useful to inspect the SOA record\nto get the TTL for negative caching.\n\nIf `Opt` is any atom, it is interpreted as `{Opt,true}` unless\nthe atom string starts with `\"no\"`, making the interpretation `{Opt,false}`.\nFor example, `usevc` is an alias for `{usevc, true}` and `nousevc`\nis an alias for `{usevc, false}`.\n\nOption `inet6` has no effect on this function. You probably want to use\n`Type = a | aaaa` instead.","ref":"inet_res.html#resolve/5"},{"type":"type","title":"inet_res.dns_class/0","doc":"","ref":"inet_res.html#t:dns_class/0"},{"type":"type","title":"inet_res.dns_data/0","doc":"DNS record data (content)\n\nThe basic type of each data element is specified in this type.\n\n`Regexp` is a UTF-8 `t:string/0`. The other `t:string/0`s\nare actually Latin-1 strings.","ref":"inet_res.html#t:dns_data/0"},{"type":"type","title":"inet_res.dns_msg/0","doc":"A DNS message.\n\nThis is the start of a hierarchy of opaque data structures that can be\nexamined with access functions in `inet_dns`, which return lists of\n`{Field,Value}` tuples. The arity 2 functions return the value\nfor a specified field.\n\n```erlang\ndns_msg() = DnsMsg\n inet_dns:msg(DnsMsg) ->\n [ {header, dns_header()}\n | {qdlist, dns_query()}\n | {anlist, dns_rr()}\n | {nslist, dns_rr()}\n | {arlist, dns_rr()} ]\n inet_dns:msg(DnsMsg, header) -> dns_header() % for example\n inet_dns:msg(DnsMsg, Field) -> Value\n\ndns_header() = DnsHeader\n inet_dns:header(DnsHeader) ->\n [ {id, integer()}\n | {qr, boolean()}\n | {opcode, query | iquery | status | integer()}\n | {aa, boolean()}\n | {tc, boolean()}\n | {rd, boolean()}\n | {ra, boolean()}\n | {pr, boolean()}\n | {rcode, integer(0..16)} ]\n inet_dns:header(DnsHeader, Field) -> Value\n\nquery_type() = axfr | mailb | maila | any | dns_rr_type()\n\ndns_query() = DnsQuery\n inet_dns:dns_query(DnsQuery) ->\n [ {domain, dns_name()}\n | {type, query_type()}\n | {class, dns_class()} ]\n inet_dns:dns_query(DnsQuery, Field) -> Value\n\ndns_rr() = DnsRr\n inet_dns:rr(DnsRr) -> DnsRrFields | DnsRrOptFields\n DnsRrFields = [ {domain, dns_name()}\n | {type, dns_rr_type()}\n | {class, dns_class()}\n | {ttl, integer()}\n | {data, dns_data()} ]\n DnsRrOptFields = [ {domain, dns_name()}\n | {type, opt}\n | {udp_payload_size, integer()}\n | {ext_rcode, integer()}\n | {version, integer()}\n | {z, integer()}\n | {data, dns_data()} ]\n inet_dns:rr(DnsRr, Field) -> Value\n```\n\nThere is an information function for the types above:\n\n```erlang\ninet_dns:record_type(dns_msg()) -> msg;\ninet_dns:record_type(dns_header()) -> header;\ninet_dns:record_type(dns_query()) -> dns_query;\ninet_dns:record_type(dns_rr()) -> rr;\ninet_dns:record_type(_) -> undefined.\n```\n\nSo, `inet_dns:(inet_dns:record_type(X))(X)` converts any of these data\nstructures into a `{Field,Value}` list.","ref":"inet_res.html#t:dns_msg/0"},{"type":"type","title":"inet_res.dns_name/0","doc":"A string with no adjacent dots.","ref":"inet_res.html#t:dns_name/0"},{"type":"type","title":"inet_res.dns_rr_type/0","doc":"","ref":"inet_res.html#t:dns_rr_type/0"},{"type":"type","title":"inet_res.hostent/0","doc":"Extended variant of `t:inet:hostent/0`.\n\nAllows `t:dns_rr_type/0` for the\n[`#hostent{}.h_addrtype`](`t:inet:hostent/0`) field, and\n`[`[`dns_data/0`](`t:dns_data/0`)`]` for the\n[`#hostent{}.h_addr_list`](`t:inet:hostent/0`) field.","ref":"inet_res.html#t:hostent/0"},{"type":"type","title":"inet_res.nameserver/0","doc":"","ref":"inet_res.html#t:nameserver/0"},{"type":"type","title":"inet_res.res_error/0","doc":"","ref":"inet_res.html#t:res_error/0"},{"type":"type","title":"inet_res.res_option/0","doc":"","ref":"inet_res.html#t:res_option/0"},{"type":"module","title":"net","doc":"Network interface.\n\nThis module provides an API for the network interface.","ref":"net.html"},{"type":"function","title":"net.getaddrinfo/1","doc":"","ref":"net.html#getaddrinfo/1"},{"type":"function","title":"net.getaddrinfo/2","doc":"Network address and service translation.\n\nThis function is the inverse of [`getnameinfo`](`getnameinfo/1`). It converts\nhost and service to a corresponding socket address.\n\nOne of the `Host` and `Service` may be `undefined` but _not_ both.","ref":"net.html#getaddrinfo/2"},{"type":"function","title":"net.gethostname/0","doc":"Return the name of the current host.","ref":"net.html#gethostname/0"},{"type":"function","title":"net.getifaddrs/0","doc":"","ref":"net.html#getifaddrs/0"},{"type":"function","title":"net.getifaddrs/1","doc":"Get interface addresses.\n\nWith argument 'Filter: get the machines interface addresses,\nfiltered according to `Filter`.\n\nWith argument `Namespace`: equivalent to\n[`getifaddrs(default, Namespace)`](`getifaddrs/2`).","ref":"net.html#getifaddrs/1"},{"type":"function","title":"net.getifaddrs/2","doc":"Get interface addresses in a namespace.\n\nThe same as [`getifaddrs(Filter)`](`getifaddrs/1`) but\nin the specified `Namespace`.","ref":"net.html#getifaddrs/2"},{"type":"function","title":"net.getnameinfo/1","doc":"","ref":"net.html#getnameinfo/1"},{"type":"function","title":"net.getnameinfo/2","doc":"Address-to-name translation in a protocol-independant manner.\n\nThis function is the inverse of [`getaddrinfo`](`getaddrinfo/1`). It converts a\nsocket address to a corresponding host and service.","ref":"net.html#getnameinfo/2"},{"type":"function","title":"net.getservbyname/1","doc":"","ref":"net.html#getservbyname/1"},{"type":"function","title":"net.getservbyname/2","doc":"Get service by name.\n\nThis function is used to get the port number of the specified protocol\nfor the named service.","ref":"net.html#getservbyname/2"},{"type":"function","title":"net.getservbyport/1","doc":"","ref":"net.html#getservbyport/1"},{"type":"function","title":"net.getservbyport/2","doc":"Get service by name.\n\nThis function is used to get the service name of the specified protocol\nfor the given port number.","ref":"net.html#getservbyport/2"},{"type":"function","title":"net.if_index2name/1","doc":"Mappings between network interface index and names.","ref":"net.html#if_index2name/1"},{"type":"function","title":"net.if_name2index/1","doc":"Mappings between network interface names and indexes.","ref":"net.html#if_name2index/1"},{"type":"function","title":"net.if_names/0","doc":"Get network interface names and indexes.","ref":"net.html#if_names/0"},{"type":"type","title":"net.address_info/0","doc":"","ref":"net.html#t:address_info/0"},{"type":"type","title":"net.ifaddrs/0","doc":"Interface addresses and flags.\n\nThis type defines addresses and flags for an interface.\n\n> #### Note {: .info }\n>\n> Not all fields of this map has to be present. The flags field can be used to\n> test for some of the fields. For example `broadaddr` will only be present if\n> the `broadcast` flag is present in flags.","ref":"net.html#t:ifaddrs/0"},{"type":"type","title":"net.ifaddrs_filter/0","doc":"Interface address filtering selector.\n\n- **all** - All interfaces\n\n- **default** - Interfaces with address family `inet` _or_ `inet6`\n\n- **inet | inet6 | packet | link** - Interfaces with _only_ the specified\n address family\n- **hwaddr** - Interfaces with address family `packet` _or_ `link`","ref":"net.html#t:ifaddrs_filter/0"},{"type":"type","title":"net.ifaddrs_filter_fun/0","doc":"Interface address filtering selector `t:function/0`.\n\nFor each `ifaddrs` entry, return either `true` to keep the entry\nor `false` to discard the entry.\n\nFor example, to get an interface list which only contains\nnon-`loopback` `inet` interfaces:\n\n```erlang\nnet:getifaddrs(\n fun (#{ addr := #{family := inet},\n flags := Flags}) ->\n not lists:member(loopback, Flags);\n (_) ->\n false\n end).\n```","ref":"net.html#t:ifaddrs_filter_fun/0"},{"type":"type","title":"net.ifaddrs_filter_map/0","doc":"Interface address filtering selector map.\n\nThe `family` field can only have the (above) specified values\n(and not all the values of socket:domain()).\nIt can also be a list of values, to cover the situation when\nany of the specified families are accepted.\nFor example, family can be set to `[inet,inet6]` if either `inet` or `inet6`\nis accepted.\n\nThe use of the `flags` field is that any flag provided must exist for the\ninterface.\n\nFor example, if `family` is set to `inet` and `flags` to\n`[broadcast, multicast]` only interfaces with address family `inet`\nand the flags `broadcast` and `multicast` will be listed.","ref":"net.html#t:ifaddrs_filter_map/0"},{"type":"type","title":"net.ifaddrs_flag/0","doc":"","ref":"net.html#t:ifaddrs_flag/0"},{"type":"type","title":"net.ifaddrs_flags/0","doc":"","ref":"net.html#t:ifaddrs_flags/0"},{"type":"type","title":"net.name_info/0","doc":"","ref":"net.html#t:name_info/0"},{"type":"type","title":"net.name_info_flag/0","doc":"","ref":"net.html#t:name_info_flag/0"},{"type":"type","title":"net.name_info_flag_ext/0","doc":"","ref":"net.html#t:name_info_flag_ext/0"},{"type":"type","title":"net.name_info_flags/0","doc":"","ref":"net.html#t:name_info_flags/0"},{"type":"type","title":"net.network_interface_index/0","doc":"","ref":"net.html#t:network_interface_index/0"},{"type":"type","title":"net.network_interface_name/0","doc":"","ref":"net.html#t:network_interface_name/0"},{"type":"module","title":"socket","doc":"Socket interface.\n\nThis module provides an API for network sockets. Functions are provided to\ncreate, delete and manipulate the sockets as well as sending and receiving data\non them.\n\nThe intent is that it shall be as \"close as possible\" to the OS level socket\ninterface. The only significant addition is that some of the functions, e.g.\n`recv/3`, have a time-out argument.\n\n[](){: #asynchronous-calls }\n\n> #### Note {: .info }\n>\n> #### Asynchronous Calls\n>\n> Some functions feature _asynchronous calls_. This is achieved by setting\n> the `Timeout` argument to `nowait` or to a `Handle ::` `t:reference/0`.\n> See the respective function's type specification.\n>\n> This module has two different implementations of asynchronous calls.\n> One on the _Unix_ family of operating systems:\n> `select` - based on the standard socket interface's\n> `select(3)`/`poll(3)` calls, and one on _Windows_: `completion` -\n> based on asynchronous I/O Completion Ports.\n> The difference shows in the return values and message formats\n> because they have slightly different semantics.\n>\n> #### The `completion` and `select` Return Values\n>\n> For instance, if calling `recv/3` like this;\n> [`recv(Socket, 0, nowait)`](#recv-nowait), when there is\n> no data available for reading, it will return one of:\n>\n> - `{completion, `[`CompletionInfo`](`t:completion_info/0`)`}`\n> - `{select, `[`SelectInfo`](`t:select_info/0`)`}`\n>\n> `CompletionInfo` contains a [CompletionHandle](`t:completion_handle/0`) and\n> `SelectInfo` contains a [SelectHandle](`t:select_handle/0`).\n> Both are types are aliases to `t:reference/0`.\n> When the operation can continue, a `completion` message containing\n> the `CompletionHandle` or a `select` message containing\n> the `SelectHandle` is sent to the calling process.\n>\n> On `select` systems some functions may also return:\n>\n> - `{select, {`[`SelectInfo`](`t:select_info/0`)`, _}`\n>\n> This may happen for sockets of type [`stream`](`t:type/0`) where\n> the stream handling can split the data stream at any point.\n> See the respective function's type specification's return type.\n>\n> #### The `completion` and `select` Messages\n>\n> The `completion` message has the format:\n>\n> - `{'$socket', `[`Socket`](`t:socket/0`)`, completion,\n> {`[`CompletionHandle`](`t:completion_handle/0`)`, CompletionStatus}}`\n>\n> The `select` message has the format:\n>\n> - `{'$socket', `[`Socket`](`t:socket/0`)`, select,\n> `[`SelectHandle`](`t:select_handle/0`)`}`\n>\n> When a `completion` message is received (which contains the _result_\n> of the operation), it means that the operation has been _completed_ with\n> `CompletionStatus :: ok | {error, Reason}`.\n> See the respective function's documentation for possible values\n> of `Reason`, which are the same `{error, Reason}` values\n> that can be returned by the function itself.\n>\n> When a `select` message is received, it only means that the operation\n> _may now continue_, by retrying the operation (which may return\n> a new `{select, _}` value). Some operations are retried by repeating\n> the same function call, and some have a dedicated function variant\n> to be used for the retry. See the respective function's documentation.\n>\n> #### Operation Queuing on `select` Systems\n>\n> On `select` systems, all other processes are _locked out_ until the\n> current process has completed the operation as in a continuation\n> call has returned a value indicating success or failure\n> (not a `select` return). Other processes are queued and get\n> a `select` return which makes them wait for their turn.\n>\n> #### Canceling an operation\n>\n> An operation that is in progress (not completed) may be canceled\n> using `cancel/2` both on `completion` and `select` systems.\n>\n> Canceling an operation ensures that there is no `completion`,\n> `select`, nor `abort` message in the inbox after the `cancel/2` call.\n>\n> #### Using a `Handle`\n>\n> If creating a `t:reference/0` with [`make_ref()`](`erlang:make_ref/0`)\n> and using that as the `Timeout | Handle` argument, the same `Handle`\n> will then be the [`SelectHandle`](`t:select_handle/0`) in the returned\n> `t:select_info/0` and the received `select` message, or be\n> the [`CompletionHandle`](`t:completion_handle/0`) in the returned\n> `t:completion_info/0` and the received `completion` message.\n>\n> The compiler may then optimize a following `receive` statement\n> to only scan the messages that arrive after the `t:reference/0`\n> is created. If the message queue is large this is a big optimization.\n>\n> The `t:reference/0` has to be unique for the call.\n>\n> #### Repeating an Operation on a `select` Systems\n>\n> On`select` systems, if a call would be repeated _before_ the `select`\n> message has been received it replaces the call in progress:\n>\n> ```erlang\n> {select, {select_info, Handle}} = socket:accept(LSock, nowait),\n> {error, timeout} = socket:accept(LSock, 500),\n> :\n> ```\n> Above, `Handle` is _no longer_ valid once the second `accept/2`, call\n> has been made (the first call is automatically canceled).\n> After the second `accept/2` call returns `{error, timeout}`,\n> the accept operation has completed.\n>\n> Note that there is a race here; there is no way to know if the call\n> is repeated _before_ the `select` message is sent since it _may_\n> have been sent just before the repeated call. So now there\n> might be a `select` message containing `Handle` in the inbox.\n>\n> #### The `abort` Message\n>\n> Another message the user must be prepared for\n> (when using `nowait | Handle`) is the `abort` message:\n>\n> - `{'$socket', `[`Socket`](`t:socket/0`)`, abort, Info}`\n>\n> This message indicates that the operation in progress has been aborted.\n> For instance, if the socket has been closed by another process;\n> `Info` will be `{Handle, closed}`.\n\n> #### Note {: .info }\n>\n> Support for IPv6 has been implemented but not _fully_ tested.\n>\n> SCTP has only been partly implemented (and not tested).\n\nThis module was introduced in OTP 22.0, as experimental code.\n* In OTP 22.1, the `nowait` argument was added for many functions,\n and the `cancel/2` and `info/1` functions were also added.\n* In OTP 22.3, the `number_of/0` function was added.\n* In OTP 23.0, the functions [`is_supported/1,2`](`is_supported/1`)\n and the [`open/1,2`](`open/1`) functions with an `FD` argument were added.\n* In OTP 23.1, the `use_registry/1` function was added.\n* In OTP 24.0, the `t:select_handle/0` argument was added for many functions,\n the `cancel/1`, `cancel_monitor/1`, `getopt/3` with tuple options,\n `getopt_native/3`, `info/0`, `monitor/1`, `open/3` with an option list,\n many variants of the [`recv/*`](`recv/2`),\n [`recvfrom/*`](`recvfrom/1`), [`recvmsg/*`](`recvmsg/1`),\n [`send/*`](`send/2`), [`sendmsg/*`](`sendmsg/2`),\n the [`sendto/*`](`sendto/3`) functions,\n the [`sendfile/*`](`sendfile/5`) functions,\n and the `setopt/3`, `setopt_native/3` functions, were added.\n* In OTP 24.1, the [`i/*`](`i/0`) functions were added.\n* In OTP 24.2, the [`ioctl/*`](`ioctl/2`) functions were added.\n* In OTP 26.0, the `t:completion_handle/0` argument was added for\n many functions, and the `cancel/2` function with `t:completion_info/0`\n argument was added. That is: support for Windows asynchronous\n I/O Completion Ports was added. The Unix-ish flavored\n ([select handle](`t:select_handle/0`)) API features could be considered\n no longer experimental.\n* In OTP 27.0, the Windows flavored\n ([completion handle](`t:completion_handle/0`))\n API features could be considered no longer experimental.","ref":"socket.html"},{"type":"module","title":"Examples - socket","doc":"```erlang\nclient(SAddr, SPort) ->\n {ok, Sock} = socket:open(inet, stream, tcp),\n ok = socket:connect(Sock, #{family => inet,\n addr => SAddr,\n port => SPort}),\n Msg = <<\"hello\">>,\n ok = socket:send(Sock, Msg),\n ok = socket:shutdown(Sock, write),\n {ok, Msg} = socket:recv(Sock),\n ok = socket:close(Sock).\n\nserver(Addr, Port) ->\n {ok, LSock} = socket:open(inet, stream, tcp),\n ok = socket:bind(LSock, #{family => inet,\n port => Port,\n addr => Addr}),\n ok = socket:listen(LSock),\n {ok, Sock} = socket:accept(LSock),\n {ok, Msg} = socket:recv(Sock),\n ok = socket:send(Sock, Msg),\n ok = socket:close(Sock),\n ok = socket:close(LSock).\n```","ref":"socket.html#module-examples"},{"type":"function","title":"socket.accept/1","doc":"Equivalent to [`accept(ListenSocket, infinity)`](`accept/2`).","ref":"socket.html#accept/1"},{"type":"function","title":"socket.accept/2","doc":"Accept a connection on a listening socket.\n\n`ListenSocket` has to be of a connection oriented type\n(types `stream` or `seqpacket`, see `open/1`), and set to listen\n(see `listen/1`).\n\n[](){: #accept-infinity }\n\nIf the `Timeout` argument is `infinity`; accepts the first pending\nincoming connection for the listen socket or wait for one to arrive,\nand return the new connection socket.\n\n[](){: #accept-timeout }\n\nIf the `Timeout` argument is a time-out value (`t:non_neg_integer/0`);\nreturns `{error, timeout}` if no connection has arrived\nafter `Timeout` milliseconds.\n\n[](){: #accept-nowait }\n\nIf the `Handle` argument `nowait` *(since OTP 22.1)*,\nstarts an [asynchronous call](#asynchronous-calls) if the operation\ncouldn't be completed immediately.\n\nIf the `Handle` argument is a `t:select_handle/0`,\n*(since OTP 24.0)*, or on _Windows_, the equivalent\n`t:completion_handle/0` *(since OTP 26.0)*, starts\nan [asynchronous call](#asynchronous-calls) like for `nowait`.\n\nSee the note [Asynchronous Calls](#asynchronous-calls)\nat the start of this module reference manual page.","ref":"socket.html#accept/2"},{"type":"function","title":"socket.bind/2","doc":"Bind a name to a socket.\n\nWhen a socket is created (with [`open`](`open/2`)), it has no address assigned\nto it. `bind` assigns the address specified by the `Addr` argument.\n\nThe rules used for name binding vary between domains.\n\nIf you bind a socket to an address in for example the `inet` or `inet6`\naddress families, with an ephemeral port number (`0`), and want to know\nwhich port that was chosen, you can find out using something like:\n`{ok, #{port := Port}} =`[`socket:sockname(Socket)`](`sockname/1`)","ref":"socket.html#bind/2"},{"type":"function","title":"socket.cancel/2","doc":"Cancel an asynchronous call in progress.\n\nCall this function to cancel an [asynchronous call](#asynchronous-calls)\nin progress, that is; it returned a value containing\na `t:completion_info/0` or `t:select_info/0`.\n\nSee the note [Asynchronous Calls](#asynchronous-calls)\nat the start of this module reference manual page.\n\nIf another process tries an operation of the same basic type\n(`accept/1` | `send/2` | `recv/2`) it will be enqueued and notified\nthrough a `select` or `completion` message when the current operation\nand all enqueued before it has been completed. If the current operation\nis canceled by this function it is treated as a completed operation;\nthe process first in queue is notified.\n\nIf [`SelectInfo`](`t:select_info/0`) `|`\n[`CompletionInfo`](`t:completion_info/0`) does not match\nan operation in progress for the calling process, this function returns\n`{error, {invalid, SelectInfo | CompletionInfo}}`.","ref":"socket.html#cancel/2"},{"type":"function","title":"socket.cancel_monitor/1","doc":"Cancel a socket monitor.\n\nIf `MRef` is a reference that the calling process obtained by calling\n`monitor/1`, this monitor is removed. If there is no such monitor\nfor the calling process (or MRef doesn't correspond to a monitor),\nnothing happens.\n\nThe returned value is one of the following:\n\n- **`true`** - The monitor was found and removed. In this case, no `'DOWN'`\n message corresponding to this monitor has been delivered and will not be\n delivered.\n\n- **`false`** - The monitor was not found so it couldn't be removed. This\n might be because the monitor has already triggered and there is\n a `'DOWN'` message from this monitor in the caller message queue.","ref":"socket.html#cancel_monitor/1"},{"type":"function","title":"socket.close/1","doc":"Close a socket.\n\n> #### Note {: .info }\n>\n> Note that for `Protocol = tcp` (see `open/3`), although\n> TCP guarantees that when the other side sees the stream close\n> all data that we sent before closing has been delivered,\n> there is no way for us to know that the other side got all data\n> and the stream close. All kinds of network and OS issues\n> may obliterate that.\n>\n> To get such a guarantee we need to implement an in-band acknowledge\n> protocol on the connection, or we can use the [`shutdown`](`shutdown/2`)\n> function to signal that no more data will be sent and then wait\n> for the other end to close the socket. Then we will see our read side\n> getting a socket close. In this way we implement a small\n> acknowledge protocol using `shutdown/2`. The other side cannot\n> know that we ever saw the socket close, but in a client/server\n> scenario that is often not relevant.","ref":"socket.html#close/1"},{"type":"function","title":"socket.connect/1","doc":"Finalize a [`connect/3`](#connect-nowait) operation.\n\nSee the note [Asynchronous Calls](#asynchronous-calls)\nat the start of this module reference manual page.\n\nOn `select` systems this function finalizes a connection setup\non a socket, after receiving a `select` message\n`{'$socket',` [`Socket`](`t:socket/0`)`, select,\n`[`SelectHandle`](`t:select_handle/0`)`}`,\nand returns whether the connection setup was successful or not.\n\nInstead of calling this function, for backwards compatibility,\nit is allowed to call [`connect/2,3`](`connect/2`) again,\nbut that incurs more overhead since the connect address and\ntime-out argument are processed in vain.\n\nThe call that completes the connect operation, the second call,\ncannot return a `select` return value.","ref":"socket.html#connect/1"},{"type":"function","title":"socket.connect/2","doc":"Equivalent to\n[`connect(Socket, SockAddr, infinity)`](#connect-infinity).","ref":"socket.html#connect/2"},{"type":"function","title":"socket.connect/3","doc":"Connect the socket to the given address.\n\nThis function connects the socket to the address specified\nby the `SockAddr` argument.\n\nIf a connection attempt is already in progress (by another process),\n`{error, already}` is returned.\n\n> #### Note {: .info }\n>\n> On _Windows_ the socket has to be [_bound_](`bind/2`).\n\n[](){: #connect-infinity }\n\nIf the time-out argument (argument 3) is `infinity` it is\nup to the OS implementation to decide when the connection\nattempt failed and then what to return; probably `{error, etimedout}`.\nThe OS time-out may be very long.\n\n[](){: #connect-timeout }\n\nIf the time-out argument (argument 3) is a time-out value\n(`t:non_neg_integer/0`); return `{error, timeout}`\nif the connection hasn't been established within `Timeout` milliseconds.\n\n> #### Note {: .info }\n>\n> Note that when this call has returned `{error, timeout}`\n> the connection state of the socket is uncertain since the platform's\n> network stack may complete the connection at any time,\n> up to some platform specific time-out.\n>\n> Repeating a connection attempt towards the same address would be ok, but\n> towards a different address could end up with a connection to either address.\n>\n> The safe play is to close the socket and start over.\n>\n> Also note that this applies to canceling a `nowait` connect call\n> described below.\n\n[](){: #connect-nowait }\n\nIf the time-out argument (argument 2) is `nowait` *(since OTP 22.1)*,\nstart an [asynchronous call](#asynchronous-calls) if the operation\ncouldn't be completed immediately.\n\nIf the time-out argument (argument 2) is a `Handle ::` `t:select_handle/0`,\n*(since OTP 24.0)*, or on _Windows_, the equivalent\n`Handle ::` `t:completion_handle/0` *(since OTP 26.0)*,\nstart an [asynchronous call](#asynchronous-calls) like for `nowait`.\n\nSee the note [Asynchronous Calls](#asynchronous-calls)\nat the start of this module reference manual page.\n\nAfter receiving a `select` message call `connect/1`\nto complete the operation.\n\nIf canceling the operation with `cancel/2` see the note above\nabout [connection time-out](#connect-timeout).","ref":"socket.html#connect/3"},{"type":"function","title":"socket.getopt/2","doc":"Get the value of a socket option.\n\nGets the value of an OS protocol level socket option, or from\nthe `otp` pseudo protocol level, which is this module's\nimplementation level above the OS protocol levels.\n\nSee the type [otp_socket_option() ](`t:otp_socket_option/0`)\nfor a description of the `otp` protocol level.\n\nSee the type `t:socket_option/0` for which OS protocol level options\nthat this implementation knows about, how they are related to OS option names,\nand if there are known peculiarities with any of them.\n\nWhat options that are valid depends on the OS, and on the kind of socket\n(`t:domain/0`,`t:type/0` and `t:protocol/0`). See the type\n`t:socket_option()` and the\n[socket options ](socket_usage.md#socket_options) chapter\nin the User's Guide for more info.\n\n> #### Note {: .info }\n>\n> Not all options are valid, nor possible to get, on all platforms. That is,\n> even if this `socket` implementation support an option; it doesn't mean\n> that the underlying OS does.","ref":"socket.html#getopt/2"},{"type":"function","title":"socket.getopt/3","doc":"Get a socket option _(backwards compatibility function)_.\n\nEquivalent to [`getopt(Socket, {Level, Opt})`](`getopt/2`),\nor as a special case if\n`Opt = {NativeOpt :: `[`integer/0`](`t:integer/0`)`, ValueSpec}`\nequivalent to\n[`getopt_native(Socket, {Level, NativeOpt}, ValueSpec)`](`getopt_native/3`).\n\nUse `getopt/2` or `getopt_native/3` instead to handle\nthe option level and name as a single term, and to make the\ndifference between known options and native options clear.","ref":"socket.html#getopt/3"},{"type":"function","title":"socket.getopt_native/3","doc":"Get a \"native\" socket option.\n\nGets a socket option that may be unknown to our implementation, or that has a\ntype not compatible with our implementation, that is; in \"native mode\".\n\nThe socket option may be specified with an ordinary\n[`socket_option()` ](`t:socket_option/0`) tuple, with a known\n[`Level = level()` ](`t:level/0`) and an integer `NativeOpt`,\nor with both an integer `NativeLevel` and `NativeOpt`.\n\nHow to decode the option value has to be specified either with `ValueType`,\nby specifying the `ValueSize` for a `t:binary/0` that will contain the fetched\noption value, or by specifying a `t:binary/0` `ValueSpec` that will be copied\nto a buffer for the `getsockopt()` call to write the value in which will be\nreturned as a new `t:binary/0`.\n\nIf `ValueType` is `integer` a `C` type `(int)` will be fetched, if it is\n`boolean` a `C` type `(int)` will be fetched and converted into a `t:boolean/0`\naccording to the `C` implementation's notion about true and false.\n\nIf an option is valid depends both on the platform and on\nwhat kind of socket it is (`t:domain/0`, `t:type/0` and `t:protocol/0`).\n\nThe integer values for `NativeLevel` and `NativeOpt` as well as the `Value`\nencoding has to be deduced from the header files for the running system.","ref":"socket.html#getopt_native/3"},{"type":"function","title":"socket.i/0","doc":"Print information to the erlang shell in table format\nfor all sockets.\n\nThe information printed for each socket is specified by the default set\nof `t:info_keys/0` (all keys).\n\nThe sockets that are printed are all sockets created by this\n`socket` module's implementation.","ref":"socket.html#i/0"},{"type":"function","title":"socket.i/1","doc":"Print information to the erlang shell in table format\nfor all sockets.\n\nIf the argument is a list of `t:info_keys/0`, print the specified\ninformation for all sockets. See `i/0`.\n\nOtherwise the same as `i/2` with the same first argument\nand the default information (see `i/0`).","ref":"socket.html#i/1"},{"type":"function","title":"socket.i/2","doc":"Print information to the erlang shell in table format\nfor a selection of sockets.\n\nThe argument [`InfoKeys`](`t:info_keys/0`) specifies which information\nis printed for each socket.\n\nIf the first argument is `Domain` print information for\nall sockets of that specific `t:domain/0`.\n\nIf the first argument is `Proto` print information for\nall sockets of that specific `t:protocol/0`.\n\nIf the first argument is `Type` print information for\nall sockets of that specific `t:type/0`.","ref":"socket.html#i/2"},{"type":"function","title":"socket.info/0","doc":"Get miscellaneous information about this `socket` library.\n\nThe function returns a map with each information item as a key-value pair.\n\n> #### Note {: .info }\n>\n> In order to ensure data integrity, mutexes are taken when needed.\n> So, don't call this function often.","ref":"socket.html#info/0"},{"type":"function","title":"socket.info/1","doc":"Get miscellaneous info about a socket.\n\nThe function returns a map with each information item as a key-value pair\nreflecting the \"current\" state of the socket.\n\n> #### Note {: .info }\n>\n> In order to ensure data integrity, mutexes are taken when needed.\n> So, don't call this function often.","ref":"socket.html#info/1"},{"type":"function","title":"socket.ioctl/2","doc":"Set socket (device) parameters.\n\nThis function retrieves a specific parameter, according to\nthe `GetRequest` argument.\n\n- **`gifconf`** - Get a list of interface (transport layer) addresses.\n\n Result; a list of `t:map/0`s, one for each interface,\n with its name and address.\n\n- **`nread`** - Get the number of bytes immediately available for reading\n *(since OTP 26.1)*.\n\n Result; the number of bytes, `t:integer/0`.\n\n- **`nwrite`** - Get the number of bytes in the send queue\n *(since OTP 26.1)*.\n\n Result; the number of bytes, `t:integer/0`.\n\n- **`nspace`** - Get the free space in the send queue\n *(since OTP 26.1)*.\n\n Result; the number of bytes, `t:integer/0`.\n\n- **`atmark`** - Test if there is OOB (out-of-bound) data waiting to be read\n *(since OTP 26.1)*.\n\n Result; a `t:boolean/0`.\n\n- **`tcp_info`** - Get miscellaneous TCP related information for a\n _connected_ socket *(since OTP 26.1)*.\n\n Result; a `t:map/0` with information items as key-value pairs.\n\n> #### Note {: .info }\n>\n> Not all requests are supported by all platforms.\n> To see if a ioctl request is supported on the current platform:\n>\n> ```erlang\n> \t Request = nread,\n> \t true = socket:is_supported(ioctl_requests, Request),\n> \t :\n> ```","ref":"socket.html#ioctl/2"},{"type":"function","title":"socket.ioctl/3","doc":"Get or set socket (device) parameters.\n\n[](){: #ioctl-get }\n\nThis function retrieves a specific parameter, according to\none of the following `GetRequest` arguments. The third argument is\nthe (lookup) \"key\", identifying the interface, for most requests\nthe name of the interface as a `t:string/0`.\nAlso, see the note above.\n\n- **`gifname`** - Get the name of the interface with the specified index\n (`t:integer/0`).\n\n Result; the name of the interface, `t:string/0`.\n\n- **`gifindex`** - Get the index of the interface with the specified name.\n\n Result; the interface index, `t:integer/0`.\n\n- **`gifaddr`** - Get the address of the interface with the specified name.\n\n Result; the address of the interface, `t:sockaddr/0`.\n\n- **`gifdstaddr`** - Get the destination address of the point-to-point\n interface with the specified name.\n\n Result; the destination address of the interface, `t:sockaddr/0`.\n\n- **`gifbrdaddr`** - Get the broadcast address of the interface with the\n specified name.\n\n Result; broadcast address of the interface, `t:sockaddr/0`.\n\n- **`gifnetmask`** - Get the network mask of the interface with\n the specified name.\n\n Result; the network mask of the interface, `t:sockaddr/0`.\n\n- **`gifhwaddr` | `genaddr`** - Get the hardware address for the interface with the\n specified name.\n\n Result; the hardware address of the interface, `t:sockaddr/0` | `t:binary/0`.\n The family field contains the 'ARPHRD' device type (or an integer).\n\n- **`gifmtu`** - Get the MTU (Maximum Transfer Unit) for the interface with the\n specified name.\n\n Result; MTU of the interface, `t:integer/0`.\n\n- **`giftxqlen`** - Get the transmit queue length of the interface with the\n specified name.\n\n Result; transmit queue length of the interface, `t:integer/0`.\n\n- **`gifflags`** - Get the active flag word of the interface\n with the specified name.\n\n Result; the active flag word of the interface, is a list of\n `t:ioctl_device_flag/0` `|` `t:integer( )`.\n\n[](){: #ioctl-set }\n\nWith the following `SetRequest` argument this function sets\nthe `Value` for the request parameter *(since OTP 26.1)*.\n\n- **`rcvall`** - Enables (or disables) a socket to receive all IPv4 or IPv6\n packages passing through a network interface.\n\n The `Socket` has to be one of:\n\n - **An IPv4 socket** - Created with the address\n [domain `inet`](`t:domain/0`), socket [type `raw`](`t:type/0`)\n and [protocol `ip`](`t:protocol/0`).\n\n - **An IPv6 socket** - Created with the address\n [domain `inet6`](`t:domain/0`), socket [type `raw`](`t:type/0`)\n and [protocol `ipv6`](`t:protocol/0`).\n\n The socket must also be bound to an (explicit) local IPv4 or IPv6 interface\n (`any` isn't allowed).\n\n Setting this IOCTL requires elevated privileges.\n\nWith the following `SetRequest` arguments this function sets\nthe `Value` for the request parameter *(since OTP 26.1)*.\n\n- **`rcvall_igmpmcall`** - Enables (or disables) a socket to receive IGMP\n multicast IP traffic, _without_ receiving any other IP traffic.\n\n The socket has to be created with the address\n [domain `inet`](`t:domain/0`), socket [type `raw`](`t:type/0`)\n and [protocol `igmp`](`t:protocol/0`).\n\n The socket must also be bound to an (explicit) local interface\n (`any` isn't allowed).\n\n The receive buffer must be sufficiently large.\n\n Setting this IOCTL requires elevated privileges.\n\n- **`rcvall_mcall`** - Enables (or disables) a socket to receive all multicast\n IP traffic (as in; all IP packets destined for IP addresses in the range\n 224.0.0.0 to 239.255.255.255).\n\n The socket has to be created with the address\n [domain `inet`](`t:domain/0`), socket [type `raw`](`t:type/0`)\n and [protocol `udp`](`t:protocol/0`).\n\n The socket must also be bound to an (explicit) local interface\n (`any` isn't allowed), And bound to port `0`.\n\n The receive buffer must be sufficiently large.\n\n Setting this IOCTL requires elevated privileges.","ref":"socket.html#ioctl/3"},{"type":"function","title":"socket.ioctl/4","doc":"Set socket (device) parameters.\n\nThis function sets a specific parameter, according to the `SetRequest`\nargument. The `Name` argument is the name of the interface,\nand the `Value` argument is the value to set.\n\nThese operations require elevated privileges.\n\n- **`sifflags`** - Set the the active flag word, `#{Flag => boolean()}`, of the\n interface with the specified name.\n\n Each flag to be changed should be added to the value `t:map/0`,\n with the value `true` if the `Flag` should be set and `false`\n if the flag should be cleared.\n\n- **`sifaddr`** - Set the address, `t:sockaddr/0`, of the interface with the\n specified name.\n\n- **`sifdstaddr`** - Set the destination address, `t:sockaddr/0`, of a\n point-to-point interface with the specified name.\n\n- **`sifbrdaddr`** - Set the broadcast address, `t:sockaddr/0`,\nof the interface with the specified name.\n\n- **`sifnetmask`** - Set the network mask, `t:sockaddr/0`, of the interface\n with the specified name.\n\n- **`sifhwaddr`** - Set the hardware address, `t:sockaddr/0`,\nof the interface with the specified name.\n\n- **`sifmtu`** - Set the MTU (Maximum Transfer Unit), `t:integer/0`,\n for the interface with the specified name.\n\n- **`siftxqlen`** - Set the transmit queue length, `t:integer/0`,\n of the interface with the specified name.","ref":"socket.html#ioctl/4"},{"type":"function","title":"socket.is_supported/1","doc":"Check if a socket feature is supported.\n\nReturns `true` if `supports/0` has a `{Key1, true}` tuple\nor a `{Key1, list()}` tuple in its returned list,\notherwise `false` (also for unknown keys).\n\nExample:\n``` erlang\ntrue = socket:is_supported(local),\n```","ref":"socket.html#is_supported/1"},{"type":"function","title":"socket.is_supported/2","doc":"Check if a socket feature is supported.\n\nReturns `true` if [`supports(Key1)`](`supports/1`) has a `{Key2, true}` tuple\nin its returned list, otherwise `false` (also for unknown keys).\n\nExample:\n``` erlang\ntrue = socket:is_supported(msg_flags, errqueue),\n```","ref":"socket.html#is_supported/2"},{"type":"function","title":"socket.listen/1","doc":"Make a socket listen for connections.\n\nEquivalent to [`listen(Socket, Backlog)`](`listen/2`) with a default\nvalue for `Backlog` (currently `5`).","ref":"socket.html#listen/1"},{"type":"function","title":"socket.listen/2","doc":"Make a socket listen for connections.\n\nThe `Backlog` argument states the length of the queue for\nincoming not yet accepted connections.\nExactly how that number is interpreted is up to the OS'\nprotocol stack, but the resulting effective queue length\nwill most probably be perceived as at least that long.\n\n> #### Note {: .info }\n>\n> On _Windows_ the socket has to be _bound_.","ref":"socket.html#listen/2"},{"type":"function","title":"socket.monitor/1","doc":"Start a socket monitor.\n\nIf the `Socket` doesn't exist or when later the monitor is triggered,\na `'DOWN'` message is sent to the process that called `monitor/1`\nwith the following pattern:\n\n``` erlang\n\t {'DOWN', MonitorRef, socket, Socket, Info}\n```\n`Info` is the termination reason of the socket or `nosock` if\n`Socket` did not exist when the monitor was started.\n\nMaking several calls to `socket:monitor/1` for the same `Socket` is not an\nerror; each call creates an independent monitor instance.","ref":"socket.html#monitor/1"},{"type":"function","title":"socket.number_of/0","doc":"Return the number of active sockets.","ref":"socket.html#number_of/0"},{"type":"function","title":"socket.open/1","doc":"Equivalent to [`open(FD, #{})`](`open/2`).","ref":"socket.html#open/1"},{"type":"function","title":"socket.open/2","doc":"Create a socket.\n\n#### With arguments `Domain` and `Type`\n\nEquivalent to [`open(Domain, Type, default, #{})`](`open/4`).\n\n#### With arguments `FD` and `Opts` *(since OTP 23.0)*\n\nCreates an endpoint for communication (socket) based on\nan already existing file descriptor that must be a socket.\nThis function attempts to retrieve the file descriptor's\n`domain`, `type` and `protocol` from the system.\nThis is however not possible on all platforms;\nin that case they should be specified in `Opts`.\n\nThe `Opts` argument can provide extra information:\n\n- **`domain`** - The file descriptor's communication domain. See also\n\n [`open/2,3,4`](`open/3`).\n\n- **`type`** - The file descriptor's socket type.\n\n See also [`open/2,3,4`](`open/3`).\n\n- **`protocol`** - The file descriptor's protocol. The atom `default` is\n equivalent to the integer protocol number `0` which means the default\n protocol for a given domain and type.\n\n If the protocol can not be retrieved from the platform for the socket, and\n `protocol` is not specified, the default protocol is used, which may\n or may not be correct.\n\n See also [`open/2,3,4`](`open/3`).\n\n- **`dup`** - If `false` don't duplicate the provided file descriptor.\n\n Defaults to `true`; do duplicate the file descriptor.\n\n- **`debug`** - If `true` enable socket debug logging.\n\n Defaults to `false`; don't enable socket debug logging.\n\n- **`use_registry`** - Enable or disable use of the socket registry\n for this socket. This overrides the global setting.\n\n Defaults to the global setting, see `use_registry/1`.\n\n> #### Note {: .info }\n>\n> This function should be used with care\\!\n>\n> On some platforms it is _necessary_ to provide `domain`, `type` and `protocol`\n> since they cannot be retrieved from the platform.\n>\n> On some platforms it is not easy to get hold of a file descriptor\n> to use in this function.","ref":"socket.html#open/2"},{"type":"function","title":"socket.open/3","doc":"Create a socket.\n\n#### With arguments `Domain`, `Type` and `Protocol`\n\nEquivalent to [`open(Domain, Type, Protocol, #{})`](`open/4`).\n\n#### With arguments `Domain`, `Type` and `Opts` *(since OTP 24.0)*\n\nEquivalent to [`open(Domain, Type, default, #{})`](`open/4`).","ref":"socket.html#open/3"},{"type":"function","title":"socket.open/4","doc":"Create a socket.\n\nCreates an endpoint for communication (socket).\n\n`Domain` and `Type` may be `t:integer/0`s, as defined in the platform's\nheader files. The same goes for `Protocol` as defined in the platform's\n`services(5)` database. See also the OS man page for the library call\n`socket(2)`.\n\n> #### Note {: .info }\n>\n> For some combinations of `Domain` and `Type` the platform has got\n> a default protocol that can be selected with `Protocol = default`,\n> and the platform may allow or require selecting the default protocol,\n> or a specific protocol.\n>\n> Examples:\n>\n> - **`socket:open(inet, stream, tcp)`** - It is common that for\n> protocol domain and type `inet,stream` it is allowed to select\n> the `tcp` protocol although that mostly is the default.\n> - **`socket:open(local, dgram)`** - It is common that for\n> the protocol domain `local` it is mandatory to not select a protocol,\n> that is; to select the default protocol.\n\nThe `Opts` argument is intended for \"other\" options.\nThe supported option(s) are described below:\n\n- **`netns: string()`** - Used to set the network namespace during the open\n call. Only supported on Linux.\n\n- **`debug: boolean()`** - Enable or disable debug logging.\n\n Defaults to `false`.\n\n- **`use_registry: boolean()`** - Enable or disable use of the socket registry\n for this socket. This overrides the global value.\n\n Defaults to the global value, see `use_registry/1`.","ref":"socket.html#open/4"},{"type":"function","title":"socket.peername/1","doc":"Return the remote address of a socket.\n\nReturns the address of the connected peer, that is,\nthe remote end of the socket.","ref":"socket.html#peername/1"},{"type":"function","title":"socket.recv/1","doc":"Equivalent to [`recv(Socket, 0, [], infinity)`](`recv/4`).","ref":"socket.html#recv/1"},{"type":"function","title":"socket.recv/2","doc":"Receive data on a connected socket.\n\nWith argument `Length`; equivalent to\n[`recv(Socket, Length, [], infinity)`](`recv/4`).\n\nWith argument `Flags`; equivalent to\n[`recv(Socket, 0, Flags, infinity)`](`recv/4`) *(since OTP 24.0)*.","ref":"socket.html#recv/2"},{"type":"function","title":"socket.recv/3","doc":"Receive data on a connected socket.\n\nWith arguments `Length` and `Flags`; equivalent to\n[`recv(Socket, Length, Flags, infinity)`](`recv/4`).\n\nWith arguments `Length` and `TimeoutOrHandle`; equivalent to\n[`recv(Socket, Length, [], TimeoutOrHandle)`](`recv/4`).\n`TimeoutOrHandle :: nowait` has been allowed *since OTP 22.1*.\n`TimeoutOrHandle :: Handle` has been allowed *since OTP 24.0*.\n\nWith arguments `Flags` and `TimeoutOrHandle`; equivalent to\n[`recv(Socket, 0, Flags, TimeoutOrHandle)`](`recv/4`)\n*(since OTP 24.0)*.","ref":"socket.html#recv/3"},{"type":"function","title":"socket.recv/4","doc":"Receive data on a connected socket.\n\nThe argument `Length` specifies how many bytes to receive,\nwith the special case `0` meaning \"all available\".\n\nWhen `Length` is `0`, a default buffer size is used, which can be set by\n[`socket:setopt(Socket, {otp,recvbuf}, BufSz)`](`setopt/3`).\n\nThe message `Flags` may be symbolic `t:msg_flag/0`s and/or\n`t:integer/0`s as in the platform's appropriate header files.\nThe values of all symbolic flags and integers are or:ed together.\n\nWhen there is a socket error this function returns `{error, Reason}`,\nor if some data arrived before the error; `{error, {Reason, Data}}`\n(can only happen for a socket of [type `stream`](`t:type/0`)).\n\n[](){: #recv-infinity }\n\nIf the `Timeout` argument is `infinity`; waits for the data to arrive.\nFor a socket of [type `stream`](`t:type/0`) this call\nwon't return until _all_ requested data can be delivered,\nor if \"all available\" was requested when the first data chunk arrives,\nor if the OS reports an error for the operation.\n\n[](){: #recv-timeout }\n\nIf the `Timeout` argument is a time-out value\n(`t:non_neg_integer/0`); return `{error, timeout}`\nif no data has arrived after `Timeout` milliseconds,\nor `{error, {timeout, Data}}` if some but not enough data\nhas been received on a socket of [type `stream`](`t:type/0`).\n\n`Timeout = 0` only polls the OS receive call and doesn't\nengage the Asynchronous Calls mechanisms. If no data\nis immediately available `{error, timeout} is returned.\n`On a socket of type [`stream`](`t:type/0`), `{error, {timeout, Data}}`\nis returned if there is an insufficient amount of data immediately available.\n\n[](){: #recv-nowait }\n\nIf the `Handle` argument is `nowait` *(since OTP 22.1)*,\nstarts an [asynchronous call](#asynchronous-calls) if the operation\ncouldn't be completed immediately.\n\nIf the `Handle` argument is a `t:select_handle/0`,\n*(since OTP 24.0)*, or on _Windows_, the equivalent\n`t:completion_handle/0` *(since OTP 26.0)*, starts\nan [asynchronous call](#asynchronous-calls) like for `nowait`.\n\nSee the note [Asynchronous Calls](#asynchronous-calls)\nat the start of this module reference manual page.\n\nOn `select` systems, for a socket of type [`stream`](`t:type/0`),\nif `Length > 0` and there isn't enough data available, this function\nwill return [`{select, {SelectInfo, Data}}`](`t:select_info/0`)\nwith partial `Data`. A repeated call to complete the operation\nwill probably need an updated `Length` argument.","ref":"socket.html#recv/4"},{"type":"function","title":"socket.recvfrom/1","doc":"Equivalent to [`recvfrom(Socket, 0, [], infinity)`](`recvfrom/4`).","ref":"socket.html#recvfrom/1"},{"type":"function","title":"socket.recvfrom/2","doc":"Receive a message on a socket.\n\nWith argument `BufSz`; equivalent to\n[`recvfrom(Socket, BufSz, [], infinity)`](`recvfrom/4`).\n\nWith argument `Flags`; equivalent to\n[`recvfrom(Socket, 0, Flags, infinity)`](`recvfrom/4`) *(since OTP 24.0)*.","ref":"socket.html#recvfrom/2"},{"type":"function","title":"socket.recvfrom/3","doc":"Receive a message on a socket.\n\nWith arguments `BufSz` and `Flags`; equivalent to\n[`recvfrom(Socket, BufSz, Flags, infinity)`](`recvfrom/4`).\n\nWith arguments `BufSz` and `TimeoutOrHandle`; equivalent to\n[`recv(Socket, BufSz, [], TimeoutOrHandle)`](`recvfrom/4`).\n\nWith arguments `Flags` and `TimeoutOrHandle`; equivalent to\n[`recv(Socket, 0, Flags, TimeoutOrHandle)`](`recvfrom/4`)\n\n`TimeoutOrHandle :: 'nowait'` has been allowed *since OTP 22.1*.\n\n`TimeoutOrHandle :: Handle` has been allowed *since OTP 24.0*.","ref":"socket.html#recvfrom/3"},{"type":"function","title":"socket.recvfrom/4","doc":"Receive a message on a socket.\n\nThis function is intended for sockets that are not connection\noriented such as type [`dgram`](`t:type/0`) or [`seqpacket`](`t:type/0`)\nwhere it may arrive messages from different source addresses.\n\nArgument `BufSz` specifies the number of bytes for the receive buffer.\nIf the buffer size is too small, the message will be truncated.\n\nIf `BufSz` is `0`, a default buffer size is used, which can be set by\n[`socket:setopt(Socket, {otp,recvbuf}, BufSz)`](`setopt/3`).\n\nIf there is no known appropriate buffer size, it may be possible\nto use the receive [message flag](`t:msg_flag/0`) `peek`.\nWhen this flag is used, the message is _not_ \"consumed\" from\nthe underlying buffers, so another `recvfrom/1,2,3,4` call\nis needed, possibly with an adjusted buffer size.\n\nThe message `Flags` may be symbolic `t:msg_flag/0`s and/or\n`t:integer/0`s, as in the platform's appropriate header files.\nThe values of all symbolic flags and integers are or:ed together.\n\n[](){: #recvfrom-infinity }\n\nIf the `Timeout` argument is `infinity`; waits for a message\nto arrive, or for a socket error.\n\n[](){: #recvfrom-timeout }\n\nIf the `Timeout` argument is a time-out value\n(`t:non_neg_integer/0`); returns `{error, timeout}`\nif no message has arrived after `Timeout` milliseconds.\n\n`Timeout = 0` only polls the OS receive call and doesn't\nengage the Asynchronous Calls mechanisms. If no message\nis immediately available `{error, timeout}` is returned.\n\n[](){: #recvfrom-nowait }\n\nIf the `Handle` argument is `nowait` *(since OTP 22.1)*,\nstarts an [asynchronous call](#asynchronous-calls) if the operation\ncouldn't be completed immediately.\n\nIf the 'Handle' argument is a `t:select_handle/0`,\n*(since OTP 24.0)*, or on _Windows_, the equivalent\n`t:completion_handle/0` *(since OTP 26.0)*,\nstarts an [asynchronous call](#asynchronous-calls) like for `nowait`.\n\nSee the note [Asynchronous Calls](#asynchronous-calls)\nat the start of this module reference manual page.","ref":"socket.html#recvfrom/4"},{"type":"function","title":"socket.recvmsg/1","doc":"Equivalent to [`recvmsg(Socket, 0, 0, [], infinity)`](`recvmsg/5`).","ref":"socket.html#recvmsg/1"},{"type":"function","title":"socket.recvmsg/2","doc":"Receive a message on a socket.\n\nWith argument `Flags`; equivalent to\n[`recvmsg(Socket, 0, 0, Flags, infinity)`](`recvmsg/5`).\n\nWith argument `TimeoutOrHandle`; equivalent to\n[`recvmsg(Socket, 0, 0, [], TimeoutOrHandle)`](`recvmsg/5`).\n\n`TimeoutOrHandle :: nowait` has been allowed *since OTP 22.1*.\n\n`TimeoutOrHandle :: Handle` has been allowed *since OTP 24.0*.","ref":"socket.html#recvmsg/2"},{"type":"function","title":"socket.recvmsg/3","doc":"Receive a message on a socket.\n\nWith arguments `Flags`; equivalent to\n[`recvmsg(Socket, 0, 0, Flags, infinity)`](`recvmsg/5`).\n\nWith argument `TimeoutOrHandle`; equivalent to\n[`recvmsg(Socket, 0, 0, [], TimeoutOrHandle)`](`recvmsg/5`).\n\n`TimeoutOrHandle :: nowait` has been allowed *since OTP 22.1*.\n\n`TimeoutOrHandle :: Handle` has been allowed *since OTP 24.0*.","ref":"socket.html#recvmsg/3"},{"type":"function","title":"socket.recvmsg/4","doc":"Equivalent to\n[`recvmsg(Socket, BufSz, CtrlSz, [], TimeoutOrHandle)`](`recvmsg/5`).","ref":"socket.html#recvmsg/4"},{"type":"function","title":"socket.recvmsg/5","doc":"Receive a message on a socket.\n\nThis function receives both data and control messages.\n\nArguments `BufSz` and `CtrlSz` specifies the number of bytes for the\nreceive buffer and the control message buffer. If the buffer size(s)\nis(are) too small, the message and/or control message list will be truncated.\n\nIf `BufSz` is `0`, a default buffer size is used, which can be set by\n[`socket:setopt(Socket, {otp,recvbuf}, BufSz)`](`setopt/3`).\nThe same applies to `CtrlSz` and\n[`socket:setopt(Socket, {otp,recvctrlbuf}, CtrlSz)`](`setopt/3`).\n\nIf there is no known appropriate buffer size, it may be possible\nto use the receive [message flag](`t:msg_flag/0`) `peek`.\nWhen this flag is used, the message is _not_ \"consumed\" from\nthe underlying buffers, so another `recvfrom/1,2,3,4` call\nis needed, possibly with an adjusted buffer size.\n\nThe message `Flags` may be symbolic `t:msg_flag/0`s and/or\n`t:integer/0`s, as in the platform's appropriate header files.\nThe values of all symbolic flags and integers are or:ed together.\n\n[](){: #recvmsg-infinity }\n\nIf the `Timeout` argument is `infinity`; waits for the message\nto arrive, or for a socket error.\n\n[](){: #recvmsg-timeout }\n\nIf the `Timeout` argument is a time-out value\n(`t:non_neg_integer/0`); return `{error, timeout}`\nif no message has arrived after `Timeout` milliseconds.\n\n`Timeout = 0` only polls the OS receive call and doesn't\nengage the Asynchronous Calls mechanisms. If no message\nis immediately available `{error, timeout}` is returned.\n\n[](){: #recvmsg-nowait }\n\nIf the `Handle` argument is `nowait` *(since OTP 22.1)*,\nstarts an [asynchronous call](#asynchronous-calls) if the operation\ncouldn't be completed immediately.\n\nIf the 'Handle' argument is a `t:select_handle/0`,\n*(since OTP 24.0)*, or on _Windows_, the equivalent\n`t:completion_handle/0` *(since OTP 26.0)*,\nstarts an [asynchronous call](#asynchronous-calls) like for `nowait`.\n\nSee the note [Asynchronous Calls](#asynchronous-calls)\nat the start of this module reference manual page.","ref":"socket.html#recvmsg/5"},{"type":"function","title":"socket.send/2","doc":"Equivalent to [`send(Socket, Data, [], infinity)`](`send/4`).","ref":"socket.html#send/2"},{"type":"function","title":"socket.send/3","doc":"Send data on a connected socket.\n\nWith argument `Timeout`; equivalent to\n[`send(Socket, Data, [], Timeout)`](`send/4`).\n\nWith argument `Flags`; equivalent to\n[`send(Socket, Data, Flags, infinity)`](`send/4`).\n\nWith argument `Cont`; equivalent to\n[`send(Socket, Data, Cont, infinity)`](`send/4`) *(since OTP 24.0)*.","ref":"socket.html#send/3"},{"type":"function","title":"socket.send/4","doc":"Send data on a connected socket.\n\nThe message `Flags` may be symbolic `t:msg_flag/0`s and/or\n`t:integer/0`s as in the platform's appropriate header files.\nThe values of all symbolic flags and integers are or:ed together.\n\nThe `Data`, if it is not a `t:binary/0`, is copied into one before\ncalling the platform network API, because a single buffer is required.\nA returned `RestData` is a sub binary of it.\n\nThe return value indicates the result from the platform's network layer:\n\n- **`ok`** - All data was accepted by the OS for delivery\n\n- **`{ok, RestData}`** - Some but not all data was accepted,\n but no error was reported (partially successful send). `RestData`\n is the tail of `Data` that wasn't accepted.\n\n This cannot happen for a socket of [type `stream`](`t:type/0`) where\n such a partially successful send is retried until the data is either\n accepted for delivery or there is an error.\n\n For a socket of [type `dgram`](`t:type/0`) this should probably\n also not happen since a message that cannot be passed atomically\n should render an error.\n\n It is nevertheless possible for the platform's network layer\n to return this, surely more possible for a socket of\n [type `seqpacket`](`t:type/0`).\n\n- **`{error, Reason}`** - An error has been reported and no data\n was accepted for delivery. [`Reason :: posix/0`](`t:posix/0`)\n is what the platform's network layer reported. `closed` means\n that this socket library was informed that the socket was closed,\n and `t:invalid/0` means that this socket library found\n an argument to be invalid.\n\n- **`{error, {Reason, RestData}}`** - An error was reported but before that\n some data was accepted for delivery. `RestData` is the tail of `Data`\n that wasn't accepted. See `{error, Reason}` above.\n\n This can only happen for a socket of [type `stream`](`t:type/0`)\n when a partially successful send is retried until there is an error.\n\n[](){: #send-infinity }\n\nIf the `Timeout` argument is `infinity`; wait for the OS to\ncomplete the send operation (take responsibility for the data),\nor return an error.\n\n[](){: #send-timeout }\n\nIf the `Timeout` argument is a time-out value\n(`t:non_neg_integer/0`); return `{error, timeout}`\nif no data has been sent within `Timeout` millisecond,\nor `{error, {timeout, RestData}}` if some data was sent\n(accepted by the OS for delivery). `RestData` is the tail of the data\nthat hasn't been sent.\n\n[](){: #send-nowait }\n\nIf the `Handle` argument is `nowait` *(since OTP 22.1)*,\nstarts an [asynchronous call](#asynchronous-calls) if the operation\ncouldn't be completed immediately.\n\nIf the `Handle` argument is a `t:select_handle/0`,\n*(since OTP 24.0)*, or on _Windows_, the equivalent\n`t:completion_handle/0` *(since OTP 26.0)*, starts\nan [asynchronous call](#asynchronous-calls) like for `nowait`.\n\nSee the note [Asynchronous Calls](#asynchronous-calls)\nat the start of this module reference manual page.\n\n[](){: #send-cont }\n\nIf the function is called with a `Cont` argument, that is;\nthe [`SelectInfo`](`t:select_info/0`) from the previous\n[`send/3,4`](`send/3`) call; the send is continued with\npreprocessed send parameters in the `SelectInfo`.\nUsing this argument variant avoids for example having to validate\nand encode message flags in every call but the first.","ref":"socket.html#send/4"},{"type":"function","title":"socket.sendfile/2","doc":"Send a file on a socket.\n\nEquivalent to\n[`sendfile(Socket, FileHandle_or_Continuation, 0, 0, infinity)`](`sendfile/5`).","ref":"socket.html#sendfile/2"},{"type":"function","title":"socket.sendfile/3","doc":"Send a file on a socket.\n\nEquivalent to\n[`sendfile(Socket, FileHandle_or_Continuation, 0, 0, Timeout_or_Handle)`](`sendfile/5`).","ref":"socket.html#sendfile/3"},{"type":"function","title":"socket.sendfile/4","doc":"Send a file on a socket.\n\nEquivalent to\n[`sendfile(Socket, FileHandle_or_Continuation, Offset, Count, infinity)`](`sendfile/5`).","ref":"socket.html#sendfile/4"},{"type":"function","title":"socket.sendfile/5","doc":"Send a file on a socket.\n\n> #### Note {: .info }\n> This function unsupported on Windows.\n\nThe `FileHandle` argument must refer to an open raw file\nas described in `file:open/2`.\n\nThe `Offset` argument is the file offset to start reading from.\nThe default offset is `0`.\n\nThe `Count` argument is the number of bytes to transfer\nfrom `FileHandle` to `Socket`. If `Count = 0` (the default)\nthe transfer stops at the end of file.\n\nThe return value indicates the result from the platform's network layer:\n\n- **`{ok, BytesSent}`** - The transfer completed successfully after `BytesSent`\n bytes of data.\n\n- **`{error, Reason}`** - An error has been reported and no data\n was transferred. [`Reason :: posix/0`](`t:posix/0`)\n is what the platform's network layer reported. `closed` means\n that this socket library was informed that the socket was closed,\n and `t:invalid/0` means that this socket library found\n an argument to be invalid.\n\n- **`{error, {Reason, BytesSent}}`** - An error has been reported\n but before that some data was transferred. See `{error, Reason}`\n and `{ok, BytesSent}` above.\n\n[](){: #sendfile-infinity }\n\nIf the `Timeout` argument is `infinity`; wait for the OS to\ncomplete the send operation (take responsibility for the data),\nor return an error.\n\n[](){: #sendfile-timeout }\n\nIf the `Timeout` argument is a time-out value\n(`t:non_neg_integer/0`); return `{error, timeout}`\nif no data has been sent within `Timeout` millisecond,\nor `{error, {timeout, BytesSent}}` if some but not all data was sent\n(accepted by the OS for delivery).\n\n[](){: #sendfile-nowait }\n\nIf the `Handle` argument is `nowait`,\nstarts an [asynchronous call](#asynchronous-calls) if the operation\ncouldn't be completed immediately.\n\nIf the `Handle` argument is a `t:select_handle/0`, starts\nan [asynchronous call](#asynchronous-calls) like for `nowait`.\n\nSee the note [Asynchronous Calls](#asynchronous-calls)\nat the start of this module reference manual page.\n\nAfter receiving a `select` message call [`sendfile/2,3,4,5`](`sendfile/2`)\nwith `SelectInfo` as the `Continuation` argument, to complete the operation.\n\n[](){: #sendfile-cont }\n\nIf the function is called with a `Continuation` argument, that is;\nthe [`SelectInfo`](`t:select_info/0`) from the previous\n`sendfile/5` call; the transfer is continued with\npreprocessed parameters in the `SelectInfo`.\n\nThe `Offset` and maybe `Count` arguments will probably\nneed to be updated between continuation calls.","ref":"socket.html#sendfile/5"},{"type":"function","title":"socket.sendmsg/2","doc":"Equivalent to [`sendmsg(Socket, Msg, [], infinity)`](`sendmsg/4`).","ref":"socket.html#sendmsg/2"},{"type":"function","title":"socket.sendmsg/3","doc":"Send data and control messages on a socket.\n\nWith arguments `Msg` and `Timeout`; equivalent to\n[`sendmsg(Socket, Msg, [], Timeout)`](`sendmsg/4`).\n\nWith arguments `Msg` and `Flags`; equivalent to\n[`sendmsg(Socket, Msg, Flags, infinity)`](`sendmsg/4`).\n\nWith arguments `Data` and `Cont`; equivalent to\n[`sendmsg(Socket, Data, Cont, infinity)`](`sendmsg/4`) *since OTP 24.0*.","ref":"socket.html#sendmsg/3"},{"type":"function","title":"socket.sendmsg/4","doc":"Send data and control messages on a socket.\n\nThe argument `Msg` is a map that contains the data to be sent\nunder the key `iov` as an`t:erlang:iovec/0` (list of `t:binary/0`).\nIt may also contain the destination address under the key `addr`,\nwhich is mandatory if the socket isn't connected. If the socket\n_is_ connected it is best to not have an `addr` key since\nthe platform may regard that as an error (or ignore it).\nUnder the key `ctrl` there may be a list of protocol and platform dependent\ncontrol messages (a.k.a ancillary data, a.k.a control information)\nto send.\n\n[](){: #sendmsg-iov }\n\nThe message data is given to the platform's network layer as an\nI/O vector without copying the content. If the number of elements\nin the I/O vector is larger than allowed on the platform (reported\nin the [`iov_max`](`t:info/0`) field from `info/0`), on a socket of\n[type `stream`](`t:type/0`) the send is iterated over all elements,\nbut for other socket types the call fails.\n\nSee `send/4` for a description of the `Flags` argument\nand the return values.\n\n> #### Note {: .info }\n>\n> On Windows, this function can only be used with datagram and raw sockets.\n\n[](){: #sendmsg-infinity }\n\nIf the `Timeout` argument is `infinity`; wait for the OS to\ncomplete the send operation (take responsibility for the data),\nor return an error.\n\n[](){: #sendmsg-timeout }\n\nIf the `Timeout` argument is a time-out value\n(`t:non_neg_integer/0`); return `{error, timeout}`\nif no data has been sent within `Timeout` millisecond,\nor `{error, {timeout, RestData}}` if some data was sent\n(accepted by the OS for delivery). `RestData` is the tail of the data\nthat hasn't been sent.\n\n[](){: #sendmsg-nowait }\n\nIf the `Handle` argument is `nowait` *(since OTP 22.1)*,\nstarts an [asynchronous call](#asynchronous-calls) if the operation\ncouldn't be completed immediately.\n\nIf the `Handle` argument is a `t:select_handle/0`,\n*(since OTP 24.0)*, or on _Windows_, the equivalent\n`t:completion_handle/0` *(since OTP 26.0)*, starts\nan [asynchronous call](#asynchronous-calls) like for `nowait`.\n\nSee the note [Asynchronous Calls](#asynchronous-calls)\nat the start of this module reference manual page.\n\nAfter receiving a `select` message call [`sendmsg/3,4`](`sendmsg/3`)\nwith `SelectInfo` as the `Cont` argument, to complete the operation.\n\n[](){: #sendmsg-cont }\n\nWith the arguments `Data` and [`Cont`](`t:select_info/0`),\ncontinues the send operation. `Cont` should be\nthe [`SelectInfo`](`t:select_info/0`) returned from the previous\n[`sendmsg/2,3,4`](`sendmsg/2`) call.\n\n`Data` can be a [`Msg`](`t:msg_send/0`) `t:map/0`\nwhere only the key `iov` is used, or an `t:erlang:iovec/0`.","ref":"socket.html#sendmsg/4"},{"type":"function","title":"socket.sendto/3","doc":"Send data on a socket.\n\nWith argument `Dest`; equivalent to\n[`sendto(Socket, Data, Dest, [], infinity)`](`sendto/5`).\n\nWith argument `Cont`; equivalent to\n[`sendto(Socket, Data, Cont, infinity)`](`sendto/4`) *since OTP 24.0*.","ref":"socket.html#sendto/3"},{"type":"function","title":"socket.sendto/4","doc":"Send data on a socket.\n\nWith arguments `Dest` and `TimeoutOrHandle`; equivalent to\n[`sendto(Socket, Data, Dest, [], TimeoutOrHandle)`](`sendto/5`).\n\nWith arguments `Dest` and `Flags`; equivalent to\n[`sendto(Socket, Data, Dest, Flags, infinity)`](`sendto/5`).\n\nWith arguments `Cont` and `TimeoutOrHandle`; `Cont` must be\nthe [`SelectInfo`](`t:select_info/0`) from the previous\n[`sendto/3,4,5`](`sendto/3`) call and the send is continued with\npreprocessed send parameters in the `SelectInfo`.\nUsing this argument variant avoids for example having o validate\nand encode message flags in every call but the first.\n*(Since OTP 24.0)*\n\nSee the last argument (argument 5) of `sendto/5` for\nan explanation of `TimeoutOrHandle`.","ref":"socket.html#sendto/4"},{"type":"function","title":"socket.sendto/5","doc":"Send data on a socket.\n\nThe `To` argument is the destination address where to send the data.\nFor a connected socket this argument is still passed to the OS call\nthat may ignore the address or return an error.\n\nSee `send/4` for a description of the `Flags` and `Data` arguments,\nand the return values.\n\n[](){: #sendto-infinity }\n\nIf the `Timeout` argument is `infinity`; wait for the OS to\ncomplete the send operation (take responsibility for the data),\nor return an error.\n\n[](){: #sendto-timeout }\n\nIf the `Timeout` argument is a time-out value\n(`t:non_neg_integer/0`); return `{error, timeout}`\nif no data has been sent within `Timeout` millisecond,\nor `{error, {timeout, RestData}}` if some data was sent\n(accepted by the OS for delivery). `RestData` is the tail of the data\nthat hasn't been sent.\n\n[](){: #sendto-nowait }\n\nIf the `Handle` argument is `nowait` *(since OTP 22.1)*,\nstarts an [asynchronous call](#asynchronous-calls) if the operation\ncouldn't be completed immediately.\n\nIf the `Handle` argument is a `t:select_handle/0`,\n*(since OTP 24.0)*, or on _Windows_, the equivalent\n`t:completion_handle/0` *(since OTP 26.0)*, starts\nan [asynchronous call](#asynchronous-calls) like for `nowait`.\n\nSee the note [Asynchronous Calls](#asynchronous-calls)\nat the start of this module reference manual page.\n\nAfter receiving a `select` message call [`sendto/3,4`](`sendto/3`)\nwith `SelectInfo` as the `Cont` argument, to complete the operation.","ref":"socket.html#sendto/5"},{"type":"function","title":"socket.sendv/2","doc":"","ref":"socket.html#sendv/2"},{"type":"function","title":"socket.sendv/3","doc":"Send `t:erlang:iovec/0` data on a connected socket.\n\nSee [`sendmsg/4`](#sendmsg-iov) about how the [`IOV`](`t:erlang:iovec/0`)\ndata is handled towards the platform's network layer.\n\nThe return value indicates the result from the platform's network layer:\n\n- **`ok`** - All data has been accepted by the OS for delivery.\n\n- **`{ok, RestIOV}`** - Some but not all data was accepted,\n but no error was reported (partially successful send). `RestIOV`\n is the tail of `IOV` that wasn't accepted.\n\n- **`{error, Reason}`** - An error has been reported and no data\n was accepted for delivery. [`Reason :: posix/0`](`t:posix/0`)\n is what the platform's network layer reported. `closed` means\n that this socket library was informed that the socket was closed,\n and `t:invalid/0` means that this socket library found\n an argument to be invalid.\n\n- **`{error, {Reason, RestIOV}}`** - - An error was reported but before that\n some data was accepted for delivery. `RestIOV` is the tail of `IOV`\n that wasn't accepted. See `{error, Reason}` above.\n\n[](){: #sendv-infinity }\n\nIf the `Timeout` argument is `infinity`; wait for the OS to\ncomplete the send operation (take responsibility for the data),\nor return an error.\n\n[](){: #sendv-timeout }\n\nIf the `Timeout` argument is a time-out value\n(`t:non_neg_integer/0`); return `{error, timeout}`\nif no data has been sent within `Timeout` millisecond,\nor `{error, {timeout, RestIOV}}` if some data was sent\n(accepted by the OS for delivery). `RestIOV` is the tail of the data\nthat hasn't been sent.\n\n[](){: #sendv-nowait }\n\nIf the `Handle` argument is `nowait`,\nstarts an [asynchronous call](#asynchronous-calls) if the operation\ncouldn't be completed immediately.\n\nIf the `Handle` argument is a `t:select_handle/0`,\nor on _Windows_, the equivalent `t:completion_handle/0`, starts\nan [asynchronous call](#asynchronous-calls) like for `nowait`.\n\nSee the note [Asynchronous Calls](#asynchronous-calls)\nat the start of this module reference manual page.\n\n[](){: #sendv-cont }\n\nWith the argument [`Cont`](`t:select_info/0`), equivalent to\n[`sendv(Socket, IOV, Cont, infinity)`](`sendv/4`).","ref":"socket.html#sendv/3"},{"type":"function","title":"socket.sendv/4","doc":"Send data on a connected socket, continuation.\n\nContinues sending data on a connected socket.\n`Cont` is the [`SelectInfo`](`t:select_info/0`) returned from\nthe previous [`sendv/2,3`](`sendv/2`) call.\n`IOV` should be the rest data that wasn't sent.\n\nSee [asynchronous calls](#asynchronous-calls) about continuing\nunfinished calls.\n\nSee `sendv/3` about the return values.","ref":"socket.html#sendv/4"},{"type":"function","title":"socket.setopt/3","doc":"Set a socket option.\n\nSet an OS protocol level option, or an `otp` pseudo protocol level option.\nThe latter level is this module's implementation level above\nthe OS protocol levels.\n\nSee the type [otp_socket_option() ](`t:otp_socket_option/0`)\nfor a description of the `otp` protocol level.\n\nSee the type `t:socket_option/0` for which OS protocol level options\nthat this implementation knows about, how they are related to OS option names,\nand if there are known peculiarities with any of them.\n\nWhat options that are valid depends on the OS, and on the kind of socket\n(`t:domain/0`,`t:type/0` and `t:protocol/0`). See the type\n`t:socket_option()` and the\n[socket options ](socket_usage.md#socket_options) chapter\nin the User's Guide for more info.\n\n> #### Note {: .info }\n>\n> Not all options are valid, nor possible to set, on all platforms. That is,\n> even if this `socket` implementation support an option; it doesn't mean\n> that the underlying OS does.","ref":"socket.html#setopt/3"},{"type":"function","title":"socket.setopt/4","doc":"Set a socket option _(backwards compatibility function)_.\n\nEquivalent to [`setopt(Socket, {Level, Opt}, Value)`](`setopt/3`),\nor as a special case if `Opt = NativeOpt ::` `t:integer/0`\nand `Value =` `t:binary/0` equivalent to\n[`setopt_native(Socket, {Level, NativeOpt}, ValueSpec)`](`setopt_native/3`).\n\nUse `setopt/3` or `setopt_native/3` instead to handle\nthe option level and name as a single term, and to make the\ndifference between known options and native options clear.","ref":"socket.html#setopt/4"},{"type":"function","title":"socket.setopt_native/3","doc":"Set a \"native\" socket option.\n\nSets a socket option that may be unknown to our implementation, or that has a\ntype not compatible with our implementation, that is; in \"native mode\".\n\nIf `Value` is an `t:integer/0` it will be used as a `C` type `(int)`,\nif it is a `t:boolean/0` it will be used as a `C` type `(int)`\nwith the `C` implementations values for `false` or `true`,\nand if it is a `t:binary/0` its content and size will be used\nas the option value.\n\nThe socket option may be specified with an ordinary\n`t:socket_option/0` tuple, with a symbolic `Level` as\n`{`[`Level :: level/0`](`t:level/0`)`, `[`NativeOpt :: integer/0`](`t:integer/0`)`}`,\nor with integers for both `NativeLevel` and `NativeOpt` as\n`{`[`NativeLevel :: integer/0`](`t:integer/0`)`, `[`NativeOpt :: integer/0`](`t:integer/0`)`}`.\n\nIf an option is valid depends both on the platform and on\nwhat kind of socket it is (`t:domain/0`, `t:type/0` and `t:protocol/0`).\n\nThe integer values for `NativeLevel` and `NativeOpt` as well as the `Value`\nencoding has to be deduced from the header files for the running system.","ref":"socket.html#setopt_native/3"},{"type":"function","title":"socket.shutdown/2","doc":"Shut down all or part of a full-duplex connection.","ref":"socket.html#shutdown/2"},{"type":"function","title":"socket.sockname/1","doc":"Get the socket's address.\n\nReturns the address to which the socket is currently bound.\nIf the bind address had the wildcard port `0`,\nthe address returned by this function contains the ephemeral port\nselected by the OS.","ref":"socket.html#sockname/1"},{"type":"function","title":"socket.supports/0","doc":"Retrieve information about what socket features\nthe module and the platform supports.\n\nReturns a list of, in no particular order,\n`{Key1, `[`supports(Key1)`](`supports/1`)`}` tuples\nfor every `Key1` described in `supports/1`,\nand `{Key, boolean()}` tuples for each of the following keys:\n\n- **`sctp`** - SCTP support\n\n- **`ipv6`** - IPv6 support\n\n- **`local`** - Unix Domain sockets support (`AF_UNIX | AF_LOCAL`)\n\n- **`netns`** - Network Namespaces support (Linux, `setns(2)`)\n\n- **`sendfile`** - Sendfile support (`sendfile(2)`)","ref":"socket.html#supports/0"},{"type":"function","title":"socket.supports/1","doc":"Retrieve information about what socket features\nthe module and the platform supports.\n\nIf `Key1 = msg_flags` returns a list of `{Flag, boolean()}`\ntuples for every `Flag` in `t:msg_flag/0` with the `t:boolean/0`\nindicating if the flag is supported on this platform.\n\nIf `Key1 = protocols` returns a list of `{Name, boolean()}`\ntuples for every `Name` in`t:protocol/0` with the `t:boolean/0`\nindicating if the protocol is supported on this platform.\n\nIf `Key1 = options` returns a list of `{SocketOption, boolean()}`\ntuples for every `SocketOption` in `t:socket_option/0` with the `t:boolean/0`\nindicating if the socket option is supported on this platform.\n\nThere is no particular order of any of the returned lists.\n\nFor other values of `Key1` returns `[]`.\nNote that in future versions of this module or on different platforms,\nthere might be more supported keys.","ref":"socket.html#supports/1"},{"type":"function","title":"socket.supports/2","doc":"Retrieve information about what socket features\nthe module and the platform supports.\n\nIf `Key1 = options`, for a `Key2` in `t:level/0` returns\na list of `{Opt, boolean()}` tuples for all known socket options\n[`Opt` on that `Level = Key2`](`t:socket_option/0`) with the `t:boolean/0`\nindicating if the socket option is supported on this platform.\nSee `setopt/3` and `getopt/2`.\n\nThere is no particular order of any of the returned lists.\n\nFor other values of `Key1` or `Key2` returns `[]`.\nNote that in future versions of this module or on different platforms,\nthere might be more supported keys.","ref":"socket.html#supports/2"},{"type":"function","title":"socket.use_registry/1","doc":"Set the global [`use_registry`](`t:otp_socket_option/0`)\noption default value.\n\nGlobally change if the socket registry is to be used or not.\nNote that its still possible to override this explicitly\nwhen creating an individual sockets, see [`open/2,3,4`](`open/2`)\nfor more info (the [`Opts :: map/0`](`t:map/0`)).","ref":"socket.html#use_registry/1"},{"type":"function","title":"socket.which_sockets/0","doc":"Return a list of all known sockets.\n\nEquivalent to [`which_sockets(fun (_) -> true end)`](`which_sockets/1`).","ref":"socket.html#which_sockets/0"},{"type":"function","title":"socket.which_sockets/1","doc":"Return a filtered list of known sockets.\n\nThere are several predefined `FilterRule`s and one general:\n\n- **`inet | inet6`** - Only the sockets with matching `t:domain/0`\n are returned.\n\n- **`stream | dgram | seqpacket`** - Only the sockets with\n matching `t:type/0` are returned.\n\n- **`sctp | tcp | udp`** - Only the sockets with\n matching `t:protocol/0` are returned.\n\n- **`t:pid/0`** - Only the sockets with matching Controlling Process\n are returned. See the OTP socket option\n [`controlling_process`](`t:otp_socket_option/0`).\n\n- **`fun((socket_info()) -> boolean())`** - The general filter rule.\n A fun that takes the socket info and returns a `t:boolean/0`\n indicating if the socket should be returned or not.","ref":"socket.html#which_sockets/1"},{"type":"type","title":"socket.cmsg/0","doc":"Control messages (ancillary messages).","ref":"socket.html#t:cmsg/0"},{"type":"type","title":"socket.cmsg_recv/0","doc":"Control messages (ancillary messages) returned by\n[`recvmsg/1,2,3,5`](`recvmsg/1`).\n\nA control message has got a `data` field with a native (`binary`) value for the\nmessage data, and may also have a decoded `value` field if this socket library\nsuccessfully decoded the data.","ref":"socket.html#t:cmsg_recv/0"},{"type":"type","title":"socket.cmsg_send/0","doc":"Control messages (ancillary messages) accepted by\n[`sendmsg/2,3,4`](`sendmsg/2`).\n\nA control message may for some message types have a `value` field with a\nsymbolic value, or a `data` field with a native value, that has to be binary\ncompatible what is defined in the platform's header files.","ref":"socket.html#t:cmsg_send/0"},{"type":"type","title":"socket.completion_handle/0","doc":"[Completion operation](#asynchronous-calls) handle.\n\nA `t:reference/0` that uniquely identifies the (completion) operation,\ncontained in the returned `t:completion_info/0`.","ref":"socket.html#t:completion_handle/0"},{"type":"type","title":"socket.completion_info/0","doc":"[Completion operation](#asynchronous-calls) info.\n\nReturned by an operation that requires the caller to wait for a\n[completion message](`m:socket#asynchronous-calls`) containing the\n[`CompletionHandle`](`t:completion_handle/0`) _and_ the result of the operation;\nthe `CompletionStatus`.","ref":"socket.html#t:completion_info/0"},{"type":"type","title":"socket.completion_tag/0","doc":"[Completion operation](#asynchronous-calls) tag.\n\n\nA tag that describes the ongoing (completion) operation (= function name),\ncontained in the returned `t:completion_info/0`.","ref":"socket.html#t:completion_tag/0"},{"type":"type","title":"socket.domain/0","doc":"Protocol _domain_ a.k.a address _family_.\n\nA lowercase `t:atom/0` representing a protocol _domain_\non the platform named `AF_*` (or `PF_*`). For example\n`inet` corresponds to `AF_INET`.\n\n[`is_supported(ipv6)` ](`is_supported/1`) tells if the IPv6 protocol,\nprotocol domain `inet6`, is supported.\n\n[`is_supported(local)` ](`is_supported/1`) tells if the\nprotocol domain `local` is supported.\n\n`supports/0` reports both values, but also many more, with a single call.","ref":"socket.html#t:domain/0"},{"type":"type","title":"socket.ee_origin/0","doc":"","ref":"socket.html#t:ee_origin/0"},{"type":"type","title":"socket.eei/0","doc":"Extended Error Information.\n\nA term containing additional (error) information\n_if_ the socket NIF has been configured to produce it.","ref":"socket.html#t:eei/0"},{"type":"type","title":"socket.extended_err/0","doc":"","ref":"socket.html#t:extended_err/0"},{"type":"type","title":"socket.hatype/0","doc":"","ref":"socket.html#t:hatype/0"},{"type":"type","title":"socket.icmp_dest_unreach/0","doc":"","ref":"socket.html#t:icmp_dest_unreach/0"},{"type":"type","title":"socket.icmpv6_dest_unreach/0","doc":"","ref":"socket.html#t:icmpv6_dest_unreach/0"},{"type":"type","title":"socket.in6_addr/0","doc":"","ref":"socket.html#t:in6_addr/0"},{"type":"type","title":"socket.in6_flow_info/0","doc":"","ref":"socket.html#t:in6_flow_info/0"},{"type":"type","title":"socket.in6_scope_id/0","doc":"","ref":"socket.html#t:in6_scope_id/0"},{"type":"type","title":"socket.in_addr/0","doc":"","ref":"socket.html#t:in_addr/0"},{"type":"type","title":"socket.info/0","doc":"Platform dependent information items.\n\nThe value of `iov_max` is the value of the `IOV_MAX` constant\nin the system headers, which is the largest allowed I/O vector.\nSee also `sendmsg/4` regarding the `iov` key of `t:msg_send/0`.\nThe smallest allowed `IOV_MAX` value according to POSIX is `16`,\nbut check your platform documentation to be sure.\n\nAbout the `use_registry` key, see `use_registry/1`\nand the `t:otp_socket_option/0` with the same name.","ref":"socket.html#t:info/0"},{"type":"type","title":"socket.info_keys/0","doc":"Information element designators for the `i/1` and `i/2` functions.","ref":"socket.html#t:info_keys/0"},{"type":"type","title":"socket.interface_type/0","doc":"The interface type (of the datalink). We only translate a few values to atoms,\nthe rest are left as (unsigned) integer values.","ref":"socket.html#t:interface_type/0"},{"type":"type","title":"socket.invalid/0","doc":"","ref":"socket.html#t:invalid/0"},{"type":"type","title":"socket.ioctl_device_flag/0","doc":"","ref":"socket.html#t:ioctl_device_flag/0"},{"type":"type","title":"socket.ioctl_device_map/0","doc":"","ref":"socket.html#t:ioctl_device_map/0"},{"type":"type","title":"socket.ip_mreq/0","doc":"C: `struct ip_mreq`\n\nCorresponds to the C `struct ip_mreq` for managing multicast groups.","ref":"socket.html#t:ip_mreq/0"},{"type":"type","title":"socket.ip_mreq_source/0","doc":"C: `struct ip_mreq_source`\n\nCorresponds to the C `struct ip_mreq_source` for managing multicast groups.","ref":"socket.html#t:ip_mreq_source/0"},{"type":"type","title":"socket.ip_msfilter/0","doc":"C: `struct ip_msfilter`\n\nCorresponds to the C `struct ip_msfilter` for managing\nmulticast source filtering (RFC 3376).","ref":"socket.html#t:ip_msfilter/0"},{"type":"type","title":"socket.ip_pktinfo/0","doc":"C: `struct ip_pktinfo`","ref":"socket.html#t:ip_pktinfo/0"},{"type":"type","title":"socket.ip_pmtudisc/0","doc":"C: `IP_PMTUDISC_*` values.\n\nLowercase `t:atom/0` values corresponding to the C library constants\n`IP_PMTUDISC_*`. Some constant(s) may be unsupported by the platform.","ref":"socket.html#t:ip_pmtudisc/0"},{"type":"type","title":"socket.ip_tos/0","doc":"C: `IPTOS_*` values.\n\nLowercase `t:atom/0` values corresponding to the C library constants `IPTOS_*`.\nSome constant(s) may be unsupported by the platform.","ref":"socket.html#t:ip_tos/0"},{"type":"type","title":"socket.ipv6_hops/0","doc":"IPv6 hop limit value.\n\nThe value `default` is only valid to _set_ and is translated to the C value\n`-1`, meaning the route default.","ref":"socket.html#t:ipv6_hops/0"},{"type":"type","title":"socket.ipv6_mreq/0","doc":"C: `struct ipv6_mreq`\n\nCorresponds to the C `struct ipv6_mreq` for managing multicast groups. See also\nRFC 2553.","ref":"socket.html#t:ipv6_mreq/0"},{"type":"type","title":"socket.ipv6_pktinfo/0","doc":"C: `struct in6_pktinfo`","ref":"socket.html#t:ipv6_pktinfo/0"},{"type":"type","title":"socket.ipv6_pmtudisc/0","doc":"C: `IPV6_PMTUDISC_*` values\n\nLowercase `t:atom/0` values corresponding to the C library constants\n`IPV6_PMTUDISC_*`. Some constant(s) may be unsupported by the platform.","ref":"socket.html#t:ipv6_pmtudisc/0"},{"type":"type","title":"socket.level/0","doc":"Protocol level.\n\nA lowercase `t:atom/0` OS protocol level, that is:\n`socket` or a `t:protocol/0` name.\n\n`socket` is the `SOL_SOCKET` protocol level in the OS header files,\nwith options named `SO_`\\* .","ref":"socket.html#t:level/0"},{"type":"type","title":"socket.linger/0","doc":"C: `struct linger`\n\nCorresponds to the C `struct linger` for managing the\n[socket option](`t:socket_option/0`) `{socket, linger}`.","ref":"socket.html#t:linger/0"},{"type":"type","title":"socket.msg/0","doc":"C: `struct msghdr`","ref":"socket.html#t:msg/0"},{"type":"type","title":"socket.msg_flag/0","doc":"Platform dependent message flags.\n\nTranslates to/from message flag constants on the platform.\nThese flags are lowercase while the constants are uppercase\nwith prefix `MSG_`; for example `oob` translates to `MSG_OOB`.\n\nSome flags are only used for sending, some only for receiving, some in received\ncontrol messages, and some for several of these. Not all flags are supported on\nall platforms. See the platform's documentation,\n[`supports(msg_flags)`](`supports/1`), and\n[`is_supported(msg_flags, MsgFlag)`](`is_supported/2`).","ref":"socket.html#t:msg_flag/0"},{"type":"type","title":"socket.msg_recv/0","doc":"Message returned by [`recvmsg/1,2,3,5`](`recvmsg/1`).\n\nCorresponds to a C `struct msghdr`, see your platform documentation for\n[`recvmsg(2)`](`recvmsg/1`).\n\n- **`addr`** - Optional peer address, used on unconnected sockets. Corresponds\n to `msg_name` and `msg_namelen` fields of a `struct msghdr`. If `NULL` the map\n key is not present.\n\n- **`iov`** - Data as a list of binaries. The `msg_iov` and `msg_iovlen` fields\n of a `struct msghdr`.\n\n- **`ctrl`** - A possibly empty list of control messages (CMSG). Corresponds to\n the `msg_control` and `msg_controllen` fields of a `struct msghdr`.\n\n- **`flags`** - Message flags. Corresponds to the `msg_flags` field of a\n `struct msghdr`. Unknown flags, if any, are returned in one `t:integer/0`,\n last in the containing list.","ref":"socket.html#t:msg_recv/0"},{"type":"type","title":"socket.msg_send/0","doc":"Message sent by [`sendmsg/2,3,4`](`sendmsg/2`).\n\nCorresponds to a C `struct msghdr`, see your platform documentation for\n`sendmsg(2)`.\n\n- **`addr`** - Optional peer address, used on unconnected sockets. Corresponds\n to `msg_name` and `msg_namelen` fields of a `struct msghdr`. If not used they\n are set to `NULL`, `0`.\n\n- **`iov`** - Mandatory data as a list of binaries. The `msg_iov` and\n `msg_iovlen` fields of a `struct msghdr`.\n\n- **`ctrl`** - Optional list of control messages (CMSG). Corresponds to the\n `msg_control` and `msg_controllen` fields of a `struct msghdr`. If not used\n they are set to `NULL`, `0`.\n\nThe `msg_flags` field of the `struct msghdr` is set to `0`.","ref":"socket.html#t:msg_send/0"},{"type":"type","title":"socket.native_value/0","doc":"","ref":"socket.html#t:native_value/0"},{"type":"type","title":"socket.otp_socket_option/0","doc":"Protocol level `otp` socket option.\n\nSocket options for the `otp` pseudo protocol level,\nthat is: `{otp, Name}` options.\n\nThis protocol level is the Erlang/OTP's socket implementation layer,\nhence above all OS protocol levels.\n\n- **`debug`** - `t:boolean/0` \\- Activate debug logging.\n\n- **`iow`** - `t:boolean/0` \\- Inform On Wrap of statistics counters.\n\n- **`controlling_process`** - `t:pid/0` \\- The socket \"owner\". Only the current\n controlling process can set this option.\n\n- **`rcvbuf`** -\n `BufSize :: (default | integer()>0) | {N :: integer()>0, BufSize :: (default | integer()>0)} `\\-\n Receive buffer size.\n\n The value `default` is only valid to _set_.\n\n `N` specifies the number of read attempts to do in a tight loop before\n assuming no more data is pending.\n\n This is the allocation size for the receive buffer used when calling the OS\n protocol stack's receive API, when no specific size (size 0) is requested.\n When the receive function returns the receive buffer is reallocated to the\n actually received size. If the data is copied or shrunk in place is up to\n the allocator, and can to some extent be configured in the Erlang VM.\n\n The similar socket option; `{socket,rcvbuf}` is a related option for the OS'\n protocol stack that on Unix corresponds to `SOL_SOCKET,SO_RCVBUF`.\n\n- **`rcvctrlbuf`** - `BufSize :: (default | integer()>0) `\\- Allocation size for\n the ancillary data buffer used when calling the OS protocol stack's receive\n API.\n\n The value `default` is only valid to _set_.\n\n- **`sndctrlbuf`** - `BufSize :: (default | integer()>0) `\\- Allocation size for\n the ancillary data buffer used when calling the OS protocol stack's\n [sendmsg](`sendmsg/2`) API.\n\n The value `default` is only valid to _set_.\n\n It is the user's responsibility to set a buffer size that has room for the\n encoded ancillary data in the message to send.\n\n See [sendmsg](`sendmsg/2`) and also the `ctrl` field of the `t:msg_send/0`\n type.\n\n- **`fd`** - `t:integer/0` \\- Only valid to _get_. The OS protocol levels'\n socket descriptor. Functions [`open/1,2`](`open/1`) can be used to create a\n socket according to this module from an existing OS socket descriptor.\n\n- **`use_registry`** - `t:boolean/0` \\- Only valid to _get_. The value is set\n when the socket is created with `open/2` or `open/4`.\n\nOptions not described here are intentionally undocumented and for Erlang/OTP\ninternal use only.","ref":"socket.html#t:otp_socket_option/0"},{"type":"type","title":"socket.packet_type/0","doc":"","ref":"socket.html#t:packet_type/0"},{"type":"type","title":"socket.port_number/0","doc":"","ref":"socket.html#t:port_number/0"},{"type":"type","title":"socket.posix/0","doc":"Posix error codes.\n\nLocal alias for `t:inet:posix/0`, a set of `t:atom/0`s.","ref":"socket.html#t:posix/0"},{"type":"type","title":"socket.protocol/0","doc":"Protocol name.\n\nA lowercase `t:atom/0` representing an OS protocol name.\nTo be used for example in `t:socket_option/0`\nin [control messages](`t:cmsg/0`).\n\nThey have the following names in the OS header files:\n\n- **`ip`** - `IPPROTO_IP` a.k.a `SOL_IP` with options named `IP_`\\*.\n\n- **`ipv6`** - `IPPROTO_IPV6` a.k.a `SOL_IPV6` with options named `IPV6_`\\*.\n\n- **`tcp`** - `IPPROTO_TCP` with options named `TCP_`\\*.\n\n- **`udp`** - `IPPROTO_UDP` with options named `UDP_`\\*.\n\n- **`sctp`** - `IPPROTO_SCTP` with options named `SCTP_`\\*.\n\nThere are many other possible protocols, but the ones above are those for which\nthis socket library implements socket options and/or control messages.\n\nAll protocols known to the OS are enumerated when the Erlang VM is started,\nthrough the `C` library call `getprotoent()`. See the OS man page for\nprotocols(5). Those in the list above are valid if supported by the platform,\neven if they aren't enumerated.\n\nThe calls [`is_supported(ipv6)` ](`is_supported/1`)\nand [`is_supported(sctp)` ](`is_supported/1`) can be used to find out\nif the protocols `ipv6` and `sctp` are supported on the platform\nas in appropriate header file and library exists.\n\nThe call [`is_supported(protocols, Protocol)` ](`is_supported/2`)\ncan only be used to find out if the platform knows the protocol number\nfor a named `Protocol`.\n\nSee [`open/2,3,4`](`open/3`)","ref":"socket.html#t:protocol/0"},{"type":"type","title":"socket.sctp_assocparams/0","doc":"C: `struct sctp_assocparams`","ref":"socket.html#t:sctp_assocparams/0"},{"type":"type","title":"socket.sctp_event_subscribe/0","doc":"C: `struct sctp_event_subscribe`.\n\nNot all fields are implemented on all platforms; unimplemented fields are\nignored, but implemented fields are mandatory. Note that the '\\_event' suffixes\nhave been stripped from the C struct field names, for convenience.","ref":"socket.html#t:sctp_event_subscribe/0"},{"type":"type","title":"socket.sctp_initmsg/0","doc":"C: `struct sctp_initmsg`.","ref":"socket.html#t:sctp_initmsg/0"},{"type":"type","title":"socket.sctp_rtoinfo/0","doc":"C: `struct sctp_rtoinfo`.","ref":"socket.html#t:sctp_rtoinfo/0"},{"type":"type","title":"socket.select_handle/0","doc":"[Select operation](#asynchronous-calls) handle.\n\nA `t:reference/0` that uniquely identifies the (select) operation,\ncontained in the returned `t:select_info/0`.","ref":"socket.html#t:select_handle/0"},{"type":"type","title":"socket.select_info/0","doc":"[Select operation](#asynchronous-calls) info.\n\nReturned by an operation that requires the caller to wait for a\n[select message](`m:socket#asynchronous-calls`) containing the\n[`SelectHandle`](`t:select_handle/0`).","ref":"socket.html#t:select_info/0"},{"type":"type","title":"socket.select_tag/0","doc":"[Select operation](#asynchronous-calls) tag.\n\nA tag that describes the (select) operation (= function name),\ncontained in the returned `t:select_info/0`.","ref":"socket.html#t:select_tag/0"},{"type":"type","title":"socket.sockaddr/0","doc":"","ref":"socket.html#t:sockaddr/0"},{"type":"type","title":"socket.sockaddr_dl/0","doc":"C: `struct sockaddr_dl`\n\nLink level address (PF_LINK) on BSD:s.","ref":"socket.html#t:sockaddr_dl/0"},{"type":"type","title":"socket.sockaddr_in6/0","doc":"C: `struct sockaddr_in6`\n\n[Domain `inet6`](`t:domain/0`) (IPv6) address.","ref":"socket.html#t:sockaddr_in6/0"},{"type":"type","title":"socket.sockaddr_in/0","doc":"C: `struct sockaddr_in`\n\n[Domain `inet`](`t:domain/0`) (IPv4) address.","ref":"socket.html#t:sockaddr_in/0"},{"type":"type","title":"socket.sockaddr_ll/0","doc":"C: `struct sockaddr_ll`\n\n[Domain `packet`](`t:domain/0`), [type `raw`](`t:type/0`)\n(link level) address.","ref":"socket.html#t:sockaddr_ll/0"},{"type":"type","title":"socket.sockaddr_native/0","doc":"C: `struct sockaddr`\n\nIn C, a `struct sockaddr` with the integer value of `sa_family`\nin the `t:map/0` key `family`,\nand the content of `sa_data` in the `t:map/0` key `addr`.","ref":"socket.html#t:sockaddr_native/0"},{"type":"type","title":"socket.sockaddr_recv/0","doc":"","ref":"socket.html#t:sockaddr_recv/0"},{"type":"type","title":"socket.sockaddr_un/0","doc":"C: `struct sockaddr_un`.\n\nA Unix Domain socket address, a.k.a local address (`AF_LOCAL`).\n\nThe `path` element will always be a `binary` when returned from this module.\nWhen supplied to an API function in this module it may be a `t:string/0`, which\nwill be encoded into a binary according to the\n[native file name encoding ](`file:native_name_encoding/0`)on the platform.\n\nA terminating zero character will be appended before the address path is given\nto the OS, and the terminating zero will be stripped before giving the address\npath to the caller.\n\nLinux's non-portable abstract socket address extension is handled by not doing\nany terminating zero processing in either direction, if the first byte of the\naddress is zero.","ref":"socket.html#t:sockaddr_un/0"},{"type":"type","title":"socket.sockaddr_unspec/0","doc":"C: `struct sockaddr` of `AF_UNSPEC`\n\nIn C, a `struct sockaddr` with `sa_family = AF_UNSPEC`\nand the content of `sa_data` in the `t:map/0` key `addr`.","ref":"socket.html#t:sockaddr_unspec/0"},{"type":"type","title":"socket.socket/0","doc":"A socket, according to this module.\n\nCreated and returned by [`open/1,2,3,4`](`open/1`)\nand [`accept/1,2`](`accept/1`).","ref":"socket.html#t:socket/0"},{"type":"type","title":"socket.socket_counters/0","doc":"A `t:map/0` of `Name := Counter` associations.","ref":"socket.html#t:socket_counters/0"},{"type":"opaque","title":"socket.socket_handle/0","doc":"Opaque socket handle unique for the socket.","ref":"socket.html#t:socket_handle/0"},{"type":"type","title":"socket.socket_info/0","doc":"","ref":"socket.html#t:socket_info/0"},{"type":"type","title":"socket.socket_option/0","doc":"Socket option.\n\nSocket options on the form `{Level, Opt}` where the OS protocol `Level` =\n`t:level/0` and `Opt` is a socket option on that protocol level.\n\nThe OS name for an options is, except where otherwise noted, the `Opt` atom, in\ncapitals, with prefix according to `t:level/0`.\n\n> #### Note {: .info }\n>\n> The `IPv6` option `pktoptions` is a special (barf) case. It is intended for\n> backward compatibility usage only.\n>\n> Do _not_ use this option.\n\n> #### Note {: .info }\n>\n> See the OS documentation for every socket option.\n\nAn option below that has the value type `t:boolean/0` will translate the value\n`false` to a C `int` with value `0`, and the value `true` to `!!0` (not (not\nfalse)).\n\nAn option with value type `t:integer/0` will be translated to a C `int` that may\nhave a restricted range, for example byte: `0..255`. See the OS documentation.\n\nThe calls [`supports(options)`](`supports/1`),\n[`supports(options, Level)`](`supports/1`) and\n[`is_supported(options, {Level, Opt})` ](`is_supported/2`)can be used to find\nout which socket options that are supported by the platform.\n\n_Options for protocol level_ [_`socket`_:](`t:level/0`)\n\n- **`{socket, acceptconn}`** - `Value = boolean()`\n\n- **`{socket, bindtodevice}`** - `Value = string()`\n\n- **`{socket, broadcast}`** - `Value = boolean()`\n\n- **`{socket, debug}`** - `Value = integer()`\n\n- **`{socket, domain}`** - `Value =` `t:domain/0`\n\n Only valid to _get_.\n\n The socket's protocol domain. Does _not_ work on for instance FreeBSD.\n\n- **`{socket, dontroute}`** - `Value = boolean()`\n\n- **`{socket, keepalive}`** - `Value = boolean()`\n\n- **`{socket, linger}`** - `Value = abort |` `t:linger/0`\n\n The value `abort` is shorthand for `#{onoff => true, linger => 0}`, and only\n valid to _set_.\n\n- **`{socket, oobinline}`** - `Value = boolean()`\n\n- **`{socket, passcred}`** - `Value = boolean()`\n\n- **`{socket, peek_off}`** - `Value = integer()`\n\n Currently disabled due to a possible infinite loop when calling\n [`recv/1-4`](`recv/1`) with [`peek`](`t:msg_flag/0`) in `Flags`.\n\n- **`{socket, priority}`** - `Value = integer()`\n\n- **`{socket, protocol}`** - `Value =` `t:protocol/0`\n\n Only valid to _get_.\n\n The socket's protocol. Does _not_ work on for instance Darwin.\n\n- **`{socket, rcvbuf}`** - `Value = integer()`\n\n- **`{socket, rcvlowat}`** - `Value = integer()`\n\n- **`{socket, rcvtimeo}`** - `Value =` `t:timeval/0`\n\n This option is unsupported per default; OTP has to be explicitly built with\n the `--enable-esock-rcvsndtimeo` configure option for this to be available.\n\n Since our implementation uses non-blocking sockets, it is unknown if and how\n this option works, or even if it may cause malfunction. Therefore, we do not\n recommend setting this option.\n\n Instead, use the `Timeout` argument to, for instance, the `recv/3` function.\n\n- **`{socket, reuseaddr}`** - `Value = boolean()`\n\n- **`{socket, reuseport}`** - `Value = boolean()`\n\n- **`{socket, sndbuf}`** - `Value = integer()`\n\n- **`{socket, sndlowat}`** - `Value = integer()`\n\n- **`{socket, sndtimeo}`** - `Value =` `t:timeval/0`\n\n This option is unsupported per default; OTP has to be explicitly built with\n the `--enable-esock-rcvsndtimeo` configure option for this to be available.\n\n Since our implementation uses non-blocking sockets, it is unknown if and how\n this option works, or even if it may cause malfunction. Therefore, we do not\n recommend setting this option.\n\n Instead, use the `Timeout` argument to, for instance, the `send/3` function.\n\n- **`{socket, timestamp}`** - `Value = boolean()`\n\n- **`{socket, type}`** - `Value =` `t:type/0`\n\n Only valid to _get_.\n\n The socket's type.\n\n_Options for protocol level_ [_`ip`_:](`t:level/0`)\n\n- **`{ip, add_membership}`** - `Value =` `t:ip_mreq/0`\n\n Only valid to _set_.\n\n- **`{ip, add_source_membership}`** - `Value =` `t:ip_mreq_source/0`\n\n Only valid to _set_.\n\n- **`{ip, block_source}`** - `Value =` `t:ip_mreq_source/0`\n\n Only valid to _set_.\n\n- **`{ip, drop_membership}`** - `Value =` `t:ip_mreq/0`\n\n Only valid to _set_.\n\n- **`{ip, drop_source_membership}`** - `Value =` `t:ip_mreq_source/0`\n\n Only valid to _set_.\n\n- **`{ip, freebind}`** - `Value = boolean()`\n\n- **`{ip, hdrincl}`** - `Value = boolean()`\n\n- **`{ip, minttl}`** - `Value = integer()`\n\n- **`{ip, msfilter}`** - `Value =` `null |` `t:ip_msfilter/0`\n\n Only valid to _set_.\n\n The value `null` passes a `NULL` pointer and size `0` to the C library call.\n\n- **`{ip, mtu}`** - `Value = integer()`\n\n Only valid to _get_.\n\n- **`{ip, mtu_discover}`** - `Value =`\n [`ip_pmtudisc()` ](`t:ip_pmtudisc/0`)`| integer()`\n\n An `t:integer/0` value according to the platform's header files.\n\n- **`{ip, multicast_all}`** - `Value = boolean()`\n\n- **`{ip, multicast_if}`** - `Value =` `any |` `t:in_addr/0`\n\n- **`{ip, multicast_loop}`** - `Value = boolean()`\n\n- **`{ip, multicast_ttl}`** - `Value = integer()`\n\n- **`{ip, nodefrag}`** - `Value = boolean()`\n\n- **`{ip, pktinfo}`** - `Value = boolean()`\n\n- **`{ip, recvdstaddr}`** - `Value = boolean()`\n\n- **`{ip, recverr}`** - `Value = boolean()`\n\n Enable extended reliable error message passing.\n\n _Warning\\!_ When this option is enabled, error messages may arrive on the\n socket's error queue, which should be read using the message flag\n [`errqueue`](`t:msg_flag/0`), and using [`recvmsg/1,2,3,4,5`](`recvmsg/1`) to\n get all error information in the [message's](`t:msg_recv/0`) `ctrl` field as a\n [control message](`t:cmsg_recv/0`) `#{level := ip, type := recverr}`.\n\n A working strategy should be to first poll the error queue using\n [`recvmsg/2,3,4` ](`m:socket#recvmsg-timeout`)with `Timeout =:= 0` and `Flags`\n containing `errqueue` (ignore the return value `{error, timeout}`) before\n reading the actual data to ensure that the error queue gets cleared. And read\n the data using one of the `nowait |`\n [`select_handle()` ](`t:select_handle/0`)recv functions:\n [`recv/3,4`](`m:socket#recv-nowait`),\n [`recvfrom/3,4`](`m:socket#recvfrom-nowait`) or\n [`recvmsg/3,4,5`](`m:socket#recvmsg-nowait`). Otherwise you might accidentally\n cause a busy loop in and out of 'select' for the socket.\n\n- **`{ip, recvif}`** - `Value = boolean()`\n\n- **`{ip, recvopts}`** - `Value = boolean()`\n\n- **`{ip, recvorigdstaddr}`** - `Value = boolean()`\n\n- **`{ip, recvtos}`** - `Value = boolean()`\n\n- **`{ip, recvttl}`** - `Value = boolean()`\n\n- **`{ip, retopts}`** - `Value = boolean()`\n\n- **`{ip, router_alert}`** - `Value = integer()`\n\n- **`{ip, sendsrcaddr}`** - `Value = boolean()`\n\n- **`{ip, tos}`** - `Value =` [`ip_tos()` ](`t:ip_tos/0`)`| integer()`\n\n An `t:integer/0` value is according to the platform's header files.\n\n- **`{ip, transparent}`** - `Value = boolean()`\n\n- **`{ip, ttl}`** - `Value = integer()`\n\n- **`{ip, unblock_source}`** - `Value =` `t:ip_mreq_source/0`\n\n Only valid to _set_.\n\n_Options for protocol level_ [_`ipv6`_:](`t:level/0`)\n\n- **`{ipv6, addrform}`** - `Value =` `t:domain/0`\n\n As far as we know the only valid value is `inet` and it is only allowed for an\n IPv6 socket that is connected and bound to an IPv4-mapped IPv6 address.\n\n- **`{ipv6, add_membership}`** - `Value =` `t:ipv6_mreq/0`\n\n Only valid to _set_.\n\n- **`{ipv6, authhdr}`** - `Value = boolean()`\n\n- **`{ipv6, drop_membership}`** - `Value =` `t:ipv6_mreq/0`\n\n Only valid to _set_.\n\n- **`{ipv6, dstopts}`** - `Value = boolean()`\n\n- **`{ipv6, flowinfo}`** - `Value = boolean()`\n\n- **`{ipv6, hoplimit}`** - `Value = boolean()`\n\n- **`{ipv6, hopopts}`** - `Value = boolean()`\n\n- **`{ipv6, mtu}`** - `Value = integer()`\n\n- **`{ipv6, mtu_discover}`** - `Value =`\n [`ipv6_pmtudisc()` ](`t:ipv6_pmtudisc/0`)`| integer()`\n\n An `t:integer/0` value is according to the platform's header files.\n\n- **`{ipv6, multicast_hops}`** - `Value =` `t:ipv6_hops/0`\n\n- **`{ipv6, multicast_if}`** - `Value = integer()`\n\n- **`{ipv6, multicast_loop}`** - `Value = boolean()`\n\n- **`{ipv6, recverr}`** - `Value = boolean()`\n\n _Warning\\!_ See the socket option `{ip, recverr}` regarding the socket's error\n queue. The same warning applies for this option.\n\n- **`{ipv6, recvhoplimit}`** - `Value = boolean()`\n\n- **`{ipv6, recvpktinfo}`** - `Value = boolean()`\n\n- **`{ipv6, recvtclass}`** - `Value = boolean()`\n\n- **`{ipv6, router_alert}`** - `Value = integer()`\n\n- **`{ipv6, rthdr}`** - `Value = boolean()`\n\n- **`{ipv6, tclass}`** - `Value = boolean()`\n\n- **`{ipv6, unicast_hops}`** - `Value =` `t:ipv6_hops/0`\n\n- **`{ipv6, v6only}`** - `Value = boolean()`\n\n_Options for protocol level_ [_`sctp`_](`t:level/0`). See also RFC 6458.\n\n- **`{sctp, associnfo}`** - `Value =` `t:sctp_assocparams/0`\n\n- **`{sctp, autoclose}`** - `Value = integer()`\n\n- **`{sctp, disable_fragments}`** - `Value = boolean()`\n\n- **`{sctp, events}`** - `Value =` `t:sctp_event_subscribe/0`\n\n Only valid to _set_.\n\n- **`{sctp, initmsg}`** - `Value =` `t:sctp_initmsg/0`\n\n- **`{sctp, maxseg}`** - `Value = integer()`\n\n- **`{sctp, nodelay}`** - `Value = boolean()`\n\n- **`{sctp, rtoinfo}`** - `Value =` `t:sctp_rtoinfo/0`\n\n_Options for protocol level_ [_`tcp`:_](`t:level/0`)\n\n- **`{tcp, congestion}`** - `Value = string()`\n\n- **`{tcp, cork}`** - `Value = boolean()`\n\n- **`{tcp, maxseg}`** - `Value = integer()`\n\n- **`{tcp, nodelay}`** - `Value = boolean()`\n\n_Options for protocol level_ [_`udp`:_](`t:level/0`)\n\n- **`{udp, cork}`** - `Value = boolean()`","ref":"socket.html#t:socket_option/0"},{"type":"type","title":"socket.timeval/0","doc":"C: `struct timeval`\n\nCorresponds to the C `struct timeval`. The field `sec` holds seconds, and `usec`\nmicroseconds.","ref":"socket.html#t:timeval/0"},{"type":"type","title":"socket.type/0","doc":"Protocol type.\n\nA lowercase `t:atom/0` representing a protocol _type_\non the platform named `SOCK_*`. For example\n`stream` corresponds to `SOCK_STREAM`.","ref":"socket.html#t:type/0"},{"type":"module","title":"disk_log","doc":"`disk_log` is a disk-based term logger that enables efficient logging of items\non files.\n\nThree types of logs are supported:\n\n- **halt logs** - Appends items to a single file, which size can be limited by\n the `disk_log` module.\n\n- **wrap logs** - Uses a sequence of wrap log files of limited size. As a wrap\n log file is filled up, further items are logged on to the next file in the\n sequence, starting all over with the first file when the last file is filled\n up.\n\n- **rotate logs** - Uses a sequence of rotate log files of limited size. As a\n log file is filled up, it is rotated and then compressed. There is one active\n log file and upto the configured number of compressed log files. Only\n externally formatted logs are supported. It follows the same naming convention\n as the handler logger_std_h for Logger. For more details about the naming\n convention check the file parameter for `open/1`.\n\n It follows the same naming convention as that for the compressed files for\n Linux's logrotate and BSD's newsyslog.\n\nFor efficiency reasons, items are always written to files as binaries.\n\nTwo formats of the log files are supported:\n\n- **internal format** - Supports automatic repair of log files that are not\n properly closed and enables efficient reading of logged items in _chunks_\n using a set of functions defined in this module. This is the only way to read\n internally formatted logs. An item logged to an internally formatted log must\n not occupy more than 4 GB of disk space (the size must fit in 4 bytes).\n\n- **external format** - Leaves it up to the user to read and interpret the\n logged data. The `disk_log` module cannot repair externally formatted logs.\n\nFor each open disk log, one process handles requests made to the disk log. This\nprocess is created when `open/1` is called, provided there exists no process\nhandling the disk log. A process that opens a disk log can be an _owner_ or an\nanonymous _user_ of the disk log. Each owner is linked to the disk log process,\nand an owner can close the disk log either explicitly (by calling\n[`close/1`](`close/1`)) or by terminating.\n\nOwners can subscribe to _notifications_, messages of the form\n`{disk_log, Node, Log, Info}`, which are sent from the disk log process when\ncertain events occur, see the functions and in particular the\n[`open/1`](`open/1`) option [`notify`](`m:disk_log#notify`). A log can have many\nowners, but a process cannot own a log more than once. However, the same process\ncan open the log as a user more than once.\n\nFor a disk log process to close its file properly and terminate, it must be\nclosed by its owners and once by some non-owner process for each time the log\nwas used anonymously. The users are counted and there must not be any users left\nwhen the disk log process terminates.\n\nItems can be logged _synchronously_ by using functions `log/2`, `blog/2`,\n`log_terms/2`, and `blog_terms/2`. For each of these functions, the caller is\nput on hold until the items are logged (but not necessarily written, use\n[`sync/1`](`sync/1`) to ensure that). By adding an `a` to each of the mentioned\nfunction names, we get functions that log items _asynchronously_. Asynchronous\nfunctions do not wait for the disk log process to write the items to the file,\nbut return the control to the caller more or less immediately.\n\nWhen using the internal format for logs, use functions `log/2`, `log_terms/2`,\n`alog/2`, and `alog_terms/2`. These functions log one or more Erlang terms. By\nprefixing each of the functions with a `b` (for \"binary\"), we get the\ncorresponding `blog()` functions for the external format. These functions log\none or more chunks of bytes. For example, to log the string `\"hello\"` in ASCII\nformat, you can use [`disk_log:blog(Log, \"hello\")`](`blog/2`), or\n[`disk_log:blog(Log, list_to_binary(\"hello\"))`](`blog/2`). The two alternatives\nare equally efficient.\n\nThe `blog()` functions can also be used for internally formatted logs, but in\nthis case they must be called with binaries constructed with calls to\n[`term_to_binary/1`](`erlang:term_to_binary/1`). There is no check to ensure\nthis, it is entirely the responsibility of the caller. If these functions are\ncalled with binaries that do not correspond to Erlang terms, the\n[`chunk/2,3`](`chunk/3`) and automatic repair functions fail. The corresponding\nterms (not the binaries) are returned when [`chunk/2,3`](`chunk/3`) is called.\n\nAn open disk log is only accessible from the node where the disk log process\nruns. All processes on the node where the disk log process runs can log items or\notherwise change, inspect, or close the log.\n\nErrors are reported differently for asynchronous log attempts and other uses of\nthe `m:disk_log` module. When used synchronously, this module replies with an\nerror message, but when called asynchronously, this module does not know where\nto send the error message. Instead, owners subscribing to notifications receive\nan `error_status` message.\n\nThe `m:disk_log` module does not report errors to the `m:error_logger` module. It\nis up to the caller to decide whether to employ the error logger. Function\n`format_error/1` can be used to produce readable messages from error replies.\nHowever, information events are sent to the error logger in two situations,\nnamely when a log is repaired, or when a file is missing while reading chunks.\n\nError message `no_such_log` means that the specified disk log is not open.\nNothing is said about whether the disk log files exist or not.\n\n> #### Note {: .info }\n>\n> If an attempt to reopen or truncate a log fails (see\n> [`reopen/2,3`](`reopen/3`) and [`truncate/1,2`](`truncate/2`)) the disk log\n> process terminates immediately. Before the process terminates, links to owners\n> and blocking processes (see [`block/1,2`](`block/2`)) are removed. The effect\n> is that the links work in one direction only. Any process using a disk log\n> must check for error message `no_such_log` if some other process truncates or\n> reopens the log simultaneously.","ref":"disk_log.html"},{"type":"module","title":"See Also - disk_log","doc":"`m:file`, `m:wrap_log_reader`","ref":"disk_log.html#module-see-also"},{"type":"function","title":"disk_log.all/0","doc":"Returns the names of the disk logs accessible on the current node.","ref":"disk_log.html#all/0"},{"type":"function","title":"disk_log.alog/2","doc":"Asynchronously version of `log/2`.\n\nOwners subscribing to notifications receive message `read_only`, `blocked_log`,\nor `format_external` if the item cannot be written on the log, and possibly one\nof the messages `wrap`, `full`, or `error_status` if an item is written on the\nlog. Message `error_status` is sent if something is wrong with the header\nfunction or if a file error occurs.","ref":"disk_log.html#alog/2"},{"type":"function","title":"disk_log.alog_terms/2","doc":"Asynchronously version of `log_terms/2`.\n\nOwners subscribing to notifications receive message `read_only`, `blocked_log`,\nor `format_external` if the items cannot be written on the log, and possibly one\nor more of the messages `wrap`, `full`, and `error_status` if items are written\non the log. Message `error_status` is sent if something is wrong with the header\nfunction or if a file error occurs.","ref":"disk_log.html#alog_terms/2"},{"type":"function","title":"disk_log.balog/2","doc":"Asynchronously version of `blog/2`.\n\nOwners subscribing to notifications receive message `read_only`, `blocked_log`,\nor `format_external` if the item cannot be written on the log, and possibly one\nof the messages `wrap`, `full`, or `error_status` if an item is written on the\nlog. Message `error_status` is sent if something is wrong with the header\nfunction or if a file error occurs.","ref":"disk_log.html#balog/2"},{"type":"function","title":"disk_log.balog_terms/2","doc":"Asynchronously version of `blog_terms/2`.\n\nOwners subscribing to notifications receive message `read_only`, `blocked_log`,\nor `format_external` if the items cannot be written on the log, and possibly one\nor more of the messages `wrap`, `full`, and `error_status` if items are written\non the log. Message `error_status` is sent if something is wrong with the header\nfunction or if a file error occurs.","ref":"disk_log.html#balog_terms/2"},{"type":"function","title":"disk_log.bchunk/2","doc":"","ref":"disk_log.html#bchunk/2"},{"type":"function","title":"disk_log.bchunk/3","doc":"Equivalent to [`chunk(Log, Continuation, N)`](`chunk/3`) except that\nit returns the binaries read from the file, that is it does not call\n`binary_to_term/1`.","ref":"disk_log.html#bchunk/3"},{"type":"function","title":"disk_log.block/1","doc":"","ref":"disk_log.html#block/1"},{"type":"function","title":"disk_log.block/2","doc":"With a call to `block/2` a process can block a log.\n\nIf the blocking process is not an owner of the log, a temporary link is created\nbetween the disk log process and the blocking process. The link ensures that the disk log is\nunblocked if the blocking process terminates without first closing or unblocking\nthe log.\n\nAny process can probe a blocked log with [`info/1`](`info/1`) or close it with\n[`close/1`](`close/1`). The blocking process can also use functions [`chunk/2,3`](`chunk/3`),\n[`bchunk/2,3`](`chunk/3`), [`chunk_step/3`](`chunk_step/3`), and [`unblock/1`](`unblock/1`)\nwithout being affected by the block. Any other attempt than those mentioned so\nfar to update or read a blocked log suspends the calling process until the log\nis unblocked or returns error message `{blocked_log, Log}`, depending on whether\nthe value of `QueueLogRecords` is `true` or `false`.","ref":"disk_log.html#block/2"},{"type":"function","title":"disk_log.blog/2","doc":"Equivalent to `log/2` except that it is used for externally formatted logs.\n\n`blog/2` can also be used for internally formatted logs\nif the binaries are constructed with calls to `term_to_binary/1`.","ref":"disk_log.html#blog/2"},{"type":"function","title":"disk_log.blog_terms/2","doc":"Equivalent to `log_terms/2` except that it is used for externally formatted logs.\n\n`blog_terms/2` can also be used for internally formatted logs\nif the binaries are constructed with calls to `term_to_binary/1`.","ref":"disk_log.html#blog_terms/2"},{"type":"function","title":"disk_log.breopen/3","doc":"Equivalent to `reopen` except that it is used for externally formatted logs.","ref":"disk_log.html#breopen/3"},{"type":"function","title":"disk_log.btruncate/2","doc":"Equivalent to `truncate/2` for externally formatted logs.","ref":"disk_log.html#btruncate/2"},{"type":"function","title":"disk_log.change_header/2","doc":"Changes the value of option `head` or `head_func` for an owner of a disk log.","ref":"disk_log.html#change_header/2"},{"type":"function","title":"disk_log.change_notify/3","doc":"Changes the value of option `notify` for an owner of a disk log.","ref":"disk_log.html#change_notify/3"},{"type":"function","title":"disk_log.change_size/2","doc":"Changes the size of an open log. For a halt log, the size can always be\nincreased, but it cannot be decreased to something less than the current file\nsize.\n\nFor a wrap or rotate log, both the size and the number of files can always be\nincreased, as long as the number of files does not exceed 65000. For wrap logs,\nif the maximum number of files is decreased, the change is not valid until the\ncurrent file is full and the log wraps to the next file. The redundant files are\nremoved the next time the log wraps around, that is, starts to log to file\nnumber 1.\n\nAs an example, assume that the old maximum number of files is 10 and that the\nnew maximum number of files is 6. If the current file number is not greater than\nthe new maximum number of files, files 7-10 are removed when file 6 is full and\nthe log starts to write to file number 1 again. Otherwise, the files greater\nthan the current file are removed when the current file is full (for example, if\nthe current file is 8, files 9 and 10 are removed). The files between the new\nmaximum number of files and the current file (that is, files 7 and 8) are\nremoved the next time file 6 is full.\n\nFor rotate logs, if the maximum number of files is decreased, the redundant\nfiles are deleted instantly.\n\nIf the size of the files is decreased, the change immediately affects the\ncurrent log. It does not change the size of log files already full until the\nnext time they are used.\n\nIf the log size is decreased, for example, to save space, function\n`next_file/1`, can be used to force the log to wrap.","ref":"disk_log.html#change_size/2"},{"type":"function","title":"disk_log.chunk/2","doc":"","ref":"disk_log.html#chunk/2"},{"type":"function","title":"disk_log.chunk/3","doc":"Efficiently reads the terms that are appended to an internally formatted log.\n\nIt minimizes disk I/O by reading 64 kilobyte chunks from the file.\n\nThe first time `chunk()` is called, an initial continuation, the\natom `start`, must be provided.\n\nWhen [`chunk/3`](`chunk/3`) is called, `N` controls the maximum number of terms\nthat are read from the log in each chunk. `infinity` means\nthat all the terms contained in the 64 kilobyte chunk are read. If less than `N`\nterms are returned, this does not necessarily mean that the end of the file is\nreached.\n\n`chunk/3` returns a tuple `{Continuation2, Terms}`, where `Terms` is a list of\nterms found in the log. `Continuation2` is yet another continuation, which must\nbe passed on to any subsequent calls to `chunk()`. With a series of calls to\n`chunk()`, all terms from a log can be extracted.\n\n`chunk/3` returns a tuple `{Continuation2, Terms, Badbytes}` if the log is\nopened in read-only mode and the read chunk is corrupt. `Badbytes` is the number\nof bytes in the file found not to be Erlang terms in the chunk. Notice that the\nlog is not repaired. When trying to read chunks from a log opened in read-write\nmode, tuple `{corrupt_log_file, FileName}` is returned if the read chunk is\ncorrupt.\n\n`chunk/3` returns `eof` when the end of the log is reached, or `{error, Reason}`\nif an error occurs. If a wrap log file is missing, a message is output on the\nerror log.\n\nWhen [`chunk/2,3`](`chunk/3`) is used with wrap logs, the returned continuation might not be\nvalid in the next call to `chunk/3`. This is because the log can wrap and delete\nthe file into which the continuation points. To prevent this, the log can be\nblocked during the search.","ref":"disk_log.html#chunk/3"},{"type":"function","title":"disk_log.chunk_info/1","doc":"Returns the pair `{node, Node}`, describing the chunk continuation returned by\n`chunk/2,3`, [`bchunk/2,3`](`bchunk/3`), or [`chunk_step/3`](`chunk_step/3`).\n\nTerms are read from the disk log running on `Node`.","ref":"disk_log.html#chunk_info/1"},{"type":"function","title":"disk_log.chunk_step/3","doc":"Can be used with [`chunk/2,3`](`chunk/3`) and [`bchunk/2,3`](`chunk/3`) to\nsearch through an internally formatted wrap log.\n\nIt takes as argument a continuation as returned by [`chunk/2,3`](`chunk/3`),\n[`bchunk/2,3`](`bchunk/3`), or [`chunk_step/3`](`chunk_step/3`), and steps\nforward (or backward) `Step` files in the wrap log. The continuation returned,\npoints to the first log item in the new current file.\n\nIf atom `start` is specified as continuation, the first file of the wrap log is\nchosen as the new current file.\n\nIf the wrap log is not full because all files are not yet used,\n`{error, end_of_log}` is returned if trying to step outside the log.","ref":"disk_log.html#chunk_step/3"},{"type":"function","title":"disk_log.close/1","doc":"Closes a disk log properly.\n\nAn internally formatted log must be closed before the Erlang system is stopped.\nOtherwise, the log is regarded as unclosed and the automatic repair procedure is\nactivated next time the log is opened.\n\nThe disk log process is not terminated as long as there are owners or users of\nthe log. All owners must close the log, possibly by terminating. Also, any other\nprocess, not only the processes that have opened the log anonymously, can\ndecrement the `users` counter by closing the log. Attempts to close a log by a\nprocess that is not an owner are ignored if there are no users.\n\nIf the log is blocked by the closing process, the log is also unblocked.","ref":"disk_log.html#close/1"},{"type":"function","title":"disk_log.format_error/1","doc":"Given the error returned by any function in this module, this function returns a\ndescriptive string of the error in English.\n\nFor file errors, function [`format_error/1`](`format_error/1`) in module\n[`file`](`file:format_error/1`) is called.","ref":"disk_log.html#format_error/1"},{"type":"function","title":"disk_log.inc_wrap_file/1","doc":"Forces the internally formatted disk log to start logging to the next log file.\nIt can be used, for example, with [`change_size/2`](`change_size/2`) to reduce\nthe amount of disk space allocated by the disk log.\n\nOwners subscribing to notifications normally receive a `wrap` message, but if an\nerror occurs with a reason tag of `invalid_header` or `file_error`, an\n`error_status` message is sent.","ref":"disk_log.html#inc_wrap_file/1"},{"type":"function","title":"disk_log.info/1","doc":"Returns a list of `{Tag, Value}` pairs describing a log running on the node.\n\nThe following pairs are returned for all logs:\n\n- **`{name, Log}`** - `Log` is the log name as specified by the\n [`open/1`](`open/1`) option `name`.\n\n- **`{file, File}`** - For halt logs `File` is the filename, and for wrap logs\n `File` is the base name.\n\n- **`{type, Type}`** - `Type` is the log type as specified by the\n [`open/1`](`open/1`) option `type`.\n\n- **`{format, Format}`** - `Format` is the log format as specified by the\n [`open/1`](`open/1`) option `format`.\n\n- **`{size, Size}`** - `Size` is the log size as specified by the\n [`open/1`](`open/1`) option `size`, or the size set by\n [`change_size/2`](`change_size/2`). The value set by\n [`change_size/2`](`change_size/2`) is reflected immediately.\n\n- **`{mode, Mode}`** - `Mode` is the log mode as specified by the\n [`open/1`](`open/1`) option `mode`.\n\n- **`{owners, [{pid(), Notify}]}`** - `Notify` is the value set by the\n [`open/1`](`open/1`) option `notify` or function\n [`change_notify/3`](`change_notify/3`) for the owners of the log.\n\n- **`{users, Users}`** - `Users` is the number of anonymous users of the log,\n see the [`open/1`](`open/1`) option [`linkto`](`m:disk_log#linkto`).\n\n- **`{status, Status}`** - `Status` is `ok` or `{blocked, QueueLogRecords}` as\n set by functions `block/1,2` and [`unblock/1`](`unblock/1`).\n\n- **`{node, Node}`** - The information returned by the current invocation of\n function [`info/1`](`info/1`) is gathered from the disk log process running on\n `Node`.\n\nThe following pairs are returned for all logs opened in `read_write` mode:\n\n- **`{head, Head}`** - Depending on the value of the [`open/1`](`open/1`)\n options `head` and `head_func`, or set by function\n [`change_header/2`](`change_header/2`), the value of `Head` is `none`\n (default), `{head, H}` (`head` option), or `{M,F,A}` (`head_func` option).\n\n- **`{no_written_items, NoWrittenItems}`** - `NoWrittenItems` is the number of\n items written to the log since the disk log process was created.\n\nThe following pair is returned for halt logs opened in `read_write` mode:\n\n- **`{full, Full}`** - `Full` is `true` or `false` depending on whether the halt\n log is full or not.\n\nThe following pairs are returned for wrap logs opened in `read_write` mode:\n\n- **`{no_current_bytes, integer() >= 0}`** - The number of bytes written to the\n current wrap log file.\n\n- **`{no_current_items, integer() >= 0}`** - The number of items written to the\n current wrap log file, header inclusive.\n\n- **`{no_items, integer() >= 0}`** - The total number of items in all wrap log\n files.\n\n- **`{current_file, integer()}`** - The ordinal for the current wrap log file in\n the range `1..MaxNoFiles`, where `MaxNoFiles` is specified by the\n [`open/1`](`open/1`) option `size` or set by\n [`change_size/2`](`change_size/2`).\n\n- **`{no_overflows, {SinceLogWasOpened, SinceLastInfo}}`** - `SinceLogWasOpened`\n (`SinceLastInfo`) is the number of times a wrap log file has been filled up\n and a new one is opened or [`inc_wrap_file/1`](`inc_wrap_file/1`) has been\n called since the disk log was last opened ([`info/1`](`info/1`) was last\n called). The first time `info/2` is called after a log was (re)opened or\n truncated, the two values are equal.\n\nNotice that functions [`chunk/2,3`](`chunk/3`), [`bchunk/2,3`](`bchunk/3`), and\n[`chunk_step/3`](`chunk_step/3`) do not affect any value returned by\n[`info/1`](`info/1`).","ref":"disk_log.html#info/1"},{"type":"function","title":"disk_log.log/2","doc":"Synchronously appends a term to a internally formatted disk log. Returns `ok`\nor `{error, Reason}` when the term is written to disk.\n\nTerms are written by the ordinary `write()` function of the operating system.\nHence, it is not guaranteed that the term is written to disk, it can linger in\nthe operating system kernel for a while. To ensure that the item is written to disk,\nfunction `sync/1` must be called.\n\nOwners subscribing to notifications are notified of an error with an\n`error_status` message if the error reason tag is `invalid_header` or\n`file_error`.","ref":"disk_log.html#log/2"},{"type":"function","title":"disk_log.log_terms/2","doc":"Synchronously appends a list of items to an internally formatted log.\n\nIt is more efficient to use this functions instead of [`log/2`](`log/2`). The specified\nlist is split into as large sublists as possible (limited by the size of wrap log files),\nand each sublist is logged as one single item, which reduces the overhead.\n\nOwners subscribing to notifications are notified of an error with an\n`error_status` message if the error reason tag is `invalid_header` or\n`file_error`.","ref":"disk_log.html#log_terms/2"},{"type":"function","title":"disk_log.next_file/1","doc":"For wrap logs, it forces the disk log to start logging to the next log file. It\ncan be used, for example, with [`change_size/2`](`change_size/2`) to reduce the\namount of disk space allocated by the disk log.\n\nOwners subscribing to notifications normally receive a `wrap` message, but if an\nerror occurs with a reason tag of `invalid_header` or `file_error`, an\n`error_status` message is sent.\n\nFor rotate logs, it forces rotation of the currently active log file, compresses\nit and opens a new active file for logging.","ref":"disk_log.html#next_file/1"},{"type":"function","title":"disk_log.open/1","doc":"Open a new disk_log file for reading or writing.\n\nParameter `ArgL` is a list of the following options:\n\n- **`{name, Log}`** - Specifies the log name. This name must be passed on as a\n parameter in all subsequent logging operations. A name must always be\n supplied.\n\n- **`{file, FileName}`** - Specifies the name of the file to be used for logged\n terms. If this value is omitted and the log name is an atom or a string, the\n filename defaults to `lists:concat([Log, \".LOG\"])` for halt logs.\n\n For wrap logs, this is the base name of the files. Each file in a wrap log is\n called ` .N`, where `N` is an integer. Each wrap log also has two\n files called ` .idx` and ` .siz`.\n\n For rotate logs, this is the name of the active log file. The compressed files\n are named as ` .N.gz`, where `N` is an integer and ` .0.gz`\n is the latest compressed log file. All the compressed files are renamed at\n each rotation so that the latest files have the smallest index. The maximum\n value for N is the value of `MaxNoFiles` minus 1.\n\n- **`{linkto, LinkTo}`[](){: #linkto } ** \n If `LinkTo` is a pid, it becomes an owner of the log. If `LinkTo` is `none`, the\n log records that it is used anonymously by some process by incrementing the `users`\n counter. By default, the process that calls [`open/1`](`open/1`) owns the log.\n\n- **`{repair, Repair}`** - If `Repair` is `true`, the current log file is\n repaired, if needed. As the restoration is initiated, a message is output on\n the error log. If `false` is specified, no automatic repair is attempted.\n Instead, the tuple `{error, {need_repair, Log}}` is returned if an attempt is\n made to open a corrupt log file. If `truncate` is specified, the log file\n becomes truncated, creating an empty log, regardless of previous content.\n Defaults to `true`, which has no effect on logs opened in read-only mode.\n\n- **`{type, Type}`** - The log type. Defaults to `halt`.\n\n- **`{format, Format}`** - Disk log format. Defaults to `internal`.\n\n- **`{size, Size}`** - Log size.\n\n When a halt log has reached its maximum size, all attempts to log more items\n are rejected. Defaults to `infinity`, which for halt implies that there is no\n maximum size.\n\n For wrap and rotate logs, parameter `Size` can be a pair\n `{MaxNoBytes, MaxNoFiles}`. For wrap logs it can also be `infinity`. In the\n latter case, if the files of an existing wrap log with the same name can be\n found, the size is read from the existing wrap log, otherwise an error is\n returned.\n\n Wrap logs write at most `MaxNoBytes` bytes on each file and use `MaxNoFiles`\n files before starting all over with the first wrap log file. Regardless of\n `MaxNoBytes`, at least the header (if there is one) and one item are written\n on each wrap log file before wrapping to the next file.\n\n The first time an existing wrap log is opened, that is, when the disk log\n process is created, the value of the option `size` is allowed to differ from\n the current log size, and the size of the disk log is changed as per\n `change_size/2`.\n\n When opening an existing wrap log, it is not necessary to supply a value for\n option `size`, but if the log is already open, that is, the disk log process\n exists, the supplied value must equal the current log size, otherwise the\n tuple `{error, {size_mismatch, CurrentSize, NewSize}}` is returned.\n\n > #### Note {: .info }\n >\n > Before Erlang/OTP 24.0, the supplied value of option `size` was to be equal\n > to the current log size when opening an existing wrap log for the first\n > time, that is, when creating the disk log process.\n\n Rotate logs write at most `MaxNoBytes` bytes on the active log file and keep\n the latest `MaxNoFiles` compressed files. Regardless of `MaxNoBytes`, at least\n the header (if there is one) and one item are written on each rotate log file\n before rotation.\n\n When opening an already open halt log, option `size` is ignored.\n\n- **`{notify, boolean()}`**{: #notify } - If `true`, the log owners are notified\n when certain log events occur. Defaults to `false`. The owners are sent one of the\n following messages when an event occurs:\n\n - **`{disk_log, Node, Log, {wrap, NoLostItems}}`** - Sent when a wrap log has\n filled up one of its files and a new file is opened. `NoLostItems` is the\n number of previously logged items that were lost when truncating existing\n files.\n\n - **`{disk_log, Node, Log, {truncated, NoLostItems}}`** - Sent when a log is\n truncated or reopened. For halt logs `NoLostItems` is the number of items\n written on the log since the disk log process was created. For wrap logs\n `NoLostItems` is the number of items on all wrap log files.\n\n - **`{disk_log, Node, Log, {read_only, Items}}`** - Sent when an asynchronous\n log attempt is made to a log file opened in read-only mode. `Items` is the\n items from the log attempt.\n\n - **`{disk_log, Node, Log, {blocked_log, Items}}`** - Sent when an\n asynchronous log attempt is made to a blocked log that does not queue log\n attempts. `Items` is the items from the log attempt.\n\n - **`{disk_log, Node, Log, {format_external, Items}}`** - Sent when function\n [`alog/2`](`alog/2`) or [`alog_terms/2`](`alog_terms/2`) is used for\n internally formatted logs. `Items` is the items from the log attempt.\n\n - **`{disk_log, Node, Log, full}`** - Sent when an attempt to log items to a\n wrap log would write more bytes than the limit set by option `size`.\n\n - **`{disk_log, Node, Log, {error_status, Status}}`** - Sent when the error\n status changes. The error status is defined by the outcome of the last\n attempt to log items to the log, or to truncate the log, or the last use of\n function [`sync/1`](`sync/1`), [`inc_wrap_file/1`](`inc_wrap_file/1`), or\n [`change_size/2`](`change_size/2`). `Status` is either `ok` or\n `{error, Error}`, the former is the initial value.\n\n- **`{head, Head}`** - Specifies a header to be written first on the log file.\n If the log is a wrap or rotate log, the item `Head` is written first in each\n new file. `Head` is to be a term if the format is `internal`, otherwise an\n `t:iodata/0`. Defaults to `none`, which means that no header is written first\n on the file.\n\n- **`{head_func, {M,F,A}}`** - Specifies a function to be called each time a new\n log file is opened. The call `M:F(A)` is assumed to return `{ok, Head}`. The\n item `Head` is written first in each file. `Head` is to be a term if the\n format is `internal`, otherwise an `t:iodata/0`.\n\n- **`{mode, Mode}`** - Specifies if the log is to be opened in read-only or\n read-write mode. Defaults to `read_write`.\n\n- **`{quiet, Boolean}`** - Specifies if messages will be sent to `error_logger`\n on recoverable errors with the log files. Defaults to `false`.\n\n[`open/1`](`open/1`) returns `{ok, Log}` if the log file is successfully opened.\nIf the file is successfully repaired, the tuple\n`{repaired, Log, {recovered, Rec}, {badbytes, Bad}}` is returned, where `Rec` is\nthe number of whole Erlang terms found in the file and `Bad` is the number of\nbytes in the file that are non-Erlang terms.\n\nWhen a disk log is opened in read-write mode, any existing log file is checked\nfor. If there is none, a new empty log is created, otherwise the existing file\nis opened at the position after the last logged item, and the logging of items\nstarts from there. If the format is `internal` and the existing file is not\nrecognized as an internally formatted log, a tuple\n`{error, {not_a_log_file, FileName}}` is returned.\n\n[`open/1`](`open/1`) cannot be used for changing the values of options of an\nopen log. When there are prior owners or users of a log, all option values\nexcept `name`, `linkto`, and `notify` are only checked against the values\nsupplied before as option values to function [`open/1`](`open/1`),\n[`change_header/2`](`change_header/2`), [`change_notify/3`](`change_notify/3`),\nor [`change_size/2`](`change_size/2`). Thus, none of the options except `name`\nis mandatory. If some specified value differs from the current value, a tuple\n`{error, {arg_mismatch, OptionName, CurrentValue, Value}}` is returned.\n\n> #### Note {: .info }\n>\n> If an owner attempts to open a log as owner once again, it is acknowledged\n> with the return value `{ok, Log}`, but the state of the disk log is not\n> affected.\n\nA log file can be opened more than once by giving different values to option\n`name` or by using the same file when opening a log on different nodes. It is up\nto the user of module `disk_log` to ensure that not more than one disk log\nprocess has write access to any file, otherwise the file can be corrupted.\n\nIf an attempt to open a log file for the first time fails, the disk log process\nterminates with the EXIT message `{{failed,Reason},[{disk_log,open,1}]}`. The\nfunction returns `{error, Reason}` for all other errors.","ref":"disk_log.html#open/1"},{"type":"function","title":"disk_log.pid2name/1","doc":"Returns the log name given the pid of a disk log process on the current node, or\n`undefined` if the specified pid is not a disk log process.\n\nThis function is meant to be used for debugging only.","ref":"disk_log.html#pid2name/1"},{"type":"function","title":"disk_log.reopen/2","doc":"Equivalent to [`reopen(Log, File, Head)`](`reopen/3`) where `Head` is\nthe `Head` specified in `open/1`.","ref":"disk_log.html#reopen/2"},{"type":"function","title":"disk_log.reopen/3","doc":"Renames an internally formatted log file to `File` and then recreates a new log file. If a\nwrap/rotate log exists, `File` is used as the base name of the renamed files.\n\nWrites the value of `Head` first in the newly opened log file. The header argument\nis used only once. Next time a wrap/rotate log file is opened, the header given to\n[`open/1`](`open/1`) is used.\n\nOwners subscribing to notifications receive a `truncate` message.\n\nUpon failure to reopen the log, the disk log process terminates with the EXIT\nmessage `{{failed,Error},[{disk_log,Fun,Arity}]}`. Other processes having\nrequests queued receive the message\n`{disk_log, Node, {error, disk_log_stopped}}`.","ref":"disk_log.html#reopen/3"},{"type":"function","title":"disk_log.sync/1","doc":"Ensures that the contents of the log are written to the disk. This is usually a\nrather expensive operation.","ref":"disk_log.html#sync/1"},{"type":"function","title":"disk_log.truncate/1","doc":"Equivalent to [`truncate(Log, Head)`](`truncate/2`) where `Head` is\nthe `Head` specified in `open/1`.\n\nThis function can be used for both internally and externally\nformatted logs.","ref":"disk_log.html#truncate/1"},{"type":"function","title":"disk_log.truncate/2","doc":"Removes all items from an internally formatted disk log. The argument `Head` or\nis written first in the newly truncated log.\n\nThe header argument is used only once. Next time a wrap/rotate log file is opened,\nthe header given to [`open/1`](`open/1`) is used.\n\nOwners subscribing to notifications receive a `truncate` message.\n\nIf the attempt to truncate the log fails, the disk log process terminates with\nthe EXIT message `{{failed,Reason},[{disk_log,Fun,Arity}]}`. Other processes\nhaving requests queued receive the message\n`{disk_log, Node, {error, disk_log_stopped}}`.","ref":"disk_log.html#truncate/2"},{"type":"function","title":"disk_log.unblock/1","doc":"Unblocks a log. A log can only be unblocked by the blocking process.","ref":"disk_log.html#unblock/1"},{"type":"type","title":"disk_log.bchunk_ret/0","doc":"","ref":"disk_log.html#t:bchunk_ret/0"},{"type":"type","title":"disk_log.block_error_rsn/0","doc":"","ref":"disk_log.html#t:block_error_rsn/0"},{"type":"type","title":"disk_log.chunk_error_rsn/0","doc":"","ref":"disk_log.html#t:chunk_error_rsn/0"},{"type":"type","title":"disk_log.chunk_ret/0","doc":"","ref":"disk_log.html#t:chunk_ret/0"},{"type":"type","title":"disk_log.close_error_rsn/0","doc":"","ref":"disk_log.html#t:close_error_rsn/0"},{"type":"opaque","title":"disk_log.continuation/0","doc":"Chunk continuation returned by [`chunk/2,3`](`chunk/3`),\n[`bchunk/2,3`](`bchunk/3`), or [`chunk_step/3`](`chunk_step/3`).","ref":"disk_log.html#t:continuation/0"},{"type":"type","title":"disk_log.dlog_format/0","doc":"","ref":"disk_log.html#t:dlog_format/0"},{"type":"type","title":"disk_log.dlog_head_opt/0","doc":"","ref":"disk_log.html#t:dlog_head_opt/0"},{"type":"type","title":"disk_log.dlog_info/0","doc":"","ref":"disk_log.html#t:dlog_info/0"},{"type":"type","title":"disk_log.dlog_mode/0","doc":"","ref":"disk_log.html#t:dlog_mode/0"},{"type":"type","title":"disk_log.dlog_optattr/0","doc":"","ref":"disk_log.html#t:dlog_optattr/0"},{"type":"type","title":"disk_log.dlog_option/0","doc":"","ref":"disk_log.html#t:dlog_option/0"},{"type":"type","title":"disk_log.dlog_options/0","doc":"","ref":"disk_log.html#t:dlog_options/0"},{"type":"type","title":"disk_log.dlog_size/0","doc":"","ref":"disk_log.html#t:dlog_size/0"},{"type":"type","title":"disk_log.dlog_type/0","doc":"","ref":"disk_log.html#t:dlog_type/0"},{"type":"type","title":"disk_log.file_error/0","doc":"","ref":"disk_log.html#t:file_error/0"},{"type":"type","title":"disk_log.inc_wrap_error_rsn/0","doc":"","ref":"disk_log.html#t:inc_wrap_error_rsn/0"},{"type":"type","title":"disk_log.invalid_header/0","doc":"","ref":"disk_log.html#t:invalid_header/0"},{"type":"type","title":"disk_log.log/0","doc":"","ref":"disk_log.html#t:log/0"},{"type":"type","title":"disk_log.log_error_rsn/0","doc":"","ref":"disk_log.html#t:log_error_rsn/0"},{"type":"type","title":"disk_log.next_file_error_rsn/0","doc":"","ref":"disk_log.html#t:next_file_error_rsn/0"},{"type":"type","title":"disk_log.notify_ret/0","doc":"","ref":"disk_log.html#t:notify_ret/0"},{"type":"type","title":"disk_log.open_error_rsn/0","doc":"","ref":"disk_log.html#t:open_error_rsn/0"},{"type":"type","title":"disk_log.open_ret/0","doc":"","ref":"disk_log.html#t:open_ret/0"},{"type":"type","title":"disk_log.reopen_error_rsn/0","doc":"","ref":"disk_log.html#t:reopen_error_rsn/0"},{"type":"type","title":"disk_log.sync_error_rsn/0","doc":"","ref":"disk_log.html#t:sync_error_rsn/0"},{"type":"type","title":"disk_log.trunc_error_rsn/0","doc":"","ref":"disk_log.html#t:trunc_error_rsn/0"},{"type":"type","title":"disk_log.unblock_error_rsn/0","doc":"","ref":"disk_log.html#t:unblock_error_rsn/0"},{"type":"module","title":"error_logger","doc":"Erlang error logger.\n\n> #### Note {: .info }\n>\n> In Erlang/OTP 21.0, a new API for logging was added. The old `m:error_logger`\n> module can still be used by legacy code, but log events are redirected to the\n> new Logger API. New code should use the Logger API directly.\n>\n> `m:error_logger` is no longer started by default, but is automatically started\n> when an event handler is added with [`error_logger:add_report_handler/1,2`](`error_logger:add_report_handler/2`). The\n> `m:error_logger` module is then also added as a handler to the new logger.\n>\n> See `m:logger` and the [Logging](logger_chapter.md) chapter in the User's\n> Guide for more information.\n\nThe Erlang _error logger_ is an event manager (see\n[OTP Design Principles](`e:system:design_principles.md`) and `m:gen_event`),\nregistered as `m:error_logger`.\n\nError logger is no longer started by default, but is automatically started when\nan event handler is added with\n[`add_report_handler/1,2`](`add_report_handler/1`). The `m:error_logger` module is\nthen also added as a handler to the new logger, causing log events to be\nforwarded from logger to error logger, and consequently to all installed error\nlogger event handlers.\n\nUser-defined event handlers can be added to handle application-specific events.\n\nExisting event handlers provided by STDLIB and SASL are still available, but are\nno longer used by OTP.\n\nWarning events were introduced in Erlang/OTP R9C and are enabled by default as\nfrom Erlang/OTP 18.0. To retain backwards compatibility with existing\nuser-defined event handlers, the warning events can be tagged as `errors` or\n`info` using command-line flag `+W `, thus showing up as\n`ERROR REPORT` or `INFO REPORT` in the logs.\n\n[](){: #events }","ref":"error_logger.html"},{"type":"module","title":"Events - error_logger","doc":"All event handlers added to the error logger must handle the following events.\n`Gleader` is the group leader pid of the process that sent the event, and `Pid`\nis the process that sent the event.\n\n- **`{error, Gleader, {Pid, Format, Data}}`** -\n Generated when [`error_msg/1,2`](`error_msg/2`) or `format/2` is called.\n\n- **`{error_report, Gleader, {Pid, std_error, Report}}`** -\n Generated when [`error_report/1`](`error_report/1`) is called.\n\n- **`{error_report, Gleader, {Pid, Type, Report}}`** -\n Generated when [`error_report/2`](`error_report/2`) is called.\n\n- **`{warning_msg, Gleader, {Pid, Format, Data}}`** -\n Generated when [`warning_msg/1,2`](`warning_msg/2`) is called if warnings are set to\n be tagged as warnings.\n\n- **`{warning_report, Gleader, {Pid, std_warning, Report}}`** -\n Generated when [`warning_report/1`](`warning_report/1`) is called if warnings are\n set to be tagged as warnings.\n\n- **`{warning_report, Gleader, {Pid, Type, Report}}`** - Generated when\n [`warning_report/2`](`warning_report/2`) is called if warnings are set to be\n tagged as warnings.\n\n- **`{info_msg, Gleader, {Pid, Format, Data}}`** -\n Generated when [`info_msg/1,2`](`info_msg/2`) is called.\n\n- **`{info_report, Gleader, {Pid, std_info, Report}}`** -\n Generated when [`info_report/1`](`info_report/1`) is called.\n\n- **`{info_report, Gleader, {Pid, Type, Report}}`** -\n Generated when [`info_report/2`](`info_report/2`) is called.\n\nNotice that some system-internal events can also be received. Therefore a\ncatch-all clause last in the definition of the event handler callback function\n`c:gen_event:handle_event/2` is necessary. This also applies for\n`c:gen_event:handle_info/2`, as the event handler must also take care of some\nsystem-internal messages.","ref":"error_logger.html#module-events"},{"type":"module","title":"See Also - error_logger","doc":"`m:gen_event`, `m:logger`, `m:log_mf_h`, [`kernel`](kernel_app.md),\n[`sasl`](`e:sasl:sasl_app.md`)","ref":"error_logger.html#module-see-also"},{"type":"function","title":"error_logger.add_report_handler/1","doc":"","ref":"error_logger.html#add_report_handler/1"},{"type":"function","title":"error_logger.add_report_handler/2","doc":"Adds a new event handler to the error logger. The event handler must be\nimplemented as a `m:gen_event` callback module.\n\n`Handler` is typically the name of the callback module and `Args` is an optional\nterm (defaults to []) passed to the initialization callback function\n`c:gen_event:init/1`. The function returns `ok` if successful.\n\nThe event handler must be able to handle the events in this module, see section\n[Events](`m:error_logger#module-events`).\n\nThe first time this function is called, `m:error_logger` is added as a Logger\nhandler, and the `m:error_logger` process is started.","ref":"error_logger.html#add_report_handler/2"},{"type":"function","title":"error_logger.delete_report_handler/1","doc":"Deletes an event handler from the error logger by calling\n[`gen_event:delete_handler(error_logger, Handler, [])`](`gen_event:delete_handler/3`).\n\nIf no more event handlers exist after the deletion, `m:error_logger` is removed as\na Logger handler, and the `m:error_logger` process is stopped.","ref":"error_logger.html#delete_report_handler/1"},{"type":"function","title":"error_logger.error_msg/1","doc":"","ref":"error_logger.html#error_msg/1"},{"type":"function","title":"error_logger.error_msg/2","doc":"Log a standard error event. The `Format` and `Data` arguments are the same as\nthe arguments of `io:format/2` in STDLIB.\n\nError logger forwards the event to Logger, including metadata that allows\nbackwards compatibility with legacy error logger event handlers.\n\nThe event is handled by the default Logger handler.\n\nThis function is kept for backwards compatibility and must not be used by new\ncode. Use the [`?LOG_ERROR`](`m:logger#module-macros`) macro or\n[`logger:error/1,2,3`](`logger:error/1`) instead.\n\n_Example:_\n\n```text\n1> error_logger:error_msg(\"An error occurred in ~p\", [a_module]).\n=ERROR REPORT==== 22-May-2018::11:18:43.376917 ===\nAn error occurred in a_module\nok\n```\n\n> #### Warning {: .warning }\n>\n> If the Unicode translation modifier (`t`) is used in the format string, all\n> event handlers must ensure that the formatted output is correctly encoded for\n> the I/O device.","ref":"error_logger.html#error_msg/2"},{"type":"function","title":"error_logger.error_report/1","doc":"Log a standard error event. Error logger forwards the event to Logger, including\nmetadata that allows backwards compatibility with legacy error logger event\nhandlers.\n\nThe event is handled by the default Logger handler.\n\nThis functions is kept for backwards compatibility and must not be used by new\ncode. Use the [`?LOG_ERROR`](`m:logger#module-macros`) macro or\n[`logger:error/1,2,3`](`logger:error/1`) instead.\n\n_Example:_\n\n```text\n2> error_logger:error_report([{tag1,data1},a_term,{tag2,data}]).\n=ERROR REPORT==== 22-May-2018::11:24:23.699306 ===\n tag1: data1\n a_term\n tag2: data\nok\n3> error_logger:error_report(\"Serious error in my module\").\n=ERROR REPORT==== 22-May-2018::11:24:45.972445 ===\nSerious error in my module\nok\n```","ref":"error_logger.html#error_report/1"},{"type":"function","title":"error_logger.error_report/2","doc":"Log a user-defined error event. Error logger forwards the event to Logger,\nincluding metadata that allows backwards compatibility with legacy error logger\nevent handlers.\n\nError logger also adds a `domain` field with value `[Type]` to this event's\nmetadata, causing the filters of the default Logger handler to discard the\nevent. A different Logger handler, or an error logger event handler, must be\nadded to handle this event.\n\nIt is recommended that `Report` follows the same structure as for\n`error_report/1`.\n\nThis functions is kept for backwards compatibility and must not be used by new\ncode. Use the [`?LOG_ERROR`](`m:logger#module-macros`) macro or\n[`logger:error/1,2,3`](`logger:error/1`) instead.","ref":"error_logger.html#error_report/2"},{"type":"function","title":"error_logger.format/2","doc":"","ref":"error_logger.html#format/2"},{"type":"function","title":"error_logger.get_format_depth/0","doc":"Returns [`max(10, Depth)`](`max/2`), where `Depth` is the value of\n[`error_logger_format_depth`](kernel_app.md#error_logger_format_depth) in the\nKernel application, if Depth is an integer. Otherwise, `unlimited` is returned.\n\n> #### Note {: .info }\n>\n> The [`error_logger_format_depth`](kernel_app.md#error_logger_format_depth) variable is\n> [deprecated](kernel_app.md#deprecated-configuration-parameters) since the\n> [Logger API](`m:logger`) was introduced in Erlang/OTP 21.0. The variable, and\n> this function, are kept for backwards compatibility since they still might be\n> used by legacy report handlers.","ref":"error_logger.html#get_format_depth/0"},{"type":"function","title":"error_logger.info_msg/1","doc":"","ref":"error_logger.html#info_msg/1"},{"type":"function","title":"error_logger.info_msg/2","doc":"Log a standard information event. The `Format` and `Data` arguments are the same\nas the arguments of `io:format/2` in STDLIB.\n\nError logger forwards the event to Logger, including metadata that allows\nbackwards compatibility with legacy error logger event handlers.\n\nThe event is handled by the default Logger handler.\n\nThese functions are kept for backwards compatibility and must not be used by new\ncode. Use the [`?LOG_INFO`](`m:logger#module-macros`) macro or\n[`logger:info/1,2,3`](`logger:info/1`) instead.\n\n_Example:_\n\n```text\n1> error_logger:info_msg(\"Something happened in ~p\", [a_module]).\n=INFO REPORT==== 22-May-2018::12:03:32.612462 ===\nSomething happened in a_module\nok\n```\n\n> #### Warning {: .warning }\n>\n> If the Unicode translation modifier (`t`) is used in the format string, all\n> event handlers must ensure that the formatted output is correctly encoded for\n> the I/O device.","ref":"error_logger.html#info_msg/2"},{"type":"function","title":"error_logger.info_report/1","doc":"Log a standard information event. Error logger forwards the event to Logger,\nincluding metadata that allows backwards compatibility with legacy error logger\nevent handlers.\n\nThe event is handled by the default Logger handler.\n\nThis functions is kept for backwards compatibility and must not be used by new\ncode. Use the [`?LOG_INFO`](`m:logger#module-macros`) macro or\n[`logger:info/1,2,3`](`logger:info/1`) instead.\n\n_Example:_\n\n```text\n2> error_logger:info_report([{tag1,data1},a_term,{tag2,data}]).\n=INFO REPORT==== 22-May-2018::12:06:35.994440 ===\n tag1: data1\n a_term\n tag2: data\nok\n3> error_logger:info_report(\"Something strange happened\").\n=INFO REPORT==== 22-May-2018::12:06:49.066872 ===\nSomething strange happened\nok\n```","ref":"error_logger.html#info_report/1"},{"type":"function","title":"error_logger.info_report/2","doc":"Log a user-defined information event. Error logger forwards the event to Logger,\nincluding metadata that allows backwards compatibility with legacy error logger\nevent handlers.\n\nError logger also adds a `domain` field with value `[Type]` to this event's\nmetadata, causing the filters of the default Logger handler to discard the\nevent. A different Logger handler, or an error logger event handler, must be\nadded to handle this event.\n\nIt is recommended that `Report` follows the same structure as for\n`info_report/1`.\n\nThis functions is kept for backwards compatibility and must not be used by new\ncode. Use the [`?LOG_INFO`](`m:logger#module-macros`) macro or\n[`logger:info/1,2,3`](`logger:info/1`) instead.","ref":"error_logger.html#info_report/2"},{"type":"function","title":"error_logger.logfile/1","doc":"Enables or disables printout of standard events to a file.\n\nThis is done by adding or deleting the `error_logger_file_h` event handler, and\nthus indirectly adding `m:error_logger` as a Logger handler.\n\nNotice that this function does not manipulate the Logger configuration directly,\nmeaning that if the default Logger handler is already logging to a file, this\nfunction can potentially cause logging to a second file.\n\nThis function is useful as a shortcut during development and testing, but must\nnot be used in a production system. See section [Logging](logger_chapter.md) in\nthe Kernel User's Guide, and the `m:logger` manual page for information about\nhow to configure Logger for live systems.\n\n`Request` is one of the following:\n\n- **`{open, Filename}`** - Opens log file `Filename`. Returns `ok` if\n successful, or `{error, allready_have_logfile}` if logging to file is already\n enabled, or an error tuple if another error occurred (for example, if\n `Filename` cannot be opened). The file is opened with encoding UTF-8.\n\n- **`close`** - Closes the current log file. Returns `ok`, or\n `{error, module_not_found}`.\n\n- **`filename`** - Returns the name of the log file `Filename`, or\n `{error, no_log_file}` if logging to file is not enabled.","ref":"error_logger.html#logfile/1"},{"type":"function","title":"error_logger.tty/1","doc":"Enables (`Flag == true`) or disables (`Flag == false`) printout of standard\nevents to the terminal.\n\nThis is done by manipulating the Logger configuration. The function is useful as\na shortcut during development and testing, but must not be used in a production\nsystem. See section [Logging](logger_chapter.md) in the Kernel User's Guide, and\nthe `m:logger` manual page for information about how to configure Logger for\nlive systems.","ref":"error_logger.html#tty/1"},{"type":"function","title":"error_logger.warning_map/0","doc":"Returns the current mapping for warning events.\n\nEvents sent using [`warning_msg/1,2`](`warning_msg/2`) or\n[`warning_report/1,2`](`warning_report/2`) are tagged as errors, warnings\n(default), or info, depending on the value of command-line flag `+W`.\n\n_Example:_\n\n```text\nos$ erl\nErlang (BEAM) emulator version 5.4.8 [hipe] [threads:0] [kernel-poll]\n\nEshell V5.4.8 (abort with ^G)\n1> error_logger:warning_map().\nwarning\n2> error_logger:warning_msg(\"Warnings tagged as: ~p~n\", [warning]).\n\n=WARNING REPORT==== 11-Aug-2005::15:31:55 ===\nWarnings tagged as: warning\nok\n3>\nUser switch command\n --> q\nos$ erl +W e\nErlang (BEAM) emulator version 5.4.8 [hipe] [threads:0] [kernel-poll]\n\nEshell V5.4.8 (abort with ^G)\n1> error_logger:warning_map().\nerror\n2> error_logger:warning_msg(\"Warnings tagged as: ~p~n\", [error]).\n\n=ERROR REPORT==== 11-Aug-2005::15:31:23 ===\nWarnings tagged as: error\nok\n```","ref":"error_logger.html#warning_map/0"},{"type":"function","title":"error_logger.warning_msg/1","doc":"","ref":"error_logger.html#warning_msg/1"},{"type":"function","title":"error_logger.warning_msg/2","doc":"Log a standard warning event. The `Format` and `Data` arguments are the same as\nthe arguments of `io:format/2` in STDLIB.\n\nError logger forwards the event to Logger, including metadata that allows\nbackwards compatibility with legacy error logger event handlers.\n\nThe event is handled by the default Logger handler. The log level can be changed\nto error or info, see `warning_map/0`.\n\nThese functions are kept for backwards compatibility and must not be used by new\ncode. Use the [`?LOG_WARNING`](`m:logger#module-macros`) macro or\n[`logger:warning/1,2,3`](`logger:warning/1`) instead.\n\n> #### Warning {: .warning }\n>\n> If the Unicode translation modifier (`t`) is used in the format string, all\n> event handlers must ensure that the formatted output is correctly encoded for\n> the I/O device.","ref":"error_logger.html#warning_msg/2"},{"type":"function","title":"error_logger.warning_report/1","doc":"Log a standard warning event. Error logger forwards the event to Logger,\nincluding metadata that allows backwards compatibility with legacy error logger\nevent handlers.\n\nThe event is handled by the default Logger handler. The log level can be changed\nto error or info, see `warning_map/0`.\n\nThis functions is kept for backwards compatibility and must not be used by new\ncode. Use the [`?LOG_WARNING`](`m:logger#module-macros`) macro or\n[`logger:warning/1,2,3`](`logger:warning/1`) instead.","ref":"error_logger.html#warning_report/1"},{"type":"function","title":"error_logger.warning_report/2","doc":"Log a user-defined warning event. Error logger forwards the event to Logger,\nincluding metadata that allows backwards compatibility with legacy error logger\nevent handlers.\n\nError logger also adds a `domain` field with value `[Type]` to this event's\nmetadata, causing the filters of the default Logger handler to discard the\nevent. A different Logger handler, or an error logger event handler, must be\nadded to handle this event.\n\nThe log level can be changed to error or info, see `warning_map/0`.\n\nIt is recommended that `Report` follows the same structure as for\n`warning_report/1`.\n\nThis functions is kept for backwards compatibility and must not be used by new\ncode. Use the [`?LOG_WARNING`](`m:logger#module-macros`) macro or\n[`logger:warning/1,2,3`](`logger:warning/1`) instead.","ref":"error_logger.html#warning_report/2"},{"type":"type","title":"error_logger.open_error/0","doc":"","ref":"error_logger.html#t:open_error/0"},{"type":"type","title":"error_logger.report/0","doc":"","ref":"error_logger.html#t:report/0"},{"type":"module","title":"logger","doc":"API module for Logger, the standard logging facility in Erlang/OTP.\n\nThis module implements the main API for logging in Erlang/OTP. To create a log\nevent, use the [API functions](#logging-api-functions) or the log\n[macros](#module-macros), for example:\n\n```erlang\n?LOG_ERROR(\"error happened because: ~p\", [Reason]). % With macro\nlogger:error(\"error happened because: ~p\", [Reason]). % Without macro\n```\n\nTo configure the Logger backend, use\n[Kernel configuration parameters](kernel_app.md#logger) or\n[configuration functions](#configuration-api-functions) in the Logger API.\n\nBy default, the Kernel application installs one log handler at system start.\nThis handler is named `default`. It receives and processes standard log events\nproduced by the Erlang runtime system, standard behaviours and different\nErlang/OTP applications. The log events are by default printed to the terminal.\n\nIf you want your systems logs to be printed to a file instead, you must\nconfigure the default handler to do so. The simplest way is to include the\nfollowing in your [`sys.config`](config.md):\n\n```erlang\n[{kernel,\n [{logger,\n [{handler, default, logger_std_h,\n #{config => #{file => \"path/to/file.log\"}}}]}]}].\n```\n\nFor more information about:\n\n- the Logger facility in general, see the [User's Guide](logger_chapter.md).\n- how to configure Logger, see the\n [Configuration](logger_chapter.md#configuration) section in the User's Guide.\n- the built-in handlers, see `m:logger_std_h` and `m:logger_disk_log_h`.\n- the built-in formatter, see `m:logger_formatter`.\n- built-in filters, see `m:logger_filters`.","ref":"logger.html"},{"type":"module","title":"Macros - logger","doc":"The following macros are defined in `logger.hrl`, which is included in a module\nwith the directive\n\n```erlang\n -include_lib(\"kernel/include/logger.hrl\").\n```\n\n- `?LOG_EMERGENCY(StringOrReport[,Metadata])`\n- `?LOG_EMERGENCY(FunOrFormat,Args[,Metadata])`\n- `?LOG_ALERT(StringOrReport[,Metadata])`\n- `?LOG_ALERT(FunOrFormat,Args[,Metadata])`\n- `?LOG_CRITICAL(StringOrReport[,Metadata])`\n- `?LOG_CRITICAL(FunOrFormat,Args[,Metadata])`\n- `?LOG_ERROR(StringOrReport[,Metadata])`\n- `?LOG_ERROR(FunOrFormat,Args[,Metadata])`\n- `?LOG_WARNING(StringOrReport[,Metadata])`\n- `?LOG_WARNING(FunOrFormat,Args[,Metadata])`\n- `?LOG_NOTICE(StringOrReport[,Metadata])`\n- `?LOG_NOTICE(FunOrFormat,Args[,Metadata])`\n- `?LOG_INFO(StringOrReport[,Metadata])`\n- `?LOG_INFO(FunOrFormat,Args[,Metadata])`\n- `?LOG_DEBUG(StringOrReport[,Metadata])`\n- `?LOG_DEBUG(FunOrFormat,Args[,Metadata])`\n- `?LOG(Level,StringOrReport[,Metadata])`\n- `?LOG(Level,FunOrFormat,Args[,Metadata])`\n\nAll macros expand to a call to Logger, where `Level` is taken from the macro\nname, or from the first argument in the case of the `?LOG` macro. Location data\nis added to the metadata as described under the `t:metadata/0` type definition.\n\nThe call is wrapped in a case statement and will be evaluated only if `Level` is\nequal to or below the configured log level.","ref":"logger.html#module-macros"},{"type":"module","title":"See Also - logger","doc":"[`config`](config.md), `m:erlang`, `m:io`, `m:logger_disk_log_h`,\n`m:logger_filters`, `m:logger_handler`, `m:logger_formatter`, `m:logger_std_h`,\n`m:unicode`","ref":"logger.html#module-see-also"},{"type":"function","title":"logger.add_handler/3","doc":"Add a handler with the given configuration.\n\n`HandlerId` is a unique identifier which must be used in all subsequent calls\nreferring to this handler.","ref":"logger.html#add_handler/3"},{"type":"function","title":"logger.add_handler_filter/3","doc":"Add a filter to the specified handler.\n\nThe filter fun is called with the log event as the first parameter, and the\nspecified `filter_args()` as the second parameter.\n\nThe return value of the fun specifies if a log event is to be discarded or\nforwarded to the handler callback:\n\n- **`t:log_event/0`** - The filter _passed_. The next handler filter, if any, is\n applied. If no more filters exist for this handler, the log event is forwarded\n to the handler callback.\n\n- **`stop`** - The filter _did not pass_, and the log event is immediately\n discarded.\n\n- **`ignore`** - The filter has no knowledge of the log event. The next handler\n filter, if any, is applied. If no more filters exist for this handler, the\n value of the `filter_default` configuration parameter for the handler\n specifies if the log event shall be discarded or forwarded to the handler\n callback.\n\nSee section [Filters](logger_chapter.md#filters) in the User's Guide for more\ninformation about filters.\n\nSome built-in filters exist. These are defined in `m:logger_filters`.","ref":"logger.html#add_handler_filter/3"},{"type":"function","title":"logger.add_handlers/1","doc":"Reads the application configuration parameter `logger` and calls\n[`add_handlers/1`](`add_handlers/1`) with its contents.\n\nThis function should be used by custom Logger handlers to make configuration\nconsistent no matter which handler the system uses. Normal usage is to add a\ncall to `logger:add_handlers/1` just after the processes that the handler needs\nare started, and pass the application's `logger` configuration as the argument.\nFor example:\n\n```erlang\n-behaviour(application).\nstart(_, []) ->\n case supervisor:start_link({local, my_sup}, my_sup, []) of\n {ok, Pid} ->\n ok = logger:add_handlers(my_app),\n {ok, Pid, []};\n Error -> Error\n end.\n```\n\nThis reads the `logger` configuration parameter from the `my_app` application\nand starts the configured handlers. The contents of the configuration use the\nsame rules as the\n[logger handler configuration](logger_chapter.md#handler-configuration).\n\nIf the handler is meant to replace the default handler, the Kernel's default\nhandler have to be disabled before the new handler is added. A `sys.config` file\nthat disables the Kernel handler and adds a custom handler could look like this:\n\n```erlang\n[{kernel,\n [{logger,\n %% Disable the default Kernel handler\n [{handler, default, undefined}]}]},\n {my_app,\n [{logger,\n %% Enable this handler as the default\n [{handler, default, my_handler, #{}}]}]}].\n```","ref":"logger.html#add_handlers/1"},{"type":"function","title":"logger.add_primary_filter/2","doc":"Add a primary filter to Logger.\n\nThe filter fun is called with the log event as the first parameter, and the\nspecified `filter_args()` as the second parameter.\n\nThe return value of the fun specifies if a log event is to be discarded or\nforwarded to the handlers:\n\n- **`t:log_event/0`** - The filter _passed_. The next primary filter, if any, is\n applied. If no more primary filters exist, the log event is forwarded to the\n handler part of Logger, where handler filters are applied.\n\n- **`stop`** - The filter _did not pass_, and the log event is immediately\n discarded.\n\n- **`ignore`** - The filter has no knowledge of the log event. The next primary\n filter, if any, is applied. If no more primary filters exist, the value of the\n primary `filter_default` configuration parameter specifies if the log event\n shall be discarded or forwarded to the handler part.\n\nSee section [Filters](logger_chapter.md#filters) in the User's Guide for more\ninformation about filters.\n\nSome built-in filters exist. These are defined in `m:logger_filters`.","ref":"logger.html#add_primary_filter/2"},{"type":"function","title":"logger.alert/1","doc":"","ref":"logger.html#alert/1"},{"type":"function","title":"logger.alert/2","doc":"Create a alert log event.\n\nEquivalent to [`log(alert, StringOrReport, Metadata)`](`log/3`) if called\nas [`alert(StringOrReport, Metadata)`](`alert/2`).\n\nEquivalent to [`alert(FormatOrFun, Args, #{})`](`alert/3`) if called as\n[`alert(FormatOrFun, Args)`](`alert/2`).","ref":"logger.html#alert/2"},{"type":"function","title":"logger.alert/3","doc":"","ref":"logger.html#alert/3"},{"type":"function","title":"logger.compare_levels/2","doc":"Compare the severity of two log levels. Returns `gt` if `Level1` is more severe\nthan `Level2`, `lt` if `Level1` is less severe, and `eq` if the levels are\nequal.","ref":"logger.html#compare_levels/2"},{"type":"function","title":"logger.critical/1","doc":"","ref":"logger.html#critical/1"},{"type":"function","title":"logger.critical/2","doc":"Create a critical log event.\n\nEquivalent to [`log(critical, StringOrReport, Metadata)`](`log/3`) if called\nas [`critical(StringOrReport, Metadata)`](`critical/2`).\n\nEquivalent to [`critical(FormatOrFun, Args, #{})`](`critical/3`) if called as\n[`critical(FormatOrFun, Args)`](`critical/2`).","ref":"logger.html#critical/2"},{"type":"function","title":"logger.critical/3","doc":"","ref":"logger.html#critical/3"},{"type":"function","title":"logger.debug/1","doc":"","ref":"logger.html#debug/1"},{"type":"function","title":"logger.debug/2","doc":"Create a debug log event.\n\nEquivalent to [`log(debug, StringOrReport, Metadata)`](`log/3`) if called\nas [`debug(StringOrReport, Metadata)`](`debug/2`).\n\nEquivalent to [`debug(FormatOrFun, Args, #{})`](`debug/3`) if called as\n[`debug(FormatOrFun, Args)`](`debug/2`).","ref":"logger.html#debug/2"},{"type":"function","title":"logger.debug/3","doc":"","ref":"logger.html#debug/3"},{"type":"function","title":"logger.emergency/1","doc":"","ref":"logger.html#emergency/1"},{"type":"function","title":"logger.emergency/2","doc":"Create a emergency log event.\n\nEquivalent to [`log(emergency, StringOrReport, Metadata)`](`log/3`) if called\nas [`emergency(StringOrReport, Metadata)`](`emergency/2`).\n\nEquivalent to [`emergency(FormatOrFun, Args, #{})`](`emergency/3`) if called as\n[`emergency(FormatOrFun, Args)`](`emergency/2`).","ref":"logger.html#emergency/2"},{"type":"function","title":"logger.emergency/3","doc":"","ref":"logger.html#emergency/3"},{"type":"function","title":"logger.error/1","doc":"","ref":"logger.html#error/1"},{"type":"function","title":"logger.error/2","doc":"Create a error log event.\n\nEquivalent to [`log(error, StringOrReport, Metadata)`](`log/3`) if called\nas [`error(StringOrReport, Metadata)`](`error/2`).\n\nEquivalent to [`error(FormatOrFun, Args, #{})`](`error/3`) if called as\n[`error(FormatOrFun, Args)`](`error/2`).","ref":"logger.html#error/2"},{"type":"function","title":"logger.error/3","doc":"","ref":"logger.html#error/3"},{"type":"function","title":"logger.format_report/1","doc":"Convert a log message on report form to `{Format, Args}`. This is the default\nreport callback used by `m:logger_formatter` when no custom report callback is\nfound. See section [Log Message](logger_chapter.md#log-message) in the Kernel\nUser's Guide for information about report callbacks and valid forms of log\nmessages.\n\nThe function produces lines of `Key: Value` from key-value lists. Strings are\nprinted with `~ts` and other terms with `~tp`.\n\nIf `Report` is a map, it is converted to a key-value list before formatting as\nsuch.","ref":"logger.html#format_report/1"},{"type":"function","title":"logger.get_config/0","doc":"Look up all current Logger configuration, including primary, handler, and proxy\nconfiguration, and module level settings.","ref":"logger.html#get_config/0"},{"type":"function","title":"logger.get_handler_config/0","doc":"Look up the current configuration for all handlers.","ref":"logger.html#get_handler_config/0"},{"type":"function","title":"logger.get_handler_config/1","doc":"Look up the current configuration for the given handler.","ref":"logger.html#get_handler_config/1"},{"type":"function","title":"logger.get_handler_ids/0","doc":"Look up the identities for all installed handlers.","ref":"logger.html#get_handler_ids/0"},{"type":"function","title":"logger.get_module_level/0","doc":"Look up all current module levels. Returns a list containing one\n`{Module,Level}` element for each module for which the module level was\npreviously set with `set_module_level/2`.","ref":"logger.html#get_module_level/0"},{"type":"function","title":"logger.get_module_level/1","doc":"Look up the current level for the given modules. Returns a list containing one\n`{Module,Level}` element for each of the given modules for which the module\nlevel was previously set with `set_module_level/2`.","ref":"logger.html#get_module_level/1"},{"type":"function","title":"logger.get_primary_config/0","doc":"Look up the current primary configuration for Logger.","ref":"logger.html#get_primary_config/0"},{"type":"function","title":"logger.get_process_metadata/0","doc":"Retrieve data set with `set_process_metadata/1` or `update_process_metadata/1`.","ref":"logger.html#get_process_metadata/0"},{"type":"function","title":"logger.get_proxy_config/0","doc":"Look up the current configuration for the Logger proxy.\n\nFor more information about the proxy, see section\n[Logger Proxy](logger_chapter.md#logger-proxy) in the Kernel User's Guide.","ref":"logger.html#get_proxy_config/0"},{"type":"function","title":"logger.i/0","doc":"Pretty print all Logger configuration.","ref":"logger.html#i/0"},{"type":"function","title":"logger.i/1","doc":"Pretty print the Logger configuration.","ref":"logger.html#i/1"},{"type":"function","title":"logger.info/1","doc":"","ref":"logger.html#info/1"},{"type":"function","title":"logger.info/2","doc":"Create a info log event.\n\nEquivalent to [`log(info, StringOrReport, Metadata)`](`log/3`) if called\nas [`info(StringOrReport, Metadata)`](`info/2`).\n\nEquivalent to [`info(FormatOrFun, Args, #{})`](`info/3`) if called as\n[`info(FormatOrFun, Args)`](`info/2`).","ref":"logger.html#info/2"},{"type":"function","title":"logger.info/3","doc":"","ref":"logger.html#info/3"},{"type":"function","title":"logger.log/2","doc":"","ref":"logger.html#log/2"},{"type":"function","title":"logger.log/3","doc":"Create a log event at the given [log level](logger_chapter.md#log-level), with\nthe given [message](logger_chapter.md#log-message) to be logged and\n[_metadata_](logger_chapter.md#metadata).\n\n*Example*:\n\n```erlang\n%% A plain string\n1> logger:log(info, \"Hello World\").\n%% A plain string with metadata\n2> logger:log(debug, \"Hello World\", #{ meta => data }).\n%% A format string with arguments\n3> logger:log(warning, \"The roof is on ~ts\",[Cause]).\n%% A report\n4> logger:log(warning, #{ what => roof, cause => Cause }).\n```\n\nEquivalent to [`log(Level, FormatOrFun, Args, #{})`](`log/4`) if called as\n`log(Level, FormatOrFun, Args)`.","ref":"logger.html#log/3"},{"type":"function","title":"logger.log/4","doc":"Create a log event at the given [log level](logger_chapter.md#log-level), with\nthe given [message](logger_chapter.md#log-message) to be logged and\n[_metadata_](logger_chapter.md#metadata).\n\nThe message and metadata can either be given directly in the arguments, or\nreturned from a fun. Passing a fun instead of the message/metadata directly is\nuseful in scenarios when the message/metadata is very expensive to compute. This\nis because the fun is only evaluated when the message/metadata is actually\nneeded, which may be not at all if the log event is not to be logged. Examples:\n\n```erlang\n%% A plain string with expensive metadata\n1> logger:info(fun([]) -> {\"Hello World\", #{ meta => expensive() }} end,[]).\n%% An expensive report\n2> logger:debug(fun(What) -> #{ what => What, cause => expensive() } end,roof).\n%% A plain string with expensive metadata and normal metadata\n3> logger:debug(fun([]) -> {\"Hello World\", #{ meta => expensive() }} end,[],\n #{ meta => data }).\n```\n\nWhen metadata is given both as an argument and returned from the fun they are\nmerged. If equal keys exists the values are taken from the metadata returned by\nthe fun.","ref":"logger.html#log/4"},{"type":"function","title":"logger.notice/1","doc":"","ref":"logger.html#notice/1"},{"type":"function","title":"logger.notice/2","doc":"Create a notice log event.\n\nEquivalent to [`log(notice, StringOrReport, Metadata)`](`log/3`) if called\nas [`notice(StringOrReport, Metadata)`](`notice/2`).\n\nEquivalent to [`notice(FormatOrFun, Args, #{})`](`notice/3`) if called as\n[`notice(FormatOrFun, Args)`](`notice/2`).","ref":"logger.html#notice/2"},{"type":"function","title":"logger.notice/3","doc":"","ref":"logger.html#notice/3"},{"type":"function","title":"logger.reconfigure/0","doc":"Reconfigure Logger using updated `kernel` configuration that was set after\n`kernel` application was loaded.\n\nBeware, that this is meant to be run only by the build tools, not manually\nduring application lifetime, as this may cause missing log entries.","ref":"logger.html#reconfigure/0"},{"type":"function","title":"logger.remove_handler/1","doc":"Remove the handler identified by `HandlerId`.","ref":"logger.html#remove_handler/1"},{"type":"function","title":"logger.remove_handler_filter/2","doc":"Remove the filter identified by `FilterId` from the handler identified by\n`HandlerId`.","ref":"logger.html#remove_handler_filter/2"},{"type":"function","title":"logger.remove_primary_filter/1","doc":"Remove the primary filter identified by `FilterId` from Logger.","ref":"logger.html#remove_primary_filter/1"},{"type":"function","title":"logger.set_application_level/2","doc":"Set the log level for all the modules of the specified application.\n\nThis function is a convenience function that calls\n[logger:set_module_level/2](`set_module_level/2`) for each module associated\nwith an application.","ref":"logger.html#set_application_level/2"},{"type":"function","title":"logger.set_handler_config/2","doc":"Set configuration data for the specified handler. This overwrites the current\nhandler configuration.\n\nTo modify the existing configuration, use `update_handler_config/2`, or, if a\nmore complex merge is needed, read the current configuration with\n[`get_handler_config/1` ](`get_handler_config/1`), then do the merge before\nwriting the new configuration back with this function.\n\nIf a key is removed compared to the current configuration, and the key is known\nby Logger, the default value is used. If it is a custom key, then it is up to\nthe handler implementation if the value is removed or a default value is\ninserted.","ref":"logger.html#set_handler_config/2"},{"type":"function","title":"logger.set_handler_config/3","doc":"Add or update configuration data for the specified handler. If the given `Key`\nalready exists, its associated value will be changed to the given value. If it\ndoes not exist, it will be added.\n\nIf the value is incomplete, which for example can be the case for the `config`\nkey, it is up to the handler implementation how the unspecified parts are set.\nFor all handlers in the Kernel application, unspecified data for the `config`\nkey is set to default values. To update only specified data, and keep the\nexisting configuration for the rest, use `update_handler_config/3`.\n\nSee the definition of the `t:logger_handler:config/0` type for more information\nabout the different parameters.","ref":"logger.html#set_handler_config/3"},{"type":"function","title":"logger.set_module_level/2","doc":"Set the log level for the specified modules.\n\nThe log level for a module overrides the primary log level of Logger for log\nevents originating from the module in question. Notice, however, that it does\nnot override the level configuration for any handler.\n\nFor example: Assume that the primary log level for Logger is `info`, and there\nis one handler, `h1`, with level `info` and one handler, `h2`, with level\n`debug`.\n\nWith this configuration, no debug messages will be logged, since they are all\nstopped by the primary log level.\n\nIf the level for `mymodule` is now set to `debug`, then debug events from this\nmodule will be logged by the handler `h2`, but not by handler `h1`.\n\nDebug events from other modules are still not logged.\n\nTo change the primary log level for Logger, use\n[`set_primary_config(level, Level)`](`set_primary_config/2`).\n\nTo change the log level for a handler, use\n[`set_handler_config(HandlerId, level, Level)` ](`set_handler_config/3`).\n\n> #### Note {: .info }\n>\n> The originating module for a log event is only detected if the key `mfa`\n> exists in the metadata, and is associated with `{Module, Function, Arity}`.\n> When log macros are used, this association is automatically added to all log\n> events. If an API function is called directly, without using a macro, the\n> logging client must explicitly add this information if module levels shall\n> have any effect.","ref":"logger.html#set_module_level/2"},{"type":"function","title":"logger.set_primary_config/1","doc":"Set primary configuration data for Logger. This overwrites the current\nconfiguration.\n\nTo modify the existing configuration, use `update_primary_config/1`, or, if a\nmore complex merge is needed, read the current configuration with\n[`get_primary_config/0` ](`get_primary_config/0`), then do the merge before\nwriting the new configuration back with this function.\n\nIf a key is removed compared to the current configuration, the default value is\nused.","ref":"logger.html#set_primary_config/1"},{"type":"function","title":"logger.set_primary_config/2","doc":"Add or update primary configuration data for Logger. If the given `Key` already\nexists, its associated value will be changed to the given value. If it does not\nexist, it will be added.\n\nThe `metadata` key was added in OTP 24.0.","ref":"logger.html#set_primary_config/2"},{"type":"function","title":"logger.set_process_metadata/1","doc":"Set metadata which Logger shall automatically insert in all log events produced\non the current process.\n\nLocation data produced by the log macros, and/or metadata given as argument to\nthe log call (API function or macro), are merged with the process metadata. If\nthe same keys occur, values from the metadata argument to the log call overwrite\nvalues from the process metadata, which in turn overwrite values from the\nlocation data.\n\nSubsequent calls to this function overwrites previous data set. To update\nexisting data instead of overwriting it, see `update_process_metadata/1`.","ref":"logger.html#set_process_metadata/1"},{"type":"function","title":"logger.set_proxy_config/1","doc":"Set configuration data for the Logger proxy. This overwrites the current proxy\nconfiguration. Keys that are not specified in the `Config` map gets default\nvalues.\n\nTo modify the existing configuration, use `update_proxy_config/1`, or, if a more\ncomplex merge is needed, read the current configuration with\n[`get_proxy_config/0` ](`get_proxy_config/0`), then do the merge before writing\nthe new configuration back with this function.\n\nFor more information about the proxy, see section\n[Logger Proxy](logger_chapter.md#logger-proxy) in the Kernel User's Guide.","ref":"logger.html#set_proxy_config/1"},{"type":"function","title":"logger.timestamp/0","doc":"Return a timestamp that can be inserted as the `time` field in the meta data for\na log event. It is produced with\n[`os:system_time(microsecond)`](`os:system_time/1`).\n\nNotice that Logger automatically inserts a timestamp in the meta data unless it\nalready exists. This function is exported for the rare case when the timestamp\nmust be taken at a different point in time than when the log event is issued.","ref":"logger.html#timestamp/0"},{"type":"function","title":"logger.unset_application_level/1","doc":"Unset the log level for all the modules of the specified application.\n\nThis function is a utility function that calls\n[logger:unset_module_level/2](`unset_module_level/1`) for each module associated\nwith an application.","ref":"logger.html#unset_application_level/1"},{"type":"function","title":"logger.unset_module_level/0","doc":"Remove module specific log settings. After this, the primary log level is used\nfor all modules.","ref":"logger.html#unset_module_level/0"},{"type":"function","title":"logger.unset_module_level/1","doc":"Remove module specific log settings. After this, the primary log level is used\nfor the specified modules.","ref":"logger.html#unset_module_level/1"},{"type":"function","title":"logger.unset_process_metadata/0","doc":"Delete data set with `set_process_metadata/1` or `update_process_metadata/1`.","ref":"logger.html#unset_process_metadata/0"},{"type":"function","title":"logger.update_formatter_config/2","doc":"Update the formatter configuration for the specified handler.\n\nThe new configuration is merged with the existing formatter configuration.\n\nTo overwrite the existing configuration without any merge, use\n\n```erlang\nset_handler_config(HandlerId, formatter,\n\t {FormatterModule, FormatterConfig}).\n```","ref":"logger.html#update_formatter_config/2"},{"type":"function","title":"logger.update_formatter_config/3","doc":"","ref":"logger.html#update_formatter_config/3"},{"type":"function","title":"logger.update_handler_config/2","doc":"Update configuration data for the specified handler. This function behaves as if\nit was implemented as follows:\n\n```erlang\n{ok, {_, Old}} = logger:get_handler_config(HandlerId),\nlogger:set_handler_config(HandlerId, maps:merge(Old, Config)).\n```\n\nTo overwrite the existing configuration without any merge, use\n[`set_handler_config/2` ](`set_handler_config/2`).","ref":"logger.html#update_handler_config/2"},{"type":"function","title":"logger.update_handler_config/3","doc":"Add or update configuration data for the specified handler. If the given `Key`\nalready exists, its associated value will be changed to the given value. If it\ndoes not exist, it will be added.\n\nIf the value is incomplete, which for example can be the case for the `config`\nkey, it is up to the handler implementation how the unspecified parts are set.\nFor all handlers in the Kernel application, unspecified data for the `config`\nkey is not changed. To reset unspecified data to default values, use\n`set_handler_config/3`.\n\nSee the definition of the `t:logger_handler:config/0` type for more information\nabout the different parameters.","ref":"logger.html#update_handler_config/3"},{"type":"function","title":"logger.update_primary_config/1","doc":"Update primary configuration data for Logger. This function behaves as if it was\nimplemented as follows:\n\n```erlang\nOld = logger:get_primary_config(),\nlogger:set_primary_config(maps:merge(Old, Config)).\n```\n\nTo overwrite the existing configuration without any merge, use\n[`set_primary_config/1` ](`set_primary_config/1`).","ref":"logger.html#update_primary_config/1"},{"type":"function","title":"logger.update_process_metadata/1","doc":"Set or update metadata to use when logging from current process\n\nIf process metadata exists for the current process, this function behaves as if\nit was implemented as follows:\n\n```erlang\nlogger:set_process_metadata(maps:merge(logger:get_process_metadata(), Meta)).\n```\n\nIf no process metadata exists, the function behaves as\n[`set_process_metadata/1` ](`set_process_metadata/1`).","ref":"logger.html#update_process_metadata/1"},{"type":"function","title":"logger.update_proxy_config/1","doc":"Update configuration data for the Logger proxy. This function behaves as if it\nwas implemented as follows:\n\n```erlang\nOld = logger:get_proxy_config(),\nlogger:set_proxy_config(maps:merge(Old, Config)).\n```\n\nTo overwrite the existing configuration without any merge, use\n[`set_proxy_config/1` ](`set_proxy_config/1`).\n\nFor more information about the proxy, see section\n[Logger Proxy](logger_chapter.md#logger-proxy) in the Kernel User's Guide.","ref":"logger.html#update_proxy_config/1"},{"type":"function","title":"logger.warning/1","doc":"","ref":"logger.html#warning/1"},{"type":"function","title":"logger.warning/2","doc":"Create a warning log event.\n\nEquivalent to [`log(warning, StringOrReport, Metadata)`](`log/3`) if called\nas [`warning(StringOrReport, Metadata)`](`warning/2`).\n\nEquivalent to [`warning(FormatOrFun, Args, #{})`](`warning/3`) if called as\n[`warning(FormatOrFun, Args)`](`warning/2`).","ref":"logger.html#warning/2"},{"type":"function","title":"logger.warning/3","doc":"","ref":"logger.html#warning/3"},{"type":"type","title":"logger.config_handler/0","doc":"Configuration used when adding or updating a handler.","ref":"logger.html#t:config_handler/0"},{"type":"type","title":"logger.filter/0","doc":"A filter which can be installed as a handler filter, or as a primary filter in\nLogger.","ref":"logger.html#t:filter/0"},{"type":"type","title":"logger.filter_arg/0","doc":"The second argument to the filter fun.","ref":"logger.html#t:filter_arg/0"},{"type":"type","title":"logger.filter_id/0","doc":"A unique identifier for a filter.","ref":"logger.html#t:filter_id/0"},{"type":"type","title":"logger.filter_return/0","doc":"The return value from the filter fun.","ref":"logger.html#t:filter_return/0"},{"type":"type","title":"logger.formatter_config/0","doc":"Configuration data for the formatter. See `m:logger_formatter` for an example of\na formatter implementation.","ref":"logger.html#t:formatter_config/0"},{"type":"type","title":"logger.handler_config/0","doc":"Handler configuration data for Logger.\n\n> #### Note {: .info }\n>\n> DEPRECATED: Use `t:logger_handler:config/0` instead.","ref":"logger.html#t:handler_config/0"},{"type":"type","title":"logger.handler_id/0","doc":"A unique identifier for a handler instance.\n\n> #### Note {: .info }\n>\n> DEPRECATED: Use `t:logger_handler:id/0` instead.","ref":"logger.html#t:handler_id/0"},{"type":"type","title":"logger.level/0","doc":"The severity level for the message to be logged.","ref":"logger.html#t:level/0"},{"type":"type","title":"logger.log_event/0","doc":"A log event passed to filters and handlers","ref":"logger.html#t:log_event/0"},{"type":"type","title":"logger.metadata/0","doc":"Metadata for the log event.\n\nLogger adds the following metadata to each log event:\n\n- `pid => self()`\n- `gl => group_leader()`\n- `time => logger:timestamp()`\n\nWhen a log macro is used, Logger also inserts location information:\n\n- `mfa => {?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY}`\n- `file => ?FILE`\n- `line => ?LINE`\n\nYou can add custom metadata, either by:\n\n- specifying a map as the last parameter to any of the log macros or the logger\n API functions.\n- setting process metadata with `set_process_metadata/1` or\n `update_process_metadata/1`.\n- setting primary metadata with `set_primary_config/1` or through the kernel\n configuration parameter [logger_metadata](kernel_app.md#logger_metadata)\n\n> #### Note {: .info }\n>\n> When adding custom metadata, make sure not to use any of the keys mentioned\n> above as that may cause a lot of confusion about the log events.\n\nLogger merges all the metadata maps before forwarding the log event to the\nhandlers. If the same keys occur, values from the log call overwrite process\nmetadata, which overwrites the primary metadata, which in turn overwrite values\nset by Logger.\n\nThe following custom metadata keys have special meaning:\n\n- **`domain`** - The value associated with this key is used by filters for\n grouping log events originating from, for example, specific functional areas.\n See `logger_filters:domain/2` for a description of how this field can be used.\n\n- **`report_cb`** - If the log message is specified as a `t:report/0`, the\n `report_cb` key can be associated with a fun (report callback) that converts\n the report to a format string and arguments, or directly to a string. See the\n type definition of `t:report_cb/0`, and section\n [Log Message](logger_chapter.md#log-message) in the User's Guide for more\n information about report callbacks.","ref":"logger.html#t:metadata/0"},{"type":"type","title":"logger.msg_fun/0","doc":"","ref":"logger.html#t:msg_fun/0"},{"type":"type","title":"logger.msg_fun_return/0","doc":"","ref":"logger.html#t:msg_fun_return/0"},{"type":"type","title":"logger.olp_config/0","doc":"Overload protection configuration.\n\n> #### Note {: .info }\n>\n> DEPRECATED: Use `t:logger_handler:olp_config/0` instead.","ref":"logger.html#t:olp_config/0"},{"type":"type","title":"logger.primary_config/0","doc":"Primary configuration data for Logger. The following default values apply:\n\n- `level => info`\n- `filter_default => log`\n- `filters => []`","ref":"logger.html#t:primary_config/0"},{"type":"type","title":"logger.report/0","doc":"A log report.","ref":"logger.html#t:report/0"},{"type":"type","title":"logger.report_cb/0","doc":"A fun which converts a [`report()`](`t:report/0`) to a format string and\narguments, or directly to a string.\n\nSee section [Log Message](logger_chapter.md#log-message) in the User's Guide\nfor more information.","ref":"logger.html#t:report_cb/0"},{"type":"type","title":"logger.report_cb_config/0","doc":"","ref":"logger.html#t:report_cb_config/0"},{"type":"type","title":"logger.timestamp/0","doc":"A timestamp produced with [`logger:timestamp()`](`timestamp/0`).","ref":"logger.html#t:timestamp/0"},{"type":"module","title":"logger_disk_log_h","doc":"A disk_log based handler for Logger\n\nThis is a handler for Logger that offers circular (wrapped) logs by using\n`m:disk_log`. Multiple instances of this handler can be added to Logger, and\neach instance prints to its own disk log file, created with the name and\nsettings specified in the handler configuration.\n\nThe default standard handler, `m:logger_std_h`, can be replaced by a disk_log\nhandler at startup of the Kernel application. See an example of this below.\n\nThe handler has an overload protection mechanism that keeps the handler process\nand the Kernel application alive during high loads of log events. How overload\nprotection works, and how to configure it, is described in the\n[`User's Guide`](logger_chapter.md#overload_protection).\n\nTo add a new instance of the disk_log handler, use\n[`logger:add_handler/3`](`logger:add_handler/3`). The handler configuration\nargument is a map which can contain general configuration parameters, as\ndocumented in the [`User's Guide`](logger_chapter.md#handler-configuration),\nand handler specific parameters. The specific data is stored in a sub map with\nthe key `config`, and can contain the following parameters:\n\n- **`file`** - This is the full name of the disk log file. The option\n corresponds to the `name` property in the [`dlog_option()`](`disk_log:open/1`)\n datatype.\n\n The value is set when the handler is added, and it cannot be changed in\n runtime.\n\n Defaults to the same name as the handler identity, in the current directory.\n\n- **`type`** - This is the disk log type, `wrap` or `halt`. The option\n corresponds to the `type` property in the [`dlog_option()`](`disk_log:open/1`)\n datatype.\n\n The value is set when the handler is added, and it cannot be changed in\n runtime.\n\n Defaults to `wrap`.\n\n- **`max_no_files`** - This is the maximum number of files that disk_log uses\n for its circular logging. The option corresponds to the `MaxNoFiles` element\n in the `size` property in the [`dlog_option()`](`disk_log:open/1`) datatype.\n\n The value is set when the handler is added, and it cannot be changed in\n runtime.\n\n Defaults to `10`.\n\n The setting has no effect on a halt log.\n\n- **`max_no_bytes`** - This is the maximum number of bytes that is written to a\n log file before disk_log proceeds with the next file in order, or generates an\n error in case of a full halt log. The option corresponds to the `MaxNoBytes`\n element in the `size` property in the [`dlog_option()`](`disk_log:open/1`)\n datatype.\n\n The value is set when the handler is added, and it cannot be changed in\n runtime.\n\n Defaults to `1048576` bytes for a wrap log, and `infinity` for a halt log.\n\n- **`filesync_repeat_interval`** - This value, in milliseconds, specifies how\n often the handler does a disk_log sync operation to write buffered data to\n disk. The handler attempts the operation repeatedly, but only performs a new\n sync if something has actually been logged.\n\n Defaults to `5000` milliseconds.\n\n If `no_repeat` is set as value, the repeated sync operation is disabled. The\n user can also call the [`filesync/1`](`filesync/1`) function to perform a\n disk_log sync.\n\nOther configuration parameters exist, to be used for customizing the overload\nprotection behaviour. The same parameters are used both in the standard handler\nand the disk_log handler, and are documented in the\n[`User's Guide`](logger_chapter.md#overload_protection).\n\nNotice that when changing the configuration of the handler in runtime, the\ndisk_log options (`file`, `type`, `max_no_files`, `max_no_bytes`) must not be\nmodified.\n\nExample of adding a disk_log handler:\n\n```erlang\nlogger:add_handler(my_disk_log_h, logger_disk_log_h,\n #{config => #{file => \"./my_disk_log\",\n type => wrap,\n max_no_files => 4,\n max_no_bytes => 10000,\n filesync_repeat_interval => 1000}}).\n```\n\nTo use the disk_log handler instead of the default standard handler when\nstarting an Erlang node, change the Kernel default logger to use\n`logger_disk_log_h`. Example:\n\n```text\nerl -kernel logger '[{handler,default,logger_disk_log_h,\n #{config => #{file => \"./system_disk_log\"}}}]'\n```","ref":"logger_disk_log_h.html"},{"type":"module","title":"See Also - logger_disk_log_h","doc":"`m:logger`, `m:logger_std_h`, `m:disk_log`","ref":"logger_disk_log_h.html#module-see-also"},{"type":"function","title":"logger_disk_log_h.filesync/1","doc":"Write buffered data to disk.","ref":"logger_disk_log_h.html#filesync/1"},{"type":"module","title":"logger_filters","doc":"Filters to use with Logger.\n\nAll functions exported from this module can be used as primary or handler\nfilters. See `logger:add_primary_filter/2` and `logger:add_handler_filter/3` for\nmore information about how filters are added.\n\nFilters are removed with `logger:remove_primary_filter/1` and\n`logger:remove_handler_filter/2`.","ref":"logger_filters.html"},{"type":"module","title":"See Also - logger_filters","doc":"`m:logger`","ref":"logger_filters.html#module-see-also"},{"type":"function","title":"logger_filters.domain/2","doc":"This filter provides a way of filtering log events based on a `domain` field in\n`Metadata`. This field is optional, and the purpose of using it is to group log\nevents from, for example, a specific functional area. This allows filtering or\nother specialized treatment in a Logger handler.\n\nA domain field must be a list of atoms, creating smaller and more specialized\ndomains as the list grows longer. The greatest domain is `[]`, which comprises\nall possible domains.\n\nFor example, consider the following domains:\n\n```erlang\nD1 = [otp]\nD2 = [otp, sasl]\n```\n\n`D1` is the greatest of the two, and is said to be a super-domain of `D2`. `D2`\nis a sub-domain `D1`. Both `D1` and `D2` are sub-domains of `[]`.\n\nThe above domains are used for logs originating from Erlang/OTP. D1 specifies\nthat the log event comes from Erlang/OTP in general, and D2 indicates that the\nlog event is a so called [SASL report](logger_chapter.md#sasl_reports).\n\nThe `Extra` parameter to the [`domain/2`](`domain/2`) function is specified when\nadding the filter via `logger:add_primary_filter/2` or\n`logger:add_handler_filter/3`.\n\nThe filter compares the value of the `domain` field in the log event's metadata\n(`Domain`) against `MatchDomain`. The filter matches if the value of `Compare`\nis:\n\n- **`sub`** - and `Domain` is equal to or a sub-domain of `MatchDomain`, that\n is, if `MatchDomain` is a prefix of `Domain`.\n\n- **`super`** - and `Domain` is equal to or a super-domain of `MatchDomain`,\n that is, if `Domain` is a prefix of `MatchDomain`.\n\n- **`equal`** - and `Domain` is equal to `MatchDomain`.\n\n- **`not_equal`** - and `Domain` differs from `MatchDomain`, or if there is no\n domain field in metadata.\n\n- **`undefined`** - and there is no domain field in metadata. In this case\n `MatchDomain` must be set to `[]`.\n\nIf the filter matches and `Action` is `log`, the log event is allowed. If the\nfilter matches and `Action` is `stop`, the log event is stopped.\n\nIf the filter does not match, it returns `ignore`, meaning that other filters,\nor the value of the configuration parameter `filter_default`, decide if the\nevent is allowed or not.\n\nLog events that do not contain any domain field, match only when `Compare` is\nequal to `undefined` or `not_equal`.\n\nExample: stop all events with domain `[otp, sasl | _]`\n\n```erlang\n1> logger:set_handler_config(h1, filter_default, log). % this is the default\nok\n2> Filter = {fun logger_filters:domain/2, {stop, sub, [otp, sasl]}}.\n...\n3> logger:add_handler_filter(h1, no_sasl, Filter).\nok\n```","ref":"logger_filters.html#domain/2"},{"type":"function","title":"logger_filters.level/2","doc":"This filter provides a way of filtering log events based on the log level. It\nmatches log events by comparing the log level with a specified `MatchLevel`\n\nThe `Extra` parameter is specified when adding the filter via\n`logger:add_primary_filter/2` or `logger:add_handler_filter/3`.\n\nThe filter compares the value of the event's log level (`Level`) to `MatchLevel`\nby calling\n[`logger:compare_levels(Level, MatchLevel)`](`logger:compare_levels/2`). The\nfilter matches if the value of `Operator` is:\n\n- **`neq`** - and the compare function returns `lt` or `gt`.\n\n- **`eq`** - and the compare function returns `eq`.\n\n- **`lt`** - and the compare function returns `lt`.\n\n- **`gt`** - and the compare function returns `gt`.\n\n- **`lteq`** - and the compare function returns `lt` or `eq`.\n\n- **`gteq`** - and the compare function returns `gt` or `eq`.\n\nIf the filter matches and `Action` is `log`, the log event is allowed. If the\nfilter matches and `Action` is `stop`, the log event is stopped.\n\nIf the filter does not match, it returns `ignore`, meaning that other filters,\nor the value of the configuration parameter `filter_default`, will decide if the\nevent is allowed or not.\n\nExample: only allow debug level log events\n\n```erlang\nlogger:set_handler_config(h1, filter_default, stop).\nFilter = {fun logger_filters:level/2, {log, eq, debug}}.\nlogger:add_handler_filter(h1, debug_only, Filter).\nok\n```","ref":"logger_filters.html#level/2"},{"type":"function","title":"logger_filters.progress/2","doc":"This filter matches all progress reports from `m:supervisor` and\n[`application_controller`](`m:application`).\n\nIf `Extra` is `log`, the progress reports are allowed. If `Extra` is `stop`, the\nprogress reports are stopped.\n\nThe filter returns `ignore` for all other log events.","ref":"logger_filters.html#progress/2"},{"type":"function","title":"logger_filters.remote_gl/2","doc":"This filter matches all events originating from a process that has its group\nleader on a remote node.\n\nIf `Extra` is `log`, the matching events are allowed. If `Extra` is `stop`, the\nmatching events are stopped.\n\nThe filter returns `ignore` for all other log events.","ref":"logger_filters.html#remote_gl/2"},{"type":"behaviour","title":"logger_formatter","doc":"Default formatter for Logger.\n\nEach Logger handler has a configured formatter specified as a module and a\nconfiguration term. The purpose of the formatter is to translate the log events\nto a final printable string ([`unicode:chardata()`](`t:unicode:chardata/0`))\nwhich can be written to the output device of the handler. See sections\n[Handlers](logger_chapter.md#handlers) and\n[Formatters](logger_chapter.md#formatters) in the Kernel User's Guide for more\ninformation.\n\n`m:logger_formatter` is the default formatter used by Logger.","ref":"logger_formatter.html"},{"type":"behaviour","title":"See Also - logger_formatter","doc":"`m:calendar`, `m:error_logger`, `m:io`, `m:io_lib`, `m:logger`, `m:maps`,\n[`sasl(6)`](`e:sasl:sasl_app.md`), `m:unicode`","ref":"logger_formatter.html#module-see-also"},{"type":"function","title":"logger_formatter.check_config/1","doc":"The function is called by Logger when the formatter configuration for a handler\nis set or modified. It returns `ok` if the configuration is valid, and\n`{error,term()}` if it is faulty.\n\nThe following Logger API functions can trigger this callback:\n\n- `logger:add_handler/3`\n- [`logger:set_handler_config/2,3`](`logger:set_handler_config/2`)\n- `logger:update_handler_config/2`\n- `logger:update_formatter_config/2`","ref":"logger_formatter.html#check_config/1"},{"type":"callback","title":"logger_formatter.check_config/1","doc":"The function is called by a Logger when formatter configuration is set or\nmodified. The formatter must validate the given configuration and return `ok` if\nit is correct, and `{error,Reason}` if it is faulty.\n\nThe following Logger API functions can trigger this callback:\n\n- `logger:add_handler/3`\n- [`logger:set_handler_config/2,3`](`logger:set_handler_config/2`)\n- [`logger:update_handler_config/2,3`](`logger:update_handler_config/2`)\n- `logger:update_formatter_config/2`\n\nSee `m:logger_formatter` for an example implementation. `m:logger_formatter` is\nthe default formatter used by Logger.","ref":"logger_formatter.html#c:check_config/1"},{"type":"function","title":"logger_formatter.format/2","doc":"This the formatter callback function to be called from handlers.\n\nThe log event is processed as follows:\n\n- If the message is on report form, it is converted to `{Format,Args}` by\n calling the report callback. See section\n [Log Message](logger_chapter.md#log-message) in the Kernel User's Guide for\n more information about report callbacks and valid forms of log messages.\n- The message size is limited according to the values of configuration\n parameters [`chars_limit`](`m:logger_formatter#chars_limit`) and\n [`depth`](`m:logger_formatter#depth`).\n- The full log entry is composed according to the\n [`template`](`m:logger_formatter#template`).\n- If the final string is too long, it is truncated according to the value of\n configuration parameter [`max_size`](`m:logger_formatter#max_size`).","ref":"logger_formatter.html#format/2"},{"type":"callback","title":"logger_formatter.format/2","doc":"The function can be called by a log handler to convert a log event term to a\nprintable string. The returned value can, for example, be printed as a log entry\nto the console or a file using [`io:put_chars/1,2`](`io:put_chars/1`).\n\nSee `m:logger_formatter` for an example implementation. `m:logger_formatter` is\nthe default formatter used by Logger.","ref":"logger_formatter.html#c:format/2"},{"type":"type","title":"logger_formatter.config/0","doc":"The configuration term for `logger_formatter` is a [map](`m:maps`), and the\nfollowing keys can be set as configuration parameters:\n\n- **`chars_limit = integer() > 0 | unlimited`{: #chars_limit }** - A positive\n integer representing the value of the option with the same name to be used\n when calling `io_lib:format/3`. This value limits the total number of\n characters printed for each log event. Notice that this is a soft limit. For a\n hard truncation limit, see option `max_size`.\n\n Defaults to `unlimited`.\n\n- **`depth = integer() > 0 | unlimited`{: #depth }** - A positive integer\n representing the maximum depth to which terms shall be printed by this\n formatter. Format strings passed to this formatter are rewritten. The format\n controls ~p and ~w are replaced with ~P and ~W, respectively, and the value is\n used as the depth parameter. For details, see [`io:format/2,3`](`io:format/2`)\n in STDLIB.\n\n Defaults to `unlimited`.\n\n- **`legacy_header = boolean()`** - If set to `true` a header field is added to\n logger_formatter's part of `Metadata`. The value of this field is a string\n similar to the header created by the old `m:error_logger` event handlers. It\n can be included in the log event by adding the list\n `[logger_formatter,header]` to the template. See the description of the\n `t:template/0` type for more information.\n\n Defaults to `false`.\n\n- **`max_size = integer() > 0 | unlimited`{: #max_size }** - A positive integer\n representing the absolute maximum size a string returned from this formatter\n can have. If the formatted string is longer, after possibly being limited by\n `chars_limit` or `depth`, it is truncated.\n\n Defaults to `unlimited`.\n\n- **`report_cb = ` `t:logger:report_cb/0`** - A report callback is used by the\n formatter to transform log messages on report form to a format string and\n arguments. The report callback can be specified in the metadata for the log\n event. If no report callback exists in metadata, `logger_formatter` will use\n `logger:format_report/1` as default callback.\n\n If this configuration parameter is set, it replaces both the default report\n callback, and any report callback found in metadata. That is, all reports are\n converted by this configured function.\n\n- **`single_line = boolean()`** - If set to `true`, each log event is printed as\n a single line. To achieve this, `logger_formatter` sets the field width to `0`\n for all `~p` and `~P` control sequences in the format a string (see\n `io:format/2`), and replaces all newlines in the message with `\", \"`. White\n spaces following directly after newlines are removed. Notice that newlines\n added by the `template` parameter are not replaced.\n\n Defaults to `true`.\n\n- **`template = `{: #template }`t:template/0`** - The template describes how the\n formatted string is composed by combining different data values from the log\n event. See the description of the `t:template/0` type for more information\n about this.\n\n- **`time_designator = byte()`** - Timestamps are formatted according to\n RFC3339, and the time designator is the character used as date and time\n separator.\n\n Defaults to `$T`.\n\n The value of this parameter is used as the `time_designator` option to\n `calendar:system_time_to_rfc3339/2`.\n\n- **`time_offset = integer() | [byte()]`** - The time offset, either a string or\n an integer, to be used when formatting the timestamp.\n\n An empty string is interpreted as local time. The values `\"Z\"`, `\"z\"` or `0`\n are interpreted as Universal Coordinated Time (UTC).\n\n Strings, other than `\"Z\"`, `\"z\"`, or `\"\"`, must be on the form `±[hh]:[mm]`,\n for example `\"-02:00\"` or `\"+00:00\"`.\n\n Integers must be in microseconds, meaning that the offset `7200000000` is\n equivalent to `\"+02:00\"`.\n\n Defaults to an empty string, meaning that timestamps are displayed in local\n time. However, for backwards compatibility, if the SASL configuration\n parameter [`utc_log`](`e:sasl:sasl_app.md#utc_log`)`=true`, the default is\n changed to `\"Z\"`, meaning that timestamps are displayed in UTC.\n\n The value of this parameter is used as the `offset` option to\n `calendar:system_time_to_rfc3339/2`.","ref":"logger_formatter.html#t:config/0"},{"type":"type","title":"logger_formatter.metakey/0","doc":"","ref":"logger_formatter.html#t:metakey/0"},{"type":"type","title":"logger_formatter.template/0","doc":"The template to be used by a logger formatter.\n\nThe template is a list of atoms, atom lists, tuples and strings. The atoms\n`level` or `msg`, are treated as placeholders for the severity level and the log\nmessage, respectively. Other atoms or atom lists are interpreted as placeholders\nfor metadata, where atoms are expected to match top level keys, and atom lists\nrepresent paths to sub keys when the metadata is a nested map. For example the\nlist `[key1,key2]` is replaced by the value of the `key2` field in the nested\nmap below. The atom `key1` on its own is replaced by the complete value of the\n`key1` field. The values are converted to strings.\n\n```text\n#{key1 => #{key2 => my_value,\n ...}\n ...}\n```\n\nTuples in the template express if-exist tests for metadata keys. For example,\nthe following tuple says that if `key1` exists in the metadata map, print\n`\"key1=Value\"`, where `Value` is the value that `key1` is associated with in the\nmetadata map. If `key1` does not exist, print nothing.\n\n```text\n{key1, [\"key1=\",key1], []}\n```\n\nStrings in the template are printed literally.\n\nThe default value for the `template` configuration parameter depends on the\nvalue of the `single_line` and `legacy_header` configuration parameters as\nfollows.\n\nThe log event used in the examples is:\n\n```text\n?LOG_ERROR(\"name: ~p~nexit_reason: ~p\", [my_name, \"It crashed\"])\n```\n\n- **`legacy_header = true, single_line = false`** - Default template:\n `[[logger_formatter,header],\"\\n\",msg,\"\\n\"]`\n\n Example log entry:\n\n ```text\n =ERROR REPORT==== 17-May-2018::18:30:19.453447 ===\n name: my_name\n exit_reason: \"It crashed\"\n ```\n\n Notice that all eight levels can occur in the heading, not only `ERROR`,\n `WARNING` or `INFO` as `m:error_logger` produces. And microseconds are added\n at the end of the timestamp.\n\n- **`legacy_header = true, single_line = true`** - Default template:\n `[[logger_formatter,header],\"\\n\",msg,\"\\n\"]`\n\n Notice that the template is here the same as for `single_line=false`, but the\n resulting log entry differs in that there is only one line after the heading:\n\n ```text\n =ERROR REPORT==== 17-May-2018::18:31:06.952665 ===\n name: my_name, exit_reason: \"It crashed\"\n ```\n\n- **`legacy_header = false, single_line = true`** - Default template:\n `[time,\" \",level,\": \",msg,\"\\n\"]`\n\n Example log entry:\n\n ```text\n 2018-05-17T18:31:31.152864+02:00 error: name: my_name, exit_reason: \"It crashed\"\n ```\n\n- **`legacy_header = false, single_line = false`** - Default template:\n `[time,\" \",level,\":\\n\",msg,\"\\n\"]`\n\n Example log entry:\n\n ```text\n 2018-05-17T18:32:20.105422+02:00 error:\n name: my_name\n exit_reason: \"It crashed\"\n ```","ref":"logger_formatter.html#t:template/0"},{"type":"behaviour","title":"logger_handler","doc":"logger_handler behavior module.\n\nThe behaviour module for logger handlers. A logger handler is a callback module\nthat is called when a log event has passed all filters and is ready to be logged\nsomewhere. For more information see [Handlers](logger_chapter.md#handlers) in\nthe Users Guide.","ref":"logger_handler.html"},{"type":"behaviour","title":"See Also - logger_handler","doc":"`m:logger_filters`, `m:logger_formatter`, `m:logger`","ref":"logger_handler.html#module-see-also"},{"type":"callback","title":"logger_handler.adding_handler/1","doc":"The function is called on a temporary process when a new handler is about to be\nadded. The purpose is to verify the configuration and initiate all resources\nneeded by the handler.\n\nThe handler identity is associated with the `id` key in `Config1`.\n\nIf everything succeeds, the callback function can add possible default values or\ninternal state values to the configuration, and return the adjusted map in\n`{ok,Config2}`.\n\nIf the configuration is faulty, or if the initiation fails, the callback\nfunction must return `{error,Reason}`.","ref":"logger_handler.html#c:adding_handler/1"},{"type":"callback","title":"logger_handler.changing_config/3","doc":"The function is called on a temporary process when the configuration for a\nhandler is about to change. The purpose is to verify and act on the new\nconfiguration.\n\n`OldConfig` is the existing configuration and `NewConfig` is the new\nconfiguration.\n\nThe handler identity is associated with the `id` key in `OldConfig`.\n\n`SetOrUpdate` has the value `set` if the configuration change originates from a\ncall to [`logger:set_handler_config/2,3`](`logger:set_handler_config/2`), and\n`update` if it originates from\n[`logger:update_handler_config/2,3`](`logger:update_handler_config/2`). The\nhandler can use this parameter to decide how to update the value of the `config`\nfield, that is, the handler specific configuration data. Typically, if\n`SetOrUpdate` equals `set`, values that are not specified must be given their\ndefault values. If `SetOrUpdate` equals `update`, the values found in\n`OldConfig` must be used instead.\n\nIf everything succeeds, the callback function must return a possibly adjusted\nconfiguration in `{ok,Config}`.\n\nIf the configuration is faulty, the callback function must return\n`{error,Reason}`.","ref":"logger_handler.html#c:changing_config/3"},{"type":"callback","title":"logger_handler.filter_config/1","doc":"The function is called when one of the Logger API functions for fetching the\nhandler configuration is called, for example `logger:get_handler_config/1`.\n\nIt allows the handler to remove internal data fields from its configuration data\nbefore it is returned to the caller.","ref":"logger_handler.html#c:filter_config/1"},{"type":"callback","title":"logger_handler.log/2","doc":"The function is called when all primary filters and all handler filters for the\nhandler in question have passed for the given log event. It is called on the\nclient process, that is, the process that issued the log event.\n\nThe handler identity is associated with the `id` key in `Config`.\n\nThe handler must log the event.\n\nThe return value from this function is ignored by Logger.","ref":"logger_handler.html#c:log/2"},{"type":"callback","title":"logger_handler.removing_handler/1","doc":"The function is called on a temporary process when a handler is about to be\nremoved. The purpose is to release all resources used by the handler.\n\nThe handler identity is associated with the `id` key in `Config`.\n\nThe return value is ignored by Logger.","ref":"logger_handler.html#c:removing_handler/1"},{"type":"type","title":"logger_handler.config/0","doc":"Handler configuration data for Logger. The following default values apply:\n\n- `level => all`\n- `filter_default => log`\n- `filters => []`\n- `formatter => {logger_formatter, DefaultFormatterConfig`\\}\n\nIn addition to these, the following fields are automatically inserted by Logger,\nvalues taken from the two first parameters to `logger:add_handler/3`:\n\n- `id => HandlerId`\n- `module => Module`\n\nThese are read-only and cannot be changed in runtime.\n\nHandler specific configuration data is inserted by the handler callback itself,\nin a sub structure associated with the field named `config`. See the\n`m:logger_std_h` and `m:logger_disk_log_h` manual pages for information about\nthe specific configuration for these handlers.\n\nSee the [`logger_formatter`](`t:logger_formatter:config/0`) manual page for\ninformation about the default configuration for this formatter.","ref":"logger_handler.html#t:config/0"},{"type":"type","title":"logger_handler.id/0","doc":"A unique identifier for a handler instance.","ref":"logger_handler.html#t:id/0"},{"type":"type","title":"logger_handler.olp_config/0","doc":"Overload protection configuration.\n\nSee [Protecting the Handler from Overload](logger_chapter.md#protecting-the-handler-from-overload)\nfor more details.","ref":"logger_handler.html#t:olp_config/0"},{"type":"module","title":"logger_std_h","doc":"Standard handler for Logger.\n\nThis is the standard handler for Logger. Multiple instances of this handler can\nbe added to Logger, and each instance prints logs to\n[`standard_io`](`t:io:standard_io/0`),\n[`standard_error`](`t:io:standard_error/0`), or to file.\n\nThe handler has an overload protection mechanism that keeps the handler process\nand the Kernel application alive during high loads of log events. How overload\nprotection works, and how to configure it, is described in the\n[`User's Guide`](logger_chapter.md#overload_protection).\n\nTo add a new instance of the standard handler, use\n[`logger:add_handler/3`](`logger:add_handler/3`). The handler configuration\nargument is a map which can contain general configuration parameters, as\ndocumented in the [`User's Guide`](logger_chapter.md#handler-configuration),\nand handler specific parameters. The specific data is stored in a sub map with\nthe key `config`, and can contain the following parameters:\n\n- **`type = ` `t:io:standard_io/0` ` | ` `t:io:standard_error/0` ` | file | {device, ` `t:io:device/0` `}`**{: #type } -\n Specifies the log destination.\n\n The value is set when the handler is added, and it cannot be changed in\n runtime.\n\n Defaults to [`standard_io`](`t:io:standard_io/0`), unless parameter\n [`file`](`m:logger_std_h#file`) is given, in which case it defaults to `file`.\n\n- **`file = ` `t:file:filename/0`**{: #file } - This specifies the name of the\n log file when the handler is of type `file`.\n\n The value is set when the handler is added, and it cannot be changed in\n runtime.\n\n Defaults to the same name as the handler identity, in the current directory.\n\n- **`modes = [` `t:file:mode/0` `]`**{: #modes } - This specifies the file modes\n to use when opening the log file, see `file:open/2`. If `modes` are not\n specified, the default list used is `[raw,append,delayed_write]`. If `modes`\n are specified, the list replaces the default modes list with the following\n adjustments:\n\n - If `raw` is not found in the list, it is added.\n - If none of `write`, `append` or `exclusive` is found in the list, `append`\n is added.\n - If none of `delayed_write` or `{delayed_write,Size,Delay}` is found in the\n list, `delayed_write` is added.\n\n Log files are always UTF-8 encoded. The encoding cannot be changed by setting\n the mode `{encoding,Encoding}`.\n\n The value is set when the handler is added, and it cannot be changed in\n runtime.\n\n Defaults to `[raw,append,delayed_write]`.\n\n- **`max_no_bytes = ` `t:pos_integer/0` ` | infinity`{: #max_no_bytes }** - This\n parameter specifies if the log file should be rotated or not. The value\n `infinity` means the log file will grow indefinitely, while an integer value\n specifies at which file size (bytes) the file is rotated.\n\n Defaults to `infinity`.\n\n- **`max_no_files = ` `t:non_neg_integer/0`**{: #max_no_files } - This parameter\n specifies the number of rotated log file archives to keep. This has meaning\n only if [`max_no_bytes`](`m:logger_std_h#max_no_bytes`) is set to an integer\n value.\n\n The log archives are named `FileName.0`, `FileName.1`, ... `FileName.N`, where\n `FileName` is the name of the current log file. `FileName.0` is the newest of\n the archives. The maximum value for `N` is the value of `max_no_files`\n minus 1.\n\n Notice that setting this value to `0` does not turn off rotation. It only\n specifies that no archives are kept.\n\n Defaults to `0`.\n\n- **`compress_on_rotate = ` `t:boolean/0`**{: #compress_on_rotate } - This parameter\n specifies if the rotated log file archives shall be compressed or not. If set\n to `true`, all archives are compressed with `gzip`, and renamed to\n `FileName.N.gz`\n\n `compress_on_rotate` has no meaning if\n [`max_no_bytes`](`m:logger_std_h#max_no_bytes`) has the value `infinity`.\n\n Defaults to `false`.\n\n- **`file_check = ` `t:non_neg_integer/0`**{: #file_check } - When `logger_std_h`\n logs to a file, it reads the file information of the log file prior to each\n write operation. This is to make sure the file still exists and has the same\n inode as when it was opened. This implies some performance loss, but ensures\n that no log events are lost in the case when the file has been removed or\n renamed by an external actor.\n\n In order to allow minimizing the performance loss, the `file_check` parameter\n can be set to a positive integer value, `N`. The handler will then skip\n reading the file information prior to writing, as long as no more than `N`\n milliseconds have passed since it was last read.\n\n Notice that the risk of losing log events grows when the `file_check` value\n grows.\n\n Defaults to 0.\n\n- **`filesync_repeat_interval = ` `t:pos_integer/0` ` | no_repeat`** - This value, in\n milliseconds, specifies how often the handler does a file sync operation to\n write buffered data to disk. The handler attempts the operation repeatedly,\n but only performs a new sync if something has actually been logged.\n\n If `no_repeat` is set as value, the repeated file sync operation is disabled,\n and it is the operating system settings that determine how quickly or slowly\n data is written to disk. The user can also call the `filesync/1` function to\n perform a file sync.\n\n Defaults to `5000` milliseconds.\n\nOther configuration parameters exist, to be used for customizing the overload\nprotection behaviour. The same parameters are used both in the standard handler\nand the disk_log handler, and are documented in the\n[`User's Guide`](logger_chapter.md#overload_protection).\n\nNotice that if changing the configuration of the handler in runtime, the `type`,\n`file`, or `modes` parameters must not be modified.\n\nExample of adding a standard handler:\n\n```erlang\nlogger:add_handler(my_standard_h, logger_std_h,\n #{config => #{file => \"./system_info.log\",\n filesync_repeat_interval => 1000}}).\n```\n\nTo set the default handler, that starts initially with the Kernel application,\nto log to file instead of [`standard_io`](`t:io:standard_io/0`), change the\nKernel default logger configuration. Example:\n\n```text\nerl -kernel logger '[{handler,default,logger_std_h,\n #{config => #{file => \"./log.log\"}}}]'\n```\n\nAn example of how to replace the standard handler with a disk_log handler at\nstartup is found in the `m:logger_disk_log_h` manual.","ref":"logger_std_h.html"},{"type":"module","title":"See Also - logger_std_h","doc":"`m:logger`, `m:logger_disk_log_h`","ref":"logger_std_h.html#module-see-also"},{"type":"function","title":"logger_std_h.filesync/1","doc":"Write buffered data to disk.","ref":"logger_std_h.html#filesync/1"},{"type":"module","title":"wrap_log_reader","doc":"A service to read internally formatted wrap disk logs.\n\nThis module makes it possible to read internally formatted wrap disk logs, see\n`m:disk_log`. `m:wrap_log_reader` does not interfere with `m:disk_log` activities;\nthere is however a bug in this version of the `m:wrap_log_reader`, see section\n[Known Limitations](`m:wrap_log_reader#module-known-limitations`).\n\nA wrap disk log file consists of many files, called index files. A log file can\nbe opened and closed. Also, a single index file can be opened separately. If a\nnon-existent or non-internally formatted file is opened, an error message is\nreturned. If the file is corrupt, no attempt is made to repair it, but an error\nmessage is returned.\n\nIf a log is configured to be distributed, it is possible that all items are not\nlogged on all nodes. `m:wrap_log_reader` only reads the log on the called node; it\nis up to the user to be sure that all items are read.","ref":"wrap_log_reader.html"},{"type":"module","title":"Known Limitations - wrap_log_reader","doc":"This version of `m:wrap_log_reader` does not detect if `m:disk_log` wraps to a new\nindex file between a call to `wrap_log_reader:open/1` and the first call to\n`wrap_log_reader:chunk/1`. If this occurs, the call to `chunk/1` reads the last\nlogged items in the log file, as the opened index file was truncated by\n`m:disk_log`.","ref":"wrap_log_reader.html#module-known-limitations"},{"type":"function","title":"wrap_log_reader.chunk/1","doc":"","ref":"wrap_log_reader.html#chunk/1"},{"type":"function","title":"wrap_log_reader.chunk/2","doc":"Enables to efficiently read the terms that are appended to a log. Minimises disk\nI/O by reading 64 kilobyte chunks from the file.\n\nThe first time `chunk/2` is called, an initial continuation returned from\n[`open/1`](`open/1`) or [`open/2`](`open/2`) must be provided.\n\nWhen `chunk/2` is called, `N` controls the maximum number of terms that are read\nfrom the log in each chunk. `infinity` means that all the\nterms contained in the 8K chunk are read. If less than `N` terms are returned,\nthis does not necessarily mean that end of file is reached.\n\nReturns a tuple `{Continuation2, Terms}`, where `Terms` is a list of terms found\nin the log. `Continuation2` is yet another continuation that must be passed on\nto any subsequent calls to `chunk()`. With a series of calls to `chunk()`, it is\nthen possible to extract all terms from a log.\n\nReturns a tuple `{Continuation2, Terms, Badbytes}` if the log is opened in read\nonly mode and the read chunk is corrupt. `Badbytes` indicates the number of\nnon-Erlang terms found in the chunk. Notice that the log is not repaired.\n\nReturns `{Continuation2, eof}` when the end of the log is reached, and\n`{error, Reason}` if an error occurs.\n\nThe returned continuation either is or is not valid in the next call to this\nfunction. This is because the log can wrap and delete the file into which the\ncontinuation points. To ensure this does not occur, the log can be blocked\nduring the search.","ref":"wrap_log_reader.html#chunk/2"},{"type":"function","title":"wrap_log_reader.close/1","doc":"Closes a log file properly.","ref":"wrap_log_reader.html#close/1"},{"type":"function","title":"wrap_log_reader.open/1","doc":"Equivalent to [`open(Filename, ...)`](`open/2`) except that the whole\nwrap log file is read.","ref":"wrap_log_reader.html#open/1"},{"type":"function","title":"wrap_log_reader.open/2","doc":"`Filename` specifies the name of the file to be read.\n\n`N` specifies the index of the file to be read. Use `open/1` to read the entire\nwrap log.\n\nReturns `{ok, Continuation}` if the log/index file is opened successfully.\n`Continuation` is to be used when chunking or closing the file.\n\nReturns `{error, Reason}` for all errors.","ref":"wrap_log_reader.html#open/2"},{"type":"type","title":"wrap_log_reader.chunk_ret/0","doc":"","ref":"wrap_log_reader.html#t:chunk_ret/0"},{"type":"opaque","title":"wrap_log_reader.continuation/0","doc":"Continuation returned by `open/1,2` or `chunk/1,2`.","ref":"wrap_log_reader.html#t:continuation/0"},{"type":"type","title":"wrap_log_reader.open_ret/0","doc":"","ref":"wrap_log_reader.html#t:open_ret/0"},{"type":"module","title":"seq_trace","doc":"Sequential tracing of information transfers.\n\nSequential tracing makes it possible to trace information flows between\nprocesses resulting from one initial transfer of information. Sequential tracing\nis independent of the ordinary tracing in Erlang, which is controlled by the\n`erlang:trace/3` BIF. For more information about what sequential tracing is and\nhow it can be used, see section [Sequential Tracing](`m:seq_trace#whatis`).\n\n`seq_trace` provides functions that control all aspects of sequential tracing.\nThere are functions for activation, deactivation, inspection, and for collection\nof the trace output.","ref":"seq_trace.html"},{"type":"module","title":"Trace Messages Sent to the System Tracer - seq_trace","doc":"The format of the messages is one of the following, depending on if flag\n`timestamp` of the trace token is set to `true` or `false`:\n\n```text\n{seq_trace, Label, SeqTraceInfo, TimeStamp}\n```\n\nor\n\n```text\n{seq_trace, Label, SeqTraceInfo}\n```\n\nWhere:\n\n```erlang\nLabel = int()\nTimeStamp = {Seconds, Milliseconds, Microseconds}\n Seconds = Milliseconds = Microseconds = int()\n```\n\n`SeqTraceInfo` can have the following formats:\n\n- **`{send, Serial, From, To, Message}`** - Used when a process `From` with its\n trace token flag `send` set to `true` has sent information. `To` may be a\n process identifier, a registered name on a node represented as\n `{NameAtom, NodeAtom}`, or a node name represented as an atom. `From` may be a\n process identifier or a node name represented as an atom. `Message` contains\n the information passed along in this information transfer. If the transfer is\n done via message passing, it is the actual message.\n\n- **`{'receive', Serial, From, To, Message}`** - Used when a process `To`\n receives information with a trace token that has flag `'receive'` set to\n `true`. `To` may be a process identifier, or a node name represented as an\n atom. `From` may be a process identifier or a node name represented as an\n atom. `Message` contains the information passed along in this information\n transfer. If the transfer is done via message passing, it is the actual\n message.\n\n- **`{print, Serial, From, _, Info}`** - Used when a process `From` has called\n `seq_trace:print(Label, TraceInfo)` and has a trace token with flag `print`\n set to `true`, and `label` set to `Label`.\n\n`Serial` is a tuple `{PreviousSerial, ThisSerial}`, where:\n\n- Integer `PreviousSerial` denotes the serial counter passed in the last\n received information that carried a trace token. If the process is the first\n in a new sequential trace, `PreviousSerial` is set to the value of the process\n internal \"trace clock\".\n- Integer `ThisSerial` is the serial counter that a process sets on outgoing\n messages. It is based on the process internal \"trace clock\", which is\n incremented by one before it is attached to the trace token in the message.\n\n[](){: #whatis }","ref":"seq_trace.html#module-trace-messages-sent-to-the-system-tracer"},{"type":"module","title":"Sequential Tracing - seq_trace","doc":"Sequential tracing is a way to trace a sequence of information transfers between\ndifferent local or remote processes, where the sequence is initiated by a single\ntransfer. The typical information transfer is an ordinary Erlang message passed\nbetween two processes, but information is transferred also in other ways. In\nshort, it works as follows:\n\nEach process has a _trace token_, which can be empty or not empty. When not\nempty, the trace token can be seen as the tuple `{Label, Flags, Serial, From}`.\nThe trace token is passed invisibly when information is passed between\nprocesses. In most cases the information is passed in ordinary messages between\nprocesses, but information is also passed between processes by other means. For\nexample, by spawning a new process. An information transfer between two\nprocesses is represented by a send event and a receive event regardless of how\nit is passed.\n\nTo start a sequential trace, the user must explicitly set the trace token in the\nprocess that will send the first information in a sequence.\n\nThe trace token of a process is set each time the process receives information.\nThis is typically when the process matches a message in a receive statement,\naccording to the trace token carried by the received message, empty or not.\n\nOn each Erlang node, a process can be set as the _system tracer_. This process\nwill receive trace messages each time information with a trace token is sent or\nreceived (if the trace token flag `send` or `'receive'` is set). The system\ntracer can then print each trace event, write it to a file, or whatever\nsuitable.\n\n> #### Note {: .info }\n>\n> The system tracer only receives those trace events that occur locally within\n> the Erlang node. To get the whole picture of a sequential trace, involving\n> processes on many Erlang nodes, the output from the system tracer on each\n> involved node must be merged (offline).\n\nThe following sections describe sequential tracing and its most fundamental\nconcepts.","ref":"seq_trace.html#module-sequential-tracing"},{"type":"module","title":"Different Information Transfers - seq_trace","doc":"Information flows between processes in a lot of different ways. Not all flows of\ninformation will be covered by sequential tracing. One example is information\npassed via ETS tables. Below is a list of information paths that are covered by\nsequential tracing:\n\n- **Message Passing** - All ordinary messages passed between Erlang processes.\n\n- **Exit signals** - An exit signal is represented as an `{'EXIT', Pid, Reason}`\n tuple.\n\n- **Process Spawn** - A process spawn is represented as multiple information\n transfers. At least one spawn request and one spawn reply. The actual amount\n of information transfers depends on what type of spawn it is and may also\n change in future implementations. Note that this is more or less an internal\n protocol that you are peeking at. The spawn request will be represented as a\n tuple with the first element containing the atom `spawn_request`, but this is\n more or less all that you can depend on.\n\n> #### Note {: .info }\n>\n> If you do ordinary `send` or `receive` trace on the system, you will only see\n> ordinary message passing, not the other information transfers listed above.\n\n> #### Note {: .info }\n>\n> When a send event and corresponding receive event do not both correspond to\n> ordinary Erlang messages, the `Message` part of the trace messages may not be\n> identical. This since all information not necessarily are available when\n> generating the trace messages.","ref":"seq_trace.html#module-different-information-transfers"},{"type":"module","title":"Trace Token - seq_trace","doc":"Each process has a current trace token which is \"invisibly\" passed from the\nparent process on creation of the process.\n\nThe current token of a process is set in one of the following two ways:\n\n- Explicitly by the process itself, through a call to `seq_trace:set_token/1,2`\n- When information is received. This is typically when a received message is\n matched out in a receive expression, but also when information is received in\n other ways.\n\nIn both cases, the current token is set. In particular, if the token of a\nreceived message is empty, the current token of the process is set to empty.\n\nA trace token contains a label and a set of flags. Both the label and the flags\nare set in both alternatives above.","ref":"seq_trace.html#module-trace-token"},{"type":"module","title":"Serial - seq_trace","doc":"The trace token contains a component called `serial`. It consists of two\nintegers, `Previous` and `Current`. The purpose is to uniquely identify each\ntraced event within a trace sequence, as well as to order the messages\nchronologically and in the different branches, if any.\n\nThe algorithm for updating `Serial` can be described as follows:\n\nLet each process have two counters, `prev_cnt` and `curr_cnt`, both are set to\n`0` when a process is created outside of a trace sequence. The counters are\nupdated at the following occasions:\n\n- _When the process is about to pass along information to another process and\n the trace token is not empty._ This typically occurs when sending a message,\n but also, for example, when spawning another process.\n\n Let the serial of the trace token be `tprev` and `tcurr`.\n\n ```text\n curr_cnt := curr_cnt + 1\n tprev := prev_cnt\n tcurr := curr_cnt\n ```\n\n The trace token with `tprev` and `tcurr` is then passed along with the\n information passed to the other process.\n\n- _When the process calls_ `seq_trace:print(Label, Info)`, `Label` _matches the\n label part of the trace token and the trace token print flag is `true`._\n\n The algorithm is the same as for send above.\n\n- _When information is received that also contains a non-empty trace token. For\n example, when a message is matched out in a receive expression, or when a new\n process is spawned._\n\n The process trace token is set to the trace token from the message.\n\n Let the serial of the trace token be `tprev` and `tcurr`.\n\n ```text\n if (curr_cnt < tcurr )\n curr_cnt := tcurr\n prev_cnt := tcurr\n ```\n\n`curr_cnt` of a process is incremented each time the process is involved in a\nsequential trace. The counter can reach its limit (27 bits) if a process is very\nlong-lived and is involved in much sequential tracing. If the counter overflows,\nthe serial for ordering of the trace events cannot be used. To prevent the\ncounter from overflowing in the middle of a sequential trace, function\n`seq_trace:reset_trace/0` can be called to reset `prev_cnt` and `curr_cnt` of\nall processes in the Erlang node. This function also sets all trace tokens in\nprocesses and their message queues to empty, and thus stops all ongoing\nsequential tracing.","ref":"seq_trace.html#module-serial"},{"type":"module","title":"Performance Considerations - seq_trace","doc":"The performance degradation for a system that is enabled for sequential tracing\nis negligible as long as no tracing is activated. When tracing is activated,\nthere is an extra cost for each traced message, but all other messages are\nunaffected.","ref":"seq_trace.html#module-performance-considerations"},{"type":"module","title":"Ports - seq_trace","doc":"Sequential tracing is not performed across ports.\n\nIf the user for some reason wants to pass the trace token to a port, this must\nbe done manually in the code of the port controlling process. The port\ncontrolling processes have to check the appropriate sequential trace settings\n(as obtained from `seq_trace:get_token/1`) and include trace information in the\nmessage data sent to their respective ports.\n\nSimilarly, for messages received from a port, a port controller has to retrieve\ntrace-specific information, and set appropriate sequential trace flags through\ncalls to `seq_trace:set_token/2`.","ref":"seq_trace.html#module-ports"},{"type":"module","title":"Distribution - seq_trace","doc":"Sequential tracing between nodes is performed transparently. This applies to\nC-nodes built with `Erl_Interface` too. A C-node built with `Erl_Interface` only\nmaintains one trace token, which means that the C-node appears as one process\nfrom the sequential tracing point of view.","ref":"seq_trace.html#module-distribution"},{"type":"module","title":"Example of Use - seq_trace","doc":"This example gives a rough idea of how the new primitives can be used and what\nkind of output it produces.\n\nAssume that you have an initiating process with `Pid == <0.30.0>` like this:\n\n```erlang\n-module(seqex).\n-compile(export_all).\n\nloop(Port) ->\n receive\n {Port,Message} ->\n seq_trace:set_token(label,17),\n seq_trace:set_token('receive',true),\n seq_trace:set_token(print,true),\n seq_trace:print(17,\"**** Trace Started ****\"),\n call_server ! {self(),the_message};\n {ack,Ack} ->\n ok\n end,\n loop(Port).\n```\n\nAnd a registered process `call_server` with `Pid == <0.31.0>` like this:\n\n```erlang\nloop() ->\n receive\n {PortController,Message} ->\n Ack = {received, Message},\n seq_trace:print(17,\"We are here now\"),\n PortController ! {ack,Ack}\n end,\n loop().\n```\n\nA possible output from the system's `sequential_tracer` can be like this:\n\n```erlang\n17:<0.30.0> Info {0,1} WITH\n\"**** Trace Started ****\"\n17:<0.31.0> Received {0,2} FROM <0.30.0> WITH\n{<0.30.0>,the_message}\n17:<0.31.0> Info {2,3} WITH\n\"We are here now\"\n17:<0.30.0> Received {2,4} FROM <0.31.0> WITH\n{ack,{received,the_message}}\n```\n\nThe implementation of a system tracer process that produces this printout can\nlook like this:\n\n```erlang\ntracer() ->\n receive\n {seq_trace,Label,TraceInfo} ->\n print_trace(Label,TraceInfo,false);\n {seq_trace,Label,TraceInfo,Ts} ->\n print_trace(Label,TraceInfo,Ts);\n _Other -> ignore\n end,\n tracer().\n\nprint_trace(Label,TraceInfo,false) ->\n io:format(\"~p:\",[Label]),\n print_trace(TraceInfo);\nprint_trace(Label,TraceInfo,Ts) ->\n io:format(\"~p ~p:\",[Label,Ts]),\n print_trace(TraceInfo).\n\nprint_trace({print,Serial,From,_,Info}) ->\n io:format(\"~p Info ~p WITH~n~p~n\", [From,Serial,Info]);\nprint_trace({'receive',Serial,From,To,Message}) ->\n io:format(\"~p Received ~p FROM ~p WITH~n~p~n\",\n [To,Serial,From,Message]);\nprint_trace({send,Serial,From,To,Message}) ->\n io:format(\"~p Sent ~p TO ~p WITH~n~p~n\",\n [From,Serial,To,Message]).\n```\n\nThe code that creates a process that runs this tracer function and sets that\nprocess as the system tracer can look like this:\n\n```erlang\nstart() ->\n Pid = spawn(?MODULE,tracer,[]),\n seq_trace:set_system_tracer(Pid), % set Pid as the system tracer\n ok.\n```\n\nWith a function like `test/0`, the whole example can be started:\n\n```erlang\ntest() ->\n P = spawn(?MODULE, loop, [port]),\n register(call_server, spawn(?MODULE, loop, [])),\n start(),\n P ! {port,message}.\n```","ref":"seq_trace.html#module-example-of-use"},{"type":"function","title":"seq_trace.get_system_tracer/0","doc":"Returns the pid, port identifier or tracer module of the current system tracer\nor `false` if no system tracer is activated.","ref":"seq_trace.html#get_system_tracer/0"},{"type":"function","title":"seq_trace.get_token/0","doc":"Returns the value of the trace token for the calling process. If `[]` is\nreturned, it means that tracing is not active. Any other value returned is the\nvalue of an active trace token. The value returned can be used as input to the\n[`set_token/1`](`set_token/1`) function.","ref":"seq_trace.html#get_token/0"},{"type":"function","title":"seq_trace.get_token/1","doc":"Returns the value of the trace token component `Component`. See `set_token/2`\nfor possible values of `Component` and `Val`.","ref":"seq_trace.html#get_token/1"},{"type":"function","title":"seq_trace.print/1","doc":"Puts the Erlang term `TraceInfo` into the sequential trace output if the calling\nprocess currently is executing within a sequential trace and the `print` flag of\nthe trace token is set.","ref":"seq_trace.html#print/1"},{"type":"function","title":"seq_trace.print/2","doc":"Same as [`print/1`](`print/1`) with the additional condition that `TraceInfo` is\noutput only if `Label` is equal to the label component of the trace token.","ref":"seq_trace.html#print/2"},{"type":"function","title":"seq_trace.reset_trace/0","doc":"Sets the trace token to empty for all processes on the local node. The process\ninternal counters used to create the serial of the trace token is set to 0. The\ntrace token is set to empty for all messages in message queues. Together this\nwill effectively stop all ongoing sequential tracing in the local node.","ref":"seq_trace.html#reset_trace/0"},{"type":"function","title":"seq_trace.set_system_tracer/1","doc":"Sets the system tracer. The system tracer can be either a process, port or\n[tracer module](`m:erl_tracer`) denoted by `Tracer`. Returns the previous value\n(which can be `false` if no system tracer is active).\n\nFailure: `{badarg, Info}}` if `Pid` is not an existing local pid.","ref":"seq_trace.html#set_system_tracer/1"},{"type":"function","title":"seq_trace.set_token/1","doc":"Sets the trace token for the calling process to `Token`. If `Token == []` then\ntracing is disabled, otherwise `Token` should be an Erlang term returned from\n`get_token/0` or [`set_token/1`](`set_token/1`). [`set_token/1`](`set_token/1`)\ncan be used to temporarily exclude message passing from the trace by setting the\ntrace token to empty like this:\n\n```erlang\nOldToken = seq_trace:set_token([]), % set to empty and save\n % old value\n% do something that should not be part of the trace\nio:format(\"Exclude the signalling caused by this~n\"),\nseq_trace:set_token(OldToken), % activate the trace token again\n...\n```\n\nReturns the previous value of the trace token.","ref":"seq_trace.html#set_token/1"},{"type":"function","title":"seq_trace.set_token/2","doc":"Sets the individual `Component` of the trace token to `Val`. Returns the\nprevious value of the component.\n\n- **[`set_token(label, Label)`](`set_token/2`)** - The `label` component is a\n term which identifies all events belonging to the same sequential trace. If\n several sequential traces can be active simultaneously, `label` is used to\n identify the separate traces. Default is 0.\n\n > #### Warning {: .warning }\n >\n > Labels were restricted to small signed integers (28 bits) prior to OTP 21.\n > The trace token will be silently dropped if it crosses over to a node that\n > does not support the label.\n\n- **[`set_token(serial, SerialValue)`](`set_token/2`)** -\n `SerialValue = {Previous, Current}`. The `serial` component contains counters\n which enables the traced messages to be sorted, should never be set explicitly\n by the user as these counters are updated automatically. Default is `{0, 0}`.\n\n- **[`set_token(send, Bool)`](`set_token/2`)** - A trace token flag\n (`true | false`) which enables/disables tracing on information sending.\n Default is `false`.\n\n- **[`set_token('receive', Bool)`](`set_token/2`)** - A trace token flag\n (`true | false`) which enables/disables tracing on information reception.\n Default is `false`.\n\n- **[`set_token(print, Bool)`](`set_token/2`)** - A trace token flag\n (`true | false`) which enables/disables tracing on explicit calls to\n `seq_trace:print/1`. Default is `false`.\n\n- **[`set_token(timestamp, Bool)`](`set_token/2`)** - A trace token flag\n (`true | false`) which enables/disables a timestamp to be generated for each\n traced event. Default is `false`.\n\n- **[`set_token(strict_monotonic_timestamp, Bool)`](`set_token/2`)** - A trace\n token flag (`true | false`) which enables/disables a strict monotonic\n timestamp to be generated for each traced event. Default is `false`.\n Timestamps will consist of\n [Erlang monotonic time](`e:erts:time_correction.md#erlang-monotonic-time`) and\n a monotonically increasing integer. The time-stamp has the same format and\n value as produced by\n `{erlang:monotonic_time(nanosecond), erlang:unique_integer([monotonic])}`.\n\n- **[`set_token(monotonic_timestamp, Bool)`](`set_token/2`)** - A trace token\n flag (`true | false`) which enables/disables a strict monotonic timestamp to\n be generated for each traced event. Default is `false`. Timestamps will use\n [Erlang monotonic time](`e:erts:time_correction.md#erlang-monotonic-time`).\n The time-stamp has the same format and value as produced by\n `erlang:monotonic_time(nanosecond)`.\n\nIf multiple timestamp flags are passed, `timestamp` has precedence over\n`strict_monotonic_timestamp` which in turn has precedence over\n`monotonic_timestamp`. All timestamp flags are remembered, so if two are passed\nand the one with highest precedence later is disabled the other one will become\nactive.","ref":"seq_trace.html#set_token/2"},{"type":"type","title":"seq_trace.component/0","doc":"","ref":"seq_trace.html#t:component/0"},{"type":"type","title":"seq_trace.flag/0","doc":"","ref":"seq_trace.html#t:flag/0"},{"type":"type","title":"seq_trace.token/0","doc":"An opaque term (a tuple) representing a trace token.","ref":"seq_trace.html#t:token/0"},{"type":"type","title":"seq_trace.tracer/0","doc":"","ref":"seq_trace.html#t:tracer/0"},{"type":"type","title":"seq_trace.value/0","doc":"","ref":"seq_trace.html#t:value/0"},{"type":"module","title":"trace","doc":"The Erlang trace interface.\n\nThe Erlang run-time system exposes several trace points that allow users\nto be notified when they are triggered. Trace points are things such as\nfunction calls, message sending and receiving, garbage collection, and\nprocess scheduling.\n\nThe functions in this module can be used directly, but can also be\nused as building blocks to build more sophisticated debugging or\nprofiling tools. For debugging Erlang code it is recommended to use\n`m:dbg` and for profiling to use `m:tprof`.","ref":"trace.html"},{"type":"module","title":"Trace Sessions - trace","doc":"All tracing is done within a trace session. Trace sessions can be\n[created](`session_create/3`) and [destroyed](`session_destroy/1`)\ndynamically. Each session has its own tracer that will receive all trace\nmessages. Several sessions can exist at the same time without interfering with\neach other. When a trace session is destroyed, all its trace settings are\nautomatically cleaned up.\n\n*Example*:\n\n```erlang\n%% Create a tracer process that will receive the trace events\n1> Tracer = spawn(fun F() -> receive M -> io:format(\"~p~n\",[M]), F() end end).\n<0.91.0>\n%% Create a session using the Tracer\n2> Session = trace:session_create(my_session, Tracer, []).\n{#Ref<0.1543805153.1548353537.92331>,{my_session, 0}}\n%% Setup call tracing on self()\n3> trace:process(Session, self(), true, [call]).\n1\n%% Setup call tracing on lists:seq/2\n4> trace:function(Session, {lists,seq,2}, [], []).\n1\n%% Call the traced function\n5> lists:seq(1, 10).\n{trace,<0.89.0>,call,{lists,seq,[1,10]}} % The trace message\n[1,2,3,4,5,6,7,8,9,10] % The return value\n%% Cleanup the trace session\n6> trace:session_destroy(Session).\nok\n```","ref":"trace.html#module-trace-sessions"},{"type":"module","title":"Node Local Tracing Only - trace","doc":"The functions in this module only operates on the local node. That is, both the\ntraced processes/ports as well as the tracer process/port/module must all reside\non the same local node as the call is made. To trace remote nodes use `m:dbg` or\n`m:ttb`.\n\n> #### Change {: .info }\n>\n> This `trace` module was introduced in OTP 27.0. The interface and semantics are\n> similar to the older functions `erlang:trace/3`, `erlang:trace_pattern/3`,\n> and `erlang:trace_info/2`.\n>\n> The main difference is the old functions operate on a single static\n> trace session per node. That could impose the problem that different\n> users and tools would interfere with each other's trace settings. The new trace\n> functions in this module all operate on dynamically created trace sesssions\n> isolated from each other. Also, this makes it easier to safely disable all trace\n> settings when done by a single call to `session_destroy/1`.\n>\n> To change an existing tool to use the interface the following table can be\n> useful:\n>\n> | Old function call | corresponds to |\n> | ------------------------------------------- | ------------------------------------------------------------------ |\n> | [`erlang:trace(Pid, ...)`][1] | [`process(S, Pid, ...)`][p] |\n> | [`erlang:trace(processes, ...)`][1] | [`process(S, all, ...)`][p] |\n> | [`erlang:trace(existing_processes, ...)`][1] | [`process(S, existing, ...)`][p] |\n> | [`erlang:trace(new_processes, ...)`][1] | [`process(S, new, ...)`][p] |\n> | [`erlang:trace(Port, ...)`][1] | [`port(S, Port, ...)`][o] |\n> | [`erlang:trace(ports, ...)`][1] | [`port(S, all, ...)`][o] |\n> | [`erlang:trace(existing_ports, ...)`][1] | [`port(S, existing, ...)`][o] |\n> | [`erlang:trace(new_ports, ...)`][1] | [`port(S, new, ...)`][o] |\n> | [`erlang:trace(all, ...)`][1] | [`process(S, all, ...)`][p] and [`port(S, all, ...)`][o] |\n> | [`erlang:trace(existing, ...)`][1] | [`process(S, existing, ...)`][p] and [`port(S, existing, ...)`][o] |\n> | [`erlang:trace(new, ...)`][1] | [`process(S, new, ...)`][p] and [`port(S, new, ...)`][o] |\n> | [`erlang:trace_pattern(MFA, ...)`][2] | [`function(S, MFA, ...)`][f] |\n> | [`erlang:trace_pattern(send, ...)`][2] | [`send(S, ...)`][s] |\n> | [`erlang:trace_pattern('receive', ...)`][2] | [`recv(S, ...)`][r] |\n> | [`erlang:trace_info(...)`][3] | [`info(S, ...)`][i] |\n>\n> Argument `S` is the trace session that must first be created with\n> `session_create/3`. The other arguments (implied by `...`) are mostly the\n> same. The only other difference is that the tracer is always the tracer\n> specified when the session was created. Options `{tracer,T}`, `{tracer,M,S}`,\n> `{meta,T}`, and `{meta,M,S}` are therefore not allowed, and the default tracer is\n> never the calling process.\n\n[1]: `erlang:trace/3`\n[2]: `erlang:trace_pattern/3`\n[3]: `erlang:trace_info/2`\n[p]: `process/4`\n[o]: `port/4`\n[f]: `function/4`\n[s]: `send/3`\n[r]: `recv/3`\n[i]: `info/3`","ref":"trace.html#module-node-local-tracing-only"},{"type":"function","title":"trace.delivered/2","doc":"Equivalent to [`erlang:trace_delivered(Tracee)`](`erlang:trace_delivered/1`)\nexcept that it is run within the given `t:session/0`.","ref":"trace.html#delivered/2"},{"type":"function","title":"trace.function/4","doc":"Enable or disable _call tracing_ for one or more functions.\n\nMust be combined with `process/4` to set the `call` trace flag for one or more\nprocesses.\n\nConceptually, call tracing works as follows. In each trace session, a\nset of processes and a set of functions have been marked for\ntracing. If a traced process calls a traced function, the trace action\nis taken. Otherwise, nothing happens.\n\nTo add or remove one or more processes to the set of traced processes, use\n`process/4`.\n\nUse this function to add or remove functions to the set of traced functions\nin a trace session.\n\nArgument `Session` is the trace session to operate on as returned by\n`session_create/3`.\n\nArgument **`MFA`** is to be a tuple, such as `{Module, Function, Arity}`, or the\natom `on_load` (described below). The `MFA` tuple specifies the module,\nfunction, and arity for the functions to be traced. The atom `'_'` can be used\nas a wildcard in any of the following ways:\n\n- **`{Module,Function,'_'}`** - All functions of any arity named `Function` in\n module `Module`.\n\n- **`{Module,'_','_'}`** - All functions in module `Module`.\n\n- **`{'_','_','_'}`** - All functions in all loaded modules.\n\nOther combinations, such as `{Module,'_',Arity}`, are not allowed.\n\nIf argument `MFA` is the atom `on_load`, the match specification and flag list\nare used on all functions in all modules that are newly loaded.\n\nArgument **`MatchSpec`** can take the following forms:\n\n- **`true`** - Enable tracing for the matching functions. Any match\n specification is removed.\n\n- **`false`** - Disable tracing for the matching functions. Any match\n specification is removed.\n\n- **`MatchExpression`** - A match specification. An empty list is equivalent to\n `true`. For a description of match specifications, see section\n [Match Specifications in Erlang](`e:erts:match_spec.md`) in the User's Guide\n for the ERTS application.\n\n- **`restart`** - For the `FlagList` options `call_count`, `call_time` and\n `call_memory`: restarts the existing counters. The behavior is undefined for\n other `FlagList` options.\n\n- **`pause`** - For the `FlagList` options `call_count`, `call_time` and\n `call_memory`: pauses the existing counters. The behavior is undefined for\n other `FlagList` options.\n\nArgument **`FlagList`** is a list of options. The following are the valid options:\n\n- **`global`** - Turn on or off call tracing for global function calls (that\n is, calls specifying the module explicitly). Only exported functions match and\n only global calls generate trace messages. **This is the default if `FlagList`\n is empty**.\n\n- **`local`** - Turn on or off call tracing for all types of function calls.\n Trace messages are sent whenever any of the specified functions are called,\n regardless of how they are called. If flag `return_to` is set for the process,\n a `return_to` message is also sent when this function returns to its caller.\n\n- **`meta`** - Turn on or off meta-tracing for all types of function\n calls. Trace messages are sent to the tracer whenever any of the specified\n functions are called.\n\n Meta-tracing traces all processes and does not care about the process trace\n flags set by `process/4`, the trace flags are instead fixed to\n `[call, timestamp]`.\n\n The match specification function `{return_trace}` works with meta-trace.\n\n- **`call_count`**{: #call_count } - Start (`MatchSpec == true`) or stop\n (`MatchSpec == false`) call count tracing for all types of function calls. For\n every function, a counter is incremented when the function is called, in any\n process. No process trace flags need to be activated.\n\n If call count tracing is started while already running, the count is restarted\n from zero. To pause running counters, use `MatchSpec == pause`. Paused and\n running counters can be restarted from zero with `MatchSpec == restart`.\n\n To read the counter value for a function, call\n [`trace:info(_, MFA, call_count)`](`info/3`).\n\n- **`call_time`**{: #call_time } - Start (`MatchSpec` is `true`) or stops (`MatchSpec` is `false`)\n call time tracing for all types of function calls. For every function, a\n counter is incremented when the function is called and the time spent in the\n function is measured and accumulated in another counter. The counters are\n stored for each call traced process.\n\n If call time tracing is started while already running, the count and time\n restart from zero. To pause running counters, use `MatchSpec == pause`. Paused\n and running counters can be restarted from zero with `MatchSpec == restart`.\n\n To read the counter values, use `info/3`.\n\n- **`call_memory`**{: #call_memory } - Start (`MatchSpec == true`) or stop\n (`MatchSpec == false`) call memory tracing for all types of function calls.\n\n If call memory tracing is started while already running, counters and\n allocations restart from zero. To pause running counters, use\n `MatchSpec == pause`. Paused and running counters can be restarted from zero\n with `MatchSpec == restart`.\n\n To read the counter value, use `info/3`.\n\nOption `global` cannot be combined with any of the other options, which all\nperform some kind of local tracing. If global tracing is specified for\na set of functions, then `local`, `meta`, `call_count`, `call_time`,\nand `call_memory` tracing for the matching set of functions are\ndisabled, and vice versa.\n\nWhen disabling trace, the option must match the type of trace set on the\nfunction. That is, local tracing must be disabled with option `local` and global\ntracing with option `global` (or no option), and so on.\n\nPart of a match specification cannot be changed directly. If a function has\na match specification, it can be replaced with a new one. Function `info/3` can\nbe used to retrieve the existing match specification.\n\nReturns the number of functions matching argument `MFA`. Zero is returned if\nnone matched or if `on_load` was specified.\n\nFails by raising an error exception with an error reason of:\n\n- **`badarg`** - If an argument is invalid.\n\n- **`system_limit`** - If a match specification passed as argument has excessive\n nesting which causes scheduler stack exhaustion for the scheduler that the\n calling process is executing on.\n [Scheduler stack size](`e:erts:erl_cmd.md#sched_thread_stack_size`) can be configured\n when starting the runtime system.","ref":"trace.html#function/4"},{"type":"function","title":"trace.info/3","doc":"Return trace information about a port, process, function, or event.\n\nArgument `Session` is the trace session to inspect as returned by\n`session_create/3` or `session_info/1`.\n\n**To get information about a port or process**, `PidPortFuncEvent` is to be a\nprocess identifier (pid), port identifier, or one of the atoms `new`,\n`new_processes`, or `new_ports`. The atom `new` or `new_processes` means that\nthe default trace state for processes to be created is returned. The atom\n`new_ports` means that the default trace state for ports to be created is\nreturned.\n\nValid `Item` values for ports and processes:\n\n- **`flags`** - Returns a list of atoms indicating what kind of traces is\n enabled for the process. The list is empty if no traces are enabled, and one\n or more of [`trace_info_flag()`](`t:trace_info_flag/0`) if traces are enabled.\n The order is arbitrary.\n\n- **`tracer`** - Returns the identifier for process, port, or a tuple containing\n the tracer module and tracer state tracing this process. If this process is\n not traced, the return value is `[]`.\n\n**To get information about a function**, `PidPortFuncEvent` is to be the\nthree-element tuple `{Module, Function, Arity}` or the atom `on_load`. No\nwildcards are allowed. Returns `undefined` if the function does not exist or\n`false` if the function is not traced. If `PidPortFuncEvent` is `on_load`, the\ninformation returned refers to the default value for code that will be loaded.\n\nValid `Item` values for functions:\n\n- **`traced`** - Returns `global` if this function is traced on global function\n calls, `local` if this function is traced on local function calls (that is,\n local and global function calls), and `false` if local or global function\n calls are not traced.\n\n- **`match_spec`** - Returns the match specification for this function, if it\n has one. If the function is locally or globally traced but has no match\n specification defined, the returned value is `[]`.\n\n- **`meta`** - Returns the meta-trace tracer process, port, or trace module for\n this function, if it has one. If the function is not meta-traced, the returned\n value is `false`. If the function is meta-traced but has once detected that\n the tracer process is invalid, the returned value is `[]`.\n\n- **`meta_match_spec`** - Returns the meta-trace match specification for this\n function, if it has one. If the function is meta-traced but has no match\n specification defined, the returned value is `[]`.\n\n- **`call_count`** - Returns the call count value for this function or `true`\n for the pseudo function `on_load` if call count tracing is active. Otherwise\n `false` is returned.\n\n See also `function/4`.\n\n- **`call_time`** - Returns the call time values for this function or `true` for\n the pseudo function `on_load` if call time tracing is active. Otherwise\n `false` is returned. The call time values returned, `[{Pid, Count, S, Us}]`,\n is a list of each process that executed the function and its specific\n counters. `Count` is the call count. `S` and `Us` are the accumulated call\n time expressed in seconds and microseconds.\n\n See also `function/4`.\n\n- **`call_memory`** - Returns the accumulated number of words allocated by this\n function. Accumulation stops at the next memory traced function: if there are\n `outer`, `middle` and `inner` functions each allocating 3 words, but only\n `outer` is traced, it will report 9 allocated words. If `outer` and `inner`\n are traced, 6 words are reported for `outer` and 3 for `inner`. When function\n is not traced, `false` is returned. Returned tuple is `[{Pid, Count, Words}]`,\n for each process that executed the function.\n\n See also `function/4`.\n\n- **`all`** - Returns a list containing the `{Item, Value}` tuples for all other\n items, or returns `false` if no tracing is active for this function.\n\n**To get information about an event**, `PidPortFuncEvent` is to be one of the\natoms `send` or `'receive'`.\n\nOne valid `Item` for events exists:\n\n- **`match_spec`** - Returns the match specification for this event, if it has\n one, or `true` if no match specification has been set.\n\n**To get information about monitored system events**, `PidPortFuncEvent` is to\n be the atom `system`.\n\nOnly valid `Item` for `system` is\n\n- **`all`** - Returns a list of all monitored system events enabled by\n `system/3`.\n\nThe return value is `{Item, Value}`, where `Value` is the requested information\nas described earlier. If a pid for a dead process was specified, or the name of\na non-existing function, `Value` is `undefined`.","ref":"trace.html#info/3"},{"type":"function","title":"trace.port/4","doc":"Turn on or off trace flags for one or more ports.\n\nArgument `Session` is the trace session to operate on as returned by\n`session_create/3`.\n\n`Ports` is either a port identifier for a local port or one of the following atoms:\n\n- **`all`** - All currently existing ports and all that will be\n created in the future.\n\n- **`existing`** - All currently existing ports.\n\n- **`new`** - All ports that will be created in the future.\n\n`FlagList` can contain any number of the following flags (the \"message tags\"\nrefers to the list of [`trace messages`](#port_trace_messages)):\n\n- **`all`** - Sets all trace flags except `cpu_timestamp`, which are in its\n nature different than the others.\n\n- **`send`** - Traces sending of messages.\n\n Message tags: [`send`](#port_trace_messages_send) and\n [`send_to_non_existing_process`](#port_trace_messages_send_to_non_existing_process).\n\n- **`'receive'`** - Traces receiving of messages.\n\n Message tags: [`'receive'`](#port_trace_messages_receive).\n\n- **`ports`** - Traces port-related events.\n\n Message tags: [`open`](#port_trace_messages_open),\n [`closed`](#port_trace_messages_closed),\n [`register`](#port_trace_messages_register),\n [`unregister`](#port_trace_messages_unregister),\n [`getting_linked`](#port_trace_messages_getting_linked), and\n [`getting_unlinked`](#port_trace_messages_getting_unlinked).\n\n- **`running_ports`** - Traces scheduling of ports.\n\n Message tags: [`in`](#port_trace_messages_in_port) and\n [`out`](#port_trace_messages_out_port).\n\n- **`timestamp`**, **`cpu_timestamp`**, **`monotonic_timestamp`**,\n **`strict_monotonic_timestamp`** - Same as for timestamps in\n [`process/4`](#timestamp).\n\nThe tracing process receives the _trace messages_ described in the following\nlist. `Port` is the port identifier of the traced port in which the traced\nevent has occurred. The third tuple element is the message tag.\n\nIf flag `timestamp`, `strict_monotonic_timestamp`, or `monotonic_timestamp` is\nspecified, the first tuple element is `trace_ts` instead, and the time stamp is\nadded as an extra element last in the message tuple. If multiple time stamp\nflags are passed, `timestamp` has precedence over `strict_monotonic_timestamp`,\nwhich in turn has precedence over `monotonic_timestamp`. All time stamp flags\nare remembered, so if two are passed and the one with highest precedence later\nis disabled, the other one becomes active.\n\nIf a match specification (applicable only for `send` and `'receive'`\ntracing) contains a `{message}` action function with a non-boolean value, that\nvalue is added as an extra element to the message tuple either in the last\nposition or before the timestamp (if it is present).\n\nTrace messages:\n\n[](){: #port_trace_messages }\n\n- **`{trace, Port, send, Msg, To}`{: #port_trace_messages_send }** - When\n `Port` sends message `Msg` to process `To`.\n\n- **`{trace, Port, send_to_non_existing_process, Msg, To}`{:\n #port_trace_messages_send_to_non_existing_process }** - When `Port`\n sends message `Msg` to the non-existing process `To`.\n\n- **`{trace, Port, 'receive', Msg}`{: #port_trace_messages_receive }** -\n When `Port` receives message `Msg`. If `Msg` is set to time-out, a receive\n statement can have timed out, or the process received a message with the\n payload `timeout`.\n\n- **`{trace, Port, register, RegName}`{: #port_trace_messages_register\n }** - When `Port` gets the name `RegName` registered.\n\n- **`{trace, Port, unregister, RegName}`{: #port_trace_messages_unregister\n }** - When `Port` gets the name `RegName` unregistered. This is done\n automatically when a registered process or port exits.\n\n- **`{trace, Port, getting_linked, Pid2}`{:\n #port_trace_messages_getting_linked }** - When `Port` gets linked to a\n process `Pid2`.\n\n- **`{trace, Port, getting_unlinked, Pid2}`{:\n #port_trace_messages_getting_unlinked }** - When `Port` gets unlinked\n from a process `Pid2`.\n\n- **`{trace, Port, open, Pid, Driver}`{: #port_trace_messages_open }** - When\n `Pid` opens a new port `Port` with the running `Driver`.\n\n `Driver` is the name of the driver as an atom.\n\n- **`{trace, Port, closed, Reason}`{: #port_trace_messages_closed }** - When\n `Port` closes with `Reason`.\n\n- **`{trace, Port, in, Command | 0}`{: #port_trace_messages_in_port }** -\n When `Port` is scheduled to run. `Command` is the first thing the port will\n execute, it can however run several commands before being scheduled out. On\n some rare occasions, the current function cannot be determined, then the last\n element is `0`.\n\n The possible commands are `call`, `close`, `command`, `connect`, `control`,\n `flush`, `info`, `link`, `open`, and `unlink`.\n\n- **`{trace, Port, out, Command | 0}`{: #port_trace_messages_out_port }** -\n When `Port` is scheduled out. The last command run was `Command`. On some rare\n occasions, the current function cannot be determined, then the last element is\n `0`. `Command` can contain the same commands as `in`\n\nIf the tracing process/port dies or the tracer module returns `remove`, the\nflags are silently removed.\n\nReturns a number indicating the number of ports that matched `Ports`.\nIf `Ports` is a port identifier, the return value is `1`. If\n`Ports` is `all` or `existing`, the return value is the number of\nexisting ports. If `Ports` is `new`, the return value is `0`.\n\nFailure: `badarg` if the specified arguments are not supported. For example,\n`cpu_timestamp` is not supported on all platforms.","ref":"trace.html#port/4"},{"type":"function","title":"trace.process/4","doc":"Turn on or off trace flags for one or more processes.\n\nArgument `Session` is the trace session to operate on as returned by\n`session_create/3`.\n\nArgument `Procs` is either a process identifier (pid) for a local process or\none of the following atoms:\n\n- **`all`** - All currently existing processes and all that will be\n created in the future.\n\n- **`existing`** - All currently existing processes.\n\n- **`new`** - All processes that will be created in the future.\n\nArgument `How` is either `true` to turn on trace flags or `false` to turn them off.\n\nArgument `FlagList` can contain any number of the following flags (the \"message\ntags\" refers to the list of [`trace messages`](#process_trace_messages)):\n\n- **`all`** - Sets all trace flags except `cpu_timestamp`, which\n is in its nature different than the others.\n\n- **`send`** - Traces sending of messages. Limit which sent messages to trace by\n calling `send/3`.\n\n Message tags: [`send`](#process_trace_messages_send) and\n [`send_to_non_existing_process`](#process_trace_messages_send_to_non_existing_process).\n\n- **`'receive'`** - Traces receiving of messages. Limit which received messages\n to trace by calling `recv/3`.\n\n Message tags: [`'receive'`](#process_trace_messages_receive).\n\n- **`call`** - Traces certain function calls. Specify which function calls to\n trace by calling `function/4`.\n\n Message tags: [`call`](#process_trace_messages_call) and\n [`return_from`](#process_trace_messages_return_from).\n\n- **`silent`** - Used with the `call` trace flag. The `call`, `return_from`, and\n `return_to` trace messages are inhibited if this flag is set, but they are\n executed as normal if there are match specifications.\n\n Silent mode is inhibited by executing `trace:process(_, _, false, [silent|_])`, or\n by a match specification executing the function `{silent, false}`.\n\n The `silent` trace flag facilitates setting up a trace on many or even all\n processes in the system. The trace can then be activated and deactivated using\n the match specification function `{silent,Bool}`, giving a high degree of\n control of which functions with which arguments that trigger the trace.\n\n Message tags: [`call`](#process_trace_messages_call),\n [`return_from`](#process_trace_messages_return_from), and\n [`return_to`](#process_trace_messages_return_to). Or rather, the\n absence of.\n\n- **`return_to`** - Used with the `call` trace flag. Traces the exit from\n call traced functions back to where the execution resumes. Only works for\n functions traced with option `local` to `function/4`.\n\n The semantics is that a `return_to` trace message is sent when a call traced\n function returns or throws and exception that is caught. For tail calls, only\n one trace message is sent per chain of tail calls, so the properties of tail\n recursiveness for function calls are kept while tracing with this\n flag. Similar for exceptions, only one `return_to` trace message is sent, even\n if the exception passed more than one call traced function before it was\n caught.\n\n Using `call` and `return_to` trace together makes it possible to know exactly\n in which function a process executes at any time.\n\n To get trace messages containing return values from functions, use the\n `{return_trace}` match specification action instead.\n\n Message tags: [`return_to`](#process_trace_messages_return_to).\n\n- **`procs`** - Traces process-related events.\n\n Message tags: [`spawn`](#process_trace_messages_spawn),\n [`spawned`](#process_trace_messages_spawned),\n [`exit`](#process_trace_messages_exit),\n [`register`](#process_trace_messages_register),\n [`unregister`](#process_trace_messages_unregister),\n [`link`](#process_trace_messages_link),\n [`unlink`](#process_trace_messages_unlink),\n [`getting_linked`](#process_trace_messages_getting_linked), and\n [`getting_unlinked`](#process_trace_messages_getting_unlinked).\n\n- **`running`** - Traces scheduling of processes.\n\n Message tags: [`in`](#process_trace_messages_in_proc) and\n [`out`](#process_trace_messages_out_proc).\n\n- **`exiting`** - Traces scheduling of exiting processes.\n\n Message tags:\n [`in_exiting`](#process_trace_messages_in_exiting_proc),\n [`out_exiting`](#process_trace_messages_out_exiting_proc), and\n [`out_exited`](#process_trace_messages_out_exited_proc).\n\n- **`running_procs`** - Traces scheduling of processes just like `running`.\n However, this option also includes schedule events when the process executes\n within the context of a port without being scheduled out itself.\n\n Message tags: [`in`](#process_trace_messages_in_proc) and\n [`out`](#process_trace_messages_out_proc).\n\n- **`garbage_collection`** - Traces garbage collections of processes.\n\n Message tags:\n [`gc_minor_start`](#process_trace_messages_gc_minor_start),\n [`gc_max_heap_size`](#process_trace_messages_gc_max_heap_size), and\n [`gc_minor_end`](#process_trace_messages_gc_minor_end).\n\n- **`timestamp`{: #timestamp }** - Includes a time stamp in all trace\n messages. The time stamp (Ts) has the same form as returned by\n `erlang:now/0`.\n\n- **`cpu_timestamp`** - A global trace flag for the Erlang node that makes all\n trace time stamps using flag `timestamp` to be in CPU time, not wall clock\n time. That is, `cpu_timestamp` is not be used if `monotonic_timestamp` or\n `strict_monotonic_timestamp` is enabled. Only allowed with `Procs==all`.\n If the host machine OS does not support high-resolution CPU time measurements,\n `process/4` exits with `badarg`. Notice that most OS do not\n synchronize this value across cores, so be prepared that time can seem to go\n backwards when using this option.\n\n- **`monotonic_timestamp`** - Includes an\n [Erlang monotonic time](`e:erts:time_correction.md#erlang-monotonic-time`) time stamp\n in all trace messages. The time stamp (Ts) has the same format and value as\n produced by [`erlang:monotonic_time(nanosecond)`](`erlang:monotonic_time/1`). This\n flag overrides flag `cpu_timestamp`.\n\n- **`strict_monotonic_timestamp`** - Includes an time stamp consisting of\n [Erlang monotonic time](`e:erts:time_correction.md#erlang-monotonic-time`) and a\n monotonically increasing integer in all trace messages. The time stamp (Ts)\n has the same format and value as produced by `{`\n [`erlang:monotonic_time(nanosecond)`](`erlang:monotonic_time/1`)`,`\n [`erlang:unique_integer([monotonic])`](`erlang:unique_integer/1`)`}`. This flag\n overrides flag `cpu_timestamp`.\n\n If multiple time stamp flags are passed, `timestamp` has precedence over\n `strict_monotonic_timestamp`, which in turn has precedence over\n `monotonic_timestamp`. All time stamp flags are remembered, so if two are\n passed and the one with highest precedence later is disabled, the other one\n becomes active.\n\n- **`arity`** - Used with the `call` trace flag. `{M, F, Arity}` is specified\n instead of `{M, F, Args}` in call trace messages.\n\n- **`set_on_spawn`** - Makes any process created by a traced process inherit all\n its trace flags, including flag `set_on_spawn` itself.\n\n- **`set_on_first_spawn`** - Makes the first process created by a traced process\n inherit all its trace flags, excluding flag `set_on_first_spawn` itself. That\n is, after the first spawn is done, `set_on_first_spawn` will be cleared in\n both the spawned process and the spawning process.\n\n If both are set, `set_on_first_spawn` will supersede `set_on_spawn`.\n\n- **`set_on_link`** - Makes any process linked by a traced process inherit all\n its trace flags, including flag `set_on_link` itself.\n\n- **`set_on_first_link`** - Makes the first process linked to by a traced\n process inherit all its trace flags, excluding flag `set_on_first_link`\n itself. That is, after the first link is done, `set_on_first_link` will be\n cleared in both the linked process and the linking process.\n\n If both are set, `set_on_first_link` will supersede `set_on_link`.\n\nThe tracing process receives the _trace messages_ described in the following\nlist. `Pid` is the process identifier of the traced process in which the traced\nevent has occurred. The third tuple element is the message tag.\n\nIf flag `timestamp`, `strict_monotonic_timestamp`, or `monotonic_timestamp` is\nspecified, the first tuple element is `trace_ts` instead, and the time stamp is\nadded as an extra element last in the message tuple.\n\nIf a match specification (applicable only for `call`, `send`, and `'receive'`\ntracing) contains a `{message}` action function with a non-boolean value, that\nvalue is added as an extra element to the message tuple either in the last\nposition or before the timestamp (if it is present).\n\nTrace messages:\n\n[](){: #process_trace_messages }\n\n- **`{trace, Pid, send, Msg, To}`{: #process_trace_messages_send }** - When\n process `Pid` sends message `Msg` to process `To`.\n\n- **`{trace, Pid, send_to_non_existing_process, Msg, To}`{:\n #process_trace_messages_send_to_non_existing_process }** - When process `Pid`\n sends message `Msg` to the non-existing process `To`.\n\n- **`{trace, Pid, 'receive', Msg}`{: #process_trace_messages_receive }** -\n When process `Pid` receives message `Msg`. If `Msg` is set to time-out, a receive\n statement can have timed out, or the process received a message with the\n payload `timeout`.\n\n- **`{trace, Pid, call, {M, F, Args}}`{: #process_trace_messages_call }** - When\n process `Pid` calls a traced function. The return values of calls are never\n supplied, only the call and its arguments.\n\n Trace flag `arity` can be used to change the contents of this message, so that\n `Arity` is specified instead of `Args`.\n\n- **`{trace, Pid, return_to, {M, F, Arity}}`{: #process_trace_messages_return_to\n }** - When process `Pid` returns _to_ the specified function. This trace\n message is sent if both the flags `call` and `return_to` are set, and the\n function is set to be traced on _local_ function calls. The message is only\n sent when returning from a chain of tail recursive function calls, where at\n least one call generated a `call` trace message (that is, the functions match\n specification matched, and `{message, false}` was not an action).\n\n- **`{trace, Pid, return_from, {M, F, Arity}, ReturnValue}`{:\n #process_trace_messages_return_from }** - When `Pid` returns _from_ the\n specified function. This trace message is sent if flag `call` is set, and the\n function has a match specification with a `return_trace` or `exception_trace`\n action.\n\n- **`{trace, Pid, exception_from, {M, F, Arity}, {Class, Value}}`{:\n #process_trace_messages_exception_from }** - When `Pid` exits _from_ the\n specified function because of an exception. This trace message is sent if flag\n `call` is set, and the function has a match specification with an\n `exception_trace` action.\n\n- **`{trace, Pid, spawn, Pid2, {M, F, Args}}`{: #process_trace_messages_spawn\n }** - When `Pid` spawns a new process `Pid2` with the specified function call\n as entry point.\n\n `Args` is supposed to be the argument list, but can be any term if the spawn\n is erroneous.\n\n- **`{trace, Pid, spawned, Pid2, {M, F, Args}}`{:\n #process_trace_messages_spawned }** - When `Pid` is spawned by process `Pid2`\n with the specified function call as entry point.\n\n `Args` is supposed to be the argument list, but can be any term if the spawn\n is erroneous.\n\n- **`{trace, Pid, exit, Reason}`{: #process_trace_messages_exit }** - When `Pid`\n exits with reason `Reason`.\n\n- **`{trace, Pid, register, RegName}`{: #process_trace_messages_register\n }** - When process `Pid` gets the name `RegName` registered.\n\n- **`{trace, Pid, unregister, RegName}`{: #process_trace_messages_unregister\n }** - When process `Pid` gets the name `RegName` unregistered. This is done\n automatically when a registered process or port exits.\n\n- **`{trace, Pid, link, Pid2}`{: #process_trace_messages_link }** - When `Pid`\n links to a process `Pid2`.\n\n- **`{trace, Pid, unlink, Pid2}`{: #process_trace_messages_unlink }** - When\n `Pid` removes the link from a process `Pid2`.\n\n- **`{trace, Pid, getting_linked, Pid2}`{:\n #process_trace_messages_getting_linked }** - When `Pid` gets linked to a\n process `Pid2`.\n\n- **`{trace, Pid, getting_unlinked, Pid2}`{:\n #process_trace_messages_getting_unlinked }** - When `Pid` gets unlinked\n from a process `Pid2`.\n\n- **`{trace, Port, open, Pid, Driver}`{: #process_trace_messages_open }** - When\n `Pid` opens a new port `Port` with the running `Driver`.\n\n `Driver` is the name of the driver as an atom.\n\n- **[](){: #process_trace_messages_in_proc }\n `{trace, Pid, in | in_exiting, {M, F, Arity} | 0}`{:\n #process_trace_messages_in_exiting_proc }**\n When `Pid` is scheduled to run. The process runs in function `{M, F, Arity}`.\n On some rare occasions, the current function cannot be determined, then the\n last element is `0`.\n\n- **[](){: #process_trace_messages_out_proc } [](){:\n #process_trace_messages_out_exiting_proc }\n `{trace, Pid, out | out_exiting | out_exited, {M, F, Arity} | 0}`{:\n #process_trace_messages_out_exited_proc }**\n When `Pid` is scheduled out. The process was running in function `{M, F,\n Arity}`. On some rare occasions, the current function cannot be determined,\n then the last element is `0`.\n\n- **`{trace, Pid, gc_minor_start, Info}`{:\n #process_trace_messages_gc_minor_start }** - [](){: #gc_minor_start } Sent\n when a garbage collection of the young generation is about to be started.\n `Info` is a list of two-element tuples, where the first element is a key,\n and the second is the value. Do not depend on any order of the tuples.\n The following keys are defined:\n\n - **`heap_size`** - The size of the used part of the heap.\n\n - **`heap_block_size`** - The size of the memory block used for storing the\n heap and the stack.\n\n - **`old_heap_size`** - The size of the used part of the old heap.\n\n - **`old_heap_block_size`** - The size of the memory block used for storing\n the old heap.\n\n - **`stack_size`** - The size of the stack.\n\n - **`recent_size`** - The size of the data that survived the previous garbage\n collection.\n\n - **`mbuf_size`** - The combined size of message buffers associated with the\n process.\n\n - **`bin_vheap_size`** - The total size of unique off-heap binaries referenced\n from the process heap.\n\n - **`bin_vheap_block_size`** - The total size of binaries allowed in the\n virtual heap in the process before doing a garbage collection.\n\n - **`bin_old_vheap_size`** - The total size of unique off-heap binaries\n referenced from the process old heap.\n\n - **`bin_old_vheap_block_size`** - The total size of binaries allowed in the\n virtual old heap in the process before doing a garbage collection.\n\n - **`wordsize`** - For the `gc_minor_start` event it is the size of the need\n that triggered the GC. For the corresponding `gc_minor_end` event it is the\n size of reclaimed memory = start `heap_size` - end `heap_size`.\n\n All sizes are in words.\n\n- **`{trace, Pid, gc_max_heap_size, Info}`{:\n #process_trace_messages_gc_max_heap_size }** - Sent when the\n [`max_heap_size`](`e:erts:erlang#process_flag_max_heap_size`) is reached during\n garbage collection. `Info` contains the same kind of list as in message\n `gc_start`, but the sizes reflect the sizes that triggered `max_heap_size` to\n be reached.\n\n- **`{trace, Pid, gc_minor_end, Info}`{: #process_trace_messages_gc_minor_end\n }** - Sent when young garbage collection is finished. `Info` contains the same\n kind of list as in message `gc_minor_start`, but the sizes reflect the new\n sizes after garbage collection.\n\n- **`{trace, Pid, gc_major_start, Info}`{:\n #process_trace_messages_gc_major_start }** - Sent when fullsweep garbage\n collection is about to be started. `Info` contains the same kind of list as in\n message `gc_minor_start`.\n\n- **`{trace, Pid, gc_major_end, Info}`{: #process_trace_messages_gc_major_end\n }** - Sent when fullsweep garbage collection is finished. `Info` contains the\n same kind of list as in message `gc_minor_start`, but the sizes reflect the\n new sizes after a fullsweep garbage collection.\n\nIf the tracing process dies or the tracer module returns `remove`, the\nflags are silently removed.\n\nReturns a number indicating the number of processes that matched `Procs`.\nIf `Procs` is a process identifier, the return value is `1`. If\n`Procs` is `all` or `existing`, the return value is the number of\nprocesses running. If `Procs` is `new`, the return value is `0`.\n\nFailure: `badarg` if the specified arguments are not supported. For example,\n`cpu_timestamp` is not supported on all platforms.","ref":"trace.html#process/4"},{"type":"function","title":"trace.recv/3","doc":"Set trace pattern for _message receiving_.\n\nMust be combined with `process/4` or `port/4` to set the `'receive'` trace flag\nfor one or more processes or ports.\n\nArgument `Session` is the trace session to operate on as returned by\n`session_create/3`.\n\nThe default value for the `receive` trace pattern in each session is\n`true`. That is, all messages received by processes having `'receive'`\ntrace enabled will be traced. Use this function to limit traced\n`'receive'` events based on the message content, the sender, and/or the\nreceiver.\n\nArgument `MatchSpec` can take the following forms:\n\n- **`MatchExpression`** - A match specification. The matching is done on\n the list `[Node, Sender, Msg]`. `Node` is the node name of the sender.\n `Sender` is the process or port identity of the sender, or the atom\n `undefined` if the sender is not known (which can be the case for remote\n senders). `Msg` is the message term. The pid of the receiving process can be\n accessed with the guard function `self/0`. An empty list is the same as\n `true`. For more information, see section\n [Match Specifications in Erlang](`e:erts:match_spec.md`) in the User's Guide\n for the ERTS application.\n\n- **`true`** - Enable tracing for all received messages (to `'receive'` traced\n processes). Any match specification is removed. _This is the default_.\n\n- **`false`** - Disable tracing for all received messages. Any match\n specification is removed.\n\nArgument `FlagList` must be `[]` for receive tracing.\n\nThe return value is always `1`.\n\n*Examples:*\n\nOnly trace messages from a specific process `Pid`:\n\n```erlang\n> trace:recv(Session, [{['_',Pid, '_'],[],[]}], []).\n1\n```\n\nOnly trace messages matching `{reply, _}`:\n\n```erlang\n> trace:recv(Session, [{['_','_', {reply,'_'}],[],[]}], []).\n1\n```\n\nOnly trace messages from other nodes:\n\n```erlang\n> trace:recv(Session, [{['$1', '_', '_'],[{'=/=','$1',{node}}],[]}], []).\n1\n```\n\n> #### Note {: .info }\n>\n> A match specification for `'receive'` trace can use all guard and body\n> functions except `caller`, `is_seq_trace`, `get_seq_token`, `set_seq_token`,\n> `enable_trace`, `disable_trace`, `trace`, `silent`, and `process_dump`.\n\nFails by raising an error exception with an error reason of:\n\n- **`badarg`** - If an argument is invalid.\n\n- **`system_limit`** - If a match specification passed as argument has excessive\n nesting which causes scheduler stack exhaustion for the scheduler that the\n calling process is executing on.\n [Scheduler stack size](`e:erts:erl_cmd.md#sched_thread_stack_size`) can be configured\n when starting the runtime system.","ref":"trace.html#recv/3"},{"type":"function","title":"trace.send/3","doc":"Set trace pattern for _message sending_.\n\nMust be combined with `process/4` or `port/4` to set the `send` trace flag for\none or more processes or ports.\n\nArgument `Session` is the trace session to operate on as returned by\n`session_create/3`.\n\nThe default value for the `send` trace pattern in each session is\n`true`. That is, all messages sent from processes having `send` trace\nenabled will be traced. Use this function to limit traced `send`\nevents based on the message content, the sender, and/or the receiver.\n\nArgument `MatchSpec` can take the following forms:\n\n- **`MatchExpression`** - A match specification. The matching is done on\n the list `[Receiver, Msg]`. `Receiver` is the process or port identity of the\n receiver and `Msg` is the message term. The pid of the sending process can be\n accessed with the guard function `self/0`. An empty list is the same as\n `true`. For more information, see section\n [Match Specifications in Erlang](`e:erts:match_spec.md`) in the User's Guide\n for the ERTS application.\n\n- **`true`** - Enable tracing for all sent messages (from `send` traced\n processes). Any match specification is removed.\n\n- **`false`** - Disable tracing for all sent messages. Any match specification\n is removed.\n\nArgument `FlagList` must be `[]`.\n\nThe return value is always `1`.\n\n*Examples:*\n\nOnly trace messages to a specific process `Pid`:\n\n```erlang\n> trace:send(Session, [{[Pid, '_'],[],[]}], []).\n1\n```\n\nOnly trace messages matching `{reply, _}`:\n\n```erlang\n> trace:send(Session, [{['_', {reply,'_'}],[],[]}], []).\n1\n```\n\nOnly trace messages sent to the sender itself:\n\n```erlang\n> trace:send(Session, [{['$1', '_'],[{'=:=','$1',{self}}],[]}], []).\n1\n```\n\nOnly trace messages sent to other nodes:\n\n```erlang\n> trace:send(Session, [{['$1', '_'],[{'=/=',{node,'$1'},{node}}],[]}], []).\n1\n```\n\n> #### Note {: .info }\n>\n> A match specification for `send` trace can use all guard and body functions\n> except `caller`.\n\nFails by raising an error exception with an error reason of:\n\n- **`badarg`** - If an argument is invalid.\n\n- **`system_limit`** - If a match specification passed as argument has excessive\n nesting which causes scheduler stack exhaustion for the scheduler that the\n calling process is executing on.\n [Scheduler stack size](`e:erts:erl_cmd.md#sched_thread_stack_size`) can be configured\n when starting the runtime system.","ref":"trace.html#send/3"},{"type":"function","title":"trace.session_create/3","doc":"Create a new trace session.\n\nArgument `Name` is an atom name for the session. It will be returned when\ninspecting with `session_info/1`.\n\nArgument `Tracer` specifies the consumer of all trace events for the session. It\ncan be an identifier of a local process or port to receive all trace\nmessages.\n\n`Tracer` can also be a tuple `{TracerModule, TracerState}` for a tracer module\nto be called instead of sending a trace message. The tracer module can then\nignore or change the trace message. For more details on how to write a tracer\nmodule, see module `m:erl_tracer`.\n\nArgument `Opts` must be `[]`.\n\nReturns an opaque handle to the trace session. The handle will keep the session\nalive. If the handle is dropped and garbage collected, the session will be\ndestroyed and cleaned up as if `session_destroy/1` was called.","ref":"trace.html#session_create/3"},{"type":"function","title":"trace.session_destroy/1","doc":"Destroy a trace session and cleanup all its settings on processes, ports, and\nfunctions.\n\nThe only things not cleaned up are trace messages that have already been sent.\n\nReturns `true` if the session was active. Returns `false` if the session had\nalready been destroyed by either an earler call to this function or the garbage\ncollector.","ref":"trace.html#session_destroy/1"},{"type":"function","title":"trace.session_info/1","doc":"Return which trace sessions that affect a port, process, function, or event.\n\nArgument `all` returns all active trace sessions that exists on the node.\n\nReturns a list of [weak session handles](`t:session_weak_ref/0`) or `undefined` if the\nprocess/port/function does not exists.","ref":"trace.html#session_info/1"},{"type":"function","title":"trace.system/3","doc":"Enable/disable monitoring of system events.\n\nArgument `Session` is the trace session to operate on as returned by\n`session_create/3`.\n\nArgument `Event` is an atom describing the kind of system event to\nmonitor. To enable monitoring argument `Value` is, depending on event, either a\nlimit of that event or the atom `true`. To disable monitoring pass `Value` as the\natom `false`.\n\nWhen a monitored system event happens, a message is sent to the session\ntracer. The session tracer must be a process otherwise the function call will\nfail.\n\nThe following `Event`s with `Value`s can be monitored:\n\n- **`long_gc, Time`** - If a garbage collection in the system takes at least\n `Time` wall clock milliseconds, a message `{monitor, GcPid, long_gc, Info}` is\n sent. `GcPid` is the pid that was garbage collected. `Info` is a list of\n two-element tuples describing the result of the garbage collection.\n\n One of the tuples is `{timeout, GcTime}`, where `GcTime` is the time for the\n garbage collection in milliseconds. The other tuples are tagged with\n `heap_size`, `heap_block_size`, `stack_size`, `mbuf_size`, `old_heap_size`,\n and `old_heap_block_size`. These tuples are explained in the description of\n trace message [`gc_minor_start`](`m:trace#gc_minor_start`) (see\n `trace:process/4`). New tuples can be added, and the order of the tuples in\n the `Info` list can be changed at any time without prior notice.\n\n- **`long_message_queue, {Disable, Enable}`** - If the number of messages in the\n message queue of a process reach `Enable`, a message `{monitor, Pid,\n long_message_queue, Long}` is sent. `Pid` is the process identifier of the\n process that got a long message queue and `Long` will equal `true` indicating\n that it is in a _long message queue_ state. No more `long_message_queue`\n monitor messages will be sent due to the process identified by `Pid` until its\n message queue length falls down to a length of `Disable` length. When this\n happens, a `long_message_queue` monitor message with `Long` equal to `false`\n will be sent indicating that the process is no longer in a _long message\n queue_ state. As of this, if the message queue length should again reach\n `Enable` length, a new `long_message_queue` monitor message with `Long` set to\n `true` will again be sent. That is, a `long_message_queue` monitor message is\n sent when a process enters or leaves a _long message queue_ state where these\n state changes are defined by the `Enable` and `Disable` parameters.\n\n `Enable` must be an integer larger than zero. `Disable` must be an integer\n larger than or equal to zero and smaller than `Enable`. If the above is not\n satisfied the operation will fail with a `badarg` error exception. You are\n recommended to use a much smaller value for `Disable` length than `Enable`\n length in order not to be flooded with `long_message_queue` monitor messages.\n\n- **`long_schedule, Time`** - If a process or port in the system runs\n uninterrupted for at least `Time` wall clock milliseconds, a message\n `{monitor, PidOrPort, long_schedule, Info}` is sent.\n `PidOrPort` is the process or port that was running. `Info` is a list of\n two-element tuples describing the event.\n\n If a `t:pid/0`, the tuples `{timeout, Millis}`, `{in, Location}`, and\n `{out, Location}` are present, where `Location` is either an MFA\n (`{Module, Function, Arity}`) describing the function where the process was\n scheduled in/out, or the atom `undefined`.\n\n If a `t:port/0`, the tuples `{timeout, Millis}` and `{port_op,Op}` are\n present. `Op` is one of `proc_sig`, `timeout`, `input`, `output`, `event`, or\n `dist_cmd`, depending on which driver callback was executing.\n\n `proc_sig` is an internal operation and is never to appear, while the others\n represent the corresponding driver callbacks `timeout`, `ready_input`,\n `ready_output`, `event`, and `outputv` (when the port is used by\n distribution). Value `Millis` in tuple `timeout` informs about the\n uninterrupted execution time of the process or port, which always is equal to\n or higher than the `Time` value supplied when starting the trace. New tuples\n can be added to the `Info` list in a future release. The order of the tuples\n in the list can be changed at any time without prior notice.\n\n This can be used to detect problems with NIFs or drivers that take too long to\n execute. 1 ms is considered a good maximum time for a driver callback or a\n NIF. However, a time-sharing system is usually to consider everything < 100 ms\n as \"possible\" and fairly \"normal\". However, longer schedule times can indicate\n swapping or a misbehaving NIF/driver. Misbehaving NIFs and drivers can cause\n bad resource utilization and bad overall system performance.\n\n- **`large_heap, Size`** - If a garbage collection in the system results in\n the allocated size of a heap being at least `Size` words, a message\n `{monitor, GcPid, large_heap, Info}` is sent. `GcPid` and `Info` are the same\n as for `long_gc` described above, except that the tuple tagged with `timeout`\n is not present.\n\n The monitor message is sent if the sum of the sizes of all memory blocks\n allocated for all heap generations after a garbage collection is equal to or\n higher than `Size`.\n\n When a process is killed by\n [`max_heap_size`](`e:erts:erlang#process_flag_max_heap_size`), it is killed before\n the garbage collection is complete and thus no large heap message is sent.\n\n- **`busy_port, true`** - If a process in the system gets suspended because it sends\n to a busy port, a message `{monitor, SusPid, busy_port, Port}` is\n sent. `SusPid` is the pid that got suspended when sending to `Port`.\n\n- **`busy_dist_port, true`[](){: #busy_dist_port } **\n If a process in the system gets suspended because it sends to a process on a remote\n node whose inter-node communication was handled by a busy port, a message\n `{monitor, SusPid, busy_dist_port, Port}` is sent. `SusPid` is the pid that\n got suspended when sending through the inter-node communication port `Port`.\n\nTo disable system monitoring of a event pass the value as `false`. There are no\nother special values (like zero) to disable monitoring of an event. Some of the\nevents have an unspecified minimum value. Lower values will be adjusted to the\nminimum value. For example, it is currently not possible to monitor all garbage\ncollections with `{long_gc, 0}`.\n\n> #### Note {: .info }\n>\n> If the session tracer process gets so large that it itself starts to cause\n> system monitor messages when garbage collecting, the messages enlarge the\n> process message queue and probably make the problem worse.\n>\n> Keep the tracer process neat and do not set the system monitor limits too\n> tight.\n\nFailures:\n\n- **`badarg`** - If the session tracer is not a local process.","ref":"trace.html#system/3"},{"type":"type","title":"trace.match_variable/0","doc":"","ref":"trace.html#t:match_variable/0"},{"type":"type","title":"trace.session/0","doc":"A handle to an isolated trace session.","ref":"trace.html#t:session/0"},{"type":"opaque","title":"trace.session_strong_ref/0","doc":"","ref":"trace.html#t:session_strong_ref/0"},{"type":"opaque","title":"trace.session_weak_ref/0","doc":"A weak session handle as returned by `session_info/1`. A weak session handle can\nbe used like a full session handle, but it will not prevent the session from\nbeing destroyed when the last strong handle is garbage collected.","ref":"trace.html#t:session_weak_ref/0"},{"type":"type","title":"trace.system_event/0","doc":"","ref":"trace.html#t:system_event/0"},{"type":"type","title":"trace.system_value/0","doc":"","ref":"trace.html#t:system_value/0"},{"type":"type","title":"trace.trace_flag/0","doc":"","ref":"trace.html#t:trace_flag/0"},{"type":"type","title":"trace.trace_info_flag/0","doc":"","ref":"trace.html#t:trace_info_flag/0"},{"type":"type","title":"trace.trace_info_item_result/0","doc":"","ref":"trace.html#t:trace_info_item_result/0"},{"type":"type","title":"trace.trace_info_return/0","doc":"","ref":"trace.html#t:trace_info_return/0"},{"type":"type","title":"trace.trace_info_system_item/0","doc":"","ref":"trace.html#t:trace_info_system_item/0"},{"type":"type","title":"trace.trace_match_spec/0","doc":"","ref":"trace.html#t:trace_match_spec/0"},{"type":"type","title":"trace.trace_pattern_flag/0","doc":"","ref":"trace.html#t:trace_pattern_flag/0"},{"type":"type","title":"trace.trace_pattern_mfa/0","doc":"","ref":"trace.html#t:trace_pattern_mfa/0"},{"type":"extras","title":"Kernel Application","doc":"\n# Kernel Application","ref":"kernel_app.html"},{"type":"extras","title":"Description - Kernel Application","doc":"The Kernel application has all the code necessary to run the Erlang runtime\nsystem: file servers, code servers, and so on.\n\nThe Kernel application is the first application started. It is mandatory in the\nsense that the minimal system based on Erlang/OTP consists of Kernel and STDLIB.\nKernel contains the following functional areas:\n\n- Start, stop, supervision, configuration, and distribution of applications\n- Code loading\n- Logging\n- Global name service\n- Supervision of Erlang/OTP\n- Communication with sockets\n- Operating system interface","ref":"kernel_app.html#description"},{"type":"extras","title":"Logger Handlers - Kernel Application","doc":"Two standard logger handlers are defined in the Kernel application. These are\ndescribed in the [Kernel User's Guide](logger_chapter.md), and in the\n`m:logger_std_h` and [`logger_disk_log_h` ](`m:logger_disk_log_h`)manual pages.\n\n[](){: #erl_signal_server }","ref":"kernel_app.html#logger-handlers"},{"type":"extras","title":"OS Signal Event Handler - Kernel Application","doc":"Asynchronous OS signals may be subscribed to via the Kernel applications event\nmanager (see [OTP Design Principles](`e:system:design_principles.md`) and\n`m:gen_event`) registered as `erl_signal_server`. A default signal handler is\ninstalled which handles the following signals:\n\n- **`sigusr1`** - The default handler will halt Erlang and produce a crashdump\n with slogan \"Received SIGUSR1\". This is equivalent to calling\n `erlang:halt(\"Received SIGUSR1\")`.\n\n- **`sigquit`** - The default handler will halt Erlang immediately. This is\n equivalent to calling `erlang:halt()`.\n\n- **`sigterm`** - The default handler will terminate Erlang normally. This is\n equivalent to calling `init:stop()`.","ref":"kernel_app.html#os-signal-event-handler"},{"type":"extras","title":"Events - Kernel Application","doc":"Any event handler added to `erl_signal_server` must handle the following events.\n\n- **`sighup`** - Hangup detected on controlling terminal or death of controlling\n process\n\n- **`sigquit`** - Quit from keyboard\n\n- **`sigabrt`** - Abort signal from abort\n\n- **`sigalrm`** - Timer signal from alarm\n\n- **`sigterm`** - Termination signal\n\n- **`sigusr1`** - User-defined signal 1\n\n- **`sigusr2`** - User-defined signal 2\n\n- **`sigchld`** - Child process stopped or terminated\n\n- **`sigstop`** - Stop process\n\n- **`sigtstp`** - Stop typed at terminal\n\n- **`sigcont`** - Continue after stop\n\n- **`sigwinch`** - Window size change\n\n- **`siginfo`** - Status request from keyboard. Note several operating systems\n (Linux in particular) do not support this signal. `os:set_signal/2` will thow\n a `badarg` exception if support is missing.\n\nSetting OS signals are described in `os:set_signal/2`.","ref":"kernel_app.html#events"},{"type":"extras","title":"Configuration - Kernel Application","doc":"The following configuration parameters are defined for the Kernel application.\nFor more information about configuration parameters, see file\n[`app`](app.md).\n\n- **`connect_all = true | false`{: #connect_all }** - If enabled (`true`), which\n also is the default, `m:global` will actively connect to all nodes that\n becomes known to it. Note that you also want to enable\n [`prevent_overlapping_partitions`](kernel_app.md#prevent_overlapping_partitions)\n in order for `global` to ensure that a fully connected network is maintained.\n `prevent_overlapping_partitions` will also prevent inconsistencies in\n `global`'s name registration and locking.\n\n The now deprecated command line argument\n [`-connect_all `](`e:erts:erl_cmd.md#connect_all`) has the same\n effect as the `connect_all` configuration parameter. If this configuration\n parameter is defined, it will override the command line argument.\n\n- **`distributed = [Distrib]`{: #distributed }** - Specifies which applications\n that are distributed and on which nodes they are allowed to execute. In this\n parameter:\n\n - `Distrib = {App,Nodes} | {App,Time,Nodes}`\n - `App = atom()`\n - `Time = integer()>0`\n - `Nodes = [node() | {node(),...,node()}]`\n\n The parameter is described in `application:load/2`.\n\n- **`dist_auto_connect = Value`{: #dist_auto_connect }** - Specifies when nodes\n are automatically connected. If this parameter is not specified, a node is\n always automatically connected, for example, when a message is to be sent to\n that node. `Value` is one of:\n\n - **`never`** - Connections are never automatically established, they must be\n explicitly connected. See `m:net_kernel`.\n\n - **`once`** - Connections are established automatically, but only once per\n node. If a node goes down, it must thereafter be explicitly connected. See\n `m:net_kernel`.\n\n- **`epmd_module = module()`{: #epmd_module }** - Configures the module\n responsible for communication with [epmd](`e:erts:epmd_cmd.md`). If this parameter\n is undefined, it defaults to `erl_epmd`.\n\n The now deprecated command line argument\n [`-epmd_module `](`e:erts:erl_cmd.md#epmd_module`) has the same\n effect as the `epmd_module` configuration parameter. If this configuration\n parameter is defined, it will override the command line argument.\n\n- **`erl_epmd_node_listen_port = integer()`{: #erl_epmd_node_listen_port }** - Configures the port used by `m:erl_epmd`\n to listen for connection and connect to other nodes. If this flag is set, the\n Erlang VM will boot in distributed mode even if EPMD is not available. If not\n set, a port is chosen automatically (equivalent to port `0`). See `m:erl_epmd`\n for more details.\n\n The now deprecated command line argument\n [`erl_epmd_port `](`e:erts:erl_cmd.md#erl_epmd_port`) has the same\n effect as the `erl_epmd_node_listen_port` configuration parameter. If this\n configuration parameter is defined, it will override the command line argument.\n\n- **`permissions = [Perm]`{: #permissions }** - Specifies the default permission\n for applications when they are started. In this parameter:\n\n - `Perm = {ApplName,Bool}`\n - `ApplName = atom()`\n - `Bool = boolean()`\n\n Permissions are described in `application:permit/2`.\n\n- **`logger = [Config]`{: #logger }** - Specifies the configuration for\n [Logger](`m:logger`), except the primary log level, which is specified with\n [`logger_level`](kernel_app.md#logger_level), and the compatibility with\n [SASL Error Logging](`e:sasl:error_logging.md`), which is specified with\n [`logger_sasl_compatible`](kernel_app.md#logger_sasl_compatible).\n\n The `logger `parameter is described in section\n [Logging](logger_chapter.md#logger_parameter) in the Kernel User's Guide.\n\n- **`logger_level = Level`{: #logger_level }** - Specifies the primary log level\n for Logger. Log events with the same, or a more severe level, pass through the\n primary log level check. See section [Logging](logger_chapter.md) in the\n Kernel User's Guide for more information about Logger and log levels.\n\n `Level = emergency | alert | critical | error | warning | notice | info | debug | all | none`\n\n To change the primary log level at runtime, use\n [`logger:set_primary_config(level, Level)`](`logger:set_primary_config/2`).\n\n Defaults to `notice`.\n\n- **`logger_metadata = Metadata`{: #logger_metadata }** - Specifies primary\n metadata for log events.\n\n `Metadata = map()`\n\n Defaults to `#{}`.\n\n- **`logger_sasl_compatible = true | false`{: #logger_sasl_compatible }** -\n Specifies if Logger behaves backwards compatible with the SASL error logging\n functionality from releases prior to Erlang/OTP 21.0.\n\n If this parameter is set to `true`, the default Logger handler does not log\n any progress-, crash-, or supervisor reports. If the SASL application is then\n started, it adds a Logger handler named `sasl`, which logs these events\n according to values of the SASL configuration parameter `sasl_error_logger`\n and `sasl_errlog_type`.\n\n See section\n [Deprecated Error Logger Event Handlers and Configuration](`e:sasl:sasl_app.md#deprecated_error_logger_config`)\n in the sasl(6) manual page for information about the SASL configuration\n parameters.\n\n See section [SASL Error Logging](`e:sasl:error_logging.md`) in the SASL User's\n Guide, and section\n [Backwards Compatibility with error_logger](logger_chapter.md#backwards-compatibility-with-error_logger)\n in the Kernel User's Guide for information about the SASL error logging\n functionality, and how Logger can be backwards compatible with this.\n\n Defaults to `false`.\n\n > #### Note {: .info }\n >\n > If this parameter is set to `true`, `sasl_errlog_type` indicates that\n > progress reports shall be logged, and the configured primary log level is\n > `notice` or more severe, then SASL automatically sets the primary log level\n > to `info`. That is, this setting can potentially overwrite the value of the\n > Kernel configuration parameter `logger_level`. This is to allow progress\n > reports, which have log level `info`, to be forwarded to the handlers.\n\n- **`global_groups = [GroupTuple]`{: #global_groups }** - Defines global groups,\n see `m:global_group`. In this parameter:\n\n - `GroupTuple = {GroupName, [Node]} | {GroupName, PublishType, [Node]}`\n - `GroupName = atom()`\n - `PublishType = normal | hidden`\n - `Node = node()`\n\n- **`inet_default_connect_options = [{Opt, Val}]`{: #inet_default_connect_options }** - Specifies default options for `connect`\n sockets, see `m:inet`.\n\n- **`inet_default_listen_options = [{Opt, Val}]`{: #inet_default_listen_options\n }** - Specifies default options for `listen` (and `accept`) sockets, see\n `m:inet`.\n\n- **`inet_dist_use_interface = ip_address()`{: #inet_dist_use_interface }** - If\n the host of an Erlang node has many network interfaces, this parameter\n specifies which one to listen on. For the type definition of `ip_address()`,\n see `m:inet`.\n\n- **`inet_dist_listen_min = First`{: #inet_dist_listen } \n `inet_dist_listen_max = Last`** \n Defines the `First..Last` port range for the listener socket of a distributed\n Erlang node.\n\n- **`inet_dist_listen_options = Opts`{: #inet_dist_listen_options }** - Defines\n a list of extra socket options to be used when opening the listening socket\n for a distributed Erlang node. See `gen_tcp:listen/2`.\n\n- **`inet_dist_connect_options = Opts`{: #inet_dist_connect_options }** -\n Defines a list of extra socket options to be used when connecting to other\n distributed Erlang nodes. See `gen_tcp:connect/4`.\n\n- **`inet_parse_error_log = silent`{: #inet_parse_error_log }** - If set, no log\n events are issued when erroneous lines are found and skipped in the various\n Inet configuration files.\n\n- **`inetrc = Filename`{: #inetrc }** - The name (string) of an Inet user\n configuration file. For details, see section\n [`Inet Configuration`](`e:erts:inet_cfg.md`) in the ERTS User's Guide.\n\n- **`net_setuptime = SetupTime`{: #net_setuptime }** -\n `SetupTime` must be a positive integer or floating point number, and is\n interpreted as the maximum allowed time for each network operation during\n connection setup to another Erlang node. The maximum allowed value is `120`.\n If higher values are specified, `120` is used. Default is 7 seconds if the\n variable is not specified, or if the value is incorrect (for example, not a\n number).\n\n Notice that this value does not limit the total connection setup time, but\n rather each individual network operation during the connection setup and\n handshake.\n\n- **`net_ticker_spawn_options = Opts`{: #net_ticker_spawn_options }** - Defines\n a list of extra spawn options for net ticker processes. There exist one such\n process for each connection to another node. A net ticker process is\n responsible for supervising the connection it is associated with. These\n processes also execute the distribution handshake protocol when setting up\n connections. When there is a large number of distribution connections, setting\n up garbage collection options can be helpful to reduce memory usage. Default\n is `[link, {priority, max}]`, and these two options cannot be changed. The\n `monitor` and `{monitor, MonitorOpts}` options are not allowed and will be\n dropped if present. See the documentation of the `erlang:spawn_opt/4` BIF for\n information about valid options. If the `Opts` list is not a proper list, or\n containing invalid options the setup of connections will fail.\n\n Note that the behavior described above is only true if the distribution\n carrier protocol used is implemented as described in\n [ERTS User's Guide ➜ How to implement an Alternative Carrier for the Erlang Distribution ➜ Distribution Module](`e:erts:alt_dist.md#distribution-module`)\n without further alterations. The implementer of the distribution carrier\n protocol used, may have chosen to ignore the `net_ticker_spawn_options`\n parameter or altered its behavior. Currently all distribution modules shipped\n with OTP do, however, behave as described above.\n\n- **`net_tickintensity = NetTickIntensity`{: #net_tickintensity }** - _Net tick\n intensity_ specifies how many ticks to send during a\n [net tick time](kernel_app.md#net_ticktime) period when no other data is sent\n over a connection to another node. This also determines how often to check for\n data from the other node. The higher net tick intensity, the closer to the\n chosen net tick time period the node will detect an unresponsive node. The net\n tick intensity defaults to `4`. The value of `NetTickIntensity` should be an\n integer in the range `4..1000`. If the `NetTickIntensity` is not an integer or\n an integer less than `4`, `4` will silently be used. If `NetTickIntensity` is\n an integer larger than `1000`, `1000` will silently be used.\n\n > #### Note {: .info }\n >\n > Note that all communicating nodes are expected to use the same _net tick\n > intensity_ as well as the same _net tick time_.\n\n > #### Warning {: .warning }\n >\n > Be careful not to set a too high net tick intensity, since you can overwhelm\n > the node with work if it is set too high.\n\n- **`net_ticktime = NetTickTime`{: #net_ticktime }** - Specifies the _net tick\n time_ in seconds. This is the approximate time a connected node may be\n unresponsive until it is considered down and thereby disconnected.\n\n Net tick time together with\n [net tick intensity](kernel_app.md#net_tickintensity) determines an interval\n `TickInterval = NetTickTime/NetTickIntensity`. Once every `TickInterval`\n seconds, each connected node is ticked if nothing has been sent to it during\n that last `TickInterval` seconds. A tick is a small package sent on the\n connection. A connected node is considered to be down if no ticks or payload\n packages have been received during the last `NetTickIntensity` number of\n `TickInterval` seconds intervals. This ensures that nodes that are not\n responding, for reasons such as hardware errors, are considered to be down.\n\n As the availability is only checked every `TickInterval` seconds, the actual\n time `T` a node have been unresponsive when detected may vary between `MinT`\n and `MaxT`, where:\n\n ```c\n MinT = NetTickTime - NetTickTime / NetTickIntensity\n MaxT = NetTickTime + NetTickTime / NetTickIntensity\n ```\n\n `NetTickTime` defaults to `60` seconds and `NetTickIntensity` defaults to `4`.\n Thus, `45 #### Note {: .info }\n >\n > Notice that _all_ communicating nodes are to have the _same_ `NetTickTime`\n > and `NetTickIntensity` values specified, as it determines both the frequency\n > of outgoing ticks and the expected frequency of incominging ticks.\n\n `NetTickTime` needs to be a multiple of `NetTickIntensity`. If the configured\n values are not, `NetTickTime` will internally be rounded up to the nearest\n millisecond.\n [`net_kernel:get_net_ticktime()`](`net_kernel:get_net_ticktime/0`) will,\n however, report net tick time truncated to the nearest second.\n\n Normally, a terminating node is detected immediately by the transport protocol\n (like TCP/IP).\n\n- **`prevent_overlapping_partitions = true | false`{:\n #prevent_overlapping_partitions }** - If enabled (`true`), `global` will\n actively prevent overlapping partitions from forming when connections are lost\n between nodes. This fix is enabled by default. If you are about to disable\n this fix, make sure to read the\n [`global`](`m:global#prevent_overlapping_partitions`) documentation about this\n fix for more important information about this.\n\n- **`shutdown_timeout = integer() | infinity`{: #shutdown_timeout }** -\n Specifies the time `application_controller` waits for an application to\n terminate during node shutdown. If the timer expires, `application_controller`\n brutally kills `application_master` of the hanging application. If this\n parameter is undefined, it defaults to `infinity`.\n\n- **`sync_nodes_mandatory = [NodeName]`{: #sync_nodes_mandatory }** - Specifies\n which other nodes that _must_ be alive for this node to start properly. If\n some node in the list does not start within the specified time, this node does\n not start either. If this parameter is undefined, it defaults to `[]`.\n\n- **`sync_nodes_optional = [NodeName]`{: #sync_nodes_optional }** - Specifies\n which other nodes that _can_ be alive for this node to start properly. If some\n node in this list does not start within the specified time, this node starts\n anyway. If this parameter is undefined, it defaults to the empty list.\n\n- **`sync_nodes_timeout = integer() | infinity`{: #sync_nodes_timeout }** -\n Specifies the time (in milliseconds) that this node waits for the mandatory\n and optional nodes to start. If this parameter is undefined, no node\n synchronization is performed. This option ensures that `global` is\n synchronized.\n\n- **`start_distribution = true | false`{: #start_distribution }** - Starts all\n distribution services, such as `rpc`, `global`, and `net_kernel` if the\n parameter is `true`. This parameter is to be set to `false` for systems who\n want to disable all distribution functionality.\n\n Defaults to `true`.\n\n- **`start_dist_ac = true | false`{: #start_dist_ac }** - Starts the `dist_ac`\n server if the parameter is `true`. This parameter is to be set to `true` for\n systems using distributed applications.\n\n Defaults to `false`. If this parameter is undefined, the server is started if\n parameter `distributed` is set.\n\n- **`start_boot_server = true | false`{: #start_boot_server }** - Starts the\n `boot_server` if the parameter is `true` (see `m:erl_boot_server`). This\n parameter is to be set to `true` in an embedded system using this service.\n\n Defaults to `false`.\n\n- **`boot_server_slaves = [SlaveIP]`{: #boot_server_slaves }** - If\n configuration parameter `start_boot_server` is `true`, this parameter can be\n used to initialize `boot_server` with a list of slave IP addresses:\n\n `SlaveIP = string() | atom | {integer(),integer(),integer(),integer()}`,\n\n where `0 <= integer() <=255`.\n\n Examples of `SlaveIP` in atom, string, and tuple form:\n\n `'150.236.16.70', \"150,236,16,70\", {150,236,16,70}`.\n\n Defaults to `[]`.\n\n- **`start_disk_log = true | false`{: #start_disk_log }** - Starts the\n `disk_log_server` if the parameter is `true` (see `m:disk_log`). This\n parameter is to be set to `true` in an embedded system using this service.\n\n Defaults to `false`.\n\n- **`start_pg = true | false`{: #start_pg }** - Starts the\n default `pg` scope server (see `m:pg`) if the parameter is `true`. This\n parameter is to be set to `true` in an embedded system that uses this service.\n\n Defaults to `false`.\n\n- **`start_timer = true | false`{: #start_timer }** - Starts the `timer_server`\n if the parameter is `true` (see `m:timer`). This parameter is to be set to\n `true` in an embedded system using this service.\n\n Defaults to `false`.\n\n- **`shell_docs_ansi = boolean()`{: #shell_docs_ansi }** - Specifies whether\n the documentation rendered in the shell should use ANSI escape codes.\n\n See also `t:shell_docs:config/0`.\n\n- **`shell_history = enabled | disabled | module()`{: #shell_history }** -\n Specifies whether shell history should be logged to disk between usages of\n `erl` (`enabled`), not logged at all (`disabled`), or a user-specified module\n will be used to log shell history. This module should export\n `load() -> [string()]` returning a list of strings to load in the shell when\n it starts, and `add(iodata()) -> ok.` called every time new line is entered in\n the shell. By default logging is disabled.\n\n- **`shell_history_drop = [string()]`{: #shell_history_drop }** - Specific log\n lines that should not be persisted. For example `[\"q().\", \"init:stop().\"]`\n will allow to ignore commands that shut the node down. Defaults to `[]`.\n\n- **`shell_history_file_bytes = integer()`{: #shell_history_file_bytes }** - How\n many bytes the shell should remember. By default, the value is set to 512kb,\n and the minimal value is 50kb.\n\n- **`shell_history_path = string()`{: #shell_history_path }** - Specifies where\n the shell history files will be stored. defaults to the user's cache directory\n as returned by `filename:basedir(user_cache, \"erlang-history\")`.\n\n- **`shutdown_func = {Mod :: atom(), Func :: atom()}`{: #shutdown_func }** -\n Sets a function that `application_controller` calls when it starts to\n terminate. The function is called as `Mod:Func(Reason)`, where `Reason` is the\n terminate reason for `application_controller`, and it must return as soon as\n possible for `application_controller` to terminate properly.\n\n- **`source_search_rules = [DirRule] | [SuffixRule]`{: #source_search_rules }**\n\n Where:\n\n - `DirRule = {ObjDirSuffix,SrcDirSuffix}`\n - `SuffixRule = {ObjSuffix,SrcSuffix,[DirRule]}`\n - `ObjDirSuffix = string()`\n - `SrcDirSuffix = string()`\n - `ObjSuffix = string()`\n - `SrcSuffix = string()`\n\n Specifies a list of rules for use by `filelib:find_file/2`\n `filelib:find_source/2` If this is set to some other value than the empty\n list, it replaces the default rules. Rules can be simple pairs of directory\n suffixes, such as `{\"ebin\", \"src\"}`, which are used by `filelib:find_file/2`,\n or triples specifying separate directory suffix rules depending on file name\n extensions, for example `[{\".beam\", \".erl\", [{\"ebin\", \"src\"}]}`, which are\n used by `filelib:find_source/2`. Both kinds of rules can be mixed in the list.\n\n The interpretation of `ObjDirSuffix` and `SrcDirSuffix` is as follows: if the\n end of the directory name where an object is located matches `ObjDirSuffix`,\n then the name created by replacing `ObjDirSuffix` with `SrcDirSuffix` is\n expanded by calling `filelib:wildcard/1`, and the first regular file found\n among the matches is the source file.\n\n- **`standard_io_encoding = Encoding`{: #standard_io_encoding }** - Set whether\n bytes sent or received via standard_io should be interpreted as unicode or\n latin1. By default input and output is interpreted as Unicode if it is\n supported on the host. With this flag you may configure the encoding on\n startup.\n\n This works similarly to\n [`io:setopts(standard_io, {encoding, Encoding})`](`io:setopts/2`) but is\n applied before any bytes on standard_io may have been read.\n\n Encoding is one of:\n\n - **`unicode`** - Configure standard_io to use unicode mode.\n\n - **`latin1`** - Configure standard_io to use latin1 mode.\n\n - **`_`** - Anything other than unicode or latin1 will be ignored and the\n system will configure the encoding by itself, typically unicode on modern\n systems.\n\n See\n [Escripts and non-interactive I/O in Unicode Usage in Erlang](`e:stdlib:unicode_usage.md#escripts-and-non-interactive-i-o`)\n for more details.\n\n- **`os_cmd_shell = string()`{: #os_cmd_shell }** - Specifies which shell to\n use when invoking system commands via `os:cmd/2`. By default the shell is detected\n automatically.","ref":"kernel_app.html#configuration"},{"type":"extras","title":"Deprecated Configuration Parameters - Kernel Application","doc":"In Erlang/OTP 21.0, a new API for logging was added. The old `error_logger`\nevent manager, and event handlers running on this manager, still work, but they\nare no longer used by default.\n\nThe following application configuration parameters can still be set, but they\nare only used if the corresponding configuration parameters for Logger are not\nset.\n\n- **`error_logger`** - Replaced by setting the [`type`](`m:logger_std_h#type`),\n and possibly [`file`](`m:logger_std_h#file`) and\n [`modes`](`m:logger_std_h#modes`) parameters of the default `logger_std_h`\n handler. Example:\n\n ```text\n erl -kernel logger '[{handler,default,logger_std_h,#{config=>#{file=>\"/tmp/erlang.log\"}}}]'\n ```\n\n- **`error_logger_format_depth`**{: #error_logger_format_depth } - Replaced by setting the\n [`depth`](`m:logger_formatter#depth`) parameter of the default handlers\n formatter. Example:\n\n ```text\n erl -kernel logger '[{handler,default,logger_std_h,#{formatter=>{logger_formatter,#{legacy_header=>true,template=>[{logger_formatter,header},\"\\n\",msg,\"\\n\"],depth=>10}}}]'\n ```\n\nSee [Backwards compatibility with error_logger](logger_chapter.md#backwards-compatibility-with-error_logger)\nfor more information.","ref":"kernel_app.html#deprecated-configuration-parameters"},{"type":"extras","title":"Kernel Release Notes","doc":"\n# Kernel Release Notes\n\nThis document describes the changes made to the Kernel application.","ref":"notes.html"},{"type":"extras","title":"Kernel 10.1.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-10-1-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- 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.\n \n This happened with low probability when the OS signaled that the socket was ready for reading in combination with an internal time-out retry.\n \n 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.\n\n Own Id: OTP-19235 Aux Id: ERIERL-1133, [PR-8837]\n\n- 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.\n\n Own Id: OTP-19258 Aux Id: OTP-19061, ERIERL-1134\n\n[PR-8837]: https://github.com/erlang/otp/pull/8837","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 10.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-10-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- 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.\n\n Own Id: OTP-19097 Aux Id: [PR-8503]\n\n- Opening a `disk_log` file and combining `head_func` with `rotate` options did not work.\n\n Own Id: OTP-19104 Aux Id: ERIERL-870\n\n- Fixed an error info printout for `erlang:is_process_alive/1` on non-local pids.\n\n Own Id: OTP-19134 Aux Id: [PR-8560]\n\n- 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.\n\n Own Id: OTP-19175 Aux Id: [GH-8561], [PR-8690]\n\n- 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.\n\n Own Id: OTP-19205\n\n- 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.\n\n Own Id: OTP-19208 Aux Id: [PR-8672]\n\n- Corrected socket:ioctl for genaddr (SIOCGENADDR).\n\n Own Id: OTP-19216\n\n[PR-8503]: https://github.com/erlang/otp/pull/8503\n[PR-8560]: https://github.com/erlang/otp/pull/8560\n[GH-8561]: https://github.com/erlang/otp/issues/8561\n[PR-8690]: https://github.com/erlang/otp/pull/8690\n[PR-8672]: https://github.com/erlang/otp/pull/8672","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Added functions `getservbyname` and `getservbyport` to the `net` module.\n\n Own Id: OTP-19101 Aux Id: OTP-18835\n\n- Introduced enet | esock variants of `m:inet` functions, either when called with sockets,\n with explicit inet_backend config or with the e inet_backend kernel config option.\n\n Own Id: OTP-19132 Aux Id: OTP-19101\n\n- The function `socket:i/0` now uses the `m:net` module (instead of the `m:inet` module) for service translation.\n\n Own Id: OTP-19138 Aux Id: OTP-19101\n\n- 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.\n\n Own Id: OTP-19199 Aux Id: OTP-19175, [GH-8561], [GH-8690], [GH-8785]\n\n[GH-8561]: https://github.com/erlang/otp/issues/8561\n[GH-8690]: https://github.com/erlang/otp/issues/8690\n[GH-8785]: https://github.com/erlang/otp/issues/8785","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 10.0.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-10-0-1"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Polish the `m:logger` documentation.\n\n Own Id: OTP-19118 Aux Id: [PR-8534]\n\n[PR-8534]: https://github.com/erlang/otp/pull/8534","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 10.0 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-10-0"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fixed a crash when calling `file:delete/2` with an empty option list.\n\n Own Id: OTP-18590 Aux Id: [PR-7220]\n\n- 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.\n\n Own Id: OTP-18878 Aux Id: [GH-7718], OTP-17734\n\n- The error information for `erlang:phash/2` has been corrected.\n\n Own Id: OTP-18904 Aux Id: [PR-7960]\n\n- `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.\n\n Own Id: OTP-18930 Aux Id: [PR-7993], [GH-4992]\n\n- Calling `logger:add_handlers/1` with config option now works.\n\n Own Id: OTP-18954 Aux Id: [GH-8061], [PR-8076]\n\n- The `code:del_path/1` function now also works on paths added through `-pa`, `-pz` , `-path` and the boot script.\n\n Own Id: OTP-18959 Aux Id: [GH-6692], [PR-7697]\n\n- A call to `socket:[recv|recvfrom|recvmsg]/*` with Timeout = 0 on Windows could cause a (case clause) crash if data is immediately available.\n\n Own Id: OTP-19063 Aux Id: OTP-18835\n\n- Improve heuristic for when a characters is wide in the shell for systems with old libc versions.\n\n Own Id: OTP-19087 Aux Id: [PR-8382]\n\n- Fix reading a line when reading from `t:io:user/0` to not consider `\\r` without `\\n` to be a new line when `erl` is started with `-noshell`.\n\n Own Id: OTP-19088 Aux Id: [PR-8396], [GH-8360]\n\n[PR-7220]: https://github.com/erlang/otp/pull/7220\n[GH-7718]: https://github.com/erlang/otp/issues/7718\n[PR-7960]: https://github.com/erlang/otp/pull/7960\n[PR-7993]: https://github.com/erlang/otp/pull/7993\n[GH-4992]: https://github.com/erlang/otp/issues/4992\n[GH-8061]: https://github.com/erlang/otp/issues/8061\n[PR-8076]: https://github.com/erlang/otp/pull/8076\n[GH-6692]: https://github.com/erlang/otp/issues/6692\n[PR-7697]: https://github.com/erlang/otp/pull/7697\n[PR-8382]: https://github.com/erlang/otp/pull/8382\n[PR-8396]: https://github.com/erlang/otp/pull/8396\n[GH-8360]: https://github.com/erlang/otp/issues/8360","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Added `file:read_file/2` with a `raw` option for reading files without going through the file server.\n\n Own Id: OTP-18589 Aux Id: [PR-7220]\n\n- 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. \n \n Kudos to Alexander Clouter that did almost all the work!\n\n Own Id: OTP-18713 Aux Id: [PR-6985], [GH-6985]\n\n- The `ebin` directories for escripts are now cached.\n\n Own Id: OTP-18778 Aux Id: [PR-7556]\n\n- `-callback` attributes haven been added to `m:application`, `m:logger_handler`, and `m:logger_formatter`.\n\n Own Id: OTP-18795 Aux Id: [PR-7703]\n\n- Progress reports from before logger is started are now logged when log level is set to debug.\n\n Own Id: OTP-18807 Aux Id: [PR-7732] ERIERL-985\n\n- The `code:where_is_file/2` and\n `code:which/1` functions now check for existence of the file directly instead of listing the content of each directory in the code path.\n\n Own Id: OTP-18816 Aux Id: [PR-7711]\n\n- Type specs has been added to the [`logger:Level/1,2,3`](`m:logger`) functions.\n\n Own Id: OTP-18820 Aux Id: [PR-7779]\n\n- 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.\n\n Own Id: OTP-18835\n\n- New functions `socket:sendv/*` for sending I/O vectors have been added.\n\n Own Id: OTP-18845\n\n- The shell now pages long output from the documentation help command ([`h(Module)`](`c:h/1`)), auto completions and the search command.\n\n Own Id: OTP-18846 Aux Id: [PR-7845]\n\n- Native coverage support has been implemented in the JIT. It will automatically be used by the `m:cover` tool to reduce the execution overhead when running cover-compiled code.\n \n There are also new APIs to support native coverage without using the `cover` tool.\n \n To instrument code for native coverage it must be compiled with the [`line_coverage`](`m:compile#line_coverage`) option.\n \n To enable native coverage in the runtime system, start it like so:\n \n ```text\n $ erl +JPcover true\n ```\n \n There are also the following new functions for supporting native coverage:\n \n * `code:coverage_support/0`\n * `code:get_coverage/2`\n * `code:reset_coverage/1`\n * `code:get_coverage_mode/0`\n * `code:get_coverage_mode/1`\n * `code:set_coverage_mode/1`\n\n Own Id: OTP-18856 Aux Id: [PR-7856]\n\n- Optimized code loading by moving certain operations from the code server to the caller.\n\n Own Id: OTP-18941 Aux Id: [PR-7981]\n\n- The documentation has been migrated to use Markdown and ExDoc.\n\n Own Id: OTP-18955 Aux Id: [PR-8026]\n\n- Application startup has been optimized by removing an intermediary process.\n\n Own Id: OTP-18963 Aux Id: [PR-8042]\n\n- 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.\n \n As of Erlang/OTP 27, the function `code:lib_dir/2`, the `-code_path_choice` flag, and using `m:erl_prim_loader` for reading members of an archive are deprecated.\n \n 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`.\n\n *** POTENTIAL INCOMPATIBILITY ***\n\n Own Id: OTP-18966 Aux Id: [PR-8091]\n\n- The undocumented and deprecated `file:pid2name` function has been removed.\n\n Own Id: OTP-18967 Aux Id: [PR-8092]\n\n- There is a new module `m: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**.\n\n Own Id: OTP-18980\n\n- Error logging has been improved when the `t:io:standard_io/0` reader and/or writer terminates with an error.\n\n Own Id: OTP-18989 Aux Id: [PR-8103]\n\n- `inet_backend = socket` has been optimized and reworked to be more compatible with the original `inet_backend = inet`.\n\n Own Id: OTP-19004 Aux Id: OTP-18835\n\n- Add an simple example (echo server) )to the socket users guide.\n\n Own Id: OTP-19042\n\n- `inet:i/0,1,2` has been improved to allow port numbers to be shown explicitly.\n\n Own Id: OTP-19053 Aux Id: [#6724]\n\n- The `socket` documentation has been reworked, and due to\n that a few details were fixed:\n * `socket:is_supported/1` now returns `true` for example for `protocols`\n that is a \"category\", not an item.\n * `socket:cancel_monitor/1` no longer badargs for a monitor that was set by\n another process, instead it returns `false` as for other unknown\n `reference()`s.\n\n Own Id: OTP-19054\n\n- Add `stdin`, `stdout` and `stderr` keys to `io:getopts/1` on `t:io:standard_io/0` to indicate if the respective I/O device is backed by a terminal.\n\n Own Id: OTP-19089 Aux Id: [PR-8396]\n\n[PR-7220]: https://github.com/erlang/otp/pull/7220\n[PR-6985]: https://github.com/erlang/otp/pull/6985\n[GH-6985]: https://github.com/erlang/otp/issues/6985\n[PR-7556]: https://github.com/erlang/otp/pull/7556\n[PR-7703]: https://github.com/erlang/otp/pull/7703\n[PR-7732]: https://github.com/erlang/otp/pull/7732\n[PR-7711]: https://github.com/erlang/otp/pull/7711\n[PR-7779]: https://github.com/erlang/otp/pull/7779\n[PR-7845]: https://github.com/erlang/otp/pull/7845\n[PR-7856]: https://github.com/erlang/otp/pull/7856\n[PR-7981]: https://github.com/erlang/otp/pull/7981\n[PR-8026]: https://github.com/erlang/otp/pull/8026\n[PR-8042]: https://github.com/erlang/otp/pull/8042\n[PR-8091]: https://github.com/erlang/otp/pull/8091\n[PR-8092]: https://github.com/erlang/otp/pull/8092\n[PR-8103]: https://github.com/erlang/otp/pull/8103\n[#6724]: https://github.com/erlang/otp/issues/6724\n[PR-8396]: https://github.com/erlang/otp/pull/8396","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 9.2.4.3 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-9-2-4-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"* 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.\n\n This happened with low probability when the OS signaled that the socket was ready for reading in combination with an internal time-out retry.\n\n 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.\n\n Own Id: OTP-19235 Aux Id: ERIERL-1133, PR-8837\n* 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.\n\n Own Id: OTP-19258 Aux Id: OTP-19061, ERIERL-1134","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 9.2.4.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-9-2-4-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"* A race in the kTLS flavour of SSL distribution has been fixed so 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.\n\n Own Id: OTP-19175 Aux Id: GH-8561, PR-8690\n* Fix 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.\n\n Own Id: OTP-19205\n* Add the stdlib application parameters `shell_redraw_prompt_on_output` which when set to `false` disables redrawing of the shell prompt if any other output is done.\n\n Own Id: OTP-19213 Aux Id: PR-8763 ERIERL-1108","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 9.2.4.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-9-2-4-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"* A call to socket:\\[recv|recvfrom|recvmsg]/* with Timeout = 0 on Windows could cause a (case clause) crash if data is immediately available.\n\n Own Id: OTP-19063 Aux Id: OTP-18835\n* Open a `disk_log` file and combining `head_func` with `rotate` options did not work.\n\n Own Id: OTP-19104 Aux Id: ERIERL-870","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 9.2.4 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-9-2-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"* Fix the shell Job Control Mode to not crash when typing `TAB` or `CTRL+R`.\n\n Own Id: OTP-19072 Aux Id: PR-8391\n* Fix calls to blocking `m:application` APIs to throw an exception with reason `terminating` if called when the system is terminating.\n\n This is done in order to avoid deadlocks during shutdown or restart.\n\n Own Id: OTP-19078 Aux Id: PR-8422","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 9.2.3 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-9-2-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"* When using IPv6, classic gen_udp failed to add (group) membership (drop was used instead).\n\n Own Id: OTP-19049 Aux Id: #8176\n* The check in inet_res of the RD bit has been relaxed slightly.\n\n Own Id: OTP-19056 Aux Id: PR-8312, OTP-17323","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 9.2.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-9-2-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"* Fix performance bug when using `io:fread` to read from `standard_io`. This regression was introduced in OTP 26.0.\n\n Own Id: OTP-18910 Aux Id: PR-7933 GH-7924\n* A bug in the code server could cause it to crash in some concurrent scenarios. This bug was introduced in 26.1.\n\n Own Id: OTP-18948 Aux Id: PR-8046\n* Fixed gen_udp:open/2 type spec to include already supported module socket address types.\n\n Own Id: OTP-18990 Aux Id: GH-8158\n* Fix reading of password for ssh client when in `user_interactive` mode.\n\n Own Id: OTP-19007 Aux Id: ERIERL-1049","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 9.2.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-9-2-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"* Fix `group` (that is the shell) to properly handle when an `get_until` callback function returned `{done, eof, []}` when an `eof` was detected.\n\n Own Id: OTP-18901","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 9.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-9-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- For `inet_backend = socket`, an unexpected receive error such as `etimedout`\n caused the receiving state machine server to crash. This bug has now been\n fixed.\n\n Own Id: OTP-18749 Aux Id: GH-7608\n\n- Fix bug where reading using `file` from a unicode enabled `standard_io`,\n `standard_error` or any other `group` backed device would result in incorrect\n values being returned or a crash.\n\n Now instead a no_translation error is returned to the caller when unicode data\n is read using `file`. See\n [Using Unicode](`e:stdlib:unicode_usage.md#escripts-and-non-interactive-i-o`)\n in the STDLIB User's Guide for more details on how to correctly read from\n `standard_io`.\n\n Own Id: OTP-18800 Aux Id: PR-7714 GH-7591\n\n- The native resolver interface module has gotten a rewrite of its ETS table\n handling to minimize term copying, and also to move the handling of client\n time-outs to the clients, which helps the native resolver name server from\n digging itself into a tar pit when heavily loaded.\n\n Own Id: OTP-18812 Aux Id: ERIERL-997\n\n- Replaced unintentional Erlang Public License 1.1 headers in some files with\n the intended Apache License 2.0 header.\n\n Own Id: OTP-18815 Aux Id: PR-7780\n\n- Fix bug in `pg` if a client process both monitored a group/scope and joined a\n group. The termination of such process resulted in crash of the `pg` server\n process.\n\n Own Id: OTP-18833 Aux Id: GH-7625, PR-7659\n\n- Fix crash when using `file:consult` and the underlying file read returns an\n error while reading.\n\n Own Id: OTP-18873 Aux Id: PR-7831\n\n- Corrected gen_tcp_socket listen option handling.\n\n Own Id: OTP-18883 Aux Id: #7764","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Add Windows support for DGRAM socket connect.\n\n Own Id: OTP-18762\n\n- Document the, previously opaque, types select_tag() and completion_tag().\n\n Own Id: OTP-18818 Aux Id: #7337","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 9.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-9-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fixed an issue with truncated crash slogans on failed emulator start.\n\n Own Id: OTP-18623 Aux Id: GH-7344\n\n- Fix shell:start_interactive function specification.\n\n Own Id: OTP-18628 Aux Id: GH-7280\n\n- Fix code:get_doc/1 to return missing, when it can't find erts instead of\n crashing.\n\n Own Id: OTP-18654 Aux Id: PR-7404\n\n- Function socket:close/1 could cause a VM crash on Windows.\n\n Own Id: OTP-18669 Aux Id: OTP-18029\n\n- Fix deadlock when `erl.exe` is used as part of a pipe on Windows and trying to\n set the encoding of the `standard_io` device.\n\n Own Id: OTP-18675 Aux Id: PR-7473 GH-7459\n\n- Expanded the documentation about how to use the `standard_io`,\n `standard_error` and `user` I/O devices.\n\n Added the types [`io:standard_io/0`](`t:io:standard_io/0`),\n `io:standard:error/0` and [`io:user/0`](`t:io:user/0`).\n\n Own Id: OTP-18676 Aux Id: PR-7473 GH-7459\n\n- Fix logger's overload protection mechanism to only fetch memory used by\n messages when needed.\n\n Own Id: OTP-18677 Aux Id: PR-7418 GH-7417\n\n- Fixed a number of socket-related issues causing incompatibilities with gen_tcp\n and gen_udp respectively.\n\n Own Id: OTP-18685\n\n- gen_tcp:connect with socket address and socket (inet-) backend fails because\n of missing callback function.\n\n Own Id: OTP-18707 Aux Id: #7530\n\n- The DNS RR cache used by \\`inet_res\\` has been fixed to preserve insert order,\n which is beneficial when the DNS server returns RRs in some specific order for\n e.g load balancing purposes.\n\n Own Id: OTP-18731 Aux Id: GH-7577, PR-7578\n\n- The options \\`reuseport\\`, \\`reuseport_lb\\` and \\`exclusiveaddruse\\` were\n accidentally not allowed for e.g \\`gen_udp:open/1,2\\`, which has now been\n corrected.\n\n Own Id: OTP-18734 Aux Id: OTP-18344, PR-6522, GH-6461, GH-7569\n\n- `gen_udp:recv/*` for Unix Domain Socket in binary mode and passive mode has\n been fixed to not crash.\n\n Own Id: OTP-18747 Aux Id: GH-7605\n\n- Fixed issue where cursor would not be placed at the end of the expression when\n navigating shell history.\n\n Own Id: OTP-18757 Aux Id: PR-7631","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Update gen_tcp_socket and gen_udp_socket to handle 'completion' (socket on\n Windows).\n\n Own Id: OTP-18586 Aux Id: OTP-18029\n\n- Add support for Unix Domain Sockets (only for STREAM sockets) on Windows for\n 'socket'.\n\n Own Id: OTP-18611 Aux Id: OTP-18029, #5024\n\n- Add basic support for socket ioctl on Windows.\n\n Own Id: OTP-18660\n\n- The [`file:location/0`](`t:file:location/0`) type is now exported.\n\n Own Id: OTP-18681\n\n- Add support for (Windows) socket option exclusiveaddruse.\n\n Own Id: OTP-18686\n\n- \\[socket] Add support for the 'nopush' option.\n\n Own Id: OTP-18687\n\n- Add support for socket option 'BSP STATE'.\n\n Own Id: OTP-18693\n\n- Add tcp socket options 'keepcnt', 'keepidle' and 'keepintvl'.\n\n Own Id: OTP-18698\n\n- Add support for misc (Windows) socket options ('max_msg_size' and 'maxdg').\n\n Own Id: OTP-18710\n\n- The keyboard shortcuts for the shell are now configurable.\n\n Own Id: OTP-18754 Aux Id: PR-7604 PR-7647\n\n- Optimized code_server to reduce repeated work when loading the same module\n concurrently.\n\n Own Id: OTP-18755 Aux Id: PR-7503","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 9.0.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-9-0-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fix bug where when you entered Alt+Enter in the terminal, the cursor would\n move to the last line, instead of moving to the next line.\n\n Own Id: OTP-18580 Aux Id: PR-7242\n\n- Fix so that the shell does not crash on startup when termcap is not available.\n\n Own Id: OTP-18624 Aux Id: GH-7296\n\n- Multiple socket:accept calls issue. When making multiple accept calls, only\n the last call is active.\n\n Own Id: OTP-18635 Aux Id: #7328\n\n- Fix the shell to ignore terminal delay when the terminal capabilities report\n that they should be used.\n\n Own Id: OTP-18636 Aux Id: PR-7352 GH-7308\n\n- Fix \"oldshell\" to echo characters while typing on Windows.\n\n Own Id: OTP-18637 Aux Id: PR-7359 GH-7324\n\n- Fix eof handling when reading from stdin when erlang is started using\n `-noshell`.\n\n Own Id: OTP-18640 Aux Id: PR-7384 GH-7368 GH-7286 GH-6881\n\n- On Windows, a call to the function socket:close, when there are waiting active\n calls to read, write or accept functions, could hang.\n\n Own Id: OTP-18646\n\n- Fix issues when reading or configuring `standard_io` on Windows when erl.exe\n is started using `-noshell` flag.\n\n Own Id: OTP-18649 Aux Id: GH-7261 PR-7400\n\n- gen_udp:connect with inet_backend = socket fails when the Address is a\n hostname (string or atom).\n\n Own Id: OTP-18650\n\n- Fixed problem which would cause shell to crash if particular escape sequence\n was written to stdout.\n\n Own Id: OTP-18651 Aux Id: PR-7242\n\n- Fixed problem where output would disappear if it was received after a prompt\n was written in the shell.\n\n Own Id: OTP-18652 Aux Id: PR-7242\n\n- Fix a crash where the location of erts could not be found in rebar3 dev\n builds.\n\n Own Id: OTP-18656 Aux Id: PR-7404 GH-7390\n\n- Introduce the KERNEL application parameter `standard_io_encoding` that can be\n used to set the default encoding for standard_io. This option needs to be set\n to `latin1` if the application wants to treat all input data as bytes rather\n than utf-8 encoded characters.\n\n Own Id: OTP-18657 Aux Id: GH-7230 PR-7384","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 9.0.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-9-0-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- The POSIX error `exdev` was sometimes incorrectly described as \"cross domain\n link\" in some error messages.\n\n Own Id: OTP-18578 Aux Id: GH-7213\n\n- Corrected the socket send function description (send with Timeout = nowait).\n The send function(s) could not return \\{ok, \\{RestData, SelectInfo\\}\\}\n\n Own Id: OTP-18584 Aux Id: #7238","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 9.0 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-9-0"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fixed a bug where duplicate keys were allowed in the .app file of an\n application. Duplicate keys are now rejected and the application will not\n start if they exist.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18210 Aux Id: GH-5877 PR-5878\n\n- Fix inconsistent handling in logger_formatter of the branched values in\n conditional branches. For example using `msg` in a conditional branch would\n not be formatted as it should before this fix.\n\n Own Id: OTP-18225 Aux Id: PR-6036\n\n- Fix the logger_std_h handler to log to standard_error if logging to\n standard_io fails for any reason.\n\n Own Id: OTP-18226 Aux Id: PR-6253\n\n- Fix the TLS distribution to work when starting Erlang in embedded mode and a\n connection is done before kernel is fully started.\n\n Own Id: OTP-18248 Aux Id: PR-6227 GH-6085\n\n- erl `-remsh` has been improved to provide better error reasons and work when\n using a shell without terminal support (that is an \"oldshell\").\n\n Own Id: OTP-18271 Aux Id: PR-6279\n\n- Fix logging of log events generated before kernel is started to not fail if\n the code for formatting those log messaged have not yet been loaded.\n\n Own Id: OTP-18286 Aux Id: PR-5955\n\n- `proc_lib:start*/*` has become synchronous when the started process fails.\n This requires that a failing process use a new function\n `proc_lib:init_fail/2,3`, or exits, to indicate failure. All OTP behaviours\n have been fixed to do this.\n\n All these start functions now consume the `'EXIT'` message from a process link\n for all error returns. Previously it was only the `start_link/*` functions\n that did this, and only when the started function exited, not when it used\n `init_ack/1,2` or `init_fail/2,3` to create the return value.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18471 Aux Id: GH-6339, PR-6843\n\n- Fixed a bug where `file:read(standard_io, ...)` unexpectedly returned `eof` in\n binary mode.\n\n Own Id: OTP-18486 Aux Id: PR-6881\n\n- Return type for `seq_trace:get_token/1` fixed.\n\n Own Id: OTP-18528 Aux Id: PR-7009\n\n- Looking up, connecting to and sending to a host with an empty name is now\n handled by trying to look up the address of the root domain, which fails.\n Previously some of these operations caused an internal exception, which\n contradicted type specifications.\n\n Own Id: OTP-18543 Aux Id: GH-6353\n\n- Replaced a regex with a special case handling of ANSI Select Graphic Rendition\n escape characters, to speed up io output that make use of these escape\n sequences.\n\n Own Id: OTP-18547 Aux Id: PR-7092","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- The Erlang shell has been improved to support the following features:\n\n - Auto-complete variables, record names, record field names, map keys,\n function parameter types and filenames.\n - Open external editor in the shell (with C-o) to edit the current expression\n in an editor.\n - Support defining records (with types), functions and function typespecs, and\n custom types in the shell.\n - Do not save pager commands, and input to io:getline in history.\n\n Own Id: OTP-14835 Aux Id: PR-5924\n\n- The TTY/terminal subsystem has been rewritten by moving more code to Erlang\n from the old linked-in driver and implementing all the I/O primitives needed\n in a NIF instead.\n\n On Unix platforms the user should not notice a lot of difference, besides\n better handling of unicode characters and fixing of some long standing bugs.\n\n Windows users will notice that erl.exe has the same functionality as a normal\n Unix shell and that werl.exe has been removed and replaced with a symlink to\n erl.exe. This makes the Windows Erlang terminal experience identical to that\n of Unix.\n\n The re-write brings with it a number of bug fixes and feature additions:\n\n - The TTY is now reset when Erlang exits, fixing zsh to not break when\n terminating an Erlang session.\n - `standard_error` now uses the same unicode mode as `standard_io`.\n - Hitting backspace when searching the shell history with an empty search\n string no longer breaks the shell.\n - Tab expansion now works on remote nodes started using the JCL interface.\n - It is now possible to configure the shell slogan and the session slogans\n (that is the texts that appear when you start an Erlang shell). See the\n kernel documentation for more details.\n - Added shell:start_interactive for starting the interactive shell from a\n non-interactive Erlang session (for example an escript).\n - On Windows, when starting in detached mode the standard handler are now set\n to `nul` devices instead of being unset.\n - Standard I/O now always defaults to `unicode` mode if supported. Previously\n the default was `latin1` if the runtime system had been started with\n `-oldshell` or `-noshell` (for example in an `escript`). To send raw bytes\n over standard out, one now explicitly has to specify\n `io:setopts(standard_io, [{encoding, latin1}]).`\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17932 Aux Id: PR-6144 GH-3150 GH-3390 GH-4343 GH-4225\n\n- Add support for socket on Windows.\n\n - Pre release status.\n - Error codes not finalized.\n - No explicit support for Windows specific options (socket options, flags for\n read and write).\n - New async api for Windows (completion). See the `Asynchronous calls` chapter\n in the (Socket Usage) Users Guide.\n - To ensure platform independence, gen_tcp and gen_udp is _intended_ to be\n used (not yet updated).\n\n Own Id: OTP-18029\n\n- As announced since the release of OTP 24, support for:\n\n - version 4 node container types in the external term format are now\n mandatory. That is, references supporting up to 5 32-bit integer\n identifiers, and process and port identifiers with support for 64-bit data\n storage. The distribution flag\n [`DFLAG_V4_NC`](`e:erts:erl_dist_protocol.md#DFLAG_V4_NC`) is therefor now\n also mandatory. OTP has since OTP 24 supported this. Also note that the\n external format produced by `term_to_binary()` and `term_to_iovec()` will\n unconditionally produce pids, ports, and references supporting this larger\n format.\n - the [new link protocol](`e:erts:erl_dist_protocol.md#new_link_protocol`)\n introduced in OTP 23.3 is now mandatory. The distribution flag\n [`DFLAG_UNLINK_ID`](`e:erts:erl_dist_protocol.md#DFLAG_UNLINK_ID`) is\n therefor now also mandatory.\n\n Due to the above, OTP 26 nodes will refuse to connect to OTP nodes from\n releases prior to OTP 24.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18140 Aux Id: PR-6072\n\n- Support for Kernel TLS (kTLS), has been added to the SSL application, for TLS\n distribution (`-proto_dist inet_tls`), the SSL option `{ktls, true}`. Using\n this for general SSL sockets is uncomfortable, undocumented and not\n recommended since it requires very platform dependent raw options.\n\n This, for now, only works for some not too old Linux distributions. Roughly, a\n kernel 5.2.0 or later with support for UserLand Protocols and the kernel\n module `tls` is required.\n\n Own Id: OTP-18235 Aux Id: PR-6104, PR-5840\n\n- Add code:get_doc/2 which adds support to fetch documentation skeletons of\n functions using debug_info chunks instead of eep48 doc chunks.\n\n Own Id: OTP-18261 Aux Id: PR-5924\n\n- The Erlang shell's auto-completion when typing `tab` has been changed to\n happen after the editing current line instead of before it.\n\n This behaviour can be configured using a the `shell_expand_location` STDLIB\n configuration parameter.\n\n Own Id: OTP-18278 Aux Id: PR-6260\n\n- Typing `Ctrl+L` in a shell now clears the screen and redraws the current line\n instead of only redrawing the current line. To only redraw the current line,\n you must now type `Alt+L`. This brings the behaviour of `Ctrl+L` closer to how\n bash and other shells work.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18285 Aux Id: PR-6262\n\n- gen_server optimized by caching callback functions\n\n Own Id: OTP-18305 Aux Id: PR-5831\n\n- Prepare the `pg` communication protocol for upgrade. The plan is for OTP-28\n nodes to be able to use an upgraded `pg` protocol while still being able to\n talk with OTP 26 nodes.\n\n Own Id: OTP-18327 Aux Id: PR-6433\n\n- New `disk_log` log type `rotate`, where the log files are compressed upon\n rotation.\n\n Own Id: OTP-18331 Aux Id: ERIERL-870\n\n- The following `inet:setopts/2` options have been introduced:\n\n - **[`reuseport`](`m:inet#option-reuseport`)** - Reuse of local port. Load\n balancing may or may not be provided depending on underlying OS.\n\n - **[`reuseport_lb`](`m:inet#option-reuseport_lb`)** - Reuse of local port.\n Load balancing provided.\n\n - **[`exclusiveaddruse`](`m:inet#option-exclusiveaddruse`)** - Exclusive\n address/port usage on Windows. This socket option is Windows specific and\n will silently be ignored on other systems.\n\n The behavior of setting [`reuseaddr`](`m:inet#option-reuseaddr`) on Windows\n have changed in a _backwards incompatible_ way. The underlying `SO_REUSEADDR`\n socket option is now only set if both the `reusaddr` and the `reuseport`\n `inet` options have been set. This since the underlying `SO_REUSEADDR` socket\n option on Windows behaves similar to how BSD behaves if both the underlying\n socket options `SO_REUSEADDR` and `SO_REUSEPORT` have been set. See the\n documentation of the `reuseaddr` option for more information.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18344 Aux Id: PR-6522, PR-6944, OTP-18324, PR-6481, GH-6461\n\n- Replace size/1 with either tuple_size/1 or byte_size/1\n\n The [`size/1`](`size/1`) BIF is not optimized by the JIT, and its use can\n result in worse types for Dialyzer.\n\n When one knows that the value being tested must be a tuple,\n [`tuple_size/1`](`tuple_size/1`) should always be preferred.\n\n When one knows that the value being tested must be a binary,\n [`byte_size/1`](`byte_size/1`) should be preferred. However,\n [`byte_size/1`](`byte_size/1`) also accepts a bitstring (rounding up size to a\n whole number of bytes), so one must make sure that the call to `byte_size/` is\n preceded by a call to [`is_binary/1`](`is_binary/1`) to ensure that bitstrings\n are rejected. Note that the compiler removes redundant calls to\n [`is_binary/1`](`is_binary/1`), so if one is not sure whether previous code\n had made sure that the argument is a binary, it does not harm to add an\n [`is_binary/1`](`is_binary/1`) test immediately before the call to\n [`byte_size/1`](`byte_size/1`).\n\n Own Id: OTP-18405 Aux Id:\n GH-6672,PR-6702,PR-6768,PR-6700,PR-6769,PR-6812,PR-6814\n\n- The function `file:pid2name/1` is deprecated and will be removed in\n Erlang/OTP 27.\n\n Own Id: OTP-18419\n\n- The modules Erlang DNS resolver `inet_res` and helper modules have been\n updated for RFC6891; to handle OPT RR with DNSSEC OK (DO) bit.\n\n Own Id: OTP-18442 Aux Id: PR-6786, GH-6606\n\n- Introduced `application:get_supervisor/1`.\n\n Own Id: OTP-18444 Aux Id: PR-6035\n\n- Handling of `on_load` modules during boot has been improved by adding an extra\n step in the boot order for embedded mode that runs all `on_load` handlers,\n instead of relying on explicit invocation of them, later, when the kernel\n supervision tree starts.\n\n This is mostly a code improvement and OTP internal simplification to avoid\n future bugs and to simplify code maintenance.\n\n Own Id: OTP-18447\n\n- Reduce contention on the code_server by doing the code preparation on the\n client.\n\n Own Id: OTP-18448 Aux Id: PR-6736\n\n- Added a mode to ensure_all_loaded, to start children application and their\n dependencies concurrently.\n\n Own Id: OTP-18451 Aux Id: PR-6737\n\n- Cache OTP boot code paths, to limit how many folders that are being accessed\n during a module lookup. Can be disabled with -cache_boot_path false. OTP boot\n code paths consists of ERL_LIB environment variables. The various otp/\\*/ebin\n folders. And the \\{path, ...\\} clauses in the init script.\n\n Own Id: OTP-18452 Aux Id: PR-6729\n\n- Erlang distribution code in Kernel and SSL has been refactored a bit to\n facilitate debugging and re-usability, which shouldn't have any noticeable\n effects on behaviour or performance.\n\n Own Id: OTP-18456\n\n- Add cache attribute to code path apis.\n\n Added an optional cache/nocache argument to all code:add_path*,\n code:set_path*, and code:replace_path\\* functions. These functions will then\n avoid doing file-accesses if they are cached. Cache can be cleared with\n code:clear_cache/0. Added code:del_paths/1 to make it easier to clear multiple\n paths.\n\n Own Id: OTP-18466 Aux Id: PR-6832\n\n- Deprecates `dbg:stop_clear/0` because it is simply a function alias to\n `dbg:stop/0`\n\n Own Id: OTP-18478 Aux Id: GH-6903\n\n- Improvements to code:ensure_modules_loaded/1: Previously it would prepare\n modules and then abandon references to said modules if they had on_load\n callbacks. This pull request makes it so they keep the references around and\n then serially load them without having to fetch the object code and prepare\n them again.\n\n Own Id: OTP-18484 Aux Id: PR-6844\n\n- The internal DNS resolver has been updated to handle DNS LOC RR:s (RFC 1876).\n This is an undocumented module, although still used by power users. See the\n source code.\n\n Own Id: OTP-18510 Aux Id: GH-6098, PR-6982\n\n- Reduced memory consumption in `global` when informing other nodes about lost\n connections.\n\n Own Id: OTP-18521 Aux Id: PR-7025\n\n- The `net_kernel`, `global`, and `global_group` servers now have\n [_fully asynchronous distributed signaling_](`m:erlang#process_flag_async_dist`)\n enabled all the time which prevents them from ever getting blocked on send of\n distributed signals.\n\n Documentation about blocking distributed signals has also been improved.\n\n Own Id: OTP-18533 Aux Id: PR-7061\n\n- Allow IPv6 addresses as host in `http` packets decoded by\n `erlang:decode_packet/3` and `gen_tcp` packet option. The IPv6 address should\n be enclosed within `[]` according to RFC2732.\n\n Own Id: OTP-18540 Aux Id: PR-6900\n\n- Remove deprecated functions in OTP-26\n\n Own Id: OTP-18542\n\n- Removed `code:is_module_native/1` since HiPE has been removed. It has since\n OTP 24 been deprecated and scheduled for removal in OTP 26.\n\n Removed `code:rehash/0` since the code path feature no longer is present. It\n has since OTP 19 been deprecated and has since OTP 24 been scheduled for\n removal in OTP 26.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18551 Aux Id: PR-7106\n\n- Added support for multiple line expressions and navigation in the shell. Added\n new keybindings:\n\n - navigate up (ctrl+up)/(alt+up)\n - navigate down (ctrl+down)/(alt+down)\n - insert newline in middle of line (alt+enter)\n - navigate top (alt+<)/(alt+shift+up)\n - navigate bottom (alt+>)/(alt+shift+down)\n - clear current expression (alt+c)\n - cancel search (alt+c)\n - opening editor on mac (option+o)/(alt+o)\n\n Modifies the prompt for new lines to make it clearer that the prompt has\n entered multi-line mode. Supports terminal with small window size, recommend\n not go lower than 7 rows and 40 columns. Modifies the search prompt to support\n multi-line statements. Redraw the prompt after continuing from JCL menu.\n\n Own Id: OTP-18575 Aux Id: PR-7169","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 8.5.4.3 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-8-5-4-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"* Fixed gen_udp:open/2 type spec to include already supported module socket address types.\n\n Own Id: OTP-19050 Aux Id: OTP-18990","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 8.5.4.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-8-5-4-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- gen_tcp:connect with socket address and socket (inet-) backend fails because\n of missing callback function.\n\n Own Id: OTP-18707 Aux Id: #7530","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 8.5.4.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-8-5-4-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Multiple socket:accept calls issue. When making multiple accept calls, only\n the last call is active.\n\n Own Id: OTP-18635 Aux Id: #7328\n\n- gen_udp:connect with inet_backend = socket fails when the Address is a\n hostname (string or atom).\n\n Own Id: OTP-18650","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 8.5.4 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-8-5-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fixed a bug on Windows where `file:read_file_info/1` would fail for files with\n corrupt metadata.\n\n Own Id: OTP-18348 Aux Id: GH-6356\n\n- Accept connection setup from OTP 23 and 24 nodes that are not using epmd.\n\n Own Id: OTP-18404 Aux Id: GH-6595, PR-6625","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 8.5.3 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-8-5-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- The tcp connect option 'bind_to_device' could not be used with inet_backend =\n 'socket'. 'inet' requires value type binarry() and 'socket' requires value\n type 'string()'.\n\n Own Id: OTP-18357 Aux Id: #6509\n\n- Minor issue processing options when calling gen_tcp:connect with a sockaddr()\n and inet_backend = socket.\n\n Own Id: OTP-18358 Aux Id: #6528","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 8.5.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-8-5-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fixed shutdown crash in gen_tcp socket backend, when the other end closed the\n socket.\n\n Own Id: OTP-18270 Aux Id: #6331\n\n- `erl_tar` can now read gzip-compressed tar files that are padded. There is a\n new option `compressed_one` for `file:open/2` that will read a single member\n from a gzip file,\n\n Own Id: OTP-18289 Aux Id: PR-6343\n\n- Fix `os:cmd` to not translate all exceptions thrown to `badarg`. For example\n `emfile` from `erlang:open_port` was translated to `badarg`.\n\n This bug has existed since Erlang/OTP 24.\n\n Own Id: OTP-18291 Aux Id: PR-6382\n\n- Spec for function net:if_names/0 incorrect\n\n Own Id: OTP-18296 Aux Id: OTP-16464\n\n- Missing ctrl option name transation for TOS and TTL (on FreeBSD) when using\n gen_udp with the 'socket' inet_backend.\n\n Own Id: OTP-18315\n\n- gen_udp:open/2 with option(s) add_membership or drop_membership would drop\n earlier options.\n\n Own Id: OTP-18323 Aux Id: #6476\n\n- The `inet:setopts/2` `{reuseaddr, true}` option will now be ignored on Windows\n unless the socket is an UDP socket. For more information see the documentation\n of the `reuseaddr` option part of the documentation of `inet:setopts/2`.\n\n Prior to OTP 25 the `{reuseaddr, true}` option was ignored for all sockets on\n Windows, but as of OTP 25.0 this was changed so that it was not ignored for\n any sockets.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18324 Aux Id: GH-6461, PR-6481","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- The distribution socket option handling in `inet_tcp_dist` has been cleaned up\n to clarify which were mandatory and which just had default values.\n\n Own Id: OTP-18293\n\n- Improve warning message format for gen_tcp_socket.\n\n Own Id: OTP-18317","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 8.5.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-8-5-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Listen sockets created with the socket module, leaked (erlang-) monitors.\n\n Own Id: OTP-18240 Aux Id: #6285\n\n- `m:peer` nodes failed to halt when the process supervising the control\n connection crashed. When an alternative control connection was used, this\n supervision process also quite frequently crashed when the `peer` node was\n stopped by the node that started it which caused the `peer` node to linger\n without ever halting.\n\n Own Id: OTP-18249 Aux Id: PR-6301","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 8.5 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-8-5"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fixed inconsistency bugs in `m:global` due to `nodeup`/`nodedown` messages not\n being delivered before/after traffic over connections. Also fixed various\n other inconsistency bugs and deadlocks in both `m:global_group` and `global`.\n\n As building blocks for these fixes, a new BIF `erlang:nodes/2` has been\n introduced and `net_kernel:monitor_nodes/2` has been extended.\n\n The [`-hidden`](`e:erts:erl_cmd.md#hidden`) and\n [`-connect_all`](`e:erts:erl_cmd.md#connect_all`) command line arguments did\n not work if multiple instances were present on the command line which has been\n fixed. The new kernel parameter [`connect_all`](kernel_app.md#connect_all) has\n also been introduced in order to replace the `-connect_all` command line\n argument.\n\n Own Id: OTP-17934 Aux Id: PR-6007\n\n- Fixed IPv6 multicast_if and membership socket options.\n\n Own Id: OTP-18091 Aux Id: #5789\n\n- Fixed issue with inet:getifaddrs hanging on pure IPv6 Windows\n\n Own Id: OTP-18102 Aux Id: #5904\n\n- The type specifications for `inet:getopts/2` and `inet:setopts/2` have been\n corrected regarding SCTP options.\n\n Own Id: OTP-18115 Aux Id: PR-5939\n\n- The type specifications for `inet:parse_*` have been tightened.\n\n Own Id: OTP-18121 Aux Id: PR-5972\n\n- Fix gen_tcp:connect/3 spec to include the inet_backend option.\n\n Own Id: OTP-18171 Aux Id: PR-6131\n\n- Fix bug where using a binary as the format when calling\n `logger:log(Level, Format, Args)` (or any other logging function) would cause\n a crash or incorrect logging.\n\n Own Id: OTP-18229 Aux Id: PR-6212","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Add rudimentary debug feature (option) for the inet-driver based sockets, such\n as gen_tcp and gen_udp.\n\n Own Id: OTP-18032\n\n- Introduced the `hidden` and `dist_listen` options to `net_kernel:start/2`.\n\n Also documented the [`-dist_listen`](`e:erts:erl_cmd.md#dist_listen`) command\n line argument which was erroneously documented as a `kernel` parameter and not\n as a command line argument.\n\n Own Id: OTP-18107 Aux Id: PR-6009\n\n- Scope and group monitoring have been introduced in `m:pg`. For more\n information see the documentation of\n [`pg:monitor_scope()`](`pg:monitor_scope/0`),\n [`pg:monitor()`](`pg:monitor/1`), and [`pg:demonitor()`](`pg:demonitor/1`).\n\n Own Id: OTP-18163 Aux Id: PR-6058, PR-6275\n\n- A new function `global:disconnect/0` has been introduced with which one can\n cleanly disconnect a node from all other nodes in a cluster of `global` nodes.\n\n Own Id: OTP-18232 Aux Id: OTP-17843, PR-6264","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 8.4.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-8-4-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- A call to [`net_kernel:setopts(new, Opts)`](`net_kernel:setopts/2`) at the\n same time as a connection was being set up could cause a deadlock between the\n `net_kernel` process and the process setting up the connection.\n\n Own Id: OTP-18198 Aux Id: GH-6129, PR-6216","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 8.4.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-8-4-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- The DNS resolver `inet_res` has been fixed to ignore trailing dot difference\n in the request domain between the sent request and the received response, when\n validating a response.\n\n Own Id: OTP-18112 Aux Id: ERIERL-811\n\n- A bug in `inet_res` has been fixed where a missing internal `{ok,_}` wrapper\n caused `inet_res:resolve/*` to return a calculated host name instead of an\n `{ok,Msg}` tuple, when resolving an IP address or a host name that is an IP\n address string.\n\n Own Id: OTP-18122 Aux Id: GH-6015, PR-6020\n\n- The `erlang:is_alive()` BIF could return `true` before configured distribution\n service was available. This bug was introduced in OTP 25.0 ERTS version 13.0.\n\n The `erlang:monitor_node()` and `erlang:monitor()` BIFs could erroneously fail\n even though configured distribution service was available. This occurred if\n these BIFs were called after the distribution had been started using dynamic\n node name assignment but before the name had been assigned.\n\n Own Id: OTP-18124 Aux Id: OTP-17558, PR-6032\n\n- Added the missing mandatory `address/0` callback in the `gen_tcp_dist`\n example.\n\n Own Id: OTP-18136","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 8.4 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-8-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- The DNS resolver implementation has been rewritten to validate replies more\n thoroughly, and a bit optimized to create less garbage.\n\n Own Id: OTP-17323\n\n- The socket option 'reuseaddr' is _no longer_ ignored on Windows.\n\n Own Id: OTP-17447 Aux Id: GH-4819\n\n- Fix bug where using the atoms `string` or `report` as the format when calling\n `logger:log(Level, Format, Args)` (or any other logging function) would cause\n a crash or incorrect logging.\n\n Own Id: OTP-17551 Aux Id: GH-5071 PR-5075\n\n- As of OTP 25, `global` will by default prevent overlapping partitions due to\n network issues by actively disconnecting from nodes that reports that they\n have lost connections to other nodes. This will cause fully connected\n partitions to form instead of leaving the network in a state with overlapping\n partitions.\n\n Prevention of overlapping partitions can be disabled using the\n [`prevent_overlapping_partitions`](kernel_app.md#prevent_overlapping_partitions)\n `kernel(6)` parameter, making `global` behave like it used to do. This is,\n however, problematic for all applications expecting a fully connected network\n to be provided, such as for example `mnesia`, but also for `global` itself. A\n network of overlapping partitions might cause the internal state of `global`\n to become inconsistent. Such an inconsistency can remain even after such\n partitions have been brought together to form a fully connected network again.\n The effect on other applications that expects that a fully connected network\n is maintained may vary, but they might misbehave in very subtle hard to detect\n ways during such a partitioning. Since you might get hard to detect issues\n without this fix, you are _strongly_ advised _not_ to disable this fix. Also\n note that this fix _has_ to be enabled on _all_ nodes in the network in order\n to work properly.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17911 Aux Id: PR-5687, PR-5611, OTP-17843\n\n- Starting the helper program for name resolving; `inet_gethost`, has been\n improved to use an absolute file system path to ensure that the right program\n is started.\n\n If the helper program can not be started - the system now halts, to avoid\n running with a silently broken name resolver.\n\n Own Id: OTP-17958 Aux Id: OTP-17978\n\n- The type specification for `inet_res:getbyname/2,3` has been corrected to\n reflect that it can return peculiar `#hostent{}` records.\n\n Own Id: OTP-17986 Aux Id: PR-5412, PR-5803\n\n- `code:module_status/1` would always report BEAM files loaded from an archive\n as `modified`, and `code:modified_modules/0` would always return the name of\n all modules loaded from archives.\n\n Own Id: OTP-17990 Aux Id: GH-5801\n\n- In logger fix file handler shutdown delay by using erlang timers instead of\n the timer module's timers.\n\n Own Id: OTP-18001 Aux Id: GH-5780 PR-5829\n\n- Fix the meta data in log events generated by logger on failure to not contain\n the original log event's meta data.\n\n Own Id: OTP-18003 Aux Id: PR-5771\n\n- Fix logger file backend to re-create the log folder if it has been deleted.\n\n Own Id: OTP-18015 Aux Id: GH-5828 PR-5845\n\n- \\[socket] Encode of sockaddr has been improved.\n\n Own Id: OTP-18020\n\n- Fix `put_chars` requests to the io server with incomplete unicode data to exit\n with `no_translation` error.\n\n Own Id: OTP-18070 Aux Id: PR-5885","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- The net module now works on Windows.\n\n Own Id: OTP-16464\n\n- An Erlang installation directory is now relocatable on the file system given\n that the paths in the installation's `RELEASES` file are paths that are\n relative to the installations root directory. The\n `` `release_handler:create_RELEASES/4 `` function can generate a `RELEASES`\n file with relative paths if its `RootDir` parameter is set to the empty\n string.\n\n Own Id: OTP-17304\n\n- The following distribution flags are now mandatory: `DFLAG_BIT_BINARIES`,\n `DFLAG_EXPORT_PTR_TAG`, `DFLAG_MAP_TAGS`, `DFLAG_NEW_FLOATS`, and\n `DFLAG_FUN_TAGS`. This mainly concerns libraries or application that implement\n the distribution protocol themselves.\n\n Own Id: OTP-17318 Aux Id: PR-4972\n\n- Fix `os:cmd` to work on Android OS.\n\n Own Id: OTP-17479 Aux Id: PR-4917\n\n- The configuration files [`.erlang`](`e:erts:erl_cmd.md`),\n [`.erlang.cookie`](`e:system:distributed.md`) and\n [`.erlang.crypt`](`m:beam_lib#module-erlang-crypt`) can now be located in the XDG\n Config Home directory.\n\n See the documentation for each file and `filename:basedir/2` for more details.\n\n Own Id: OTP-17554 Aux Id: GH-5016 PR-5408 OTP-17821\n\n- Dynamic node name improvements: `erlang:is_alive/0` changed to return true for\n pending dynamic node name and new function `net_kernel:get_state/0`.\n\n Own Id: OTP-17558 Aux Id: OTP-17538, PR-5111, GH-5402\n\n- The types for callback result types in `gen_statem` has bee augmented with\n arity 2 types where it is possible for a callback module to specify the type\n of the callback data, so the callback module can get type validation of it.\n\n Own Id: OTP-17589 Aux Id: PR-4926\n\n- The tagged tuple tests and fun-calls have been optimized and are now a little\n bit cheaper than previously.\n\n These optimizations become possible after making sure that all boxed terms\n have at least one word allocated after the arity word. This has been\n accomplished by letting all empty tuples refer to the same empty tuple literal\n which also reduces memory usage for empty tuples.\n\n Own Id: OTP-17608\n\n- A [`net_ticker_spawn_options`](kernel_app.md#net_ticker_spawn_options)\n `kernel` configuration parameter with which one can set spawn options for the\n distribution channel ticker processes has been introduced.\n\n Own Id: OTP-17617 Aux Id: PR-5069\n\n- The most, or at least the most used, `m:rpc` operations now require `m:erpc`\n support in order to communicate with other Erlang nodes. `erpc` was introduced\n in OTP 23. That is, `rpc` operations against Erlang nodes of releases prior to\n OTP 23 will fail.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17681 Aux Id: PR-5307\n\n- The new module `peer` supersedes the `slave` module. The `slave` module is now\n deprecated and will be removed in OTP 27.\n\n `peer` contains an extended and more robust API for starting erlang nodes.\n\n Own Id: OTP-17720 Aux Id: PR-5162\n\n- In order to make it easier for the user to manage multiple outstanding\n asynchronous `call` requests, new functionality utilizing request identifier\n collections have been introduced in\n [`erpc`](`t:erpc:request_id_collection/0`),\n [`gen_server`](`t:gen_server:request_id_collection/0`),\n [`gen_statem`](`t:gen_statem:request_id_collection/0`), and\n [`gen_event`](`t:gen_event:request_id_collection/0`).\n\n Own Id: OTP-17784 Aux Id: PR-5792\n\n- Type specifications have been added to the `gen_server`, and the documentation\n has been updated to utilize this.\n\n This surfaced a few type violations that has been corrected in `global`,\n `logger_olp` and `rpc`.\n\n Own Id: OTP-17915 Aux Id: PR-5751, GH-2375, GH-2690\n\n- IP address validation functions `is_ipv4_address/1`, `is_ipv6_address/1` and\n `is_ip_address/1` have been added to the module `inet` in Kernel.\n\n Own Id: OTP-17923 Aux Id: PR-5646\n\n- An API for multihomed SCTP connect has been added in the guise of\n `gen_sctp:connectx_init/*`\n\n Own Id: OTP-17951 Aux Id: PR-5656\n\n- \\[socket] Add encoding of the field hatype of the type sockaddr_ll (family\n 'packet').\n\n Own Id: OTP-17968 Aux Id: OTP-16464\n\n- Added support for configurable features as described in EEP-60. Features can\n be enabled/disabled during compilation with options\n (`-enable-feature Feature`, `-disable-feature Feature` and\n `+{feature, Feature, enable|disable}`) to `erlc` as well as with directives\n (`-feature(Feature, enable|disable).`) in the file. Similar options can be\n used to `erl` for enabling/disabling features allowed at runtime. The new\n `maybe` expression (EEP-49) is fully supported as the feature `maybe_expr`.\n The features support is documented in the reference manual.\n\n Own Id: OTP-17988","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 8.3.2.4 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-8-3-2-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- gen_tcp:connect with socket address and socket (inet-) backend fails because\n of missing callback function.\n\n Own Id: OTP-18707 Aux Id: #7530","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 8.3.2.3 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-8-3-2-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Spec for function net:if_names/0 incorrect\n\n Own Id: OTP-18296 Aux Id: OTP-16464\n\n- Missing ctrl option name transation for TOS and TTL (on FreeBSD) when using\n gen_udp with the 'socket' inet_backend.\n\n Own Id: OTP-18315\n\n- The tcp connect option 'bind_to_device' could not be used with inet_backend =\n 'socket'. 'inet' requires value type binarry() and 'socket' requires value\n type 'string()'.\n\n Own Id: OTP-18357 Aux Id: #6509\n\n- Minor issue processing options when calling gen_tcp:connect with a sockaddr()\n and inet_backend = socket.\n\n Own Id: OTP-18358 Aux Id: #6528","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Improve warning message format for gen_tcp_socket.\n\n Own Id: OTP-18317","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 8.3.2.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-8-3-2-2"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- A new function `global:disconnect/0` has been introduced with which one can\n cleanly disconnect a node from all other nodes in a cluster of `global` nodes.\n\n Own Id: OTP-18232 Aux Id: OTP-17843, PR-6264","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 8.3.2.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-8-3-2-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- A call to [`net_kernel:setopts(new, Opts)`](`net_kernel:setopts/2`) at the\n same time as a connection was being set up could cause a deadlock between the\n `net_kernel` process and the process setting up the connection.\n\n Own Id: OTP-18198 Aux Id: GH-6129, PR-6216","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 8.3.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-8-3-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- inet:getopts/2 for the 'raw' option for a socket created with inet-backend\n 'socket' failed.\n\n Own Id: OTP-18078 Aux Id: GH-5930\n\n- Corrected the behaviour of the shutdown function when using with the\n inet_backend = socket. It was not sufficiently compatible with the \"old\"\n gen_tcp.\n\n Own Id: OTP-18080 Aux Id: GH-5930","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 8.3.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-8-3-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fix failed accepted connection setup after previous established connection\n from same node closed down silently.\n\n Own Id: OTP-17979 Aux Id: ERIERL-780\n\n- Fixed a problem where typing Ctrl-R in the shell could hang if there were some\n problem with the history log file.\n\n Own Id: OTP-17981 Aux Id: PR-5791","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 8.3 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-8-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Handling of `send_timeout` for `gen_tcp` has been corrected so that the\n timeout is honored also when sending 0 bytes.\n\n Own Id: OTP-17840\n\n- By default `global` does _not_ take any actions to restore a fully connected\n network when connections are lost due to network issues. This is problematic\n for all applications expecting a fully connected network to be provided, such\n as for example `mnesia`, but also for `global` itself. A network of\n overlapping partitions might cause the internal state of `global` to become\n inconsistent. Such an inconsistency can remain even after such partitions have\n been brought together to form a fully connected network again. The effect on\n other applications that expects that a fully connected network is maintained\n may vary, but they might misbehave in very subtle hard to detect ways during\n such a partitioning.\n\n In order to prevent such issues, we have introduced a _prevent overlapping\n partitions_ fix which can be enabled using the\n [`prevent_overlapping_partitions`](kernel_app.md#prevent_overlapping_partitions)\n `kernel(6)` parameter. When this fix has been enabled, `global` will actively\n disconnect from nodes that reports that they have lost connections to other\n nodes. This will cause fully connected partitions to form instead of leaving\n the network in a state with overlapping partitions. Note that this fix _has_\n to be enabled on _all_ nodes in the network in order to work properly. Since\n this quite substantially changes the behavior, this fix is currently disabled\n by default. Since you might get hard to detect issues without this fix you\n are, however, _strongly_ advised to enable this fix in order to avoid issues\n such as the ones described above. As of OTP 25 this fix will become enabled by\n default.\n\n Own Id: OTP-17843 Aux Id: ERIERL-732, PR-5611\n\n- Fix bug where `logger` would crash when logging a report including improper\n lists.\n\n Own Id: OTP-17851\n\n- Make `erlang:set_cookie` work for dynamic node names.\n\n Own Id: OTP-17902 Aux Id: GH-5402, PR-5670","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Add support for using socket:sockaddr_in() and socket:sockaddr_in6() when\n using gen_sctp, gen_tcp and gen_udp. This will make it possible to use Link\n Local IPv6 addresses.\n\n Own Id: OTP-17455 Aux Id: GH-4852\n\n- A [`net_tickintensity`](kernel_app.md#net_tickintensity) `kernel` parameter\n has been introduced. It can be used to control the amount of ticks during a\n [`net_ticktime`](kernel_app.md#net_ticktime) period.\n\n A new `net_kernel:start/2` function has also been introduced in order to make\n it easier to add new options. The use of `net_kernel:start/1` has been\n deprecated.\n\n Own Id: OTP-17905 Aux Id: ERIERL-732, PR-5740\n\n- Improve documentation for the dynamic node name feature.\n\n Own Id: OTP-17918","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 8.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-8-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- socket:which_sockets( pid() ) uses wrong keyword when looking up socket owner\n ('ctrl' instead of 'owner').\n\n Own Id: OTP-17716\n\n- In epmd_ntop, the #if defined(EPMD6) conditional was inverted and it was only\n including the IPv6-specific code when EPMD6 was undefined. This was causing\n IPv6 addrs to be interpreted as IPv4 addrs and generating nonsense IPv4\n addresses as output.\n\n Several places were incorrectly using 'num_sockets' instead of 'i' to index\n into the iserv_addr array during error logging. This would result in a read\n into uninitialized data in the iserv_addr array.\n\n Thanks to John Eckersberg for providing this fix.\n\n Own Id: OTP-17730\n\n- Minor fix of the `erl_uds_dist` distribution module example.\n\n Own Id: OTP-17765 Aux Id: PR-5289\n\n- A bug has been fixed for the legacy TCP socket adaption module\n `gen_tcp_socket` where it did bind to a socket address when given a file\n descriptor, but should not.\n\n Own Id: OTP-17793 Aux Id: PR-5348, OTP-17451, PR-4787, GH-4680, PR-2989,\n OTP-17216\n\n- Improve the error printout when [`open_port/2`](`open_port/2`) fails because\n of invalid arguments.\n\n Own Id: OTP-17805 Aux Id: PR-5406\n\n- Calling socket:monitor/1 on an already closed socket should succeed and result\n in an immediate DOWN message. This has now been fixed.\n\n Own Id: OTP-17806\n\n- Fix the configuration option `logger_metadata` to work.\n\n Own Id: OTP-17807 Aux Id: PR-5418\n\n- Fix tls and non-tls distribution to use erl_epmd:address_please to figure out\n if IPv4 or IPv6 addresses should be used when connecting to the remote node.\n\n Before this fix, a dns lookup of the remote node hostname determined which IP\n version was to be used which meant that the hostname had to resolve to a valid\n ip address.\n\n Own Id: OTP-17809 Aux Id: PR-5337 GH-5334","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Add `logger:reconfigure/0`.\n\n Own Id: OTP-17375 Aux Id: PR-4663 PR-5186\n\n- Add socket function ioctl/2,3,4 for socket device control.\n\n Own Id: OTP-17528\n\n- Add simple support for socknames/1 for gen_tcp_socket and gen_udp_socket.\n\n Own Id: OTP-17531\n\n- The types for callback result types in `gen_statem` has bee augmented with\n arity 2 types where it is possible for a callback module to specify the type\n of the callback data, so the callback module can get type validation of it.\n\n Own Id: OTP-17738 Aux Id: PR-4926, OTP-17589","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 8.1.3 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-8-1-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- The internal, undocumented, but used, module `inet_dns` has been fixed to\n handle mDNS high bit usage of the Class field.\n\n Code that uses the previously obsolete, undocumented and unused record field\n `#dns_rr.func` will need to be updated since that field is now used as a\n boolean flag for the mDNS high Class bit. Code that uses the also undocumented\n record `#dns_query` will need to be recompiled since a boolean field\n `#dns_query.unicast_response` has been added for the mDNS high Class bit.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17734 Aux Id: GH-5327, OTP-17659\n\n- The fix for Linux's behaviour when reconnecting an UDP socket in PR-5120\n released in OTP-24.1.2 has been refined to only dissolve the socket's\n connection before a connect if the socket is already connected, that is: only\n for a reconnect.\n\n This allows code to open a socket with an ephemeral port, get the port number\n and connect; without the port number changing (on Linux). This turned out to\n have at least one valid use case (besides test cases).\n\n Should one reconnect the socket then the port number may change, on Linux; it\n is a known quirk, which can be worked around by binding to a specific port\n number when opening the socket. If you can do without an ephemeral port, that\n is...\n\n Own Id: OTP-17736 Aux Id: GH-5279, PR-5120, OTP-17559","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 8.1.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-8-1-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- The undocumented DNS encode/decode module `inet_dns` has been cleaned up to\n handle the difference between \"symbolic\" and \"raw\" records in a more\n consistent manner.\n\n PR-5145/OTP-17584 introduced a change that contributed to an already existing\n confusion, which this correction should remedy.\n\n Own Id: OTP-17659 Aux Id: ERIERL-702","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 8.1.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-8-1-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Add more info about the socket 'type' ('socket' or 'port') for the DOWN\n message when monitoring sockets.\n\n Own Id: OTP-17640","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 8.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-8-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- The extended error information has been corrected and improved for the\n following BIFs: [`binary_to_existing_atom/2`](`binary_to_existing_atom/2`),\n [`list_to_existing_atom/1`](`list_to_existing_atom/1`),\n `erlang:send_after/{3,4}`, and `erlang:start_timer/{3,4}`.\n\n Own Id: OTP-17449 Aux Id: GH-4900\n\n- Fixed rare bug that could cause net_kernel process to hang for ever. Have seen\n to happen with massive number of TLS connections while remote nodes are\n restarting. Bug exists since OTP-22.0.\n\n Own Id: OTP-17476 Aux Id: GH-4931, PR-4934\n\n- Improve handling of closed sockets for inet:info/1.\n\n Own Id: OTP-17492\n\n- This change fixes a performance problem introduced in pull-request #2675.\n Pull-request #2675 made so the system tried to start children of already\n started applications which is unnecessary. This change fixes this performance\n problem.\n\n Own Id: OTP-17519\n\n- Fix code:get_doc/1 to not crash when module is located in an escript.\n\n Own Id: OTP-17570 Aux Id: PR-5139 GH-4256 ERL-1261\n\n- Parsing of the result value in the native DNS resolver has been made more\n defensive against incorrect results.\n\n Own Id: OTP-17578 Aux Id: ERIERL-683\n\n- A bug in the option handling for the legacy socket adaptor, that is; when\n using `inet_backend = socket`, has been fixed. Now socket options are set\n before the bind() call so options regarding, for example address reuse have\n the desired effect.\n\n Own Id: OTP-17580 Aux Id: GH-5122\n\n- `inet:ntoa/1` has been fixed to not accept invalid numerical addresses.\n\n Own Id: OTP-17583 Aux Id: GH-5136\n\n- Parsing of DNS records has been improved for records of known types to not\n accept and present malformed ones in raw format.\n\n Own Id: OTP-17584 Aux Id: PR-5145\n\n- The `ip_mreq()` type for the `{ip,add_membership}` and `{ip,drop_membership}`\n socket options has been corrected to have an `interface` field instead of,\n incorrectly, an `address` field.\n\n Own Id: OTP-17590 Aux Id: PR-5170","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Add simple utility function to display existing sockets i the erlang shell\n (socket:i/0).\n\n Own Id: OTP-17376 Aux Id: OTP-17157\n\n- gen_udp can now be configured to use the socket inet-backend (in the same way\n as gen_tcp).\n\n Own Id: OTP-17410\n\n- Functions `erlang:set_cookie(Cookie)` and `erlang:get_cookie(Node)` have been\n added for completeness and to facilitate configuring distributed nodes with\n different cookies.\n\n The documentation regarding distribution cookies has been improved to be less\n vague.\n\n Own Id: OTP-17538 Aux Id: GH-5063, PR-5111\n\n- A workaround has been implemented for Linux's quirky behaviour to not adjust\n the source IP address when connecting a connected (reconnecing) UDP socket.\n\n The workaround is to, on Linux, always dissolve any connection before\n connecting an UDP socket.\n\n Own Id: OTP-17559 Aux Id: GH-5092, PR-5120\n\n- Documented our recommendation against opening NFS-mounted files, FIFOs,\n devices, and similar using `file:open/2`.\n\n Own Id: OTP-17576 Aux Id: ERIERL-685","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 8.0.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-8-0-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- For `gen_tcp:connect/3,4` it is possible to specify a specific source port,\n which should be enough to bind the socket to an address with that port before\n connecting.\n\n Unfortunately that feature was lost in OTP-17216 that made it mandatory to\n specify the source address to get an address binding, and ignored a specified\n source port if no source address was specified.\n\n That bug has now been corrected.\n\n Own Id: OTP-17536 Aux Id: OTP-17216, ERIERL-677","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 8.0.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-8-0-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fix a race condition in Global.\n\n Own Id: OTP-16033 Aux Id: ERIERL-329, ERL-1414, GH-4448, ERL-885, GH-3923\n\n- After a node restart with `init:restart/0,1`, the module `socket` was not\n usable because supporting tables had been cleared and not re-initialized. This\n has now been fixed.\n\n Handling of the \".\" domain as a search domain was incorrect and caused a crash\n in the DNS resolver `inet_res`, which has now been fixed.\n\n Own Id: OTP-17439 Aux Id: GH-4827, PR-4888, GH-4838\n\n- Handling of combinations of the `fd` option and binding to an address has been\n corrected, especially for the `local` address family.\n\n Own Id: OTP-17451 Aux Id: OTP-17374\n\n- Bug fixes and code cleanup for the new `socket` implementation, such as:\n\n Assertions on the result of demonitoring has been added in the NIF code, where\n appropriate.\n\n Internal state handling for socket close in the NIF code has been reviewed.\n\n Looping over `close()` for `EINTR` in the NIF code has been removed, since it\n is strongly discouraged on Linux and Posix is not clear about if it is\n allowed.\n\n The `inet_backend` temporary socket option for legacy `gen_tcp` sockets has\n been documented.\n\n The return value from `net:getaddrinfo/2` has been corrected: the `protocol`\n field is now an `t:atom/0`, instead of, incorrectly,\n [`list(atom())`](`t:list/1`). The documentation has also been corrected about\n this return type.\n\n Deferred close of a `socket:sendfile/*` file was broken and has been\n corrected.\n\n Some debug code, not enabled by default, in the socket NIF has been corrected\n to not accidentally core dump for debug printouts of more or less innocent\n events.\n\n Own Id: OTP-17452","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 8.0 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-8-0"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- A bug has been fixed for the internal `inet_res` resolver cache that handled a\n resolver configuration file status timer incorrectly and caused performance\n problems due to many unnecessary file system accesses.\n\n Own Id: OTP-14700 Aux Id: PR-2848\n\n- Change the value of the tag `head` returned by `disk_log:info/1` from\n `{ok, Head}` to just `Head`.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-16809 Aux Id: ERL-1313\n\n- Two options have been added to `erl_call`. The `-fetch_stdout` option fetches\n stdout data resulting from the code invoked by `erl_call`. The `-fetch_stdout`\n option disables printing of the result term. In order to implement the first\n of these two options a new function called `ei_xrpc_from` has been added to\n erl_interface. For details see the `erl_call` documentation and\n `erl_interface` documentation.\n\n Own Id: OTP-17132\n\n- Missing runtime dependencies has been added to this application.\n\n Own Id: OTP-17243 Aux Id: PR-4557\n\n- `inet:get_rc/0` has been corrected to return host entries as separate entries\n instead of (incorrectly) in a list within the list. This bug was introduced by\n OTP-16487 in OTP-23.0-rc1.\n\n Own Id: OTP-17262 Aux Id: GH-4588, PR-4604, OTP-16487\n\n- The type gen_tcp:option_name() had a duplicate pktoptions value.\n\n Own Id: OTP-17277\n\n- Fixed removal of empty groups from internal state in `pg`.\n\n Own Id: OTP-17286 Aux Id: PR-4619\n\n- `erl -remsh` now prints an error message when it fails to connect to the\n remote node.\n\n Own Id: OTP-17287 Aux Id: PR-4581\n\n- Fix bugs related to corrupt shell history files.\n\n Error messages printed by shell history are now logged as logger error reports\n instead of written to standard error.\n\n Own Id: OTP-17288 Aux Id: PR-4581\n\n- A logger warning is now issues when too many arguments are given to `-name` or\n `-sname`. Example: `erl -name a b`.\n\n Own Id: OTP-17315 Aux Id: GH-4626\n\n- The cache used by `inet_res` now, again, can handle multiple IP addresses per\n domain name, and thus fixes a bug introduced in PR-3041 (OTP-13126) and\n PR-2891 (OTP-14485).\n\n Own Id: OTP-17344 Aux Id: PR-4633, GH-4631, OTP-14485, OTP-12136\n\n- Sockets created with socket:accept not counted (socket:info/0).\n\n Own Id: OTP-17372\n\n- The `{fd, Fd}` option to `gen_tcp:listen/2` did not work for `inet_backend`\n `socket`, which has been fixed.\n\n Own Id: OTP-17374 Aux Id: PR-4787, GH-4680, PR-2989, OTP-17216","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- The cache used by the DNS resolver `inet_res` has been improved to use ETS\n lookups instead of server calls. This is a considerable speed improvement for\n cache hits.\n\n Own Id: OTP-13126 Aux Id: PR-3041\n\n- The cache ETS table type for the internal DNS resolver `inet_res` has changed\n type (internally) to get better speed and atomicity.\n\n Own Id: OTP-14485 Aux Id: PR-2891\n\n- The experimental `socket` module can now use any protocol (by name) the OS\n supports. Suggested in PR-2641, implemented in PR-2670.\n\n Own Id: OTP-14601 Aux Id: PR-2641, PR-2670, OTP-16749\n\n- The DNS resolver `inet_res` has been updated to support CAA (RFC 6844) and URI\n (RFC 7553) records.\n\n Own Id: OTP-16517 Aux Id: PR-2827\n\n- A compatibility adaptor for `gen_tcp` to use the new `socket` API has been\n implemented (`gen_tcp_socket`). Used when setting the kernel application\n variable `inet_backend = socket`.\n\n Own Id: OTP-16611 Aux Id: OTP-16749\n\n- Extended error information for failing BIF calls as proposed in\n [EEP 54](https://github.com/erlang/eep/blob/master/eeps/eep-0054.md) has been\n implemented.\n\n When a BIF call from the Erlang shell fails, more information about which\n argument or arguments that were in error will be printed. The same extended\n error information will by `proc_lib`, `common_test`, and `qlc` when BIF calls\n fail.\n\n For applications that wish to provide the same extended error information,\n there are new functions `erl_error:format_exception/3` and\n `erl_error:format_exception/4`.\n\n There is a new [`error/3`](`error/3`) BIF that allows applications or\n libraries to provide extended error information in the same way for their own\n exceptions.\n\n Own Id: OTP-16686\n\n- The file server can now be bypassed in `file:delete/1,2` with the `raw`\n option.\n\n Own Id: OTP-16698 Aux Id: PR-2634\n\n- An example implementation of Erlang distribution over UDS using distribution\n processes has been introduced.\n\n Thanks to Jérôme de Bretagne\n\n Own Id: OTP-16703 Aux Id: PR-2620\n\n- The [_process alias_](`e:system:ref_man_processes.md#process-aliases`) feature\n as outlined by\n [EEP 53](https://github.com/erlang/eep/blob/master/eeps/eep-0053.md) has been\n introduced. It is introduced in order to provide a lightweight mechanism that\n can prevent late replies after timeout or connection loss. For more\n information, see EEP 53 and the documentation of the new\n [`alias/1`](`erlang:alias/1`) BIF and the new options to the\n [`monitor/3`](`erlang:monitor/3`) BIF.\n\n The `call` operation in the framework used by `gen_server`, `gen_statem`, and\n `gen_event` has been updated to utilize alias in order to prevent late\n responses. The `gen_statem` behavior still use a proxy process in the\n distributed case, since it has always prevented late replies and aliases won't\n work against pre OTP 24 nodes. The proxy process can be removed in OTP 26.\n\n The alias feature also made it possible to introduce new functions similar to\n the [`erpc:receive_response()`](`erpc:receive_response/2`) function in the gen\n behaviors, so the new functions\n [`gen_server:receive_response()`](`gen_server:receive_response/2`),\n [`gen_statem:receive_response()`](`gen_statem:receive_response/2`),\n [`gen_event:receive_response()`](`gen_event:receive_response/2`) have also\n been introduced.\n\n Own Id: OTP-16718 Aux Id: PR-2735\n\n- The experimental new socket API has been further developed. Some backwards\n incompatible changes with respect to OTP 23 have been made.\n\n The control message format has been changed so a decoded value is now in the\n 'value' field instead of in the 'data' field. The 'data' field now always\n contains binary data.\n\n Some type names have been changed regarding message headers and control\n message headers.\n\n `socket:bind/2` now returns plain `ok` instead of `{ok, Port}` which was only\n relevant for the `inet` and `inet6` address families and often not\n interesting. To find out which port was chosen use `socket:sockname/1`.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-16749 Aux Id: OTP-14601\n\n- New function `os:env/0` returns all OS environment variables as a list of\n 2-tuples.\n\n Own Id: OTP-16793 Aux Id: ERL-1332, PR-2740\n\n- Remove the support for distributed disk logs. The new function\n `disk_log:all/0` is to be used instead of `disk_log:accessible_logs/0`. The\n function `disk_log:close/1` is to be used instead of `disk_log:lclose/1,2`.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-16811\n\n- Expand the spec for `erl_epmd:listen_port_please/2` to mirror\n `erl_epmd:port_please/2`.\n\n Own Id: OTP-16947 Aux Id: PR-2781\n\n- A new erl parameter for specifying a file descriptor with configuration data\n has been added. This makes it possible to pass the parameter \"-configfd FD\"\n when executing the erl command. When this option is given, the system will try\n to read and parse configuration parameters from the file descriptor.\n\n Own Id: OTP-16952\n\n- The experimental HiPE application has been removed, together with all related\n functionality in other applications.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-16963\n\n- The `pg2` module has been removed.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-16968\n\n- Accept references up to a size of 160-bits from remote nodes. This is the\n first step in an upgrade path toward using references up to 160-bits in a\n future OTP release.\n\n Own Id: OTP-17005 Aux Id: OTP-16718\n\n- Allow utf-8 binaries as parts of logger_formatter template.\n\n Own Id: OTP-17015\n\n- Let `disk_log:open/1` change the size if a wrap log is opened for the first\n time, that is, the disk log process does not exist, and the value of option\n `size` does not match the current size of the disk log.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17062 Aux Id: ERL-1418, GH-4469, ERIERL-537\n\n- Allow the shell history of an erlang node to be fetched and stores using a\n custom callback module. See `shell_history` configuration parameter in the\n [kernel documentation](kernel_app.md) for more details.\n\n Own Id: OTP-17103 Aux Id: PR-2949\n\n- The simple logger (used to log events that happen before kernel has been\n started) has been improved to print prettier error messages.\n\n Own Id: OTP-17106 Aux Id: PR-2885\n\n- `socket:sendfile/2,3,4,5` has been implemented, for platforms that support the\n underlying socket library call.\n\n Own Id: OTP-17154 Aux Id: OTP-16749\n\n- Add socket monitor(s) for all types sockets.\n\n Own Id: OTP-17155\n\n- Fix various issues with the gen_tcp_socket. Including documenting some\n incompatibilities.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17156\n\n- inet:i/0 now also shows existing gen_tcp compatibility sockets (based on\n 'socket').\n\n Own Id: OTP-17157\n\n- Added support in logger for setting primary metadata. The primary metadata is\n passed as a base metadata to all log events in the system. See\n [Metadata](logger_chapter.md#metadata) in the Logger chapter of the Kernel\n User's Guide for more details.\n\n Own Id: OTP-17181 Aux Id: PR-2457\n\n- Recognize new key 'optional_applications' in application resource files.\n\n Own Id: OTP-17189 Aux Id: PR-2675\n\n- The `Fun`'s passed to logger:log/2,3,4 can now return metadata that will only\n be fetched when needed. See [`logger:log/2,3,4`](`logger:log/2`) for more\n details.\n\n Own Id: OTP-17198 Aux Id: PR-2721\n\n- `erpc:multicall()` has been rewritten to be able to utilize the newly\n introduced and improved selective receive optimization.\n\n Own Id: OTP-17201 Aux Id: PR-4534\n\n- Add utility fiunction inet:info/1 to provide miscellaneous info about a\n socket.\n\n Own Id: OTP-17203 Aux Id: OTP-17156\n\n- The behaviour for `gen_tcp:connect/3,4` has been changed to not per default\n bind to an address, which allows the network stack to delay the address and\n port selection to when the remote address is known. This allows better port\n re-use, and thus enables far more outgoing connections, since the ephemeral\n port range no longer has to be a hard limit.\n\n There is a theoretical possibility that this behaviour change can affect the\n set of possible error values, or have other small implications on some\n platforms.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17216 Aux Id: PR-2989\n\n- An option `{nxdomain_reply, boolean()}` has been implemented in the DNS\n resolver `inet_res`. It is useful since an `nxdomain` error from a name server\n does contain the SOA record if the domain exists at all. This record is useful\n to determine a TTL for negative caching of the failed entry.\n\n Own Id: OTP-17266 Aux Id: PR-4564\n\n- Optimized lookup of local processes part of groups in `pg`.\n\n Own Id: OTP-17284 Aux Id: PR-4615\n\n- The return values from module `socket` functions `send()`, `sendto()`,\n `sendmsg()`, `sendfile()` and `recv()` has been changed to return a tuple\n tagged with `select` when a `SelectInfo` was returned, and not sometimes\n tagged with `ok`.\n\n This is a backwards incompatible change that improves usability for code using\n asynchronous operations.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17355 Aux Id: OTP-17154\n\n- Fixed warnings in code matching on underscore prefixed variables.\n\n Own Id: OTP-17385 Aux Id: OTP-17123","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 7.3.1.7 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-7-3-1-7"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- A new function `global:disconnect/0` has been introduced with which one can\n cleanly disconnect a node from all other nodes in a cluster of `global` nodes.\n\n Own Id: OTP-18232 Aux Id: OTP-17843, PR-6264","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 7.3.1.6 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-7-3-1-6"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- A call to [`net_kernel:setopts(new, Opts)`](`net_kernel:setopts/2`) at the\n same time as a connection was being set up could cause a deadlock between the\n `net_kernel` process and the process setting up the connection.\n\n Own Id: OTP-18198 Aux Id: GH-6129, PR-6216","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 7.3.1.5 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-7-3-1-5"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- By default `global` does _not_ take any actions to restore a fully connected\n network when connections are lost due to network issues. This is problematic\n for all applications expecting a fully connected network to be provided, such\n as for example `mnesia`, but also for `global` itself. A network of\n overlapping partitions might cause the internal state of `global` to become\n inconsistent. Such an inconsistency can remain even after such partitions have\n been brought together to form a fully connected network again. The effect on\n other applications that expects that a fully connected network is maintained\n may vary, but they might misbehave in very subtle hard to detect ways during\n such a partitioning.\n\n In order to prevent such issues, we have introduced a _prevent overlapping\n partitions_ fix which can be enabled using the\n [`prevent_overlapping_partitions`](kernel_app.md#prevent_overlapping_partitions)\n `kernel(6)` parameter. When this fix has been enabled, `global` will actively\n disconnect from nodes that reports that they have lost connections to other\n nodes. This will cause fully connected partitions to form instead of leaving\n the network in a state with overlapping partitions. Note that this fix _has_\n to be enabled on _all_ nodes in the network in order to work properly. Since\n this quite substantially changes the behavior, this fix is currently disabled\n by default. Since you might get hard to detect issues without this fix you\n are, however, _strongly_ advised to enable this fix in order to avoid issues\n such as the ones described above. As of OTP 25 this fix will become enabled by\n default.\n\n Own Id: OTP-17843 Aux Id: ERIERL-732, PR-5611\n\n- Fix failed accepted connection setup after previous established connection\n from same node closed down silently.\n\n Own Id: OTP-17979 Aux Id: ERIERL-780","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- A [`net_tickintensity`](kernel_app.md#net_tickintensity) `kernel` parameter\n has been introduced. It can be used to control the amount of ticks during a\n [`net_ticktime`](kernel_app.md#net_ticktime) period.\n\n A new `net_kernel:start/2` function has also been introduced in order to make\n it easier to add new options. The use of `net_kernel:start/1` has been\n deprecated.\n\n Own Id: OTP-17905 Aux Id: ERIERL-732, PR-5740","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 7.3.1.4 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-7-3-1-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Parsing of the result value in the native DNS resolver has been made more\n defensive against incorrect results.\n\n Own Id: OTP-17578 Aux Id: ERIERL-683","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 7.3.1.3 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-7-3-1-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fix code:get_doc/1 to not crash when module is located in an escript.\n\n Own Id: OTP-17570 Aux Id: PR-5139 GH-4256 ERL-1261","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 7.3.1.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-7-3-1-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Handling of the \".\" domain as a search domain was incorrect and caused a crash\n in the DNS resolver `inet_res`, which has now been fixed.\n\n Own Id: OTP-17473 Aux Id: GH-4838, OTP-17439\n\n- Fixed rare bug that could cause net_kernel process to hang for ever. Have seen\n to happen with massive number of TLS connections while remote nodes are\n restarting. Bug exists since OTP-22.0.\n\n Own Id: OTP-17476 Aux Id: GH-4931, PR-4934","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 7.3.1.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-7-3-1-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fix a race condition in Global.\n\n Own Id: OTP-16033 Aux Id: ERIERL-329, ERL-1414, GH-4448, ERL-885, GH-3923","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 7.3.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-7-3-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- A bug in the Erlang DNS resolver has been fixed, where it could be made to\n bring down the kernel supervisor and thereby the whole node, when getting an\n incorrect (IN A reply to an IN CNAME query) reply from the DNS server and used\n the reply record's value without verifying its type.\n\n Own Id: OTP-17361","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 7.3 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-7-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- The range check for compression pointers in DNS encoding was faulty, which\n caused incorrect label compression encoding for very large DNS messages;\n larger than about 16 kBytes, such as AXFR responses. This more than 11 year\n old bug has now been corrected.\n\n Own Id: OTP-13641 Aux Id: PR-2959\n\n- Fix of internal links in the `erpc` documentation.\n\n Own Id: OTP-17202 Aux Id: PR-4516\n\n- Fix bug where complex seq_trace tokens (that is lists, tuples, maps etc) could\n becomes corrupted by the GC. The bug was introduced in OTP-21.\n\n Own Id: OTP-17209 Aux Id: PR-3039\n\n- When running Xref in the `modules` mode, the Debugger application would show\n up as a dependency for the Kernel applications.\n\n Own Id: OTP-17223 Aux Id: GH-4546, PR-4554","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- `m:erl_epmd` (the epmd client) will now try to reconnect to the local EPMD if\n the connection is broken.\n\n Own Id: OTP-17178 Aux Id: PR-3003","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 7.2.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-7-2-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- When using the DNS resolver option `servfail_retry_timeout` it did not honour\n the overall call time-out in e.g `inet_res:getbyname/3`. This misbehaviour has\n now been fixed. Also, the `servfail_retry_timeout` behaviour has been improved\n to only be enforced for servers that gives a servfail answer.\n\n Own Id: OTP-12960 Aux Id: ERIERL-598, PR-4509","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 7.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-7-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- The `apply` call's in `logger.hrl` are now called with `erlang` prefix to\n avoid clashed with local [`apply/3`](`apply/3`) functions.\n\n Own Id: OTP-16976 Aux Id: PR-2807\n\n- Fix memory leak in `pg`.\n\n Own Id: OTP-17034 Aux Id: PR-2866\n\n- Fix crash in `logger_proxy` due to stray `gen_server:call` replies not being\n handled. The stray replies come when logger is under heavy load and the flow\n control mechanism is reaching its limit.\n\n Own Id: OTP-17038\n\n- Fixed a bug in `erl_epmd:names()` that caused it to return the illegal return\n value `noport` instead of `{error, Reason}` where `Reason` is the actual error\n reason. This bug also propagated to `net_adm:names()`.\n\n This bug was introduced in `kernel` version 7.1 (OTP 23.1).\n\n Own Id: OTP-17054 Aux Id: ERL-1424","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Add export of some resolver documented types.\n\n Own Id: OTP-16954 Aux Id: ERIERL-544\n\n- Add configurable retry timeout for resolver lookups.\n\n Own Id: OTP-16956 Aux Id: ERIERL-547\n\n- `gen_server:multi_call()` has been optimized in the special case of only\n calling the local node with timeout set to `infinity`.\n\n Own Id: OTP-17058 Aux Id: PR-2887","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 7.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-7-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- A fallback has been implemented for file:sendfile when using inet_backend\n socket\n\n Own Id: OTP-15187 Aux Id: ERL-1293\n\n- Make default TCP distribution honour option `backlog` in\n `inet_dist_listen_options`.\n\n Own Id: OTP-16694 Aux Id: PR-2625\n\n- Raw option handling for the experimental `gen_tcp_socket` backend was broken\n so that all raw options were ignored by for example `gen_tcp:listen/2`, a bug\n that now has been fixed. Reported by Jan Uhlig.\n\n Own Id: OTP-16743 Aux Id: ERL-1287\n\n- Accept fails with inet-backend socket.\n\n Own Id: OTP-16748 Aux Id: ERL-1284\n\n- Fixed various minor errors in the socket backend of gen_tcp.\n\n Own Id: OTP-16754\n\n- Correct `disk_log:truncate/1` to count the header. Also correct the\n documentation to state that `disk_log:truncate/1` can be used with external\n disk logs.\n\n Own Id: OTP-16768 Aux Id: ERL-1312\n\n- Fix erl_epmd:port_please/2,3 type specs to include all possible error values.\n\n Own Id: OTP-16783\n\n- Fix `erl -erl_epmd_port` to work properly. Before this fix it did not work at\n all.\n\n Own Id: OTP-16785\n\n- Fix typespec for internal function `erlang:seq_trace_info/1` to allow\n `t:term/0` as returned label. This in turn fixes so that calls to\n `seq_trace:get_token/1` can be correctly analyzer by dialyzer.\n\n Own Id: OTP-16823 Aux Id: PR-2722\n\n- Fix erroneous double registration of processes in `pg` when distribution is\n dynamically started.\n\n Own Id: OTP-16832 Aux Id: PR-2738","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Make (use of) the socket registry optional (still enabled by default). Its now\n possible to build OTP with the socket registry turned off, turn it off by\n setting an environment variable and controlling in runtime (via function calls\n and arguments when creating sockets).\n\n Own Id: OTP-16763\n\n- `erl -remsh nodename` no longer requires the hostname to be given when used\n together with dynamic nodenames.\n\n Own Id: OTP-16784","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 7.0 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-7-0"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fix race condition during shutdown when `shell_history` is enabled. The race\n condition would trigger crashes in `disk_log`.\n\n Own Id: OTP-16008 Aux Id: PR-2302\n\n- Fix the Erlang distribution to handle the scenario when a node connects that\n can handle message fragmentation but can not handle the atom cache. This bug\n only affects users that have implemented a custom distribution carrier. It has\n been present since OTP-21.\n\n The `DFLAG_FRAGMENT` distribution flag was added to the set of flags that can\n be rejected by a distribution implementation.\n\n Own Id: OTP-16284\n\n- Fix bug where a binary was not allowed to be the format string in calls to\n `logger:log`.\n\n Own Id: OTP-16395 Aux Id: PR-2444\n\n- Fix bug where `logger` would end up in an infinite loop when trying to log the\n crash of a handler or formatter.\n\n Own Id: OTP-16489 Aux Id: ERL-1134\n\n- `code:lib_dir/1` has been fixed to also return the lib dir for `erts`.\n\n This is been marked as an incompatibility for any application that depended on\n `{error,bad_name}` to be returned for `erts`.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-16502\n\n- The application `stop/1` callback was not called if the application master of\n the application terminated.\n\n Own Id: OTP-16504 Aux Id: PR-2328\n\n- Fix bug in `application:loaded_applications/0` that could cause it to fail\n with `badarg` if for example a concurrent upgrade/downgrade is running.\n\n Own Id: OTP-16627 Aux Id: PR-2601","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- A new module `m:erpc` has been introduced in the `kernel` application. The\n `erpc` module implements an enhanced subset of the operations provided by the\n `m:rpc` module. Enhanced in the sense that it makes it possible to distinguish\n between returned value, raised exceptions, and other errors. `erpc` also has\n better performance and scalability than the original `rpc` implementation.\n This by utilizing the newly introduced\n [`spawn_request()`](`erlang:spawn_request/5`) BIF. Also the `rpc` module\n benefits from these improvements by utilizing `erpc` when it is possible.\n\n This change has been marked as a potential incompatibility since\n [`rpc:block_call()`](`rpc:block_call/5`) now only is guaranteed to block other\n `block_call()` operations. The documentation previously claimed that it would\n block all `rpc` operations. This has however never been the case. It\n previously did not block node-local `block_call()` operations.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-13450 Aux Id: OTP-15251\n\n- A client node can receive its node name dynamically from the node that it\n first connects to. This featured can by used by\n\n - starting with `erl -sname undefined`\n - erl_interface functions `ei_connect_init` and friends\n - `erl_call -R`\n\n Own Id: OTP-13812\n\n- Improved the printout of single line logger events for most of the OTP\n behaviours in STDLIB and Kernel. This includes `proc_lib`, `gen_server`,\n `gen_event`, `gen_statem`, `gen_fsm`, `supervisor`, `supervisor_bridge` and\n `application`.\n\n Improved the [`chars_limit`](`m:logger_formatter#chars_limit`) and\n [`depth`](`m:logger_formatter#depth`) handling in `proc_lib` and when\n formatting of exceptions.\n\n Own Id: OTP-15299\n\n- Remove usage and documentation of old requests of the I/O-protocol.\n\n Own Id: OTP-15695\n\n- Directories can now be opened by `file:open/2` when passing the `directory`\n option.\n\n Own Id: OTP-15835 Aux Id: PR-2212\n\n- The check of whether to log or not based on the log level in `logger` has been\n optimized by using `persistent_term` to store the log level.\n\n Own Id: OTP-15948 Aux Id: PR-2356\n\n- `file:read_file_info/2` can now be used on opened files and directories.\n\n Own Id: OTP-15956 Aux Id: PR-2231\n\n- The `-config` option to `erl` now can take multiple config files without\n repeating the `-config` option. Example:\n\n erl -config sys local\n\n Own Id: OTP-16148 Aux Id: PR-2373\n\n- Improved node connection setup handshake protocol. Made possible to agree on\n protocol version without dependence on `epmd` or other prior knowledge of peer\n node version. Also added exchange of node incarnation (\"creation\") values and\n expanded the distribution capability flag field from 32 to 64 bits.\n\n Own Id: OTP-16229\n\n- The possibility to run Erlang distribution without relying on EPMD has been\n extended. To achieve this a couple of new options to the inet distribution has\n been added.\n\n - **\\-dist_listen false** - Setup the distribution channel, but do not listen\n for incoming connection. This is useful when you want to use the current\n node to interact with another node on the same machine without it joining\n the entire cluster.\n\n - **\\-erl_epmd_port Port** - Configure a default port that the built-in EPMD\n client should return. This allows the local node to know the port to connect\n to for any other node in the cluster.\n\n The `erl_epmd` callback API has also been extended to allow returning `-1` as\n the creation which means that a random creation will be created by the node.\n\n In addition a new callback function called `listen_port_please` has been added\n that allows the callback to return which listen port the distribution should\n use. This can be used instead of `inet_dist_listen_min/max` if the listen port\n is to be fetched from an external service.\n\n Own Id: OTP-16250\n\n- A first EXPERIMENTAL module that is a `socket` backend to `gen_tcp` and `inet`\n has been implemented. Others will follow. Feedback will be appreciated.\n\n Own Id: OTP-16260 Aux Id: OTP-15403\n\n- The new experimental `socket` module has been moved to the Kernel application.\n\n Own Id: OTP-16312\n\n- Replace usage of deprecated function in the `group` module.\n\n Own Id: OTP-16345\n\n- Minor updates due to the new spawn improvements made.\n\n Own Id: OTP-16368 Aux Id: OTP-15251\n\n- Update of [sequential tracing](`m:seq_trace#whatis`) to also support other\n information transfers than message passing.\n\n Own Id: OTP-16370 Aux Id: OTP-15251, OTP-15232\n\n- `code:module_status/1` now accepts a list of modules. `code:module_status/0`,\n which returns the statuses for all loaded modules, has been added.\n\n Own Id: OTP-16402\n\n- `filelib:wildcard/1,2` is now twice as fast when a double star (`**`) is part\n of the pattern.\n\n Own Id: OTP-16419\n\n- A new implementation of distributed named process groups has been introduced.\n It is available in the `m:pg` module.\n\n Note that this `pg` module only has the name in common with the experimental\n `pg` module that was present in `stdlib` up until OTP 17.\n\n Thanks to Maxim Fedorov for the implementation.\n\n Own Id: OTP-16453 Aux Id: PR-2524\n\n- The `pg2` module has been deprecated. It has also been scheduled for removal\n in OTP 24.\n\n You are advised to replace the usage of `pg2` with the newly introduced `m:pg`\n module. `pg` has a similar API, but with a more scalable implementation.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-16455\n\n- Refactored the internal handling of deprecated and removed functions.\n\n Own Id: OTP-16469\n\n- The internal hosts file resolver cache `inet_hosts` has been rewritten to\n behave better when the hosts file changes. For example the cache is updated\n per entry instead of cleared and reloaded so lookups do not temporarily fail\n during reloading, and; when multiple processes simultaneously request reload\n these are now folded into one instead of all done in sequence. Reported and\n first solution suggestion by Maxim Fedorov.\n\n Own Id: OTP-16487 Aux Id: PR-2516\n\n- Add `code:all_available/0` that can be used to get all available modules.\n\n Own Id: OTP-16494\n\n- As of OTP 23, the distributed `m:disk_log` feature has been deprecated. It has\n also been scheduled for removal in OTP 24.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-16495\n\n- Add the function `code:fetch_docs/1` for fetching embedded documentation for\n aa Erlang module.\n\n Own Id: OTP-16499\n\n- Improve configure for the net nif, which should increase portability.\n\n Own Id: OTP-16530 Aux Id: OTP-16464\n\n- socket: Socket counters and socket global counters are now represented as maps\n (instead of property lists).\n\n Own Id: OTP-16535\n\n- The experimental socket module has gotten restrictions removed so now the\n 'seqpacket' socket type should work for any communication domain (protocol\n family) where the OS supports it, typically the Unix Domain.\n\n Own Id: OTP-16550 Aux Id: ERIERL-476\n\n- Allow using custom IO devices in `logger_std_h`.\n\n Own Id: OTP-16563 Aux Id: PR-2523\n\n- Added `file:del_dir_r/1` which deletes a directory together with all of its\n contents, similar to `rm -rf` on Unix systems.\n\n Own Id: OTP-16570 Aux Id: PR-2565\n\n- socket: By default the socket options rcvtimeo and sndtimeo are now disabled.\n To enable these, OTP now has to be built with the configure option\n --enable-esock-rcvsndtimeo\n\n Own Id: OTP-16620\n\n- The experimental gen_tcp compatibility code utilizing the socket module could\n loose buffered data when receiving a specified number of bytes. This bug has\n been fixed. Reported by Maksim Lapshin on bugs.erlang.org ERL-1234\n\n Own Id: OTP-16632 Aux Id: ERL-1234","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 6.5.2.5 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-6-5-2-5"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- By default `global` does _not_ take any actions to restore a fully connected\n network when connections are lost due to network issues. This is problematic\n for all applications expecting a fully connected network to be provided, such\n as for example `mnesia`, but also for `global` itself. A network of\n overlapping partitions might cause the internal state of `global` to become\n inconsistent. Such an inconsistency can remain even after such partitions have\n been brought together to form a fully connected network again. The effect on\n other applications that expects that a fully connected network is maintained\n may vary, but they might misbehave in very subtle hard to detect ways during\n such a partitioning.\n\n In order to prevent such issues, we have introduced a _prevent overlapping\n partitions_ fix which can be enabled using the\n `prevent_overlapping_partitions` `kernel(6)` parameter. When this fix has been\n enabled, `global` will actively disconnect from nodes that reports that they\n have lost connections to other nodes. This will cause fully connected\n partitions to form instead of leaving the network in a state with overlapping\n partitions. Note that this fix _has_ to be enabled on _all_ nodes in the\n network in order to work properly. Since this quite substantially changes the\n behavior, this fix is currently disabled by default. Since you might get hard\n to detect issues without this fix you are, however, _strongly_ advised to\n enable this fix in order to avoid issues such as the ones described above. As\n of OTP 25 this fix will become enabled by default.\n\n Own Id: OTP-17843 Aux Id: ERIERL-732, PR-5611","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- A `net_tickintensity` `kernel` parameter has been introduced. It can be used\n to control the amount of ticks during a `net_ticktime` period.\n\n A new `net_kernel:start/2` function has also been introduced in order to make\n it easier to add new options. The use of `net_kernel:start/1` has been\n deprecated.\n\n Own Id: OTP-17905 Aux Id: ERIERL-732, PR-5740","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 6.5.2.4 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-6-5-2-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fixed rare bug that could cause net_kernel process to hang for ever. Have seen\n to happen with massive number of TLS connections while remote nodes are\n restarting. Bug exists since OTP-22.0.\n\n Own Id: OTP-17476 Aux Id: GH-4931, PR-4934","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 6.5.2.3 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-6-5-2-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fix a race condition in Global.\n\n Own Id: OTP-16033 Aux Id: ERIERL-329, ERL-1414, GH-4448, ERL-885, GH-3923","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 6.5.2.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-6-5-2-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- When running Xref in the `modules` mode, the Debugger application would show\n up as a dependency for the Kernel applications.\n\n Own Id: OTP-17223 Aux Id: GH-4546, PR-4554","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 6.5.2.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-6-5-2-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fix bug in `application:loaded_applications/0` that could cause it to fail\n with `badarg` if for example a concurrent upgrade/downgrade is running.\n\n Own Id: OTP-16627 Aux Id: PR-2601","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 6.5.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-6-5-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- The DNS resolver \\`inet_res\\` has been fixed to return the last intermediate\n error when subsequent requests times out.\n\n Own Id: OTP-16414 Aux Id: ERIERL-452\n\n- The prim_net nif (net/kernel) made use of an undefined atom, notsup. This has\n now been corrected.\n\n Own Id: OTP-16440\n\n- Fix a crash when attempting to log faults when loading files during early\n boot.\n\n Own Id: OTP-16491\n\n- Fix crash in logger when logging to a remote node during boot.\n\n Own Id: OTP-16493 Aux Id: ERIERL-459","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Improved `net_kernel` debug functionality.\n\n Own Id: OTP-16458 Aux Id: PR-2525","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 6.5.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-6-5-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- The 'socket state' info provided by the inet info function has been improved\n\n Own Id: OTP-16043 Aux Id: ERL-1036\n\n- Fix bug where `logger` would crash when starting when a very large log file\n needed to be rotated and compressed.\n\n Own Id: OTP-16145 Aux Id: ERL-1034\n\n- Fixed a bug causing actual nodedown reason reported by\n [`net_kernel:monitor_nodes(true, [nodedown_reason])`](`net_kernel:monitor_nodes/2`)\n to be lost and replaced by the reason `killed`.\n\n Own Id: OTP-16216\n\n- The documentation for `rpc:call/4,5/` has been updated to describe what\n happens when the called function throws or return an `'EXIT'` tuple.\n\n Own Id: OTP-16279 Aux Id: ERL-1066","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 6.5 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-6-5"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- The type specification for `gen_sctp:connect/4,5` has been corrected.\n\n Own Id: OTP-15344 Aux Id: ERL-947\n\n- Extra `-mode` flags given to `erl` are ignored with a warning.\n\n Own Id: OTP-15852\n\n- Fix type spec for `seq_trace:set_token/2`.\n\n Own Id: OTP-15858 Aux Id: ERL-700\n\n- `logger:compare_levels/2` would fail with a `badarg` exception if given the\n values `all` or `none` as any of the parameters. This is now corrected.\n\n Own Id: OTP-15942 Aux Id: PR-2301\n\n- Fix bug where the log file in `logger_std_h` would not be closed when the\n inode of the file changed. This would in turn cause a file descriptor leak\n when tools like logrotate are used.\n\n Own Id: OTP-15997 Aux Id: PR-2331\n\n- Fix a race condition in the debugging function `net_kernel:nodes_info/0`.\n\n Own Id: OTP-16022\n\n- Fix race condition when closing a file opened in `compressed` or\n `delayed_write` mode.\n\n Own Id: OTP-16023","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- The possibility to send ancillary data, in particular the TOS field, has been\n added to `gen_udp:send/4,5`.\n\n Own Id: OTP-15747 Aux Id: ERIERL-294\n\n- If the log file was given with relative path, the standard logger handler\n (`logger_std_h`) would store the file name with relative path. If the current\n directory of the node was later changed, a new file would be created relative\n the new current directory, potentially failing with an `enoent` if the new\n directory did not exist. This is now corrected and `logger_std_h` always\n stores the log file name as an absolute path, calculated from the current\n directory at the time of the handler startup.\n\n Own Id: OTP-15850\n\n- Support local sockets with inet:i/0.\n\n Own Id: OTP-15935 Aux Id: PR-2299","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 6.4.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-6-4-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- `user`/`user_drv` could respond to io requests before they had been processed,\n which could cause data to be dropped if the emulator was halted soon after a\n call to `io:format/2`, such as in an escript.\n\n Own Id: OTP-15805","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 6.4 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-6-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fix so that when multiple `-sname` or `-name` are given to `erl` the first one\n is chosen. Before this fix distribution was not started at all when multiple\n name options were given.\n\n Own Id: OTP-15786 Aux Id: ERL-918\n\n- Fix `inet_res` configuration pointing to non-existing files to work again.\n This was broken in KERNEL-6.3 (OTP-21.3).\n\n Own Id: OTP-15806","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- A simple socket API is provided through the socket module. This is a low level\n API that does _not_ replace gen\\_\\[tcp|udp|sctp]. It is intended to\n _eventually_ replace the inet driver, but not the high level gen-modules\n (gen_tcp, gen_udp and gen_sctp). It also provides a basic API that facilitates\n the implementation of other protocols, that is TCP, UDP and SCTP.\n\n Known issues are; No support for the Windows OS (currently).\n\n Own Id: OTP-14831\n\n- Improved the documentation for the linger option.\n\n Own Id: OTP-15491 Aux Id: PR-2019\n\n- Global no longer tries more than once when connecting to other nodes.\n\n Own Id: OTP-15607 Aux Id: ERIERL-280\n\n- The dist messages EXIT, EXIT2 and MONITOR_DOWN have been updated with new\n versions that send the reason term as part of the payload of the message\n instead of as part of the control message.\n\n The old versions are still present and can be used when communicating with\n nodes that don't support the new versions.\n\n Own Id: OTP-15611\n\n- Kernel configuration parameter `start_distribution = boolean()` is added. If\n set to `false`, the system is started with all distribution functionality\n disabled. Defaults to `true`.\n\n Own Id: OTP-15668 Aux Id: PR-2088\n\n- In OTP-21.3, a warning was introduced for duplicated applications/keys in\n configuration. This warning would be displayed both when the configuration was\n given as a file on system start, and during runtime via\n `application:set_env/1,2`.\n\n The warning is now changed to a `badarg` exception in\n `application:set_env/1,2`. If the faulty configuration is given in a\n configuration file on system start, the startup will fail.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15692 Aux Id: PR-2170","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 6.3.1.3 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-6-3-1-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fix bug where the log file in `logger_std_h` would not be closed when the\n inode of the file changed. This would in turn cause a file descriptor leak\n when tools like logrotate are used.\n\n Own Id: OTP-15997 Aux Id: PR-2331","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 6.3.1.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-6-3-1-2"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- The possibility to send ancillary data, in particular the TOS field, has been\n added to `gen_udp:send/4,5`.\n\n Own Id: OTP-15747 Aux Id: ERIERL-294","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 6.3.1.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-6-3-1-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fix type spec for `seq_trace:set_token/2`.\n\n Own Id: OTP-15858 Aux Id: ERL-700","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 6.3.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-6-3-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fixed a performance regression when reading files opened with the `compressed`\n flag.\n\n Own Id: OTP-15706 Aux Id: ERIERL-336","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 6.3 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-6-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- If for example the `/etc/hosts` did not come into existence until after the\n kernel application had started, its content was never read. This bug has now\n been corrected.\n\n Own Id: OTP-14702 Aux Id: PR-2066\n\n- Fix bug where doing `seq_trace:reset_trace()` while another process was doing\n a garbage collection could cause the run-time system to segfault.\n\n Own Id: OTP-15490\n\n- Fix `erl_epmd:port_please` spec to include `t:atom/0` and `t:string/0`.\n\n Own Id: OTP-15557 Aux Id: PR-2117\n\n- The Logger handler logger_std_h now keeps track of the inode of its log file\n in order to re-open the file if the inode changes. This may happen, for\n instance, if the log file is opened and saved by an editor.\n\n Own Id: OTP-15578 Aux Id: ERL-850\n\n- When user specific file modes are given to the logger handler `logger_std_h`,\n they were earlier accepted without any control. This is now changes, so Logger\n will adjust the file modes as follows:\n\n \\- If `raw` is not found in the list, it is added. \n \\- If none of `write`, `append` or `exclusive` are found in the list, `append`\n is added. \n \\- If none of `delayed_write` or `{delayed_write,Size,Delay}` are found in the\n list, `delayed_write` is added.\n\n Own Id: OTP-15602","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- The standard logger handler, `logger_std_h`, now has a new internal feature\n for log rotation. The rotation scheme is as follows:\n\n The log file to which the handler currently writes always has the same name,\n i.e. the name which is configured for the handler. The archived files have the\n same name, but with extension \".N\", where N is an integer. The newest archive\n has extension \".0\", and the oldest archive has the highest number.\n\n The size at which the log file is rotated, and the number of archive files\n that are kept, is specified with the handler specific configuration parameters\n `max_no_bytes` and `max_no_files` respectively.\n\n Archives can be compressed, in which case they get a \".gz\" file extension\n after the integer. Compression is specified with the handler specific\n configuration parameter `compress_on_rotate`.\n\n Own Id: OTP-15479\n\n- The new functions `logger:i/0` and `logger:i/1` are added. These provide the\n same information as `logger:get_config/0` and other `logger:get_*_config`\n functions, but the information is more logically sorted and more readable.\n\n Own Id: OTP-15600\n\n- Logger is now protected against overload due to massive amounts of log events\n from the emulator or from remote nodes.\n\n Own Id: OTP-15601\n\n- Logger now uses os:system_time/1 instead of erlang:system_time/1 to generate\n log event timestamps.\n\n Own Id: OTP-15625\n\n- Add functions `application:set_env/1,2` and `application:set_env/2`. These\n take a list of application configuration parameters, and the behaviour is\n equivalent to calling `application:set_env/4` individually for each\n application/key combination, except it is more efficient.\n\n `set_env/1,2` warns about duplicated applications or keys. The warning is also\n emitted during boot, if applications or keys are duplicated within one\n configuration file, e.g. sys.config.\n\n Own Id: OTP-15642 Aux Id: PR-2164\n\n- Handler specific configuration parameters for the standard handler\n `logger_std_h` are changed to be more intuitive and more similar to the\n disk_log handler.\n\n Earlier there was only one parameter, `type`, which could have the values\n `standard_io`, `standard_error`, `{file,FileName}` or `{file,FileName,Modes}`.\n\n This is now changed, so the following parameters are allowed:\n\n `type = standard_io | standard_error | file` \n `file = file:filename()` \n `modes = [file:mode()]`\n\n All parameters are optional. `type` defaults to `standard_io`, unless a file\n name is given, in which case it defaults to `file`. If `type` is set to\n `file`, the file name defaults to the same as the handler id.\n\n The potential incompatibility is that `logger:get_config/0` and\n `logger:get_handler_config/1` now returns the new parameters, even if the\n configuration was set with the old variant, e.g. `#{type=>{file,FileName}}`.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15662\n\n- The new configuration parameter `file_check` is added to the Logger handler\n `logger_std_h`. This parameter specifies how long (in milliseconds) the\n handler may wait before checking if the log file still exists and the inode is\n the same as when it was opened.\n\n The default value is 0, which means that this check is done prior to each\n write operation. Setting a higher number may improve performance, but adds the\n risk of losing log events.\n\n Own Id: OTP-15663","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 6.2.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-6-2-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Setting the `recbuf` size of an inet socket the `buffer` is also automatically\n increased. Fix a bug where the auto adjustment of inet buffer size would be\n triggered even if an explicit inet buffer size had already been set.\n\n Own Id: OTP-15651 Aux Id: ERIERL-304","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 6.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-6-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- A new function, `logger:update_handler_config/3` is added, and the handler\n callback `changing_config` now has a new argument, `SetOrUpdate`, which\n indicates if the configuration change comes from `set_handler_config/2,3` or\n `update_handler_config/2,3`.\n\n This allows the handler to consistently merge the new configuration with the\n old (if the change comes from `update_handler_config/2,3`) or with the default\n (if the change comes from `set_handler_config/2,3`).\n\n The built-in handlers `logger_std_h` and `logger_disk_log_h` are updated\n accordingly. A bug which could cause inconsistency between the handlers'\n internal state and the stored configuration is also corrected.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15364\n\n- Fix fallback when custom erl_epmd client does not implement address_please.\n\n Own Id: OTP-15388 Aux Id: PR-1983\n\n- The logger ets table did not have the `read_concurrency` option. This is now\n added.\n\n Own Id: OTP-15453 Aux Id: ERL-782\n\n- During system start, logger has a simple handler which prints to stdout. After\n the kernel supervision is started, this handler is removed and replaced by the\n default handler. Due to a bug, logger earlier issued a debug printout saying\n it received an unexpected message, which was the EXIT message from the simple\n handler's process. This is now corrected. The simple handler's process now\n unlinks from the logger process before terminating.\n\n Own Id: OTP-15466 Aux Id: ERL-788\n\n- The logger handler `logger_std_h` would not re-create it's log file if it was\n removed. Due to this it could not be used with tools like 'logrotate'. This is\n now corrected.\n\n Own Id: OTP-15469","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- A function `inet:getifaddrs/1` that takes a list with a namespace option has\n been added, for platforms that support that feature, for example Linux\n (only?).\n\n Own Id: OTP-15121 Aux Id: ERIERL-189, PR-1974\n\n- Added the `nopush` option for TCP sockets, which corresponds to `TCP_NOPUSH`\n on \\*BSD and `TCP_CORK` on Linux.\n\n This is also used internally in `file:sendfile` to reduce latency on\n subsequent send operations.\n\n Own Id: OTP-15357 Aux Id: ERL-698\n\n- Optimize handling of send_delay for tcp sockes to better work with the new\n pollthread implementation introduced in OTP-21.\n\n Own Id: OTP-15471 Aux Id: ERIERL-229","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 6.1.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-6-1-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fix bug causing net_kernel process crash on connection attempt from node with\n name identical to local node.\n\n Own Id: OTP-15438 Aux Id: ERL-781","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 6.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-6-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- The values `all` and `none` are documented as valid value for the Kernel\n configuration parameter `logger_level`, but would cause a crash during node\n start. This is now corrected.\n\n Own Id: OTP-15143\n\n- Fix some potential buggy behavior in how ticks are sent on inter node\n distribution connections. Tick is now sent to c-node even if there are unsent\n buffered data, as c-nodes need ticks in order to send reply ticks. The amount\n of sent data was also calculated wrongly when ticks were suppressed due to\n unsent buffered data.\n\n Own Id: OTP-15162 Aux Id: ERIERL-191\n\n- Non semantic change in dist_util.erl to silence dialyzer warning.\n\n Own Id: OTP-15170\n\n- Fixed `net_kernel:connect_node(node())` to return `true` (and do nothing) as\n it always has before OTP-21.0. Also documented this successful \"self connect\"\n as the expected behavior.\n\n Own Id: OTP-15182 Aux Id: ERL-643\n\n- The single_line option on logger_formatter would in some cases add an unwanted\n comma after the association arrows in a map. This is now corrected.\n\n Own Id: OTP-15228\n\n- Improved robustness of distribution connection setup. In OTP-21.0 a truly\n asynchronous connection setup was introduced. This is further improvement on\n that work to make the emulator more robust and also be able to recover in\n cases when involved Erlang processes misbehave.\n\n Own Id: OTP-15297 Aux Id: OTP-15279, OTP-15280","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- A new macro, `?LOG(Level,...)`, is added. This is equivalent to the existing\n `?LOG_ (...)` macros.\n\n A new variant of Logger report callback is added, which takes an extra\n argument containing options for size limiting and line breaks. Module\n `proc_lib` in `STDLIB` uses this for crash reports.\n\n Logger configuration is now checked a bit more for errors.\n\n Own Id: OTP-15132\n\n- The socket options `recvtos`, `recvttl`, `recvtclass` and `pktoptions` have\n been implemented in the socket modules. See the documentation for the\n `gen_tcp`, `gen_udp` and `inet` modules. Note that support for these in the\n runtime system is platform dependent. Especially for `pktoptions` which is\n very Linux specific and obsoleted by the RFCs that defined it.\n\n Own Id: OTP-15145 Aux Id: ERIERL-187\n\n- Add `logger:set_application_level/2` for setting the logger level of all\n modules in one application.\n\n Own Id: OTP-15146","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 6.0.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-6-0-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fixed bug in `net_kernel` that could cause an emulator crash if certain\n connection attempts failed. Bug exists since kernel-6.0 (OTP-21.0).\n\n Own Id: OTP-15280 Aux Id: ERIERL-226, OTP-15279","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 6.0 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-6-0"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Clarify the documentation of `rpc:multicall/5`.\n\n Own Id: OTP-10551\n\n- The DNS resolver when getting econnrefused from a server retained an invalid\n socket so look up towards the next server(s) also failed.\n\n Own Id: OTP-13133 Aux Id: PR-1557\n\n- No resolver backend returns V4Mapped IPv6 addresses any more. This was\n inconsistent before, some did, some did not. To facilitate working with such\n addresses a new function `inet:ipv4_mapped_ipv6_address/1` has been added.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-13761 Aux Id: ERL-503\n\n- The type specifications for [`file:posix/0`](`t:file:posix/0`) and\n [`inet:posix/0`](`t:inet:posix/0`) have been updated according to which errors\n file and socket operations should be able to return.\n\n Own Id: OTP-14019 Aux Id: ERL-550\n\n- Fix name resolving in IPv6 only environments when doing the initial\n distributed connection.\n\n Own Id: OTP-14501\n\n- File operations used to accept [filenames](`t:file:name_all/0`) containing\n null characters (integer value zero). This caused the name to be truncated and\n in some cases arguments to primitive operations to be mixed up. Filenames\n containing null characters inside the filename are now _rejected_ and will\n cause primitive file operations to fail.\n\n Also environment variable operations used to accept\n [names](`t:os:env_var_name/0`) and [values](`t:os:env_var_value/0`) of\n environment variables containing null characters (integer value zero). This\n caused operations to silently produce erroneous results. Environment variable\n names and values containing null characters inside the name or value are now\n _rejected_ and will cause environment variable operations to fail.\n\n Primitive environment variable operations also used to accept the `$=`\n character in environment variable names causing various problems. `$=`\n characters in environment variable names are now also _rejected_.\n\n Also `os:cmd/1` now reject null characters inside its\n [command](`t:os:os_command/0`).\n\n `erlang:open_port/2` will also reject null characters inside the port name\n from now on.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-14543 Aux Id: ERL-370\n\n- `os:putenv` and `os:getenv` no longer access the process environment directly\n and instead work on a thread-safe emulation. The only observable difference is\n that it's _not_ kept in sync with libc `getenv(3)` / `putenv(3)`, so those who\n relied on that behavior in drivers or NIFs will need to add manual\n synchronization.\n\n On Windows this means that you can no longer resolve DLL dependencies by\n modifying the `PATH` just before loading the driver/NIF. To make this less of\n a problem, the emulator now adds the target DLL's folder to the DLL search\n path.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-14666\n\n- Fixed connection tick toward primitive hidden nodes (erl_interface) that could\n cause faulty tick timeout in rare cases when payload data is sent to hidden\n node but not received.\n\n Own Id: OTP-14681\n\n- Make group react immediately on an EXIT-signal from shell in e.g ssh.\n\n Own Id: OTP-14991 Aux Id: PR1705\n\n- Calls to `gen_tcp:send/2` on closed sockets now returns `{error, closed}`\n instead of `{error,enotconn}`.\n\n Own Id: OTP-15001\n\n- The `included_applications` key are no longer duplicated as application\n environment variable. Earlier, the included applications could be read both\n with `application:get[_all]_env(...)` and `application:get[_all]_key(...)`\n functions. Now, it can only be read with `application:get[_all]_key(...)`.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15071\n\n- Owner and group changes through `file:write_file_info`, `file:change_owner`,\n and `file:change_group` will no longer report success on permission errors.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15118","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- A new logging API is added to Erlang/OTP, see the `m:logger` manual page, and\n section [Logging](logger_chapter.md) in the Kernel User's Guide.\n\n Calls to `error_logger` are automatically redirected to the new API, and\n legacy error logger event handlers can still be used. It is, however,\n recommended to use the Logger API directly when writing new code.\n\n Notice the following potential incompatibilities:\n\n - Kernel configuration parameters `error_logger` still works, but is overruled\n if the default handler's output destination is configured with Kernel\n configuration parameter `logger`.\n\n In general, parameters for configuring error logger are overwritten by new\n parameters for configuring Logger.\n\n - The concept of SASL error logging is deprecated, meaning that by default the\n SASL application does not affect which log events are logged.\n\n By default, supervisor reports and crash reports are logged by the default\n Logger handler started by Kernel, and end up at the same destination\n (terminal or file) as other standard log event from Erlang/OTP.\n\n Progress reports are not logged by default, but can be enabled by setting\n the primary log level to info, for example with the Kernel configuration\n parameter `logger_level`.\n\n To obtain backwards compatibility with the SASL error logging functionality\n from earlier releases, set Kernel configuration parameter\n `logger_sasl_compatible` to `true`. This prevents the default Logger handler\n from logging any supervisor-, crash-, or progress reports. Instead, SASL\n adds a separate Logger handler during application start, which takes care of\n these log events. The SASL configuration parameters `sasl_error_logger` and\n `sasl_errlog_type` specify the destination (terminal or file) and severity\n level to log for these events.\n\n Since Logger is new in Erlang/OTP 21.0, we do reserve the right to introduce\n changes to the Logger API and functionality in patches following this release.\n These changes might or might not be backwards compatible with the initial\n version.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-13295\n\n- The function `inet:i/0` has been documented.\n\n Own Id: OTP-13713 Aux Id: PR-1645\n\n- Typespecs for `netns` and `bind_to_device` options have been added to\n `gen_tcp`, `gen_udp` and `gen_sctp` functions.\n\n Own Id: OTP-14359 Aux Id: PR-1816\n\n- New functionality for implementation of alternative carriers for the Erlang\n distribution has been introduced. This mainly consists of support for usage of\n distribution controller processes (previously only ports could be used as\n distribution controllers). For more information see\n [ERTS User's Guide ➜ How to implement an Alternative Carrier for the Erlang Distribution ➜ Distribution Module](`e:erts:alt_dist.md#distribution-module`).\n\n Own Id: OTP-14459\n\n- `seq_trace` labels may now be any erlang term.\n\n Own Id: OTP-14899\n\n- The SSL distribution protocol `-proto inet_tls` has stopped setting the SSL\n option `server_name_indication`. New verify funs for client and server in\n `inet_tls_dist` has been added, not documented yet, that checks node name if\n present in peer certificate. Usage is still also yet to be documented.\n\n Own Id: OTP-14969 Aux Id: OTP-14465, ERL-598\n\n- Changed timeout of `gen_server` calls to `auth` server from default 5 seconds\n to `infinity`.\n\n Own Id: OTP-15009 Aux Id: ERL-601\n\n- The callback module passed as `-epmd_module` to erl has been expanded to be\n able to do name and port resolving.\n\n Documentation has also been added in the `m:erl_epmd` reference manual and\n ERTS User's Guide\n [How to Implement an Alternative Node Discovery for Erlang Distribution](`e:erts:alt_disco.md`).\n\n Own Id: OTP-15086 Aux Id: PR-1694\n\n- Included config file specified with relative path in sys.config are now first\n searched for relative to the directory of sys.config itself. If not found, it\n is also searched for relative to the current working directory. The latter is\n for backwards compatibility.\n\n Own Id: OTP-15137 Aux Id: PR-1838","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 5.4.3.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-5-4-3-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Non semantic change in dist_util.erl to silence dialyzer warning.\n\n Own Id: OTP-15170","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 5.4.3.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-5-4-3-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fix some potential buggy behavior in how ticks are sent on inter node\n distribution connections. Tick is now sent to c-node even if there are unsent\n buffered data, as c-nodes need ticks in order to send reply ticks. The amount\n of sent data was calculated wrongly when ticks where suppressed due to unsent\n buffered data.\n\n Own Id: OTP-15162 Aux Id: ERIERL-191","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 5.4.3 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-5-4-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Correct a few contracts.\n\n Own Id: OTP-14889\n\n- Reject loading modules with names containing directory separators ('/' or '\\\\'\n on Windows).\n\n Own Id: OTP-14933 Aux Id: ERL-564, PR-1716\n\n- Fix bug in handling of os:cmd/2 option max_size on windows.\n\n Own Id: OTP-14940","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 5.4.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-5-4-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Add `os:cmd/2` that takes an options map as the second argument.\n\n Add `max_size` as an option to `os:cmd/2` that control the maximum size of the\n result that `os:cmd/2` will return.\n\n Own Id: OTP-14823","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 5.4.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-5-4-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Refactored an internal API.\n\n Own Id: OTP-14784","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 5.4 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-5-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Processes which did output after switching jobs (Ctrl+G) could be left forever\n stuck in the io request.\n\n Own Id: OTP-14571 Aux Id: ERL-472","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Lock counting can now be fully toggled at runtime in the lock counting\n emulator (`-emu_type lcnt`). Everything is enabled by default to match the old\n behavior, but specific categories can be toggled at will with minimal runtime\n overhead when disabled. Refer to the documentation on `lcnt:rt_mask/1` for\n details.\n\n Own Id: OTP-13170\n\n- `lcnt:collect` and `lcnt:clear` will no longer block all other threads in the\n runtime system.\n\n Own Id: OTP-14412\n\n- General Unicode improvements.\n\n Own Id: OTP-14462","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 5.3.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-5-3-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- The documentation for the 'quiet' option in disk_log:open/1 had an incorrect\n default value.\n\n Own Id: OTP-14498","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 5.3 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-5-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Function `inet:ntoa/1` has been fixed to return lowercase letters according to\n RFC 5935 that has been approved after this function was written. Previously\n uppercase letters were returned so this may be a backwards incompatible change\n depending on how the returned address string is used.\n\n Function `inet:parse_address/1` has been fixed to accept %-suffixes on scoped\n addresses. The addresses does not work yet, but gives no parse errors.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-13006 Aux Id: ERIERL-20, ERL-429\n\n- Fix bug where gethostname would incorrectly fail with enametoolong on Linux.\n\n Own Id: OTP-14310\n\n- Fix bug causing `code:is_module_native` to falsely return true when `local`\n call trace is enabled for the module.\n\n Own Id: OTP-14390\n\n- Add early reject of invalid node names from distributed nodes.\n\n Own Id: OTP-14426","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Since Unicode is now allowed in atoms an extra check is needed for node names,\n which are restricted to Latin-1.\n\n Own Id: OTP-13805\n\n- Replaced usage of deprecated symbolic [`time unit`](`t:erlang:time_unit/0`)\n representations.\n\n Own Id: OTP-13831 Aux Id: OTP-13735\n\n- `file:write_file(Name, Data, [raw])` would turn `Data` into a single binary\n before writing. This meant it could not take advantage of the `writev()`\n system call if it was given a list of binaries and told to write with `raw`\n mode.\n\n Own Id: OTP-13909\n\n- The performance of the `disk_log` has been somewhat improved in some corner\n cases (big items), and the documentation has been clarified.\n\n Own Id: OTP-14057 Aux Id: PR-1245\n\n- Functions for detecting changed code has been added. `code:modified_modules/0`\n returns all currently loaded modules that have changed on disk.\n `code:module_status/1` returns the status for a module. In the shell and in\n `c` module, `mm/0` is short for `code:modified_modules/0`, and `lm/0` reloads\n all currently loaded modules that have changed on disk.\n\n Own Id: OTP-14059\n\n- Introduce an event manager in Erlang to handle OS signals. A subset of OS\n signals may be subscribed to and those are described in the Kernel\n application.\n\n Own Id: OTP-14186\n\n- Sockets can now be bound to device (SO_BINDTODEVICE) on platforms where it is\n supported.\n\n This has been implemented e.g to support VRF-Lite under Linux; see\n [VRF ](https://www.kernel.org/doc/Documentation/networking/vrf.txt), and\n GitHub pull request [\\#1326](https://github.com/erlang/otp/pull/1326).\n\n Own Id: OTP-14357 Aux Id: PR-1326\n\n- Added option to store shell_history on disk so that the history can be reused\n between sessions.\n\n Own Id: OTP-14409 Aux Id: PR-1420\n\n- The size of crash reports created by `gen_server`, `gen_statem` and `proc_lib`\n is limited with aid of the Kernel application variable\n `error_logger_format_depth`. The purpose is to limit the size of the messages\n sent to the `error_logger` process when processes with huge message queues or\n states crash.\n\n The crash report generated by `proc_lib` includes the new tag\n `message_queue_len`. The neighbour report also includes the new tag\n `current_stacktrace`. Finally, the neighbour report no longer includes the\n tags `messages` and `dictionary`.\n\n The new function `error_logger:get_format_depth/0` can be used to retrieve the\n value of the Kernel application variable `error_logger_format_depth`.\n\n Own Id: OTP-14417\n\n- One of the ETS tables used by the `global` module is created with\n `{read_concurrency, true}` in order to reduce contention.\n\n Own Id: OTP-14419\n\n- Warnings have been added to the relevant documentation about not using\n un-secure distributed nodes in exposed environments.\n\n Own Id: OTP-14425","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 5.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-5-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fix a race during cleanup of os:cmd that would cause os:cmd to hang\n indefinitely.\n\n Own Id: OTP-14232 Aux Id: seq13275","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- The functions in the '`file`' module that take a list of paths (e.g.\n `file:path_consult/2`) will now continue to search in the path if the path\n contains something that is not a directory.\n\n Own Id: OTP-14191\n\n- Two OTP processes that are known to receive many messages are 'rex' (used by\n 'rpc') and 'error_logger'. Those processes will now store unprocessed messages\n outside the process heap, which will potentially decrease the cost of garbage\n collections.\n\n Own Id: OTP-14192","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 5.1.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-5-1-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- `code:add_pathsa/1` and command line option `-pa` both revert the given list\n of directories when adding it at the beginning of the code path. This is now\n documented.\n\n Own Id: OTP-13920 Aux Id: ERL-267\n\n- Add lost runtime dependency to erts-8.1. This should have been done in\n kernel-5.1 (OTP-19.1) as it cannot run without at least erts-8.1 (OTP-19.1).\n\n Own Id: OTP-14003\n\n- Type and doc for gen\\_\\{tcp,udp,sctp\\}:controlling_process/2 has been\n improved.\n\n Own Id: OTP-14022 Aux Id: PR-1208","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 5.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-5-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fix a memory leak when calling seq_trace:get_system_tracer().\n\n Own Id: OTP-13742\n\n- Fix for the problem that when adding the ebin directory of an application to\n the code path, the `code:priv_dir/1` function returns an incorrect path to the\n priv directory of the same application.\n\n Own Id: OTP-13758 Aux Id: ERL-195\n\n- Fix code_server crash when adding code paths of two levels.\n\n Own Id: OTP-13765 Aux Id: ERL-194\n\n- Respect -proto_dist switch while connection to EPMD\n\n Own Id: OTP-13770 Aux Id: PR-1129\n\n- Fixed a bug where init:stop could deadlock if a process with infinite shutdown\n timeout (e.g. a supervisor) attempted to load code while terminating.\n\n Own Id: OTP-13802\n\n- Close stdin of commands run in os:cmd. This is a backwards compatibility fix\n that restores the behaviour of pre 19.0 os:cmd.\n\n Own Id: OTP-13867 Aux Id: seq13178","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Add `net_kernel:setopts/2` and `net_kernel:getopts/2` to control options for\n distribution sockets in runtime.\n\n Own Id: OTP-13564\n\n- Rudimentary support for DSCP has been implemented in the guise of a `tclass`\n socket option for IPv6 sockets.\n\n Own Id: OTP-13582","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 5.0.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-5-0-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- When calling os:cmd from a process that has set trap_exit to true an 'EXIT'\n message would be left in the message queue. This bug was introduced in kernel\n vsn 5.0.1.\n\n Own Id: OTP-13813","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 5.0.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-5-0-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fix a os:cmd bug where creating a background job using & would cause os:cmd to\n hang until the background job terminated or closed its stdout and stderr file\n descriptors. This bug has existed from kernel 5.0.\n\n Own Id: OTP-13741","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 5.0 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-5-0"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- The handling of `on_load` functions has been improved. The major improvement\n is that if a code upgrade fails because the `on_load` function fails, the\n previous version of the module will now be retained.\n\n Own Id: OTP-12593\n\n- `rpc:call()` and `rpc:block_call()` would sometimes cause an exception (which\n was not mentioned in the documentation). This has been corrected so that\n `{badrpc,Reason}` will be returned instead.\n\n Own Id: OTP-13409\n\n- On Windows, for modules that were loaded early (such as the `lists` module),\n `code:which/1` would return the path with mixed slashes and backslashes, for\n example: `\"C:\\\\Program Files\\\\erl8.0/lib/stdlib-2.7/ebin/lists.beam\"`. This\n has been corrected.\n\n Own Id: OTP-13410\n\n- Make file:datasync use fsync instead of fdatasync on Mac OSX.\n\n Own Id: OTP-13411\n\n- The default chunk size for the fallback sendfile implementation, used on\n platforms that do not have a native sendfile, has been decreased in order to\n reduce connectivity issues.\n\n Own Id: OTP-13444\n\n- Large file writes (2Gb or more) could fail on some Unix platforms (for\n example, OS X and FreeBSD).\n\n Own Id: OTP-13461\n\n- A bug has been fixed where the DNS resolver inet_res did not refresh its view\n of the contents of for example resolv.conf immediately after start and hence\n then failed name resolution. Reported and fix suggested by Michal Ptaszek in\n GitHUB pull req #949.\n\n Own Id: OTP-13470 Aux Id: Pull #969\n\n- Fix process leak from global_group.\n\n Own Id: OTP-13516 Aux Id: PR-1008\n\n- The function `inet:gethostbyname/1` now honors the resolver option `inet6`\n instead of always looking up IPv4 addresses.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-13622 Aux Id: PR-1065\n\n- The `Status` argument to `init:stop/1` is now sanity checked to make sure\n `erlang:halt` does not fail.\n\n Own Id: OTP-13631 Aux Id: PR-911","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Add \\{line_delim, byte()\\} option to inet:setopts/2 and decode_packet/3\n\n Own Id: OTP-12837\n\n- Added `os:perf_counter/1`.\n\n The perf_counter is a very very cheap and high resolution timer that can be\n used to timestamp system events. It does not have monoticity guarantees, but\n should on most OS's expose a monotonous time.\n\n Own Id: OTP-12908\n\n- The os:cmd call has been optimized on unix platforms to be scale better with\n the number of schedulers.\n\n Own Id: OTP-13089\n\n- New functions that can load multiple modules at once have been added to the\n '`code`' module. The functions are `code:atomic_load/1`,\n `code:prepare_loading/1`, `code:finish_loading/1`, and\n `code:ensure_modules_loaded/1`.\n\n Own Id: OTP-13111\n\n- The code path cache feature turned out not to be very useful in practice and\n has been removed. If an attempt is made to enable the code path cache, there\n will be a warning report informing the user that the feature has been removed.\n\n Own Id: OTP-13191\n\n- When an attempt is made to start a distributed Erlang node with the same name\n as an existing node, the error message will be much shorter and easier to read\n than before. Example:\n\n `Protocol 'inet_tcp': the name somename@somehost seems to be in use by another Erlang node`\n\n Own Id: OTP-13294\n\n- The output of the default error logger is somewhat prettier and easier to\n read. The default error logger is used during start-up of the OTP system. If\n the start-up fails, the output will be easier to read.\n\n Own Id: OTP-13325\n\n- The functions `rpc:safe_multi_server_call/2,3` that were deprecated in R12B\n have been removed.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-13449\n\n- Update the error reasons in dist_util, and show them in the logs if\n net_kernel:verbose(1) has been called.\n\n Own Id: OTP-13458\n\n- Experimental support for Unix Domain Sockets has been implemented. Read the\n sources if you want to try it out. Example:\n `gen_udp:open(0, [{ifaddr,{local,\"/tmp/socket\"}}])`. Documentation will be\n written after user feedback on the experimental API.\n\n Own Id: OTP-13572 Aux Id: PR-612\n\n- Allow heart to be configured to not kill the previous emulator before calling\n the HEART_COMMAND. This is done by setting the environment variable\n HEART_NO_KILL to TRUE.\n\n Own Id: OTP-13650","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 4.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-4-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- `code:load_abs([10100])` would bring down the entire runtime system and create\n a crash dump. Corrected to generate an error exception in the calling process.\n\n Also corrected specs for code loading functions and added more information in\n the documentation about the error reasons returned by code-loading functions.\n\n Own Id: OTP-9375\n\n- `gen_tcp:accept/2` was not\n [time warp safe](`e:erts:time_correction.md#time-warp-safe-code`). This since\n it used the same time as returned by `erlang:now/0` when calculating timeout.\n This has now been fixed.\n\n Own Id: OTP-13254 Aux Id: OTP-11997, OTP-13222\n\n- Correct the contract for `inet:getifaddrs/1`.\n\n Own Id: OTP-13335 Aux Id: ERL-95","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Time warp safety improvements.\n\n Introduced the options `monotonic_timestamp`, and `strict_monotonic_timestamp`\n to the trace, sequential trace, and system profile functionality. This since\n the already existing `timestamp` option is not time warp safe.\n\n Introduced the option `safe_fixed_monotonic_time` to `ets:info/2` and\n `dets:info/2`. This since the already existing `safe_fixed` option is not time\n warp safe.\n\n Own Id: OTP-13222 Aux Id: OTP-11997\n\n- Add validation callback for heart\n\n The erlang heart process may now have a validation callback installed. The\n validation callback will be executed, if present, before any heartbeat to\n heart port program. If the validation fails, or stalls, no heartbeat will be\n sent and the node will go down.\n\n With the option `'check_schedulers'` heart executes a responsiveness check of\n the schedulers before a heartbeat is sent to the port program. If the\n responsiveness check fails, the heartbeat will not be performed (as intended).\n\n Own Id: OTP-13250\n\n- Clarify documentation of `net_kernel:allow/1`\n\n Own Id: OTP-13299\n\n- EPMD supports both IPv4 and IPv6\n\n Also affects oldest supported windows version.\n\n Own Id: OTP-13364","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 4.1.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-4-1-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Host name lookups though inet_res, the Erlang DNS resolver, are now done case\n insensitively according to RFC 4343. Patch by Holger Weiß.\n\n Own Id: OTP-12836\n\n- IPv6 distribution handler has been updated to share code with IPv4 so that all\n features are supported in IPv6 as well. A bug when using an IPv4 address as\n hostname has been fixed.\n\n Own Id: OTP-13040\n\n- Caching of host names in the internal DNS resolver inet_res has been made\n character case insensitive for host names according to RFC 4343.\n\n Own Id: OTP-13083\n\n- Cooked file mode buffering has been fixed so file:position/2 now works\n according to Posix on Posix systems i.e. when file:position/2 returns an error\n the file pointer is unaffected.\n\n The Windows system documentation, however, is unclear on this point so the\n documentation of file:position/2 still does not promise anything.\n\n Cooked file mode file:pread/2,3 and file:pwrite/2,3 have been corrected to\n honor character encoding like the combination of file:position/2 and\n file:read/2 or file:write/2 already does. This is probably not very useful\n since the character representation on the caller's side is latin1, period.\n\n Own Id: OTP-13155 Aux Id: PR#646","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Add \\{line_delim, byte()\\} option to inet:setopts/2 and decode_packet/3\n\n Own Id: OTP-12837","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 4.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-4-1"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- A mechanism for limiting the amount of text that the built-in error logger\n events will produce has been introduced. It is useful for limiting both the\n size of log files and the CPU time used to produce them.\n\n This mechanism is experimental in the sense that it may be changed if it turns\n out that it does not solve the problem it is supposed to solve. In that case,\n there may be backward incompatible improvements to this mechanism.\n\n See the documentation for the config parameter `error_logger_format_depth` in\n the Kernel application for information about how to turn on this feature.\n\n Own Id: OTP-12864","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 4.0 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-4-0"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fix error handling in `file:read_line/1` for Unicode contents.\n\n Own Id: OTP-12144\n\n- Introduce `os:getenv/2` which is similar to `os:getenv/1` but returns the\n passed default value if the required environment variable is undefined.\n\n Own Id: OTP-12342\n\n- It is now possible to paste text in JCL mode (using Ctrl-Y) that has been\n copied in the previous shell session. Also a bug that caused the JCL mode to\n crash when pasting text has been fixed.\n\n Own Id: OTP-12673\n\n- Ensure that each segment of an IPv6 address when parsed from a string has a\n maximum of 4 hex digits\n\n Own Id: OTP-12773","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- New BIF: `erlang:get_keys/0`, lists all keys associated with the process\n dictionary. Note: `erlang:get_keys/0` is auto-imported.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-12151 Aux Id: seq12521\n\n- The internal group to user_drv protocol has been changed to be synchronous in\n order to guarantee that output sent to a process implementing the user_drv\n protocol is printed before replying. This protocol is used by the\n standard_output device and the ssh application when acting as a client.\n\n This change changes the previous unlimited buffer when printing to standard_io\n and other devices that end up in user_drv to 1KB.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-12240\n\n- The `inflateInit/2` and `deflateInit/6` functions now accepts a WindowBits\n argument equal to 8 and -8.\n\n Own Id: OTP-12564\n\n- Map error logger warnings to warning messages by default.\n\n Own Id: OTP-12755\n\n- Map beam error logger warnings to warning messages by default. Previously\n these messages were mapped to the error channel by default.\n\n Own Id: OTP-12781\n\n- gen_tcp:shutdown/2 is now asynchronous\n\n This solves the following problems with the old implementation:\n\n It doesn't block when the TCP peer is idle or slow. This is the expected\n behaviour when shutdown() is called: the caller needs to be able to continue\n reading from the socket, not be prevented from doing so.\n\n It doesn't truncate the output. The current version of gen_tcp:shutdown/2 will\n truncate any outbound data in the driver queue after about 10 seconds if the\n TCP peer is idle of slow. Worse yet, it doesn't even inform anyone that the\n data has been truncated: 'ok' is returned to the caller; and a FIN rather than\n an RST is sent to the TCP peer.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-12797\n\n- There are many cases where user code needs to be able to distinguish between a\n socket that was closed normally and one that was aborted. Setting the option\n \\{show_econnreset, true\\} enables the user to receive ECONNRESET errors on\n both active and passive sockets.\n\n Own Id: OTP-12843","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 3.2.0.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-3-2-0-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- The 'raw' socket option could not be used multiple times in one call to any\n e.g gen_tcp function because only one of the occurrences were used. This bug\n has been fixed, and also a small bug concerning propagating error codes from\n within inet:setopts/2.\n\n Own Id: OTP-11482 Aux Id: seq12872","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 3.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-3-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- A bug causing an infinite loop in hostname resolving has been corrected. To\n trigger this bug you would have to enter an bogus search method from a\n configuration file e.g .inetrc.\n\n Bug pinpointed by Emil Holmström\n\n Own Id: OTP-12133\n\n- The standard_error process now handles the getopts I/O protocol request\n correctly and stores its encoding in the same way as standard_io.\n\n Also, io:put_chars(standard_error, \\[oops]) could previously crash the\n standard_error process. This is now corrected.\n\n Own Id: OTP-12424","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Configuration parameters for the Kernel application that allows setting socket\n options for the distribution sockets have been added. See the application\n Kernel documentation; parameters 'inet_dist_listen_options' and\n 'inet_dist_connect_options'.\n\n Own Id: OTP-12476 Aux Id: OTP-12476","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 3.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-3-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Make sure to install .hrl files when needed\n\n Own Id: OTP-12197\n\n- Removed the undocumented application environment variable 'raw_files' from the\n kernel application. This variable was checked (by call to\n application:get_env/2) each time a raw file was to be opened in the file\n module.\n\n Own Id: OTP-12276\n\n- A bug has been fixed when using the netns option to gen_udp, which\n accidentally only worked if it was the last option.\n\n Own Id: OTP-12314","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Updated documentation for inet buffer size options.\n\n Own Id: OTP-12296\n\n- Introduce new option 'raw' in file_info and link_info functions. This option\n allows the caller not to go through the file server for information about\n files guaranteed to be local.\n\n Own Id: OTP-12325","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 3.0.3 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-3-0-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Accept inet:ip_address() in net_adm:names/1\n\n Own Id: OTP-12154","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 3.0.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-3-0-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- OTP-11850 fixed filelib:wildcard/1 to work with broken symlinks. This\n correction, however, introduced problems since symlinks were no longer\n followed for functions like filelib:ensure_dir/1, filelib:is_dir/1,\n filelib:file_size/1, etc. This is now corrected.\n\n Own Id: OTP-12054 Aux Id: seq12660","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 3.0.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-3-0-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- If the Config given to application_controller:change_application_data included\n other config files, it was only expanded for already existing (loaded)\n applications. If an upgrade added a new application which had config data in\n an included config file, the new application did not get correct config data.\n\n This is now changed so config data will be expanded for all applications.\n\n Own Id: OTP-11864\n\n- It was allowed to re-load pre-loaded modules such as `erlang`, but that could\n cause strange and unwanted things to happen, such as call\n [`apply/3`](`apply/3`) to loop. Pre-loaded modules are now sticky by default.\n (Thanks to Loïc Hoguin for reporting this bug.)\n\n `code:add_path(\"/ending/in/slash/\")` removes the trailing slash, adding\n `/ending/in/slash` to the code path. However,\n `code:del_path(\"/ending/in/slash/\")` would fail to remove the path since it\n did not remove the trailing slash. This has been fixed.\n\n Own Id: OTP-11913\n\n- Fix erts_debug:size/1 to handle Map sizes\n\n Own Id: OTP-11923\n\n- The documentation for `file:file_info/1` has been removed. The function itself\n was removed a long time ago.\n\n Own Id: OTP-11982","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 3.0 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-3-0"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fixed a deadlock possibility in terminate application\n\n Own Id: OTP-11171\n\n- Fixed bug where sendfile would return the wrong error code for a remotely\n closed socket if the socket was in passive mode. (Thanks to Vincent Siliakus\n for reporting the bug.)\n\n Own Id: OTP-11614\n\n- The new option `persistent` is added to `application:set_env/4` and\n `application:unset_env/3`. An environment key set with the `persistent` option\n will not be overridden by the ones configured in the application resource file\n on load. This means persistent values will stick after the application is\n loaded and also on application reload. (Thanks to José Valim)\n\n Own Id: OTP-11708\n\n- The spec for file:set_cwd/1 is modified to also accept binaries as arguments.\n This has always been allowed in the code, but it was not reflected in the spec\n since binaries are mostly used for raw file names. Raw file names are names\n that are not encoded according to file:native_name_encoding(), and these are\n not allowed in file:set_cwd/1. The spec is now, however, more allowing in\n order to avoid unnecessary dialyzer warnings. Raw file names will still fail\n in runtime with reason 'no_translation'. (Thanks to José Valim)\n\n Own Id: OTP-11787","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- heart:set_cmd/1 is updated to allow unicode code points > 255 in the given\n heart command\n\n Own Id: OTP-10843\n\n- Dialyzer's `unmatched_return` warnings have been corrected.\n\n Own Id: OTP-10908\n\n- Make erlang:open_port/2 spawn and spawn_executable handle unicode.\n\n Own Id: OTP-11105\n\n- Erlang/OTP has been ported to the realtime operating system OSE. The port\n supports both smp and non-smp emulator. For details around the port and how to\n started see the User's Guide in the ose application.\n\n Note that not all parts of Erlang/OTP has been ported.\n\n Notable things that work are: non-smp and smp emulators, OSE signal\n interaction, crypto, asn1, run_erl/to_erl, tcp, epmd, distribution and most if\n not all non-os specific functionality of Erlang.\n\n Notable things that does not work are: udp/sctp, os_mon, erl_interface,\n binding of schedulers.\n\n Own Id: OTP-11334\n\n- Add the \\{active,N\\} socket option for TCP, UDP, and SCTP, where N is an\n integer in the range -32768..32767, to allow a caller to specify the number of\n data messages to be delivered to the controlling process. Once the socket's\n delivered message count either reaches 0 or is explicitly set to 0 with\n inet:setopts/2 or by including \\{active,0\\} as an option when the socket is\n created, the socket transitions to passive (\\{active, false\\}) mode and the\n socket's controlling process receives a message to inform it of the\n transition. TCP sockets receive \\{tcp_passive,Socket\\}, UDP sockets receive\n \\{udp_passive,Socket\\} and SCTP sockets receive \\{sctp_passive,Socket\\}.\n\n The socket's delivered message counter defaults to 0, but it can be set using\n \\{active,N\\} via any gen_tcp, gen_udp, or gen_sctp function that takes socket\n options as arguments, or via inet:setopts/2. New N values are added to the\n socket's current counter value, and negative numbers can be used to reduce the\n counter value. Specifying a number that would cause the socket's counter value\n to go above 32767 causes an einval error. If a negative number is specified\n such that the counter value would become negative, the socket's counter value\n is set to 0 and the socket transitions to passive mode. If the counter value\n is already 0 and inet:setopts(Socket, \\[\\{active,0\\}]) is specified, the\n counter value remains at 0 but the appropriate passive mode transition message\n is generated for the socket.\n\n Thanks to Steve Vinoski\n\n Own Id: OTP-11368\n\n- A call to either the [`garbage_collect/1`](`garbage_collect/1`) BIF or the\n [`check_process_code/2`](`check_process_code/2`) BIF may trigger garbage\n collection of another processes than the process calling the BIF. The previous\n implementations performed these kinds of garbage collections without\n considering the internal state of the process being garbage collected. In\n order to be able to more easily and more efficiently implement yielding native\n code, these types of garbage collections have been rewritten. A garbage\n collection like this is now triggered by an asynchronous request signal, the\n actual garbage collection is performed by the process being garbage collected\n itself, and finalized by a reply signal to the process issuing the request.\n Using this approach processes can disable garbage collection and yield without\n having to set up the heap in a state that can be garbage collected.\n\n The [`garbage_collect/2`](`erlang:garbage_collect/2`), and\n [`check_process_code/3`](`erlang:check_process_code/3`) BIFs have been\n introduced. Both taking an option list as last argument. Using these, one can\n issue asynchronous requests.\n\n `code:purge/1` and `code:soft_purge/1` have been rewritten to utilize\n asynchronous `check_process_code` requests in order to parallelize work.\n\n Characteristics impact: A call to the\n [`garbage_collect/1`](`garbage_collect/1`) BIF or the\n [`check_process_code/2`](`check_process_code/2`) BIF will normally take longer\n time to complete while the system as a whole won't be as much negatively\n effected by the operation as before. A call to `code:purge/1` and\n `code:soft_purge/1` may complete faster or slower depending on the state of\n the system while the system as a whole won't be as much negatively effected by\n the operation as before.\n\n Own Id: OTP-11388 Aux Id: OTP-11535, OTP-11648\n\n- Add sync option to file:open/2.\n\n The sync option adds the POSIX O_SYNC flag to the open system call on\n platforms that support the flag or its equivalent, e.g.,\n FILE_FLAG_WRITE_THROUGH on Windows. For platforms that don't support it,\n file:open/2 returns \\{error, enotsup\\} if the sync option is passed in. Thank\n to Steve Vinoski and Joseph Blomstedt\n\n Own Id: OTP-11498\n\n- The contract of `inet:ntoa/1` has been corrected.\n\n Thanks to Max Treskin.\n\n Own Id: OTP-11730","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.16.4.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-16-4-1"},{"type":"extras","title":"Known Bugs and Problems - Kernel Release Notes","doc":"- When using gen_tcp:connect and the `fd` option with `port` and/or `ip`, the\n `port` and `ip` options were ignored. This has been fixed so that if `port`\n and/or `ip` is specified together with `fd` a bind is requested for that `fd`.\n If `port` and/or `ip` is not specified bind will not be called.\n\n Own Id: OTP-12061","ref":"notes.html#known-bugs-and-problems"},{"type":"extras","title":"Kernel 2.16.4 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-16-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fix the typespec for the inet:ifget/2 and inet:ifget/3 return value. Thanks to\n Ali Sabil.\n\n Own Id: OTP-11377\n\n- Fix various typos in erts, kernel and ssh. Thanks to Martin Hässler.\n\n Own Id: OTP-11414\n\n- Fix rpc multicall sample code. Thanks to Edwin Fine.\n\n Own Id: OTP-11471\n\n- Under rare circumstances a process calling `inet:close/1`, `gen_tcp:close/1`,\n `gen_udp:close/1`, or `gen_sctp:close/1` could hang in the call indefinitely.\n\n Own Id: OTP-11491","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Add more SCTP errors as described in RFC 4960. Thanks to Artem Teslenko.\n\n Own Id: OTP-11379\n\n- Add new BIF os:unsetenv/1 which deletes an environment variable. Thanks to\n Martin Hässler.\n\n Own Id: OTP-11446","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.16.3 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-16-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fix indentation of User switch command help in Erlang shell. Thanks to Sylvain\n Benner.\n\n Own Id: OTP-11209","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- The previous undocumented function ntoa/1 has been added to inet docs and\n exported in the inet module.\n\n Own Id: OTP-10676 Aux Id: OTP-10314\n\n- Fix typo in abcast() function comment. Thanks to Johannes Weissl.\n\n Own Id: OTP-11219\n\n- Add application:ensure_all_started/1-2. Thanks to Fred Hebert.\n\n Own Id: OTP-11250\n\n- Make edlin understand a few important control keys. Thanks to Stefan\n Zegenhagen.\n\n Own Id: OTP-11251\n\n- Cleanup of hipe_unified_loader, eliminating uses of is_subtype/2 in specs,\n change module-local void functions to return 'ok' instead of [] and made sure\n there are no dialyzer warnings with --Wunmatched_returns. Thanks to Kostis\n Sagonas.\n\n Own Id: OTP-11301","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.16.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-16-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- A bug in prim_inet has been corrected. If the port owner was killed at a bad\n time while closing the socket port the port could become orphaned hence\n causing port and socket leaking. Reported by Fred Herbert, Dmitry Belyaev and\n others.\n\n Own Id: OTP-10497 Aux Id: OTP-10562\n\n- A few bugs regarding case sensitivity for hostname resolution while using e.g\n the internal lookup types 'file' and 'dns' has been corrected. When looking up\n hostnames ASCII letters a-z are to be regarded as the same as A-Z according to\n RFC 4343 \"Domain Name System (DNS) Case Insensitivity Clarification\", and this\n was not always the case.\n\n Own Id: OTP-10689 Aux Id: seq12227","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Add `application:ensure_started/1,2`. It is equivavlent to\n `application:start/1,2` except it returns `ok` for already started\n applications.\n\n Own Id: OTP-10910\n\n- Optimize communication with file io server. Thanks to Anthony Ramine.\n\n Own Id: OTP-11040\n\n- Erlang source files with non-ASCII characters are now encoded in UTF-8\n (instead of latin1).\n\n Own Id: OTP-11041 Aux Id: OTP-10907\n\n- Optimization of simultaneous `inet_db` operations on the same socket by using\n a lock free implementation.\n\n Impact on the characteristics of the system: Improved performance.\n\n Own Id: OTP-11074\n\n- The `high_msgq_watermark` and `low_msgq_watermark` `inet` socket options\n introduced in OTP-R16A could only be set on TCP sockets. These options are now\n generic and can be set on all types of sockets.\n\n Own Id: OTP-11075 Aux Id: OTP-10336\n\n- Fix deep list argument error under Windows in os:cmd/1. Thanks to Aleksandr\n Vinokurov .\n\n Own Id: OTP-11104","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.16.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-16-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- A bug that could cause a crash with wrong reason has been corrected in the\n `application_controller` module.\n\n Own Id: OTP-10754\n\n- Fix `code:is_module_native/1` that sometimes in R16A returned false for hipe\n compiled modules containing BIFs such as `lists`.\n\n Own Id: OTP-10870\n\n- Respect `{exit_on_close,false}` option on tcp socket in non-passive mode when\n receiving fails (due to an ill-formed packet for example) by only doing a half\n close and still allow sending on the socket. (Thanks to Anthony Molinaro and\n Steve Vinoski for reporting the problem)\n\n Own Id: OTP-10879","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Slightly nicer error message when node start fails due to duplicate name.\n Thanks to Magnus Henoch.\n\n Own Id: OTP-10797\n\n- Miscellaneous updates due to Unicode support.\n\n Own Id: OTP-10820\n\n- Add a new function code:get_mode() can be used to detect how the code servers\n behaves. Thanks to Vlad Dumitrescu\n\n Own Id: OTP-10823\n\n- Fix type of error Reason on gen_tcp:send/2. Thanks to Sean Cribbs.\n\n Own Id: OTP-10839\n\n- `file:list_dir_all/1` and `file:read_link_all/1` that can handle raw file\n names have been added. See the User Guide for STDLIB for information about raw\n file names.\n\n Own Id: OTP-10852","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.16 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-16"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- It is no longer possible to have `{Mod,Vsn}` in the 'modules' list in a .app\n file.\n\n This was earlier possible, although never documented in the .app file\n reference manual. It was however visible in the documentation of\n `application:load/[1,2]`, where the same term as in a .app file can be used as\n the first argument.\n\n The possibility has been removed since the `Vsn` part was never used.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-10417\n\n- The contract of `erl_ddll:format_error/1` has been corrected. (Thanks to\n Joseph Wayne Norton.)\n\n Own Id: OTP-10473\n\n- Change printout of application crash message on startup to formatted strings\n (Thanks to Serge Aleynikov)\n\n Own Id: OTP-10620\n\n- The type `ascii_string()` in the `base64` module has been corrected. The type\n [`file:file_info()`](`t:file:file_info/0`) has been cleaned up. The type\n [`file:fd()`](`t:file:fd/0`) has been made opaque in the documentation.\n\n Own Id: OTP-10624 Aux Id: kunagi-352 \\[263]","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Inet exported functionality\n\n inet:parse_ipv4_address/1, inet:parse_ipv4strict_address/1,\n inet:parse_ipv6_address/1, inet:parse_ipv6strict_address/1,\n inet:parse_address/1 and inet:parse_strict_address is now exported from the\n inet module.\n\n Own Id: OTP-8067 Aux Id: kunagi-274 \\[185]\n\n- A boolean socket option 'ipv6_v6only' for IPv6 sockets has been added. The\n default value of the option is OS dependent, so applications aiming to be\n portable should consider using `{ipv6_v6only,true}` when creating an `inet6`\n listening/destination socket, and if necessary also create an `inet` socket on\n the same port for IPv4 traffic. See the documentation.\n\n Own Id: OTP-8928 Aux Id: kunagi-193 \\[104]\n\n- Support for Unicode has been implemented.\n\n Own Id: OTP-10302\n\n- The documentation for `global:register_name/3` has been updated to mention\n that the use of `{Module,Function}` as the method argument (resolve function)\n is deprecated.\n\n Own Id: OTP-10419\n\n- Fixed bug where sendfile on oracle solaris would return an error when a\n partial send was done.\n\n Own Id: OTP-10549\n\n- The `error_handler` module will now call `'$handle_undefined_function'/2` if\n an attempt is made to call a non-existing function in a module that exists.\n See the documentation for `error_handler` module for details.\n\n Own Id: OTP-10617 Aux Id: kunagi-340 \\[251]\n\n- Where necessary a comment stating encoding has been added to Erlang files. The\n comment is meant to be removed in Erlang/OTP R17B when UTF-8 becomes the\n default encoding.\n\n Own Id: OTP-10630\n\n- Do not return wrong terms unnecessarily. (Thanks to Kostis Sagonas.)\n\n Own Id: OTP-10662\n\n- Some examples overflowing the width of PDF pages have been corrected.\n\n Own Id: OTP-10665\n\n- Add file:allocate/3 operation\n\n This operation allows pre-allocation of space for files. It succeeds only on\n systems that support such operation. (Thanks to Filipe David Manana)\n\n Own Id: OTP-10680\n\n- Add application:get_key/3. The new function provides a default value for a\n configuration parameter. Thanks to Serge Aleynikov.\n\n Own Id: OTP-10694\n\n- Add search to Erlang shell's history. Thanks to Fred Herbert.\n\n Own Id: OTP-10739","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.15.3 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-15-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Ensure 'erl_crash.dump' when asked for it. This will change erl_crash.dump\n behaviour.\n\n \\* Not setting ERL_CRASH_DUMP_SECONDS will now terminate beam immediately on a\n crash without writing a crash dump file.\n\n \\* Setting ERL_CRASH_DUMP_SECONDS to 0 will also terminate beam immediately on\n a crash without writing a crash dump file, i.e. same as not setting\n ERL_CRASH_DUMP_SECONDS environment variable.\n\n \\* Setting ERL_CRASH_DUMP_SECONDS to a negative value will let the beam wait\n indefinitely on the crash dump file being written.\n\n \\* Setting ERL_CRASH_DUMP_SECONDS to a positive value will let the beam wait\n that many seconds on the crash dump file being written.\n\n A positive value will set an alarm/timeout for restart both in beam and in\n heart if heart is running.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-10422 Aux Id: kunagi-250 \\[161]","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 2.15.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-15-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fixed issue where using controlling_process/2 with self() as the second\n argument caused the port to leak if self() crashes. (Thanks to Ricardo\n Catalinas Jiménez)\n\n Own Id: OTP-10094\n\n- When sending large files using the file:sendfile fallback file:sendfile would\n crash. This is now fixed.\n\n Own Id: OTP-10098\n\n- Fix rpc:call/5 for local calls with a finite Timeout (Thanks to Tomer\n Chachamu)\n\n Own Id: OTP-10149\n\n- fix escript/primary archive reloading\n\n If the mtime of an escript/primary archive file changes after being added to\n the code path, correctly reload the archive and update the cache. (Thanks to\n Tuncer Ayaz)\n\n Own Id: OTP-10151\n\n- Support added for home directories named with non-ASCII characters (codepoints\n above 127) on a system running in Unicode file mode (e.g. on MacOSX or Linux\n with startup arguments +fnu or +fna with the right LOCALE). Also environment\n variables with Unicode content are supported in applicable environments.\n\n Own Id: OTP-10160\n\n- Allow mixed IPv4 and IPv6 addresses to sctp_bindx\n\n Also allow mixed address families to bind, since the first address on a\n multihomed sctp socket must be bound with bind, while the rest are to be bound\n using sctp_bindx. At least Linux supports adding address of mixing families.\n Make inet_set_faddress function available also when HAVE_SCTP is not defined,\n since we use it to find an address for bind to be able to mix ipv4 and ipv6\n addresses. Thanks to Tomas Abrahamsson\n\n Own Id: OTP-10217","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Document inet options: high_watermark, priority, linger and a some other\n options that previously was undocumented.\n\n Own Id: OTP-10053\n\n- Remove bit8 option support from inet\n\n Own Id: OTP-10056\n\n- The type of the disk log header has been corrected. (Thanks to Niclas Eklund.)\n\n Own Id: OTP-10131","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.15.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-15-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Driver output has been corrected so output of large binaries (> 4 GiB) now\n does not silently fail or crash the emulator, but either outputs the binary or\n fails the call. This means that writing a binary > 4 Gib to file now works but\n on e.g 64-bit Windows (that has scatter/gather I/O buffer segment lengths of\n 32 bits) fails. The behaviour may change in the future to always write the\n binary, in parts if necessary.\n\n Own Id: OTP-9820 Aux Id: OTP-9795\n\n- erts: minor fix for unnecessary condition erts: change SENDFILE_CHUNK_SIZE\n from signed to unsigned (Thanks to jovi zhang)\n\n Own Id: OTP-9872\n\n- Two contracts in `gen_sctp` have been corrected.\n\n Own Id: OTP-9874\n\n- If a process calls a module with an running on_load handler, the process is\n supposed to be suspended. But if the module with the on_load handler was\n loading used `code:load_binary/3`, the call would instead fail with an `undef`\n exception.\n\n Own Id: OTP-9875\n\n- File name and error reason is now returned if creation of a cookie fails.\n (Thanks to Magnus Henoch)\n\n Own Id: OTP-9954\n\n- Fix port leak in `zlib` when passing invalid data to\n `compress,uncompress,zip,unzip,gzip,gunzip`.\n\n Own Id: OTP-9981\n\n- Various typographical errors corrected in documentation for the global,\n error_logger, etop, lists, ets and supervisor modules and in the c_portdriver\n and kernel_app documentation. (Thanks to Ricardo Catalinas Jiménez)\n\n Own Id: OTP-9987\n\n- Fix returned error from gen_tcp:accept/1,2 when running out of ports.\n\n The \\{error, enfile\\} return value is badly misleading and confusing for this\n case, since the Posix ENFILE errno value has a well-defined meaning that has\n nothing to do with Erlang ports. The fix changes the return value to \\{error,\n system_limit\\}, which is consistent with e.g. various file(3) functions.\n inet:format_error/1 has also been updated to support system_limit in the same\n manner as file:format_error/1. (Thanks to Per Hedeland)\n\n Own Id: OTP-9990\n\n- `erts_debug:size/1` has been corrected to take sharing in the environment of\n funs into account. For funs it used to always give the same result as\n `erts_debug:flat_size/1`.\n\n Own Id: OTP-9991\n\n- In some cases when the process doing file:sendfile crashes while sending the\n file the efile_drv code would not clean up after itself correctly. This has\n now been fixed.\n\n Own Id: OTP-9993\n\n- On BSD based platforms file:sendfile would sometime go into an infinite loop\n when sending big files. This has now been fixed.\n\n Own Id: OTP-9994\n\n- While `disk_log` eagerly collects logged terms for better performance,\n collecting too much data may choke the system and cause huge binaries to be\n written.\n\n The problem was addressed in OTP-9764, but the situation was not improved in\n all cases.\n\n (Thanks to Richard Carlsson.)\n\n Own Id: OTP-9999 Aux Id: OTP-9764\n\n- The documentation of .app files incorrectly said that the default value for\n the `mod` parameter is `undefined`. This is now corrected to `[]`.\n\n Own Id: OTP-10002","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 2.15 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-15"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Calls to `global:whereis_name/1` have been substituted for calls to\n `global:safe_whereis_name/1` since the latter is not safe at all.\n\n The reason for not doing this earlier is that setting a global lock masked out\n a bug concerning the restart of supervised children. The bug has now been\n fixed by a modification of `global:whereis_name/1`. (Thanks to Ulf Wiger for\n code contribution.)\n\n A minor race conditions in `gen_fsm:start*` has been fixed: if one of these\n functions returned `{error, Reason}` or ignore, the name could still be\n registered (either locally or in `global`. (This is the same modification as\n was done for gen_server in OTP-7669.)\n\n The undocumented function `global:safe_whereis_name/1` has been removed.\n\n Own Id: OTP-9212 Aux Id: seq7117, OTP-4174\n\n- Honor option `packet_size` for http packet parsing by both TCP socket and\n `erlang:decode_packet`. This gives the ability to accept HTTP headers larger\n than the default setting, but also avoid DoS attacks by accepting lines only\n up to whatever length you wish to allow. For consistency, packet type `line`\n also honor option `packet_size`. (Thanks to Steve Vinoski)\n\n Own Id: OTP-9389\n\n- `disk_log:reopen/2,3` and `disk_log:breopen/3` could return the error reason\n from `file:rename/2` rather than the reason `{file_error, Filename, Reason}`.\n This bug has been fixed.\n\n The message `{disk_log, Node, {error, disk_log_stopped}}` which according the\n documentation is sent upon failure to truncate or reopen a disk log was\n sometimes turned into a reply. This bug has been fixed.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-9508\n\n- Environment variable 'shutdown_timeout' is added to kernel application.\n Earlier, application_controller would hang forever if an application top\n supervisor did not terminate upon a shutdown request. If this new environment\n variable is set to a positive integer T, then application controller will now\n give up after T milliseconds and instead brutally kill the application. For\n backwards compatibility, the default value for shutdown_timeout is 'infinity'.\n\n Own Id: OTP-9540\n\n- Add '-callback' attributes in stdlib's behaviours\n\n Replace the behaviour_info(callbacks) export in stdlib's behaviours with\n -callback' attributes for all the callbacks. Update the documentation with\n information on the callback attribute Automatically generate 'behaviour_info'\n function from '-callback' attributes\n\n 'behaviour_info(callbacks)' is a special function that is defined in a module\n which describes a behaviour and returns a list of its callbacks.\n\n This function is now automatically generated using the '-callback' specs. An\n error is returned by lint if user defines both '-callback' attributes and the\n behaviour_info/1 function. If no type info is needed for a callback use a\n generic spec for it. Add '-callback' attribute to language syntax\n\n Behaviours may define specs for their callbacks using the familiar spec\n syntax, replacing the '-spec' keyword with '-callback'. Simple lint checks are\n performed to ensure that no callbacks are defined twice and all types referred\n are declared.\n\n These attributes can be then used by tools to provide documentation to the\n behaviour or find discrepancies in the callback definitions in the callback\n module.\n\n Add callback specs into 'application' module in kernel Add callback specs to\n tftp module following internet documentation Add callback specs to\n inets_service module following possibly deprecated comments\n\n Own Id: OTP-9621\n\n- make tab completion work in remote shells (Thanks to Mats Cronqvist)\n\n Own Id: OTP-9673\n\n- Add missing parenthesis in heart doc.\n\n Add missing spaces in the Reference Manual distributed section.\n\n In the HTML version of the doc those spaces are necessary to separate those\n words.\n\n Own Id: OTP-9693\n\n- Fixes net_kernel:get_net_ticktime() doc\n\n Adds missing description when \\`ignored' is returned. (Thanks to Ricardo\n Catalinas Jiménez )\n\n Own Id: OTP-9713\n\n- While `disk_log` eagerly collects logged terms for better performance,\n collecting too much data may choke the system and cause huge binaries to be\n written. In order to remedy the situation a (small) limit on the amount of\n data that is collected before writing to disk has been introduced.\n\n Own Id: OTP-9764\n\n- - Correct callback spec in application module\n - Refine warning about callback specs with extra ranges\n - Cleanup autoimport compiler directives\n - Fix Dialyzer's warnings in typer\n - Fix Dialyzer's warning for its own code\n - Fix bug in Dialyzer's behaviours analysis\n - Fix crash in Dialyzer\n - Variable substitution was not generalizing any unknown variables.\n\n Own Id: OTP-9776\n\n- Fix a crash when file:change_time/2,3 are called with invalid dates\n\n Calling file:change_time/2,3 with an invalid date tuple (e.g\n file:change_time(\"file.txt\", \\{undefined, undefined\\})) will cause\n file_server_2 to crash. error_logger will shutdown and the whole VM will stop.\n Change behavior to validate given dates on system boundaries. (i.e before\n issuing a server call).(Thanks to Ahmed Omar)\n\n Own Id: OTP-9785","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- An option list argument can now be passed to\n `file:read_file_info/2, file:read_link_info/2` and `file:write_file_info/3`\n and set time type information in the call. Valid options are\n `{time, local}, {time, universal}` and `{time, posix}`. In the case of `posix`\n time no conversions are made which makes the operation a bit faster.\n\n Own Id: OTP-7687\n\n- `file:list_dir/1,2` will now fill an buffer entire with filenames from the\n efile driver before sending it to an erlang process. This will speed up this\n file operation in most cases.\n\n Own Id: OTP-9023\n\n- gen_sctp:open/0-2 may now return \\{error,eprotonosupport\\} if SCTP is not\n supported\n\n gen_sctp:peeloff/1 has been implemented and creates a one-to-one socket which\n also are supported now\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-9239\n\n- Sendfile has been added to the file module's API. sendfile/2 is used to read\n data from a file and send it to a tcp socket using a zero copying mechanism if\n available on that OS.\n\n Thanks to Tuncer Ayaz and Steve Vinovski for original implementation\n\n Own Id: OTP-9240\n\n- Tuple funs (a two-element tuple with a module name and a function) are now\n officially deprecated and will be removed in R16. Use '`fun M:F/A`' instead.\n To make you aware that your system uses tuple funs, the very first time a\n tuple fun is applied, a warning will be sent to the error logger.\n\n Own Id: OTP-9649","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.14.5 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-14-5"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fix type of Packet arg of gen_tcp:send/2 and gen_udp:send/4\n\n The type is marked as a binary() or a string() but in practice it can be an\n iodata(). The test suite was updated to confirm the gen_tcp/2 and\n gen_udp:send/4 functions accept iodata() (iolists) packets. (Thanks to Filipe\n David Manana)\n\n Own Id: OTP-9514\n\n- XML files have been corrected.\n\n Own Id: OTP-9550 Aux Id: OTP-9541","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- The types and specifications of the inet modules have been improved.\n\n Own Id: OTP-9260\n\n- Types and specifications have been added.\n\n Own Id: OTP-9356\n\n- Contracts in STDLIB and Kernel have been improved and type errors have been\n corrected.\n\n Own Id: OTP-9485\n\n- Update documentation and specifications of some of the zlib functions.\n\n Own Id: OTP-9506","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.14.4 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-14-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- The send_timeout option in gen_tcp did not work properly in active mode or\n with \\{active,once\\} options. This is now corrected.\n\n Own Id: OTP-9145\n\n- Fixed various typos across the documentation (Thanks to Tuncer Ayaz)\n\n Own Id: OTP-9154\n\n- Fix typo in doc of rpc:pmap/3 (Thanks to Ricardo Catalinas Jiménez)\n\n Own Id: OTP-9168\n\n- A bug in inet_res, the specialized DNS resolver, has been corrected. A late\n answer with unfortunate timing could cause a runtime exception. Some code\n cleanup and improvements also tagged along. Thanks to Evegeniy Khramtsov for a\n pinpointing bug report and bug fix testing.\n\n Own Id: OTP-9221 Aux Id: OTP-8712","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Types and specifications have been added.\n\n Own Id: OTP-9268\n\n- Erlang types and specifications are used for documentation.\n\n Own Id: OTP-9272\n\n- Two opaque types that could cause warnings when running Dialyzer have been\n modified.\n\n Own Id: OTP-9337","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.14.3 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-14-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- `os:find_executable/{1,2}` will no longer return the path of a directory that\n happens to be in the PATH.\n\n Own Id: OTP-8983 Aux Id: seq11749\n\n- Fix -spec for file:write_file/3\n\n Change type for second parameter from binary() to iodata(), since the function\n explicitly takes steps to accept lists as well as binaries. (thanks to Magnus\n Henoch).\n\n Own Id: OTP-9067\n\n- Sanitize the specs of the code module\n\n After the addition of unicode_binary() to the file:filename() type, dialyzer\n started complaining about erroneous or incomplete specs in some functions of\n the 'code' module. The culprit was hard-coded information in erl_bif_types for\n functions of this module, which were not updated. Since these functions have\n proper specs these days and code duplication (pun intended) is never a good\n idea, their type information was removed from erl_bif_types.\n\n While doing this, some erroneous comments were fixed in the code module and\n also made sure that the code now runs without dialyzer warnings even when the\n -Wunmatched_returns option is used.\n\n Some cleanups were applied to erl_bif_types too.\n\n Own Id: OTP-9100\n\n- \\- Add spec for function that does not return - Strengthen spec - Introduce\n types to avoid duplication in specs - Add specs for functions that do not\n return - Add specs for behaviour callbacks - Simplify two specs\n\n Own Id: OTP-9127","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 2.14.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-14-2"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- The Erlang VM now supports Unicode filenames. The feature is turned on by\n default on systems where Unicode filenames are mandatory (Windows and MacOSX),\n but can be enabled on other systems with the '+fnu' emulator option. Enabling\n the Unicode filename feature on systems where it is not default is however\n considered experimental and not to be used for production. Together with the\n Unicode file name support, the concept of \"raw filenames\" is introduced, which\n means filenames provided without implicit unicode encoding translation. Raw\n filenames are provided as binaries, not lists. For further information, see\n stdlib users guide and the chapter about using Unicode in Erlang. Also see the\n file module manual page.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8887\n\n- There is now a new function inet:getifaddrs/0 modeled after C library function\n getifaddrs() on BSD and LInux that reports existing interfaces and their\n addresses on the host. This replaces the undocumented and unsupported\n inet:getiflist/0 and inet:ifget/2.\n\n Own Id: OTP-8926","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.14.1.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-14-1-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- In embedded mode, on_load handlers that called `code:priv_dir/1` or other\n functions in `code` would hang the system. Since the `crypto` application now\n contains an on_loader handler that calls `code:priv_dir/1`, including the\n `crypto` application in the boot file would prevent the system from starting.\n\n Also extended the `-init_debug` option to print information about on_load\n handlers being run to facilitate debugging.\n\n Own Id: OTP-8902 Aux Id: seq11703","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 2.14.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-14-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fixed: inet:setopts(S, \\[\\{linger,\\{true,2\\}\\}]) returned \\{error,einval\\} for\n SCTP sockets. The inet_drv had a bug when checking the option size.\n\n Own Id: OTP-8726 Aux Id: seq11617\n\n- gen_udp:connect/3 was broken for SCTP enabled builds. It did not detect remote\n end errors as it should.\n\n Own Id: OTP-8729\n\n- reference() has been substituted for ref() in the documentation.\n\n Own Id: OTP-8733\n\n- A bug introduced in kernel-2.13.5.3 has been fixed. If running\n `net_kernel:set_net_ticktime/1` twice within the `TransitionPerod` the second\n call caused the net_kernel process to crash with a `badmatch`.\n\n Own Id: OTP-8787 Aux Id: seq11657, OTP-8643\n\n- inet:getsockopt for SCTP sctp_default_send_param had a bug to not initialize\n required feilds causing random answers. It is now corrected.\n\n Own Id: OTP-8795 Aux Id: seq11655\n\n- For a socket in the HTTP packet mode, the return value from `gen_tcp:recv/2,3`\n if there is an error in the header will be `{ok,{http_error,String}}` instead\n of `{error,{http_error,String}}` to be consistent with `ssl:recv/2,3`.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8831","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Even when configuring erlang with --enable-native-libs, the native code for\n modules loaded very early (such as lists) would not get loaded. This has been\n corrected. (Thanks to Paul Guyot.)\n\n Own Id: OTP-8750\n\n- The undocumented function inet:ifget/2 has been improved to return interface\n hardware address (MAC) on platforms supporting getaddrinfo() (such as BSD\n unixes). Note it still does not work on all platforms for example not Windows\n nor Solaris, so the function is still undocumented.\n\n Buffer overflow and field init bugs for inet:ifget/2 and inet:getservbyname/2\n has also been fixed.\n\n Thanks to Michael Santos.\n\n Own Id: OTP-8816\n\n- As a usability improvement the 'inet6' option to functions gen_tcp:listen/2,\n gen_tcp:connect/3-4, gen_udp:open/2 and gen_sctp:open/1-2 is now implicit if\n the address argument or the 'ip' option contain an IPv6 address (8-tuple).\n\n Own Id: OTP-8822","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.14 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-14"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- os:find_executable can now be fed with the complete name of the executable on\n Windows and still find it. I.e os:find_executable(\"werl.exe\") will work as\n os:find_executable(\"werl\").\n\n Own Id: OTP-3626\n\n- The shell's line editing has been improved to more resemble the behaviour of\n readline and other shells. (Thanks to Dave Peticolas)\n\n Own Id: OTP-8635\n\n- Under certain circumstances the net kernel could hang. (Thanks to Scott Lystig\n Fritchie.)\n\n Own Id: OTP-8643 Aux Id: seq11584\n\n- The kernel DNS resolver was leaking one or two ports if the DNS reply could\n not be parsed or if the resolver(s) caused noconnection type errors. Bug now\n fixed. A DNS specification borderline truncated reply triggering the port\n leakage bug has also been fixed.\n\n Own Id: OTP-8652","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- As of this version, the global name server no longer supports nodes running\n Erlang/OTP R11B.\n\n Own Id: OTP-8527\n\n- The file module's functions write,read and read_line now handles named\n io_servers like 'standard_io' and 'standard_error' correctly.\n\n Own Id: OTP-8611\n\n- The functions file:advise/4 and file:datasync/1 have been added. (Thanks to\n Filipe David Manana.)\n\n Own Id: OTP-8637\n\n- When exchanging groups between nodes `pg2` did not remove duplicated members.\n This bug was introduced in R13B03 (kernel-2.13.4).\n\n Own Id: OTP-8653\n\n- There is a new option 'exclusive' to file:open/2 that uses the OS O_EXCL flag\n where supported to open the file in exclusive mode.\n\n Own Id: OTP-8670","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.13.5.3 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-13-5-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- A bug introduced in Kernel 2.13.5.2 has been fixed.\n\n Own Id: OTP-8686 Aux Id: OTP-8643","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 2.13.5.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-13-5-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Under certain circumstances the net kernel could hang. (Thanks to Scott Lystig\n Fritchie.)\n\n Own Id: OTP-8643 Aux Id: seq11584","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 2.13.5.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-13-5-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- A race condition in `os:cmd/1` could cause the caller to get stuck in\n `os:cmd/1` forever.\n\n Own Id: OTP-8502","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 2.13.5 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-13-5"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- A race bug affecting `pg2:get_local_members/1` has been fixed. The bug was\n introduced in R13B03.\n\n Own Id: OTP-8358\n\n- The loading of native code was not properly atomic in the SMP emulator, which\n could cause crashes. Also a per-MFA information table for the native code has\n now been protected with a lock since it turns that it could be accessed\n concurrently in the SMP emulator. (Thanks to Mikael Pettersson.)\n\n Own Id: OTP-8397\n\n- user.erl (used in oldshell) is updated to handle unicode in prompt strings\n (io:get_line/\\{1,2\\}). io_lib is also updated to format prompts with the 't'\n modifier (i.e. ~ts instead of ~s).\n\n Own Id: OTP-8418 Aux Id: OTP-8393\n\n- The resolver routines failed to look up the own node name as hostname, if the\n OS native resolver was erroneously configured, bug reported by Yogish Baliga,\n now fixed.\n\n The resolver routines now tries to parse the hostname as an IP string as most\n OS resolvers do, unless the native resolver is used.\n\n The DNS resolver inet_res and file resolver inet_hosts now do not read OS\n configuration files until they are needed. Since the native resolver is\n default, in most cases they are never needed.\n\n The DNS resolver's automatic updating of OS configuration file data\n (/etc/resolv.conf) now uses the 'domain' keyword as default search domain if\n there is no 'search' keyword.\n\n Own Id: OTP-8426 Aux Id: OTP-8381","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- The expected return value for an on_load function has been changed. (See the\n section about code loading in the Reference manual.)\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8339\n\n- Explicit top directories in archive files are now optional.\n\n For example, if an archive (app-vsn.ez) just contains an app-vsn/ebin/mod.beam\n file, the file info for the app-vsn and app-vsn/ebin directories are faked\n using the file info from the archive file as origin. The virtual directories\n can also be listed. For short, the top directories are virtual if they does\n not exist.\n\n Own Id: OTP-8387\n\n- `code:clash/0` now looks inside archives (.ez files). (Thanks to Tuncer Ayaz.)\n\n Own Id: OTP-8413\n\n- There are new `gen_sctp:connect_init/*` functions that initiate an SCTP\n connection without blocking for the result. The result is delivered\n asynchronously as an sctp_assoc_change event. (Thanks to Simon Cornish.)\n\n Own Id: OTP-8414","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.13.4 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-13-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- A link in `m:pg2` has been fixed. (Thanks to Christophe Romain.)\n\n Own Id: OTP-8198\n\n- A ticker process could potentially be blocked indefinitely trying to send a\n tick to a node not responding. If this happened, the connection would not be\n brought down as it should.\n\n Own Id: OTP-8218\n\n- A bug in `pg2` when members who died did not leave process groups has been\n fixed. (Thanks to Matthew Dempsky.)\n\n Own Id: OTP-8259","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- The documentation is now built with open source tools (xsltproc and fop) that\n exists on most platforms. One visible change is that the frames are removed.\n\n Own Id: OTP-8201\n\n- The top directory in archive files does not need to have a `-vsn` suffix\n anymore. For example if the archive file has the name like `mnesia-4.4.7.ez`\n the top directory in the archive can either be named `mnesia` or\n `mnesia-4.4.7`. If the archive file has a name like `mnesia.ez` the top\n directory in the archive must be named `mnesia` as earlier.\n\n Own Id: OTP-8266\n\n- The -on_load() directive can be used to run a function when a module is\n loaded. It is documented in the section about code loading in the Reference\n Manual.\n\n Own Id: OTP-8295","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.13.3 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-13-3"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- The DNS resolver client inet_res has been rewritten, documented and released.\n See inet_res(3) and Erts User's Guide: Inet configuration.\n\n It can formally not be incompatible with respect to earlier versions since\n there was no earlier official version. However it was used before and some\n details have changed.\n\n Configuration now initializes from /etc/resolv.conf and /etc/hosts on all unix\n platforms regardless of which distribution mode the node is started in. The\n directory (/etc) these files are supposed to reside in can be changed via an\n environment variable. These configuration file locations can also be changed\n in the inet configuration. The files are monitored for change and re-read,\n which makes a few resolver configuration variables out of application control.\n The /etc/hosts entries have now their own cache table that is shadowed (with\n lookup method 'file' is used) by the application configured host entries. This\n problem (that inet_res configuration only worked for distribution mode long\n names) was among other reported by Matthew O'Gorman many moons ago.\n\n The lookup methods are still 'native' only per default. Resolver configuration\n is done on all Unix platforms just to get a usable configuration for direct\n calls to inet_res.\n\n The functions `inet_res:nslookup/3..5` and `inet_res:nnslookup/4..4` are no\n longer recommended to use, instead use `inet_res:lookup/3..5` and\n `inet_res:resolve/3..5` which provide clearer argument types and the\n possibility to override options in the call.\n\n Users of previous unsupported versions of inet_res have included internal\n header files to get to the internal record definitions in order to examine DNS\n replies. This is still unsupported and there are access functions in inet_dns\n to use instead. These are documented in inet_res(3).\n\n Bug fix: a compression reference loop would make DNS message decoding loop\n forever. Problem reported by Florian Weimer.\n\n Bug fix and patch suggestion by Sergei Golovan: configuring IPv6 nameservers\n did not work. His patch (as he warned) created many UDP sockets; one per\n nameserver. This has been fixed in the released version.\n\n Improvement: `inet_res` is now EDNS0 capable. The current implementation is\n simple and does not probe and cache EDNS info for nameservers, which a fully\n capable implementation probably should do. EDNS has to be enabled via resolver\n configuration, and if a nameserver replies that it does not support EDNS,\n `inet_res` falls back to a regular DNS query.\n\n Improvement: now `inet_res` automatically falls back to TCP if it gets a\n truncated answer from a nameserver.\n\n Warning: some of the ancient and exotic record types handled by `inet_res` and\n `inet_dns` are not supported by current versions of BIND, so they could not be\n tested after the rewrite, with reasonable effort, e.g MD, MF, NULL, and SPF.\n The risk for bugs in these particular records is still low since their code is\n mostly shared with other tested record types.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-7955 Aux Id: OTP-7107 OTP-6852\n\n- A TCP socket with option `{packet,4}` could crash the emulator if it received\n a packet header with a very large size value (>2Gb). The same bug caused\n `erlang:decode_packet/3` to return faulty values. (Thanks to Georgos Seganos.)\n\n Own Id: OTP-8102\n\n- The file module has now a read_line/1 function similar to the io:get_line/2,\n but with byte oriented semantics. The function file:read_line/1 works for raw\n files as well, but for good performance it is recommended to use it together\n with the 'read_ahead' option for raw file access.\n\n Own Id: OTP-8108","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.13.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-13-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- A bug when doing io:get_line (among other calls) from a file opened with\n encoding other than latin1, causing false unicode errors to occur, is now\n corrected.\n\n Own Id: OTP-7974","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Added functionality to get higher resolution timestamp from system. The\n erlang:now function returns a timestamp that's not always consistent with the\n actual operating system time (due to resilience against large time changes in\n the operating system). The function os:timestamp/0 is added to get a similar\n timestamp as the one being returned by erlang:now, but untouched by Erlangs\n time correcting and smoothing algorithms. The timestamp returned by\n os:timestamp is always consistent with the operating systems view of time,\n like the calendar functions for getting wall clock time, but with higher\n resolution. Example of usage can be found in the os manual page.\n\n Own Id: OTP-7971","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.13.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-13-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Many concurrent calls to `os:cmd/1` will only block one scheduler thread at a\n time, making an smp emulator more responsive if the OS is slow forking\n processes.\n\n Own Id: OTP-7890 Aux Id: seq11219\n\n- Fixed hanging early RPC that did IO operation during node start.\n\n Own Id: OTP-7903 Aux Id: seq11224\n\n- The error behavior of gen_tcp and gen_udp has been corrected.\n gen_tcp:connect/3,4 and gen_udp:send/4 now returns \\{error,eafnosupport\\} for\n conflicting destination address versus socket address family. Other corner\n cases for IP address string host names combined with not using the native (OS)\n resolver (which is not default) has also been changed to return\n \\{error,nxdomain\\} instead of \\{error,einval\\}. Those changes just may\n surprise old existing code. gen_tcp:listen/2 and gen_udp:open/2 now fails for\n conflicting local address versus socket address family instead of trying to\n use an erroneous address. Problem reported by Per Hedeland.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-7929","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Several glitches and performance issues in the Unicode and I/O-system\n implementation of R13A have been corrected.\n\n Own Id: OTP-7896 Aux Id: OTP-7648 OTP-7887\n\n- The unsupported DNS resolver client inet_res has now been improved to handle\n NAPTR queries.\n\n Own Id: OTP-7925 Aux Id: seq11231","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.13 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-13"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- The old Erlang DNS resolver inet_res has been corrected to handle TXT records\n with more than one character string. Patch courtesy of Geoff Cant.\n\n Own Id: OTP-7588\n\n- When chunk reading a disk log opened in read_only mode, bad terms could crash\n the disk log process.\n\n Own Id: OTP-7641 Aux Id: seq11090\n\n- `gen_tcp:send()` did sometimes (only observed on Solaris) return\n `{error,enotconn}` instead of the expected `{error,closed}` as the peer socket\n had been explicitly closed.\n\n Own Id: OTP-7647\n\n- The gen_sctp option sctp_peer_addr_params,\n #sctp_paddrparams\\{address=\\{IP,Port\\} was erroneously decoded in the inet\n driver. This bug has now been corrected.\n\n Own Id: OTP-7755","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Erlang programs can now access STDERR on platforms where such a file\n descriptor is available by using the io_server 'standard_error', i.e.\n io:format(standard_error,\"~s~n\",\\[ErrorMessage]),\n\n Own Id: OTP-6688\n\n- The format of the string returned by `erlang:system_info(system_version)` (as\n well as the first message when Erlang is started) has changed. The string now\n contains the both the OTP version number as well as the erts version number.\n\n Own Id: OTP-7649\n\n- As of this version, the global name server no longer supports nodes running\n Erlang/OTP R10B.\n\n Own Id: OTP-7661\n\n- A `{nodedown, Node}` message passed by the `net_kernel:monitor_nodes/X`\n functionality is now guaranteed to be sent after `Node` has been removed from\n the result returned by `erlang:nodes/Y`.\n\n Own Id: OTP-7725\n\n- The deprecated functions `erlang:fault/1`, `erlang:fault/2`, and\n `file:rawopen/2` have been removed.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-7812\n\n- Nodes belonging to different independent clusters can now co-exist on the same\n host with the help of a new environment variable setting ERL_EPMD_PORT.\n\n Own Id: OTP-7826\n\n- The copyright notices have been updated.\n\n Own Id: OTP-7851","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.12.5.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-12-5-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- When chunk reading a disk log opened in read_only mode, bad terms could crash\n the disk log process.\n\n Own Id: OTP-7641 Aux Id: seq11090\n\n- Calling `gen_tcp:send()` from several processes on socket with option\n `send_timeout` could lead to much longer timeout than specified. The solution\n is a new socket option `{send_timeout_close,true}` that will do automatic\n close on timeout. Subsequent calls to send will then immediately fail due to\n the closed connection.\n\n Own Id: OTP-7731 Aux Id: seq11161","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 2.12.5 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-12-5"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- The documentation of `rpc:pmap/3` has been corrected. (Thanks to Kirill\n Zaborski.)\n\n Own Id: OTP-7537\n\n- The listen socket used for the distributed Erlang protocol now uses the socket\n option 'reuseaddr', which is useful when you force the listen port number\n using kernel options 'inet_dist_listen_min' and 'inet_dist_listen_max' and\n restarts a node with open connections.\n\n Own Id: OTP-7563\n\n- Fixed memory leak of unclosed TCP-ports. A gen_tcp:send() followed by a\n failing gen_tcp:recv() could in some cases cause the port to linger after\n being closed.\n\n Own Id: OTP-7615","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Processes spawned using `proc_lib` (including `gen_server` and other library\n modules that use `proc_lib`) no longer keep the entire argument list for the\n initial call, but only the arity.\n\n Also, if `proc_lib:spawn/1` is used to spawn a fun, the actual fun is not\n kept, but only module, function name, and arity of the function that\n implements the fun.\n\n The reason for the change is that keeping the initial fun (or a fun in an\n argument list), would prevent upgrading the code for the module. A secondary\n reason is that keeping the fun and function arguments could waste a\n significant amount of memory.\n\n The drawback with the change is that the crash reports will provide less\n precise information about the initial call (only `Module:Function/Arity`\n instead of `Module:Function(Arguments)`). The function\n `proc_lib:initial_call/1` still returns a list, but each argument has been\n replaced with a dummy atom.\n\n Own Id: OTP-7531 Aux Id: seq11036\n\n- `io:get_line/1` when reading from standard input is now substantially faster.\n There are also some minor performance improvements in `io:get_line/1` when\n reading from any file opened in binary mode. (Thanks to Fredrik Svahn.)\n\n Own Id: OTP-7542\n\n- There is now experimental support for loading of code from archive files. See\n the documentation of `code`, `init`, `erl_prim_loader `and `escript` for more\n info.\n\n The error handling of `escripts` has been improved.\n\n An `escript` may now set explicit arguments to the emulator, such as\n `-smp enabled`.\n\n An `escript` may now contain a precompiled beam file.\n\n An `escript` may now contain an archive file containing one or more\n applications (experimental).\n\n The internal module `code_aux` has been removed.\n\n Own Id: OTP-7548 Aux Id: otp-6622\n\n- `code:is_sticky/1` is now documented. (Thanks to Vlad Dumitrescu.)\n\n Own Id: OTP-7561\n\n- In the job control mode, the \"s\" and \"r\" commands now take an optional\n argument to specify which shell to start. (Thanks to Robert Virding.)\n\n Own Id: OTP-7617\n\n- `net_adm:world/0,1` could crash if called in an emulator that has not been\n started with either the `-sname` or `-name` option; now it will return an\n empty list. (Thanks to Edwin Fine.)\n\n Own Id: OTP-7618","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.12.4 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-12-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Large files are now handled on Windows, where the filesystem supports it.\n\n Own Id: OTP-7410","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- New BIF `erlang:decode_packet/3` that extracts a protocol packet from a\n binary. Similar to the socket option `{packet, Type}`. Also documented the\n socket packet type `http` and made it official. _NOTE_: The tuple format for\n `http` packets sent from an active socket has been changed in an incompatible\n way.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-7404\n\n- Setting the `{active,once}` for a socket (using inets:setopts/2) is now\n specially optimized (because the `{active,once}` option is typically used much\n more frequently than other options).\n\n Own Id: OTP-7520","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.12.3 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-12-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- SCTP_ADDR_CONFIRMED events are now handled by gen_sctp.\n\n Own Id: OTP-7276\n\n- When leaving a process group with `pg2:leave/2` the process was falsely\n assumed to be a member of the group. This bug has been fixed.\n\n Own Id: OTP-7277\n\n- In the Erlang shell, using up and down arrow keys, the wrong previous command\n could sometimes be retrieved.\n\n Own Id: OTP-7278\n\n- The documentation for `erlang:trace/3` has been corrected.\n\n Own Id: OTP-7279 Aux Id: seq10927\n\n- In the SMP emulator, there was small risk that `code:purge(Mod)` would kill a\n process that was running code in `Mod` and unload the module `Mod` before the\n process had terminated. `code:purge(Mod)` now waits for confirmation (using\n `erlang:monitor/2`) that the process has been killed before proceeding.\n\n Own Id: OTP-7282\n\n- `zlib:inflate` failed when the size of the inflated data was an exact multiple\n of the internal buffer size (4000 bytes by default).\n\n Own Id: OTP-7359","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Additional library directories can now be specified in the environment\n variable ERL_LIBS. See the manual page for the `code` module. (Thanks to Serge\n Aleynikov.)\n\n Own Id: OTP-6940\n\n- crypto and zlib drivers improved to allow concurrent smp access.\n\n Own Id: OTP-7262\n\n- There is a new function `init:stop/1` which can be used to shutdown the system\n cleanly AND generate a non-zero exit status or crash dump. (Thanks to Magnus\n Froberg.)\n\n Own Id: OTP-7308\n\n- The `hide` option for [`open_port/2`](`open_port/2`) is now documented.\n (Thanks to Richard Carlsson.)\n\n Own Id: OTP-7358","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.12.2.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-12-2-1"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- `os:cmd/1` on unix platforms now use `/bin/sh` as shell instead of looking for\n `sh` in the `PATH` environment.\n\n Own Id: OTP-7283","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.12.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-12-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- A bug caused by a race condition involving `disk_log` and `pg2` has been\n fixed.\n\n Own Id: OTP-7209 Aux Id: seq10890\n\n- The beta testing module `gen_sctp` now supports active mode as stated in the\n documentation. Active mode is still rather untested, and there are some issues\n about what should be the right semantics for `gen_sctp:connect/5`. In\n particular: should it be blocking or non-blocking or choosable. There is a\n high probability it will change semantics in a (near) future patch.\n\n Try it, give comments and send in bug reports\\!\n\n Own Id: OTP-7225","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- `erlang:system_info/1` now accepts the `logical_processors`, and\n `debug_compiled` arguments. For more info see the, `m:erlang` documentation.\n\n The scale factor returned by `test_server:timetrap_scale_factor/0` is now also\n effected if the emulator uses a larger amount of scheduler threads than the\n amount of logical processors on the system.\n\n Own Id: OTP-7175\n\n- Updated the documentation for `erlang:function_exported/3` and `io:format/2`\n functions to no longer state that those functions are kept mainly for\n backwards compatibility.\n\n Own Id: OTP-7186\n\n- A process executing the `processes/0` BIF can now be preempted by other\n processes during its execution. This in order to disturb the rest of the\n system as little as possible. The returned result is, of course, still a\n consistent snapshot of existing processes at a time during the call to\n `processes/0`.\n\n The documentation of the `processes/0` BIF and the\n [`is_process_alive/1`](`is_process_alive/1`) BIF have been updated in order to\n clarify the difference between an existing process and a process that is\n alive.\n\n Own Id: OTP-7213\n\n- [`tuple_size/1`](`tuple_size/1`) and [`byte_size/1`](`byte_size/1`) have been\n substituted for [`size/1`](`size/1`) in the documentation.\n\n Own Id: OTP-7244","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.12.1.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-12-1-2"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- The `{allocator_sizes, Alloc}` and `alloc_util_allocators` arguments are now\n accepted by `erlang:system_info/1`. For more information see the `m:erlang`\n documentation.\n\n Own Id: OTP-7167","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.12.1.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-12-1-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Fixed a problem in group that could cause the ssh server to lose answers or\n hang.\n\n Own Id: OTP-7185 Aux Id: seq10871","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 2.12.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-12-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- file:read/2 and file:consult_stream/1,3 did not use an empty prompt on I/O\n devices. This bug has now been corrected.\n\n Own Id: OTP-7013\n\n- The sctp driver has been updated to work against newer lksctp packages e.g\n 1.0.7 that uses the API spelling change adaption -> adaptation. Older lksctp\n (1.0.6) still work. The erlang API in gen_sctp.erl and inet_sctp.hrl now\n spells 'adaptation' regardless of the underlying C API.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-7120","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- The documentation has been updated so as to reflect the last updates of the\n Erlang shell as well as the minor modifications of the control sequence `p` of\n the `io_lib` module.\n\n Superfluous empty lines have been removed from code examples and from Erlang\n shell examples.\n\n Own Id: OTP-6944 Aux Id: OTP-6554, OTP-6911\n\n- [`tuple_size/1`](`tuple_size/1`) and [`byte_size/1`](`byte_size/1`) have been\n substituted for [`size/1`](`size/1`).\n\n Own Id: OTP-7009","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.12 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-12"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- A bug for raw files when reading 0 bytes returning 'eof' instead of empty data\n has been corrected.\n\n Own Id: OTP-6291 Aux Id: OTP-6967\n\n- A bug in gen_udp:fdopen reported by David Baird and also found by Dialyzer has\n been fixed.\n\n Own Id: OTP-6836 Aux Id: OTP-6594\n\n- Calling `error_logger:tty(true)` multiple times does not give multiple error\n log printouts.\n\n Own Id: OTP-6884 Aux Id: seq10767\n\n- The global name server now ignores `nodeup` messages when the command line\n flag `-connect_all false` has been used. (Thanks to Trevor Woollacott.)\n\n Own Id: OTP-6931\n\n- file:write_file/3, file:write/2 and file:read/2 could crash (contrary to\n documentation) for odd enough file system problems, e.g write to full file\n system. This bug has now been corrected.\n\n In this process the file module has been rewritten to produce better error\n codes. Posix error codes now originate from the OS file system calls or are\n generated only for very similar causes (for example 'enomem' is generated if a\n memory allocation fails, and 'einval' is generated if the file handle in\n Erlang is a file handle but currently invalid).\n\n More Erlang-ish error codes are now generated. For example `{error,badarg}` is\n now returned from `file:close/1` if the argument is not of a file handle type.\n See file(3).\n\n The possibility to write a single byte using `file:write/2` instead of a list\n or binary of one byte, contradictory to the documentation, has been removed.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-6967 Aux Id: OTP-6597 OTP-6291\n\n- Monitor messages produced by the system monitor functionality, and garbage\n collect trace messages could contain erroneous heap and/or stack sizes when\n the actual heaps and/or stacks were huge.\n\n As of erts version 5.6 the `large_heap` option to\n `erlang:system_monitor/[1,2]` has been modified. The monitor message is sent\n if the sum of the sizes of all memory blocks allocated for all heap\n generations is equal to or larger than the specified size. Previously the\n monitor message was sent if the memory block allocated for the youngest\n generation was equal to or larger than the specified size.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-6974 Aux Id: seq10796\n\n- `inet:getopts/2` returned random values on Windows Vista.\n\n Own Id: OTP-7003","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Minor documentation corrections for file:pread/2 and file:pread/3.\n\n Own Id: OTP-6853\n\n- The deprecated functions `file:file_info/1`, `init:get_flag/1`,\n `init:get_flags/0`, and `init:get_args/0` have been removed.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-6886\n\n- Contract directives for modules in Kernel and STDLIB.\n\n Own Id: OTP-6895\n\n- The functions io:columns/0, io:columns/1, io:rows/0 and io:rows/1 are added to\n allow the user to get information about the terminal geometry. The shell takes\n some advantage of this when formatting output. For regular files and other\n io-devices where height and width are not applicable, the functions return\n \\{error,enotsup\\}.\n\n Potential incompatibility: If one has written a custom io-handler, the handler\n has to either return an error or take care of io-requests regarding terminal\n height and width. Usually that is no problem as io-handlers, as a rule of\n thumb, should give an error reply when receiving unknown io-requests, instead\n of crashing.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-6933\n\n- The undocumented and unsupported functions `inet:ip_to_bytes/1`,\n `inet:ip4_to_bytes/1`, `inet:ip6_to_bytes/1`, and `inet:bytes_to_ip6/16` have\n been removed.\n\n Own Id: OTP-6938\n\n- Added new checksum combine functions to `zlib`. And fixed a bug in\n `zlib:deflate`. Thanks Matthew Dempsky.\n\n Own Id: OTP-6970\n\n- The [`spawn_monitor/1`](`spawn_monitor/1`) and\n [`spawn_monitor/3`](`spawn_monitor/3`) BIFs are now auto-imported (i.e. they\n no longer need an `erlang:` prefix).\n\n Own Id: OTP-6975\n\n- All functions in the `code` module now fail with an exception if they are\n called with obviously bad arguments, such as a tuple when an atom was\n expected. Some functions now also fail for undocumented argument types (for\n instance, `ensure_loaded/1` now only accepts an atom as documented; it used to\n accept a string too).\n\n Dialyzer will generally emit warnings for any calls that use undocumented\n argument types. Even if the call happens to still work in R12B, you should\n correct your code. A future release will adhere to the documentation.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-6983","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.11.5.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-11-5-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- The kernel parameter dist_auto_connect once could fail to block a node if\n massive parallel sends were issued during a transient failure of network\n communication\n\n Own Id: OTP-6893 Aux Id: seq10753","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 2.11.5.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-11-5-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- The internal (rarely used) DNS resolver has been modified to not use the\n domain search list when asked to resolve an absolute name; a name with a\n terminating dot. There was also a bug causing it to create malformed DNS\n queries for absolute names that has been corrected, correction suggested by\n Scott Lystig Fritchie. The code has also been corrected to look up cached RRs\n in the same search order as non-cached, now allows having the root domain\n among the search domains, and can now actually do a zone transfer request.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-6806 Aux Id: seq10714 EABln35459\n\n- zlib:close/1 would leave an EXIT message in the message queue if the calling\n process had the trap_exit flag enabled.\n\n Own Id: OTP-6811","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- The documentation of [`process_flag(priority, Level)`](`process_flag/2`) has\n been updated, see the `m:erlang` documentation.\n\n Own Id: OTP-6745 Aux Id: OTP-6715","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.11.5 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-11-5"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- The shell has been updated to fix the following flaws: Shell process exit left\n you with an unresponsive initial shell if not using oldshell. Starting a\n restricted shell with a nonexisting callback module resulted in a shell where\n no commands could be used, not even init:stop/0. Fun's could not be used as\n parameters to local shell functions (in shell_default or user_default) when\n restricted_shell was active.\n\n Own Id: OTP-6537\n\n- The undocumented feature gen_tcp:fdopen/2 was broken in R11B-4. It is now\n fixed again.\n\n Own Id: OTP-6615\n\n- Corrected cancellation of timers in three places in the inet_res module.\n (Problem found by Dialyzer.)\n\n Own Id: OTP-6676","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Corrected protocol layer flue for socket options SO_LINGER, SO_SNDBUF and\n SO_RCVBUF, for SCTP.\n\n Own Id: OTP-6625 Aux Id: OTP-6336\n\n- The behaviour of the inet option \\{active,once\\} on peer close is improved and\n documented.\n\n Own Id: OTP-6681\n\n- The inet option send_timeout for connection oriented sockets is added to allow\n for timeouts in communicating send requests to the underlying TCP stack.\n\n Own Id: OTP-6684 Aux Id: seq10637 OTP-6681\n\n- Minor Makefile changes.\n\n Own Id: OTP-6689 Aux Id: OTP-6742\n\n- The documentation of [`process_flag(priority, Level)`](`process_flag/2`) has\n been updated, see the `m:erlang` documentation.\n\n Own Id: OTP-6715","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.11.4.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-11-4-2"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- process_flag/2 accepts the new flag `sensitive`.\n\n Own Id: OTP-6592 Aux Id: seq10555","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.11.4.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-11-4-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- A bug in gen_udp:open that broke the 'fd' option has been fixed.\n\n Own Id: OTP-6594 Aux Id: seq10619","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 2.11.4 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-11-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Added a warning to the documentation for the `error_logger` functions\n `error_msg/1,2`, `warning_msg/1,2` and `info_msg/1,2` that calling these\n function with bad arguments can crash the standard event handler.\n\n Own Id: OTP-4575 Aux Id: seq7693\n\n- A bug in `inet_db` concerning getting the resolver option `retry` has been\n corrected.\n\n Own Id: OTP-6380 Aux Id: seq10534\n\n- Names registered by calling `global:register_name()` or\n `global:re_register_name()` were not always unregistered when the registering\n or registered process died. This bug has been fixed.\n\n Own Id: OTP-6428\n\n- When setting the kernel configuration parameter `error_logger` to `false`, the\n documentation stated that \"No error logger handler is installed\". This is\n true, but error logging is not turned off, as the initial, primitive error\n logger event handler is kept, printing raw event messages to tty.\n\n Changing this behavior can be viewed as a backward incompatible change.\n Instead a new value `silent` for the configuration parameter has been added,\n which ensures that error logging is completely turned off.\n\n Own Id: OTP-6445\n\n- Clarified the documentation for `code:lib_dir/1` and `code:priv_dir/1`. The\n functions traverse the names of the code path, they do not search the actual\n directories.\n\n Own Id: OTP-6466\n\n- `io:setopts` returned `{error,badarg}`, when called with only an `expand_fun`\n argument. (Thanks to igwan.)\n\n Own Id: OTP-6508","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- An interface towards the SCTP Socket API Extensions has been implemented.It is\n an Open Source patch courtesy of Serge Aleynikov and Leonid Timochouk. The\n Erlang code parts has been adapted by the OTP team, changing the Erlang API\n somewhat.\n\n The Erlang interface consists of the module `gen_sctp` and an include file\n `-include_lib(\"kernel/include/inet_sctp.hrl\").` for option record definitions.\n The `gen_sctp` module is documented.\n\n The delivered Open Source patch, before the OTP team rewrites, was written\n according to\n [http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13](http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13)\n and was claimed to work fine, tested on Linux Fedora Core 5.0 (kernel\n 2.6.15-2054 or later) and on Solaris 10 and 11. The OTP team rewrites used the\n same standard document but might have accidentally broken some functionality.\n If so, it will soon be patched to working state. The tricky parts in C and the\n general design has essentially not changed. During the rewrites the code was\n hand tested on SuSE Linux Enterprise Server 10, and briefly on Solaris 10.\n Feedbach on code and docs is very much appreciated.\n\n The SCTP interface is in beta state. It has only been hand tested and has no\n automatic test suites in OTP meaning everything is most certainly not tested.\n Socket active mode is broken. IPv6 is not tested. The documentation has been\n reworked due to the API changes, but has not been proofread after this.\n\n Thank you from the OTP team to Serge Aleynikov and Leonid Timochouk for a\n valuable contribution. We hope we have not messed it up too much.\n\n Own Id: OTP-6336\n\n- A `{minor_version,Version}` option is now recognized by\n [`term_to_binary/2`](`term_to_binary/2`). \\{minor_version,1\\} will cause\n floats to be encoded in an exact and more space-efficient way compared to the\n previous encoding.\n\n Own Id: OTP-6434\n\n- Monitoring of nodes has been improved. Now the following properties apply to\n `net_kernel:monitor_nodes/[1,2]`:\n\n - `nodeup` messages will be delivered before delivery of any message from the\n remote node passed through the newly established connection.\n - `nodedown` messages will not be delivered until all messages from the remote\n node that have been passed through the connection have been delivered.\n - Subscriptions can also be made before the `net_kernel` server has been\n started.\n\n Own Id: OTP-6481\n\n- Setting and getting socket options in a \"raw\" fashion is now allowed. Using\n this feature will inevitably produce non portable code, but will allow setting\n ang getting arbitrary uncommon options on TCP stacks that do have them.\n\n Own Id: OTP-6519\n\n- Dialyzer warnings have been eliminated.\n\n Own Id: OTP-6523\n\n- The documentation for `file:delete/1` and `file:set_cwd/1` has been updated to\n clarify what happens if the input arguments are of an incorrect type.\n\n Own Id: OTP-6535","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.11.3.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-11-3-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- An erroneous packet size could be used for the first messages passed through a\n newly established connection between two Erlang nodes. This could cause\n messages to be discarded, or termination of the connection.\n\n Own Id: OTP-6473","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 2.11.3 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-11-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- On Unix, the `unix:cmd/1` function could leave an 'EXIT' message in the\n message queue for the calling process That problem was more likely to happen\n in an SMP emulator.\n\n Own Id: OTP-6368","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- More interfaces are added in erl_ddll, to support different usage scenarios.\n\n Own Id: OTP-6307 Aux Id: OTP-6234\n\n- Locks set by calling `global:set_lock()` were not always deleted when the\n locking process died. This bug has been fixed.\n\n Own Id: OTP-6341 Aux Id: seq10445","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.11.2 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-11-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Behavior in case of disappeared nodes when using he dist_auto_connect once got\n changed in R11B-1. The timeouts regarding normal distributed operations is now\n reverted to the old (pre R11B-1).\n\n Own Id: OTP-6258 Aux Id: OTP-6200, seq10449\n\n- Start-up problems for the internal process used by the `inet:gethostbyname()`\n functions were eliminated. If the internal process (`inet_gethost_native`) had\n not previously been started, and if several processes at the same time called\n one of the `inet:gethostbyname()` functions, the calls could fail.\n\n Own Id: OTP-6286","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Code cleanup: the old internal obsolete file_server has been removed. It was\n only used when communicating with R7 and older nodes.\n\n Own Id: OTP-6245\n\n- Trying to open a non-existent or badly formed disk log no longer results in a\n crash report. In particular, `ets:file2tab/1` reports no error when the\n argument is not a well-formed disk log file. (The return value has not been\n changed, it is still an error tuple.)\n\n Own Id: OTP-6278 Aux Id: seq10421\n\n- There are new BIFs `erlang:spawn_monitor/1,3`, and the new option `monitor`\n for `spawn_opt/2,3,4,5`.\n\n The `observer_backend` module has been updated to handle the new BIFs.\n\n Own Id: OTP-6281\n\n- To help Dialyzer find more bugs, many functions in the Kernel and STDLIB\n applications now only accept arguments of the type that is documented.\n\n For instance, the functions `lists:prefix/2` and `lists:suffix/2` are\n documented to only accept lists as their arguments, but they actually accepted\n anything and returned `false`. That has been changed so that the functions\n cause an exception if one or both arguments are not lists.\n\n Also, the `string:strip/3` function is documented to take a character argument\n that is a character to strip from one or both ends of the string. Given a list\n instead of a character, it used to do nothing, but will now cause an\n exception.\n\n Dialyzer will find most cases where those functions are passed arguments of\n the wrong type.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-6295","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.11.1.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-11-1-1"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- There is now an option read_packets for UDP sockets that sets the maximum\n number of UDP packets that will be read for each invocation of the socket\n driver.\n\n Own Id: OTP-6249 Aux Id: seq10452","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.11.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-11-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- In R11B-0, the erl_ddll server process is always started. Despite that, the\n configuration parameter `start_ddll` for the Kernel application was still\n obeyed, which would cause the erl_ddll server to be started TWICE (and the\n system shutting down as a result). In this release, `start_ddll` is no longer\n used and its documentation has been removed.\n\n Own Id: OTP-6163\n\n- The kernel option \\{dist_auto_connect,once\\} could block out nodes that had\n never been connected, causing persistent partitioning of networks.\n Furthermore, partial restarts of networks could cause inconsistent global name\n databases. Both problems are now solved.\n\n Own Id: OTP-6200 Aux Id: seq10377","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Late arriving tcp_closed and udp_closed messages are now removed from the\n message queue of a process calling gen_tcp:close/1, gen_udp:close/1, and\n inet:close/1.\n\n Own Id: OTP-6197","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.11 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-11"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- When repairing a disk log with a corrupt index file (caused by for instance a\n hard disk failure) the old contents of the index file is kept unmodified. This\n will make repeated attempts to open the disk log fail every time.\n\n Own Id: OTP-5558 Aux Id: seq9823\n\n- Previously [`unlink/1`](`unlink/1`) and `erlang:demonitor/2` behaved\n completely asynchronous. This had one undesirable effect, though. You could\n never know when you were guaranteed _not_ to be affected by a link that you\n had unlinked or a monitor that you had demonitored.\n\n The new behavior of [`unlink/1`](`unlink/1`) and `erlang:demonitor/2` can be\n viewed as two operations performed atomically. Asynchronously send an unlink\n signal or a demonitor signal, and ignore any future results of the link or\n monitor.\n\n _NOTE_: This change can cause some obscure code to fail which previously did\n not. For example, the following code might hang:\n\n ```erlang\n Mon = erlang:monitor(process, Pid),\n %% ...\n exit(Pid, bang),\n erlang:demonitor(Mon),\n receive\n {'DOWN', Mon, process, Pid, _} -> ok\n %% We were previously guaranteed to get a down message\n %% (since we exited the process ourself), so we could\n %% in this case leave out:\n %% after 0 -> ok\n end,\n ```\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-5772\n\n- The behavior when an application fails to start and possibly causes the\n runtime system to halt has been cleaned up, including fixing some minor bugs.\n\n `application_controller` should now always terminate with a non-nested string,\n meaning the slogan in an `erl_crash.dump` should always be easy to read.\n\n `init` now makes sure that the slogan passed to `erlang:halt/1` does not\n exceed the maximum allowed length.\n\n Redundant calls to [`list_to_atom/1`](`list_to_atom/1`) has been removed from\n the primitive `error_logger` event handler. (Thanks Serge Aleynikov for\n pointing this out).\n\n The changes only affects the contents of the error messages and crashdump file\n slogan.\n\n Own Id: OTP-5964\n\n- The `erl_ddll` server is now started when OTP is started and placed under the\n Kernel supervisor. This fixes several minor issues. It used to be started on\n demand.\n\n The documentation for the `start` and `stop` functions in the `erl_ddll`\n module has been removed, as those functions are not meant to be used by other\n applications.\n\n Furthermore, the `erl_ddll:stop/1` function no longer terminates the\n `erl_ddll` server, as that would terminate the entire runtime system.\n\n Own Id: OTP-6033","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Removed some unused functions from `application_master`.\n\n Own Id: OTP-3889\n\n- Global no longer allows the registration of a process under more than one\n name. If the old (buggy) behavior is desired the Kernel application variable\n `global_multi_name_action` can be given the value `allow`.\n\n Own Id: OTP-5640 Aux Id: OTP-5603\n\n- The (slightly misleading) warnings that was shown when the `erlang.erl` file\n was compiled has been eliminated.\n\n Own Id: OTP-5947\n\n- The `auth` module API is deprecated.\n\n Own Id: OTP-6037\n\n- Added `erlang:demonitor/2`, making it possible to at the same time flush a\n received `'DOWN'` message, if there is one. See `m:erlang`.\n\n Own Id: OTP-6100 Aux Id: OTP-5772","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.10.13 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-10-13"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Large files (more than 2 GBytes) are now handled on Solaris 8.\n\n Own Id: OTP-5849 Aux Id: seq10157\n\n- During startup, a garbage `{'DOWN', ...}` message was left by\n `inet_gethost_native`, that caused problems for the starting code server.\n\n Own Id: OTP-5978 Aux Id: OTP-5974","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- `global` now makes several attempts to connect nodes when maintaining the\n fully connected network. More than one attempt is sometimes needed under very\n heavy load.\n\n Own Id: OTP-5889\n\n- `erl_epmd` now explicitly sets the timeout to `infinity` when calling\n `gen_server:call`. The old timeout of 15 seconds could time out under very\n heavy load.\n\n Own Id: OTP-5959\n\n- Corrected the start of code server to use reference-tagged tuples to ensure\n that an unexpected message sent to the parent process does not cause a halt of\n the system. Also removed the useless `start/*` functions in both `code.erl`\n and `code_server.erl` and no longer exports the `init` function from\n `code_server.erl`.\n\n Own Id: OTP-5974 Aux Id: seq10243, OTP-5978","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.10.12 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-10-12"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- A bug in `global` has been fixed: the locker process added `nonode@nohost` to\n the list of nodes to lock. This could happen before any nodes got known to the\n global name server. Depending on net configuration the symptom was a delay.\n\n Own Id: OTP-5792 Aux Id: OTP-5563\n\n- If an `.app` file is missing, the error reason returned by\n `application:load/1` has been corrected to\n `{\"no such file or directory\", \"FILE.app\"}`, instead of the less informative\n `{\"unknown POSIX error\",\"FILE.app\"}`.\n\n Own Id: OTP-5809\n\n- Bug fixes: `disk_log:accessible_logs/0` no longer reports all `pg2` process\n groups as distributed disk logs; `disk_log:pid2name/1` did not recognize\n processes of distributed disk logs.\n\n Own Id: OTP-5810\n\n- The functions `file:consult/1`, `file:path_consult/2`, `file:eval/1,2`,\n `file:path_eval/2,3`, `file:script/1,2`, `file:path_script/2,3` now return\n correct line numbers in error tuples.\n\n Own Id: OTP-5814\n\n- If there were user-defined variables in the boot script, and their values were\n not provided using the `-boot_var` option, the emulator would refuse to start\n with a confusing error message. Corrected to show a clear, understandable\n message.\n\n The `prim_file` module was modified to not depend on the `lists` module, to\n make it possible to start the emulator using a user-defined loader. (Thanks to\n Martin Bjorklund.)\n\n Own Id: OTP-5828 Aux Id: seq10151\n\n- Minor corrections in the description of open modes. (Thanks to Richard\n Carlsson.)\n\n Own Id: OTP-5856","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- `application_controller` now terminates with the actual error reason, instead\n of `shutdown`. This means that the crash dump now should be somewhat more\n informative, in the case where the runtime system is terminated due to an\n error in an application.\n\n Example: If the (permanent) application `app1` fails to start, the slogan now\n will be:\n \"`Kernel pid terminated (application_controller) ({application_start_failure,app1,{shutdown, {app1,start,[normal,[]]}}})`\"\n\n rather than the previous\n \"`Kernel pid terminated (application_controller) (shutdown)`\".\n\n Own Id: OTP-5811","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.10.11.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-10-11-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Timers could sometimes timeout too early. This bug has now been fixed.\n\n Automatic cancellation of timers created by `erlang:send_after(Time,` pid(),\n Msg), and `erlang:start_timer(Time,` pid(), Msg) has been introduced. Timers\n created with the receiver specified by a pid, will automatically be cancelled\n when the receiver exits. For more information see the `m:erlang` man page.\n\n In order to be able to maintain a larger amount of timers without increasing\n the maintenance cost, the internal timer wheel and bif timer table have been\n enlarged.\n\n Also a number of minor bif timer optimizations have been implemented.\n\n Own Id: OTP-5795 Aux Id: OTP-5090, seq8913, seq10139, OTP-5782","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Documentation improvements:\n\n \\- documentation for `erlang:link/1` corrected\n\n \\- command line flag `-code_path_cache` added\n\n \\- `erl` command line flags clarifications\n\n \\- `m:net_kernel` clarifications\n\n Own Id: OTP-5847","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.10.11 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-10-11"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Several bug fixes and improvements in the global name registration facility\n (see `m:global`):\n\n - the name resolving procedure did not always unlink no longer registered\n processes;\n - the global name could sometimes hang when a `nodedown` was immediately\n followed by a `nodeup`;\n - global names were not always unregistered when a node went down;\n - it is now possible to set and delete locks at the same time as the global\n name server is resolving names--the handling of global locks has been\n separated from registration of global names;\n\n As of this version, `global` no longer supports nodes running Erlang/OTP R7B\n or earlier.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-5563\n\n- The functions `global:set_lock/3` and `global:trans/4` now accept the value\n `0` (zero) of the `Retries` argument.\n\n Own Id: OTP-5737\n\n- The `inet:getaddr(Addr, Family)` no longer validates the `Addr` argument if it\n is a 4 or 8 tuple containing the IP address, except for the size of the tuple\n and that it contains integers in the correct range.\n\n The reason for the change is that validation could cause the following\n sequence of calls to fail:\n\n `{ok,Addr} = inet:getaddr(localhost, inet6), gen_tcp:connect(Addr, 7, [inet6])`\n\n Own Id: OTP-5743","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- The previously undocumented and UNSUPPORTED `zlib` module has been updated in\n an incompatible way and many bugs have been corrected. It is now also\n documented.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-5715\n\n- Added `application` interface functions `which_applications/1`, `set_env/4`\n and `unset_env/3`, which take an additional `Timeout` argument. To be used in\n situations where the standard gen_server timeout (5000ms) is not adequate.\n\n Own Id: OTP-5724 Aux Id: seq10083\n\n- Improved documentation regarding synchronized start of applications with\n included applications (using start phases and `application_starter`).\n\n Own Id: OTP-5754\n\n- New socket options `priority` and `tos` for platforms that support them\n (currently only Linux).\n\n Own Id: OTP-5756\n\n- The global name server has been optimized when it comes to maintaining a fully\n connected network.\n\n Own Id: OTP-5770","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.10.10.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-10-10-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- The native resolver has gotten an control API for extended debugging and soft\n restart. It is: `inet_gethost_native:control(Control)` \n `Control = {debug_level,Level} | soft_restart` \n `Level = integer() in the range 0-4`.\n\n Own Id: OTP-5751 Aux Id: EABln25013","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 2.10.10 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-10-10"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- If several processes (at the same node) simultaneously tried to start the same\n distributed application, this could lead to `application:start` returning an\n erroneous value, or even hang.\n\n Own Id: OTP-5606 Aux Id: seq9838","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- The manual pages for most of the Kernel and some of the STDLIB modules have\n been updated, in particular regarding type definitions.\n\n The documentation of the return value for `erts:info/1` has been corrected.\n\n The documentation for `erlang:statistics/1` now lists all possible arguments.\n\n Own Id: OTP-5360\n\n- When the native resolver fails a `gethostbyaddr` lookup, `nxdomain` should be\n returned. There should be no attempt to fallback on a routine that succeeds if\n only the syntax of the IP address is valid. This has been fixed.\n\n Own Id: OTP-5598 Aux Id: OTP-5576\n\n- Replaced some tuple funs with the new `fun M:F/A` construct.\n\n The high-order functions in the `lists` module no longer accept bad funs under\n any circumstances. '`lists:map(bad_fun, [])`' used to return '`[]`' but now\n causes an exception.\n\n Unused, broken compatibility code in the `ets` module was removed. (Thanks to\n Dialyzer.)\n\n Eliminated 5 discrepancies found by Dialyzer in the Appmon application.\n\n Own Id: OTP-5633\n\n- The possibility to have comments following the list of tuples in a config file\n (file specified with the `-config` flag) has been added.\n\n Own Id: OTP-5661 Aux Id: seq10003","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.10.9 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-10-9"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- '`erl -config sys.config`' would fail to start if the `sys.config` file did\n not contain any whitespace at all after the dot. (Thanks to Anders Nygren.)\n\n Own Id: OTP-5543\n\n- A bug regarding tcp sockets which results in hanging `gen_tcp:send/2` has been\n corrected. To encounter this bug you needed one process that read from a\n socket, one that wrote more date than the reader read out so the sender got\n suspended, and then the reader closed the socket. (Reported and diagnosed by\n Alexey Shchepin.)\n\n Corrected a bug in the (undocumented and unsupported) option `{packet,http}`\n for `gen_tcp.` (Thanks to Claes Wikstrom and Luke Gorrie.)\n\n Updated the documentation regarding the second argument to `gen_tcp:recv/2`,\n the `Length` to receive.\n\n Own Id: OTP-5582 Aux Id: seq9839","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- At startup, the Erlang resolver hosts table was used to look up the name of\n the local (and possibly stand alone) host. This was incorrect. The configured\n resolver method is now used for this purpose.\n\n Own Id: OTP-5393\n\n- The `erlang:port_info/1` BIF is now documented. Minor corrections of the\n documentation for `erlang:port_info/2`.\n\n Added a note to the documentation of the `math` module that all functions are\n not available on all platforms.\n\n Added more information about the `+c` option in the `erl` man page in the ERTS\n documentation.\n\n Own Id: OTP-5555\n\n- The new `fun M:F/A` construct creates a fun that refers to the latest version\n of `M:F/A.` This syntax is meant to replace tuple funs `{M,F}` which have many\n problems.\n\n The new type test [`is_function(Fun,A)`](`is_function/2`) (which may be used\n in guards) test whether `Fun` is a fun that can be applied with `A` arguments.\n (Currently, `Fun` can also be a tuple fun.)\n\n Own Id: OTP-5584\n\n- According to the documentation `global` implements the equivalent of\n [`register/2`](`register/2`), which returns `badarg` if a process is already\n registered. As it turns out there is no check in `global` if a process is\n registered under more than one name. If some process is accidentally or by\n design given several names, it is possible that the name registry becomes\n inconsistent due to the way the resolve function is called when name clashes\n are discovered (see `register_name/3` in `m:global`).\n\n In OTP R11B `global` will not allow the registration of a process under more\n than one name. To help finding code where `no` will be returned, a Kernel\n application variable, `global_multi_name_action`, is hereby introduced.\n Depending on its value (`info`, `warning`, or `error`), messages are sent to\n the error logger when `global` discovers that some process is given more than\n one name. The variable only affects the node where it is defined.\n\n Own Id: OTP-5603","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.10.8 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-10-8"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- In case of a DNS lookup loop, `inet_db:getbyname` ends up building an infinite\n list. This has been fixed.\n\n Own Id: OTP-5449\n\n- When doing an `inet6` name lookup on an IPv4 address it was possible to get an\n address on IPv4 format back. This has been corrected. Some other minor\n inconsistencies regarding IPv6 name lookup have also been corrected.\n\n Own Id: OTP-5576","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.10.7 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-10-7"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Under certain circumstances the `net_kernel` could emit spurious nodedown\n messages. This bug has been fixed.\n\n Own Id: OTP-5396\n\n- Removed description of the `keep_zombies` configuration parameter in the\n `kernel` man page.\n\n Own Id: OTP-5497","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- Eliminated Dialyzer warnings (caused by dead code) in the `init` and\n `prim_file` modules.\n\n Own Id: OTP-5496\n\n- `inet_config` now also checks the environment variable `ERL_INETRC` for a\n possible user configuration file. See the ERTS User's Guide for details.\n\n Own Id: OTP-5512","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.10.6 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-10-6"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- The `c` option for the `+B` flag has been introduced which makes it possible\n to use Ctrl-C (Ctrl-Break on Windows) to interrupt the shell process rather\n than to invoke the emulator break handler. All new `+B` options are also\n supported on Windows (werl) as of now. Furthermore, Ctrl-C on Windows has now\n been reserved for copying text (what Ctrl-Ins was used for previously).\n Ctrl-Break should be used for break handling. Lastly, the documentation of the\n system flags has been updated.\n\n Own Id: OTP-5388\n\n- The possibility to start the Erlang shell in parallel with the rest of the\n system was reintroduced for backwards compatibility in STDLIB 1.13.1. The flag\n to be used for this is now called `async_shell_start` and has been documented.\n New shells started from the JCL menu are not synchronized with `init` anymore.\n This makes it possible to start a new shell (e.g. for debugging purposes) even\n if the initial shell has not come up.\n\n Own Id: OTP-5406 Aux Id: OTP-5218","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.10.5 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-10-5"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- Documentation for `erlang:binary_to_float/1` deleted. The BIF itself was\n removed several releases ago.\n\n Updated documentation for [`apply/2`](`apply/2`) and [`apply/3`](`apply/3`).\n\n Own Id: OTP-5391","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- `net_kernel:monitor_nodes/2` which takes a flag and an option list has been\n added. By use of `net_kernel:monitor_nodes/2` one can subscribe for\n `nodeup/nodedown` messages with extra information. It is now possible to\n monitor hidden nodes, and get `nodedown` reason. See the `m:net_kernel`\n documentation for more information.\n\n Own Id: OTP-5374","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.10.4 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-10-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- The application master for an application now terminates the application\n faster, which reduces the risk for timeouts in other parts of the system.\n\n Own Id: OTP-5363 Aux Id: EABln19084\n\n- A BIF `erlang:raise/3` has been added. See the manual for details. It is\n intended for internal system programming only, advanced error handling.\n\n Own Id: OTP-5376 Aux Id: OTP-5257","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Kernel 2.10.3 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-10-3"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- With the `-eval` flag (`erl -eval Expr`), an arbitrary expression can be\n evaluated during system initialization. This is documented in `m:init`.\n\n Own Id: OTP-5260\n\n- The unsupported and undocumented modules `socks5`, `socks5_auth`,\n `socks5_tcp`, and `socks5_udp` have been removed.\n\n Own Id: OTP-5266","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Kernel 2.10.1 - Kernel Release Notes","doc":"","ref":"notes.html#kernel-2-10-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","doc":"- The Pman 'trace shell' functionality was broken and has now been fixed.\n Furthermore, Pman could not correctly find the pid of the active shell if more\n than one shell process was running on the node. This has also been corrected.\n\n Own Id: OTP-5191\n\n- The documentation for the `auth:open/1` function which no longer exists has\n been removed. (Thanks to Miguel Barreiro.)\n\n Own Id: OTP-5208\n\n- Corrected the `crc32/3` function in the undocumented and unsupported `zlib`\n module.\n\n Own Id: OTP-5227","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Kernel Release Notes","doc":"- You can now start Erlang with the `-rsh` flag which gives you a remote initial\n shell instead of a local one. Example:\n\n ```text\n erl -sname this_node -rsh other_node@other_host\n ```\n\n Own Id: OTP-5210\n\n- If `/etc/hosts` specified two hosts with the same IP address (on separate\n lines), only the last host would be registered by inet_db during inet\n configuration. This has been corrected now so that both aliases are registered\n with the same IP address.\n\n Own Id: OTP-5212 Aux Id: seq7128\n\n- The documentation for BIFs that take I/O lists have been clarified. Those are\n [`list_to_binary/1`](`list_to_binary/1`),\n [`port_command/2`](`port_command/2`), [`port_control/3`](`port_control/3`).\n\n Documentation for all `is_*` BIFs (such as [`is_atom/1`](`is_atom/1`)) has\n been added.\n\n Removed the documentation for `erlang:float_to_binary/2` which was removed\n from the run-time system several releases ago.\n\n Own Id: OTP-5222","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Introduction","doc":"\n# Introduction","ref":"introduction_chapter.html"},{"type":"extras","title":"Scope - Introduction","doc":"The Kernel application has all the code necessary to run the Erlang runtime\nsystem: file servers, code servers, and so on.\n\nThe Kernel application is the first application started. It is mandatory in the\nsense that the minimal system based on Erlang/OTP consists of Kernel and STDLIB.\nKernel contains the following functional areas:\n\n- Start, stop, supervision, configuration, and distribution of applications\n- Code loading\n- Logging\n- Global name service\n- Supervision of Erlang/OTP\n- Communication with sockets\n- Operating system interface","ref":"introduction_chapter.html#scope"},{"type":"extras","title":"Prerequisites - Introduction","doc":"It is assumed that the reader is familiar with the Erlang programming language.","ref":"introduction_chapter.html#prerequisites"},{"type":"extras","title":"Socket Usage","doc":"\n# Socket Usage","ref":"socket_usage.html"},{"type":"extras","title":"Introduction - Socket Usage","doc":"The socket interface (module) is basically a \"thin\" layer on top of the OS\nsocket interface. It is assumed that, unless you have special needs,\ngen\\_\\[tcp|udp|sctp] should be sufficient (when they become available).\n\nNote that just because we have a documented and described option, it does _not_\nmean that the OS supports it. So its recommended that the user reads the\nplatform specific documentation for the option used.","ref":"socket_usage.html#introduction"},{"type":"extras","title":"Asynchronous calls - Socket Usage","doc":"Some functions allow for an _asynchronous_ call\n([`accept/2`](`m:socket#accept-nowait`),\n[`connect/3`](`m:socket#connect-nowait`), [`recv/3,4`](`m:socket#recv-nowait`),\n[`recvfrom/3,4`](`m:socket#recvfrom-nowait`),\n[`recvmsg/2,3,5`](`m:socket#recvmsg-nowait`),\n[`send/3,4`](`m:socket#send-nowait`), [`sendmsg/3,4`](`m:socket#sendmsg-nowait`)\nand [`sendto/4,5`](`m:socket#sendto-nowait`)). This is achieved by setting the\n`Timeout` argument to `nowait`. For instance, if calling the\n[`recv/3`](`m:socket#recv-nowait`) function with Timeout set to `nowait` (i.e.\n`recv(Sock, 0, nowait)`) when there is actually nothing to read, it will return\nwith:\n\n- **On Unix** - `{select, `[`SelectInfo`](`t:socket:select_info/0`)`}`\n\n `SelectInfo` contains the [`SelectHandle`](`t:socket:select_handle/0`).\n\n- **On Windows** -\n `{completion, `[`CompletionInfo`](`t:socket:completion_info/0`)`}`\n\n `CompletionInfo` contains the\n [`CompletionHandle`](`t:socket:completion_handle/0`).\n\nWhen data eventually arrives a 'select' or 'completion' message will be sent to\nthe caller:\n\n- **On Unix** - `{'$socket', socket(), select, SelectHandle}`\n\n The caller can then make another call to the recv function and now expect\n data.\n\n Note that all other users are _locked out_ until the 'current user' has called\n the function (recv in this case). So either immediately call the function or\n [`cancel`](`socket:cancel/2`).\n\n- **On Windows** -\n `{'$socket', socket(), completion, {CompletionHandle, CompletionStatus}}`\n\n The `CompletionStatus` contains the result of the operation (read).\n\nThe user must also be prepared to receive an abort message:\n\n- `{'$socket', socket(), abort, Info}`\n\nIf the operation is aborted for whatever reason (e.g. if the socket is closed\n\"by someone else\"). The `Info` part contains the abort reason (in this case that\nthe socket has been closed `Info = {SelectHandle, closed}`).\n\nThe general form of the 'socket' message is:\n\n- `{'$socket', Sock :: socket(), Tag :: atom(), Info :: term()}`\n\nWhere the format of `Info` is a function of `Tag`:\n\n| _Tag_ | _Info value type_ |\n| ---------- | ----------------------------------------- |\n| select | select_handle() |\n| completion | \\{completion_handle(), CompletionStatus\\} |\n| abort | \\{select_handle(), Reason :: term()\\} |\n\n_Table: socket message info value type_\n\nThe `select_handle()` is the same as was returned in the\n[`SelectInfo`](`t:socket:select_info/0`).\n\nThe `completion_handle()` is the same as was returned in the\n[`CompletionInfo`](`t:socket:completion_info/0`).","ref":"socket_usage.html#asynchronous-calls"},{"type":"extras","title":"Socket Registry - Socket Usage","doc":"The _socket registry_ is how we keep track of sockets. There are two functions\nthat can be used for interaction: `socket:number_of/0` and\n`socket:which_sockets/1`.\n\nIn systems which create and delete _many_ sockets dynamically, it (the socket\nregistry) could become a bottleneck. For such systems, there are a couple of\nways to control the use of the socket registry.\n\nFirstly, its possible to effect the global default value when building OTP from\nsource with the two configure options:\n\n```text\n--enable-esock-socket-registry (default) | --disable-esock-socket-registry\n```\n\nSecond, its possible to effect the global default value by setting the\nenvironment variable `ESOCK_USE_SOCKET_REGISTRY` (boolean) before starting the\nerlang.\n\nThird, its possible to alter the global default value in runtime by calling the\nfunction [`use_registry/1`](`socket:use_registry/1`).\n\nAnd finally, its possible to override the global default when creating a socket\n(with [`open/2`](`socket:open/2`) and [`open/4`](`socket:open/4`)) by providing\nthe attribute `use_registry` (boolean) in the their `Opts` argument (which\neffects _that_ specific socket).","ref":"socket_usage.html#socket-registry"},{"type":"extras","title":"Example - Socket Usage","doc":"This example is intended to show how to create a simple (echo) server\n(and client).\n\n```erlang\n-module(example).\n\n-export([client/2, client/3]).\n-export([server/0, server/1, server/2]).\n\n\n%% ======================================================================\n\n%% === Client ===\n\nclient(#{family := Family} = ServerSockAddr, Msg)\n when is_list(Msg) orelse is_binary(Msg) ->\n {ok, Sock} = socket:open(Family, stream, default),\n ok = maybe_bind(Sock, Family),\n ok = socket:connect(Sock, ServerSockAddr),\n client_exchange(Sock, Msg);\n\nclient(ServerPort, Msg)\n when is_integer(ServerPort) andalso (ServerPort > 0) ->\n Family = inet, % Default\n Addr = get_local_addr(Family), % Pick an address\n SockAddr = #{family => Family,\n\t\t addr => Addr,\n\t\t port => ServerPort},\n client(SockAddr, Msg).\n\nclient(ServerPort, ServerAddr, Msg)\n when is_integer(ServerPort) andalso (ServerPort > 0) andalso\n is_tuple(ServerAddr) ->\n Family = which_family(ServerAddr),\n SockAddr = #{family => Family,\n\t\t addr => ServerAddr,\n\t\t port => ServerPort},\n client(SockAddr, Msg).\n\n%% Send the message to the (echo) server and wait for the echo to come back.\nclient_exchange(Sock, Msg) when is_list(Msg) ->\n client_exchange(Sock, list_to_binary(Msg));\nclient_exchange(Sock, Msg) when is_binary(Msg) ->\n ok = socket:send(Sock, Msg, infinity),\n {ok, Msg} = socket:recv(Sock, byte_size(Msg), infinity),\n ok.\n\n\n%% ======================================================================\n\n%% === Server ===\n\nserver() ->\n %% Make system choose port (and address)\n server(0).\n\n%% This function return the port and address that it actually uses,\n%% in case server/0 or server/1 (with a port number) was used to start it.\n\nserver(#{family := Family, addr := Addr, port := _} = SockAddr) ->\n {ok, Sock} = socket:open(Family, stream, tcp),\n ok = socket:bind(Sock, SockAddr),\n ok = socket:listen(Sock),\n {ok, #{port := Port}} = socket:sockname(Sock),\n Acceptor = start_acceptor(Sock),\n {ok, {Port, Addr, Acceptor}};\n\nserver(Port) when is_integer(Port) ->\n Family = inet, % Default\n Addr = get_local_addr(Family), % Pick an address\n SockAddr = #{family => Family,\n\t\t addr => Addr,\n\t\t port => Port},\n server(SockAddr).\n\nserver(Port, Addr)\n when is_integer(Port) andalso (Port >= 0) andalso\n is_tuple(Addr) ->\n Family = which_family(Addr),\n SockAddr = #{family => Family,\n\t\t addr => Addr,\n\t\t port => Port},\n server(SockAddr).\n\n\n%% --- Echo Server - Acceptor ---\n\nstart_acceptor(LSock) ->\n Self = self(),\n {Pid, MRef} = spawn_monitor(fun() -> acceptor_init(Self, LSock) end),\n receive\n\t{'DOWN', MRef, process, Pid, Info} ->\n\t erlang:error({failed_starting_acceptor, Info});\n\t{Pid, started} ->\n\t %% Transfer ownership\n\t socket:setopt(LSock, otp, owner, Pid),\n\t Pid ! {self(), continue},\n\t erlang:demonitor(MRef),\n\t Pid\n end.\n \nacceptor_init(Parent, LSock) ->\n Parent ! {self(), started},\n receive\n\t{Parent, continue} ->\n\t ok\n end,\n acceptor_loop(LSock).\n\nacceptor_loop(LSock) ->\n case socket:accept(LSock, infinity) of\n\t{ok, ASock} ->\n\t start_handler(ASock),\n\t acceptor_loop(LSock);\n\t{error, Reason} ->\n\t erlang:error({accept_failed, Reason})\n end.\n\n\n%% --- Echo Server - Handler ---\n\nstart_handler(Sock) ->\n Self = self(),\n {Pid, MRef} = spawn_monitor(fun() -> handler_init(Self, Sock) end),\n receive\n\t{'DOWN', MRef, process, Pid, Info} ->\n\t erlang:error({failed_starting_handler, Info});\n\t{Pid, started} ->\n\t %% Transfer ownership\n\t socket:setopt(Sock, otp, owner, Pid),\n\t Pid ! {self(), continue},\n\t erlang:demonitor(MRef),\n\t Pid\n end.\n\nhandler_init(Parent, Sock) ->\n Parent ! {self(), started},\n receive\n\t{Parent, continue} ->\n\t ok\n end,\n handler_loop(Sock, undefined).\n\n%% No \"ongoing\" reads\n%% The use of 'nowait' here is clearly *overkill* for this use case,\n%% but is intended as an example of how to use it.\nhandler_loop(Sock, undefined) ->\n case socket:recv(Sock, 0, nowait) of\n\t{ok, Data} ->\n\t echo(Sock, Data),\n\t handler_loop(Sock, undefined);\n\n\t{select, SelectInfo} ->\n\t handler_loop(Sock, SelectInfo);\n\n\t{completion, CompletionInfo} ->\n\t handler_loop(Sock, CompletionInfo);\n\n\t{error, Reason} ->\n\t erlang:error({recv_failed, Reason})\n end;\n\n%% This is the standard (asyncronous) behaviour.\nhandler_loop(Sock, {select_info, recv, SelectHandle}) ->\n receive\n\t{'$socket', Sock, select, SelectHandle} ->\n\t case socket:recv(Sock, 0, nowait) of\n\t\t{ok, Data} ->\n\t\t echo(Sock, Data),\n\t\t handler_loop(Sock, undefined);\n\n\t\t{select, NewSelectInfo} ->\n\t\t handler_loop(Sock, NewSelectInfo);\n\n\t\t{error, Reason} ->\n\t\t erlang:error({recv_failed, Reason})\n\t end\n end;\n\n%% This is the (asyncronous) behaviour on platforms that support 'completion',\n%% currently only Windows.\nhandler_loop(Sock, {completion_info, recv, CompletionHandle}) ->\n receive\n\t{'$socket', Sock, completion, {CompletionHandle, CompletionStatus}} ->\n\t case CompletionStatus of\n\t\t{ok, Data} ->\n\t\t echo(Sock, Data),\n\t\t handler_loop(Sock, undefined);\n\t\t{error, Reason} ->\n\t\t erlang:error({recv_failed, Reason})\n\t end\n end.\n\necho(Sock, Data) when is_binary(Data) ->\n ok = socket:send(Sock, Data, infinity),\n io:format(\"** ECHO **\"\n\t \"~n~s~n\", [binary_to_list(Data)]).\n\n\n%% ======================================================================\n\n%% === Utility functions ===\n\nmaybe_bind(Sock, Family) ->\n maybe_bind(Sock, Family, os:type()).\n\nmaybe_bind(Sock, Family, {win32, _}) ->\n Addr = get_local_addr(Family),\n SockAddr = #{family => Family,\n addr => Addr,\n port => 0},\n socket:bind(Sock, SockAddr);\nmaybe_bind(_Sock, _Family, _OS) ->\n ok.\n\n%% The idea with this is extract a \"usable\" local address\n%% that can be used even from *another* host. And doing\n%% so using the net module.\n\nget_local_addr(Family) ->\n Filter =\n\tfun(#{addr := #{family := Fam},\n\t flags := Flags}) ->\n\t\t(Fam =:= Family) andalso (not lists:member(loopback, Flags));\n\t (_) ->\n\t\tfalse\n\tend,\n {ok, [SockAddr|_]} = net:getifaddrs(Filter),\n #{addr := #{addr := Addr}} = SockAddr,\n Addr.\n\nwhich_family(Addr) when is_tuple(Addr) andalso (tuple_size(Addr) =:= 4) ->\n inet;\nwhich_family(Addr) when is_tuple(Addr) andalso (tuple_size(Addr) =:= 8) ->\n inet6.\n```\n\n\n[](){: #socket_options }","ref":"socket_usage.html#example"},{"type":"extras","title":"Socket Options - Socket Usage","doc":"Options for level `otp`:\n\n| _Option Name_ | _Value Type_ | _Set_ | _Get_ | _Other Requirements and comments_ |\n| ------------------- | ------------------------------------------------------------- | ----- | ----- | ---------------------------------------------------------------------------------------------------------------------------------------------- |\n| assoc_id | integer() | no | yes | type = seqpacket, protocol = sctp, is an association |\n| debug | boolean() | yes | yes | none |\n| iow | boolean() | yes | yes | none |\n| controlling_process | pid() | yes | yes | none |\n| rcvbuf | default \\| pos_integer() \\| \\{pos_integer(), pos_ineteger()\\} | yes | yes | The tuple format is _not_ allowed on Windows. 'default' only valid for set. The tuple form is only valid for type 'stream' and protocol 'tcp'. |\n| rcvctrlbuf | default \\| pos_integer() | yes | yes | default only valid for set |\n| sndctrlbuf | default \\| pos_integer() | yes | yes | default only valid for set |\n| fd | integer() | no | yes | none |\n| use_registry | boolean() | no | yes | the value is set when the socket is created, by a call to [`open/2`](`socket:open/2`) or [`open/4`](`socket:open/4`). |\n\n_Table: option levels_\n\nOptions for level `socket`:\n\n| _Option Name_ | _Value Type_ | _Set_ | _Get_ | _Other Requirements and comments_ |\n| ---------------- | ----------------- | ----- | ----- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| acceptconn | boolean() | no | yes | none |\n| bindtodevice | string() | yes | yes | Before Linux 3.8, this socket option could be set, but not get. Only works for some socket types (e.g. `inet`). If empty value is set, the binding is removed. |\n| broadcast | boolean() | yes | yes | type = dgram |\n| bsp_state | map() | no | yes | Windows only |\n| debug | integer() | yes | yes | may require admin capability |\n| domain | domain() | no | yes | _Not_ on FreeBSD (for instance) |\n| dontroute | boolean() | yes | yes | none |\n| exclusiveaddruse | boolean() | yes | yes | Windows only |\n| keepalive | boolean() | yes | yes | none |\n| linger | abort \\| linger() | yes | yes | none |\n| maxdg | integer() | no | yes | Windows only |\n| max_msg_size | integer() | no | yes | Windows only |\n| oobinline | boolean() | yes | yes | none |\n| peek_off | integer() | yes | yes | domain = local (unix). Currently disabled due to a possible infinite loop when calling recv(\\[peek]) the second time. |\n| priority | integer() | yes | yes | none |\n| protocol | protocol() | no | yes | _Not_ on (some) Darwin (for instance) |\n| rcvbuf | non_neg_integer() | yes | yes | none |\n| rcvlowat | non_neg_integer() | yes | yes | none |\n| rcvtimeo | timeval() | yes | yes | This option is not normally supported (see why below). OTP has to be explicitly built with the `--enable-esock-rcvsndtime` configure option for this to be available. Since our implementation is _nonblocking_, its unknown if and how this option works, or even if it may cause malfunctions. Therefore, we do not recommend setting this option. Instead, use the `Timeout` argument to, for instance, the [`recv/3`](`socket:recv/3`) function. |\n| reuseaddr | boolean() | yes | yes | none |\n| reuseport | boolean() | yes | yes | domain = inet \\| inet6 |\n| sndbuf | non_neg_integer() | yes | yes | none |\n| sndlowat | non_neg_integer() | yes | yes | not changeable on Linux |\n| sndtimeo | timeval() | yes | yes | This option is not normally supported (see why below). OTP has to be explicitly built with the `--enable-esock-rcvsndtime` configure option for this to be available. Since our implementation is _nonblocking_, its unknown if and how this option works, or even if it may cause malfunctions. Therefore, we do not recommend setting this option. Instead, use the `Timeout` argument to, for instance, the [`send/3`](`socket:send/3`) function. |\n| timestamp | boolean() | yes | yes | none |\n| type | type() | no | yes | none |\n\n_Table: socket options_\n\nOptions for level `ip`:\n\n| _Option Name_ | _Value Type_ | _Set_ | _Get_ | _Other Requirements and comments_ |\n| ---------------------- | --------------------- | ----- | ----- | ---------------------------------------------------------- |\n| add_membership | ip_mreq() | yes | no | none |\n| add_source_membership | ip_mreq_source() | yes | no | none |\n| block_source | ip_mreq_source() | yes | no | none |\n| drop_membership | ip_mreq() | yes | no | none |\n| drop_source_membership | ip_mreq_source() | yes | no | none |\n| freebind | boolean() | yes | yes | none |\n| hdrincl | boolean() | yes | yes | type = raw |\n| minttl | integer() | yes | yes | type = raw |\n| msfilter | null \\| ip_msfilter() | yes | no | none |\n| mtu | integer() | no | yes | type = raw |\n| mtu_discover | ip_pmtudisc() | yes | yes | none |\n| multicast_all | boolean() | yes | yes | none |\n| multicast_if | any \\| ip4_address() | yes | yes | none |\n| multicast_loop | boolean() | yes | yes | none |\n| multicast_ttl | uint8() | yes | yes | none |\n| nodefrag | boolean() | yes | yes | type = raw |\n| pktinfo | boolean() | yes | yes | type = dgram |\n| recvdstaddr | boolean() | yes | yes | type = dgram |\n| recverr | boolean() | yes | yes | none |\n| recvif | boolean() | yes | yes | type = dgram \\| raw |\n| recvopts | boolean() | yes | yes | type =/= stream |\n| recvorigdstaddr | boolean() | yes | yes | none |\n| recvttl | boolean() | yes | yes | type =/= stream |\n| retopts | boolean() | yes | yes | type =/= stream |\n| router_alert | integer() | yes | yes | type = raw |\n| sendsrcaddr | boolean() | yes | yes | none |\n| tos | ip_tos() | yes | yes | some high-priority levels may require superuser capability |\n| transparent | boolean() | yes | yes | requires admin capability |\n| ttl | integer() | yes | yes | none |\n| unblock_source | ip_mreq_source() | yes | no | none |\n\n_Table: ip options_\n\nOptions for level `ipv6`:\n\n| _Option Name_ | _Value Type_ | _Set_ | _Get_ | _Other Requirements and comments_ |\n| ---------------------- | ------------------ | ----- | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| addrform | inet | yes | no | allowed only for IPv6 sockets that are connected and bound to a v4-mapped-on-v6 address |\n| add_membership | ipv6_mreq() | yes | no | none |\n| authhdr | boolean() | yes | yes | type = dgram \\| raw, obsolete? |\n| drop_membership | ipv6_mreq() | yes | no | none |\n| dstopts | boolean() | yes | yes | type = dgram \\| raw, requires superuser privileges to update |\n| flowinfo | boolean() | yes | yes | type = dgram \\| raw, requires superuser privileges to update |\n| hoplimit | boolean() | yes | yes | type = dgram \\| raw. On some platforms (e.g. FreeBSD) is used to set in order to get `hoplimit` as a control message heeader. On others (e.g. Linux), `recvhoplimit` is set in order to get `hoplimit`. |\n| hopopts | boolean() | yes | yes | type = dgram \\| raw, requires superuser privileges to update |\n| mtu | boolean() | yes | yes | Get: Only after the socket has been connected |\n| mtu_discover | ipv6_pmtudisc() | yes | yes | none |\n| multicast_hops | default \\| uint8() | yes | yes | none |\n| multicast_if | integer() | yes | yes | type = dgram \\| raw |\n| multicast_loop | boolean() | yes | yes | none |\n| recverr | boolean() | yes | yes | none |\n| recvhoplimit | boolean() | yes | yes | type = dgram \\| raw. On some platforms (e.g. Linux), `recvhoplimit` is set in order to get `hoplimit` |\n| recvpktinfo \\| pktinfo | boolean() | yes | yes | type = dgram \\| raw. On some platforms (e.g. FreeBSD) is used to set in order to get `hoplimit` as a control message heeader. On others (e.g. Linux), `recvhoplimit` is set in order to get `hoplimit`. |\n| recvtclass | boolean() | yes | yes | type = dgram \\| raw. On some platforms is used to set (=true) in order to get the `tclass` control message heeader. On others, `tclass` is set in order to get `tclass` control message heeader. |\n| router_alert | integer() | yes | yes | type = raw |\n| rthdr | boolean() | yes | yes | type = dgram \\| raw, requires superuser privileges to update |\n| tclass | integer() | yes | yes | Set the traffic class associated with outgoing packets. RFC3542. |\n| unicast_hops | default \\| uint8() | yes | yes | none |\n| v6only | boolean() | yes | no | none |\n\n_Table: ipv6 options_\n\nOptions for level `tcp`:\n\n| _Option Name_ | _Value Type_ | _Set_ | _Get_ | _Other Requirements and comments_ |\n| ------------- | ------------ | ----- | ----- | -------------------------------------------------------------------------------------------------------- |\n| congestion | string() | yes | yes | none |\n| cork | boolean() | yes | yes | 'nopush' one some platforms (FreeBSD) |\n| keepcnt | integer() | yes | yes | On Windows (at least), it is illegal to set to a value greater than 255. |\n| keepidle | integer() | yes | yes | none |\n| keepintvl | integer() | yes | yes | none |\n| maxseg | integer() | yes | yes | Set not allowed on all platforms. |\n| nodelay | boolean() | yes | yes | none |\n| nopush | boolean() | yes | yes | 'cork' on some platforms (Linux). On Darwin this has a different meaning than on, for instance, FreeBSD. |\n\n_Table: tcp options_\n\nOptions for level `udp`:\n\n| _Option Name_ | _Value Type_ | _Set_ | _Get_ | _Other Requirements and comments_ |\n| ------------- | ------------ | ----- | ----- | --------------------------------- |\n| cork | boolean() | yes | yes | none |\n\n_Table: udp options_\n\nOptions for level `sctp`:\n\n| _Option Name_ | _Value Type_ | _Set_ | _Get_ | _Other Requirements and comments_ |\n| ----------------- | ---------------------- | ----- | ----- | --------------------------------- |\n| associnfo | sctp_assocparams() | yes | yes | none |\n| autoclose | non_neg_integer() | yes | yes | none |\n| disable_fragments | boolean() | yes | yes | none |\n| events | sctp_event_subscribe() | yes | no | none |\n| initmsg | sctp_initmsg() | yes | yes | none |\n| maxseg | non_neg_integer() | yes | yes | none |\n| nodelay | boolean() | yes | yes | none |\n| rtoinfo | sctp_rtoinfo() | yes | yes | none |\n\n_Table: sctp options_","ref":"socket_usage.html#socket-options"},{"type":"extras","title":"Logging","doc":"\n# Logging\n\nErlang provides a standard API for logging through `Logger`, which is part of\nthe Kernel application. Logger consists of the API for issuing log events, and a\ncustomizable backend where log handlers, filters and formatters can be plugged\nin.\n\nBy default, the Kernel application installs one log handler at system start.\nThis handler is named `default`. It receives and processes standard log events\nproduced by the Erlang runtime system, standard behaviours and different\nErlang/OTP applications. The log events are by default written to the terminal.\n\nYou can also configure the system so that the default handler prints log events\nto a single file, or to a set of wrap logs via `m:disk_log`.\n\nBy configuration, you can also modify or disable the default handler, replace it\nby a custom handler, and install additional handlers.","ref":"logger_chapter.html"},{"type":"extras","title":"Overview - Logging","doc":"A _log event_ consists of a _log level_, the _message_ to be logged, and\n_metadata_.\n\nThe Logger backend forwards log events from the API, first through a set of\n_primary filters_, then through a set of secondary filters attached to each log\nhandler. The secondary filters are in the following named _handler filters_.\n\nEach filter set consists of a _log level check_, followed by zero or more\n_filter functions_.\n\nThe following figure shows a conceptual overview of Logger. The figure shows two\nlog handlers, but any number of handlers can be installed.\n\n```mermaid\n---\ntitle: Conceptual Overview\n---\nflowchart TD\n DB[(Config DB)]\n API ---> ML[Module Level Global Level Global Filters]\n API -.Update configuration.-> DB\n ML -.-> DB\n ML ---> HL1[Hander Level Handler Filter]\n ML ---> HL2[Hander Level Handler Filter]\n HL1 ---> HC1[Handler Callback]\n HL2 ---> HC2[Handler Callback]\n HL1 -.-> DB\n HL2 -.-> DB\n subgraph Legend\n direction LR\n start1[ ] -->|Log event flow| stop1[ ]\n style start1 height:0px;\n style stop1 height:0px;\n start2[ ] -.->|Look up configuration| stop2[ ]\n style start2 height:0px;\n style stop2 height:0px;\n end\n```\n\nLog levels are expressed as atoms. Internally in Logger, the atoms are mapped to\ninteger values, and a log event passes the log level check if the integer value\nof its log level is less than or equal to the currently configured log level.\nThat is, the check passes if the event is equally or more severe than the\nconfigured level. See section [Log Level](#log-level) for a\nlisting and description of all log levels.\n\nThe primary log level can be overridden by a log level configured per module.\nThis is to, for instance, allow more verbose logging from a specific part of the\nsystem.\n\nFilter functions can be used for more sophisticated filtering than the log level\ncheck provides. A filter function can stop or pass a log event, based on any of\nthe event's contents. It can also modify all parts of the log event. See section\n[Filters](#filters) for more details.\n\nIf a log event passes through all primary filters and all handler filters for a\nspecific handler, Logger forwards the event to the _handler callback_. The\nhandler formats and prints the event to its destination. See section\n[Handlers](#handlers) for more details.\n\nEverything up to and including the call to the handler callbacks is executed on\nthe client process, that is, the process where the log event was issued. It is\nup to the handler implementation if other processes are involved or not.\n\nThe handlers are called in sequence, and the order is not defined.","ref":"logger_chapter.html#overview"},{"type":"extras","title":"Logger API - Logging","doc":"The API for logging consists of a set of [macros](`m:logger#module-macros`), and a set\nof functions on the form `logger:Level/1,2,3`, which are all shortcuts for\n[`logger:log(Level,Arg1[,Arg2[,Arg3]])`](`logger:log/2`).\n\nThe macros are defined in `logger.hrl`, which is included in a module with the\ndirective\n\n```erlang\n-include_lib(\"kernel/include/logger.hrl\").\n```\n\nThe difference between using the macros and the exported functions is that\nmacros add location (originator) information to the metadata, and performs lazy\nevaluation by wrapping the logger call in a case statement, so it is only\nevaluated if the log level of the event passes the primary log level check.","ref":"logger_chapter.html#logger-api"},{"type":"extras","title":"Log Level - Logging","doc":"The log level indicates the severity of a event. In accordance with the Syslog\nprotocol, [RFC 5424](https://www.ietf.org/rfc/rfc5424.txt), eight log levels can\nbe specified. The following table lists all possible log levels by name (atom),\ninteger value, and description:\n\n| **Level** | **Integer** | **Description** |\n| --------- | ----------- | --------------------------------- |\n| emergency | 0 | system is unusable |\n| alert | 1 | action must be taken immediately |\n| critical | 2 | critical conditions |\n| error | 3 | error conditions |\n| warning | 4 | warning conditions |\n| notice | 5 | normal but significant conditions |\n| info | 6 | informational messages |\n| debug | 7 | debug-level messages |\n\n_Table: Log Levels_\n\nNotice that the integer value is only used internally in Logger. In the API, you\nmust always use the atom. To compare the severity of two log levels, use\n`logger:compare_levels/2`.","ref":"logger_chapter.html#log-level"},{"type":"extras","title":"Log Message - Logging","doc":"The log message contains the information to be logged. The message can consist\nof a format string and arguments (given as two separate parameters in the Logger\nAPI), a string or a report.\n\nExample, format string and arguments:\n\n```erlang\nlogger:error(\"The file does not exist: ~ts\",[Filename])\n```\n\nExample, string:\n\n```erlang\nlogger:notice(\"Something strange happened!\")\n```\n\nA report, which is either a map or a key-value list, is the preferred way to log\nusing Logger as it makes it possible for different backends to filter and format\nthe log event as it needs to.\n\nExample, report:\n\n```erlang\n?LOG_ERROR(#{ user => joe, filename => Filename, reason => enoent })\n```\n\nReports can be accompanied by a _report callback_ specified in the log event's\n[metadata](#metadata). The report callback is a convenience\nfunction that the [formatter](#formatters) can use to convert\nthe report to a format string and arguments, or directly to a string. The\nformatter can also use its own conversion function, if no callback is provided,\nor if a customized formatting is desired.\n\nThe report callback must be a fun with one or two arguments. If it takes one\nargument, this is the report itself, and the fun returns a format string and\narguments:\n\n```erlang\nfun((logger:report()) -> {io:format(),[term()]})\n```\n\nIf it takes two arguments, the first is the report, and the second is a map\ncontaining extra data that allows direct conversion to a string:\n\n```erlang\nfun((logger:report(),logger:report_cb_config()) -> unicode:chardata())\n```\n\nThe fun must obey the `depth` and `chars_limit` parameters provided in the\nsecond argument, as the formatter cannot do anything useful of these parameters\nwith the returned string. The extra data also contains a field named\n`single_line`, indicating if the printed log message may contain line breaks or\nnot. This variant is used when the formatting of the report depends on the size\nor single line parameters.\n\nExample, report, and metadata with report callback:\n\n```erlang\nlogger:debug(#{got => connection_request, id => Id, state => State},\n #{report_cb => fun(R) -> {\"~p\",[R]} end})\n```\n\nThe log message can also be provided through a fun for lazy evaluation. The fun\nis only evaluated if the primary log level check passes, and is therefore\nrecommended if it is expensive to generate the message. The lazy fun must return\na string, a report, or a tuple with format string and arguments.","ref":"logger_chapter.html#log-message"},{"type":"extras","title":"Metadata - Logging","doc":"Metadata contains additional data associated with a log message. Logger inserts\nsome metadata fields by default, and the client can add custom metadata in three\ndifferent ways:\n\n- **Set primary metadata** - Primary metadata applies is the base metadata given\n to all log events. At startup it can be set using the kernel configuration\n parameter [logger_metadata](kernel_app.md#logger_metadata). At run-time it can\n be set and updated using `logger:set_primary_config/1` and\n `logger:update_primary_config/1` respectively.\n\n- **Set process metadata** - Process metadata is set and updated with\n `logger:set_process_metadata/1` and `logger:update_process_metadata/1`,\n respectively. This metadata applies to the process on which these calls are\n made, and Logger adds the metadata to all log events issued on that process.\n\n- **Add metadata to a specific log event** - Metadata associated with one\n specific log event is given as the last parameter to the log macro or Logger\n API function when the event is issued. For example:\n\n ```text\n ?LOG_ERROR(\"Connection closed\",#{context => server})\n ```\n\nSee the description of the `t:logger:metadata/0` type for information about\nwhich default keys Logger inserts, and how the different metadata maps are\nmerged.","ref":"logger_chapter.html#metadata"},{"type":"extras","title":"Filters - Logging","doc":"Filters can be primary, or attached to a specific handler. Logger calls the\nprimary filters first, and if they all pass, it calls the handler filters for\neach handler. Logger calls the handler callback only if all filters attached to\nthe handler in question also pass.\n\nA filter is defined as:\n\n```text\n{FilterFun, Extra}\n```\n\nwhere `FilterFun` is a function of arity 2, and `Extra` is any term. When\napplying the filter, Logger calls the function with the log event as the first\nargument, and the value of `Extra` as the second argument. See\n`t:logger:filter/0` for type definitions.\n\nThe filter function can return `stop`, `ignore` or the (possibly modified) log\nevent.\n\nIf `stop` is returned, the log event is immediately discarded. If the filter is\nprimary, no handler filters or callbacks are called. If it is a handler filter,\nthe corresponding handler callback is not called, but the log event is forwarded\nto filters attached to the next handler, if any.\n\nIf the log event is returned, the next filter function is called with the\nreturned value as the first argument. That is, if a filter function modifies the\nlog event, the next filter function receives the modified event. The value\nreturned from the last filter function is the value that the handler callback\nreceives.\n\nIf the filter function returns `ignore`, it means that it did not recognize the\nlog event, and thus leaves to other filters to decide the event's destiny.\n\nThe configuration option `filter_default` specifies the behaviour if all filter\nfunctions return `ignore`, or if no filters exist. `filter_default` is by\ndefault set to `log`, meaning that if all existing filters ignore a log event,\nLogger forwards the event to the handler callback. If `filter_default` is set to\n`stop`, Logger discards such events.\n\nPrimary filters are added with `logger:add_primary_filter/2` and removed with\n`logger:remove_primary_filter/1`. They can also be added at system start via the\nKernel configuration parameter [`logger`](#logger_parameter).\n\nHandler filters are added with `logger:add_handler_filter/3` and removed with\n`logger:remove_handler_filter/2`. They can also be specified directly in the\nconfiguration when adding a handler with `logger:add_handler/3` or via the\nKernel configuration parameter [`logger`](#logger_parameter).\n\nTo see which filters are currently installed in the system, use\n`logger:get_config/0`, or `logger:get_primary_config/0` and\n`logger:get_handler_config/1`. Filters are listed in the order they are applied,\nthat is, the first filter in the list is applied first, and so on.\n\nFor convenience, the following built-in filters exist:\n\n- **`logger_filters:domain/2`** - Provides a way of filtering log events based\n on a `domain` field in `Metadata`.\n\n- **`logger_filters:level/2`** - Provides a way of filtering log events based on\n the log level.\n\n- **`logger_filters:progress/2`** - Stops or allows progress reports from\n `supervisor` and `application_controller`.\n\n- **`logger_filters:remote_gl/2`** - Stops or allows log events originating from\n a process that has its group leader on a remote node.","ref":"logger_chapter.html#filters"},{"type":"extras","title":"Handlers - Logging","doc":"A handler is defined as a module exporting at least the following callback\nfunction:\n\n```text\nlog(LogEvent, Config) -> term()\n```\n\nThis function is called when a log event has passed through all primary filters,\nand all handler filters attached to the handler in question. The function call\nis executed on the client process, and it is up to the handler implementation if\nother processes are involved or not.\n\nLogger allows adding multiple instances of a handler callback. That is, if a\ncallback module implementation allows it, you can add multiple handler instances\nusing the same callback module. The different instances are identified by unique\nhandler identities.\n\nIn addition to the mandatory callback function `log/2`, a handler module can\nexport the optional callback functions `adding_handler/1`, `changing_config/3`,\n`filter_config/1`, and `removing_handler/1`. See `m:logger_handler` for more\ninformation about these function.\n\nThe following built-in handlers exist:\n\n- **`logger_std_h`** - This is the default handler used by OTP. Multiple\n instances can be started, and each instance will write log events to a given\n destination, terminal or file.\n\n- **`logger_disk_log_h`** - This handler behaves much like `logger_std_h`,\n except it uses `m:disk_log` as its destination.\n\n- **`error_logger`{: #ErrorLoggerManager }** - This handler is provided for\n backwards compatibility only. It is not started by default, but will be\n automatically started the first time an `error_logger` event handler is added\n with\n [`error_logger:add_report_handler/1,2`](`error_logger:add_report_handler/1`).\n\n The old `error_logger` event handlers in STDLIB and SASL still exist, but they\n are not added by Erlang/OTP 21.0 or later.","ref":"logger_chapter.html#handlers"},{"type":"extras","title":"Formatters - Logging","doc":"A formatter can be used by the handler implementation to do the final formatting\nof a log event, before printing to the handler's destination. The handler\ncallback receives the formatter information as part of the handler\nconfiguration, which is passed as the second argument to\n[`HModule:log/2`](`c:logger_handler:log/2`).\n\nThe formatter information consist of a formatter module, `FModule` and its\nconfiguration, `FConfig`. `FModule` must export the following function, which\ncan be called by the handler:\n\n```text\nformat(LogEvent,FConfig)\n\t-> FormattedLogEntry\n```\n\nThe formatter information for a handler is set as a part of its configuration\nwhen the handler is added. It can also be changed during runtime with\n[`logger:set_handler_config(HandlerId,formatter,{Module,FConfig})` ](`logger:set_handler_config/3`),\nwhich overwrites the current formatter information, or with\n[`logger:update_formatter_config/2,3`](`logger:update_formatter_config/2`),\nwhich only modifies the formatter configuration.\n\nIf the formatter module exports the optional callback function\n[`check_config(FConfig)`](`c:logger_formatter:check_config/1`), Logger calls\nthis function when the formatter information is set or modified, to verify the\nvalidity of the formatter configuration.\n\nIf no formatter information is specified for a handler, Logger uses\n`logger_formatter` as default. See the `m:logger_formatter` manual page for more\ninformation about this module.","ref":"logger_chapter.html#formatters"},{"type":"extras","title":"Configuration - Logging","doc":"At system start, Logger is configured through Kernel configuration parameters.\nThe parameters that apply to Logger are described in section\n[Kernel Configuration Parameters](#kernel-configuration-parameters).\nExamples are found in section\n[Configuration Examples](#configuration-examples).\n\nDuring runtime, Logger configuration is changed via API functions. See section\n[Configuration API Functions](`m:logger#configuration-api-functions`) in the `m:logger`\nmanual page.","ref":"logger_chapter.html#configuration"},{"type":"extras","title":"Primary Logger Configuration - Logging","doc":"Logger API functions that apply to the primary Logger configuration are:\n\n- [`get_primary_config/0`](`logger:get_primary_config/0`)\n- [`set_primary_config/1,2`](`logger:set_primary_config/1`)\n- [`update_primary_config/1`](`logger:update_primary_config/1`)\n- [`add_primary_filter/2`](`logger:add_primary_filter/2`)\n- [`remove_primary_filter/1`](`logger:remove_primary_filter/1`)\n\nThe primary Logger configuration is a map with the following keys:\n\n- **`level = `{: #primary_level }`t:logger:level/0` ` | all | none`** - Specifies\n the primary log level, that is, log event that are equally or more severe than\n this level, are forwarded to the primary filters. Less severe log events are\n immediately discarded.\n\n See section [Log Level](#log-level) for a listing and\n description of possible log levels.\n\n The initial value of this option is set by the Kernel configuration parameter\n [`logger_level`](#logger_level). It is changed during runtime\n with\n [`logger:set_primary_config(level,Level)`](`logger:set_primary_config/2`).\n\n Defaults to `notice`.\n\n- **`filters = [{FilterId,Filter}]`** - Specifies the primary filters.\n\n - `FilterId = ` `t:logger:filter_id/0`\n - `Filter = ` `t:logger:filter/0`\n\n The initial value of this option is set by the Kernel configuration parameter\n [`logger`](#logger_parameter). During runtime, primary\n filters are added and removed with `logger:add_primary_filter/2` and\n `logger:remove_primary_filter/1`, respectively.\n\n See section [Filters](#filters) for more detailed\n information.\n\n Defaults to `[]`.\n\n- **`filter_default = log | stop`** - Specifies what happens to a log event if\n all filters return `ignore`, or if no filters exist.\n\n See section [Filters](#filters) for more information about\n how this option is used.\n\n Defaults to `log`.\n\n- **`metadata = `[`metadata()`](`t:logger:metadata/0`)** - The primary metadata\n to be used for all log calls.\n\n See section [Metadata](#metadata) for more information about\n how this option is used.\n\n Defaults to `#{}`.","ref":"logger_chapter.html#primary-logger-configuration"},{"type":"extras","title":"Handler Configuration - Logging","doc":"Logger API functions that apply to handler configuration are:\n\n- [`get_handler_config/0,1`](`logger:get_handler_config/0`)\n- [`set_handler_config/2,3`](`logger:set_handler_config/2`)\n- [`update_handler_config/2,3`](`logger:update_handler_config/2`)\n- [`add_handler_filter/3`](`logger:add_handler_filter/3`)\n- [`remove_handler_filter/2`](`logger:remove_handler_filter/2`)\n- [`update_formatter_config/2,3`](`logger:update_formatter_config/2`)\n\nThe configuration for a handler is a map with the following keys:\n\n- **`id =` `t:logger_handler:id/0`** - Automatically inserted by Logger. The\n value is the same as the `HandlerId` specified when adding the handler, and it\n cannot be changed.\n\n- **`module = module()`** - Automatically inserted by Logger. The value is the\n same as the `Module` specified when adding the handler, and it cannot be\n changed.\n\n- **`level =` `t:logger:level/0` ` | all | none`** - Specifies the log level for\n the handler, that is, log events that are equally or more severe than this\n level, are forwarded to the handler filters for this handler.\n\n See section [Log Level](#log-level) for a listing and\n description of possible log levels.\n\n The log level is specified when adding the handler, or changed during runtime\n with, for instance,\n [`logger:set_handler_config(HandlerId,level,Level)`](`logger:set_handler_config/3`).\n\n Defaults to `all`.\n\n- **`filters = [{FilterId,Filter}]`** - Specifies the handler filters.\n\n - `FilterId = ` `t:logger:filter_id/0`\n - `Filter = ` `t:logger:filter/0`\n\n Handler filters are specified when adding the handler, or added or removed\n during runtime with `logger:add_handler_filter/3` and\n `logger:remove_handler_filter/2`, respectively.\n\n See [Filters](#filters) for more detailed information.\n\n Defaults to `[]`.\n\n- **`filter_default = log | stop`** - Specifies what happens to a log event if\n all filters return `ignore`, or if no filters exist.\n\n See section [Filters](#filters) for more information about\n how this option is used.\n\n Defaults to `log`.\n\n- **`formatter = {FormatterModule,FormatterConfig}`** - Specifies a formatter\n that the handler can use for converting the log event term to a printable\n string.\n\n - `FormatterModule = module()`\n - `FormatterConfig =` `t:logger:formatter_config/0`\n\n The formatter information is specified when adding the handler. The formatter\n configuration can be changed during runtime with\n [`logger:update_formatter_config/2,3`](`logger:update_formatter_config/2`), or\n the complete formatter information can be overwritten with, for instance,\n `logger:set_handler_config/3`.\n\n See section [Formatters](#formatters) for more detailed\n information.\n\n Defaults to `{logger_formatter,DefaultFormatterConfig}`. See the\n `m:logger_formatter` manual page for information about this formatter and its\n default configuration.\n\n- **`config = term()`** - Handler specific configuration, that is, configuration\n data related to a specific handler implementation.\n\n The configuration for the built-in handlers is described in the\n `m:logger_std_h` and [`logger_disk_log_h` ](`m:logger_disk_log_h`)manual\n pages.\n\nNotice that `level` and `filters` are obeyed by Logger itself before forwarding\nthe log events to each handler, while `formatter` and all handler specific\noptions are left to the handler implementation.","ref":"logger_chapter.html#handler-configuration"},{"type":"extras","title":"Kernel Configuration Parameters - Logging","doc":"The following Kernel configuration parameters apply to Logger:\n\n- **`logger = [Config]`{: #logger_parameter }** - Specifies the configuration\n for [Logger](`m:logger`), except the primary log level, which is specified\n with [`logger_level`](#logger_level), and the compatibility\n with [SASL Error Logging](`e:sasl:error_logging.md`), which is specified with\n [`logger_sasl_compatible`](#logger_sasl_compatible).\n\n With this parameter, you can modify or disable the default handler, add custom\n handlers and primary logger filters, set log levels per module, and modify the\n [proxy](#logger-proxy) configuration.\n\n `Config` is any (zero or more) of the following:\n\n - **`{handler, default, undefined}`** - Disables the default handler. This\n allows another application to add its own default handler.\n\n Only one entry of this type is allowed.\n\n - **`{handler, HandlerId, Module, HandlerConfig}`** - If `HandlerId` is\n `default`, then this entry modifies the default handler, equivalent to\n calling\n\n ```text\n \t\tlogger:remove_handler(default)\n\n ```\n\n followed by\n\n ```erlang\n \t\tlogger:add_handler(default, Module, HandlerConfig)\n\n ```\n\n For all other values of `HandlerId`, this entry adds a new handler,\n equivalent to calling\n\n ```erlang\n \t\tlogger:add_handler(HandlerId, Module, HandlerConfig)\n\n ```\n\n Multiple entries of this type are allowed.\n\n - **`{filters, FilterDefault, [Filter]}`** - Adds the specified primary\n filters.\n\n - `FilterDefault = log | stop`\n - `Filter = {FilterId, {FilterFun, FilterConfig}}`\n\n Equivalent to calling\n\n ```erlang\n \t\tlogger:add_primary_filter(FilterId, {FilterFun, FilterConfig})\n\n ```\n\n for each `Filter`.\n\n `FilterDefault` specifies the behaviour if all primary filters return\n `ignore`, see section [Filters](#filters).\n\n Only one entry of this type is allowed.\n\n - **`{module_level, Level, [Module]}`** - Sets module log level for the given\n modules. Equivalent to calling\n\n ```erlang\n \t\tlogger:set_module_level(Module, Level)\n ```\n\n for each `Module`.\n\n Multiple entries of this type are allowed.\n\n - **`{proxy, ProxyConfig}`** - Sets the proxy configuration, equivalent to\n calling\n\n ```text\n \t\tlogger:set_proxy_config(ProxyConfig)\n\n ```\n\n Only one entry of this type is allowed.\n\n See section [Configuration Examples](#configuration-examples) for\n examples using the `logger` parameter for system configuration.\n\n- **`logger_metadata = map()`{: #logger_metadata }** - Specifies the primary\n metadata. See the [`kernel(6)`](kernel_app.md#logger_metadata) manual page for\n more information about this parameter.\n\n- **`logger_level = Level`{: #logger_level }** - Specifies the primary log\n level. See the [`kernel(6)`](kernel_app.md#logger_level) manual page for more\n information about this parameter.\n\n- **`logger_sasl_compatible = true | false`{: #logger_sasl_compatible }** -\n Specifies Logger's compatibility with\n [SASL Error Logging](`e:sasl:error_logging.md`). See the\n [`kernel(6)`](kernel_app.md#logger_sasl_compatible) manual page for more\n information about this parameter.","ref":"logger_chapter.html#kernel-configuration-parameters"},{"type":"extras","title":"Configuration Examples - Logging","doc":"The value of the Kernel configuration parameter `logger` is a list of tuples. It\nis possible to write the term on the command line when starting an erlang node,\nbut as the term grows, a better approach is to use the system configuration\nfile. See the [`config(4)`](config.md) manual page for more information about\nthis file.\n\nEach of the following examples shows a simple system configuration file that\nconfigures Logger according to the description.\n\nModify the default handler to print to a file instead of\n[`standard_io`](`t:io:standard_io/0`):\n\n```erlang\n[{kernel,\n [{logger,\n [{handler, default, logger_std_h, % {handler, HandlerId, Module,\n #{config => #{file => \"log/erlang.log\"}}} % Config}\n ]}]}].\n```\n\nModify the default handler to print each log event as a single line:\n\n```erlang\n[{kernel,\n [{logger,\n [{handler, default, logger_std_h,\n #{formatter => {logger_formatter, #{single_line => true}}}}\n ]}]}].\n```\n\nModify the default handler to print the pid of the logging process for each log\nevent:\n\n```erlang\n[{kernel,\n [{logger,\n [{handler, default, logger_std_h,\n #{formatter => {logger_formatter,\n #{template => [time,\" \",pid,\" \",msg,\"\\n\"]}}}}\n ]}]}].\n```\n\nModify the default handler to only print errors and more severe log events to\n\"log/erlang.log\", and add another handler to print all log events to\n\"log/debug.log\".\n\n```erlang\n[{kernel,\n [{logger,\n [{handler, default, logger_std_h,\n #{level => error,\n config => #{file => \"log/erlang.log\"}}},\n {handler, info, logger_std_h,\n #{level => debug,\n config => #{file => \"log/debug.log\"}}}\n ]}]}].\n```","ref":"logger_chapter.html#configuration-examples"},{"type":"extras","title":"Backwards Compatibility with error_logger - Logging","doc":"Logger provides backwards compatibility with `error_logger` in the following\nways:\n\n- **API for Logging** - The `error_logger` API still exists, but should only be\n used by legacy code. It will be removed in a later release.\n\n Calls to [`error_logger:error_report/1,2`](`error_logger:error_report/1`),\n [`error_logger:error_msg/1,2`](`error_logger:error_msg/1`), and corresponding\n functions for warning and info messages, are all forwarded to Logger as calls\n to [`logger:log(Level,Report,Metadata)`](`logger:log/3`).\n\n `Level = error | warning | info` and is taken from the function name. `Report`\n contains the actual log message, and `Metadata` contains additional\n information which can be used for creating backwards compatible events for\n legacy `error_logger` event handlers, see section\n [Legacy Event Handlers](#legacy_event_handlers).\n\n- **Output Format** - To get log events on the same format as produced by\n `error_logger_tty_h` and `error_logger_file_h`, use the default formatter,\n `logger_formatter`, with configuration parameter `legacy_header` set to\n `true`. This is the default configuration of the `default` handler started by\n Kernel.\n\n- **Default Format of Log Events from OTP** - By default, all log events\n originating from within OTP, except the former so called \"SASL reports\", look\n the same as before.\n\n- **[](){: #sasl_reports } SASL Reports** - By SASL reports we mean supervisor\n reports, crash reports and progress reports.\n\n Prior to Erlang/OTP 21.0, these reports were only logged when the SASL\n application was running, and they were printed through SASL's own event\n handlers `sasl_report_tty_h` and `sasl_report_file_h`.\n\n The destination of these log events was configured by\n [SASL configuration parameters](`e:sasl:sasl_app.md#deprecated_error_logger_config`).\n\n Due to the specific event handlers, the output format slightly differed from\n other log events.\n\n As of Erlang/OTP 21.0, the concept of SASL reports is removed, meaning that\n the default behaviour is as follows:\n\n - Supervisor reports, crash reports, and progress reports are no longer\n connected to the SASL application.\n - Supervisor reports and crash reports are issued as `error` level log events,\n and are logged through the default handler started by Kernel.\n - Progress reports are issued as `info` level log events, and since the\n default primary log level is `notice`, these are not logged by default. To\n enable printing of progress reports, set the\n [primary log level](#primary_level) to `info`.\n - The output format is the same for all log events.\n\n If the old behaviour is preferred, the Kernel configuration parameter\n [`logger_sasl_compatible`](kernel_app.md#logger_sasl_compatible) can be set to\n `true`. The\n [SASL configuration parameters](`e:sasl:sasl_app.md#deprecated_error_logger_config`)\n can then be used as before, and the SASL reports will only be printed if the\n SASL application is running, through a second log handler named `sasl`.\n\n All SASL reports have a metadata field `domain` which is set to `[otp,sasl]`.\n This field can be used by filters to stop or allow the log events.\n\n See section [SASL User's Guide](`e:sasl:error_logging.md`) for more\n information about the old SASL error logging functionality.\n\n- **[](){: #legacy_event_handlers } Legacy Event Handlers** - To use event\n handlers written for `error_logger`, just add your event handler\n with\n\n ```text\n error_logger:add_report_handler/1,2.\n ```\n\n This automatically starts the error logger event manager, and adds\n `error_logger` as a handler to Logger, with the following configuration:\n\n ```erlang\n #{level => info,\n filter_default => log,\n filters => []}.\n ```\n\n > #### Note {: .info }\n >\n > This handler ignores events that do not originate from the `error_logger`\n > API, or from within OTP. This means that if your code uses the Logger API\n > for logging, then your log events will be discarded by this handler.\n >\n > The handler is not overload protected.","ref":"logger_chapter.html#backwards-compatibility-with-error_logger"},{"type":"extras","title":"Error Handling - Logging","doc":"Logger does, to a certain extent, check its input data before forwarding a log\nevent to filters and handlers. It does, however, not evaluate report callbacks,\nor check the validity of format strings and arguments. This means that all\nfilters and handlers must be careful when formatting the data of a log event,\nmaking sure that it does not crash due to bad input data or faulty callbacks.\n\nIf a filter or handler still crashes, Logger will remove the filter or handler\nin question from the configuration, and print a short error message to the\nterminal. A debug event containing the crash reason and other details is also\nissued.\n\nSee section [Log Message](#log-message) for more information\nabout report callbacks and valid forms of log messages.","ref":"logger_chapter.html#error-handling"},{"type":"extras","title":"Example: Add a handler to log info events to file - Logging","doc":"When starting an Erlang node, the default behaviour is that all log events on\nlevel `notice` or more severe, are logged to the terminal via the default\nhandler. To also log info events, you can either change the primary log level to\n`info`:\n\n```text\n1> logger:set_primary_config(level, info).\nok\n```\n\nor set the level for one or a few modules only:\n\n```erlang\n2> logger:set_module_level(mymodule, info).\nok\n```\n\nThis allows info events to pass through to the default handler, and be printed\nto the terminal as well. If there are many info events, it can be useful to\nprint these to a file instead.\n\nFirst, set the log level of the default handler to `notice`, preventing it from\nprinting info events to the terminal:\n\n```erlang\n3> logger:set_handler_config(default, level, notice).\nok\n```\n\nThen, add a new handler which prints to file. You can use the handler module\n`m:logger_std_h`, and configure it to log to file:\n\n```erlang\n4> Config = #{config => #{file => \"./info.log\"}, level => info}.\n#{config => #{file => \"./info.log\"},level => info}\n5> logger:add_handler(myhandler, logger_std_h, Config).\nok\n```\n\nSince `filter_default` defaults to `log`, this handler now receives all log\nevents. If you want info events only in the file, you must add a filter to stop\nall non-info events. The built-in filter `logger_filters:level/2` can do this:\n\n```erlang\n6> logger:add_handler_filter(myhandler, stop_non_info,\n {fun logger_filters:level/2, {stop, neq, info}}).\nok\n```\n\nSee section [Filters](#filters) for more information about the\nfilters and the `filter_default` configuration parameter.","ref":"logger_chapter.html#example-add-a-handler-to-log-info-events-to-file"},{"type":"extras","title":"Example: Implement a handler - Logging","doc":"`m:logger_handler` describes the callback functions that can be implemented for\na Logger handler.\n\nA handler callback module must export:\n\n- `log(Log, Config)`\n\nIt can optionally also export some, or all, of the following:\n\n- `adding_handler(Config)`\n- `removing_handler(Config)`\n- `changing_config(SetOrUpdate, OldConfig, NewConfig)`\n- `filter_config(Config)`\n\nWhen a handler is added, by for example a call to\n[`logger:add_handler(Id, HModule, Config)`](`logger:add_handler/3`), Logger\nfirst calls `HModule:adding_handler(Config)`. If this function returns\n`{ok,Config1}`, Logger writes `Config1` to the configuration database, and the\n`logger:add_handler/3` call returns. After this, the handler is installed and\nmust be ready to receive log events as calls to `HModule:log/2`.\n\nA handler can be removed by calling\n[`logger:remove_handler(Id)`](`logger:remove_handler/1`). Logger calls\n`HModule:removing_handler(Config)`, and removes the handler's configuration from\nthe configuration database.\n\nWhen [`logger:set_handler_config/2,3`](`logger:set_handler_config/2`) or\n[`logger:update_handler_config/2,3`](`logger:update_handler_config/2`) is\ncalled, Logger calls\n`HModule:changing_config(SetOrUpdate, OldConfig, NewConfig)`. If this function\nreturns `{ok,NewConfig1}`, Logger writes `NewConfig1` to the configuration\ndatabase.\n\nWhen `logger:get_config/0` or\n[`logger:get_handler_config/0,1`](`logger:get_handler_config/0`) is called,\nLogger calls `HModule:filter_config(Config)`. This function must return the\nhandler configuration where internal data is removed.\n\nA simple handler that prints to the terminal can be implemented as follows:\n\n```erlang\n-module(myhandler1).\n-export([log/2]).\n\nlog(LogEvent, #{formatter := {FModule, FConfig}}) ->\n io:put_chars(FModule:format(LogEvent, FConfig)).\n```\n\nNotice that the above handler does not have any overload protection, and all log\nevents are printed directly from the client process.\n\nFor information and examples of overload protection, please refer to section\n[Protecting the Handler from Overload](#overload_protection),\nand the implementation of `m:logger_std_h` and\n[`logger_disk_log_h` ](`m:logger_disk_log_h`).\n\nThe following is a simpler example of a handler which logs to a file through one\nsingle process:\n\n```erlang\n-module(myhandler2).\n-export([adding_handler/1, removing_handler/1, log/2]).\n-export([init/1, handle_call/3, handle_cast/2, terminate/2]).\n\nadding_handler(Config) ->\n MyConfig = maps:get(config,Config,#{file => \"myhandler2.log\"}),\n {ok, Pid} = gen_server:start(?MODULE, MyConfig, []),\n {ok, Config#{config => MyConfig#{pid => Pid}}}.\n\nremoving_handler(#{config := #{pid := Pid}}) ->\n gen_server:stop(Pid).\n\nlog(LogEvent,#{config := #{pid := Pid}} = Config) ->\n gen_server:cast(Pid, {log, LogEvent, Config}).\n\ninit(#{file := File}) ->\n {ok, Fd} = file:open(File, [append, {encoding, utf8}]),\n {ok, #{file => File, fd => Fd}}.\n\nhandle_call(_, _, State) ->\n {reply, {error, bad_request}, State}.\n\nhandle_cast({log, LogEvent, Config}, #{fd := Fd} = State) ->\n do_log(Fd, LogEvent, Config),\n {noreply, State}.\n\nterminate(_Reason, #{fd := Fd}) ->\n _ = file:close(Fd),\n ok.\n\ndo_log(Fd, LogEvent, #{formatter := {FModule, FConfig}}) ->\n String = FModule:format(LogEvent, FConfig),\n io:put_chars(Fd, String).\n```\n\n[](){: #overload_protection }","ref":"logger_chapter.html#example-implement-a-handler"},{"type":"extras","title":"Protecting the Handler from Overload - Logging","doc":"The default handlers, `m:logger_std_h` and `m:logger_disk_log_h`, feature\nmultiple overload protection mechanisms, which make it possible for the\nhandlers to survive, and stay responsive, during periods of high load\n(when huge numbers of incoming log requests must be handled).\n\nThe mechanisms are as follows:\n* [**message queue length**](#message-queue-length): the handler process tracks\nits message queue length and takes actions depending on its size, from turning\non a sync mode to dropping messages.\n* [**limit the number of logs emitted**](#controlling-bursts-of-log-requests):\nthe handlers will handle a maximum number of log events per time unit,\ndefaulting to 500 per second.\n* [**terminate an overloaded handler**](#terminating-an-overloaded-handler):\na handler can be terminated and restarted automatically if it exceeds message\nqueue length or memory thresholds - this is disabled by default.\n\nThese mechanisms are described in more detail in the following sections.","ref":"logger_chapter.html#protecting-the-handler-from-overload"},{"type":"extras","title":"Message Queue Length - Logging","doc":"The handler process keeps track of the length of its message queue and takes\nsome form of action when the current length exceeds a configurable threshold.\nThe purpose is to keep the handler in, or to as quickly as possible get the\nhandler into, a state where it can keep up with the pace of incoming log events.\nThe memory use of the handler must never grow larger and larger, since that will\neventually cause the handler to crash. These three thresholds, with associated\nactions, exist:\n\n- **`sync_mode_qlen`** - As long as the length of the message queue is lower\n than this value, all log events are handled asynchronously. This means that\n the client process sending the log event, by calling a log function in the\n [Logger API](#logger-api), does not wait for a response from\n the handler but continues executing immediately after the event is sent. It is\n not affected by the time it takes the handler to print the event to the log\n device. If the message queue grows larger than this value, the handler starts\n handling log events synchronously instead, meaning that the client process\n sending the event must wait for a response. When the handler reduces the\n message queue to a level below the `sync_mode_qlen` threshold, asynchronous\n operation is resumed. The switch from asynchronous to synchronous mode can\n slow down the logging tempo of one, or a few, busy senders, but cannot protect\n the handler sufficiently in a situation of many busy concurrent senders.\n\n Defaults to `10` messages.\n\n- **`drop_mode_qlen`** - When the message queue grows larger than this\n threshold, the handler switches to a mode in which it drops all new events\n that senders want to log. Dropping an event in this mode means that the call\n to the log function never results in a message being sent to the handler, but\n the function returns without taking any action. The handler keeps logging the\n events that are already in its message queue, and when the length of the\n message queue is reduced to a level below the threshold, synchronous or\n asynchronous mode is resumed. Notice that when the handler activates or\n deactivates drop mode, information about it is printed in the log.\n The emitted log message is on the `:notice` level and looks like this:\n `Handler :default switched from :sync to :drop mode`\n\n Defaults to `200` messages.\n\n- **`flush_qlen`** - If the length of the message queue grows larger than this\n threshold, a flush (delete) operation takes place. To flush events, the\n handler discards the messages in the message queue by receiving them in a loop\n without logging. Client processes waiting for a response from a synchronous\n log request receive a reply from the handler indicating that the request is\n dropped. The handler process increases its priority during the flush loop to\n make sure that no new events are received during the operation. Notice that\n after the flush operation is performed, the handler prints information in the\n log about how many events have been deleted.\n The emitted log message is on the `:notice` level and looks like this:\n `Handler :default flushed 1070 log events`\n\n Defaults to `1000` messages.\n\nFor the overload protection algorithm to work properly, it is required that:\n\n`sync_mode_qlen = 1`\n\nTo disable certain modes, do the following:\n\n- If `sync_mode_qlen` is set to `0`, all log events are handled synchronously.\n That is, asynchronous logging is disabled.\n- If `sync_mode_qlen` is set to the same value as `drop_mode_qlen`, synchronous\n mode is disabled. That is, the handler always runs in asynchronous mode,\n unless dropping or flushing is invoked.\n- If `drop_mode_qlen` is set to the same value as `flush_qlen`, drop mode is\n disabled and can never occur.\n\nDuring high load scenarios, the length of the handler message queue rarely grows\nin a linear and predictable way. Instead, whenever the handler process is\nscheduled in, it can have an almost arbitrary number of messages waiting in the\nmessage queue. It is for this reason that the overload protection mechanism is\nfocused on acting quickly, and quite drastically, such as immediately dropping\nor flushing messages, when a large queue length is detected.\n\nThe values of the previously listed thresholds can be specified by the user.\nThis way, a handler can be configured to, for example, not drop or flush\nmessages unless the message queue length of the handler process grows extremely\nlarge. Notice that large amounts of memory can be required for the node under\nsuch circumstances. Another example of user configuration is when, for\nperformance reasons, the client processes must never be blocked by synchronous\nlog requests. It is possible, perhaps, that dropping or flushing events is still\nacceptable, since it does not affect the performance of the client processes\nsending the log events.\n\nA configuration example:\n\n```erlang\nlogger:add_handler(my_standard_h, logger_std_h,\n #{config => #{file => \"./system_info.log\",\n sync_mode_qlen => 100,\n drop_mode_qlen => 1000,\n flush_qlen => 2000}}).\n```","ref":"logger_chapter.html#message-queue-length"},{"type":"extras","title":"Controlling Bursts of Log Requests - Logging","doc":"Large bursts of log events - many events received by the handler under a short\nperiod of time - can potentially cause problems, such as:\n\n- Log files grow very large, very quickly.\n- Circular logs wrap too quickly so that important data is overwritten.\n- Write buffers grow large, which slows down file sync operations.\n\nNote that these examples apply to file-based logging. If you're logging to\nthe console the protections discussed below should be safe to disable or\ntweak, as long as your system can handle the load of them.\n\nFor this reason, both built-in handlers offer the possibility to specify the\nmaximum number of events to be handled within a certain time frame. With this\nburst control feature enabled, the handler can avoid choking the log with\nmassive amounts of printouts. The configuration parameters are:\n\n- **`burst_limit_enable`** - Value `true` enables burst control and `false`\n disables it.\n\n Defaults to `true`.\n\n- **`burst_limit_max_count`** - This is the maximum number of events to handle\n within a `burst_limit_window_time` time frame. After the limit is reached,\n successive events are dropped until the end of the time frame.\n\n Defaults to `500` events.\n\n- **`burst_limit_window_time`** - See the previous description of\n `burst_limit_max_count`.\n\n Defaults to `1000` milliseconds.\n\nA configuration example:\n\n```erlang\nlogger:add_handler(my_disk_log_h, logger_disk_log_h,\n #{config => #{file => \"./my_disk_log\",\n burst_limit_enable => true,\n burst_limit_max_count => 20,\n burst_limit_window_time => 500}}).\n```","ref":"logger_chapter.html#controlling-bursts-of-log-requests"},{"type":"extras","title":"Terminating an Overloaded Handler - Logging","doc":"It is possible that a handler, even if it can successfully manage peaks of high\nload without crashing, can build up a large message queue, or use a large amount\nof memory. The overload protection mechanism includes an automatic termination\nand restart feature for the purpose of guaranteeing that a handler does not grow\nout of bounds. The feature is configured with the following parameters:\n\n- **`overload_kill_enable`** - Value `true` enables the feature and `false`\n disables it.\n\n Defaults to `false`.\n\n- **`overload_kill_qlen`** - This is the maximum allowed queue length. If the\n message queue grows larger than this, the handler process is terminated.\n\n Defaults to `20000` messages.\n\n- **`overload_kill_mem_size`** - This is the maximum memory size that the\n handler process is allowed to use. If the handler grows larger than this, the\n process is terminated.\n\n Defaults to `3000000` bytes.\n\n- **`overload_kill_restart_after`** - If the handler is terminated, it restarts\n automatically after a delay specified in milliseconds. The value `infinity`\n prevents restarts.\n\n Defaults to `5000` milliseconds.\n\nIf the handler process is terminated because of overload, it prints information\nabout it in the log. It also prints information about when a restart has taken\nplace, and the handler is back in action.\n\n> #### Note {: .info }\n>\n> The sizes of the log events affect the memory needs of the handler. For\n> information about how to limit the size of log events, see the\n> `m:logger_formatter` manual page.","ref":"logger_chapter.html#terminating-an-overloaded-handler"},{"type":"extras","title":"Logger Proxy - Logging","doc":"The Logger proxy is an Erlang process which is part of the Kernel application's\nsupervision tree. During startup, the proxy process registers itself as the\n`system_logger`, meaning that log events produced by the emulator are sent to\nthis process.\n\nWhen a log event is issued on a process which has its group leader on a remote\nnode, Logger automatically forwards the log event to the group leader's node. To\nachieve this, it first sends the log event as an Erlang message from the\noriginal client process to the proxy on the local node, and the proxy in turn\nforwards the event to the proxy on the remote node.\n\nWhen receiving a log event, either from the emulator or from a remote node, the\nproxy calls the Logger API to log the event.\n\nThe proxy process is overload protected in the same way as described in section\n[Protecting the Handler from Overload](#overload_protection),\nbut with the following default values:\n\n```erlang\n #{sync_mode_qlen => 500,\n drop_mode_qlen => 1000,\n flush_qlen => 5000,\n burst_limit_enable => false,\n overload_kill_enable => false}\n```\n\nFor log events from the emulator, synchronous message passing mode is not\napplicable, since all messages are passed asynchronously by the emulator. Drop\nmode is achieved by setting the `system_logger` to `undefined`, forcing the\nemulator to drop events until it is set back to the proxy pid again.\n\nThe proxy uses `erlang:send_nosuspend/2` when sending log events to a remote\nnode. If the message could not be sent without suspending the sender, it is\ndropped. This is to avoid blocking the proxy process.","ref":"logger_chapter.html#logger-proxy"},{"type":"extras","title":"See Also - Logging","doc":"`m:disk_log`, `m:erlang`, `m:error_logger`, `m:logger`, `m:logger_disk_log_h`,\n`m:logger_filters`, `m:logger_formatter`, `m:logger_std_h`,\n[`sasl(6)`](`e:sasl:sasl_app.md`)","ref":"logger_chapter.html#see-also"},{"type":"extras","title":"Logging Cookbook","doc":"\n# Logging Cookbook\n\nUsing and especially configuring Logger can be difficult at times as there are\nmany different options that can be changed and often more than one way to\nachieve the same result. This User's Guide tries to help by giving many\ndifferent examples of how you can use logger.\n\nFor more examples of practical use-cases of using Logger, Fred Hebert's blog\npost\n[Erlang/OTP 21's new logger](https://ferd.ca/erlang-otp-21-s-new-logger.html) is\na great starting point.\n\n> #### Note {: .info }\n>\n> If you find that some common Logger usage is missing from this guide, please\n> open a pull request on github with the suggested addition","ref":"logger_cookbook.html"},{"type":"extras","title":"Get Logger information - Logging Cookbook","doc":"","ref":"logger_cookbook.html#get-logger-information"},{"type":"extras","title":"Print the primary Logger configurations. - Logging Cookbook","doc":"```erlang\n1> logger:i(primary).\nPrimary configuration:\n Level: notice\n Filter Default: log\n Filters:\n (none)\n```\n\nIt is also possible to fetch the configuration using\n[`logger:get_primary_config()`](`logger:get_primary_config/0`).\n\n#### See also\n\n- [logger:i()](`logger:i/0`)\n- [Configuration](logger_chapter.md#configuration) in the Logging User's Guide","ref":"logger_cookbook.html#print-the-primary-logger-configurations"},{"type":"extras","title":"Print the configuration of all handlers. - Logging Cookbook","doc":"```erlang\n2> logger:i(handlers).\nHandler configuration:\n Id: default\n Module: logger_std_h\n Level: all\n Formatter:\n Module: logger_formatter\n Config:\n legacy_header: true\n single_line: false\n Filter Default: stop\n Filters:\n Id: remote_gl\n Fun: fun logger_filters:remote_gl/2\n Arg: stop\n Id: domain\n Fun: fun logger_filters:domain/2\n Arg: {log,super,[otp,sasl]}\n Id: no_domain\n Fun: fun logger_filters:domain/2\n Arg: {log,undefined,[]}\n Handler Config:\n burst_limit_enable: true\n burst_limit_max_count: 500\n burst_limit_window_time: 1000\n drop_mode_qlen: 200\n filesync_repeat_interval: no_repeat\n flush_qlen: 1000\n overload_kill_enable: false\n overload_kill_mem_size: 3000000\n overload_kill_qlen: 20000\n overload_kill_restart_after: 5000\n sync_mode_qlen: 10\n type: standard_io\n```\n\nYou can also print the configuration of a specific handler using\n[`logger:i(HandlerName)`](`logger:i/1`), or fetch the configuration using\n[`logger:get_handler_config()`](`logger:get_handler_config/0`), or\n[`logger:get_handler_config(HandlerName)`](`logger:get_handler_config/1`) for a\nspecific handler.\n\n#### See also\n\n- [`logger:i()`](`logger:i/0`)\n- [Configuration](logger_chapter.md#configuration) in the Logging User's Guide","ref":"logger_cookbook.html#print-the-configuration-of-all-handlers"},{"type":"extras","title":"Configure the Logger - Logging Cookbook","doc":"","ref":"logger_cookbook.html#configure-the-logger"},{"type":"extras","title":"Where did my progress reports go? - Logging Cookbook","doc":"In OTP-21 the default primary log level is `notice`. The means that many log\nmessages are by default not printed. This includes the progress reports of\nsupervisors. In order to get progress reports you need to raise the primary log\nlevel to `info`\n\n```erlang\n$ erl -kernel logger_level info\n=PROGRESS REPORT==== 4-Nov-2019::16:33:11.742069 ===\n application: kernel\n started_at: nonode@nohost\n=PROGRESS REPORT==== 4-Nov-2019::16:33:11.746546 ===\n application: stdlib\n started_at: nonode@nohost\nEshell V10.5.3 (abort with ^G)\n1>\n```","ref":"logger_cookbook.html#where-did-my-progress-reports-go"},{"type":"extras","title":"Configure Logger formatter - Logging Cookbook","doc":"In order to fit better into your existing logging infrastructure Logger can\nformat its logging messages any way you want to. Either you can use the built-in\nformatter, or you can build your own.","ref":"logger_cookbook.html#configure-logger-formatter"},{"type":"extras","title":"Single line configuration - Logging Cookbook","doc":"Since single line logging is the default of the built-in formatter you only have\nto provide the empty map as the configuration. The example below uses the\n`sys.config` to change the formatter configuration.\n\n```erlang\n$ cat sys.config\n[{kernel,\n [{logger,\n [{handler, default, logger_std_h,\n #{ formatter => {logger_formatter, #{ }}}}]}]}].\n$ erl -config sys\nEshell V10.5.1 (abort with ^G)\n1> logger:error(\"Oh noes, an error\").\n1962-10-03T11:07:47.466763-04:00 error: Oh noes, an error\n```\n\nHowever, if you just want to change it for the current session you can also do\nthat.\n\n```erlang\n1> logger:set_handler_config(default, formatter, {logger_formatter, #{}}).\nok\n2> logger:error(\"Oh noes, another error\").\n1962-10-04T15:34:02.648713-04:00 error: Oh noes, another error\n```\n\n#### See also\n\n- [logger_formatter's Configuration](`t:logger_formatter:config/0`)\n- [Formatters](logger_chapter.md#formatters) in the Logging User's Guide\n- `logger:set_handler_config/3`","ref":"logger_cookbook.html#single-line-configuration"},{"type":"extras","title":"Add file and line number to log entries - Logging Cookbook","doc":"You can change what is printed to the log by using the formatter template:\n\n```erlang\n$ cat sys.config\n[{kernel,\n [{logger,\n [{handler, default, logger_std_h,\n #{ formatter => {logger_formatter,\n #{ template => [time,\" \", file,\":\",line,\" \",level,\": \",msg,\"\\n\"] }}}}]}]}].\n$ erl -config sys\nEshell V10.5.1 (abort with ^G)\n1> logger:error(\"Oh noes, more errors\",#{ file => \"shell.erl\", line => 1 }).\n1962-10-05T07:37:44.104241+02:00 shell.erl:1 error: Oh noes, more errors\n```\n\nNote that file and line have to be added in the metadata by the caller of\n`logger:log/3` as otherwise Logger will not know from where it was called. The\nfile and line number are automatically added if you use the `?LOG_ERROR` macros\nin `kernel/include/logger.hrl`.\n\n#### See also\n\n- [logger_formatter's Configuration](`t:logger_formatter:config/0`)\n- [logger_formatter's Template](`t:logger_formatter:template/0`)\n- [Logger Macros](`m:logger#module-macros`)\n- [Metadata](logger_chapter.md#metadata) in the Logging User's Guide","ref":"logger_cookbook.html#add-file-and-line-number-to-log-entries"},{"type":"extras","title":"Configuring handlers - Logging Cookbook","doc":"","ref":"logger_cookbook.html#configuring-handlers"},{"type":"extras","title":"Print logs to a file - Logging Cookbook","doc":"Instead of printing the logs to stdout we print them to a rotating file log.\n\n```erlang\n$ cat sys.config\n[{kernel,\n [{logger,\n [{handler, default, logger_std_h,\n #{ config => #{ file => \"log/erlang.log\",\n max_no_bytes => 4096,\n max_no_files => 5},\n formatter => {logger_formatter, #{}}}}]}]}].\n$ erl -config sys\nEshell V10.5.1 (abort with ^G)\n1> logger:error(\"Oh noes, even more errors\").\nok\n2> erlang:halt().\n$ cat log/erlang.log\n2019-10-07T11:47:16.837958+02:00 error: Oh noes, even more errors\n```\n\n#### See also\n\n- `m:logger_std_h`\n- [Handlers](logger_chapter.md#handlers) in the Logging User's Guide","ref":"logger_cookbook.html#print-logs-to-a-file"},{"type":"extras","title":"Debug only handler - Logging Cookbook","doc":"Add a handler that prints `debug` log events to a file, while the default\nhandler prints only up to `notice` level events to standard out.\n\n```erlang\n$ cat sys.config\n[{kernel,\n [{logger_level, all},\n {logger,\n [{handler, default, logger_std_h,\n #{ level => notice }},\n {handler, debug, logger_std_h,\n #{ filters => [{debug,{fun logger_filters:level/2, {stop, neq, debug}}}],\n config => #{ file => \"log/debug.log\" } }}\n ]}]}].\n$ erl -config sys\nEshell V10.5.1 (abort with ^G)\n1> logger:error(\"Oh noes, even more errors\").\n=ERROR REPORT==== 9-Oct-2019::14:40:54.784162 ===\nOh noes, even more errors\nok\n2> logger:debug(\"A debug event\").\nok\n3> erlang:halt().\n$ cat log/debug.log\n2019-10-09T14:41:03.680541+02:00 debug: A debug event\n```\n\nIn the configuration above we first raise the primary log level to max in order\nfor the debug log events to get to the handlers. Then we configure the default\nhandler to only log notice and below events, the default log level for a handler\nis `all`. Then the debug handler is configured with a filter to stop any log\nmessage that is not a debug level message.\n\nIt is also possible to do the same changes in an already running system using\nthe `logger` module. Then you do like this:\n\n```erlang\n$ erl\n1> logger:set_handler_config(default, level, notice).\nok\n2> logger:add_handler(debug, logger_std_h, #{\n filters => [{debug,{fun logger_filters:level/2, {stop, neq, debug}}}],\n config => #{ file => \"log/debug.log\" } }).\nok\n3> logger:set_primary_config(level, all).\nok\n```\n\nIt is important that you do not raise the primary log level before adjusting the\ndefault handler's level as otherwise your standard out may be flooded by debug\nlog messages.\n\n#### See also\n\n- `m:logger_std_h`\n- [Filters](logger_chapter.md#filters) in the Logging User's Guide","ref":"logger_cookbook.html#debug-only-handler"},{"type":"extras","title":"Logging - Logging Cookbook","doc":"","ref":"logger_cookbook.html#logging"},{"type":"extras","title":"What to log and how - Logging Cookbook","doc":"The simplest way to log something is by using the Logger macros and give a\nreport to the macro. For example if you want to log an error:\n\n```erlang\n?LOG_ERROR(#{ what => http_error, status => 418, src => ClientIP, dst => ServerIP }).\n```\n\nThis will print the following in the default log:\n\n```text\n=ERROR REPORT==== 10-Oct-2019::12:13:10.089073 ===\n dst: {8,8,4,4}\n src: {8,8,8,8}\n status: 418\n what: http_error\n```\n\nor the below if you use a single line formatter:\n\n```text\n2019-10-10T12:14:11.921843+02:00 error: dst: {8,8,4,4}, src: {8,8,8,8}, status: 418, what: http_error\n```\n\n#### See also\n\n- [Log Message](logger_chapter.md#log-message) in the Logging User's Guide","ref":"logger_cookbook.html#what-to-log-and-how"},{"type":"extras","title":"Report call-backs and printing of events - Logging Cookbook","doc":"If you want to do structured logging, but still want to have some control of how\nthe final log message is formatted you can give a `report_cb` as part of the\nmetadata with your log event.\n\n```erlang\nReportCB = fun(#{ what := What, status := Status, src := Src, dst := Dst }) ->\n {ok, #hostent{ h_name = SrcName }} = inet:gethostbyaddr(Src),\n {ok, #hostent{ h_name = DstName }} = inet:gethostbyaddr(Dst),\n {\"What: ~p~nStatus: ~p~nSrc: ~s (~s)~nDst: ~s (~s)~n\",\n [What, Status, inet:ntoa(Src), SrcName, inet:ntoa(Dst), DstName]}\n end,\n?LOG_ERROR(#{ what => http_error, status => 418, src => ClientIP, dst => ServerIP },\n #{ report_cb => ReportCB }).\n```\n\nThis will print the following:\n\n```text\n=ERROR REPORT==== 10-Oct-2019::13:29:02.230863 ===\nWhat: http_error\nStatus: 418\nSrc: 8.8.8.8 (dns.google)\nDst: 192.121.151.106 (erlang.org)\n```\n\nNote that the order that things are printed have changed, and also I added a\nreverse-dns lookup of the IP address. This will not print as nicely when using a\nsingle line formatter, however you can also use a report_cb fun with 2 arguments\nwhere the second argument is the formatting options.\n\n#### See also\n\n- [Log Message](logger_chapter.md#log-message) in the Logging User's Guide\n- [Logger Report Callbacks](`t:logger:report_cb/0`)","ref":"logger_cookbook.html#report-call-backs-and-printing-of-events"},{"type":"extras","title":"Filters - Logging Cookbook","doc":"Filters are used to remove or change log events before they reach the handlers.","ref":"logger_cookbook.html#filters"},{"type":"extras","title":"Process filters - Logging Cookbook","doc":"If we only want debug messages from a specific process it is possible to do this\nwith a filter like this:\n\n```erlang\n%% Initial setup to use a filter for the level filter instead of the primary level\nPrimaryLevel = maps:get(level, logger:get_primary_config()),\nok = logger:add_primary_filter(primary_level,\n {fun logger_filters:level/2, {log, gteq, PrimaryLevel}}),\nlogger:set_primary_config(filter_default, stop),\nlogger:set_primary_config(level, all),\n\n%% Test that things work as they should\nlogger:notice(\"Notice should be logged\"),\nlogger:debug(\"Should not be logged\"),\n\n%% Add the filter to allow PidToLog to send debug events\nPidToLog = self(),\nPidFilter = fun(LogEvent, _) when PidToLog =:= self() -> LogEvent;\n (_LogEvent, _) -> ignore end,\nok = logger:add_primary_filter(pid, {PidFilter,[]}),\nlogger:debug(\"Debug should be logged\").\n```\n\nThere is a bit of setup needed to allow filters to decide whether a specific\nprocess should be allowed to log. This is because the default primary log level\nis notice and it is enforced before the primary filters. So in order for the pid\nfilter to be useful we have to raise the primary log level to `all` and then add\na level filter that only lets certain messages at or greater than notice\nthrough. When the setup is done, it is simple to add a filter that allows a\ncertain pid through.\n\nNote that doing the primary log level filtering through a filter and not through\nthe level is quite a lot more expensive, so make sure to test that your system\ncan handle the extra load before you enable it on a production node.\n\n#### See also\n\n- [Filters](logger_chapter.md#filters) in the Logging User's Guide\n- `logger_filters:level/2`\n- `logger:set_primary_config/2`","ref":"logger_cookbook.html#process-filters"},{"type":"extras","title":"Domains - Logging Cookbook","doc":"Domains are used to specify which subsystem a certain log event originates from.\nThe default handler will by default only log events with the domain `[otp]` or\nwithout a domain. If you would like to include SSL log events into the default\nhandler log you could do this:\n\n```erlang\n1> logger:add_handler_filter(default,ssl_domain,\n {fun logger_filters:domain/2,{log,sub,[otp,ssl]}}).\n2> application:ensure_all_started(ssl).\n{ok,[crypto,asn1,public_key,ssl]}\n3> ssl:connect(\"www.erlang.org\",443,[{log_level,debug}]).\n%% lots of text\n```\n\n#### See also\n\n- [Filters](logger_chapter.md#filters) in the Logging User's Guide\n- `logger_filters:domain/2`\n- `logger:set_primary_config/2`","ref":"logger_cookbook.html#domains"},{"type":"extras","title":"EEP-48: Documentation storage and format","doc":"\n# EEP-48: Documentation storage and format\n\nThis User's Guide describes the documentation storage format initially described\nin [EEP-48](https://www.erlang.org/erlang-enhancement-proposals/eep-0048.html).\nBy standardizing how API documentation is stored, it will be possible to write\ntools that work across languages.\n\nTo fetch the EEP-48 documentation for a module, use `code:get_doc/1`.\n\nTo render the EEP-48 documentation for an Erlang module, use\n`shell_docs:render/2`.","ref":"eep48_chapter.html"},{"type":"extras","title":"The \"Docs\" storage - EEP-48: Documentation storage and format","doc":"To look for documentation for a module named `example`, a tool should:\n\nLook for `example.beam` in the code path, parse the BEAM file, and retrieve the\n`Docs` chunk. If the chunk is not available, it should look for `\"example.beam\"`\nin the code path and find the `doc/chunks/example.chunk` file in the application\nthat defines the `example` module. If no `.chunk` file exists,\ndocumentation is not available.\n\nThe choice of using a chunk or the filesystem is completely up to the language\nor library. In both cases, the documentation can be added or removed at any\nmoment by stripping the `Docs` chunk (using `m:beam_lib`) or by removing the\n`doc/chunks` directory.\n\nFor example, languages such as Elixir and LFE attach the `Docs` chunk at\ncompilation time, which can be controlled via a compiler flag, while\nother languages might want to generate the documentation separate from\nthe compilation of the source code.","ref":"eep48_chapter.html#the-docs-storage"},{"type":"extras","title":"The \"Docs\" format - EEP-48: Documentation storage and format","doc":"In both storages, the documentation is written in the exactly same format: an\nErlang term serialized to binary via\n[`term_to_binary/1`](`erlang:term_to_binary/1`). The term can be optionally\ncompressed when serialized. It must follow the type specification below:\n\n```erlang\n{docs_v1,\n Anno :: erl_anno:anno(),\n BeamLanguage :: atom(),\n Format :: binary(),\n ModuleDoc :: #{DocLanguage := DocValue} | none | hidden,\n Metadata :: map(),\n Docs ::\n [{{Kind, Name, Arity},\n Anno :: erl_anno:anno(),\n Signature :: [binary()],\n Doc :: #{DocLanguage := DocValue} | none | hidden,\n Metadata :: map()\n }]} when DocLanguage :: binary(),\n DocValue :: binary() | term()\n```\n\nwhere in the root tuple we have:\n\n- **`Anno`** - annotation (line, column, file) of the definition itself (see\n `m:erl_anno`)\n\n- **`BeamLanguage`** - an atom representing the language, for example: `erlang`,\n `elixir`, `lfe`, `alpaca`, and so on\n\n- **`Format`** - the mime type of the documentation, such as `<<\"text/markdown\">>`\n or `<<\"application/erlang+html\">>`. For details of the format used by Erlang\n see the [`EEP-48 Chapter`](`e:edoc:doc_storage.md`) in EDoc's User's\n Guide.\n\n- **`ModuleDoc`** - a map with the documentation language as key, such as\n `<<\"en\">>` or `<<\"pt_BR\">>`, and the documentation as a binary value. It can\n be atom `none` if no documentation exists or the atom `hidden` if\n documentation has been explicitly disabled for this entry.\n\n- **`Metadata`** - a map of atom keys with any term as value. This can be used to\n add annotations like the `authors` of a module, `deprecated`, or anything else\n a language or documentation tool finds relevant.\n\n- **`Docs`** - a list of documentation for other entities (such as functions and\n types) in the module.\n\nFor each entry in Docs, we have:\n\n- **`{Kind, Name, Arity}`** - the kind, name and arity identifying the function,\n callback, type, and so on. The official entities are: `function`, `type`, and\n `callback`. Other languages will add their own. For instance, Elixir and LFE\n might add `macro`.\n\n- **`Anno`** - annotation (line, column, file) of the module documentation\n (see `m:erl_anno`).\n\n- **`Signature`** - the signature of the entity. It is is a list of binaries.\n Each entry represents a binary in the signature that can be joined with\n whitespace or newline. For example,\n `[<<\"binary_to_atom(Binary, Encoding)\">>, <<\"when is_binary(Binary)\">>]` can\n be rendered as a single line or two lines. It exists exclusively for\n exhibition purposes.\n\n- **`Doc`** - a map with the documentation language as key, such as `<<\"en\">>` or\n `<<\"pt_BR\">>`, and the documentation as a value. The documentation can either be\n a binary or any Erlang term, both described by `Format`. If it is an Erlang\n term, then `Format` must be `<<\"application/erlang+SUFFIX\">>`, such as\n `<<\"application/erlang+html\">>` when the documentation is an Erlang\n representation of an HTML document. `Doc` can also be atom `none`\n if no documentation exists or the atom `hidden` if documentation has been\n explicitly disabled for this entry.\n\n- **`Metadata`** - a map of atom keys with any term as value.\n\nThis shared format is the heart of the EEP as it is what effectively allows\ncross-language collaboration.\n\nThe Metadata field exists to allow languages, tools, and libraries to add custom\ninformation to each entry. This EEP documents the following metadata keys:\n\n- **`authors := [binary()]`** - a list of authors as binaries.\n\n- **`behaviours := [module()]`** - a list of the behaviours implemented by\n this module.\n\n- **`cross_references := [module() | {module(), {Kind, Name, Arity}}]`** - a\n list of modules or module entries that can be used as cross references when\n generating documentation.\n\n- **`deprecated := binary()`** - when present, it means the current entry is\n deprecated with a binary that represents the reason for deprecation and a\n recommendation to replace the deprecated code.\n\n- **`since := binary()`** - a binary representing the version such entry was\n added, such as `<<\"1.3.0\">>` or `<<\"20.0\">>`.\n\n- **`source_path := binary()`** - the absolute location of the source file for\n this module. Applies only to the module metadata.\n\n- **`source_annos := [erl_anno:anno()]`** - a list of source code locations.\n You may either store one for each clause or only for the first clause.\n\nAny key may be added to Metadata at any time. Keys that are frequently used by\nthe community can be standardized in future versions.","ref":"eep48_chapter.html#the-docs-format"},{"type":"extras","title":"See Also - EEP-48: Documentation storage and format","doc":"`m:erl_anno`, `m:shell_docs`,\n[`EEP-48 Chapter in EDoc's User's Guide`](`e:edoc:doc_storage.md`),\n`code:get_doc/1`","ref":"eep48_chapter.html#see-also"},{"type":"extras","title":"app","doc":"\n# app\n\nApplication resource file.","ref":"app.html"},{"type":"extras","title":"Description - app","doc":"The _application resource file_ specifies the resources an application uses, and\nhow the application is started. There must always be one application resource\nfile called `Application.app` for each application `Application` in the system.\n\nThe file is read by the application controller when an application is\nloaded/started. It is also used by the functions in `systools`, for example when\ngenerating start scripts.","ref":"app.html#description"},{"type":"extras","title":"File Syntax - app","doc":"The application resource file is to be called `Application.app`, where\n`Application` is the application name. The file is to be located in directory\n`ebin` for the application.\n\nThe file must contain a single Erlang term, which is called an _application\nspecification_:\n\n```erlang\n{application, Application,\n [{description, Description},\n {id, Id},\n {vsn, Vsn},\n {modules, Modules},\n {maxP, MaxP},\n {maxT, MaxT},\n {registered, Names},\n {included_applications, Apps},\n {optional_applications, Apps},\n {applications, Apps},\n {env, Env},\n {mod, Start},\n {start_phases, Phases},\n {runtime_dependencies, RTDeps}]}.\n\n Value Default\n ----- -------\nApplication atom() -\nDescription string() \"\"\nId string() \"\"\nVsn string() \"\"\nModules [Module] []\nMaxP int() infinity\nMaxT int() infinity\nNames [Name] []\nApps [App] []\nEnv [{Par,Val}] []\nStart {Module,StartArgs} []\nPhases [{Phase,PhaseArgs}] undefined\nRTDeps [ApplicationVersion] []\n\nModule = Name = App = Par = Phase = atom()\nVal = StartArgs = PhaseArgs = term()\nApplicationVersion = string()\n```\n\n- **`Application`** - Application name.\n\nFor the application controller, all keys are optional. The respective default\nvalues are used for any omitted keys.\n\nThe functions in `systools` require more information. If they are used, the\nfollowing keys are mandatory:\n\n- `description`\n- `vsn`\n- `modules`\n- `registered`\n- `applications`\n\nThe other keys are ignored by `systools`.\n\n- **`description`** - A one-line description of the application.\n\n- **`id`** - Product identification, or similar.\n\n- **`vsn`** - Version of the application.\n\n- **`modules`** - All modules introduced by this application. `systools` uses\n this list when generating start scripts and tar files. A module can only be\n defined in one application.\n\n- **`maxP`** - _Deprecated - is ignored_\n\n Maximum number of processes allowed in the application.\n\n- **`maxT`** - Maximum time, in milliseconds, that the application is allowed to\n run. After the specified time, the application terminates automatically.\n\n- **`registered`** - All names of registered processes started in this\n application. `systools` uses this list to detect name clashes between\n different applications.\n\n- **`included_applications`** - All applications included by this application.\n When this application is started, all included applications are loaded\n automatically, but not started, by the application controller. It is assumed\n that the top-most supervisor of the included application is started by a\n supervisor of this application.\n\n- **`applications`** - All applications that must be started before this\n application. If an application is also listed in `optional_applications`, then\n the application is not required to exist (but if it exists, it is also\n guaranteed to be started before this one).\n\n `systools` uses this list to generate correct start scripts. Defaults to the\n empty list, but notice that all applications have dependencies to (at least)\n Kernel and STDLIB.\n\n- **`optional_applications`** - A list of `applications` that are optional. Note\n if you want an optional dependency to be automatically started before the\n current application whenever it is available, it must be listed on both\n `applications` and `optional_applications`.\n\n- **`env`** - Configuration parameters used by the application. The value of a\n configuration parameter is retrieved by calling `application:get_env/1,2`. The\n values in the application resource file can be overridden by values in a\n configuration file (see [`config(4)`](config.md)) or by command-line flags\n (see [`erts:erl(1)`](`e:erts:erl_cmd.md`)).\n\n- **`mod`** - Specifies the application callback module and a start argument,\n see `m:application`.\n\n Key `mod` is necessary for an application implemented as a supervision tree,\n otherwise the application controller does not know how to start it. `mod` can\n be omitted for applications without processes, typically code libraries, for\n example, STDLIB.\n\n- **`start_phases`** - A list of start phases and corresponding start arguments\n for the application. If this key is present, the application master, in\n addition to the usual call to `Module:start/2`, also calls\n `Module:start_phase(Phase,Type,PhaseArgs)` for each start phase defined by key\n `start_phases`. Only after this extended start procedure,\n `application:start(Application)` returns.\n\n Start phases can be used to synchronize startup of an application and its\n included applications. In this case, key `mod` must be specified as follows:\n\n ```erlang\n {mod, {application_starter,[Module,StartArgs]}}\n ```\n\n The application master then calls `Module:start/2` for the primary\n application, followed by calls to `Module:start_phase/3` for each start phase\n (as defined for the primary application), both for the primary application and\n for each of its included applications, for which the start phase is defined.\n\n This implies that for an included application, the set of start phases must be\n a subset of the set of phases defined for the primary application. For more\n information, see [OTP Design Principles](`e:system:applications.md`).\n\n- **`runtime_dependencies`{: #runtime_dependencies }** - A list of application\n versions that the application depends on. An example of such an application\n version is `\"kernel-3.0\"`. Application versions specified as runtime\n dependencies are minimum requirements. That is, a larger application version\n than the one specified in the dependency satisfies the requirement. For\n information about how to compare application versions, see section\n [Versions](`e:system:versions.md`) in the System Principles User's Guide.\n\n Notice that the application version specifies a source code version. One more,\n indirect, requirement is that the installed binary application of the\n specified version is built so that it is compatible with the rest of the\n system.\n\n Some dependencies can only be required in specific runtime scenarios. When\n such optional dependencies exist, these are specified and documented in the\n corresponding \"App\" documentation of the specific application.","ref":"app.html#file-syntax"},{"type":"extras","title":"See Also - app","doc":"`m:application`, `m:systools`","ref":"app.html#see-also"},{"type":"extras","title":"config","doc":"\n# config\n\nConfiguration file.","ref":"config.html"},{"type":"extras","title":"Description - config","doc":"A _configuration file_ contains values for configuration parameters for the\napplications in the system. The `erl` command-line argument\n[`-config Name`](`e:erts:erl_cmd.md#config`) tells the system to use data in the\nsystem configuration file `Name.config`.\n\nThe erl command-line argument [`-configfd`](`e:erts:erl_cmd.md#configfd`) works\nthe same way as the `-config` option but specifies a file descriptor to read\nconfiguration data from instead of a file.\n\nThe configuration data from configuration files and file descriptors are read in\nthe same order as they are given on the command line. For example,\n`erl -config a -configfd 3 -config b -configfd 4` would cause the system to read\nconfiguration data in the following order `a.config`, file descriptor `3`,\n`b.config`, and file descriptor `4`. If a configuration parameter is specified\nmore than once in the given files and file descriptors, the last one overrides\nthe previous ones.\n\nConfiguration parameter values in a configuration file or file descriptor\noverride the values in the application resource files (see [`app(4)`](app.md)).\nThe values in the configuration file are always overridden by command-line flags\n(see [`erts:erl(1)`](`e:erts:erl_cmd.md`)).\n\nThe value of a configuration parameter is retrieved by calling\n`application:get_env/1,2`.","ref":"config.html#description"},{"type":"extras","title":"File Syntax - config","doc":"The configuration file is to be called `Name.config`, where `Name` is any name.\n\nFile `.config` contains a single Erlang term and has the following syntax:\n\n```erlang\n[{Application1, [{Par11, Val11}, ...]},\n ...\n {ApplicationN, [{ParN1, ValN1}, ...]}].\n```\n\n- **`Application = atom()`** - Application name.\n\n- **`Par = atom()`** - Name of a configuration parameter.\n\n- **`Val = term()`** - Value of a configuration parameter.","ref":"config.html#file-syntax"},{"type":"extras","title":"sys.config - config","doc":"When starting Erlang in embedded mode, it is assumed that exactly one system\nconfiguration file is used, named `sys.config`. This file is to be located in\n`$ROOT/releases/Vsn`, where `$ROOT` is the Erlang/OTP root installation\ndirectory and `Vsn` is the release version.\n\nRelease handling relies on this assumption. When installing a new release\nversion, the new `sys.config` is read and used to update the application's\nconfigurations.\n\nThis means that specifying another `.config` file, or more `.config` files,\nleads to an inconsistent update of application configurations. There is,\nhowever, a way to point out other config files from a `sys.config`. How to do\nthis is described in the next section.","ref":"config.html#sys-config"},{"type":"extras","title":"Including Files from sys.config and -configfd Configurations - config","doc":"There is a way to include other configuration files from a `sys.config` file and\nfrom a configuration that comes from a file descriptor that has been pointed out\nwith the [`-configfd`](`e:erts:erl_cmd.md#configfd`) command-line argument.\n\nThe syntax for including files can be described by the\n[Erlang type language](`e:system:typespec.md`) like this:\n\n```text\n[{Application, [{Par, Val}]} | IncludeFile].\n```\n\n- **`IncludeFile = string()`** - Name of a `.config` file. The extension\n `.config` can be omitted. It is recommended to use absolute paths. If a\n relative path is used in a `sys.config`, `IncludeFile` is searched, first,\n relative to the `sys.config` directory, then relative to the current working\n directory of the emulator. If a relative path is used in a `-configfd`\n configuration, `IncludeFile` is searched, first, relative to the dictionary\n containing the [boot script](`e:sasl:script.md`) (see also the\n [`-boot`](`e:erts:erl_cmd.md#boot`) command-line argument) for the emulator,\n then relative to the current working directory of the emulator. This makes it\n possible to use `sys.config` for pointing out other `.config` files in a\n release or in a node started manually using `-config` or `-configfd` with the\n same result whatever the current working directory is.\n\nWhen traversing the contents of a `sys.config` or a `-configfd` configuration\nand a filename is encountered, its contents are read and merged with the result\nso far. When an application configuration tuple `{Application, Env}` is found,\nit is merged with the result so far. Merging means that new parameters are added\nand existing parameter values are overwritten.\n\n_Example:_\n\n```text\nsys.config:\n\n[\"/home/user/myconfig1\"\n {myapp,[{par1,val1},{par2,val2}]},\n \"/home/user/myconfig2\"].\n\nmyconfig1.config:\n\n[{myapp,[{par0,val0},{par1,val0},{par2,val0}]}].\n\nmyconfig2.config:\n\n[{myapp,[{par2,val3},{par3,val4}]}].\n```\n\nThis yields the following environment for `myapp`:\n\n```text\n[{par0,val0},{par1,val1},{par2,val3},{par3,val4}]\n```\n\nThe run-time system will abort before staring up if an include file specified in\n`sys.config` or a `-configfd` configuration does not exist, or is erroneous.\nHowever, installing a new release version will not fail if there is an error\nwhile loading an include file, but an error message is returned and the\nerroneous file is ignored.","ref":"config.html#including-files-from-sys-config-and-configfd-configurations"},{"type":"extras","title":"See Also - config","doc":"[`app(4)`](app.md), [`erts:erl(1)`](`e:erts:erl_cmd.md`),\n[OTP Design Principles](`e:system:design_principles.md`)","ref":"config.html#see-also"}],"content_type":"text/plain","producer":{"name":"ex_doc","version":[48,46,51,52,46,49]}} \ No newline at end of file diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/dist/search_data-9B590B76.js b/prs/9045/lib/kernel-10.1.1/doc/html/dist/search_data-9B590B76.js deleted file mode 100644 index bfce5616a658..000000000000 --- a/prs/9045/lib/kernel-10.1.1/doc/html/dist/search_data-9B590B76.js +++ /dev/null @@ -1 +0,0 @@ -searchData={"items":[{"type":"behaviour","doc":"Generic OTP application functions\n\nIn OTP, _application_ denotes a component implementing some specific\nfunctionality, that can be started and stopped as a unit, and that can be reused\nin other systems. This module interacts with _application controller_, a process\nstarted at every Erlang runtime system. This module contains functions for\ncontrolling applications (for example, starting and stopping applications), and\nfunctions to access information about applications (for example, configuration\nparameters).\n\nAn application is defined by an _application specification_. The specification\nis normally located in an _application resource file_ named `Application.app`,\nwhere `Application` is the application name. For details about the application\nspecification, see [`app`](app.md).\n\nThis module can also be viewed as a behaviour for an application implemented\naccording to the OTP design principles as a supervision tree. The definition of\nhow to start and stop the tree is to be located in an _application callback\nmodule_, exporting a predefined set of functions.\n\nFor details about applications and behaviours, see\n[OTP Design Principles](`e:system:design_principles.md`).","title":"application","ref":"application.html"},{"type":"behaviour","doc":"[OTP Design Principles](`e:system:design_principles.md`),\n[kernel](kernel_app.md), [app](app.md)","title":"See Also - application","ref":"application.html#module-see-also"},{"type":"callback","doc":"This function is called by an application after a code replacement, if the\nconfiguration parameters have changed.\n\n`Changed` is a list of parameter-value tuples including all configuration\nparameters with changed values.\n\n`New` is a list of parameter-value tuples including all added configuration\nparameters.\n\n`Removed` is a list of all removed parameters.","title":"application.config_change/3","ref":"application.html#c:config_change/3"},{"type":"function","doc":"","title":"application.ensure_all_started/1","ref":"application.html#ensure_all_started/1"},{"type":"function","doc":"","title":"application.ensure_all_started/2","ref":"application.html#ensure_all_started/2"},{"type":"function","doc":"`Applications` is either an an `t:atom/0` or a list of `t:atom/0` representing\nmultiple applications.\n\nThis function is equivalent to calling [`start/1,2`](`start/1`) repeatedly on\nall dependencies that are not yet started of each application. Optional\ndependencies will also be loaded and started if they are available.\n\nThe `Mode` argument controls if the applications should be started in `serial`\nmode (one at a time) or `concurrent` mode. In concurrent mode, a dependency\ngraph is built and the leaves of the graph are started concurrently and\nrecursively. In both modes, no assertion can be made about the order the\napplications are started. If not supplied, it defaults to `serial`.\n\nReturns `{ok, AppNames}` for a successful start or for an already started\napplication (which is, however, omitted from the `AppNames` list).\n\nThe function reports `{error, {AppName,Reason}}` for errors, where `Reason` is\nany possible reason returned by [`start/1,2`](`start/1`) when starting a\nspecific dependency.\n\nIf an error occurs, the applications started by the function are stopped to\nbring the set of running applications back to its initial state.","title":"application.ensure_all_started/3","ref":"application.html#ensure_all_started/3"},{"type":"function","doc":"Equivalent to [`start(Application)`](`start/1`) except it returns `ok` for\nalready started applications.","title":"application.ensure_started/1","ref":"application.html#ensure_started/1"},{"type":"function","doc":"Equivalent to [`start(Application, Type)`](`start/2`) except it returns `ok` for\nalready started applications.","title":"application.ensure_started/2","ref":"application.html#ensure_started/2"},{"type":"function","doc":"","title":"application.get_all_env/0","ref":"application.html#get_all_env/0"},{"type":"function","doc":"Returns the configuration parameters and their values for `Application`.\n\nIf the specified application is not loaded, or if the process executing the call\ndoes not belong to any application, the function returns `[]`.","title":"application.get_all_env/1","ref":"application.html#get_all_env/1"},{"type":"function","doc":"","title":"application.get_all_key/0","ref":"application.html#get_all_key/0"},{"type":"function","doc":"Returns the application specification keys and their values for `Application`.\nIf the argument is omitted, it defaults to the application of the calling\nprocess.\n\nIf the specified application is not loaded, the function returns `undefined`. If\nthe process executing the call does not belong to any application, the function\nreturns `[]`.","title":"application.get_all_key/1","ref":"application.html#get_all_key/1"},{"type":"function","doc":"","title":"application.get_application/0","ref":"application.html#get_application/0"},{"type":"function","doc":"Returns the name of the application to which the process `Pid` or the module\n`Module` belongs.\n\nIf the specified process does not belong to any application, or if the specified\nprocess or module does not exist, the function returns `undefined`.","title":"application.get_application/1","ref":"application.html#get_application/1"},{"type":"function","doc":"","title":"application.get_env/1","ref":"application.html#get_env/1"},{"type":"function","doc":"Returns the value of configuration parameter `Par` for `Application`.\n\nReturns `undefined` if any of the following applies:\n\n- The specified application is not loaded.\n- The configuration parameter does not exist.\n- The process executing the call does not belong to any application.","title":"application.get_env/2","ref":"application.html#get_env/2"},{"type":"function","doc":"Works like `get_env/2` but returns value `Def` when configuration parameter\n`Par` does not exist.","title":"application.get_env/3","ref":"application.html#get_env/3"},{"type":"function","doc":"","title":"application.get_key/1","ref":"application.html#get_key/1"},{"type":"function","doc":"Returns the value of the application specification key `Key` for `Application`.\n\nReturns `undefined` if any of the following applies:\n\n- The specified application is not loaded.\n- The specification key does not exist.\n- The process executing the call does not belong to any application.","title":"application.get_key/2","ref":"application.html#get_key/2"},{"type":"function","doc":"Returns the `Pid` of the supervisor running at the root of `Application`.\n\nIf the specified application does not exist or does not define a callback\nmodule, the function returns `undefined`.","title":"application.get_supervisor/1","ref":"application.html#get_supervisor/1"},{"type":"function","doc":"","title":"application.load/1","ref":"application.html#load/1"},{"type":"function","doc":"Loads the application specification for an application into the application\ncontroller. It also loads the application specifications for any included\napplications. Notice that the function does not load the Erlang object code.\n\nThe application can be specified by its name `Application`. In this case, the\napplication controller searches the code path for the application resource file\n`Application.app` and loads the specification it contains.\n\nThe application specification can also be specified directly as a tuple\n`AppSpec`, having the format and contents as described in [`app`](app.md).\n\nIf `Distributed == {Application,[Time,]Nodes}`, the application becomes\ndistributed. The argument overrides the value for the application in the Kernel\nconfiguration parameter `distributed`. `Application` must be the application\nname (same as in the first argument). If a node crashes and `Time` is specified,\nthe application controller waits for `Time` milliseconds before attempting to\nrestart the application on another node. If `Time` is not specified, it defaults\nto `0` and the application is restarted immediately.\n\n`Nodes` is a list of node names where the application can run, in priority from\nleft to right. Node names can be grouped using tuples to indicate that they have\nthe same priority.\n\n_Example:_\n\n```erlang\nNodes = [cp1@cave, {cp2@cave, cp3@cave}]\n```\n\nThis means that the application is preferably to be started at `cp1@cave`. If\n`cp1@cave` is down, the application is to be started at `cp2@cave` or\n`cp3@cave`.\n\nIf `Distributed == default`, the value for the application in the Kernel\nconfiguration parameter `distributed` is used.","title":"application.load/2","ref":"application.html#load/2"},{"type":"function","doc":"Returns a list with information about the applications, and included\napplications, which are loaded using `load/1,2`. `Application` is the\napplication name. `Description` and `Vsn` are the values of their `description`\nand `vsn` application specification keys, respectively.","title":"application.loaded_applications/0","ref":"application.html#loaded_applications/0"},{"type":"function","doc":"Changes the permission for `Application` to run at the current node. The\napplication must be loaded using `load/1,2` for the function to have effect.\n\nIf the permission of a loaded, but not started, application is set to `false`,\n`start` returns `ok` but the application is not started until the permission is\nset to `true`.\n\nIf the permission of a running application is set to `false`, the application is\nstopped. If the permission later is set to `true`, it is restarted.\n\nIf the application is distributed, setting the permission to `false` means that\nthe application will be started at, or moved to, another node according to how\nits distribution is configured (see `load/2`).\n\nThe function does not return until the application is started, stopped, or\nsuccessfully moved to another node. However, in some cases where permission is\nset to `true`, the function returns `ok` even though the application is not\nstarted. This is true when an application cannot start because of dependencies\nto other applications that are not yet started. When they are started,\n`Application` is started as well.\n\nBy default, all applications are loaded with permission `true` on all nodes. The\npermission can be configured using the Kernel configuration parameter\n`permissions`.","title":"application.permit/2","ref":"application.html#permit/2"},{"type":"callback","doc":"This function is called when an application is about to be stopped, before\nshutting down the processes of the application.\n\n`State` is the state returned from [`Module:start/2`](`c:start/2`), or `[]` if\nno state was returned. `NewState` is any term and is passed to\n[`Module:stop/1`](`c:stop/1`).\n\nThe function is optional. If it is not defined, the processes are terminated and\nthen [`Module:stop(State)`](`c:stop/1`) is called.","title":"application.prep_stop/1","ref":"application.html#c:prep_stop/1"},{"type":"function","doc":"","title":"application.set_env/1","ref":"application.html#set_env/1"},{"type":"function","doc":"Sets the configuration `Config` for multiple applications.\n\nIt is equivalent to calling [`set_env/4`](`set_env/4`) on each application\nindividually, except it is more efficient. The given `Config` is validated before\nthe configuration is set.\n\n[`set_env/2`](`set_env/2`) uses the standard `gen_server` time-out value (5000\nms). Option `timeout` can be specified if another time-out value is useful, for\nexample, in situations where the application controller is heavily loaded.\n\nOption `persistent` can be set to `true` to guarantee that parameters set with\n[`set_env/2`](`set_env/2`) are not overridden by those defined in the\napplication resource file on load. This means that persistent values will stick\nafter the application is loaded and also on application reload.\n\nIf an application is given more than once or if an application has the same key\ngiven more than once, the behaviour is undefined and a warning message will be\nlogged. In future releases, an error will be raised.\n\n> #### Warning {: .warning }\n>\n> Use this function only if you know what you are doing, that is, on your own\n> applications. It is very application-dependent and configuration\n> parameter-dependent when and how often the value is read by the application.\n> Careless use of this function can put the application in a weird,\n> inconsistent, and malfunctioning state.","title":"application.set_env/2","ref":"application.html#set_env/2"},{"type":"function","doc":"","title":"application.set_env/3","ref":"application.html#set_env/3"},{"type":"function","doc":"Sets the value of configuration parameter `Par` for `Application`.\n\n[`set_env/4`](`set_env/4`) uses the standard `gen_server` time-out value (5000\nms). Option `timeout` can be specified if another time-out value is useful, for\nexample, in situations where the application controller is heavily loaded.\n\nIf [`set_env/4`](`set_env/4`) is called before the application is loaded, the\napplication environment values specified in file `Application.app` override the\nones previously set. This is also true for application reloads.\n\nOption `persistent` can be set to `true` to guarantee that parameters set with\n[`set_env/4`](`set_env/4`) are not overridden by those defined in the\napplication resource file on load. This means that persistent values will stick\nafter the application is loaded and also on application reload.\n\n> #### Warning {: .warning }\n>\n> Use this function only if you know what you are doing, that is, on your own\n> applications. It is very application-dependent and configuration\n> parameter-dependent when and how often the value is read by the application.\n> Careless use of this function can put the application in a weird,\n> inconsistent, and malfunctioning state.","title":"application.set_env/4","ref":"application.html#set_env/4"},{"type":"function","doc":"","title":"application.start/1","ref":"application.html#start/1"},{"type":"function","doc":"Starts `Application`. If it is not loaded, the application controller first\nloads it using [`load/1`](`load/1`). It ensures that any included applications\nare loaded, but does not start them. That is assumed to be taken care of in the\ncode for `Application`.\n\nThe application controller checks the value of the application specification key\n`applications`, to ensure that all applications needed to be started before this\napplication are running. If an application is missing and the application is not\nmarked as optional, `{error,{not_started,App}}` is returned, where `App` is the\nname of the missing application. Note this function makes no attempt to start\nany of the applications listed in `applications`, not even optional ones. See\n[`ensure_all_started/1,2`](`ensure_all_started/1`) for recursively starting the\ncurrent application and its dependencies.\n\nOnce validated, the application controller then creates an _application master_\nfor the application. The application master becomes the group leader of all the\nprocesses in the application. I/O is forwarded to the previous group leader,\nthough, this is just a way to identify processes that belong to the application.\nUsed for example to find itself from any process, or, reciprocally, to kill them\nall when it terminates.\n\nThe application master starts the application by calling the application\ncallback function [`Module:start/2`](`c:start/2`) as defined by the application\nspecification key `mod`.\n\nArgument `Type` specifies the type of the application. If omitted, it defaults\nto `temporary`.\n\n- If a permanent application terminates, all other applications and the entire\n Erlang node are also terminated.\n- If a transient application terminates:\n - with `Reason == normal`, this is reported but no other applications are\n terminated.\n - abnormally, all other applications and the entire Erlang node are also\n terminated.\n- If a temporary application terminates, this is reported but no other\n applications are terminated.\n\nNotice that an application can always be stopped explicitly by calling\n[`stop/1`](`stop/1`). Regardless of the type of the application, no other\napplications are affected.\n\nNotice also that the transient type is of little practical use, because when a\nsupervision tree terminates, the reason is set to `shutdown`, not `normal`.","title":"application.start/2","ref":"application.html#start/2"},{"type":"callback","doc":"This function is called whenever an application is started using `start/1,2`,\nand is to start the processes of the application. If the application is\nstructured according to the OTP design principles as a supervision tree, this\nmeans starting the top supervisor of the tree.\n\n`StartType`{: #start_type } defines the type of start:\n\n- `normal` if it is a normal startup.\n- `normal` also if the application is distributed and started at the current\n node because of a failover from another node, and the application\n specification key `start_phases == undefined`.\n- `{takeover,Node}` if the application is distributed and started at the current\n node because of a takeover from `Node`, either because\n [`takeover/2`](`takeover/2`) has been called or because the current node has\n higher priority than `Node`.\n- `{failover,Node}` if the application is distributed and started at the current\n node because of a failover from `Node`, and the application specification key\n `start_phases /= undefined`.\n\n`StartArgs` is the `StartArgs` argument defined by the application specification\nkey `mod`.\n\nThe function is to return `{ok,Pid}` or `{ok,Pid,State}`, where `Pid` is the pid\nof the top supervisor and `State` is any term. If omitted, `State` defaults to\n`[]`. If the application is stopped later, `State` is passed to\n[`Module:prep_stop/1`](`c:prep_stop/1`).","title":"application.start/2","ref":"application.html#c:start/2"},{"type":"callback","doc":"Starts an application with included applications, when synchronization is needed\nbetween processes in the different applications during startup.\n\nThe start phases are defined by the application specification key\n`start_phases == [{Phase,PhaseArgs}]`. For included applications, the set of\nphases must be a subset of the set of phases defined for the including\napplication.\n\nThe function is called for each start phase (as defined for the primary\napplication) for the primary application and all included applications, for\nwhich the start phase is defined.\n\nFor a description of `StartType`, see [`Module:start/2`](`c:start/2`).","title":"application.start_phase/3","ref":"application.html#c:start_phase/3"},{"type":"function","doc":"This function is intended to be called by a process belonging to an application,\nwhen the application is started, to determine the start type, which is\n`StartType` or `local`.\n\nFor a description of `StartType`, see\n[`Module:start/2`](`m:application#start_type`).\n\n`local` is returned if only parts of the application are restarted (by a\nsupervisor), or if the function is called outside a startup.\n\nIf the process executing the call does not belong to any application, the\nfunction returns `undefined`.","title":"application.start_type/0","ref":"application.html#start_type/0"},{"type":"function","doc":"Stops `Application`. The application master calls\n[`Module:prep_stop/1`](`c:prep_stop/1`), if such a function is defined, and then\ntells the top supervisor of the application to shut down (see `m:supervisor`).\n\nThis means that the entire supervision tree, including included applications, is\nterminated in reversed start order. After the shutdown, the application master\ncalls [`Module:stop/1`](`c:stop/1`). `Module` is the callback module as defined\nby the application specification key `mod`.\n\nLast, the application master terminates. Notice that all processes with the\napplication master as group leader, that is, processes spawned from a process\nbelonging to the application, are also terminated.\n\nWhen stopped, the application is still loaded.\n\nTo stop a distributed application, [`stop/1`](`stop/1`) must be called on all\nnodes where it can execute (that is, on all nodes where it has been started).\nThe call to [`stop/1`](`stop/1`) on the node where the application currently\nexecutes stops its execution. The application is not moved between nodes, as\n[`stop/1`](`stop/1`) is called on the node where the application currently\nexecutes before [`stop/1`](`stop/1`) is called on the other nodes.","title":"application.stop/1","ref":"application.html#stop/1"},{"type":"callback","doc":"This function is called whenever an application has stopped. It is intended to\nbe the opposite of [`Module:start/2`](`c:start/2`) and is to do any necessary\ncleaning up. The return value is ignored.\n\n`State` is the return value of [`Module:prep_stop/1`](`c:prep_stop/1`), if such\na function exists. Otherwise `State` is taken from the return value of\n[`Module:start/2`](`c:start/2`).","title":"application.stop/1","ref":"application.html#c:stop/1"},{"type":"function","doc":"Takes over the distributed application `Application`, which executes at another\nnode `Node`.\n\nAt the current node, the application is restarted by calling\n[`Module:start({takeover,Node},StartArgs)`](`c:start/2`). `Module` and\n`StartArgs` are retrieved from the loaded application specification. The\napplication at the other node is not stopped until the startup is completed,\nthat is, when [`Module:start/2`](`c:start/2`) and any calls to\n[`Module:start_phase/3`](`c:start_phase/3`) have returned.\n\nThus, two instances of the application run simultaneously during the takeover,\nso that data can be transferred from the old to the new instance. If this is not\nan acceptable behavior, parts of the old instance can be shut down when the new\ninstance is started. However, the application cannot be stopped entirely, at\nleast the top supervisor must remain alive.\n\nFor a description of `Type`, see [`start/1,2`](`start/1`).","title":"application.takeover/2","ref":"application.html#takeover/2"},{"type":"function","doc":"Unloads the application specification for `Application` from the application\ncontroller. It also unloads the application specifications for any included\napplications. Notice that the function does not purge the Erlang object code.","title":"application.unload/1","ref":"application.html#unload/1"},{"type":"function","doc":"","title":"application.unset_env/2","ref":"application.html#unset_env/2"},{"type":"function","doc":"Removes the configuration parameter `Par` and its value for `Application`.\n\n[`unset_env/3`](`unset_env/3`) uses the standard `gen_server` time-out value\n(5000 ms). Option `timeout` can be specified if another time-out value is\nuseful, for example, in situations where the application controller is heavily\nloaded.\n\n[`unset_env/3`](`unset_env/3`) also allows the persistent option to be passed\n(see `set_env/4`).\n\n> #### Warning {: .warning }\n>\n> Use this function only if you know what you are doing, that is, on your own\n> applications. It is very application-dependent and configuration\n> parameter-dependent when and how often the value is read by the application.\n> Careless use of this function can put the application in a weird,\n> inconsistent, and malfunctioning state.","title":"application.unset_env/3","ref":"application.html#unset_env/3"},{"type":"function","doc":"","title":"application.which_applications/0","ref":"application.html#which_applications/0"},{"type":"function","doc":"Returns a list with information about the applications that are currently\nrunning.\n\n`Application` is the application name. `Description` and `Vsn` are the\nvalues of their `description` and `vsn` application specification keys,\nrespectively.\n\nA `Timeout` argument can be specified in situations where the application\ncontroller is heavily loaded.","title":"application.which_applications/1","ref":"application.html#which_applications/1"},{"type":"type","doc":"The built-in options available to an application.\n\nSee [app](app.md) for descriptions of the options.","title":"application.application_opt/0","ref":"application.html#t:application_opt/0"},{"type":"type","doc":"An application specification.","title":"application.application_spec/0","ref":"application.html#t:application_spec/0"},{"type":"type","doc":"The type of restart behaviour an application should have.","title":"application.restart_type/0","ref":"application.html#t:restart_type/0"},{"type":"type","doc":"The reason for the application to be started on the current node.","title":"application.start_type/0","ref":"application.html#t:start_type/0"},{"type":"type","doc":"A tuple where the elements are of type `T`.","title":"application.tuple_of/1","ref":"application.html#t:tuple_of/1"},{"type":"module","doc":"Interface to the Erlang code server process.\n\nThis module contains the interface to the Erlang _code server_, which deals with\nthe loading of compiled code into a running Erlang runtime system.\n\nThe runtime system can be started in _interactive_ or _embedded_ mode. Which one\nis decided by the command-line flag `-mode`:\n\n```bash\n% erl -mode embedded\n```\n\nThe modes are as follows:\n\n- In _interactive_ mode, which is default, only the modules needed by\n the runtime system are loaded during system startup. Other code is\n dynamically loaded when first referenced. When a call to a function\n in a certain module is made, and that module is not loaded, the code\n server searches for and tries to load that module.\n\n- In _embedded_ mode, modules are not auto-loaded. Trying to use a\n module that has not been loaded results in an error. This mode is\n recommended when the boot script loads all modules, as it is\n typically done in OTP releases. (Code can still be loaded later by\n explicitly ordering the code server to do so).\n\nTo prevent accidentally reloading of modules affecting the Erlang runtime\nsystem, directories `kernel`, `stdlib`, and `compiler` are considered _sticky_.\nThis means that the system issues a warning and rejects the request if a user\ntries to reload a module residing in any of them. The feature can be disabled by\nusing command-line flag `-nostick`.","title":"code","ref":"code.html"},{"type":"module","doc":"In interactive mode, the code server maintains a _code path_,\nconsisting of a list of directories, which it searches sequentially\nwhen trying to load a module.\n\nInitially, the code path consists of the current working directory and all\nErlang object code directories under library directory `$OTPROOT/lib`, where\n`$OTPROOT` is the installation directory of Erlang/OTP, `code:root_dir()`.\nDirectories can be named `Name[-Vsn]` and the code server, by default, chooses\nthe directory with the highest version number among those having the same\n`Name`. Suffix `-Vsn` is optional. If an `ebin` directory exists under\n`Name[-Vsn]`, this directory is added to the code path.\n\nEnvironment variable `ERL_LIBS` (defined in the operating system) can be used to\ndefine more library directories to be handled in the same way as the standard\nOTP library directory described above, except that directories without an `ebin`\ndirectory are ignored.\n\nAll application directories found in the additional directories appear before\nthe standard OTP applications, except for the Kernel and STDLIB applications,\nwhich are placed before any additional applications. In other words, modules\nfound in any of the additional library directories override modules with the\nsame name in OTP, except for modules in Kernel and STDLIB.\n\nEnvironment variable `ERL_LIBS` (if defined) is to contain a colon-separated\n(for Unix-like systems) or semicolon-separated (for Windows) list of additional\nlibraries.\n\n_Example:_\n\nOn a Unix-like system, `ERL_LIBS` can be set to the following:\n\n```text\n/usr/local/jungerl:/home/some_user/my_erlang_lib\n```\n\nThe code paths specified by `$OTPROOT`, `ERL_LIBS`, and boot scripts have their\nlistings cached by default (except for `\".\"`) The code server will\nlookup the contents in their directories once and avoid future file system\ntraversals. Therefore, modules added to such directories after the Erlang VM\nboots will not be picked up. This behaviour can be disabled by setting\n`-cache_boot_paths false` or by calling `code:set_path(code:get_path())`.\n\n> #### Change {: .info }\n>\n> The support for caching directories in the code path was added\n> in Erlang/OTP 26.\n\nDirectories given by the command line options `-pa` and `-pz` are not\ncached by default. Many of the functions that manipulate the code path\naccept the `cache` atom as an optional argument to enable caching\nselectively.","title":"Code Path - code","ref":"code.html#module-code-path"},{"type":"module","doc":"> #### Change {: .info }\n>\n> The existing experimental support for archive files will be changed\n> in a future release. As of Erlang/OTP 27, the function `code:lib_dir/2`,\n> the `-code_path_choice` flag, and using `m:erl_prim_loader` for\n> reading files from an archive are deprecated.\n>\n> `escript` scripts that use archive files should use\n> `escript:extract/2` to read data files from its archive instead of using\n> `code:lib_dir/2` and `m:erl_prim_loader`.\n\nThe Erlang archives are `ZIP` files with extension `.ez`. Erlang archives can\nalso be [enclosed in `escript`](`m:escript`) files whose file extension is arbitrary.\n\nErlang archive files can contain entire Erlang applications or parts of\napplications. The structure in an archive file is the same as the directory\nstructure for an application. If you, for example, create an archive of\n`mnesia-4.4.7`, the archive file must be named `mnesia-4.4.7.ez` and it must\ncontain a top directory named `mnesia-4.4.7`. If the version part of the name is\nomitted, it must also be omitted in the archive. That is, a `mnesia.ez` archive\nmust contain a `mnesia` top directory.\n\nAn archive file for an application can, for example, be created like this:\n\n```erlang\nzip:create(\"mnesia-4.4.7.ez\",\n\t[\"mnesia-4.4.7\"],\n\t[{cwd, code:lib_dir()},\n\t {compress, all},\n\t {uncompress,[\".beam\",\".app\"]}]).\n```\n\nAny file in the archive can be compressed, but to speed up the access of\nfrequently read files, it can be a good idea to store `beam` and `app` files\nuncompressed in the archive.\n\nNormally the top directory of an application is located in library directory\n`$OTPROOT/lib` or in a directory referred to by environment variable `ERL_LIBS`.\nAt startup, when the initial code path is computed, the code server also looks\nfor archive files in these directories and possibly adds `ebin` directories in\narchives to the code path. The code path then contains paths to directories that\nlook like `$OTPROOT/lib/mnesia.ez/mnesia/ebin` or\n`$OTPROOT/lib/mnesia-4.4.7.ez/mnesia-4.4.7/ebin`.\n\nThe code server uses module `erl_prim_loader` in ERTS (possibly through\n`erl_boot_server`) to read code files from archives. However, the functions in\n`erl_prim_loader` can also be used by other applications to read files from\narchives. For example, the call\n`erl_prim_loader:list_dir( \"/otp/root/lib/mnesia-4.4.7.ez/mnesia-4.4.7/examples/bench)\"`\nwould list the contents of a directory inside an archive. See\n`m:erl_prim_loader`.\n\nAn application archive file and a regular application directory can coexist.\nThis can be useful when it is needed to have parts of the application as regular\nfiles. A typical case is the `priv` directory, which must reside as a regular\ndirectory to link in drivers dynamically and start port programs. For other\napplications that do not need this, directory `priv` can reside in the archive\nand the files under the directory `priv` can be read through `erl_prim_loader`.\n\nWhen a directory is added to the code path and when the entire code path is\n(re)set, the code server decides which subdirectories in an application that are\nto be read from the archive and which that are to be read as regular files. If\ndirectories are added or removed afterwards, the file access can fail if the\ncode path is not updated (possibly to the same path as before, to trigger the\ndirectory resolution update).\n\nFor each directory on the second level in the application archive (`ebin`,\n`priv`, `src`, and so on), the code server first chooses the regular directory\nif it exists and second from the archive. Function `code:lib_dir/2` returns the\npath to the subdirectory. For example, `code:lib_dir(megaco, ebin)` can return\n`/otp/root/lib/megaco-3.9.1.1.ez/megaco-3.9.1.1/ebin` while\n`code:lib_dir(megaco, priv)` can return `/otp/root/lib/megaco-3.9.1.1/priv`.\n\nWhen an `escript` file contains an archive, there are no restrictions on the\nname of the `escript` and no restrictions on how many applications that can be\nstored in the embedded archive. Single Beam files can also reside on the top\nlevel in the archive. At startup, the top directory in the embedded archive and\nall (second level) `ebin` directories in the embedded archive are added to the\ncode path. See [`escript`](`e:erts:escript_cmd.md`).\n\nA future-proof way for `escript` scripts to read data files from the archive is\nto use the `escript:extract/2` function.\n\nWhen the choice of directories in the code path is `strict` (which is\nthe default as of Erlang/OTP 27), the directory that ends up in the\ncode path is exactly the stated one. This means that if, for example,\nthe directory `$OTPROOT/lib/mnesia-4.4.7/ebin` is explicitly added to\nthe code path, the code server does not load files from\n`$OTPROOT/lib/mnesia-4.4.7.ez/mnesia-4.4.7/ebin`.\n\nThis behavior can be controlled through command-line flag\n`-code_path_choice Choice`. If the flag is set to `relaxed`, the code server\ninstead chooses a suitable directory depending on the actual file structure. If\na regular application `ebin` directory exists, it is chosen. Otherwise, the\ndirectory `ebin` in the archive is chosen if it exists. If neither of them\nexists, the original directory is chosen.\n\nCommand-line flag `-code_path_choice Choice` also affects how module `init`\ninterprets the `boot script`. The interpretation of the explicit code paths in\nthe `boot script` can be `strict` or `relaxed`. It is particularly useful to set\nthe flag to `relaxed` when elaborating with code loading from archives without\nediting the `boot script`. The default has changed to `strict` in OTP 27 and the\noption is scheduled for removal in OTP 28. See module `m:init` in the\nErts application.","title":"Loading of Code From Archive Files - code","ref":"code.html#module-loading-of-code-from-archive-files"},{"type":"module","doc":"The code for a module can exist in two variants in a system: _current code_ and\n_old code_. When a module is loaded into the system for the first time, the\nmodule code becomes *current* and the global _export table_ is updated with\nreferences to all functions exported from the module.\n\nWhen a new instance of the module is loaded, the code of the previous\ninstance becomes *old*, and all export entries referring to the\nprevious instance are removed. After that, the new instance is loaded\nas for the first time, and becomes current.\n\nBoth old and current code for a module are valid, and can even be executed\nconcurrently. The difference is that exported functions in old code are\nunavailable. Hence, a global call cannot be made to an exported function in old\ncode, but old code can still be executed because of processes lingering in it.\n\nIf a third instance of the module is loaded, the code server removes (purges)\nthe old code and any processes lingering in it are terminated. Then the third\ninstance becomes current and the previously current code becomes old.\n\nFor more information about old and current code, and how to make a process\nswitch from old to current code, see section Compilation and Code Loading in the\n[Erlang Reference Manual](`e:system:code_loading.md`).","title":"Current and Old Code - code","ref":"code.html#module-current-and-old-code"},{"type":"module","doc":"In runtime systems that use the JIT, native coverage is a light-weight\nway to find out which functions or lines that have been executed, or\nhow many times each function or line has been executed.\n\n> #### Change {: .info }\n>\n> The support for native coverage was added in Erlang/OTP 27.\n\nNative coverage works by instrumenting code at load-time. When a\nmodule has been instrumented for native coverage collection it is not\npossible to later disable the coverage collection, except by reloading\nthe module. However, the overhead for keeping coverage collection\nrunning is often neligible, especially for [coverage\nmode](`t:coverage_mode/0`) `function` that only keeps track of which\nfunctions that have been executed.\n\nThe `m:cover` tool in the Tools application will automatically use the\nnative coverage support if the runtime system supports it.\n\nIt is only necessary to use the functionality described next if\n`m:cover` is not sufficient, for example:\n\n* If one wants to collect coverage information for the code that runs\n when the runtime system is starting (module `m:init` and so on).\n `m:cover` can only be used when the Erlang system has started, and\n it will reload every module that is to be analyzed.\n\n* If it is necessary to collect coverage information with the absolute\n minimum disturbance of the test system. `m:cover` always counts how\n many times each line is executed (coverage mode `line_counters`),\n but by using native coverage one can use a less expensive coverage\n mode such as `function`, which has almost negligible overhead.","title":"Native Coverage Support - code","ref":"code.html#module-native-coverage-support"},{"type":"module","doc":"If the `line` or `line_counters` coverage mode is to be used,\nthe code to be tested must be compiled with option\n[`line_coverage`](`e:compiler:compile#line_coverage`).\n\nUse [set_coverage_mode(Mode)](`set_coverage_mode/1`) to set a\n[coverage mode](`t:coverage_mode/0`) for all code subsequently\nloaded, or set it with option [\\+JPcover](`e:erts:erl_cmd.md#%2BJPcover`)\nfor `erl`.\n\nOptionally reset coverage information for all\nmodules that are to be tested by calling\n[reset_coverage(Module)](`reset_coverage/1`).\n\nRun the code whose coverage information is to be collected.\n\nRead out the counters for all interesting modules by calling\n[get_coverage(Level, Module)](`get_coverage/2`), where `Level`\nis either `function` or `line`.","title":"Short summary of using native coverage - code","ref":"code.html#module-short-summary-of-using-native-coverage"},{"type":"module","doc":"The following BIFs are sometimes useful, for example to fail gracefully\nif the runtime system does not support native coverage:\n\n* [coverage_support()](`coverage_support/0`) - check whether\n the runtime system supports native coverage\n\n* [get_coverage_mode()](`get_coverage_mode/0`) - get the current\n coverage mode\n\n* [get_coverage_mode(Module)](`get_coverage_mode/1`) - get the coverage\n mode for module `Module`","title":"The other native coverage BIFs - code","ref":"code.html#module-the-other-native-coverage-bifs"},{"type":"module","doc":"Module and application names are atoms, while file and directory names are\nstrings. For backward compatibility reasons, some functions accept both strings\nand atoms, but a future release will probably only allow the arguments that are\ndocumented.\n\nFunctions in this module generally fail with an exception if they are passed an\nincorrect type (for example, an integer or a tuple where an atom is expected).\nAn error tuple is returned if the argument type is correct, but there are some\nother errors (for example, a non-existing directory is specified to\n[`set_path/1`](`set_path/1`)).\n\n[](){: #error_reasons }","title":"Argument Types and Invalid Arguments - code","ref":"code.html#module-argument-types-and-invalid-arguments"},{"type":"module","doc":"Functions that load code (such as [`load_file/1`](`load_file/1`)) will return\n`{error,Reason}` if the load operation fails. Here follows a description of the\ncommon reasons.\n\n- **`badfile`** - The object code has an incorrect format or the module name in\n the object code is not the expected module name.\n\n- **`nofile`** - No file with object code was found.\n\n- **`not_purged`** - The object code could not be loaded because an old version\n of the code already existed.\n\n- **`on_load_failure`** - The module has an\n [\\-on_load function](`e:system:code_loading.md#on_load`) that failed when it\n was called.\n\n- **`sticky_directory`** - The object code resides in a sticky directory.","title":"Error Reasons for Code-Loading Functions - code","ref":"code.html#module-error-reasons-for-code-loading-functions"},{"type":"function","doc":"","title":"code.add_path/1","ref":"code.html#add_path/1"},{"type":"function","doc":"","title":"code.add_path/2","ref":"code.html#add_path/2"},{"type":"function","doc":"","title":"code.add_patha/1","ref":"code.html#add_patha/1"},{"type":"function","doc":"Adds `Dir` to the beginning of the code path.\n\nIf `Dir` exists, it is removed from the old position in the code path.\n\nArgument `Cache` controls whether the content of the directory\nshould be cached on first traversal. If `Cache` is `cache` the directory\ncontents will be cached; if `Cache` is `nocache` it will not be cached.\n\nReturns `true` if successful, or `{error, bad_directory}` if `Dir` is\nnot the name of a directory.","title":"code.add_patha/2","ref":"code.html#add_patha/2"},{"type":"function","doc":"","title":"code.add_paths/1","ref":"code.html#add_paths/1"},{"type":"function","doc":"","title":"code.add_paths/2","ref":"code.html#add_paths/2"},{"type":"function","doc":"","title":"code.add_pathsa/1","ref":"code.html#add_pathsa/1"},{"type":"function","doc":"Traverses `Dirs` and adds each `Dir` to the beginning of the code path.\n\nThis means that the order of `Dirs` is reversed in the resulting code\npath. For example, if `Dirs` is `[Dir1,Dir2]`, the resulting path will\nbe `[Dir2,Dir1|OldCodePath]`.\n\nIf a `Dir` already exists in the code path, it is removed from the old position.\n\nArgument `Cache` controls whether the content of the directory\nshould be cached on first traversal. If `Cache` is `cache` the directory\ncontents will be cached; if `Cache` is `nocache` it will not be cached.\n\nAlways returns `ok`, regardless of the validity of each individual `Dir`.","title":"code.add_pathsa/2","ref":"code.html#add_pathsa/2"},{"type":"function","doc":"","title":"code.add_pathsz/1","ref":"code.html#add_pathsz/1"},{"type":"function","doc":"Adds the directories in `Dirs` to the end of the code path.\n\nDirectories that are already present in the path will not be added.\n\nArgument `Cache` controls whether the content of the directory\nshould be cached on first traversal. If `Cache` is `cache` the directory\ncontents will be cached; if `Cache` is `nocache` it will not be cached.\n\nAlways returns `ok`, regardless of the validity of each individual `Dir`.","title":"code.add_pathsz/2","ref":"code.html#add_pathsz/2"},{"type":"function","doc":"","title":"code.add_pathz/1","ref":"code.html#add_pathz/1"},{"type":"function","doc":"Adds `Dir` as the directory last in the code path.\n\nIf `Dir` already exists in the path, it is not added.\n\nArgument `Cache` controls whether the content of the directory\nshould be cached on first traversal. If `Cache` is `cache` the directory\ncontents will be cached; if `Cache` is `nocache` it will not be cached.\n\nReturns `true` if successful, or `{error, bad_directory}` if `Dir` is\nnot the name of a directory.","title":"code.add_pathz/2","ref":"code.html#add_pathz/2"},{"type":"function","doc":"Returns a list of tuples `{Module, Filename, Loaded}` for all available modules.\n\nA module is considered to be available if it either is loaded or would be loaded\nif called. `Filename` is normally the absolute filename, as described for\n`is_loaded/1`.","title":"code.all_available/0","ref":"code.html#all_available/0"},{"type":"function","doc":"Returns a list of tuples `{Module, Loaded}` for all loaded modules.\n\n`Loaded` is normally the absolute filename, as described for `is_loaded/1`.","title":"code.all_loaded/0","ref":"code.html#all_loaded/0"},{"type":"function","doc":"Tries to load all of the modules in the list `Modules` atomically.\n\nThat means that either all modules are loaded at the same time, or\nnone of the modules are loaded if there is a problem with any of the\nmodules.\n\nLoading can fail for one the following reasons:\n\n- **`badfile`** - The object code has an incorrect format or the module name in\n the object code is not the expected module name.\n\n- **`nofile`** - No file with object code exists.\n\n- **`on_load_not_allowed`** - A module contains an\n [\\-on_load function](`e:system:code_loading.md#on_load`).\n\n- **`duplicated`** - A module is included more than once in `Modules`.\n\n- **`not_purged`** - The object code cannot be loaded because an old version of\n the code already exists.\n\n- **`sticky_directory`** - The object code resides in a sticky directory.\n\n- **`pending_on_load`** - A previously loaded module contains an `-on_load`\n function that never finished.\n\nIf it is important to minimize the time that an application is inactive while\nchanging code, use `prepare_loading/1` and `finish_loading/1` instead of\n[`atomic_load/1`](`atomic_load/1`). Here is an example:\n\n```erlang\n{ok,Prepared} = code:prepare_loading(Modules),\n%% Put the application into an inactive state or do any\n%% other preparation needed before changing the code.\nok = code:finish_loading(Prepared),\n%% Resume the application.\n```","title":"code.atomic_load/1","ref":"code.html#atomic_load/1"},{"type":"function","doc":"Searches all directories in the code path for module names with identical names\nand writes a report to `stdout`.","title":"code.clash/0","ref":"code.html#clash/0"},{"type":"function","doc":"Clears the code path cache.\n\nIf a directory is cached, its cache is cleared once and then it will\nbe recalculated and cached once more in a future traversal.\n\nTo clear the cache for a single path, either re-add it to the code\npath (with [`add_path/2`](`add_path/2`)) or replace it (with\n[`replace_path/3`](`replace_path/3`)). To disable all caching, reset\nthe code path with `code:set_path(code:get_path())`.\n\nAlways returns `ok`.","title":"code.clear_cache/0","ref":"code.html#clear_cache/0"},{"type":"function","doc":"Returns the compiler library directory.\n\nEquivalent to [`code:lib_dir(compiler)`](`code:lib_dir/1`).","title":"code.compiler_dir/0","ref":"code.html#compiler_dir/0"},{"type":"function","doc":"Returns `true` if the system supports coverage and `false` otherwise.\n\n_See also:_ [Native Coverage Support](#module-native-coverage-support)","title":"code.coverage_support/0","ref":"code.html#coverage_support/0"},{"type":"function","doc":"Deletes a directory from the code path.\n\nThe argument can be an atom `Name`, in which case the directory with\nthe name `.../Name[-Vsn][/ebin]` is deleted from the code path. Also,\nthe complete directory name `Dir` can be specified as argument.\n\nReturns:\n\n- **`true`** - If successful\n\n- **`false`** - If the directory is not found\n\n- **`{error, bad_name}`** - If the argument is invalid","title":"code.del_path/1","ref":"code.html#del_path/1"},{"type":"function","doc":"Deletes directories from the code path.\n\nThe argument is a list of either atoms or complete directory names. If\n`Name` is an atom, the directory with the name `.../Name[-Vsn][/ebin]` is\ndeleted from the code path.\n\nAlways returns `ok`, regardless of the validity of each individual\n`NamesOrDirs`.","title":"code.del_paths/1","ref":"code.html#del_paths/1"},{"type":"function","doc":"Removes the current code for `Module`, that is, the current code for `Module` is\nmade old.\n\nThis means that processes can continue to execute the code in the\nmodule, but no external function calls can be made to it.\n\nReturns `true` if successful, or `false` if there is old code for `Module` that\nmust be purged first, or if `Module` is not a (loaded) module.","title":"code.delete/1","ref":"code.html#delete/1"},{"type":"function","doc":"Tries to load a module in the same way as `load_file/1`, unless the module is\nalready loaded.\n\nIf called concurrently, this function ensures that only one process\nattempts to load said module at a given time.\n\nIn embedded mode, it does not load a module that is not already loaded, but\nreturns `{error, embedded}` instead. See\n[Error Reasons for Code-Loading Functions](`m:code#error_reasons`) for a\ndescription of other possible error reasons.","title":"code.ensure_loaded/1","ref":"code.html#ensure_loaded/1"},{"type":"function","doc":"Tries to load any modules not already loaded in the list `Modules` in the same\nway as `load_file/1`.\n\nUnlike `ensure_loaded/1`, modules are loaded even in `embedded` mode.\n\nReturns `ok` if successful, or `{error,[{Module,Reason}]}` if loading of some\nmodules fails. See\n[Error Reasons for Code-Loading Functions](`m:code#error_reasons`) for a\ndescription of other possible error reasons.","title":"code.ensure_modules_loaded/1","ref":"code.html#ensure_modules_loaded/1"},{"type":"function","doc":"Tries to load code for all modules that have been previously prepared by\n`prepare_loading/1`.\n\nThe loading occurs atomically, meaning that either all modules are\nloaded at the same time, or none of the modules are loaded.\n\nThis function can fail with one of the following error reasons:\n\n- **`not_purged`** - The object code cannot be loaded because an old version of\n the code already exists.\n\n- **`sticky_directory`** - The object code resides in a sticky directory.\n\n- **`pending_on_load`** - A previously loaded module contains an `-on_load`\n function that never finished.","title":"code.finish_loading/1","ref":"code.html#finish_loading/1"},{"type":"function","doc":"Return either `function` or `line` coverage data for module `Module`.\n\nIf Level is `function`, returns function coverage for the given module\naccording to its [coverage mode](`t:coverage_mode/0`):\n\n- **`function`** - For each function in module Module, a boolean indicating\n whether that function has been executed at least once is returned.\n\n- **`function_counters`** - For each function in module Module, an integer\n giving the number of times that line has been executed is returned.\n\n- **`line`** - For each function in module Module, a boolean indicating whether\n that function has been executed at least once is returned.\n\n- **`line_counters`** - For each function in module Module, a boolean indicating\n whether that function has been executed at least once is returned (note that\n in this mode, counters for the number of times each function has been executed\n **cannot** be retrieved).\n\nIf Level is `line`, returns line coverage for the given module according to its\ncoverage mode:\n\n- **`line`** - For each executable line in the module, a boolean indicating\n whether that line has been executed at least once is returned.\n\n- **`line_counters`** - For each executable line in the module, an integer\n giving the number of times that line was executed is returned.\n\nLevel `cover_id_line` is used by the `m:cover` tool.\n\nFailures:\n\n- **`badarg`** - If `Level` is not `function` or `line`.\n\n- **`badarg`** - If `Module` is not an atom.\n\n- **`badarg`** - If `Module` does not refer to a loaded module.\n\n- **`badarg`** - If `Module` was not loaded in another coverage mode than\n `none`.\n\n- **`badarg`** - If Level is `line` and `Module` has not been loaded with either\n `line` or `line_counters` enabled.\n\n- **`badarg`** - If the runtime system does not support coverage.\n\n_See also:_ [Native Coverage Support](#module-native-coverage-support)","title":"code.get_coverage/2","ref":"code.html#get_coverage/2"},{"type":"function","doc":"Returns the coverage mode as set by option\n[\\+JPcover](`e:erts:erl_cmd.md#%2BJPcover`) for `erl` or `set_coverage_mode/1`.\n\nFailure:\n\n- **`badarg`** - If the runtime system does not support coverage.\n\n_See also:_ [Native Coverage Support](#module-native-coverage-support)","title":"code.get_coverage_mode/0","ref":"code.html#get_coverage_mode/0"},{"type":"function","doc":"Get coverage mode for the given module.\n\nFailures:\n\n- **`badarg`** - If `Module` is not an atom.\n\n- **`badarg`** - If `Module` does not refer to a loaded module.\n\n- **`badarg`** - If the runtime system does not support coverage.\n\n_See also:_ [Native Coverage Support](#module-native-coverage-support)","title":"code.get_coverage_mode/1","ref":"code.html#get_coverage_mode/1"},{"type":"function","doc":"Returns [EEP 48](https://www.erlang.org/eeps/eep-0048.html) style\ndocumentation for `Module` if available.\n\nIf `Module` is not found in the code path, this function returns\n`{error,non_existing}`.\n\nIf no documentation can be found this function attempts to generate\ndocumentation from the debug information in the module. If no debug\ninformation is available, this function returns `{error,missing}`.\n\nFor more information about the documentation chunk see\n[Documentation Storage and Format](eep48_chapter.md) in\nKernel's User's Guide.","title":"code.get_doc/1","ref":"code.html#get_doc/1"},{"type":"function","doc":"Returns an atom describing the mode of the code server: `interactive` or\n`embedded`.\n\nThis information is useful when an external entity (for example, an IDE)\nprovides additional code for a running node. If the code server is in\ninteractive mode, it only has to add the path to the code. If the code server is\nin embedded mode, the code must be loaded with `load_binary/3`.","title":"code.get_mode/0","ref":"code.html#get_mode/0"},{"type":"function","doc":"Returns the object code for module `Module` if found in the code path.\n\nReturns `{Module, Binary, Filename}` if successful, otherwise\n`error`. `Binary` is a binary data object, which contains the object\ncode for the module. This is useful if code is to be loaded on a\nremote node in a distributed system. For example, loading module\n`Module` on a node `Node` is done as follows:\n\n```erlang\n...\n{_Module, Binary, Filename} = code:get_object_code(Module),\nerpc:call(Node, code, load_binary, [Module, Filename, Binary]),\n...\n```","title":"code.get_object_code/1","ref":"code.html#get_object_code/1"},{"type":"function","doc":"Returns the code path.","title":"code.get_path/0","ref":"code.html#get_path/0"},{"type":"function","doc":"Checks whether `Module` is loaded.\n\nIf it is, `{file, Loaded}` is returned, otherwise `false`.\n\nNormally, `Loaded` is the absolute filename `Filename` from which the code is\nobtained. If the module is preloaded (see [`script(4)`](`e:sasl:script.md`)),\n`Loaded =:= preloaded`. If the module is Cover-compiled (see `m:cover`),\n`Loaded =:= cover_compiled`.","title":"code.is_loaded/1","ref":"code.html#is_loaded/1"},{"type":"function","doc":"Returns `true` if `Module` is the name of a module that has been loaded from a\nsticky directory (in other words: an attempt to reload the module will fail), or\n`false` if `Module` is not a loaded module or is not sticky.","title":"code.is_sticky/1","ref":"code.html#is_sticky/1"},{"type":"function","doc":"Returns the library directory, `$OTPROOT/lib`, where `$OTPROOT` is the root\ndirectory of Erlang/OTP.\n\n_Example:_\n\n```erlang\n1> code:lib_dir().\n\"/usr/local/otp/lib\"\n```","title":"code.lib_dir/0","ref":"code.html#lib_dir/0"},{"type":"function","doc":"Returns the path for the *library directory*, the top directory, for an\napplication `Name` located under `$OTPROOT/lib` or in a directory referred to\nwith environment variable `ERL_LIBS`.\n\nIf a regular directory called `Name` or `Name-Vsn` exists in the code path with\nan `ebin` subdirectory, the path to this directory is returned (not the `ebin`\ndirectory).\n\nIf the directory refers to a directory in an archive, the archive name is\nstripped away before the path is returned. For example, if directory\n`/usr/local/otp/lib/mnesia-4.2.2.ez/mnesia-4.2.2/ebin` is in the path,\n`/usr/local/otp/lib/mnesia-4.2.2/ebin` is returned. This means that the library\ndirectory for an application is the same, regardless if the application resides\nin an archive or not.\n\n> #### Warning {: .info }\n>\n> Archives are experimental. In a future release, they can be removed or\n> their behavior can change.\n\n_Example:_\n\n```erlang\n> code:lib_dir(mnesia).\n\"/usr/local/otp/lib/mnesia-4.23\"\n```\n\nReturns `{error, bad_name}` if `Name` is not the name of an application under\n`$OTPROOT/lib` or on a directory referred to through environment variable\n`ERL_LIBS`. Fails with an exception if `Name` has the wrong type.\n\n> #### Warning {: .warning }\n>\n> For backward compatibility, `Name` is also allowed to be a string. That will\n> probably change in a future release.","title":"code.lib_dir/1","ref":"code.html#lib_dir/1"},{"type":"function","doc":"Returns the path to a subdirectory directly under the top directory of an\napplication.\n\n> #### Change {: .info }\n>\n> This function is part of the archive support, which is an experimental\n> feature that will be changed or removed in a future release.\n\nNormally the subdirectories reside under the top directory for the\napplication, but when applications at least partly reside in an archive, the\nsituation is different. Some of the subdirectories can reside as regular\ndirectories while others reside in an archive file. It is not checked whether\nthis directory exists.\n\nInstead of using this function, use [`code:lib_dir/1`](`code:lib_dir/1`)\nand `filename:join/2`.\n\n_Example:_\n\n```erlang\n1> filename:join(code:lib_dir(megaco), \"priv\").\n\"/usr/local/otp/lib/megaco-3.9.1.1/priv\"\n```\n\nFails with an exception if `Name` or `SubDir` has the wrong type.","title":"code.lib_dir/2","ref":"code.html#lib_dir/2"},{"type":"function","doc":"Equivalent to [`load_file(Module)`](`load_file/1`), except that `Filename` is\nan absolute or relative filename.\n\nThe code path is not searched. It returns a value in the same way as\n`load_file/1`. Notice that `Filename` must not contain the extension\n(for example, `.beam`) because [`load_abs/1`](`load_abs/1`) adds the\ncorrect extension.","title":"code.load_abs/1","ref":"code.html#load_abs/1"},{"type":"function","doc":"Loads object code from a binary.\n\nThis function can be used to load object code on remote Erlang nodes. Argument\n`Binary` must contain object code for `Module`. `Filename` is only used by the\ncode server to keep a record of from which file the object code for `Module`\noriginates. Thus, `Filename` is not opened and read by the code server.\n\nReturns `{module, Module}` if successful, or `{error, Reason}` if loading fails.\nSee [Error Reasons for Code-Loading Functions](`m:code#error_reasons`) for a\ndescription of the possible error reasons.","title":"code.load_binary/3","ref":"code.html#load_binary/3"},{"type":"function","doc":"Tries to load the Erlang module `Module` using the code path.\n\nIt looks for the object code file with an extension corresponding to\nthe Erlang machine used, for example, `Module.beam`. The loading fails\nif the module name found in the object code differs from the name\n`Module`. Use `load_binary/3` to load object code with a module name\nthat is different from the file name.\n\nReturns `{module, Module}` if successful, or `{error, Reason}` if loading fails.\nSee [Error Reasons for Code-Loading Functions](`m:code#error_reasons`) for a\ndescription of the possible error reasons.","title":"code.load_file/1","ref":"code.html#load_file/1"},{"type":"function","doc":"Returns the list of all currently loaded modules for which `module_status/1`\nreturns `modified`.\n\nSee also `all_loaded/0`.","title":"code.modified_modules/0","ref":"code.html#modified_modules/0"},{"type":"function","doc":"See `module_status/1` and `all_loaded/0` for details.","title":"code.module_status/0","ref":"code.html#module_status/0"},{"type":"function","doc":"Returns the status of `Module` in relation to object file on disk.\n\nThe status of a module can be one of:\n\n- **`not_loaded`** - If `Module` is not currently loaded.\n\n- **`loaded`** - If `Module` is loaded, and the object file exists and contains\n the same code.\n\n- **`removed`** - If `Module` is loaded, but no corresponding object file can be\n found in the code path.\n\n- **`modified`** - If `Module` is loaded, but the object file contains code with\n a different MD5 checksum.\n\nPreloaded modules are always reported as `loaded`, without inspecting the\ncontents on disk. Cover-compiled modules will always be reported as `modified`\nif an object file exists, or as `removed` otherwise. Modules whose load path is\nan empty string (which is the convention for auto-generated code) will only be\nreported as `loaded` or `not_loaded`.\n\nSee also `modified_modules/0`.","title":"code.module_status/1","ref":"code.html#module_status/1"},{"type":"function","doc":"Returns the object code file extension corresponding to the Erlang machine used.\n\nFor the official Erlang/OTP release, the return value is always `.beam`.","title":"code.objfile_extension/0","ref":"code.html#objfile_extension/0"},{"type":"function","doc":"Prepares to load the modules in the list `Modules`.\n\nFinish the loading by calling\n[finish_loading(Prepared)](`finish_loading/1`).\n\nThis function can fail with one of the following error reasons:\n\n- **`badfile`** - The object code has an incorrect format or the module name in\n the object code is not the expected module name.\n\n- **`nofile`** - No file with object code exists.\n\n- **`on_load_not_allowed`** - A module contains an\n [\\-on_load function](`e:system:code_loading.md#on_load`).\n\n- **`duplicated`** - A module is included more than once in `Modules`.","title":"code.prepare_loading/1","ref":"code.html#prepare_loading/1"},{"type":"function","doc":"Returns the path to the `priv` directory in an application.\n\n> #### Warning {: .warning }\n>\n> For backward compatibility, `Name` is also allowed to be a string. That will\n> probably change in a future release.","title":"code.priv_dir/1","ref":"code.html#priv_dir/1"},{"type":"function","doc":"Purges the code for `Module`, that is, removes code marked as old.\n\nIf some processes still linger in the old code, these processes are\nkilled before the code is removed.\n\n> #### Change {: .info }\n>\n> As of Erlang/OTP 20.0, a process is only considered to be lingering in the\n> code if it has direct references to the code. For more information see\n> documentation of `erlang:check_process_code/3`, which is used in order to\n> determine whether a process is lingering.\n\nReturns `true` if successful and any process is needed to be killed, otherwise\n`false`.","title":"code.purge/1","ref":"code.html#purge/1"},{"type":"function","doc":"","title":"code.replace_path/2","ref":"code.html#replace_path/2"},{"type":"function","doc":"Replaces an old occurrence of a directory named `.../Name[-Vsn][/ebin]` in the\ncode path, with `Dir`.\n\nIf `Name` does not exist, it adds the new directory `Dir` last in the\ncode path. The new directory must also be named\n`.../Name[-Vsn][/ebin]`. This function is to be used if a new version\nof the directory (library) is added to a running system.\n\nArgument `Cache` controls whether the content of the directory\nshould be cached on first traversal. If `Cache` is `cache` the directory\ncontents will be cached; if `Cache` is `nocache` it will not be cached.\n\nReturns:\n\n- **`true`** - If successful\n\n- **`{error, bad_name}`** - If `Name` is not found\n\n- **`{error, bad_directory}`** - If `Dir` does not exist\n\n- **`{error, {badarg, [Name, Dir]}}`** - If `Name` or `Dir` is invalid","title":"code.replace_path/3","ref":"code.html#replace_path/3"},{"type":"function","doc":"Resets coverage information for module `Module`.\n\nIf the [coverage mode](`t:coverage_mode/0`) is either `function` or\n`line`, all booleans for `Module` keeping track of executed functions\nor lines are set to `false`.\n\nIf the coverage mode is either `function_counters` or\n`line_counters`, all counters for `Module` are reset to zero.\n\nFailures:\n\n- **`badarg`** - If `Module` is not an atom.\n\n- **`badarg`** - If `Module` does not refer to a loaded module.\n\n- **`badarg`** - If `Module` was not loaded with coverage enabled.\n\n- **`badarg`** - If the runtime system does not support coverage.\n\n_See also:_ [Native Coverage Support](#module-native-coverage-support)","title":"code.reset_coverage/1","ref":"code.html#reset_coverage/1"},{"type":"function","doc":"Returns the root directory of Erlang/OTP, which is the directory where it is\ninstalled.\n\n_Example:_\n\n```erlang\n1> code:root_dir().\n\"/usr/local/otp\"\n```","title":"code.root_dir/0","ref":"code.html#root_dir/0"},{"type":"function","doc":"Sets the coverage mode for modules that are subsequently loaded, similar to\noption [\\+JPcover](`e:erts:erl_cmd.md#%2BJPcover`) for `erl`.\n\nThe coverage mode will have the following effect on code that is\nloaded following this call:\n\n- **`function`** - All modules that are loaded will be instrumented to keep\n track of which functions are executed. Information about which functions that\n have been executed can be retrieved by calling\n [`get_coverage(function, Module)`](`get_coverage/2`).\n\n- **`function_counters`** - All modules that are loaded will be instrumented to\n count how many times each function is executed. Information about how many\n times each function has been executed can be retrieved by calling\n [`get_coverage(function, Module)`](`get_coverage/2`).\n\n- **`line`** - When modules that have been compiled with the\n [`line_coverage`](`m:compile#line_coverage`) option are loaded, they will be\n instrumented to keep track of which lines have been executed. Information\n about which lines have been executed can be retrieved by calling\n [`get_coverage(line, Module)`](`get_coverage/2`), and information about which\n functions that have been executed can be retrieved by calling\n [`get_coverage(function, Module)`](`get_coverage/2`).\n\n- **`line_counters`** - When modules that have been compiled with the\n [`line_coverage`](`m:compile#line_coverage`) option are loaded, they will be\n instrumented to count the number of times each line is executed. Information\n about how many times each line has been executed can be retrieved by calling\n [`get_coverage(line, Module)`](`get_coverage/2`), and information about which\n functions that have been executed can be retrieved by calling\n [`get_coverage(function, Module)`](`get_coverage/2`) (note that in this mode,\n counters for the number of times each function has been executed **cannot** be\n retrieved).\n\n- **`none`** - Modules will be loaded without coverage instrumentation.\n\nReturns the previous coverage mode.\n\nFailures:\n\n- **`badarg`** - If `Mode` is not a valid coverage mode.\n\n- **`badarg`** - If the runtime system does not support coverage.\n\n_See also:_ [Native Coverage Support](#module-native-coverage-support)","title":"code.set_coverage_mode/1","ref":"code.html#set_coverage_mode/1"},{"type":"function","doc":"","title":"code.set_path/1","ref":"code.html#set_path/1"},{"type":"function","doc":"Sets the code path to the list of directories `Path`.\n\nArgument `Cache` controls whether the content of the directory\nshould be cached on first traversal. If `Cache` is `cache` the directory\ncontents will be cached; if `Cache` is `nocache` it will not be cached.\n\nReturns:\n\n- **`true`** - If successful\n\n- **`{error, bad_directory}`** - If any `Dir` is not a directory name","title":"code.set_path/2","ref":"code.html#set_path/2"},{"type":"function","doc":"Purges the code for `Module`, that is, removes code marked as old, but only if\nno processes linger in it.\n\n> #### Change {: .info }\n>\n> As of Erlang/OTP 20.0, a process is only considered to be lingering in the\n> code if it has direct references to the code. For more information see\n> documentation of `erlang:check_process_code/3`, which is used in order to\n> determine whether a process is lingering.\n\nReturns `false` if the module cannot be purged because of processes lingering in\nold code, otherwise `true`.","title":"code.soft_purge/1","ref":"code.html#soft_purge/1"},{"type":"function","doc":"Marks `Dir` as sticky.\n\nReturns `ok` if successful, otherwise `error`.","title":"code.stick_dir/1","ref":"code.html#stick_dir/1"},{"type":"function","doc":"Unsticks a directory that is marked as sticky.\n\nReturns `ok` if successful, otherwise `error`.","title":"code.unstick_dir/1","ref":"code.html#unstick_dir/1"},{"type":"function","doc":"Searches the code path for `Filename`, which is a file of arbitrary type.\n\nIf found, the full name is returned. `non_existing` is returned if the\nfile cannot be found. The function can be useful, for example, to\nlocate application resource files.","title":"code.where_is_file/1","ref":"code.html#where_is_file/1"},{"type":"function","doc":"If the module is not loaded, this function searches the code path for the first\nfile containing object code for `Module` and returns the absolute filename.\n\n- If the module is loaded, it returns the name of the file containing the loaded\n object code.\n\n- If the module is preloaded, `preloaded` is returned.\n\n- If the module is Cover-compiled, `cover_compiled` is returned.\n\n- If the module cannot be found, `non_existing` is returned.","title":"code.which/1","ref":"code.html#which/1"},{"type":"type","doc":"","title":"code.add_path_ret/0","ref":"code.html#t:add_path_ret/0"},{"type":"type","doc":"","title":"code.cache/0","ref":"code.html#t:cache/0"},{"type":"type","doc":"","title":"code.coverage_mode/0","ref":"code.html#t:coverage_mode/0"},{"type":"type","doc":"","title":"code.load_error_rsn/0","ref":"code.html#t:load_error_rsn/0"},{"type":"type","doc":"","title":"code.load_ret/0","ref":"code.html#t:load_ret/0"},{"type":"type","doc":"","title":"code.loaded_filename/0","ref":"code.html#t:loaded_filename/0"},{"type":"type","doc":"","title":"code.loaded_ret_atoms/0","ref":"code.html#t:loaded_ret_atoms/0"},{"type":"type","doc":"","title":"code.module_status/0","ref":"code.html#t:module_status/0"},{"type":"opaque","doc":"An opaque term holding prepared code.","title":"code.prepared_code/0","ref":"code.html#t:prepared_code/0"},{"type":"type","doc":"","title":"code.replace_path_ret/0","ref":"code.html#t:replace_path_ret/0"},{"type":"type","doc":"","title":"code.set_path_ret/0","ref":"code.html#t:set_path_ret/0"},{"type":"module","doc":"Dynamic driver loader and linker.\n\nThis module provides an interface for loading and unloading _Erlang linked-in\ndrivers_ in runtime.\n\n> #### Note {: .info }\n>\n> This is a large reference document. For casual use of this module, and for\n> most real world applications, the descriptions of functions `load/2` and\n> `unload/1` are enough to getting started.\n\nThe driver is to be provided as a dynamically linked library in an object code\nformat specific for the platform in use, that is, `.so` files on most Unix\nsystems and `.ddl` files on Windows. An Erlang linked-in driver must provide\nspecific interfaces to the emulator, so this module is not designed for loading\narbitrary dynamic libraries. For more information about Erlang drivers, see\n[`erl_driver`](`e:erts:erl_driver.md`) .\n\n[](){: #users }\n\nWhen describing a set of functions (that is, a module, a part of a module, or an\napplication), executing in a process and wanting to use a ddll-driver, we use\nthe term _user_. A process can have many users (different modules needing the\nsame driver) and many processes running the same code, making up many _users_ of\na driver.\n\nIn the basic scenario, each user loads the driver before starting to use it and\nunloads the driver when done. The reference counting keeps track of processes\nand the number of loads by each process. This way the driver is only unloaded\nwhen no one wants it (it has no user). The driver also keeps track of ports that\nare opened to it. This enables delay of unloading until all ports are closed, or\nkilling of all ports that use the driver when it is unloaded.\n\n[](){: #scenarios }\n\nThe interface supports two basic scenarios of loading and unloading. Each\nscenario can also have the option of either killing ports when the driver is\nunloading, or waiting for the ports to close themselves. The scenarios are as\nfollows:\n\n- **_Load and Unload on a \"When Needed Basis\"_** - This (most common) scenario\n simply supports that each [user](`m:erl_ddll#users`) of the driver loads it\n when needed and unloads it when no longer needed. The driver is always\n reference counted and as long as a process keeping the driver loaded is still\n alive, the driver is present in the system.\n\n Each [user](`m:erl_ddll#users`) of the driver use _literally_ the same\n pathname for the driver when demanding load, but the\n [users](`m:erl_ddll#users`) are not concerned with if the driver is already\n loaded from the file system or if the object code must be loaded from file\n system.\n\n The following two pairs of functions support this scenario:\n\n - **_load/2 and unload/1_** - When using the `load/unload` interfaces, the\n driver is not unloaded until the _last port_ using the driver is closed.\n Function [`unload/1`](`unload/1`) can return immediately, as the\n [users](`m:erl_ddll#users`) have no interest in when the unloading occurs.\n The driver is unloaded when no one needs it any longer.\n\n If a process having the driver loaded dies, it has the same effect as if\n unloading is done.\n\n When loading, function [`load/2`](`load/2`) returns `ok` when any instance\n of the driver is present. Thus, if a driver is waiting to get unloaded\n (because of open ports), it simply changes state to no longer need\n unloading.\n\n - **_load_driver/2 and unload_driver/1_** - These interfaces are intended to\n be used when it is considered an error that ports are open to a driver that\n no [user](`m:erl_ddll#users`) has loaded. The ports that are still open when\n the last [user](`m:erl_ddll#users`) calls\n [`unload_driver/1`](`unload_driver/1`) or when the last process having the\n driver loaded dies, are killed with reason `driver_unloaded`.\n\n The function names `load_driver` and `unload_driver` are kept for backward\n compatibility.\n\n- **_Loading and Reloading for Code Replacement_** - This scenario can occur if\n the driver code needs replacement during operation of the Erlang emulator.\n Implementing driver code replacement is a little more tedious than Beam code\n replacement, as one driver cannot be loaded as both \"old\" and \"new\" code. All\n [users](`m:erl_ddll#users`) of a driver must have it closed (no open ports)\n before the old code can be unloaded and the new code can be loaded.\n\n The unloading/loading is done as one atomic operation, blocking all processes\n in the system from using the driver in question while in progress.\n\n The preferred way to do driver code replacement is to let _one single process_\n keep track of the driver. When the process starts, the driver is loaded. When\n replacement is required, the driver is reloaded. Unload is probably never\n done, or done when the process exits. If more than one\n [user](`m:erl_ddll#users`) has a driver loaded when code replacement is\n demanded, the replacement cannot occur until the last \"other\"\n [user](`m:erl_ddll#users`) has unloaded the driver.\n\n Demanding reload when a reload is already in progress is always an error.\n Using the high-level functions, it is also an error to demand reloading when\n more than one [user](`m:erl_ddll#users`) has the driver loaded.\n\n To simplify driver replacement, avoid designing your system so that more than\n one [user](`m:erl_ddll#users`) has the driver loaded.\n\n The two functions for reloading drivers are to be used together with\n corresponding load functions to support the two different behaviors concerning\n open ports:\n\n - **_load/2 and reload/2_** - This pair of functions is used when reloading is\n to be done after the last open port to the driver is closed.\n\n As [`reload/2`](`reload/2`) waits for the reloading to occur, a misbehaving\n process keeping open ports to the driver (or keeping the driver loaded) can\n cause infinite waiting for reload. Time-outs must be provided outside of the\n process demanding the reload or by using the low-level interface\n `try_load/3` in combination with driver monitors.\n\n - **_load_driver/2 and reload_driver/2_** - This pair of functions are used\n when open ports to the driver are to be killed with reason `driver_unloaded`\n to allow for new driver code to get loaded.\n\n However, if another process has the driver loaded, calling `reload_driver`\n returns error code `pending_process`. As stated earlier, the recommended\n design is to not allow other [users](`m:erl_ddll#users`) than the \"driver\n reloader\" to demand loading of the driver in question.","title":"erl_ddll","ref":"erl_ddll.html"},{"type":"module","doc":"[`erl_driver(4)`](`e:erts:erl_driver.md`), [`driver_entry(4)`](`e:erts:driver_entry.md`)","title":"See Also - erl_ddll","ref":"erl_ddll.html#module-see-also"},{"type":"function","doc":"Removes a driver monitor in much the same way as `erlang:demonitor/1` in ERTS\ndoes with process monitors.\n\nFor details about how to create driver monitors, see `monitor/2`,\n`try_load/3`, and `try_unload/2`.\n\nThe function throws a `badarg` exception if the parameter is not a\n`t:reference/0`.","title":"erl_ddll.demonitor/1","ref":"erl_ddll.html#demonitor/1"},{"type":"function","doc":"Takes an `ErrorDesc` returned by load, unload, or reload functions and returns a\nstring that describes the error or warning.\n\n> #### Note {: .info }\n>\n> Because of peculiarities in the dynamic loading interfaces on different\n> platforms, the returned string is only guaranteed to describe the correct\n> error _if format_error/1 is called in the same instance of the Erlang virtual\n> machine as the error appeared in_ (meaning the same operating system process).","title":"erl_ddll.format_error/1","ref":"erl_ddll.html#format_error/1"},{"type":"function","doc":"Returns a list of tuples `{DriverName, InfoList}`, where `InfoList` is the\nresult of calling `info/1` for that `DriverName`. Only dynamically linked-in\ndrivers are included in the list.","title":"erl_ddll.info/0","ref":"erl_ddll.html#info/0"},{"type":"function","doc":"Returns a list of tuples `{Tag, Value}`, where `Tag` is the information item and\n`Value` is the result of calling `info/2` with this driver name and this tag.\nThe result is a tuple list containing all information available about a driver.\n\nThe following tags appears in the list:\n\n- `processes`\n- `driver_options`\n- `port_count`\n- `linked_in_driver`\n- `permanent`\n- `awaiting_load`\n- `awaiting_unload`\n\nFor a detailed description of each value, see `info/2`.\n\nThe function throws a `badarg` exception if the driver is not present in the\nsystem.","title":"erl_ddll.info/1","ref":"erl_ddll.html#info/1"},{"type":"function","doc":"Returns specific information about one aspect of a driver. Parameter `Tag`\nspecifies which aspect to get information about. The return `Value` differs\nbetween different tags:\n\n- **`processes`** - Returns all processes containing [users](`m:erl_ddll#users`)\n of the specific drivers as a list of tuples `{pid(),integer() >= 0}`, where\n `t:integer/0` denotes the number of users in process `t:pid/0`.\n\n- **`driver_options`** - Returns a list of the driver options provided when\n loading, and any options set by the driver during initialization. The only\n valid option is `kill_ports`.\n\n- **`port_count`** - Returns the number of ports (an `integer() >= 0`) using the\n driver.\n\n- **`linked_in_driver`** - Returns a `t:boolean/0`, which is `true` if the\n driver is a statically linked-in one, otherwise `false`.\n\n- **`permanent`** - Returns a `t:boolean/0`, which is `true` if the driver has\n made itself permanent (and is _not_ a statically linked-in driver), otherwise\n `false`.\n\n- **`awaiting_load`** - Returns a list of all processes having monitors for\n `loading` active. Each process is returned as `{pid(),integer() >= 0}`, where\n `t:integer/0` is the number of monitors held by process `t:pid/0`.\n\n- **`awaiting_unload`** - Returns a list of all processes having monitors for\n `unloading` active. Each process is returned as `{pid(),integer() >= 0}`,\n where `t:integer/0` is the number of monitors held by process `t:pid/0`.\n\nIf option `linked_in_driver` or `permanent` returns `true`, all other options\nreturn `linked_in_driver` or `permanent`, respectively.\n\nThe function throws a `badarg` exception if the driver is not present in the\nsystem or if the tag is not supported.","title":"erl_ddll.info/2","ref":"erl_ddll.html#info/2"},{"type":"function","doc":"Loads and links the dynamic driver `Name`. `Path` is a file path to the\ndirectory containing the driver. `Name` must be a shareable object/dynamic\nlibrary. Two drivers with different `Path` parameters cannot be loaded under the\nsame name. `Name` is a string or atom containing at least one character.\n\nThe `Name` specified is to correspond to the filename of the dynamically\nloadable object file residing in the directory specified as `Path`, but\n_without_ the extension (that is, `.so`). The driver name provided in the driver\ninitialization routine must correspond with the filename, in much the same way\nas Erlang module names correspond to the names of the `.beam` files.\n\nIf the driver was previously unloaded, but is still present because of open\nports to it, a call to [`load/2`](`load/2`) stops the unloading and keeps the\ndriver (as long as `Path` is the same), and `ok` is returned. If you really want\nthe object code to be reloaded, use `reload/2` or the low-level interface\n`try_load/3` instead. See also the description of\n[`different scenarios`](`m:erl_ddll#scenarios`) for loading/unloading in the\nintroduction.\n\nIf more than one process tries to load an already loaded driver with the same\n`Path`, or if the same process tries to load it many times, the function returns\n`ok`. The emulator keeps track of the [`load/2`](`load/2`) calls, so that a\ncorresponding number of `unload/2` calls must be done from the same process\nbefore the driver gets unloaded. It is therefore safe for an application to load\na driver that is shared between processes or applications when needed. It can\nsafely be unloaded without causing trouble for other parts of the system.\n\nIt is not allowed to load multiple drivers with the same name but with different\n`Path` parameters.\n\n> #### Note {: .info }\n>\n> `Path` is interpreted literally, so that all loaders of the same driver must\n> specify the same _literal_ `Path` string, although different paths can point\n> out the same directory in the file system (because of use of relative paths\n> and links).\n\nOn success, the function returns `ok`. On failure, the return value is\n`{error,ErrorDesc}`, where `ErrorDesc` is an opaque term to be translated into\nhuman readable form by function `format_error/1`.\n\nFor more control over the error handling, use the `try_load/3` interface\ninstead.\n\nThe function throws a `badarg` exception if the parameters are not specified as\ndescribed here.","title":"erl_ddll.load/2","ref":"erl_ddll.html#load/2"},{"type":"function","doc":"Works essentially as [`load/2`](`load/2`), but loads the driver with other\noptions. All ports using the driver are killed with reason `driver_unloaded`\nwhen the driver is to be unloaded.\n\nThe number of loads and unloads by different [users](`m:erl_ddll#users`)\ninfluences the loading and unloading of a driver file. The port killing\ntherefore only occurs when the _last_ [user](`m:erl_ddll#users`) unloads the\ndriver, or when the last process having loaded the driver exits.\n\nThis interface (or at least the name of the functions) is kept for backward\ncompatibility. Using `try_load/3` with `{driver_options,[kill_ports]}` in the\noption list gives the same effect regarding the port killing.\n\nThe function throws a `badarg` exception if the parameters are not specified as\ndescribed here.","title":"erl_ddll.load_driver/2","ref":"erl_ddll.html#load_driver/2"},{"type":"function","doc":"Returns a list of all the available drivers, both (statically) linked-in and\ndynamically loaded ones.\n\nThe driver names are returned as a list of strings rather than a list of atoms\nfor historical reasons.\n\nFor more information about drivers, see [`info`](`info/0`).","title":"erl_ddll.loaded_drivers/0","ref":"erl_ddll.html#loaded_drivers/0"},{"type":"function","doc":"Creates a driver monitor and works in many ways as `erlang:monitor/2` in ERTS,\ndoes for processes. When a driver changes state, the monitor results in a\nmonitor message that is sent to the calling process. `MonitorRef` returned by\nthis function is included in the message sent.\n\nAs with process monitors, each driver monitor set only generates _one single\nmessage_. The monitor is \"destroyed\" after the message is sent, so it is then\nnot needed to call `demonitor/1`.\n\n`MonitorRef` can also be used in subsequent calls to `demonitor/1` to remove a\nmonitor.\n\nThe function accepts the following parameters:\n\n- **`Tag`** - The monitor tag is always `driver`, as this function can only be\n used to create driver monitors. In the future, driver monitors will be\n integrated with process monitors, why this parameter has to be specified for\n consistence.\n\n- **`Item`** - Parameter `Item` specifies which driver to monitor (the driver\n name) and which state change to monitor. The parameter is a tuple of arity two\n whose first element is the driver name and second element is one of the\n following:\n\n - **`loaded`** - Notifies when the driver is reloaded (or loaded if loading is\n underway). It only makes sense to monitor drivers that are in the process of\n being loaded or reloaded. A future driver name for loading cannot be\n monitored. That only results in a `DOWN` message sent immediately.\n Monitoring for loading is therefore most useful when triggered by function\n `try_load/3`, where the monitor is created _because_ the driver is in such a\n pending state.\n\n Setting a driver monitor for `loading` eventually leads to one of the\n following messages being sent:\n\n - **`{'UP', reference(), driver, Name, loaded}`** - This message is sent\n either immediately if the driver is already loaded and no reloading is\n pending, or when reloading is executed if reloading is pending.\n\n The [user](`m:erl_ddll#users`) is expected to know if reloading is\n demanded before creating a monitor for loading.\n\n - **`{'UP', reference(), driver, Name, permanent}`** - This message is sent\n if reloading was expected, but the (old) driver made itself permanent\n before reloading. It is also sent if the driver was permanent or\n statically linked-in when trying to create the monitor.\n\n - **`{'DOWN', reference(), driver, Name, load_cancelled}`** - This message\n arrives if reloading was underway, but the requesting\n [user](`m:erl_ddll#users`) cancelled it by dying or calling `try_unload/2`\n (or [`unload/1`](`unload/1`)/[`unload_driver/1`](`unload_driver/1`)) again\n before it was reloaded.\n\n - **`{'DOWN', reference(), driver, Name, {load_failure, Failure}}`** - This\n message arrives if reloading was underway but the loading for some reason\n failed. The `Failure` term is one of the errors that can be returned from\n `try_load/3`. The error term can be passed to `format_error/1` for\n translation into human readable form. Notice that the translation must be\n done in the same running Erlang virtual machine as the error was detected\n in.\n\n - **`unloaded`** - Monitors when a driver gets unloaded. If one monitors a\n driver that is not present in the system, one immediately gets notified that\n the driver got unloaded. There is no guarantee that the driver was ever\n loaded.\n\n A driver monitor for unload eventually results in one of the following\n messages being sent:\n\n - **`{'DOWN', reference(), driver, Name, unloaded}`** - The monitored driver\n instance is now unloaded. As the unload can be a result of a\n [`reload/2`](`reload/2`) request, the driver can once again have been\n loaded when this message arrives.\n\n - **`{'UP', reference(), driver, Name, unload_cancelled}`** - This message\n is sent if unloading was expected, but while the driver was waiting for\n all ports to get closed, a new [user](`m:erl_ddll#users`) of the driver\n appeared, and the unloading was cancelled.\n\n This message appears if `{ok, pending_driver}` was returned from\n `try_unload/2` for the last [user](`m:erl_ddll#users`) of the driver, and\n then `{ok, already_loaded}` is returned from a call to `try_load/3`.\n\n If one _really_ wants to monitor when the driver gets unloaded, this\n message distorts the picture, because no unloading was done. Option\n `unloaded_only` creates a monitor similar to an `unloaded` monitor, but\n never results in this message.\n\n - **`{'UP', reference(), driver, Name, permanent}`** - This message is sent\n if unloading was expected, but the driver made itself permanent before\n unloading. It is also sent if trying to monitor a permanent or statically\n linked-in driver.\n\n - **`unloaded_only`** - A monitor created as `unloaded_only` behaves exactly\n as one created as `unloaded` except that the\n `{'UP', reference(), driver, Name, unload_cancelled}` message is never sent,\n but the monitor instead persists until the driver _really_ gets unloaded.\n\nThe function throws a `badarg` exception if the parameters are not specified as\ndescribed here.","title":"erl_ddll.monitor/2","ref":"erl_ddll.html#monitor/2"},{"type":"function","doc":"Reloads the driver named `Name` from a possibly different `Path` than previously\nused. This function is used in the code change\n[`scenario`](`m:erl_ddll#scenarios`) described in the introduction.\n\nIf there are other [users](`m:erl_ddll#users`) of this driver, the function\nreturns `{error, pending_process}`, but if there are no other users, the\nfunction call hangs until all open ports are closed.\n\n> #### Note {: .info }\n>\n> Avoid mixing multiple [users](`m:erl_ddll#users`) with driver reload requests.\n\nTo avoid hanging on open ports, use function `try_load/3` instead.\n\nThe `Name` and `Path` parameters have exactly the same meaning as when calling\nthe plain function `load/2`.\n\nOn success, the function returns `ok`. On failure, the function returns an\nopaque error, except the `pending_process` error described earlier. The opaque\nerrors are to be translated into human readable form by function\n`format_error/1`.\n\nFor more control over the error handling, use the `try_load/3` interface\ninstead.\n\nThe function throws a `badarg` exception if the parameters are not specified as\ndescribed here.","title":"erl_ddll.reload/2","ref":"erl_ddll.html#reload/2"},{"type":"function","doc":"Works exactly as `reload/2`, but for drivers loaded with the `load_driver/2`\ninterface.\n\nAs this interface implies that ports are killed when the last user disappears,\nthe function does not hang waiting for ports to get closed.\n\nFor more details, see [`scenarios`](`m:erl_ddll#scenarios`) in this module\ndescription and the function description for `reload/2`.\n\nThe function throws a `badarg` exception if the parameters are not specified as\ndescribed here.","title":"erl_ddll.reload_driver/2","ref":"erl_ddll.html#reload_driver/2"},{"type":"function","doc":"Provides more control than the [`load/2`](`load/2`)/[`reload/2`](`reload/2`) and\n[`load_driver/2`](`load_driver/2`)/[`reload_driver/2`](`reload_driver/2`)\ninterfaces. It never waits for completion of other operations related to the\ndriver, but immediately returns the status of the driver as one of the\nfollowing:\n\n- **`{ok, loaded}`** - The driver was loaded and is immediately usable.\n\n- **`{ok, already_loaded}`** - The driver was already loaded by another process\n or is in use by a living port, or both. The load by you is registered and a\n corresponding `try_unload` is expected sometime in the future.\n\n- **`{ok, pending_driver}`or `{ok, pending_driver, reference()}`** - The load\n request is registered, but the loading is delayed because an earlier instance\n of the driver is still waiting to get unloaded (open ports use it). Still,\n unload is expected when you are done with the driver. This return value\n _mostly_ occurs when options `{reload,pending_driver}` or `{reload,pending}`\n are used, but _can_ occur when another [user](`m:erl_ddll#users`) is unloading\n a driver in parallel and driver option `kill_ports` is set. In other words,\n this return value always needs to be handled.\n\n- **`{ok, pending_process}`or `{ok, pending_process, reference()}`** - The load\n request is registered, but the loading is delayed because an earlier instance\n of the driver is still waiting to get unloaded by another\n [user](`m:erl_ddll#users`) (not only by a port, in which case\n `{ok,pending_driver}` would have been returned). Still, unload is expected\n when you are done with the driver. This return value _only_ occurs when option\n `{reload,pending}` is used.\n\nWhen the function returns `{ok, pending_driver}` or `{ok, pending_process}`, one\ncan get information about when the driver is _actually_ loaded by using option\n`{monitor, MonitorOption}`.\n\nWhen monitoring is requested, and a corresponding `{ok, pending_driver}` or\n`{ok, pending_process}` would be returned, the function instead returns a tuple\n`{ok, PendingStatus, reference()}` and the process then gets a monitor message\nlater, when the driver gets loaded. The monitor message to expect is described\nin the function description of `monitor/2`.\n\n> #### Note {: .info }\n>\n> In case of loading, monitoring can _not_ only get triggered by using option\n> `{reload, ReloadOption}`, but also in special cases where the load error is\n> transient. Thus, `{monitor, pending_driver}` is to be used under basically\n> _all_ real world circumstances.\n\nThe function accepts the following parameters:\n\n- **`Path`** - The file system path to the directory where the driver object\n file is located. The filename of the object file (minus extension) must\n correspond to the driver name (used in parameter `Name`) and the driver must\n identify itself with the same name. `Path` can be provided as an _iolist()_,\n meaning it can be a list of other `t:iolist/0`s, characters (8-bit integers),\n or binaries, all to be flattened into a sequence of characters.\n\n The (possibly flattened) `Path` parameter must be consistent throughout the\n system. A driver is to, by all [users](`m:erl_ddll#users`), be loaded using\n the same _literal_ `Path`. The exception is when _reloading_ is requested, in\n which case `Path` can be specified differently. Notice that all\n [users](`m:erl_ddll#users`) trying to load the driver later need to use the\n _new_ `Path` if `Path` is changed using a `reload` option. This is yet another\n reason to have _only one loader_ of a driver one wants to upgrade in a running\n system.\n\n- **`Name`** - This parameter is the name of the driver to be used in subsequent\n calls to function [`erlang:open_port`](`erlang:open_port/2`) in ERTS. The name\n can be specified as an `t:iolist/0` or an `t:atom/0`. The name specified when\n loading is used to find the object file (with the help of `Path` and the\n system-implied extension suffix, that is, `.so`). The name by which the driver\n identifies itself must also be consistent with this `Name` parameter, much as\n the module name of a Beam file much corresponds to its filename.\n\n- **`OptionList`** - Some options can be specified to control the loading\n operation. The options are specified as a list of two-tuples. The tuples have\n the following values and meanings:\n\n - **`{driver_options, DriverOptionList}`** - This is to provide options that\n changes its general behavior and \"sticks\" to the driver throughout its\n lifespan.\n\n The driver options for a specified driver name need always to be consistent,\n _even when the driver is reloaded_, meaning that they are as much a part of\n the driver as the name.\n\n The only allowed driver option is `kill_ports`, which means that all ports\n opened to the driver are killed with exit reason `driver_unloaded` when no\n process any longer has the driver loaded. This situation arises either when\n the last [user](`m:erl_ddll#users`) calls `try_unload/2`, or when the last\n process having loaded the driver exits.\n\n - **`{monitor, MonitorOption}`** - A `MonitorOption` tells\n [`try_load/3`](`try_load/3`) to trigger a driver monitor under certain\n conditions. When the monitor is triggered, the function returns a\n three-tuple `{ok, PendingStatus, reference()}`, where `t:reference/0` is the\n monitor reference for the driver monitor.\n\n Only one `MonitorOption` can be specified. It is one of the following:\n\n - The atom `pending`, which means that a monitor is to be created whenever a\n load operation is delayed,\n - The atom `pending_driver`, in which a monitor is created whenever the\n operation is delayed because of open ports to an otherwise unused driver.\n\n Option `pending_driver` is of little use, but is present for completeness,\n as it is well defined which reload options that can give rise to which\n delays. However, it can be a good idea to use the same `MonitorOption` as\n the `ReloadOption`, if present.\n\n If reloading is not requested, it can still be useful to specify option\n `monitor`, as forced unloads (driver option `kill_ports` or option\n `kill_ports` to `try_unload/2`) trigger a transient state where driver\n loading cannot be performed until all closing ports are closed. Thus, as\n `try_unload` can, in almost all situations, return `{ok, pending_driver}`,\n always specify at least `{monitor, pending_driver}` in production code (see\n the monitor discussion earlier).\n\n - **`{reload, ReloadOption}`** - This option is used to _reload_ a driver from\n disk, most often in a code upgrade scenario. Having a `reload` option also\n implies that parameter `Path` does _not_ need to be consistent with earlier\n loads of the driver.\n\n To reload a driver, the process must have loaded the driver before, that is,\n there must be an active [user](`m:erl_ddll#users`) of the driver in the\n process.\n\n The `reload` option can be either of the following:\n\n - **`pending`** - With the atom `pending`, reloading is requested for any\n driver and is effectuated when _all_ ports opened to the driver are\n closed. The driver replacement in this case takes place regardless if\n there are still pending [users](`m:erl_ddll#users`) having the driver\n loaded.\n\n The option also triggers port-killing (if driver option `kill_ports` is\n used) although there are pending users, making it usable for forced driver\n replacement, but laying much responsibility on the driver\n [users](`m:erl_ddll#users`). The pending option is seldom used as one does\n not want other [users](`m:erl_ddll#users`) to have loaded the driver when\n code change is underway.\n\n - **`pending_driver`** - This option is more useful. Here, reloading is\n queued if the driver is _not_ loaded by any other\n [users](`m:erl_ddll#users`), but the driver has opened ports, in which\n case `{ok, pending_driver}` is returned (a `monitor` option is\n recommended).\n\n If the driver is unloaded (not present in the system), error code\n `not_loaded` is returned. Option `reload` is intended for when the user has\n already loaded the driver in advance.\n\nThe function can return numerous errors, some can only be returned given a\ncertain combination of options.\n\nSome errors are opaque and can only be interpreted by passing them to function\n`format_error/1`, but some can be interpreted directly:\n\n- **`{error,linked_in_driver}`** - The driver with the specified name is an\n Erlang statically linked-in driver, which cannot be manipulated with this API.\n\n- **`{error,inconsistent}`** - The driver is already loaded with other\n `DriverOptionList` or a different _literal_ `Path` argument.\n\n This can occur even if a `reload` option is specified, if `DriverOptionList`\n differs from the current.\n\n- **`{error, permanent}`** - The driver has requested itself to be permanent,\n making it behave like an Erlang linked-in driver and can no longer be\n manipulated with this API.\n\n- **`{error, pending_process}`** - The driver is loaded by other\n [users](`m:erl_ddll#users`) when option `{reload, pending_driver}` was\n specified.\n\n- **`{error, pending_reload}`** - Driver reload is already requested by another\n [user](`m:erl_ddll#users`) when option `{reload, ReloadOption}` was specified.\n\n- **`{error, not_loaded_by_this_process}`** - Appears when option `reload` is\n specified. The driver `Name` is present in the system, but there is no\n [user](`m:erl_ddll#users`) of it in this process.\n\n- **`{error, not_loaded}`** - Appears when option `reload` is specified. The\n driver `Name` is not in the system. Only drivers loaded by this process can be\n reloaded.\n\nAll other error codes are to be translated by function `format_error/1`. Notice\nthat calls to `format_error` are to be performed from the same running instance\nof the Erlang virtual machine as the error is detected in, because of\nsystem-dependent behavior concerning error values.\n\nIf the arguments or options are malformed, the function throws a `badarg`\nexception.","title":"erl_ddll.try_load/3","ref":"erl_ddll.html#try_load/3"},{"type":"function","doc":"This is the low-level function to unload (or decrement reference counts of) a\ndriver. It can be used to force port killing, in much the same way as the driver\noption `kill_ports` implicitly does. Also, it can trigger a monitor either\nbecause other [users](`m:erl_ddll#users`) still have the driver loaded or\nbecause open ports use the driver.\n\nUnloading can be described as the process of telling the emulator that this\nparticular part of the code in this particular process (that is, this\n[user](`m:erl_ddll#users`)) no longer needs the driver. That can, if there are\nno other users, trigger unloading of the driver, in which case the driver name\ndisappears from the system and (if possible) the memory occupied by the driver\nexecutable code is reclaimed.\n\nIf the driver has option `kill_ports` set, or if `kill_ports` is specified as an\noption to this function, all pending ports using this driver are killed when\nunloading is done by the last [user](`m:erl_ddll#users`). If no port-killing is\ninvolved and there are open ports, the unloading is delayed until no more open\nports use the driver. If, in this case, another [user](`m:erl_ddll#users`) (or\neven this user) loads the driver again before the driver is unloaded, the\nunloading never takes place.\n\nTo allow the [user](`m:erl_ddll#users`) to _request unloading_ to wait for\n_actual unloading_, `monitor` triggers can be specified in much the same way as\nwhen loading. However, as [users](`m:erl_ddll#users`) of this function seldom\nare interested in more than decrementing the reference counts, monitoring is\nseldom needed.\n\n> #### Note {: .info }\n>\n> If option `kill_ports` is used, monitor trigging is crucial, as the ports are\n> not guaranteed to be killed until the driver is unloaded. Thus, a monitor must\n> be triggered for at least the `pending_driver` case.\n\nThe possible monitor messages to expect are the same as when using option\n`unloaded` to function `monitor/2`.\n\nThe function returns one of the following statuses upon success:\n\n- **`{ok, unloaded}`** - The driver was immediately unloaded, meaning that the\n driver name is now free to use by other drivers and, if the underlying OS\n permits it, the memory occupied by the driver object code is now reclaimed.\n\n The driver can only be unloaded when there are no open ports using it and no\n more [users](`m:erl_ddll#users`) require it to be loaded.\n\n- **`{ok, pending_driver}`or `{ok, pending_driver, reference()}`** - Indicates\n that this call removed the last [user](`m:erl_ddll#users`) from the driver,\n but there are still open ports using it. When all ports are closed and no new\n [users](`m:erl_ddll#users`) have arrived, the driver is reloaded and the name\n and memory reclaimed.\n\n This return value is valid even if option `kill_ports` was used, as killing\n ports can be a process that does not complete immediately. However, the\n condition is in that case transient. Monitors are always useful to detect when\n the driver is really unloaded.\n\n- **`{ok, pending_process}`or `{ok, pending_process, reference()}`** - The\n unload request is registered, but other [users](`m:erl_ddll#users`) still hold\n the driver. Notice that the term `pending_process` can refer to the running\n process; there can be more than one [user](`m:erl_ddll#users`) in the same\n process.\n\n This is a normal, healthy, return value if the call was just placed to inform\n the emulator that you have no further use of the driver. It is the most common\n return value in the most common [`scenario`](`m:erl_ddll#scenarios`) described\n in the introduction.\n\nThe function accepts the following parameters:\n\n- **`Name`** - `Name` is the name of the driver to be unloaded. The name can be\n specified as an `t:iolist/0` or as an `t:atom/0`.\n\n- **`OptionList`** - Argument `OptionList` can be used to specify certain\n behavior regarding ports and triggering monitors under certain conditions:\n\n - **`kill_ports`** - Forces killing of all ports opened using this driver,\n with exit reason `driver_unloaded`, if you are the _last_\n [user](`m:erl_ddll#users`) of the driver.\n\n If other [users](`m:erl_ddll#users`) have the driver loaded, this option has\n no effect.\n\n To get the consistent behavior of killing ports when the last\n [user](`m:erl_ddll#users`) unloads, use driver option `kill_ports` when\n loading the driver instead.\n\n - **`{monitor, MonitorOption}`** - Creates a driver monitor if the condition\n specified in `MonitorOption` is true. The valid options are:\n\n - **`pending_driver`** - Creates a driver monitor if the return value is to\n be `{ok, pending_driver}`.\n\n - **`pending`** - Creates a monitor if the return value is\n `{ok, pending_driver}` or `{ok, pending_process}`.\n\n The `pending_driver` `MonitorOption` is by far the most useful. It must be\n used to ensure that the driver really is unloaded and the ports closed\n whenever option `kill_ports` is used, or the driver can have been loaded\n with driver option `kill_ports`.\n\n Using the monitor triggers in the call to `try_unload` ensures that the\n monitor is added before the unloading is executed, meaning that the monitor\n is always properly triggered, which is not the case if\n [`monitor/2`](`monitor/2`) is called separately.\n\nThe function can return the following error conditions, all well specified (no\nopaque values):\n\n- **`{error, linked_in_driver}`** - You were trying to unload an Erlang\n statically linked-in driver, which cannot be manipulated with this interface\n (and cannot be unloaded at all).\n\n- **`{error, not_loaded}`** - The driver `Name` is not present in the system.\n\n- **`{error, not_loaded_by_this_process}`** - The driver `Name` is present in\n the system, but there is no [user](`m:erl_ddll#users`) of it in this process.\n\n As a special case, drivers can be unloaded from processes that have done no\n corresponding call to [`try_load/3`](`try_load/3`) if, and only if, there are\n _no users of the driver at all_, which can occur if the process containing the\n last user dies.\n\n- **`{error, permanent}`** - The driver has made itself permanent, in which case\n it can no longer be manipulated by this interface (much like a statically\n linked-in driver).\n\nThe function throws a `badarg` exception if the parameters are not specified as\ndescribed here.","title":"erl_ddll.try_unload/2","ref":"erl_ddll.html#try_unload/2"},{"type":"function","doc":"Unloads, or at least dereferences the driver named `Name`. If the caller is the\nlast [user](`m:erl_ddll#users`) of the driver, and no more open ports use the\ndriver, the driver gets unloaded. Otherwise, unloading is delayed until all\nports are closed and no [users](`m:erl_ddll#users`) remain.\n\nIf there are other [users](`m:erl_ddll#users`) of the driver, the reference\ncounts of the driver is merely decreased, so that the caller is no longer\nconsidered a [user](`m:erl_ddll#users`) of the driver. For use scenarios, see\nthe [`description`](`m:erl_ddll#scenarios`) in the beginning of this module.\n\nThe `ErrorDesc` returned is an opaque value to be passed further on to function\n`format_error/1`. For more control over the operation, use the `try_unload/2`\ninterface.\n\nThe function throws a `badarg` exception if the parameters are not specified as\ndescribed here.","title":"erl_ddll.unload/1","ref":"erl_ddll.html#unload/1"},{"type":"function","doc":"Unloads, or at least dereferences the driver named `Name`. If the caller is the\nlast [user](`m:erl_ddll#users`) of the driver, all remaining open ports using\nthe driver are killed with reason `driver_unloaded` and the driver eventually\ngets unloaded.\n\nIf there are other [users](`m:erl_ddll#users`) of the driver, the reference\ncounts of the driver is merely decreased, so that the caller is no longer\nconsidered a [user](`m:erl_ddll#users`). For use scenarios, see the\n[`description`](`m:erl_ddll#scenarios`) in the beginning of this module.\n\nThe `ErrorDesc` returned is an opaque value to be passed further on to function\n`format_error/1`. For more control over the operation, use the `try_unload/2`\ninterface.\n\nThe function throws a `badarg` exception if the parameters are not specified as\ndescribed here.","title":"erl_ddll.unload_driver/1","ref":"erl_ddll.html#unload_driver/1"},{"type":"type","doc":"","title":"erl_ddll.driver/0","ref":"erl_ddll.html#t:driver/0"},{"type":"type","doc":"","title":"erl_ddll.path/0","ref":"erl_ddll.html#t:path/0"},{"type":"module","doc":"Default system error handler.\n\nThis module defines what happens when certain types of errors occur.\n\nYou can change the error handler of a process by calling\n[`erlang:process_flag(error_handler, NewErrorHandler)`](`erlang#process_flag_error_handler`).","title":"error_handler","ref":"error_handler.html"},{"type":"module","doc":"The code in `error_handler` is complex. Do not change it without fully\nunderstanding the interaction between the error handler, the `init` process of\nthe code server, and the I/O mechanism of the code.\n\nCode changes that seem small can cause a deadlock, as unforeseen consequences\ncan occur. The use of `input` is dangerous in this type of code.","title":"Notes - error_handler","ref":"error_handler.html#module-notes"},{"type":"function","doc":"Raises an `undef` exception with a stacktrace, indicating that\n`Module:Function/N` is undefined.","title":"error_handler.raise_undef_exception/3","ref":"error_handler.html#raise_undef_exception/3"},{"type":"function","doc":"This function is called by the runtime system if a call is made to\n`Module:Function(Arg1,.., ArgN)` and `Module:Function/N` is undefined. Notice\nthat this function is evaluated inside the process making the original call.\n\nThis function first attempts to autoload `Module`. If that is not possible, an\n`undef` exception is raised.\n\nIf it is possible to load `Module` and function `Function/N` is exported, it is\ncalled.\n\nOtherwise, if function `'$handle_undefined_function'/2` is exported, it is\ncalled as `'$handle_undefined_function'(`Function, Args).\n\n> #### Warning {: .warning }\n>\n> Defining `'$handle_undefined_function'/2` in ordinary application code is\n> highly discouraged. It is very easy to make subtle errors that can take a long\n> time to debug. Furthermore, none of the tools for static code analysis (such\n> as Dialyzer and Xref) supports the use of `'$handle_undefined_function'/2` and\n> no such support will be added. Only use this function after having carefully\n> considered other, less dangerous, solutions. One example of potential\n> legitimate use is creating stubs for other sub-systems during testing and\n> debugging.\n\nOtherwise an `undef` exception is raised.","title":"error_handler.undefined_function/3","ref":"error_handler.html#undefined_function/3"},{"type":"function","doc":"This function is evaluated if a call is made to `Fun(Arg1,.., ArgN)` when the\nmodule defining the fun is not loaded. The function is evaluated inside the\nprocess making the original call.\n\nIf `Module` is interpreted, the interpreter is invoked and the return value of\nthe interpreted `Fun(Arg1,.., ArgN)` call is returned.\n\nOtherwise, it returns, if possible, the value of [`apply(Fun, Args)`](`apply/2`)\nafter an attempt is made to autoload `Module`. If this is not possible, the call\nfails with exit reason `undef`.","title":"error_handler.undefined_lambda/3","ref":"error_handler.html#undefined_lambda/3"},{"type":"module","doc":"Heartbeat monitoring of an Erlang runtime system.\n\nThis modules contains the interface to the `heart` process. `heart` sends\nperiodic heartbeats to an external port program, which is also named `heart`.\nThe purpose of the `heart` port program is to check that the Erlang runtime\nsystem it is supervising is still running. If the port program has not received\nany heartbeats within `HEART_BEAT_TIMEOUT` seconds (defaults to 60 seconds), the\nsystem can be rebooted.\n\nAn Erlang runtime system to be monitored by a heart program is to be started\nwith command-line flag `-heart` (see also [`erl(1)`](`e:erts:erl_cmd.md`)). The\n`heart` process is then started automatically:\n\n```text\n% erl -heart ...\n```\n\nIf the system is to be rebooted because of missing heartbeats, or a terminated\nErlang runtime system, environment variable `HEART_COMMAND` must be set before\nthe system is started. If this variable is not set, a warning text is printed\nbut the system does not reboot.\n\nTo reboot on Windows, `HEART_COMMAND` can be set to `heart -shutdown` (included\nin the Erlang delivery) or to any other suitable program that can activate a\nreboot.\n\nThe environment variable `HEART_BEAT_TIMEOUT` can be used to configure the heart\ntime-outs; it can be set in the operating system shell before Erlang is started\nor be specified at the command line:\n\n```text\n% erl -heart -env HEART_BEAT_TIMEOUT 30 ...\n```\n\nThe value (in seconds) must be in the range `10 < X <= 65535`.\n\nWhen running on OSs lacking support for monotonic time, `heart` is susceptible\nto system clock adjustments of more than `HEART_BEAT_TIMEOUT` seconds. When this\nhappens, `heart` times out and tries to reboot the system. This can occur, for\nexample, if the system clock is adjusted automatically by use of the Network\nTime Protocol (NTP).\n\nIf a crash occurs, an `erl_crash.dump` is _not_ written unless environment\nvariable `ERL_CRASH_DUMP_SECONDS` is set:\n\n```text\n% erl -heart -env ERL_CRASH_DUMP_SECONDS 10 ...\n```\n\nIf a regular core dump is wanted, let `heart` know by setting the kill signal to\nabort using environment variable `HEART_KILL_SIGNAL=SIGABRT`. If unset, or not\nset to `SIGABRT`, the default behavior is a kill signal using `SIGKILL`:\n\n```text\n% erl -heart -env HEART_KILL_SIGNAL SIGABRT ...\n```\n\nIf heart should _not_ kill the Erlang runtime system, this can be indicated\nusing the environment variable `HEART_NO_KILL=TRUE`. This can be useful if the\ncommand executed by heart takes care of this, for example as part of a specific\ncleanup sequence. If unset, or not set to `TRUE`, the default behaviour will be\nto kill as described above.\n\n```text\n% erl -heart -env HEART_NO_KILL 1 ...\n```\n\nFurthermore, `ERL_CRASH_DUMP_SECONDS` has the following behavior on `heart`:\n\n- **`ERL_CRASH_DUMP_SECONDS=0`** - Suppresses the writing of a crash dump file\n entirely, thus rebooting the runtime system immediately. This is the same as\n not setting the environment variable.\n\n- **`ERL_CRASH_DUMP_SECONDS=-1`** - Setting the environment variable to a\n negative value does not reboot the runtime system until the crash dump file is\n completely written.\n\n- **`ERL_CRASH_DUMP_SECONDS=S`** - `heart` waits for `S` seconds to let the\n crash dump file be written. After `S` seconds, `heart` reboots the runtime\n system, whether the crash dump file is written or not.\n\nIn the following descriptions, all functions fail with reason `badarg` if\n`heart` is not started.","title":"heart","ref":"heart.html"},{"type":"function","doc":"Removes the validation callback call before heartbeats.","title":"heart.clear_callback/0","ref":"heart.html#clear_callback/0"},{"type":"function","doc":"Clears the temporary boot command. If the system terminates, the normal\n`HEART_COMMAND` is used to reboot.","title":"heart.clear_cmd/0","ref":"heart.html#clear_cmd/0"},{"type":"function","doc":"Get the validation callback. If the callback is cleared, `none` will be\nreturned.","title":"heart.get_callback/0","ref":"heart.html#get_callback/0"},{"type":"function","doc":"Gets the temporary reboot command. If the command is cleared, the empty string\nis returned.","title":"heart.get_cmd/0","ref":"heart.html#get_cmd/0"},{"type":"function","doc":"Returns `{ok, Options}` where `Options` is a list of current options enabled for\nheart. If the callback is cleared, `none` will be returned.","title":"heart.get_options/0","ref":"heart.html#get_options/0"},{"type":"function","doc":"This validation callback will be executed before any heartbeat is sent to the\nport program. For the validation to succeed it needs to return with the value\n`ok`.\n\nAn exception within the callback will be treated as a validation failure.\n\nThe callback will be removed if the system reboots.","title":"heart.set_callback/2","ref":"heart.html#set_callback/2"},{"type":"function","doc":"Sets a temporary reboot command. This command is used if a `HEART_COMMAND` other\nthan the one specified with the environment variable is to be used to reboot the\nsystem. The new Erlang runtime system uses (if it misbehaves) environment\nvariable `HEART_COMMAND` to reboot.\n\nLimitations: Command string `Cmd` is sent to the `heart` program as an ISO\nLatin-1 or UTF-8 encoded binary, depending on the filename encoding mode of the\nemulator (see `file:native_name_encoding/0`). The size of the encoded binary\nmust be less than 2047 bytes.","title":"heart.set_cmd/1","ref":"heart.html#set_cmd/1"},{"type":"function","doc":"Valid options `set_options` are:\n\n- **`check_schedulers`** - If enabled, a signal will be sent to each scheduler\n to check its responsiveness. The system check occurs before any heartbeat sent\n to the port program. If any scheduler is not responsive enough the heart\n program will not receive its heartbeat and thus eventually terminate the node.\n\nReturns with the value `ok` if the options are valid.","title":"heart.set_options/1","ref":"heart.html#set_options/1"},{"type":"type","doc":"","title":"heart.heart_option/0","ref":"heart.html#t:heart_option/0"},{"type":"module","doc":"Operating system-specific functions.\n\nThe functions in this module are operating system-specific. Careless use of\nthese functions results in programs that will only run on a specific platform.\nOn the other hand, with careful use, these functions can be of help in enabling\na program to run on most platforms.\n\n> #### Note {: .info }\n>\n> The functions in this module will raise a `badarg` exception if their\n> arguments contain invalid characters according to the description in the \"Data\n> Types\" section.","title":"os","ref":"os.html"},{"type":"function","doc":"","title":"os.cmd/1","ref":"os.html#cmd/1"},{"type":"function","doc":"Executes `Command` in a command shell of the target OS, captures the standard\noutput and standard error of the command, and returns this result as a string.\n\nThe command shell can be set using the\n[kernel configuration parameter](kernel_app.md#os_cmd_shell), by default the\nshell is detected upon system startup.\n\n_Examples:_\n\n```erlang\nLsOut = os:cmd(\"ls\"), % on unix platform\nDirOut = os:cmd(\"dir\"), % on Win32 platform\n```\n\nNotice that in some cases, standard output of a command when called from another\nprogram can differ, compared with the standard output of the command when called\ndirectly from an OS command shell.\n\nThe possible options are:\n\n- **`max_size`** - The maximum size of the data returned by the `os:cmd` call.\n This option is a safety feature that should be used when the command executed\n can return a very large, possibly infinite, result.\n\n ```erlang\n > os:cmd(\"cat /dev/zero\", #{ max_size => 20 }).\n [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]\n ```","title":"os.cmd/2","ref":"os.html#cmd/2"},{"type":"function","doc":"Returns a list of all environment variables. Each environment variable is\nexpressed as a tuple `{VarName,Value}`, where `VarName` is the name of the\nvariable and `Value` its value.\n\nIf Unicode filename encoding is in effect (see the\n[`erl` manual page](`e:erts:erl_cmd.md#file_name_encoding`)), the strings can\ncontain characters with codepoints > 255.","title":"os.env/0","ref":"os.html#env/0"},{"type":"function","doc":"Equivalent to [`find_executable(Name, Path)`](`find_executable/2`) where\n`Path` is the current execution path (that is, the environment variable `PATH`\non Unix and Windows).","title":"os.find_executable/1","ref":"os.html#find_executable/1"},{"type":"function","doc":"Look up an executable program, with the specified name and a search path, in the\nsame way as the underlying OS.\n\n`Path` is to conform to the syntax of execution paths on the OS.\nReturns the absolute filename of the executable program `Name`, or `false` if\nthe program is not found.","title":"os.find_executable/2","ref":"os.html#find_executable/2"},{"type":"function","doc":"Returns a list of all environment variables. Each environment variable is\nexpressed as a single string on the format `\"VarName=Value\"`, where `VarName` is\nthe name of the variable and `Value` its value.\n\nIf Unicode filename encoding is in effect (see the\n[`erl` manual page](`e:erts:erl_cmd.md#file_name_encoding`)), the strings can\ncontain characters with codepoints > 255.\n\nConsider using `env/0` for a nicer 2-tuple format.","title":"os.getenv/0","ref":"os.html#getenv/0"},{"type":"function","doc":"Returns the `Value` of the environment variable `VarName`, or `false` if the\nenvironment variable is undefined.\n\nIf Unicode filename encoding is in effect (see the\n[`erl` manual page](`e:erts:erl_cmd.md#file_name_encoding`)), the strings\n`VarName` and `Value` can contain characters with codepoints > 255.","title":"os.getenv/1","ref":"os.html#getenv/1"},{"type":"function","doc":"Returns the `Value` of the environment variable `VarName`, or `DefaultValue` if\nthe environment variable is undefined.\n\nIf Unicode filename encoding is in effect (see the\n[`erl` manual page](`e:erts:erl_cmd.md#file_name_encoding`)), the strings\n`VarName` and `Value` can contain characters with codepoints > 255.","title":"os.getenv/2","ref":"os.html#getenv/2"},{"type":"function","doc":"Returns the process identifier of the current Erlang emulator in the format most\ncommonly used by the OS environment.\n\nReturns `Value` as a string containing the (usually) numerical identifier for a process.\n\n- On Unix, this is typically the return value of the `getpid/0` system call.\n- On Windows, the process id as returned by the `GetCurrentProcessId()` system call\n is used.","title":"os.getpid/0","ref":"os.html#getpid/0"},{"type":"function","doc":"Returns the current performance counter value in `perf_counter`\n[time unit](`t:erlang:time_unit/0`). This is a highly optimized call that\nmight not be traceable.","title":"os.perf_counter/0","ref":"os.html#perf_counter/0"},{"type":"function","doc":"Returns a performance counter that can be used as a very fast and high\nresolution timestamp.\n\nThis counter is read directly from the hardware or operating system with the\nsame guarantees. This means that two consecutive calls to the function are not\nguaranteed to be monotonic, though it most likely will be. The performance\ncounter will be converted to the resolution passed as an argument.\n\n```erlang\n1> T1 = os:perf_counter(1000),receive after 10000 -> ok end,T2 = os:perf_counter(1000).\n176525861\n2> T2 - T1.\n10004\n```","title":"os.perf_counter/1","ref":"os.html#perf_counter/1"},{"type":"function","doc":"Sets a new `Value` for environment variable `VarName`.\n\nIf Unicode filename encoding is in effect (see the\n[`erl` manual page](`e:erts:erl_cmd.md#file_name_encoding`)), the strings\n`VarName` and `Value` can contain characters with codepoints > 255.\n\nOn Unix platforms, the environment is set using UTF-8 encoding if Unicode\nfilename translation is in effect. On Windows, the environment is set using wide\ncharacter interfaces.","title":"os.putenv/2","ref":"os.html#putenv/2"},{"type":"function","doc":"Enables or disables OS signals.\n\nEach signal my be set to one of the following options:\n\n- **`ignore`** - This signal will be ignored.\n\n- **`default`** - This signal will use the default signal handler for the\n operating system.\n\n- **`handle`** - This signal will notify\n [`erl_signal_server`](kernel_app.md#erl_signal_server) when it is received by\n the Erlang runtime system.","title":"os.set_signal/2","ref":"os.html#set_signal/2"},{"type":"function","doc":"Returns the current [OS system time](`e:erts:time_correction.md#os-system-time`)\nin `native` [time unit](`t:erlang:time_unit/0`).\n\n> #### Note {: .info }\n>\n> This time is _not_ a monotonically increasing time.","title":"os.system_time/0","ref":"os.html#system_time/0"},{"type":"function","doc":"Returns the current [OS system time](`e:erts:time_correction.md#os-system-time`)\nconverted into the `Unit` passed as argument.\n\nCalling `os:system_time(Unit)` is equivalent to\n[`erlang:convert_time_unit`](`erlang:convert_time_unit/3`)([`os:system_time()`](`system_time/0`)`, native, Unit)`.\n\n> #### Note {: .info }\n>\n> This time is _not_ a monotonically increasing time.","title":"os.system_time/1","ref":"os.html#system_time/1"},{"type":"function","doc":"Returns the current [OS system time](`e:erts:time_correction.md#os-system-time`)\nin the same format as `erlang:timestamp/0`.\n\nThe tuple can be used together with function `calendar:now_to_universal_time/1`\nor `calendar:now_to_local_time/1` to get calendar time. Using the calendar time,\ntogether with the `MicroSecs` part of the return tuple from this function,\nallows you to log time stamps in high resolution and consistent with the time in\n the rest of the OS.\n\nExample of code formatting a string in format \"DD Mon YYYY HH:MM:SS.mmmmmm\",\nwhere DD is the day of month, Mon is the textual month name, YYYY is the year,\nHH:MM:SS is the time, and mmmmmm is the microseconds in six positions:\n\n```erlang\n-module(print_time).\n-export([format_utc_timestamp/0]).\nformat_utc_timestamp() ->\n TS = {_,_,Micro} = os:timestamp(),\n {{Year,Month,Day},{Hour,Minute,Second}} =\ncalendar:now_to_universal_time(TS),\n Mstr = element(Month,{\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\n \"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"}),\n io_lib:format(\"~2w ~s ~4w ~2w:~2..0w:~2..0w.~6..0w\",\n [Day,Mstr,Year,Hour,Minute,Second,Micro]).\n```\n\nThis module can be used as follows:\n\n```erlang\n1> io:format(\"~s~n\",[print_time:format_utc_timestamp()]).\n29 Apr 2009 9:55:30.051711\n```\n\nOS system time can also be retrieved by `system_time/0` and `system_time/1`.","title":"os.timestamp/0","ref":"os.html#timestamp/0"},{"type":"function","doc":"Returns the `Osfamily` and, in some cases, the `Osname` of the current OS.\n\nOn Unix, `Osname` has the same value as `uname -s` returns, but in lower case.\nFor example, on Solaris 1 and 2, it is `sunos`.\n\nOn Windows, `Osname` is `nt`.\n\n> #### Note {: .info }\n>\n> Think twice before using this function. Use module `m:filename` if you want to\n> inspect or build filenames in a portable way. Avoid matching on atom `Osname`.","title":"os.type/0","ref":"os.html#type/0"},{"type":"function","doc":"Deletes the environment variable `VarName`.\n\nIf Unicode filename encoding is in effect (see the\n[`erl` manual page](`e:erts:erl_cmd.md#file_name_encoding`)), the string\n`VarName` can contain characters with codepoints > 255.","title":"os.unsetenv/1","ref":"os.html#unsetenv/1"},{"type":"function","doc":"Returns the OS version. On most systems, this function returns a tuple, but a\nstring is returned instead if the system has versions that cannot be expressed\nas three numbers.\n\n> #### Note {: .info }\n>\n> Think twice before using this function. If you still need to use it, always\n> `call os:type()` first.","title":"os.version/0","ref":"os.html#version/0"},{"type":"type","doc":"A string containing valid characters on the specific OS for environment variable\nnames using [`file:native_name_encoding()`](`file:native_name_encoding/0`)\nencoding.\n\nNull characters (integer value zero) are not allowed. On Unix, `=`\ncharacters are not allowed. On Windows, a `=` character is only allowed as the\nvery first character in the string.","title":"os.env_var_name/0","ref":"os.html#t:env_var_name/0"},{"type":"type","doc":"Assuming that environment variables has been correctly set, a strings containing\nvalid characters on the specific OS for environment variable names and values\nusing [`file:native_name_encoding()`](`file:native_name_encoding/0`) encoding.\n\nThe first `=` characters appearing in the string separates environment variable\nname (on the left) from environment variable value (on the right).","title":"os.env_var_name_value/0","ref":"os.html#t:env_var_name_value/0"},{"type":"type","doc":"A string containing valid characters on the specific OS for environment variable\nvalues using [`file:native_name_encoding()`](`file:native_name_encoding/0`)\nencoding.\n\nNull characters (integer value zero) are not allowed.","title":"os.env_var_value/0","ref":"os.html#t:env_var_value/0"},{"type":"type","doc":"All characters needs to be valid characters on the specific OS using\n[`file:native_name_encoding()`](`file:native_name_encoding/0`) encoding. Null\ncharacters (integer value zero) are not allowed.","title":"os.os_command/0","ref":"os.html#t:os_command/0"},{"type":"type","doc":"Options for [`os:cmd/2`](`cmd/2`).\n\n- **`max_size`** - The maximum size of the data returned by the `os:cmd/2` call.\n See the [`os:cmd/2`](`cmd/2`) documentation for more details.","title":"os.os_command_opts/0","ref":"os.html#t:os_command_opts/0"},{"type":"module","doc":"Erlang network authentication server.\n\nFor a description of the Magic Cookie system, refer\nto [Distributed Erlang](`e:system:distributed.md`) in the Erlang Reference\nManual.","title":"auth","ref":"auth.html"},{"type":"function","doc":"Use [`erlang:get_cookie()`](`erlang:get_cookie/0`) in ERTS instead.","title":"auth.cookie/0","ref":"auth.html#cookie/0"},{"type":"function","doc":"Use [`erlang:set_cookie(node(), Cookie)` in ERTS](`erlang:set_cookie/2`)\ninstead.","title":"auth.cookie/1","ref":"auth.html#cookie/1"},{"type":"function","doc":"Returns `yes` if communication with `Node` is authorized.\n\nUse [`net_adm:ping(Node)`](`net_adm:ping/1`) instead.\n\nNotice that a connection to `Node` is established in this case. Returns `no` if\n`Node` does not exist or communication is not authorized (it has another cookie\nthan `auth` thinks it has).","title":"auth.is_auth/1","ref":"auth.html#is_auth/1"},{"type":"function","doc":"Equivalent to [`node_cookie(Node, Cookie)`](`node_cookie/2`).","title":"auth.node_cookie/1","ref":"auth.html#node_cookie/1"},{"type":"function","doc":"Sets the magic cookie of `Node` to `Cookie` and verifies the status of the\nauthorization.\n\nEquivalent to calling [`erlang:set_cookie(Node, Cookie)`](`erlang:set_cookie/2`),\nfollowed by [`auth:is_auth(Node)`](`is_auth/1`).","title":"auth.node_cookie/2","ref":"auth.html#node_cookie/2"},{"type":"type","doc":"","title":"auth.cookie/0","ref":"auth.html#t:cookie/0"},{"type":"module","doc":"Boot server for other Erlang machines.\n\nThis server is used to assist diskless Erlang nodes that fetch all Erlang code\nfrom another machine.\n\nThis server is used to fetch all code, including the start script, if an Erlang\nruntime system is started with command-line flag `-loader inet`. All hosts\nspecified with command-line flag `-hosts Host` must have one instance of this\nserver running.\n\nThis server can be started with the Kernel configuration parameter\n`start_boot_server`.\n\nThe `erl_boot_server` can read regular files and files in archives. See `m:code`\nand `m:erl_prim_loader` in ERTS.\n\n> #### Warning {: .warning }\n>\n> The support for loading code from archive files is experimental. It is\n> released before it is ready to obtain early feedback. The file format,\n> semantics, interfaces, and so on, can be changed in a future release.","title":"erl_boot_server","ref":"erl_boot_server.html"},{"type":"module","doc":"[`erts:init`](`m:init`), [`erts:erl_prim_loader`](`m:erl_prim_loader`)","title":"SEE ALSO - erl_boot_server","ref":"erl_boot_server.html#module-see-also"},{"type":"function","doc":"Adds a `Slave` node to the list of allowed slave hosts.","title":"erl_boot_server.add_slave/1","ref":"erl_boot_server.html#add_slave/1"},{"type":"function","doc":"Deletes a `Slave` node from the list of allowed slave hosts.","title":"erl_boot_server.delete_slave/1","ref":"erl_boot_server.html#delete_slave/1"},{"type":"function","doc":"Starts the boot server. `Slaves` is a list of IP addresses for hosts, which are\nallowed to use this server as a boot server.","title":"erl_boot_server.start/1","ref":"erl_boot_server.html#start/1"},{"type":"function","doc":"Starts the boot server and links to the caller. This function is used to start\nthe server if it is included in a supervision tree.","title":"erl_boot_server.start_link/1","ref":"erl_boot_server.html#start_link/1"},{"type":"function","doc":"Returns the current list of allowed slave hosts.","title":"erl_boot_server.which_slaves/0","ref":"erl_boot_server.html#which_slaves/0"},{"type":"module","doc":"Erlang interface towards epmd\n\nThis module communicates with the EPMD daemon, see [epmd](`e:erts:epmd_cmd.md`).\nTo implement your own epmd module please see\n[ERTS User's Guide: How to Implement an Alternative Node Discovery for Erlang Distribution](`e:erts:alt_disco.md`)","title":"erl_epmd","ref":"erl_epmd.html"},{"type":"function","doc":"Called by the distribution module to resolves the `Host` to an IP address of a\nremote node.\n\nAs an optimization this function may also return the port and version of the\nremote node. If port and version are returned `port_please/3` will not be\ncalled.","title":"erl_epmd.address_please/3","ref":"erl_epmd.html#address_please/3"},{"type":"function","doc":"Called by the distribution module to get which port the local node should listen\nto when accepting new distribution requests.","title":"erl_epmd.listen_port_please/2","ref":"erl_epmd.html#listen_port_please/2"},{"type":"function","doc":"Called by [`net_adm:names/0`](`m:net_adm`). `Host` defaults to the localhost.\nReturns the names and associated port numbers of the Erlang nodes that `epmd`\nregistered at the specified host. Returns `{error, address}` if `epmd` is not\noperational.\n\n_Example:_\n\n```erlang\n(arne@dunn)1> erl_epmd:names(localhost).\n{ok,[{\"arne\",40262}]}\n```","title":"erl_epmd.names/1","ref":"erl_epmd.html#names/1"},{"type":"function","doc":"","title":"erl_epmd.port_please/2","ref":"erl_epmd.html#port_please/2"},{"type":"function","doc":"Requests the distribution port for the given node of an EPMD instance. Together\nwith the port it returns a distribution protocol version which has been 5 since\nErlang/OTP R6.","title":"erl_epmd.port_please/3","ref":"erl_epmd.html#port_please/3"},{"type":"function","doc":"","title":"erl_epmd.register_node/2","ref":"erl_epmd.html#register_node/2"},{"type":"function","doc":"Registers the node with `epmd` and tells epmd what port will be used for the\ncurrent node. It returns a creation number. This number is incremented on each\nregister to help differentiate a new node instance connecting to epmd with the\nsame name.\n\nAfter the node has successfully registered with epmd it will automatically\nattempt reconnect to the daemon if the connection is broken.","title":"erl_epmd.register_node/3","ref":"erl_epmd.html#register_node/3"},{"type":"function","doc":"This function is invoked as this module is added as a child of the\n`erl_distribution` supervisor.","title":"erl_epmd.start_link/0","ref":"erl_epmd.html#start_link/0"},{"type":"module","doc":"Enhanced Remote Procedure Call\n\nThis module provide services similar to Remote Procedure Calls. A remote\nprocedure call is a method to call a function on a remote node and collect the\nanswer. It is used for collecting information on a remote node, or for running a\nfunction with some specific side effects on the remote node.\n\nThis is an enhanced subset of the operations provided by the `m:rpc` module.\nEnhanced in the sense that it makes it possible to distinguish between returned\nvalue, raised exceptions, and other errors. `erpc` also has better performance\nand scalability than the original `rpc` implementation. However, current `rpc`\nmodule will utilize `erpc` in order to also provide these properties when\npossible.\n\nIn order for an `erpc` operation to succeed, the remote node also needs to\nsupport `erpc`. Typically only ordinary Erlang nodes as of OTP 23 have `erpc`\nsupport.\n\nNote that it is up to the user to ensure that correct code to execute via `erpc`\nis available on the involved nodes.\n\n> #### Note {: .info }\n>\n> For some important information about distributed signals, see the\n> [Blocking Signaling Over Distribution](`e:system:ref_man_processes.md#blocking-signaling-over-distribution`)\n> section in the _Processes_ chapter of the _Erlang Reference Manual_. Blocking\n> signaling can, for example, cause timeouts in `erpc` to be significantly\n> delayed.","title":"erpc","ref":"erpc.html"},{"type":"function","doc":"","title":"erpc.call/2","ref":"erpc.html#call/2"},{"type":"function","doc":"Equivalent to\n[`erpc:call(Node, erlang, apply, [Fun,[]], #{timeout => Timeout})`](`call/5`).\n\nMay raise all the same exceptions as [`call/5`](`call/5`) plus an `{erpc, badarg}`\n`error` exception if `Fun` is not a fun of zero arity.","title":"erpc.call/3","ref":"erpc.html#call/3"},{"type":"function","doc":"","title":"erpc.call/4","ref":"erpc.html#call/4"},{"type":"function","doc":"Evaluates [`apply(Module, Function, Args)`](`apply/3`) on node `Node` and\nreturns the corresponding value `Result`.\n\n`TimeoutOrOptions` can be either a [`timeout time`](`t:timeout_time/0`) or a\n[`call options`](`t:call_options/0`) map (since OTP 28.0).\n\nThe `call()` function only returns if the applied function successfully returned\nwithout raising any uncaught exceptions, the operation did not time out, and no\nfailures occurred. In all other cases an exception is raised. The following\nexceptions, listed by exception class, can currently be raised by `call()`:\n\n- **`throw`** - The applied function called [`throw(Value)`](`throw/1`) and did\n not catch this exception. The exception reason `Value` equals the argument\n passed to [`throw/1`](`throw/1`).\n\n- **`exit`** - Exception reason:\n\n - **`{exception, ExitReason}`** - The applied function called\n [`exit(ExitReason)`](`exit/1`) and did not catch this exception. The exit\n reason `ExitReason` equals the argument passed to [`exit/1`](`exit/1`).\n\n - **`{signal, ExitReason}`** - The process that applied the function received\n an exit signal and terminated due to this signal. The process terminated\n with exit reason `ExitReason`.\n\n- **`error`** - Exception reason:\n\n - **`{exception, ErrorReason, StackTrace}`** - A runtime error occurred which\n raised an error exception while applying the function, and the applied\n function did not catch the exception. The error reason `ErrorReason`\n indicates the type of error that occurred. `StackTrace` is formatted as when\n caught in a `try/catch` construct. The `StackTrace` is limited to the\n applied function and functions called by it.\n\n - **`{erpc, ERpcErrorReason}`** - The `erpc` operation failed. The following\n `ERpcErrorReason`s are the most common ones:\n\n - **`badarg`** - If any one of these are true:\n\n - `Node` is not an atom.\n - `Module` is not an atom.\n - `Function` is not an atom.\n - `Args` is not a list. Note that the list is not verified to be a proper\n list at the client side.\n - `Timeout` is invalid.\n\n - **`noconnection`** - The connection to `Node` was lost or could not be\n established. The function may or may not be applied.\n\n - **`system_limit`** - The `erpc` operation failed due to some system limit\n being reached. This typically due to failure to create a process on the\n remote node `Node`, but can be other things as well.\n\n - **`timeout`** - The `erpc` operation timed out. The function may or may\n not be applied.\n\n - **`notsup`** - The remote node `Node` does not support this `erpc`\n operation.\n\nIf the `erpc` operation fails, but it is unknown if the function is/will be\napplied (that is, a timeout or a connection loss), the caller will not receive\nany further information about the result if/when the applied function completes.\nIf the applied function explicitly communicates with the calling process, such\ncommunication may, of course, reach the calling process.\n\n> #### Note {: .info }\n>\n> If the `always_spawn` option is `false` (which is the default), you cannot make\n> _any_ assumptions about the process that will perform the `apply()`. It may be\n> the calling process itself, or a freshly spawned process.","title":"erpc.call/5","ref":"erpc.html#call/5"},{"type":"function","doc":"Equivalent to [`erpc:cast(Node,erlang,apply,[Fun,[]])`](`cast/4`).\n\n[`cast/2`](`cast/2`) fails with an `{erpc, badarg}` `error` exception if:\n\n- `Node` is not an atom.\n- `Fun` is not a a fun of zero arity.","title":"erpc.cast/2","ref":"erpc.html#cast/2"},{"type":"function","doc":"Evaluates [`apply(Module, Function, Args)`](`apply/3`) on node `Node`. No\nresponse is delivered to the calling process. `cast()` returns immediately after\nthe cast request has been sent. Any failures beside bad arguments are silently\nignored.\n\n[`cast/4`](`cast/4`) fails with an `{erpc, badarg}` `error` exception if:\n\n- `Node` is not an atom.\n- `Module` is not an atom.\n- `Function` is not an atom.\n- `Args` is not a list. Note that the list is not verified to be a proper list\n at the client side.","title":"erpc.cast/4","ref":"erpc.html#cast/4"},{"type":"function","doc":"Check if a message is a response to a `call` request previously made by the\ncalling process using `send_request/4`.\n\n`RequestId` should be the value returned from the previously made\n[`send_request/4`](`send_request/4`) call, and the\ncorresponding response should not already have been received and handled to\ncompletion by [`check_response/2`](`check_response/2`), `receive_response/2`, or\n`wait_response/2`. `Message` is the message to check.\n\nIf `Message` does not correspond to the response, the atom `no_response` is\nreturned. If `Message` corresponds to the response, the `call` operation is\ncompleted and either the result is returned as `{response, Result}` where\n`Result` corresponds to the value returned from the applied function or an\nexception is raised. The exceptions that can be raised corresponds to the same\nexceptions as can be raised by `call/4`. That is, no `{erpc, timeout}` `error`\nexception can be raised. `check_response()` will fail with an `{erpc, badarg}`\nexception if/when an invalid `RequestId` is detected.\n\nIf the `erpc` operation fails, but it is unknown if the function is/will be\napplied (that is, a connection loss), the caller will not receive any further\ninformation about the result if/when the applied function completes. If the\napplied function explicitly communicates with the calling process, such\ncommunication may, of course, reach the calling process.","title":"erpc.check_response/2","ref":"erpc.html#check_response/2"},{"type":"function","doc":"Check if a message is a response to a `call` request corresponding to a request\nidentifier saved in `RequestIdCollection`. All request identifiers of\n`RequestIdCollection` must correspond to requests that have been made using\n`send_request/4` or `send_request/6`, and all requests must have been made by\nthe process calling this function.\n\n`Label` is the label associated with the request identifier of the request that\nthe response corresponds to. A request identifier is associated with a label\nwhen [adding a request identifier](`reqids_add/3`) in a\n[request identifier collection](`t:request_id_collection/0`), or when sending\nthe request using `send_request/6`.\n\nCompared to `check_response/2`, the returned result associated with a specific\nrequest identifier or an exception associated with a specific request identifier\nwill be wrapped in a 3-tuple. The first element of this tuple equals the value\nthat would have been produced by [`check_response/2`](`check_response/2`), the\nsecond element equals the `Label` associated with the specific request\nidentifier, and the third element `NewRequestIdCollection` is a possibly\nmodified request identifier collection. The `error` exception `{erpc, badarg}`\nis not associated with any specific request identifier, and will hence not be\nwrapped.\n\nIf `RequestIdCollection` is empty, the atom `no_request` will be returned. If\n`Message` does not correspond to any of the request identifiers in\n`RequestIdCollection`, the atom `no_response` is returned.\n\nIf `Delete` equals `true`, the association with `Label` will have been deleted\nfrom `RequestIdCollection` in the resulting `NewRequestIdCollection`. If\n`Delete` equals `false`, `NewRequestIdCollection` will equal\n`RequestIdCollection`. Note that deleting an association is not for free and\nthat a collection containing already handled requests can still be used by\nsubsequent calls to [`check_response/3`](`check_response/3`),\n`receive_response/3`, and `wait_response/3`. However, without deleting handled\nassociations, the above calls will not be able to detect when there are no more\noutstanding requests to handle, so you will have to keep track of this some\nother way than relying on a `no_request` return. Note that if you pass a\ncollection only containing associations of already handled or abandoned requests\nto [`check_response/3`](`check_response/3`), it will always return\n`no_response`.\n\nNote that a response might have been consumed uppon an `{erpc, badarg}`\nexception and if so, will be lost for ever.","title":"erpc.check_response/3","ref":"erpc.html#check_response/3"},{"type":"function","doc":"","title":"erpc.multicall/2","ref":"erpc.html#multicall/2"},{"type":"function","doc":"Equivalent to\n[`erpc:multicall(Nodes, erlang, apply, [Fun,[]], #{timeout => Timeout})`](`multicall/5`).\n\nMay raise all the same exceptions as [`multicall/5`](`multicall/5`) plus an\n`{erpc, badarg}` `error` exception if `Fun` is not a fun of zero arity.","title":"erpc.multicall/3","ref":"erpc.html#multicall/3"},{"type":"function","doc":"","title":"erpc.multicall/4","ref":"erpc.html#multicall/4"},{"type":"function","doc":"Performs multiple `call` operations in parallel on multiple nodes.\n\nThat is, evaluates [`apply(Module, Function, Args)`](`apply/3`) on the nodes `Nodes` in\nparallel.\n\n`TimeoutOrOptions` can be either a [`timeout time`](`t:timeout_time/0`) or a\n[`call options`](`t:call_options/0`) map (since OTP 28.0).\n\nThe result is returned as a list where the result from each node is\nplaced at the same position as the node name is placed in `Nodes`. Each item in\nthe resulting list is formatted as either:\n\n- **`{ok, Result}`** - The `call` operation for this specific node returned\n `Result`.\n\n- **`{Class, ExceptionReason}`** - The `call` operation for this specific node\n raised an exception of class `Class` with exception reason `ExceptionReason`.\n These correspond to the exceptions that `call/5` can raise.\n\n[`multicall/5`](`multicall/5`) fails with an `{erpc, badarg}` `error` exception\nif:\n\n- `Nodes` is not a proper list of atoms. Note that some requests may already\n have been sent when the failure occurs. That is, the function may or may not\n be applied on some nodes.\n- `Module` is not an atom.\n- `Function` is not an atom.\n- `Args` is not a list. Note that the list is not verified to be a proper list\n at the client side.\n\nThe call `erpc:multicall(Nodes, Module, Function, Args)` is equivalent to the\ncall `erpc:multicall(Nodes, Module, Function, Args, infinity)`. These calls are\nalso equivalent to calling `my_multicall(Nodes, Module, Function, Args)` below\nif one disregard performance and failure behavior. `multicall()` can utilize a\nselective receive optimization which removes the need to scan the message queue\nfrom the beginning in order to find a matching message. The\n`send_request()/receive_response()` combination can, however, not utilize this\noptimization.\n\n```erlang\nmy_multicall(Nodes, Module, Function, Args) ->\n ReqIds = lists:map(fun (Node) ->\n erpc:send_request(Node, Module, Function, Args)\n end,\n Nodes),\n lists:map(fun (ReqId) ->\n try\n {ok, erpc:receive_response(ReqId, infinity)}\n catch\n Class:Reason ->\n {Class, Reason}\n end\n end,\n ReqIds).\n```\n\nIf an `erpc` operation fails, but it is unknown if the function is/will be\napplied (that is, a timeout, connection loss, or an improper `Nodes` list), the\ncaller will not receive any further information about the result if/when the\napplied function completes. If the applied function communicates with the\ncalling process, such communication may, of course, reach the calling process.\n\n> #### Note {: .info }\n>\n> If the `always_spawn` option is `false` (which is the default), you cannot make\n> _any_ assumptions about the processes that will perform the `apply()`s. It may be\n> the calling process itself, or freshly spawned processes, or a mix of both.","title":"erpc.multicall/5","ref":"erpc.html#multicall/5"},{"type":"function","doc":"Equivalent to\n[`erpc:multicast(Nodes,erlang,apply,[Fun,[]])`](`multicast/4`).\n\n[`multicast/2`](`multicast/2`) fails with an `{erpc, badarg}` `error` exception\nif:\n\n- `Nodes` is not a proper list of atoms.\n- `Fun` is not a a fun of zero arity.","title":"erpc.multicast/2","ref":"erpc.html#multicast/2"},{"type":"function","doc":"Evaluates [`apply(Module, Function, Args)`](`apply/3`) on the nodes `Nodes`. No\nresponse is delivered to the calling process. `multicast()` returns immediately\nafter the cast requests have been sent. Any failures beside bad arguments are\nsilently ignored.\n\n[`multicast/4`](`multicast/4`) fails with an `{erpc, badarg}` `error` exception\nif:\n\n- `Nodes` is not a proper list of atoms. Note that some requests may already\n have been sent when the failure occurs. That is, the function may or may not\n be applied on some nodes.\n- `Module` is not an atom.\n- `Function` is not an atom.\n- `Args` is not a list. Note that the list is not verified to be a proper list\n at the client side.","title":"erpc.multicast/4","ref":"erpc.html#multicast/4"},{"type":"function","doc":"","title":"erpc.receive_response/1","ref":"erpc.html#receive_response/1"},{"type":"function","doc":"Receive a response to a `call` request previously made by the calling process\nusing `send_request/4`.\n\n`RequestId` should be the value returned from the\npreviously made [`send_request/4`](`send_request/4`) call, and the corresponding\nresponse should not already have been received and handled to completion by\n`receive_response()`, [`check_response/4`](`check_response/2`), or\n[`wait_response/4`](`wait_response/2`).\n\n`Timeout` sets an upper time limit on how long to wait for a response. If the\noperation times out, the request identified by `RequestId` will be abandoned,\nthen an `{erpc, timeout}` `error` exception will be raised. That is, no response\ncorresponding to the request will ever be received after a timeout. If a\nresponse is received, the `call` operation is completed and either the result is\nreturned or an exception is raised. The exceptions that can be raised\ncorresponds to the same exceptions as can be raised by `call/5`.\n[`receive_response/2`](`receive_response/2`) will fail with an `{erpc, badarg}`\nexception if/when an invalid `RequestId` is detected or if an invalid `Timeout`\nis passed.\n\nA call to the function `my_call(Node, Module, Function, Args, Timeout)` below is\nequivalent to the call\n[`erpc:call(Node, Module, Function, Args, Timeout)`](`call/5`) if one disregards\nperformance. `call()` can utilize a selective receive optimization which removes\nthe need to scan the message queue from the beginning in order to find a\nmatching message. The `send_request()/receive_response()` combination can,\nhowever, not utilize this optimization.\n\n```erlang\nmy_call(Node, Module, Function, Args, Timeout) ->\n RequestId = erpc:send_request(Node, Module, Function, Args),\n erpc:receive_response(RequestId, Timeout).\n```\n\nIf the `erpc` operation fails, but it is unknown if the function is/will be\napplied (that is, a timeout, or a connection loss), the caller will not receive\nany further information about the result if/when the applied function completes.\nIf the applied function explicitly communicates with the calling process, such\ncommunication may, of course, reach the calling process.","title":"erpc.receive_response/2","ref":"erpc.html#receive_response/2"},{"type":"function","doc":"Receive a response to a `call` request corresponding to a request identifier\nsaved in `RequestIdCollection`. All request identifiers of `RequestIdCollection`\nmust correspond to requests that have been made using `send_request/4` or\n`send_request/6`, and all requests must have been made by the process calling\nthis function.\n\n`Label` is the label associated with the request identifier of the request that\nthe response corresponds to. A request identifier is associated with a label\nwhen [adding a request identifier](`reqids_add/3`) in a\n[request identifier collection](`t:request_id_collection/0`), or when sending\nthe request using `send_request/6`.\n\nCompared to `receive_response/2`, the returned result associated with a specific\nrequest identifier or an exception associated with a specific request identifier\nwill be wrapped in a 3-tuple. The first element of this tuple equals the value\nthat would have been produced by [`receive_response/2`](`receive_response/2`),\nthe second element equals the `Label` associated with the specific request\nidentifier, and the third element `NewRequestIdCollection` is a possibly\nmodified request identifier collection. The `error` exceptions `{erpc, badarg}`\nand `{erpc, timeout}` are not associated with any specific request identifiers,\nand will hence not be wrapped.\n\nIf `RequestIdCollection` is empty, the atom `no_request` will be returned.\n\nIf the operation times out, all requests identified by `RequestIdCollection`\nwill be abandoned, then an `{erpc, timeout}` `error` exception will be raised.\nThat is, no responses corresponding to any of the request identifiers in\n`RequestIdCollection` will ever be received after a timeout. The difference\nbetween [`receive_response/3`](`receive_response/3`) and `wait_response/3` is\nthat [`receive_response/3`](`receive_response/3`) abandons the requests at\ntimeout so that any potential future responses are ignored, while\n[`wait_response/3`](`wait_response/3`) does not.\n\nIf `Delete` equals `true`, the association with `Label` will have been deleted\nfrom `RequestIdCollection` in the resulting `NewRequestIdCollection`. If\n`Delete` equals `false`, `NewRequestIdCollection` will equal\n`RequestIdCollection`. Note that deleting an association is not for free and\nthat a collection containing already handled requests can still be used by\nsubsequent calls to [`receive_response/3`](`receive_response/3`),\n`check_response/3`, and `wait_response/3`. However, without deleting handled\nassociations, the above calls will not be able to detect when there are no more\noutstanding requests to handle, so you will have to keep track of this some\nother way than relying on a `no_request` return. Note that if you pass a\ncollection only containing associations of already handled or abandoned requests\nto [`receive_response/3`](`receive_response/3`), it will always block until a\ntimeout determined by `Timeout` is triggered.\n\nNote that a response might have been consumed uppon an `{erpc, badarg}`\nexception and if so, will be lost for ever.","title":"erpc.receive_response/3","ref":"erpc.html#receive_response/3"},{"type":"function","doc":"Saves `RequestId` and associates a `Label` with the request identifier by adding\nthis information to `RequestIdCollection` and returning the resulting request\nidentifier collection.","title":"erpc.reqids_add/3","ref":"erpc.html#reqids_add/3"},{"type":"function","doc":"Returns a new empty request identifier collection. A request identifier\ncollection can be utilized in order the handle multiple outstanding requests.\n\nRequest identifiers of requests made by `send_request/4` can be saved in a\nrequest identifier collection using `reqids_add/3`. Such a collection of request\nidentifiers can later be used in order to get one response corresponding to a\nrequest in the collection by passing the collection as argument to\n`check_response/3`, `receive_response/3`, and `wait_response/3`.\n\n`reqids_size/1` can be used to determine the amount of request identifiers in a\nrequest identifier collection.","title":"erpc.reqids_new/0","ref":"erpc.html#reqids_new/0"},{"type":"function","doc":"Returns the amount of request identifiers saved in `RequestIdCollection`.","title":"erpc.reqids_size/1","ref":"erpc.html#reqids_size/1"},{"type":"function","doc":"Returns a list of `{RequestId, Label}` tuples which corresponds to all request\nidentifiers with their associated labels present in the `RequestIdCollection`\ncollection.","title":"erpc.reqids_to_list/1","ref":"erpc.html#reqids_to_list/1"},{"type":"function","doc":"Equivalent to\n[`erpc:send_request(Node, erlang, apply, [Fun, []])`](`send_request/4`).\n\nFails with an `{erpc, badarg}` `error` exception if:\n\n- `Node` is not an atom.\n- `Fun` is not a fun of zero arity.","title":"erpc.send_request/2","ref":"erpc.html#send_request/2"},{"type":"function","doc":"Send an asynchronous `call` request to the node `Node`.\n\n[`send_request/4`](`send_request/4`) returns a request identifier that later is\nto be passed to either `receive_response/2`, `wait_response/2`, or,\n`check_response/2` in order to get the response of the call request. Besides\npassing the request identifier directly to these functions, it can also be added\nin a request identifier collection using `reqids_add/3`. Such a collection of\nrequest identifiers can later be used in order to get one response corresponding\nto a request in the collection by passing the collection as argument to\n`receive_response/3`, `wait_response/3`, or, `check_response/3`. If you are\nabout to save the request identifier in a request identifier collection, you may\nwant to consider using `send_request/6` instead.\n\nA call to the function `my_call(Node, Module, Function, Args, Timeout)` below is\nequivalent to the call\n[`erpc:call(Node, Module, Function, Args, Timeout)`](`call/5`) if one disregards\nperformance. `call()` can utilize a selective receive optimization which removes\nthe need to scan the message queue from the beginning in order to find a\nmatching message. The `send_request()/receive_response()` combination can,\nhowever, not utilize this optimization.\n\n```erlang\nmy_call(Node, Module, Function, Args, Timeout) ->\n RequestId = erpc:send_request(Node, Module, Function, Args),\n erpc:receive_response(RequestId, Timeout).\n```\n\nFails with an `{erpc, badarg}` `error` exception if:\n\n- `Node` is not an atom.\n- `Module` is not an atom.\n- `Function` is not an atom.\n- `Args` is not a list. Note that the list is not verified to be a proper list\n at the client side.\n\nEquivalent to\n[`erpc:send_request(Node, erlang, apply, [Fun,[]]), Label, RequestIdCollection)`](`send_request/6`).\n\nFails with an `{erpc, badarg}` `error` exception if:\n\n- `Node` is not an atom.\n- `Fun` is not a fun of zero arity.\n- `RequestIdCollection` is detected not to be request identifier collection.","title":"erpc.send_request/4","ref":"erpc.html#send_request/4"},{"type":"function","doc":"Send an asynchronous `call` request to the node `Node`. The `Label` will be\nassociated with the request identifier of the operation and added to the\nreturned request identifier collection `NewRequestIdCollection`. The collection\ncan later be used in order to get one response corresponding to a request in the\ncollection by passing the collection as argument to `receive_response/3`,\n`wait_response/3`, or, `check_response/3`.\n\nEquivalent to\n[`erpc:reqids_add`](`reqids_add/3`)([`erpc:send_request`](`send_request/4`)`(Node, Module, Function, Args), Label, RequestIdCollection)`,\nbut calling [`send_request/6`](`send_request/6`) is slightly more efficient.\n\nFails with an `{erpc, badarg}` `error` exception if:\n\n- `Node` is not an atom.\n- `Module` is not an atom.\n- `Function` is not an atom.\n- `Args` is not a list. Note that the list is not verified to be a proper list\n at the client side.\n- `RequestIdCollection` is detected not to be request identifier collection.","title":"erpc.send_request/6","ref":"erpc.html#send_request/6"},{"type":"function","doc":"Equivalent to [`erpc:wait_response(RequestId, 0)`](`wait_response/2`).\nThat is, poll for a response message to a `call` request previously made by the\ncalling process.","title":"erpc.wait_response/1","ref":"erpc.html#wait_response/1"},{"type":"function","doc":"Wait or poll for a response message to a `call` request previously made by the\ncalling process using `send_request/4`.\n\n`RequestId` should be the value returned from the previously made `send_request()`\ncall, and the corresponding response should not already have been received and\nhandled to completion by `check_response/2`, `receive_response/2`, or `wait_response()`.\n\n`WaitTime` sets an upper time limit on how long to wait for a response. If no\nresponse is received before the `WaitTime` timeout has triggered, the atom\n`no_response` is returned. It is valid to continue waiting for a response as\nmany times as needed up until a response has been received and completed by\n`check_response()`, `receive_response()`, or `wait_response()`. If a response is\nreceived, the `call` operation is completed and either the result is returned as\n`{response, Result}` where `Result` corresponds to the value returned from the\napplied function or an exception is raised. The exceptions that can be raised\ncorresponds to the same exceptions as can be raised by `call/4`. That is, no\n`{erpc, timeout}` `error` exception can be raised.\n[`wait_response/2`](`wait_response/2`) will fail with an `{erpc, badarg}`\nexception if/when an invalid `RequestId` is detected or if an invalid `WaitTime`\nis passed.\n\nIf the `erpc` operation fails, but it is unknown if the function is/will be\napplied (that is, a too large wait time value, or a connection loss), the caller\nwill not receive any further information about the result if/when the applied\nfunction completes. If the applied function explicitly communicates with the\ncalling process, such communication may, of course, reach the calling process.","title":"erpc.wait_response/2","ref":"erpc.html#wait_response/2"},{"type":"function","doc":"Wait or poll for a response to a `call` request corresponding to a request\nidentifier saved in `RequestIdCollection`. All request identifiers of\n`RequestIdCollection` must correspond to requests that have been made using\n`send_request/4` or `send_request/6`, and all requests must have been made by\nthe process calling this function.\n\n`Label` is the label associated with the request identifier of the request that\nthe response corresponds to. A request identifier is associated with a label\nwhen [adding a request identifier](`reqids_add/3`) in a\n[request identifier collection](`t:request_id_collection/0`), or when sending\nthe request using `send_request/6`.\n\nCompared to `wait_response/2`, the returned result associated with a specific\nrequest identifier or an exception associated with a specific request identifier\nwill be wrapped in a 3-tuple. The first element of this tuple equals the value\nthat would have been produced by [`wait_response/2`](`wait_response/2`), the\nsecond element equals the `Label` associated with the specific request\nidentifier, and the third element `NewRequestIdCollection` is a possibly\nmodified request identifier collection. The `error` exception `{erpc, badarg}`\nis not associated with any specific request identifier, and will hence not be\nwrapped.\n\nIf `RequestIdCollection` is empty, `no_request` will be returned. If no response\nis received before the `WaitTime` timeout has triggered, the atom `no_response`\nis returned. It is valid to continue waiting for a response as many times as\nneeded up until a response has been received and completed by\n`check_response()`, `receive_response()`, or `wait_response()`. The difference\nbetween `receive_response/3` and [`wait_response/3`](`wait_response/3`) is that\n[`receive_response/3`](`receive_response/3`) abandons requests at timeout so\nthat any potential future responses are ignored, while\n[`wait_response/3`](`wait_response/3`) does not.\n\nIf `Delete` equals `true`, the association with `Label` will have been deleted\nfrom `RequestIdCollection` in the resulting `NewRequestIdCollection`. If\n`Delete` equals `false`, `NewRequestIdCollection` will equal\n`RequestIdCollection`. Note that deleting an association is not for free and\nthat a collection containing already handled requests can still be used by\nsubsequent calls to [`wait_response/3`](`wait_response/3`), `check_response/3`,\nand `receive_response/3`. However, without deleting handled associations, the\nabove calls will not be able to detect when there are no more outstanding\nrequests to handle, so you will have to keep track of this some other way than\nrelying on a `no_request` return. Note that if you pass a collection only\ncontaining associations of already handled or abandoned requests to\n[`wait_response/3`](`wait_response/3`), it will always block until a timeout\ndetermined by `WaitTime` is triggered and then return `no_response`.\n\nNote that a response might have been consumed uppon an `{erpc, badarg}`\nexception and if so, will be lost for ever.","title":"erpc.wait_response/3","ref":"erpc.html#wait_response/3"},{"type":"type","doc":"Options to be used in [`call/3,5`](`call/5`) and\n[`multicall/3,5`](`multicall/5`) functions.\n\n- **`timeout`** - Upper time limit for call operations to complete, see\n `t:timeout_time/0`. Default: `infinity`.\n\n- **`always_spawn`** - If `true`, the `apply()` will _always_ be performed\n in a freshly spawned process. If `false`, the calling process _may_ be\n used instead, if possible. Default: `false`.","title":"erpc.call_options/0","ref":"erpc.html#t:call_options/0"},{"type":"type","doc":"","title":"erpc.caught_call_exception/0","ref":"erpc.html#t:caught_call_exception/0"},{"type":"opaque","doc":"An opaque request identifier. For more information see `send_request/4`.","title":"erpc.request_id/0","ref":"erpc.html#t:request_id/0"},{"type":"opaque","doc":"An opaque collection of request identifiers (`t:request_id/0`) where each\nrequest identifier can be associated with a label chosen by the user. For more\ninformation see `reqids_new/0`.","title":"erpc.request_id_collection/0","ref":"erpc.html#t:request_id_collection/0"},{"type":"type","doc":"","title":"erpc.stack_item/0","ref":"erpc.html#t:stack_item/0"},{"type":"type","doc":"The timeout time used by erpc functions.\n\nThe value can be:\n\n- **`0..4294967295`** - Timeout relative to current time in milliseconds.\n\n- **`infinity`** - Infinite timeout. That is, the operation will never time out.\n\n- **`{abs, Timeout}`** - An absolute\n [Erlang monotonic time](`erlang:monotonic_time/1`) timeout in milliseconds.\n That is, the operation will time out when\n [`erlang:monotonic_time(millisecond)`](`erlang:monotonic_time/1`) returns a\n value larger than or equal to `Timeout`. `Timeout` is not allowed to identify\n a time further into the future than `4294967295` milliseconds. Identifying the\n timeout using an absolute timeout value is especially handy when you have a\n deadline for responses corresponding to a complete collection of requests\n (`t:request_id_collection/0`), since you do not have to recalculate the\n relative time until the deadline over and over again.","title":"erpc.timeout_time/0","ref":"erpc.html#t:timeout_time/0"},{"type":"module","doc":"A global name registration facility.\n\nThis module consists of the following services:\n\n- Registration of global names\n- Global locks\n- Maintenance of the fully connected network\n\n[](){: #prevent_overlapping_partitions }\n\nAs of OTP 25, `global` will by default prevent overlapping partitions due to\nnetwork issues by actively disconnecting from nodes that reports that they have\nlost connections to other nodes. This will cause fully connected partitions to\nform instead of leaving the network in a state with overlapping partitions.\n\n> #### Warning {: .warning }\n>\n> Prevention of overlapping partitions can be disabled using the\n> [`prevent_overlapping_partitions`](kernel_app.md#prevent_overlapping_partitions)\n> Kernel parameter, making `global` behave like it used to do. This is,\n> however, problematic for all applications expecting a fully connected network\n> to be provided, such as for example `mnesia`, but also for `global` itself. A\n> network of overlapping partitions might cause the internal state of `global`\n> to become inconsistent. Such an inconsistency can remain even after such\n> partitions have been brought together to form a fully connected network again.\n> The effect on other applications that expects that a fully connected network\n> is maintained may vary, but they might misbehave in very subtle hard to detect\n> ways during such a partitioning. Since you might get hard to detect issues\n> without this fix, you are _strongly_ advised _not_ to disable this fix. Also\n> note that this fix _has_ to be enabled on _all_ nodes in the network in order\n> to work properly.\n\n> #### Note {: .info }\n>\n> None of the above services will be reliably delivered unless both of the\n> kernel parameters [`connect_all`](kernel_app.md#connect_all) and\n> [`prevent_overlapping_partitions`](kernel_app.md#prevent_overlapping_partitions)\n> are enabled. Calls to the `global` API will, however, _not_ fail even though\n> one or both of them are disabled. You will just get unreliable results.\n\nThese services are controlled through the process `global_name_server` that\nexists on every node. The global name server starts automatically when a node is\nstarted. With the term _global_ is meant over a system consisting of many Erlang\nnodes.\n\nThe ability to globally register names is a central concept in the programming\nof distributed Erlang systems. In this module, the equivalent of the\n[`register/2`](`register/2`) and [`whereis/1`](`whereis/1`) BIFs (for local name\nregistration) are provided, but for a network of Erlang nodes. A registered name\nis an alias for a process identifier (pid). The global name server monitors\nglobally registered pids. If a process terminates, the name is also globally\nunregistered.\n\nThe registered names are stored in replica global name tables on every node.\nThere is no central storage point. Thus, the translation of a name to a pid is\nfast, as it is always done locally. For any action resulting in a change to the\nglobal name table, all tables on other nodes are automatically updated.\n\nGlobal locks have lock identities and are set on a specific resource. For\nexample, the specified resource can be a pid. When a global lock is set, access\nto the locked resource is denied for all resources other than the lock\nrequester.\n\nBoth the registration and lock services are atomic. All nodes involved in these\nactions have the same view of the information.\n\nThe global name server also performs the critical task of continuously\nmonitoring changes in node configuration. If a node that runs a globally\nregistered process goes down, the name is globally unregistered. To this end,\nthe global name server subscribes to `nodeup` and `nodedown` messages sent from\nmodule `net_kernel`. Relevant Kernel application variables in this context are\n[`net_setuptime`](kernel_app.md#net_setuptime), [`net_ticktime`](kernel_app.md#net_ticktime),\nand [`dist_auto_connect`](kernel_app.md#dist_auto_connect).\n\nThe name server also maintains a fully connected network. For example, if node\n`N1` connects to node `N2` (which is already connected to `N3`), the global name\nservers on the nodes `N1` and `N3` ensure that also `N1` and `N3` are connected.\nIn this case, the name registration service cannot be used, but the lock\nmechanism still works.\n\nIf the global name server fails to connect nodes (`N1` and `N3` in the example),\na warning event is sent to the error logger. The presence of such an event does\nnot exclude the nodes to connect later (you can, for example, try command\n`rpc:call(N1, net_adm, ping, [N2])` in the Erlang shell), but it indicates a\nnetwork problem.\n\n> #### Note {: .info }\n>\n> If the fully connected network is not set up properly, try first to increase\n> the value of `net_setuptime`.","title":"global","ref":"global.html"},{"type":"module","doc":"`m:global_group`, `m:net_kernel`","title":"See Also - global","ref":"global.html#module-see-also"},{"type":"function","doc":"","title":"global.del_lock/1","ref":"global.html#del_lock/1"},{"type":"function","doc":"Deletes the lock `Id` synchronously.","title":"global.del_lock/2","ref":"global.html#del_lock/2"},{"type":"function","doc":"Disconnect from all other nodes known to `global`.\n\nA list of node names (in an unspecified order) is returned which corresponds to\nthe nodes that were disconnected. All disconnect operations performed have completed when\n`global:disconnect/0` returns.\n\nThe disconnects will be made in such a way that only the current node will be\nremoved from the cluster of `global` nodes. If\n[`prevent_overlapping_partitions`] is\nenabled and you disconnect, from other nodes in the cluster of `global` nodes,\nby other means, `global` on the other nodes may partition the remaining nodes in\norder to ensure that no overlapping partitions appear. Even if\n[`prevent_overlapping_partitions`] is disabled, you should preferably use\n`global:disconnect/0` in order to remove current node from a cluster of `global`\nnodes, since you otherwise likely _will_ create overlapping partitions which\nmight [cause problems](`m:global#prevent_overlapping_partitions`).\n\nNote that if the node is going to be halted, there is _no_ need to remove it\nfrom a cluster of `global` nodes explicitly by calling `global:disconnect/0`\nbefore halting it. The removal from the cluster is taken care of automatically\nwhen the node halts regardless of whether [`prevent_overlapping_partitions`] is\nenabled or not.\n\nIf current node has been configured to be part of a\n[_global group_](`m:global_group`), only connected and/or synchronized nodes in\nthat group are known to `global`, so `global:disconnect/0` will _only_\ndisconnect from those nodes. If current node is _not_ part of a _global group_,\nall [connected visible nodes](`erlang:nodes/0`) will be known to `global`, so\n`global:disconnect/0` will disconnect from all those nodes.\n\nNote that information about connected nodes does not instantaneously reach\n`global`, so the caller might see a node part of the result returned by\n[`nodes()`](`erlang:nodes/0`) while it still is not known to `global`. The\ndisconnect operation will, however, still not cause any overlapping partitions\nwhen [`prevent_overlapping_partitions`] is enabled. If\n[`prevent_overlapping_partitions`] is disabled, overlapping partitions might form\nin this case.\n\nNote that when [`prevent_overlapping_partitions`] is enabled, you may see warning\nreports on other nodes when they detect that current node has disconnected.\nThese are in this case completely harmless and can be ignored.\n\n[`prevent_overlapping_partitions`]: kernel_app.md#prevent_overlapping_partitions","title":"global.disconnect/0","ref":"global.html#disconnect/0"},{"type":"function","doc":"The function unregisters both pids and sends the message\n`{global_name_conflict, Name, OtherPid}` to both processes.\n\nCan be used as a name resolving function for `register_name/3` and\n`re_register_name/3`.","title":"global.notify_all_name/3","ref":"global.html#notify_all_name/3"},{"type":"function","doc":"The function randomly selects one of the pids for registration and kills the\nother one.\n\nCan be used as a name resolving function for `register_name/3` and\n`re_register_name/3`.","title":"global.random_exit_name/3","ref":"global.html#random_exit_name/3"},{"type":"function","doc":"The function randomly selects one of the pids for registration, and sends the\nmessage `{global_name_conflict, Name}` to the other pid.\n\nCan be used as a name resolving function for `register_name/3` and\n`re_register_name/3`.","title":"global.random_notify_name/3","ref":"global.html#random_notify_name/3"},{"type":"function","doc":"","title":"global.re_register_name/2","ref":"global.html#re_register_name/2"},{"type":"function","doc":"Atomically changes the registered name `Name` on all nodes to refer to `Pid`.\n\nFunction `Resolve` has the same behavior as in\n[`register_name/2,3`](`register_name/2`).","title":"global.re_register_name/3","ref":"global.html#re_register_name/3"},{"type":"function","doc":"","title":"global.register_name/2","ref":"global.html#register_name/2"},{"type":"function","doc":"Globally associates name `Name` with a pid, that is, globally notifies all nodes\nof a new global name in a network of Erlang nodes.\n\nWhen new nodes are added to the network, they are informed of the globally\nregistered names that already exist. The network is also informed of any global\nnames in newly connected nodes. If any name clashes are discovered, function\n`Resolve` is called. Its purpose is to decide which pid is correct. If the\nfunction crashes, or returns anything other than one of the pids, the name is\nunregistered. This function is called once for each name clash.\n\n> #### Warning {: .warning }\n>\n> If you plan to change code without restarting your system, you must use an\n> external fun (`fun Module:Function/Arity`) as function `Resolve`. If you use a\n> local fun, you can never replace the code for the module that the fun belongs\n> to.\n\nThree predefined resolve functions exist:\n[`random_exit_name/3`](`random_exit_name/3`),\n[`random_notify_name/3`](`random_notify_name/3`), and\n[`notify_all_name/3`](`notify_all_name/3`).\n\nThis function is completely synchronous, that is, when this function returns,\nthe name is either registered on all nodes or none.\n\nThe function returns `yes` if successful, `no` if it fails. For example, `no` is\nreturned if an attempt is made to register an already registered process or to\nregister a process with a name that is already in use.\n\n> #### Note {: .info }\n>\n> Releases up to and including Erlang/OTP R10 did not check if the process was\n> already registered. The global name table could therefore become inconsistent.\n> The old (buggy) behavior can be chosen by giving the Kernel application\n> variable `global_multi_name_action` the value `allow`.\n\nIf a process with a registered name dies, or the node goes down, the name is\nunregistered on all nodes.","title":"global.register_name/3","ref":"global.html#register_name/3"},{"type":"function","doc":"Returns a list of all globally registered names.","title":"global.registered_names/0","ref":"global.html#registered_names/0"},{"type":"function","doc":"Sends message `Msg` to the pid globally registered as `Name`.\n\nIf `Name` is not a globally registered name, the calling function exits with\nreason `{badarg, {Name, Msg}}`.","title":"global.send/2","ref":"global.html#send/2"},{"type":"function","doc":"","title":"global.set_lock/1","ref":"global.html#set_lock/1"},{"type":"function","doc":"","title":"global.set_lock/2","ref":"global.html#set_lock/2"},{"type":"function","doc":"Sets a lock on the specified nodes on using `t:id/0`.\n\nIf a lock already exists on `ResourceId` for another requester than `LockRequesterId`,\nand `Retries` is not equal to `0`, the process sleeps for a while and tries to\nexecute the action later. When `Retries` attempts have been made, `false` is\nreturned, otherwise `true`. If `Retries` is `infinity`, `true` is eventually\nreturned (unless the lock is never released).\n\nThis function is completely synchronous.\n\nIf a process that holds a lock dies, or the node goes down, the locks held by\nthe process are deleted.\n\nThe global name server keeps track of all processes sharing the same lock, that\nis, if two processes set the same lock, both processes must delete the lock.\n\nThis function does not address the problem of a deadlock. A deadlock can never\noccur as long as processes only lock one resource at a time. A deadlock can\noccur if some processes try to lock two or more resources. It is up to the\napplication to detect and rectify a deadlock.\n\n> #### Note {: .info }\n>\n> Avoid the following values of `ResourceId`, otherwise Erlang/OTP does not work\n> properly:\n>\n> - `dist_ac`\n> - `global`\n> - `mnesia_adjust_log_writes`\n> - `mnesia_table_lock`","title":"global.set_lock/3","ref":"global.html#set_lock/3"},{"type":"function","doc":"Synchronizes the global name server with all nodes known to this node.\n\nThese are the nodes that are returned from [`nodes()`](`erlang:nodes/0`). When\nthis function returns, the global name server receives global information from\nall nodes. This function can be called when new nodes are added to the network.\n\nThe only possible error reason `Reason` is\n`{\"global_groups definition error\", Error}`.","title":"global.sync/0","ref":"global.html#sync/0"},{"type":"function","doc":"","title":"global.trans/2","ref":"global.html#trans/2"},{"type":"function","doc":"","title":"global.trans/3","ref":"global.html#trans/3"},{"type":"function","doc":"Sets a lock on `Id` (using `set_lock/3`).\n\nIf this succeeds, `Fun()` is evaluated and the result `Res` is returned.\nReturns `aborted` if the lock attempt fails. If `Retries` is set to `infinity`,\nthe transaction does not abort.\n\n`infinity` is the default setting and is used if no value is specified for\n`Retries`.","title":"global.trans/4","ref":"global.html#trans/4"},{"type":"function","doc":"Removes the globally registered name `Name` from the network of Erlang nodes.","title":"global.unregister_name/1","ref":"global.html#unregister_name/1"},{"type":"function","doc":"Returns the pid with the globally registered name `Name`. Returns `undefined` if\nthe name is not globally registered.","title":"global.whereis_name/1","ref":"global.html#whereis_name/1"},{"type":"type","doc":"A lock id used to set or delete lock `ResourceId` on behalf of `LockRequesterId`.","title":"global.id/0","ref":"global.html#t:id/0"},{"type":"type","doc":"","title":"global.method/0","ref":"global.html#t:method/0"},{"type":"type","doc":"","title":"global.retries/0","ref":"global.html#t:retries/0"},{"type":"type","doc":"","title":"global.trans_fun/0","ref":"global.html#t:trans_fun/0"},{"type":"module","doc":"Grouping nodes to global name registration groups.\n\nThis module makes it possible to partition the nodes of a system into _global\ngroups_. Each global group has its own global namespace, see `m:global`.\n\nThe main advantage of dividing systems into global groups is that the background\nload decreases while the number of nodes to be updated is reduced when\nmanipulating globally registered names.\n\nThe Kernel configuration parameter [`global_groups`](kernel_app.md#global_groups)\ndefines the global groups:\n\n```erlang\n{global_groups, [GroupTuple :: group_tuple()]}\n```\n\nFor the processes and nodes to run smoothly using the global group\nfunctionality, the following criteria must be met:\n\n- An instance of the global group server, `global_group`, must be running on\n each node. The processes are automatically started and synchronized when a\n node is started.\n- All involved nodes must agree on the global group definition, otherwise the\n behavior of the system is undefined.\n- _All_ nodes in the system must belong to exactly one global group.\n\nIn the following descriptions, a _group node_ is a node belonging to the same\nglobal group as the local node.","title":"global_group","ref":"global_group.html"},{"type":"module","doc":"- In the situation where a node has lost its connections to other nodes in its\n global group, but has connections to nodes in other global groups, a request\n from another global group can produce an incorrect or misleading result. For\n example, the isolated node can have inaccurate information about registered\n names in its global group.\n- Function [`send/2,3`](`send/2`) is not secure.\n- Distribution of applications is highly dependent of the global group\n definitions. It is not recommended that an application is distributed over\n many global groups, as the registered names can be moved to another global\n group at failover/takeover. Nothing prevents this to be done, but the\n application code must then handle the situation.","title":"Notes - global_group","ref":"global_group.html#module-notes"},{"type":"module","doc":"`m:global`, [`erl`](`e:erts:erl_cmd.md`)","title":"See Also - global_group","ref":"global_group.html#module-see-also"},{"type":"function","doc":"Returns a tuple containing the name of the global group that the local node\nbelongs to, and the list of all other known group names.\n\nReturns `undefined` if no global groups are defined.","title":"global_group.global_groups/0","ref":"global_group.html#global_groups/0"},{"type":"function","doc":"Returns a list containing information about the global groups. Each list element\nis a tuple. The order of the tuples is undefined.\n\n- **`{state, State}`** - If the local node is part of a global group, `State` is\n equal to `synced`. If no global groups are defined, `State` is equal to\n `no_conf`.\n\n- **`{own_group_name, GroupName}`** - The name (atom) of the group that the\n local node belongs to.\n\n- **`{own_group_nodes, Nodes}`** - A list of node names (atoms), the group\n nodes.\n\n- **`{synced_nodes, Nodes}`** - A list of node names, the group nodes currently\n synchronized with the local node.\n\n- **`{sync_error, Nodes}`** - A list of node names, the group nodes with which\n the local node has failed to synchronize.\n\n- **`{no_contact, Nodes}`** - A list of node names, the group nodes to which\n there are currently no connections.\n\n- **`{other_groups, Groups}`** - `Groups` is a list of tuples\n `{GroupName, Nodes}`, specifying the name and nodes of the other global\n groups.\n\n- **`{monitoring, Pids}`** - A list of pids, specifying the processes that have\n subscribed to `nodeup` and `nodedown` messages.","title":"global_group.info/0","ref":"global_group.html#info/0"},{"type":"function","doc":"Alter the calling process' subscription of node status change messages.\n\nIf `Flag` is equal to `true` the calling process starts subscribing to\nnode status change messages. If equal to `false` it stops subscribing.\n\nA process that has subscribed receives the messages `{nodeup, Node}` and\n`{nodedown, Node}` when a group node connects or disconnects, respectively.","title":"global_group.monitor_nodes/1","ref":"global_group.html#monitor_nodes/1"},{"type":"function","doc":"Returns the names of all group nodes, regardless of their current status.","title":"global_group.own_nodes/0","ref":"global_group.html#own_nodes/0"},{"type":"function","doc":"Returns a list of all names that are globally registered on the specified node\nor in the specified global group.","title":"global_group.registered_names/1","ref":"global_group.html#registered_names/1"},{"type":"function","doc":"Sends `Msg` to the pid represented by the globally registered name `Name`.\n\n`send/2` searches for `Name` any any global group. The global groups are searched\nin the order that they appear in the value of configuration parameter\n[`global_groups`](kernel_app.md#global_groups).\n\nIf `Name` is found, message `Msg` is sent to the corresponding pid. The pid is\nalso the return value of the function. If the name is not found, the function\nreturns `{badarg, {Name, Msg}}`.","title":"global_group.send/2","ref":"global_group.html#send/2"},{"type":"function","doc":"Equivalent to [`send(Name, Msg)`](`send/2`) except that he search is limited\nto the node or global group specified by `Where`.","title":"global_group.send/3","ref":"global_group.html#send/3"},{"type":"function","doc":"Synchronizes the group nodes, that is, the global name servers on the group\nnodes. Also checks the names globally registered in the current global group and\nunregisters them on any known node not part of the group.\n\nIf synchronization is not possible, an error report is sent to the error logger\n(see also `m:error_logger`.\n\nReturns `{error, {'invalid global_groups definition', Bad}}` if configuration\nparameter `global_groups` has an invalid value `Bad`.","title":"global_group.sync/0","ref":"global_group.html#sync/0"},{"type":"function","doc":"Searched for `Name` in any global group.\n\nThe global groups are searched in the order that they appear in the value\nof configuration parameter `global_groups`.\n\nIf `Name` is found, the corresponding pid is returned. If the name is not found,\nthe function returns `undefined`.","title":"global_group.whereis_name/1","ref":"global_group.html#whereis_name/1"},{"type":"function","doc":"Equivalent to [`whereis_name(Name)`](`whereis_name/1`) except that he search is limited\nto the node or global group specified by `Where`.","title":"global_group.whereis_name/2","ref":"global_group.html#whereis_name/2"},{"type":"type","doc":"","title":"global_group.group_name/0","ref":"global_group.html#t:group_name/0"},{"type":"type","doc":"A `GroupTuple` without `PublishType` is the same as a `GroupTuple` with\n`PublishType` equal to `normal`.","title":"global_group.group_tuple/0","ref":"global_group.html#t:group_tuple/0"},{"type":"type","doc":"","title":"global_group.info_item/0","ref":"global_group.html#t:info_item/0"},{"type":"type","doc":"A registered name.","title":"global_group.name/0","ref":"global_group.html#t:name/0"},{"type":"type","doc":"A node started with command-line flag `-hidden` (see\n[`erl`](`e:erts:erl_cmd.md`)) is said to be a _hidden_ node. A hidden node\nestablishes hidden connections to nodes not part of the same global group, but\nnormal (visible) connections to nodes part of the same global group.\n\nA global group defined with `PublishType` equal to `hidden` is said to be a\nhidden global group. All nodes in a hidden global group are hidden nodes,\nwhether they are started with command-line flag `-hidden` or not.","title":"global_group.publish_type/0","ref":"global_group.html#t:publish_type/0"},{"type":"type","doc":"","title":"global_group.sync_state/0","ref":"global_group.html#t:sync_state/0"},{"type":"type","doc":"","title":"global_group.where/0","ref":"global_group.html#t:where/0"},{"type":"module","doc":"Various Erlang net administration routines.\n\nThis module contains various network utility functions.","title":"net_adm","ref":"net_adm.html"},{"type":"module","doc":"File `.hosts.erlang` consists of a number of host names written as Erlang terms.\nIt is looked for in the current work directory, the user's home directory, and\n`$OTPROOT` (the root directory of Erlang/OTP), in that order.\n\nThe format of file `.hosts.erlang` must be one host name per line. The host\nnames must be within quotes.\n\n_Example:_\n\n```text\n'super.eua.ericsson.se'.\n'renat.eua.ericsson.se'.\n'grouse.eua.ericsson.se'.\n'gauffin1.eua.ericsson.se'.\n^ (new line)\n```","title":"Files - net_adm","ref":"net_adm.html#module-files"},{"type":"function","doc":"Returns the official name of `Host`, or `{error, Host}` if no such name is\nfound. See also `m:inet`.","title":"net_adm.dns_hostname/1","ref":"net_adm.html#dns_hostname/1"},{"type":"function","doc":"Reads file `.hosts.erlang`, see section [Files](`m:net_adm#module-files`). Returns the\nhosts in this file as a list. Returns `{error, Reason}` if the file cannot be\nread or the Erlang terms on the file cannot be interpreted.","title":"net_adm.host_file/0","ref":"net_adm.html#host_file/0"},{"type":"function","doc":"Returns the name of the local host. If Erlang was started with command-line flag\n`-name`, `Name` is the fully qualified name.","title":"net_adm.localhost/0","ref":"net_adm.html#localhost/0"},{"type":"function","doc":"","title":"net_adm.names/0","ref":"net_adm.html#names/0"},{"type":"function","doc":"Returns the names and associated port numbers of the Erlang nodes that `epmd`\nregistered at the specified host.\n\nSimilar to `epmd -names`, see [`erts:epmd`](`e:erts:epmd_cmd.md`).\n\nReturns `{error, address}` if `epmd` is not operational.\n\n_Example:_\n\n```erlang\n(arne@dunn)1> net_adm:names().\n{ok,[{\"arne\",40262}]}\n```","title":"net_adm.names/1","ref":"net_adm.html#names/1"},{"type":"function","doc":"Sets up a connection to `Node`. Returns `pong` if it is successful, otherwise\n`pang`.","title":"net_adm.ping/1","ref":"net_adm.html#ping/1"},{"type":"function","doc":"","title":"net_adm.world/0","ref":"net_adm.html#world/0"},{"type":"function","doc":"Calls [`names(Host)`](`names/1`) for all hosts that are specified in the Erlang\nhost file `.hosts.erlang`, collects the replies, and then evaluates\n[`ping(Node)`](`ping/1`) on all those nodes. Returns the list of all nodes that\nare successfully pinged.\n\nIf `Arg == verbose`, the function writes information about which nodes it is\npinging to `stdout`.\n\nThis function can be useful when a node is started, and the names of the other\nnetwork nodes are not initially known.\n\nReturns `{error, Reason}` if `host_file/0` returns `{error, Reason}`.","title":"net_adm.world/1","ref":"net_adm.html#world/1"},{"type":"function","doc":"","title":"net_adm.world_list/1","ref":"net_adm.html#world_list/1"},{"type":"function","doc":"Same as [`world/0,1`](`world/1`), but the hosts are specified as argument\ninstead of being read from `.hosts.erlang`.","title":"net_adm.world_list/2","ref":"net_adm.html#world_list/2"},{"type":"type","doc":"","title":"net_adm.verbosity/0","ref":"net_adm.html#t:verbosity/0"},{"type":"module","doc":"Erlang networking kernel.\n\nThe net kernel is a system process, registered as `net_kernel`, which must be\noperational for distributed Erlang to work. The purpose of this process is to\nimplement parts of the BIFs [`spawn/4`](`spawn/4`) and\n[`spawn_link/4`](`spawn_link/4`), and to provide monitoring of the network.\n\nAn Erlang node is started using command-line flag `-name` or `-sname`:\n\n```text\n$ erl -sname foobar\n```\n\nIt is also possible to call [`net_kernel:start(foobar, #{})`](`start/2`)\ndirectly from the normal Erlang shell prompt:\n\n```erlang\n1> net_kernel:start(foobar, #{name_domain => shortnames}).\n{ok,<0.64.0>}\n(foobar@gringotts)2>\n```\n\nIf the node is started with command-line flag `-sname`, the node name is\n`foobar@Host`, where `Host` is the short name of the host (not the fully\nqualified domain name). If started with flag `-name`, the node name is\n`foobar@Host`, where `Host` is the fully qualified domain name. For more\ninformation, see [`erl`](`e:erts:erl_cmd.md`).\n\nNormally, connections are established automatically when another node is\nreferenced. This functionality can be disabled by setting Kernel configuration\nparameter `dist_auto_connect` to `never`, see [`kernel(6)`](kernel_app.md). In\nthis case, connections must be established explicitly by calling\n`connect_node/1`.\n\nWhich nodes that are allowed to communicate with each other is handled by the\nmagic cookie system, see section [Distributed Erlang](`e:system:distributed.md`)\nin the Erlang Reference Manual.\n\n> #### Warning {: .warning }\n>\n> Starting a distributed node without also specifying\n> [`-proto_dist inet_tls`](`e:erts:erl_cmd.md#proto_dist`) will expose the node\n> to attacks that may give the attacker complete access to the node and in\n> extension the cluster. When using un-secure distributed nodes, make sure that\n> the network is configured to keep potential attackers out. See the\n> [Using SSL for Erlang Distribution](`e:ssl:ssl_distribution.md`) User's Guide\n> for details on how to setup a secure distributed node.","title":"net_kernel","ref":"net_kernel.html"},{"type":"function","doc":"Permits access to the specified set of nodes.\n\nBefore the first call to [`allow/1`](`allow/1`), any node with the correct\ncookie can be connected. When [`allow/1`](`allow/1`) is called, a list of\nallowed nodes is established. Any access attempts made from (or to) nodes not in\nthat list will be rejected.\n\nSubsequent calls to [`allow/1`](`allow/1`) will add the specified nodes to the\nlist of allowed nodes. It is not possible to remove nodes from the list.\n\nDisallowing an already connected node will not cause it to be disconnected. It\nwill, however, prevent any future reconnection attempts.\n\nPassing `Nodes` as an empty list has never any affect at all.\n\nReturns `error` if any element in `Nodes` is not an atom, and `ignored` if the\nlocal node is not alive.","title":"net_kernel.allow/1","ref":"net_kernel.html#allow/1"},{"type":"function","doc":"Returns a list of nodes that are explicitly allowed to connect to the node by calling\n[`allow/1`](`allow/1`). If empty list is returned, it means that any node using the\nsame cookie will be able to connect.","title":"net_kernel.allowed/0","ref":"net_kernel.html#allowed/0"},{"type":"function","doc":"Establishes a connection to `Node`.\n\nReturns `true` if a connection was established or was already established or if\n`Node` is the local node itself. Returns `false` if the connection attempt failed,\nand `ignored` if the local node is not alive.","title":"net_kernel.connect_node/1","ref":"net_kernel.html#connect_node/1"},{"type":"function","doc":"Returns currently used net tick time in seconds.\n\nFor more information see the [`net_ticktime`](kernel_app.md#net_ticktime)\n`Kernel` parameter.\n\nDefined return values (`Res`):\n\n- **`NetTicktime`** - `net_ticktime` is `NetTicktime` seconds.\n\n- **`{ongoing_change_to, NetTicktime}`** - `net_kernel` is currently changing\n `net_ticktime` to `NetTicktime` seconds.\n\n- **`ignored`** - The local node is not alive.","title":"net_kernel.get_net_ticktime/0","ref":"net_kernel.html#get_net_ticktime/0"},{"type":"function","doc":"Get the current state of the distribution for the local node.\n\nReturns a map with (at least) the following key-value pairs:\n\n- **`started => Started`** - Valid values for `Started`:\n\n - **`no`** - The distribution is not started. In this state none of the other\n keys below are present in the map.\n\n - **`static`** - The distribution was started with command line arguments\n [`-name`](`e:erts:erl_cmd.md#name`) or\n [`-sname`](`e:erts:erl_cmd.md#sname`).\n\n - **`dynamic`** - The distribution was started with\n [`net_kernel:start/1`](`start/1`) and can be stopped with\n [`net_kernel:stop/0`](`start/1`).\n\n- **`name => Name`** - The name of the node. Same as returned by `erlang:node/0`\n except when `name_type` is `dynamic` in which case `Name` may be `undefined`\n (instead of `nonode@nohost`).\n\n- **`name_type => NameType`** - Valid values for `NameType`:\n\n - **`static`** - The node has a static node name set by the node itself.\n\n - **`dynamic`** - The distribution was started in\n [dynamic node name](`e:system:distributed.md#dyn_node_name`) mode, and will\n get its node name assigned from the first node it connects to. If key `name`\n has value `undefined` that has not happened yet.\n\n- **`name_domain => NameDomain`** - Valid values for `NameDomain`:\n\n - **`shortnames`** - The distribution was started to use node names with a\n short host portion (not fully qualified).\n\n - **`longnames`** - The distribution was started to use node names with a long\n fully qualified host portion.","title":"net_kernel.get_state/0","ref":"net_kernel.html#get_state/0"},{"type":"function","doc":"Get one or more options for the distribution socket connected to `Node`.\n\nIf `Node` is a connected node the return value is the same as from\n[`inet:getopts(Sock, Options)`](`inet:getopts/2`) where `Sock` is the\ndistribution socket for `Node`.\n\nReturns `ignored` if the local node is not alive or `{error, noconnection}` if\n`Node` is not connected.","title":"net_kernel.getopts/2","ref":"net_kernel.html#getopts/2"},{"type":"function","doc":"","title":"net_kernel.monitor_nodes/1","ref":"net_kernel.html#monitor_nodes/1"},{"type":"function","doc":"The calling process subscribes or unsubscribes to node status change messages. A\n`nodeup` message is delivered to all subscribing processes when a new node is\nconnected, and a `nodedown` message is delivered when a node is disconnected.\n\nIf `Flag` is `true`, a new subscription is started. If `Flag` is `false`, all\nprevious subscriptions started with the same `Options` are stopped. Two option\nlists are considered the same if they contain the same set of options.\n\nDelivery guarantees of `nodeup`/`nodedown` messages:\n\n- `nodeup` messages are delivered before delivery of any signals from the remote\n node through the newly established connection.\n- `nodedown` messages are delivered after all the signals from the remote node\n over the connection have been delivered.\n- `nodeup` messages are delivered after the corresponding node appears in\n results from `erlang:nodes()`.\n- `nodedown` messages are delivered after the corresponding node has disappeared\n in results from `erlang:nodes()`.\n- As of OTP 23.0, a `nodedown` message for a connection being taken down will be\n delivered before a `nodeup` message due to a new connection to the same node.\n Prior to OTP 23.0, this was not guaranteed to be the case.\n\nThe format of the node status change messages depends on `Options`. If `Options`\nis the empty list or if `net_kernel:monitor_nodes/1` is called, the format is as\nfollows:\n\n```erlang\n{nodeup, Node} | {nodedown, Node}\n Node = node()\n```\n\nWhen `Options` is the empty map or empty list, the caller will only subscribe\nfor status change messages for visible nodes. That is, only nodes that appear in\nthe result of `erlang:nodes/0`.\n\nIf `Options` equals anything other than the empty list, the format of the status\nchange messages is as follows:\n\n```erlang\n{nodeup, Node, Info} | {nodedown, Node, Info}\n Node = node()\n Info = #{Tag => Val} | [{Tag, Val}]\n```\n\n`Info` is either a map or a list of 2-tuples. Its content depends on `Options`.\nIf `Options` is a map, `Info` will also be a map. If `Options` is a list, `Info`\nwill also be a list.\n\nWhen `Options` is a map, currently the following associations are allowed:\n\n- **`connection_id => boolean()`** - If the value of the association equals\n `true`, a `connection_id => ConnectionId` association will be included in the\n `Info` map where `ConnectionId` is the connection identifier of the connection\n coming up or going down. For more info about this connection identifier see\n the documentation of [erlang:nodes/2](`m:erlang#connection_id`).\n\n- **`node_type => NodeType`** - Valid values for `NodeType`:\n\n - **`visible`** - Subscribe to node status change messages for visible nodes\n only. The association `node_type => visible` will be included in the `Info`\n map.\n\n - **`hidden`** - Subscribe to node status change messages for hidden nodes\n only. The association `node_type => hidden` will be included in the `Info`\n map.\n\n - **`all`** - Subscribe to node status change messages for both visible and\n hidden nodes. The association `node_type => visible | hidden` will be\n included in the `Info` map.\n\n If no `node_type => NodeType` association is included in the `Options` map,\n the caller will subscribe for status change messages for visible nodes only,\n but _no_ `node_type => visible` association will be included in the `Info`\n map.\n\n- **`nodedown_reason => boolean()`** - If the value of the association equals\n `true`, a `nodedown_reason => Reason` association will be included in the\n `Info` map for `nodedown` messages.\n\n [](){: #nodedown_reasons } `Reason` can, depending on which distribution\n module or process that is used, be any term, but for the standard TCP\n distribution module it is one of the following:\n\n - **`connection_setup_failed`** - The connection setup failed (after `nodeup`\n messages were sent).\n\n - **`no_network`** - No network is available.\n\n - **`net_kernel_terminated`** - The `net_kernel` process terminated.\n\n - **`shutdown`** - Unspecified connection shutdown.\n\n - **`connection_closed`** - The connection was closed.\n\n - **`disconnect`** - The connection was disconnected (forced from the current\n node).\n\n - **`net_tick_timeout`** - Net tick time-out.\n\n - **`send_net_tick_failed`** - Failed to send net tick over the connection.\n\n - **`get_status_failed`** - Status information retrieval from the `Port`\n holding the connection failed.\n\nWhen `Options` is a list, currently `ListOption` can be one of the following:\n\n- **`connection_id`** - A `{connection_id, ConnectionId}` tuple will be included\n in `Info` where `ConnectionId` is the connection identifier of the connection\n coming up or going down. For more info about this connection identifier see\n the documentation of [erlang:nodes/2](`m:erlang#connection_id`).\n\n- **`{node_type, NodeType}`** - Valid values for `NodeType`:\n\n - **`visible`** - Subscribe to node status change messages for visible nodes\n only. The tuple `{node_type, visible}` will be included in the `Info` list.\n\n - **`hidden`** - Subscribe to node status change messages for hidden nodes\n only. The tuple `{node_type, hidden}` will be included in the `Info` list.\n\n - **`all`** - Subscribe to node status change messages for both visible and\n hidden nodes. The tuple `{node_type, visible | hidden}` will be included in\n the `Info` list.\n\n If no `{node_type, NodeType}` option has been given. The caller will subscribe\n for status change messages for visible nodes only, but _no_\n `{node_type, visible}` tuple will be included in the `Info` list.\n\n- **`nodedown_reason`** - The tuple `{nodedown_reason, Reason}` will be included\n in the `Info` list for `nodedown` messages.\n\n See the documentation of the\n [`nodedown_reason => boolean()`](`m:net_kernel#nodedown_reasons`) association\n above for information about possible `Reason` values.\n\nExample:\n\n```erlang\n(a@localhost)1> net_kernel:monitor_nodes(true, #{connection_id=>true, node_type=>all, nodedown_reason=>true}).\nok\n(a@localhost)2> flush().\nShell got {nodeup,b@localhost,\n #{connection_id => 3067552,node_type => visible}}\nShell got {nodeup,c@localhost,\n #{connection_id => 13892107,node_type => hidden}}\nShell got {nodedown,b@localhost,\n #{connection_id => 3067552,node_type => visible,\n nodedown_reason => connection_closed}}\nShell got {nodedown,c@localhost,\n #{connection_id => 13892107,node_type => hidden,\n nodedown_reason => net_tick_timeout}}\nShell got {nodeup,b@localhost,\n #{connection_id => 3067553,node_type => visible}}\nok\n(a@localhost)3>\n```","title":"net_kernel.monitor_nodes/2","ref":"net_kernel.html#monitor_nodes/2"},{"type":"function","doc":"","title":"net_kernel.set_net_ticktime/1","ref":"net_kernel.html#set_net_ticktime/1"},{"type":"function","doc":"Sets `net_ticktime` (see [`kernel(6)`](kernel_app.md)) to `NetTicktime` seconds.\n`TransitionPeriod` defaults to `60`.\n\nSome definitions:\n\n- **Minimum transition traffic interval (`MTTI`)** -\n `minimum(NetTicktime, PreviousNetTicktime)*1000 div 4` milliseconds.\n\n- **Transition period** - The time of the least number of consecutive `MTTI`s to\n cover `TransitionPeriod` seconds following the call to\n [`set_net_ticktime/2`](`set_net_ticktime/2`) (that is,\n ((`TransitionPeriod*1000 - 1) div MTTI + 1)*MTTI` milliseconds).\n\nIf `NetTicktime #### Note {: .info }\n>\n> The `net_ticktime` changes must be initiated on all nodes in the network (with\n> the same `NetTicktime`) before the end of any transition period on any node;\n> otherwise connections can erroneously be disconnected.\n\nReturns one of the following:\n\n- **`unchanged`** - `net_ticktime` already has the value of `NetTicktime` and is\n left unchanged.\n\n- **`change_initiated`** - `net_kernel` initiated the change of `net_ticktime`\n to `NetTicktime` seconds.\n\n- **`{ongoing_change_to, NewNetTicktime}`** - The request is _ignored_ because\n `net_kernel` is busy changing `net_ticktime` to `NewNetTicktime` seconds.","title":"net_kernel.set_net_ticktime/2","ref":"net_kernel.html#set_net_ticktime/2"},{"type":"function","doc":"Set one or more options for distribution sockets. Argument `Node` can be either\none node name or the atom `new` to affect the distribution sockets of all future\nconnected nodes.\n\nThe return value is the same as from `inet:setopts/2` or `{error, noconnection}`\nif `Node` is not a connected node or `new`.\n\nIf `Node` is `new` the `Options` will then also be added to kernel configuration\nparameters [inet_dist_listen_options](kernel_app.md#inet_dist_listen_options)\nand [inet_dist_connect_options](kernel_app.md#inet_dist_connect_options).\n\nReturns `ignored` if the local node is not alive.","title":"net_kernel.setopts/2","ref":"net_kernel.html#setopts/2"},{"type":"function","doc":"Turns a non-distributed node into a distributed node by starting `net_kernel`\nand other necessary processes.\n\n`Options` list can only be exactly one of the following lists (order is\nimporant):\n\n- **`[Name]`** - The same as `net_kernel:start([Name, longnames, 15000])`.\n\n- **`[Name, NameDomain]`** - The same as\n `net_kernel:start([Name, NameDomain, 15000])`.\n\n- **`[Name, NameDomain, TickTime]`** - The same as\n [`net_kernel:start(Name, #{name_domain => NameDomain, net_ticktime => ((TickTime*4-1) div 1000) + 1, net_tickintensity => 4})`](`start/2`).\n Note that `TickTime` is _not_ the same as net tick time expressed in\n milliseconds. `TickTime` is the time between ticks when net tick intensity\n equals `4`.","title":"net_kernel.start/1","ref":"net_kernel.html#start/1"},{"type":"function","doc":"Turns a non-distributed node into a distributed node by starting `net_kernel`\nand other necessary processes.\n\nIf `Name` is set to _`undefined`_ the distribution will be started to request a\ndynamic node name from the first node it connects to. See\n[Dynamic Node Name](`e:system:distributed.md#dyn_node_name`). Setting `Name` to\n`undefined` implies options `dist_listen => false` and `hidden => true`.\n\nCurrently supported options:\n\n- **`name_domain => NameDomain`** - Determines the host name part of the node\n name. If `NameDomain` equals `longnames`, fully qualified domain names will be\n used which also is the default. If `NameDomain` equals `shortnames`, only the\n short name of the host will be used.\n\n- **`net_ticktime => NetTickTime`** - _Net tick time_ to use in seconds.\n Defaults to the value of the [`net_ticktime`](kernel_app.md#net_ticktime)\n `kernel(6)` parameter. For more information about _net tick time_, see the\n `kernel` parameter. However, note that if the value of the `kernel` parameter\n is invalid, it will silently be replaced by a valid value, but if an invalid\n `NetTickTime` value is passed as option value to this function, the call will\n fail.\n\n- **`net_tickintensity => NetTickIntensity`** - _Net tick intensity_ to use.\n Defaults to the value of the\n [`net_tickintensity`](kernel_app.md#net_tickintensity) `kernel(6)` parameter.\n For more information about _net tick intensity_, see the `kernel` parameter.\n However, note that if the value of the `kernel` parameter is invalid, it will\n silently be replaced by a valid value, but if an invalid `NetTickIntensity`\n value is passed as option value to this function, the call will fail.\n\n- **`dist_listen => boolean()`** - Enable or disable listening for incoming\n connections. Defaults to the value of the\n [`-dist_listen`](`e:erts:erl_cmd.md#dist_listen`) `erl` command line argument.\n Note that `dist_listen => false` implies `hidden => true`.\n\n If `undefined` has been passed as `Name`, the `dist_listen` option will be\n overridden with `dist_listen => false`.\n\n- **`hidden => boolean()`** - Enable or disable hidden node. Defaults to `true`\n if the [`-hidden`](`e:erts:erl_cmd.md#hidden`) `erl` command line argument has\n been passed; otherwise `false`.\n\n If `undefined` has been passed as `Name`, or the option `dist_listen` equals\n `false`, the `hidden` option will be overridden with `hidden => true`.","title":"net_kernel.start/2","ref":"net_kernel.html#start/2"},{"type":"function","doc":"Turns a distributed node into a non-distributed node.\n\nFor other nodes in the network, this is the same as the node going down.\nOnly possible when the net kernel was started using `start/2`, otherwise\n`{error, not_allowed}` is returned. Returns `{error, not_found}` if the local\nnode is not alive.","title":"net_kernel.stop/0","ref":"net_kernel.html#stop/0"},{"type":"type","doc":"","title":"net_kernel.connection_state/0","ref":"net_kernel.html#t:connection_state/0"},{"type":"type","doc":"","title":"net_kernel.connection_type/0","ref":"net_kernel.html#t:connection_type/0"},{"type":"module","doc":"Distributed named process groups.\n\nThis module implements process groups. A message can be sent to one, some, or\nall group members.\n\nUp until OTP 17 there used to exist an experimental `pg` module in `stdlib`.\nThis `pg` module is not the same module as that experimental `pg` module, and\nonly share the same module name.\n\nA group of processes can be accessed by a common name. For example, if there is\na group named `foobar`, there can be a set of processes (which can be located on\ndifferent nodes) that are all members of the group `foobar`. There are no\nspecial functions for sending a message to the group. Instead, client functions\nare to be written with the functions `get_members/1` and `get_local_members/1`\nto determine which processes are members of the group. Then the message can be\nsent to one or more group members.\n\nIf a member terminates, it is automatically removed from the group.\n\nA process may join multiple groups. It may join the same group multiple times.\nIt is only allowed to join processes running on local node.\n\nProcess Groups implement strong eventual consistency. Process Groups membership\nview may temporarily diverge. For example, when processes on `node1` and `node2`\njoin concurrently, `node3` and `node4` may receive updates in a different order.\n\nMembership view is not transitive. If `node1` is not directly connected to\n`node2`, they will not see each other groups. But if both are connected to\n`node3`, `node3` will have the full view.\n\nGroups are automatically created when any process joins, and are removed when\nall processes leave the group. Non-existing group is considered empty\n(containing no processes).\n\nProcess groups can be organised into multiple scopes. Scopes are completely\nindependent of each other. A process may join any number of groups in any number\nof scopes. Scopes are designed to decouple single mesh into a set of overlay\nnetworks, reducing amount of traffic required to propagate group membership\ninformation. Default scope `pg` is started automatically when\n[Kernel](kernel_app.md#start_pg) is configured to do so.\n\n> #### Note {: .info }\n>\n> Scope name is used to register process locally, and to name an ETS table. If\n> there is another process registered under this name, or another ETS table\n> exists, scope fails to start.\n>\n> Local membership is not preserved if scope process exits and restarts.\n>\n> A scope can be kept local-only by using a scope name that is unique\n> cluster-wide, e.g. the node name: `pg:start_link(node()).`","title":"pg","ref":"pg.html"},{"type":"module","doc":"[Kernel](kernel_app.md)","title":"See Also - pg","ref":"pg.html#module-see-also"},{"type":"function","doc":"","title":"pg.demonitor/1","ref":"pg.html#demonitor/1"},{"type":"function","doc":"Unsubscribes the caller from updates (scope or group). Flushes all outstanding\nupdates that were already in the message queue of the calling process.","title":"pg.demonitor/2","ref":"pg.html#demonitor/2"},{"type":"function","doc":"","title":"pg.get_local_members/1","ref":"pg.html#get_local_members/1"},{"type":"function","doc":"Returns all processes running on the local node in the group `Group`. Processes\nare returned in no specific order. This function is optimised for speed.","title":"pg.get_local_members/2","ref":"pg.html#get_local_members/2"},{"type":"function","doc":"","title":"pg.get_members/1","ref":"pg.html#get_members/1"},{"type":"function","doc":"Returns all processes in the group `Group`. Processes are returned in no\nspecific order. This function is optimised for speed.","title":"pg.get_members/2","ref":"pg.html#get_members/2"},{"type":"function","doc":"","title":"pg.join/2","ref":"pg.html#join/2"},{"type":"function","doc":"Joins single process or multiple processes to the group `Group`. A process can\njoin a group many times and must then leave the group the same number of times.\n\n`PidOrPids` may contain the same process multiple times.","title":"pg.join/3","ref":"pg.html#join/3"},{"type":"function","doc":"","title":"pg.leave/2","ref":"pg.html#leave/2"},{"type":"function","doc":"Makes the process `PidOrPids` leave the group `Group`. If the process is not a\nmember of the group, `not_joined` is returned.\n\nWhen list of processes is passed as `PidOrPids`, function returns `not_joined`\nonly when all processes of the list are not joined.","title":"pg.leave/3","ref":"pg.html#leave/3"},{"type":"function","doc":"","title":"pg.monitor/1","ref":"pg.html#monitor/1"},{"type":"function","doc":"Subscribes the caller to updates for the specified group.\n\nReturns list of processes currently in the group, and a reference to match the\nupcoming notifications.\n\nSee `monitor_scope/0` for the update message structure.","title":"pg.monitor/2","ref":"pg.html#monitor/2"},{"type":"function","doc":"","title":"pg.monitor_scope/0","ref":"pg.html#monitor_scope/0"},{"type":"function","doc":"Subscribes the caller to updates from the specified scope.\n\nReturns content of the entire scope and a reference to match the upcoming\nnotifications.\n\nWhenever any group membership changes, an update message is sent to the\nsubscriber:\n\n```erlang\n{Ref, join, Group, [JoinPid1, JoinPid2]}\n```\n\n```erlang\n{Ref, leave, Group, [LeavePid1]}\n```","title":"pg.monitor_scope/1","ref":"pg.html#monitor_scope/1"},{"type":"function","doc":"Starts additional scope.","title":"pg.start/1","ref":"pg.html#start/1"},{"type":"function","doc":"Starts the default `pg` scope within supervision tree.\n\nKernel may be configured to do it automatically by setting\nthe Kernel configuration parameter [`start_pg`](kernel_app.md#start_pg).","title":"pg.start_link/0","ref":"pg.html#start_link/0"},{"type":"function","doc":"Equivalent to [`start(Scope)`](`start/1`), except that it also creates\na `link/1` with the calling process.","title":"pg.start_link/1","ref":"pg.html#start_link/1"},{"type":"function","doc":"","title":"pg.which_groups/0","ref":"pg.html#which_groups/0"},{"type":"function","doc":"Returns a list of all known groups.","title":"pg.which_groups/1","ref":"pg.html#which_groups/1"},{"type":"type","doc":"The identifier of a process group.","title":"pg.group/0","ref":"pg.html#t:group/0"},{"type":"module","doc":"Remote Procedure Call services.\n\nThis module contains services similar to Remote Procedure Calls. It also\ncontains broadcast facilities and parallel evaluators. A remote procedure call\nis a method to call a function on a remote node and collect the answer. It is\nused for collecting information on a remote node, or for running a function with\nsome specific side effects on the remote node.\n\n> #### Note {: .info }\n>\n> `rpc:call/4` and friends makes it quite hard to distinguish between successful\n> results, raised exceptions, and other errors. This cannot be changed due to\n> compatibility reasons. As of OTP 23, a new module `m:erpc` was introduced in\n> order to provide an API that makes it possible to distinguish between the\n> different results. The `erpc` module provides a subset (however, the central\n> subset) of the functionality available in the `rpc` module. The `erpc`\n> implementation also provides a more scalable implementation with better\n> performance than the original `rpc` implementation. However, since the\n> introduction of `erpc`, the `rpc` module implements large parts of its central\n> functionality using `erpc`, so the `rpc` module won't not suffer scalability\n> wise and performance wise compared to `erpc`.\n\n> #### Note {: .info }\n>\n> For some important information about distributed signals, see the\n> [Blocking Signaling Over Distribution](`e:system:ref_man_processes.md#blocking-signaling-over-distribution`)\n> section in the _Processes_ chapter of the _Erlang Reference Manual_. Blocking\n> signaling can, for example, cause timeouts in `rpc` to be significantly\n> delayed.","title":"rpc","ref":"rpc.html"},{"type":"function","doc":"Equivalent to [`abcast([node()|nodes()], Name, Msg)`](`abcast/3`).","title":"rpc.abcast/2","ref":"rpc.html#abcast/2"},{"type":"function","doc":"Broadcasts the message `Msg` asynchronously to the registered process `Name` on\nthe specified nodes.","title":"rpc.abcast/3","ref":"rpc.html#abcast/3"},{"type":"function","doc":"Implements _call streams with promises_, a type of RPC that does not suspend the\ncaller until the result is finished. Instead, a key is returned, which can be\nused later to collect the value. The key can be viewed as a promise to deliver\nthe answer.\n\nIn this case, the key `Key` is returned, which can be used in a subsequent call\nto `yield/1` or [`nb_yield/1,2`](`nb_yield/1`) to retrieve the value of\nevaluating [`apply(Module, Function, Args)`](`apply/3`) on node `Node`.\n\n> #### Note {: .info }\n>\n> If you want the ability to distinguish between results, you may want to\n> consider using the [`erpc:send_request()`](`erpc:send_request/4`) function\n> from the `erpc` module instead. This also gives you the ability retrieve the\n> results in other useful ways.\n\n> #### Note {: .info }\n>\n> `yield/1` and [`nb_yield/1,2`](`nb_yield/1`) must be called by the same\n> process from which this function was made otherwise they will never yield\n> correctly.\n\n> #### Note {: .info }\n>\n> You cannot make _any_ assumptions about the process that will perform the\n> `apply()`. It may be an `rpc` server, another server, or a freshly spawned\n> process.","title":"rpc.async_call/4","ref":"rpc.html#async_call/4"},{"type":"function","doc":"The same as calling\n[`rpc:block_call(Node, Module, Function, Args, infinity)`](`block_call/5`).","title":"rpc.block_call/4","ref":"rpc.html#block_call/4"},{"type":"function","doc":"The same as calling\n[`rpc:call(Node, Module, Function, Args, Timeout)`](`call/5`) with the exception\nthat it also blocks other `rpc:block_call/5` operations from executing\nconcurrently on the node `Node`.\n\n> #### Warning {: .warning }\n>\n> Note that it also blocks other operations than just `rpc:block_call/5`\n> operations, so use it with care.","title":"rpc.block_call/5","ref":"rpc.html#block_call/5"},{"type":"function","doc":"Evaluates [`apply(Module, Function, Args)`](`apply/3`) on node `Node` and\nreturns the corresponding value `Res`, or `{badrpc, Reason}` if the call fails.\nThe same as calling\n[`rpc:call(Node, Module, Function, Args, infinity)`](`call/5`).","title":"rpc.call/4","ref":"rpc.html#call/4"},{"type":"function","doc":"Evaluates [`apply(Module, Function, Args)`](`apply/3`) on node `Node` and\nreturns the corresponding value `Res`, or `{badrpc, Reason}` if the call fails.\n`Timeout` is a time-out value in milliseconds. If the call times out, `Reason`\nis `timeout`.\n\nIf the reply arrives after the call times out, no message contaminates the\ncaller's message queue.\n\n> #### Note {: .info }\n>\n> If you want the ability to distinguish between results, you may want to\n> consider using the [`erpc:call()`](`erpc:call/4`) function from the `erpc`\n> module instead.\n\n> #### Note {: .info }\n>\n> Here follows the details of what exactly is returned.\n>\n> `{badrpc, Reason}` will be returned in the following circumstances:\n>\n> - The called function fails with an `exit` exception.\n> - The called function fails with an `error` exception.\n> - The called function returns a term that matches `{'EXIT', _}`.\n> - The called function `throws` a term that matches `{'EXIT', _}`.\n>\n> `Res` is returned in the following circumstances:\n>\n> - The called function returns normally with a term that does **not** match\n> `{'EXIT',_}`.\n> - The called function `throw`s a term that does **not** match `{'EXIT',_}`.\n\n> #### Note {: .info }\n>\n> You cannot make _any_ assumptions about the process that will perform the\n> `apply()`. It may be the calling process itself, an `rpc` server, another\n> server, or a freshly spawned process.","title":"rpc.call/5","ref":"rpc.html#call/5"},{"type":"function","doc":"Evaluates [`apply(Module, Function, Args)`](`apply/3`) on node `Node`. No\nresponse is delivered and the calling process is not suspended until the\nevaluation is complete, as is the case with [`call/4,5`](`call/4`).\n\n> #### Note {: .info }\n>\n> You cannot make _any_ assumptions about the process that will perform the\n> `apply()`. It may be an `rpc` server, another server, or a freshly spawned\n> process.","title":"rpc.cast/4","ref":"rpc.html#cast/4"},{"type":"function","doc":"Equivalent to\n[`eval_everywhere([node()|nodes()], Module, Function, Args)`](`eval_everywhere/4`).","title":"rpc.eval_everywhere/3","ref":"rpc.html#eval_everywhere/3"},{"type":"function","doc":"Evaluates [`apply(Module, Function, Args)`](`apply/3`) on the specified nodes.\nNo answers are collected.","title":"rpc.eval_everywhere/4","ref":"rpc.html#eval_everywhere/4"},{"type":"function","doc":"Equivalent to\n[`multi_server_call([node()|nodes()], Name, Msg)`](`multi_server_call/3`).","title":"rpc.multi_server_call/2","ref":"rpc.html#multi_server_call/2"},{"type":"function","doc":"Can be used when interacting with servers called `Name` on the specified nodes.\nIt is assumed that the servers receive messages in the format `{From, Msg}` and\nreply using `From ! {Name, Node, Reply}`, where `Node` is the name of the node\nwhere the server is located. The function returns `{Replies, BadNodes}`, where\n`Replies` is a list of all `Reply` values, and `BadNodes` is one of the\nfollowing:\n\n- A list of the nodes that do not exist\n- A list of the nodes where the server does not exist\n- A list of the nodes where the server terminated before sending any reply.","title":"rpc.multi_server_call/3","ref":"rpc.html#multi_server_call/3"},{"type":"function","doc":"Equivalent to\n[`multicall([node()|nodes()], Module, Function, Args, infinity)`](`multicall/5`).","title":"rpc.multicall/3","ref":"rpc.html#multicall/3"},{"type":"function","doc":"Equivalent to\n[`multicall(Nodes, Module, Function, Args, infinity)`](`multicall/5`).\n\nEquivalent to\n[`multicall([node()|nodes()], Module, Function, Args, Timeout)`](`multicall/5`).","title":"rpc.multicall/4","ref":"rpc.html#multicall/4"},{"type":"function","doc":"In contrast to an RPC, a multicall is an RPC that is sent concurrently from one\nclient to multiple servers. This is useful for collecting information from a set\nof nodes, or for calling a function on a set of nodes to achieve some side\neffects. It is semantically the same as iteratively making a series of RPCs on\nall the nodes, but the multicall is faster, as all the requests are sent at the\nsame time and are collected one by one as they come back.\n\nThe function evaluates [`apply(Module, Function, Args)`](`apply/3`) on the\nspecified nodes and collects the answers. It returns `{ResL, BadNodes}`, where\n`BadNodes` is a list of the nodes that do not exist, and `ResL` is a list of the\nreturn values, or `{badrpc, Reason}` for failing calls. `Timeout` is a time\n(integer) in milliseconds, or `infinity`.\n\nThe following example is useful when new object code is to be loaded on all\nnodes in the network, and indicates some side effects that RPCs can produce:\n\n```erlang\n%% Find object code for module Mod\n{Mod, Bin, File} = code:get_object_code(Mod),\n\n%% and load it on all nodes including this one\n{ResL, _} = rpc:multicall(code, load_binary, [Mod, File, Bin]),\n\n%% and then maybe check the ResL list.\n```\n\n> #### Note {: .info }\n>\n> If you want the ability to distinguish between results, you may want to\n> consider using the [`erpc:multicall()`](`erpc:multicall/4`) function from the\n> `erpc` module instead.\n\n> #### Note {: .info }\n>\n> You cannot make _any_ assumptions about the process that will perform the\n> `apply()`. It may be the calling process itself, an `rpc` server, another\n> server, or a freshly spawned process.","title":"rpc.multicall/5","ref":"rpc.html#multicall/5"},{"type":"function","doc":"Equivalent to [`nb_yield(Key, 0)`](`nb_yield/2`).","title":"rpc.nb_yield/1","ref":"rpc.html#nb_yield/1"},{"type":"function","doc":"Non-blocking version of `yield/1`. It returns the tuple `{value, Val}` when the\ncomputation is finished, or `timeout` when `Timeout` milliseconds has elapsed.\n\nSee the note in `call/4` for more details of Val.\n\n> #### Note {: .info }\n>\n> This function must be called by the same process from which `async_call/4` was\n> made otherwise it will only return `timeout`.","title":"rpc.nb_yield/2","ref":"rpc.html#nb_yield/2"},{"type":"function","doc":"Evaluates, for every tuple in `FuncCalls`,\n[`apply(Module, Function, Args)`](`apply/3`) on some node in the network.\nReturns the list of return values, in the same order as in `FuncCalls`.","title":"rpc.parallel_eval/1","ref":"rpc.html#parallel_eval/1"},{"type":"function","doc":"Location transparent version of the BIF `erlang:process_info/1` in ERTS.","title":"rpc.pinfo/1","ref":"rpc.html#pinfo/1"},{"type":"function","doc":"Location transparent version of the BIF `erlang:process_info/2` in ERTS.","title":"rpc.pinfo/2","ref":"rpc.html#pinfo/2"},{"type":"function","doc":"Evaluates [`apply(Module, Function, [Elem|ExtraArgs])`](`apply/3`) for every\nelement `Elem` in `List1`, in parallel. Returns the list of return values, in\nthe same order as in `List1`.","title":"rpc.pmap/3","ref":"rpc.html#pmap/3"},{"type":"function","doc":"Equivalent to [`sbcast([node()|nodes()], Name, Msg)`](`sbcast/3`).","title":"rpc.sbcast/2","ref":"rpc.html#sbcast/2"},{"type":"function","doc":"Broadcasts the message `Msg` synchronously to the registered process `Name` on\nthe specified nodes.\n\nReturns `{GoodNodes, BadNodes}`, where `GoodNodes` is the list of nodes that\nhave `Name` as a registered process.\n\nThe function is synchronous in the sense that it is known that all servers have\nreceived the message when the call returns. It is not possible to know that the\nservers have processed the message.\n\nAny further messages sent to the servers, after this function has returned, are\nreceived by all servers after this message.","title":"rpc.sbcast/3","ref":"rpc.html#sbcast/3"},{"type":"function","doc":"Can be used when interacting with a server called `Name` on node `Node`. It is\nassumed that the server receives messages in the format `{From, Msg}` and\nreplies using `From ! {ReplyWrapper, Node, Reply}`. This function makes such a\nserver call and ensures that the entire call is packed into an atomic\ntransaction, which either succeeds or fails. It never hangs, unless the server\nitself hangs.\n\nThe function returns the answer `Reply` as produced by the server `Name`, or\n`{error, Reason}`.","title":"rpc.server_call/4","ref":"rpc.html#server_call/4"},{"type":"function","doc":"Returns the promised answer from a previous `async_call/4`. If the answer is\navailable, it is returned immediately. Otherwise, the calling process is\nsuspended until the answer arrives from `Node`.\n\n> #### Note {: .info }\n>\n> This function must be called by the same process from which `async_call/4` was\n> made otherwise it will never return.\n\nSee the note in `call/4` for more details of the return value.","title":"rpc.yield/1","ref":"rpc.html#yield/1"},{"type":"opaque","doc":"Opaque value returned by `async_call/4`.","title":"rpc.key/0","ref":"rpc.html#t:key/0"},{"type":"module","doc":"File interface module.\n\nThis module provides an interface to the file system.\n\n> #### Warning {: .warning }\n>\n> File operations are only guaranteed to appear atomic when going through the\n> same file server. A NIF or other OS process may observe intermediate steps on\n> certain operations on some operating systems, eg. renaming an existing file on\n> Windows, or [`write_file_info/2`](`write_file_info/2`) on any OS at the time\n> of writing.\n\nRegarding filename encoding, the Erlang VM can operate in two modes. The current\nmode can be queried using function `native_name_encoding/0`. It returns `latin1`\nor `utf8`.\n\nIn `latin1` mode, the Erlang VM does not change the encoding of filenames. In\n`utf8` mode, filenames can contain Unicode characters greater than 255 and the\nVM converts filenames back and forth to the native filename encoding (usually\nUTF-8, but UTF-16 on Windows).\n\nThe default mode depends on the operating system. Windows, MacOS X and Android\nenforce consistent filename encoding and therefore the VM uses `utf8` mode.\n\nOn operating systems with transparent naming (for example, all Unix systems\nexcept MacOS X), default is `utf8` if the terminal supports UTF-8, otherwise\n`latin1`. The default can be overridden using `+fnl` (to force `latin1` mode) or\n`+fnu` (to force `utf8` mode) when starting [`erl`](`e:erts:erl_cmd.md`).\n\nOn operating systems with transparent naming, files can be inconsistently named,\nfor example, some files are encoded in UTF-8 while others are encoded in ISO\nLatin-1. The concept of _raw filenames_ is introduced to handle file systems\nwith inconsistent naming when running in `utf8` mode.\n\nA _raw filename_ is a filename specified as a binary. The Erlang VM does not\ntranslate a filename specified as a binary on systems with transparent naming.\n\nWhen running in `utf8` mode, functions `list_dir/1` and `read_link/1` never\nreturn raw filenames. To return all filenames including raw filenames, use\nfunctions [`list_dir_all/1`](`m:file#list_dir_all`) and\n[`read_link_all/1`](`m:file#read_link_all`).\n\nSee also section\n[Notes About Raw Filenames](`e:stdlib:unicode_usage.md#notes-about-raw-filenames`)\nin the STDLIB User's Guide.\n\n> #### Note {: .info }\n>\n> File operations used to accept filenames containing null characters (integer\n> value zero). This caused the name to be truncated and in some cases arguments\n> to primitive operations to be mixed up. Filenames containing null characters\n> inside the filename are now _rejected_ and will cause primitive file\n> operations fail.","title":"file","ref":"file.html"},{"type":"module","doc":"- `eacces` \\- Permission denied\n- `eagain` \\- Resource temporarily unavailable\n- `ebadf` \\- Bad file number\n- `ebusy` \\- File busy\n- `edquot` \\- Disk quota exceeded\n- `eexist` \\- File already exists\n- `efault` \\- Bad address in system call argument\n- `efbig` \\- File too large\n- `eintr` \\- Interrupted system call\n- `einval` \\- Invalid argument\n- `eio` \\- I/O error\n- `eisdir` \\- Illegal operation on a directory\n- `eloop` \\- Too many levels of symbolic links\n- `emfile` \\- Too many open files\n- `emlink` \\- Too many links\n- `enametoolong` \\- Filename too long\n- `enfile` \\- File table overflow\n- `enodev` \\- No such device\n- `enoent` \\- No such file or directory\n- `enomem` \\- Not enough memory\n- `enospc` \\- No space left on device\n- `enotblk` \\- Block device required\n- `enotdir` \\- Not a directory\n- `enotsup` \\- Operation not supported\n- `enxio` \\- No such device or address\n- `eperm` \\- Not owner\n- `epipe` \\- Broken pipe\n- `erofs` \\- Read-only file system\n- `espipe` \\- Invalid seek\n- `esrch` \\- No such process\n- `estale` \\- Stale remote file handle\n- `exdev` \\- Cross-device link","title":"POSIX Error Codes - file","ref":"file.html#module-posix-error-codes"},{"type":"module","doc":"For increased performance, raw files are recommended.\n\nA normal file is really a process so it can be used as an I/O device (see\n`m:io`). Therefore, when data is written to a normal file, the sending of the\ndata to the file process, copies all data that are not binaries. Opening the\nfile in binary mode and writing binaries is therefore recommended. If the file\nis opened on another node, or if the file server runs as slave to the file\nserver of another node, also binaries are copied.\n\n> #### Note {: .info }\n>\n> Raw files use the file system of the host machine of the node. For normal\n> files (non-raw), the file server is used to find the files, and if the node is\n> running its file server as slave to the file server of another node, and the\n> other node runs on some other host machine, they can have different file\n> systems. However, this is seldom a problem.\n\n`open/2` can be given the options `delayed_write` and `read_ahead` to turn on\ncaching, which will reduce the number of operating system calls and greatly\nimprove performance for small reads and writes. However, the overhead won't\ndisappear completely and it's best to keep the number of file operations to a\nminimum. As a contrived example, the following function writes 4MB in 2.5\nseconds when tested:\n\n```erlang\ncreate_file_slow(Name) ->\n {ok, Fd} = file:open(Name, [raw, write, delayed_write, binary]),\n create_file_slow_1(Fd, 4 bsl 20),\n file:close(Fd).\n\ncreate_file_slow_1(_Fd, 0) ->\n ok;\ncreate_file_slow_1(Fd, M) ->\n ok = file:write(Fd, <<0>>),\n create_file_slow_1(Fd, M - 1).\n```\n\nThe following functionally equivalent code writes 128 bytes per call to\n`write/2` and so does the same work in 0.08 seconds, which is roughly 30 times\nfaster:\n\n```erlang\ncreate_file(Name) ->\n {ok, Fd} = file:open(Name, [raw, write, delayed_write, binary]),\n create_file_1(Fd, 4 bsl 20),\n file:close(Fd),\n ok.\n\ncreate_file_1(_Fd, 0) ->\n ok;\ncreate_file_1(Fd, M) when M >= 128 ->\n ok = file:write(Fd, <<0:(128)/unit:8>>),\n create_file_1(Fd, M - 128);\ncreate_file_1(Fd, M) ->\n ok = file:write(Fd, <<0:(M)/unit:8>>),\n create_file_1(Fd, M - 1).\n```\n\nWhen writing data it's generally more efficient to write a list of binaries\nrather than a list of integers. It is not needed to flatten a deep list before\nwriting. On Unix hosts, scatter output, which writes a set of buffers in one\noperation, is used when possible. In this way\n[`write(FD, [Bin1, Bin2 | Bin3])`](`write/2`) writes the contents of the\nbinaries without copying the data at all, except for perhaps deep down in the\noperating system kernel.\n\n> #### Warning {: .warning }\n>\n> If an error occurs when accessing an open file with module `m:io`, the process\n> handling the file exits. The dead file process can hang if a process tries to\n> access it later. This will be fixed in a future release.","title":"Performance - file","ref":"file.html#module-performance"},{"type":"module","doc":"`m:filename`","title":"See Also - file","ref":"file.html#module-see-also"},{"type":"function","doc":"[`advise/4`](`advise/4`) can be used to announce an intention to access file\ndata in a specific pattern in the future, thus allowing the operating system to\nperform appropriate optimizations.\n\nOn some platforms, this function might have no effect.","title":"file.advise/4","ref":"file.html#advise/4"},{"type":"function","doc":"[`allocate/3`](`allocate/3`) can be used to preallocate space for a file.\n\nThis function only succeeds in platforms that provide this feature.","title":"file.allocate/3","ref":"file.html#allocate/3"},{"type":"function","doc":"Changes group of a file. See `write_file_info/2`.","title":"file.change_group/2","ref":"file.html#change_group/2"},{"type":"function","doc":"Changes permissions of a file. See `write_file_info/2`.","title":"file.change_mode/2","ref":"file.html#change_mode/2"},{"type":"function","doc":"Changes owner of a file. See `write_file_info/2`.","title":"file.change_owner/2","ref":"file.html#change_owner/2"},{"type":"function","doc":"Changes owner and group of a file. See `write_file_info/2`.","title":"file.change_owner/3","ref":"file.html#change_owner/3"},{"type":"function","doc":"Changes the modification and access times of a file. See `write_file_info/2`.","title":"file.change_time/2","ref":"file.html#change_time/2"},{"type":"function","doc":"Changes the modification and last access times of a file. See\n`write_file_info/2`.","title":"file.change_time/3","ref":"file.html#change_time/3"},{"type":"function","doc":"Closes the file referenced by `IoDevice`. It mostly returns `ok`, except for\nsome severe errors such as out of memory.\n\nNotice that if option `delayed_write` was used when opening the file,\n[`close/1`](`close/1`) can return an old write error and not even try to close\nthe file. See `open/2`.","title":"file.close/1","ref":"file.html#close/1"},{"type":"function","doc":"Reads Erlang terms, separated by `.`, from `Filename`. Returns one of the\nfollowing:\n\n- **`{ok, Terms}`** - The file was successfully read.\n\n- **`{error, atom()}`** - An error occurred when opening the file or reading it.\n For a list of typical error codes, see `open/2`.\n\n- **`{error, {Line, Mod, Term}}`** - An error occurred when interpreting the\n Erlang terms in the file. To convert the three-element tuple to an English\n description of the error, use `format_error/1`.\n\n_Example:_\n\n```text\nf.txt: {person, \"kalle\", 25}.\n {person, \"pelle\", 30}.\n```\n\n```erlang\n1> file:consult(\"f.txt\").\n{ok,[{person,\"kalle\",25},{person,\"pelle\",30}]}\n```\n\nThe encoding of `Filename` can be set by a comment, as described in\n[`epp`](`m:epp#encoding`).","title":"file.consult/1","ref":"file.html#consult/1"},{"type":"function","doc":"","title":"file.copy/2","ref":"file.html#copy/2"},{"type":"function","doc":"Copies `ByteCount` bytes from `Source` to `Destination`. `Source` and\n`Destination` refer to either filenames or IO devices from, for example,\n[`open/2`](`open/2`).\n\nArgument `Modes` is a list of possible modes, see `open/2`, and defaults to\n`[]`.\n\nIf both `Source` and `Destination` refer to filenames, the files are opened with\n`[read, binary]` and `[write, binary]` prepended to their mode lists,\nrespectively, to optimize the copy.\n\nIf `Source` refers to a filename, it is opened with `read` mode prepended to the\nmode list before the copy, and closed when done.\n\nIf `Destination` refers to a filename, it is opened with `write` mode prepended\nto the mode list before the copy, and closed when done.\n\nReturns `{ok, BytesCopied}`, where `BytesCopied` is the number of bytes that was\ncopied, which can be less than `ByteCount` if end of file was encountered on the\nsource. If the operation fails, `{error, Reason}` is returned.\n\nTypical error reasons: as for `open/2` if a file had to be opened, and as for\n`read/2` and `write/2`.","title":"file.copy/3","ref":"file.html#copy/3"},{"type":"function","doc":"Ensures that any buffers kept by the operating system (not by the Erlang runtime\nsystem) are written to disk. In many ways it resembles `fsync` but it does not\nupdate some of the metadata of the file, such as the access time. On some\nplatforms this function has no effect.\n\nApplications that access databases or log files often write a tiny data fragment\n(for example, one line in a log file) and then call `fsync()` immediately to\nensure that the written data is physically stored on the hard disk.\nUnfortunately, `fsync()` always initiates two write operations: one for the\nnewly written data and another one to update the modification time stored in the\n`inode`. If the modification time is not a part of the transaction concept,\n`fdatasync()` can be used to avoid unnecessary `inode` disk write operations.\n\nAvailable only in some POSIX systems, this call results in a call to `fsync()`,\nor has no effect in systems not providing the `fdatasync()` syscall.","title":"file.datasync/1","ref":"file.html#datasync/1"},{"type":"function","doc":"Tries to delete directory `Dir`. The directory must be empty before it can be\ndeleted. Returns `ok` if successful.\n\nTypical error reasons:\n\n- **`eacces`** - Missing search or write permissions for the parent directories\n of `Dir`.\n\n- **`eexist`** - The directory is not empty.\n\n- **`enoent`** - The directory does not exist.\n\n- **`enotdir`** - A component of `Dir` is not a directory. On some platforms,\n `enoent` is returned instead.\n\n- **`einval`** - Attempt to delete the current directory. On some platforms,\n `eacces` is returned instead.","title":"file.del_dir/1","ref":"file.html#del_dir/1"},{"type":"function","doc":"Deletes file or directory `File`. If `File` is a directory, its contents is\nfirst recursively deleted. Returns:\n\n- **`ok`** - The operation completed without errors.\n\n- **`{error, posix()}`** - An error occurred when accessing or deleting `File`.\n If some file or directory under `File` could not be deleted, `File` cannot be\n deleted as it is non-empty, and `{error, eexist}` is returned.","title":"file.del_dir_r/1","ref":"file.html#del_dir_r/1"},{"type":"function","doc":"","title":"file.delete/1","ref":"file.html#delete/1"},{"type":"function","doc":"Tries to delete file `Filename`. Returns `ok` if successful.\n\nIf the option `raw` is set, the file server is not called. This can be useful in\nparticular during the early boot stage when the file server is not yet\nregistered, to still be able to delete local files.\n\nTypical error reasons:\n\n- **`enoent`** - The file does not exist.\n\n- **`eacces`** - Missing permission for the file or one of its parents.\n\n- **`eperm`** - The file is a directory and the user is not superuser.\n\n- **`enotdir`** - A component of the filename is not a directory. On some\n platforms, `enoent` is returned instead.\n\n- **`einval`** - `Filename` has an improper type, such as tuple.\n\n> #### Warning {: .warning }\n>\n> In a future release, a bad type for argument `Filename` will probably generate\n> an exception.","title":"file.delete/2","ref":"file.html#delete/2"},{"type":"function","doc":"Reads and evaluates Erlang expressions, separated by `.` (or `,`, a sequence of\nexpressions is also an expression) from `Filename`. The result of the evaluation\nis not returned; any expression sequence in the file must be there for its side\neffect.\n\nReturns one of the following:\n\n- **`ok`** - The file was read and evaluated.\n\n- **`{error, atom()}`** - An error occurred when opening the file or reading it.\n For a list of typical error codes, see `open/2`.\n\n- **`{error, {Line, Mod, Term}}`** - An error occurred when interpreting the\n Erlang expressions in the file. To convert the three-element tuple to an\n English description of the error, use `format_error/1`.\n\nThe encoding of `Filename` can be set by a comment, as described in\n[`epp`](`m:epp#encoding`).","title":"file.eval/1","ref":"file.html#eval/1"},{"type":"function","doc":"The same as [`eval/1`](`eval/1`), but the variable bindings `Bindings` are used\nin the evaluation. For information about the variable bindings, see\n`m:erl_eval`.","title":"file.eval/2","ref":"file.html#eval/2"},{"type":"function","doc":"Given the error reason returned by any function in this module, returns a\ndescriptive string of the error in English.","title":"file.format_error/1","ref":"file.html#format_error/1"},{"type":"function","doc":"Returns `{ok, Dir}`, where `Dir` is the current working directory of the file\nserver.\n\n> #### Note {: .info }\n>\n> In rare circumstances, this function can fail on Unix. It can occur if read\n> permission does not exist for the parent directories of the current directory.\n\nA typical error reason:\n\n- **`eacces`** - Missing read permission for one of the parents of the current\n directory.","title":"file.get_cwd/0","ref":"file.html#get_cwd/0"},{"type":"function","doc":"Returns `{ok, Dir}` or `{error, Reason}`, where `Dir` is the current working\ndirectory of the specified drive.\n\n`Drive` is to be of the form `Letter:`, for example, `c:`.\n\nReturns `{error, enotsup}` on platforms that have no concept of current drive\n(Unix, for example).\n\nTypical error reasons:\n\n- **`enotsup`** - The operating system has no concept of drives.\n\n- **`eacces`** - The drive does not exist.\n\n- **`einval`** - The format of `Drive` is invalid.","title":"file.get_cwd/1","ref":"file.html#get_cwd/1"},{"type":"function","doc":"Lists all files in a directory, _except_ files with raw filenames. Returns\n`{ok, Filenames}` if successful, otherwise `{error, Reason}`. `Filenames` is a\nlist of the names of all the files in the directory. The names are not sorted.\n\nTypical error reasons:\n\n- **`eacces`** - Missing search or write permissions for `Dir` or one of its\n parent directories.\n\n- **`enoent`** - The directory does not exist.\n\n- **`{no_translation, Filename}`** - `Filename` is a `t:binary/0` with\n characters coded in ISO Latin-1 and the VM was started with parameter `+fnue`.","title":"file.list_dir/1","ref":"file.html#list_dir/1"},{"type":"function","doc":"[](){: #list_dir_all } Lists all the files in a directory, including files with\nraw filenames. Returns `{ok, Filenames}` if successful, otherwise\n`{error, Reason}`. `Filenames` is a list of the names of all the files in the\ndirectory. The names are not sorted.\n\nTypical error reasons:\n\n- **`eacces`** - Missing search or write permissions for `Dir` or one of its\n parent directories.\n\n- **`enoent`** - The directory does not exist.","title":"file.list_dir_all/1","ref":"file.html#list_dir_all/1"},{"type":"function","doc":"Tries to create directory `Dir`. Missing parent directories are _not_ created.\nReturns `ok` if successful.\n\nTypical error reasons:\n\n- **`eacces`** - Missing search or write permissions for the parent directories\n of `Dir`.\n\n- **`eexist`** - A file or directory named `Dir` exists already.\n\n- **`enoent`** - A component of `Dir` does not exist.\n\n- **`enospc`** - No space is left on the device.\n\n- **`enotdir`** - A component of `Dir` is not a directory. On some platforms,\n `enoent` is returned instead.","title":"file.make_dir/1","ref":"file.html#make_dir/1"},{"type":"function","doc":"Makes a hard link from `Existing` to `New` on platforms supporting links (Unix\nand Windows). This function returns `ok` if the link was successfully created,\notherwise `{error, Reason}`. On platforms not supporting links,\n`{error,enotsup}` is returned.\n\nTypical error reasons:\n\n- **`eacces`** - Missing read or write permissions for the parent directories of\n `Existing` or `New`.\n\n- **`eexist`** - `New` already exists.\n\n- **`enotsup`** - Hard links are not supported on this platform.","title":"file.make_link/2","ref":"file.html#make_link/2"},{"type":"function","doc":"Creates a symbolic link `New` to the file or directory `Existing` on platforms\nsupporting symbolic links (most Unix systems and Windows, beginning with Vista).\n`Existing` does not need to exist. Returns `ok` if the link is successfully\ncreated, otherwise `{error, Reason}`. On platforms not supporting symbolic\nlinks, `{error, enotsup}` is returned.\n\nTypical error reasons:\n\n- **`eacces`** - Missing read or write permissions for the parent directories of\n `Existing` or `New`.\n\n- **`eexist`** - `New` already exists.\n\n- **`enotsup`** - Symbolic links are not supported on this platform.\n\n- **`eperm`** - User does not have privileges to create symbolic links\n (`SeCreateSymbolicLinkPrivilege` on Windows).","title":"file.make_symlink/2","ref":"file.html#make_symlink/2"},{"type":"function","doc":"[](){: #native_name_encoding } Returns the filename encoding mode. If it is\n`latin1`, the system translates no filenames. If it is `utf8`, filenames are\nconverted back and forth to the native filename encoding (usually UTF-8, but\nUTF-16 on Windows).","title":"file.native_name_encoding/0","ref":"file.html#native_name_encoding/0"},{"type":"function","doc":"Opens file `File` in the mode determined by `Modes`, which can contain one or\nmore of the following options:\n\n- **`read`** - The file, which must exist, is opened for reading.\n\n- **`write`** - The file is opened for writing. It is created if it does not\n exist. If the file exists and `write` is not combined with `read`, the file is\n truncated.\n\n- **`append`** - The file is opened for writing. It is created if it does not\n exist. Every write operation to a file opened with `append` takes place at the\n end of the file.\n\n- **`exclusive`** - The file is opened for writing. It is created if it does not\n exist. If the file exists, `{error, eexist}` is returned.\n\n > #### Warning {: .warning }\n >\n > This option does not guarantee exclusiveness on file systems not supporting\n > `O_EXCL` properly, such as NFS. Do not depend on this option unless you know\n > that the file system supports it (in general, local file systems are safe).\n\n- **`raw`** - [](){: #raw } Allows faster access to a file, as no Erlang process\n is needed to handle the file. However, a file opened in this way has the\n following limitations:\n\n - The functions in the `io` module cannot be used, as they can only talk to an\n Erlang process. Instead, use functions `read/2`, `read_line/1`, and\n `write/2`.\n - Especially if [`read_line/1`](`read_line/1`) is to be used on a `raw` file,\n it is recommended to combine this option with option `{read_ahead, Size}` as\n line-oriented I/O is inefficient without buffering.\n - Only the Erlang process that opened the file can use it.\n - A remote Erlang file server cannot be used. The computer on which the Erlang\n node is running must have access to the file system (directly or through\n NFS).\n\n- **`binary`** - Read operations on the file return binaries rather than lists.\n\n- **`{delayed_write, Size, Delay}`** - Data in subsequent [`write/2`](`write/2`)\n calls is buffered until at least `Size` bytes are buffered, or until the\n oldest buffered data is `Delay` milliseconds old. Then all buffered data is\n written in one operating system call. The buffered data is also flushed before\n some other file operation than [`write/2`](`write/2`) is executed.\n\n The purpose of this option is to increase performance by reducing the number\n of operating system calls. Thus, the [`write/2`](`write/2`) calls must be for\n sizes significantly less than `Size`, and not interspersed by too many other\n file operations.\n\n When this option is used, the result of [`write/2`](`write/2`) calls can\n prematurely be reported as successful, and if a write error occurs, the error\n is reported as the result of the next file operation, which is not executed.\n\n For example, when `delayed_write` is used, after a number of\n [`write/2`](`write/2`) calls, [`close/1`](`close/1`) can return\n `{error, enospc}`, as there is not enough space on the disc for previously\n written data. [`close/1`](`close/1`) must probably be called again, as the\n file is still open.\n\n- **`delayed_write`** - The same as `{delayed_write, Size, Delay}` with\n reasonable default values for `Size` and `Delay` (roughly some 64 KB, 2\n seconds).\n\n- **`{read_ahead, Size}`** - Activates read data buffering. If\n [`read/2`](`read/2`) calls are for significantly less than `Size` bytes, read\n operations to the operating system are still performed for blocks of `Size`\n bytes. The extra data is buffered and returned in subsequent\n [`read/2`](`read/2`) calls, giving a performance gain as the number of\n operating system calls is reduced.\n\n The `read_ahead` buffer is also highly used by function\n [`read_line/1`](`read_line/1`) in `raw` mode, therefore this option is\n recommended (for performance reasons) when accessing raw files using that\n function.\n\n If [`read/2`](`read/2`) calls are for sizes not significantly less than, or\n even greater than `Size` bytes, no performance gain can be expected.\n\n- **`read_ahead`** - The same as `{read_ahead, Size}` with a reasonable default\n value for `Size` (roughly some 64 KB).\n\n- **`compressed`** - Makes it possible to read or write gzip compressed files.\n Option `compressed` must be combined with `read` or `write`, but not both.\n Notice that the file size obtained with `read_file_info/1` does probably not\n match the number of bytes that can be read from a compressed file.\n\n- **`compressed_one`** - Read one member of a gzip compressed file. Option\n `compressed_one` can only be combined with `read`.\n\n- **`{encoding, Encoding}`** - Makes the file perform automatic translation of\n characters to and from a specific (Unicode) encoding. Notice that the data\n supplied to `write/2` or returned by `read/2` still is byte-oriented; this\n option denotes only how data is stored in the disk file.\n\n Depending on the encoding, different methods of reading and writing data is\n preferred. The default encoding of `latin1` implies using this module (`file`)\n for reading and writing data as the interfaces provided here work with\n byte-oriented data. Using other (Unicode) encodings makes the `m:io` functions\n `get_chars`, `get_line`, and `put_chars` more suitable, as they can work with\n the full Unicode range.\n\n If data is sent to an `t:io_device/0` in a format that cannot be converted to\n the specified encoding, or if data is read by a function that returns data in\n a format that cannot cope with the character range of the data, an error\n occurs and the file is closed.\n\n Allowed values for `Encoding`:\n\n - **`latin1`** - The default encoding. Bytes supplied to the file, that is,\n `write/2` are written \"as is\" on the file. Likewise, bytes read from the\n file, that is, `read/2` are returned \"as is\". If module `m:io` is used for\n writing, the file can only cope with Unicode characters up to code point 255\n (the ISO Latin-1 range).\n\n - **`unicode or utf8`** - Characters are translated to and from UTF-8 encoding\n before they are written to or read from the file. A file opened in this way\n can be readable using function `read/2`, as long as no data stored on the\n file lies beyond the ISO Latin-1 range (0..255), but failure occurs if the\n data contains Unicode code points beyond that range. The file is best read\n with the functions in the Unicode aware module `m:io`.\n\n Bytes written to the file by any means are translated to UTF-8 encoding\n before being stored on the disk file.\n\n - **`utf16 or {utf16,big}`** - Works like `unicode`, but translation is done\n to and from big endian UTF-16 instead of UTF-8.\n\n - **`{utf16,little}`** - Works like `unicode`, but translation is done to and\n from little endian UTF-16 instead of UTF-8.\n\n - **`utf32 or {utf32,big}`** - Works like `unicode`, but translation is done\n to and from big endian UTF-32 instead of UTF-8.\n\n - **`{utf32,little}`** - Works like `unicode`, but translation is done to and\n from little endian UTF-32 instead of UTF-8.\n\n The Encoding can be changed for a file \"on the fly\" by using function\n `io:setopts/2`. So a file can be analyzed in latin1 encoding for, for example,\n a BOM, positioned beyond the BOM and then be set for the right encoding before\n further reading. For functions identifying BOMs, see module `m:unicode`.\n\n This option is not allowed on `raw` files.\n\n- **`ram`** - `File` must be `t:iodata/0`. Returns an `t:fd/0`, which lets\n module `file` operate on the data in-memory as if it is a file.\n\n- **`sync`** - On platforms supporting it, enables the POSIX `O_SYNC`\n synchronous I/O flag or its platform-dependent equivalent (for example,\n `FILE_FLAG_WRITE_THROUGH` on Windows) so that writes to the file block until\n the data is physically written to disk. However, be aware that the exact\n semantics of this flag differ from platform to platform. For example, none of\n Linux or Windows guarantees that all file metadata are also written before the\n call returns. For precise semantics, check the details of your platform\n documentation. On platforms with no support for POSIX `O_SYNC` or equivalent,\n use of the `sync` flag causes `open` to return `{error, enotsup}`.\n\n- **`directory`** - Allows `open` to work on directories.\n\nReturns:\n\n- **`{ok, IoDevice}`** - The file is opened in the requested mode. `IoDevice` is\n a reference to the file.\n\n- **`{error, Reason}`** - The file cannot be opened.\n\n`IoDevice` is really the pid of the process that handles the file. This process\nmonitors the process that originally opened the file (the owner process). If the\nowner process terminates, the file is closed and the process itself terminates\ntoo. An `IoDevice` returned from this call can be used as an argument to the I/O\nfunctions (see `m:io`).\n\n> #### Warning {: .warning }\n>\n> While this function can be used to open any file, we recommend against using\n> it for NFS-mounted files, FIFOs, devices, or similar since they can cause IO\n> threads to hang forever.\n>\n> If your application needs to interact with these kinds of files we recommend\n> breaking out those parts to a port program instead.\n\n> #### Note {: .info }\n>\n> In previous versions of `file`, modes were specified as one of the atoms\n> `read`, `write`, or `read_write` instead of a list. This is still allowed for\n> reasons of backwards compatibility, but is not to be used for new code. Also\n> note that `read_write` is not allowed in a mode list.\n\nTypical error reasons:\n\n- **`enoent`** - The file does not exist.\n\n- **`eacces`** - Missing permission for reading the file or searching one of the\n parent directories.\n\n- **`eisdir`** - The named file is a directory.\n\n- **`enotdir`** - A component of the filename is not a directory, or the\n filename itself is not a directory if `directory` mode was specified. On some\n platforms, `enoent` is returned instead.\n\n- **`enospc`** - There is no space left on the device (if `write` access was\n specified).","title":"file.open/2","ref":"file.html#open/2"},{"type":"function","doc":"Searches the path `Path` (a list of directory names) until the file `Filename`\nis found. If `Filename` is an absolute filename, `Path` is ignored. Then reads\nErlang terms, separated by `.`, from the file.\n\nReturns one of the following:\n\n- **`{ok, Terms, FullName}`** - The file is successfully read. `FullName` is the\n full name of the file.\n\n- **`{error, enoent}`** - The file cannot be found in any of the directories in\n `Path`.\n\n- **`{error, atom()}`** - An error occurred when opening the file or reading it.\n For a list of typical error codes, see `open/2`.\n\n- **`{error, {Line, Mod, Term}}`** - An error occurred when interpreting the\n Erlang terms in the file. Use `format_error/1` to convert the three-element\n tuple to an English description of the error.\n\nThe encoding of `Filename` can be set by a comment as described in\n[`epp`](`m:epp#encoding`).","title":"file.path_consult/2","ref":"file.html#path_consult/2"},{"type":"function","doc":"Searches the path `Path` (a list of directory names) until the file `Filename`\nis found. If `Filename` is an absolute filename, `Path` is ignored. Then reads\nand evaluates Erlang expressions, separated by `.` (or `,`, a sequence of\nexpressions is also an expression), from the file. The result of evaluation is\nnot returned; any expression sequence in the file must be there for its side\neffect.\n\nReturns one of the following:\n\n- **`{ok, FullName}`** - The file is read and evaluated. `FullName` is the full\n name of the file.\n\n- **`{error, enoent}`** - The file cannot be found in any of the directories in\n `Path`.\n\n- **`{error, atom()}`** - An error occurred when opening the file or reading it.\n For a list of typical error codes, see `open/2`.\n\n- **`{error, {Line, Mod, Term}}`** - An error occurred when interpreting the\n Erlang expressions in the file. Use `format_error/1` to convert the\n three-element tuple to an English description of the error.\n\nThe encoding of `Filename` can be set by a comment as described in\n[`epp`](`m:epp#encoding`).","title":"file.path_eval/2","ref":"file.html#path_eval/2"},{"type":"function","doc":"Searches the path `Path` (a list of directory names) until the file `Filename`\nis found. If `Filename` is an absolute filename, `Path` is ignored. Then opens\nthe file in the mode determined by `Modes`.\n\nReturns one of the following:\n\n- **`{ok, IoDevice, FullName}`** - The file is opened in the requested mode.\n `IoDevice` is a reference to the file and `FullName` is the full name of the\n file.\n\n- **`{error, enoent}`** - The file cannot be found in any of the directories in\n `Path`.\n\n- **`{error, atom()}`** - The file cannot be opened.","title":"file.path_open/3","ref":"file.html#path_open/3"},{"type":"function","doc":"Searches the path `Path` (a list of directory names) until the file `Filename`\nis found. If `Filename` is an absolute filename, `Path` is ignored. Then reads\nand evaluates Erlang expressions, separated by `.` (or `,`, a sequence of\nexpressions is also an expression), from the file.\n\nReturns one of the following:\n\n- **`{ok, Value, FullName}`** - The file is read and evaluated. `FullName` is\n the full name of the file and `Value` the value of the last expression.\n\n- **`{error, enoent}`** - The file cannot be found in any of the directories in\n `Path`.\n\n- **`{error, atom()}`** - An error occurred when opening the file or reading it.\n For a list of typical error codes, see `open/2`.\n\n- **`{error, {Line, Mod, Term}}`** - An error occurred when interpreting the\n Erlang expressions in the file. Use `format_error/1` to convert the\n three-element tuple to an English description of the error.\n\nThe encoding of `Filename` can be set by a comment as described in\n[`epp`](`m:epp#encoding`).","title":"file.path_script/2","ref":"file.html#path_script/2"},{"type":"function","doc":"The same as [`path_script/2`](`path_script/2`) but the variable bindings\n`Bindings` are used in the evaluation. See `m:erl_eval` about variable bindings.","title":"file.path_script/3","ref":"file.html#path_script/3"},{"type":"function","doc":"Sets the position of the file referenced by `IoDevice` to `Location`. Returns\n`{ok, NewPosition}` (as absolute offset) if successful, otherwise\n`{error, Reason}`. `Location` is one of the following:\n\n- **`Offset`** - The same as `{bof, Offset}`.\n\n- **`{bof, Offset}`** - Absolute offset.\n\n- **`{cur, Offset}`** - Offset from the current position.\n\n- **`{eof, Offset}`** - Offset from the end of file.\n\n- **`bof | cur | eof`** - The same as above with `Offset` 0.\n\nNotice that offsets are counted in bytes, not in characters. If the file is\nopened using some other `encoding` than `latin1`, one byte does not correspond\nto one character. Positioning in such a file can only be done to known character\nboundaries. That is, to a position earlier retrieved by getting a current\nposition, to the beginning/end of the file or to some other position _known_ to\nbe on a correct character boundary by some other means (typically beyond a byte\norder mark in the file, which has a known byte-size).\n\nA typical error reason is:\n\n- **`einval`** - Either `Location` is illegal, or it is evaluated to a negative\n offset in the file. Notice that if the resulting position is a negative value,\n the result is an error, and after the call the file position is undefined.","title":"file.position/2","ref":"file.html#position/2"},{"type":"function","doc":"Performs a sequence of [`pread/3`](`pread/3`) in one operation, which is more\nefficient than calling them one at a time. Returns `{ok, [Data, ...]}` or\n`{error, Reason}`, where each `Data`, the result of the corresponding `pread`,\nis either a list or a binary depending on the mode of the file, or `eof` if the\nrequested position is beyond end of file.\n\nAs the position is specified as a byte-offset, take special caution when working\nwith files where `encoding` is set to something else than `latin1`, as not every\nbyte position is a valid character boundary on such a file.","title":"file.pread/2","ref":"file.html#pread/2"},{"type":"function","doc":"Combines [`position/2`](`position/2`) and [`read/2`](`read/2`) in one operation,\nwhich is more efficient than calling them one at a time.\n\n`Location` is only allowed to be an integer for `raw` and `ram` modes.\n\nThe current position of the file after the operation is undefined for `raw` mode\nand unchanged for `ram` mode.\n\nAs the position is specified as a byte-offset, take special caution when working\nwith files where `encoding` is set to something else than `latin1`, as not every\nbyte position is a valid character boundary on such a file.","title":"file.pread/3","ref":"file.html#pread/3"},{"type":"function","doc":"Performs a sequence of [`pwrite/3`](`pwrite/3`) in one operation, which is more\nefficient than calling them one at a time. Returns `ok` or\n`{error, {N, Reason}}`, where `N` is the number of successful writes done before\nthe failure.\n\nWhen positioning in a file with other `encoding` than `latin1`, caution must be\ntaken to set the position on a correct character boundary. For details, see\n`position/2`.","title":"file.pwrite/2","ref":"file.html#pwrite/2"},{"type":"function","doc":"Combines [`position/2`](`position/2`) and [`write/2`](`write/2`) in one\noperation, which is more efficient than calling them one at a time.\n\n`Location` is only allowed to be an integer for `raw` and `ram` modes.\n\nThe current position of the file after the operation is undefined for `raw` mode\nand unchanged for `ram` mode.\n\nWhen positioning in a file with other `encoding` than `latin1`, caution must be\ntaken to set the position on a correct character boundary. For details, see\n`position/2`.","title":"file.pwrite/3","ref":"file.html#pwrite/3"},{"type":"function","doc":"Reads `Number` bytes/characters from the file referenced by `IoDevice`.\n\nThe functions `read/2`, `pread/3`, and `read_line/1` are the only ways to read from\na file opened in `raw` mode (although they work for normally opened files, too).\n\nFor files where `encoding` is set to something else than `latin1`, one character\ncan be represented by more than one byte on the file. The parameter `Number`\nalways denotes the number of _characters_ read from the file, while the position\nin the file can be moved much more than this number when reading a Unicode file.\n\nAlso, if `encoding` is set to something else than `latin1`, the\n[`read/2`](`read/2`) call fails if the data contains characters larger than 255,\nwhich is why `io:get_chars/3` is to be preferred when reading such a file.\n\nThe function returns:\n\n- **`{ok, Data}`** - If the file was opened in binary mode, the read bytes are\n returned in a binary, otherwise in a list. The list or binary is shorter than\n the number of bytes requested if end of file was reached.\n\n- **`eof`** - Returned if `Number>0` and end of file was reached before anything\n at all could be read.\n\n- **`{error, Reason}`** - An error occurred.\n\nTypical error reasons:\n\n- **`ebadf`** - The file is not opened for reading.\n\n- **`{no_translation, unicode, latin1}`** - The file is opened with another\n `encoding` than `latin1` and the data in the file cannot be translated to the\n byte-oriented data that this function returns.","title":"file.read/2","ref":"file.html#read/2"},{"type":"function","doc":"","title":"file.read_file/1","ref":"file.html#read_file/1"},{"type":"function","doc":"Returns `{ok, Binary}`, where `Binary` is a binary data object that contains the\ncontents of `Filename`, or `{error, Reason}` if an error occurs.\n\nIf the option `raw` is set, the file server is not called.\n\nTypical error reasons:\n\n- **`enoent`** - The file does not exist.\n\n- **`eacces`** - Missing permission for reading the file, or for searching one\n of the parent directories.\n\n- **`eisdir`** - The named file is a directory.\n\n- **`enotdir`** - A component of the filename is not a directory. On some\n platforms, `enoent` is returned instead.\n\n- **`enomem`** - There is not enough memory for the contents of the file.","title":"file.read_file/2","ref":"file.html#read_file/2"},{"type":"function","doc":"","title":"file.read_file_info/1","ref":"file.html#read_file_info/1"},{"type":"function","doc":"Retrieves information about a file. Returns `{ok, FileInfo}` if successful,\notherwise `{error, Reason}`.\n\n`FileInfo` is a record `file_info`, defined in the Kernel include file `file.hrl`.\nInclude the following directive in the module from which the function is called:\n\n```erlang\n-include_lib(\"kernel/include/file.hrl\").\n```\n\nThe time type returned in `atime`, `mtime`, and `ctime` is dependent on the time\ntype set in `Opts :: {time, Type}` as follows:\n\n- **`local`** - Returns local time.\n\n- **`universal`** - Returns universal time.\n\n- **`posix`** - Returns seconds since or before Unix time epoch, which is\n 1970-01-01 00:00 UTC.\n\nDefault is `{time, local}`.\n\nIf the option `raw` is set, the file server is not called and only information\nabout local files is returned. Note that this will break this module's atomicity\nguarantees as it can race with a concurrent call to\n[`write_file_info/1,2` ](`write_file_info/2`).\n\nThis option has no effect when the function is given an I/O device instead of a\nfile name. Use `open/2` with the `raw` mode to obtain a file descriptor first.\n\n> #### Note {: .info }\n>\n> As file times are stored in POSIX time on most OS, it is faster to query file\n> information with option `posix`.\n\nThe record `file_info` contains the following fields:\n\n- **`size = ` `t:non_neg_integer/0`** - Size of file in bytes.\n\n- **`type = device | directory | other | regular`** - The type of the file. Can\n also contain `symlink` when returned from\n [read_link_info/1,2](`read_link_info/1`).\n\n- **`access = read | write | read_write | none`** - The current system access to\n the file.\n\n- **`atime = ` `t:date_time/0` ` | ` `t:non_neg_integer/0`** - The last time the file was\n read.\n\n- **`mtime = ` `t:date_time/0` ` | ` `t:non_neg_integer/0`** - The last time the file was\n written.\n\n- **`ctime = ` `t:date_time/0` ` | ` `t:non_neg_integer/0`** - The interpretation of this\n time field depends on the operating system. On Unix, it is the last time the\n file or the `inode` was changed. In Windows, it is the create time.\n\n- **`mode = ` `t:non_neg_integer/0`** - The file permissions as the sum of the following\n bit values:\n\n - **`8#00400`** - read permission: owner\n\n - **`8#00200`** - write permission: owner\n\n - **`8#00100`** - execute permission: owner\n\n - **`8#00040`** - read permission: group\n\n - **`8#00020`** - write permission: group\n\n - **`8#00010`** - execute permission: group\n\n - **`8#00004`** - read permission: other\n\n - **`8#00002`** - write permission: other\n\n - **`8#00001`** - execute permission: other\n\n - **`16#800`** - set user id on execution\n\n - **`16#400`** - set group id on execution\n\n On Unix platforms, other bits than those listed above may be set.\n\n- **`links = ` `t:non_neg_integer/0`** - Number of links to the file (this is always 1\n for file systems that have no concept of links).\n\n- **`major_device = ` `t:non_neg_integer/0`** - Identifies the file system where the\n file is located. In Windows, the number indicates a drive as follows: 0 means\n A:, 1 means B:, and so on.\n\n- **`minor_device = ` `t:non_neg_integer/0`** - Only valid for character devices on\n Unix. In all other cases, this field is zero.\n\n- **`inode = ` `t:non_neg_integer/0`** - Gives the `inode` number. On non-Unix file\n systems, this field is zero.\n\n- **`uid = ` `t:non_neg_integer/0`** - Indicates the owner of the file. On non-Unix file\n systems, this field is zero.\n\n- **`gid = ` `t:non_neg_integer/0`** - Gives the group that the owner of the file\n belongs to. On non-Unix file systems, this field is zero.\n\nTypical error reasons:\n\n- **`eacces`** - Missing search permission for one of the parent directories of\n the file.\n\n- **`enoent`** - The file does not exist.\n\n- **`enotdir`** - A component of the filename is not a directory. On some\n platforms, `enoent` is returned instead.","title":"file.read_file_info/2","ref":"file.html#read_file_info/2"},{"type":"function","doc":"Reads a line of bytes/characters from the file referenced by `IoDevice`.\n\nLines are defined to be delimited by the linefeed (LF, `\\n`) character, but any\ncarriage return (CR, `\\r`) followed by a newline is also treated as a single LF\ncharacter (the carriage return is silently ignored). The line is returned\n_including_ the LF, but excluding any CR immediately followed by an LF. This\nbehaviour is consistent with the behaviour of `io:get_line/2`. If end of file is\nreached without any LF ending the last line, a line with no trailing LF is\nreturned.\n\nThe function can be used on files opened in `raw` mode. However, it is\ninefficient to use it on `raw` files if the file is not opened with option\n`{read_ahead, Size}` specified. Thus, combining `raw` and `{read_ahead, Size}`\nis highly recommended when opening a text file for raw line-oriented reading.\n\nIf `encoding` is set to something else than `latin1`, the\n[`read_line/1`](`read_line/1`) call fails if the data contains characters larger\nthan 255, why `io:get_line/2` is to be preferred when reading such a file.\n\nThe function returns:\n\n- **`{ok, Data}`** - One line from the file is returned, including the trailing\n LF, but with CRLF sequences replaced by a single LF (see above).\n\n If the file is opened in binary mode, the read bytes are returned in a binary,\n otherwise in a list.\n\n- **`eof`** - Returned if end of file was reached before anything at all could\n be read.\n\n- **`{error, Reason}`** - An error occurred.\n\nTypical error reasons:\n\n- **`ebadf`** - The file is not opened for reading.\n\n- **`{no_translation, unicode, latin1}`** - The file is opened with another\n `encoding` than `latin1` and the data on the file cannot be translated to the\n byte-oriented data that this function returns.","title":"file.read_line/1","ref":"file.html#read_line/1"},{"type":"function","doc":"[](){: #read_link_all } Returns `{ok, Filename}` if `Name` refers to a symbolic\nlink that is not a raw filename, or `{error, Reason}` otherwise. On platforms\nthat do not support symbolic links, the return value is `{error,enotsup}`.\n\nTypical error reasons:\n\n- **`einval`** - `Name` does not refer to a symbolic link or the name of the\n file that it refers to does not conform to the expected encoding.\n\n- **`enoent`** - The file does not exist.\n\n- **`enotsup`** - Symbolic links are not supported on this platform.","title":"file.read_link/1","ref":"file.html#read_link/1"},{"type":"function","doc":"Returns `{ok, Filename}` if `Name` refers to a symbolic link or\n`{error, Reason}` otherwise. On platforms that do not support symbolic links,\nthe return value is `{error,enotsup}`.\n\nNotice that `Filename` can be either a list or a binary.\n\nTypical error reasons:\n\n- **`einval`** - `Name` does not refer to a symbolic link.\n\n- **`enoent`** - The file does not exist.\n\n- **`enotsup`** - Symbolic links are not supported on this platform.","title":"file.read_link_all/1","ref":"file.html#read_link_all/1"},{"type":"function","doc":"","title":"file.read_link_info/1","ref":"file.html#read_link_info/1"},{"type":"function","doc":"Works like [`read_file_info/1,2`](`read_file_info/2`) except that if `Name` is a\nsymbolic link, information about the link is returned in the `file_info` record\nand the `type` field of the record is set to `symlink`.\n\nIf the option `raw` is set, the file server is not called and only information\nabout local files is returned. Note that this will break this module's atomicity\nguarantees as it can race with a concurrent call to\n[`write_file_info/1,2`](`write_file_info/2`)\n\nIf `Name` is not a symbolic link, this function returns the same result as\n[`read_file_info/1`](`read_file_info/1`). On platforms that do not support\nsymbolic links, this function is always equivalent to\n[`read_file_info/1`](`read_file_info/1`).","title":"file.read_link_info/2","ref":"file.html#read_link_info/2"},{"type":"function","doc":"Tries to rename the file `Source` to `Destination`. It can be used to move files\n(and directories) between directories, but it is not sufficient to specify the\ndestination only. The destination filename must also be specified. For example,\nif `bar` is a normal file and `foo` and `baz` are directories,\n[`rename(\"foo/bar\", \"baz\")`](`rename/2`) returns an error, but\n[`rename(\"foo/bar\", \"baz/bar\")`](`rename/2`) succeeds. Returns `ok` if it is\nsuccessful.\n\n> #### Note {: .info }\n>\n> Renaming of open files is not allowed on most platforms (see `eacces` below).\n\nTypical error reasons:\n\n- **`eacces`** - Missing read or write permissions for the parent directories of\n `Source` or `Destination`. On some platforms, this error is given if either\n `Source` or `Destination` is open.\n\n- **`eexist`** - `Destination` is not an empty directory. On some platforms,\n also given when `Source` and `Destination` are not of the same type.\n\n- **`einval`** - `Source` is a root directory, or `Destination` is a\n subdirectory of `Source`.\n\n- **`eisdir`** - `Destination` is a directory, but `Source` is not.\n\n- **`enoent`** - `Source` does not exist.\n\n- **`enotdir`** - `Source` is a directory, but `Destination` is not.\n\n- **`exdev`** - `Source` and `Destination` are on different file systems.","title":"file.rename/2","ref":"file.html#rename/2"},{"type":"function","doc":"Reads and evaluates Erlang expressions, separated by `.` (or `,`, a sequence of\nexpressions is also an expression), from the file.\n\nReturns one of the following:\n\n- **`{ok, Value}`** - The file is read and evaluated. `Value` is the value of\n the last expression.\n\n- **`{error, atom()}`** - An error occurred when opening the file or reading it.\n For a list of typical error codes, see `open/2`.\n\n- **`{error, {Line, Mod, Term}}`** - An error occurred when interpreting the\n Erlang expressions in the file. Use `format_error/1` to convert the\n three-element tuple to an English description of the error.\n\nThe encoding of `Filename` can be set by a comment as described in\n[`epp`](`m:epp#encoding`).","title":"file.script/1","ref":"file.html#script/1"},{"type":"function","doc":"The same as [`script/1`](`script/1`) but the variable bindings `Bindings` are\nused in the evaluation. See `m:erl_eval` about variable bindings.","title":"file.script/2","ref":"file.html#script/2"},{"type":"function","doc":"Sends the file `Filename` to `Socket`. Returns `{ok, BytesSent}` if successful,\notherwise `{error, Reason}`.","title":"file.sendfile/2","ref":"file.html#sendfile/2"},{"type":"function","doc":"Sends `Bytes` from the file referenced by `RawFile` beginning at `Offset` to\n`Socket`. Returns `{ok, BytesSent}` if successful, otherwise `{error, Reason}`.\nIf `Bytes` is set to `0` all data after the specified `Offset` is sent.\n\nThe file used must be opened using the `raw` flag, and the process calling\n`sendfile` must be the controlling process of the socket. See\n`gen_tcp:controlling_process/2` or module [`socket`'s](`socket:setopt/3`)\n[level `otp` socket option ](`t:socket:otp_socket_option/0`)`controlling_process`.\n\nIf the OS used does not support non-blocking `sendfile`, an Erlang fallback\nusing `read/2` and `gen_tcp:send/2` is used.\n\nThe option list can contain the following options:\n\n- **`chunk_size`** - The chunk size used by the Erlang fallback to send data. If\n using the fallback, set this to a value that comfortably fits in the systems\n memory. Default is 20 MB.","title":"file.sendfile/5","ref":"file.html#sendfile/5"},{"type":"function","doc":"Sets the current working directory of the file server to `Dir`. Returns `ok` if\nsuccessful.\n\nThe functions in the module `file` usually treat binaries as raw filenames, that\nis, they are passed \"as is\" even when the encoding of the binary does not agree\nwith [`native_name_encoding()`](`native_name_encoding/0`). However, this\nfunction expects binaries to be encoded according to the value returned by\n`native_name_encoding/0`.\n\nTypical error reasons are:\n\n- **`enoent`** - The directory does not exist.\n\n- **`enotdir`** - A component of `Dir` is not a directory. On some platforms,\n `enoent` is returned.\n\n- **`eacces`** - Missing permission for the directory or one of its parents.\n\n- **`badarg`** - `Dir` has an improper type, such as tuple.\n\n- **`no_translation`** - `Dir` is a `t:binary/0` with characters coded in\n ISO-latin-1 and the VM is operating with unicode filename encoding.\n\n> #### Warning {: .warning }\n>\n> In a future release, a bad type for argument `Dir` will probably generate an\n> exception.","title":"file.set_cwd/1","ref":"file.html#set_cwd/1"},{"type":"function","doc":"Ensures that any buffers kept by the operating system (not by the Erlang runtime\nsystem) are written to disk. On some platforms, this function might have no\neffect.\n\nA typical error reason is:\n\n- **`enospc`** - Not enough space left to write the file.","title":"file.sync/1","ref":"file.html#sync/1"},{"type":"function","doc":"Truncates the file referenced by `IoDevice` at the current position. Returns\n`ok` if successful, otherwise `{error, Reason}`.","title":"file.truncate/1","ref":"file.html#truncate/1"},{"type":"function","doc":"Writes `Bytes` to the file referenced by `IoDevice`. This function is the only\nway to write to a file opened in `raw` mode (although it works for normally\nopened files too). Returns `ok` if successful, and `{error, Reason}` otherwise.\n\nIf the file is opened with `encoding` set to something else than `latin1`, each\nbyte written can result in many bytes being written to the file, as the byte\nrange 0..255 can represent anything between one and four bytes depending on\nvalue and UTF encoding type. If you want to write `t:unicode:chardata/0` to the\n`IoDevice` you should use `io:put_chars/2` instead.\n\nTypical error reasons:\n\n- **`ebadf`** - The file is not opened for writing.\n\n- **`enospc`** - No space is left on the device.","title":"file.write/2","ref":"file.html#write/2"},{"type":"function","doc":"Writes the contents of the `iodata` term `Bytes` to file `Filename`. The file is\ncreated if it does not exist. If it exists, the previous contents are\noverwritten. Returns `ok` if successful, otherwise `{error, Reason}`.\n\nTypical error reasons:\n\n- **`enoent`** - A component of the filename does not exist.\n\n- **`enotdir`** - A component of the filename is not a directory. On some\n platforms, `enoent` is returned instead.\n\n- **`enospc`** - No space is left on the device.\n\n- **`eacces`** - Missing permission for writing the file or searching one of the\n parent directories.\n\n- **`eisdir`** - The named file is a directory.","title":"file.write_file/2","ref":"file.html#write_file/2"},{"type":"function","doc":"Same as [`write_file/2`](`write_file/2`), but takes a third argument `Modes`, a\nlist of possible modes, see `open/2`. The mode flags `binary` and `write` are\nimplicit, so they are not to be used.","title":"file.write_file/3","ref":"file.html#write_file/3"},{"type":"function","doc":"","title":"file.write_file_info/2","ref":"file.html#write_file_info/2"},{"type":"function","doc":"Changes file information. Returns `ok` if successful, otherwise\n`{error, Reason}`.\n\n`FileInfo` is a record `file_info`, defined in the Kernel\ninclude file `file.hrl`. Include the following directive in the module from\nwhich the function is called:\n\n```erlang\n-include_lib(\"kernel/include/file.hrl\").\n```\n\nThe time type set in `atime`, `mtime`, and `ctime` depends on the time type set\nin `Opts :: {time, Type}` as follows:\n\n- **`local`** - Interprets the time set as local.\n\n- **`universal`** - Interprets it as universal time.\n\n- **`posix`** - Must be seconds since or before Unix time epoch, which is\n 1970-01-01 00:00 UTC.\n\nDefault is `{time, local}`.\n\nIf the option `raw` is set, the file server is not called and only information\nabout local files is returned.\n\nThe following fields are used from the record, if they are specified:\n\n- **`atime = ` `t:date_time/0` ` | ` `t:non_neg_integer/0`** - The last time the file was\n read.\n\n- **`mtime = ` `t:date_time/0` ` | ` `t:non_neg_integer/0`** - The last time the file was\n written.\n\n- **`ctime = ` `t:date_time/0` ` | ` `t:non_neg_integer/0`** - On Unix, any value\n specified for this field is ignored (the \"ctime\" for the file is set to the\n current time). On Windows, this field is the new creation time to set for the\n file.\n\n- **`mode = ` `t:non_neg_integer/0`** - The file permissions as the sum of the following\n bit values:\n\n - **`8#00400`** - Read permission: owner\n\n - **`8#00200`** - Write permission: owner\n\n - **`8#00100`** - Execute permission: owner\n\n - **`8#00040`** - Read permission: group\n\n - **`8#00020`** - Write permission: group\n\n - **`8#00010`** - Execute permission: group\n\n - **`8#00004`** - Read permission: other\n\n - **`8#00002`** - Write permission: other\n\n - **`8#00001`** - Execute permission: other\n\n - **`16#800`** - Set user id on execution\n\n - **`16#400`** - Set group id on execution\n\n On Unix platforms, other bits than those listed above may be set.\n\n- **`uid = ` `t:non_neg_integer/0`** - Indicates the file owner. Ignored for non-Unix\n file systems.\n\n- **`gid = ` `t:non_neg_integer/0`** - Gives the group that the file owner belongs to.\n Ignored for non-Unix file systems.\n\nTypical error reasons:\n\n- **`eacces`** - Missing search permission for one of the parent directories of\n the file.\n\n- **`enoent`** - The file does not exist.\n\n- **`enotdir`** - A component of the filename is not a directory. On some\n platforms, `enoent` is returned instead.","title":"file.write_file_info/3","ref":"file.html#write_file_info/3"},{"type":"type","doc":"Must denote a valid date and time.","title":"file.date_time/0","ref":"file.html#t:date_time/0"},{"type":"type","doc":"","title":"file.deep_list/0","ref":"file.html#t:deep_list/0"},{"type":"type","doc":"","title":"file.delete_option/0","ref":"file.html#t:delete_option/0"},{"type":"type","doc":"A file descriptor representing a file opened in [`raw`](`m:file#raw`) mode.","title":"file.fd/0","ref":"file.html#t:fd/0"},{"type":"type","doc":"","title":"file.file_info/0","ref":"file.html#t:file_info/0"},{"type":"type","doc":"","title":"file.file_info_option/0","ref":"file.html#t:file_info_option/0"},{"type":"type","doc":"A file name as returned from `m:file` API functions.\n\nSee the documentation of the `t:name_all/0` type.","title":"file.filename/0","ref":"file.html#t:filename/0"},{"type":"type","doc":"A file name as returned from `m:file` API functions.\n\nSee the documentation of the `t:name_all/0` type.","title":"file.filename_all/0","ref":"file.html#t:filename_all/0"},{"type":"type","doc":"An IO device as returned by `open/2`.\n\n`t:io_server/0` is returned by default and `t:fd/0` is returned if the `raw` option is given.","title":"file.io_device/0","ref":"file.html#t:io_device/0"},{"type":"type","doc":"A process handling the I/O protocol.","title":"file.io_server/0","ref":"file.html#t:io_server/0"},{"type":"type","doc":"","title":"file.location/0","ref":"file.html#t:location/0"},{"type":"type","doc":"","title":"file.mode/0","ref":"file.html#t:mode/0"},{"type":"type","doc":"A restricted file name used as input into `m:file` API functions.\n\nIf VM is in Unicode filename mode, `t:string/0` and `t:char/0` are allowed to\nbe > 255. See also the documentation of the `t:name_all/0` type.","title":"file.name/0","ref":"file.html#t:name/0"},{"type":"type","doc":"A file name used as input into `m:file` API functions.\n\nIf VM is in Unicode filename mode, characters are allowed to be > 255.\n`RawFilename` is a filename not subject to Unicode translation, meaning that it\ncan contain characters not conforming to the Unicode encoding expected from the\nfile system (that is, non-UTF-8 characters although the VM is started in Unicode\nfilename mode). Null characters (integer value zero) are _not_ allowed in\nfilenames (not even at the end).","title":"file.name_all/0","ref":"file.html#t:name_all/0"},{"type":"type","doc":"An atom that is named from the POSIX error codes used in Unix, and in the\nruntime libraries of most C compilers.","title":"file.posix/0","ref":"file.html#t:posix/0"},{"type":"type","doc":"","title":"file.posix_file_advise/0","ref":"file.html#t:posix_file_advise/0"},{"type":"type","doc":"","title":"file.read_file_option/0","ref":"file.html#t:read_file_option/0"},{"type":"type","doc":"","title":"file.sendfile_option/0","ref":"file.html#t:sendfile_option/0"},{"type":"module","doc":"Interface to SCTP sockets.\n\nThis module provides functions for communicating over SCTP sockets.\nThe implementation assumes that the OS kernel supports SCTP\n[(RFC 2960)](http://www.rfc-archive.org/getrfc.php?rfc=2960)\nthrough the user-level\n[Sockets API Extensions](http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13).\n\nDuring development, this implementation was tested on:\n\n- Linux Fedora Core 5.0 (kernel 2.6.15-2054 or later is needed)\n- Solaris 10, 11\n\nDuring OTP adaptation it was tested on:\n\n- SUSE Linux Enterprise Server 10 (x86_64) kernel 2.6.16.27-0.6-smp, with\n lksctp-tools-1.0.6\n- Briefly on Solaris 10\n- SUSE Linux Enterprise Server 10 Service Pack 1 (x86_64) kernel\n 2.6.16.54-0.2.3-smp with lksctp-tools-1.0.7\n- FreeBSD 8.2\n\nThis module was written for one-to-many style sockets (type `seqpacket`).\nWith the addition of `peeloff/2`, one-to-one style sockets (type `stream`)\nwere introduced.\n\nRecord definitions for this module can be found using:\n\n```erlang\n-include_lib(\"kernel/include/inet_sctp.hrl\").\n```\n\nThese record definitions use the \"new\" spelling 'adaptation',\nnot the deprecated 'adaption', regardless of which spelling\nthe underlying C API uses.\n\n[](){: #options } SCTP Socket Options\n-------------------------------------\n\nThe set of admissible SCTP socket options is by construction orthogonal\nto the sets of TCP, UDP, and generic `inet` options. Here are only\noptions listed that are allowed for SCTP sockets.\n\nOptions can be set on the socket when calling [`open/1,2`](`open/1`),\nand changed when calling [`connect/4,5`](`connect/4`) or\nby calling `inet:setopts/2`. They can be retrieved using `inet:getopts/2`.\n\n- **`{mode, list|binary} | list | binary`** [](){: #option-binary } [](){: #option-list } -\n Determines the type of data returned from [`recv/1,2`](`recv/1`)\n or in _active mode_ data messages.\n\n- **`{active, false|true|once|N}`** [](){: #option-active }\n\n - If `false` (_passive mode_, the default), the caller must do an explicit\n [`recv`](`recv/1`) call to retrieve the available data from the socket.\n\n - If `true|once|N` (_active modes_) received data or events are sent\n to the owning process. See [`open/0..2`](`open/0`) for the message format.\n\n - If `true` (fully _active mode_) there is no flow control.\n\n > #### Note {: .info }\n >\n > Note that this can cause the message queue to overflow\n > causing for example the virtual machine to run out of memory and crash.\n\n - If `once`, only one message is automatically placed in the message queue,\n and the mode resets to passive. This provides flow control\n and the possibility for the receiver to listen for incoming\n SCTP data interleaved with other inter-process messages.\n\n - If `active` is specified as an integer `N` in the range -32768 to 32767\n (inclusive), that number is added to the socket's data messages counter.\n If the result of the addition is negative, the counter is set to `0`.\n Once the counter reaches `0`, either through the delivery of messages\n or by being explicitly set with `inet:setopts/2`, the socket mode\n resets to passive (`{active, false}`). When a socket in `{active, N}`\n mode transitions to passive mode, the message `{sctp_passive, Socket}`\n is sent to the controlling process to notify that if it wants to receive\n more data messages from the socket, it must call `inet:setopts/2`\n to set the socket back into an active mode.\n\n- **`{tos, integer()}`** - Sets the Type-Of-Service field on the IP datagrams\n that are sent, to the specified value. This effectively determines a\n prioritization policy for the outbound packets. The acceptable values are\n system-dependent.\n\n- **`{priority, integer()}`** - A protocol-independent equivalent of `tos`\n above. Setting priority implies setting `tos` as well.\n\n- **`{dontroute, true|false}`** - Defaults to `false`.\n If `true`, the kernel does not send packets through any gateway,\n but only sends them to directly connected hosts.\n\n- **`{reuseaddr, true|false}`** - Defaults to `false`.\n If `true`, the local binding address `{IP,Port}` of the socket can be\n reused immediately. No waiting in state `CLOSE_WAIT` is performed\n (can be required for some types of servers).\n\n- **`{sndbuf, integer()}`** - The size, in bytes, of the OS kernel send buffer\n for this socket. Sending errors would occur for datagrams larger than\n `val(sndbuf)`. Setting this option also adjusts the size of\n the driver buffer (see `buffer` above).\n\n- **`{recbuf, integer()}`** - The size, in bytes, of the OS kernel receive\n buffer for this socket. Sending errors would occur for datagrams\n larger than `val(recbuf)`. Setting this option also adjusts the size\n of the driver buffer (see `buffer` above).\n\n### [](){: #option_non_block_send }\n\n- **`{non_block_send, boolean()}`** - A send call that would otherwise block (hang),\n will instead immediately return with e.g. `{error, eagain}`\n *if* this option has been set to `true`.\n Defaults to `false`.\n\n- **`{sctp_module, module()}`** - Overrides which callback module is used.\nDefaults to `inet_sctp` for IPv4 and `inet6_sctp` for IPv6.\n\n- **`{sctp_rtoinfo, #sctp_rtoinfo{}}`**\n\n ```erlang\n #sctp_rtoinfo{\n assoc_id = assoc_id(),\n initial = integer(),\n max = integer(),\n min = integer()\n }\n ```\n\n Determines retransmission time-out parameters, in milliseconds, for the\n association(s) specified by `assoc_id`.\n\n `assoc_id = 0` (default) indicates the whole endpoint. See\n [RFC 2960](http://www.rfc-archive.org/getrfc.php?rfc=2960) and\n [Sockets API Extensions for SCTP](http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13)\n for the exact semantics of the field values.\n\n- **`{sctp_associnfo, #sctp_assocparams{}}`**\n\n ```erlang\n #sctp_assocparams{\n assoc_id = assoc_id(),\n asocmaxrxt = integer(),\n number_peer_destinations = integer(),\n peer_rwnd = integer(),\n local_rwnd = integer(),\n cookie_life = integer()\n }\n ```\n\n Determines association parameters for the association(s) specified by\n `assoc_id`.\n\n `assoc_id = 0` (default) indicates the whole endpoint. See\n [Sockets API Extensions for SCTP](http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13)\n for the discussion of their semantics. Rarely used.\n\n- **`{sctp_initmsg, #sctp_initmsg{}}`**\n\n ```erlang\n #sctp_initmsg{\n num_ostreams = integer(),\n max_instreams = integer(),\n max_attempts = integer(),\n max_init_timeo = integer()\n }\n ```\n\n Determines the default parameters that this socket tries to negotiate\n with its peer while establishing an association with it. Is to be set after\n [`open/*`](`open/1`) but before the first [`connect/*`](`connect/4`).\n `#sctp_initmsg{}` can also be used as ancillary data with the first call of\n [`send/*`](`send/3`) to a new peer (when a new association is created).\n\n - **`num_ostreams`** - Number of outbound streams\n\n - **`max_instreams`** - Maximum number of inbound streams\n\n - **`max_attempts`** - Maximum retransmissions while establishing an\n association\n\n - **`max_init_timeo`** - Time-out, in milliseconds, for establishing an\n association\n\n- **`{sctp_autoclose, integer() >= 0}`** - Determines the time, in seconds,\n after which an idle association is automatically closed. `0` means that the\n association is never automatically closed.\n\n- **`{sctp_nodelay, true|false}`** - Turns on|off the Nagle algorithm for\n merging small packets into larger ones. This improves throughput at the\n expense of latency.\n\n- **`{sctp_disable_fragments, true|false}`** - If `true`, induces an error on an\n attempt to send a message larger than the current PMTU size (which would\n require fragmentation/reassembling). Notice that message fragmentation does\n not affect the logical atomicity of its delivery; this option is provided for\n performance reasons only.\n\n- **`{sctp_i_want_mapped_v4_addr, true|false}`** - Turns on|off automatic\n mapping of IPv4 addresses into IPv6 ones (if the socket address family is\n `AF_INET6`).\n\n- **`{sctp_maxseg, integer()}`** - Determines the maximum chunk size if message\n fragmentation is used. If `0`, the chunk size is limited by the Path MTU only.\n\n- **`{sctp_primary_addr, #sctp_prim{}}`**\n\n ```erlang\n #sctp_prim{\n assoc_id = assoc_id(),\n addr = {IP, Port}\n }\n IP = ip_address()\n Port = port_number()\n ```\n\n For the association specified by `assoc_id`, `{IP,Port}` must be one of the\n peer addresses. This option determines that the specified address is treated\n by the local SCTP stack as the primary address of the peer.\n\n- **`{sctp_set_peer_primary_addr, #sctp_setpeerprim{}}`**\n\n ```erlang\n #sctp_setpeerprim{\n assoc_id = assoc_id(),\n addr = {IP, Port}\n }\n IP = ip_address()\n Port = port_number()\n ```\n\n When set, informs the peer to use `{IP, Port}` as the primary address of the\n local endpoint for the association specified by `assoc_id`.\n\n\n- **`{sctp_adaptation_layer, #sctp_setadaptation{}}`** [](){: #option-sctp_adaptation_layer }\n\n ```erlang\n #sctp_setadaptation{\n adaptation_ind = integer()\n }\n ```\n\n When set, requests that the local endpoint uses the value specified by\n `adaptation_ind` as the Adaptation Indication parameter for establishing\n new associations. For details, see\n [RFC 2960](http://www.rfc-archive.org/getrfc.php?rfc=2960) and\n [Sockets API Extensions for SCTP](http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13).\n\n- **`{sctp_peer_addr_params, #sctp_paddrparams{}}`**\n\n ```erlang\n #sctp_paddrparams{\n assoc_id = assoc_id(),\n address = {IP, Port},\n hbinterval = integer(),\n pathmaxrxt = integer(),\n pathmtu = integer(),\n sackdelay = integer(),\n flags = list()\n }\n IP = ip_address()\n Port = port_number()\n ```\n\n Determines various per-address parameters for the association specified by\n `assoc_id` and the peer address `address` (the SCTP protocol supports\n multi-homing, so more than one address can correspond to a specified\n association).\n\n - **`hbinterval`** - Heartbeat interval, in milliseconds\n\n - **`pathmaxrxt`** - Maximum number of retransmissions before this address is\n considered unreachable (and an alternative address is selected)\n\n - **`pathmtu`** - Fixed Path MTU, if automatic discovery is disabled (see\n `flags` below)\n\n - **`sackdelay`** - Delay, in milliseconds, for SAC messages (if the delay is\n enabled, see `flags` below)\n\n - **`flags`** - The following flags are available:\n\n - **`hb_enable`** - Enables heartbeat\n\n - **`hb_disable`** - Disables heartbeat\n\n - **`hb_demand`** - Initiates heartbeat immediately\n\n - **`pmtud_enable`** - Enables automatic Path MTU discovery\n\n - **`pmtud_disable`** - Disables automatic Path MTU discovery\n\n - **`sackdelay_enable`** - Enables SAC delay\n\n - **`sackdelay_disable`** - Disables SAC delay\n\n- **`{sctp_default_send_param, #sctp_sndrcvinfo{}}`**\n\n [](){: #record-sctp_sndrcvinfo }\n ```erlang\n #sctp_sndrcvinfo{\n stream = integer(),\n ssn = integer(),\n flags = list(),\n ppid = integer(),\n context = integer(),\n timetolive = integer(),\n tsn = integer(),\n cumtsn = integer(),\n assoc_id = assoc_id()\n }\n ```\n\n `#sctp_sndrcvinfo{}` is used both in this socket option, and as\n ancillary data while sending or receiving SCTP messages. When set\n as an option, it provides default values for subsequent\n [`send`](`send/3`) calls on the association specified by `assoc_id`.\n\n `assoc_id = 0` (default) indicates the whole endpoint.\n\n The following fields typically must be specified by the sender:\n\n - **`sinfo_stream`** - Stream number (0-base) within the association to send\n the messages through;\n\n - **`sinfo_flags`** - The following flags are recognised:\n\n - **`unordered`** - The message is to be sent unordered\n\n - **`addr_over`** - The address specified in [`send`](`send/3`) overwrites\n the primary peer address\n\n - **`abort`** - Aborts the current association without flushing any unsent\n data\n\n - **`eof`** - Gracefully shuts down the current association, with flushing\n of unsent data\n\n Other fields are rarely used. For complete information, see\n [RFC 2960](http://www.rfc-archive.org/getrfc.php?rfc=2960) and\n [Sockets API Extensions for SCTP](http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13).\n\n- **`{sctp_events, #sctp_event_subscribe{}}`** [](){: #option-sctp_events }\n\n ```erlang\n #sctp_event_subscribe{\n data_io_event = true | false,\n association_event = true | false,\n address_event = true | false,\n send_failure_event = true | false,\n peer_error_event = true | false,\n shutdown_event = true | false,\n partial_delivery_event = true | false,\n adaptation_layer_event = true | false\n }\n ```\n\n This option determines which [SCTP Events](#sctp-events) that are to be\n received (through [`recv/*`](`recv/1`)) along with the data. The only\n exception is `data_io_event`, which enables or disables receiving of\n [`#sctp_sndrcvinfo{}`](#record-sctp_sndrcvinfo) ancillary data,\n not events. By default, all flags except `adaptation_layer_event` are enabled,\n although `sctp_data_io_event` and `association_event` are used by the driver\n itself and not exported to the user level.\n\n- **`{sctp_delayed_ack_time, #sctp_assoc_value{}}`**\n\n ```erlang\n #sctp_assoc_value{\n assoc_id = assoc_id(),\n assoc_value = integer()\n }\n ```\n\n Rarely used. Determines the ACK time (specified by `assoc_value`, in\n milliseconds) for the specified association or the whole endpoint if\n `assoc_value = 0` (default).\n\n- **`{sctp_status, #sctp_status{}}`**\n\n ```erlang\n #sctp_status{\n assoc_id = assoc_id(),\n state = atom(),\n rwnd = integer(),\n unackdata = integer(),\n penddata = integer(),\n instrms = integer(),\n outstrms = integer(),\n fragmentation_point = integer(),\n primary = #sctp_paddrinfo{}\n }\n ```\n\n This option is read-only. It determines the status of the SCTP association\n specified by `assoc_id`. The following are the possible values of `state`\n (the state designations are mostly self-explanatory):\n\n - **`sctp_state_empty`** - Default. Means that no other state is active.\n\n - **`sctp_state_closed`**\n\n - **`sctp_state_cookie_wait`**\n\n - **`sctp_state_cookie_echoed`**\n\n - **`sctp_state_established`**\n\n - **`sctp_state_shutdown_pending`**\n\n - **`sctp_state_shutdown_sent`**\n\n - **`sctp_state_shutdown_received`**\n\n - **`sctp_state_shutdown_ack_sent`**\n\n Semantics of the other fields:\n\n - **`sstat_rwnd`** - Current receiver window size of the association\n\n - **`sstat_unackdata`** - Number of unacked data chunks\n\n - **`sstat_penddata`** - Number of data chunks pending receipt\n\n - **`sstat_instrms`** - Number of inbound streams\n\n - **`sstat_outstrms`** - Number of outbound streams\n\n - **`sstat_fragmentation_point`** - Message size at which SCTP fragmentation\n occurs\n\n - **`sstat_primary`** - Information on the current primary peer address (see\n below for the format of `#sctp_paddrinfo{}`)\n\n\n- **`{sctp_get_peer_addr_info, #sctp_paddrinfo{}}`** [](){: #option-sctp_get_peer_addr_info }\n\n ```erlang\n #sctp_paddrinfo{\n assoc_id = assoc_id(),\n address = {IP, Port},\n state = inactive | active | unconfirmed,\n cwnd = integer(),\n srtt = integer(),\n rto = integer(),\n mtu = integer()\n }\n IP = ip_address()\n Port = port_number()\n ```\n\n This option is read-only. It determines the parameters specific to\n the peer address specified by `address` within the association specified\n by `assoc_id`. Field `address` fmust be set by the caller; all other fields\n are filled in on return. If `assoc_id = 0` (default), the `address`\n is automatically translated into the corresponding association ID.\n This option is rarely used. For the semantics of all fields, see\n [RFC 2960](http://www.rfc-archive.org/getrfc.php?rfc=2960) and\n [Sockets API Extensions for SCTP](http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13).\n\n[](){: #examples } SCTP Examples\n--------------------------------\n\nExample of an Erlang SCTP server that receives SCTP messages\nand prints them on the standard output:\n\n```erlang\n-module(sctp_server).\n\n-export([server/0,server/1,server/2]).\n-include_lib(\"kernel/include/inet.hrl\").\n-include_lib(\"kernel/include/inet_sctp.hrl\").\n\nserver() ->\n server(any, 2006).\n\nserver([Host,Port]) when is_list(Host), is_list(Port) ->\n {ok, #hostent{h_addr_list = [IP|_]}} = inet:gethostbyname(Host),\n io:format(\"~w -> ~w~n\", [Host, IP]),\n server([IP, list_to_integer(Port)]).\n\nserver(IP, Port) when is_tuple(IP) orelse IP == any orelse IP == loopback,\n is_integer(Port) ->\n {ok,S} = gen_sctp:open(Port, [{recbuf,65536}, {ip,IP}]),\n io:format(\"Listening on ~w:~w. ~w~n\", [IP,Port,S]),\n ok = gen_sctp:listen(S, true),\n server_loop(S).\n\nserver_loop(S) ->\n case gen_sctp:recv(S) of\n {error, Error} ->\n io:format(\"SCTP RECV ERROR: ~p~n\", [Error]);\n Data ->\n io:format(\"Received: ~p~n\", [Data])\n end,\n server_loop(S).\n```\n\nExample of an Erlang SCTP client interacting with the above server.\nNote that in this example the client creates an association with\nthe server with 5 outbound streams. Therefore, sending of `\"Test 0\"`\nover stream 0 succeeds, but sending of `\"Test 5\"` over stream 5 fails.\nThe client then `abort`s the association, which results in that\nthe corresponding event is received on the server side.\n\n```erlang\n-module(sctp_client).\n\n-export([client/0, client/1, client/2]).\n-include_lib(\"kernel/include/inet.hrl\").\n-include_lib(\"kernel/include/inet_sctp.hrl\").\n\nclient() ->\n client([localhost]).\n\nclient([Host]) ->\n client(Host, 2006);\n\nclient([Host, Port]) when is_list(Host), is_list(Port) ->\n client(Host,list_to_integer(Port)),\n init:stop().\n\nclient(Host, Port) when is_integer(Port) ->\n {ok,S} = gen_sctp:open(),\n {ok,Assoc} = gen_sctp:connect\n (S, Host, Port, [{sctp_initmsg,#sctp_initmsg{num_ostreams=5}}]),\n io:format(\"Connection Successful, Assoc=~p~n\", [Assoc]),\n\n io:write(gen_sctp:send(S, Assoc, 0, <<\"Test 0\">>)),\n io:nl(),\n timer:sleep(10000),\n io:write(gen_sctp:send(S, Assoc, 5, <<\"Test 5\">>)),\n io:nl(),\n timer:sleep(10000),\n io:write(gen_sctp:abort(S, Assoc)),\n io:nl(),\n\n timer:sleep(1000),\n gen_sctp:close(S).\n```\n\nA simple Erlang SCTP client that uses the `connect_init` API:\n\n```erlang\n-module(ex3).\n\n-export([client/4]).\n-include_lib(\"kernel/include/inet.hrl\").\n-include_lib(\"kernel/include/inet_sctp.hrl\").\n\nclient(Peer1, Port1, Peer2, Port2)\n when is_tuple(Peer1), is_integer(Port1), is_tuple(Peer2), is_integer(Port2) ->\n {ok,S} = gen_sctp:open(),\n SctpInitMsgOpt = {sctp_initmsg,#sctp_initmsg{num_ostreams=5}},\n ActiveOpt = {active, true},\n Opts = [SctpInitMsgOpt, ActiveOpt],\n ok = gen_sctp:connect(S, Peer1, Port1, Opts),\n ok = gen_sctp:connect(S, Peer2, Port2, Opts),\n io:format(\"Connections initiated~n\", []),\n client_loop(S, Peer1, Port1, undefined, Peer2, Port2, undefined).\n\nclient_loop(S, Peer1, Port1, AssocId1, Peer2, Port2, AssocId2) ->\n receive\n {sctp, S, Peer1, Port1, {_Anc, SAC}}\n when is_record(SAC, sctp_assoc_change), AssocId1 == undefined ->\n io:format(\"Association 1 connect result: ~p. AssocId: ~p~n\",\n [SAC#sctp_assoc_change.state,\n SAC#sctp_assoc_change.assoc_id]),\n client_loop(S, Peer1, Port1, SAC#sctp_assoc_change.assoc_id,\n Peer2, Port2, AssocId2);\n\n {sctp, S, Peer2, Port2, {_Anc, SAC}}\n when is_record(SAC, sctp_assoc_change), AssocId2 == undefined ->\n io:format(\"Association 2 connect result: ~p. AssocId: ~p~n\",\n [SAC#sctp_assoc_change.state, SAC#sctp_assoc_change.assoc_id]),\n client_loop(S, Peer1, Port1, AssocId1, Peer2, Port2,\n SAC#sctp_assoc_change.assoc_id);\n\n {sctp, S, Peer1, Port1, Data} ->\n io:format(\"Association 1: received ~p~n\", [Data]),\n client_loop(S, Peer1, Port1, AssocId1,\n Peer2, Port2, AssocId2);\n\n {sctp, S, Peer2, Port2, Data} ->\n io:format(\"Association 2: received ~p~n\", [Data]),\n client_loop(S, Peer1, Port1, AssocId1,\n Peer2, Port2, AssocId2);\n\n Other ->\n io:format(\"Other ~p~n\", [Other]),\n client_loop(S, Peer1, Port1, AssocId1,\n Peer2, Port2, AssocId2)\n\n after 5000 ->\n ok\n end.\n```\n\n[](){: #seealso } See Also\n--------------------------\n\n`m:gen_tcp`, `m:gen_udp`, `m:inet`,\n[RFC 2960](http://www.rfc-archive.org/getrfc.php?rfc=2960) (Stream Control\nTransmission Protocol),\n[Sockets API Extensions for SCTP](http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13)","title":"gen_sctp","ref":"gen_sctp.html"},{"type":"function","doc":"Abort an association.\n\nAbnormally terminates the association specified by `Assoc`,\nwithout flushing unsent data. The socket itself remains open.\nOther associations opened on this socket are still valid,\nand the socket can be used in new associations.","title":"gen_sctp.abort/2","ref":"gen_sctp.html#abort/2"},{"type":"function","doc":"Close an SCTP socket.\n\nCloses the socket and all associations on it. The unsent data is flushed\nas for `eof/2`. The [`close/1`](`close/1`) call is blocking\ndepending of the value of the [`linger`](`m:inet#option-linger`)\nsocket [option]. If it is `false` or the linger time-out expires,\nthe call returns and unsent data is flushed in the background.","title":"gen_sctp.close/1","ref":"gen_sctp.html#close/1"},{"type":"function","doc":"","title":"gen_sctp.connect/3","ref":"gen_sctp.html#connect/3"},{"type":"function","doc":"Establish an association with a peer.\n\nWith arguments `Addr` and `Port`, equivalent to\n[`connect(Socket, Addr, Port, Opts, infinity)`](`connect/5`).\n\nWith arguments `SockAddr` and `Opts` _(since OTP 24.3)_, equivalent to\n[`connect(Socket, Addr, Port, Opts, Timeout)`](`connect/5`)\nwhere `Addr` and `Port` are extracted from `SockAddr`.","title":"gen_sctp.connect/4","ref":"gen_sctp.html#connect/4"},{"type":"function","doc":"Establish an association with a peer.\n\nEstablishes a new association for socket `Socket`, with the peer\n(SCTP server socket) specified by `Addr` and `Port`.\n`Timeout`, is expressed in milliseconds.\nA socket can be associated with multiple peers.\nThe socket has to be of type `seqpacket`.\n\n> #### Warning {: .warning }\n>\n> Using a value of `Timeout` less than the maximum time taken by the OS to\n> establish an association (around 4.5 minutes if the default values from\n> [RFC 4960](https://tools.ietf.org/html/rfc4960) are used), can result in\n> inconsistent or incorrect return values. This is especially relevant for\n> associations sharing the same `Socket` (that is, source address and port), as\n> the controlling process blocks until `connect/*` returns.\n> [`connect_init/*`](`connect_init/4`) provides an alternative without this\n> limitation.\n\n### [](){: #record-sctp_assoc_change } `#sctp_assoc_change{}`\n\nThe result of `connect/*` is an `#sctp_assoc_change{}` event that contains,\nin particular, the new [Association ID](`t:assoc_id/0`):\nl\n```erlang\n#sctp_assoc_change{\n state = atom(),\n error = integer(),\n outbound_streams = integer(),\n inbound_streams = integer(),\n assoc_id = assoc_id()\n}\n```\n\nThe number of outbound and inbound streams for the association\ncan be set by giving an `sctp_initmsg` option to `connect` as in:\n\n```erlang\nconnect(Socket, Ip, Port>,\n [{sctp_initmsg,#sctp_initmsg{num_ostreams=OutStreams,\n max_instreams=MaxInStreams}}])\n```\n\nAll options `Opt` are set on the socket before the association is attempted.\nIf an option record has undefined field values, the options record\nis first read from the socket for those values. In effect,\n`Opt` option records only need to define field values to change\nbefore connecting.\n\nThe returned `outbound_streams` and `inbound_streams` are the number of\nstream on the socket. These can be different from the requested values\n(`OutStreams` and `MaxInStreams`, respectively), if the peer\nrequires lower values.\n\n`state` can have the following values:\n\n- **`comm_up`** - Association is successfully established. This indicates\n a successful completion of `connect`.\n\n- **`cant_assoc`** - The association cannot be established\n (`connect/*` failure).\n\nOther states do not normally occur in the output from `connect/*`.\nRather, they can occur in `#sctp_assoc_change{}` events received\ninstead of data from [`recv/*`](`recv/1`) calls or socket messages.\nAll of them indicate losing the association because of various\nerror conditions, and are listed here for the sake of completeness:\n\n- **`comm_lost`**\n\n- **`restart`**\n\n- **`shutdown_comp`**\n\nThe field `error` can provide more detailed diagnostics. Its value\ncan be converted into a string using `error_string/1`.","title":"gen_sctp.connect/5","ref":"gen_sctp.html#connect/5"},{"type":"function","doc":"","title":"gen_sctp.connect_init/3","ref":"gen_sctp.html#connect_init/3"},{"type":"function","doc":"Start establishing an association with a peer.\n\nWith arguments `Addr` and `Port`, equivalent to\n[`connect_init(Socket, Addr, Port, Opts, infinity)`](`connect/5`).\n\nWith arguments `SockAddr` and `Opts` _(since OTP 24.3)_, equivalent to\n[`connect_init(Socket, Addr, Port, Opts, Timeout)`](`connect/5`)\nwhere `Addr` and `Port` are extracted from `SockAddr`.","title":"gen_sctp.connect_init/4","ref":"gen_sctp.html#connect_init/4"},{"type":"function","doc":"Start establishing an association with a peer.\n\nInitiates a new association for socket `Socket`, with the peer\n(SCTP server socket) specified by `Addr` and `Port`.\n\nThe fundamental difference between this API and `connect/*` is that\nthe return value is that of the underlying OS `connect(2)` system call.\nIf `ok` is returned, the operation has been succesfully initiated,\nand the final result result of the association establishment\nis sent to the socket owner (controlling process) as an\n[`#sctp_assoc_change{}`](#record-sctp_assoc_change) event.\nThe socket owner must be prepared to receive this, the\n[`recv/*`](`recv/1`) call has to be polled, depending on the value\nof the [active option](#option-active).\n\nThe parameters are as described for [`connect/*`](`connect/5`),\nexcept the `Timeout` value since for this function, the time-out only\napplies to the name resolving of `Addr` when it is a `t:inet:hostname/0`.","title":"gen_sctp.connect_init/5","ref":"gen_sctp.html#connect_init/5"},{"type":"function","doc":"Start establishing an association with a peer (multiple addresses).\n\nSimilar to `connectx_init/5` except using socket addresses, and not having a\n`Timeout`. Since the addresses do not need lookup and the connect is\nnon-blocking this call returns immediately.\n\nThe value of each socket address `port` must be the same or zero.\nAt least one socket address must have a non-zero `port`","title":"gen_sctp.connectx_init/3","ref":"gen_sctp.html#connectx_init/3"},{"type":"function","doc":"","title":"gen_sctp.connectx_init/4","ref":"gen_sctp.html#connectx_init/4"},{"type":"function","doc":"Start establishing an association with a peer (multiple addresses).\n\nInitiates a new association for socket `Socket`, with the peer\n(SCTP server socket) specified by `Addrs` and `Port`.\n\nThis API is similar to `connect_init/*` except the underlying OS\n`sctp_connectx(3)` system call is used, that accepts multiple\ndestination addresses.\n\nIf successful, the association ID is returned which will be received in a\nsubsequent [`#sctp_assoc_change{}`](#record-sctp_assoc_change)\nevent.\n\nThe parameters are as described in `connect_init/5`\n\n> #### Note {: .info }\n> This API allows the OS to use all Addrs when establishing an association,\n> but does not guarantee it will. Therefore, if the connection fails,\n> the user may want to rotate the order of addresses for a subsequent call.","title":"gen_sctp.connectx_init/5","ref":"gen_sctp.html#connectx_init/5"},{"type":"function","doc":"Change the controlling process (owner) of a socket.\n\nAssigns a new controlling process `Pid` to `Socket`.\nSee `gen_udp:controlling_process/2`.","title":"gen_sctp.controlling_process/2","ref":"gen_sctp.html#controlling_process/2"},{"type":"function","doc":"Terminate an association gracefully.\n\nGracefully terminates the association specified by `Assoc`, flushing\nall unsent data. The socket itself remains open. Other associations\nopened on this socket are still valid. The socket can be used\nin new associations.","title":"gen_sctp.eof/2","ref":"gen_sctp.html#eof/2"},{"type":"function","doc":"Translate an error number into a string or atom.\n\nTranslates an SCTP error number from, for example, `#sctp_remote_error{}`\nor `#sctp_send_failed{}` into an explanatory string, or into\none of the atoms `ok` for no error, or `unknown_error`\nfor an unrecognized integer.","title":"gen_sctp.error_string/1","ref":"gen_sctp.html#error_string/1"},{"type":"function","doc":"Make an SCTP socket listen to incoming associations.\n\nThe socket will listen on the IP address(es) and port number it is bound to.\n\nFor type `seqpacket`, sockets (the default), the argument`IsServer`\nmust be a `t:boolean/0`. In contrast to `stream` sockets, there is\nno listening queue length. If `IsServer` is `true`, the socket accepts\nnew associations, that is, it becomes an SCTP server socket.\n\nFor type `stream` sockets, the argument `Backlog` sets\nthe backlog queue length just like for TCP.","title":"gen_sctp.listen/2","ref":"gen_sctp.html#listen/2"},{"type":"function","doc":"","title":"gen_sctp.open/0","ref":"gen_sctp.html#open/0"},{"type":"function","doc":"Create an SCTP socket.\n\nWith argument [`Port`](`t:inet:port_number/0`),\nequivalent to`open([{port, Port}]`.\n\nCreates an SCTP socket and binds it to the local addresses specified by all\n`{ip,IP}` (or synonymously `{ifaddr,IP}`) options (this feature is called\nSCTP multi-homing). The default `IP` and `Port` are `any` and `0`,\nmeaning bind to all local addresses on any free port.\n\nIt is also possible to use `{ifaddr, SockAddr}`, in which case it takes\nprecedence over the `ip` and `port` options. These options can however\nbe used to update the address and port of ifaddr (if they occur\nafter ifaddr in the options list), although this is not recommended.\n\nOther options:\n\n- **`inet6`** - Sets up the socket for IPv6.\n\n- **`inet`** - Sets up the socket for IPv4. This is the default.\n\nA default set of socket [options](#options) is used.\nIn particular, the socket is opened in [binary](#option-binary)\nand [passive](#option-active) mode, with SockType `seqpacket`,\nand with reasonably large [kernel](`m:inet#option-sndbuf`) and driver\n[buffers](`m:inet#option-buffer`).\n\nWhen the socket is in [passive](#option-active) mode,\ndata can be received through the [`recv/1,2`](`recv/1`) calls.\n\nWhen the socket is in [active](#option-active) mode,\ndata received data is delivered to the controlling process as messages:\n\n```erlang\n{sctp, Socket, FromIP, FromPort, {AncData, Data}}\n```\n\nSee [`recv/1,2`](`recv/1`) for a description of the message fields.\n\n> #### Note {: .info }\n>\n> This message format unfortunately differs slightly from the\n> [`gen_udp`](`gen_udp:open/1`) message format with ancillary data,\n> and from the [`recv/1,2`](`recv/1`) return tuple format.","title":"gen_sctp.open/1","ref":"gen_sctp.html#open/1"},{"type":"function","doc":"","title":"gen_sctp.open/2","ref":"gen_sctp.html#open/2"},{"type":"function","doc":"Branch off an association into a new socket of type `stream`.\n\nThe existing association `Assoc` in the socket `Socket` (that has to\nbe of type `seqpacket`; one-to-many style) is branched off into\na new socket `NewSocket` of type `stream` (one-to-one style).\n\nThe existing association argument `Assoc` can be a\n[`#sctp_assoc_change{}`](#record-sctp_assoc_change) record as\nreturned from, for example, [`recv/*`](`recv/2`), [`connect/*`](`connect/5`),\nor from a listening socket in active mode.\nIt can also be just the field `assoc_id` `t:integer/0` from such a record.","title":"gen_sctp.peeloff/2","ref":"gen_sctp.html#peeloff/2"},{"type":"function","doc":"","title":"gen_sctp.recv/1","ref":"gen_sctp.html#recv/1"},{"type":"function","doc":"Receive a `Data` message.\n\nReceives the `Data` message from any association of the socket.\nIf the receive times out, `{error,timeout}` is returned. The default\ntime-out is `infinity`. `FromIP` and `FromPort` indicate the address\nof the sender.\n\n`AncData` is a list of ancillary data items received with the main `Data`.\nThis list can be empty, or contain a single\n[`#sctp_sndrcvinfo{}`](#record-sctp_sndrcvinfo) record,\nif receiving ancillary data is enabled\n(see option [`sctp_events`](#option-sctp_events)).\nPer default, it is enabled, as such ancillary data provides an easy way\nto determine the association and stream over which the message was received.\n(An alternative way is to get the association ID from `FromIP` and `FromPort`\nusing socket option\n[`sctp_get_peer_addr_info`](#option-sctp_get_peer_addr_info),\nbut this does still not give the stream number).\n\n`AncData` may also contain [ancillary data](`t:inet:ancillary_data/0`)\nfrom the socket [options](#options)\n[`recvtos`](`m:inet#option-recvtos`),\n[`recvtclass`](`m:inet#option-recvtclass`) or\n[`recvttl`](`m:inet#option-recvttl`), if that is supported for the socket\nby the platform.\n\nThe `Data` received can, depending on the socket [mode](#option-binary)\nbe a `t:binary/0` or a `t:list/0` of bytes (integers in the range\n`0` through `255`), or it can be an SCTP event.\n\n### [](){: #sctp-events } Possible SCTP events\n\n- [`#sctp_sndrcvinfo{}`](#record-sctp_sndrcvinfo)\n- [`#sctp_assoc_change{}`](#record-sctp_assoc_change)\n- ```erlang\n #sctp_paddr_change{\n addr = {ip_address(),port()},\n state = atom(),\n error = integer(),\n assoc_id = assoc_id()\n }\n ```\n\n Indicates change of the status of the IP address of the peer specified by\n `addr` within association `assoc_id`. Possible values of `state` (mostly\n self-explanatory) include:\n\n - **`addr_unreachable`**\n\n - **`addr_available`**\n\n - **`addr_removed`**\n\n - **`addr_added`**\n\n - **`addr_made_prim`**\n\n - **`addr_confirmed`**\n\n In case of an error (for example, `addr_unreachable`), the field `error`\n provides more diagnostics. In such cases, event `#sctp_paddr_change{}`\n is automatically converted into an `error` term returned by\n [`recv`](`recv/1`). The `error` field value can be converted\n into a string using `error_string/1`.\n\n- ```erlang\n #sctp_send_failed{\n flags = true | false,\n error = integer(),\n info = #sctp_sndrcvinfo{},\n assoc_id = assoc_id()\n data = binary()\n }\n ```\n\n The sender can receive this event if a send operation fails.\n\n - **`flags`** - A Boolean specifying if the data has been transmitted\n over the wire.\n\n - **`error`** - Provides extended diagnostics, use\n [`error_string/1`.](`error_string/1`)\n\n - **`info`** - The original\n [`#sctp_sndrcvinfo{}`](#record-sctp_sndrcvinfo) record\n used in the failed [`send/*`.](`send/3`)\n\n - **`data`** - The whole original data chunk attempted to be sent.\n\n In the current implementation of the Erlang/SCTP binding, this event is\n internally converted into an `error` term returned by [`recv/*`](`recv/1`).\n\n- ```erlang\n #sctp_adaptation_event{\n adaptation_ind = integer(),\n assoc_id = assoc_id()\n }\n ```\n\n Delivered when a peer sends an adaptation layer indication parameter\n (configured through option\n [`sctp_adaptation_layer`](#option-sctp_adaptation_layer)).\n Notie that with the current implementation of the Erlang/SCTP binding,\n this event is disabled by default.\n\n- ```erlang\n #sctp_pdapi_event{\n indication = sctp_partial_delivery_aborted,\n assoc_id = assoc_id()\n }\n ```\n\n A partial delivery failure. In the current implementation\n of the Erlang/SCTP binding, this event is internally converted\n into an `error` term returned by [`recv/*`](`recv/1`).","title":"gen_sctp.recv/2","ref":"gen_sctp.html#recv/2"},{"type":"function","doc":"Send a `Data` message, full-featured.\n\nSends the `Data` message with all sending parameters from a\n[`#sctp_sndrcvinfo{}`](#record-sctp_sndrcvinfo) record.\nThis way, the user can specify the PPID (passed to the remote end)\nand context (passed to the local SCTP layer), which can be used,\nfor example, for error identification. However, such a fine grained\nuser control is rarely required. The function [`send/4`](`send/4`)\nis sufficient for most applications.\n\n> #### Note {: .info }\n>\n> Send is normally blocking, but if the socket option\n> [`non_block_send`](#option_non_block_send) is set to true,\n> the function will return with e.g. {error, eagain}\n> in the case when the function would otherwise block.\n> It is then up to the user to try again later.","title":"gen_sctp.send/3","ref":"gen_sctp.html#send/3"},{"type":"function","doc":"Send a data message.\n\nSends a `Data` message on the association `Assoc` and `Stream`.\n\n`Assoc` can be specified with a\n[`#sctp_assoc_change{}`](#record-sctp_assoc_change) record\nfrom an association establishment, or as the `t:assoc_id/0`\n`t:integer/0` field value.\n\n> #### Note {: .info }\n>\n> Send is normally blocking, but if the socket option\n> [`non_block_send`](#option_non_block_send) is set to true,\n> the function will return with e.g. {error, eagain}\n> in the case when the function would otherwise block.\n> It is then up to the user to try again later.","title":"gen_sctp.send/4","ref":"gen_sctp.html#send/4"},{"type":"type","doc":"Association ID.\n\nAn opaque term returned in, for example, `#sctp_paddr_change{}`, which\nidentifies an association for an SCTP socket. The term is opaque except for the\nspecial value `0`, which has a meaning such as \"the whole endpoint\" or \"all\nfuture associations\".","title":"gen_sctp.assoc_id/0","ref":"gen_sctp.html#t:assoc_id/0"},{"type":"type","doc":"","title":"gen_sctp.elementary_option/0","ref":"gen_sctp.html#t:elementary_option/0"},{"type":"type","doc":"","title":"gen_sctp.elementary_option_name/0","ref":"gen_sctp.html#t:elementary_option_name/0"},{"type":"type","doc":"[SCTP Socket Option](#options) name and value, to set.","title":"gen_sctp.option/0","ref":"gen_sctp.html#t:option/0"},{"type":"type","doc":"[SCTP Socket Option](#options) name, to get.","title":"gen_sctp.option_name/0","ref":"gen_sctp.html#t:option_name/0"},{"type":"type","doc":"[SCTP Socket Option](#options) name and value, what you get.","title":"gen_sctp.option_value/0","ref":"gen_sctp.html#t:option_value/0"},{"type":"type","doc":"","title":"gen_sctp.record_option/0","ref":"gen_sctp.html#t:record_option/0"},{"type":"type","doc":"","title":"gen_sctp.ro_option/0","ref":"gen_sctp.html#t:ro_option/0"},{"type":"type","doc":"Socket identifier returned from [`open/*`](`open/0`).","title":"gen_sctp.sctp_socket/0","ref":"gen_sctp.html#t:sctp_socket/0"},{"type":"module","doc":"Interface to TCP/IP sockets.\n\nThis module provides functions for communicating over TCP/IP\nprotocol sockets.\n\nThe following code fragment is a simple example of a client connecting to a\nserver at port 5678, transferring a binary, and closing the connection:\n\n```erlang\nclient() ->\n SomeHostInNet = \"localhost\", % to make it runnable on one machine\n {ok, Sock} = gen_tcp:connect(SomeHostInNet, 5678,\n [binary, {packet, 0}]),\n ok = gen_tcp:send(Sock, \"Some Data\"),\n ok = gen_tcp:close(Sock).\n```\n\nAt the other end, a server is listening on port 5678, accepts the connection,\nand receives the binary:\n\n```erlang\nserver() ->\n {ok, LSock} = gen_tcp:listen(5678, [binary, {packet, 0},\n {active, false}]),\n {ok, Sock} = gen_tcp:accept(LSock),\n {ok, Bin} = do_recv(Sock, []),\n ok = gen_tcp:close(Sock),\n ok = gen_tcp:close(LSock),\n Bin.\n\ndo_recv(Sock, Bs) ->\n case gen_tcp:recv(Sock, 0) of\n {ok, B} ->\n do_recv(Sock, [Bs, B]);\n {error, closed} ->\n {ok, list_to_binary(Bs)}\n end.\n```\n\nFor more examples, see section [Examples](#module-examples).\n\n> #### Note {: .info }\n>\n> Functions that create sockets can take an optional option;\n> `{inet_backend, Backend}` that, if specified, has to be the first option. This\n> selects the implementation backend towards the platform's socket API.\n>\n> This is a _temporary_ option that will be ignored in a future release.\n>\n> The default is `Backend = inet` that selects the traditional `inet_drv.c`\n> driver. The other choice is `Backend = socket` that selects the new `m:socket`\n> module and its NIF implementation.\n>\n> The system default can be changed when the node is started with the\n> application `kernel`'s configuration variable `inet_backend`.\n>\n> For `gen_tcp` with `inet_backend = socket` we have tried to be as \"compatible\"\n> as possible which has sometimes been impossible. Here is a list of cases when\n> the behaviour of inet-backend `inet` (default) and `socket` are different:\n>\n> - [Non-blocking send](#non_blocking_send)\n>\n> If a user calling [`gen_tcp:send/2`](`send/2`) with `inet_backend = inet`,\n> tries to send more data than there is room for in the OS buffers, the \"rest\n> data\" is buffered by the inet driver (and later sent in the background). The\n> effect for the user is that the call is non-blocking.\n>\n> This is _not_ the effect when `inet_backend = socket`, since there is no\n> buffering. Instead the user hangs either until all data has been sent or the\n> `send_timeout` timeout has been reached.\n>\n> - `shutdown/2` may hide errors\n>\n> The call does not involve the receive process state, and is done\n> right on the underlying socket. On for example Linux, it is a known\n> misbehaviour that it skips some checks so doing shutdown on a\n> listen socket returns `ok` while the logical result should have been\n> `{error, enotconn}`. The `inet_drv.c` driver did an extra check\n> and simulated the correct error, but with `Backend = socket`\n> it would introduce overhead to involve the receive process.\n>\n> - The option [nodelay](`m:inet#option-nodelay`) is a TCP specific option that\n> is _not_ compatible with `domain = local`.\n>\n> When using `inet_backend = socket`, trying to create a socket (via listen or\n> connect) with `domain = local` (for example with option \\{ifaddr,\n> \\{local,\"/tmp/test\"\\}\\}) _will fail_ with `{error, enotsup}`.\n>\n> This does not actually work for `inet_backend = inet` either, but in that\n> case the error is simply _ignored_, which is a _bad_ idea. We have chosen to\n> _not_ ignore this error for `inet_backend = socket`.\n>\n> - [Async shutdown write](#async_shutdown_write)\n>\n> Calling [gen_tcp:shutdown(Socket, write | read_write)](`shutdown/2`) on a\n> socket created with `inet_backend = socket` will take _immediate_ effect,\n> unlike for a socket created with `inet_backend = inet`.\n>\n> See [async shutdown write](#async_shutdown_write) for more info.\n>\n> - Windows require sockets (domain = `inet | inet6`) to be bound.\n>\n> _Currently_ all sockets created on Windows with `inet_backend = socket` will\n> be bound. If the user does not provide an address, gen_tcp will try to\n> 'figure out' an address itself.","title":"gen_tcp","ref":"gen_tcp.html"},{"type":"module","doc":"The following example illustrates use of option `{active,once}` and multiple\naccepts by implementing a server as a number of worker processes doing accept on\na single listening socket. Function `start/2` takes the number of worker\nprocesses and the port number on which to listen for incoming connections. If\n`LPort` is specified as `0`, an ephemeral port number is used, which is why the\nstart function returns the actual port number allocated:\n\n```erlang\nstart(Num,LPort) ->\n case gen_tcp:listen(LPort,[{active, false},{packet,2}]) of\n {ok, ListenSock} ->\n start_servers(Num,ListenSock),\n {ok, Port} = inet:port(ListenSock),\n Port;\n {error,Reason} ->\n {error,Reason}\n end.\n\nstart_servers(0,_) ->\n ok;\nstart_servers(Num,LS) ->\n spawn(?MODULE,server,[LS]),\n start_servers(Num-1,LS).\n\nserver(LS) ->\n case gen_tcp:accept(LS) of\n {ok,S} ->\n loop(S),\n server(LS);\n Other ->\n io:format(\"accept returned ~w - goodbye!~n\",[Other]),\n ok\n end.\n\nloop(S) ->\n inet:setopts(S,[{active,once}]),\n receive\n {tcp,S,Data} ->\n Answer = process(Data), % Not implemented in this example\n gen_tcp:send(S,Answer),\n loop(S);\n {tcp_closed,S} ->\n io:format(\"Socket ~w closed [~w]~n\",[S,self()]),\n ok\n end.\n```\n\nExample of a simple client:\n\n```erlang\nclient(PortNo,Message) ->\n {ok,Sock} = gen_tcp:connect(\"localhost\",PortNo,[{active,false},\n {packet,2}]),\n gen_tcp:send(Sock,Message),\n A = gen_tcp:recv(Sock,0),\n gen_tcp:close(Sock),\n A.\n```\n\nThe `send` call does not accept a time-out option because time-outs on send is\nhandled through socket option `send_timeout`. The behavior of a send operation\nwith no receiver is mainly defined by the underlying TCP stack and the network\ninfrastructure. To write code that handles a hanging receiver that can\neventually cause the sender to hang on a `send` do like the following.\n\nConsider a process that receives data from a client process to be forwarded to a\nserver on the network. The process is connected to the server through TCP/IP and\ndoes not get any acknowledge for each message it sends, but has to rely on the\nsend time-out option to detect that the other end is unresponsive. Option\n`send_timeout` can be used when connecting:\n\n```erlang\n...\n{ok,Sock} = gen_tcp:connect(HostAddress, Port,\n [{active,false},\n {send_timeout, 5000},\n {packet,2}]),\n loop(Sock), % See below\n...\n```\n\nIn the loop where requests are handled, send time-outs can now be detected:\n\n```erlang\nloop(Sock) ->\n receive\n {Client, send_data, Binary} ->\n case gen_tcp:send(Sock,[Binary]) of\n {error, timeout} ->\n io:format(\"Send timeout, closing!~n\",\n []),\n handle_send_timeout(), % Not implemented here\n Client ! {self(),{error_sending, timeout}},\n %% Usually, it's a good idea to give up in case of a\n %% send timeout, as you never know how much actually\n %% reached the server, maybe only a packet header?!\n gen_tcp:close(Sock);\n {error, OtherSendError} ->\n io:format(\"Some other error on socket (~p), closing\",\n [OtherSendError]),\n Client ! {self(),{error_sending, OtherSendError}},\n gen_tcp:close(Sock);\n ok ->\n Client ! {self(), data_sent},\n loop(Sock)\n end\n end.\n```\n\nUsually it suffices to detect time-outs on receive, as most protocols include\nsome sort of acknowledgment from the server, but if the protocol is strictly one\nway, option `send_timeout` comes in handy.","title":"Examples - gen_tcp","ref":"gen_tcp.html#module-examples"},{"type":"function","doc":"","title":"gen_tcp.accept/1","ref":"gen_tcp.html#accept/1"},{"type":"function","doc":"Accept an incoming connection request on a listen socket.\n\n`Socket` must be a socket returned from `listen/2`. `Timeout` specifies\na time-out value in milliseconds. Defaults to `infinity`.\n\nReturns:\n\n- `{ok, Socket}` if a connection is established\n- `{error, closed}` if `ListenSocket` is closed\n- `{error, timeout}` if no connection is established within `Timeout`\n- `{error, system_limit}` if all available ports in the Erlang emulator\n are in use\n- A POSIX error value if something else goes wrong, see `m:inet`\n about possible values\n\nTo send packets (outbound) on the returned `Socket`, use `send/2`.\nPackets sent from the peer (inbound) are delivered as messages\nto the socket owner; the process that created the socket.\nUnless `{active, false}` is specified in the option list when creating\nthe [listening socket](`listen/2`).\n\nSee `connect/4` about _active mode_ socket messages and _passive mode_.\n\n> #### Note {: .info }\n>\n> The `accept` call _doesn't have to be_ issued from the socket owner process.\n> Using version 5.5.3 and higher of the emulator, multiple simultaneous accept\n> calls can be issued from different processes, which allows for a pool of\n> acceptor processes handling incoming connections.","title":"gen_tcp.accept/2","ref":"gen_tcp.html#accept/2"},{"type":"function","doc":"Close a TCP socket.\n\nNote that in most implementations of TCP, doing a `close` does not guarantee\nthat the data sent is delivered to the recipient. It is guaranteed that\nthe recepient will see all sent data before getting the close, but the\nsender gets no indication of that.\n\nIf the sender needs to know that the recepient has received all data\nthere are two common ways to achieve this:\n\n1. Use [`gen_tcp:shutdown(Sock, write)`](`shutdown/2`) to signal that no more\n data is to be sent and wait for the other side to acknowledge seeing\n its read side being closed, by closing its write side, which shows\n as a socket close on this side.\n2. Implement an acknowledgement in the protocol on top of TCP\n that both connection ends adhere to, indicating that all data\n has been seen. The socket option [`{packet, N}`](`m:inet#option-packet`)\n may be useful.","title":"gen_tcp.close/1","ref":"gen_tcp.html#close/1"},{"type":"function","doc":"Equivalent to [`connect(SockAddr, Opts, infinity)`](`connect/3`).","title":"gen_tcp.connect/2","ref":"gen_tcp.html#connect/2"},{"type":"function","doc":"Create a socket connected to the specified address.","title":"gen_tcp.connect/3","ref":"gen_tcp.html#connect/3"},{"type":"function","doc":"Equivalent to [`connect(Address, Port, Opts, infinity)`](`connect/4`).","title":"With arguments `Address` and `Port` - gen_tcp.connect/3","ref":"gen_tcp.html#connect/3-with-arguments-address-and-port"},{"type":"function","doc":"Connects to a remote listen socket specified by `SockAddr`\nwhere `t:socket:sockaddr_in6/0` for example allows specifying\nthe `scope_id` for link local IPv6 addresses.\n\n[IPv4 addresses](`t:socket:sockaddr_in/0`) on the same\n`t:map/0` format is also allowed.\n\nEquivalent to `connect/4`, besides the format of the destination address.","title":"With argument `SockAddr` **(since OTP 24.3)** - gen_tcp.connect/3","ref":"gen_tcp.html#connect/3-with-argument-sockaddr-since-otp-24-3"},{"type":"function","doc":"Create a socket connected to the specified address.\n\nCreates a socket and connects it to a server on TCP port `Port`\non the host with IP address `Address`, that may also be a hostname.\n\n### `Opts` (connect options)\n\n- **`{ip, Address}`** - If the local host has many IP addresses,\n this option specifies which one to use.\n\n- **`{ifaddr, Address}`** - Same as `{ip, Address}`.\n\n However, if `Address` instead is a `t:socket:sockaddr_in/0` or\n `t:socket:sockaddr_in6/0` this takes precedence over any value\n previously set with the `ip` and `port` options. If these options\n (`ip` or/and `port`) however comes _after_ this option,\n they may be used to _update_ the corresponding fields of this option\n (for `ip`, the `addr` field, and for `port`, the `port` field).\n\n- **`{fd, integer() >= 0}`** - If a socket has somehow been connected without\n using `gen_tcp`, use this option to pass the file descriptor for it.\n If `{ip, Address}` and/or `{port, port_number()}` is combined\n with this option, the `fd` is bound to the specified interface\n and port before connecting. If these options are not specified,\n it is assumed that the `fd` is already bound appropriately.\n\n- **`inet`** - Sets up the socket for IPv4.\n\n- **`inet6`** - Sets up the socket for IPv6.\n\n- **`local`** - Sets up a Unix Domain Socket. See `t:inet:local_address/0`\n\n- **`{port, Port}`** - Specifies which local port number to use.\n\n- **`{tcp_module, module()}`** - Overrides which callback module is used.\n Defaults to `inet_tcp` for IPv4 and `inet6_tcp` for IPv6.\n\n- **`t:option/0`** - See `inet:setopts/2`.","title":"gen_tcp.connect/4","ref":"gen_tcp.html#connect/4"},{"type":"function","doc":"Packets can be sent to the peer (outbound) with\n[`send(Socket, Packet)`](`send/2`). Packets sent from the peer\n(inbound) are delivered as messages to the socket owner;\nthe process that created the socket, unless `{active, false}`\nis specified in the `Options` list.\n\n#### Active mode socket messages\n\n- **`{tcp, Socket, Data}`** - Inbound data from the socket.\n\n- **`{tcp_passive, Socket}`** -\n The socket was in `{active, N}` mode (see `inet:setopts/2` for details)\n and its message counter reached `0`, indicating that\n the socket has transitioned to passive (`{active, false}`) mode.\n\n\n- **`{tcp_closed, Socket}`** - The socket was closed.\n\n- **`{tcp_error, Socket, Reason}`** A socket error occurred.\n\n#### Passive mode\n\nIf `{active, false}` is specified in the option list for the socket,\npackets and errors are retrieved by calling [`recv/2,3`](`recv/3`)\n(`send/2` may also return errors).\n\n#### Timeout\n\nThe optional `Timeout` parameter specifies a connect time-out in milliseconds.\nDefaults to `infinity`.\n\n> #### Note {: .info }\n>\n> Keep in mind that if the underlying OS `connect()` call returns a timeout,\n> `gen_tcp:connect` will also return a timeout (i.e. `{error, etimedout}`),\n> even if a larger `Timeout` was specified (for example `infinity`).\n\n> #### Note {: .info }\n>\n> The default values for options specified to `connect` can be affected by the\n> Kernel configuration parameter `inet_default_connect_options`.\n> For details, see `m:inet`.","title":"Socket Data - gen_tcp.connect/4","ref":"gen_tcp.html#connect/4-socket-data"},{"type":"function","doc":"Change the controlling process (owner) of a socket.\n\nAssigns a new controlling process `Pid` to `Socket`. The controlling process\nis the process that the socket sends messages to. If this function\nis called from any other process than the current controlling process,\n`{error, not_owner}` is returned.\n\nIf the process identified by `Pid` is not an existing local `t:pid/0`,\n`{error, badarg}` is returned. `{error, badarg}` may also be returned\nin some cases when `Socket` is closed during the execution of this function.\n\nIf the socket is in _active mode_, this function will transfer any messages\nfrom the socket in the mailbox of the caller to the new controlling process.\n\nIf any other process is interacting with the socket during the transfer,\nit may not work correctly and messages may remain in the caller's mailbox.\nFor instance, changing the sockets active mode during the transfer\ncould cause this.","title":"gen_tcp.controlling_process/2","ref":"gen_tcp.html#controlling_process/2"},{"type":"function","doc":"Create a listen socket.\n\nCreates a socket and sets it to listen on port `Port` on the local host.\n\nIf `Port == 0`, the underlying OS assigns an available (ephemeral)\nport number, use `inet:port/1` to retrieve it.\n\nThe following options are available:\n\n- **`list`** - Received `Packet`s are delivered as lists of bytes,\n `[`[`byte/0`](`t:byte/0`)`]`.\n\n- **`binary`** - Received `Packet`s are delivered as `t:binary/0`s.\n\n- **`{backlog, B}`** - `B ::` `t:non_neg_integer/0`. The backlog value\n defines the maximum length that the queue of pending connections\n can grow to. Defaults to `5`.\n\n- **`inet6`** - Sets up the socket for IPv6.\n\n- **`inet`** - Sets up the socket for IPv4.\n\n- **`{fd, Fd}`** - If a socket has somehow been created without using\n `gen_tcp`, use this option to pass the file descriptor for it.\n\n- **`{ip, Address}`** - If the host has many IP addresses, this option\n specifies which one to listen on.\n\n- **`{port, Port}`** - Specifies which local port number to use.\n\n- **`{ifaddr, Address}`** - Same as `{ip, Address}`.\n\n However, if this instead is an `t:socket:sockaddr_in/0` or\n `t:socket:sockaddr_in6/0` this takes precedence over any value\n previously set with the `ip` and `port` options. If these options\n (`ip` or/and `port`) however comes _after_ this option,\n they may be used to _update_ their corresponding fields of this option\n (for `ip`, the `addr` field, and for `port`, the `port` field).\n\n- **`{tcp_module, module()}`** - Overrides which callback module is used.\n Defaults to `inet_tcp` for IPv4 and `inet6_tcp` for IPv6.\n\n- **`t:option/0`** - See `inet:setopts/2`.\n\nThe returned socket `ListenSocket` should be used when calling\n[`accept/1,2`](`accept/1`) to accept an incoming connection request.\n\n> #### Note {: .info }\n>\n> The default values for options specified to `listen` can be affected by the\n> Kernel configuration parameter `inet_default_listen_options`. For details, see\n> `m:inet`.","title":"gen_tcp.listen/2","ref":"gen_tcp.html#listen/2"},{"type":"function","doc":"","title":"gen_tcp.recv/2","ref":"gen_tcp.html#recv/2"},{"type":"function","doc":"Receive a packet, from a socket in _passive mode_.\n\nA closed socket is indicated by the return value `{error, closed}`.\nIf the socket is not in passive mode, the return value is `{error, einval}`.\n\nArgument `Length` is only meaningful when the socket is in `raw` mode and\ndenotes the number of bytes to read. If `Length` is `0`, all available\nbytes are returned. If `Length > 0`, exactly `Length` bytes are returned,\nor an error; except if the socket is closed from the other side,\nthen the last read before the one returning `{error, closed}`\nmay return less than `Length` bytes of data.\n\nThe optional `Timeout` parameter specifies a time-out in milliseconds.\nDefaults to `infinity`.\n\nAny process can receive data from a passive socket, even if that process is not\nthe controlling process of the socket. However, only one process can call this\nfunction on a socket at any given time. Using simultaneous calls to `recv` is\nnot recommended as the behavior depends on the socket implementation,\nand could return errors such as `{error, ealready}`.","title":"gen_tcp.recv/3","ref":"gen_tcp.html#recv/3"},{"type":"function","doc":"Send a packet on a socket.\n\nThere is no `send/2` call with a time-out option; use socket option\n`send_timeout` if time-outs are desired. See section\n[Examples](#module-examples).\n\nThe return value `{error, {timeout, RestData}}` can only be returned when\n`inet_backend = socket`.\n\n[](){: #non_blocking_send }\n\n> #### Note {: .info }\n>\n> #### Non-blocking send.\n>\n> If the user tries to send more data than there is room for in the OS send\n> buffers, the 'rest data' is stored in (inet driver) internal buffers and later\n> sent in the background. The function immediately returns ok (_not_ informing\n> the caller that some date isn'nt sent yet). Any issue while\n> sending the 'rest data' may be returned later.\n>\n> When using `inet_backend = socket`, the behaviour is different. There is\n> _no_ buffering, instead the caller will \"hang\" until all of the data\n> has been sent or the send timeout (as specified by the `send_timeout`\n> option) expires (the function can \"hang\" even when using the `inet`\n> backend if the internal buffers are full).\n>\n> If this happens when using `packet =/= raw`, a partial package has been\n> written. A new package therefore _mustn't_ be written at this point,\n> as there is no way for the peer to distinguish this from data in\n> the current package. Instead, set package to raw, send the rest data\n> (as raw data) and then set package to the correct package type again.","title":"gen_tcp.send/2","ref":"gen_tcp.html#send/2"},{"type":"function","doc":"Close the socket in one or both directions.\n\n`How == write` means closing the socket for writing, reading from it is still\npossible.\n\nIf `How == read` or there is no outgoing data buffered in the `Socket` port, the\nshutdown is performed immediately and any error encountered is returned in\n`Reason`.\n\nIf there is data buffered in the socket port, shutdown isn't performed\non the socket until that buffered data has been written to the OS\nprotocol stack. If any errors are encountered, the socket is closed\nand `{error, closed}` is returned by the next `recv/2` or `send/2` call.\n\nOption `{exit_on_close, false}` is useful if the peer performs a shurdown\nof its write side. Then the socket stays open for writing after\nreceive has indicated that the socket was closed.\n\n[](){: #async_shutdown_write }\n\n> #### Note {: .info }\n>\n> Async shutdown write (`How :: write | read_write`).\n>\n> If the shutdown attempt is made while the inet driver is sending\n> buffered data in the background, the shutdown is postponed until\n> all buffered data has been sent. This function immediately returns `ok`,\n> and the caller _isn't_ informed (that the shutdown has been postponed).\n>\n> When using `inet_backend = socket`, the behaviour is different. A shutdown\n> with `How :: write | read_write` will always be performed _immediately_.","title":"gen_tcp.shutdown/2","ref":"gen_tcp.html#shutdown/2"},{"type":"type","doc":"","title":"gen_tcp.connect_option/0","ref":"gen_tcp.html#t:connect_option/0"},{"type":"type","doc":"","title":"gen_tcp.listen_option/0","ref":"gen_tcp.html#t:listen_option/0"},{"type":"type","doc":"","title":"gen_tcp.option/0","ref":"gen_tcp.html#t:option/0"},{"type":"type","doc":"","title":"gen_tcp.option_name/0","ref":"gen_tcp.html#t:option_name/0"},{"type":"type","doc":"Value from socket option [`pktoptions`](`t:option_name/0`).\n\nIf the platform implements the IPv4 option `IP_PKTOPTIONS`,\nor the IPv6 option `IPV6_PKTOPTIONS` or `IPV6_2292PKTOPTIONS` for the socket;\nthis value is returned from `inet:getopts/2` when called with the option name\n[`pktoptions`](`t:option_name/0`).\n\n> #### Note {: .info }\n>\n> This option appears to be VERY Linux specific, and its existence in future\n> Linux kernel versions is also worrying since the option is part of RFC 2292\n> which is since long (2003) obsoleted by RFC 3542 that _explicitly_ removes\n> this possibility to get packet information from a stream socket. For\n> comparison: it has existed in FreeBSD but is now removed, at least since\n> FreeBSD 10.","title":"gen_tcp.pktoptions_value/0","ref":"gen_tcp.html#t:pktoptions_value/0"},{"type":"type","doc":"As returned by [`accept/1,2`](`accept/1`) and [`connect/3,4`](`connect/3`).","title":"gen_tcp.socket/0","ref":"gen_tcp.html#t:socket/0"},{"type":"module","doc":"Interface to UDP sockets.\n\nThis module provides functions for communicating over UDP\nprotocol sockets.\n\n> #### Note {: .info }\n>\n> Functions that create sockets can take an optional option;\n> `{inet_backend, Backend}` that, if specified, has to be the first option. This\n> selects the implementation backend towards the platform's socket API.\n>\n> This is a _temporary_ option that will be ignored in a future release.\n>\n> The default is `Backend = inet` that selects the traditional `inet_drv.c`\n> driver. The other choice is `Backend = socket` that selects the new `m:socket`\n> module and its NIF implementation.\n>\n> The system default can be changed when the node is started with the\n> application `kernel`'s configuration variable `inet_backend`.\n>\n> For `gen_udp` with `inet_backend = socket` we have tried to be as \"compatible\"\n> as possible which has sometimes been impossible. Here is a list of cases when\n> the behaviour of inet-backend `inet` (default) and `socket` are different:\n>\n> - The option [read_packets](`m:inet#option-read_packets`) is currently\n> _ignored_.\n> - Windows require sockets (domain = `inet | inet6`) to be bound.\n>\n> _Currently_ all sockets created on Windows with `inet_backend = socket` will\n> be bound. If the user does not provide an address, gen_udp will try to\n> 'figure out' an address itself.","title":"gen_udp","ref":"gen_udp.html"},{"type":"function","doc":"Closes a UDP socket.","title":"gen_udp.close/1","ref":"gen_udp.html#close/1"},{"type":"function","doc":"Connect a UDP socket.\n\nConnecting a UDP socket only means storing the specified (destination) socket\naddress, as specified by `SockAddr`, so that the system knows where to send\ndata.\n\nWhen the socket is \"connected\" it is not necessary to specify\nthe destination address when sending a datagram.\nThat is; `send/2` may be used.\n\nIt also means that the socket will only receive data from\nthe connected address. Other messages are discarded on arrival\nby the OS protocol stack.","title":"gen_udp.connect/2","ref":"gen_udp.html#connect/2"},{"type":"function","doc":"Connect a UDP socket.\n\nSee `connect/2`.\n\nWith this function the destination is specified\nwith separate `Address` and `Port` arguments where `Address` may be\nan [IP address](`t:inet:socket_address/0`)\nor a [host name](`t:inet:hostname/0`).","title":"gen_udp.connect/3","ref":"gen_udp.html#connect/3"},{"type":"function","doc":"Change the controlling process (owner) of a socket.\n\nAssigns a new controlling process `Pid` to `Socket`. The controlling process\nis the process that the socket sends messages to. If this function\nis called from any other process than the current controlling process,\n`{error, not_owner}` is returned.\n\nIf the process identified by `Pid` is not an existing local `t:pid/0`,\n`{error, badarg}` is returned. `{error, badarg}` may also be returned\nin some cases when `Socket` is closed during the execution of this function.\n\nIf the socket is in _active mode_, this function will transfer any messages\nfrom the socket in the mailbox of the caller to the new controlling process.\n\nIf any other process is interacting with the socket during the transfer,\nit may not work correctly and messages may remain in the caller's mailbox.\nFor instance, changing the sockets active mode during the transfer\ncould cause this.","title":"gen_udp.controlling_process/2","ref":"gen_udp.html#controlling_process/2"},{"type":"function","doc":"","title":"gen_udp.open/1","ref":"gen_udp.html#open/1"},{"type":"function","doc":"Open a UDP socket.\n\nThe created socket is bound to the UDP port number `Port`.\nIf `Port == 0`, the underlying OS assigns a free (ephemeral) UDP port;\nuse `inet:port/1` to retrieve it.\n\nThe process that calls this function becomes the `Socket`'s\ncontrolling process (socket owner).","title":"gen_udp.open/2","ref":"gen_udp.html#open/2"},{"type":"function","doc":"- **`list`** - Received `Packet` is delivered as a list.\n\n- **`binary`** - Received `Packet` is delivered as a binary.\n\n- **`{ip, Address}`** - If the local host has many IP addresses,\n this option specifies which one to use.\n\n- **`{ifaddr, Address}`** - Same as `{ip, Address}`.\n\n However, if this instead is a `t:socket:sockaddr_in/0` or\n `t:socket:sockaddr_in6/0` this takes precedence over any value\n previously set with the `ip` options. If the `ip` option comes\n _after_ the `ifaddr` option, it may be used to _update_ its corresponding\n field of the `ifaddr` option (the `addr` field).\n\n- **`{fd, integer() >= 0}`** - If a socket has somehow been opened without\n using `gen_udp`, use this option to pass the file descriptor for it.\n If `Port` is not set to `0` and/or `{ip, ip_address()}` is combined\n with this option, the `fd` is bound to the specified interface\n and port after it is being opened. If these options are not specified,\n it is assumed that the `fd` is already bound appropriately.\n\n- **`inet6`** - Sets up the socket for IPv6.\n\n- **`inet`** - Sets up the socket for IPv4.\n\n- **`local`** - Sets up a Unix Domain Socket. See `t:inet:local_address/0`\n\n- **`{udp_module, module()}`** - Overrides which callback module is used.\n Defaults to `inet_udp` for IPv4 and `inet6_udp` for IPv6.\n\n- **`{multicast_if, Address}`** - Sets the local device for a multicast socket.\n\n- **`{multicast_loop, true | false}`** - When `true`, sent multicast packets\n are looped back to the local sockets.\n\n- **`{multicast_ttl, Integer}`** - Option `multicast_ttl` changes the\n time-to-live (TTL) for outgoing multicast datagrams to control the scope of\n the multicasts.\n\n Datagrams with a TTL of 1 are not forwarded beyond the local network.\n Defaults to `1`.\n\n- **`{add_membership, {MultiAddress, InterfaceAddress}}`** -\n Joins a multicast group.\n\n- **`{drop_membership, {MultiAddress, InterfaceAddress}}`** -\n Leaves a multicast group.\n\n- **`t:option/0`** - See `inet:setopts/2`.\n\nUDP packets are sent with this socket using [`send(Socket, ...)`](`send/3`).\nWhen UDP packets arrive to the `Socket`'s UDP port, and the socket is in\nan _active mode_, the packets are delivered as messages to the\ncontrolling process (socket owner):\n\n```erlang\n{udp, Socket, PeerIP, PeerPort, Packet} % Without ancillary data\n{udp, Socket, PeerIP, PeerPort, AncData, Packet} % With ancillary data\n```\n\n`PeerIP` and `PeerPort` are the address from which `Packet` was sent.\n`Packet` is a list of bytes (`[`[`byte/0`](`t:byte/0`)`]` if option `list`\nis active and a `t:binary/0` if option `binary`is active\n(they are mutually exclusive).\n\nThe message contains an `AncData` field only if any of the socket\n[options](`t:option/0`) [`recvtos`](`m:inet#option-recvtos`),\n[`recvtclass`](`m:inet#option-recvtclass`) or\n[`recvttl`](`m:inet#option-recvttl`) are active.\n\nWhen a socket in `{active, N}` mode (see `inet:setopts/2` for details),\ntransitions to passive (`{active, false}`) mode (`N` counts down to `0`),\nthe controlling process is notified by a message on this form:\n\n```erlang\n{udp_passive, Socket}\n```\n\nIf the OS protocol stack reports an error for the socket, the following\nmessage is sent to the controlling process:\n\n```erlang\n{udp_error, Socket, Reason}\n```\n`Reason` is mostly a [POSIX Error Code](`m:inet#posix-error-codes`).\n\nIf the socket is in _passive mode_ (not in an _active mode_), received data\ncan be retrieved with the`recv/2,3`](`recv/2`) calls. Note that incoming\nUDP packets that are longer than the receive buffer option specifies\ncan be truncated without warning.\n\nThe default value for the receive buffer option is `{recbuf, 8192}`.","title":"UDP socket options - gen_udp.open/2","ref":"gen_udp.html#open/2-udp-socket-options"},{"type":"function","doc":"","title":"gen_udp.recv/2","ref":"gen_udp.html#recv/2"},{"type":"function","doc":"Receive a packet from a socket in _passive mode_.\n\n`Timeout` specifies a time-out in milliseconds.\n\nIf any of the socket [options](`t:option/0`)\n[`recvtos`](`m:inet#option-recvtos`),\n[`recvtclass`](`m:inet#option-recvtclass`)\nor [`recvttl`](`m:inet#option-recvttl`) are active,\nthe `RecvData` tuple contains an `AncData` field,\notherwise it doesn't.","title":"gen_udp.recv/3","ref":"gen_udp.html#recv/3"},{"type":"function","doc":"Send a packet on a connected UDP socket.\n\nTo connect a UDP socket, use `connect/2` or `connect/3`.","title":"gen_udp.send/2","ref":"gen_udp.html#send/2"},{"type":"function","doc":"Equivalent to [`send(Socket, Destination, [], Packet)`](#send-4-AncData).","title":"gen_udp.send/3","ref":"gen_udp.html#send/3"},{"type":"function","doc":"Send a UDP packet to the specified destination.","title":"gen_udp.send/4","ref":"gen_udp.html#send/4"},{"type":"function","doc":"Argument `Host` can be a hostname or a socket address, and `Port`\ncan be a port number or a service name atom. These are resolved to\na `Destination` and then this function is equivalent to\n[`send(Socket, Destination, [], Packet)`](#send-4-AncData)\njust below.\n\n### [](){: #send-4-AncData } With arguments `Destination` and `AncData` _(since OTP 22.1)_\n\nSends a packet to the specified `Destination` with ancillary data `AncData`.\n\n> #### Note {: .info }\n>\n> The ancillary data `AncData` contains options that for this single message\n> override the default options for the socket, an operation that may not be\n> supported on all platforms, and if so return `{error, einval}`. Using more\n> than one of an ancillary data item type may also not be supported.\n> `AncData =:= []` is always supported.","title":"With arguments `Host` and `Port` - gen_udp.send/4","ref":"gen_udp.html#send/4-with-arguments-host-and-port"},{"type":"function","doc":"Sends a packet to the specified `Destination`. Since `Destination`\nis a complete address, `PortZero` is redundant and has to be `0`.\n\nThis is a legacy clause mostly for `Destination = {local, Binary}`\nwhere `PortZero` is superfluous. Equivalent to\n[`send(Socket, Destination, [], Packet)`](#send-4-AncData), right above here.","title":"With arguments `Destination` and `PortZero` _(since OTP 22.1)_ - gen_udp.send/4","ref":"gen_udp.html#send/4-with-arguments-destination-and-portzero-_-since-otp-22-1-_"},{"type":"function","doc":"Send a packet to the specified destination, with ancillary data.\n\nEquvalent to [`send(Socket, Host, Port, Packet)`](`send/4`)\nregarding `Host` and `Port` and also equivalent to\n[`send(Socket, Destination, AncData, Packet)`](#send-4-AncData)\nregarding the ancillary data: `AncData`.","title":"gen_udp.send/5","ref":"gen_udp.html#send/5"},{"type":"type","doc":"","title":"gen_udp.ip6_membership/0","ref":"gen_udp.html#t:ip6_membership/0"},{"type":"type","doc":"IPv6 this multicast interface index (an integer).","title":"gen_udp.ip6_multicast_if/0","ref":"gen_udp.html#t:ip6_multicast_if/0"},{"type":"type","doc":"IP multicast membership.\n\nThe 3-tuple form _isn't_ supported on all platforms.\n'ifindex' defaults to zero (0) on platforms that supports the 3-tuple variant.","title":"gen_udp.ip_membership/0","ref":"gen_udp.html#t:ip_membership/0"},{"type":"type","doc":"","title":"gen_udp.ip_multicast_if/0","ref":"gen_udp.html#t:ip_multicast_if/0"},{"type":"type","doc":"","title":"gen_udp.membership/0","ref":"gen_udp.html#t:membership/0"},{"type":"type","doc":"","title":"gen_udp.multicast_if/0","ref":"gen_udp.html#t:multicast_if/0"},{"type":"type","doc":"","title":"gen_udp.open_option/0","ref":"gen_udp.html#t:open_option/0"},{"type":"type","doc":"","title":"gen_udp.option/0","ref":"gen_udp.html#t:option/0"},{"type":"type","doc":"","title":"gen_udp.option_name/0","ref":"gen_udp.html#t:option_name/0"},{"type":"type","doc":"A socket as returned by [`open/1,2`](`open/1`).","title":"gen_udp.socket/0","ref":"gen_udp.html#t:socket/0"},{"type":"module","doc":"Access to Network protocols.\n\nThis module, together with `m:gen_tcp`, `m:gen_udp` and `m:gen_sctp`\nprovides access to the Network protocols TCP, SCTP and UDP over IP,\nas well as stream and datagram protocols over the local (unix)\naddress domain / protocol domain.\n\nSee also [ERTS User's Guide: Inet Configuration](`e:erts:inet_cfg.md`)\nor more information about how to configure an Erlang runtime system\nfor IP communication.\n\nThe following two Kernel configuration parameters affect the behavior of all\n`m:gen_tcp` sockets opened on an Erlang node:\n\n- `inet_default_connect_options` can contain a list of\n default options used for all sockets created by\n a `gen_tcp:connect/2,3,4`](`gen_tcp:connect/2`) call.\n- `inet_default_listen_options` can contain a list of default options\n used for sockets created by a `gen_tcp:listen/2` call.\n\nFor the [`gen_tcp:accept/1,2`](`gen_tcp:accept/1`) call,\nthe values of the listening socket options are inherited.\nTherefore there is no corresponding application variable for `accept`.\n\nUsing the Kernel configuration parameters above, one can set default options\nfor all TCP sockets on a node, but use this with care. Options such as\n`{delay_send,true}` can be specified in this way. The following is an example\nof starting an Erlang node with all sockets using delayed send:\n\n```text\n$ erl -sname test -kernel \\\ninet_default_connect_options '[{delay_send,true}]' \\\ninet_default_listen_options '[{delay_send,true}]'\n```\n\n**Please note** that the default option `{active, true}` cannot be changed,\nfor internal implementation reasons.\n\nAddresses as inputs to functions can be either a string or a tuple.\nFor example, the IP address 150.236.20.73 can be passed to\n`gethostbyaddr/1`, either as a string `\"150.236.20.73\"`\nor as a tuple `{150, 236, 20, 73}`.\n\n_IPv4 address examples:_\n\n```text\nAddress ip_address()\n------- ------------\n127.0.0.1 {127,0,0,1}\n192.168.42.2 {192,168,42,2}\n```\n\n_IPv6 address examples:_\n\n```erlang\nAddress ip_address()\n------- ------------\n::1 {0,0,0,0,0,0,0,1}\n::192.168.42.2 {0,0,0,0,0,0,(192 bsl 8) bor 168,(42 bsl 8) bor 2}\n::FFFF:192.168.42.2\n {0,0,0,0,0,16#FFFF,(192 bsl 8) bor 168,(42 bsl 8) bor 2}\n3ffe:b80:1f8d:2:204:acff:fe17:bf38\n {16#3ffe,16#b80,16#1f8d,16#2,16#204,16#acff,16#fe17,16#bf38}\nfe80::204:acff:fe17:bf38\n {16#fe80,0,0,0,16#204,16#acff,16#fe17,16#bf38}\n```\n\nFunction `parse_address/1` can be useful:\n\n```erlang\n1> inet:parse_address(\"192.168.42.2\").\n{ok,{192,168,42,2}}\n2> inet:parse_address(\"::FFFF:192.168.42.2\").\n{ok,{0,0,0,0,0,65535,49320,10754}}\n```\n\n[](){: #posix-error-codes } POSIX Error Codes\n---------------------------------------------\n\n- `e2big` - Too long argument list\n- `eacces` - Permission denied\n- `eaddrinuse` - Address already in use\n- `eaddrnotavail` - Cannot assign requested address\n- `eadv` - Advertise error\n- `eafnosupport` - Address family not supported by protocol family\n- `eagain` - Resource temporarily unavailable\n- `ealign` - EALIGN\n- `ealready` - Operation already in progress\n- `ebade` - Bad exchange descriptor\n- `ebadf` - Bad file number\n- `ebadfd` - File descriptor in bad state\n- `ebadmsg` - Not a data message\n- `ebadr` - Bad request descriptor\n- `ebadrpc` - Bad RPC structure\n- `ebadrqc` - Bad request code\n- `ebadslt` - Invalid slot\n- `ebfont` - Bad font file format\n- `ebusy` - File busy\n- `echild` - No children\n- `echrng` - Channel number out of range\n- `ecomm` - Communication error on send\n- `econnaborted` - Software caused connection abort\n- `econnrefused` - Connection refused\n- `econnreset` - Connection reset by peer\n- `edeadlk` - Resource deadlock avoided\n- `edeadlock` - Resource deadlock avoided\n- `edestaddrreq` - Destination address required\n- `edirty` - Mounting a dirty fs without force\n- `edom` - Math argument out of range\n- `edotdot` - Cross mount point\n- `edquot` - Disk quota exceeded\n- `eduppkg` - Duplicate package name\n- `eexist` - File already exists\n- `efault` - Bad address in system call argument\n- `efbig` - File too large\n- `ehostdown` - Host is down\n- `ehostunreach` - Host is unreachable\n- `eidrm` - Identifier removed\n- `einit` - Initialization error\n- `einprogress` - Operation now in progress\n- `eintr` - Interrupted system call\n- `einval` - Invalid argument\n- `eio` - I/O error\n- `eisconn` - Socket is already connected\n- `eisdir` - Illegal operation on a directory\n- `eisnam` - Is a named file\n- `el2hlt` - Level 2 halted\n- `el2nsync` - Level 2 not synchronized\n- `el3hlt` - Level 3 halted\n- `el3rst` - Level 3 reset\n- `elbin` - ELBIN\n- `elibacc` - Cannot access a needed shared library\n- `elibbad` - Accessing a corrupted shared library\n- `elibexec` - Cannot exec a shared library directly\n- `elibmax` - Attempting to link in more shared libraries than system limit\n- `elibscn` - `.lib` section in `a.out` corrupted\n- `elnrng` - Link number out of range\n- `eloop` - Too many levels of symbolic links\n- `emfile` - Too many open files\n- `emlink` - Too many links\n- `emsgsize` - Message too long\n- `emultihop` - Multihop attempted\n- `enametoolong` - Filename too long\n- `enavail` - Unavailable\n- `enet` - ENET\n- `enetdown` - Network is down\n- `enetreset` - Network dropped connection on reset\n- `enetunreach` - Network is unreachable\n- `enfile` - File table overflow\n- `enoano` - Anode table overflow\n- `enobufs` - No buffer space available\n- `enocsi` - No CSI structure available\n- `enodata` - No data available\n- `enodev` - No such device\n- `enoent` - No such file or directory\n- `enoexec` - Exec format error\n- `enolck` - No locks available\n- `enolink` - Link has been severed\n- `enomem` - Not enough memory\n- `enomsg` - No message of desired type\n- `enonet` - Machine is not on the network\n- `enopkg` - Package not installed\n- `enoprotoopt` - Bad protocol option\n- `enospc` - No space left on device\n- `enosr` - Out of stream resources or not a stream device\n- `enosym` - Unresolved symbol name\n- `enosys` - Function not implemented\n- `enotblk` - Block device required\n- `enotconn` - Socket is not connected\n- `enotdir` - Not a directory\n- `enotempty` - Directory not empty\n- `enotnam` - Not a named file\n- `enotsock` - Socket operation on non-socket\n- `enotsup` - Operation not supported\n- `enotty` - Inappropriate device for `ioctl`\n- `enotuniq` - Name not unique on network\n- `enxio` - No such device or address\n- `eopnotsupp` - Operation not supported on socket\n- `eperm` - Not owner\n- `epfnosupport` - Protocol family not supported\n- `epipe` - Broken pipe\n- `eproclim` - Too many processes\n- `eprocunavail` - Bad procedure for program\n- `eprogmismatch` - Wrong program version\n- `eprogunavail` - RPC program unavailable\n- `eproto` - Protocol error\n- `eprotonosupport` - Protocol not supported\n- `eprototype` - Wrong protocol type for socket\n- `erange` - Math result unrepresentable\n- `erefused` - EREFUSED\n- `eremchg` - Remote address changed\n- `eremdev` - Remote device\n- `eremote` - Pathname hit remote filesystem\n- `eremoteio` - Remote I/O error\n- `eremoterelease` - EREMOTERELEASE\n- `erofs` - Read-only filesystem\n- `erpcmismatch` - Wrong RPC version\n- `erremote` - Object is remote\n- `eshutdown` - Cannot send after socket shutdown\n- `esocktnosupport` - Socket type not supported\n- `espipe` - Invalid seek\n- `esrch` - No such process\n- `esrmnt` - Srmount error\n- `estale` - Stale remote file handle\n- `esuccess` - Error 0\n- `etime` - Timer expired\n- `etimedout` - Connection timed out\n- `etoomanyrefs` - Too many references\n- `etxtbsy` - Text file or pseudo-device busy\n- `euclean` - Structure needs cleaning\n- `eunatch` - Protocol driver not attached\n- `eusers` - Too many users\n- `eversion` - Version mismatch\n- `ewouldblock` - Operation would block\n- `exdev` - Cross-device link\n- `exfull` - Message tables full\n- `nxdomain` - Hostname or domain name cannot be found","title":"inet","ref":"inet.html"},{"type":"function","doc":"Cancel a socket monitor.\n\nIf `MRef` is a reference that the calling process obtained by calling\n`monitor/1`, this monitor is removed. If the monitoring is already removed,\nnothing happens.\n\nThe returned value is one of the following:\n\n- **`true`** - The monitor was found and removed. In this case, no `'DOWN'`\n message corresponding to this monitor has been delivered and will not be\n delivered.\n\n- **`false`** - The monitor was not found and couldn't be removed.\n Probably because the monitor has already triggered and there is\n a corresponding `'DOWN'` message in the caller message queue.","title":"inet.cancel_monitor/1","ref":"inet.html#cancel_monitor/1"},{"type":"function","doc":"Close a socket of any type.","title":"inet.close/1","ref":"inet.html#close/1"},{"type":"function","doc":"Format an error code into a `t:string/0`.\n\nReturns a diagnostic error string. For possible POSIX values\nand corresponding strings, see section\n[POSIX Error Codes](#posix-error-codes).","title":"inet.format_error/1","ref":"inet.html#format_error/1"},{"type":"function","doc":"Get the `inet` configuration.\n\nReturns the state of the `inet` configuration database in form of\na list of recorded configuration parameters. For more information, see\n[ERTS User's Guide: Inet Configuration](`e:erts:inet_cfg.md`).\n\nOnly actual parameters with other than default values are returned,\nfor example not directives that specify other sources for configuration\nparameters nor directives that clear parameters.","title":"inet.get_rc/0","ref":"inet.html#get_rc/0"},{"type":"function","doc":"Resolve a host to an address, in a specific addresss family.\n\nReturns the [IP address](`t:ip_address/0`) for `Host` as a tuple of integers.\n`Host` can be an [IP address](`t:ip_address/0`), a single `t:hostname/0`,\nor a fully qualified `t:hostname/0`.","title":"inet.getaddr/2","ref":"inet.html#getaddr/2"},{"type":"function","doc":"Resolve a host to a list of addresses, in a specific address family.\n\nReturns a list of all IP addresses for `Host`.\n`Host` can be an [IP address](`t:ip_address/0`),\na single `t:hostname/0`, or a fully qualified `t:hostname/0`.","title":"inet.getaddrs/2","ref":"inet.html#getaddrs/2"},{"type":"function","doc":"Resolve (reverse) an address to a [`#hostent{}`](`t:hostent/0`) record.\n\nReturns a [`#hostent{}`](`t:hostent/0`) record for the host\nwith the specified address.","title":"inet.gethostbyaddr/1","ref":"inet.html#gethostbyaddr/1"},{"type":"function","doc":"Resolve a hostname to a [`#hostent{}`](`t:hostent/0`) record.\n\nReturns a [`#hostent{}`](`t:hostent/0`) record for the host\nwith the specified `Hostname`.\n\nThis function uses the resolver, which is often the native (OS) resolver.\n\nIf resolver option `inet6` is `true`, an IPv6 address is looked up.\n\nSee [ERTS User's Guide: Inet Configuration](`e:erts:inet_cfg.md`) for\ninformation about the resolver configuration.\n\nA quirk of many resolvers is that an integer string is interpreted\nas an IP address. For instance, the integer string \"3232235521\"\nand the string \"192.168.0.1\" are both translated\nto the IP address `{192,168,0,1}`.","title":"inet.gethostbyname/1","ref":"inet.html#gethostbyname/1"},{"type":"function","doc":"Resolve a hostname to a [`#hostent{}`](`t:hostent/0`) record,\nin a specific address family.\n\nReturns a [`#hostent{}`](`t:hostent/0`) record for the host\nwith the specified `Hostname`, restricted to the specified address `Family`.\n\nSee also `gethostbyname/1`.","title":"inet.gethostbyname/2","ref":"inet.html#gethostbyname/2"},{"type":"function","doc":"Get the local hostname.\n\nReturns the local hostname. Never fails.","title":"inet.gethostname/0","ref":"inet.html#gethostname/0"},{"type":"function","doc":"Get interface names and addresses.\n\nReturns a list of 2-tuples containing interface names and the interfaces'\naddresses. `Ifname` is a Unicode string and `Ifopts` is a list of interface\naddress description tuples.\n\nThe interface address description tuples are documented under\nthe type of the [`Ifopts`](`t:getifaddrs_ifopts/0`) value.","title":"inet.getifaddrs/0","ref":"inet.html#getifaddrs/0"},{"type":"function","doc":"Get interface names and addresses, in a specific namespace.\n\nEquivalent to `getifaddrs/0`, but accepts an `Option`\n`{netns, Namespace}` that, on platforms that support the feature (Linux),\nsets a network namespace for the OS call.\nAlso,\nIf the option 'inet_backend' is *first* in the options list,\nthe specified backend will be used (for 'inet', inet and\nfor 'socket' the equivalent net functions will be used).\n \n\nSee the socket option [`{netns, Namespace}`](#option-netns)\nunder `setopts/2`.","title":"inet.getifaddrs/1","ref":"inet.html#getifaddrs/1"},{"type":"function","doc":"Get one or more options for a socket.\n\nGets all options in the list `Options` from `Socket`.\nSee `setopts/2` for a list of available options. See also\nthe descriptions of protocol specific types referenced by\n[`socket_optval()` ](`t:socket_optval/0`).\n\nThe number of elements in the returned `OptionValues` list does not necessarily\ncorrespond to the number of options asked for. If the operating system fails to\nsupport an option, it is left out in the returned list. An error tuple is\nreturned only when getting options for the socket is impossible (that is, the\nsocket is closed or the buffer size in a raw request is too large). This\nbehavior is kept for backward compatibility reasons.\n\nA raw option request `RawOptReq = {raw, Protocol, OptionNum, ValueSpec}` can be\nused to get information about socket options not (explicitly) supported by the\nemulator. The use of raw socket options makes the code non-portable, but allows\nthe Erlang programmer to take advantage of unusual features present on a\nparticular platform.\n\n`RawOptReq` consists of tag `raw` followed by the protocol level, the option\nnumber, and either a binary or the size, in bytes, of the buffer in which the\noption value is to be stored. A binary is to be used when the underlying\n`getsockopt` requires _input_ in the argument field. In this case, the binary\nsize shall correspond to the required buffer size of the return value. The\nsupplied values in a `RawOptReq` correspond to the second, third, and\nfourth/fifth parameters to the `getsockopt` call in the C socket API. The value\nstored in the buffer is returned as a binary `ValueBin`, where all values are\ncoded in native endianness.\n\nAsking for and inspecting raw socket options require low-level information about\nthe current operating system and TCP stack.\n\n_Example:_\n\nConsider a Linux machine where option `TCP_INFO` can be used to collect TCP\nstatistics for a socket. Assume you are interested in field `tcpi_sacked` of\n`struct tcp_info` filled in when asking for `TCP_INFO`. To be able to access\nthis information, you need to know the following:\n\n- The numeric value of protocol level `IPPROTO_TCP`\n- The numeric value of option `TCP_INFO`\n- The size of `struct tcp_info`\n- The size and offset of the specific field\n\nBy inspecting the headers or writing a small C program, it is found that\n`IPPROTO_TCP` is 6, `TCP_INFO` is 11, the structure size is 92 (bytes), the\noffset of `tcpi_sacked` is 28 bytes, and the value is a 32-bit integer. The\nfollowing code can be used to retrieve the value:\n\n```erlang\nget_tcpi_sacked(Sock) ->\n {ok,[{raw,_,_,Info}]} = inet:getopts(Sock,[{raw,6,11,92}]),\n <<_:28/binary,TcpiSacked:32/native,_/binary>> = Info,\n TcpiSacked.\n```\n\nPreferably, you would check the machine type, the operating system, and the\nKernel version before executing anything similar to this code.","title":"inet.getopts/2","ref":"inet.html#getopts/2"},{"type":"function","doc":"","title":"inet.getstat/1","ref":"inet.html#getstat/1"},{"type":"function","doc":"Get one or more statistics options for a socket.\n\n[`getstat(Socket)`](`getstat/1`) is equivalent to\n[`getstat(Socket, [recv_avg, recv_cnt, recv_dvi, recv_max, recv_oct, send_avg, send_cnt, send_pend, send_max, send_oct])`](`getstat/2`).\n\nThe following options are available:\n\n- **`recv_avg`** - Average size of packets, in bytes, received by the socket.\n\n- **`recv_cnt`** - Number of packets received by the socket.\n\n- **`recv_dvi`** - Average packet size deviation, in bytes, received by the\n socket.\n\n- **`recv_max`** - Size of the largest packet, in bytes, received by the socket.\n\n- **`recv_oct`** - Number of bytes received by the socket.\n\n- **`send_avg`** - Average size of packets, in bytes, sent from the socket.\n\n- **`send_cnt`** - Number of packets sent from the socket.\n\n- **`send_pend`** - Number of bytes waiting to be sent by the socket.\n\n- **`send_max`** - Size of the largest packet, in bytes, sent from the socket.\n\n- **`send_oct`** - Number of bytes sent from the socket.","title":"inet.getstat/2","ref":"inet.html#getstat/2"},{"type":"function","doc":"Equivalent to `i/1` for the protocols `tcp`, `udp`, and `sctp`","title":"inet.i/0","ref":"inet.html#i/0"},{"type":"function","doc":"List network sockets.\n\nWith argument `Proto` equivalent to [`i(Proto, Options)`](`i/2`)\nwhere `Options` is a list of all `t:atom/0`s in `t:i_option/0`.\n\nWith argument `Options`, equivalent to [`i(Proto, Options)](`i/2`)\nfor `Proto`: `tcp`, `udp`, and `sctp`.\n\nWith argument `show_ports` **(since OTP 27.0)** equivalent to\n[`i(Proto, Options)](`i/2`) where `Option` is a list of all\noptions in `t:i_option/0` with `ShowPorts = true`.","title":"inet.i/1","ref":"inet.html#i/1"},{"type":"function","doc":"List network sockets.\n\nLists all TCP, UDP and SCTP sockets on the terminal, those created by\nthe Erlang runtime system as well as by the application.\n\nThe following options are available:\n\n- **`port`** - An internal index of the port.\n\n- **`module`** - The callback module of the socket.\n\n- **`recv`** - Number of bytes received by the socket.\n\n- **`sent`** - Number of bytes sent from the socket.\n\n- **`owner`** - The socket owner process.\n\n- **`local_address`** - The local address of the socket.\n\n- **`foreign_address`** - The address and port of the other end of the\n connection.\n\n- **`state`** - The connection state.\n\n- **`type`** - STREAM or DGRAM or SEQPACKET.\n\nThe `Options` argument may also be **(since OTP 27.0)**:\n\n- **`show_ports`** - Do *not* translate the port numbers\n (of 'local_address' and 'foreign_address') to service name(s).","title":"inet.i/2","ref":"inet.html#i/2"},{"type":"function","doc":"Get information about a socket.\n\nReturns a term containing miscellaneous information about a socket.","title":"inet.info/1","ref":"inet.html#info/1"},{"type":"function","doc":"Convert between an IPv4 address and an IPv4-mapped IPv6 address.\n\nConvert an IPv4 address to an IPv4-mapped IPv6 address or the reverse.\nWhen converting from an IPv6 address all but the 2 low words are ignored\nso this function also works on some other types of IPv6 addresses\nthan IPv4-mapped.","title":"inet.ipv4_mapped_ipv6_address/1","ref":"inet.html#ipv4_mapped_ipv6_address/1"},{"type":"function","doc":"Test for an IP address.\n\nTests if the argument `IPAddress` is an `t:ip_address/0`\nand if so returns `true`, otherwise `false`.","title":"inet.is_ip_address/1","ref":"inet.html#is_ip_address/1"},{"type":"function","doc":"Test for an IPv4 address.\n\nTests if the argument `IPv4Address` is an `t:ip4_address/0`\nand if so returns `true`, otherwise `false`.","title":"inet.is_ipv4_address/1","ref":"inet.html#is_ipv4_address/1"},{"type":"function","doc":"Test for an IPv6 address.\n\nTests if the argument `IPv6Address` is an `t:ip6_address/0`\nand if so returns `true`, otherwise `false`.","title":"inet.is_ipv6_address/1","ref":"inet.html#is_ipv6_address/1"},{"type":"function","doc":"Start a socket monitor.\n\nIf the `Socket` to monitor doesn't exist or when the monitor is triggered,\na `'DOWN'` message is sent that has the following pattern:\n\n```erlang\n\t {'DOWN', MonitorRef, Type, Object, Info}\n```\n\n- **`MonitorRef`** - The return value from this function.\n\n- **`Type`** - The type of socket, can be one of the following\n `t:atom/0`s: `port` or `socket`.\n\n- **`Object`** - The monitored entity, the socket, which triggered the event.\n\n- **`Info`** - Either the termination reason of the socket or `nosock`\n (the `Socket` did not exist when this function was called).\n\nMaking several calls to `inet:monitor/1` for the same `Socket`\nis not an error; one monitor is created per call.\n\nThe monitor is triggered when the socket is closed in any way such as\nan API call, remote end close, closed by signal when owner exits, ...","title":"inet.monitor/1","ref":"inet.html#monitor/1"},{"type":"function","doc":"Parse an `t:ip_address/0` to an IPv4 or IPv6 address string.","title":"inet.ntoa/1","ref":"inet.html#ntoa/1"},{"type":"function","doc":"Parse an IP address string to an `t:ip_address/0`.\n\nReturns an `t:ip4_address/0` or an `t:ip6_address/0` depending\non which parsing that succeeds.\n\nAccepts a short form IPv4 address string like `parse_ipv4_address/1`.","title":"inet.parse_address/1","ref":"inet.html#parse_address/1"},{"type":"function","doc":"Parse (relaxed) an IPv4 address string to an `t:ip4_address/0`.\n\nAccepts a short form IPv4 address string (less than 4 fields)\nsuch as `\"127.1\"` or `\"0x7f000001\"`.","title":"inet.parse_ipv4_address/1","ref":"inet.html#parse_ipv4_address/1"},{"type":"function","doc":"Parse an IPv4 address string to an `t:ip4_address/0`.\n\nRequires an IPv4 address string containing four fields,\nthat is; _not_ a short form address string.","title":"inet.parse_ipv4strict_address/1","ref":"inet.html#parse_ipv4strict_address/1"},{"type":"function","doc":"Parse (relaxed) an IPv6 address string to an `t:ip6_address/0`.\n\nAlso accepts a (relaxed) IPv4 address string like `parse_ipv4_address/1`\nand returns an IPv4-mapped IPv6 address.","title":"inet.parse_ipv6_address/1","ref":"inet.html#parse_ipv6_address/1"},{"type":"function","doc":"Parse an IPv6 address string to an `t:ip6_address/0`.\n\n_Doesn't_ accept an IPv4 address string. An IPv6 address string, though,\nallows an IPv4 tail like this: `\"::127.0.0.1\"`\n(which is the same as `\"::7f00:0001\"`).","title":"inet.parse_ipv6strict_address/1","ref":"inet.html#parse_ipv6strict_address/1"},{"type":"function","doc":"Parse an IP address string to an `t:ip_address/0`.\n\nLike `parse_address/1` but _doesn't_ accept a short form IPv4 address string.","title":"inet.parse_strict_address/1","ref":"inet.html#parse_strict_address/1"},{"type":"function","doc":"Return the address of the socket's remote end.\n\nReturns the address and port for the other end of a connection.\n\nNotice that for SCTP sockets, this function returns only one of\nthe peer addresses of the socket. Function [`peernames/1,2`](`peernames/1`)\nreturns all.","title":"inet.peername/1","ref":"inet.html#peername/1"},{"type":"function","doc":"Equivalent to [`peernames(Socket, 0)`](`peernames/2`).\n\nNotice that the behavior of this function for an SCTP one-to-many style socket\nis not defined by the\n[SCTP Sockets API Extensions](http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13).","title":"inet.peernames/1","ref":"inet.html#peernames/1"},{"type":"function","doc":"Return the addresses of all remote ends of a socket.\n\nReturns a list of all address/port number pairs for the remote end of an\nassociation `Assoc` of a socket.\n\nThis function can return multiple addresses for multihomed sockets,\nsuch as SCTP sockets. For other sockets it returns a one-element list.\n\nNotice that parameter `Assoc` is by the\n[SCTP Sockets API Extensions](http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13)\ndefined to be ignored for one-to-one style sockets.\nWhat the special value `0` means, is unfortunately undefined,\nand hence the behavior for one-to-many style sockets.","title":"inet.peernames/2","ref":"inet.html#peernames/2"},{"type":"function","doc":"Return the local port number for a socket.","title":"inet.port/1","ref":"inet.html#port/1"},{"type":"function","doc":"Set one or more options for a socket.\n\nSets the list of `Options` on `Socket`.\n\nThe following options are available:\n\n- **`{active, true | false | once | N}`** [](){: #option-active } -\n If the value is `true`, which is the default, everything received\n from the socket is sent as messages to the receiving process.\n\n If the value is `false` (passive mode), the process must explicitly receive\n incoming data by calling [`gen_tcp:recv/2,3`](`gen_tcp:recv/2`),\n [`gen_udp:recv/2,3`](`gen_udp:recv/2`), or\n [`gen_sctp:recv/1,2`](`gen_sctp:recv/1`) (depending on the type of socket).\n\n If the value is `once` (`{active, once}`), _one_ data message from the socket\n is sent to the process. To receive one more message,\n [`setopts/2`](`setopts/2`) must be called again with option `{active, once}`.\n\n If the value is an integer `N` in the range -32768 to 32767 (inclusive), the\n value is added to the socket's count of data messages sent to the controlling\n process. A socket's default message count is `0`. If a negative value is\n specified, and its magnitude is equal to or greater than the socket's current\n message count, the socket's message count is set to `0`. Once the socket's\n message count reaches `0`, either because of sending received data messages to\n the process or by being explicitly set, the process is then notified by a\n special message, specific to the type of socket, that the socket has entered\n passive mode. Once the socket enters passive mode, to receive more messages\n [`setopts/2`](`setopts/2`) must be called again to set the socket back into an\n active mode.\n\n When using `{active, once}` or `{active, N}`, the socket changes behavior\n automatically when data is received. This can be confusing in combination with\n connection-oriented sockets (that is, `gen_tcp`), as a socket with\n `{active, false}` behavior reports closing differently than a socket with\n `{active, true}` behavior. To simplify programming, a socket where the peer\n closed, and this is detected while in `{active, false}` mode, still generates\n message `{tcp_closed, Socket}` when set to `{active, once}`, `{active, true}`,\n or `{active, N}` mode. It is therefore safe to assume that message\n `{tcp_closed, Socket}`, possibly followed by socket port termination (depending\n on option `exit_on_close`) eventually appears when a socket changes back and\n forth between `{active, true}` and `{active, false}` mode. However, _when_\n peer closing is detected it is all up to the underlying TCP/IP stack and\n protocol.\n\n Notice that `{active, true}` mode provides no flow control; a fast sender can\n easily overflow the receiver with incoming messages. The same is true for\n `{active, N}` mode, while the message count is greater than zero.\n\n Use active mode only if your high-level protocol provides its own flow control\n (for example, acknowledging received messages) or the amount of data exchanged\n is small. `{active, false}` mode, use of the `{active, once}` mode, or\n `{active, N}` mode with values of `N` appropriate for the application\n to provide flow control. The other side cannot send faster than\n the receiver can read.\n\n- **`{broadcast, Boolean}` (UDP sockets)** [](){: #option-broadcast } -\n Enables/disables permission to send broadcasts.\n\n- **`{buffer, Size}`** [](){: #option-buffer } -\n The size of the user-level buffer used by the driver. Not to be confused\n with options `sndbuf` and `recbuf`, which correspond to the\n Kernel socket buffers. For TCP it is recommended to have\n `val(buffer) >= val(recbuf)` to avoid performance issues because of\n unnecessary copying. For UDP the same recommendation applies, but the max\n should not be larger than the MTU of the network path. `val(buffer)` is\n automatically set to the above maximum when `recbuf` is set. However, as the\n size set for `recbuf` usually become larger, you are encouraged to use\n `getopts/2` to analyze the behavior of your operating system.\n\n Note that this is also the maximum amount of data that can be received from a\n single recv call. If you are using higher than normal MTU consider setting\n buffer higher.\n\n- **`{delay_send, Boolean}`** - Normally, when an Erlang process sends to a\n socket, the driver tries to send the data immediately. If that fails, the\n driver uses any means available to queue up the message to be sent whenever\n the operating system says it can handle it. Setting `{delay_send, true}` makes\n _all_ messages queue up. The messages sent to the network are then larger but\n fewer. The option affects the scheduling of send requests versus Erlang\n processes instead of changing any real property of the socket. The option is\n implementation-specific. Defaults to `false`.\n\n- **`{deliver, port | term}`** - When `{active, true}`, data is delivered on the\n form `port` : `{S, {data, [H1,..Hsz | Data]}}`\n or `term` : `{tcp, S, [H1..Hsz | Data]}`.\n\n- **`{dontroute, Boolean}`** - Enables/disables routing bypass for outgoing\n messages.\n\n- **`{exit_on_close, Boolean}`** - This option is set to `true` by default.\n\n The only reason to set it to `false` is if you want to continue sending data\n to the socket after a close is detected, for example, if the peer uses\n `gen_tcp:shutdown/2` to shut down the write side.\n\n- **`{exclusiveaddruse, Boolean}`** [](){: #option-exclusiveaddruse } -\n Enables/disables exclusive address/port usage on Windows. That is, by enabling\n this option you can prevent other sockets from binding to the same\n address/port. By default this option is disabled. That is, other sockets\n may use the same address/port by setting\n [`{reuseaddr, true}`](#option-reuseaddr) in combination with\n [`{reuseport, true}`](#option-reuseport) unless\n `{exclusiveaddruse, true}` has been set on `Socket`. On non-Windows systems\n this option is silently ignored.\n\n > #### Note {: .info }\n >\n > This option is _currently_ not supported for socket created with\n > `inet_backend = socket`\n\n- **`{header, Size}`** - This option is only meaningful if option `binary` was\n specified when the socket was created. If option `header` is specified, the\n first `Size` number bytes of data received from the socket are elements of a\n list, and the remaining data is a binary specified as the tail of the same\n list. For example, if `Size == 2`, the data received matches\n `[Byte1, Byte2 | Binary]`.\n\n- **`{high_msgq_watermark, Size}`** - The socket message queue is set to a busy\n state when the amount of data on the message queue reaches this limit. Notice\n that this limit only concerns data that has not yet reached the ERTS internal\n socket implementation. Defaults to 8 kB.\n\n Senders of data to the socket are suspended if either the socket message queue\n is busy or the socket itself is busy.\n\n For more information, see options `low_msgq_watermark`, `high_watermark`, and\n `low_watermark`.\n\n Notice that distribution sockets disable the use of `high_msgq_watermark` and\n `low_msgq_watermark`. Instead use the\n [distribution buffer busy limit](`m:erlang#system_info_dist_buf_busy_limit`),\n which is a similar feature.\n\n- **`{high_watermark, Size}` (TCP/IP sockets)** - The socket is set to a busy\n state when the amount of data queued internally by the ERTS socket\n implementation reaches this limit. Defaults to 8 kB.\n\n Senders of data to the socket are suspended if either the socket message queue\n is busy or the socket itself is busy.\n\n For more information, see options `low_watermark`, `high_msgq_watermark`, and\n `low_msqg_watermark`.\n\n- **`{ipv6_v6only, Boolean}`** - Restricts the socket to use only IPv6,\n prohibiting any IPv4 connections. This is only applicable for IPv6 sockets\n (option `inet6`).\n\n On most platforms this option must be set on the socket before associating it\n to an address. It is therefore only reasonable to specify it when creating the\n socket and not to use it when calling function (`setopts/2`) containing this\n description.\n\n The behavior of a socket with this option set to `true` is the only portable\n one. The original idea when IPv6 was new of using IPv6 for all traffic is now\n not recommended by FreeBSD (you can use `{ipv6_v6only,false}` to override the\n recommended system default value), forbidden by OpenBSD (the supported GENERIC\n kernel), and impossible on Windows (which has separate IPv4 and IPv6 protocol\n stacks). Most Linux distros still have a system default value of `false`. This\n policy shift among operating systems to separate IPv6 from IPv4 traffic has\n evolved, as it gradually proved hard and complicated to get a dual stack\n implementation correct and secure.\n\n On some platforms, the only allowed value for this option is `true`, for\n example, OpenBSD and Windows. Trying to set this option to `false`, when\n creating the socket, fails in this case.\n\n Setting this option on platforms where it does not exist is ignored. Getting\n this option with `getopts/2` returns no value, that is, the returned list does\n not contain an `{ipv6_v6only,_}` tuple. On Windows, the option does not exist,\n but it is emulated as a read-only option with value `true`.\n\n Therefore, setting this option to `true` when creating a socket never fails,\n except possibly on a platform where you have customized the kernel to only\n allow `false`, which can be doable (but awkward) on, for example, OpenBSD.\n\n If you read back the option value using `getopts/2` and get no value, the\n option does not exist in the host operating system. The behavior of both an\n IPv6 and an IPv4 socket listening on the same port, and for an IPv6 socket\n getting IPv4 traffic is then no longer predictable.\n\n- **`{keepalive, Boolean}` (TCP/IP sockets)** - Enables/disables periodic\n transmission on a connected socket when no other data is exchanged. If the\n other end does not respond, the connection is considered broken and an error\n message is sent to the controlling process. Defaults to `false`.\n\n- **`{linger, {true|false, Seconds}}`** [](){: #option-linger } -\n Determines the time-out, in seconds, for flushing unsent data\n in the [`close/1`](`close/1`) socket call.\n\n The first component is if linger is enabled, the second component is the\n flushing time-out, in seconds. There are 3 alternatives:\n\n - **`{false, _}`** - close/1 or shutdown/2 returns immediately, not waiting\n for data to be flushed, with closing happening in the background.\n\n - **`{true, 0}`** - Aborts the connection when it is closed. Discards any data\n still remaining in the send buffers and sends RST to the peer.\n\n This avoids TCP's TIME_WAIT state, but leaves open the possibility that\n another \"incarnation\" of this connection being created.\n\n - **`{true, Time} when Time > 0`** - close/1 or shutdown/2 will not return\n until all queued messages for the socket have been successfully sent or the\n linger timeout (Time) has been reached.\n\n- **`{low_msgq_watermark, Size}`** - If the socket message queue is in a busy\n state, the socket message queue is set in a not busy state when the amount of\n data queued in the message queue falls below this limit. Notice that this\n limit only concerns data that has not yet reached the ERTS internal socket\n implementation. Defaults to 4 kB.\n\n Senders that are suspended because of either a busy message queue or a busy\n socket are resumed when the socket message queue and the socket are not busy.\n\n For more information, see options `high_msgq_watermark`, `high_watermark`, and\n `low_watermark`.\n\n Notice that distribution sockets disable the use of `high_msgq_watermark` and\n `low_msgq_watermark`. Instead they use the\n [distribution buffer busy limit](`m:erlang#system_info_dist_buf_busy_limit`),\n which is a similar feature.\n\n- **`{low_watermark, Size}` (TCP/IP sockets)** - If the socket is in a busy\n state, the socket is set in a not busy state when the amount of data queued\n internally by the ERTS socket implementation falls below this limit. Defaults\n to 4 kB.\n\n Senders that are suspended because of a busy message queue or a busy socket\n are resumed when the socket message queue and the socket are not busy.\n\n For more information, see options `high_watermark`, `high_msgq_watermark`, and\n `low_msgq_watermark`.\n\n- **`{mode, Mode :: binary | list}`** - Received `Packet` is delivered as\n defined by `Mode`.\n\n- **`{netns, Namespace :: file:filename_all()}`{: #option-netns }** - Sets a\n network namespace for the socket. Parameter `Namespace` is a filename defining\n the namespace, for example, `\"/var/run/netns/example\"`, typically created by\n command `ip netns add example`. This option must be used in a function call\n that creates a socket, that is, [`gen_tcp:connect/3,4`](`gen_tcp:connect/3`),\n `gen_tcp:listen/2`, [`gen_udp:open/1,2`](`gen_udp:open/1`) or\n [`gen_sctp:open/0,1,2`](`gen_sctp:open/0`), and also `getifaddrs/1`.\n\n This option uses the Linux-specific syscall `setns()`, such as in Linux kernel\n 3.0 or later, and therefore only exists when the runtime system is compiled\n for such an operating system.\n\n The virtual machine also needs elevated privileges, either running as\n superuser or (for Linux) having capability `CAP_SYS_ADMIN` according to the\n documentation for `setns(2)`. However, during testing also `CAP_SYS_PTRACE`\n and `CAP_DAC_READ_SEARCH` have proven to be necessary.\n\n _Example:_\n\n ```text\n setcap cap_sys_admin,cap_sys_ptrace,cap_dac_read_search+epi beam.smp\n ```\n\n Notice that the filesystem containing the virtual machine executable\n (`beam.smp` in the example) must be local, mounted without flag `nosetuid`,\n support extended attributes, and the kernel must support file capabilities.\n All this runs out of the box on at least Ubuntu 12.04 LTS, except that SCTP\n sockets appear to not support network namespaces.\n\n `Namespace` is a filename and is encoded and decoded as discussed in module\n `m:file`, with the following exceptions:\n\n - Emulator flag `+fnu` is ignored.\n - `getopts/2` for this option returns a binary for the filename if the stored\n filename cannot be decoded. This is only to occur if you set the option\n using a binary that cannot be decoded with the emulator's filename encoding:\n `file:native_name_encoding/0`.\n\n- **`{bind_to_device, Ifname :: binary()}`** - Binds a socket to a specific\n network interface. This option must be used in a function call that creates a\n socket, that is, [`gen_tcp:connect/3,4`](`gen_tcp:connect/3`),\n `gen_tcp:listen/2`, [`gen_udp:open/1,2`](`gen_udp:open/1`), or\n [`gen_sctp:open/0,1,2`](`gen_sctp:open/0`).\n\n Unlike `getifaddrs/0`, Ifname is encoded a binary. In the unlikely case that a\n system is using non-7-bit-ASCII characters in network device names, special\n care has to be taken when encoding this argument.\n\n This option uses the Linux-specific socket option `SO_BINDTODEVICE`, such as\n in Linux kernel 2.0.30 or later, and therefore only exists when the runtime\n system is compiled for such an operating system.\n\n Before Linux 3.8, this socket option could be set, but could not retrieved\n with `getopts/2`. Since Linux 3.8, it is readable.\n\n The virtual machine also needs elevated privileges, either running as\n superuser or (for Linux) having capability `CAP_NET_RAW`.\n\n The primary use case for this option is to bind sockets into\n [Linux VRF instances](http://www.kernel.org/doc/Documentation/networking/vrf.txt).\n\n- **`list`** - Received `Packet` is delivered as a list.\n\n- **`binary`** - Received `Packet` is delivered as a binary.\n\n- **`{nodelay, Boolean}` (TCP/IP sockets)** [](){: #option-nodelay } -\n If `Boolean == true`, option `TCP_NODELAY` is turned on for the socket,\n which means that also small amounts of data are sent immediately.\n\n This option is _not_ supported for `domain = local`, but if\n `inet_backend =/= socket` this error will be _ignored_.\n\n- **`{nopush, Boolean}` (TCP/IP sockets)** - This translates to `TCP_NOPUSH` on\n BSD and to `TCP_CORK` on Linux.\n\n If `Boolean == true`, the corresponding option is turned on for the socket,\n which means that small amounts of data are accumulated until a full MSS-worth\n of data is available or this option is turned off.\n\n Note that while `TCP_NOPUSH` socket option is available on OSX, its semantics\n is very different (e.g., unsetting it does not cause immediate send of\n accumulated data). Hence, `nopush` option is intentionally ignored on OSX.\n\n- **`{packet, PacketType}` (TCP/IP sockets)** [](){: #option-packet } -\n Defines the type of packets to use for a socket. Possible values:\n\n - **`raw | 0`** - No packaging is done.\n\n - **`1 | 2 | 4`** - Packets consist of a header specifying the number of bytes\n in the packet, followed by that number of bytes. The header length can be\n one, two, or four bytes, and containing an unsigned integer in big-endian\n byte order. Each send operation generates the header, and the header is\n stripped off on each receive operation.\n\n The 4-byte header is limited to 2Gb.\n\n - **`asn1 | cdr | sunrm | fcgi | tpkt | line`** - These packet types only have\n effect on receiving. When sending a packet, it is the responsibility of the\n application to supply a correct header. On receiving, however, one message\n is sent to the controlling process for each complete packet received, and,\n similarly, each call to `gen_tcp:recv/2,3` returns one complete packet. The\n header is _not_ stripped off.\n\n The meanings of the packet types are as follows:\n\n - `asn1` - ASN.1 BER\n - `sunrm` - Sun's RPC encoding\n - `cdr` - CORBA (GIOP 1.1)\n - `fcgi` - Fast CGI\n - `tpkt` - TPKT format \\[RFC1006]\n - `line` - Line mode, a packet is a line-terminated with newline, lines\n longer than the receive buffer are truncated\n\n - **`http | http_bin`** - The Hypertext Transfer Protocol. The packets are\n returned with the format according to `HttpPacket` described in\n `erlang:decode_packet/3` in ERTS. A socket in passive mode returns\n `{ok, HttpPacket}` from `gen_tcp:recv` while an active socket sends messages\n like `{http, Socket, HttpPacket}`.\n\n - **`httph | httph_bin`** - These two types are often not needed, as the\n socket automatically switches from `http`/`http_bin` to `httph`/`httph_bin`\n internally after the first line is read. However, there can be occasions\n when they are useful, such as parsing trailers from chunked encoding.\n\n- **`{packet_size, Integer}`(TCP/IP sockets)** - Sets the maximum allowed length\n of the packet body. If the packet header indicates that the length of the\n packet is longer than the maximum allowed length, the packet is considered\n invalid. The same occurs if the packet header is too large for the socket\n receive buffer.\n\n For line-oriented protocols (`line`, `http*`), option `packet_size` also\n guarantees that lines up to the indicated length are accepted and not\n considered invalid because of internal buffer limitations.\n\n- **`{line_delimiter, Char}` (TCP/IP sockets)**\n [](){: #option-line_delimiter } -\n Sets the line delimiting character for line-oriented protocols (`line`).\n Defaults to `$\\n`.\n\n- **`{raw, Protocol, OptionNum, ValueBin}`** - See below.\n\n- **`{read_ahead, Boolean}`** [](){: #option-read_ahead } -\n If set to `false` avoids reading ahead from the OS socket layer.\n The default for this option is `true` which speeds up packet header parsing.\n Setting `false` has a performance penalty because the packet header\n has to be read first, to know exactly how many bytes to read for the body,\n which roughly doubles the number of read operations.\n\n The use of this option is essential for example before switching to kTLS\n which activates OS socket layer encryption and decryption by setting\n special (raw) socket options. So if the Erlang socket layer has read ahead,\n it has read bytes that was for the OS socket layer to decrypt,\n which makes packet decryption derail for the connection.\n\n > #### Warning {: .warning }\n >\n > For packet modes that doesn't have the packet length at a fixed location\n > in a packet header, such as `line` or `asn1`, not reading ahead\n > can become very inefficient since sometimes the only way to accomplish\n > this is to read one byte at the time until the length\n > or packet end is found.\n\n- **`{read_packets, Integer}` (UDP sockets)** [](){: #option-read_packets } -\n Sets the maximum number of UDP packets to read without intervention\n from the socket when data is available. When this many packets\n have been read and delivered to the destination process,\n new packets are not read until a new notification of available data\n has arrived. Defaults to `5`. If this parameter is set too high, the system\n can become unresponsive because of UDP packet flooding.\n\n- **`{recbuf, Size}`** [](){: #option-recbuf } -\n The minimum size of the receive buffer to use for the socket.\n You are encouraged to use `getopts/2` to retrieve the size\n set by your operating system.\n\n- **`{recvtclass, Boolean}`** [](){: #option-recvtclass } -\n If set to `true` activates returning the received `TCLASS` value\n on platforms that implements the protocol `IPPROTO_IPV6` option\n `IPV6_RECVTCLASS` or `IPV6_2292RECVTCLASS` for the socket.\n The value is returned as a `{tclass,TCLASS}` tuple regardless of if\n the platform returns an `IPV6_TCLASS` or an `IPV6_RECVTCLASS` CMSG value.\n\n For packet oriented sockets that supports receiving ancillary data with the\n payload data (`gen_udp` and `gen_sctp`), the `TCLASS` value is returned in an\n extended return tuple contained in an\n [ancillary data](`t:ancillary_data/0`) list. For stream oriented sockets\n (`gen_tcp`) the only way to get the `TCLASS` value is if the platform supports\n the [`pktoptions`](`t:gen_tcp:pktoptions_value/0`) option.\n\n- **`{recvtos, Boolean}`** [](){: #option-recvtos } -\n If set to `true` activates returning the received `TOS` value\n on platforms that implements the protocol `IPPROTO_IP` option\n `IP_RECVTOS` for the socket. The value is returned as a `{tos,TOS}` tuple\n regardless of if the platform returns an `IP_TOS` or an `IP_RECVTOS` CMSG\n value.\n\n For packet oriented sockets that supports receiving ancillary data with the\n payload data (`gen_udp` and `gen_sctp`), the `TOS` value is returned in an\n extended return tuple contained in an\n [ancillary data](`t:ancillary_data/0`) list. For stream oriented sockets\n (`gen_tcp`) the only way to get the `TOS` value is if the platform supports\n the [`pktoptions`](`t:gen_tcp:pktoptions_value/0`) option.\n\n- **`{recvttl, Boolean}`** [](){: #option-recvttl } -\n If set to `true` activates returning the received `TTL` value\n on platforms that implements the protocol `IPPROTO_IP` option `IP_RECVTTL`\n for the socket. The value is returned as a `{ttl,TTL}` tuple\n regardless of if the platform returns an `IP_TTL` or an `IP_RECVTTL` CMSG\n value.\n\n For packet oriented sockets that supports receiving ancillary data with the\n payload data (`gen_udp` and `gen_sctp`), the `TTL` value is returned in an\n extended return tuple contained in an\n [ancillary data](`t:ancillary_data/0`) list. For stream oriented sockets\n (`gen_tcp`) the only way to get the `TTL` value is if the platform supports\n the [`pktoptions`](`t:gen_tcp:pktoptions_value/0`) option.\n\n- **`{reuseaddr, Boolean}`[](){: #option-reuseaddr }** -\n Allows or disallows reuse of local address. By default, reuse is disallowed.\n\n > #### Note {: .info }\n >\n > On windows `{reuseaddr, true}` will have no effect unless also\n > [`{reuseport, true}`](#option-reuseport) is set. If both are set,\n > the `SO_REUSEADDR` Windows socket option will be enabled. This since setting\n > `SO_REUSEADDR` on Windows more or less has the same behavior as setting both\n > `SO_REUSEADDR` and `SO_REUSEPORT` on BSD. This behavior was introduced as of\n > OTP 26.0.\n >\n > > #### Change {: .info }\n > >\n > > Previous behavior on Windows:\n > >\n > > - Prior to OTP 25.0, the `{reuseaddr, true}` option was silently ignored.\n > > - Between OTP 25.0 and up to the predecessor of OTP 25.2, the underlying\n > > `SO_REUSEADDR` socket option was set if `{reuseaddr, true}` was set.\n > > - Between OTP 25.2 and up to the predecessor of OTP 26.0, the underlying\n > > `SO_REUSEADDR` socket option was only set on UDP sockets if\n > > `{reuseaddr, true}` was set, and silently ignored on other sockets.\n >\n > See also the [`exclusiveaddruse`](#option-exclusiveaddruse) option.\n\n- **`{reuseport, Boolean}`[](){: #option-reuseport }** -\n Allows or disallows reuse of local port which _may or may not_\n have load balancing depending on the underlying OS. By default,\n reuse is disallowed. See also [`reuseport_lb`](#option-reuseport_lb).\n\n > #### Note {: .info }\n >\n > On windows `{reuseport, true}` will have no effect unless also\n > [`{reuseaddr, true}`](#option-reuseaddr) is set. If both are set,\n > the `SO_REUSEADDR` Windows socket option will be enabled. This since setting\n > `SO_REUSEADDR` on Windows more or less has the same behavior as setting both\n > `SO_REUSEADDR` and `SO_REUSEPORT` on BSD. The `reuseport` option was\n > introduced as of OTP 26.0.\n >\n > See also the [`exclusiveaddruse`](#option-exclusiveaddruse) option.\n\n > #### Note {: .info }\n >\n > `reuseport` _may or may not_ be the same underlying option as\n > [`reuseport_lb`](#option-reuseport_lb) depending on the underlying\n > OS. They, for example, are on Linux. When they are the same underlying\n > option, operating on both may cause them to interact in surprising ways. For\n > example, by enabling `reuseport` and then disabling `reuseport_lb` both will\n > end up being disabled.\n\n > #### Note {: .info }\n >\n > This option is _currently_ not supported for socket created with\n > `inet_backend = socket`\n\n- **`{reuseport_lb, Boolean}`[](){: #option-reuseport_lb }** -\n Allows or disallows reuse of local port _with_ load balancing.\n By default, reuse is disallowed. See also [`reuseport`](#option-reuseport).\n\n > #### Note {: .info }\n >\n > `reuseport_lb` _may or may not_ be the same underlying option as\n > [`reuseport`](#option-reuseport) depending on the underlying OS.\n > On Linux, for example, they are. And when they are the same\n > underlying option, operating on both may cause them to interact\n > in surprising ways. For example, by enabling `reuseport_lb`,\n > and then disabling `reuseport`, both will end up being disabled.\n\n > #### Note {: .info }\n >\n > This option is _currently_ not supported for socket created with\n > `inet_backend = socket`\n\n- **`{send_timeout, Integer}`** - Only allowed for connection-oriented sockets.\n\n Specifies a longest time to wait for a send operation to be accepted by the\n underlying TCP stack. When the limit is exceeded, the send operation returns\n `{error, timeout}`. How much of a packet that got sent is unknown; the socket\n is therefore to be closed whenever a time-out has occurred (see\n `send_timeout_close` below). Defaults to `infinity`.\n\n- **`{send_timeout_close, Boolean}`** - Only allowed for connection-oriented\n sockets.\n\n Used together with `send_timeout` to specify whether the socket is to be\n automatically closed when the send operation returns `{error, timeout}`. The\n recommended setting is `true`, which automatically closes the socket. Defaults\n to `false` because of backward compatibility.\n\n- **`{show_econnreset, Boolean}` (TCP/IP sockets)**\n [](){: #option-show_econnreset } -\n When this option is set to `false`, which is default, an RST\n received from the TCP peer is treated as a normal close\n (as though an FIN was sent). A caller to `gen_tcp:recv/2` gets\n `{error, closed}`. In active mode, the controlling process receives a\n `{tcp_closed, Socket}` message, indicating that the peer has closed the\n connection.\n\n Setting this option to `true` allows you to distinguish between a connection\n that was closed normally, and one that was aborted (intentionally or\n unintentionally) by the TCP peer. A call to `gen_tcp:recv/2` returns\n `{error, econnreset}`. In active mode, the controlling process receives a\n `{tcp_error, Socket, econnreset}` message before the usual\n `{tcp_closed, Socket}`, as is the case for any other socket error. Calls to\n `gen_tcp:send/2` also returns `{error, econnreset}` when it is detected that a\n TCP peer has sent an RST.\n\n A connected socket returned from `gen_tcp:accept/1` inherits the\n `show_econnreset` setting from the listening socket.\n\n- **`{sndbuf, Size}`** [](){: #option-sndbuf } -\n The minimum size of the send buffer to use for the socket.\n You are encouraged to use `getopts/2`, to retrieve the size\n set by your operating system.\n\n- **`{priority, Integer}`** - Sets the `SO_PRIORITY` socket level option on\n platforms where this is implemented. The behavior and allowed range varies\n between different systems. The option is ignored on platforms where it is not\n implemented. Use with caution.\n\n- **`{tos, Integer}`** - Sets `IP_TOS IP` level options on platforms where this\n is implemented. The behavior and allowed range varies between different\n systems. The option is ignored on platforms where it is not implemented. Use\n with caution.\n\n- **`{tclass, Integer}`** - Sets `IPV6_TCLASS IP` level options on platforms\n where this is implemented. The behavior and allowed range varies between\n different systems. The option is ignored on platforms where it is not\n implemented. Use with caution.\n\nIn addition to these options, _raw_ option specifications can be used. The raw\noptions are specified as a tuple of arity four, beginning with tag `raw`,\nfollowed by the protocol level, the option number, and the option value\nspecified as a binary. This corresponds to the second, third, and fourth\narguments to the `setsockopt` call in the C socket API. The option value must be\ncoded in the native endianness of the platform and, if a structure is required,\nmust follow the structure alignment conventions on the specific platform.\n\nUsing raw socket options requires detailed knowledge about the current operating\nsystem and TCP stack.\n\n_Example:_\n\nThis example concerns the use of raw options. Consider a Linux system where you\nwant to set option `TCP_LINGER2` on protocol level `IPPROTO_TCP` in the stack.\nYou know that on this particular system it defaults to 60 (seconds), but you\nwant to lower it to 30 for a particular socket. Option `TCP_LINGER2` is not\nexplicitly supported by `inet`, but you know that the protocol level translates\nto number 6, the option number to number 8, and the value is to be specified as\na 32-bit integer. You can use this code line to set the option for the socket\nnamed `Sock`:\n\n```text\ninet:setopts(Sock, [{raw,6,8,<<30:32/native>>}]),\n```\n\nAs many options are silently discarded by the stack if they are specified out of\nrange; it can be a good idea to check that a raw option is accepted. The\nfollowing code places the value in variable `TcpLinger2:`\n\n```text\n{ok,[{raw,6,8,< >}]}=inet:getopts(Sock,[{raw,6,8,4}]),\n```\n\nCode such as these examples is inherently non-portable, even different versions\nof the same OS on the same platform can respond differently to this kind of\noption manipulation. Use with care.\n\nNotice that the default options for TCP/IP sockets can be changed with the\nKernel configuration parameters mentioned in the beginning of this manual page.","title":"inet.setopts/2","ref":"inet.html#setopts/2"},{"type":"function","doc":"Return the local address and port number for a socket.\n\nNotice that for SCTP sockets this function returns only one of the socket\naddresses. Function [`socknames/1,2`](`socknames/1`) returns all.","title":"inet.sockname/1","ref":"inet.html#sockname/1"},{"type":"function","doc":"Equivalent to [`socknames(Socket, 0)`](`socknames/2`).","title":"inet.socknames/1","ref":"inet.html#socknames/1"},{"type":"function","doc":"Return all localaddresses for a socket.\n\nReturns a list of all local address/port number pairs for a socket,\nfor the specified association `Assoc`.\n\nThis function can return multiple addresses for multihomed sockets,\nsuch as SCTP sockets. For other sockets it returns a one-element list.\n\nNotice that parameter `Assoc` is by the\n[SCTP Sockets API Extensions](http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13)\ndefined to be ignored for one-to-one style sockets. For one-to-many style\nsockets, the special value `0` is defined to mean that the returned addresses\nmust be without any particular association. How different SCTP implementations\ninterpret this varies somewhat.","title":"inet.socknames/2","ref":"inet.html#socknames/2"},{"type":"type","doc":"","title":"inet.address_family/0","ref":"inet.html#t:address_family/0"},{"type":"type","doc":"Ancillary data / control messages.\n\nAncillary data received with a data packet, read with the socket option\n[`pktoptions`](`t:gen_tcp:pktoptions_value/0`) from a TCP socket,\nor to set in a call to [`gen_udp:send/4`](`m:gen_udp#send-4-AncData`)\nor `gen_udp:send/5`.\n\nThe value(s) correspond to the currently active socket\n[options](`t:socket_setopt/0`) [`recvtos`](#option-recvtos),\n[`recvtclass`](#option-recvtclass) and [`recvttl`](#option-recvttl),\nor for a single send operation the option(s) to override\nthe currently active socket option(s).","title":"inet.ancillary_data/0","ref":"inet.html#t:ancillary_data/0"},{"type":"type","doc":"","title":"inet.ether_address/0","ref":"inet.html#t:ether_address/0"},{"type":"type","doc":"A general network address.\n\nA general network address format on the form `{Family, Destination}`\nwhere `Family` is an atom such as `local` and the format of `Destination`\ndepends on `Family`. `Destination` is a complete address (for example\nan IP address with port number).","title":"inet.family_address/0","ref":"inet.html#t:family_address/0"},{"type":"type","doc":"Interface address description list.\n\nA list returned from [`getifaddrs/0,1`](`getifaddrs/0`)\nfor a named interface, translated from the\nreturned data of the POSIX API function `getaddrinfo()`.\n\n`Hwaddr` is hardware dependent, for example, on Ethernet interfaces it is the\n6-byte Ethernet address (MAC address (EUI-48 address)).\n\nThe tuples `{addr,Addr}`, `{netmask,Netmask}`, and possibly\n`{broadaddr,Broadaddr}` or `{dstaddr,Dstaddr}` are repeated in the list\nif the interface has got multiple addresses. An interface may have multiple\n`{flag,_}` tuples for example if it has different flags for different\naddress families.\n\nMultiple `{hwaddr,Hwaddr}` tuples is hard to say anything definite about,\nthough. The tuple `{flag,Flags}` is mandatory, all others are optional.\n\nDo not rely too much on the order of `Flags` atoms or the `Ifopt` tuples.\nThere are however some rules:\n\n- A `{flag,_}` tuple applies to all other tuples that follow.\n- Immediately after `{addr,_}` follows `{netmask,_}`.\n- Immediately thereafter may `{broadaddr,_}` follow if `broadcast`\n is member of `Flags`, or `{dstaddr,_}` if `pointtopoint`\n is member of `Flags`. Both `{dstaddr,_}` and `{broadaddr,_}` doesn't\n occur for the same `{addr,_}`.\n- Any `{netmask,_}`, `{broadaddr,_}`, or `{dstaddr,_}` tuples that follow an\n `{addr,Addr}` tuple concerns the address `Addr`.\n\nThe tuple `{hwaddr,_}` is not returned on Solaris, as the hardware address\nhistorically belongs to the link layer and it is not returned\nby the Solaris API function `getaddrinfo()`.\n\n> #### Warning {: .warning }\n>\n> On Windows, the data is fetched from different OS API functions, so the\n> `Netmask` and `Broadaddr` values may be calculated, just as some `Flags`\n> values.","title":"inet.getifaddrs_ifopts/0","ref":"inet.html#t:getifaddrs_ifopts/0"},{"type":"type","doc":"A record describing a host; name and address.\n\nCorresponds to the `C`: `struct hostent` as returned by for example\n`gethostbyname(3)`.\n\nThe record is defined in the Kernel include file `\"inet.hrl\"`.\n\nAdd the following directive to the module:\n\n```erlang\n-include_lib(\"kernel/include/inet.hrl\").\n```","title":"inet.hostent/0","ref":"inet.html#t:hostent/0"},{"type":"type","doc":"","title":"inet.hostname/0","ref":"inet.html#t:hostname/0"},{"type":"type","doc":"Options for selecting statistics items.\n\nRegarding `ShowPorts`, see `show_ports` as described in the `i/2` function,\ndefaults to `false`.","title":"inet.i_option/0","ref":"inet.html#t:i_option/0"},{"type":"type","doc":"A network address for the `inet6` family (`AF_INET6`, IPv6)\n> #### Warning {: .warning }\n>\n> This address format is currently experimental and for completeness\n> to make all address families have a `{Family, Destination}` representation.","title":"inet.inet6_address/0","ref":"inet.html#t:inet6_address/0"},{"type":"type","doc":"A network address for the `inet` family (`AF_INET`, IPv4)\n> #### Warning {: .warning }\n>\n> This address format is currently experimental and for completeness\n> to make all address families have a `{Family, Destination}` representation.","title":"inet.inet_address/0","ref":"inet.html#t:inet_address/0"},{"type":"type","doc":"Implementation backend selector for `t:socket/0`.\n\nSelects the implementation backend for [sockets](`t:socket/0`.\nThe current default is `inet` which uses `inet_drv.c` to call\nthe platform's socket API. The value `socket` instead uses\nthe `m:socket` module and its NIF implementation.\n\nThis is a _temporary_ option that will be ignored in a future release.","title":"inet.inet_backend/0","ref":"inet.html#t:inet_backend/0"},{"type":"type","doc":"","title":"inet.ip4_address/0","ref":"inet.html#t:ip4_address/0"},{"type":"type","doc":"","title":"inet.ip6_address/0","ref":"inet.html#t:ip6_address/0"},{"type":"type","doc":"","title":"inet.ip_address/0","ref":"inet.html#t:ip_address/0"},{"type":"type","doc":"A network address for the `local` family (`AF_LOCAL | AF_UNIX`)\n\nThis address family, also known as \"Unix domain sockets\" only works\non Unix-like systems.\n\n`File` is normally a file pathname in a local filesystem. It is limited in\nlength by the operating system, traditionally to 108 bytes.\n\nA `t:binary/0` is passed as is to the operating system,\nbut a `t:string/0` is encoded according to the\n[system filename encoding mode.](`file:native_name_encoding/0`)\n\nOther addresses are possible, for example Linux implements\n\"Abstract Addresses\". See the documentation for Unix Domain Sockets\non your system, normally `unix` in manual section 7.\n\nIn most API functions where you can use this address family\nthe port number must be `0`.","title":"inet.local_address/0","ref":"inet.html#t:local_address/0"},{"type":"type","doc":"","title":"inet.module_socket/0","ref":"inet.html#t:module_socket/0"},{"type":"type","doc":"","title":"inet.port_number/0","ref":"inet.html#t:port_number/0"},{"type":"type","doc":"POSIX Error Code `t:atom/0`.\n\nAn atom that is named from the POSIX error codes used in Unix,\nand in the runtime libraries of most C compilers.\nSee section [POSIX Error Codes](#posix-error-codes).","title":"inet.posix/0","ref":"inet.html#t:posix/0"},{"type":"type","doc":"a non-IP network address.\n\nAddresses besides `t:ip_address/0` ones that are returned from\nsocket API functions. See in particular `t:local_address/0`.\nThe `unspec` family corresponds to `AF_UNSPEC` and can occur\nif the other side has no socket address. The `undefined`\nfamily can only occur in the unlikely event of an address family\nthat the VM doesn't recognize.","title":"inet.returned_non_ip_address/0","ref":"inet.html#t:returned_non_ip_address/0"},{"type":"type","doc":"A socket recognized by this module and its siblings.\n\nSee `t:gen_tcp:socket/0` and `t:gen_udp:socket/0`.","title":"inet.socket/0","ref":"inet.html#t:socket/0"},{"type":"type","doc":"","title":"inet.socket_address/0","ref":"inet.html#t:socket_address/0"},{"type":"type","doc":"","title":"inet.socket_getopt/0","ref":"inet.html#t:socket_getopt/0"},{"type":"type","doc":"","title":"inet.socket_optval/0","ref":"inet.html#t:socket_optval/0"},{"type":"type","doc":"","title":"inet.socket_protocol/0","ref":"inet.html#t:socket_protocol/0"},{"type":"type","doc":"","title":"inet.socket_setopt/0","ref":"inet.html#t:socket_setopt/0"},{"type":"type","doc":"","title":"inet.stat_option/0","ref":"inet.html#t:stat_option/0"},{"type":"module","doc":"A rudimentary DNS client.\n\nThis module performs DNS name resolving towards recursive name servers.\n\nSee also [ERTS User's Guide: Inet Configuration](`e:erts:inet_cfg.md`)\nor more information about how to configure an Erlang runtime system for IP\ncommunication, and how to enable this DNS client by defining `'dns'`\nas a lookup method. The DNS client then acts as a backend for\nthe resolving functions in `m:inet`.\n\nThis DNS client can resolve DNS records even if it is not used\nfor normal name resolving in the node.\n\nThis is not a full-fledged resolver, only a DNS client that relies on asking\ntrusted recursive name servers.","title":"inet_res","ref":"inet_res.html"},{"type":"module","doc":"UDP queries are used unless resolver option `usevc` is `true`,\nwhich forces TCP queries. If the query is too large for UDP,\nTCP is used instead. For regular DNS queries, 512 bytes is the size limit.\n\nWhen EDNS is enabled (resolver option `edns` is set to the EDNS version\n(that is; `0` instead of `false`), resolver option `udp_payload_size`\nsets the payload size limit. If a name server replies with the TC bit set\n(truncation), indicating that the answer is incomplete, the query is retried\ntowards the same name server using TCP. Resolver option `udp_payload_size`\nalso sets the advertised size for the maximum allowed reply size,\nif EDNS is enabled, otherwise the name server uses the limit 512 bytes.\nIf the reply is larger, it gets truncated, forcing a TCP requery.\n\nFor UDP queries, resolver options `timeout` and `retry` control\nretransmission. Each name server in the `nameservers` list is tried\nwith a time-out of `timeout`/`retry`. Then all name servers are tried again,\ndoubling the time-out, for a total of `retry` times.\n\n[](){: #servfail_retry_timeout }\n\nBut before all name servers are tried again, there is a (user configurable)\ntime-out, `servfail_retry_timeout`. The point of this is to prevent\nthe new query to be handled by a server's servfail cache (a client\nthat is too eager will actually only get what is in the servfail cache).\nIf there is too little time left of the resolver call's time-out\nto do a retry, the resolver call may return before the call's time-out\nhas expired.\n\nFor queries not using the `search` list, if the query to all `nameservers`\nresults in `{error,nxdomain}` or an empty answer, the same query is tried for\n`alt_nameservers`.","title":"Name Resolving - inet_res","ref":"inet_res.html#module-name-resolving"},{"type":"module","doc":"The following data types concern the resolver:","title":"Resolver Types - inet_res","ref":"inet_res.html#module-resolver-types"},{"type":"module","doc":"The following data types concern the DNS client:","title":"DNS Types - inet_res","ref":"inet_res.html#module-dns-types"},{"type":"module","doc":"This access functions example shows how `lookup/3` can be implemented using\n`resolve/3` from outside the module:\n\n```erlang\nexample_lookup(Name, Class, Type) ->\n case inet_res:resolve(Name, Class, Type) of\n {ok,Msg} ->\n [inet_dns:rr(RR, data)\n || RR <- inet_dns:msg(Msg, anlist),\n inet_dns:rr(RR, type) =:= Type,\n inet_dns:rr(RR, class) =:= Class];\n {error,_} ->\n []\n end.\n```","title":"Example - inet_res","ref":"inet_res.html#module-example"},{"type":"function","doc":"","title":"inet_res.getbyname/2","ref":"inet_res.html#getbyname/2"},{"type":"function","doc":"Resolve a DNS query.\n\nResolves a DNS query of the specified `Type` for the specified host,\nof class`in`. Returns, on success, when resolving a `Type = a|aaaa`\nDNS record, a `#hostent{}` record with `#hostent.h_addrtype = inet|inet6`,\nrespectively; see `t:inet:hostent/0`.\n\nWhen resolving other `Type = dns_rr_type()`:s (of class `in`), also returns\na `#hostent{}` record but with `t:dns_rr_type/0` in `#hostent.h_addrtype`,\nand the resolved `t:dns_data/0` in `#hostent.h_addr_list`; see `t:hostent/0`.\n\nThis function uses resolver option `search` that is a list of domain names.\nIf the name to resolve contains no dots, it is prepended to each domain\nname in the search list, and they are tried in order. If the name\ncontains dots, it is first tried as an absolute name and if that fails,\nthe search list is used. If the name has a trailing dot, it is supposed\nto be an absolute name and the search list is not used.","title":"inet_res.getbyname/3","ref":"inet_res.html#getbyname/3"},{"type":"function","doc":"","title":"inet_res.gethostbyaddr/1","ref":"inet_res.html#gethostbyaddr/1"},{"type":"function","doc":"Backend function used by `inet:gethostbyaddr/1`.","title":"inet_res.gethostbyaddr/2","ref":"inet_res.html#gethostbyaddr/2"},{"type":"function","doc":"Backend functions used by [`inet:gethostbyname/1,2`](`inet:gethostbyname/1`).\n\nIf resolver option `inet6` is `true`, equivalent to\n[`gethostbyname(Name, inet6, infinity)`](`gethostbyname/3`),\notherwise [`gethostbyname(Name, inet, infinity)`](`gethostbyname/3`).","title":"inet_res.gethostbyname/1","ref":"inet_res.html#gethostbyname/1"},{"type":"function","doc":"","title":"inet_res.gethostbyname/2","ref":"inet_res.html#gethostbyname/2"},{"type":"function","doc":"Backend functions used by [`inet:gethostbyname/1,2`](`inet:gethostbyname/1`).\n\nThis function uses resolver option `search` just like\n[`getbyname/2,3`](`getbyname/2`).","title":"inet_res.gethostbyname/3","ref":"inet_res.html#gethostbyname/3"},{"type":"function","doc":"","title":"inet_res.lookup/3","ref":"inet_res.html#lookup/3"},{"type":"function","doc":"","title":"inet_res.lookup/4","ref":"inet_res.html#lookup/4"},{"type":"function","doc":"Look up DNS data.\n\nResolves the DNS data for the record `Name` of the specified\n`Type` and `Class`. On success, filters out the answer records\nwith the correct `Class` and `Type`, and returns a list of their data fields.\nSo, a lookup for type `any` gives an empty answer, as the answer records\nhave specific types that are not `any`. An empty answer or a failed lookup\nreturns an empty list.\n\nCalls [`resolve/*`](`resolve/3`) with the same arguments and filters the result,\nso `Opts` is described for those functions.","title":"inet_res.lookup/5","ref":"inet_res.html#lookup/5"},{"type":"function","doc":"","title":"inet_res.nnslookup/4","ref":"inet_res.html#nnslookup/4"},{"type":"function","doc":"Resolve a DNS query.\n\nLike `nslookup/4` but calls `resolve/5` with both the arguments\n`Opts = [{nameservers, Nameservers}]` and `Timeout`.","title":"inet_res.nnslookup/5","ref":"inet_res.html#nnslookup/5"},{"type":"function","doc":"","title":"inet_res.nslookup/3","ref":"inet_res.html#nslookup/3"},{"type":"function","doc":"Resolve a DNS query.\n\nThis function is a legacy wrapper to `resolve/5` that simplifies\nerrors matching `{error, {Reason, _}}` into `{error, Reason}`\nor `{error, einval}`.\n\nWith argument `Timeout` calls `resolve/5` with `Opts = []`.\n\nWith argument `Nameservers` calls `resolve/5` with\n`Opts = [{nameservers, Nameservers}]` and `Timeout = infinity`.","title":"inet_res.nslookup/4","ref":"inet_res.html#nslookup/4"},{"type":"function","doc":"","title":"inet_res.resolve/3","ref":"inet_res.html#resolve/3"},{"type":"function","doc":"","title":"inet_res.resolve/4","ref":"inet_res.html#resolve/4"},{"type":"function","doc":"Resolve a DNS query.\n\nResolves a DNS query for the specified `Type`, `Class`, and `Name`,\ninto a DNS message possibly containing Resource Records.\nThe returned `t:dns_msg/0` can be examined using access functions\nin `inet_db`, as described in section in [DNS Types](#module-dns-types).\n\nIf `Name` is an `ip_address()`, the domain name to query about is generated\nas the standard reverse `\".IN-ADDR.ARPA.\"` name for an IPv4 address, or the\n`\".IP6.ARPA.\"` name for an IPv6 address. In this case, you most probably\nwant to use `Class = in` and `Type = ptr`, but it is not done automatically.\n\n`Opts` overrides the corresponding resolver options. If option `nameservers`\nis specified, it is assumed that it is the complete list of name serves,\nso resolver option `alt_nameserves` is ignored. However, if option\n`alt_nameserves` is also specified to this function, it is used.\n\nOption `verbose` (or rather `{verbose,true}`) causes diagnostics printout\nthrough [`io:format/2`](`io:format/3`) of queries, replies, retransmissions,\nand so on, similar to utilities such as `dig` and `nslookup`.\n\nOption `nxdomain_reply` (or rather `{nxdomain_reply, true}`) causes NXDOMAIN\nerrors from DNS servers to be returned as `{error, {nxdomain, dns_msg()}}`.\n`t:dns_msg/0` contains the additional sections that where included by the\nanswering server. This is mainly useful to inspect the SOA record\nto get the TTL for negative caching.\n\nIf `Opt` is any atom, it is interpreted as `{Opt,true}` unless\nthe atom string starts with `\"no\"`, making the interpretation `{Opt,false}`.\nFor example, `usevc` is an alias for `{usevc, true}` and `nousevc`\nis an alias for `{usevc, false}`.\n\nOption `inet6` has no effect on this function. You probably want to use\n`Type = a | aaaa` instead.","title":"inet_res.resolve/5","ref":"inet_res.html#resolve/5"},{"type":"type","doc":"","title":"inet_res.dns_class/0","ref":"inet_res.html#t:dns_class/0"},{"type":"type","doc":"DNS record data (content)\n\nThe basic type of each data element is specified in this type.\n\n`Regexp` is a UTF-8 `t:string/0`. The other `t:string/0`s\nare actually Latin-1 strings.","title":"inet_res.dns_data/0","ref":"inet_res.html#t:dns_data/0"},{"type":"type","doc":"A DNS message.\n\nThis is the start of a hierarchy of opaque data structures that can be\nexamined with access functions in `inet_dns`, which return lists of\n`{Field,Value}` tuples. The arity 2 functions return the value\nfor a specified field.\n\n```erlang\ndns_msg() = DnsMsg\n inet_dns:msg(DnsMsg) ->\n [ {header, dns_header()}\n | {qdlist, dns_query()}\n | {anlist, dns_rr()}\n | {nslist, dns_rr()}\n | {arlist, dns_rr()} ]\n inet_dns:msg(DnsMsg, header) -> dns_header() % for example\n inet_dns:msg(DnsMsg, Field) -> Value\n\ndns_header() = DnsHeader\n inet_dns:header(DnsHeader) ->\n [ {id, integer()}\n | {qr, boolean()}\n | {opcode, query | iquery | status | integer()}\n | {aa, boolean()}\n | {tc, boolean()}\n | {rd, boolean()}\n | {ra, boolean()}\n | {pr, boolean()}\n | {rcode, integer(0..16)} ]\n inet_dns:header(DnsHeader, Field) -> Value\n\nquery_type() = axfr | mailb | maila | any | dns_rr_type()\n\ndns_query() = DnsQuery\n inet_dns:dns_query(DnsQuery) ->\n [ {domain, dns_name()}\n | {type, query_type()}\n | {class, dns_class()} ]\n inet_dns:dns_query(DnsQuery, Field) -> Value\n\ndns_rr() = DnsRr\n inet_dns:rr(DnsRr) -> DnsRrFields | DnsRrOptFields\n DnsRrFields = [ {domain, dns_name()}\n | {type, dns_rr_type()}\n | {class, dns_class()}\n | {ttl, integer()}\n | {data, dns_data()} ]\n DnsRrOptFields = [ {domain, dns_name()}\n | {type, opt}\n | {udp_payload_size, integer()}\n | {ext_rcode, integer()}\n | {version, integer()}\n | {z, integer()}\n | {data, dns_data()} ]\n inet_dns:rr(DnsRr, Field) -> Value\n```\n\nThere is an information function for the types above:\n\n```erlang\ninet_dns:record_type(dns_msg()) -> msg;\ninet_dns:record_type(dns_header()) -> header;\ninet_dns:record_type(dns_query()) -> dns_query;\ninet_dns:record_type(dns_rr()) -> rr;\ninet_dns:record_type(_) -> undefined.\n```\n\nSo, `inet_dns:(inet_dns:record_type(X))(X)` converts any of these data\nstructures into a `{Field,Value}` list.","title":"inet_res.dns_msg/0","ref":"inet_res.html#t:dns_msg/0"},{"type":"type","doc":"A string with no adjacent dots.","title":"inet_res.dns_name/0","ref":"inet_res.html#t:dns_name/0"},{"type":"type","doc":"","title":"inet_res.dns_rr_type/0","ref":"inet_res.html#t:dns_rr_type/0"},{"type":"type","doc":"Extended variant of `t:inet:hostent/0`.\n\nAllows `t:dns_rr_type/0` for the\n[`#hostent{}.h_addrtype`](`t:inet:hostent/0`) field, and\n`[`[`dns_data/0`](`t:dns_data/0`)`]` for the\n[`#hostent{}.h_addr_list`](`t:inet:hostent/0`) field.","title":"inet_res.hostent/0","ref":"inet_res.html#t:hostent/0"},{"type":"type","doc":"","title":"inet_res.nameserver/0","ref":"inet_res.html#t:nameserver/0"},{"type":"type","doc":"","title":"inet_res.res_error/0","ref":"inet_res.html#t:res_error/0"},{"type":"type","doc":"","title":"inet_res.res_option/0","ref":"inet_res.html#t:res_option/0"},{"type":"module","doc":"Network interface.\n\nThis module provides an API for the network interface.","title":"net","ref":"net.html"},{"type":"function","doc":"","title":"net.getaddrinfo/1","ref":"net.html#getaddrinfo/1"},{"type":"function","doc":"Network address and service translation.\n\nThis function is the inverse of [`getnameinfo`](`getnameinfo/1`). It converts\nhost and service to a corresponding socket address.\n\nOne of the `Host` and `Service` may be `undefined` but _not_ both.","title":"net.getaddrinfo/2","ref":"net.html#getaddrinfo/2"},{"type":"function","doc":"Return the name of the current host.","title":"net.gethostname/0","ref":"net.html#gethostname/0"},{"type":"function","doc":"","title":"net.getifaddrs/0","ref":"net.html#getifaddrs/0"},{"type":"function","doc":"Get interface addresses.\n\nWith argument 'Filter: get the machines interface addresses,\nfiltered according to `Filter`.\n\nWith argument `Namespace`: equivalent to\n[`getifaddrs(default, Namespace)`](`getifaddrs/2`).","title":"net.getifaddrs/1","ref":"net.html#getifaddrs/1"},{"type":"function","doc":"Get interface addresses in a namespace.\n\nThe same as [`getifaddrs(Filter)`](`getifaddrs/1`) but\nin the specified `Namespace`.","title":"net.getifaddrs/2","ref":"net.html#getifaddrs/2"},{"type":"function","doc":"","title":"net.getnameinfo/1","ref":"net.html#getnameinfo/1"},{"type":"function","doc":"Address-to-name translation in a protocol-independant manner.\n\nThis function is the inverse of [`getaddrinfo`](`getaddrinfo/1`). It converts a\nsocket address to a corresponding host and service.","title":"net.getnameinfo/2","ref":"net.html#getnameinfo/2"},{"type":"function","doc":"","title":"net.getservbyname/1","ref":"net.html#getservbyname/1"},{"type":"function","doc":"Get service by name.\n\nThis function is used to get the port number of the specified protocol\nfor the named service.","title":"net.getservbyname/2","ref":"net.html#getservbyname/2"},{"type":"function","doc":"","title":"net.getservbyport/1","ref":"net.html#getservbyport/1"},{"type":"function","doc":"Get service by name.\n\nThis function is used to get the service name of the specified protocol\nfor the given port number.","title":"net.getservbyport/2","ref":"net.html#getservbyport/2"},{"type":"function","doc":"Mappings between network interface index and names.","title":"net.if_index2name/1","ref":"net.html#if_index2name/1"},{"type":"function","doc":"Mappings between network interface names and indexes.","title":"net.if_name2index/1","ref":"net.html#if_name2index/1"},{"type":"function","doc":"Get network interface names and indexes.","title":"net.if_names/0","ref":"net.html#if_names/0"},{"type":"type","doc":"","title":"net.address_info/0","ref":"net.html#t:address_info/0"},{"type":"type","doc":"Interface addresses and flags.\n\nThis type defines addresses and flags for an interface.\n\n> #### Note {: .info }\n>\n> Not all fields of this map has to be present. The flags field can be used to\n> test for some of the fields. For example `broadaddr` will only be present if\n> the `broadcast` flag is present in flags.","title":"net.ifaddrs/0","ref":"net.html#t:ifaddrs/0"},{"type":"type","doc":"Interface address filtering selector.\n\n- **all** - All interfaces\n\n- **default** - Interfaces with address family `inet` _or_ `inet6`\n\n- **inet | inet6 | packet | link** - Interfaces with _only_ the specified\n address family\n- **hwaddr** - Interfaces with address family `packet` _or_ `link`","title":"net.ifaddrs_filter/0","ref":"net.html#t:ifaddrs_filter/0"},{"type":"type","doc":"Interface address filtering selector `t:function/0`.\n\nFor each `ifaddrs` entry, return either `true` to keep the entry\nor `false` to discard the entry.\n\nFor example, to get an interface list which only contains\nnon-`loopback` `inet` interfaces:\n\n```erlang\nnet:getifaddrs(\n fun (#{ addr := #{family := inet},\n flags := Flags}) ->\n not lists:member(loopback, Flags);\n (_) ->\n false\n end).\n```","title":"net.ifaddrs_filter_fun/0","ref":"net.html#t:ifaddrs_filter_fun/0"},{"type":"type","doc":"Interface address filtering selector map.\n\nThe `family` field can only have the (above) specified values\n(and not all the values of socket:domain()).\nIt can also be a list of values, to cover the situation when\nany of the specified families are accepted.\nFor example, family can be set to `[inet,inet6]` if either `inet` or `inet6`\nis accepted.\n\nThe use of the `flags` field is that any flag provided must exist for the\ninterface.\n\nFor example, if `family` is set to `inet` and `flags` to\n`[broadcast, multicast]` only interfaces with address family `inet`\nand the flags `broadcast` and `multicast` will be listed.","title":"net.ifaddrs_filter_map/0","ref":"net.html#t:ifaddrs_filter_map/0"},{"type":"type","doc":"","title":"net.ifaddrs_flag/0","ref":"net.html#t:ifaddrs_flag/0"},{"type":"type","doc":"","title":"net.ifaddrs_flags/0","ref":"net.html#t:ifaddrs_flags/0"},{"type":"type","doc":"","title":"net.name_info/0","ref":"net.html#t:name_info/0"},{"type":"type","doc":"","title":"net.name_info_flag/0","ref":"net.html#t:name_info_flag/0"},{"type":"type","doc":"","title":"net.name_info_flag_ext/0","ref":"net.html#t:name_info_flag_ext/0"},{"type":"type","doc":"","title":"net.name_info_flags/0","ref":"net.html#t:name_info_flags/0"},{"type":"type","doc":"","title":"net.network_interface_index/0","ref":"net.html#t:network_interface_index/0"},{"type":"type","doc":"","title":"net.network_interface_name/0","ref":"net.html#t:network_interface_name/0"},{"type":"module","doc":"Socket interface.\n\nThis module provides an API for network sockets. Functions are provided to\ncreate, delete and manipulate the sockets as well as sending and receiving data\non them.\n\nThe intent is that it shall be as \"close as possible\" to the OS level socket\ninterface. The only significant addition is that some of the functions, e.g.\n`recv/3`, have a time-out argument.\n\n[](){: #asynchronous-calls }\n\n> #### Note {: .info }\n>\n> #### Asynchronous Calls\n>\n> Some functions feature _asynchronous calls_. This is achieved by setting\n> the `Timeout` argument to `nowait` or to a `Handle ::` `t:reference/0`.\n> See the respective function's type specification.\n>\n> This module has two different implementations of asynchronous calls.\n> One on the _Unix_ family of operating systems:\n> `select` - based on the standard socket interface's\n> `select(3)`/`poll(3)` calls, and one on _Windows_: `completion` -\n> based on asynchronous I/O Completion Ports.\n> The difference shows in the return values and message formats\n> because they have slightly different semantics.\n>\n> #### The `completion` and `select` Return Values\n>\n> For instance, if calling `recv/3` like this;\n> [`recv(Socket, 0, nowait)`](#recv-nowait), when there is\n> no data available for reading, it will return one of:\n>\n> - `{completion, `[`CompletionInfo`](`t:completion_info/0`)`}`\n> - `{select, `[`SelectInfo`](`t:select_info/0`)`}`\n>\n> `CompletionInfo` contains a [CompletionHandle](`t:completion_handle/0`) and\n> `SelectInfo` contains a [SelectHandle](`t:select_handle/0`).\n> Both are types are aliases to `t:reference/0`.\n> When the operation can continue, a `completion` message containing\n> the `CompletionHandle` or a `select` message containing\n> the `SelectHandle` is sent to the calling process.\n>\n> On `select` systems some functions may also return:\n>\n> - `{select, {`[`SelectInfo`](`t:select_info/0`)`, _}`\n>\n> This may happen for sockets of type [`stream`](`t:type/0`) where\n> the stream handling can split the data stream at any point.\n> See the respective function's type specification's return type.\n>\n> #### The `completion` and `select` Messages\n>\n> The `completion` message has the format:\n>\n> - `{'$socket', `[`Socket`](`t:socket/0`)`, completion,\n> {`[`CompletionHandle`](`t:completion_handle/0`)`, CompletionStatus}}`\n>\n> The `select` message has the format:\n>\n> - `{'$socket', `[`Socket`](`t:socket/0`)`, select,\n> `[`SelectHandle`](`t:select_handle/0`)`}`\n>\n> When a `completion` message is received (which contains the _result_\n> of the operation), it means that the operation has been _completed_ with\n> `CompletionStatus :: ok | {error, Reason}`.\n> See the respective function's documentation for possible values\n> of `Reason`, which are the same `{error, Reason}` values\n> that can be returned by the function itself.\n>\n> When a `select` message is received, it only means that the operation\n> _may now continue_, by retrying the operation (which may return\n> a new `{select, _}` value). Some operations are retried by repeating\n> the same function call, and some have a dedicated function variant\n> to be used for the retry. See the respective function's documentation.\n>\n> #### Operation Queuing on `select` Systems\n>\n> On `select` systems, all other processes are _locked out_ until the\n> current process has completed the operation as in a continuation\n> call has returned a value indicating success or failure\n> (not a `select` return). Other processes are queued and get\n> a `select` return which makes them wait for their turn.\n>\n> #### Canceling an operation\n>\n> An operation that is in progress (not completed) may be canceled\n> using `cancel/2` both on `completion` and `select` systems.\n>\n> Canceling an operation ensures that there is no `completion`,\n> `select`, nor `abort` message in the inbox after the `cancel/2` call.\n>\n> #### Using a `Handle`\n>\n> If creating a `t:reference/0` with [`make_ref()`](`erlang:make_ref/0`)\n> and using that as the `Timeout | Handle` argument, the same `Handle`\n> will then be the [`SelectHandle`](`t:select_handle/0`) in the returned\n> `t:select_info/0` and the received `select` message, or be\n> the [`CompletionHandle`](`t:completion_handle/0`) in the returned\n> `t:completion_info/0` and the received `completion` message.\n>\n> The compiler may then optimize a following `receive` statement\n> to only scan the messages that arrive after the `t:reference/0`\n> is created. If the message queue is large this is a big optimization.\n>\n> The `t:reference/0` has to be unique for the call.\n>\n> #### Repeating an Operation on a `select` Systems\n>\n> On`select` systems, if a call would be repeated _before_ the `select`\n> message has been received it replaces the call in progress:\n>\n> ```erlang\n> {select, {select_info, Handle}} = socket:accept(LSock, nowait),\n> {error, timeout} = socket:accept(LSock, 500),\n> :\n> ```\n> Above, `Handle` is _no longer_ valid once the second `accept/2`, call\n> has been made (the first call is automatically canceled).\n> After the second `accept/2` call returns `{error, timeout}`,\n> the accept operation has completed.\n>\n> Note that there is a race here; there is no way to know if the call\n> is repeated _before_ the `select` message is sent since it _may_\n> have been sent just before the repeated call. So now there\n> might be a `select` message containing `Handle` in the inbox.\n>\n> #### The `abort` Message\n>\n> Another message the user must be prepared for\n> (when using `nowait | Handle`) is the `abort` message:\n>\n> - `{'$socket', `[`Socket`](`t:socket/0`)`, abort, Info}`\n>\n> This message indicates that the operation in progress has been aborted.\n> For instance, if the socket has been closed by another process;\n> `Info` will be `{Handle, closed}`.\n\n> #### Note {: .info }\n>\n> Support for IPv6 has been implemented but not _fully_ tested.\n>\n> SCTP has only been partly implemented (and not tested).\n\nThis module was introduced in OTP 22.0, as experimental code.\n* In OTP 22.1, the `nowait` argument was added for many functions,\n and the `cancel/2` and `info/1` functions were also added.\n* In OTP 22.3, the `number_of/0` function was added.\n* In OTP 23.0, the functions [`is_supported/1,2`](`is_supported/1`)\n and the [`open/1,2`](`open/1`) functions with an `FD` argument were added.\n* In OTP 23.1, the `use_registry/1` function was added.\n* In OTP 24.0, the `t:select_handle/0` argument was added for many functions,\n the `cancel/1`, `cancel_monitor/1`, `getopt/3` with tuple options,\n `getopt_native/3`, `info/0`, `monitor/1`, `open/3` with an option list,\n many variants of the [`recv/*`](`recv/2`),\n [`recvfrom/*`](`recvfrom/1`), [`recvmsg/*`](`recvmsg/1`),\n [`send/*`](`send/2`), [`sendmsg/*`](`sendmsg/2`),\n the [`sendto/*`](`sendto/3`) functions,\n the [`sendfile/*`](`sendfile/5`) functions,\n and the `setopt/3`, `setopt_native/3` functions, were added.\n* In OTP 24.1, the [`i/*`](`i/0`) functions were added.\n* In OTP 24.2, the [`ioctl/*`](`ioctl/2`) functions were added.\n* In OTP 26.0, the `t:completion_handle/0` argument was added for\n many functions, and the `cancel/2` function with `t:completion_info/0`\n argument was added. That is: support for Windows asynchronous\n I/O Completion Ports was added. The Unix-ish flavored\n ([select handle](`t:select_handle/0`)) API features could be considered\n no longer experimental.\n* In OTP 27.0, the Windows flavored\n ([completion handle](`t:completion_handle/0`))\n API features could be considered no longer experimental.","title":"socket","ref":"socket.html"},{"type":"module","doc":"```erlang\nclient(SAddr, SPort) ->\n {ok, Sock} = socket:open(inet, stream, tcp),\n ok = socket:connect(Sock, #{family => inet,\n addr => SAddr,\n port => SPort}),\n Msg = <<\"hello\">>,\n ok = socket:send(Sock, Msg),\n ok = socket:shutdown(Sock, write),\n {ok, Msg} = socket:recv(Sock),\n ok = socket:close(Sock).\n\nserver(Addr, Port) ->\n {ok, LSock} = socket:open(inet, stream, tcp),\n ok = socket:bind(LSock, #{family => inet,\n port => Port,\n addr => Addr}),\n ok = socket:listen(LSock),\n {ok, Sock} = socket:accept(LSock),\n {ok, Msg} = socket:recv(Sock),\n ok = socket:send(Sock, Msg),\n ok = socket:close(Sock),\n ok = socket:close(LSock).\n```","title":"Examples - socket","ref":"socket.html#module-examples"},{"type":"function","doc":"Equivalent to [`accept(ListenSocket, infinity)`](`accept/2`).","title":"socket.accept/1","ref":"socket.html#accept/1"},{"type":"function","doc":"Accept a connection on a listening socket.\n\n`ListenSocket` has to be of a connection oriented type\n(types `stream` or `seqpacket`, see `open/1`), and set to listen\n(see `listen/1`).\n\n[](){: #accept-infinity }\n\nIf the `Timeout` argument is `infinity`; accepts the first pending\nincoming connection for the listen socket or wait for one to arrive,\nand return the new connection socket.\n\n[](){: #accept-timeout }\n\nIf the `Timeout` argument is a time-out value (`t:non_neg_integer/0`);\nreturns `{error, timeout}` if no connection has arrived\nafter `Timeout` milliseconds.\n\n[](){: #accept-nowait }\n\nIf the `Handle` argument `nowait` *(since OTP 22.1)*,\nstarts an [asynchronous call](#asynchronous-calls) if the operation\ncouldn't be completed immediately.\n\nIf the `Handle` argument is a `t:select_handle/0`,\n*(since OTP 24.0)*, or on _Windows_, the equivalent\n`t:completion_handle/0` *(since OTP 26.0)*, starts\nan [asynchronous call](#asynchronous-calls) like for `nowait`.\n\nSee the note [Asynchronous Calls](#asynchronous-calls)\nat the start of this module reference manual page.","title":"socket.accept/2","ref":"socket.html#accept/2"},{"type":"function","doc":"Bind a name to a socket.\n\nWhen a socket is created (with [`open`](`open/2`)), it has no address assigned\nto it. `bind` assigns the address specified by the `Addr` argument.\n\nThe rules used for name binding vary between domains.\n\nIf you bind a socket to an address in for example the `inet` or `inet6`\naddress families, with an ephemeral port number (`0`), and want to know\nwhich port that was chosen, you can find out using something like:\n`{ok, #{port := Port}} =`[`socket:sockname(Socket)`](`sockname/1`)","title":"socket.bind/2","ref":"socket.html#bind/2"},{"type":"function","doc":"Cancel an asynchronous call in progress.\n\nCall this function to cancel an [asynchronous call](#asynchronous-calls)\nin progress, that is; it returned a value containing\na `t:completion_info/0` or `t:select_info/0`.\n\nSee the note [Asynchronous Calls](#asynchronous-calls)\nat the start of this module reference manual page.\n\nIf another process tries an operation of the same basic type\n(`accept/1` | `send/2` | `recv/2`) it will be enqueued and notified\nthrough a `select` or `completion` message when the current operation\nand all enqueued before it has been completed. If the current operation\nis canceled by this function it is treated as a completed operation;\nthe process first in queue is notified.\n\nIf [`SelectInfo`](`t:select_info/0`) `|`\n[`CompletionInfo`](`t:completion_info/0`) does not match\nan operation in progress for the calling process, this function returns\n`{error, {invalid, SelectInfo | CompletionInfo}}`.","title":"socket.cancel/2","ref":"socket.html#cancel/2"},{"type":"function","doc":"Cancel a socket monitor.\n\nIf `MRef` is a reference that the calling process obtained by calling\n`monitor/1`, this monitor is removed. If there is no such monitor\nfor the calling process (or MRef doesn't correspond to a monitor),\nnothing happens.\n\nThe returned value is one of the following:\n\n- **`true`** - The monitor was found and removed. In this case, no `'DOWN'`\n message corresponding to this monitor has been delivered and will not be\n delivered.\n\n- **`false`** - The monitor was not found so it couldn't be removed. This\n might be because the monitor has already triggered and there is\n a `'DOWN'` message from this monitor in the caller message queue.","title":"socket.cancel_monitor/1","ref":"socket.html#cancel_monitor/1"},{"type":"function","doc":"Close a socket.\n\n> #### Note {: .info }\n>\n> Note that for `Protocol = tcp` (see `open/3`), although\n> TCP guarantees that when the other side sees the stream close\n> all data that we sent before closing has been delivered,\n> there is no way for us to know that the other side got all data\n> and the stream close. All kinds of network and OS issues\n> may obliterate that.\n>\n> To get such a guarantee we need to implement an in-band acknowledge\n> protocol on the connection, or we can use the [`shutdown`](`shutdown/2`)\n> function to signal that no more data will be sent and then wait\n> for the other end to close the socket. Then we will see our read side\n> getting a socket close. In this way we implement a small\n> acknowledge protocol using `shutdown/2`. The other side cannot\n> know that we ever saw the socket close, but in a client/server\n> scenario that is often not relevant.","title":"socket.close/1","ref":"socket.html#close/1"},{"type":"function","doc":"Finalize a [`connect/3`](#connect-nowait) operation.\n\nSee the note [Asynchronous Calls](#asynchronous-calls)\nat the start of this module reference manual page.\n\nOn `select` systems this function finalizes a connection setup\non a socket, after receiving a `select` message\n`{'$socket',` [`Socket`](`t:socket/0`)`, select,\n`[`SelectHandle`](`t:select_handle/0`)`}`,\nand returns whether the connection setup was successful or not.\n\nInstead of calling this function, for backwards compatibility,\nit is allowed to call [`connect/2,3`](`connect/2`) again,\nbut that incurs more overhead since the connect address and\ntime-out argument are processed in vain.\n\nThe call that completes the connect operation, the second call,\ncannot return a `select` return value.","title":"socket.connect/1","ref":"socket.html#connect/1"},{"type":"function","doc":"Equivalent to\n[`connect(Socket, SockAddr, infinity)`](#connect-infinity).","title":"socket.connect/2","ref":"socket.html#connect/2"},{"type":"function","doc":"Connect the socket to the given address.\n\nThis function connects the socket to the address specified\nby the `SockAddr` argument.\n\nIf a connection attempt is already in progress (by another process),\n`{error, already}` is returned.\n\n> #### Note {: .info }\n>\n> On _Windows_ the socket has to be [_bound_](`bind/2`).\n\n[](){: #connect-infinity }\n\nIf the time-out argument (argument 3) is `infinity` it is\nup to the OS implementation to decide when the connection\nattempt failed and then what to return; probably `{error, etimedout}`.\nThe OS time-out may be very long.\n\n[](){: #connect-timeout }\n\nIf the time-out argument (argument 3) is a time-out value\n(`t:non_neg_integer/0`); return `{error, timeout}`\nif the connection hasn't been established within `Timeout` milliseconds.\n\n> #### Note {: .info }\n>\n> Note that when this call has returned `{error, timeout}`\n> the connection state of the socket is uncertain since the platform's\n> network stack may complete the connection at any time,\n> up to some platform specific time-out.\n>\n> Repeating a connection attempt towards the same address would be ok, but\n> towards a different address could end up with a connection to either address.\n>\n> The safe play is to close the socket and start over.\n>\n> Also note that this applies to canceling a `nowait` connect call\n> described below.\n\n[](){: #connect-nowait }\n\nIf the time-out argument (argument 2) is `nowait` *(since OTP 22.1)*,\nstart an [asynchronous call](#asynchronous-calls) if the operation\ncouldn't be completed immediately.\n\nIf the time-out argument (argument 2) is a `Handle ::` `t:select_handle/0`,\n*(since OTP 24.0)*, or on _Windows_, the equivalent\n`Handle ::` `t:completion_handle/0` *(since OTP 26.0)*,\nstart an [asynchronous call](#asynchronous-calls) like for `nowait`.\n\nSee the note [Asynchronous Calls](#asynchronous-calls)\nat the start of this module reference manual page.\n\nAfter receiving a `select` message call `connect/1`\nto complete the operation.\n\nIf canceling the operation with `cancel/2` see the note above\nabout [connection time-out](#connect-timeout).","title":"socket.connect/3","ref":"socket.html#connect/3"},{"type":"function","doc":"Get the value of a socket option.\n\nGets the value of an OS protocol level socket option, or from\nthe `otp` pseudo protocol level, which is this module's\nimplementation level above the OS protocol levels.\n\nSee the type [otp_socket_option() ](`t:otp_socket_option/0`)\nfor a description of the `otp` protocol level.\n\nSee the type `t:socket_option/0` for which OS protocol level options\nthat this implementation knows about, how they are related to OS option names,\nand if there are known peculiarities with any of them.\n\nWhat options that are valid depends on the OS, and on the kind of socket\n(`t:domain/0`,`t:type/0` and `t:protocol/0`). See the type\n`t:socket_option()` and the\n[socket options ](socket_usage.md#socket_options) chapter\nin the User's Guide for more info.\n\n> #### Note {: .info }\n>\n> Not all options are valid, nor possible to get, on all platforms. That is,\n> even if this `socket` implementation support an option; it doesn't mean\n> that the underlying OS does.","title":"socket.getopt/2","ref":"socket.html#getopt/2"},{"type":"function","doc":"Get a socket option _(backwards compatibility function)_.\n\nEquivalent to [`getopt(Socket, {Level, Opt})`](`getopt/2`),\nor as a special case if\n`Opt = {NativeOpt :: `[`integer/0`](`t:integer/0`)`, ValueSpec}`\nequivalent to\n[`getopt_native(Socket, {Level, NativeOpt}, ValueSpec)`](`getopt_native/3`).\n\nUse `getopt/2` or `getopt_native/3` instead to handle\nthe option level and name as a single term, and to make the\ndifference between known options and native options clear.","title":"socket.getopt/3","ref":"socket.html#getopt/3"},{"type":"function","doc":"Get a \"native\" socket option.\n\nGets a socket option that may be unknown to our implementation, or that has a\ntype not compatible with our implementation, that is; in \"native mode\".\n\nThe socket option may be specified with an ordinary\n[`socket_option()` ](`t:socket_option/0`) tuple, with a known\n[`Level = level()` ](`t:level/0`) and an integer `NativeOpt`,\nor with both an integer `NativeLevel` and `NativeOpt`.\n\nHow to decode the option value has to be specified either with `ValueType`,\nby specifying the `ValueSize` for a `t:binary/0` that will contain the fetched\noption value, or by specifying a `t:binary/0` `ValueSpec` that will be copied\nto a buffer for the `getsockopt()` call to write the value in which will be\nreturned as a new `t:binary/0`.\n\nIf `ValueType` is `integer` a `C` type `(int)` will be fetched, if it is\n`boolean` a `C` type `(int)` will be fetched and converted into a `t:boolean/0`\naccording to the `C` implementation's notion about true and false.\n\nIf an option is valid depends both on the platform and on\nwhat kind of socket it is (`t:domain/0`, `t:type/0` and `t:protocol/0`).\n\nThe integer values for `NativeLevel` and `NativeOpt` as well as the `Value`\nencoding has to be deduced from the header files for the running system.","title":"socket.getopt_native/3","ref":"socket.html#getopt_native/3"},{"type":"function","doc":"Print information to the erlang shell in table format\nfor all sockets.\n\nThe information printed for each socket is specified by the default set\nof `t:info_keys/0` (all keys).\n\nThe sockets that are printed are all sockets created by this\n`socket` module's implementation.","title":"socket.i/0","ref":"socket.html#i/0"},{"type":"function","doc":"Print information to the erlang shell in table format\nfor all sockets.\n\nIf the argument is a list of `t:info_keys/0`, print the specified\ninformation for all sockets. See `i/0`.\n\nOtherwise the same as `i/2` with the same first argument\nand the default information (see `i/0`).","title":"socket.i/1","ref":"socket.html#i/1"},{"type":"function","doc":"Print information to the erlang shell in table format\nfor a selection of sockets.\n\nThe argument [`InfoKeys`](`t:info_keys/0`) specifies which information\nis printed for each socket.\n\nIf the first argument is `Domain` print information for\nall sockets of that specific `t:domain/0`.\n\nIf the first argument is `Proto` print information for\nall sockets of that specific `t:protocol/0`.\n\nIf the first argument is `Type` print information for\nall sockets of that specific `t:type/0`.","title":"socket.i/2","ref":"socket.html#i/2"},{"type":"function","doc":"Get miscellaneous information about this `socket` library.\n\nThe function returns a map with each information item as a key-value pair.\n\n> #### Note {: .info }\n>\n> In order to ensure data integrity, mutexes are taken when needed.\n> So, don't call this function often.","title":"socket.info/0","ref":"socket.html#info/0"},{"type":"function","doc":"Get miscellaneous info about a socket.\n\nThe function returns a map with each information item as a key-value pair\nreflecting the \"current\" state of the socket.\n\n> #### Note {: .info }\n>\n> In order to ensure data integrity, mutexes are taken when needed.\n> So, don't call this function often.","title":"socket.info/1","ref":"socket.html#info/1"},{"type":"function","doc":"Set socket (device) parameters.\n\nThis function retrieves a specific parameter, according to\nthe `GetRequest` argument.\n\n- **`gifconf`** - Get a list of interface (transport layer) addresses.\n\n Result; a list of `t:map/0`s, one for each interface,\n with its name and address.\n\n- **`nread`** - Get the number of bytes immediately available for reading\n *(since OTP 26.1)*.\n\n Result; the number of bytes, `t:integer/0`.\n\n- **`nwrite`** - Get the number of bytes in the send queue\n *(since OTP 26.1)*.\n\n Result; the number of bytes, `t:integer/0`.\n\n- **`nspace`** - Get the free space in the send queue\n *(since OTP 26.1)*.\n\n Result; the number of bytes, `t:integer/0`.\n\n- **`atmark`** - Test if there is OOB (out-of-bound) data waiting to be read\n *(since OTP 26.1)*.\n\n Result; a `t:boolean/0`.\n\n- **`tcp_info`** - Get miscellaneous TCP related information for a\n _connected_ socket *(since OTP 26.1)*.\n\n Result; a `t:map/0` with information items as key-value pairs.\n\n> #### Note {: .info }\n>\n> Not all requests are supported by all platforms.\n> To see if a ioctl request is supported on the current platform:\n>\n> ```erlang\n> \t Request = nread,\n> \t true = socket:is_supported(ioctl_requests, Request),\n> \t :\n> ```","title":"socket.ioctl/2","ref":"socket.html#ioctl/2"},{"type":"function","doc":"Get or set socket (device) parameters.\n\n[](){: #ioctl-get }\n\nThis function retrieves a specific parameter, according to\none of the following `GetRequest` arguments. The third argument is\nthe (lookup) \"key\", identifying the interface, for most requests\nthe name of the interface as a `t:string/0`.\nAlso, see the note above.\n\n- **`gifname`** - Get the name of the interface with the specified index\n (`t:integer/0`).\n\n Result; the name of the interface, `t:string/0`.\n\n- **`gifindex`** - Get the index of the interface with the specified name.\n\n Result; the interface index, `t:integer/0`.\n\n- **`gifaddr`** - Get the address of the interface with the specified name.\n\n Result; the address of the interface, `t:sockaddr/0`.\n\n- **`gifdstaddr`** - Get the destination address of the point-to-point\n interface with the specified name.\n\n Result; the destination address of the interface, `t:sockaddr/0`.\n\n- **`gifbrdaddr`** - Get the broadcast address of the interface with the\n specified name.\n\n Result; broadcast address of the interface, `t:sockaddr/0`.\n\n- **`gifnetmask`** - Get the network mask of the interface with\n the specified name.\n\n Result; the network mask of the interface, `t:sockaddr/0`.\n\n- **`gifhwaddr` | `genaddr`** - Get the hardware address for the interface with the\n specified name.\n\n Result; the hardware address of the interface, `t:sockaddr/0` | `t:binary/0`.\n The family field contains the 'ARPHRD' device type (or an integer).\n\n- **`gifmtu`** - Get the MTU (Maximum Transfer Unit) for the interface with the\n specified name.\n\n Result; MTU of the interface, `t:integer/0`.\n\n- **`giftxqlen`** - Get the transmit queue length of the interface with the\n specified name.\n\n Result; transmit queue length of the interface, `t:integer/0`.\n\n- **`gifflags`** - Get the active flag word of the interface\n with the specified name.\n\n Result; the active flag word of the interface, is a list of\n `t:ioctl_device_flag/0` `|` `t:integer( )`.\n\n[](){: #ioctl-set }\n\nWith the following `SetRequest` argument this function sets\nthe `Value` for the request parameter *(since OTP 26.1)*.\n\n- **`rcvall`** - Enables (or disables) a socket to receive all IPv4 or IPv6\n packages passing through a network interface.\n\n The `Socket` has to be one of:\n\n - **An IPv4 socket** - Created with the address\n [domain `inet`](`t:domain/0`), socket [type `raw`](`t:type/0`)\n and [protocol `ip`](`t:protocol/0`).\n\n - **An IPv6 socket** - Created with the address\n [domain `inet6`](`t:domain/0`), socket [type `raw`](`t:type/0`)\n and [protocol `ipv6`](`t:protocol/0`).\n\n The socket must also be bound to an (explicit) local IPv4 or IPv6 interface\n (`any` isn't allowed).\n\n Setting this IOCTL requires elevated privileges.\n\nWith the following `SetRequest` arguments this function sets\nthe `Value` for the request parameter *(since OTP 26.1)*.\n\n- **`rcvall_igmpmcall`** - Enables (or disables) a socket to receive IGMP\n multicast IP traffic, _without_ receiving any other IP traffic.\n\n The socket has to be created with the address\n [domain `inet`](`t:domain/0`), socket [type `raw`](`t:type/0`)\n and [protocol `igmp`](`t:protocol/0`).\n\n The socket must also be bound to an (explicit) local interface\n (`any` isn't allowed).\n\n The receive buffer must be sufficiently large.\n\n Setting this IOCTL requires elevated privileges.\n\n- **`rcvall_mcall`** - Enables (or disables) a socket to receive all multicast\n IP traffic (as in; all IP packets destined for IP addresses in the range\n 224.0.0.0 to 239.255.255.255).\n\n The socket has to be created with the address\n [domain `inet`](`t:domain/0`), socket [type `raw`](`t:type/0`)\n and [protocol `udp`](`t:protocol/0`).\n\n The socket must also be bound to an (explicit) local interface\n (`any` isn't allowed), And bound to port `0`.\n\n The receive buffer must be sufficiently large.\n\n Setting this IOCTL requires elevated privileges.","title":"socket.ioctl/3","ref":"socket.html#ioctl/3"},{"type":"function","doc":"Set socket (device) parameters.\n\nThis function sets a specific parameter, according to the `SetRequest`\nargument. The `Name` argument is the name of the interface,\nand the `Value` argument is the value to set.\n\nThese operations require elevated privileges.\n\n- **`sifflags`** - Set the the active flag word, `#{Flag => boolean()}`, of the\n interface with the specified name.\n\n Each flag to be changed should be added to the value `t:map/0`,\n with the value `true` if the `Flag` should be set and `false`\n if the flag should be cleared.\n\n- **`sifaddr`** - Set the address, `t:sockaddr/0`, of the interface with the\n specified name.\n\n- **`sifdstaddr`** - Set the destination address, `t:sockaddr/0`, of a\n point-to-point interface with the specified name.\n\n- **`sifbrdaddr`** - Set the broadcast address, `t:sockaddr/0`,\nof the interface with the specified name.\n\n- **`sifnetmask`** - Set the network mask, `t:sockaddr/0`, of the interface\n with the specified name.\n\n- **`sifhwaddr`** - Set the hardware address, `t:sockaddr/0`,\nof the interface with the specified name.\n\n- **`sifmtu`** - Set the MTU (Maximum Transfer Unit), `t:integer/0`,\n for the interface with the specified name.\n\n- **`siftxqlen`** - Set the transmit queue length, `t:integer/0`,\n of the interface with the specified name.","title":"socket.ioctl/4","ref":"socket.html#ioctl/4"},{"type":"function","doc":"Check if a socket feature is supported.\n\nReturns `true` if `supports/0` has a `{Key1, true}` tuple\nor a `{Key1, list()}` tuple in its returned list,\notherwise `false` (also for unknown keys).\n\nExample:\n``` erlang\ntrue = socket:is_supported(local),\n```","title":"socket.is_supported/1","ref":"socket.html#is_supported/1"},{"type":"function","doc":"Check if a socket feature is supported.\n\nReturns `true` if [`supports(Key1)`](`supports/1`) has a `{Key2, true}` tuple\nin its returned list, otherwise `false` (also for unknown keys).\n\nExample:\n``` erlang\ntrue = socket:is_supported(msg_flags, errqueue),\n```","title":"socket.is_supported/2","ref":"socket.html#is_supported/2"},{"type":"function","doc":"Make a socket listen for connections.\n\nEquivalent to [`listen(Socket, Backlog)`](`listen/2`) with a default\nvalue for `Backlog` (currently `5`).","title":"socket.listen/1","ref":"socket.html#listen/1"},{"type":"function","doc":"Make a socket listen for connections.\n\nThe `Backlog` argument states the length of the queue for\nincoming not yet accepted connections.\nExactly how that number is interpreted is up to the OS'\nprotocol stack, but the resulting effective queue length\nwill most probably be perceived as at least that long.\n\n> #### Note {: .info }\n>\n> On _Windows_ the socket has to be _bound_.","title":"socket.listen/2","ref":"socket.html#listen/2"},{"type":"function","doc":"Start a socket monitor.\n\nIf the `Socket` doesn't exist or when later the monitor is triggered,\na `'DOWN'` message is sent to the process that called `monitor/1`\nwith the following pattern:\n\n``` erlang\n\t {'DOWN', MonitorRef, socket, Socket, Info}\n```\n`Info` is the termination reason of the socket or `nosock` if\n`Socket` did not exist when the monitor was started.\n\nMaking several calls to `socket:monitor/1` for the same `Socket` is not an\nerror; each call creates an independent monitor instance.","title":"socket.monitor/1","ref":"socket.html#monitor/1"},{"type":"function","doc":"Return the number of active sockets.","title":"socket.number_of/0","ref":"socket.html#number_of/0"},{"type":"function","doc":"Equivalent to [`open(FD, #{})`](`open/2`).","title":"socket.open/1","ref":"socket.html#open/1"},{"type":"function","doc":"Create a socket.\n\n#### With arguments `Domain` and `Type`\n\nEquivalent to [`open(Domain, Type, default, #{})`](`open/4`).\n\n#### With arguments `FD` and `Opts` *(since OTP 23.0)*\n\nCreates an endpoint for communication (socket) based on\nan already existing file descriptor that must be a socket.\nThis function attempts to retrieve the file descriptor's\n`domain`, `type` and `protocol` from the system.\nThis is however not possible on all platforms;\nin that case they should be specified in `Opts`.\n\nThe `Opts` argument can provide extra information:\n\n- **`domain`** - The file descriptor's communication domain. See also\n\n [`open/2,3,4`](`open/3`).\n\n- **`type`** - The file descriptor's socket type.\n\n See also [`open/2,3,4`](`open/3`).\n\n- **`protocol`** - The file descriptor's protocol. The atom `default` is\n equivalent to the integer protocol number `0` which means the default\n protocol for a given domain and type.\n\n If the protocol can not be retrieved from the platform for the socket, and\n `protocol` is not specified, the default protocol is used, which may\n or may not be correct.\n\n See also [`open/2,3,4`](`open/3`).\n\n- **`dup`** - If `false` don't duplicate the provided file descriptor.\n\n Defaults to `true`; do duplicate the file descriptor.\n\n- **`debug`** - If `true` enable socket debug logging.\n\n Defaults to `false`; don't enable socket debug logging.\n\n- **`use_registry`** - Enable or disable use of the socket registry\n for this socket. This overrides the global setting.\n\n Defaults to the global setting, see `use_registry/1`.\n\n> #### Note {: .info }\n>\n> This function should be used with care\\!\n>\n> On some platforms it is _necessary_ to provide `domain`, `type` and `protocol`\n> since they cannot be retrieved from the platform.\n>\n> On some platforms it is not easy to get hold of a file descriptor\n> to use in this function.","title":"socket.open/2","ref":"socket.html#open/2"},{"type":"function","doc":"Create a socket.\n\n#### With arguments `Domain`, `Type` and `Protocol`\n\nEquivalent to [`open(Domain, Type, Protocol, #{})`](`open/4`).\n\n#### With arguments `Domain`, `Type` and `Opts` *(since OTP 24.0)*\n\nEquivalent to [`open(Domain, Type, default, #{})`](`open/4`).","title":"socket.open/3","ref":"socket.html#open/3"},{"type":"function","doc":"Create a socket.\n\nCreates an endpoint for communication (socket).\n\n`Domain` and `Type` may be `t:integer/0`s, as defined in the platform's\nheader files. The same goes for `Protocol` as defined in the platform's\n`services(5)` database. See also the OS man page for the library call\n`socket(2)`.\n\n> #### Note {: .info }\n>\n> For some combinations of `Domain` and `Type` the platform has got\n> a default protocol that can be selected with `Protocol = default`,\n> and the platform may allow or require selecting the default protocol,\n> or a specific protocol.\n>\n> Examples:\n>\n> - **`socket:open(inet, stream, tcp)`** - It is common that for\n> protocol domain and type `inet,stream` it is allowed to select\n> the `tcp` protocol although that mostly is the default.\n> - **`socket:open(local, dgram)`** - It is common that for\n> the protocol domain `local` it is mandatory to not select a protocol,\n> that is; to select the default protocol.\n\nThe `Opts` argument is intended for \"other\" options.\nThe supported option(s) are described below:\n\n- **`netns: string()`** - Used to set the network namespace during the open\n call. Only supported on Linux.\n\n- **`debug: boolean()`** - Enable or disable debug logging.\n\n Defaults to `false`.\n\n- **`use_registry: boolean()`** - Enable or disable use of the socket registry\n for this socket. This overrides the global value.\n\n Defaults to the global value, see `use_registry/1`.","title":"socket.open/4","ref":"socket.html#open/4"},{"type":"function","doc":"Return the remote address of a socket.\n\nReturns the address of the connected peer, that is,\nthe remote end of the socket.","title":"socket.peername/1","ref":"socket.html#peername/1"},{"type":"function","doc":"Equivalent to [`recv(Socket, 0, [], infinity)`](`recv/4`).","title":"socket.recv/1","ref":"socket.html#recv/1"},{"type":"function","doc":"Receive data on a connected socket.\n\nWith argument `Length`; equivalent to\n[`recv(Socket, Length, [], infinity)`](`recv/4`).\n\nWith argument `Flags`; equivalent to\n[`recv(Socket, 0, Flags, infinity)`](`recv/4`) *(since OTP 24.0)*.","title":"socket.recv/2","ref":"socket.html#recv/2"},{"type":"function","doc":"Receive data on a connected socket.\n\nWith arguments `Length` and `Flags`; equivalent to\n[`recv(Socket, Length, Flags, infinity)`](`recv/4`).\n\nWith arguments `Length` and `TimeoutOrHandle`; equivalent to\n[`recv(Socket, Length, [], TimeoutOrHandle)`](`recv/4`).\n`TimeoutOrHandle :: nowait` has been allowed *since OTP 22.1*.\n`TimeoutOrHandle :: Handle` has been allowed *since OTP 24.0*.\n\nWith arguments `Flags` and `TimeoutOrHandle`; equivalent to\n[`recv(Socket, 0, Flags, TimeoutOrHandle)`](`recv/4`)\n*(since OTP 24.0)*.","title":"socket.recv/3","ref":"socket.html#recv/3"},{"type":"function","doc":"Receive data on a connected socket.\n\nThe argument `Length` specifies how many bytes to receive,\nwith the special case `0` meaning \"all available\".\n\nWhen `Length` is `0`, a default buffer size is used, which can be set by\n[`socket:setopt(Socket, {otp,recvbuf}, BufSz)`](`setopt/3`).\n\nThe message `Flags` may be symbolic `t:msg_flag/0`s and/or\n`t:integer/0`s as in the platform's appropriate header files.\nThe values of all symbolic flags and integers are or:ed together.\n\nWhen there is a socket error this function returns `{error, Reason}`,\nor if some data arrived before the error; `{error, {Reason, Data}}`\n(can only happen for a socket of [type `stream`](`t:type/0`)).\n\n[](){: #recv-infinity }\n\nIf the `Timeout` argument is `infinity`; waits for the data to arrive.\nFor a socket of [type `stream`](`t:type/0`) this call\nwon't return until _all_ requested data can be delivered,\nor if \"all available\" was requested when the first data chunk arrives,\nor if the OS reports an error for the operation.\n\n[](){: #recv-timeout }\n\nIf the `Timeout` argument is a time-out value\n(`t:non_neg_integer/0`); return `{error, timeout}`\nif no data has arrived after `Timeout` milliseconds,\nor `{error, {timeout, Data}}` if some but not enough data\nhas been received on a socket of [type `stream`](`t:type/0`).\n\n`Timeout = 0` only polls the OS receive call and doesn't\nengage the Asynchronous Calls mechanisms. If no data\nis immediately available `{error, timeout} is returned.\n`On a socket of type [`stream`](`t:type/0`), `{error, {timeout, Data}}`\nis returned if there is an insufficient amount of data immediately available.\n\n[](){: #recv-nowait }\n\nIf the `Handle` argument is `nowait` *(since OTP 22.1)*,\nstarts an [asynchronous call](#asynchronous-calls) if the operation\ncouldn't be completed immediately.\n\nIf the `Handle` argument is a `t:select_handle/0`,\n*(since OTP 24.0)*, or on _Windows_, the equivalent\n`t:completion_handle/0` *(since OTP 26.0)*, starts\nan [asynchronous call](#asynchronous-calls) like for `nowait`.\n\nSee the note [Asynchronous Calls](#asynchronous-calls)\nat the start of this module reference manual page.\n\nOn `select` systems, for a socket of type [`stream`](`t:type/0`),\nif `Length > 0` and there isn't enough data available, this function\nwill return [`{select, {SelectInfo, Data}}`](`t:select_info/0`)\nwith partial `Data`. A repeated call to complete the operation\nwill probably need an updated `Length` argument.","title":"socket.recv/4","ref":"socket.html#recv/4"},{"type":"function","doc":"Equivalent to [`recvfrom(Socket, 0, [], infinity)`](`recvfrom/4`).","title":"socket.recvfrom/1","ref":"socket.html#recvfrom/1"},{"type":"function","doc":"Receive a message on a socket.\n\nWith argument `BufSz`; equivalent to\n[`recvfrom(Socket, BufSz, [], infinity)`](`recvfrom/4`).\n\nWith argument `Flags`; equivalent to\n[`recvfrom(Socket, 0, Flags, infinity)`](`recvfrom/4`) *(since OTP 24.0)*.","title":"socket.recvfrom/2","ref":"socket.html#recvfrom/2"},{"type":"function","doc":"Receive a message on a socket.\n\nWith arguments `BufSz` and `Flags`; equivalent to\n[`recvfrom(Socket, BufSz, Flags, infinity)`](`recvfrom/4`).\n\nWith arguments `BufSz` and `TimeoutOrHandle`; equivalent to\n[`recv(Socket, BufSz, [], TimeoutOrHandle)`](`recvfrom/4`).\n\nWith arguments `Flags` and `TimeoutOrHandle`; equivalent to\n[`recv(Socket, 0, Flags, TimeoutOrHandle)`](`recvfrom/4`)\n\n`TimeoutOrHandle :: 'nowait'` has been allowed *since OTP 22.1*.\n\n`TimeoutOrHandle :: Handle` has been allowed *since OTP 24.0*.","title":"socket.recvfrom/3","ref":"socket.html#recvfrom/3"},{"type":"function","doc":"Receive a message on a socket.\n\nThis function is intended for sockets that are not connection\noriented such as type [`dgram`](`t:type/0`) or [`seqpacket`](`t:type/0`)\nwhere it may arrive messages from different source addresses.\n\nArgument `BufSz` specifies the number of bytes for the receive buffer.\nIf the buffer size is too small, the message will be truncated.\n\nIf `BufSz` is `0`, a default buffer size is used, which can be set by\n[`socket:setopt(Socket, {otp,recvbuf}, BufSz)`](`setopt/3`).\n\nIf there is no known appropriate buffer size, it may be possible\nto use the receive [message flag](`t:msg_flag/0`) `peek`.\nWhen this flag is used, the message is _not_ \"consumed\" from\nthe underlying buffers, so another `recvfrom/1,2,3,4` call\nis needed, possibly with an adjusted buffer size.\n\nThe message `Flags` may be symbolic `t:msg_flag/0`s and/or\n`t:integer/0`s, as in the platform's appropriate header files.\nThe values of all symbolic flags and integers are or:ed together.\n\n[](){: #recvfrom-infinity }\n\nIf the `Timeout` argument is `infinity`; waits for a message\nto arrive, or for a socket error.\n\n[](){: #recvfrom-timeout }\n\nIf the `Timeout` argument is a time-out value\n(`t:non_neg_integer/0`); returns `{error, timeout}`\nif no message has arrived after `Timeout` milliseconds.\n\n`Timeout = 0` only polls the OS receive call and doesn't\nengage the Asynchronous Calls mechanisms. If no message\nis immediately available `{error, timeout}` is returned.\n\n[](){: #recvfrom-nowait }\n\nIf the `Handle` argument is `nowait` *(since OTP 22.1)*,\nstarts an [asynchronous call](#asynchronous-calls) if the operation\ncouldn't be completed immediately.\n\nIf the 'Handle' argument is a `t:select_handle/0`,\n*(since OTP 24.0)*, or on _Windows_, the equivalent\n`t:completion_handle/0` *(since OTP 26.0)*,\nstarts an [asynchronous call](#asynchronous-calls) like for `nowait`.\n\nSee the note [Asynchronous Calls](#asynchronous-calls)\nat the start of this module reference manual page.","title":"socket.recvfrom/4","ref":"socket.html#recvfrom/4"},{"type":"function","doc":"Equivalent to [`recvmsg(Socket, 0, 0, [], infinity)`](`recvmsg/5`).","title":"socket.recvmsg/1","ref":"socket.html#recvmsg/1"},{"type":"function","doc":"Receive a message on a socket.\n\nWith argument `Flags`; equivalent to\n[`recvmsg(Socket, 0, 0, Flags, infinity)`](`recvmsg/5`).\n\nWith argument `TimeoutOrHandle`; equivalent to\n[`recvmsg(Socket, 0, 0, [], TimeoutOrHandle)`](`recvmsg/5`).\n\n`TimeoutOrHandle :: nowait` has been allowed *since OTP 22.1*.\n\n`TimeoutOrHandle :: Handle` has been allowed *since OTP 24.0*.","title":"socket.recvmsg/2","ref":"socket.html#recvmsg/2"},{"type":"function","doc":"Receive a message on a socket.\n\nWith arguments `Flags`; equivalent to\n[`recvmsg(Socket, 0, 0, Flags, infinity)`](`recvmsg/5`).\n\nWith argument `TimeoutOrHandle`; equivalent to\n[`recvmsg(Socket, 0, 0, [], TimeoutOrHandle)`](`recvmsg/5`).\n\n`TimeoutOrHandle :: nowait` has been allowed *since OTP 22.1*.\n\n`TimeoutOrHandle :: Handle` has been allowed *since OTP 24.0*.","title":"socket.recvmsg/3","ref":"socket.html#recvmsg/3"},{"type":"function","doc":"Equivalent to\n[`recvmsg(Socket, BufSz, CtrlSz, [], TimeoutOrHandle)`](`recvmsg/5`).","title":"socket.recvmsg/4","ref":"socket.html#recvmsg/4"},{"type":"function","doc":"Receive a message on a socket.\n\nThis function receives both data and control messages.\n\nArguments `BufSz` and `CtrlSz` specifies the number of bytes for the\nreceive buffer and the control message buffer. If the buffer size(s)\nis(are) too small, the message and/or control message list will be truncated.\n\nIf `BufSz` is `0`, a default buffer size is used, which can be set by\n[`socket:setopt(Socket, {otp,recvbuf}, BufSz)`](`setopt/3`).\nThe same applies to `CtrlSz` and\n[`socket:setopt(Socket, {otp,recvctrlbuf}, CtrlSz)`](`setopt/3`).\n\nIf there is no known appropriate buffer size, it may be possible\nto use the receive [message flag](`t:msg_flag/0`) `peek`.\nWhen this flag is used, the message is _not_ \"consumed\" from\nthe underlying buffers, so another `recvfrom/1,2,3,4` call\nis needed, possibly with an adjusted buffer size.\n\nThe message `Flags` may be symbolic `t:msg_flag/0`s and/or\n`t:integer/0`s, as in the platform's appropriate header files.\nThe values of all symbolic flags and integers are or:ed together.\n\n[](){: #recvmsg-infinity }\n\nIf the `Timeout` argument is `infinity`; waits for the message\nto arrive, or for a socket error.\n\n[](){: #recvmsg-timeout }\n\nIf the `Timeout` argument is a time-out value\n(`t:non_neg_integer/0`); return `{error, timeout}`\nif no message has arrived after `Timeout` milliseconds.\n\n`Timeout = 0` only polls the OS receive call and doesn't\nengage the Asynchronous Calls mechanisms. If no message\nis immediately available `{error, timeout}` is returned.\n\n[](){: #recvmsg-nowait }\n\nIf the `Handle` argument is `nowait` *(since OTP 22.1)*,\nstarts an [asynchronous call](#asynchronous-calls) if the operation\ncouldn't be completed immediately.\n\nIf the 'Handle' argument is a `t:select_handle/0`,\n*(since OTP 24.0)*, or on _Windows_, the equivalent\n`t:completion_handle/0` *(since OTP 26.0)*,\nstarts an [asynchronous call](#asynchronous-calls) like for `nowait`.\n\nSee the note [Asynchronous Calls](#asynchronous-calls)\nat the start of this module reference manual page.","title":"socket.recvmsg/5","ref":"socket.html#recvmsg/5"},{"type":"function","doc":"Equivalent to [`send(Socket, Data, [], infinity)`](`send/4`).","title":"socket.send/2","ref":"socket.html#send/2"},{"type":"function","doc":"Send data on a connected socket.\n\nWith argument `Timeout`; equivalent to\n[`send(Socket, Data, [], Timeout)`](`send/4`).\n\nWith argument `Flags`; equivalent to\n[`send(Socket, Data, Flags, infinity)`](`send/4`).\n\nWith argument `Cont`; equivalent to\n[`send(Socket, Data, Cont, infinity)`](`send/4`) *(since OTP 24.0)*.","title":"socket.send/3","ref":"socket.html#send/3"},{"type":"function","doc":"Send data on a connected socket.\n\nThe message `Flags` may be symbolic `t:msg_flag/0`s and/or\n`t:integer/0`s as in the platform's appropriate header files.\nThe values of all symbolic flags and integers are or:ed together.\n\nThe `Data`, if it is not a `t:binary/0`, is copied into one before\ncalling the platform network API, because a single buffer is required.\nA returned `RestData` is a sub binary of it.\n\nThe return value indicates the result from the platform's network layer:\n\n- **`ok`** - All data was accepted by the OS for delivery\n\n- **`{ok, RestData}`** - Some but not all data was accepted,\n but no error was reported (partially successful send). `RestData`\n is the tail of `Data` that wasn't accepted.\n\n This cannot happen for a socket of [type `stream`](`t:type/0`) where\n such a partially successful send is retried until the data is either\n accepted for delivery or there is an error.\n\n For a socket of [type `dgram`](`t:type/0`) this should probably\n also not happen since a message that cannot be passed atomically\n should render an error.\n\n It is nevertheless possible for the platform's network layer\n to return this, surely more possible for a socket of\n [type `seqpacket`](`t:type/0`).\n\n- **`{error, Reason}`** - An error has been reported and no data\n was accepted for delivery. [`Reason :: posix/0`](`t:posix/0`)\n is what the platform's network layer reported. `closed` means\n that this socket library was informed that the socket was closed,\n and `t:invalid/0` means that this socket library found\n an argument to be invalid.\n\n- **`{error, {Reason, RestData}}`** - An error was reported but before that\n some data was accepted for delivery. `RestData` is the tail of `Data`\n that wasn't accepted. See `{error, Reason}` above.\n\n This can only happen for a socket of [type `stream`](`t:type/0`)\n when a partially successful send is retried until there is an error.\n\n[](){: #send-infinity }\n\nIf the `Timeout` argument is `infinity`; wait for the OS to\ncomplete the send operation (take responsibility for the data),\nor return an error.\n\n[](){: #send-timeout }\n\nIf the `Timeout` argument is a time-out value\n(`t:non_neg_integer/0`); return `{error, timeout}`\nif no data has been sent within `Timeout` millisecond,\nor `{error, {timeout, RestData}}` if some data was sent\n(accepted by the OS for delivery). `RestData` is the tail of the data\nthat hasn't been sent.\n\n[](){: #send-nowait }\n\nIf the `Handle` argument is `nowait` *(since OTP 22.1)*,\nstarts an [asynchronous call](#asynchronous-calls) if the operation\ncouldn't be completed immediately.\n\nIf the `Handle` argument is a `t:select_handle/0`,\n*(since OTP 24.0)*, or on _Windows_, the equivalent\n`t:completion_handle/0` *(since OTP 26.0)*, starts\nan [asynchronous call](#asynchronous-calls) like for `nowait`.\n\nSee the note [Asynchronous Calls](#asynchronous-calls)\nat the start of this module reference manual page.\n\n[](){: #send-cont }\n\nIf the function is called with a `Cont` argument, that is;\nthe [`SelectInfo`](`t:select_info/0`) from the previous\n[`send/3,4`](`send/3`) call; the send is continued with\npreprocessed send parameters in the `SelectInfo`.\nUsing this argument variant avoids for example having to validate\nand encode message flags in every call but the first.","title":"socket.send/4","ref":"socket.html#send/4"},{"type":"function","doc":"Send a file on a socket.\n\nEquivalent to\n[`sendfile(Socket, FileHandle_or_Continuation, 0, 0, infinity)`](`sendfile/5`).","title":"socket.sendfile/2","ref":"socket.html#sendfile/2"},{"type":"function","doc":"Send a file on a socket.\n\nEquivalent to\n[`sendfile(Socket, FileHandle_or_Continuation, 0, 0, Timeout_or_Handle)`](`sendfile/5`).","title":"socket.sendfile/3","ref":"socket.html#sendfile/3"},{"type":"function","doc":"Send a file on a socket.\n\nEquivalent to\n[`sendfile(Socket, FileHandle_or_Continuation, Offset, Count, infinity)`](`sendfile/5`).","title":"socket.sendfile/4","ref":"socket.html#sendfile/4"},{"type":"function","doc":"Send a file on a socket.\n\n> #### Note {: .info }\n> This function unsupported on Windows.\n\nThe `FileHandle` argument must refer to an open raw file\nas described in `file:open/2`.\n\nThe `Offset` argument is the file offset to start reading from.\nThe default offset is `0`.\n\nThe `Count` argument is the number of bytes to transfer\nfrom `FileHandle` to `Socket`. If `Count = 0` (the default)\nthe transfer stops at the end of file.\n\nThe return value indicates the result from the platform's network layer:\n\n- **`{ok, BytesSent}`** - The transfer completed successfully after `BytesSent`\n bytes of data.\n\n- **`{error, Reason}`** - An error has been reported and no data\n was transferred. [`Reason :: posix/0`](`t:posix/0`)\n is what the platform's network layer reported. `closed` means\n that this socket library was informed that the socket was closed,\n and `t:invalid/0` means that this socket library found\n an argument to be invalid.\n\n- **`{error, {Reason, BytesSent}}`** - An error has been reported\n but before that some data was transferred. See `{error, Reason}`\n and `{ok, BytesSent}` above.\n\n[](){: #sendfile-infinity }\n\nIf the `Timeout` argument is `infinity`; wait for the OS to\ncomplete the send operation (take responsibility for the data),\nor return an error.\n\n[](){: #sendfile-timeout }\n\nIf the `Timeout` argument is a time-out value\n(`t:non_neg_integer/0`); return `{error, timeout}`\nif no data has been sent within `Timeout` millisecond,\nor `{error, {timeout, BytesSent}}` if some but not all data was sent\n(accepted by the OS for delivery).\n\n[](){: #sendfile-nowait }\n\nIf the `Handle` argument is `nowait`,\nstarts an [asynchronous call](#asynchronous-calls) if the operation\ncouldn't be completed immediately.\n\nIf the `Handle` argument is a `t:select_handle/0`, starts\nan [asynchronous call](#asynchronous-calls) like for `nowait`.\n\nSee the note [Asynchronous Calls](#asynchronous-calls)\nat the start of this module reference manual page.\n\nAfter receiving a `select` message call [`sendfile/2,3,4,5`](`sendfile/2`)\nwith `SelectInfo` as the `Continuation` argument, to complete the operation.\n\n[](){: #sendfile-cont }\n\nIf the function is called with a `Continuation` argument, that is;\nthe [`SelectInfo`](`t:select_info/0`) from the previous\n`sendfile/5` call; the transfer is continued with\npreprocessed parameters in the `SelectInfo`.\n\nThe `Offset` and maybe `Count` arguments will probably\nneed to be updated between continuation calls.","title":"socket.sendfile/5","ref":"socket.html#sendfile/5"},{"type":"function","doc":"Equivalent to [`sendmsg(Socket, Msg, [], infinity)`](`sendmsg/4`).","title":"socket.sendmsg/2","ref":"socket.html#sendmsg/2"},{"type":"function","doc":"Send data and control messages on a socket.\n\nWith arguments `Msg` and `Timeout`; equivalent to\n[`sendmsg(Socket, Msg, [], Timeout)`](`sendmsg/4`).\n\nWith arguments `Msg` and `Flags`; equivalent to\n[`sendmsg(Socket, Msg, Flags, infinity)`](`sendmsg/4`).\n\nWith arguments `Data` and `Cont`; equivalent to\n[`sendmsg(Socket, Data, Cont, infinity)`](`sendmsg/4`) *since OTP 24.0*.","title":"socket.sendmsg/3","ref":"socket.html#sendmsg/3"},{"type":"function","doc":"Send data and control messages on a socket.\n\nThe argument `Msg` is a map that contains the data to be sent\nunder the key `iov` as an`t:erlang:iovec/0` (list of `t:binary/0`).\nIt may also contain the destination address under the key `addr`,\nwhich is mandatory if the socket isn't connected. If the socket\n_is_ connected it is best to not have an `addr` key since\nthe platform may regard that as an error (or ignore it).\nUnder the key `ctrl` there may be a list of protocol and platform dependent\ncontrol messages (a.k.a ancillary data, a.k.a control information)\nto send.\n\n[](){: #sendmsg-iov }\n\nThe message data is given to the platform's network layer as an\nI/O vector without copying the content. If the number of elements\nin the I/O vector is larger than allowed on the platform (reported\nin the [`iov_max`](`t:info/0`) field from `info/0`), on a socket of\n[type `stream`](`t:type/0`) the send is iterated over all elements,\nbut for other socket types the call fails.\n\nSee `send/4` for a description of the `Flags` argument\nand the return values.\n\n> #### Note {: .info }\n>\n> On Windows, this function can only be used with datagram and raw sockets.\n\n[](){: #sendmsg-infinity }\n\nIf the `Timeout` argument is `infinity`; wait for the OS to\ncomplete the send operation (take responsibility for the data),\nor return an error.\n\n[](){: #sendmsg-timeout }\n\nIf the `Timeout` argument is a time-out value\n(`t:non_neg_integer/0`); return `{error, timeout}`\nif no data has been sent within `Timeout` millisecond,\nor `{error, {timeout, RestData}}` if some data was sent\n(accepted by the OS for delivery). `RestData` is the tail of the data\nthat hasn't been sent.\n\n[](){: #sendmsg-nowait }\n\nIf the `Handle` argument is `nowait` *(since OTP 22.1)*,\nstarts an [asynchronous call](#asynchronous-calls) if the operation\ncouldn't be completed immediately.\n\nIf the `Handle` argument is a `t:select_handle/0`,\n*(since OTP 24.0)*, or on _Windows_, the equivalent\n`t:completion_handle/0` *(since OTP 26.0)*, starts\nan [asynchronous call](#asynchronous-calls) like for `nowait`.\n\nSee the note [Asynchronous Calls](#asynchronous-calls)\nat the start of this module reference manual page.\n\nAfter receiving a `select` message call [`sendmsg/3,4`](`sendmsg/3`)\nwith `SelectInfo` as the `Cont` argument, to complete the operation.\n\n[](){: #sendmsg-cont }\n\nWith the arguments `Data` and [`Cont`](`t:select_info/0`),\ncontinues the send operation. `Cont` should be\nthe [`SelectInfo`](`t:select_info/0`) returned from the previous\n[`sendmsg/2,3,4`](`sendmsg/2`) call.\n\n`Data` can be a [`Msg`](`t:msg_send/0`) `t:map/0`\nwhere only the key `iov` is used, or an `t:erlang:iovec/0`.","title":"socket.sendmsg/4","ref":"socket.html#sendmsg/4"},{"type":"function","doc":"Send data on a socket.\n\nWith argument `Dest`; equivalent to\n[`sendto(Socket, Data, Dest, [], infinity)`](`sendto/5`).\n\nWith argument `Cont`; equivalent to\n[`sendto(Socket, Data, Cont, infinity)`](`sendto/4`) *since OTP 24.0*.","title":"socket.sendto/3","ref":"socket.html#sendto/3"},{"type":"function","doc":"Send data on a socket.\n\nWith arguments `Dest` and `TimeoutOrHandle`; equivalent to\n[`sendto(Socket, Data, Dest, [], TimeoutOrHandle)`](`sendto/5`).\n\nWith arguments `Dest` and `Flags`; equivalent to\n[`sendto(Socket, Data, Dest, Flags, infinity)`](`sendto/5`).\n\nWith arguments `Cont` and `TimeoutOrHandle`; `Cont` must be\nthe [`SelectInfo`](`t:select_info/0`) from the previous\n[`sendto/3,4,5`](`sendto/3`) call and the send is continued with\npreprocessed send parameters in the `SelectInfo`.\nUsing this argument variant avoids for example having o validate\nand encode message flags in every call but the first.\n*(Since OTP 24.0)*\n\nSee the last argument (argument 5) of `sendto/5` for\nan explanation of `TimeoutOrHandle`.","title":"socket.sendto/4","ref":"socket.html#sendto/4"},{"type":"function","doc":"Send data on a socket.\n\nThe `To` argument is the destination address where to send the data.\nFor a connected socket this argument is still passed to the OS call\nthat may ignore the address or return an error.\n\nSee `send/4` for a description of the `Flags` and `Data` arguments,\nand the return values.\n\n[](){: #sendto-infinity }\n\nIf the `Timeout` argument is `infinity`; wait for the OS to\ncomplete the send operation (take responsibility for the data),\nor return an error.\n\n[](){: #sendto-timeout }\n\nIf the `Timeout` argument is a time-out value\n(`t:non_neg_integer/0`); return `{error, timeout}`\nif no data has been sent within `Timeout` millisecond,\nor `{error, {timeout, RestData}}` if some data was sent\n(accepted by the OS for delivery). `RestData` is the tail of the data\nthat hasn't been sent.\n\n[](){: #sendto-nowait }\n\nIf the `Handle` argument is `nowait` *(since OTP 22.1)*,\nstarts an [asynchronous call](#asynchronous-calls) if the operation\ncouldn't be completed immediately.\n\nIf the `Handle` argument is a `t:select_handle/0`,\n*(since OTP 24.0)*, or on _Windows_, the equivalent\n`t:completion_handle/0` *(since OTP 26.0)*, starts\nan [asynchronous call](#asynchronous-calls) like for `nowait`.\n\nSee the note [Asynchronous Calls](#asynchronous-calls)\nat the start of this module reference manual page.\n\nAfter receiving a `select` message call [`sendto/3,4`](`sendto/3`)\nwith `SelectInfo` as the `Cont` argument, to complete the operation.","title":"socket.sendto/5","ref":"socket.html#sendto/5"},{"type":"function","doc":"","title":"socket.sendv/2","ref":"socket.html#sendv/2"},{"type":"function","doc":"Send `t:erlang:iovec/0` data on a connected socket.\n\nSee [`sendmsg/4`](#sendmsg-iov) about how the [`IOV`](`t:erlang:iovec/0`)\ndata is handled towards the platform's network layer.\n\nThe return value indicates the result from the platform's network layer:\n\n- **`ok`** - All data has been accepted by the OS for delivery.\n\n- **`{ok, RestIOV}`** - Some but not all data was accepted,\n but no error was reported (partially successful send). `RestIOV`\n is the tail of `IOV` that wasn't accepted.\n\n- **`{error, Reason}`** - An error has been reported and no data\n was accepted for delivery. [`Reason :: posix/0`](`t:posix/0`)\n is what the platform's network layer reported. `closed` means\n that this socket library was informed that the socket was closed,\n and `t:invalid/0` means that this socket library found\n an argument to be invalid.\n\n- **`{error, {Reason, RestIOV}}`** - - An error was reported but before that\n some data was accepted for delivery. `RestIOV` is the tail of `IOV`\n that wasn't accepted. See `{error, Reason}` above.\n\n[](){: #sendv-infinity }\n\nIf the `Timeout` argument is `infinity`; wait for the OS to\ncomplete the send operation (take responsibility for the data),\nor return an error.\n\n[](){: #sendv-timeout }\n\nIf the `Timeout` argument is a time-out value\n(`t:non_neg_integer/0`); return `{error, timeout}`\nif no data has been sent within `Timeout` millisecond,\nor `{error, {timeout, RestIOV}}` if some data was sent\n(accepted by the OS for delivery). `RestIOV` is the tail of the data\nthat hasn't been sent.\n\n[](){: #sendv-nowait }\n\nIf the `Handle` argument is `nowait`,\nstarts an [asynchronous call](#asynchronous-calls) if the operation\ncouldn't be completed immediately.\n\nIf the `Handle` argument is a `t:select_handle/0`,\nor on _Windows_, the equivalent `t:completion_handle/0`, starts\nan [asynchronous call](#asynchronous-calls) like for `nowait`.\n\nSee the note [Asynchronous Calls](#asynchronous-calls)\nat the start of this module reference manual page.\n\n[](){: #sendv-cont }\n\nWith the argument [`Cont`](`t:select_info/0`), equivalent to\n[`sendv(Socket, IOV, Cont, infinity)`](`sendv/4`).","title":"socket.sendv/3","ref":"socket.html#sendv/3"},{"type":"function","doc":"Send data on a connected socket, continuation.\n\nContinues sending data on a connected socket.\n`Cont` is the [`SelectInfo`](`t:select_info/0`) returned from\nthe previous [`sendv/2,3`](`sendv/2`) call.\n`IOV` should be the rest data that wasn't sent.\n\nSee [asynchronous calls](#asynchronous-calls) about continuing\nunfinished calls.\n\nSee `sendv/3` about the return values.","title":"socket.sendv/4","ref":"socket.html#sendv/4"},{"type":"function","doc":"Set a socket option.\n\nSet an OS protocol level option, or an `otp` pseudo protocol level option.\nThe latter level is this module's implementation level above\nthe OS protocol levels.\n\nSee the type [otp_socket_option() ](`t:otp_socket_option/0`)\nfor a description of the `otp` protocol level.\n\nSee the type `t:socket_option/0` for which OS protocol level options\nthat this implementation knows about, how they are related to OS option names,\nand if there are known peculiarities with any of them.\n\nWhat options that are valid depends on the OS, and on the kind of socket\n(`t:domain/0`,`t:type/0` and `t:protocol/0`). See the type\n`t:socket_option()` and the\n[socket options ](socket_usage.md#socket_options) chapter\nin the User's Guide for more info.\n\n> #### Note {: .info }\n>\n> Not all options are valid, nor possible to set, on all platforms. That is,\n> even if this `socket` implementation support an option; it doesn't mean\n> that the underlying OS does.","title":"socket.setopt/3","ref":"socket.html#setopt/3"},{"type":"function","doc":"Set a socket option _(backwards compatibility function)_.\n\nEquivalent to [`setopt(Socket, {Level, Opt}, Value)`](`setopt/3`),\nor as a special case if `Opt = NativeOpt ::` `t:integer/0`\nand `Value =` `t:binary/0` equivalent to\n[`setopt_native(Socket, {Level, NativeOpt}, ValueSpec)`](`setopt_native/3`).\n\nUse `setopt/3` or `setopt_native/3` instead to handle\nthe option level and name as a single term, and to make the\ndifference between known options and native options clear.","title":"socket.setopt/4","ref":"socket.html#setopt/4"},{"type":"function","doc":"Set a \"native\" socket option.\n\nSets a socket option that may be unknown to our implementation, or that has a\ntype not compatible with our implementation, that is; in \"native mode\".\n\nIf `Value` is an `t:integer/0` it will be used as a `C` type `(int)`,\nif it is a `t:boolean/0` it will be used as a `C` type `(int)`\nwith the `C` implementations values for `false` or `true`,\nand if it is a `t:binary/0` its content and size will be used\nas the option value.\n\nThe socket option may be specified with an ordinary\n`t:socket_option/0` tuple, with a symbolic `Level` as\n`{`[`Level :: level/0`](`t:level/0`)`, `[`NativeOpt :: integer/0`](`t:integer/0`)`}`,\nor with integers for both `NativeLevel` and `NativeOpt` as\n`{`[`NativeLevel :: integer/0`](`t:integer/0`)`, `[`NativeOpt :: integer/0`](`t:integer/0`)`}`.\n\nIf an option is valid depends both on the platform and on\nwhat kind of socket it is (`t:domain/0`, `t:type/0` and `t:protocol/0`).\n\nThe integer values for `NativeLevel` and `NativeOpt` as well as the `Value`\nencoding has to be deduced from the header files for the running system.","title":"socket.setopt_native/3","ref":"socket.html#setopt_native/3"},{"type":"function","doc":"Shut down all or part of a full-duplex connection.","title":"socket.shutdown/2","ref":"socket.html#shutdown/2"},{"type":"function","doc":"Get the socket's address.\n\nReturns the address to which the socket is currently bound.\nIf the bind address had the wildcard port `0`,\nthe address returned by this function contains the ephemeral port\nselected by the OS.","title":"socket.sockname/1","ref":"socket.html#sockname/1"},{"type":"function","doc":"Retrieve information about what socket features\nthe module and the platform supports.\n\nReturns a list of, in no particular order,\n`{Key1, `[`supports(Key1)`](`supports/1`)`}` tuples\nfor every `Key1` described in `supports/1`,\nand `{Key, boolean()}` tuples for each of the following keys:\n\n- **`sctp`** - SCTP support\n\n- **`ipv6`** - IPv6 support\n\n- **`local`** - Unix Domain sockets support (`AF_UNIX | AF_LOCAL`)\n\n- **`netns`** - Network Namespaces support (Linux, `setns(2)`)\n\n- **`sendfile`** - Sendfile support (`sendfile(2)`)","title":"socket.supports/0","ref":"socket.html#supports/0"},{"type":"function","doc":"Retrieve information about what socket features\nthe module and the platform supports.\n\nIf `Key1 = msg_flags` returns a list of `{Flag, boolean()}`\ntuples for every `Flag` in `t:msg_flag/0` with the `t:boolean/0`\nindicating if the flag is supported on this platform.\n\nIf `Key1 = protocols` returns a list of `{Name, boolean()}`\ntuples for every `Name` in`t:protocol/0` with the `t:boolean/0`\nindicating if the protocol is supported on this platform.\n\nIf `Key1 = options` returns a list of `{SocketOption, boolean()}`\ntuples for every `SocketOption` in `t:socket_option/0` with the `t:boolean/0`\nindicating if the socket option is supported on this platform.\n\nThere is no particular order of any of the returned lists.\n\nFor other values of `Key1` returns `[]`.\nNote that in future versions of this module or on different platforms,\nthere might be more supported keys.","title":"socket.supports/1","ref":"socket.html#supports/1"},{"type":"function","doc":"Retrieve information about what socket features\nthe module and the platform supports.\n\nIf `Key1 = options`, for a `Key2` in `t:level/0` returns\na list of `{Opt, boolean()}` tuples for all known socket options\n[`Opt` on that `Level = Key2`](`t:socket_option/0`) with the `t:boolean/0`\nindicating if the socket option is supported on this platform.\nSee `setopt/3` and `getopt/2`.\n\nThere is no particular order of any of the returned lists.\n\nFor other values of `Key1` or `Key2` returns `[]`.\nNote that in future versions of this module or on different platforms,\nthere might be more supported keys.","title":"socket.supports/2","ref":"socket.html#supports/2"},{"type":"function","doc":"Set the global [`use_registry`](`t:otp_socket_option/0`)\noption default value.\n\nGlobally change if the socket registry is to be used or not.\nNote that its still possible to override this explicitly\nwhen creating an individual sockets, see [`open/2,3,4`](`open/2`)\nfor more info (the [`Opts :: map/0`](`t:map/0`)).","title":"socket.use_registry/1","ref":"socket.html#use_registry/1"},{"type":"function","doc":"Return a list of all known sockets.\n\nEquivalent to [`which_sockets(fun (_) -> true end)`](`which_sockets/1`).","title":"socket.which_sockets/0","ref":"socket.html#which_sockets/0"},{"type":"function","doc":"Return a filtered list of known sockets.\n\nThere are several predefined `FilterRule`s and one general:\n\n- **`inet | inet6`** - Only the sockets with matching `t:domain/0`\n are returned.\n\n- **`stream | dgram | seqpacket`** - Only the sockets with\n matching `t:type/0` are returned.\n\n- **`sctp | tcp | udp`** - Only the sockets with\n matching `t:protocol/0` are returned.\n\n- **`t:pid/0`** - Only the sockets with matching Controlling Process\n are returned. See the OTP socket option\n [`controlling_process`](`t:otp_socket_option/0`).\n\n- **`fun((socket_info()) -> boolean())`** - The general filter rule.\n A fun that takes the socket info and returns a `t:boolean/0`\n indicating if the socket should be returned or not.","title":"socket.which_sockets/1","ref":"socket.html#which_sockets/1"},{"type":"type","doc":"Control messages (ancillary messages).","title":"socket.cmsg/0","ref":"socket.html#t:cmsg/0"},{"type":"type","doc":"Control messages (ancillary messages) returned by\n[`recvmsg/1,2,3,5`](`recvmsg/1`).\n\nA control message has got a `data` field with a native (`binary`) value for the\nmessage data, and may also have a decoded `value` field if this socket library\nsuccessfully decoded the data.","title":"socket.cmsg_recv/0","ref":"socket.html#t:cmsg_recv/0"},{"type":"type","doc":"Control messages (ancillary messages) accepted by\n[`sendmsg/2,3,4`](`sendmsg/2`).\n\nA control message may for some message types have a `value` field with a\nsymbolic value, or a `data` field with a native value, that has to be binary\ncompatible what is defined in the platform's header files.","title":"socket.cmsg_send/0","ref":"socket.html#t:cmsg_send/0"},{"type":"type","doc":"[Completion operation](#asynchronous-calls) handle.\n\nA `t:reference/0` that uniquely identifies the (completion) operation,\ncontained in the returned `t:completion_info/0`.","title":"socket.completion_handle/0","ref":"socket.html#t:completion_handle/0"},{"type":"type","doc":"[Completion operation](#asynchronous-calls) info.\n\nReturned by an operation that requires the caller to wait for a\n[completion message](`m:socket#asynchronous-calls`) containing the\n[`CompletionHandle`](`t:completion_handle/0`) _and_ the result of the operation;\nthe `CompletionStatus`.","title":"socket.completion_info/0","ref":"socket.html#t:completion_info/0"},{"type":"type","doc":"[Completion operation](#asynchronous-calls) tag.\n\n\nA tag that describes the ongoing (completion) operation (= function name),\ncontained in the returned `t:completion_info/0`.","title":"socket.completion_tag/0","ref":"socket.html#t:completion_tag/0"},{"type":"type","doc":"Protocol _domain_ a.k.a address _family_.\n\nA lowercase `t:atom/0` representing a protocol _domain_\non the platform named `AF_*` (or `PF_*`). For example\n`inet` corresponds to `AF_INET`.\n\n[`is_supported(ipv6)` ](`is_supported/1`) tells if the IPv6 protocol,\nprotocol domain `inet6`, is supported.\n\n[`is_supported(local)` ](`is_supported/1`) tells if the\nprotocol domain `local` is supported.\n\n`supports/0` reports both values, but also many more, with a single call.","title":"socket.domain/0","ref":"socket.html#t:domain/0"},{"type":"type","doc":"","title":"socket.ee_origin/0","ref":"socket.html#t:ee_origin/0"},{"type":"type","doc":"Extended Error Information.\n\nA term containing additional (error) information\n_if_ the socket NIF has been configured to produce it.","title":"socket.eei/0","ref":"socket.html#t:eei/0"},{"type":"type","doc":"","title":"socket.extended_err/0","ref":"socket.html#t:extended_err/0"},{"type":"type","doc":"","title":"socket.hatype/0","ref":"socket.html#t:hatype/0"},{"type":"type","doc":"","title":"socket.icmp_dest_unreach/0","ref":"socket.html#t:icmp_dest_unreach/0"},{"type":"type","doc":"","title":"socket.icmpv6_dest_unreach/0","ref":"socket.html#t:icmpv6_dest_unreach/0"},{"type":"type","doc":"","title":"socket.in6_addr/0","ref":"socket.html#t:in6_addr/0"},{"type":"type","doc":"","title":"socket.in6_flow_info/0","ref":"socket.html#t:in6_flow_info/0"},{"type":"type","doc":"","title":"socket.in6_scope_id/0","ref":"socket.html#t:in6_scope_id/0"},{"type":"type","doc":"","title":"socket.in_addr/0","ref":"socket.html#t:in_addr/0"},{"type":"type","doc":"Platform dependent information items.\n\nThe value of `iov_max` is the value of the `IOV_MAX` constant\nin the system headers, which is the largest allowed I/O vector.\nSee also `sendmsg/4` regarding the `iov` key of `t:msg_send/0`.\nThe smallest allowed `IOV_MAX` value according to POSIX is `16`,\nbut check your platform documentation to be sure.\n\nAbout the `use_registry` key, see `use_registry/1`\nand the `t:otp_socket_option/0` with the same name.","title":"socket.info/0","ref":"socket.html#t:info/0"},{"type":"type","doc":"Information element designators for the `i/1` and `i/2` functions.","title":"socket.info_keys/0","ref":"socket.html#t:info_keys/0"},{"type":"type","doc":"The interface type (of the datalink). We only translate a few values to atoms,\nthe rest are left as (unsigned) integer values.","title":"socket.interface_type/0","ref":"socket.html#t:interface_type/0"},{"type":"type","doc":"","title":"socket.invalid/0","ref":"socket.html#t:invalid/0"},{"type":"type","doc":"","title":"socket.ioctl_device_flag/0","ref":"socket.html#t:ioctl_device_flag/0"},{"type":"type","doc":"","title":"socket.ioctl_device_map/0","ref":"socket.html#t:ioctl_device_map/0"},{"type":"type","doc":"C: `struct ip_mreq`\n\nCorresponds to the C `struct ip_mreq` for managing multicast groups.","title":"socket.ip_mreq/0","ref":"socket.html#t:ip_mreq/0"},{"type":"type","doc":"C: `struct ip_mreq_source`\n\nCorresponds to the C `struct ip_mreq_source` for managing multicast groups.","title":"socket.ip_mreq_source/0","ref":"socket.html#t:ip_mreq_source/0"},{"type":"type","doc":"C: `struct ip_msfilter`\n\nCorresponds to the C `struct ip_msfilter` for managing\nmulticast source filtering (RFC 3376).","title":"socket.ip_msfilter/0","ref":"socket.html#t:ip_msfilter/0"},{"type":"type","doc":"C: `struct ip_pktinfo`","title":"socket.ip_pktinfo/0","ref":"socket.html#t:ip_pktinfo/0"},{"type":"type","doc":"C: `IP_PMTUDISC_*` values.\n\nLowercase `t:atom/0` values corresponding to the C library constants\n`IP_PMTUDISC_*`. Some constant(s) may be unsupported by the platform.","title":"socket.ip_pmtudisc/0","ref":"socket.html#t:ip_pmtudisc/0"},{"type":"type","doc":"C: `IPTOS_*` values.\n\nLowercase `t:atom/0` values corresponding to the C library constants `IPTOS_*`.\nSome constant(s) may be unsupported by the platform.","title":"socket.ip_tos/0","ref":"socket.html#t:ip_tos/0"},{"type":"type","doc":"IPv6 hop limit value.\n\nThe value `default` is only valid to _set_ and is translated to the C value\n`-1`, meaning the route default.","title":"socket.ipv6_hops/0","ref":"socket.html#t:ipv6_hops/0"},{"type":"type","doc":"C: `struct ipv6_mreq`\n\nCorresponds to the C `struct ipv6_mreq` for managing multicast groups. See also\nRFC 2553.","title":"socket.ipv6_mreq/0","ref":"socket.html#t:ipv6_mreq/0"},{"type":"type","doc":"C: `struct in6_pktinfo`","title":"socket.ipv6_pktinfo/0","ref":"socket.html#t:ipv6_pktinfo/0"},{"type":"type","doc":"C: `IPV6_PMTUDISC_*` values\n\nLowercase `t:atom/0` values corresponding to the C library constants\n`IPV6_PMTUDISC_*`. Some constant(s) may be unsupported by the platform.","title":"socket.ipv6_pmtudisc/0","ref":"socket.html#t:ipv6_pmtudisc/0"},{"type":"type","doc":"Protocol level.\n\nA lowercase `t:atom/0` OS protocol level, that is:\n`socket` or a `t:protocol/0` name.\n\n`socket` is the `SOL_SOCKET` protocol level in the OS header files,\nwith options named `SO_`\\* .","title":"socket.level/0","ref":"socket.html#t:level/0"},{"type":"type","doc":"C: `struct linger`\n\nCorresponds to the C `struct linger` for managing the\n[socket option](`t:socket_option/0`) `{socket, linger}`.","title":"socket.linger/0","ref":"socket.html#t:linger/0"},{"type":"type","doc":"C: `struct msghdr`","title":"socket.msg/0","ref":"socket.html#t:msg/0"},{"type":"type","doc":"Platform dependent message flags.\n\nTranslates to/from message flag constants on the platform.\nThese flags are lowercase while the constants are uppercase\nwith prefix `MSG_`; for example `oob` translates to `MSG_OOB`.\n\nSome flags are only used for sending, some only for receiving, some in received\ncontrol messages, and some for several of these. Not all flags are supported on\nall platforms. See the platform's documentation,\n[`supports(msg_flags)`](`supports/1`), and\n[`is_supported(msg_flags, MsgFlag)`](`is_supported/2`).","title":"socket.msg_flag/0","ref":"socket.html#t:msg_flag/0"},{"type":"type","doc":"Message returned by [`recvmsg/1,2,3,5`](`recvmsg/1`).\n\nCorresponds to a C `struct msghdr`, see your platform documentation for\n[`recvmsg(2)`](`recvmsg/1`).\n\n- **`addr`** - Optional peer address, used on unconnected sockets. Corresponds\n to `msg_name` and `msg_namelen` fields of a `struct msghdr`. If `NULL` the map\n key is not present.\n\n- **`iov`** - Data as a list of binaries. The `msg_iov` and `msg_iovlen` fields\n of a `struct msghdr`.\n\n- **`ctrl`** - A possibly empty list of control messages (CMSG). Corresponds to\n the `msg_control` and `msg_controllen` fields of a `struct msghdr`.\n\n- **`flags`** - Message flags. Corresponds to the `msg_flags` field of a\n `struct msghdr`. Unknown flags, if any, are returned in one `t:integer/0`,\n last in the containing list.","title":"socket.msg_recv/0","ref":"socket.html#t:msg_recv/0"},{"type":"type","doc":"Message sent by [`sendmsg/2,3,4`](`sendmsg/2`).\n\nCorresponds to a C `struct msghdr`, see your platform documentation for\n`sendmsg(2)`.\n\n- **`addr`** - Optional peer address, used on unconnected sockets. Corresponds\n to `msg_name` and `msg_namelen` fields of a `struct msghdr`. If not used they\n are set to `NULL`, `0`.\n\n- **`iov`** - Mandatory data as a list of binaries. The `msg_iov` and\n `msg_iovlen` fields of a `struct msghdr`.\n\n- **`ctrl`** - Optional list of control messages (CMSG). Corresponds to the\n `msg_control` and `msg_controllen` fields of a `struct msghdr`. If not used\n they are set to `NULL`, `0`.\n\nThe `msg_flags` field of the `struct msghdr` is set to `0`.","title":"socket.msg_send/0","ref":"socket.html#t:msg_send/0"},{"type":"type","doc":"","title":"socket.native_value/0","ref":"socket.html#t:native_value/0"},{"type":"type","doc":"Protocol level `otp` socket option.\n\nSocket options for the `otp` pseudo protocol level,\nthat is: `{otp, Name}` options.\n\nThis protocol level is the Erlang/OTP's socket implementation layer,\nhence above all OS protocol levels.\n\n- **`debug`** - `t:boolean/0` \\- Activate debug logging.\n\n- **`iow`** - `t:boolean/0` \\- Inform On Wrap of statistics counters.\n\n- **`controlling_process`** - `t:pid/0` \\- The socket \"owner\". Only the current\n controlling process can set this option.\n\n- **`rcvbuf`** -\n `BufSize :: (default | integer()>0) | {N :: integer()>0, BufSize :: (default | integer()>0)} `\\-\n Receive buffer size.\n\n The value `default` is only valid to _set_.\n\n `N` specifies the number of read attempts to do in a tight loop before\n assuming no more data is pending.\n\n This is the allocation size for the receive buffer used when calling the OS\n protocol stack's receive API, when no specific size (size 0) is requested.\n When the receive function returns the receive buffer is reallocated to the\n actually received size. If the data is copied or shrunk in place is up to\n the allocator, and can to some extent be configured in the Erlang VM.\n\n The similar socket option; `{socket,rcvbuf}` is a related option for the OS'\n protocol stack that on Unix corresponds to `SOL_SOCKET,SO_RCVBUF`.\n\n- **`rcvctrlbuf`** - `BufSize :: (default | integer()>0) `\\- Allocation size for\n the ancillary data buffer used when calling the OS protocol stack's receive\n API.\n\n The value `default` is only valid to _set_.\n\n- **`sndctrlbuf`** - `BufSize :: (default | integer()>0) `\\- Allocation size for\n the ancillary data buffer used when calling the OS protocol stack's\n [sendmsg](`sendmsg/2`) API.\n\n The value `default` is only valid to _set_.\n\n It is the user's responsibility to set a buffer size that has room for the\n encoded ancillary data in the message to send.\n\n See [sendmsg](`sendmsg/2`) and also the `ctrl` field of the `t:msg_send/0`\n type.\n\n- **`fd`** - `t:integer/0` \\- Only valid to _get_. The OS protocol levels'\n socket descriptor. Functions [`open/1,2`](`open/1`) can be used to create a\n socket according to this module from an existing OS socket descriptor.\n\n- **`use_registry`** - `t:boolean/0` \\- Only valid to _get_. The value is set\n when the socket is created with `open/2` or `open/4`.\n\nOptions not described here are intentionally undocumented and for Erlang/OTP\ninternal use only.","title":"socket.otp_socket_option/0","ref":"socket.html#t:otp_socket_option/0"},{"type":"type","doc":"","title":"socket.packet_type/0","ref":"socket.html#t:packet_type/0"},{"type":"type","doc":"","title":"socket.port_number/0","ref":"socket.html#t:port_number/0"},{"type":"type","doc":"Posix error codes.\n\nLocal alias for `t:inet:posix/0`, a set of `t:atom/0`s.","title":"socket.posix/0","ref":"socket.html#t:posix/0"},{"type":"type","doc":"Protocol name.\n\nA lowercase `t:atom/0` representing an OS protocol name.\nTo be used for example in `t:socket_option/0`\nin [control messages](`t:cmsg/0`).\n\nThey have the following names in the OS header files:\n\n- **`ip`** - `IPPROTO_IP` a.k.a `SOL_IP` with options named `IP_`\\*.\n\n- **`ipv6`** - `IPPROTO_IPV6` a.k.a `SOL_IPV6` with options named `IPV6_`\\*.\n\n- **`tcp`** - `IPPROTO_TCP` with options named `TCP_`\\*.\n\n- **`udp`** - `IPPROTO_UDP` with options named `UDP_`\\*.\n\n- **`sctp`** - `IPPROTO_SCTP` with options named `SCTP_`\\*.\n\nThere are many other possible protocols, but the ones above are those for which\nthis socket library implements socket options and/or control messages.\n\nAll protocols known to the OS are enumerated when the Erlang VM is started,\nthrough the `C` library call `getprotoent()`. See the OS man page for\nprotocols(5). Those in the list above are valid if supported by the platform,\neven if they aren't enumerated.\n\nThe calls [`is_supported(ipv6)` ](`is_supported/1`)\nand [`is_supported(sctp)` ](`is_supported/1`) can be used to find out\nif the protocols `ipv6` and `sctp` are supported on the platform\nas in appropriate header file and library exists.\n\nThe call [`is_supported(protocols, Protocol)` ](`is_supported/2`)\ncan only be used to find out if the platform knows the protocol number\nfor a named `Protocol`.\n\nSee [`open/2,3,4`](`open/3`)","title":"socket.protocol/0","ref":"socket.html#t:protocol/0"},{"type":"type","doc":"C: `struct sctp_assocparams`","title":"socket.sctp_assocparams/0","ref":"socket.html#t:sctp_assocparams/0"},{"type":"type","doc":"C: `struct sctp_event_subscribe`.\n\nNot all fields are implemented on all platforms; unimplemented fields are\nignored, but implemented fields are mandatory. Note that the '\\_event' suffixes\nhave been stripped from the C struct field names, for convenience.","title":"socket.sctp_event_subscribe/0","ref":"socket.html#t:sctp_event_subscribe/0"},{"type":"type","doc":"C: `struct sctp_initmsg`.","title":"socket.sctp_initmsg/0","ref":"socket.html#t:sctp_initmsg/0"},{"type":"type","doc":"C: `struct sctp_rtoinfo`.","title":"socket.sctp_rtoinfo/0","ref":"socket.html#t:sctp_rtoinfo/0"},{"type":"type","doc":"[Select operation](#asynchronous-calls) handle.\n\nA `t:reference/0` that uniquely identifies the (select) operation,\ncontained in the returned `t:select_info/0`.","title":"socket.select_handle/0","ref":"socket.html#t:select_handle/0"},{"type":"type","doc":"[Select operation](#asynchronous-calls) info.\n\nReturned by an operation that requires the caller to wait for a\n[select message](`m:socket#asynchronous-calls`) containing the\n[`SelectHandle`](`t:select_handle/0`).","title":"socket.select_info/0","ref":"socket.html#t:select_info/0"},{"type":"type","doc":"[Select operation](#asynchronous-calls) tag.\n\nA tag that describes the (select) operation (= function name),\ncontained in the returned `t:select_info/0`.","title":"socket.select_tag/0","ref":"socket.html#t:select_tag/0"},{"type":"type","doc":"","title":"socket.sockaddr/0","ref":"socket.html#t:sockaddr/0"},{"type":"type","doc":"C: `struct sockaddr_dl`\n\nLink level address (PF_LINK) on BSD:s.","title":"socket.sockaddr_dl/0","ref":"socket.html#t:sockaddr_dl/0"},{"type":"type","doc":"C: `struct sockaddr_in6`\n\n[Domain `inet6`](`t:domain/0`) (IPv6) address.","title":"socket.sockaddr_in6/0","ref":"socket.html#t:sockaddr_in6/0"},{"type":"type","doc":"C: `struct sockaddr_in`\n\n[Domain `inet`](`t:domain/0`) (IPv4) address.","title":"socket.sockaddr_in/0","ref":"socket.html#t:sockaddr_in/0"},{"type":"type","doc":"C: `struct sockaddr_ll`\n\n[Domain `packet`](`t:domain/0`), [type `raw`](`t:type/0`)\n(link level) address.","title":"socket.sockaddr_ll/0","ref":"socket.html#t:sockaddr_ll/0"},{"type":"type","doc":"C: `struct sockaddr`\n\nIn C, a `struct sockaddr` with the integer value of `sa_family`\nin the `t:map/0` key `family`,\nand the content of `sa_data` in the `t:map/0` key `addr`.","title":"socket.sockaddr_native/0","ref":"socket.html#t:sockaddr_native/0"},{"type":"type","doc":"","title":"socket.sockaddr_recv/0","ref":"socket.html#t:sockaddr_recv/0"},{"type":"type","doc":"C: `struct sockaddr_un`.\n\nA Unix Domain socket address, a.k.a local address (`AF_LOCAL`).\n\nThe `path` element will always be a `binary` when returned from this module.\nWhen supplied to an API function in this module it may be a `t:string/0`, which\nwill be encoded into a binary according to the\n[native file name encoding ](`file:native_name_encoding/0`)on the platform.\n\nA terminating zero character will be appended before the address path is given\nto the OS, and the terminating zero will be stripped before giving the address\npath to the caller.\n\nLinux's non-portable abstract socket address extension is handled by not doing\nany terminating zero processing in either direction, if the first byte of the\naddress is zero.","title":"socket.sockaddr_un/0","ref":"socket.html#t:sockaddr_un/0"},{"type":"type","doc":"C: `struct sockaddr` of `AF_UNSPEC`\n\nIn C, a `struct sockaddr` with `sa_family = AF_UNSPEC`\nand the content of `sa_data` in the `t:map/0` key `addr`.","title":"socket.sockaddr_unspec/0","ref":"socket.html#t:sockaddr_unspec/0"},{"type":"type","doc":"A socket, according to this module.\n\nCreated and returned by [`open/1,2,3,4`](`open/1`)\nand [`accept/1,2`](`accept/1`).","title":"socket.socket/0","ref":"socket.html#t:socket/0"},{"type":"type","doc":"A `t:map/0` of `Name := Counter` associations.","title":"socket.socket_counters/0","ref":"socket.html#t:socket_counters/0"},{"type":"opaque","doc":"Opaque socket handle unique for the socket.","title":"socket.socket_handle/0","ref":"socket.html#t:socket_handle/0"},{"type":"type","doc":"","title":"socket.socket_info/0","ref":"socket.html#t:socket_info/0"},{"type":"type","doc":"Socket option.\n\nSocket options on the form `{Level, Opt}` where the OS protocol `Level` =\n`t:level/0` and `Opt` is a socket option on that protocol level.\n\nThe OS name for an options is, except where otherwise noted, the `Opt` atom, in\ncapitals, with prefix according to `t:level/0`.\n\n> #### Note {: .info }\n>\n> The `IPv6` option `pktoptions` is a special (barf) case. It is intended for\n> backward compatibility usage only.\n>\n> Do _not_ use this option.\n\n> #### Note {: .info }\n>\n> See the OS documentation for every socket option.\n\nAn option below that has the value type `t:boolean/0` will translate the value\n`false` to a C `int` with value `0`, and the value `true` to `!!0` (not (not\nfalse)).\n\nAn option with value type `t:integer/0` will be translated to a C `int` that may\nhave a restricted range, for example byte: `0..255`. See the OS documentation.\n\nThe calls [`supports(options)`](`supports/1`),\n[`supports(options, Level)`](`supports/1`) and\n[`is_supported(options, {Level, Opt})` ](`is_supported/2`)can be used to find\nout which socket options that are supported by the platform.\n\n_Options for protocol level_ [_`socket`_:](`t:level/0`)\n\n- **`{socket, acceptconn}`** - `Value = boolean()`\n\n- **`{socket, bindtodevice}`** - `Value = string()`\n\n- **`{socket, broadcast}`** - `Value = boolean()`\n\n- **`{socket, debug}`** - `Value = integer()`\n\n- **`{socket, domain}`** - `Value =` `t:domain/0`\n\n Only valid to _get_.\n\n The socket's protocol domain. Does _not_ work on for instance FreeBSD.\n\n- **`{socket, dontroute}`** - `Value = boolean()`\n\n- **`{socket, keepalive}`** - `Value = boolean()`\n\n- **`{socket, linger}`** - `Value = abort |` `t:linger/0`\n\n The value `abort` is shorthand for `#{onoff => true, linger => 0}`, and only\n valid to _set_.\n\n- **`{socket, oobinline}`** - `Value = boolean()`\n\n- **`{socket, passcred}`** - `Value = boolean()`\n\n- **`{socket, peek_off}`** - `Value = integer()`\n\n Currently disabled due to a possible infinite loop when calling\n [`recv/1-4`](`recv/1`) with [`peek`](`t:msg_flag/0`) in `Flags`.\n\n- **`{socket, priority}`** - `Value = integer()`\n\n- **`{socket, protocol}`** - `Value =` `t:protocol/0`\n\n Only valid to _get_.\n\n The socket's protocol. Does _not_ work on for instance Darwin.\n\n- **`{socket, rcvbuf}`** - `Value = integer()`\n\n- **`{socket, rcvlowat}`** - `Value = integer()`\n\n- **`{socket, rcvtimeo}`** - `Value =` `t:timeval/0`\n\n This option is unsupported per default; OTP has to be explicitly built with\n the `--enable-esock-rcvsndtimeo` configure option for this to be available.\n\n Since our implementation uses non-blocking sockets, it is unknown if and how\n this option works, or even if it may cause malfunction. Therefore, we do not\n recommend setting this option.\n\n Instead, use the `Timeout` argument to, for instance, the `recv/3` function.\n\n- **`{socket, reuseaddr}`** - `Value = boolean()`\n\n- **`{socket, reuseport}`** - `Value = boolean()`\n\n- **`{socket, sndbuf}`** - `Value = integer()`\n\n- **`{socket, sndlowat}`** - `Value = integer()`\n\n- **`{socket, sndtimeo}`** - `Value =` `t:timeval/0`\n\n This option is unsupported per default; OTP has to be explicitly built with\n the `--enable-esock-rcvsndtimeo` configure option for this to be available.\n\n Since our implementation uses non-blocking sockets, it is unknown if and how\n this option works, or even if it may cause malfunction. Therefore, we do not\n recommend setting this option.\n\n Instead, use the `Timeout` argument to, for instance, the `send/3` function.\n\n- **`{socket, timestamp}`** - `Value = boolean()`\n\n- **`{socket, type}`** - `Value =` `t:type/0`\n\n Only valid to _get_.\n\n The socket's type.\n\n_Options for protocol level_ [_`ip`_:](`t:level/0`)\n\n- **`{ip, add_membership}`** - `Value =` `t:ip_mreq/0`\n\n Only valid to _set_.\n\n- **`{ip, add_source_membership}`** - `Value =` `t:ip_mreq_source/0`\n\n Only valid to _set_.\n\n- **`{ip, block_source}`** - `Value =` `t:ip_mreq_source/0`\n\n Only valid to _set_.\n\n- **`{ip, drop_membership}`** - `Value =` `t:ip_mreq/0`\n\n Only valid to _set_.\n\n- **`{ip, drop_source_membership}`** - `Value =` `t:ip_mreq_source/0`\n\n Only valid to _set_.\n\n- **`{ip, freebind}`** - `Value = boolean()`\n\n- **`{ip, hdrincl}`** - `Value = boolean()`\n\n- **`{ip, minttl}`** - `Value = integer()`\n\n- **`{ip, msfilter}`** - `Value =` `null |` `t:ip_msfilter/0`\n\n Only valid to _set_.\n\n The value `null` passes a `NULL` pointer and size `0` to the C library call.\n\n- **`{ip, mtu}`** - `Value = integer()`\n\n Only valid to _get_.\n\n- **`{ip, mtu_discover}`** - `Value =`\n [`ip_pmtudisc()` ](`t:ip_pmtudisc/0`)`| integer()`\n\n An `t:integer/0` value according to the platform's header files.\n\n- **`{ip, multicast_all}`** - `Value = boolean()`\n\n- **`{ip, multicast_if}`** - `Value =` `any |` `t:in_addr/0`\n\n- **`{ip, multicast_loop}`** - `Value = boolean()`\n\n- **`{ip, multicast_ttl}`** - `Value = integer()`\n\n- **`{ip, nodefrag}`** - `Value = boolean()`\n\n- **`{ip, pktinfo}`** - `Value = boolean()`\n\n- **`{ip, recvdstaddr}`** - `Value = boolean()`\n\n- **`{ip, recverr}`** - `Value = boolean()`\n\n Enable extended reliable error message passing.\n\n _Warning\\!_ When this option is enabled, error messages may arrive on the\n socket's error queue, which should be read using the message flag\n [`errqueue`](`t:msg_flag/0`), and using [`recvmsg/1,2,3,4,5`](`recvmsg/1`) to\n get all error information in the [message's](`t:msg_recv/0`) `ctrl` field as a\n [control message](`t:cmsg_recv/0`) `#{level := ip, type := recverr}`.\n\n A working strategy should be to first poll the error queue using\n [`recvmsg/2,3,4` ](`m:socket#recvmsg-timeout`)with `Timeout =:= 0` and `Flags`\n containing `errqueue` (ignore the return value `{error, timeout}`) before\n reading the actual data to ensure that the error queue gets cleared. And read\n the data using one of the `nowait |`\n [`select_handle()` ](`t:select_handle/0`)recv functions:\n [`recv/3,4`](`m:socket#recv-nowait`),\n [`recvfrom/3,4`](`m:socket#recvfrom-nowait`) or\n [`recvmsg/3,4,5`](`m:socket#recvmsg-nowait`). Otherwise you might accidentally\n cause a busy loop in and out of 'select' for the socket.\n\n- **`{ip, recvif}`** - `Value = boolean()`\n\n- **`{ip, recvopts}`** - `Value = boolean()`\n\n- **`{ip, recvorigdstaddr}`** - `Value = boolean()`\n\n- **`{ip, recvtos}`** - `Value = boolean()`\n\n- **`{ip, recvttl}`** - `Value = boolean()`\n\n- **`{ip, retopts}`** - `Value = boolean()`\n\n- **`{ip, router_alert}`** - `Value = integer()`\n\n- **`{ip, sendsrcaddr}`** - `Value = boolean()`\n\n- **`{ip, tos}`** - `Value =` [`ip_tos()` ](`t:ip_tos/0`)`| integer()`\n\n An `t:integer/0` value is according to the platform's header files.\n\n- **`{ip, transparent}`** - `Value = boolean()`\n\n- **`{ip, ttl}`** - `Value = integer()`\n\n- **`{ip, unblock_source}`** - `Value =` `t:ip_mreq_source/0`\n\n Only valid to _set_.\n\n_Options for protocol level_ [_`ipv6`_:](`t:level/0`)\n\n- **`{ipv6, addrform}`** - `Value =` `t:domain/0`\n\n As far as we know the only valid value is `inet` and it is only allowed for an\n IPv6 socket that is connected and bound to an IPv4-mapped IPv6 address.\n\n- **`{ipv6, add_membership}`** - `Value =` `t:ipv6_mreq/0`\n\n Only valid to _set_.\n\n- **`{ipv6, authhdr}`** - `Value = boolean()`\n\n- **`{ipv6, drop_membership}`** - `Value =` `t:ipv6_mreq/0`\n\n Only valid to _set_.\n\n- **`{ipv6, dstopts}`** - `Value = boolean()`\n\n- **`{ipv6, flowinfo}`** - `Value = boolean()`\n\n- **`{ipv6, hoplimit}`** - `Value = boolean()`\n\n- **`{ipv6, hopopts}`** - `Value = boolean()`\n\n- **`{ipv6, mtu}`** - `Value = integer()`\n\n- **`{ipv6, mtu_discover}`** - `Value =`\n [`ipv6_pmtudisc()` ](`t:ipv6_pmtudisc/0`)`| integer()`\n\n An `t:integer/0` value is according to the platform's header files.\n\n- **`{ipv6, multicast_hops}`** - `Value =` `t:ipv6_hops/0`\n\n- **`{ipv6, multicast_if}`** - `Value = integer()`\n\n- **`{ipv6, multicast_loop}`** - `Value = boolean()`\n\n- **`{ipv6, recverr}`** - `Value = boolean()`\n\n _Warning\\!_ See the socket option `{ip, recverr}` regarding the socket's error\n queue. The same warning applies for this option.\n\n- **`{ipv6, recvhoplimit}`** - `Value = boolean()`\n\n- **`{ipv6, recvpktinfo}`** - `Value = boolean()`\n\n- **`{ipv6, recvtclass}`** - `Value = boolean()`\n\n- **`{ipv6, router_alert}`** - `Value = integer()`\n\n- **`{ipv6, rthdr}`** - `Value = boolean()`\n\n- **`{ipv6, tclass}`** - `Value = boolean()`\n\n- **`{ipv6, unicast_hops}`** - `Value =` `t:ipv6_hops/0`\n\n- **`{ipv6, v6only}`** - `Value = boolean()`\n\n_Options for protocol level_ [_`sctp`_](`t:level/0`). See also RFC 6458.\n\n- **`{sctp, associnfo}`** - `Value =` `t:sctp_assocparams/0`\n\n- **`{sctp, autoclose}`** - `Value = integer()`\n\n- **`{sctp, disable_fragments}`** - `Value = boolean()`\n\n- **`{sctp, events}`** - `Value =` `t:sctp_event_subscribe/0`\n\n Only valid to _set_.\n\n- **`{sctp, initmsg}`** - `Value =` `t:sctp_initmsg/0`\n\n- **`{sctp, maxseg}`** - `Value = integer()`\n\n- **`{sctp, nodelay}`** - `Value = boolean()`\n\n- **`{sctp, rtoinfo}`** - `Value =` `t:sctp_rtoinfo/0`\n\n_Options for protocol level_ [_`tcp`:_](`t:level/0`)\n\n- **`{tcp, congestion}`** - `Value = string()`\n\n- **`{tcp, cork}`** - `Value = boolean()`\n\n- **`{tcp, maxseg}`** - `Value = integer()`\n\n- **`{tcp, nodelay}`** - `Value = boolean()`\n\n_Options for protocol level_ [_`udp`:_](`t:level/0`)\n\n- **`{udp, cork}`** - `Value = boolean()`","title":"socket.socket_option/0","ref":"socket.html#t:socket_option/0"},{"type":"type","doc":"C: `struct timeval`\n\nCorresponds to the C `struct timeval`. The field `sec` holds seconds, and `usec`\nmicroseconds.","title":"socket.timeval/0","ref":"socket.html#t:timeval/0"},{"type":"type","doc":"Protocol type.\n\nA lowercase `t:atom/0` representing a protocol _type_\non the platform named `SOCK_*`. For example\n`stream` corresponds to `SOCK_STREAM`.","title":"socket.type/0","ref":"socket.html#t:type/0"},{"type":"module","doc":"`disk_log` is a disk-based term logger that enables efficient logging of items\non files.\n\nThree types of logs are supported:\n\n- **halt logs** - Appends items to a single file, which size can be limited by\n the `disk_log` module.\n\n- **wrap logs** - Uses a sequence of wrap log files of limited size. As a wrap\n log file is filled up, further items are logged on to the next file in the\n sequence, starting all over with the first file when the last file is filled\n up.\n\n- **rotate logs** - Uses a sequence of rotate log files of limited size. As a\n log file is filled up, it is rotated and then compressed. There is one active\n log file and upto the configured number of compressed log files. Only\n externally formatted logs are supported. It follows the same naming convention\n as the handler logger_std_h for Logger. For more details about the naming\n convention check the file parameter for `open/1`.\n\n It follows the same naming convention as that for the compressed files for\n Linux's logrotate and BSD's newsyslog.\n\nFor efficiency reasons, items are always written to files as binaries.\n\nTwo formats of the log files are supported:\n\n- **internal format** - Supports automatic repair of log files that are not\n properly closed and enables efficient reading of logged items in _chunks_\n using a set of functions defined in this module. This is the only way to read\n internally formatted logs. An item logged to an internally formatted log must\n not occupy more than 4 GB of disk space (the size must fit in 4 bytes).\n\n- **external format** - Leaves it up to the user to read and interpret the\n logged data. The `disk_log` module cannot repair externally formatted logs.\n\nFor each open disk log, one process handles requests made to the disk log. This\nprocess is created when `open/1` is called, provided there exists no process\nhandling the disk log. A process that opens a disk log can be an _owner_ or an\nanonymous _user_ of the disk log. Each owner is linked to the disk log process,\nand an owner can close the disk log either explicitly (by calling\n[`close/1`](`close/1`)) or by terminating.\n\nOwners can subscribe to _notifications_, messages of the form\n`{disk_log, Node, Log, Info}`, which are sent from the disk log process when\ncertain events occur, see the functions and in particular the\n[`open/1`](`open/1`) option [`notify`](`m:disk_log#notify`). A log can have many\nowners, but a process cannot own a log more than once. However, the same process\ncan open the log as a user more than once.\n\nFor a disk log process to close its file properly and terminate, it must be\nclosed by its owners and once by some non-owner process for each time the log\nwas used anonymously. The users are counted and there must not be any users left\nwhen the disk log process terminates.\n\nItems can be logged _synchronously_ by using functions `log/2`, `blog/2`,\n`log_terms/2`, and `blog_terms/2`. For each of these functions, the caller is\nput on hold until the items are logged (but not necessarily written, use\n[`sync/1`](`sync/1`) to ensure that). By adding an `a` to each of the mentioned\nfunction names, we get functions that log items _asynchronously_. Asynchronous\nfunctions do not wait for the disk log process to write the items to the file,\nbut return the control to the caller more or less immediately.\n\nWhen using the internal format for logs, use functions `log/2`, `log_terms/2`,\n`alog/2`, and `alog_terms/2`. These functions log one or more Erlang terms. By\nprefixing each of the functions with a `b` (for \"binary\"), we get the\ncorresponding `blog()` functions for the external format. These functions log\none or more chunks of bytes. For example, to log the string `\"hello\"` in ASCII\nformat, you can use [`disk_log:blog(Log, \"hello\")`](`blog/2`), or\n[`disk_log:blog(Log, list_to_binary(\"hello\"))`](`blog/2`). The two alternatives\nare equally efficient.\n\nThe `blog()` functions can also be used for internally formatted logs, but in\nthis case they must be called with binaries constructed with calls to\n[`term_to_binary/1`](`erlang:term_to_binary/1`). There is no check to ensure\nthis, it is entirely the responsibility of the caller. If these functions are\ncalled with binaries that do not correspond to Erlang terms, the\n[`chunk/2,3`](`chunk/3`) and automatic repair functions fail. The corresponding\nterms (not the binaries) are returned when [`chunk/2,3`](`chunk/3`) is called.\n\nAn open disk log is only accessible from the node where the disk log process\nruns. All processes on the node where the disk log process runs can log items or\notherwise change, inspect, or close the log.\n\nErrors are reported differently for asynchronous log attempts and other uses of\nthe `m:disk_log` module. When used synchronously, this module replies with an\nerror message, but when called asynchronously, this module does not know where\nto send the error message. Instead, owners subscribing to notifications receive\nan `error_status` message.\n\nThe `m:disk_log` module does not report errors to the `m:error_logger` module. It\nis up to the caller to decide whether to employ the error logger. Function\n`format_error/1` can be used to produce readable messages from error replies.\nHowever, information events are sent to the error logger in two situations,\nnamely when a log is repaired, or when a file is missing while reading chunks.\n\nError message `no_such_log` means that the specified disk log is not open.\nNothing is said about whether the disk log files exist or not.\n\n> #### Note {: .info }\n>\n> If an attempt to reopen or truncate a log fails (see\n> [`reopen/2,3`](`reopen/3`) and [`truncate/1,2`](`truncate/2`)) the disk log\n> process terminates immediately. Before the process terminates, links to owners\n> and blocking processes (see [`block/1,2`](`block/2`)) are removed. The effect\n> is that the links work in one direction only. Any process using a disk log\n> must check for error message `no_such_log` if some other process truncates or\n> reopens the log simultaneously.","title":"disk_log","ref":"disk_log.html"},{"type":"module","doc":"`m:file`, `m:wrap_log_reader`","title":"See Also - disk_log","ref":"disk_log.html#module-see-also"},{"type":"function","doc":"Returns the names of the disk logs accessible on the current node.","title":"disk_log.all/0","ref":"disk_log.html#all/0"},{"type":"function","doc":"Asynchronously version of `log/2`.\n\nOwners subscribing to notifications receive message `read_only`, `blocked_log`,\nor `format_external` if the item cannot be written on the log, and possibly one\nof the messages `wrap`, `full`, or `error_status` if an item is written on the\nlog. Message `error_status` is sent if something is wrong with the header\nfunction or if a file error occurs.","title":"disk_log.alog/2","ref":"disk_log.html#alog/2"},{"type":"function","doc":"Asynchronously version of `log_terms/2`.\n\nOwners subscribing to notifications receive message `read_only`, `blocked_log`,\nor `format_external` if the items cannot be written on the log, and possibly one\nor more of the messages `wrap`, `full`, and `error_status` if items are written\non the log. Message `error_status` is sent if something is wrong with the header\nfunction or if a file error occurs.","title":"disk_log.alog_terms/2","ref":"disk_log.html#alog_terms/2"},{"type":"function","doc":"Asynchronously version of `blog/2`.\n\nOwners subscribing to notifications receive message `read_only`, `blocked_log`,\nor `format_external` if the item cannot be written on the log, and possibly one\nof the messages `wrap`, `full`, or `error_status` if an item is written on the\nlog. Message `error_status` is sent if something is wrong with the header\nfunction or if a file error occurs.","title":"disk_log.balog/2","ref":"disk_log.html#balog/2"},{"type":"function","doc":"Asynchronously version of `blog_terms/2`.\n\nOwners subscribing to notifications receive message `read_only`, `blocked_log`,\nor `format_external` if the items cannot be written on the log, and possibly one\nor more of the messages `wrap`, `full`, and `error_status` if items are written\non the log. Message `error_status` is sent if something is wrong with the header\nfunction or if a file error occurs.","title":"disk_log.balog_terms/2","ref":"disk_log.html#balog_terms/2"},{"type":"function","doc":"","title":"disk_log.bchunk/2","ref":"disk_log.html#bchunk/2"},{"type":"function","doc":"Equivalent to [`chunk(Log, Continuation, N)`](`chunk/3`) except that\nit returns the binaries read from the file, that is it does not call\n`binary_to_term/1`.","title":"disk_log.bchunk/3","ref":"disk_log.html#bchunk/3"},{"type":"function","doc":"","title":"disk_log.block/1","ref":"disk_log.html#block/1"},{"type":"function","doc":"With a call to `block/2` a process can block a log.\n\nIf the blocking process is not an owner of the log, a temporary link is created\nbetween the disk log process and the blocking process. The link ensures that the disk log is\nunblocked if the blocking process terminates without first closing or unblocking\nthe log.\n\nAny process can probe a blocked log with [`info/1`](`info/1`) or close it with\n[`close/1`](`close/1`). The blocking process can also use functions [`chunk/2,3`](`chunk/3`),\n[`bchunk/2,3`](`chunk/3`), [`chunk_step/3`](`chunk_step/3`), and [`unblock/1`](`unblock/1`)\nwithout being affected by the block. Any other attempt than those mentioned so\nfar to update or read a blocked log suspends the calling process until the log\nis unblocked or returns error message `{blocked_log, Log}`, depending on whether\nthe value of `QueueLogRecords` is `true` or `false`.","title":"disk_log.block/2","ref":"disk_log.html#block/2"},{"type":"function","doc":"Equivalent to `log/2` except that it is used for externally formatted logs.\n\n`blog/2` can also be used for internally formatted logs\nif the binaries are constructed with calls to `term_to_binary/1`.","title":"disk_log.blog/2","ref":"disk_log.html#blog/2"},{"type":"function","doc":"Equivalent to `log_terms/2` except that it is used for externally formatted logs.\n\n`blog_terms/2` can also be used for internally formatted logs\nif the binaries are constructed with calls to `term_to_binary/1`.","title":"disk_log.blog_terms/2","ref":"disk_log.html#blog_terms/2"},{"type":"function","doc":"Equivalent to `reopen` except that it is used for externally formatted logs.","title":"disk_log.breopen/3","ref":"disk_log.html#breopen/3"},{"type":"function","doc":"Equivalent to `truncate/2` for externally formatted logs.","title":"disk_log.btruncate/2","ref":"disk_log.html#btruncate/2"},{"type":"function","doc":"Changes the value of option `head` or `head_func` for an owner of a disk log.","title":"disk_log.change_header/2","ref":"disk_log.html#change_header/2"},{"type":"function","doc":"Changes the value of option `notify` for an owner of a disk log.","title":"disk_log.change_notify/3","ref":"disk_log.html#change_notify/3"},{"type":"function","doc":"Changes the size of an open log. For a halt log, the size can always be\nincreased, but it cannot be decreased to something less than the current file\nsize.\n\nFor a wrap or rotate log, both the size and the number of files can always be\nincreased, as long as the number of files does not exceed 65000. For wrap logs,\nif the maximum number of files is decreased, the change is not valid until the\ncurrent file is full and the log wraps to the next file. The redundant files are\nremoved the next time the log wraps around, that is, starts to log to file\nnumber 1.\n\nAs an example, assume that the old maximum number of files is 10 and that the\nnew maximum number of files is 6. If the current file number is not greater than\nthe new maximum number of files, files 7-10 are removed when file 6 is full and\nthe log starts to write to file number 1 again. Otherwise, the files greater\nthan the current file are removed when the current file is full (for example, if\nthe current file is 8, files 9 and 10 are removed). The files between the new\nmaximum number of files and the current file (that is, files 7 and 8) are\nremoved the next time file 6 is full.\n\nFor rotate logs, if the maximum number of files is decreased, the redundant\nfiles are deleted instantly.\n\nIf the size of the files is decreased, the change immediately affects the\ncurrent log. It does not change the size of log files already full until the\nnext time they are used.\n\nIf the log size is decreased, for example, to save space, function\n`next_file/1`, can be used to force the log to wrap.","title":"disk_log.change_size/2","ref":"disk_log.html#change_size/2"},{"type":"function","doc":"","title":"disk_log.chunk/2","ref":"disk_log.html#chunk/2"},{"type":"function","doc":"Efficiently reads the terms that are appended to an internally formatted log.\n\nIt minimizes disk I/O by reading 64 kilobyte chunks from the file.\n\nThe first time `chunk()` is called, an initial continuation, the\natom `start`, must be provided.\n\nWhen [`chunk/3`](`chunk/3`) is called, `N` controls the maximum number of terms\nthat are read from the log in each chunk. `infinity` means\nthat all the terms contained in the 64 kilobyte chunk are read. If less than `N`\nterms are returned, this does not necessarily mean that the end of the file is\nreached.\n\n`chunk/3` returns a tuple `{Continuation2, Terms}`, where `Terms` is a list of\nterms found in the log. `Continuation2` is yet another continuation, which must\nbe passed on to any subsequent calls to `chunk()`. With a series of calls to\n`chunk()`, all terms from a log can be extracted.\n\n`chunk/3` returns a tuple `{Continuation2, Terms, Badbytes}` if the log is\nopened in read-only mode and the read chunk is corrupt. `Badbytes` is the number\nof bytes in the file found not to be Erlang terms in the chunk. Notice that the\nlog is not repaired. When trying to read chunks from a log opened in read-write\nmode, tuple `{corrupt_log_file, FileName}` is returned if the read chunk is\ncorrupt.\n\n`chunk/3` returns `eof` when the end of the log is reached, or `{error, Reason}`\nif an error occurs. If a wrap log file is missing, a message is output on the\nerror log.\n\nWhen [`chunk/2,3`](`chunk/3`) is used with wrap logs, the returned continuation might not be\nvalid in the next call to `chunk/3`. This is because the log can wrap and delete\nthe file into which the continuation points. To prevent this, the log can be\nblocked during the search.","title":"disk_log.chunk/3","ref":"disk_log.html#chunk/3"},{"type":"function","doc":"Returns the pair `{node, Node}`, describing the chunk continuation returned by\n`chunk/2,3`, [`bchunk/2,3`](`bchunk/3`), or [`chunk_step/3`](`chunk_step/3`).\n\nTerms are read from the disk log running on `Node`.","title":"disk_log.chunk_info/1","ref":"disk_log.html#chunk_info/1"},{"type":"function","doc":"Can be used with [`chunk/2,3`](`chunk/3`) and [`bchunk/2,3`](`chunk/3`) to\nsearch through an internally formatted wrap log.\n\nIt takes as argument a continuation as returned by [`chunk/2,3`](`chunk/3`),\n[`bchunk/2,3`](`bchunk/3`), or [`chunk_step/3`](`chunk_step/3`), and steps\nforward (or backward) `Step` files in the wrap log. The continuation returned,\npoints to the first log item in the new current file.\n\nIf atom `start` is specified as continuation, the first file of the wrap log is\nchosen as the new current file.\n\nIf the wrap log is not full because all files are not yet used,\n`{error, end_of_log}` is returned if trying to step outside the log.","title":"disk_log.chunk_step/3","ref":"disk_log.html#chunk_step/3"},{"type":"function","doc":"Closes a disk log properly.\n\nAn internally formatted log must be closed before the Erlang system is stopped.\nOtherwise, the log is regarded as unclosed and the automatic repair procedure is\nactivated next time the log is opened.\n\nThe disk log process is not terminated as long as there are owners or users of\nthe log. All owners must close the log, possibly by terminating. Also, any other\nprocess, not only the processes that have opened the log anonymously, can\ndecrement the `users` counter by closing the log. Attempts to close a log by a\nprocess that is not an owner are ignored if there are no users.\n\nIf the log is blocked by the closing process, the log is also unblocked.","title":"disk_log.close/1","ref":"disk_log.html#close/1"},{"type":"function","doc":"Given the error returned by any function in this module, this function returns a\ndescriptive string of the error in English.\n\nFor file errors, function [`format_error/1`](`format_error/1`) in module\n[`file`](`file:format_error/1`) is called.","title":"disk_log.format_error/1","ref":"disk_log.html#format_error/1"},{"type":"function","doc":"Forces the internally formatted disk log to start logging to the next log file.\nIt can be used, for example, with [`change_size/2`](`change_size/2`) to reduce\nthe amount of disk space allocated by the disk log.\n\nOwners subscribing to notifications normally receive a `wrap` message, but if an\nerror occurs with a reason tag of `invalid_header` or `file_error`, an\n`error_status` message is sent.","title":"disk_log.inc_wrap_file/1","ref":"disk_log.html#inc_wrap_file/1"},{"type":"function","doc":"Returns a list of `{Tag, Value}` pairs describing a log running on the node.\n\nThe following pairs are returned for all logs:\n\n- **`{name, Log}`** - `Log` is the log name as specified by the\n [`open/1`](`open/1`) option `name`.\n\n- **`{file, File}`** - For halt logs `File` is the filename, and for wrap logs\n `File` is the base name.\n\n- **`{type, Type}`** - `Type` is the log type as specified by the\n [`open/1`](`open/1`) option `type`.\n\n- **`{format, Format}`** - `Format` is the log format as specified by the\n [`open/1`](`open/1`) option `format`.\n\n- **`{size, Size}`** - `Size` is the log size as specified by the\n [`open/1`](`open/1`) option `size`, or the size set by\n [`change_size/2`](`change_size/2`). The value set by\n [`change_size/2`](`change_size/2`) is reflected immediately.\n\n- **`{mode, Mode}`** - `Mode` is the log mode as specified by the\n [`open/1`](`open/1`) option `mode`.\n\n- **`{owners, [{pid(), Notify}]}`** - `Notify` is the value set by the\n [`open/1`](`open/1`) option `notify` or function\n [`change_notify/3`](`change_notify/3`) for the owners of the log.\n\n- **`{users, Users}`** - `Users` is the number of anonymous users of the log,\n see the [`open/1`](`open/1`) option [`linkto`](`m:disk_log#linkto`).\n\n- **`{status, Status}`** - `Status` is `ok` or `{blocked, QueueLogRecords}` as\n set by functions `block/1,2` and [`unblock/1`](`unblock/1`).\n\n- **`{node, Node}`** - The information returned by the current invocation of\n function [`info/1`](`info/1`) is gathered from the disk log process running on\n `Node`.\n\nThe following pairs are returned for all logs opened in `read_write` mode:\n\n- **`{head, Head}`** - Depending on the value of the [`open/1`](`open/1`)\n options `head` and `head_func`, or set by function\n [`change_header/2`](`change_header/2`), the value of `Head` is `none`\n (default), `{head, H}` (`head` option), or `{M,F,A}` (`head_func` option).\n\n- **`{no_written_items, NoWrittenItems}`** - `NoWrittenItems` is the number of\n items written to the log since the disk log process was created.\n\nThe following pair is returned for halt logs opened in `read_write` mode:\n\n- **`{full, Full}`** - `Full` is `true` or `false` depending on whether the halt\n log is full or not.\n\nThe following pairs are returned for wrap logs opened in `read_write` mode:\n\n- **`{no_current_bytes, integer() >= 0}`** - The number of bytes written to the\n current wrap log file.\n\n- **`{no_current_items, integer() >= 0}`** - The number of items written to the\n current wrap log file, header inclusive.\n\n- **`{no_items, integer() >= 0}`** - The total number of items in all wrap log\n files.\n\n- **`{current_file, integer()}`** - The ordinal for the current wrap log file in\n the range `1..MaxNoFiles`, where `MaxNoFiles` is specified by the\n [`open/1`](`open/1`) option `size` or set by\n [`change_size/2`](`change_size/2`).\n\n- **`{no_overflows, {SinceLogWasOpened, SinceLastInfo}}`** - `SinceLogWasOpened`\n (`SinceLastInfo`) is the number of times a wrap log file has been filled up\n and a new one is opened or [`inc_wrap_file/1`](`inc_wrap_file/1`) has been\n called since the disk log was last opened ([`info/1`](`info/1`) was last\n called). The first time `info/2` is called after a log was (re)opened or\n truncated, the two values are equal.\n\nNotice that functions [`chunk/2,3`](`chunk/3`), [`bchunk/2,3`](`bchunk/3`), and\n[`chunk_step/3`](`chunk_step/3`) do not affect any value returned by\n[`info/1`](`info/1`).","title":"disk_log.info/1","ref":"disk_log.html#info/1"},{"type":"function","doc":"Synchronously appends a term to a internally formatted disk log. Returns `ok`\nor `{error, Reason}` when the term is written to disk.\n\nTerms are written by the ordinary `write()` function of the operating system.\nHence, it is not guaranteed that the term is written to disk, it can linger in\nthe operating system kernel for a while. To ensure that the item is written to disk,\nfunction `sync/1` must be called.\n\nOwners subscribing to notifications are notified of an error with an\n`error_status` message if the error reason tag is `invalid_header` or\n`file_error`.","title":"disk_log.log/2","ref":"disk_log.html#log/2"},{"type":"function","doc":"Synchronously appends a list of items to an internally formatted log.\n\nIt is more efficient to use this functions instead of [`log/2`](`log/2`). The specified\nlist is split into as large sublists as possible (limited by the size of wrap log files),\nand each sublist is logged as one single item, which reduces the overhead.\n\nOwners subscribing to notifications are notified of an error with an\n`error_status` message if the error reason tag is `invalid_header` or\n`file_error`.","title":"disk_log.log_terms/2","ref":"disk_log.html#log_terms/2"},{"type":"function","doc":"For wrap logs, it forces the disk log to start logging to the next log file. It\ncan be used, for example, with [`change_size/2`](`change_size/2`) to reduce the\namount of disk space allocated by the disk log.\n\nOwners subscribing to notifications normally receive a `wrap` message, but if an\nerror occurs with a reason tag of `invalid_header` or `file_error`, an\n`error_status` message is sent.\n\nFor rotate logs, it forces rotation of the currently active log file, compresses\nit and opens a new active file for logging.","title":"disk_log.next_file/1","ref":"disk_log.html#next_file/1"},{"type":"function","doc":"Open a new disk_log file for reading or writing.\n\nParameter `ArgL` is a list of the following options:\n\n- **`{name, Log}`** - Specifies the log name. This name must be passed on as a\n parameter in all subsequent logging operations. A name must always be\n supplied.\n\n- **`{file, FileName}`** - Specifies the name of the file to be used for logged\n terms. If this value is omitted and the log name is an atom or a string, the\n filename defaults to `lists:concat([Log, \".LOG\"])` for halt logs.\n\n For wrap logs, this is the base name of the files. Each file in a wrap log is\n called ` .N`, where `N` is an integer. Each wrap log also has two\n files called ` .idx` and ` .siz`.\n\n For rotate logs, this is the name of the active log file. The compressed files\n are named as ` .N.gz`, where `N` is an integer and ` .0.gz`\n is the latest compressed log file. All the compressed files are renamed at\n each rotation so that the latest files have the smallest index. The maximum\n value for N is the value of `MaxNoFiles` minus 1.\n\n- **`{linkto, LinkTo}`[](){: #linkto } ** \n If `LinkTo` is a pid, it becomes an owner of the log. If `LinkTo` is `none`, the\n log records that it is used anonymously by some process by incrementing the `users`\n counter. By default, the process that calls [`open/1`](`open/1`) owns the log.\n\n- **`{repair, Repair}`** - If `Repair` is `true`, the current log file is\n repaired, if needed. As the restoration is initiated, a message is output on\n the error log. If `false` is specified, no automatic repair is attempted.\n Instead, the tuple `{error, {need_repair, Log}}` is returned if an attempt is\n made to open a corrupt log file. If `truncate` is specified, the log file\n becomes truncated, creating an empty log, regardless of previous content.\n Defaults to `true`, which has no effect on logs opened in read-only mode.\n\n- **`{type, Type}`** - The log type. Defaults to `halt`.\n\n- **`{format, Format}`** - Disk log format. Defaults to `internal`.\n\n- **`{size, Size}`** - Log size.\n\n When a halt log has reached its maximum size, all attempts to log more items\n are rejected. Defaults to `infinity`, which for halt implies that there is no\n maximum size.\n\n For wrap and rotate logs, parameter `Size` can be a pair\n `{MaxNoBytes, MaxNoFiles}`. For wrap logs it can also be `infinity`. In the\n latter case, if the files of an existing wrap log with the same name can be\n found, the size is read from the existing wrap log, otherwise an error is\n returned.\n\n Wrap logs write at most `MaxNoBytes` bytes on each file and use `MaxNoFiles`\n files before starting all over with the first wrap log file. Regardless of\n `MaxNoBytes`, at least the header (if there is one) and one item are written\n on each wrap log file before wrapping to the next file.\n\n The first time an existing wrap log is opened, that is, when the disk log\n process is created, the value of the option `size` is allowed to differ from\n the current log size, and the size of the disk log is changed as per\n `change_size/2`.\n\n When opening an existing wrap log, it is not necessary to supply a value for\n option `size`, but if the log is already open, that is, the disk log process\n exists, the supplied value must equal the current log size, otherwise the\n tuple `{error, {size_mismatch, CurrentSize, NewSize}}` is returned.\n\n > #### Note {: .info }\n >\n > Before Erlang/OTP 24.0, the supplied value of option `size` was to be equal\n > to the current log size when opening an existing wrap log for the first\n > time, that is, when creating the disk log process.\n\n Rotate logs write at most `MaxNoBytes` bytes on the active log file and keep\n the latest `MaxNoFiles` compressed files. Regardless of `MaxNoBytes`, at least\n the header (if there is one) and one item are written on each rotate log file\n before rotation.\n\n When opening an already open halt log, option `size` is ignored.\n\n- **`{notify, boolean()}`**{: #notify } - If `true`, the log owners are notified\n when certain log events occur. Defaults to `false`. The owners are sent one of the\n following messages when an event occurs:\n\n - **`{disk_log, Node, Log, {wrap, NoLostItems}}`** - Sent when a wrap log has\n filled up one of its files and a new file is opened. `NoLostItems` is the\n number of previously logged items that were lost when truncating existing\n files.\n\n - **`{disk_log, Node, Log, {truncated, NoLostItems}}`** - Sent when a log is\n truncated or reopened. For halt logs `NoLostItems` is the number of items\n written on the log since the disk log process was created. For wrap logs\n `NoLostItems` is the number of items on all wrap log files.\n\n - **`{disk_log, Node, Log, {read_only, Items}}`** - Sent when an asynchronous\n log attempt is made to a log file opened in read-only mode. `Items` is the\n items from the log attempt.\n\n - **`{disk_log, Node, Log, {blocked_log, Items}}`** - Sent when an\n asynchronous log attempt is made to a blocked log that does not queue log\n attempts. `Items` is the items from the log attempt.\n\n - **`{disk_log, Node, Log, {format_external, Items}}`** - Sent when function\n [`alog/2`](`alog/2`) or [`alog_terms/2`](`alog_terms/2`) is used for\n internally formatted logs. `Items` is the items from the log attempt.\n\n - **`{disk_log, Node, Log, full}`** - Sent when an attempt to log items to a\n wrap log would write more bytes than the limit set by option `size`.\n\n - **`{disk_log, Node, Log, {error_status, Status}}`** - Sent when the error\n status changes. The error status is defined by the outcome of the last\n attempt to log items to the log, or to truncate the log, or the last use of\n function [`sync/1`](`sync/1`), [`inc_wrap_file/1`](`inc_wrap_file/1`), or\n [`change_size/2`](`change_size/2`). `Status` is either `ok` or\n `{error, Error}`, the former is the initial value.\n\n- **`{head, Head}`** - Specifies a header to be written first on the log file.\n If the log is a wrap or rotate log, the item `Head` is written first in each\n new file. `Head` is to be a term if the format is `internal`, otherwise an\n `t:iodata/0`. Defaults to `none`, which means that no header is written first\n on the file.\n\n- **`{head_func, {M,F,A}}`** - Specifies a function to be called each time a new\n log file is opened. The call `M:F(A)` is assumed to return `{ok, Head}`. The\n item `Head` is written first in each file. `Head` is to be a term if the\n format is `internal`, otherwise an `t:iodata/0`.\n\n- **`{mode, Mode}`** - Specifies if the log is to be opened in read-only or\n read-write mode. Defaults to `read_write`.\n\n- **`{quiet, Boolean}`** - Specifies if messages will be sent to `error_logger`\n on recoverable errors with the log files. Defaults to `false`.\n\n[`open/1`](`open/1`) returns `{ok, Log}` if the log file is successfully opened.\nIf the file is successfully repaired, the tuple\n`{repaired, Log, {recovered, Rec}, {badbytes, Bad}}` is returned, where `Rec` is\nthe number of whole Erlang terms found in the file and `Bad` is the number of\nbytes in the file that are non-Erlang terms.\n\nWhen a disk log is opened in read-write mode, any existing log file is checked\nfor. If there is none, a new empty log is created, otherwise the existing file\nis opened at the position after the last logged item, and the logging of items\nstarts from there. If the format is `internal` and the existing file is not\nrecognized as an internally formatted log, a tuple\n`{error, {not_a_log_file, FileName}}` is returned.\n\n[`open/1`](`open/1`) cannot be used for changing the values of options of an\nopen log. When there are prior owners or users of a log, all option values\nexcept `name`, `linkto`, and `notify` are only checked against the values\nsupplied before as option values to function [`open/1`](`open/1`),\n[`change_header/2`](`change_header/2`), [`change_notify/3`](`change_notify/3`),\nor [`change_size/2`](`change_size/2`). Thus, none of the options except `name`\nis mandatory. If some specified value differs from the current value, a tuple\n`{error, {arg_mismatch, OptionName, CurrentValue, Value}}` is returned.\n\n> #### Note {: .info }\n>\n> If an owner attempts to open a log as owner once again, it is acknowledged\n> with the return value `{ok, Log}`, but the state of the disk log is not\n> affected.\n\nA log file can be opened more than once by giving different values to option\n`name` or by using the same file when opening a log on different nodes. It is up\nto the user of module `disk_log` to ensure that not more than one disk log\nprocess has write access to any file, otherwise the file can be corrupted.\n\nIf an attempt to open a log file for the first time fails, the disk log process\nterminates with the EXIT message `{{failed,Reason},[{disk_log,open,1}]}`. The\nfunction returns `{error, Reason}` for all other errors.","title":"disk_log.open/1","ref":"disk_log.html#open/1"},{"type":"function","doc":"Returns the log name given the pid of a disk log process on the current node, or\n`undefined` if the specified pid is not a disk log process.\n\nThis function is meant to be used for debugging only.","title":"disk_log.pid2name/1","ref":"disk_log.html#pid2name/1"},{"type":"function","doc":"Equivalent to [`reopen(Log, File, Head)`](`reopen/3`) where `Head` is\nthe `Head` specified in `open/1`.","title":"disk_log.reopen/2","ref":"disk_log.html#reopen/2"},{"type":"function","doc":"Renames an internally formatted log file to `File` and then recreates a new log file. If a\nwrap/rotate log exists, `File` is used as the base name of the renamed files.\n\nWrites the value of `Head` first in the newly opened log file. The header argument\nis used only once. Next time a wrap/rotate log file is opened, the header given to\n[`open/1`](`open/1`) is used.\n\nOwners subscribing to notifications receive a `truncate` message.\n\nUpon failure to reopen the log, the disk log process terminates with the EXIT\nmessage `{{failed,Error},[{disk_log,Fun,Arity}]}`. Other processes having\nrequests queued receive the message\n`{disk_log, Node, {error, disk_log_stopped}}`.","title":"disk_log.reopen/3","ref":"disk_log.html#reopen/3"},{"type":"function","doc":"Ensures that the contents of the log are written to the disk. This is usually a\nrather expensive operation.","title":"disk_log.sync/1","ref":"disk_log.html#sync/1"},{"type":"function","doc":"Equivalent to [`truncate(Log, Head)`](`truncate/2`) where `Head` is\nthe `Head` specified in `open/1`.\n\nThis function can be used for both internally and externally\nformatted logs.","title":"disk_log.truncate/1","ref":"disk_log.html#truncate/1"},{"type":"function","doc":"Removes all items from an internally formatted disk log. The argument `Head` or\nis written first in the newly truncated log.\n\nThe header argument is used only once. Next time a wrap/rotate log file is opened,\nthe header given to [`open/1`](`open/1`) is used.\n\nOwners subscribing to notifications receive a `truncate` message.\n\nIf the attempt to truncate the log fails, the disk log process terminates with\nthe EXIT message `{{failed,Reason},[{disk_log,Fun,Arity}]}`. Other processes\nhaving requests queued receive the message\n`{disk_log, Node, {error, disk_log_stopped}}`.","title":"disk_log.truncate/2","ref":"disk_log.html#truncate/2"},{"type":"function","doc":"Unblocks a log. A log can only be unblocked by the blocking process.","title":"disk_log.unblock/1","ref":"disk_log.html#unblock/1"},{"type":"type","doc":"","title":"disk_log.bchunk_ret/0","ref":"disk_log.html#t:bchunk_ret/0"},{"type":"type","doc":"","title":"disk_log.block_error_rsn/0","ref":"disk_log.html#t:block_error_rsn/0"},{"type":"type","doc":"","title":"disk_log.chunk_error_rsn/0","ref":"disk_log.html#t:chunk_error_rsn/0"},{"type":"type","doc":"","title":"disk_log.chunk_ret/0","ref":"disk_log.html#t:chunk_ret/0"},{"type":"type","doc":"","title":"disk_log.close_error_rsn/0","ref":"disk_log.html#t:close_error_rsn/0"},{"type":"opaque","doc":"Chunk continuation returned by [`chunk/2,3`](`chunk/3`),\n[`bchunk/2,3`](`bchunk/3`), or [`chunk_step/3`](`chunk_step/3`).","title":"disk_log.continuation/0","ref":"disk_log.html#t:continuation/0"},{"type":"type","doc":"","title":"disk_log.dlog_format/0","ref":"disk_log.html#t:dlog_format/0"},{"type":"type","doc":"","title":"disk_log.dlog_head_opt/0","ref":"disk_log.html#t:dlog_head_opt/0"},{"type":"type","doc":"","title":"disk_log.dlog_info/0","ref":"disk_log.html#t:dlog_info/0"},{"type":"type","doc":"","title":"disk_log.dlog_mode/0","ref":"disk_log.html#t:dlog_mode/0"},{"type":"type","doc":"","title":"disk_log.dlog_optattr/0","ref":"disk_log.html#t:dlog_optattr/0"},{"type":"type","doc":"","title":"disk_log.dlog_option/0","ref":"disk_log.html#t:dlog_option/0"},{"type":"type","doc":"","title":"disk_log.dlog_options/0","ref":"disk_log.html#t:dlog_options/0"},{"type":"type","doc":"","title":"disk_log.dlog_size/0","ref":"disk_log.html#t:dlog_size/0"},{"type":"type","doc":"","title":"disk_log.dlog_type/0","ref":"disk_log.html#t:dlog_type/0"},{"type":"type","doc":"","title":"disk_log.file_error/0","ref":"disk_log.html#t:file_error/0"},{"type":"type","doc":"","title":"disk_log.inc_wrap_error_rsn/0","ref":"disk_log.html#t:inc_wrap_error_rsn/0"},{"type":"type","doc":"","title":"disk_log.invalid_header/0","ref":"disk_log.html#t:invalid_header/0"},{"type":"type","doc":"","title":"disk_log.log/0","ref":"disk_log.html#t:log/0"},{"type":"type","doc":"","title":"disk_log.log_error_rsn/0","ref":"disk_log.html#t:log_error_rsn/0"},{"type":"type","doc":"","title":"disk_log.next_file_error_rsn/0","ref":"disk_log.html#t:next_file_error_rsn/0"},{"type":"type","doc":"","title":"disk_log.notify_ret/0","ref":"disk_log.html#t:notify_ret/0"},{"type":"type","doc":"","title":"disk_log.open_error_rsn/0","ref":"disk_log.html#t:open_error_rsn/0"},{"type":"type","doc":"","title":"disk_log.open_ret/0","ref":"disk_log.html#t:open_ret/0"},{"type":"type","doc":"","title":"disk_log.reopen_error_rsn/0","ref":"disk_log.html#t:reopen_error_rsn/0"},{"type":"type","doc":"","title":"disk_log.sync_error_rsn/0","ref":"disk_log.html#t:sync_error_rsn/0"},{"type":"type","doc":"","title":"disk_log.trunc_error_rsn/0","ref":"disk_log.html#t:trunc_error_rsn/0"},{"type":"type","doc":"","title":"disk_log.unblock_error_rsn/0","ref":"disk_log.html#t:unblock_error_rsn/0"},{"type":"module","doc":"Erlang error logger.\n\n> #### Note {: .info }\n>\n> In Erlang/OTP 21.0, a new API for logging was added. The old `m:error_logger`\n> module can still be used by legacy code, but log events are redirected to the\n> new Logger API. New code should use the Logger API directly.\n>\n> `m:error_logger` is no longer started by default, but is automatically started\n> when an event handler is added with [`error_logger:add_report_handler/1,2`](`error_logger:add_report_handler/2`). The\n> `m:error_logger` module is then also added as a handler to the new logger.\n>\n> See `m:logger` and the [Logging](logger_chapter.md) chapter in the User's\n> Guide for more information.\n\nThe Erlang _error logger_ is an event manager (see\n[OTP Design Principles](`e:system:design_principles.md`) and `m:gen_event`),\nregistered as `m:error_logger`.\n\nError logger is no longer started by default, but is automatically started when\nan event handler is added with\n[`add_report_handler/1,2`](`add_report_handler/1`). The `m:error_logger` module is\nthen also added as a handler to the new logger, causing log events to be\nforwarded from logger to error logger, and consequently to all installed error\nlogger event handlers.\n\nUser-defined event handlers can be added to handle application-specific events.\n\nExisting event handlers provided by STDLIB and SASL are still available, but are\nno longer used by OTP.\n\nWarning events were introduced in Erlang/OTP R9C and are enabled by default as\nfrom Erlang/OTP 18.0. To retain backwards compatibility with existing\nuser-defined event handlers, the warning events can be tagged as `errors` or\n`info` using command-line flag `+W `, thus showing up as\n`ERROR REPORT` or `INFO REPORT` in the logs.\n\n[](){: #events }","title":"error_logger","ref":"error_logger.html"},{"type":"module","doc":"All event handlers added to the error logger must handle the following events.\n`Gleader` is the group leader pid of the process that sent the event, and `Pid`\nis the process that sent the event.\n\n- **`{error, Gleader, {Pid, Format, Data}}`** -\n Generated when [`error_msg/1,2`](`error_msg/2`) or `format/2` is called.\n\n- **`{error_report, Gleader, {Pid, std_error, Report}}`** -\n Generated when [`error_report/1`](`error_report/1`) is called.\n\n- **`{error_report, Gleader, {Pid, Type, Report}}`** -\n Generated when [`error_report/2`](`error_report/2`) is called.\n\n- **`{warning_msg, Gleader, {Pid, Format, Data}}`** -\n Generated when [`warning_msg/1,2`](`warning_msg/2`) is called if warnings are set to\n be tagged as warnings.\n\n- **`{warning_report, Gleader, {Pid, std_warning, Report}}`** -\n Generated when [`warning_report/1`](`warning_report/1`) is called if warnings are\n set to be tagged as warnings.\n\n- **`{warning_report, Gleader, {Pid, Type, Report}}`** - Generated when\n [`warning_report/2`](`warning_report/2`) is called if warnings are set to be\n tagged as warnings.\n\n- **`{info_msg, Gleader, {Pid, Format, Data}}`** -\n Generated when [`info_msg/1,2`](`info_msg/2`) is called.\n\n- **`{info_report, Gleader, {Pid, std_info, Report}}`** -\n Generated when [`info_report/1`](`info_report/1`) is called.\n\n- **`{info_report, Gleader, {Pid, Type, Report}}`** -\n Generated when [`info_report/2`](`info_report/2`) is called.\n\nNotice that some system-internal events can also be received. Therefore a\ncatch-all clause last in the definition of the event handler callback function\n`c:gen_event:handle_event/2` is necessary. This also applies for\n`c:gen_event:handle_info/2`, as the event handler must also take care of some\nsystem-internal messages.","title":"Events - error_logger","ref":"error_logger.html#module-events"},{"type":"module","doc":"`m:gen_event`, `m:logger`, `m:log_mf_h`, [`kernel`](kernel_app.md),\n[`sasl`](`e:sasl:sasl_app.md`)","title":"See Also - error_logger","ref":"error_logger.html#module-see-also"},{"type":"function","doc":"","title":"error_logger.add_report_handler/1","ref":"error_logger.html#add_report_handler/1"},{"type":"function","doc":"Adds a new event handler to the error logger. The event handler must be\nimplemented as a `m:gen_event` callback module.\n\n`Handler` is typically the name of the callback module and `Args` is an optional\nterm (defaults to []) passed to the initialization callback function\n`c:gen_event:init/1`. The function returns `ok` if successful.\n\nThe event handler must be able to handle the events in this module, see section\n[Events](`m:error_logger#module-events`).\n\nThe first time this function is called, `m:error_logger` is added as a Logger\nhandler, and the `m:error_logger` process is started.","title":"error_logger.add_report_handler/2","ref":"error_logger.html#add_report_handler/2"},{"type":"function","doc":"Deletes an event handler from the error logger by calling\n[`gen_event:delete_handler(error_logger, Handler, [])`](`gen_event:delete_handler/3`).\n\nIf no more event handlers exist after the deletion, `m:error_logger` is removed as\na Logger handler, and the `m:error_logger` process is stopped.","title":"error_logger.delete_report_handler/1","ref":"error_logger.html#delete_report_handler/1"},{"type":"function","doc":"","title":"error_logger.error_msg/1","ref":"error_logger.html#error_msg/1"},{"type":"function","doc":"Log a standard error event. The `Format` and `Data` arguments are the same as\nthe arguments of `io:format/2` in STDLIB.\n\nError logger forwards the event to Logger, including metadata that allows\nbackwards compatibility with legacy error logger event handlers.\n\nThe event is handled by the default Logger handler.\n\nThis function is kept for backwards compatibility and must not be used by new\ncode. Use the [`?LOG_ERROR`](`m:logger#module-macros`) macro or\n[`logger:error/1,2,3`](`logger:error/1`) instead.\n\n_Example:_\n\n```text\n1> error_logger:error_msg(\"An error occurred in ~p\", [a_module]).\n=ERROR REPORT==== 22-May-2018::11:18:43.376917 ===\nAn error occurred in a_module\nok\n```\n\n> #### Warning {: .warning }\n>\n> If the Unicode translation modifier (`t`) is used in the format string, all\n> event handlers must ensure that the formatted output is correctly encoded for\n> the I/O device.","title":"error_logger.error_msg/2","ref":"error_logger.html#error_msg/2"},{"type":"function","doc":"Log a standard error event. Error logger forwards the event to Logger, including\nmetadata that allows backwards compatibility with legacy error logger event\nhandlers.\n\nThe event is handled by the default Logger handler.\n\nThis functions is kept for backwards compatibility and must not be used by new\ncode. Use the [`?LOG_ERROR`](`m:logger#module-macros`) macro or\n[`logger:error/1,2,3`](`logger:error/1`) instead.\n\n_Example:_\n\n```text\n2> error_logger:error_report([{tag1,data1},a_term,{tag2,data}]).\n=ERROR REPORT==== 22-May-2018::11:24:23.699306 ===\n tag1: data1\n a_term\n tag2: data\nok\n3> error_logger:error_report(\"Serious error in my module\").\n=ERROR REPORT==== 22-May-2018::11:24:45.972445 ===\nSerious error in my module\nok\n```","title":"error_logger.error_report/1","ref":"error_logger.html#error_report/1"},{"type":"function","doc":"Log a user-defined error event. Error logger forwards the event to Logger,\nincluding metadata that allows backwards compatibility with legacy error logger\nevent handlers.\n\nError logger also adds a `domain` field with value `[Type]` to this event's\nmetadata, causing the filters of the default Logger handler to discard the\nevent. A different Logger handler, or an error logger event handler, must be\nadded to handle this event.\n\nIt is recommended that `Report` follows the same structure as for\n`error_report/1`.\n\nThis functions is kept for backwards compatibility and must not be used by new\ncode. Use the [`?LOG_ERROR`](`m:logger#module-macros`) macro or\n[`logger:error/1,2,3`](`logger:error/1`) instead.","title":"error_logger.error_report/2","ref":"error_logger.html#error_report/2"},{"type":"function","doc":"","title":"error_logger.format/2","ref":"error_logger.html#format/2"},{"type":"function","doc":"Returns [`max(10, Depth)`](`max/2`), where `Depth` is the value of\n[`error_logger_format_depth`](kernel_app.md#error_logger_format_depth) in the\nKernel application, if Depth is an integer. Otherwise, `unlimited` is returned.\n\n> #### Note {: .info }\n>\n> The [`error_logger_format_depth`](kernel_app.md#error_logger_format_depth) variable is\n> [deprecated](kernel_app.md#deprecated-configuration-parameters) since the\n> [Logger API](`m:logger`) was introduced in Erlang/OTP 21.0. The variable, and\n> this function, are kept for backwards compatibility since they still might be\n> used by legacy report handlers.","title":"error_logger.get_format_depth/0","ref":"error_logger.html#get_format_depth/0"},{"type":"function","doc":"","title":"error_logger.info_msg/1","ref":"error_logger.html#info_msg/1"},{"type":"function","doc":"Log a standard information event. The `Format` and `Data` arguments are the same\nas the arguments of `io:format/2` in STDLIB.\n\nError logger forwards the event to Logger, including metadata that allows\nbackwards compatibility with legacy error logger event handlers.\n\nThe event is handled by the default Logger handler.\n\nThese functions are kept for backwards compatibility and must not be used by new\ncode. Use the [`?LOG_INFO`](`m:logger#module-macros`) macro or\n[`logger:info/1,2,3`](`logger:info/1`) instead.\n\n_Example:_\n\n```text\n1> error_logger:info_msg(\"Something happened in ~p\", [a_module]).\n=INFO REPORT==== 22-May-2018::12:03:32.612462 ===\nSomething happened in a_module\nok\n```\n\n> #### Warning {: .warning }\n>\n> If the Unicode translation modifier (`t`) is used in the format string, all\n> event handlers must ensure that the formatted output is correctly encoded for\n> the I/O device.","title":"error_logger.info_msg/2","ref":"error_logger.html#info_msg/2"},{"type":"function","doc":"Log a standard information event. Error logger forwards the event to Logger,\nincluding metadata that allows backwards compatibility with legacy error logger\nevent handlers.\n\nThe event is handled by the default Logger handler.\n\nThis functions is kept for backwards compatibility and must not be used by new\ncode. Use the [`?LOG_INFO`](`m:logger#module-macros`) macro or\n[`logger:info/1,2,3`](`logger:info/1`) instead.\n\n_Example:_\n\n```text\n2> error_logger:info_report([{tag1,data1},a_term,{tag2,data}]).\n=INFO REPORT==== 22-May-2018::12:06:35.994440 ===\n tag1: data1\n a_term\n tag2: data\nok\n3> error_logger:info_report(\"Something strange happened\").\n=INFO REPORT==== 22-May-2018::12:06:49.066872 ===\nSomething strange happened\nok\n```","title":"error_logger.info_report/1","ref":"error_logger.html#info_report/1"},{"type":"function","doc":"Log a user-defined information event. Error logger forwards the event to Logger,\nincluding metadata that allows backwards compatibility with legacy error logger\nevent handlers.\n\nError logger also adds a `domain` field with value `[Type]` to this event's\nmetadata, causing the filters of the default Logger handler to discard the\nevent. A different Logger handler, or an error logger event handler, must be\nadded to handle this event.\n\nIt is recommended that `Report` follows the same structure as for\n`info_report/1`.\n\nThis functions is kept for backwards compatibility and must not be used by new\ncode. Use the [`?LOG_INFO`](`m:logger#module-macros`) macro or\n[`logger:info/1,2,3`](`logger:info/1`) instead.","title":"error_logger.info_report/2","ref":"error_logger.html#info_report/2"},{"type":"function","doc":"Enables or disables printout of standard events to a file.\n\nThis is done by adding or deleting the `error_logger_file_h` event handler, and\nthus indirectly adding `m:error_logger` as a Logger handler.\n\nNotice that this function does not manipulate the Logger configuration directly,\nmeaning that if the default Logger handler is already logging to a file, this\nfunction can potentially cause logging to a second file.\n\nThis function is useful as a shortcut during development and testing, but must\nnot be used in a production system. See section [Logging](logger_chapter.md) in\nthe Kernel User's Guide, and the `m:logger` manual page for information about\nhow to configure Logger for live systems.\n\n`Request` is one of the following:\n\n- **`{open, Filename}`** - Opens log file `Filename`. Returns `ok` if\n successful, or `{error, allready_have_logfile}` if logging to file is already\n enabled, or an error tuple if another error occurred (for example, if\n `Filename` cannot be opened). The file is opened with encoding UTF-8.\n\n- **`close`** - Closes the current log file. Returns `ok`, or\n `{error, module_not_found}`.\n\n- **`filename`** - Returns the name of the log file `Filename`, or\n `{error, no_log_file}` if logging to file is not enabled.","title":"error_logger.logfile/1","ref":"error_logger.html#logfile/1"},{"type":"function","doc":"Enables (`Flag == true`) or disables (`Flag == false`) printout of standard\nevents to the terminal.\n\nThis is done by manipulating the Logger configuration. The function is useful as\na shortcut during development and testing, but must not be used in a production\nsystem. See section [Logging](logger_chapter.md) in the Kernel User's Guide, and\nthe `m:logger` manual page for information about how to configure Logger for\nlive systems.","title":"error_logger.tty/1","ref":"error_logger.html#tty/1"},{"type":"function","doc":"Returns the current mapping for warning events.\n\nEvents sent using [`warning_msg/1,2`](`warning_msg/2`) or\n[`warning_report/1,2`](`warning_report/2`) are tagged as errors, warnings\n(default), or info, depending on the value of command-line flag `+W`.\n\n_Example:_\n\n```text\nos$ erl\nErlang (BEAM) emulator version 5.4.8 [hipe] [threads:0] [kernel-poll]\n\nEshell V5.4.8 (abort with ^G)\n1> error_logger:warning_map().\nwarning\n2> error_logger:warning_msg(\"Warnings tagged as: ~p~n\", [warning]).\n\n=WARNING REPORT==== 11-Aug-2005::15:31:55 ===\nWarnings tagged as: warning\nok\n3>\nUser switch command\n --> q\nos$ erl +W e\nErlang (BEAM) emulator version 5.4.8 [hipe] [threads:0] [kernel-poll]\n\nEshell V5.4.8 (abort with ^G)\n1> error_logger:warning_map().\nerror\n2> error_logger:warning_msg(\"Warnings tagged as: ~p~n\", [error]).\n\n=ERROR REPORT==== 11-Aug-2005::15:31:23 ===\nWarnings tagged as: error\nok\n```","title":"error_logger.warning_map/0","ref":"error_logger.html#warning_map/0"},{"type":"function","doc":"","title":"error_logger.warning_msg/1","ref":"error_logger.html#warning_msg/1"},{"type":"function","doc":"Log a standard warning event. The `Format` and `Data` arguments are the same as\nthe arguments of `io:format/2` in STDLIB.\n\nError logger forwards the event to Logger, including metadata that allows\nbackwards compatibility with legacy error logger event handlers.\n\nThe event is handled by the default Logger handler. The log level can be changed\nto error or info, see `warning_map/0`.\n\nThese functions are kept for backwards compatibility and must not be used by new\ncode. Use the [`?LOG_WARNING`](`m:logger#module-macros`) macro or\n[`logger:warning/1,2,3`](`logger:warning/1`) instead.\n\n> #### Warning {: .warning }\n>\n> If the Unicode translation modifier (`t`) is used in the format string, all\n> event handlers must ensure that the formatted output is correctly encoded for\n> the I/O device.","title":"error_logger.warning_msg/2","ref":"error_logger.html#warning_msg/2"},{"type":"function","doc":"Log a standard warning event. Error logger forwards the event to Logger,\nincluding metadata that allows backwards compatibility with legacy error logger\nevent handlers.\n\nThe event is handled by the default Logger handler. The log level can be changed\nto error or info, see `warning_map/0`.\n\nThis functions is kept for backwards compatibility and must not be used by new\ncode. Use the [`?LOG_WARNING`](`m:logger#module-macros`) macro or\n[`logger:warning/1,2,3`](`logger:warning/1`) instead.","title":"error_logger.warning_report/1","ref":"error_logger.html#warning_report/1"},{"type":"function","doc":"Log a user-defined warning event. Error logger forwards the event to Logger,\nincluding metadata that allows backwards compatibility with legacy error logger\nevent handlers.\n\nError logger also adds a `domain` field with value `[Type]` to this event's\nmetadata, causing the filters of the default Logger handler to discard the\nevent. A different Logger handler, or an error logger event handler, must be\nadded to handle this event.\n\nThe log level can be changed to error or info, see `warning_map/0`.\n\nIt is recommended that `Report` follows the same structure as for\n`warning_report/1`.\n\nThis functions is kept for backwards compatibility and must not be used by new\ncode. Use the [`?LOG_WARNING`](`m:logger#module-macros`) macro or\n[`logger:warning/1,2,3`](`logger:warning/1`) instead.","title":"error_logger.warning_report/2","ref":"error_logger.html#warning_report/2"},{"type":"type","doc":"","title":"error_logger.open_error/0","ref":"error_logger.html#t:open_error/0"},{"type":"type","doc":"","title":"error_logger.report/0","ref":"error_logger.html#t:report/0"},{"type":"module","doc":"API module for Logger, the standard logging facility in Erlang/OTP.\n\nThis module implements the main API for logging in Erlang/OTP. To create a log\nevent, use the [API functions](#logging-api-functions) or the log\n[macros](#module-macros), for example:\n\n```erlang\n?LOG_ERROR(\"error happened because: ~p\", [Reason]). % With macro\nlogger:error(\"error happened because: ~p\", [Reason]). % Without macro\n```\n\nTo configure the Logger backend, use\n[Kernel configuration parameters](kernel_app.md#logger) or\n[configuration functions](#configuration-api-functions) in the Logger API.\n\nBy default, the Kernel application installs one log handler at system start.\nThis handler is named `default`. It receives and processes standard log events\nproduced by the Erlang runtime system, standard behaviours and different\nErlang/OTP applications. The log events are by default printed to the terminal.\n\nIf you want your systems logs to be printed to a file instead, you must\nconfigure the default handler to do so. The simplest way is to include the\nfollowing in your [`sys.config`](config.md):\n\n```erlang\n[{kernel,\n [{logger,\n [{handler, default, logger_std_h,\n #{config => #{file => \"path/to/file.log\"}}}]}]}].\n```\n\nFor more information about:\n\n- the Logger facility in general, see the [User's Guide](logger_chapter.md).\n- how to configure Logger, see the\n [Configuration](logger_chapter.md#configuration) section in the User's Guide.\n- the built-in handlers, see `m:logger_std_h` and `m:logger_disk_log_h`.\n- the built-in formatter, see `m:logger_formatter`.\n- built-in filters, see `m:logger_filters`.","title":"logger","ref":"logger.html"},{"type":"module","doc":"The following macros are defined in `logger.hrl`, which is included in a module\nwith the directive\n\n```erlang\n -include_lib(\"kernel/include/logger.hrl\").\n```\n\n- `?LOG_EMERGENCY(StringOrReport[,Metadata])`\n- `?LOG_EMERGENCY(FunOrFormat,Args[,Metadata])`\n- `?LOG_ALERT(StringOrReport[,Metadata])`\n- `?LOG_ALERT(FunOrFormat,Args[,Metadata])`\n- `?LOG_CRITICAL(StringOrReport[,Metadata])`\n- `?LOG_CRITICAL(FunOrFormat,Args[,Metadata])`\n- `?LOG_ERROR(StringOrReport[,Metadata])`\n- `?LOG_ERROR(FunOrFormat,Args[,Metadata])`\n- `?LOG_WARNING(StringOrReport[,Metadata])`\n- `?LOG_WARNING(FunOrFormat,Args[,Metadata])`\n- `?LOG_NOTICE(StringOrReport[,Metadata])`\n- `?LOG_NOTICE(FunOrFormat,Args[,Metadata])`\n- `?LOG_INFO(StringOrReport[,Metadata])`\n- `?LOG_INFO(FunOrFormat,Args[,Metadata])`\n- `?LOG_DEBUG(StringOrReport[,Metadata])`\n- `?LOG_DEBUG(FunOrFormat,Args[,Metadata])`\n- `?LOG(Level,StringOrReport[,Metadata])`\n- `?LOG(Level,FunOrFormat,Args[,Metadata])`\n\nAll macros expand to a call to Logger, where `Level` is taken from the macro\nname, or from the first argument in the case of the `?LOG` macro. Location data\nis added to the metadata as described under the `t:metadata/0` type definition.\n\nThe call is wrapped in a case statement and will be evaluated only if `Level` is\nequal to or below the configured log level.","title":"Macros - logger","ref":"logger.html#module-macros"},{"type":"module","doc":"[`config`](config.md), `m:erlang`, `m:io`, `m:logger_disk_log_h`,\n`m:logger_filters`, `m:logger_handler`, `m:logger_formatter`, `m:logger_std_h`,\n`m:unicode`","title":"See Also - logger","ref":"logger.html#module-see-also"},{"type":"function","doc":"Add a handler with the given configuration.\n\n`HandlerId` is a unique identifier which must be used in all subsequent calls\nreferring to this handler.","title":"logger.add_handler/3","ref":"logger.html#add_handler/3"},{"type":"function","doc":"Add a filter to the specified handler.\n\nThe filter fun is called with the log event as the first parameter, and the\nspecified `filter_args()` as the second parameter.\n\nThe return value of the fun specifies if a log event is to be discarded or\nforwarded to the handler callback:\n\n- **`t:log_event/0`** - The filter _passed_. The next handler filter, if any, is\n applied. If no more filters exist for this handler, the log event is forwarded\n to the handler callback.\n\n- **`stop`** - The filter _did not pass_, and the log event is immediately\n discarded.\n\n- **`ignore`** - The filter has no knowledge of the log event. The next handler\n filter, if any, is applied. If no more filters exist for this handler, the\n value of the `filter_default` configuration parameter for the handler\n specifies if the log event shall be discarded or forwarded to the handler\n callback.\n\nSee section [Filters](logger_chapter.md#filters) in the User's Guide for more\ninformation about filters.\n\nSome built-in filters exist. These are defined in `m:logger_filters`.","title":"logger.add_handler_filter/3","ref":"logger.html#add_handler_filter/3"},{"type":"function","doc":"Reads the application configuration parameter `logger` and calls\n[`add_handlers/1`](`add_handlers/1`) with its contents.\n\nThis function should be used by custom Logger handlers to make configuration\nconsistent no matter which handler the system uses. Normal usage is to add a\ncall to `logger:add_handlers/1` just after the processes that the handler needs\nare started, and pass the application's `logger` configuration as the argument.\nFor example:\n\n```erlang\n-behaviour(application).\nstart(_, []) ->\n case supervisor:start_link({local, my_sup}, my_sup, []) of\n {ok, Pid} ->\n ok = logger:add_handlers(my_app),\n {ok, Pid, []};\n Error -> Error\n end.\n```\n\nThis reads the `logger` configuration parameter from the `my_app` application\nand starts the configured handlers. The contents of the configuration use the\nsame rules as the\n[logger handler configuration](logger_chapter.md#handler-configuration).\n\nIf the handler is meant to replace the default handler, the Kernel's default\nhandler have to be disabled before the new handler is added. A `sys.config` file\nthat disables the Kernel handler and adds a custom handler could look like this:\n\n```erlang\n[{kernel,\n [{logger,\n %% Disable the default Kernel handler\n [{handler, default, undefined}]}]},\n {my_app,\n [{logger,\n %% Enable this handler as the default\n [{handler, default, my_handler, #{}}]}]}].\n```","title":"logger.add_handlers/1","ref":"logger.html#add_handlers/1"},{"type":"function","doc":"Add a primary filter to Logger.\n\nThe filter fun is called with the log event as the first parameter, and the\nspecified `filter_args()` as the second parameter.\n\nThe return value of the fun specifies if a log event is to be discarded or\nforwarded to the handlers:\n\n- **`t:log_event/0`** - The filter _passed_. The next primary filter, if any, is\n applied. If no more primary filters exist, the log event is forwarded to the\n handler part of Logger, where handler filters are applied.\n\n- **`stop`** - The filter _did not pass_, and the log event is immediately\n discarded.\n\n- **`ignore`** - The filter has no knowledge of the log event. The next primary\n filter, if any, is applied. If no more primary filters exist, the value of the\n primary `filter_default` configuration parameter specifies if the log event\n shall be discarded or forwarded to the handler part.\n\nSee section [Filters](logger_chapter.md#filters) in the User's Guide for more\ninformation about filters.\n\nSome built-in filters exist. These are defined in `m:logger_filters`.","title":"logger.add_primary_filter/2","ref":"logger.html#add_primary_filter/2"},{"type":"function","doc":"","title":"logger.alert/1","ref":"logger.html#alert/1"},{"type":"function","doc":"Create a alert log event.\n\nEquivalent to [`log(alert, StringOrReport, Metadata)`](`log/3`) if called\nas [`alert(StringOrReport, Metadata)`](`alert/2`).\n\nEquivalent to [`alert(FormatOrFun, Args, #{})`](`alert/3`) if called as\n[`alert(FormatOrFun, Args)`](`alert/2`).","title":"logger.alert/2","ref":"logger.html#alert/2"},{"type":"function","doc":"","title":"logger.alert/3","ref":"logger.html#alert/3"},{"type":"function","doc":"Compare the severity of two log levels. Returns `gt` if `Level1` is more severe\nthan `Level2`, `lt` if `Level1` is less severe, and `eq` if the levels are\nequal.","title":"logger.compare_levels/2","ref":"logger.html#compare_levels/2"},{"type":"function","doc":"","title":"logger.critical/1","ref":"logger.html#critical/1"},{"type":"function","doc":"Create a critical log event.\n\nEquivalent to [`log(critical, StringOrReport, Metadata)`](`log/3`) if called\nas [`critical(StringOrReport, Metadata)`](`critical/2`).\n\nEquivalent to [`critical(FormatOrFun, Args, #{})`](`critical/3`) if called as\n[`critical(FormatOrFun, Args)`](`critical/2`).","title":"logger.critical/2","ref":"logger.html#critical/2"},{"type":"function","doc":"","title":"logger.critical/3","ref":"logger.html#critical/3"},{"type":"function","doc":"","title":"logger.debug/1","ref":"logger.html#debug/1"},{"type":"function","doc":"Create a debug log event.\n\nEquivalent to [`log(debug, StringOrReport, Metadata)`](`log/3`) if called\nas [`debug(StringOrReport, Metadata)`](`debug/2`).\n\nEquivalent to [`debug(FormatOrFun, Args, #{})`](`debug/3`) if called as\n[`debug(FormatOrFun, Args)`](`debug/2`).","title":"logger.debug/2","ref":"logger.html#debug/2"},{"type":"function","doc":"","title":"logger.debug/3","ref":"logger.html#debug/3"},{"type":"function","doc":"","title":"logger.emergency/1","ref":"logger.html#emergency/1"},{"type":"function","doc":"Create a emergency log event.\n\nEquivalent to [`log(emergency, StringOrReport, Metadata)`](`log/3`) if called\nas [`emergency(StringOrReport, Metadata)`](`emergency/2`).\n\nEquivalent to [`emergency(FormatOrFun, Args, #{})`](`emergency/3`) if called as\n[`emergency(FormatOrFun, Args)`](`emergency/2`).","title":"logger.emergency/2","ref":"logger.html#emergency/2"},{"type":"function","doc":"","title":"logger.emergency/3","ref":"logger.html#emergency/3"},{"type":"function","doc":"","title":"logger.error/1","ref":"logger.html#error/1"},{"type":"function","doc":"Create a error log event.\n\nEquivalent to [`log(error, StringOrReport, Metadata)`](`log/3`) if called\nas [`error(StringOrReport, Metadata)`](`error/2`).\n\nEquivalent to [`error(FormatOrFun, Args, #{})`](`error/3`) if called as\n[`error(FormatOrFun, Args)`](`error/2`).","title":"logger.error/2","ref":"logger.html#error/2"},{"type":"function","doc":"","title":"logger.error/3","ref":"logger.html#error/3"},{"type":"function","doc":"Convert a log message on report form to `{Format, Args}`. This is the default\nreport callback used by `m:logger_formatter` when no custom report callback is\nfound. See section [Log Message](logger_chapter.md#log-message) in the Kernel\nUser's Guide for information about report callbacks and valid forms of log\nmessages.\n\nThe function produces lines of `Key: Value` from key-value lists. Strings are\nprinted with `~ts` and other terms with `~tp`.\n\nIf `Report` is a map, it is converted to a key-value list before formatting as\nsuch.","title":"logger.format_report/1","ref":"logger.html#format_report/1"},{"type":"function","doc":"Look up all current Logger configuration, including primary, handler, and proxy\nconfiguration, and module level settings.","title":"logger.get_config/0","ref":"logger.html#get_config/0"},{"type":"function","doc":"Look up the current configuration for all handlers.","title":"logger.get_handler_config/0","ref":"logger.html#get_handler_config/0"},{"type":"function","doc":"Look up the current configuration for the given handler.","title":"logger.get_handler_config/1","ref":"logger.html#get_handler_config/1"},{"type":"function","doc":"Look up the identities for all installed handlers.","title":"logger.get_handler_ids/0","ref":"logger.html#get_handler_ids/0"},{"type":"function","doc":"Look up all current module levels. Returns a list containing one\n`{Module,Level}` element for each module for which the module level was\npreviously set with `set_module_level/2`.","title":"logger.get_module_level/0","ref":"logger.html#get_module_level/0"},{"type":"function","doc":"Look up the current level for the given modules. Returns a list containing one\n`{Module,Level}` element for each of the given modules for which the module\nlevel was previously set with `set_module_level/2`.","title":"logger.get_module_level/1","ref":"logger.html#get_module_level/1"},{"type":"function","doc":"Look up the current primary configuration for Logger.","title":"logger.get_primary_config/0","ref":"logger.html#get_primary_config/0"},{"type":"function","doc":"Retrieve data set with `set_process_metadata/1` or `update_process_metadata/1`.","title":"logger.get_process_metadata/0","ref":"logger.html#get_process_metadata/0"},{"type":"function","doc":"Look up the current configuration for the Logger proxy.\n\nFor more information about the proxy, see section\n[Logger Proxy](logger_chapter.md#logger-proxy) in the Kernel User's Guide.","title":"logger.get_proxy_config/0","ref":"logger.html#get_proxy_config/0"},{"type":"function","doc":"Pretty print all Logger configuration.","title":"logger.i/0","ref":"logger.html#i/0"},{"type":"function","doc":"Pretty print the Logger configuration.","title":"logger.i/1","ref":"logger.html#i/1"},{"type":"function","doc":"","title":"logger.info/1","ref":"logger.html#info/1"},{"type":"function","doc":"Create a info log event.\n\nEquivalent to [`log(info, StringOrReport, Metadata)`](`log/3`) if called\nas [`info(StringOrReport, Metadata)`](`info/2`).\n\nEquivalent to [`info(FormatOrFun, Args, #{})`](`info/3`) if called as\n[`info(FormatOrFun, Args)`](`info/2`).","title":"logger.info/2","ref":"logger.html#info/2"},{"type":"function","doc":"","title":"logger.info/3","ref":"logger.html#info/3"},{"type":"function","doc":"","title":"logger.log/2","ref":"logger.html#log/2"},{"type":"function","doc":"Create a log event at the given [log level](logger_chapter.md#log-level), with\nthe given [message](logger_chapter.md#log-message) to be logged and\n[_metadata_](logger_chapter.md#metadata).\n\n*Example*:\n\n```erlang\n%% A plain string\n1> logger:log(info, \"Hello World\").\n%% A plain string with metadata\n2> logger:log(debug, \"Hello World\", #{ meta => data }).\n%% A format string with arguments\n3> logger:log(warning, \"The roof is on ~ts\",[Cause]).\n%% A report\n4> logger:log(warning, #{ what => roof, cause => Cause }).\n```\n\nEquivalent to [`log(Level, FormatOrFun, Args, #{})`](`log/4`) if called as\n`log(Level, FormatOrFun, Args)`.","title":"logger.log/3","ref":"logger.html#log/3"},{"type":"function","doc":"Create a log event at the given [log level](logger_chapter.md#log-level), with\nthe given [message](logger_chapter.md#log-message) to be logged and\n[_metadata_](logger_chapter.md#metadata).\n\nThe message and metadata can either be given directly in the arguments, or\nreturned from a fun. Passing a fun instead of the message/metadata directly is\nuseful in scenarios when the message/metadata is very expensive to compute. This\nis because the fun is only evaluated when the message/metadata is actually\nneeded, which may be not at all if the log event is not to be logged. Examples:\n\n```erlang\n%% A plain string with expensive metadata\n1> logger:info(fun([]) -> {\"Hello World\", #{ meta => expensive() }} end,[]).\n%% An expensive report\n2> logger:debug(fun(What) -> #{ what => What, cause => expensive() } end,roof).\n%% A plain string with expensive metadata and normal metadata\n3> logger:debug(fun([]) -> {\"Hello World\", #{ meta => expensive() }} end,[],\n #{ meta => data }).\n```\n\nWhen metadata is given both as an argument and returned from the fun they are\nmerged. If equal keys exists the values are taken from the metadata returned by\nthe fun.","title":"logger.log/4","ref":"logger.html#log/4"},{"type":"function","doc":"","title":"logger.notice/1","ref":"logger.html#notice/1"},{"type":"function","doc":"Create a notice log event.\n\nEquivalent to [`log(notice, StringOrReport, Metadata)`](`log/3`) if called\nas [`notice(StringOrReport, Metadata)`](`notice/2`).\n\nEquivalent to [`notice(FormatOrFun, Args, #{})`](`notice/3`) if called as\n[`notice(FormatOrFun, Args)`](`notice/2`).","title":"logger.notice/2","ref":"logger.html#notice/2"},{"type":"function","doc":"","title":"logger.notice/3","ref":"logger.html#notice/3"},{"type":"function","doc":"Reconfigure Logger using updated `kernel` configuration that was set after\n`kernel` application was loaded.\n\nBeware, that this is meant to be run only by the build tools, not manually\nduring application lifetime, as this may cause missing log entries.","title":"logger.reconfigure/0","ref":"logger.html#reconfigure/0"},{"type":"function","doc":"Remove the handler identified by `HandlerId`.","title":"logger.remove_handler/1","ref":"logger.html#remove_handler/1"},{"type":"function","doc":"Remove the filter identified by `FilterId` from the handler identified by\n`HandlerId`.","title":"logger.remove_handler_filter/2","ref":"logger.html#remove_handler_filter/2"},{"type":"function","doc":"Remove the primary filter identified by `FilterId` from Logger.","title":"logger.remove_primary_filter/1","ref":"logger.html#remove_primary_filter/1"},{"type":"function","doc":"Set the log level for all the modules of the specified application.\n\nThis function is a convenience function that calls\n[logger:set_module_level/2](`set_module_level/2`) for each module associated\nwith an application.","title":"logger.set_application_level/2","ref":"logger.html#set_application_level/2"},{"type":"function","doc":"Set configuration data for the specified handler. This overwrites the current\nhandler configuration.\n\nTo modify the existing configuration, use `update_handler_config/2`, or, if a\nmore complex merge is needed, read the current configuration with\n[`get_handler_config/1` ](`get_handler_config/1`), then do the merge before\nwriting the new configuration back with this function.\n\nIf a key is removed compared to the current configuration, and the key is known\nby Logger, the default value is used. If it is a custom key, then it is up to\nthe handler implementation if the value is removed or a default value is\ninserted.","title":"logger.set_handler_config/2","ref":"logger.html#set_handler_config/2"},{"type":"function","doc":"Add or update configuration data for the specified handler. If the given `Key`\nalready exists, its associated value will be changed to the given value. If it\ndoes not exist, it will be added.\n\nIf the value is incomplete, which for example can be the case for the `config`\nkey, it is up to the handler implementation how the unspecified parts are set.\nFor all handlers in the Kernel application, unspecified data for the `config`\nkey is set to default values. To update only specified data, and keep the\nexisting configuration for the rest, use `update_handler_config/3`.\n\nSee the definition of the `t:logger_handler:config/0` type for more information\nabout the different parameters.","title":"logger.set_handler_config/3","ref":"logger.html#set_handler_config/3"},{"type":"function","doc":"Set the log level for the specified modules.\n\nThe log level for a module overrides the primary log level of Logger for log\nevents originating from the module in question. Notice, however, that it does\nnot override the level configuration for any handler.\n\nFor example: Assume that the primary log level for Logger is `info`, and there\nis one handler, `h1`, with level `info` and one handler, `h2`, with level\n`debug`.\n\nWith this configuration, no debug messages will be logged, since they are all\nstopped by the primary log level.\n\nIf the level for `mymodule` is now set to `debug`, then debug events from this\nmodule will be logged by the handler `h2`, but not by handler `h1`.\n\nDebug events from other modules are still not logged.\n\nTo change the primary log level for Logger, use\n[`set_primary_config(level, Level)`](`set_primary_config/2`).\n\nTo change the log level for a handler, use\n[`set_handler_config(HandlerId, level, Level)` ](`set_handler_config/3`).\n\n> #### Note {: .info }\n>\n> The originating module for a log event is only detected if the key `mfa`\n> exists in the metadata, and is associated with `{Module, Function, Arity}`.\n> When log macros are used, this association is automatically added to all log\n> events. If an API function is called directly, without using a macro, the\n> logging client must explicitly add this information if module levels shall\n> have any effect.","title":"logger.set_module_level/2","ref":"logger.html#set_module_level/2"},{"type":"function","doc":"Set primary configuration data for Logger. This overwrites the current\nconfiguration.\n\nTo modify the existing configuration, use `update_primary_config/1`, or, if a\nmore complex merge is needed, read the current configuration with\n[`get_primary_config/0` ](`get_primary_config/0`), then do the merge before\nwriting the new configuration back with this function.\n\nIf a key is removed compared to the current configuration, the default value is\nused.","title":"logger.set_primary_config/1","ref":"logger.html#set_primary_config/1"},{"type":"function","doc":"Add or update primary configuration data for Logger. If the given `Key` already\nexists, its associated value will be changed to the given value. If it does not\nexist, it will be added.\n\nThe `metadata` key was added in OTP 24.0.","title":"logger.set_primary_config/2","ref":"logger.html#set_primary_config/2"},{"type":"function","doc":"Set metadata which Logger shall automatically insert in all log events produced\non the current process.\n\nLocation data produced by the log macros, and/or metadata given as argument to\nthe log call (API function or macro), are merged with the process metadata. If\nthe same keys occur, values from the metadata argument to the log call overwrite\nvalues from the process metadata, which in turn overwrite values from the\nlocation data.\n\nSubsequent calls to this function overwrites previous data set. To update\nexisting data instead of overwriting it, see `update_process_metadata/1`.","title":"logger.set_process_metadata/1","ref":"logger.html#set_process_metadata/1"},{"type":"function","doc":"Set configuration data for the Logger proxy. This overwrites the current proxy\nconfiguration. Keys that are not specified in the `Config` map gets default\nvalues.\n\nTo modify the existing configuration, use `update_proxy_config/1`, or, if a more\ncomplex merge is needed, read the current configuration with\n[`get_proxy_config/0` ](`get_proxy_config/0`), then do the merge before writing\nthe new configuration back with this function.\n\nFor more information about the proxy, see section\n[Logger Proxy](logger_chapter.md#logger-proxy) in the Kernel User's Guide.","title":"logger.set_proxy_config/1","ref":"logger.html#set_proxy_config/1"},{"type":"function","doc":"Return a timestamp that can be inserted as the `time` field in the meta data for\na log event. It is produced with\n[`os:system_time(microsecond)`](`os:system_time/1`).\n\nNotice that Logger automatically inserts a timestamp in the meta data unless it\nalready exists. This function is exported for the rare case when the timestamp\nmust be taken at a different point in time than when the log event is issued.","title":"logger.timestamp/0","ref":"logger.html#timestamp/0"},{"type":"function","doc":"Unset the log level for all the modules of the specified application.\n\nThis function is a utility function that calls\n[logger:unset_module_level/2](`unset_module_level/1`) for each module associated\nwith an application.","title":"logger.unset_application_level/1","ref":"logger.html#unset_application_level/1"},{"type":"function","doc":"Remove module specific log settings. After this, the primary log level is used\nfor all modules.","title":"logger.unset_module_level/0","ref":"logger.html#unset_module_level/0"},{"type":"function","doc":"Remove module specific log settings. After this, the primary log level is used\nfor the specified modules.","title":"logger.unset_module_level/1","ref":"logger.html#unset_module_level/1"},{"type":"function","doc":"Delete data set with `set_process_metadata/1` or `update_process_metadata/1`.","title":"logger.unset_process_metadata/0","ref":"logger.html#unset_process_metadata/0"},{"type":"function","doc":"Update the formatter configuration for the specified handler.\n\nThe new configuration is merged with the existing formatter configuration.\n\nTo overwrite the existing configuration without any merge, use\n\n```erlang\nset_handler_config(HandlerId, formatter,\n\t {FormatterModule, FormatterConfig}).\n```","title":"logger.update_formatter_config/2","ref":"logger.html#update_formatter_config/2"},{"type":"function","doc":"","title":"logger.update_formatter_config/3","ref":"logger.html#update_formatter_config/3"},{"type":"function","doc":"Update configuration data for the specified handler. This function behaves as if\nit was implemented as follows:\n\n```erlang\n{ok, {_, Old}} = logger:get_handler_config(HandlerId),\nlogger:set_handler_config(HandlerId, maps:merge(Old, Config)).\n```\n\nTo overwrite the existing configuration without any merge, use\n[`set_handler_config/2` ](`set_handler_config/2`).","title":"logger.update_handler_config/2","ref":"logger.html#update_handler_config/2"},{"type":"function","doc":"Add or update configuration data for the specified handler. If the given `Key`\nalready exists, its associated value will be changed to the given value. If it\ndoes not exist, it will be added.\n\nIf the value is incomplete, which for example can be the case for the `config`\nkey, it is up to the handler implementation how the unspecified parts are set.\nFor all handlers in the Kernel application, unspecified data for the `config`\nkey is not changed. To reset unspecified data to default values, use\n`set_handler_config/3`.\n\nSee the definition of the `t:logger_handler:config/0` type for more information\nabout the different parameters.","title":"logger.update_handler_config/3","ref":"logger.html#update_handler_config/3"},{"type":"function","doc":"Update primary configuration data for Logger. This function behaves as if it was\nimplemented as follows:\n\n```erlang\nOld = logger:get_primary_config(),\nlogger:set_primary_config(maps:merge(Old, Config)).\n```\n\nTo overwrite the existing configuration without any merge, use\n[`set_primary_config/1` ](`set_primary_config/1`).","title":"logger.update_primary_config/1","ref":"logger.html#update_primary_config/1"},{"type":"function","doc":"Set or update metadata to use when logging from current process\n\nIf process metadata exists for the current process, this function behaves as if\nit was implemented as follows:\n\n```erlang\nlogger:set_process_metadata(maps:merge(logger:get_process_metadata(), Meta)).\n```\n\nIf no process metadata exists, the function behaves as\n[`set_process_metadata/1` ](`set_process_metadata/1`).","title":"logger.update_process_metadata/1","ref":"logger.html#update_process_metadata/1"},{"type":"function","doc":"Update configuration data for the Logger proxy. This function behaves as if it\nwas implemented as follows:\n\n```erlang\nOld = logger:get_proxy_config(),\nlogger:set_proxy_config(maps:merge(Old, Config)).\n```\n\nTo overwrite the existing configuration without any merge, use\n[`set_proxy_config/1` ](`set_proxy_config/1`).\n\nFor more information about the proxy, see section\n[Logger Proxy](logger_chapter.md#logger-proxy) in the Kernel User's Guide.","title":"logger.update_proxy_config/1","ref":"logger.html#update_proxy_config/1"},{"type":"function","doc":"","title":"logger.warning/1","ref":"logger.html#warning/1"},{"type":"function","doc":"Create a warning log event.\n\nEquivalent to [`log(warning, StringOrReport, Metadata)`](`log/3`) if called\nas [`warning(StringOrReport, Metadata)`](`warning/2`).\n\nEquivalent to [`warning(FormatOrFun, Args, #{})`](`warning/3`) if called as\n[`warning(FormatOrFun, Args)`](`warning/2`).","title":"logger.warning/2","ref":"logger.html#warning/2"},{"type":"function","doc":"","title":"logger.warning/3","ref":"logger.html#warning/3"},{"type":"type","doc":"Configuration used when adding or updating a handler.","title":"logger.config_handler/0","ref":"logger.html#t:config_handler/0"},{"type":"type","doc":"A filter which can be installed as a handler filter, or as a primary filter in\nLogger.","title":"logger.filter/0","ref":"logger.html#t:filter/0"},{"type":"type","doc":"The second argument to the filter fun.","title":"logger.filter_arg/0","ref":"logger.html#t:filter_arg/0"},{"type":"type","doc":"A unique identifier for a filter.","title":"logger.filter_id/0","ref":"logger.html#t:filter_id/0"},{"type":"type","doc":"The return value from the filter fun.","title":"logger.filter_return/0","ref":"logger.html#t:filter_return/0"},{"type":"type","doc":"Configuration data for the formatter. See `m:logger_formatter` for an example of\na formatter implementation.","title":"logger.formatter_config/0","ref":"logger.html#t:formatter_config/0"},{"type":"type","doc":"Handler configuration data for Logger.\n\n> #### Note {: .info }\n>\n> DEPRECATED: Use `t:logger_handler:config/0` instead.","title":"logger.handler_config/0","ref":"logger.html#t:handler_config/0"},{"type":"type","doc":"A unique identifier for a handler instance.\n\n> #### Note {: .info }\n>\n> DEPRECATED: Use `t:logger_handler:id/0` instead.","title":"logger.handler_id/0","ref":"logger.html#t:handler_id/0"},{"type":"type","doc":"The severity level for the message to be logged.","title":"logger.level/0","ref":"logger.html#t:level/0"},{"type":"type","doc":"A log event passed to filters and handlers","title":"logger.log_event/0","ref":"logger.html#t:log_event/0"},{"type":"type","doc":"Metadata for the log event.\n\nLogger adds the following metadata to each log event:\n\n- `pid => self()`\n- `gl => group_leader()`\n- `time => logger:timestamp()`\n\nWhen a log macro is used, Logger also inserts location information:\n\n- `mfa => {?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY}`\n- `file => ?FILE`\n- `line => ?LINE`\n\nYou can add custom metadata, either by:\n\n- specifying a map as the last parameter to any of the log macros or the logger\n API functions.\n- setting process metadata with `set_process_metadata/1` or\n `update_process_metadata/1`.\n- setting primary metadata with `set_primary_config/1` or through the kernel\n configuration parameter [logger_metadata](kernel_app.md#logger_metadata)\n\n> #### Note {: .info }\n>\n> When adding custom metadata, make sure not to use any of the keys mentioned\n> above as that may cause a lot of confusion about the log events.\n\nLogger merges all the metadata maps before forwarding the log event to the\nhandlers. If the same keys occur, values from the log call overwrite process\nmetadata, which overwrites the primary metadata, which in turn overwrite values\nset by Logger.\n\nThe following custom metadata keys have special meaning:\n\n- **`domain`** - The value associated with this key is used by filters for\n grouping log events originating from, for example, specific functional areas.\n See `logger_filters:domain/2` for a description of how this field can be used.\n\n- **`report_cb`** - If the log message is specified as a `t:report/0`, the\n `report_cb` key can be associated with a fun (report callback) that converts\n the report to a format string and arguments, or directly to a string. See the\n type definition of `t:report_cb/0`, and section\n [Log Message](logger_chapter.md#log-message) in the User's Guide for more\n information about report callbacks.","title":"logger.metadata/0","ref":"logger.html#t:metadata/0"},{"type":"type","doc":"","title":"logger.msg_fun/0","ref":"logger.html#t:msg_fun/0"},{"type":"type","doc":"","title":"logger.msg_fun_return/0","ref":"logger.html#t:msg_fun_return/0"},{"type":"type","doc":"Overload protection configuration.\n\n> #### Note {: .info }\n>\n> DEPRECATED: Use `t:logger_handler:olp_config/0` instead.","title":"logger.olp_config/0","ref":"logger.html#t:olp_config/0"},{"type":"type","doc":"Primary configuration data for Logger. The following default values apply:\n\n- `level => info`\n- `filter_default => log`\n- `filters => []`","title":"logger.primary_config/0","ref":"logger.html#t:primary_config/0"},{"type":"type","doc":"A log report.","title":"logger.report/0","ref":"logger.html#t:report/0"},{"type":"type","doc":"A fun which converts a [`report()`](`t:report/0`) to a format string and\narguments, or directly to a string.\n\nSee section [Log Message](logger_chapter.md#log-message) in the User's Guide\nfor more information.","title":"logger.report_cb/0","ref":"logger.html#t:report_cb/0"},{"type":"type","doc":"","title":"logger.report_cb_config/0","ref":"logger.html#t:report_cb_config/0"},{"type":"type","doc":"A timestamp produced with [`logger:timestamp()`](`timestamp/0`).","title":"logger.timestamp/0","ref":"logger.html#t:timestamp/0"},{"type":"module","doc":"A disk_log based handler for Logger\n\nThis is a handler for Logger that offers circular (wrapped) logs by using\n`m:disk_log`. Multiple instances of this handler can be added to Logger, and\neach instance prints to its own disk log file, created with the name and\nsettings specified in the handler configuration.\n\nThe default standard handler, `m:logger_std_h`, can be replaced by a disk_log\nhandler at startup of the Kernel application. See an example of this below.\n\nThe handler has an overload protection mechanism that keeps the handler process\nand the Kernel application alive during high loads of log events. How overload\nprotection works, and how to configure it, is described in the\n[`User's Guide`](logger_chapter.md#overload_protection).\n\nTo add a new instance of the disk_log handler, use\n[`logger:add_handler/3`](`logger:add_handler/3`). The handler configuration\nargument is a map which can contain general configuration parameters, as\ndocumented in the [`User's Guide`](logger_chapter.md#handler-configuration),\nand handler specific parameters. The specific data is stored in a sub map with\nthe key `config`, and can contain the following parameters:\n\n- **`file`** - This is the full name of the disk log file. The option\n corresponds to the `name` property in the [`dlog_option()`](`disk_log:open/1`)\n datatype.\n\n The value is set when the handler is added, and it cannot be changed in\n runtime.\n\n Defaults to the same name as the handler identity, in the current directory.\n\n- **`type`** - This is the disk log type, `wrap` or `halt`. The option\n corresponds to the `type` property in the [`dlog_option()`](`disk_log:open/1`)\n datatype.\n\n The value is set when the handler is added, and it cannot be changed in\n runtime.\n\n Defaults to `wrap`.\n\n- **`max_no_files`** - This is the maximum number of files that disk_log uses\n for its circular logging. The option corresponds to the `MaxNoFiles` element\n in the `size` property in the [`dlog_option()`](`disk_log:open/1`) datatype.\n\n The value is set when the handler is added, and it cannot be changed in\n runtime.\n\n Defaults to `10`.\n\n The setting has no effect on a halt log.\n\n- **`max_no_bytes`** - This is the maximum number of bytes that is written to a\n log file before disk_log proceeds with the next file in order, or generates an\n error in case of a full halt log. The option corresponds to the `MaxNoBytes`\n element in the `size` property in the [`dlog_option()`](`disk_log:open/1`)\n datatype.\n\n The value is set when the handler is added, and it cannot be changed in\n runtime.\n\n Defaults to `1048576` bytes for a wrap log, and `infinity` for a halt log.\n\n- **`filesync_repeat_interval`** - This value, in milliseconds, specifies how\n often the handler does a disk_log sync operation to write buffered data to\n disk. The handler attempts the operation repeatedly, but only performs a new\n sync if something has actually been logged.\n\n Defaults to `5000` milliseconds.\n\n If `no_repeat` is set as value, the repeated sync operation is disabled. The\n user can also call the [`filesync/1`](`filesync/1`) function to perform a\n disk_log sync.\n\nOther configuration parameters exist, to be used for customizing the overload\nprotection behaviour. The same parameters are used both in the standard handler\nand the disk_log handler, and are documented in the\n[`User's Guide`](logger_chapter.md#overload_protection).\n\nNotice that when changing the configuration of the handler in runtime, the\ndisk_log options (`file`, `type`, `max_no_files`, `max_no_bytes`) must not be\nmodified.\n\nExample of adding a disk_log handler:\n\n```erlang\nlogger:add_handler(my_disk_log_h, logger_disk_log_h,\n #{config => #{file => \"./my_disk_log\",\n type => wrap,\n max_no_files => 4,\n max_no_bytes => 10000,\n filesync_repeat_interval => 1000}}).\n```\n\nTo use the disk_log handler instead of the default standard handler when\nstarting an Erlang node, change the Kernel default logger to use\n`logger_disk_log_h`. Example:\n\n```text\nerl -kernel logger '[{handler,default,logger_disk_log_h,\n #{config => #{file => \"./system_disk_log\"}}}]'\n```","title":"logger_disk_log_h","ref":"logger_disk_log_h.html"},{"type":"module","doc":"`m:logger`, `m:logger_std_h`, `m:disk_log`","title":"See Also - logger_disk_log_h","ref":"logger_disk_log_h.html#module-see-also"},{"type":"function","doc":"Write buffered data to disk.","title":"logger_disk_log_h.filesync/1","ref":"logger_disk_log_h.html#filesync/1"},{"type":"module","doc":"Filters to use with Logger.\n\nAll functions exported from this module can be used as primary or handler\nfilters. See `logger:add_primary_filter/2` and `logger:add_handler_filter/3` for\nmore information about how filters are added.\n\nFilters are removed with `logger:remove_primary_filter/1` and\n`logger:remove_handler_filter/2`.","title":"logger_filters","ref":"logger_filters.html"},{"type":"module","doc":"`m:logger`","title":"See Also - logger_filters","ref":"logger_filters.html#module-see-also"},{"type":"function","doc":"This filter provides a way of filtering log events based on a `domain` field in\n`Metadata`. This field is optional, and the purpose of using it is to group log\nevents from, for example, a specific functional area. This allows filtering or\nother specialized treatment in a Logger handler.\n\nA domain field must be a list of atoms, creating smaller and more specialized\ndomains as the list grows longer. The greatest domain is `[]`, which comprises\nall possible domains.\n\nFor example, consider the following domains:\n\n```erlang\nD1 = [otp]\nD2 = [otp, sasl]\n```\n\n`D1` is the greatest of the two, and is said to be a super-domain of `D2`. `D2`\nis a sub-domain `D1`. Both `D1` and `D2` are sub-domains of `[]`.\n\nThe above domains are used for logs originating from Erlang/OTP. D1 specifies\nthat the log event comes from Erlang/OTP in general, and D2 indicates that the\nlog event is a so called [SASL report](logger_chapter.md#sasl_reports).\n\nThe `Extra` parameter to the [`domain/2`](`domain/2`) function is specified when\nadding the filter via `logger:add_primary_filter/2` or\n`logger:add_handler_filter/3`.\n\nThe filter compares the value of the `domain` field in the log event's metadata\n(`Domain`) against `MatchDomain`. The filter matches if the value of `Compare`\nis:\n\n- **`sub`** - and `Domain` is equal to or a sub-domain of `MatchDomain`, that\n is, if `MatchDomain` is a prefix of `Domain`.\n\n- **`super`** - and `Domain` is equal to or a super-domain of `MatchDomain`,\n that is, if `Domain` is a prefix of `MatchDomain`.\n\n- **`equal`** - and `Domain` is equal to `MatchDomain`.\n\n- **`not_equal`** - and `Domain` differs from `MatchDomain`, or if there is no\n domain field in metadata.\n\n- **`undefined`** - and there is no domain field in metadata. In this case\n `MatchDomain` must be set to `[]`.\n\nIf the filter matches and `Action` is `log`, the log event is allowed. If the\nfilter matches and `Action` is `stop`, the log event is stopped.\n\nIf the filter does not match, it returns `ignore`, meaning that other filters,\nor the value of the configuration parameter `filter_default`, decide if the\nevent is allowed or not.\n\nLog events that do not contain any domain field, match only when `Compare` is\nequal to `undefined` or `not_equal`.\n\nExample: stop all events with domain `[otp, sasl | _]`\n\n```erlang\n1> logger:set_handler_config(h1, filter_default, log). % this is the default\nok\n2> Filter = {fun logger_filters:domain/2, {stop, sub, [otp, sasl]}}.\n...\n3> logger:add_handler_filter(h1, no_sasl, Filter).\nok\n```","title":"logger_filters.domain/2","ref":"logger_filters.html#domain/2"},{"type":"function","doc":"This filter provides a way of filtering log events based on the log level. It\nmatches log events by comparing the log level with a specified `MatchLevel`\n\nThe `Extra` parameter is specified when adding the filter via\n`logger:add_primary_filter/2` or `logger:add_handler_filter/3`.\n\nThe filter compares the value of the event's log level (`Level`) to `MatchLevel`\nby calling\n[`logger:compare_levels(Level, MatchLevel)`](`logger:compare_levels/2`). The\nfilter matches if the value of `Operator` is:\n\n- **`neq`** - and the compare function returns `lt` or `gt`.\n\n- **`eq`** - and the compare function returns `eq`.\n\n- **`lt`** - and the compare function returns `lt`.\n\n- **`gt`** - and the compare function returns `gt`.\n\n- **`lteq`** - and the compare function returns `lt` or `eq`.\n\n- **`gteq`** - and the compare function returns `gt` or `eq`.\n\nIf the filter matches and `Action` is `log`, the log event is allowed. If the\nfilter matches and `Action` is `stop`, the log event is stopped.\n\nIf the filter does not match, it returns `ignore`, meaning that other filters,\nor the value of the configuration parameter `filter_default`, will decide if the\nevent is allowed or not.\n\nExample: only allow debug level log events\n\n```erlang\nlogger:set_handler_config(h1, filter_default, stop).\nFilter = {fun logger_filters:level/2, {log, eq, debug}}.\nlogger:add_handler_filter(h1, debug_only, Filter).\nok\n```","title":"logger_filters.level/2","ref":"logger_filters.html#level/2"},{"type":"function","doc":"This filter matches all progress reports from `m:supervisor` and\n[`application_controller`](`m:application`).\n\nIf `Extra` is `log`, the progress reports are allowed. If `Extra` is `stop`, the\nprogress reports are stopped.\n\nThe filter returns `ignore` for all other log events.","title":"logger_filters.progress/2","ref":"logger_filters.html#progress/2"},{"type":"function","doc":"This filter matches all events originating from a process that has its group\nleader on a remote node.\n\nIf `Extra` is `log`, the matching events are allowed. If `Extra` is `stop`, the\nmatching events are stopped.\n\nThe filter returns `ignore` for all other log events.","title":"logger_filters.remote_gl/2","ref":"logger_filters.html#remote_gl/2"},{"type":"behaviour","doc":"Default formatter for Logger.\n\nEach Logger handler has a configured formatter specified as a module and a\nconfiguration term. The purpose of the formatter is to translate the log events\nto a final printable string ([`unicode:chardata()`](`t:unicode:chardata/0`))\nwhich can be written to the output device of the handler. See sections\n[Handlers](logger_chapter.md#handlers) and\n[Formatters](logger_chapter.md#formatters) in the Kernel User's Guide for more\ninformation.\n\n`m:logger_formatter` is the default formatter used by Logger.","title":"logger_formatter","ref":"logger_formatter.html"},{"type":"behaviour","doc":"`m:calendar`, `m:error_logger`, `m:io`, `m:io_lib`, `m:logger`, `m:maps`,\n[`sasl(6)`](`e:sasl:sasl_app.md`), `m:unicode`","title":"See Also - logger_formatter","ref":"logger_formatter.html#module-see-also"},{"type":"function","doc":"The function is called by Logger when the formatter configuration for a handler\nis set or modified. It returns `ok` if the configuration is valid, and\n`{error,term()}` if it is faulty.\n\nThe following Logger API functions can trigger this callback:\n\n- `logger:add_handler/3`\n- [`logger:set_handler_config/2,3`](`logger:set_handler_config/2`)\n- `logger:update_handler_config/2`\n- `logger:update_formatter_config/2`","title":"logger_formatter.check_config/1","ref":"logger_formatter.html#check_config/1"},{"type":"callback","doc":"The function is called by a Logger when formatter configuration is set or\nmodified. The formatter must validate the given configuration and return `ok` if\nit is correct, and `{error,Reason}` if it is faulty.\n\nThe following Logger API functions can trigger this callback:\n\n- `logger:add_handler/3`\n- [`logger:set_handler_config/2,3`](`logger:set_handler_config/2`)\n- [`logger:update_handler_config/2,3`](`logger:update_handler_config/2`)\n- `logger:update_formatter_config/2`\n\nSee `m:logger_formatter` for an example implementation. `m:logger_formatter` is\nthe default formatter used by Logger.","title":"logger_formatter.check_config/1","ref":"logger_formatter.html#c:check_config/1"},{"type":"function","doc":"This the formatter callback function to be called from handlers.\n\nThe log event is processed as follows:\n\n- If the message is on report form, it is converted to `{Format,Args}` by\n calling the report callback. See section\n [Log Message](logger_chapter.md#log-message) in the Kernel User's Guide for\n more information about report callbacks and valid forms of log messages.\n- The message size is limited according to the values of configuration\n parameters [`chars_limit`](`m:logger_formatter#chars_limit`) and\n [`depth`](`m:logger_formatter#depth`).\n- The full log entry is composed according to the\n [`template`](`m:logger_formatter#template`).\n- If the final string is too long, it is truncated according to the value of\n configuration parameter [`max_size`](`m:logger_formatter#max_size`).","title":"logger_formatter.format/2","ref":"logger_formatter.html#format/2"},{"type":"callback","doc":"The function can be called by a log handler to convert a log event term to a\nprintable string. The returned value can, for example, be printed as a log entry\nto the console or a file using [`io:put_chars/1,2`](`io:put_chars/1`).\n\nSee `m:logger_formatter` for an example implementation. `m:logger_formatter` is\nthe default formatter used by Logger.","title":"logger_formatter.format/2","ref":"logger_formatter.html#c:format/2"},{"type":"type","doc":"The configuration term for `logger_formatter` is a [map](`m:maps`), and the\nfollowing keys can be set as configuration parameters:\n\n- **`chars_limit = integer() > 0 | unlimited`{: #chars_limit }** - A positive\n integer representing the value of the option with the same name to be used\n when calling `io_lib:format/3`. This value limits the total number of\n characters printed for each log event. Notice that this is a soft limit. For a\n hard truncation limit, see option `max_size`.\n\n Defaults to `unlimited`.\n\n- **`depth = integer() > 0 | unlimited`{: #depth }** - A positive integer\n representing the maximum depth to which terms shall be printed by this\n formatter. Format strings passed to this formatter are rewritten. The format\n controls ~p and ~w are replaced with ~P and ~W, respectively, and the value is\n used as the depth parameter. For details, see [`io:format/2,3`](`io:format/2`)\n in STDLIB.\n\n Defaults to `unlimited`.\n\n- **`legacy_header = boolean()`** - If set to `true` a header field is added to\n logger_formatter's part of `Metadata`. The value of this field is a string\n similar to the header created by the old `m:error_logger` event handlers. It\n can be included in the log event by adding the list\n `[logger_formatter,header]` to the template. See the description of the\n `t:template/0` type for more information.\n\n Defaults to `false`.\n\n- **`max_size = integer() > 0 | unlimited`{: #max_size }** - A positive integer\n representing the absolute maximum size a string returned from this formatter\n can have. If the formatted string is longer, after possibly being limited by\n `chars_limit` or `depth`, it is truncated.\n\n Defaults to `unlimited`.\n\n- **`report_cb = ` `t:logger:report_cb/0`** - A report callback is used by the\n formatter to transform log messages on report form to a format string and\n arguments. The report callback can be specified in the metadata for the log\n event. If no report callback exists in metadata, `logger_formatter` will use\n `logger:format_report/1` as default callback.\n\n If this configuration parameter is set, it replaces both the default report\n callback, and any report callback found in metadata. That is, all reports are\n converted by this configured function.\n\n- **`single_line = boolean()`** - If set to `true`, each log event is printed as\n a single line. To achieve this, `logger_formatter` sets the field width to `0`\n for all `~p` and `~P` control sequences in the format a string (see\n `io:format/2`), and replaces all newlines in the message with `\", \"`. White\n spaces following directly after newlines are removed. Notice that newlines\n added by the `template` parameter are not replaced.\n\n Defaults to `true`.\n\n- **`template = `{: #template }`t:template/0`** - The template describes how the\n formatted string is composed by combining different data values from the log\n event. See the description of the `t:template/0` type for more information\n about this.\n\n- **`time_designator = byte()`** - Timestamps are formatted according to\n RFC3339, and the time designator is the character used as date and time\n separator.\n\n Defaults to `$T`.\n\n The value of this parameter is used as the `time_designator` option to\n `calendar:system_time_to_rfc3339/2`.\n\n- **`time_offset = integer() | [byte()]`** - The time offset, either a string or\n an integer, to be used when formatting the timestamp.\n\n An empty string is interpreted as local time. The values `\"Z\"`, `\"z\"` or `0`\n are interpreted as Universal Coordinated Time (UTC).\n\n Strings, other than `\"Z\"`, `\"z\"`, or `\"\"`, must be on the form `±[hh]:[mm]`,\n for example `\"-02:00\"` or `\"+00:00\"`.\n\n Integers must be in microseconds, meaning that the offset `7200000000` is\n equivalent to `\"+02:00\"`.\n\n Defaults to an empty string, meaning that timestamps are displayed in local\n time. However, for backwards compatibility, if the SASL configuration\n parameter [`utc_log`](`e:sasl:sasl_app.md#utc_log`)`=true`, the default is\n changed to `\"Z\"`, meaning that timestamps are displayed in UTC.\n\n The value of this parameter is used as the `offset` option to\n `calendar:system_time_to_rfc3339/2`.","title":"logger_formatter.config/0","ref":"logger_formatter.html#t:config/0"},{"type":"type","doc":"","title":"logger_formatter.metakey/0","ref":"logger_formatter.html#t:metakey/0"},{"type":"type","doc":"The template to be used by a logger formatter.\n\nThe template is a list of atoms, atom lists, tuples and strings. The atoms\n`level` or `msg`, are treated as placeholders for the severity level and the log\nmessage, respectively. Other atoms or atom lists are interpreted as placeholders\nfor metadata, where atoms are expected to match top level keys, and atom lists\nrepresent paths to sub keys when the metadata is a nested map. For example the\nlist `[key1,key2]` is replaced by the value of the `key2` field in the nested\nmap below. The atom `key1` on its own is replaced by the complete value of the\n`key1` field. The values are converted to strings.\n\n```text\n#{key1 => #{key2 => my_value,\n ...}\n ...}\n```\n\nTuples in the template express if-exist tests for metadata keys. For example,\nthe following tuple says that if `key1` exists in the metadata map, print\n`\"key1=Value\"`, where `Value` is the value that `key1` is associated with in the\nmetadata map. If `key1` does not exist, print nothing.\n\n```text\n{key1, [\"key1=\",key1], []}\n```\n\nStrings in the template are printed literally.\n\nThe default value for the `template` configuration parameter depends on the\nvalue of the `single_line` and `legacy_header` configuration parameters as\nfollows.\n\nThe log event used in the examples is:\n\n```text\n?LOG_ERROR(\"name: ~p~nexit_reason: ~p\", [my_name, \"It crashed\"])\n```\n\n- **`legacy_header = true, single_line = false`** - Default template:\n `[[logger_formatter,header],\"\\n\",msg,\"\\n\"]`\n\n Example log entry:\n\n ```text\n =ERROR REPORT==== 17-May-2018::18:30:19.453447 ===\n name: my_name\n exit_reason: \"It crashed\"\n ```\n\n Notice that all eight levels can occur in the heading, not only `ERROR`,\n `WARNING` or `INFO` as `m:error_logger` produces. And microseconds are added\n at the end of the timestamp.\n\n- **`legacy_header = true, single_line = true`** - Default template:\n `[[logger_formatter,header],\"\\n\",msg,\"\\n\"]`\n\n Notice that the template is here the same as for `single_line=false`, but the\n resulting log entry differs in that there is only one line after the heading:\n\n ```text\n =ERROR REPORT==== 17-May-2018::18:31:06.952665 ===\n name: my_name, exit_reason: \"It crashed\"\n ```\n\n- **`legacy_header = false, single_line = true`** - Default template:\n `[time,\" \",level,\": \",msg,\"\\n\"]`\n\n Example log entry:\n\n ```text\n 2018-05-17T18:31:31.152864+02:00 error: name: my_name, exit_reason: \"It crashed\"\n ```\n\n- **`legacy_header = false, single_line = false`** - Default template:\n `[time,\" \",level,\":\\n\",msg,\"\\n\"]`\n\n Example log entry:\n\n ```text\n 2018-05-17T18:32:20.105422+02:00 error:\n name: my_name\n exit_reason: \"It crashed\"\n ```","title":"logger_formatter.template/0","ref":"logger_formatter.html#t:template/0"},{"type":"behaviour","doc":"logger_handler behavior module.\n\nThe behaviour module for logger handlers. A logger handler is a callback module\nthat is called when a log event has passed all filters and is ready to be logged\nsomewhere. For more information see [Handlers](logger_chapter.md#handlers) in\nthe Users Guide.","title":"logger_handler","ref":"logger_handler.html"},{"type":"behaviour","doc":"`m:logger_filters`, `m:logger_formatter`, `m:logger`","title":"See Also - logger_handler","ref":"logger_handler.html#module-see-also"},{"type":"callback","doc":"The function is called on a temporary process when a new handler is about to be\nadded. The purpose is to verify the configuration and initiate all resources\nneeded by the handler.\n\nThe handler identity is associated with the `id` key in `Config1`.\n\nIf everything succeeds, the callback function can add possible default values or\ninternal state values to the configuration, and return the adjusted map in\n`{ok,Config2}`.\n\nIf the configuration is faulty, or if the initiation fails, the callback\nfunction must return `{error,Reason}`.","title":"logger_handler.adding_handler/1","ref":"logger_handler.html#c:adding_handler/1"},{"type":"callback","doc":"The function is called on a temporary process when the configuration for a\nhandler is about to change. The purpose is to verify and act on the new\nconfiguration.\n\n`OldConfig` is the existing configuration and `NewConfig` is the new\nconfiguration.\n\nThe handler identity is associated with the `id` key in `OldConfig`.\n\n`SetOrUpdate` has the value `set` if the configuration change originates from a\ncall to [`logger:set_handler_config/2,3`](`logger:set_handler_config/2`), and\n`update` if it originates from\n[`logger:update_handler_config/2,3`](`logger:update_handler_config/2`). The\nhandler can use this parameter to decide how to update the value of the `config`\nfield, that is, the handler specific configuration data. Typically, if\n`SetOrUpdate` equals `set`, values that are not specified must be given their\ndefault values. If `SetOrUpdate` equals `update`, the values found in\n`OldConfig` must be used instead.\n\nIf everything succeeds, the callback function must return a possibly adjusted\nconfiguration in `{ok,Config}`.\n\nIf the configuration is faulty, the callback function must return\n`{error,Reason}`.","title":"logger_handler.changing_config/3","ref":"logger_handler.html#c:changing_config/3"},{"type":"callback","doc":"The function is called when one of the Logger API functions for fetching the\nhandler configuration is called, for example `logger:get_handler_config/1`.\n\nIt allows the handler to remove internal data fields from its configuration data\nbefore it is returned to the caller.","title":"logger_handler.filter_config/1","ref":"logger_handler.html#c:filter_config/1"},{"type":"callback","doc":"The function is called when all primary filters and all handler filters for the\nhandler in question have passed for the given log event. It is called on the\nclient process, that is, the process that issued the log event.\n\nThe handler identity is associated with the `id` key in `Config`.\n\nThe handler must log the event.\n\nThe return value from this function is ignored by Logger.","title":"logger_handler.log/2","ref":"logger_handler.html#c:log/2"},{"type":"callback","doc":"The function is called on a temporary process when a handler is about to be\nremoved. The purpose is to release all resources used by the handler.\n\nThe handler identity is associated with the `id` key in `Config`.\n\nThe return value is ignored by Logger.","title":"logger_handler.removing_handler/1","ref":"logger_handler.html#c:removing_handler/1"},{"type":"type","doc":"Handler configuration data for Logger. The following default values apply:\n\n- `level => all`\n- `filter_default => log`\n- `filters => []`\n- `formatter => {logger_formatter, DefaultFormatterConfig`\\}\n\nIn addition to these, the following fields are automatically inserted by Logger,\nvalues taken from the two first parameters to `logger:add_handler/3`:\n\n- `id => HandlerId`\n- `module => Module`\n\nThese are read-only and cannot be changed in runtime.\n\nHandler specific configuration data is inserted by the handler callback itself,\nin a sub structure associated with the field named `config`. See the\n`m:logger_std_h` and `m:logger_disk_log_h` manual pages for information about\nthe specific configuration for these handlers.\n\nSee the [`logger_formatter`](`t:logger_formatter:config/0`) manual page for\ninformation about the default configuration for this formatter.","title":"logger_handler.config/0","ref":"logger_handler.html#t:config/0"},{"type":"type","doc":"A unique identifier for a handler instance.","title":"logger_handler.id/0","ref":"logger_handler.html#t:id/0"},{"type":"type","doc":"Overload protection configuration.\n\nSee [Protecting the Handler from Overload](logger_chapter.md#protecting-the-handler-from-overload)\nfor more details.","title":"logger_handler.olp_config/0","ref":"logger_handler.html#t:olp_config/0"},{"type":"module","doc":"Standard handler for Logger.\n\nThis is the standard handler for Logger. Multiple instances of this handler can\nbe added to Logger, and each instance prints logs to\n[`standard_io`](`t:io:standard_io/0`),\n[`standard_error`](`t:io:standard_error/0`), or to file.\n\nThe handler has an overload protection mechanism that keeps the handler process\nand the Kernel application alive during high loads of log events. How overload\nprotection works, and how to configure it, is described in the\n[`User's Guide`](logger_chapter.md#overload_protection).\n\nTo add a new instance of the standard handler, use\n[`logger:add_handler/3`](`logger:add_handler/3`). The handler configuration\nargument is a map which can contain general configuration parameters, as\ndocumented in the [`User's Guide`](logger_chapter.md#handler-configuration),\nand handler specific parameters. The specific data is stored in a sub map with\nthe key `config`, and can contain the following parameters:\n\n- **`type = ` `t:io:standard_io/0` ` | ` `t:io:standard_error/0` ` | file | {device, ` `t:io:device/0` `}`**{: #type } -\n Specifies the log destination.\n\n The value is set when the handler is added, and it cannot be changed in\n runtime.\n\n Defaults to [`standard_io`](`t:io:standard_io/0`), unless parameter\n [`file`](`m:logger_std_h#file`) is given, in which case it defaults to `file`.\n\n- **`file = ` `t:file:filename/0`**{: #file } - This specifies the name of the\n log file when the handler is of type `file`.\n\n The value is set when the handler is added, and it cannot be changed in\n runtime.\n\n Defaults to the same name as the handler identity, in the current directory.\n\n- **`modes = [` `t:file:mode/0` `]`**{: #modes } - This specifies the file modes\n to use when opening the log file, see `file:open/2`. If `modes` are not\n specified, the default list used is `[raw,append,delayed_write]`. If `modes`\n are specified, the list replaces the default modes list with the following\n adjustments:\n\n - If `raw` is not found in the list, it is added.\n - If none of `write`, `append` or `exclusive` is found in the list, `append`\n is added.\n - If none of `delayed_write` or `{delayed_write,Size,Delay}` is found in the\n list, `delayed_write` is added.\n\n Log files are always UTF-8 encoded. The encoding cannot be changed by setting\n the mode `{encoding,Encoding}`.\n\n The value is set when the handler is added, and it cannot be changed in\n runtime.\n\n Defaults to `[raw,append,delayed_write]`.\n\n- **`max_no_bytes = ` `t:pos_integer/0` ` | infinity`{: #max_no_bytes }** - This\n parameter specifies if the log file should be rotated or not. The value\n `infinity` means the log file will grow indefinitely, while an integer value\n specifies at which file size (bytes) the file is rotated.\n\n Defaults to `infinity`.\n\n- **`max_no_files = ` `t:non_neg_integer/0`**{: #max_no_files } - This parameter\n specifies the number of rotated log file archives to keep. This has meaning\n only if [`max_no_bytes`](`m:logger_std_h#max_no_bytes`) is set to an integer\n value.\n\n The log archives are named `FileName.0`, `FileName.1`, ... `FileName.N`, where\n `FileName` is the name of the current log file. `FileName.0` is the newest of\n the archives. The maximum value for `N` is the value of `max_no_files`\n minus 1.\n\n Notice that setting this value to `0` does not turn off rotation. It only\n specifies that no archives are kept.\n\n Defaults to `0`.\n\n- **`compress_on_rotate = ` `t:boolean/0`**{: #compress_on_rotate } - This parameter\n specifies if the rotated log file archives shall be compressed or not. If set\n to `true`, all archives are compressed with `gzip`, and renamed to\n `FileName.N.gz`\n\n `compress_on_rotate` has no meaning if\n [`max_no_bytes`](`m:logger_std_h#max_no_bytes`) has the value `infinity`.\n\n Defaults to `false`.\n\n- **`file_check = ` `t:non_neg_integer/0`**{: #file_check } - When `logger_std_h`\n logs to a file, it reads the file information of the log file prior to each\n write operation. This is to make sure the file still exists and has the same\n inode as when it was opened. This implies some performance loss, but ensures\n that no log events are lost in the case when the file has been removed or\n renamed by an external actor.\n\n In order to allow minimizing the performance loss, the `file_check` parameter\n can be set to a positive integer value, `N`. The handler will then skip\n reading the file information prior to writing, as long as no more than `N`\n milliseconds have passed since it was last read.\n\n Notice that the risk of losing log events grows when the `file_check` value\n grows.\n\n Defaults to 0.\n\n- **`filesync_repeat_interval = ` `t:pos_integer/0` ` | no_repeat`** - This value, in\n milliseconds, specifies how often the handler does a file sync operation to\n write buffered data to disk. The handler attempts the operation repeatedly,\n but only performs a new sync if something has actually been logged.\n\n If `no_repeat` is set as value, the repeated file sync operation is disabled,\n and it is the operating system settings that determine how quickly or slowly\n data is written to disk. The user can also call the `filesync/1` function to\n perform a file sync.\n\n Defaults to `5000` milliseconds.\n\nOther configuration parameters exist, to be used for customizing the overload\nprotection behaviour. The same parameters are used both in the standard handler\nand the disk_log handler, and are documented in the\n[`User's Guide`](logger_chapter.md#overload_protection).\n\nNotice that if changing the configuration of the handler in runtime, the `type`,\n`file`, or `modes` parameters must not be modified.\n\nExample of adding a standard handler:\n\n```erlang\nlogger:add_handler(my_standard_h, logger_std_h,\n #{config => #{file => \"./system_info.log\",\n filesync_repeat_interval => 1000}}).\n```\n\nTo set the default handler, that starts initially with the Kernel application,\nto log to file instead of [`standard_io`](`t:io:standard_io/0`), change the\nKernel default logger configuration. Example:\n\n```text\nerl -kernel logger '[{handler,default,logger_std_h,\n #{config => #{file => \"./log.log\"}}}]'\n```\n\nAn example of how to replace the standard handler with a disk_log handler at\nstartup is found in the `m:logger_disk_log_h` manual.","title":"logger_std_h","ref":"logger_std_h.html"},{"type":"module","doc":"`m:logger`, `m:logger_disk_log_h`","title":"See Also - logger_std_h","ref":"logger_std_h.html#module-see-also"},{"type":"function","doc":"Write buffered data to disk.","title":"logger_std_h.filesync/1","ref":"logger_std_h.html#filesync/1"},{"type":"module","doc":"A service to read internally formatted wrap disk logs.\n\nThis module makes it possible to read internally formatted wrap disk logs, see\n`m:disk_log`. `m:wrap_log_reader` does not interfere with `m:disk_log` activities;\nthere is however a bug in this version of the `m:wrap_log_reader`, see section\n[Known Limitations](`m:wrap_log_reader#module-known-limitations`).\n\nA wrap disk log file consists of many files, called index files. A log file can\nbe opened and closed. Also, a single index file can be opened separately. If a\nnon-existent or non-internally formatted file is opened, an error message is\nreturned. If the file is corrupt, no attempt is made to repair it, but an error\nmessage is returned.\n\nIf a log is configured to be distributed, it is possible that all items are not\nlogged on all nodes. `m:wrap_log_reader` only reads the log on the called node; it\nis up to the user to be sure that all items are read.","title":"wrap_log_reader","ref":"wrap_log_reader.html"},{"type":"module","doc":"This version of `m:wrap_log_reader` does not detect if `m:disk_log` wraps to a new\nindex file between a call to `wrap_log_reader:open/1` and the first call to\n`wrap_log_reader:chunk/1`. If this occurs, the call to `chunk/1` reads the last\nlogged items in the log file, as the opened index file was truncated by\n`m:disk_log`.","title":"Known Limitations - wrap_log_reader","ref":"wrap_log_reader.html#module-known-limitations"},{"type":"function","doc":"","title":"wrap_log_reader.chunk/1","ref":"wrap_log_reader.html#chunk/1"},{"type":"function","doc":"Enables to efficiently read the terms that are appended to a log. Minimises disk\nI/O by reading 64 kilobyte chunks from the file.\n\nThe first time `chunk/2` is called, an initial continuation returned from\n[`open/1`](`open/1`) or [`open/2`](`open/2`) must be provided.\n\nWhen `chunk/2` is called, `N` controls the maximum number of terms that are read\nfrom the log in each chunk. `infinity` means that all the\nterms contained in the 8K chunk are read. If less than `N` terms are returned,\nthis does not necessarily mean that end of file is reached.\n\nReturns a tuple `{Continuation2, Terms}`, where `Terms` is a list of terms found\nin the log. `Continuation2` is yet another continuation that must be passed on\nto any subsequent calls to `chunk()`. With a series of calls to `chunk()`, it is\nthen possible to extract all terms from a log.\n\nReturns a tuple `{Continuation2, Terms, Badbytes}` if the log is opened in read\nonly mode and the read chunk is corrupt. `Badbytes` indicates the number of\nnon-Erlang terms found in the chunk. Notice that the log is not repaired.\n\nReturns `{Continuation2, eof}` when the end of the log is reached, and\n`{error, Reason}` if an error occurs.\n\nThe returned continuation either is or is not valid in the next call to this\nfunction. This is because the log can wrap and delete the file into which the\ncontinuation points. To ensure this does not occur, the log can be blocked\nduring the search.","title":"wrap_log_reader.chunk/2","ref":"wrap_log_reader.html#chunk/2"},{"type":"function","doc":"Closes a log file properly.","title":"wrap_log_reader.close/1","ref":"wrap_log_reader.html#close/1"},{"type":"function","doc":"Equivalent to [`open(Filename, ...)`](`open/2`) except that the whole\nwrap log file is read.","title":"wrap_log_reader.open/1","ref":"wrap_log_reader.html#open/1"},{"type":"function","doc":"`Filename` specifies the name of the file to be read.\n\n`N` specifies the index of the file to be read. Use `open/1` to read the entire\nwrap log.\n\nReturns `{ok, Continuation}` if the log/index file is opened successfully.\n`Continuation` is to be used when chunking or closing the file.\n\nReturns `{error, Reason}` for all errors.","title":"wrap_log_reader.open/2","ref":"wrap_log_reader.html#open/2"},{"type":"type","doc":"","title":"wrap_log_reader.chunk_ret/0","ref":"wrap_log_reader.html#t:chunk_ret/0"},{"type":"opaque","doc":"Continuation returned by `open/1,2` or `chunk/1,2`.","title":"wrap_log_reader.continuation/0","ref":"wrap_log_reader.html#t:continuation/0"},{"type":"type","doc":"","title":"wrap_log_reader.open_ret/0","ref":"wrap_log_reader.html#t:open_ret/0"},{"type":"module","doc":"Sequential tracing of information transfers.\n\nSequential tracing makes it possible to trace information flows between\nprocesses resulting from one initial transfer of information. Sequential tracing\nis independent of the ordinary tracing in Erlang, which is controlled by the\n`erlang:trace/3` BIF. For more information about what sequential tracing is and\nhow it can be used, see section [Sequential Tracing](`m:seq_trace#whatis`).\n\n`seq_trace` provides functions that control all aspects of sequential tracing.\nThere are functions for activation, deactivation, inspection, and for collection\nof the trace output.","title":"seq_trace","ref":"seq_trace.html"},{"type":"module","doc":"The format of the messages is one of the following, depending on if flag\n`timestamp` of the trace token is set to `true` or `false`:\n\n```text\n{seq_trace, Label, SeqTraceInfo, TimeStamp}\n```\n\nor\n\n```text\n{seq_trace, Label, SeqTraceInfo}\n```\n\nWhere:\n\n```erlang\nLabel = int()\nTimeStamp = {Seconds, Milliseconds, Microseconds}\n Seconds = Milliseconds = Microseconds = int()\n```\n\n`SeqTraceInfo` can have the following formats:\n\n- **`{send, Serial, From, To, Message}`** - Used when a process `From` with its\n trace token flag `send` set to `true` has sent information. `To` may be a\n process identifier, a registered name on a node represented as\n `{NameAtom, NodeAtom}`, or a node name represented as an atom. `From` may be a\n process identifier or a node name represented as an atom. `Message` contains\n the information passed along in this information transfer. If the transfer is\n done via message passing, it is the actual message.\n\n- **`{'receive', Serial, From, To, Message}`** - Used when a process `To`\n receives information with a trace token that has flag `'receive'` set to\n `true`. `To` may be a process identifier, or a node name represented as an\n atom. `From` may be a process identifier or a node name represented as an\n atom. `Message` contains the information passed along in this information\n transfer. If the transfer is done via message passing, it is the actual\n message.\n\n- **`{print, Serial, From, _, Info}`** - Used when a process `From` has called\n `seq_trace:print(Label, TraceInfo)` and has a trace token with flag `print`\n set to `true`, and `label` set to `Label`.\n\n`Serial` is a tuple `{PreviousSerial, ThisSerial}`, where:\n\n- Integer `PreviousSerial` denotes the serial counter passed in the last\n received information that carried a trace token. If the process is the first\n in a new sequential trace, `PreviousSerial` is set to the value of the process\n internal \"trace clock\".\n- Integer `ThisSerial` is the serial counter that a process sets on outgoing\n messages. It is based on the process internal \"trace clock\", which is\n incremented by one before it is attached to the trace token in the message.\n\n[](){: #whatis }","title":"Trace Messages Sent to the System Tracer - seq_trace","ref":"seq_trace.html#module-trace-messages-sent-to-the-system-tracer"},{"type":"module","doc":"Sequential tracing is a way to trace a sequence of information transfers between\ndifferent local or remote processes, where the sequence is initiated by a single\ntransfer. The typical information transfer is an ordinary Erlang message passed\nbetween two processes, but information is transferred also in other ways. In\nshort, it works as follows:\n\nEach process has a _trace token_, which can be empty or not empty. When not\nempty, the trace token can be seen as the tuple `{Label, Flags, Serial, From}`.\nThe trace token is passed invisibly when information is passed between\nprocesses. In most cases the information is passed in ordinary messages between\nprocesses, but information is also passed between processes by other means. For\nexample, by spawning a new process. An information transfer between two\nprocesses is represented by a send event and a receive event regardless of how\nit is passed.\n\nTo start a sequential trace, the user must explicitly set the trace token in the\nprocess that will send the first information in a sequence.\n\nThe trace token of a process is set each time the process receives information.\nThis is typically when the process matches a message in a receive statement,\naccording to the trace token carried by the received message, empty or not.\n\nOn each Erlang node, a process can be set as the _system tracer_. This process\nwill receive trace messages each time information with a trace token is sent or\nreceived (if the trace token flag `send` or `'receive'` is set). The system\ntracer can then print each trace event, write it to a file, or whatever\nsuitable.\n\n> #### Note {: .info }\n>\n> The system tracer only receives those trace events that occur locally within\n> the Erlang node. To get the whole picture of a sequential trace, involving\n> processes on many Erlang nodes, the output from the system tracer on each\n> involved node must be merged (offline).\n\nThe following sections describe sequential tracing and its most fundamental\nconcepts.","title":"Sequential Tracing - seq_trace","ref":"seq_trace.html#module-sequential-tracing"},{"type":"module","doc":"Information flows between processes in a lot of different ways. Not all flows of\ninformation will be covered by sequential tracing. One example is information\npassed via ETS tables. Below is a list of information paths that are covered by\nsequential tracing:\n\n- **Message Passing** - All ordinary messages passed between Erlang processes.\n\n- **Exit signals** - An exit signal is represented as an `{'EXIT', Pid, Reason}`\n tuple.\n\n- **Process Spawn** - A process spawn is represented as multiple information\n transfers. At least one spawn request and one spawn reply. The actual amount\n of information transfers depends on what type of spawn it is and may also\n change in future implementations. Note that this is more or less an internal\n protocol that you are peeking at. The spawn request will be represented as a\n tuple with the first element containing the atom `spawn_request`, but this is\n more or less all that you can depend on.\n\n> #### Note {: .info }\n>\n> If you do ordinary `send` or `receive` trace on the system, you will only see\n> ordinary message passing, not the other information transfers listed above.\n\n> #### Note {: .info }\n>\n> When a send event and corresponding receive event do not both correspond to\n> ordinary Erlang messages, the `Message` part of the trace messages may not be\n> identical. This since all information not necessarily are available when\n> generating the trace messages.","title":"Different Information Transfers - seq_trace","ref":"seq_trace.html#module-different-information-transfers"},{"type":"module","doc":"Each process has a current trace token which is \"invisibly\" passed from the\nparent process on creation of the process.\n\nThe current token of a process is set in one of the following two ways:\n\n- Explicitly by the process itself, through a call to `seq_trace:set_token/1,2`\n- When information is received. This is typically when a received message is\n matched out in a receive expression, but also when information is received in\n other ways.\n\nIn both cases, the current token is set. In particular, if the token of a\nreceived message is empty, the current token of the process is set to empty.\n\nA trace token contains a label and a set of flags. Both the label and the flags\nare set in both alternatives above.","title":"Trace Token - seq_trace","ref":"seq_trace.html#module-trace-token"},{"type":"module","doc":"The trace token contains a component called `serial`. It consists of two\nintegers, `Previous` and `Current`. The purpose is to uniquely identify each\ntraced event within a trace sequence, as well as to order the messages\nchronologically and in the different branches, if any.\n\nThe algorithm for updating `Serial` can be described as follows:\n\nLet each process have two counters, `prev_cnt` and `curr_cnt`, both are set to\n`0` when a process is created outside of a trace sequence. The counters are\nupdated at the following occasions:\n\n- _When the process is about to pass along information to another process and\n the trace token is not empty._ This typically occurs when sending a message,\n but also, for example, when spawning another process.\n\n Let the serial of the trace token be `tprev` and `tcurr`.\n\n ```text\n curr_cnt := curr_cnt + 1\n tprev := prev_cnt\n tcurr := curr_cnt\n ```\n\n The trace token with `tprev` and `tcurr` is then passed along with the\n information passed to the other process.\n\n- _When the process calls_ `seq_trace:print(Label, Info)`, `Label` _matches the\n label part of the trace token and the trace token print flag is `true`._\n\n The algorithm is the same as for send above.\n\n- _When information is received that also contains a non-empty trace token. For\n example, when a message is matched out in a receive expression, or when a new\n process is spawned._\n\n The process trace token is set to the trace token from the message.\n\n Let the serial of the trace token be `tprev` and `tcurr`.\n\n ```text\n if (curr_cnt < tcurr )\n curr_cnt := tcurr\n prev_cnt := tcurr\n ```\n\n`curr_cnt` of a process is incremented each time the process is involved in a\nsequential trace. The counter can reach its limit (27 bits) if a process is very\nlong-lived and is involved in much sequential tracing. If the counter overflows,\nthe serial for ordering of the trace events cannot be used. To prevent the\ncounter from overflowing in the middle of a sequential trace, function\n`seq_trace:reset_trace/0` can be called to reset `prev_cnt` and `curr_cnt` of\nall processes in the Erlang node. This function also sets all trace tokens in\nprocesses and their message queues to empty, and thus stops all ongoing\nsequential tracing.","title":"Serial - seq_trace","ref":"seq_trace.html#module-serial"},{"type":"module","doc":"The performance degradation for a system that is enabled for sequential tracing\nis negligible as long as no tracing is activated. When tracing is activated,\nthere is an extra cost for each traced message, but all other messages are\nunaffected.","title":"Performance Considerations - seq_trace","ref":"seq_trace.html#module-performance-considerations"},{"type":"module","doc":"Sequential tracing is not performed across ports.\n\nIf the user for some reason wants to pass the trace token to a port, this must\nbe done manually in the code of the port controlling process. The port\ncontrolling processes have to check the appropriate sequential trace settings\n(as obtained from `seq_trace:get_token/1`) and include trace information in the\nmessage data sent to their respective ports.\n\nSimilarly, for messages received from a port, a port controller has to retrieve\ntrace-specific information, and set appropriate sequential trace flags through\ncalls to `seq_trace:set_token/2`.","title":"Ports - seq_trace","ref":"seq_trace.html#module-ports"},{"type":"module","doc":"Sequential tracing between nodes is performed transparently. This applies to\nC-nodes built with `Erl_Interface` too. A C-node built with `Erl_Interface` only\nmaintains one trace token, which means that the C-node appears as one process\nfrom the sequential tracing point of view.","title":"Distribution - seq_trace","ref":"seq_trace.html#module-distribution"},{"type":"module","doc":"This example gives a rough idea of how the new primitives can be used and what\nkind of output it produces.\n\nAssume that you have an initiating process with `Pid == <0.30.0>` like this:\n\n```erlang\n-module(seqex).\n-compile(export_all).\n\nloop(Port) ->\n receive\n {Port,Message} ->\n seq_trace:set_token(label,17),\n seq_trace:set_token('receive',true),\n seq_trace:set_token(print,true),\n seq_trace:print(17,\"**** Trace Started ****\"),\n call_server ! {self(),the_message};\n {ack,Ack} ->\n ok\n end,\n loop(Port).\n```\n\nAnd a registered process `call_server` with `Pid == <0.31.0>` like this:\n\n```erlang\nloop() ->\n receive\n {PortController,Message} ->\n Ack = {received, Message},\n seq_trace:print(17,\"We are here now\"),\n PortController ! {ack,Ack}\n end,\n loop().\n```\n\nA possible output from the system's `sequential_tracer` can be like this:\n\n```erlang\n17:<0.30.0> Info {0,1} WITH\n\"**** Trace Started ****\"\n17:<0.31.0> Received {0,2} FROM <0.30.0> WITH\n{<0.30.0>,the_message}\n17:<0.31.0> Info {2,3} WITH\n\"We are here now\"\n17:<0.30.0> Received {2,4} FROM <0.31.0> WITH\n{ack,{received,the_message}}\n```\n\nThe implementation of a system tracer process that produces this printout can\nlook like this:\n\n```erlang\ntracer() ->\n receive\n {seq_trace,Label,TraceInfo} ->\n print_trace(Label,TraceInfo,false);\n {seq_trace,Label,TraceInfo,Ts} ->\n print_trace(Label,TraceInfo,Ts);\n _Other -> ignore\n end,\n tracer().\n\nprint_trace(Label,TraceInfo,false) ->\n io:format(\"~p:\",[Label]),\n print_trace(TraceInfo);\nprint_trace(Label,TraceInfo,Ts) ->\n io:format(\"~p ~p:\",[Label,Ts]),\n print_trace(TraceInfo).\n\nprint_trace({print,Serial,From,_,Info}) ->\n io:format(\"~p Info ~p WITH~n~p~n\", [From,Serial,Info]);\nprint_trace({'receive',Serial,From,To,Message}) ->\n io:format(\"~p Received ~p FROM ~p WITH~n~p~n\",\n [To,Serial,From,Message]);\nprint_trace({send,Serial,From,To,Message}) ->\n io:format(\"~p Sent ~p TO ~p WITH~n~p~n\",\n [From,Serial,To,Message]).\n```\n\nThe code that creates a process that runs this tracer function and sets that\nprocess as the system tracer can look like this:\n\n```erlang\nstart() ->\n Pid = spawn(?MODULE,tracer,[]),\n seq_trace:set_system_tracer(Pid), % set Pid as the system tracer\n ok.\n```\n\nWith a function like `test/0`, the whole example can be started:\n\n```erlang\ntest() ->\n P = spawn(?MODULE, loop, [port]),\n register(call_server, spawn(?MODULE, loop, [])),\n start(),\n P ! {port,message}.\n```","title":"Example of Use - seq_trace","ref":"seq_trace.html#module-example-of-use"},{"type":"function","doc":"Returns the pid, port identifier or tracer module of the current system tracer\nor `false` if no system tracer is activated.","title":"seq_trace.get_system_tracer/0","ref":"seq_trace.html#get_system_tracer/0"},{"type":"function","doc":"Returns the value of the trace token for the calling process. If `[]` is\nreturned, it means that tracing is not active. Any other value returned is the\nvalue of an active trace token. The value returned can be used as input to the\n[`set_token/1`](`set_token/1`) function.","title":"seq_trace.get_token/0","ref":"seq_trace.html#get_token/0"},{"type":"function","doc":"Returns the value of the trace token component `Component`. See `set_token/2`\nfor possible values of `Component` and `Val`.","title":"seq_trace.get_token/1","ref":"seq_trace.html#get_token/1"},{"type":"function","doc":"Puts the Erlang term `TraceInfo` into the sequential trace output if the calling\nprocess currently is executing within a sequential trace and the `print` flag of\nthe trace token is set.","title":"seq_trace.print/1","ref":"seq_trace.html#print/1"},{"type":"function","doc":"Same as [`print/1`](`print/1`) with the additional condition that `TraceInfo` is\noutput only if `Label` is equal to the label component of the trace token.","title":"seq_trace.print/2","ref":"seq_trace.html#print/2"},{"type":"function","doc":"Sets the trace token to empty for all processes on the local node. The process\ninternal counters used to create the serial of the trace token is set to 0. The\ntrace token is set to empty for all messages in message queues. Together this\nwill effectively stop all ongoing sequential tracing in the local node.","title":"seq_trace.reset_trace/0","ref":"seq_trace.html#reset_trace/0"},{"type":"function","doc":"Sets the system tracer. The system tracer can be either a process, port or\n[tracer module](`m:erl_tracer`) denoted by `Tracer`. Returns the previous value\n(which can be `false` if no system tracer is active).\n\nFailure: `{badarg, Info}}` if `Pid` is not an existing local pid.","title":"seq_trace.set_system_tracer/1","ref":"seq_trace.html#set_system_tracer/1"},{"type":"function","doc":"Sets the trace token for the calling process to `Token`. If `Token == []` then\ntracing is disabled, otherwise `Token` should be an Erlang term returned from\n`get_token/0` or [`set_token/1`](`set_token/1`). [`set_token/1`](`set_token/1`)\ncan be used to temporarily exclude message passing from the trace by setting the\ntrace token to empty like this:\n\n```erlang\nOldToken = seq_trace:set_token([]), % set to empty and save\n % old value\n% do something that should not be part of the trace\nio:format(\"Exclude the signalling caused by this~n\"),\nseq_trace:set_token(OldToken), % activate the trace token again\n...\n```\n\nReturns the previous value of the trace token.","title":"seq_trace.set_token/1","ref":"seq_trace.html#set_token/1"},{"type":"function","doc":"Sets the individual `Component` of the trace token to `Val`. Returns the\nprevious value of the component.\n\n- **[`set_token(label, Label)`](`set_token/2`)** - The `label` component is a\n term which identifies all events belonging to the same sequential trace. If\n several sequential traces can be active simultaneously, `label` is used to\n identify the separate traces. Default is 0.\n\n > #### Warning {: .warning }\n >\n > Labels were restricted to small signed integers (28 bits) prior to OTP 21.\n > The trace token will be silently dropped if it crosses over to a node that\n > does not support the label.\n\n- **[`set_token(serial, SerialValue)`](`set_token/2`)** -\n `SerialValue = {Previous, Current}`. The `serial` component contains counters\n which enables the traced messages to be sorted, should never be set explicitly\n by the user as these counters are updated automatically. Default is `{0, 0}`.\n\n- **[`set_token(send, Bool)`](`set_token/2`)** - A trace token flag\n (`true | false`) which enables/disables tracing on information sending.\n Default is `false`.\n\n- **[`set_token('receive', Bool)`](`set_token/2`)** - A trace token flag\n (`true | false`) which enables/disables tracing on information reception.\n Default is `false`.\n\n- **[`set_token(print, Bool)`](`set_token/2`)** - A trace token flag\n (`true | false`) which enables/disables tracing on explicit calls to\n `seq_trace:print/1`. Default is `false`.\n\n- **[`set_token(timestamp, Bool)`](`set_token/2`)** - A trace token flag\n (`true | false`) which enables/disables a timestamp to be generated for each\n traced event. Default is `false`.\n\n- **[`set_token(strict_monotonic_timestamp, Bool)`](`set_token/2`)** - A trace\n token flag (`true | false`) which enables/disables a strict monotonic\n timestamp to be generated for each traced event. Default is `false`.\n Timestamps will consist of\n [Erlang monotonic time](`e:erts:time_correction.md#erlang-monotonic-time`) and\n a monotonically increasing integer. The time-stamp has the same format and\n value as produced by\n `{erlang:monotonic_time(nanosecond), erlang:unique_integer([monotonic])}`.\n\n- **[`set_token(monotonic_timestamp, Bool)`](`set_token/2`)** - A trace token\n flag (`true | false`) which enables/disables a strict monotonic timestamp to\n be generated for each traced event. Default is `false`. Timestamps will use\n [Erlang monotonic time](`e:erts:time_correction.md#erlang-monotonic-time`).\n The time-stamp has the same format and value as produced by\n `erlang:monotonic_time(nanosecond)`.\n\nIf multiple timestamp flags are passed, `timestamp` has precedence over\n`strict_monotonic_timestamp` which in turn has precedence over\n`monotonic_timestamp`. All timestamp flags are remembered, so if two are passed\nand the one with highest precedence later is disabled the other one will become\nactive.","title":"seq_trace.set_token/2","ref":"seq_trace.html#set_token/2"},{"type":"type","doc":"","title":"seq_trace.component/0","ref":"seq_trace.html#t:component/0"},{"type":"type","doc":"","title":"seq_trace.flag/0","ref":"seq_trace.html#t:flag/0"},{"type":"type","doc":"An opaque term (a tuple) representing a trace token.","title":"seq_trace.token/0","ref":"seq_trace.html#t:token/0"},{"type":"type","doc":"","title":"seq_trace.tracer/0","ref":"seq_trace.html#t:tracer/0"},{"type":"type","doc":"","title":"seq_trace.value/0","ref":"seq_trace.html#t:value/0"},{"type":"module","doc":"The Erlang trace interface.\n\nThe Erlang run-time system exposes several trace points that allow users\nto be notified when they are triggered. Trace points are things such as\nfunction calls, message sending and receiving, garbage collection, and\nprocess scheduling.\n\nThe functions in this module can be used directly, but can also be\nused as building blocks to build more sophisticated debugging or\nprofiling tools. For debugging Erlang code it is recommended to use\n`m:dbg` and for profiling to use `m:tprof`.","title":"trace","ref":"trace.html"},{"type":"module","doc":"All tracing is done within a trace session. Trace sessions can be\n[created](`session_create/3`) and [destroyed](`session_destroy/1`)\ndynamically. Each session has its own tracer that will receive all trace\nmessages. Several sessions can exist at the same time without interfering with\neach other. When a trace session is destroyed, all its trace settings are\nautomatically cleaned up.\n\n*Example*:\n\n```erlang\n%% Create a tracer process that will receive the trace events\n1> Tracer = spawn(fun F() -> receive M -> io:format(\"~p~n\",[M]), F() end end).\n<0.91.0>\n%% Create a session using the Tracer\n2> Session = trace:session_create(my_session, Tracer, []).\n{#Ref<0.1543805153.1548353537.92331>,{my_session, 0}}\n%% Setup call tracing on self()\n3> trace:process(Session, self(), true, [call]).\n1\n%% Setup call tracing on lists:seq/2\n4> trace:function(Session, {lists,seq,2}, [], []).\n1\n%% Call the traced function\n5> lists:seq(1, 10).\n{trace,<0.89.0>,call,{lists,seq,[1,10]}} % The trace message\n[1,2,3,4,5,6,7,8,9,10] % The return value\n%% Cleanup the trace session\n6> trace:session_destroy(Session).\nok\n```","title":"Trace Sessions - trace","ref":"trace.html#module-trace-sessions"},{"type":"module","doc":"The functions in this module only operates on the local node. That is, both the\ntraced processes/ports as well as the tracer process/port/module must all reside\non the same local node as the call is made. To trace remote nodes use `m:dbg` or\n`m:ttb`.\n\n> #### Change {: .info }\n>\n> This `trace` module was introduced in OTP 27.0. The interface and semantics are\n> similar to the older functions `erlang:trace/3`, `erlang:trace_pattern/3`,\n> and `erlang:trace_info/2`.\n>\n> The main difference is the old functions operate on a single static\n> trace session per node. That could impose the problem that different\n> users and tools would interfere with each other's trace settings. The new trace\n> functions in this module all operate on dynamically created trace sesssions\n> isolated from each other. Also, this makes it easier to safely disable all trace\n> settings when done by a single call to `session_destroy/1`.\n>\n> To change an existing tool to use the interface the following table can be\n> useful:\n>\n> | Old function call | corresponds to |\n> | ------------------------------------------- | ------------------------------------------------------------------ |\n> | [`erlang:trace(Pid, ...)`][1] | [`process(S, Pid, ...)`][p] |\n> | [`erlang:trace(processes, ...)`][1] | [`process(S, all, ...)`][p] |\n> | [`erlang:trace(existing_processes, ...)`][1] | [`process(S, existing, ...)`][p] |\n> | [`erlang:trace(new_processes, ...)`][1] | [`process(S, new, ...)`][p] |\n> | [`erlang:trace(Port, ...)`][1] | [`port(S, Port, ...)`][o] |\n> | [`erlang:trace(ports, ...)`][1] | [`port(S, all, ...)`][o] |\n> | [`erlang:trace(existing_ports, ...)`][1] | [`port(S, existing, ...)`][o] |\n> | [`erlang:trace(new_ports, ...)`][1] | [`port(S, new, ...)`][o] |\n> | [`erlang:trace(all, ...)`][1] | [`process(S, all, ...)`][p] and [`port(S, all, ...)`][o] |\n> | [`erlang:trace(existing, ...)`][1] | [`process(S, existing, ...)`][p] and [`port(S, existing, ...)`][o] |\n> | [`erlang:trace(new, ...)`][1] | [`process(S, new, ...)`][p] and [`port(S, new, ...)`][o] |\n> | [`erlang:trace_pattern(MFA, ...)`][2] | [`function(S, MFA, ...)`][f] |\n> | [`erlang:trace_pattern(send, ...)`][2] | [`send(S, ...)`][s] |\n> | [`erlang:trace_pattern('receive', ...)`][2] | [`recv(S, ...)`][r] |\n> | [`erlang:trace_info(...)`][3] | [`info(S, ...)`][i] |\n>\n> Argument `S` is the trace session that must first be created with\n> `session_create/3`. The other arguments (implied by `...`) are mostly the\n> same. The only other difference is that the tracer is always the tracer\n> specified when the session was created. Options `{tracer,T}`, `{tracer,M,S}`,\n> `{meta,T}`, and `{meta,M,S}` are therefore not allowed, and the default tracer is\n> never the calling process.\n\n[1]: `erlang:trace/3`\n[2]: `erlang:trace_pattern/3`\n[3]: `erlang:trace_info/2`\n[p]: `process/4`\n[o]: `port/4`\n[f]: `function/4`\n[s]: `send/3`\n[r]: `recv/3`\n[i]: `info/3`","title":"Node Local Tracing Only - trace","ref":"trace.html#module-node-local-tracing-only"},{"type":"function","doc":"Equivalent to [`erlang:trace_delivered(Tracee)`](`erlang:trace_delivered/1`)\nexcept that it is run within the given `t:session/0`.","title":"trace.delivered/2","ref":"trace.html#delivered/2"},{"type":"function","doc":"Enable or disable _call tracing_ for one or more functions.\n\nMust be combined with `process/4` to set the `call` trace flag for one or more\nprocesses.\n\nConceptually, call tracing works as follows. In each trace session, a\nset of processes and a set of functions have been marked for\ntracing. If a traced process calls a traced function, the trace action\nis taken. Otherwise, nothing happens.\n\nTo add or remove one or more processes to the set of traced processes, use\n`process/4`.\n\nUse this function to add or remove functions to the set of traced functions\nin a trace session.\n\nArgument `Session` is the trace session to operate on as returned by\n`session_create/3`.\n\nArgument **`MFA`** is to be a tuple, such as `{Module, Function, Arity}`, or the\natom `on_load` (described below). The `MFA` tuple specifies the module,\nfunction, and arity for the functions to be traced. The atom `'_'` can be used\nas a wildcard in any of the following ways:\n\n- **`{Module,Function,'_'}`** - All functions of any arity named `Function` in\n module `Module`.\n\n- **`{Module,'_','_'}`** - All functions in module `Module`.\n\n- **`{'_','_','_'}`** - All functions in all loaded modules.\n\nOther combinations, such as `{Module,'_',Arity}`, are not allowed.\n\nIf argument `MFA` is the atom `on_load`, the match specification and flag list\nare used on all functions in all modules that are newly loaded.\n\nArgument **`MatchSpec`** can take the following forms:\n\n- **`true`** - Enable tracing for the matching functions. Any match\n specification is removed.\n\n- **`false`** - Disable tracing for the matching functions. Any match\n specification is removed.\n\n- **`MatchExpression`** - A match specification. An empty list is equivalent to\n `true`. For a description of match specifications, see section\n [Match Specifications in Erlang](`e:erts:match_spec.md`) in the User's Guide\n for the ERTS application.\n\n- **`restart`** - For the `FlagList` options `call_count`, `call_time` and\n `call_memory`: restarts the existing counters. The behavior is undefined for\n other `FlagList` options.\n\n- **`pause`** - For the `FlagList` options `call_count`, `call_time` and\n `call_memory`: pauses the existing counters. The behavior is undefined for\n other `FlagList` options.\n\nArgument **`FlagList`** is a list of options. The following are the valid options:\n\n- **`global`** - Turn on or off call tracing for global function calls (that\n is, calls specifying the module explicitly). Only exported functions match and\n only global calls generate trace messages. **This is the default if `FlagList`\n is empty**.\n\n- **`local`** - Turn on or off call tracing for all types of function calls.\n Trace messages are sent whenever any of the specified functions are called,\n regardless of how they are called. If flag `return_to` is set for the process,\n a `return_to` message is also sent when this function returns to its caller.\n\n- **`meta`** - Turn on or off meta-tracing for all types of function\n calls. Trace messages are sent to the tracer whenever any of the specified\n functions are called.\n\n Meta-tracing traces all processes and does not care about the process trace\n flags set by `process/4`, the trace flags are instead fixed to\n `[call, timestamp]`.\n\n The match specification function `{return_trace}` works with meta-trace.\n\n- **`call_count`**{: #call_count } - Start (`MatchSpec == true`) or stop\n (`MatchSpec == false`) call count tracing for all types of function calls. For\n every function, a counter is incremented when the function is called, in any\n process. No process trace flags need to be activated.\n\n If call count tracing is started while already running, the count is restarted\n from zero. To pause running counters, use `MatchSpec == pause`. Paused and\n running counters can be restarted from zero with `MatchSpec == restart`.\n\n To read the counter value for a function, call\n [`trace:info(_, MFA, call_count)`](`info/3`).\n\n- **`call_time`**{: #call_time } - Start (`MatchSpec` is `true`) or stops (`MatchSpec` is `false`)\n call time tracing for all types of function calls. For every function, a\n counter is incremented when the function is called and the time spent in the\n function is measured and accumulated in another counter. The counters are\n stored for each call traced process.\n\n If call time tracing is started while already running, the count and time\n restart from zero. To pause running counters, use `MatchSpec == pause`. Paused\n and running counters can be restarted from zero with `MatchSpec == restart`.\n\n To read the counter values, use `info/3`.\n\n- **`call_memory`**{: #call_memory } - Start (`MatchSpec == true`) or stop\n (`MatchSpec == false`) call memory tracing for all types of function calls.\n\n If call memory tracing is started while already running, counters and\n allocations restart from zero. To pause running counters, use\n `MatchSpec == pause`. Paused and running counters can be restarted from zero\n with `MatchSpec == restart`.\n\n To read the counter value, use `info/3`.\n\nOption `global` cannot be combined with any of the other options, which all\nperform some kind of local tracing. If global tracing is specified for\na set of functions, then `local`, `meta`, `call_count`, `call_time`,\nand `call_memory` tracing for the matching set of functions are\ndisabled, and vice versa.\n\nWhen disabling trace, the option must match the type of trace set on the\nfunction. That is, local tracing must be disabled with option `local` and global\ntracing with option `global` (or no option), and so on.\n\nPart of a match specification cannot be changed directly. If a function has\na match specification, it can be replaced with a new one. Function `info/3` can\nbe used to retrieve the existing match specification.\n\nReturns the number of functions matching argument `MFA`. Zero is returned if\nnone matched or if `on_load` was specified.\n\nFails by raising an error exception with an error reason of:\n\n- **`badarg`** - If an argument is invalid.\n\n- **`system_limit`** - If a match specification passed as argument has excessive\n nesting which causes scheduler stack exhaustion for the scheduler that the\n calling process is executing on.\n [Scheduler stack size](`e:erts:erl_cmd.md#sched_thread_stack_size`) can be configured\n when starting the runtime system.","title":"trace.function/4","ref":"trace.html#function/4"},{"type":"function","doc":"Return trace information about a port, process, function, or event.\n\nArgument `Session` is the trace session to inspect as returned by\n`session_create/3` or `session_info/1`.\n\n**To get information about a port or process**, `PidPortFuncEvent` is to be a\nprocess identifier (pid), port identifier, or one of the atoms `new`,\n`new_processes`, or `new_ports`. The atom `new` or `new_processes` means that\nthe default trace state for processes to be created is returned. The atom\n`new_ports` means that the default trace state for ports to be created is\nreturned.\n\nValid `Item` values for ports and processes:\n\n- **`flags`** - Returns a list of atoms indicating what kind of traces is\n enabled for the process. The list is empty if no traces are enabled, and one\n or more of [`trace_info_flag()`](`t:trace_info_flag/0`) if traces are enabled.\n The order is arbitrary.\n\n- **`tracer`** - Returns the identifier for process, port, or a tuple containing\n the tracer module and tracer state tracing this process. If this process is\n not traced, the return value is `[]`.\n\n**To get information about a function**, `PidPortFuncEvent` is to be the\nthree-element tuple `{Module, Function, Arity}` or the atom `on_load`. No\nwildcards are allowed. Returns `undefined` if the function does not exist or\n`false` if the function is not traced. If `PidPortFuncEvent` is `on_load`, the\ninformation returned refers to the default value for code that will be loaded.\n\nValid `Item` values for functions:\n\n- **`traced`** - Returns `global` if this function is traced on global function\n calls, `local` if this function is traced on local function calls (that is,\n local and global function calls), and `false` if local or global function\n calls are not traced.\n\n- **`match_spec`** - Returns the match specification for this function, if it\n has one. If the function is locally or globally traced but has no match\n specification defined, the returned value is `[]`.\n\n- **`meta`** - Returns the meta-trace tracer process, port, or trace module for\n this function, if it has one. If the function is not meta-traced, the returned\n value is `false`. If the function is meta-traced but has once detected that\n the tracer process is invalid, the returned value is `[]`.\n\n- **`meta_match_spec`** - Returns the meta-trace match specification for this\n function, if it has one. If the function is meta-traced but has no match\n specification defined, the returned value is `[]`.\n\n- **`call_count`** - Returns the call count value for this function or `true`\n for the pseudo function `on_load` if call count tracing is active. Otherwise\n `false` is returned.\n\n See also `function/4`.\n\n- **`call_time`** - Returns the call time values for this function or `true` for\n the pseudo function `on_load` if call time tracing is active. Otherwise\n `false` is returned. The call time values returned, `[{Pid, Count, S, Us}]`,\n is a list of each process that executed the function and its specific\n counters. `Count` is the call count. `S` and `Us` are the accumulated call\n time expressed in seconds and microseconds.\n\n See also `function/4`.\n\n- **`call_memory`** - Returns the accumulated number of words allocated by this\n function. Accumulation stops at the next memory traced function: if there are\n `outer`, `middle` and `inner` functions each allocating 3 words, but only\n `outer` is traced, it will report 9 allocated words. If `outer` and `inner`\n are traced, 6 words are reported for `outer` and 3 for `inner`. When function\n is not traced, `false` is returned. Returned tuple is `[{Pid, Count, Words}]`,\n for each process that executed the function.\n\n See also `function/4`.\n\n- **`all`** - Returns a list containing the `{Item, Value}` tuples for all other\n items, or returns `false` if no tracing is active for this function.\n\n**To get information about an event**, `PidPortFuncEvent` is to be one of the\natoms `send` or `'receive'`.\n\nOne valid `Item` for events exists:\n\n- **`match_spec`** - Returns the match specification for this event, if it has\n one, or `true` if no match specification has been set.\n\n**To get information about monitored system events**, `PidPortFuncEvent` is to\n be the atom `system`.\n\nOnly valid `Item` for `system` is\n\n- **`all`** - Returns a list of all monitored system events enabled by\n `system/3`.\n\nThe return value is `{Item, Value}`, where `Value` is the requested information\nas described earlier. If a pid for a dead process was specified, or the name of\na non-existing function, `Value` is `undefined`.","title":"trace.info/3","ref":"trace.html#info/3"},{"type":"function","doc":"Turn on or off trace flags for one or more ports.\n\nArgument `Session` is the trace session to operate on as returned by\n`session_create/3`.\n\n`Ports` is either a port identifier for a local port or one of the following atoms:\n\n- **`all`** - All currently existing ports and all that will be\n created in the future.\n\n- **`existing`** - All currently existing ports.\n\n- **`new`** - All ports that will be created in the future.\n\n`FlagList` can contain any number of the following flags (the \"message tags\"\nrefers to the list of [`trace messages`](#port_trace_messages)):\n\n- **`all`** - Sets all trace flags except `cpu_timestamp`, which are in its\n nature different than the others.\n\n- **`send`** - Traces sending of messages.\n\n Message tags: [`send`](#port_trace_messages_send) and\n [`send_to_non_existing_process`](#port_trace_messages_send_to_non_existing_process).\n\n- **`'receive'`** - Traces receiving of messages.\n\n Message tags: [`'receive'`](#port_trace_messages_receive).\n\n- **`ports`** - Traces port-related events.\n\n Message tags: [`open`](#port_trace_messages_open),\n [`closed`](#port_trace_messages_closed),\n [`register`](#port_trace_messages_register),\n [`unregister`](#port_trace_messages_unregister),\n [`getting_linked`](#port_trace_messages_getting_linked), and\n [`getting_unlinked`](#port_trace_messages_getting_unlinked).\n\n- **`running_ports`** - Traces scheduling of ports.\n\n Message tags: [`in`](#port_trace_messages_in_port) and\n [`out`](#port_trace_messages_out_port).\n\n- **`timestamp`**, **`cpu_timestamp`**, **`monotonic_timestamp`**,\n **`strict_monotonic_timestamp`** - Same as for timestamps in\n [`process/4`](#timestamp).\n\nThe tracing process receives the _trace messages_ described in the following\nlist. `Port` is the port identifier of the traced port in which the traced\nevent has occurred. The third tuple element is the message tag.\n\nIf flag `timestamp`, `strict_monotonic_timestamp`, or `monotonic_timestamp` is\nspecified, the first tuple element is `trace_ts` instead, and the time stamp is\nadded as an extra element last in the message tuple. If multiple time stamp\nflags are passed, `timestamp` has precedence over `strict_monotonic_timestamp`,\nwhich in turn has precedence over `monotonic_timestamp`. All time stamp flags\nare remembered, so if two are passed and the one with highest precedence later\nis disabled, the other one becomes active.\n\nIf a match specification (applicable only for `send` and `'receive'`\ntracing) contains a `{message}` action function with a non-boolean value, that\nvalue is added as an extra element to the message tuple either in the last\nposition or before the timestamp (if it is present).\n\nTrace messages:\n\n[](){: #port_trace_messages }\n\n- **`{trace, Port, send, Msg, To}`{: #port_trace_messages_send }** - When\n `Port` sends message `Msg` to process `To`.\n\n- **`{trace, Port, send_to_non_existing_process, Msg, To}`{:\n #port_trace_messages_send_to_non_existing_process }** - When `Port`\n sends message `Msg` to the non-existing process `To`.\n\n- **`{trace, Port, 'receive', Msg}`{: #port_trace_messages_receive }** -\n When `Port` receives message `Msg`. If `Msg` is set to time-out, a receive\n statement can have timed out, or the process received a message with the\n payload `timeout`.\n\n- **`{trace, Port, register, RegName}`{: #port_trace_messages_register\n }** - When `Port` gets the name `RegName` registered.\n\n- **`{trace, Port, unregister, RegName}`{: #port_trace_messages_unregister\n }** - When `Port` gets the name `RegName` unregistered. This is done\n automatically when a registered process or port exits.\n\n- **`{trace, Port, getting_linked, Pid2}`{:\n #port_trace_messages_getting_linked }** - When `Port` gets linked to a\n process `Pid2`.\n\n- **`{trace, Port, getting_unlinked, Pid2}`{:\n #port_trace_messages_getting_unlinked }** - When `Port` gets unlinked\n from a process `Pid2`.\n\n- **`{trace, Port, open, Pid, Driver}`{: #port_trace_messages_open }** - When\n `Pid` opens a new port `Port` with the running `Driver`.\n\n `Driver` is the name of the driver as an atom.\n\n- **`{trace, Port, closed, Reason}`{: #port_trace_messages_closed }** - When\n `Port` closes with `Reason`.\n\n- **`{trace, Port, in, Command | 0}`{: #port_trace_messages_in_port }** -\n When `Port` is scheduled to run. `Command` is the first thing the port will\n execute, it can however run several commands before being scheduled out. On\n some rare occasions, the current function cannot be determined, then the last\n element is `0`.\n\n The possible commands are `call`, `close`, `command`, `connect`, `control`,\n `flush`, `info`, `link`, `open`, and `unlink`.\n\n- **`{trace, Port, out, Command | 0}`{: #port_trace_messages_out_port }** -\n When `Port` is scheduled out. The last command run was `Command`. On some rare\n occasions, the current function cannot be determined, then the last element is\n `0`. `Command` can contain the same commands as `in`\n\nIf the tracing process/port dies or the tracer module returns `remove`, the\nflags are silently removed.\n\nReturns a number indicating the number of ports that matched `Ports`.\nIf `Ports` is a port identifier, the return value is `1`. If\n`Ports` is `all` or `existing`, the return value is the number of\nexisting ports. If `Ports` is `new`, the return value is `0`.\n\nFailure: `badarg` if the specified arguments are not supported. For example,\n`cpu_timestamp` is not supported on all platforms.","title":"trace.port/4","ref":"trace.html#port/4"},{"type":"function","doc":"Turn on or off trace flags for one or more processes.\n\nArgument `Session` is the trace session to operate on as returned by\n`session_create/3`.\n\nArgument `Procs` is either a process identifier (pid) for a local process or\none of the following atoms:\n\n- **`all`** - All currently existing processes and all that will be\n created in the future.\n\n- **`existing`** - All currently existing processes.\n\n- **`new`** - All processes that will be created in the future.\n\nArgument `How` is either `true` to turn on trace flags or `false` to turn them off.\n\nArgument `FlagList` can contain any number of the following flags (the \"message\ntags\" refers to the list of [`trace messages`](#process_trace_messages)):\n\n- **`all`** - Sets all trace flags except `cpu_timestamp`, which\n is in its nature different than the others.\n\n- **`send`** - Traces sending of messages. Limit which sent messages to trace by\n calling `send/3`.\n\n Message tags: [`send`](#process_trace_messages_send) and\n [`send_to_non_existing_process`](#process_trace_messages_send_to_non_existing_process).\n\n- **`'receive'`** - Traces receiving of messages. Limit which received messages\n to trace by calling `recv/3`.\n\n Message tags: [`'receive'`](#process_trace_messages_receive).\n\n- **`call`** - Traces certain function calls. Specify which function calls to\n trace by calling `function/4`.\n\n Message tags: [`call`](#process_trace_messages_call) and\n [`return_from`](#process_trace_messages_return_from).\n\n- **`silent`** - Used with the `call` trace flag. The `call`, `return_from`, and\n `return_to` trace messages are inhibited if this flag is set, but they are\n executed as normal if there are match specifications.\n\n Silent mode is inhibited by executing `trace:process(_, _, false, [silent|_])`, or\n by a match specification executing the function `{silent, false}`.\n\n The `silent` trace flag facilitates setting up a trace on many or even all\n processes in the system. The trace can then be activated and deactivated using\n the match specification function `{silent,Bool}`, giving a high degree of\n control of which functions with which arguments that trigger the trace.\n\n Message tags: [`call`](#process_trace_messages_call),\n [`return_from`](#process_trace_messages_return_from), and\n [`return_to`](#process_trace_messages_return_to). Or rather, the\n absence of.\n\n- **`return_to`** - Used with the `call` trace flag. Traces the exit from\n call traced functions back to where the execution resumes. Only works for\n functions traced with option `local` to `function/4`.\n\n The semantics is that a `return_to` trace message is sent when a call traced\n function returns or throws and exception that is caught. For tail calls, only\n one trace message is sent per chain of tail calls, so the properties of tail\n recursiveness for function calls are kept while tracing with this\n flag. Similar for exceptions, only one `return_to` trace message is sent, even\n if the exception passed more than one call traced function before it was\n caught.\n\n Using `call` and `return_to` trace together makes it possible to know exactly\n in which function a process executes at any time.\n\n To get trace messages containing return values from functions, use the\n `{return_trace}` match specification action instead.\n\n Message tags: [`return_to`](#process_trace_messages_return_to).\n\n- **`procs`** - Traces process-related events.\n\n Message tags: [`spawn`](#process_trace_messages_spawn),\n [`spawned`](#process_trace_messages_spawned),\n [`exit`](#process_trace_messages_exit),\n [`register`](#process_trace_messages_register),\n [`unregister`](#process_trace_messages_unregister),\n [`link`](#process_trace_messages_link),\n [`unlink`](#process_trace_messages_unlink),\n [`getting_linked`](#process_trace_messages_getting_linked), and\n [`getting_unlinked`](#process_trace_messages_getting_unlinked).\n\n- **`running`** - Traces scheduling of processes.\n\n Message tags: [`in`](#process_trace_messages_in_proc) and\n [`out`](#process_trace_messages_out_proc).\n\n- **`exiting`** - Traces scheduling of exiting processes.\n\n Message tags:\n [`in_exiting`](#process_trace_messages_in_exiting_proc),\n [`out_exiting`](#process_trace_messages_out_exiting_proc), and\n [`out_exited`](#process_trace_messages_out_exited_proc).\n\n- **`running_procs`** - Traces scheduling of processes just like `running`.\n However, this option also includes schedule events when the process executes\n within the context of a port without being scheduled out itself.\n\n Message tags: [`in`](#process_trace_messages_in_proc) and\n [`out`](#process_trace_messages_out_proc).\n\n- **`garbage_collection`** - Traces garbage collections of processes.\n\n Message tags:\n [`gc_minor_start`](#process_trace_messages_gc_minor_start),\n [`gc_max_heap_size`](#process_trace_messages_gc_max_heap_size), and\n [`gc_minor_end`](#process_trace_messages_gc_minor_end).\n\n- **`timestamp`{: #timestamp }** - Includes a time stamp in all trace\n messages. The time stamp (Ts) has the same form as returned by\n `erlang:now/0`.\n\n- **`cpu_timestamp`** - A global trace flag for the Erlang node that makes all\n trace time stamps using flag `timestamp` to be in CPU time, not wall clock\n time. That is, `cpu_timestamp` is not be used if `monotonic_timestamp` or\n `strict_monotonic_timestamp` is enabled. Only allowed with `Procs==all`.\n If the host machine OS does not support high-resolution CPU time measurements,\n `process/4` exits with `badarg`. Notice that most OS do not\n synchronize this value across cores, so be prepared that time can seem to go\n backwards when using this option.\n\n- **`monotonic_timestamp`** - Includes an\n [Erlang monotonic time](`e:erts:time_correction.md#erlang-monotonic-time`) time stamp\n in all trace messages. The time stamp (Ts) has the same format and value as\n produced by [`erlang:monotonic_time(nanosecond)`](`erlang:monotonic_time/1`). This\n flag overrides flag `cpu_timestamp`.\n\n- **`strict_monotonic_timestamp`** - Includes an time stamp consisting of\n [Erlang monotonic time](`e:erts:time_correction.md#erlang-monotonic-time`) and a\n monotonically increasing integer in all trace messages. The time stamp (Ts)\n has the same format and value as produced by `{`\n [`erlang:monotonic_time(nanosecond)`](`erlang:monotonic_time/1`)`,`\n [`erlang:unique_integer([monotonic])`](`erlang:unique_integer/1`)`}`. This flag\n overrides flag `cpu_timestamp`.\n\n If multiple time stamp flags are passed, `timestamp` has precedence over\n `strict_monotonic_timestamp`, which in turn has precedence over\n `monotonic_timestamp`. All time stamp flags are remembered, so if two are\n passed and the one with highest precedence later is disabled, the other one\n becomes active.\n\n- **`arity`** - Used with the `call` trace flag. `{M, F, Arity}` is specified\n instead of `{M, F, Args}` in call trace messages.\n\n- **`set_on_spawn`** - Makes any process created by a traced process inherit all\n its trace flags, including flag `set_on_spawn` itself.\n\n- **`set_on_first_spawn`** - Makes the first process created by a traced process\n inherit all its trace flags, excluding flag `set_on_first_spawn` itself. That\n is, after the first spawn is done, `set_on_first_spawn` will be cleared in\n both the spawned process and the spawning process.\n\n If both are set, `set_on_first_spawn` will supersede `set_on_spawn`.\n\n- **`set_on_link`** - Makes any process linked by a traced process inherit all\n its trace flags, including flag `set_on_link` itself.\n\n- **`set_on_first_link`** - Makes the first process linked to by a traced\n process inherit all its trace flags, excluding flag `set_on_first_link`\n itself. That is, after the first link is done, `set_on_first_link` will be\n cleared in both the linked process and the linking process.\n\n If both are set, `set_on_first_link` will supersede `set_on_link`.\n\nThe tracing process receives the _trace messages_ described in the following\nlist. `Pid` is the process identifier of the traced process in which the traced\nevent has occurred. The third tuple element is the message tag.\n\nIf flag `timestamp`, `strict_monotonic_timestamp`, or `monotonic_timestamp` is\nspecified, the first tuple element is `trace_ts` instead, and the time stamp is\nadded as an extra element last in the message tuple.\n\nIf a match specification (applicable only for `call`, `send`, and `'receive'`\ntracing) contains a `{message}` action function with a non-boolean value, that\nvalue is added as an extra element to the message tuple either in the last\nposition or before the timestamp (if it is present).\n\nTrace messages:\n\n[](){: #process_trace_messages }\n\n- **`{trace, Pid, send, Msg, To}`{: #process_trace_messages_send }** - When\n process `Pid` sends message `Msg` to process `To`.\n\n- **`{trace, Pid, send_to_non_existing_process, Msg, To}`{:\n #process_trace_messages_send_to_non_existing_process }** - When process `Pid`\n sends message `Msg` to the non-existing process `To`.\n\n- **`{trace, Pid, 'receive', Msg}`{: #process_trace_messages_receive }** -\n When process `Pid` receives message `Msg`. If `Msg` is set to time-out, a receive\n statement can have timed out, or the process received a message with the\n payload `timeout`.\n\n- **`{trace, Pid, call, {M, F, Args}}`{: #process_trace_messages_call }** - When\n process `Pid` calls a traced function. The return values of calls are never\n supplied, only the call and its arguments.\n\n Trace flag `arity` can be used to change the contents of this message, so that\n `Arity` is specified instead of `Args`.\n\n- **`{trace, Pid, return_to, {M, F, Arity}}`{: #process_trace_messages_return_to\n }** - When process `Pid` returns _to_ the specified function. This trace\n message is sent if both the flags `call` and `return_to` are set, and the\n function is set to be traced on _local_ function calls. The message is only\n sent when returning from a chain of tail recursive function calls, where at\n least one call generated a `call` trace message (that is, the functions match\n specification matched, and `{message, false}` was not an action).\n\n- **`{trace, Pid, return_from, {M, F, Arity}, ReturnValue}`{:\n #process_trace_messages_return_from }** - When `Pid` returns _from_ the\n specified function. This trace message is sent if flag `call` is set, and the\n function has a match specification with a `return_trace` or `exception_trace`\n action.\n\n- **`{trace, Pid, exception_from, {M, F, Arity}, {Class, Value}}`{:\n #process_trace_messages_exception_from }** - When `Pid` exits _from_ the\n specified function because of an exception. This trace message is sent if flag\n `call` is set, and the function has a match specification with an\n `exception_trace` action.\n\n- **`{trace, Pid, spawn, Pid2, {M, F, Args}}`{: #process_trace_messages_spawn\n }** - When `Pid` spawns a new process `Pid2` with the specified function call\n as entry point.\n\n `Args` is supposed to be the argument list, but can be any term if the spawn\n is erroneous.\n\n- **`{trace, Pid, spawned, Pid2, {M, F, Args}}`{:\n #process_trace_messages_spawned }** - When `Pid` is spawned by process `Pid2`\n with the specified function call as entry point.\n\n `Args` is supposed to be the argument list, but can be any term if the spawn\n is erroneous.\n\n- **`{trace, Pid, exit, Reason}`{: #process_trace_messages_exit }** - When `Pid`\n exits with reason `Reason`.\n\n- **`{trace, Pid, register, RegName}`{: #process_trace_messages_register\n }** - When process `Pid` gets the name `RegName` registered.\n\n- **`{trace, Pid, unregister, RegName}`{: #process_trace_messages_unregister\n }** - When process `Pid` gets the name `RegName` unregistered. This is done\n automatically when a registered process or port exits.\n\n- **`{trace, Pid, link, Pid2}`{: #process_trace_messages_link }** - When `Pid`\n links to a process `Pid2`.\n\n- **`{trace, Pid, unlink, Pid2}`{: #process_trace_messages_unlink }** - When\n `Pid` removes the link from a process `Pid2`.\n\n- **`{trace, Pid, getting_linked, Pid2}`{:\n #process_trace_messages_getting_linked }** - When `Pid` gets linked to a\n process `Pid2`.\n\n- **`{trace, Pid, getting_unlinked, Pid2}`{:\n #process_trace_messages_getting_unlinked }** - When `Pid` gets unlinked\n from a process `Pid2`.\n\n- **`{trace, Port, open, Pid, Driver}`{: #process_trace_messages_open }** - When\n `Pid` opens a new port `Port` with the running `Driver`.\n\n `Driver` is the name of the driver as an atom.\n\n- **[](){: #process_trace_messages_in_proc }\n `{trace, Pid, in | in_exiting, {M, F, Arity} | 0}`{:\n #process_trace_messages_in_exiting_proc }**\n When `Pid` is scheduled to run. The process runs in function `{M, F, Arity}`.\n On some rare occasions, the current function cannot be determined, then the\n last element is `0`.\n\n- **[](){: #process_trace_messages_out_proc } [](){:\n #process_trace_messages_out_exiting_proc }\n `{trace, Pid, out | out_exiting | out_exited, {M, F, Arity} | 0}`{:\n #process_trace_messages_out_exited_proc }**\n When `Pid` is scheduled out. The process was running in function `{M, F,\n Arity}`. On some rare occasions, the current function cannot be determined,\n then the last element is `0`.\n\n- **`{trace, Pid, gc_minor_start, Info}`{:\n #process_trace_messages_gc_minor_start }** - [](){: #gc_minor_start } Sent\n when a garbage collection of the young generation is about to be started.\n `Info` is a list of two-element tuples, where the first element is a key,\n and the second is the value. Do not depend on any order of the tuples.\n The following keys are defined:\n\n - **`heap_size`** - The size of the used part of the heap.\n\n - **`heap_block_size`** - The size of the memory block used for storing the\n heap and the stack.\n\n - **`old_heap_size`** - The size of the used part of the old heap.\n\n - **`old_heap_block_size`** - The size of the memory block used for storing\n the old heap.\n\n - **`stack_size`** - The size of the stack.\n\n - **`recent_size`** - The size of the data that survived the previous garbage\n collection.\n\n - **`mbuf_size`** - The combined size of message buffers associated with the\n process.\n\n - **`bin_vheap_size`** - The total size of unique off-heap binaries referenced\n from the process heap.\n\n - **`bin_vheap_block_size`** - The total size of binaries allowed in the\n virtual heap in the process before doing a garbage collection.\n\n - **`bin_old_vheap_size`** - The total size of unique off-heap binaries\n referenced from the process old heap.\n\n - **`bin_old_vheap_block_size`** - The total size of binaries allowed in the\n virtual old heap in the process before doing a garbage collection.\n\n - **`wordsize`** - For the `gc_minor_start` event it is the size of the need\n that triggered the GC. For the corresponding `gc_minor_end` event it is the\n size of reclaimed memory = start `heap_size` - end `heap_size`.\n\n All sizes are in words.\n\n- **`{trace, Pid, gc_max_heap_size, Info}`{:\n #process_trace_messages_gc_max_heap_size }** - Sent when the\n [`max_heap_size`](`e:erts:erlang#process_flag_max_heap_size`) is reached during\n garbage collection. `Info` contains the same kind of list as in message\n `gc_start`, but the sizes reflect the sizes that triggered `max_heap_size` to\n be reached.\n\n- **`{trace, Pid, gc_minor_end, Info}`{: #process_trace_messages_gc_minor_end\n }** - Sent when young garbage collection is finished. `Info` contains the same\n kind of list as in message `gc_minor_start`, but the sizes reflect the new\n sizes after garbage collection.\n\n- **`{trace, Pid, gc_major_start, Info}`{:\n #process_trace_messages_gc_major_start }** - Sent when fullsweep garbage\n collection is about to be started. `Info` contains the same kind of list as in\n message `gc_minor_start`.\n\n- **`{trace, Pid, gc_major_end, Info}`{: #process_trace_messages_gc_major_end\n }** - Sent when fullsweep garbage collection is finished. `Info` contains the\n same kind of list as in message `gc_minor_start`, but the sizes reflect the\n new sizes after a fullsweep garbage collection.\n\nIf the tracing process dies or the tracer module returns `remove`, the\nflags are silently removed.\n\nReturns a number indicating the number of processes that matched `Procs`.\nIf `Procs` is a process identifier, the return value is `1`. If\n`Procs` is `all` or `existing`, the return value is the number of\nprocesses running. If `Procs` is `new`, the return value is `0`.\n\nFailure: `badarg` if the specified arguments are not supported. For example,\n`cpu_timestamp` is not supported on all platforms.","title":"trace.process/4","ref":"trace.html#process/4"},{"type":"function","doc":"Set trace pattern for _message receiving_.\n\nMust be combined with `process/4` or `port/4` to set the `'receive'` trace flag\nfor one or more processes or ports.\n\nArgument `Session` is the trace session to operate on as returned by\n`session_create/3`.\n\nThe default value for the `receive` trace pattern in each session is\n`true`. That is, all messages received by processes having `'receive'`\ntrace enabled will be traced. Use this function to limit traced\n`'receive'` events based on the message content, the sender, and/or the\nreceiver.\n\nArgument `MatchSpec` can take the following forms:\n\n- **`MatchExpression`** - A match specification. The matching is done on\n the list `[Node, Sender, Msg]`. `Node` is the node name of the sender.\n `Sender` is the process or port identity of the sender, or the atom\n `undefined` if the sender is not known (which can be the case for remote\n senders). `Msg` is the message term. The pid of the receiving process can be\n accessed with the guard function `self/0`. An empty list is the same as\n `true`. For more information, see section\n [Match Specifications in Erlang](`e:erts:match_spec.md`) in the User's Guide\n for the ERTS application.\n\n- **`true`** - Enable tracing for all received messages (to `'receive'` traced\n processes). Any match specification is removed. _This is the default_.\n\n- **`false`** - Disable tracing for all received messages. Any match\n specification is removed.\n\nArgument `FlagList` must be `[]` for receive tracing.\n\nThe return value is always `1`.\n\n*Examples:*\n\nOnly trace messages from a specific process `Pid`:\n\n```erlang\n> trace:recv(Session, [{['_',Pid, '_'],[],[]}], []).\n1\n```\n\nOnly trace messages matching `{reply, _}`:\n\n```erlang\n> trace:recv(Session, [{['_','_', {reply,'_'}],[],[]}], []).\n1\n```\n\nOnly trace messages from other nodes:\n\n```erlang\n> trace:recv(Session, [{['$1', '_', '_'],[{'=/=','$1',{node}}],[]}], []).\n1\n```\n\n> #### Note {: .info }\n>\n> A match specification for `'receive'` trace can use all guard and body\n> functions except `caller`, `is_seq_trace`, `get_seq_token`, `set_seq_token`,\n> `enable_trace`, `disable_trace`, `trace`, `silent`, and `process_dump`.\n\nFails by raising an error exception with an error reason of:\n\n- **`badarg`** - If an argument is invalid.\n\n- **`system_limit`** - If a match specification passed as argument has excessive\n nesting which causes scheduler stack exhaustion for the scheduler that the\n calling process is executing on.\n [Scheduler stack size](`e:erts:erl_cmd.md#sched_thread_stack_size`) can be configured\n when starting the runtime system.","title":"trace.recv/3","ref":"trace.html#recv/3"},{"type":"function","doc":"Set trace pattern for _message sending_.\n\nMust be combined with `process/4` or `port/4` to set the `send` trace flag for\none or more processes or ports.\n\nArgument `Session` is the trace session to operate on as returned by\n`session_create/3`.\n\nThe default value for the `send` trace pattern in each session is\n`true`. That is, all messages sent from processes having `send` trace\nenabled will be traced. Use this function to limit traced `send`\nevents based on the message content, the sender, and/or the receiver.\n\nArgument `MatchSpec` can take the following forms:\n\n- **`MatchExpression`** - A match specification. The matching is done on\n the list `[Receiver, Msg]`. `Receiver` is the process or port identity of the\n receiver and `Msg` is the message term. The pid of the sending process can be\n accessed with the guard function `self/0`. An empty list is the same as\n `true`. For more information, see section\n [Match Specifications in Erlang](`e:erts:match_spec.md`) in the User's Guide\n for the ERTS application.\n\n- **`true`** - Enable tracing for all sent messages (from `send` traced\n processes). Any match specification is removed.\n\n- **`false`** - Disable tracing for all sent messages. Any match specification\n is removed.\n\nArgument `FlagList` must be `[]`.\n\nThe return value is always `1`.\n\n*Examples:*\n\nOnly trace messages to a specific process `Pid`:\n\n```erlang\n> trace:send(Session, [{[Pid, '_'],[],[]}], []).\n1\n```\n\nOnly trace messages matching `{reply, _}`:\n\n```erlang\n> trace:send(Session, [{['_', {reply,'_'}],[],[]}], []).\n1\n```\n\nOnly trace messages sent to the sender itself:\n\n```erlang\n> trace:send(Session, [{['$1', '_'],[{'=:=','$1',{self}}],[]}], []).\n1\n```\n\nOnly trace messages sent to other nodes:\n\n```erlang\n> trace:send(Session, [{['$1', '_'],[{'=/=',{node,'$1'},{node}}],[]}], []).\n1\n```\n\n> #### Note {: .info }\n>\n> A match specification for `send` trace can use all guard and body functions\n> except `caller`.\n\nFails by raising an error exception with an error reason of:\n\n- **`badarg`** - If an argument is invalid.\n\n- **`system_limit`** - If a match specification passed as argument has excessive\n nesting which causes scheduler stack exhaustion for the scheduler that the\n calling process is executing on.\n [Scheduler stack size](`e:erts:erl_cmd.md#sched_thread_stack_size`) can be configured\n when starting the runtime system.","title":"trace.send/3","ref":"trace.html#send/3"},{"type":"function","doc":"Create a new trace session.\n\nArgument `Name` is an atom name for the session. It will be returned when\ninspecting with `session_info/1`.\n\nArgument `Tracer` specifies the consumer of all trace events for the session. It\ncan be an identifier of a local process or port to receive all trace\nmessages.\n\n`Tracer` can also be a tuple `{TracerModule, TracerState}` for a tracer module\nto be called instead of sending a trace message. The tracer module can then\nignore or change the trace message. For more details on how to write a tracer\nmodule, see module `m:erl_tracer`.\n\nArgument `Opts` must be `[]`.\n\nReturns an opaque handle to the trace session. The handle will keep the session\nalive. If the handle is dropped and garbage collected, the session will be\ndestroyed and cleaned up as if `session_destroy/1` was called.","title":"trace.session_create/3","ref":"trace.html#session_create/3"},{"type":"function","doc":"Destroy a trace session and cleanup all its settings on processes, ports, and\nfunctions.\n\nThe only things not cleaned up are trace messages that have already been sent.\n\nReturns `true` if the session was active. Returns `false` if the session had\nalready been destroyed by either an earler call to this function or the garbage\ncollector.","title":"trace.session_destroy/1","ref":"trace.html#session_destroy/1"},{"type":"function","doc":"Return which trace sessions that affect a port, process, function, or event.\n\nArgument `all` returns all active trace sessions that exists on the node.\n\nReturns a list of [weak session handles](`t:session_weak_ref/0`) or `undefined` if the\nprocess/port/function does not exists.","title":"trace.session_info/1","ref":"trace.html#session_info/1"},{"type":"function","doc":"Enable/disable monitoring of system events.\n\nArgument `Session` is the trace session to operate on as returned by\n`session_create/3`.\n\nArgument `Event` is an atom describing the kind of system event to\nmonitor. To enable monitoring argument `Value` is, depending on event, either a\nlimit of that event or the atom `true`. To disable monitoring pass `Value` as the\natom `false`.\n\nWhen a monitored system event happens, a message is sent to the session\ntracer. The session tracer must be a process otherwise the function call will\nfail.\n\nThe following `Event`s with `Value`s can be monitored:\n\n- **`long_gc, Time`** - If a garbage collection in the system takes at least\n `Time` wall clock milliseconds, a message `{monitor, GcPid, long_gc, Info}` is\n sent. `GcPid` is the pid that was garbage collected. `Info` is a list of\n two-element tuples describing the result of the garbage collection.\n\n One of the tuples is `{timeout, GcTime}`, where `GcTime` is the time for the\n garbage collection in milliseconds. The other tuples are tagged with\n `heap_size`, `heap_block_size`, `stack_size`, `mbuf_size`, `old_heap_size`,\n and `old_heap_block_size`. These tuples are explained in the description of\n trace message [`gc_minor_start`](`m:trace#gc_minor_start`) (see\n `trace:process/4`). New tuples can be added, and the order of the tuples in\n the `Info` list can be changed at any time without prior notice.\n\n- **`long_message_queue, {Disable, Enable}`** - If the number of messages in the\n message queue of a process reach `Enable`, a message `{monitor, Pid,\n long_message_queue, Long}` is sent. `Pid` is the process identifier of the\n process that got a long message queue and `Long` will equal `true` indicating\n that it is in a _long message queue_ state. No more `long_message_queue`\n monitor messages will be sent due to the process identified by `Pid` until its\n message queue length falls down to a length of `Disable` length. When this\n happens, a `long_message_queue` monitor message with `Long` equal to `false`\n will be sent indicating that the process is no longer in a _long message\n queue_ state. As of this, if the message queue length should again reach\n `Enable` length, a new `long_message_queue` monitor message with `Long` set to\n `true` will again be sent. That is, a `long_message_queue` monitor message is\n sent when a process enters or leaves a _long message queue_ state where these\n state changes are defined by the `Enable` and `Disable` parameters.\n\n `Enable` must be an integer larger than zero. `Disable` must be an integer\n larger than or equal to zero and smaller than `Enable`. If the above is not\n satisfied the operation will fail with a `badarg` error exception. You are\n recommended to use a much smaller value for `Disable` length than `Enable`\n length in order not to be flooded with `long_message_queue` monitor messages.\n\n- **`long_schedule, Time`** - If a process or port in the system runs\n uninterrupted for at least `Time` wall clock milliseconds, a message\n `{monitor, PidOrPort, long_schedule, Info}` is sent.\n `PidOrPort` is the process or port that was running. `Info` is a list of\n two-element tuples describing the event.\n\n If a `t:pid/0`, the tuples `{timeout, Millis}`, `{in, Location}`, and\n `{out, Location}` are present, where `Location` is either an MFA\n (`{Module, Function, Arity}`) describing the function where the process was\n scheduled in/out, or the atom `undefined`.\n\n If a `t:port/0`, the tuples `{timeout, Millis}` and `{port_op,Op}` are\n present. `Op` is one of `proc_sig`, `timeout`, `input`, `output`, `event`, or\n `dist_cmd`, depending on which driver callback was executing.\n\n `proc_sig` is an internal operation and is never to appear, while the others\n represent the corresponding driver callbacks `timeout`, `ready_input`,\n `ready_output`, `event`, and `outputv` (when the port is used by\n distribution). Value `Millis` in tuple `timeout` informs about the\n uninterrupted execution time of the process or port, which always is equal to\n or higher than the `Time` value supplied when starting the trace. New tuples\n can be added to the `Info` list in a future release. The order of the tuples\n in the list can be changed at any time without prior notice.\n\n This can be used to detect problems with NIFs or drivers that take too long to\n execute. 1 ms is considered a good maximum time for a driver callback or a\n NIF. However, a time-sharing system is usually to consider everything < 100 ms\n as \"possible\" and fairly \"normal\". However, longer schedule times can indicate\n swapping or a misbehaving NIF/driver. Misbehaving NIFs and drivers can cause\n bad resource utilization and bad overall system performance.\n\n- **`large_heap, Size`** - If a garbage collection in the system results in\n the allocated size of a heap being at least `Size` words, a message\n `{monitor, GcPid, large_heap, Info}` is sent. `GcPid` and `Info` are the same\n as for `long_gc` described above, except that the tuple tagged with `timeout`\n is not present.\n\n The monitor message is sent if the sum of the sizes of all memory blocks\n allocated for all heap generations after a garbage collection is equal to or\n higher than `Size`.\n\n When a process is killed by\n [`max_heap_size`](`e:erts:erlang#process_flag_max_heap_size`), it is killed before\n the garbage collection is complete and thus no large heap message is sent.\n\n- **`busy_port, true`** - If a process in the system gets suspended because it sends\n to a busy port, a message `{monitor, SusPid, busy_port, Port}` is\n sent. `SusPid` is the pid that got suspended when sending to `Port`.\n\n- **`busy_dist_port, true`[](){: #busy_dist_port } **\n If a process in the system gets suspended because it sends to a process on a remote\n node whose inter-node communication was handled by a busy port, a message\n `{monitor, SusPid, busy_dist_port, Port}` is sent. `SusPid` is the pid that\n got suspended when sending through the inter-node communication port `Port`.\n\nTo disable system monitoring of a event pass the value as `false`. There are no\nother special values (like zero) to disable monitoring of an event. Some of the\nevents have an unspecified minimum value. Lower values will be adjusted to the\nminimum value. For example, it is currently not possible to monitor all garbage\ncollections with `{long_gc, 0}`.\n\n> #### Note {: .info }\n>\n> If the session tracer process gets so large that it itself starts to cause\n> system monitor messages when garbage collecting, the messages enlarge the\n> process message queue and probably make the problem worse.\n>\n> Keep the tracer process neat and do not set the system monitor limits too\n> tight.\n\nFailures:\n\n- **`badarg`** - If the session tracer is not a local process.","title":"trace.system/3","ref":"trace.html#system/3"},{"type":"type","doc":"","title":"trace.match_variable/0","ref":"trace.html#t:match_variable/0"},{"type":"type","doc":"A handle to an isolated trace session.","title":"trace.session/0","ref":"trace.html#t:session/0"},{"type":"opaque","doc":"","title":"trace.session_strong_ref/0","ref":"trace.html#t:session_strong_ref/0"},{"type":"opaque","doc":"A weak session handle as returned by `session_info/1`. A weak session handle can\nbe used like a full session handle, but it will not prevent the session from\nbeing destroyed when the last strong handle is garbage collected.","title":"trace.session_weak_ref/0","ref":"trace.html#t:session_weak_ref/0"},{"type":"type","doc":"","title":"trace.system_event/0","ref":"trace.html#t:system_event/0"},{"type":"type","doc":"","title":"trace.system_value/0","ref":"trace.html#t:system_value/0"},{"type":"type","doc":"","title":"trace.trace_flag/0","ref":"trace.html#t:trace_flag/0"},{"type":"type","doc":"","title":"trace.trace_info_flag/0","ref":"trace.html#t:trace_info_flag/0"},{"type":"type","doc":"","title":"trace.trace_info_item_result/0","ref":"trace.html#t:trace_info_item_result/0"},{"type":"type","doc":"","title":"trace.trace_info_return/0","ref":"trace.html#t:trace_info_return/0"},{"type":"type","doc":"","title":"trace.trace_info_system_item/0","ref":"trace.html#t:trace_info_system_item/0"},{"type":"type","doc":"","title":"trace.trace_match_spec/0","ref":"trace.html#t:trace_match_spec/0"},{"type":"type","doc":"","title":"trace.trace_pattern_flag/0","ref":"trace.html#t:trace_pattern_flag/0"},{"type":"type","doc":"","title":"trace.trace_pattern_mfa/0","ref":"trace.html#t:trace_pattern_mfa/0"},{"type":"extras","doc":"\n# Kernel Application","title":"Kernel Application","ref":"kernel_app.html"},{"type":"extras","doc":"The Kernel application has all the code necessary to run the Erlang runtime\nsystem: file servers, code servers, and so on.\n\nThe Kernel application is the first application started. It is mandatory in the\nsense that the minimal system based on Erlang/OTP consists of Kernel and STDLIB.\nKernel contains the following functional areas:\n\n- Start, stop, supervision, configuration, and distribution of applications\n- Code loading\n- Logging\n- Global name service\n- Supervision of Erlang/OTP\n- Communication with sockets\n- Operating system interface","title":"Description - Kernel Application","ref":"kernel_app.html#description"},{"type":"extras","doc":"Two standard logger handlers are defined in the Kernel application. These are\ndescribed in the [Kernel User's Guide](logger_chapter.md), and in the\n`m:logger_std_h` and [`logger_disk_log_h` ](`m:logger_disk_log_h`)manual pages.\n\n[](){: #erl_signal_server }","title":"Logger Handlers - Kernel Application","ref":"kernel_app.html#logger-handlers"},{"type":"extras","doc":"Asynchronous OS signals may be subscribed to via the Kernel applications event\nmanager (see [OTP Design Principles](`e:system:design_principles.md`) and\n`m:gen_event`) registered as `erl_signal_server`. A default signal handler is\ninstalled which handles the following signals:\n\n- **`sigusr1`** - The default handler will halt Erlang and produce a crashdump\n with slogan \"Received SIGUSR1\". This is equivalent to calling\n `erlang:halt(\"Received SIGUSR1\")`.\n\n- **`sigquit`** - The default handler will halt Erlang immediately. This is\n equivalent to calling `erlang:halt()`.\n\n- **`sigterm`** - The default handler will terminate Erlang normally. This is\n equivalent to calling `init:stop()`.","title":"OS Signal Event Handler - Kernel Application","ref":"kernel_app.html#os-signal-event-handler"},{"type":"extras","doc":"Any event handler added to `erl_signal_server` must handle the following events.\n\n- **`sighup`** - Hangup detected on controlling terminal or death of controlling\n process\n\n- **`sigquit`** - Quit from keyboard\n\n- **`sigabrt`** - Abort signal from abort\n\n- **`sigalrm`** - Timer signal from alarm\n\n- **`sigterm`** - Termination signal\n\n- **`sigusr1`** - User-defined signal 1\n\n- **`sigusr2`** - User-defined signal 2\n\n- **`sigchld`** - Child process stopped or terminated\n\n- **`sigstop`** - Stop process\n\n- **`sigtstp`** - Stop typed at terminal\n\n- **`sigcont`** - Continue after stop\n\n- **`sigwinch`** - Window size change\n\n- **`siginfo`** - Status request from keyboard. Note several operating systems\n (Linux in particular) do not support this signal. `os:set_signal/2` will thow\n a `badarg` exception if support is missing.\n\nSetting OS signals are described in `os:set_signal/2`.","title":"Events - Kernel Application","ref":"kernel_app.html#events"},{"type":"extras","doc":"The following configuration parameters are defined for the Kernel application.\nFor more information about configuration parameters, see file\n[`app`](app.md).\n\n- **`connect_all = true | false`{: #connect_all }** - If enabled (`true`), which\n also is the default, `m:global` will actively connect to all nodes that\n becomes known to it. Note that you also want to enable\n [`prevent_overlapping_partitions`](kernel_app.md#prevent_overlapping_partitions)\n in order for `global` to ensure that a fully connected network is maintained.\n `prevent_overlapping_partitions` will also prevent inconsistencies in\n `global`'s name registration and locking.\n\n The now deprecated command line argument\n [`-connect_all `](`e:erts:erl_cmd.md#connect_all`) has the same\n effect as the `connect_all` configuration parameter. If this configuration\n parameter is defined, it will override the command line argument.\n\n- **`distributed = [Distrib]`{: #distributed }** - Specifies which applications\n that are distributed and on which nodes they are allowed to execute. In this\n parameter:\n\n - `Distrib = {App,Nodes} | {App,Time,Nodes}`\n - `App = atom()`\n - `Time = integer()>0`\n - `Nodes = [node() | {node(),...,node()}]`\n\n The parameter is described in `application:load/2`.\n\n- **`dist_auto_connect = Value`{: #dist_auto_connect }** - Specifies when nodes\n are automatically connected. If this parameter is not specified, a node is\n always automatically connected, for example, when a message is to be sent to\n that node. `Value` is one of:\n\n - **`never`** - Connections are never automatically established, they must be\n explicitly connected. See `m:net_kernel`.\n\n - **`once`** - Connections are established automatically, but only once per\n node. If a node goes down, it must thereafter be explicitly connected. See\n `m:net_kernel`.\n\n- **`epmd_module = module()`{: #epmd_module }** - Configures the module\n responsible for communication with [epmd](`e:erts:epmd_cmd.md`). If this parameter\n is undefined, it defaults to `erl_epmd`.\n\n The now deprecated command line argument\n [`-epmd_module `](`e:erts:erl_cmd.md#epmd_module`) has the same\n effect as the `epmd_module` configuration parameter. If this configuration\n parameter is defined, it will override the command line argument.\n\n- **`erl_epmd_node_listen_port = integer()`{: #erl_epmd_node_listen_port }** - Configures the port used by `m:erl_epmd`\n to listen for connection and connect to other nodes. If this flag is set, the\n Erlang VM will boot in distributed mode even if EPMD is not available. If not\n set, a port is chosen automatically (equivalent to port `0`). See `m:erl_epmd`\n for more details.\n\n The now deprecated command line argument\n [`erl_epmd_port `](`e:erts:erl_cmd.md#erl_epmd_port`) has the same\n effect as the `erl_epmd_node_listen_port` configuration parameter. If this\n configuration parameter is defined, it will override the command line argument.\n\n- **`permissions = [Perm]`{: #permissions }** - Specifies the default permission\n for applications when they are started. In this parameter:\n\n - `Perm = {ApplName,Bool}`\n - `ApplName = atom()`\n - `Bool = boolean()`\n\n Permissions are described in `application:permit/2`.\n\n- **`logger = [Config]`{: #logger }** - Specifies the configuration for\n [Logger](`m:logger`), except the primary log level, which is specified with\n [`logger_level`](kernel_app.md#logger_level), and the compatibility with\n [SASL Error Logging](`e:sasl:error_logging.md`), which is specified with\n [`logger_sasl_compatible`](kernel_app.md#logger_sasl_compatible).\n\n The `logger `parameter is described in section\n [Logging](logger_chapter.md#logger_parameter) in the Kernel User's Guide.\n\n- **`logger_level = Level`{: #logger_level }** - Specifies the primary log level\n for Logger. Log events with the same, or a more severe level, pass through the\n primary log level check. See section [Logging](logger_chapter.md) in the\n Kernel User's Guide for more information about Logger and log levels.\n\n `Level = emergency | alert | critical | error | warning | notice | info | debug | all | none`\n\n To change the primary log level at runtime, use\n [`logger:set_primary_config(level, Level)`](`logger:set_primary_config/2`).\n\n Defaults to `notice`.\n\n- **`logger_metadata = Metadata`{: #logger_metadata }** - Specifies primary\n metadata for log events.\n\n `Metadata = map()`\n\n Defaults to `#{}`.\n\n- **`logger_sasl_compatible = true | false`{: #logger_sasl_compatible }** -\n Specifies if Logger behaves backwards compatible with the SASL error logging\n functionality from releases prior to Erlang/OTP 21.0.\n\n If this parameter is set to `true`, the default Logger handler does not log\n any progress-, crash-, or supervisor reports. If the SASL application is then\n started, it adds a Logger handler named `sasl`, which logs these events\n according to values of the SASL configuration parameter `sasl_error_logger`\n and `sasl_errlog_type`.\n\n See section\n [Deprecated Error Logger Event Handlers and Configuration](`e:sasl:sasl_app.md#deprecated_error_logger_config`)\n in the sasl(6) manual page for information about the SASL configuration\n parameters.\n\n See section [SASL Error Logging](`e:sasl:error_logging.md`) in the SASL User's\n Guide, and section\n [Backwards Compatibility with error_logger](logger_chapter.md#backwards-compatibility-with-error_logger)\n in the Kernel User's Guide for information about the SASL error logging\n functionality, and how Logger can be backwards compatible with this.\n\n Defaults to `false`.\n\n > #### Note {: .info }\n >\n > If this parameter is set to `true`, `sasl_errlog_type` indicates that\n > progress reports shall be logged, and the configured primary log level is\n > `notice` or more severe, then SASL automatically sets the primary log level\n > to `info`. That is, this setting can potentially overwrite the value of the\n > Kernel configuration parameter `logger_level`. This is to allow progress\n > reports, which have log level `info`, to be forwarded to the handlers.\n\n- **`global_groups = [GroupTuple]`{: #global_groups }** - Defines global groups,\n see `m:global_group`. In this parameter:\n\n - `GroupTuple = {GroupName, [Node]} | {GroupName, PublishType, [Node]}`\n - `GroupName = atom()`\n - `PublishType = normal | hidden`\n - `Node = node()`\n\n- **`inet_default_connect_options = [{Opt, Val}]`{: #inet_default_connect_options }** - Specifies default options for `connect`\n sockets, see `m:inet`.\n\n- **`inet_default_listen_options = [{Opt, Val}]`{: #inet_default_listen_options\n }** - Specifies default options for `listen` (and `accept`) sockets, see\n `m:inet`.\n\n- **`inet_dist_use_interface = ip_address()`{: #inet_dist_use_interface }** - If\n the host of an Erlang node has many network interfaces, this parameter\n specifies which one to listen on. For the type definition of `ip_address()`,\n see `m:inet`.\n\n- **`inet_dist_listen_min = First`{: #inet_dist_listen } \n `inet_dist_listen_max = Last`** \n Defines the `First..Last` port range for the listener socket of a distributed\n Erlang node.\n\n- **`inet_dist_listen_options = Opts`{: #inet_dist_listen_options }** - Defines\n a list of extra socket options to be used when opening the listening socket\n for a distributed Erlang node. See `gen_tcp:listen/2`.\n\n- **`inet_dist_connect_options = Opts`{: #inet_dist_connect_options }** -\n Defines a list of extra socket options to be used when connecting to other\n distributed Erlang nodes. See `gen_tcp:connect/4`.\n\n- **`inet_parse_error_log = silent`{: #inet_parse_error_log }** - If set, no log\n events are issued when erroneous lines are found and skipped in the various\n Inet configuration files.\n\n- **`inetrc = Filename`{: #inetrc }** - The name (string) of an Inet user\n configuration file. For details, see section\n [`Inet Configuration`](`e:erts:inet_cfg.md`) in the ERTS User's Guide.\n\n- **`net_setuptime = SetupTime`{: #net_setuptime }** -\n `SetupTime` must be a positive integer or floating point number, and is\n interpreted as the maximum allowed time for each network operation during\n connection setup to another Erlang node. The maximum allowed value is `120`.\n If higher values are specified, `120` is used. Default is 7 seconds if the\n variable is not specified, or if the value is incorrect (for example, not a\n number).\n\n Notice that this value does not limit the total connection setup time, but\n rather each individual network operation during the connection setup and\n handshake.\n\n- **`net_ticker_spawn_options = Opts`{: #net_ticker_spawn_options }** - Defines\n a list of extra spawn options for net ticker processes. There exist one such\n process for each connection to another node. A net ticker process is\n responsible for supervising the connection it is associated with. These\n processes also execute the distribution handshake protocol when setting up\n connections. When there is a large number of distribution connections, setting\n up garbage collection options can be helpful to reduce memory usage. Default\n is `[link, {priority, max}]`, and these two options cannot be changed. The\n `monitor` and `{monitor, MonitorOpts}` options are not allowed and will be\n dropped if present. See the documentation of the `erlang:spawn_opt/4` BIF for\n information about valid options. If the `Opts` list is not a proper list, or\n containing invalid options the setup of connections will fail.\n\n Note that the behavior described above is only true if the distribution\n carrier protocol used is implemented as described in\n [ERTS User's Guide ➜ How to implement an Alternative Carrier for the Erlang Distribution ➜ Distribution Module](`e:erts:alt_dist.md#distribution-module`)\n without further alterations. The implementer of the distribution carrier\n protocol used, may have chosen to ignore the `net_ticker_spawn_options`\n parameter or altered its behavior. Currently all distribution modules shipped\n with OTP do, however, behave as described above.\n\n- **`net_tickintensity = NetTickIntensity`{: #net_tickintensity }** - _Net tick\n intensity_ specifies how many ticks to send during a\n [net tick time](kernel_app.md#net_ticktime) period when no other data is sent\n over a connection to another node. This also determines how often to check for\n data from the other node. The higher net tick intensity, the closer to the\n chosen net tick time period the node will detect an unresponsive node. The net\n tick intensity defaults to `4`. The value of `NetTickIntensity` should be an\n integer in the range `4..1000`. If the `NetTickIntensity` is not an integer or\n an integer less than `4`, `4` will silently be used. If `NetTickIntensity` is\n an integer larger than `1000`, `1000` will silently be used.\n\n > #### Note {: .info }\n >\n > Note that all communicating nodes are expected to use the same _net tick\n > intensity_ as well as the same _net tick time_.\n\n > #### Warning {: .warning }\n >\n > Be careful not to set a too high net tick intensity, since you can overwhelm\n > the node with work if it is set too high.\n\n- **`net_ticktime = NetTickTime`{: #net_ticktime }** - Specifies the _net tick\n time_ in seconds. This is the approximate time a connected node may be\n unresponsive until it is considered down and thereby disconnected.\n\n Net tick time together with\n [net tick intensity](kernel_app.md#net_tickintensity) determines an interval\n `TickInterval = NetTickTime/NetTickIntensity`. Once every `TickInterval`\n seconds, each connected node is ticked if nothing has been sent to it during\n that last `TickInterval` seconds. A tick is a small package sent on the\n connection. A connected node is considered to be down if no ticks or payload\n packages have been received during the last `NetTickIntensity` number of\n `TickInterval` seconds intervals. This ensures that nodes that are not\n responding, for reasons such as hardware errors, are considered to be down.\n\n As the availability is only checked every `TickInterval` seconds, the actual\n time `T` a node have been unresponsive when detected may vary between `MinT`\n and `MaxT`, where:\n\n ```c\n MinT = NetTickTime - NetTickTime / NetTickIntensity\n MaxT = NetTickTime + NetTickTime / NetTickIntensity\n ```\n\n `NetTickTime` defaults to `60` seconds and `NetTickIntensity` defaults to `4`.\n Thus, `45 #### Note {: .info }\n >\n > Notice that _all_ communicating nodes are to have the _same_ `NetTickTime`\n > and `NetTickIntensity` values specified, as it determines both the frequency\n > of outgoing ticks and the expected frequency of incominging ticks.\n\n `NetTickTime` needs to be a multiple of `NetTickIntensity`. If the configured\n values are not, `NetTickTime` will internally be rounded up to the nearest\n millisecond.\n [`net_kernel:get_net_ticktime()`](`net_kernel:get_net_ticktime/0`) will,\n however, report net tick time truncated to the nearest second.\n\n Normally, a terminating node is detected immediately by the transport protocol\n (like TCP/IP).\n\n- **`prevent_overlapping_partitions = true | false`{:\n #prevent_overlapping_partitions }** - If enabled (`true`), `global` will\n actively prevent overlapping partitions from forming when connections are lost\n between nodes. This fix is enabled by default. If you are about to disable\n this fix, make sure to read the\n [`global`](`m:global#prevent_overlapping_partitions`) documentation about this\n fix for more important information about this.\n\n- **`shutdown_timeout = integer() | infinity`{: #shutdown_timeout }** -\n Specifies the time `application_controller` waits for an application to\n terminate during node shutdown. If the timer expires, `application_controller`\n brutally kills `application_master` of the hanging application. If this\n parameter is undefined, it defaults to `infinity`.\n\n- **`sync_nodes_mandatory = [NodeName]`{: #sync_nodes_mandatory }** - Specifies\n which other nodes that _must_ be alive for this node to start properly. If\n some node in the list does not start within the specified time, this node does\n not start either. If this parameter is undefined, it defaults to `[]`.\n\n- **`sync_nodes_optional = [NodeName]`{: #sync_nodes_optional }** - Specifies\n which other nodes that _can_ be alive for this node to start properly. If some\n node in this list does not start within the specified time, this node starts\n anyway. If this parameter is undefined, it defaults to the empty list.\n\n- **`sync_nodes_timeout = integer() | infinity`{: #sync_nodes_timeout }** -\n Specifies the time (in milliseconds) that this node waits for the mandatory\n and optional nodes to start. If this parameter is undefined, no node\n synchronization is performed. This option ensures that `global` is\n synchronized.\n\n- **`start_distribution = true | false`{: #start_distribution }** - Starts all\n distribution services, such as `rpc`, `global`, and `net_kernel` if the\n parameter is `true`. This parameter is to be set to `false` for systems who\n want to disable all distribution functionality.\n\n Defaults to `true`.\n\n- **`start_dist_ac = true | false`{: #start_dist_ac }** - Starts the `dist_ac`\n server if the parameter is `true`. This parameter is to be set to `true` for\n systems using distributed applications.\n\n Defaults to `false`. If this parameter is undefined, the server is started if\n parameter `distributed` is set.\n\n- **`start_boot_server = true | false`{: #start_boot_server }** - Starts the\n `boot_server` if the parameter is `true` (see `m:erl_boot_server`). This\n parameter is to be set to `true` in an embedded system using this service.\n\n Defaults to `false`.\n\n- **`boot_server_slaves = [SlaveIP]`{: #boot_server_slaves }** - If\n configuration parameter `start_boot_server` is `true`, this parameter can be\n used to initialize `boot_server` with a list of slave IP addresses:\n\n `SlaveIP = string() | atom | {integer(),integer(),integer(),integer()}`,\n\n where `0 <= integer() <=255`.\n\n Examples of `SlaveIP` in atom, string, and tuple form:\n\n `'150.236.16.70', \"150,236,16,70\", {150,236,16,70}`.\n\n Defaults to `[]`.\n\n- **`start_disk_log = true | false`{: #start_disk_log }** - Starts the\n `disk_log_server` if the parameter is `true` (see `m:disk_log`). This\n parameter is to be set to `true` in an embedded system using this service.\n\n Defaults to `false`.\n\n- **`start_pg = true | false`{: #start_pg }** - Starts the\n default `pg` scope server (see `m:pg`) if the parameter is `true`. This\n parameter is to be set to `true` in an embedded system that uses this service.\n\n Defaults to `false`.\n\n- **`start_timer = true | false`{: #start_timer }** - Starts the `timer_server`\n if the parameter is `true` (see `m:timer`). This parameter is to be set to\n `true` in an embedded system using this service.\n\n Defaults to `false`.\n\n- **`shell_docs_ansi = boolean()`{: #shell_docs_ansi }** - Specifies whether\n the documentation rendered in the shell should use ANSI escape codes.\n\n See also `t:shell_docs:config/0`.\n\n- **`shell_history = enabled | disabled | module()`{: #shell_history }** -\n Specifies whether shell history should be logged to disk between usages of\n `erl` (`enabled`), not logged at all (`disabled`), or a user-specified module\n will be used to log shell history. This module should export\n `load() -> [string()]` returning a list of strings to load in the shell when\n it starts, and `add(iodata()) -> ok.` called every time new line is entered in\n the shell. By default logging is disabled.\n\n- **`shell_history_drop = [string()]`{: #shell_history_drop }** - Specific log\n lines that should not be persisted. For example `[\"q().\", \"init:stop().\"]`\n will allow to ignore commands that shut the node down. Defaults to `[]`.\n\n- **`shell_history_file_bytes = integer()`{: #shell_history_file_bytes }** - How\n many bytes the shell should remember. By default, the value is set to 512kb,\n and the minimal value is 50kb.\n\n- **`shell_history_path = string()`{: #shell_history_path }** - Specifies where\n the shell history files will be stored. defaults to the user's cache directory\n as returned by `filename:basedir(user_cache, \"erlang-history\")`.\n\n- **`shutdown_func = {Mod :: atom(), Func :: atom()}`{: #shutdown_func }** -\n Sets a function that `application_controller` calls when it starts to\n terminate. The function is called as `Mod:Func(Reason)`, where `Reason` is the\n terminate reason for `application_controller`, and it must return as soon as\n possible for `application_controller` to terminate properly.\n\n- **`source_search_rules = [DirRule] | [SuffixRule]`{: #source_search_rules }**\n\n Where:\n\n - `DirRule = {ObjDirSuffix,SrcDirSuffix}`\n - `SuffixRule = {ObjSuffix,SrcSuffix,[DirRule]}`\n - `ObjDirSuffix = string()`\n - `SrcDirSuffix = string()`\n - `ObjSuffix = string()`\n - `SrcSuffix = string()`\n\n Specifies a list of rules for use by `filelib:find_file/2`\n `filelib:find_source/2` If this is set to some other value than the empty\n list, it replaces the default rules. Rules can be simple pairs of directory\n suffixes, such as `{\"ebin\", \"src\"}`, which are used by `filelib:find_file/2`,\n or triples specifying separate directory suffix rules depending on file name\n extensions, for example `[{\".beam\", \".erl\", [{\"ebin\", \"src\"}]}`, which are\n used by `filelib:find_source/2`. Both kinds of rules can be mixed in the list.\n\n The interpretation of `ObjDirSuffix` and `SrcDirSuffix` is as follows: if the\n end of the directory name where an object is located matches `ObjDirSuffix`,\n then the name created by replacing `ObjDirSuffix` with `SrcDirSuffix` is\n expanded by calling `filelib:wildcard/1`, and the first regular file found\n among the matches is the source file.\n\n- **`standard_io_encoding = Encoding`{: #standard_io_encoding }** - Set whether\n bytes sent or received via standard_io should be interpreted as unicode or\n latin1. By default input and output is interpreted as Unicode if it is\n supported on the host. With this flag you may configure the encoding on\n startup.\n\n This works similarly to\n [`io:setopts(standard_io, {encoding, Encoding})`](`io:setopts/2`) but is\n applied before any bytes on standard_io may have been read.\n\n Encoding is one of:\n\n - **`unicode`** - Configure standard_io to use unicode mode.\n\n - **`latin1`** - Configure standard_io to use latin1 mode.\n\n - **`_`** - Anything other than unicode or latin1 will be ignored and the\n system will configure the encoding by itself, typically unicode on modern\n systems.\n\n See\n [Escripts and non-interactive I/O in Unicode Usage in Erlang](`e:stdlib:unicode_usage.md#escripts-and-non-interactive-i-o`)\n for more details.\n\n- **`os_cmd_shell = string()`{: #os_cmd_shell }** - Specifies which shell to\n use when invoking system commands via `os:cmd/2`. By default the shell is detected\n automatically.","title":"Configuration - Kernel Application","ref":"kernel_app.html#configuration"},{"type":"extras","doc":"In Erlang/OTP 21.0, a new API for logging was added. The old `error_logger`\nevent manager, and event handlers running on this manager, still work, but they\nare no longer used by default.\n\nThe following application configuration parameters can still be set, but they\nare only used if the corresponding configuration parameters for Logger are not\nset.\n\n- **`error_logger`** - Replaced by setting the [`type`](`m:logger_std_h#type`),\n and possibly [`file`](`m:logger_std_h#file`) and\n [`modes`](`m:logger_std_h#modes`) parameters of the default `logger_std_h`\n handler. Example:\n\n ```text\n erl -kernel logger '[{handler,default,logger_std_h,#{config=>#{file=>\"/tmp/erlang.log\"}}}]'\n ```\n\n- **`error_logger_format_depth`**{: #error_logger_format_depth } - Replaced by setting the\n [`depth`](`m:logger_formatter#depth`) parameter of the default handlers\n formatter. Example:\n\n ```text\n erl -kernel logger '[{handler,default,logger_std_h,#{formatter=>{logger_formatter,#{legacy_header=>true,template=>[{logger_formatter,header},\"\\n\",msg,\"\\n\"],depth=>10}}}]'\n ```\n\nSee [Backwards compatibility with error_logger](logger_chapter.md#backwards-compatibility-with-error_logger)\nfor more information.","title":"Deprecated Configuration Parameters - Kernel Application","ref":"kernel_app.html#deprecated-configuration-parameters"},{"type":"extras","doc":"\n# Kernel Release Notes\n\nThis document describes the changes made to the Kernel application.","title":"Kernel Release Notes","ref":"notes.html"},{"type":"extras","doc":"","title":"Kernel 10.1.1 - Kernel Release Notes","ref":"notes.html#kernel-10-1-1"},{"type":"extras","doc":"- 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.\n \n This happened with low probability when the OS signaled that the socket was ready for reading in combination with an internal time-out retry.\n \n 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.\n\n Own Id: OTP-19235 Aux Id: ERIERL-1133, [PR-8837]\n\n- 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.\n\n Own Id: OTP-19258 Aux Id: OTP-19061, ERIERL-1134\n\n[PR-8837]: https://github.com/erlang/otp/pull/8837","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 10.1 - Kernel Release Notes","ref":"notes.html#kernel-10-1"},{"type":"extras","doc":"- 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.\n\n Own Id: OTP-19097 Aux Id: [PR-8503]\n\n- Opening a `disk_log` file and combining `head_func` with `rotate` options did not work.\n\n Own Id: OTP-19104 Aux Id: ERIERL-870\n\n- Fixed an error info printout for `erlang:is_process_alive/1` on non-local pids.\n\n Own Id: OTP-19134 Aux Id: [PR-8560]\n\n- 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.\n\n Own Id: OTP-19175 Aux Id: [GH-8561], [PR-8690]\n\n- 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.\n\n Own Id: OTP-19205\n\n- 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.\n\n Own Id: OTP-19208 Aux Id: [PR-8672]\n\n- Corrected socket:ioctl for genaddr (SIOCGENADDR).\n\n Own Id: OTP-19216\n\n[PR-8503]: https://github.com/erlang/otp/pull/8503\n[PR-8560]: https://github.com/erlang/otp/pull/8560\n[GH-8561]: https://github.com/erlang/otp/issues/8561\n[PR-8690]: https://github.com/erlang/otp/pull/8690\n[PR-8672]: https://github.com/erlang/otp/pull/8672","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Added functions `getservbyname` and `getservbyport` to the `net` module.\n\n Own Id: OTP-19101 Aux Id: OTP-18835\n\n- Introduced enet | esock variants of `m:inet` functions, either when called with sockets,\n with explicit inet_backend config or with the e inet_backend kernel config option.\n\n Own Id: OTP-19132 Aux Id: OTP-19101\n\n- The function `socket:i/0` now uses the `m:net` module (instead of the `m:inet` module) for service translation.\n\n Own Id: OTP-19138 Aux Id: OTP-19101\n\n- 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.\n\n Own Id: OTP-19199 Aux Id: OTP-19175, [GH-8561], [GH-8690], [GH-8785]\n\n[GH-8561]: https://github.com/erlang/otp/issues/8561\n[GH-8690]: https://github.com/erlang/otp/issues/8690\n[GH-8785]: https://github.com/erlang/otp/issues/8785","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 10.0.1 - Kernel Release Notes","ref":"notes.html#kernel-10-0-1"},{"type":"extras","doc":"- Polish the `m:logger` documentation.\n\n Own Id: OTP-19118 Aux Id: [PR-8534]\n\n[PR-8534]: https://github.com/erlang/otp/pull/8534","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 10.0 - Kernel Release Notes","ref":"notes.html#kernel-10-0"},{"type":"extras","doc":"- Fixed a crash when calling `file:delete/2` with an empty option list.\n\n Own Id: OTP-18590 Aux Id: [PR-7220]\n\n- 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.\n\n Own Id: OTP-18878 Aux Id: [GH-7718], OTP-17734\n\n- The error information for `erlang:phash/2` has been corrected.\n\n Own Id: OTP-18904 Aux Id: [PR-7960]\n\n- `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.\n\n Own Id: OTP-18930 Aux Id: [PR-7993], [GH-4992]\n\n- Calling `logger:add_handlers/1` with config option now works.\n\n Own Id: OTP-18954 Aux Id: [GH-8061], [PR-8076]\n\n- The `code:del_path/1` function now also works on paths added through `-pa`, `-pz` , `-path` and the boot script.\n\n Own Id: OTP-18959 Aux Id: [GH-6692], [PR-7697]\n\n- A call to `socket:[recv|recvfrom|recvmsg]/*` with Timeout = 0 on Windows could cause a (case clause) crash if data is immediately available.\n\n Own Id: OTP-19063 Aux Id: OTP-18835\n\n- Improve heuristic for when a characters is wide in the shell for systems with old libc versions.\n\n Own Id: OTP-19087 Aux Id: [PR-8382]\n\n- Fix reading a line when reading from `t:io:user/0` to not consider `\\r` without `\\n` to be a new line when `erl` is started with `-noshell`.\n\n Own Id: OTP-19088 Aux Id: [PR-8396], [GH-8360]\n\n[PR-7220]: https://github.com/erlang/otp/pull/7220\n[GH-7718]: https://github.com/erlang/otp/issues/7718\n[PR-7960]: https://github.com/erlang/otp/pull/7960\n[PR-7993]: https://github.com/erlang/otp/pull/7993\n[GH-4992]: https://github.com/erlang/otp/issues/4992\n[GH-8061]: https://github.com/erlang/otp/issues/8061\n[PR-8076]: https://github.com/erlang/otp/pull/8076\n[GH-6692]: https://github.com/erlang/otp/issues/6692\n[PR-7697]: https://github.com/erlang/otp/pull/7697\n[PR-8382]: https://github.com/erlang/otp/pull/8382\n[PR-8396]: https://github.com/erlang/otp/pull/8396\n[GH-8360]: https://github.com/erlang/otp/issues/8360","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Added `file:read_file/2` with a `raw` option for reading files without going through the file server.\n\n Own Id: OTP-18589 Aux Id: [PR-7220]\n\n- 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. \n \n Kudos to Alexander Clouter that did almost all the work!\n\n Own Id: OTP-18713 Aux Id: [PR-6985], [GH-6985]\n\n- The `ebin` directories for escripts are now cached.\n\n Own Id: OTP-18778 Aux Id: [PR-7556]\n\n- `-callback` attributes haven been added to `m:application`, `m:logger_handler`, and `m:logger_formatter`.\n\n Own Id: OTP-18795 Aux Id: [PR-7703]\n\n- Progress reports from before logger is started are now logged when log level is set to debug.\n\n Own Id: OTP-18807 Aux Id: [PR-7732] ERIERL-985\n\n- The `code:where_is_file/2` and\n `code:which/1` functions now check for existence of the file directly instead of listing the content of each directory in the code path.\n\n Own Id: OTP-18816 Aux Id: [PR-7711]\n\n- Type specs has been added to the [`logger:Level/1,2,3`](`m:logger`) functions.\n\n Own Id: OTP-18820 Aux Id: [PR-7779]\n\n- 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.\n\n Own Id: OTP-18835\n\n- New functions `socket:sendv/*` for sending I/O vectors have been added.\n\n Own Id: OTP-18845\n\n- The shell now pages long output from the documentation help command ([`h(Module)`](`c:h/1`)), auto completions and the search command.\n\n Own Id: OTP-18846 Aux Id: [PR-7845]\n\n- Native coverage support has been implemented in the JIT. It will automatically be used by the `m:cover` tool to reduce the execution overhead when running cover-compiled code.\n \n There are also new APIs to support native coverage without using the `cover` tool.\n \n To instrument code for native coverage it must be compiled with the [`line_coverage`](`m:compile#line_coverage`) option.\n \n To enable native coverage in the runtime system, start it like so:\n \n ```text\n $ erl +JPcover true\n ```\n \n There are also the following new functions for supporting native coverage:\n \n * `code:coverage_support/0`\n * `code:get_coverage/2`\n * `code:reset_coverage/1`\n * `code:get_coverage_mode/0`\n * `code:get_coverage_mode/1`\n * `code:set_coverage_mode/1`\n\n Own Id: OTP-18856 Aux Id: [PR-7856]\n\n- Optimized code loading by moving certain operations from the code server to the caller.\n\n Own Id: OTP-18941 Aux Id: [PR-7981]\n\n- The documentation has been migrated to use Markdown and ExDoc.\n\n Own Id: OTP-18955 Aux Id: [PR-8026]\n\n- Application startup has been optimized by removing an intermediary process.\n\n Own Id: OTP-18963 Aux Id: [PR-8042]\n\n- 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.\n \n As of Erlang/OTP 27, the function `code:lib_dir/2`, the `-code_path_choice` flag, and using `m:erl_prim_loader` for reading members of an archive are deprecated.\n \n 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`.\n\n *** POTENTIAL INCOMPATIBILITY ***\n\n Own Id: OTP-18966 Aux Id: [PR-8091]\n\n- The undocumented and deprecated `file:pid2name` function has been removed.\n\n Own Id: OTP-18967 Aux Id: [PR-8092]\n\n- There is a new module `m: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**.\n\n Own Id: OTP-18980\n\n- Error logging has been improved when the `t:io:standard_io/0` reader and/or writer terminates with an error.\n\n Own Id: OTP-18989 Aux Id: [PR-8103]\n\n- `inet_backend = socket` has been optimized and reworked to be more compatible with the original `inet_backend = inet`.\n\n Own Id: OTP-19004 Aux Id: OTP-18835\n\n- Add an simple example (echo server) )to the socket users guide.\n\n Own Id: OTP-19042\n\n- `inet:i/0,1,2` has been improved to allow port numbers to be shown explicitly.\n\n Own Id: OTP-19053 Aux Id: [#6724]\n\n- The `socket` documentation has been reworked, and due to\n that a few details were fixed:\n * `socket:is_supported/1` now returns `true` for example for `protocols`\n that is a \"category\", not an item.\n * `socket:cancel_monitor/1` no longer badargs for a monitor that was set by\n another process, instead it returns `false` as for other unknown\n `reference()`s.\n\n Own Id: OTP-19054\n\n- Add `stdin`, `stdout` and `stderr` keys to `io:getopts/1` on `t:io:standard_io/0` to indicate if the respective I/O device is backed by a terminal.\n\n Own Id: OTP-19089 Aux Id: [PR-8396]\n\n[PR-7220]: https://github.com/erlang/otp/pull/7220\n[PR-6985]: https://github.com/erlang/otp/pull/6985\n[GH-6985]: https://github.com/erlang/otp/issues/6985\n[PR-7556]: https://github.com/erlang/otp/pull/7556\n[PR-7703]: https://github.com/erlang/otp/pull/7703\n[PR-7732]: https://github.com/erlang/otp/pull/7732\n[PR-7711]: https://github.com/erlang/otp/pull/7711\n[PR-7779]: https://github.com/erlang/otp/pull/7779\n[PR-7845]: https://github.com/erlang/otp/pull/7845\n[PR-7856]: https://github.com/erlang/otp/pull/7856\n[PR-7981]: https://github.com/erlang/otp/pull/7981\n[PR-8026]: https://github.com/erlang/otp/pull/8026\n[PR-8042]: https://github.com/erlang/otp/pull/8042\n[PR-8091]: https://github.com/erlang/otp/pull/8091\n[PR-8092]: https://github.com/erlang/otp/pull/8092\n[PR-8103]: https://github.com/erlang/otp/pull/8103\n[#6724]: https://github.com/erlang/otp/issues/6724\n[PR-8396]: https://github.com/erlang/otp/pull/8396","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 9.2.4.3 - Kernel Release Notes","ref":"notes.html#kernel-9-2-4-3"},{"type":"extras","doc":"* 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.\n\n This happened with low probability when the OS signaled that the socket was ready for reading in combination with an internal time-out retry.\n\n 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.\n\n Own Id: OTP-19235 Aux Id: ERIERL-1133, PR-8837\n* 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.\n\n Own Id: OTP-19258 Aux Id: OTP-19061, ERIERL-1134","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 9.2.4.2 - Kernel Release Notes","ref":"notes.html#kernel-9-2-4-2"},{"type":"extras","doc":"* A race in the kTLS flavour of SSL distribution has been fixed so 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.\n\n Own Id: OTP-19175 Aux Id: GH-8561, PR-8690\n* Fix 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.\n\n Own Id: OTP-19205\n* Add the stdlib application parameters `shell_redraw_prompt_on_output` which when set to `false` disables redrawing of the shell prompt if any other output is done.\n\n Own Id: OTP-19213 Aux Id: PR-8763 ERIERL-1108","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 9.2.4.1 - Kernel Release Notes","ref":"notes.html#kernel-9-2-4-1"},{"type":"extras","doc":"* A call to socket:\\[recv|recvfrom|recvmsg]/* with Timeout = 0 on Windows could cause a (case clause) crash if data is immediately available.\n\n Own Id: OTP-19063 Aux Id: OTP-18835\n* Open a `disk_log` file and combining `head_func` with `rotate` options did not work.\n\n Own Id: OTP-19104 Aux Id: ERIERL-870","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 9.2.4 - Kernel Release Notes","ref":"notes.html#kernel-9-2-4"},{"type":"extras","doc":"* Fix the shell Job Control Mode to not crash when typing `TAB` or `CTRL+R`.\n\n Own Id: OTP-19072 Aux Id: PR-8391\n* Fix calls to blocking `m:application` APIs to throw an exception with reason `terminating` if called when the system is terminating.\n\n This is done in order to avoid deadlocks during shutdown or restart.\n\n Own Id: OTP-19078 Aux Id: PR-8422","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 9.2.3 - Kernel Release Notes","ref":"notes.html#kernel-9-2-3"},{"type":"extras","doc":"* When using IPv6, classic gen_udp failed to add (group) membership (drop was used instead).\n\n Own Id: OTP-19049 Aux Id: #8176\n* The check in inet_res of the RD bit has been relaxed slightly.\n\n Own Id: OTP-19056 Aux Id: PR-8312, OTP-17323","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 9.2.2 - Kernel Release Notes","ref":"notes.html#kernel-9-2-2"},{"type":"extras","doc":"* Fix performance bug when using `io:fread` to read from `standard_io`. This regression was introduced in OTP 26.0.\n\n Own Id: OTP-18910 Aux Id: PR-7933 GH-7924\n* A bug in the code server could cause it to crash in some concurrent scenarios. This bug was introduced in 26.1.\n\n Own Id: OTP-18948 Aux Id: PR-8046\n* Fixed gen_udp:open/2 type spec to include already supported module socket address types.\n\n Own Id: OTP-18990 Aux Id: GH-8158\n* Fix reading of password for ssh client when in `user_interactive` mode.\n\n Own Id: OTP-19007 Aux Id: ERIERL-1049","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 9.2.1 - Kernel Release Notes","ref":"notes.html#kernel-9-2-1"},{"type":"extras","doc":"* Fix `group` (that is the shell) to properly handle when an `get_until` callback function returned `{done, eof, []}` when an `eof` was detected.\n\n Own Id: OTP-18901","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 9.2 - Kernel Release Notes","ref":"notes.html#kernel-9-2"},{"type":"extras","doc":"- For `inet_backend = socket`, an unexpected receive error such as `etimedout`\n caused the receiving state machine server to crash. This bug has now been\n fixed.\n\n Own Id: OTP-18749 Aux Id: GH-7608\n\n- Fix bug where reading using `file` from a unicode enabled `standard_io`,\n `standard_error` or any other `group` backed device would result in incorrect\n values being returned or a crash.\n\n Now instead a no_translation error is returned to the caller when unicode data\n is read using `file`. See\n [Using Unicode](`e:stdlib:unicode_usage.md#escripts-and-non-interactive-i-o`)\n in the STDLIB User's Guide for more details on how to correctly read from\n `standard_io`.\n\n Own Id: OTP-18800 Aux Id: PR-7714 GH-7591\n\n- The native resolver interface module has gotten a rewrite of its ETS table\n handling to minimize term copying, and also to move the handling of client\n time-outs to the clients, which helps the native resolver name server from\n digging itself into a tar pit when heavily loaded.\n\n Own Id: OTP-18812 Aux Id: ERIERL-997\n\n- Replaced unintentional Erlang Public License 1.1 headers in some files with\n the intended Apache License 2.0 header.\n\n Own Id: OTP-18815 Aux Id: PR-7780\n\n- Fix bug in `pg` if a client process both monitored a group/scope and joined a\n group. The termination of such process resulted in crash of the `pg` server\n process.\n\n Own Id: OTP-18833 Aux Id: GH-7625, PR-7659\n\n- Fix crash when using `file:consult` and the underlying file read returns an\n error while reading.\n\n Own Id: OTP-18873 Aux Id: PR-7831\n\n- Corrected gen_tcp_socket listen option handling.\n\n Own Id: OTP-18883 Aux Id: #7764","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add Windows support for DGRAM socket connect.\n\n Own Id: OTP-18762\n\n- Document the, previously opaque, types select_tag() and completion_tag().\n\n Own Id: OTP-18818 Aux Id: #7337","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 9.1 - Kernel Release Notes","ref":"notes.html#kernel-9-1"},{"type":"extras","doc":"- Fixed an issue with truncated crash slogans on failed emulator start.\n\n Own Id: OTP-18623 Aux Id: GH-7344\n\n- Fix shell:start_interactive function specification.\n\n Own Id: OTP-18628 Aux Id: GH-7280\n\n- Fix code:get_doc/1 to return missing, when it can't find erts instead of\n crashing.\n\n Own Id: OTP-18654 Aux Id: PR-7404\n\n- Function socket:close/1 could cause a VM crash on Windows.\n\n Own Id: OTP-18669 Aux Id: OTP-18029\n\n- Fix deadlock when `erl.exe` is used as part of a pipe on Windows and trying to\n set the encoding of the `standard_io` device.\n\n Own Id: OTP-18675 Aux Id: PR-7473 GH-7459\n\n- Expanded the documentation about how to use the `standard_io`,\n `standard_error` and `user` I/O devices.\n\n Added the types [`io:standard_io/0`](`t:io:standard_io/0`),\n `io:standard:error/0` and [`io:user/0`](`t:io:user/0`).\n\n Own Id: OTP-18676 Aux Id: PR-7473 GH-7459\n\n- Fix logger's overload protection mechanism to only fetch memory used by\n messages when needed.\n\n Own Id: OTP-18677 Aux Id: PR-7418 GH-7417\n\n- Fixed a number of socket-related issues causing incompatibilities with gen_tcp\n and gen_udp respectively.\n\n Own Id: OTP-18685\n\n- gen_tcp:connect with socket address and socket (inet-) backend fails because\n of missing callback function.\n\n Own Id: OTP-18707 Aux Id: #7530\n\n- The DNS RR cache used by \\`inet_res\\` has been fixed to preserve insert order,\n which is beneficial when the DNS server returns RRs in some specific order for\n e.g load balancing purposes.\n\n Own Id: OTP-18731 Aux Id: GH-7577, PR-7578\n\n- The options \\`reuseport\\`, \\`reuseport_lb\\` and \\`exclusiveaddruse\\` were\n accidentally not allowed for e.g \\`gen_udp:open/1,2\\`, which has now been\n corrected.\n\n Own Id: OTP-18734 Aux Id: OTP-18344, PR-6522, GH-6461, GH-7569\n\n- `gen_udp:recv/*` for Unix Domain Socket in binary mode and passive mode has\n been fixed to not crash.\n\n Own Id: OTP-18747 Aux Id: GH-7605\n\n- Fixed issue where cursor would not be placed at the end of the expression when\n navigating shell history.\n\n Own Id: OTP-18757 Aux Id: PR-7631","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Update gen_tcp_socket and gen_udp_socket to handle 'completion' (socket on\n Windows).\n\n Own Id: OTP-18586 Aux Id: OTP-18029\n\n- Add support for Unix Domain Sockets (only for STREAM sockets) on Windows for\n 'socket'.\n\n Own Id: OTP-18611 Aux Id: OTP-18029, #5024\n\n- Add basic support for socket ioctl on Windows.\n\n Own Id: OTP-18660\n\n- The [`file:location/0`](`t:file:location/0`) type is now exported.\n\n Own Id: OTP-18681\n\n- Add support for (Windows) socket option exclusiveaddruse.\n\n Own Id: OTP-18686\n\n- \\[socket] Add support for the 'nopush' option.\n\n Own Id: OTP-18687\n\n- Add support for socket option 'BSP STATE'.\n\n Own Id: OTP-18693\n\n- Add tcp socket options 'keepcnt', 'keepidle' and 'keepintvl'.\n\n Own Id: OTP-18698\n\n- Add support for misc (Windows) socket options ('max_msg_size' and 'maxdg').\n\n Own Id: OTP-18710\n\n- The keyboard shortcuts for the shell are now configurable.\n\n Own Id: OTP-18754 Aux Id: PR-7604 PR-7647\n\n- Optimized code_server to reduce repeated work when loading the same module\n concurrently.\n\n Own Id: OTP-18755 Aux Id: PR-7503","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 9.0.2 - Kernel Release Notes","ref":"notes.html#kernel-9-0-2"},{"type":"extras","doc":"- Fix bug where when you entered Alt+Enter in the terminal, the cursor would\n move to the last line, instead of moving to the next line.\n\n Own Id: OTP-18580 Aux Id: PR-7242\n\n- Fix so that the shell does not crash on startup when termcap is not available.\n\n Own Id: OTP-18624 Aux Id: GH-7296\n\n- Multiple socket:accept calls issue. When making multiple accept calls, only\n the last call is active.\n\n Own Id: OTP-18635 Aux Id: #7328\n\n- Fix the shell to ignore terminal delay when the terminal capabilities report\n that they should be used.\n\n Own Id: OTP-18636 Aux Id: PR-7352 GH-7308\n\n- Fix \"oldshell\" to echo characters while typing on Windows.\n\n Own Id: OTP-18637 Aux Id: PR-7359 GH-7324\n\n- Fix eof handling when reading from stdin when erlang is started using\n `-noshell`.\n\n Own Id: OTP-18640 Aux Id: PR-7384 GH-7368 GH-7286 GH-6881\n\n- On Windows, a call to the function socket:close, when there are waiting active\n calls to read, write or accept functions, could hang.\n\n Own Id: OTP-18646\n\n- Fix issues when reading or configuring `standard_io` on Windows when erl.exe\n is started using `-noshell` flag.\n\n Own Id: OTP-18649 Aux Id: GH-7261 PR-7400\n\n- gen_udp:connect with inet_backend = socket fails when the Address is a\n hostname (string or atom).\n\n Own Id: OTP-18650\n\n- Fixed problem which would cause shell to crash if particular escape sequence\n was written to stdout.\n\n Own Id: OTP-18651 Aux Id: PR-7242\n\n- Fixed problem where output would disappear if it was received after a prompt\n was written in the shell.\n\n Own Id: OTP-18652 Aux Id: PR-7242\n\n- Fix a crash where the location of erts could not be found in rebar3 dev\n builds.\n\n Own Id: OTP-18656 Aux Id: PR-7404 GH-7390\n\n- Introduce the KERNEL application parameter `standard_io_encoding` that can be\n used to set the default encoding for standard_io. This option needs to be set\n to `latin1` if the application wants to treat all input data as bytes rather\n than utf-8 encoded characters.\n\n Own Id: OTP-18657 Aux Id: GH-7230 PR-7384","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 9.0.1 - Kernel Release Notes","ref":"notes.html#kernel-9-0-1"},{"type":"extras","doc":"- The POSIX error `exdev` was sometimes incorrectly described as \"cross domain\n link\" in some error messages.\n\n Own Id: OTP-18578 Aux Id: GH-7213\n\n- Corrected the socket send function description (send with Timeout = nowait).\n The send function(s) could not return \\{ok, \\{RestData, SelectInfo\\}\\}\n\n Own Id: OTP-18584 Aux Id: #7238","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 9.0 - Kernel Release Notes","ref":"notes.html#kernel-9-0"},{"type":"extras","doc":"- Fixed a bug where duplicate keys were allowed in the .app file of an\n application. Duplicate keys are now rejected and the application will not\n start if they exist.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18210 Aux Id: GH-5877 PR-5878\n\n- Fix inconsistent handling in logger_formatter of the branched values in\n conditional branches. For example using `msg` in a conditional branch would\n not be formatted as it should before this fix.\n\n Own Id: OTP-18225 Aux Id: PR-6036\n\n- Fix the logger_std_h handler to log to standard_error if logging to\n standard_io fails for any reason.\n\n Own Id: OTP-18226 Aux Id: PR-6253\n\n- Fix the TLS distribution to work when starting Erlang in embedded mode and a\n connection is done before kernel is fully started.\n\n Own Id: OTP-18248 Aux Id: PR-6227 GH-6085\n\n- erl `-remsh` has been improved to provide better error reasons and work when\n using a shell without terminal support (that is an \"oldshell\").\n\n Own Id: OTP-18271 Aux Id: PR-6279\n\n- Fix logging of log events generated before kernel is started to not fail if\n the code for formatting those log messaged have not yet been loaded.\n\n Own Id: OTP-18286 Aux Id: PR-5955\n\n- `proc_lib:start*/*` has become synchronous when the started process fails.\n This requires that a failing process use a new function\n `proc_lib:init_fail/2,3`, or exits, to indicate failure. All OTP behaviours\n have been fixed to do this.\n\n All these start functions now consume the `'EXIT'` message from a process link\n for all error returns. Previously it was only the `start_link/*` functions\n that did this, and only when the started function exited, not when it used\n `init_ack/1,2` or `init_fail/2,3` to create the return value.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18471 Aux Id: GH-6339, PR-6843\n\n- Fixed a bug where `file:read(standard_io, ...)` unexpectedly returned `eof` in\n binary mode.\n\n Own Id: OTP-18486 Aux Id: PR-6881\n\n- Return type for `seq_trace:get_token/1` fixed.\n\n Own Id: OTP-18528 Aux Id: PR-7009\n\n- Looking up, connecting to and sending to a host with an empty name is now\n handled by trying to look up the address of the root domain, which fails.\n Previously some of these operations caused an internal exception, which\n contradicted type specifications.\n\n Own Id: OTP-18543 Aux Id: GH-6353\n\n- Replaced a regex with a special case handling of ANSI Select Graphic Rendition\n escape characters, to speed up io output that make use of these escape\n sequences.\n\n Own Id: OTP-18547 Aux Id: PR-7092","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The Erlang shell has been improved to support the following features:\n\n - Auto-complete variables, record names, record field names, map keys,\n function parameter types and filenames.\n - Open external editor in the shell (with C-o) to edit the current expression\n in an editor.\n - Support defining records (with types), functions and function typespecs, and\n custom types in the shell.\n - Do not save pager commands, and input to io:getline in history.\n\n Own Id: OTP-14835 Aux Id: PR-5924\n\n- The TTY/terminal subsystem has been rewritten by moving more code to Erlang\n from the old linked-in driver and implementing all the I/O primitives needed\n in a NIF instead.\n\n On Unix platforms the user should not notice a lot of difference, besides\n better handling of unicode characters and fixing of some long standing bugs.\n\n Windows users will notice that erl.exe has the same functionality as a normal\n Unix shell and that werl.exe has been removed and replaced with a symlink to\n erl.exe. This makes the Windows Erlang terminal experience identical to that\n of Unix.\n\n The re-write brings with it a number of bug fixes and feature additions:\n\n - The TTY is now reset when Erlang exits, fixing zsh to not break when\n terminating an Erlang session.\n - `standard_error` now uses the same unicode mode as `standard_io`.\n - Hitting backspace when searching the shell history with an empty search\n string no longer breaks the shell.\n - Tab expansion now works on remote nodes started using the JCL interface.\n - It is now possible to configure the shell slogan and the session slogans\n (that is the texts that appear when you start an Erlang shell). See the\n kernel documentation for more details.\n - Added shell:start_interactive for starting the interactive shell from a\n non-interactive Erlang session (for example an escript).\n - On Windows, when starting in detached mode the standard handler are now set\n to `nul` devices instead of being unset.\n - Standard I/O now always defaults to `unicode` mode if supported. Previously\n the default was `latin1` if the runtime system had been started with\n `-oldshell` or `-noshell` (for example in an `escript`). To send raw bytes\n over standard out, one now explicitly has to specify\n `io:setopts(standard_io, [{encoding, latin1}]).`\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17932 Aux Id: PR-6144 GH-3150 GH-3390 GH-4343 GH-4225\n\n- Add support for socket on Windows.\n\n - Pre release status.\n - Error codes not finalized.\n - No explicit support for Windows specific options (socket options, flags for\n read and write).\n - New async api for Windows (completion). See the `Asynchronous calls` chapter\n in the (Socket Usage) Users Guide.\n - To ensure platform independence, gen_tcp and gen_udp is _intended_ to be\n used (not yet updated).\n\n Own Id: OTP-18029\n\n- As announced since the release of OTP 24, support for:\n\n - version 4 node container types in the external term format are now\n mandatory. That is, references supporting up to 5 32-bit integer\n identifiers, and process and port identifiers with support for 64-bit data\n storage. The distribution flag\n [`DFLAG_V4_NC`](`e:erts:erl_dist_protocol.md#DFLAG_V4_NC`) is therefor now\n also mandatory. OTP has since OTP 24 supported this. Also note that the\n external format produced by `term_to_binary()` and `term_to_iovec()` will\n unconditionally produce pids, ports, and references supporting this larger\n format.\n - the [new link protocol](`e:erts:erl_dist_protocol.md#new_link_protocol`)\n introduced in OTP 23.3 is now mandatory. The distribution flag\n [`DFLAG_UNLINK_ID`](`e:erts:erl_dist_protocol.md#DFLAG_UNLINK_ID`) is\n therefor now also mandatory.\n\n Due to the above, OTP 26 nodes will refuse to connect to OTP nodes from\n releases prior to OTP 24.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18140 Aux Id: PR-6072\n\n- Support for Kernel TLS (kTLS), has been added to the SSL application, for TLS\n distribution (`-proto_dist inet_tls`), the SSL option `{ktls, true}`. Using\n this for general SSL sockets is uncomfortable, undocumented and not\n recommended since it requires very platform dependent raw options.\n\n This, for now, only works for some not too old Linux distributions. Roughly, a\n kernel 5.2.0 or later with support for UserLand Protocols and the kernel\n module `tls` is required.\n\n Own Id: OTP-18235 Aux Id: PR-6104, PR-5840\n\n- Add code:get_doc/2 which adds support to fetch documentation skeletons of\n functions using debug_info chunks instead of eep48 doc chunks.\n\n Own Id: OTP-18261 Aux Id: PR-5924\n\n- The Erlang shell's auto-completion when typing `tab` has been changed to\n happen after the editing current line instead of before it.\n\n This behaviour can be configured using a the `shell_expand_location` STDLIB\n configuration parameter.\n\n Own Id: OTP-18278 Aux Id: PR-6260\n\n- Typing `Ctrl+L` in a shell now clears the screen and redraws the current line\n instead of only redrawing the current line. To only redraw the current line,\n you must now type `Alt+L`. This brings the behaviour of `Ctrl+L` closer to how\n bash and other shells work.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18285 Aux Id: PR-6262\n\n- gen_server optimized by caching callback functions\n\n Own Id: OTP-18305 Aux Id: PR-5831\n\n- Prepare the `pg` communication protocol for upgrade. The plan is for OTP-28\n nodes to be able to use an upgraded `pg` protocol while still being able to\n talk with OTP 26 nodes.\n\n Own Id: OTP-18327 Aux Id: PR-6433\n\n- New `disk_log` log type `rotate`, where the log files are compressed upon\n rotation.\n\n Own Id: OTP-18331 Aux Id: ERIERL-870\n\n- The following `inet:setopts/2` options have been introduced:\n\n - **[`reuseport`](`m:inet#option-reuseport`)** - Reuse of local port. Load\n balancing may or may not be provided depending on underlying OS.\n\n - **[`reuseport_lb`](`m:inet#option-reuseport_lb`)** - Reuse of local port.\n Load balancing provided.\n\n - **[`exclusiveaddruse`](`m:inet#option-exclusiveaddruse`)** - Exclusive\n address/port usage on Windows. This socket option is Windows specific and\n will silently be ignored on other systems.\n\n The behavior of setting [`reuseaddr`](`m:inet#option-reuseaddr`) on Windows\n have changed in a _backwards incompatible_ way. The underlying `SO_REUSEADDR`\n socket option is now only set if both the `reusaddr` and the `reuseport`\n `inet` options have been set. This since the underlying `SO_REUSEADDR` socket\n option on Windows behaves similar to how BSD behaves if both the underlying\n socket options `SO_REUSEADDR` and `SO_REUSEPORT` have been set. See the\n documentation of the `reuseaddr` option for more information.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18344 Aux Id: PR-6522, PR-6944, OTP-18324, PR-6481, GH-6461\n\n- Replace size/1 with either tuple_size/1 or byte_size/1\n\n The [`size/1`](`size/1`) BIF is not optimized by the JIT, and its use can\n result in worse types for Dialyzer.\n\n When one knows that the value being tested must be a tuple,\n [`tuple_size/1`](`tuple_size/1`) should always be preferred.\n\n When one knows that the value being tested must be a binary,\n [`byte_size/1`](`byte_size/1`) should be preferred. However,\n [`byte_size/1`](`byte_size/1`) also accepts a bitstring (rounding up size to a\n whole number of bytes), so one must make sure that the call to `byte_size/` is\n preceded by a call to [`is_binary/1`](`is_binary/1`) to ensure that bitstrings\n are rejected. Note that the compiler removes redundant calls to\n [`is_binary/1`](`is_binary/1`), so if one is not sure whether previous code\n had made sure that the argument is a binary, it does not harm to add an\n [`is_binary/1`](`is_binary/1`) test immediately before the call to\n [`byte_size/1`](`byte_size/1`).\n\n Own Id: OTP-18405 Aux Id:\n GH-6672,PR-6702,PR-6768,PR-6700,PR-6769,PR-6812,PR-6814\n\n- The function `file:pid2name/1` is deprecated and will be removed in\n Erlang/OTP 27.\n\n Own Id: OTP-18419\n\n- The modules Erlang DNS resolver `inet_res` and helper modules have been\n updated for RFC6891; to handle OPT RR with DNSSEC OK (DO) bit.\n\n Own Id: OTP-18442 Aux Id: PR-6786, GH-6606\n\n- Introduced `application:get_supervisor/1`.\n\n Own Id: OTP-18444 Aux Id: PR-6035\n\n- Handling of `on_load` modules during boot has been improved by adding an extra\n step in the boot order for embedded mode that runs all `on_load` handlers,\n instead of relying on explicit invocation of them, later, when the kernel\n supervision tree starts.\n\n This is mostly a code improvement and OTP internal simplification to avoid\n future bugs and to simplify code maintenance.\n\n Own Id: OTP-18447\n\n- Reduce contention on the code_server by doing the code preparation on the\n client.\n\n Own Id: OTP-18448 Aux Id: PR-6736\n\n- Added a mode to ensure_all_loaded, to start children application and their\n dependencies concurrently.\n\n Own Id: OTP-18451 Aux Id: PR-6737\n\n- Cache OTP boot code paths, to limit how many folders that are being accessed\n during a module lookup. Can be disabled with -cache_boot_path false. OTP boot\n code paths consists of ERL_LIB environment variables. The various otp/\\*/ebin\n folders. And the \\{path, ...\\} clauses in the init script.\n\n Own Id: OTP-18452 Aux Id: PR-6729\n\n- Erlang distribution code in Kernel and SSL has been refactored a bit to\n facilitate debugging and re-usability, which shouldn't have any noticeable\n effects on behaviour or performance.\n\n Own Id: OTP-18456\n\n- Add cache attribute to code path apis.\n\n Added an optional cache/nocache argument to all code:add_path*,\n code:set_path*, and code:replace_path\\* functions. These functions will then\n avoid doing file-accesses if they are cached. Cache can be cleared with\n code:clear_cache/0. Added code:del_paths/1 to make it easier to clear multiple\n paths.\n\n Own Id: OTP-18466 Aux Id: PR-6832\n\n- Deprecates `dbg:stop_clear/0` because it is simply a function alias to\n `dbg:stop/0`\n\n Own Id: OTP-18478 Aux Id: GH-6903\n\n- Improvements to code:ensure_modules_loaded/1: Previously it would prepare\n modules and then abandon references to said modules if they had on_load\n callbacks. This pull request makes it so they keep the references around and\n then serially load them without having to fetch the object code and prepare\n them again.\n\n Own Id: OTP-18484 Aux Id: PR-6844\n\n- The internal DNS resolver has been updated to handle DNS LOC RR:s (RFC 1876).\n This is an undocumented module, although still used by power users. See the\n source code.\n\n Own Id: OTP-18510 Aux Id: GH-6098, PR-6982\n\n- Reduced memory consumption in `global` when informing other nodes about lost\n connections.\n\n Own Id: OTP-18521 Aux Id: PR-7025\n\n- The `net_kernel`, `global`, and `global_group` servers now have\n [_fully asynchronous distributed signaling_](`m:erlang#process_flag_async_dist`)\n enabled all the time which prevents them from ever getting blocked on send of\n distributed signals.\n\n Documentation about blocking distributed signals has also been improved.\n\n Own Id: OTP-18533 Aux Id: PR-7061\n\n- Allow IPv6 addresses as host in `http` packets decoded by\n `erlang:decode_packet/3` and `gen_tcp` packet option. The IPv6 address should\n be enclosed within `[]` according to RFC2732.\n\n Own Id: OTP-18540 Aux Id: PR-6900\n\n- Remove deprecated functions in OTP-26\n\n Own Id: OTP-18542\n\n- Removed `code:is_module_native/1` since HiPE has been removed. It has since\n OTP 24 been deprecated and scheduled for removal in OTP 26.\n\n Removed `code:rehash/0` since the code path feature no longer is present. It\n has since OTP 19 been deprecated and has since OTP 24 been scheduled for\n removal in OTP 26.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18551 Aux Id: PR-7106\n\n- Added support for multiple line expressions and navigation in the shell. Added\n new keybindings:\n\n - navigate up (ctrl+up)/(alt+up)\n - navigate down (ctrl+down)/(alt+down)\n - insert newline in middle of line (alt+enter)\n - navigate top (alt+<)/(alt+shift+up)\n - navigate bottom (alt+>)/(alt+shift+down)\n - clear current expression (alt+c)\n - cancel search (alt+c)\n - opening editor on mac (option+o)/(alt+o)\n\n Modifies the prompt for new lines to make it clearer that the prompt has\n entered multi-line mode. Supports terminal with small window size, recommend\n not go lower than 7 rows and 40 columns. Modifies the search prompt to support\n multi-line statements. Redraw the prompt after continuing from JCL menu.\n\n Own Id: OTP-18575 Aux Id: PR-7169","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 8.5.4.3 - Kernel Release Notes","ref":"notes.html#kernel-8-5-4-3"},{"type":"extras","doc":"* Fixed gen_udp:open/2 type spec to include already supported module socket address types.\n\n Own Id: OTP-19050 Aux Id: OTP-18990","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 8.5.4.2 - Kernel Release Notes","ref":"notes.html#kernel-8-5-4-2"},{"type":"extras","doc":"- gen_tcp:connect with socket address and socket (inet-) backend fails because\n of missing callback function.\n\n Own Id: OTP-18707 Aux Id: #7530","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 8.5.4.1 - Kernel Release Notes","ref":"notes.html#kernel-8-5-4-1"},{"type":"extras","doc":"- Multiple socket:accept calls issue. When making multiple accept calls, only\n the last call is active.\n\n Own Id: OTP-18635 Aux Id: #7328\n\n- gen_udp:connect with inet_backend = socket fails when the Address is a\n hostname (string or atom).\n\n Own Id: OTP-18650","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 8.5.4 - Kernel Release Notes","ref":"notes.html#kernel-8-5-4"},{"type":"extras","doc":"- Fixed a bug on Windows where `file:read_file_info/1` would fail for files with\n corrupt metadata.\n\n Own Id: OTP-18348 Aux Id: GH-6356\n\n- Accept connection setup from OTP 23 and 24 nodes that are not using epmd.\n\n Own Id: OTP-18404 Aux Id: GH-6595, PR-6625","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 8.5.3 - Kernel Release Notes","ref":"notes.html#kernel-8-5-3"},{"type":"extras","doc":"- The tcp connect option 'bind_to_device' could not be used with inet_backend =\n 'socket'. 'inet' requires value type binarry() and 'socket' requires value\n type 'string()'.\n\n Own Id: OTP-18357 Aux Id: #6509\n\n- Minor issue processing options when calling gen_tcp:connect with a sockaddr()\n and inet_backend = socket.\n\n Own Id: OTP-18358 Aux Id: #6528","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 8.5.2 - Kernel Release Notes","ref":"notes.html#kernel-8-5-2"},{"type":"extras","doc":"- Fixed shutdown crash in gen_tcp socket backend, when the other end closed the\n socket.\n\n Own Id: OTP-18270 Aux Id: #6331\n\n- `erl_tar` can now read gzip-compressed tar files that are padded. There is a\n new option `compressed_one` for `file:open/2` that will read a single member\n from a gzip file,\n\n Own Id: OTP-18289 Aux Id: PR-6343\n\n- Fix `os:cmd` to not translate all exceptions thrown to `badarg`. For example\n `emfile` from `erlang:open_port` was translated to `badarg`.\n\n This bug has existed since Erlang/OTP 24.\n\n Own Id: OTP-18291 Aux Id: PR-6382\n\n- Spec for function net:if_names/0 incorrect\n\n Own Id: OTP-18296 Aux Id: OTP-16464\n\n- Missing ctrl option name transation for TOS and TTL (on FreeBSD) when using\n gen_udp with the 'socket' inet_backend.\n\n Own Id: OTP-18315\n\n- gen_udp:open/2 with option(s) add_membership or drop_membership would drop\n earlier options.\n\n Own Id: OTP-18323 Aux Id: #6476\n\n- The `inet:setopts/2` `{reuseaddr, true}` option will now be ignored on Windows\n unless the socket is an UDP socket. For more information see the documentation\n of the `reuseaddr` option part of the documentation of `inet:setopts/2`.\n\n Prior to OTP 25 the `{reuseaddr, true}` option was ignored for all sockets on\n Windows, but as of OTP 25.0 this was changed so that it was not ignored for\n any sockets.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18324 Aux Id: GH-6461, PR-6481","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The distribution socket option handling in `inet_tcp_dist` has been cleaned up\n to clarify which were mandatory and which just had default values.\n\n Own Id: OTP-18293\n\n- Improve warning message format for gen_tcp_socket.\n\n Own Id: OTP-18317","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 8.5.1 - Kernel Release Notes","ref":"notes.html#kernel-8-5-1"},{"type":"extras","doc":"- Listen sockets created with the socket module, leaked (erlang-) monitors.\n\n Own Id: OTP-18240 Aux Id: #6285\n\n- `m:peer` nodes failed to halt when the process supervising the control\n connection crashed. When an alternative control connection was used, this\n supervision process also quite frequently crashed when the `peer` node was\n stopped by the node that started it which caused the `peer` node to linger\n without ever halting.\n\n Own Id: OTP-18249 Aux Id: PR-6301","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 8.5 - Kernel Release Notes","ref":"notes.html#kernel-8-5"},{"type":"extras","doc":"- Fixed inconsistency bugs in `m:global` due to `nodeup`/`nodedown` messages not\n being delivered before/after traffic over connections. Also fixed various\n other inconsistency bugs and deadlocks in both `m:global_group` and `global`.\n\n As building blocks for these fixes, a new BIF `erlang:nodes/2` has been\n introduced and `net_kernel:monitor_nodes/2` has been extended.\n\n The [`-hidden`](`e:erts:erl_cmd.md#hidden`) and\n [`-connect_all`](`e:erts:erl_cmd.md#connect_all`) command line arguments did\n not work if multiple instances were present on the command line which has been\n fixed. The new kernel parameter [`connect_all`](kernel_app.md#connect_all) has\n also been introduced in order to replace the `-connect_all` command line\n argument.\n\n Own Id: OTP-17934 Aux Id: PR-6007\n\n- Fixed IPv6 multicast_if and membership socket options.\n\n Own Id: OTP-18091 Aux Id: #5789\n\n- Fixed issue with inet:getifaddrs hanging on pure IPv6 Windows\n\n Own Id: OTP-18102 Aux Id: #5904\n\n- The type specifications for `inet:getopts/2` and `inet:setopts/2` have been\n corrected regarding SCTP options.\n\n Own Id: OTP-18115 Aux Id: PR-5939\n\n- The type specifications for `inet:parse_*` have been tightened.\n\n Own Id: OTP-18121 Aux Id: PR-5972\n\n- Fix gen_tcp:connect/3 spec to include the inet_backend option.\n\n Own Id: OTP-18171 Aux Id: PR-6131\n\n- Fix bug where using a binary as the format when calling\n `logger:log(Level, Format, Args)` (or any other logging function) would cause\n a crash or incorrect logging.\n\n Own Id: OTP-18229 Aux Id: PR-6212","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add rudimentary debug feature (option) for the inet-driver based sockets, such\n as gen_tcp and gen_udp.\n\n Own Id: OTP-18032\n\n- Introduced the `hidden` and `dist_listen` options to `net_kernel:start/2`.\n\n Also documented the [`-dist_listen`](`e:erts:erl_cmd.md#dist_listen`) command\n line argument which was erroneously documented as a `kernel` parameter and not\n as a command line argument.\n\n Own Id: OTP-18107 Aux Id: PR-6009\n\n- Scope and group monitoring have been introduced in `m:pg`. For more\n information see the documentation of\n [`pg:monitor_scope()`](`pg:monitor_scope/0`),\n [`pg:monitor()`](`pg:monitor/1`), and [`pg:demonitor()`](`pg:demonitor/1`).\n\n Own Id: OTP-18163 Aux Id: PR-6058, PR-6275\n\n- A new function `global:disconnect/0` has been introduced with which one can\n cleanly disconnect a node from all other nodes in a cluster of `global` nodes.\n\n Own Id: OTP-18232 Aux Id: OTP-17843, PR-6264","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 8.4.2 - Kernel Release Notes","ref":"notes.html#kernel-8-4-2"},{"type":"extras","doc":"- A call to [`net_kernel:setopts(new, Opts)`](`net_kernel:setopts/2`) at the\n same time as a connection was being set up could cause a deadlock between the\n `net_kernel` process and the process setting up the connection.\n\n Own Id: OTP-18198 Aux Id: GH-6129, PR-6216","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 8.4.1 - Kernel Release Notes","ref":"notes.html#kernel-8-4-1"},{"type":"extras","doc":"- The DNS resolver `inet_res` has been fixed to ignore trailing dot difference\n in the request domain between the sent request and the received response, when\n validating a response.\n\n Own Id: OTP-18112 Aux Id: ERIERL-811\n\n- A bug in `inet_res` has been fixed where a missing internal `{ok,_}` wrapper\n caused `inet_res:resolve/*` to return a calculated host name instead of an\n `{ok,Msg}` tuple, when resolving an IP address or a host name that is an IP\n address string.\n\n Own Id: OTP-18122 Aux Id: GH-6015, PR-6020\n\n- The `erlang:is_alive()` BIF could return `true` before configured distribution\n service was available. This bug was introduced in OTP 25.0 ERTS version 13.0.\n\n The `erlang:monitor_node()` and `erlang:monitor()` BIFs could erroneously fail\n even though configured distribution service was available. This occurred if\n these BIFs were called after the distribution had been started using dynamic\n node name assignment but before the name had been assigned.\n\n Own Id: OTP-18124 Aux Id: OTP-17558, PR-6032\n\n- Added the missing mandatory `address/0` callback in the `gen_tcp_dist`\n example.\n\n Own Id: OTP-18136","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 8.4 - Kernel Release Notes","ref":"notes.html#kernel-8-4"},{"type":"extras","doc":"- The DNS resolver implementation has been rewritten to validate replies more\n thoroughly, and a bit optimized to create less garbage.\n\n Own Id: OTP-17323\n\n- The socket option 'reuseaddr' is _no longer_ ignored on Windows.\n\n Own Id: OTP-17447 Aux Id: GH-4819\n\n- Fix bug where using the atoms `string` or `report` as the format when calling\n `logger:log(Level, Format, Args)` (or any other logging function) would cause\n a crash or incorrect logging.\n\n Own Id: OTP-17551 Aux Id: GH-5071 PR-5075\n\n- As of OTP 25, `global` will by default prevent overlapping partitions due to\n network issues by actively disconnecting from nodes that reports that they\n have lost connections to other nodes. This will cause fully connected\n partitions to form instead of leaving the network in a state with overlapping\n partitions.\n\n Prevention of overlapping partitions can be disabled using the\n [`prevent_overlapping_partitions`](kernel_app.md#prevent_overlapping_partitions)\n `kernel(6)` parameter, making `global` behave like it used to do. This is,\n however, problematic for all applications expecting a fully connected network\n to be provided, such as for example `mnesia`, but also for `global` itself. A\n network of overlapping partitions might cause the internal state of `global`\n to become inconsistent. Such an inconsistency can remain even after such\n partitions have been brought together to form a fully connected network again.\n The effect on other applications that expects that a fully connected network\n is maintained may vary, but they might misbehave in very subtle hard to detect\n ways during such a partitioning. Since you might get hard to detect issues\n without this fix, you are _strongly_ advised _not_ to disable this fix. Also\n note that this fix _has_ to be enabled on _all_ nodes in the network in order\n to work properly.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17911 Aux Id: PR-5687, PR-5611, OTP-17843\n\n- Starting the helper program for name resolving; `inet_gethost`, has been\n improved to use an absolute file system path to ensure that the right program\n is started.\n\n If the helper program can not be started - the system now halts, to avoid\n running with a silently broken name resolver.\n\n Own Id: OTP-17958 Aux Id: OTP-17978\n\n- The type specification for `inet_res:getbyname/2,3` has been corrected to\n reflect that it can return peculiar `#hostent{}` records.\n\n Own Id: OTP-17986 Aux Id: PR-5412, PR-5803\n\n- `code:module_status/1` would always report BEAM files loaded from an archive\n as `modified`, and `code:modified_modules/0` would always return the name of\n all modules loaded from archives.\n\n Own Id: OTP-17990 Aux Id: GH-5801\n\n- In logger fix file handler shutdown delay by using erlang timers instead of\n the timer module's timers.\n\n Own Id: OTP-18001 Aux Id: GH-5780 PR-5829\n\n- Fix the meta data in log events generated by logger on failure to not contain\n the original log event's meta data.\n\n Own Id: OTP-18003 Aux Id: PR-5771\n\n- Fix logger file backend to re-create the log folder if it has been deleted.\n\n Own Id: OTP-18015 Aux Id: GH-5828 PR-5845\n\n- \\[socket] Encode of sockaddr has been improved.\n\n Own Id: OTP-18020\n\n- Fix `put_chars` requests to the io server with incomplete unicode data to exit\n with `no_translation` error.\n\n Own Id: OTP-18070 Aux Id: PR-5885","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The net module now works on Windows.\n\n Own Id: OTP-16464\n\n- An Erlang installation directory is now relocatable on the file system given\n that the paths in the installation's `RELEASES` file are paths that are\n relative to the installations root directory. The\n `` `release_handler:create_RELEASES/4 `` function can generate a `RELEASES`\n file with relative paths if its `RootDir` parameter is set to the empty\n string.\n\n Own Id: OTP-17304\n\n- The following distribution flags are now mandatory: `DFLAG_BIT_BINARIES`,\n `DFLAG_EXPORT_PTR_TAG`, `DFLAG_MAP_TAGS`, `DFLAG_NEW_FLOATS`, and\n `DFLAG_FUN_TAGS`. This mainly concerns libraries or application that implement\n the distribution protocol themselves.\n\n Own Id: OTP-17318 Aux Id: PR-4972\n\n- Fix `os:cmd` to work on Android OS.\n\n Own Id: OTP-17479 Aux Id: PR-4917\n\n- The configuration files [`.erlang`](`e:erts:erl_cmd.md`),\n [`.erlang.cookie`](`e:system:distributed.md`) and\n [`.erlang.crypt`](`m:beam_lib#module-erlang-crypt`) can now be located in the XDG\n Config Home directory.\n\n See the documentation for each file and `filename:basedir/2` for more details.\n\n Own Id: OTP-17554 Aux Id: GH-5016 PR-5408 OTP-17821\n\n- Dynamic node name improvements: `erlang:is_alive/0` changed to return true for\n pending dynamic node name and new function `net_kernel:get_state/0`.\n\n Own Id: OTP-17558 Aux Id: OTP-17538, PR-5111, GH-5402\n\n- The types for callback result types in `gen_statem` has bee augmented with\n arity 2 types where it is possible for a callback module to specify the type\n of the callback data, so the callback module can get type validation of it.\n\n Own Id: OTP-17589 Aux Id: PR-4926\n\n- The tagged tuple tests and fun-calls have been optimized and are now a little\n bit cheaper than previously.\n\n These optimizations become possible after making sure that all boxed terms\n have at least one word allocated after the arity word. This has been\n accomplished by letting all empty tuples refer to the same empty tuple literal\n which also reduces memory usage for empty tuples.\n\n Own Id: OTP-17608\n\n- A [`net_ticker_spawn_options`](kernel_app.md#net_ticker_spawn_options)\n `kernel` configuration parameter with which one can set spawn options for the\n distribution channel ticker processes has been introduced.\n\n Own Id: OTP-17617 Aux Id: PR-5069\n\n- The most, or at least the most used, `m:rpc` operations now require `m:erpc`\n support in order to communicate with other Erlang nodes. `erpc` was introduced\n in OTP 23. That is, `rpc` operations against Erlang nodes of releases prior to\n OTP 23 will fail.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17681 Aux Id: PR-5307\n\n- The new module `peer` supersedes the `slave` module. The `slave` module is now\n deprecated and will be removed in OTP 27.\n\n `peer` contains an extended and more robust API for starting erlang nodes.\n\n Own Id: OTP-17720 Aux Id: PR-5162\n\n- In order to make it easier for the user to manage multiple outstanding\n asynchronous `call` requests, new functionality utilizing request identifier\n collections have been introduced in\n [`erpc`](`t:erpc:request_id_collection/0`),\n [`gen_server`](`t:gen_server:request_id_collection/0`),\n [`gen_statem`](`t:gen_statem:request_id_collection/0`), and\n [`gen_event`](`t:gen_event:request_id_collection/0`).\n\n Own Id: OTP-17784 Aux Id: PR-5792\n\n- Type specifications have been added to the `gen_server`, and the documentation\n has been updated to utilize this.\n\n This surfaced a few type violations that has been corrected in `global`,\n `logger_olp` and `rpc`.\n\n Own Id: OTP-17915 Aux Id: PR-5751, GH-2375, GH-2690\n\n- IP address validation functions `is_ipv4_address/1`, `is_ipv6_address/1` and\n `is_ip_address/1` have been added to the module `inet` in Kernel.\n\n Own Id: OTP-17923 Aux Id: PR-5646\n\n- An API for multihomed SCTP connect has been added in the guise of\n `gen_sctp:connectx_init/*`\n\n Own Id: OTP-17951 Aux Id: PR-5656\n\n- \\[socket] Add encoding of the field hatype of the type sockaddr_ll (family\n 'packet').\n\n Own Id: OTP-17968 Aux Id: OTP-16464\n\n- Added support for configurable features as described in EEP-60. Features can\n be enabled/disabled during compilation with options\n (`-enable-feature Feature`, `-disable-feature Feature` and\n `+{feature, Feature, enable|disable}`) to `erlc` as well as with directives\n (`-feature(Feature, enable|disable).`) in the file. Similar options can be\n used to `erl` for enabling/disabling features allowed at runtime. The new\n `maybe` expression (EEP-49) is fully supported as the feature `maybe_expr`.\n The features support is documented in the reference manual.\n\n Own Id: OTP-17988","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 8.3.2.4 - Kernel Release Notes","ref":"notes.html#kernel-8-3-2-4"},{"type":"extras","doc":"- gen_tcp:connect with socket address and socket (inet-) backend fails because\n of missing callback function.\n\n Own Id: OTP-18707 Aux Id: #7530","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 8.3.2.3 - Kernel Release Notes","ref":"notes.html#kernel-8-3-2-3"},{"type":"extras","doc":"- Spec for function net:if_names/0 incorrect\n\n Own Id: OTP-18296 Aux Id: OTP-16464\n\n- Missing ctrl option name transation for TOS and TTL (on FreeBSD) when using\n gen_udp with the 'socket' inet_backend.\n\n Own Id: OTP-18315\n\n- The tcp connect option 'bind_to_device' could not be used with inet_backend =\n 'socket'. 'inet' requires value type binarry() and 'socket' requires value\n type 'string()'.\n\n Own Id: OTP-18357 Aux Id: #6509\n\n- Minor issue processing options when calling gen_tcp:connect with a sockaddr()\n and inet_backend = socket.\n\n Own Id: OTP-18358 Aux Id: #6528","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Improve warning message format for gen_tcp_socket.\n\n Own Id: OTP-18317","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 8.3.2.2 - Kernel Release Notes","ref":"notes.html#kernel-8-3-2-2"},{"type":"extras","doc":"- A new function `global:disconnect/0` has been introduced with which one can\n cleanly disconnect a node from all other nodes in a cluster of `global` nodes.\n\n Own Id: OTP-18232 Aux Id: OTP-17843, PR-6264","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 8.3.2.1 - Kernel Release Notes","ref":"notes.html#kernel-8-3-2-1"},{"type":"extras","doc":"- A call to [`net_kernel:setopts(new, Opts)`](`net_kernel:setopts/2`) at the\n same time as a connection was being set up could cause a deadlock between the\n `net_kernel` process and the process setting up the connection.\n\n Own Id: OTP-18198 Aux Id: GH-6129, PR-6216","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 8.3.2 - Kernel Release Notes","ref":"notes.html#kernel-8-3-2"},{"type":"extras","doc":"- inet:getopts/2 for the 'raw' option for a socket created with inet-backend\n 'socket' failed.\n\n Own Id: OTP-18078 Aux Id: GH-5930\n\n- Corrected the behaviour of the shutdown function when using with the\n inet_backend = socket. It was not sufficiently compatible with the \"old\"\n gen_tcp.\n\n Own Id: OTP-18080 Aux Id: GH-5930","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 8.3.1 - Kernel Release Notes","ref":"notes.html#kernel-8-3-1"},{"type":"extras","doc":"- Fix failed accepted connection setup after previous established connection\n from same node closed down silently.\n\n Own Id: OTP-17979 Aux Id: ERIERL-780\n\n- Fixed a problem where typing Ctrl-R in the shell could hang if there were some\n problem with the history log file.\n\n Own Id: OTP-17981 Aux Id: PR-5791","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 8.3 - Kernel Release Notes","ref":"notes.html#kernel-8-3"},{"type":"extras","doc":"- Handling of `send_timeout` for `gen_tcp` has been corrected so that the\n timeout is honored also when sending 0 bytes.\n\n Own Id: OTP-17840\n\n- By default `global` does _not_ take any actions to restore a fully connected\n network when connections are lost due to network issues. This is problematic\n for all applications expecting a fully connected network to be provided, such\n as for example `mnesia`, but also for `global` itself. A network of\n overlapping partitions might cause the internal state of `global` to become\n inconsistent. Such an inconsistency can remain even after such partitions have\n been brought together to form a fully connected network again. The effect on\n other applications that expects that a fully connected network is maintained\n may vary, but they might misbehave in very subtle hard to detect ways during\n such a partitioning.\n\n In order to prevent such issues, we have introduced a _prevent overlapping\n partitions_ fix which can be enabled using the\n [`prevent_overlapping_partitions`](kernel_app.md#prevent_overlapping_partitions)\n `kernel(6)` parameter. When this fix has been enabled, `global` will actively\n disconnect from nodes that reports that they have lost connections to other\n nodes. This will cause fully connected partitions to form instead of leaving\n the network in a state with overlapping partitions. Note that this fix _has_\n to be enabled on _all_ nodes in the network in order to work properly. Since\n this quite substantially changes the behavior, this fix is currently disabled\n by default. Since you might get hard to detect issues without this fix you\n are, however, _strongly_ advised to enable this fix in order to avoid issues\n such as the ones described above. As of OTP 25 this fix will become enabled by\n default.\n\n Own Id: OTP-17843 Aux Id: ERIERL-732, PR-5611\n\n- Fix bug where `logger` would crash when logging a report including improper\n lists.\n\n Own Id: OTP-17851\n\n- Make `erlang:set_cookie` work for dynamic node names.\n\n Own Id: OTP-17902 Aux Id: GH-5402, PR-5670","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add support for using socket:sockaddr_in() and socket:sockaddr_in6() when\n using gen_sctp, gen_tcp and gen_udp. This will make it possible to use Link\n Local IPv6 addresses.\n\n Own Id: OTP-17455 Aux Id: GH-4852\n\n- A [`net_tickintensity`](kernel_app.md#net_tickintensity) `kernel` parameter\n has been introduced. It can be used to control the amount of ticks during a\n [`net_ticktime`](kernel_app.md#net_ticktime) period.\n\n A new `net_kernel:start/2` function has also been introduced in order to make\n it easier to add new options. The use of `net_kernel:start/1` has been\n deprecated.\n\n Own Id: OTP-17905 Aux Id: ERIERL-732, PR-5740\n\n- Improve documentation for the dynamic node name feature.\n\n Own Id: OTP-17918","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 8.2 - Kernel Release Notes","ref":"notes.html#kernel-8-2"},{"type":"extras","doc":"- socket:which_sockets( pid() ) uses wrong keyword when looking up socket owner\n ('ctrl' instead of 'owner').\n\n Own Id: OTP-17716\n\n- In epmd_ntop, the #if defined(EPMD6) conditional was inverted and it was only\n including the IPv6-specific code when EPMD6 was undefined. This was causing\n IPv6 addrs to be interpreted as IPv4 addrs and generating nonsense IPv4\n addresses as output.\n\n Several places were incorrectly using 'num_sockets' instead of 'i' to index\n into the iserv_addr array during error logging. This would result in a read\n into uninitialized data in the iserv_addr array.\n\n Thanks to John Eckersberg for providing this fix.\n\n Own Id: OTP-17730\n\n- Minor fix of the `erl_uds_dist` distribution module example.\n\n Own Id: OTP-17765 Aux Id: PR-5289\n\n- A bug has been fixed for the legacy TCP socket adaption module\n `gen_tcp_socket` where it did bind to a socket address when given a file\n descriptor, but should not.\n\n Own Id: OTP-17793 Aux Id: PR-5348, OTP-17451, PR-4787, GH-4680, PR-2989,\n OTP-17216\n\n- Improve the error printout when [`open_port/2`](`open_port/2`) fails because\n of invalid arguments.\n\n Own Id: OTP-17805 Aux Id: PR-5406\n\n- Calling socket:monitor/1 on an already closed socket should succeed and result\n in an immediate DOWN message. This has now been fixed.\n\n Own Id: OTP-17806\n\n- Fix the configuration option `logger_metadata` to work.\n\n Own Id: OTP-17807 Aux Id: PR-5418\n\n- Fix tls and non-tls distribution to use erl_epmd:address_please to figure out\n if IPv4 or IPv6 addresses should be used when connecting to the remote node.\n\n Before this fix, a dns lookup of the remote node hostname determined which IP\n version was to be used which meant that the hostname had to resolve to a valid\n ip address.\n\n Own Id: OTP-17809 Aux Id: PR-5337 GH-5334","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add `logger:reconfigure/0`.\n\n Own Id: OTP-17375 Aux Id: PR-4663 PR-5186\n\n- Add socket function ioctl/2,3,4 for socket device control.\n\n Own Id: OTP-17528\n\n- Add simple support for socknames/1 for gen_tcp_socket and gen_udp_socket.\n\n Own Id: OTP-17531\n\n- The types for callback result types in `gen_statem` has bee augmented with\n arity 2 types where it is possible for a callback module to specify the type\n of the callback data, so the callback module can get type validation of it.\n\n Own Id: OTP-17738 Aux Id: PR-4926, OTP-17589","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 8.1.3 - Kernel Release Notes","ref":"notes.html#kernel-8-1-3"},{"type":"extras","doc":"- The internal, undocumented, but used, module `inet_dns` has been fixed to\n handle mDNS high bit usage of the Class field.\n\n Code that uses the previously obsolete, undocumented and unused record field\n `#dns_rr.func` will need to be updated since that field is now used as a\n boolean flag for the mDNS high Class bit. Code that uses the also undocumented\n record `#dns_query` will need to be recompiled since a boolean field\n `#dns_query.unicast_response` has been added for the mDNS high Class bit.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17734 Aux Id: GH-5327, OTP-17659\n\n- The fix for Linux's behaviour when reconnecting an UDP socket in PR-5120\n released in OTP-24.1.2 has been refined to only dissolve the socket's\n connection before a connect if the socket is already connected, that is: only\n for a reconnect.\n\n This allows code to open a socket with an ephemeral port, get the port number\n and connect; without the port number changing (on Linux). This turned out to\n have at least one valid use case (besides test cases).\n\n Should one reconnect the socket then the port number may change, on Linux; it\n is a known quirk, which can be worked around by binding to a specific port\n number when opening the socket. If you can do without an ephemeral port, that\n is...\n\n Own Id: OTP-17736 Aux Id: GH-5279, PR-5120, OTP-17559","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 8.1.2 - Kernel Release Notes","ref":"notes.html#kernel-8-1-2"},{"type":"extras","doc":"- The undocumented DNS encode/decode module `inet_dns` has been cleaned up to\n handle the difference between \"symbolic\" and \"raw\" records in a more\n consistent manner.\n\n PR-5145/OTP-17584 introduced a change that contributed to an already existing\n confusion, which this correction should remedy.\n\n Own Id: OTP-17659 Aux Id: ERIERL-702","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 8.1.1 - Kernel Release Notes","ref":"notes.html#kernel-8-1-1"},{"type":"extras","doc":"- Add more info about the socket 'type' ('socket' or 'port') for the DOWN\n message when monitoring sockets.\n\n Own Id: OTP-17640","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 8.1 - Kernel Release Notes","ref":"notes.html#kernel-8-1"},{"type":"extras","doc":"- The extended error information has been corrected and improved for the\n following BIFs: [`binary_to_existing_atom/2`](`binary_to_existing_atom/2`),\n [`list_to_existing_atom/1`](`list_to_existing_atom/1`),\n `erlang:send_after/{3,4}`, and `erlang:start_timer/{3,4}`.\n\n Own Id: OTP-17449 Aux Id: GH-4900\n\n- Fixed rare bug that could cause net_kernel process to hang for ever. Have seen\n to happen with massive number of TLS connections while remote nodes are\n restarting. Bug exists since OTP-22.0.\n\n Own Id: OTP-17476 Aux Id: GH-4931, PR-4934\n\n- Improve handling of closed sockets for inet:info/1.\n\n Own Id: OTP-17492\n\n- This change fixes a performance problem introduced in pull-request #2675.\n Pull-request #2675 made so the system tried to start children of already\n started applications which is unnecessary. This change fixes this performance\n problem.\n\n Own Id: OTP-17519\n\n- Fix code:get_doc/1 to not crash when module is located in an escript.\n\n Own Id: OTP-17570 Aux Id: PR-5139 GH-4256 ERL-1261\n\n- Parsing of the result value in the native DNS resolver has been made more\n defensive against incorrect results.\n\n Own Id: OTP-17578 Aux Id: ERIERL-683\n\n- A bug in the option handling for the legacy socket adaptor, that is; when\n using `inet_backend = socket`, has been fixed. Now socket options are set\n before the bind() call so options regarding, for example address reuse have\n the desired effect.\n\n Own Id: OTP-17580 Aux Id: GH-5122\n\n- `inet:ntoa/1` has been fixed to not accept invalid numerical addresses.\n\n Own Id: OTP-17583 Aux Id: GH-5136\n\n- Parsing of DNS records has been improved for records of known types to not\n accept and present malformed ones in raw format.\n\n Own Id: OTP-17584 Aux Id: PR-5145\n\n- The `ip_mreq()` type for the `{ip,add_membership}` and `{ip,drop_membership}`\n socket options has been corrected to have an `interface` field instead of,\n incorrectly, an `address` field.\n\n Own Id: OTP-17590 Aux Id: PR-5170","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add simple utility function to display existing sockets i the erlang shell\n (socket:i/0).\n\n Own Id: OTP-17376 Aux Id: OTP-17157\n\n- gen_udp can now be configured to use the socket inet-backend (in the same way\n as gen_tcp).\n\n Own Id: OTP-17410\n\n- Functions `erlang:set_cookie(Cookie)` and `erlang:get_cookie(Node)` have been\n added for completeness and to facilitate configuring distributed nodes with\n different cookies.\n\n The documentation regarding distribution cookies has been improved to be less\n vague.\n\n Own Id: OTP-17538 Aux Id: GH-5063, PR-5111\n\n- A workaround has been implemented for Linux's quirky behaviour to not adjust\n the source IP address when connecting a connected (reconnecing) UDP socket.\n\n The workaround is to, on Linux, always dissolve any connection before\n connecting an UDP socket.\n\n Own Id: OTP-17559 Aux Id: GH-5092, PR-5120\n\n- Documented our recommendation against opening NFS-mounted files, FIFOs,\n devices, and similar using `file:open/2`.\n\n Own Id: OTP-17576 Aux Id: ERIERL-685","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 8.0.2 - Kernel Release Notes","ref":"notes.html#kernel-8-0-2"},{"type":"extras","doc":"- For `gen_tcp:connect/3,4` it is possible to specify a specific source port,\n which should be enough to bind the socket to an address with that port before\n connecting.\n\n Unfortunately that feature was lost in OTP-17216 that made it mandatory to\n specify the source address to get an address binding, and ignored a specified\n source port if no source address was specified.\n\n That bug has now been corrected.\n\n Own Id: OTP-17536 Aux Id: OTP-17216, ERIERL-677","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 8.0.1 - Kernel Release Notes","ref":"notes.html#kernel-8-0-1"},{"type":"extras","doc":"- Fix a race condition in Global.\n\n Own Id: OTP-16033 Aux Id: ERIERL-329, ERL-1414, GH-4448, ERL-885, GH-3923\n\n- After a node restart with `init:restart/0,1`, the module `socket` was not\n usable because supporting tables had been cleared and not re-initialized. This\n has now been fixed.\n\n Handling of the \".\" domain as a search domain was incorrect and caused a crash\n in the DNS resolver `inet_res`, which has now been fixed.\n\n Own Id: OTP-17439 Aux Id: GH-4827, PR-4888, GH-4838\n\n- Handling of combinations of the `fd` option and binding to an address has been\n corrected, especially for the `local` address family.\n\n Own Id: OTP-17451 Aux Id: OTP-17374\n\n- Bug fixes and code cleanup for the new `socket` implementation, such as:\n\n Assertions on the result of demonitoring has been added in the NIF code, where\n appropriate.\n\n Internal state handling for socket close in the NIF code has been reviewed.\n\n Looping over `close()` for `EINTR` in the NIF code has been removed, since it\n is strongly discouraged on Linux and Posix is not clear about if it is\n allowed.\n\n The `inet_backend` temporary socket option for legacy `gen_tcp` sockets has\n been documented.\n\n The return value from `net:getaddrinfo/2` has been corrected: the `protocol`\n field is now an `t:atom/0`, instead of, incorrectly,\n [`list(atom())`](`t:list/1`). The documentation has also been corrected about\n this return type.\n\n Deferred close of a `socket:sendfile/*` file was broken and has been\n corrected.\n\n Some debug code, not enabled by default, in the socket NIF has been corrected\n to not accidentally core dump for debug printouts of more or less innocent\n events.\n\n Own Id: OTP-17452","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 8.0 - Kernel Release Notes","ref":"notes.html#kernel-8-0"},{"type":"extras","doc":"- A bug has been fixed for the internal `inet_res` resolver cache that handled a\n resolver configuration file status timer incorrectly and caused performance\n problems due to many unnecessary file system accesses.\n\n Own Id: OTP-14700 Aux Id: PR-2848\n\n- Change the value of the tag `head` returned by `disk_log:info/1` from\n `{ok, Head}` to just `Head`.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-16809 Aux Id: ERL-1313\n\n- Two options have been added to `erl_call`. The `-fetch_stdout` option fetches\n stdout data resulting from the code invoked by `erl_call`. The `-fetch_stdout`\n option disables printing of the result term. In order to implement the first\n of these two options a new function called `ei_xrpc_from` has been added to\n erl_interface. For details see the `erl_call` documentation and\n `erl_interface` documentation.\n\n Own Id: OTP-17132\n\n- Missing runtime dependencies has been added to this application.\n\n Own Id: OTP-17243 Aux Id: PR-4557\n\n- `inet:get_rc/0` has been corrected to return host entries as separate entries\n instead of (incorrectly) in a list within the list. This bug was introduced by\n OTP-16487 in OTP-23.0-rc1.\n\n Own Id: OTP-17262 Aux Id: GH-4588, PR-4604, OTP-16487\n\n- The type gen_tcp:option_name() had a duplicate pktoptions value.\n\n Own Id: OTP-17277\n\n- Fixed removal of empty groups from internal state in `pg`.\n\n Own Id: OTP-17286 Aux Id: PR-4619\n\n- `erl -remsh` now prints an error message when it fails to connect to the\n remote node.\n\n Own Id: OTP-17287 Aux Id: PR-4581\n\n- Fix bugs related to corrupt shell history files.\n\n Error messages printed by shell history are now logged as logger error reports\n instead of written to standard error.\n\n Own Id: OTP-17288 Aux Id: PR-4581\n\n- A logger warning is now issues when too many arguments are given to `-name` or\n `-sname`. Example: `erl -name a b`.\n\n Own Id: OTP-17315 Aux Id: GH-4626\n\n- The cache used by `inet_res` now, again, can handle multiple IP addresses per\n domain name, and thus fixes a bug introduced in PR-3041 (OTP-13126) and\n PR-2891 (OTP-14485).\n\n Own Id: OTP-17344 Aux Id: PR-4633, GH-4631, OTP-14485, OTP-12136\n\n- Sockets created with socket:accept not counted (socket:info/0).\n\n Own Id: OTP-17372\n\n- The `{fd, Fd}` option to `gen_tcp:listen/2` did not work for `inet_backend`\n `socket`, which has been fixed.\n\n Own Id: OTP-17374 Aux Id: PR-4787, GH-4680, PR-2989, OTP-17216","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The cache used by the DNS resolver `inet_res` has been improved to use ETS\n lookups instead of server calls. This is a considerable speed improvement for\n cache hits.\n\n Own Id: OTP-13126 Aux Id: PR-3041\n\n- The cache ETS table type for the internal DNS resolver `inet_res` has changed\n type (internally) to get better speed and atomicity.\n\n Own Id: OTP-14485 Aux Id: PR-2891\n\n- The experimental `socket` module can now use any protocol (by name) the OS\n supports. Suggested in PR-2641, implemented in PR-2670.\n\n Own Id: OTP-14601 Aux Id: PR-2641, PR-2670, OTP-16749\n\n- The DNS resolver `inet_res` has been updated to support CAA (RFC 6844) and URI\n (RFC 7553) records.\n\n Own Id: OTP-16517 Aux Id: PR-2827\n\n- A compatibility adaptor for `gen_tcp` to use the new `socket` API has been\n implemented (`gen_tcp_socket`). Used when setting the kernel application\n variable `inet_backend = socket`.\n\n Own Id: OTP-16611 Aux Id: OTP-16749\n\n- Extended error information for failing BIF calls as proposed in\n [EEP 54](https://github.com/erlang/eep/blob/master/eeps/eep-0054.md) has been\n implemented.\n\n When a BIF call from the Erlang shell fails, more information about which\n argument or arguments that were in error will be printed. The same extended\n error information will by `proc_lib`, `common_test`, and `qlc` when BIF calls\n fail.\n\n For applications that wish to provide the same extended error information,\n there are new functions `erl_error:format_exception/3` and\n `erl_error:format_exception/4`.\n\n There is a new [`error/3`](`error/3`) BIF that allows applications or\n libraries to provide extended error information in the same way for their own\n exceptions.\n\n Own Id: OTP-16686\n\n- The file server can now be bypassed in `file:delete/1,2` with the `raw`\n option.\n\n Own Id: OTP-16698 Aux Id: PR-2634\n\n- An example implementation of Erlang distribution over UDS using distribution\n processes has been introduced.\n\n Thanks to Jérôme de Bretagne\n\n Own Id: OTP-16703 Aux Id: PR-2620\n\n- The [_process alias_](`e:system:ref_man_processes.md#process-aliases`) feature\n as outlined by\n [EEP 53](https://github.com/erlang/eep/blob/master/eeps/eep-0053.md) has been\n introduced. It is introduced in order to provide a lightweight mechanism that\n can prevent late replies after timeout or connection loss. For more\n information, see EEP 53 and the documentation of the new\n [`alias/1`](`erlang:alias/1`) BIF and the new options to the\n [`monitor/3`](`erlang:monitor/3`) BIF.\n\n The `call` operation in the framework used by `gen_server`, `gen_statem`, and\n `gen_event` has been updated to utilize alias in order to prevent late\n responses. The `gen_statem` behavior still use a proxy process in the\n distributed case, since it has always prevented late replies and aliases won't\n work against pre OTP 24 nodes. The proxy process can be removed in OTP 26.\n\n The alias feature also made it possible to introduce new functions similar to\n the [`erpc:receive_response()`](`erpc:receive_response/2`) function in the gen\n behaviors, so the new functions\n [`gen_server:receive_response()`](`gen_server:receive_response/2`),\n [`gen_statem:receive_response()`](`gen_statem:receive_response/2`),\n [`gen_event:receive_response()`](`gen_event:receive_response/2`) have also\n been introduced.\n\n Own Id: OTP-16718 Aux Id: PR-2735\n\n- The experimental new socket API has been further developed. Some backwards\n incompatible changes with respect to OTP 23 have been made.\n\n The control message format has been changed so a decoded value is now in the\n 'value' field instead of in the 'data' field. The 'data' field now always\n contains binary data.\n\n Some type names have been changed regarding message headers and control\n message headers.\n\n `socket:bind/2` now returns plain `ok` instead of `{ok, Port}` which was only\n relevant for the `inet` and `inet6` address families and often not\n interesting. To find out which port was chosen use `socket:sockname/1`.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-16749 Aux Id: OTP-14601\n\n- New function `os:env/0` returns all OS environment variables as a list of\n 2-tuples.\n\n Own Id: OTP-16793 Aux Id: ERL-1332, PR-2740\n\n- Remove the support for distributed disk logs. The new function\n `disk_log:all/0` is to be used instead of `disk_log:accessible_logs/0`. The\n function `disk_log:close/1` is to be used instead of `disk_log:lclose/1,2`.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-16811\n\n- Expand the spec for `erl_epmd:listen_port_please/2` to mirror\n `erl_epmd:port_please/2`.\n\n Own Id: OTP-16947 Aux Id: PR-2781\n\n- A new erl parameter for specifying a file descriptor with configuration data\n has been added. This makes it possible to pass the parameter \"-configfd FD\"\n when executing the erl command. When this option is given, the system will try\n to read and parse configuration parameters from the file descriptor.\n\n Own Id: OTP-16952\n\n- The experimental HiPE application has been removed, together with all related\n functionality in other applications.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-16963\n\n- The `pg2` module has been removed.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-16968\n\n- Accept references up to a size of 160-bits from remote nodes. This is the\n first step in an upgrade path toward using references up to 160-bits in a\n future OTP release.\n\n Own Id: OTP-17005 Aux Id: OTP-16718\n\n- Allow utf-8 binaries as parts of logger_formatter template.\n\n Own Id: OTP-17015\n\n- Let `disk_log:open/1` change the size if a wrap log is opened for the first\n time, that is, the disk log process does not exist, and the value of option\n `size` does not match the current size of the disk log.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17062 Aux Id: ERL-1418, GH-4469, ERIERL-537\n\n- Allow the shell history of an erlang node to be fetched and stores using a\n custom callback module. See `shell_history` configuration parameter in the\n [kernel documentation](kernel_app.md) for more details.\n\n Own Id: OTP-17103 Aux Id: PR-2949\n\n- The simple logger (used to log events that happen before kernel has been\n started) has been improved to print prettier error messages.\n\n Own Id: OTP-17106 Aux Id: PR-2885\n\n- `socket:sendfile/2,3,4,5` has been implemented, for platforms that support the\n underlying socket library call.\n\n Own Id: OTP-17154 Aux Id: OTP-16749\n\n- Add socket monitor(s) for all types sockets.\n\n Own Id: OTP-17155\n\n- Fix various issues with the gen_tcp_socket. Including documenting some\n incompatibilities.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17156\n\n- inet:i/0 now also shows existing gen_tcp compatibility sockets (based on\n 'socket').\n\n Own Id: OTP-17157\n\n- Added support in logger for setting primary metadata. The primary metadata is\n passed as a base metadata to all log events in the system. See\n [Metadata](logger_chapter.md#metadata) in the Logger chapter of the Kernel\n User's Guide for more details.\n\n Own Id: OTP-17181 Aux Id: PR-2457\n\n- Recognize new key 'optional_applications' in application resource files.\n\n Own Id: OTP-17189 Aux Id: PR-2675\n\n- The `Fun`'s passed to logger:log/2,3,4 can now return metadata that will only\n be fetched when needed. See [`logger:log/2,3,4`](`logger:log/2`) for more\n details.\n\n Own Id: OTP-17198 Aux Id: PR-2721\n\n- `erpc:multicall()` has been rewritten to be able to utilize the newly\n introduced and improved selective receive optimization.\n\n Own Id: OTP-17201 Aux Id: PR-4534\n\n- Add utility fiunction inet:info/1 to provide miscellaneous info about a\n socket.\n\n Own Id: OTP-17203 Aux Id: OTP-17156\n\n- The behaviour for `gen_tcp:connect/3,4` has been changed to not per default\n bind to an address, which allows the network stack to delay the address and\n port selection to when the remote address is known. This allows better port\n re-use, and thus enables far more outgoing connections, since the ephemeral\n port range no longer has to be a hard limit.\n\n There is a theoretical possibility that this behaviour change can affect the\n set of possible error values, or have other small implications on some\n platforms.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17216 Aux Id: PR-2989\n\n- An option `{nxdomain_reply, boolean()}` has been implemented in the DNS\n resolver `inet_res`. It is useful since an `nxdomain` error from a name server\n does contain the SOA record if the domain exists at all. This record is useful\n to determine a TTL for negative caching of the failed entry.\n\n Own Id: OTP-17266 Aux Id: PR-4564\n\n- Optimized lookup of local processes part of groups in `pg`.\n\n Own Id: OTP-17284 Aux Id: PR-4615\n\n- The return values from module `socket` functions `send()`, `sendto()`,\n `sendmsg()`, `sendfile()` and `recv()` has been changed to return a tuple\n tagged with `select` when a `SelectInfo` was returned, and not sometimes\n tagged with `ok`.\n\n This is a backwards incompatible change that improves usability for code using\n asynchronous operations.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17355 Aux Id: OTP-17154\n\n- Fixed warnings in code matching on underscore prefixed variables.\n\n Own Id: OTP-17385 Aux Id: OTP-17123","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 7.3.1.7 - Kernel Release Notes","ref":"notes.html#kernel-7-3-1-7"},{"type":"extras","doc":"- A new function `global:disconnect/0` has been introduced with which one can\n cleanly disconnect a node from all other nodes in a cluster of `global` nodes.\n\n Own Id: OTP-18232 Aux Id: OTP-17843, PR-6264","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 7.3.1.6 - Kernel Release Notes","ref":"notes.html#kernel-7-3-1-6"},{"type":"extras","doc":"- A call to [`net_kernel:setopts(new, Opts)`](`net_kernel:setopts/2`) at the\n same time as a connection was being set up could cause a deadlock between the\n `net_kernel` process and the process setting up the connection.\n\n Own Id: OTP-18198 Aux Id: GH-6129, PR-6216","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 7.3.1.5 - Kernel Release Notes","ref":"notes.html#kernel-7-3-1-5"},{"type":"extras","doc":"- By default `global` does _not_ take any actions to restore a fully connected\n network when connections are lost due to network issues. This is problematic\n for all applications expecting a fully connected network to be provided, such\n as for example `mnesia`, but also for `global` itself. A network of\n overlapping partitions might cause the internal state of `global` to become\n inconsistent. Such an inconsistency can remain even after such partitions have\n been brought together to form a fully connected network again. The effect on\n other applications that expects that a fully connected network is maintained\n may vary, but they might misbehave in very subtle hard to detect ways during\n such a partitioning.\n\n In order to prevent such issues, we have introduced a _prevent overlapping\n partitions_ fix which can be enabled using the\n [`prevent_overlapping_partitions`](kernel_app.md#prevent_overlapping_partitions)\n `kernel(6)` parameter. When this fix has been enabled, `global` will actively\n disconnect from nodes that reports that they have lost connections to other\n nodes. This will cause fully connected partitions to form instead of leaving\n the network in a state with overlapping partitions. Note that this fix _has_\n to be enabled on _all_ nodes in the network in order to work properly. Since\n this quite substantially changes the behavior, this fix is currently disabled\n by default. Since you might get hard to detect issues without this fix you\n are, however, _strongly_ advised to enable this fix in order to avoid issues\n such as the ones described above. As of OTP 25 this fix will become enabled by\n default.\n\n Own Id: OTP-17843 Aux Id: ERIERL-732, PR-5611\n\n- Fix failed accepted connection setup after previous established connection\n from same node closed down silently.\n\n Own Id: OTP-17979 Aux Id: ERIERL-780","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- A [`net_tickintensity`](kernel_app.md#net_tickintensity) `kernel` parameter\n has been introduced. It can be used to control the amount of ticks during a\n [`net_ticktime`](kernel_app.md#net_ticktime) period.\n\n A new `net_kernel:start/2` function has also been introduced in order to make\n it easier to add new options. The use of `net_kernel:start/1` has been\n deprecated.\n\n Own Id: OTP-17905 Aux Id: ERIERL-732, PR-5740","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 7.3.1.4 - Kernel Release Notes","ref":"notes.html#kernel-7-3-1-4"},{"type":"extras","doc":"- Parsing of the result value in the native DNS resolver has been made more\n defensive against incorrect results.\n\n Own Id: OTP-17578 Aux Id: ERIERL-683","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 7.3.1.3 - Kernel Release Notes","ref":"notes.html#kernel-7-3-1-3"},{"type":"extras","doc":"- Fix code:get_doc/1 to not crash when module is located in an escript.\n\n Own Id: OTP-17570 Aux Id: PR-5139 GH-4256 ERL-1261","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 7.3.1.2 - Kernel Release Notes","ref":"notes.html#kernel-7-3-1-2"},{"type":"extras","doc":"- Handling of the \".\" domain as a search domain was incorrect and caused a crash\n in the DNS resolver `inet_res`, which has now been fixed.\n\n Own Id: OTP-17473 Aux Id: GH-4838, OTP-17439\n\n- Fixed rare bug that could cause net_kernel process to hang for ever. Have seen\n to happen with massive number of TLS connections while remote nodes are\n restarting. Bug exists since OTP-22.0.\n\n Own Id: OTP-17476 Aux Id: GH-4931, PR-4934","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 7.3.1.1 - Kernel Release Notes","ref":"notes.html#kernel-7-3-1-1"},{"type":"extras","doc":"- Fix a race condition in Global.\n\n Own Id: OTP-16033 Aux Id: ERIERL-329, ERL-1414, GH-4448, ERL-885, GH-3923","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 7.3.1 - Kernel Release Notes","ref":"notes.html#kernel-7-3-1"},{"type":"extras","doc":"- A bug in the Erlang DNS resolver has been fixed, where it could be made to\n bring down the kernel supervisor and thereby the whole node, when getting an\n incorrect (IN A reply to an IN CNAME query) reply from the DNS server and used\n the reply record's value without verifying its type.\n\n Own Id: OTP-17361","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 7.3 - Kernel Release Notes","ref":"notes.html#kernel-7-3"},{"type":"extras","doc":"- The range check for compression pointers in DNS encoding was faulty, which\n caused incorrect label compression encoding for very large DNS messages;\n larger than about 16 kBytes, such as AXFR responses. This more than 11 year\n old bug has now been corrected.\n\n Own Id: OTP-13641 Aux Id: PR-2959\n\n- Fix of internal links in the `erpc` documentation.\n\n Own Id: OTP-17202 Aux Id: PR-4516\n\n- Fix bug where complex seq_trace tokens (that is lists, tuples, maps etc) could\n becomes corrupted by the GC. The bug was introduced in OTP-21.\n\n Own Id: OTP-17209 Aux Id: PR-3039\n\n- When running Xref in the `modules` mode, the Debugger application would show\n up as a dependency for the Kernel applications.\n\n Own Id: OTP-17223 Aux Id: GH-4546, PR-4554","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- `m:erl_epmd` (the epmd client) will now try to reconnect to the local EPMD if\n the connection is broken.\n\n Own Id: OTP-17178 Aux Id: PR-3003","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 7.2.1 - Kernel Release Notes","ref":"notes.html#kernel-7-2-1"},{"type":"extras","doc":"- When using the DNS resolver option `servfail_retry_timeout` it did not honour\n the overall call time-out in e.g `inet_res:getbyname/3`. This misbehaviour has\n now been fixed. Also, the `servfail_retry_timeout` behaviour has been improved\n to only be enforced for servers that gives a servfail answer.\n\n Own Id: OTP-12960 Aux Id: ERIERL-598, PR-4509","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 7.2 - Kernel Release Notes","ref":"notes.html#kernel-7-2"},{"type":"extras","doc":"- The `apply` call's in `logger.hrl` are now called with `erlang` prefix to\n avoid clashed with local [`apply/3`](`apply/3`) functions.\n\n Own Id: OTP-16976 Aux Id: PR-2807\n\n- Fix memory leak in `pg`.\n\n Own Id: OTP-17034 Aux Id: PR-2866\n\n- Fix crash in `logger_proxy` due to stray `gen_server:call` replies not being\n handled. The stray replies come when logger is under heavy load and the flow\n control mechanism is reaching its limit.\n\n Own Id: OTP-17038\n\n- Fixed a bug in `erl_epmd:names()` that caused it to return the illegal return\n value `noport` instead of `{error, Reason}` where `Reason` is the actual error\n reason. This bug also propagated to `net_adm:names()`.\n\n This bug was introduced in `kernel` version 7.1 (OTP 23.1).\n\n Own Id: OTP-17054 Aux Id: ERL-1424","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add export of some resolver documented types.\n\n Own Id: OTP-16954 Aux Id: ERIERL-544\n\n- Add configurable retry timeout for resolver lookups.\n\n Own Id: OTP-16956 Aux Id: ERIERL-547\n\n- `gen_server:multi_call()` has been optimized in the special case of only\n calling the local node with timeout set to `infinity`.\n\n Own Id: OTP-17058 Aux Id: PR-2887","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 7.1 - Kernel Release Notes","ref":"notes.html#kernel-7-1"},{"type":"extras","doc":"- A fallback has been implemented for file:sendfile when using inet_backend\n socket\n\n Own Id: OTP-15187 Aux Id: ERL-1293\n\n- Make default TCP distribution honour option `backlog` in\n `inet_dist_listen_options`.\n\n Own Id: OTP-16694 Aux Id: PR-2625\n\n- Raw option handling for the experimental `gen_tcp_socket` backend was broken\n so that all raw options were ignored by for example `gen_tcp:listen/2`, a bug\n that now has been fixed. Reported by Jan Uhlig.\n\n Own Id: OTP-16743 Aux Id: ERL-1287\n\n- Accept fails with inet-backend socket.\n\n Own Id: OTP-16748 Aux Id: ERL-1284\n\n- Fixed various minor errors in the socket backend of gen_tcp.\n\n Own Id: OTP-16754\n\n- Correct `disk_log:truncate/1` to count the header. Also correct the\n documentation to state that `disk_log:truncate/1` can be used with external\n disk logs.\n\n Own Id: OTP-16768 Aux Id: ERL-1312\n\n- Fix erl_epmd:port_please/2,3 type specs to include all possible error values.\n\n Own Id: OTP-16783\n\n- Fix `erl -erl_epmd_port` to work properly. Before this fix it did not work at\n all.\n\n Own Id: OTP-16785\n\n- Fix typespec for internal function `erlang:seq_trace_info/1` to allow\n `t:term/0` as returned label. This in turn fixes so that calls to\n `seq_trace:get_token/1` can be correctly analyzer by dialyzer.\n\n Own Id: OTP-16823 Aux Id: PR-2722\n\n- Fix erroneous double registration of processes in `pg` when distribution is\n dynamically started.\n\n Own Id: OTP-16832 Aux Id: PR-2738","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Make (use of) the socket registry optional (still enabled by default). Its now\n possible to build OTP with the socket registry turned off, turn it off by\n setting an environment variable and controlling in runtime (via function calls\n and arguments when creating sockets).\n\n Own Id: OTP-16763\n\n- `erl -remsh nodename` no longer requires the hostname to be given when used\n together with dynamic nodenames.\n\n Own Id: OTP-16784","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 7.0 - Kernel Release Notes","ref":"notes.html#kernel-7-0"},{"type":"extras","doc":"- Fix race condition during shutdown when `shell_history` is enabled. The race\n condition would trigger crashes in `disk_log`.\n\n Own Id: OTP-16008 Aux Id: PR-2302\n\n- Fix the Erlang distribution to handle the scenario when a node connects that\n can handle message fragmentation but can not handle the atom cache. This bug\n only affects users that have implemented a custom distribution carrier. It has\n been present since OTP-21.\n\n The `DFLAG_FRAGMENT` distribution flag was added to the set of flags that can\n be rejected by a distribution implementation.\n\n Own Id: OTP-16284\n\n- Fix bug where a binary was not allowed to be the format string in calls to\n `logger:log`.\n\n Own Id: OTP-16395 Aux Id: PR-2444\n\n- Fix bug where `logger` would end up in an infinite loop when trying to log the\n crash of a handler or formatter.\n\n Own Id: OTP-16489 Aux Id: ERL-1134\n\n- `code:lib_dir/1` has been fixed to also return the lib dir for `erts`.\n\n This is been marked as an incompatibility for any application that depended on\n `{error,bad_name}` to be returned for `erts`.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-16502\n\n- The application `stop/1` callback was not called if the application master of\n the application terminated.\n\n Own Id: OTP-16504 Aux Id: PR-2328\n\n- Fix bug in `application:loaded_applications/0` that could cause it to fail\n with `badarg` if for example a concurrent upgrade/downgrade is running.\n\n Own Id: OTP-16627 Aux Id: PR-2601","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- A new module `m:erpc` has been introduced in the `kernel` application. The\n `erpc` module implements an enhanced subset of the operations provided by the\n `m:rpc` module. Enhanced in the sense that it makes it possible to distinguish\n between returned value, raised exceptions, and other errors. `erpc` also has\n better performance and scalability than the original `rpc` implementation.\n This by utilizing the newly introduced\n [`spawn_request()`](`erlang:spawn_request/5`) BIF. Also the `rpc` module\n benefits from these improvements by utilizing `erpc` when it is possible.\n\n This change has been marked as a potential incompatibility since\n [`rpc:block_call()`](`rpc:block_call/5`) now only is guaranteed to block other\n `block_call()` operations. The documentation previously claimed that it would\n block all `rpc` operations. This has however never been the case. It\n previously did not block node-local `block_call()` operations.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-13450 Aux Id: OTP-15251\n\n- A client node can receive its node name dynamically from the node that it\n first connects to. This featured can by used by\n\n - starting with `erl -sname undefined`\n - erl_interface functions `ei_connect_init` and friends\n - `erl_call -R`\n\n Own Id: OTP-13812\n\n- Improved the printout of single line logger events for most of the OTP\n behaviours in STDLIB and Kernel. This includes `proc_lib`, `gen_server`,\n `gen_event`, `gen_statem`, `gen_fsm`, `supervisor`, `supervisor_bridge` and\n `application`.\n\n Improved the [`chars_limit`](`m:logger_formatter#chars_limit`) and\n [`depth`](`m:logger_formatter#depth`) handling in `proc_lib` and when\n formatting of exceptions.\n\n Own Id: OTP-15299\n\n- Remove usage and documentation of old requests of the I/O-protocol.\n\n Own Id: OTP-15695\n\n- Directories can now be opened by `file:open/2` when passing the `directory`\n option.\n\n Own Id: OTP-15835 Aux Id: PR-2212\n\n- The check of whether to log or not based on the log level in `logger` has been\n optimized by using `persistent_term` to store the log level.\n\n Own Id: OTP-15948 Aux Id: PR-2356\n\n- `file:read_file_info/2` can now be used on opened files and directories.\n\n Own Id: OTP-15956 Aux Id: PR-2231\n\n- The `-config` option to `erl` now can take multiple config files without\n repeating the `-config` option. Example:\n\n erl -config sys local\n\n Own Id: OTP-16148 Aux Id: PR-2373\n\n- Improved node connection setup handshake protocol. Made possible to agree on\n protocol version without dependence on `epmd` or other prior knowledge of peer\n node version. Also added exchange of node incarnation (\"creation\") values and\n expanded the distribution capability flag field from 32 to 64 bits.\n\n Own Id: OTP-16229\n\n- The possibility to run Erlang distribution without relying on EPMD has been\n extended. To achieve this a couple of new options to the inet distribution has\n been added.\n\n - **\\-dist_listen false** - Setup the distribution channel, but do not listen\n for incoming connection. This is useful when you want to use the current\n node to interact with another node on the same machine without it joining\n the entire cluster.\n\n - **\\-erl_epmd_port Port** - Configure a default port that the built-in EPMD\n client should return. This allows the local node to know the port to connect\n to for any other node in the cluster.\n\n The `erl_epmd` callback API has also been extended to allow returning `-1` as\n the creation which means that a random creation will be created by the node.\n\n In addition a new callback function called `listen_port_please` has been added\n that allows the callback to return which listen port the distribution should\n use. This can be used instead of `inet_dist_listen_min/max` if the listen port\n is to be fetched from an external service.\n\n Own Id: OTP-16250\n\n- A first EXPERIMENTAL module that is a `socket` backend to `gen_tcp` and `inet`\n has been implemented. Others will follow. Feedback will be appreciated.\n\n Own Id: OTP-16260 Aux Id: OTP-15403\n\n- The new experimental `socket` module has been moved to the Kernel application.\n\n Own Id: OTP-16312\n\n- Replace usage of deprecated function in the `group` module.\n\n Own Id: OTP-16345\n\n- Minor updates due to the new spawn improvements made.\n\n Own Id: OTP-16368 Aux Id: OTP-15251\n\n- Update of [sequential tracing](`m:seq_trace#whatis`) to also support other\n information transfers than message passing.\n\n Own Id: OTP-16370 Aux Id: OTP-15251, OTP-15232\n\n- `code:module_status/1` now accepts a list of modules. `code:module_status/0`,\n which returns the statuses for all loaded modules, has been added.\n\n Own Id: OTP-16402\n\n- `filelib:wildcard/1,2` is now twice as fast when a double star (`**`) is part\n of the pattern.\n\n Own Id: OTP-16419\n\n- A new implementation of distributed named process groups has been introduced.\n It is available in the `m:pg` module.\n\n Note that this `pg` module only has the name in common with the experimental\n `pg` module that was present in `stdlib` up until OTP 17.\n\n Thanks to Maxim Fedorov for the implementation.\n\n Own Id: OTP-16453 Aux Id: PR-2524\n\n- The `pg2` module has been deprecated. It has also been scheduled for removal\n in OTP 24.\n\n You are advised to replace the usage of `pg2` with the newly introduced `m:pg`\n module. `pg` has a similar API, but with a more scalable implementation.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-16455\n\n- Refactored the internal handling of deprecated and removed functions.\n\n Own Id: OTP-16469\n\n- The internal hosts file resolver cache `inet_hosts` has been rewritten to\n behave better when the hosts file changes. For example the cache is updated\n per entry instead of cleared and reloaded so lookups do not temporarily fail\n during reloading, and; when multiple processes simultaneously request reload\n these are now folded into one instead of all done in sequence. Reported and\n first solution suggestion by Maxim Fedorov.\n\n Own Id: OTP-16487 Aux Id: PR-2516\n\n- Add `code:all_available/0` that can be used to get all available modules.\n\n Own Id: OTP-16494\n\n- As of OTP 23, the distributed `m:disk_log` feature has been deprecated. It has\n also been scheduled for removal in OTP 24.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-16495\n\n- Add the function `code:fetch_docs/1` for fetching embedded documentation for\n aa Erlang module.\n\n Own Id: OTP-16499\n\n- Improve configure for the net nif, which should increase portability.\n\n Own Id: OTP-16530 Aux Id: OTP-16464\n\n- socket: Socket counters and socket global counters are now represented as maps\n (instead of property lists).\n\n Own Id: OTP-16535\n\n- The experimental socket module has gotten restrictions removed so now the\n 'seqpacket' socket type should work for any communication domain (protocol\n family) where the OS supports it, typically the Unix Domain.\n\n Own Id: OTP-16550 Aux Id: ERIERL-476\n\n- Allow using custom IO devices in `logger_std_h`.\n\n Own Id: OTP-16563 Aux Id: PR-2523\n\n- Added `file:del_dir_r/1` which deletes a directory together with all of its\n contents, similar to `rm -rf` on Unix systems.\n\n Own Id: OTP-16570 Aux Id: PR-2565\n\n- socket: By default the socket options rcvtimeo and sndtimeo are now disabled.\n To enable these, OTP now has to be built with the configure option\n --enable-esock-rcvsndtimeo\n\n Own Id: OTP-16620\n\n- The experimental gen_tcp compatibility code utilizing the socket module could\n loose buffered data when receiving a specified number of bytes. This bug has\n been fixed. Reported by Maksim Lapshin on bugs.erlang.org ERL-1234\n\n Own Id: OTP-16632 Aux Id: ERL-1234","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 6.5.2.5 - Kernel Release Notes","ref":"notes.html#kernel-6-5-2-5"},{"type":"extras","doc":"- By default `global` does _not_ take any actions to restore a fully connected\n network when connections are lost due to network issues. This is problematic\n for all applications expecting a fully connected network to be provided, such\n as for example `mnesia`, but also for `global` itself. A network of\n overlapping partitions might cause the internal state of `global` to become\n inconsistent. Such an inconsistency can remain even after such partitions have\n been brought together to form a fully connected network again. The effect on\n other applications that expects that a fully connected network is maintained\n may vary, but they might misbehave in very subtle hard to detect ways during\n such a partitioning.\n\n In order to prevent such issues, we have introduced a _prevent overlapping\n partitions_ fix which can be enabled using the\n `prevent_overlapping_partitions` `kernel(6)` parameter. When this fix has been\n enabled, `global` will actively disconnect from nodes that reports that they\n have lost connections to other nodes. This will cause fully connected\n partitions to form instead of leaving the network in a state with overlapping\n partitions. Note that this fix _has_ to be enabled on _all_ nodes in the\n network in order to work properly. Since this quite substantially changes the\n behavior, this fix is currently disabled by default. Since you might get hard\n to detect issues without this fix you are, however, _strongly_ advised to\n enable this fix in order to avoid issues such as the ones described above. As\n of OTP 25 this fix will become enabled by default.\n\n Own Id: OTP-17843 Aux Id: ERIERL-732, PR-5611","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- A `net_tickintensity` `kernel` parameter has been introduced. It can be used\n to control the amount of ticks during a `net_ticktime` period.\n\n A new `net_kernel:start/2` function has also been introduced in order to make\n it easier to add new options. The use of `net_kernel:start/1` has been\n deprecated.\n\n Own Id: OTP-17905 Aux Id: ERIERL-732, PR-5740","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 6.5.2.4 - Kernel Release Notes","ref":"notes.html#kernel-6-5-2-4"},{"type":"extras","doc":"- Fixed rare bug that could cause net_kernel process to hang for ever. Have seen\n to happen with massive number of TLS connections while remote nodes are\n restarting. Bug exists since OTP-22.0.\n\n Own Id: OTP-17476 Aux Id: GH-4931, PR-4934","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 6.5.2.3 - Kernel Release Notes","ref":"notes.html#kernel-6-5-2-3"},{"type":"extras","doc":"- Fix a race condition in Global.\n\n Own Id: OTP-16033 Aux Id: ERIERL-329, ERL-1414, GH-4448, ERL-885, GH-3923","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 6.5.2.2 - Kernel Release Notes","ref":"notes.html#kernel-6-5-2-2"},{"type":"extras","doc":"- When running Xref in the `modules` mode, the Debugger application would show\n up as a dependency for the Kernel applications.\n\n Own Id: OTP-17223 Aux Id: GH-4546, PR-4554","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 6.5.2.1 - Kernel Release Notes","ref":"notes.html#kernel-6-5-2-1"},{"type":"extras","doc":"- Fix bug in `application:loaded_applications/0` that could cause it to fail\n with `badarg` if for example a concurrent upgrade/downgrade is running.\n\n Own Id: OTP-16627 Aux Id: PR-2601","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 6.5.2 - Kernel Release Notes","ref":"notes.html#kernel-6-5-2"},{"type":"extras","doc":"- The DNS resolver \\`inet_res\\` has been fixed to return the last intermediate\n error when subsequent requests times out.\n\n Own Id: OTP-16414 Aux Id: ERIERL-452\n\n- The prim_net nif (net/kernel) made use of an undefined atom, notsup. This has\n now been corrected.\n\n Own Id: OTP-16440\n\n- Fix a crash when attempting to log faults when loading files during early\n boot.\n\n Own Id: OTP-16491\n\n- Fix crash in logger when logging to a remote node during boot.\n\n Own Id: OTP-16493 Aux Id: ERIERL-459","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Improved `net_kernel` debug functionality.\n\n Own Id: OTP-16458 Aux Id: PR-2525","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 6.5.1 - Kernel Release Notes","ref":"notes.html#kernel-6-5-1"},{"type":"extras","doc":"- The 'socket state' info provided by the inet info function has been improved\n\n Own Id: OTP-16043 Aux Id: ERL-1036\n\n- Fix bug where `logger` would crash when starting when a very large log file\n needed to be rotated and compressed.\n\n Own Id: OTP-16145 Aux Id: ERL-1034\n\n- Fixed a bug causing actual nodedown reason reported by\n [`net_kernel:monitor_nodes(true, [nodedown_reason])`](`net_kernel:monitor_nodes/2`)\n to be lost and replaced by the reason `killed`.\n\n Own Id: OTP-16216\n\n- The documentation for `rpc:call/4,5/` has been updated to describe what\n happens when the called function throws or return an `'EXIT'` tuple.\n\n Own Id: OTP-16279 Aux Id: ERL-1066","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 6.5 - Kernel Release Notes","ref":"notes.html#kernel-6-5"},{"type":"extras","doc":"- The type specification for `gen_sctp:connect/4,5` has been corrected.\n\n Own Id: OTP-15344 Aux Id: ERL-947\n\n- Extra `-mode` flags given to `erl` are ignored with a warning.\n\n Own Id: OTP-15852\n\n- Fix type spec for `seq_trace:set_token/2`.\n\n Own Id: OTP-15858 Aux Id: ERL-700\n\n- `logger:compare_levels/2` would fail with a `badarg` exception if given the\n values `all` or `none` as any of the parameters. This is now corrected.\n\n Own Id: OTP-15942 Aux Id: PR-2301\n\n- Fix bug where the log file in `logger_std_h` would not be closed when the\n inode of the file changed. This would in turn cause a file descriptor leak\n when tools like logrotate are used.\n\n Own Id: OTP-15997 Aux Id: PR-2331\n\n- Fix a race condition in the debugging function `net_kernel:nodes_info/0`.\n\n Own Id: OTP-16022\n\n- Fix race condition when closing a file opened in `compressed` or\n `delayed_write` mode.\n\n Own Id: OTP-16023","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The possibility to send ancillary data, in particular the TOS field, has been\n added to `gen_udp:send/4,5`.\n\n Own Id: OTP-15747 Aux Id: ERIERL-294\n\n- If the log file was given with relative path, the standard logger handler\n (`logger_std_h`) would store the file name with relative path. If the current\n directory of the node was later changed, a new file would be created relative\n the new current directory, potentially failing with an `enoent` if the new\n directory did not exist. This is now corrected and `logger_std_h` always\n stores the log file name as an absolute path, calculated from the current\n directory at the time of the handler startup.\n\n Own Id: OTP-15850\n\n- Support local sockets with inet:i/0.\n\n Own Id: OTP-15935 Aux Id: PR-2299","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 6.4.1 - Kernel Release Notes","ref":"notes.html#kernel-6-4-1"},{"type":"extras","doc":"- `user`/`user_drv` could respond to io requests before they had been processed,\n which could cause data to be dropped if the emulator was halted soon after a\n call to `io:format/2`, such as in an escript.\n\n Own Id: OTP-15805","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 6.4 - Kernel Release Notes","ref":"notes.html#kernel-6-4"},{"type":"extras","doc":"- Fix so that when multiple `-sname` or `-name` are given to `erl` the first one\n is chosen. Before this fix distribution was not started at all when multiple\n name options were given.\n\n Own Id: OTP-15786 Aux Id: ERL-918\n\n- Fix `inet_res` configuration pointing to non-existing files to work again.\n This was broken in KERNEL-6.3 (OTP-21.3).\n\n Own Id: OTP-15806","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- A simple socket API is provided through the socket module. This is a low level\n API that does _not_ replace gen\\_\\[tcp|udp|sctp]. It is intended to\n _eventually_ replace the inet driver, but not the high level gen-modules\n (gen_tcp, gen_udp and gen_sctp). It also provides a basic API that facilitates\n the implementation of other protocols, that is TCP, UDP and SCTP.\n\n Known issues are; No support for the Windows OS (currently).\n\n Own Id: OTP-14831\n\n- Improved the documentation for the linger option.\n\n Own Id: OTP-15491 Aux Id: PR-2019\n\n- Global no longer tries more than once when connecting to other nodes.\n\n Own Id: OTP-15607 Aux Id: ERIERL-280\n\n- The dist messages EXIT, EXIT2 and MONITOR_DOWN have been updated with new\n versions that send the reason term as part of the payload of the message\n instead of as part of the control message.\n\n The old versions are still present and can be used when communicating with\n nodes that don't support the new versions.\n\n Own Id: OTP-15611\n\n- Kernel configuration parameter `start_distribution = boolean()` is added. If\n set to `false`, the system is started with all distribution functionality\n disabled. Defaults to `true`.\n\n Own Id: OTP-15668 Aux Id: PR-2088\n\n- In OTP-21.3, a warning was introduced for duplicated applications/keys in\n configuration. This warning would be displayed both when the configuration was\n given as a file on system start, and during runtime via\n `application:set_env/1,2`.\n\n The warning is now changed to a `badarg` exception in\n `application:set_env/1,2`. If the faulty configuration is given in a\n configuration file on system start, the startup will fail.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15692 Aux Id: PR-2170","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 6.3.1.3 - Kernel Release Notes","ref":"notes.html#kernel-6-3-1-3"},{"type":"extras","doc":"- Fix bug where the log file in `logger_std_h` would not be closed when the\n inode of the file changed. This would in turn cause a file descriptor leak\n when tools like logrotate are used.\n\n Own Id: OTP-15997 Aux Id: PR-2331","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 6.3.1.2 - Kernel Release Notes","ref":"notes.html#kernel-6-3-1-2"},{"type":"extras","doc":"- The possibility to send ancillary data, in particular the TOS field, has been\n added to `gen_udp:send/4,5`.\n\n Own Id: OTP-15747 Aux Id: ERIERL-294","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 6.3.1.1 - Kernel Release Notes","ref":"notes.html#kernel-6-3-1-1"},{"type":"extras","doc":"- Fix type spec for `seq_trace:set_token/2`.\n\n Own Id: OTP-15858 Aux Id: ERL-700","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 6.3.1 - Kernel Release Notes","ref":"notes.html#kernel-6-3-1"},{"type":"extras","doc":"- Fixed a performance regression when reading files opened with the `compressed`\n flag.\n\n Own Id: OTP-15706 Aux Id: ERIERL-336","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 6.3 - Kernel Release Notes","ref":"notes.html#kernel-6-3"},{"type":"extras","doc":"- If for example the `/etc/hosts` did not come into existence until after the\n kernel application had started, its content was never read. This bug has now\n been corrected.\n\n Own Id: OTP-14702 Aux Id: PR-2066\n\n- Fix bug where doing `seq_trace:reset_trace()` while another process was doing\n a garbage collection could cause the run-time system to segfault.\n\n Own Id: OTP-15490\n\n- Fix `erl_epmd:port_please` spec to include `t:atom/0` and `t:string/0`.\n\n Own Id: OTP-15557 Aux Id: PR-2117\n\n- The Logger handler logger_std_h now keeps track of the inode of its log file\n in order to re-open the file if the inode changes. This may happen, for\n instance, if the log file is opened and saved by an editor.\n\n Own Id: OTP-15578 Aux Id: ERL-850\n\n- When user specific file modes are given to the logger handler `logger_std_h`,\n they were earlier accepted without any control. This is now changes, so Logger\n will adjust the file modes as follows:\n\n \\- If `raw` is not found in the list, it is added. \n \\- If none of `write`, `append` or `exclusive` are found in the list, `append`\n is added. \n \\- If none of `delayed_write` or `{delayed_write,Size,Delay}` are found in the\n list, `delayed_write` is added.\n\n Own Id: OTP-15602","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The standard logger handler, `logger_std_h`, now has a new internal feature\n for log rotation. The rotation scheme is as follows:\n\n The log file to which the handler currently writes always has the same name,\n i.e. the name which is configured for the handler. The archived files have the\n same name, but with extension \".N\", where N is an integer. The newest archive\n has extension \".0\", and the oldest archive has the highest number.\n\n The size at which the log file is rotated, and the number of archive files\n that are kept, is specified with the handler specific configuration parameters\n `max_no_bytes` and `max_no_files` respectively.\n\n Archives can be compressed, in which case they get a \".gz\" file extension\n after the integer. Compression is specified with the handler specific\n configuration parameter `compress_on_rotate`.\n\n Own Id: OTP-15479\n\n- The new functions `logger:i/0` and `logger:i/1` are added. These provide the\n same information as `logger:get_config/0` and other `logger:get_*_config`\n functions, but the information is more logically sorted and more readable.\n\n Own Id: OTP-15600\n\n- Logger is now protected against overload due to massive amounts of log events\n from the emulator or from remote nodes.\n\n Own Id: OTP-15601\n\n- Logger now uses os:system_time/1 instead of erlang:system_time/1 to generate\n log event timestamps.\n\n Own Id: OTP-15625\n\n- Add functions `application:set_env/1,2` and `application:set_env/2`. These\n take a list of application configuration parameters, and the behaviour is\n equivalent to calling `application:set_env/4` individually for each\n application/key combination, except it is more efficient.\n\n `set_env/1,2` warns about duplicated applications or keys. The warning is also\n emitted during boot, if applications or keys are duplicated within one\n configuration file, e.g. sys.config.\n\n Own Id: OTP-15642 Aux Id: PR-2164\n\n- Handler specific configuration parameters for the standard handler\n `logger_std_h` are changed to be more intuitive and more similar to the\n disk_log handler.\n\n Earlier there was only one parameter, `type`, which could have the values\n `standard_io`, `standard_error`, `{file,FileName}` or `{file,FileName,Modes}`.\n\n This is now changed, so the following parameters are allowed:\n\n `type = standard_io | standard_error | file` \n `file = file:filename()` \n `modes = [file:mode()]`\n\n All parameters are optional. `type` defaults to `standard_io`, unless a file\n name is given, in which case it defaults to `file`. If `type` is set to\n `file`, the file name defaults to the same as the handler id.\n\n The potential incompatibility is that `logger:get_config/0` and\n `logger:get_handler_config/1` now returns the new parameters, even if the\n configuration was set with the old variant, e.g. `#{type=>{file,FileName}}`.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15662\n\n- The new configuration parameter `file_check` is added to the Logger handler\n `logger_std_h`. This parameter specifies how long (in milliseconds) the\n handler may wait before checking if the log file still exists and the inode is\n the same as when it was opened.\n\n The default value is 0, which means that this check is done prior to each\n write operation. Setting a higher number may improve performance, but adds the\n risk of losing log events.\n\n Own Id: OTP-15663","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 6.2.1 - Kernel Release Notes","ref":"notes.html#kernel-6-2-1"},{"type":"extras","doc":"- Setting the `recbuf` size of an inet socket the `buffer` is also automatically\n increased. Fix a bug where the auto adjustment of inet buffer size would be\n triggered even if an explicit inet buffer size had already been set.\n\n Own Id: OTP-15651 Aux Id: ERIERL-304","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 6.2 - Kernel Release Notes","ref":"notes.html#kernel-6-2"},{"type":"extras","doc":"- A new function, `logger:update_handler_config/3` is added, and the handler\n callback `changing_config` now has a new argument, `SetOrUpdate`, which\n indicates if the configuration change comes from `set_handler_config/2,3` or\n `update_handler_config/2,3`.\n\n This allows the handler to consistently merge the new configuration with the\n old (if the change comes from `update_handler_config/2,3`) or with the default\n (if the change comes from `set_handler_config/2,3`).\n\n The built-in handlers `logger_std_h` and `logger_disk_log_h` are updated\n accordingly. A bug which could cause inconsistency between the handlers'\n internal state and the stored configuration is also corrected.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15364\n\n- Fix fallback when custom erl_epmd client does not implement address_please.\n\n Own Id: OTP-15388 Aux Id: PR-1983\n\n- The logger ets table did not have the `read_concurrency` option. This is now\n added.\n\n Own Id: OTP-15453 Aux Id: ERL-782\n\n- During system start, logger has a simple handler which prints to stdout. After\n the kernel supervision is started, this handler is removed and replaced by the\n default handler. Due to a bug, logger earlier issued a debug printout saying\n it received an unexpected message, which was the EXIT message from the simple\n handler's process. This is now corrected. The simple handler's process now\n unlinks from the logger process before terminating.\n\n Own Id: OTP-15466 Aux Id: ERL-788\n\n- The logger handler `logger_std_h` would not re-create it's log file if it was\n removed. Due to this it could not be used with tools like 'logrotate'. This is\n now corrected.\n\n Own Id: OTP-15469","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- A function `inet:getifaddrs/1` that takes a list with a namespace option has\n been added, for platforms that support that feature, for example Linux\n (only?).\n\n Own Id: OTP-15121 Aux Id: ERIERL-189, PR-1974\n\n- Added the `nopush` option for TCP sockets, which corresponds to `TCP_NOPUSH`\n on \\*BSD and `TCP_CORK` on Linux.\n\n This is also used internally in `file:sendfile` to reduce latency on\n subsequent send operations.\n\n Own Id: OTP-15357 Aux Id: ERL-698\n\n- Optimize handling of send_delay for tcp sockes to better work with the new\n pollthread implementation introduced in OTP-21.\n\n Own Id: OTP-15471 Aux Id: ERIERL-229","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 6.1.1 - Kernel Release Notes","ref":"notes.html#kernel-6-1-1"},{"type":"extras","doc":"- Fix bug causing net_kernel process crash on connection attempt from node with\n name identical to local node.\n\n Own Id: OTP-15438 Aux Id: ERL-781","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 6.1 - Kernel Release Notes","ref":"notes.html#kernel-6-1"},{"type":"extras","doc":"- The values `all` and `none` are documented as valid value for the Kernel\n configuration parameter `logger_level`, but would cause a crash during node\n start. This is now corrected.\n\n Own Id: OTP-15143\n\n- Fix some potential buggy behavior in how ticks are sent on inter node\n distribution connections. Tick is now sent to c-node even if there are unsent\n buffered data, as c-nodes need ticks in order to send reply ticks. The amount\n of sent data was also calculated wrongly when ticks were suppressed due to\n unsent buffered data.\n\n Own Id: OTP-15162 Aux Id: ERIERL-191\n\n- Non semantic change in dist_util.erl to silence dialyzer warning.\n\n Own Id: OTP-15170\n\n- Fixed `net_kernel:connect_node(node())` to return `true` (and do nothing) as\n it always has before OTP-21.0. Also documented this successful \"self connect\"\n as the expected behavior.\n\n Own Id: OTP-15182 Aux Id: ERL-643\n\n- The single_line option on logger_formatter would in some cases add an unwanted\n comma after the association arrows in a map. This is now corrected.\n\n Own Id: OTP-15228\n\n- Improved robustness of distribution connection setup. In OTP-21.0 a truly\n asynchronous connection setup was introduced. This is further improvement on\n that work to make the emulator more robust and also be able to recover in\n cases when involved Erlang processes misbehave.\n\n Own Id: OTP-15297 Aux Id: OTP-15279, OTP-15280","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- A new macro, `?LOG(Level,...)`, is added. This is equivalent to the existing\n `?LOG_ (...)` macros.\n\n A new variant of Logger report callback is added, which takes an extra\n argument containing options for size limiting and line breaks. Module\n `proc_lib` in `STDLIB` uses this for crash reports.\n\n Logger configuration is now checked a bit more for errors.\n\n Own Id: OTP-15132\n\n- The socket options `recvtos`, `recvttl`, `recvtclass` and `pktoptions` have\n been implemented in the socket modules. See the documentation for the\n `gen_tcp`, `gen_udp` and `inet` modules. Note that support for these in the\n runtime system is platform dependent. Especially for `pktoptions` which is\n very Linux specific and obsoleted by the RFCs that defined it.\n\n Own Id: OTP-15145 Aux Id: ERIERL-187\n\n- Add `logger:set_application_level/2` for setting the logger level of all\n modules in one application.\n\n Own Id: OTP-15146","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 6.0.1 - Kernel Release Notes","ref":"notes.html#kernel-6-0-1"},{"type":"extras","doc":"- Fixed bug in `net_kernel` that could cause an emulator crash if certain\n connection attempts failed. Bug exists since kernel-6.0 (OTP-21.0).\n\n Own Id: OTP-15280 Aux Id: ERIERL-226, OTP-15279","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 6.0 - Kernel Release Notes","ref":"notes.html#kernel-6-0"},{"type":"extras","doc":"- Clarify the documentation of `rpc:multicall/5`.\n\n Own Id: OTP-10551\n\n- The DNS resolver when getting econnrefused from a server retained an invalid\n socket so look up towards the next server(s) also failed.\n\n Own Id: OTP-13133 Aux Id: PR-1557\n\n- No resolver backend returns V4Mapped IPv6 addresses any more. This was\n inconsistent before, some did, some did not. To facilitate working with such\n addresses a new function `inet:ipv4_mapped_ipv6_address/1` has been added.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-13761 Aux Id: ERL-503\n\n- The type specifications for [`file:posix/0`](`t:file:posix/0`) and\n [`inet:posix/0`](`t:inet:posix/0`) have been updated according to which errors\n file and socket operations should be able to return.\n\n Own Id: OTP-14019 Aux Id: ERL-550\n\n- Fix name resolving in IPv6 only environments when doing the initial\n distributed connection.\n\n Own Id: OTP-14501\n\n- File operations used to accept [filenames](`t:file:name_all/0`) containing\n null characters (integer value zero). This caused the name to be truncated and\n in some cases arguments to primitive operations to be mixed up. Filenames\n containing null characters inside the filename are now _rejected_ and will\n cause primitive file operations to fail.\n\n Also environment variable operations used to accept\n [names](`t:os:env_var_name/0`) and [values](`t:os:env_var_value/0`) of\n environment variables containing null characters (integer value zero). This\n caused operations to silently produce erroneous results. Environment variable\n names and values containing null characters inside the name or value are now\n _rejected_ and will cause environment variable operations to fail.\n\n Primitive environment variable operations also used to accept the `$=`\n character in environment variable names causing various problems. `$=`\n characters in environment variable names are now also _rejected_.\n\n Also `os:cmd/1` now reject null characters inside its\n [command](`t:os:os_command/0`).\n\n `erlang:open_port/2` will also reject null characters inside the port name\n from now on.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-14543 Aux Id: ERL-370\n\n- `os:putenv` and `os:getenv` no longer access the process environment directly\n and instead work on a thread-safe emulation. The only observable difference is\n that it's _not_ kept in sync with libc `getenv(3)` / `putenv(3)`, so those who\n relied on that behavior in drivers or NIFs will need to add manual\n synchronization.\n\n On Windows this means that you can no longer resolve DLL dependencies by\n modifying the `PATH` just before loading the driver/NIF. To make this less of\n a problem, the emulator now adds the target DLL's folder to the DLL search\n path.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-14666\n\n- Fixed connection tick toward primitive hidden nodes (erl_interface) that could\n cause faulty tick timeout in rare cases when payload data is sent to hidden\n node but not received.\n\n Own Id: OTP-14681\n\n- Make group react immediately on an EXIT-signal from shell in e.g ssh.\n\n Own Id: OTP-14991 Aux Id: PR1705\n\n- Calls to `gen_tcp:send/2` on closed sockets now returns `{error, closed}`\n instead of `{error,enotconn}`.\n\n Own Id: OTP-15001\n\n- The `included_applications` key are no longer duplicated as application\n environment variable. Earlier, the included applications could be read both\n with `application:get[_all]_env(...)` and `application:get[_all]_key(...)`\n functions. Now, it can only be read with `application:get[_all]_key(...)`.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15071\n\n- Owner and group changes through `file:write_file_info`, `file:change_owner`,\n and `file:change_group` will no longer report success on permission errors.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15118","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- A new logging API is added to Erlang/OTP, see the `m:logger` manual page, and\n section [Logging](logger_chapter.md) in the Kernel User's Guide.\n\n Calls to `error_logger` are automatically redirected to the new API, and\n legacy error logger event handlers can still be used. It is, however,\n recommended to use the Logger API directly when writing new code.\n\n Notice the following potential incompatibilities:\n\n - Kernel configuration parameters `error_logger` still works, but is overruled\n if the default handler's output destination is configured with Kernel\n configuration parameter `logger`.\n\n In general, parameters for configuring error logger are overwritten by new\n parameters for configuring Logger.\n\n - The concept of SASL error logging is deprecated, meaning that by default the\n SASL application does not affect which log events are logged.\n\n By default, supervisor reports and crash reports are logged by the default\n Logger handler started by Kernel, and end up at the same destination\n (terminal or file) as other standard log event from Erlang/OTP.\n\n Progress reports are not logged by default, but can be enabled by setting\n the primary log level to info, for example with the Kernel configuration\n parameter `logger_level`.\n\n To obtain backwards compatibility with the SASL error logging functionality\n from earlier releases, set Kernel configuration parameter\n `logger_sasl_compatible` to `true`. This prevents the default Logger handler\n from logging any supervisor-, crash-, or progress reports. Instead, SASL\n adds a separate Logger handler during application start, which takes care of\n these log events. The SASL configuration parameters `sasl_error_logger` and\n `sasl_errlog_type` specify the destination (terminal or file) and severity\n level to log for these events.\n\n Since Logger is new in Erlang/OTP 21.0, we do reserve the right to introduce\n changes to the Logger API and functionality in patches following this release.\n These changes might or might not be backwards compatible with the initial\n version.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-13295\n\n- The function `inet:i/0` has been documented.\n\n Own Id: OTP-13713 Aux Id: PR-1645\n\n- Typespecs for `netns` and `bind_to_device` options have been added to\n `gen_tcp`, `gen_udp` and `gen_sctp` functions.\n\n Own Id: OTP-14359 Aux Id: PR-1816\n\n- New functionality for implementation of alternative carriers for the Erlang\n distribution has been introduced. This mainly consists of support for usage of\n distribution controller processes (previously only ports could be used as\n distribution controllers). For more information see\n [ERTS User's Guide ➜ How to implement an Alternative Carrier for the Erlang Distribution ➜ Distribution Module](`e:erts:alt_dist.md#distribution-module`).\n\n Own Id: OTP-14459\n\n- `seq_trace` labels may now be any erlang term.\n\n Own Id: OTP-14899\n\n- The SSL distribution protocol `-proto inet_tls` has stopped setting the SSL\n option `server_name_indication`. New verify funs for client and server in\n `inet_tls_dist` has been added, not documented yet, that checks node name if\n present in peer certificate. Usage is still also yet to be documented.\n\n Own Id: OTP-14969 Aux Id: OTP-14465, ERL-598\n\n- Changed timeout of `gen_server` calls to `auth` server from default 5 seconds\n to `infinity`.\n\n Own Id: OTP-15009 Aux Id: ERL-601\n\n- The callback module passed as `-epmd_module` to erl has been expanded to be\n able to do name and port resolving.\n\n Documentation has also been added in the `m:erl_epmd` reference manual and\n ERTS User's Guide\n [How to Implement an Alternative Node Discovery for Erlang Distribution](`e:erts:alt_disco.md`).\n\n Own Id: OTP-15086 Aux Id: PR-1694\n\n- Included config file specified with relative path in sys.config are now first\n searched for relative to the directory of sys.config itself. If not found, it\n is also searched for relative to the current working directory. The latter is\n for backwards compatibility.\n\n Own Id: OTP-15137 Aux Id: PR-1838","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 5.4.3.2 - Kernel Release Notes","ref":"notes.html#kernel-5-4-3-2"},{"type":"extras","doc":"- Non semantic change in dist_util.erl to silence dialyzer warning.\n\n Own Id: OTP-15170","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 5.4.3.1 - Kernel Release Notes","ref":"notes.html#kernel-5-4-3-1"},{"type":"extras","doc":"- Fix some potential buggy behavior in how ticks are sent on inter node\n distribution connections. Tick is now sent to c-node even if there are unsent\n buffered data, as c-nodes need ticks in order to send reply ticks. The amount\n of sent data was calculated wrongly when ticks where suppressed due to unsent\n buffered data.\n\n Own Id: OTP-15162 Aux Id: ERIERL-191","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 5.4.3 - Kernel Release Notes","ref":"notes.html#kernel-5-4-3"},{"type":"extras","doc":"- Correct a few contracts.\n\n Own Id: OTP-14889\n\n- Reject loading modules with names containing directory separators ('/' or '\\\\'\n on Windows).\n\n Own Id: OTP-14933 Aux Id: ERL-564, PR-1716\n\n- Fix bug in handling of os:cmd/2 option max_size on windows.\n\n Own Id: OTP-14940","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 5.4.2 - Kernel Release Notes","ref":"notes.html#kernel-5-4-2"},{"type":"extras","doc":"- Add `os:cmd/2` that takes an options map as the second argument.\n\n Add `max_size` as an option to `os:cmd/2` that control the maximum size of the\n result that `os:cmd/2` will return.\n\n Own Id: OTP-14823","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 5.4.1 - Kernel Release Notes","ref":"notes.html#kernel-5-4-1"},{"type":"extras","doc":"- Refactored an internal API.\n\n Own Id: OTP-14784","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 5.4 - Kernel Release Notes","ref":"notes.html#kernel-5-4"},{"type":"extras","doc":"- Processes which did output after switching jobs (Ctrl+G) could be left forever\n stuck in the io request.\n\n Own Id: OTP-14571 Aux Id: ERL-472","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Lock counting can now be fully toggled at runtime in the lock counting\n emulator (`-emu_type lcnt`). Everything is enabled by default to match the old\n behavior, but specific categories can be toggled at will with minimal runtime\n overhead when disabled. Refer to the documentation on `lcnt:rt_mask/1` for\n details.\n\n Own Id: OTP-13170\n\n- `lcnt:collect` and `lcnt:clear` will no longer block all other threads in the\n runtime system.\n\n Own Id: OTP-14412\n\n- General Unicode improvements.\n\n Own Id: OTP-14462","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 5.3.1 - Kernel Release Notes","ref":"notes.html#kernel-5-3-1"},{"type":"extras","doc":"- The documentation for the 'quiet' option in disk_log:open/1 had an incorrect\n default value.\n\n Own Id: OTP-14498","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 5.3 - Kernel Release Notes","ref":"notes.html#kernel-5-3"},{"type":"extras","doc":"- Function `inet:ntoa/1` has been fixed to return lowercase letters according to\n RFC 5935 that has been approved after this function was written. Previously\n uppercase letters were returned so this may be a backwards incompatible change\n depending on how the returned address string is used.\n\n Function `inet:parse_address/1` has been fixed to accept %-suffixes on scoped\n addresses. The addresses does not work yet, but gives no parse errors.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-13006 Aux Id: ERIERL-20, ERL-429\n\n- Fix bug where gethostname would incorrectly fail with enametoolong on Linux.\n\n Own Id: OTP-14310\n\n- Fix bug causing `code:is_module_native` to falsely return true when `local`\n call trace is enabled for the module.\n\n Own Id: OTP-14390\n\n- Add early reject of invalid node names from distributed nodes.\n\n Own Id: OTP-14426","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Since Unicode is now allowed in atoms an extra check is needed for node names,\n which are restricted to Latin-1.\n\n Own Id: OTP-13805\n\n- Replaced usage of deprecated symbolic [`time unit`](`t:erlang:time_unit/0`)\n representations.\n\n Own Id: OTP-13831 Aux Id: OTP-13735\n\n- `file:write_file(Name, Data, [raw])` would turn `Data` into a single binary\n before writing. This meant it could not take advantage of the `writev()`\n system call if it was given a list of binaries and told to write with `raw`\n mode.\n\n Own Id: OTP-13909\n\n- The performance of the `disk_log` has been somewhat improved in some corner\n cases (big items), and the documentation has been clarified.\n\n Own Id: OTP-14057 Aux Id: PR-1245\n\n- Functions for detecting changed code has been added. `code:modified_modules/0`\n returns all currently loaded modules that have changed on disk.\n `code:module_status/1` returns the status for a module. In the shell and in\n `c` module, `mm/0` is short for `code:modified_modules/0`, and `lm/0` reloads\n all currently loaded modules that have changed on disk.\n\n Own Id: OTP-14059\n\n- Introduce an event manager in Erlang to handle OS signals. A subset of OS\n signals may be subscribed to and those are described in the Kernel\n application.\n\n Own Id: OTP-14186\n\n- Sockets can now be bound to device (SO_BINDTODEVICE) on platforms where it is\n supported.\n\n This has been implemented e.g to support VRF-Lite under Linux; see\n [VRF ](https://www.kernel.org/doc/Documentation/networking/vrf.txt), and\n GitHub pull request [\\#1326](https://github.com/erlang/otp/pull/1326).\n\n Own Id: OTP-14357 Aux Id: PR-1326\n\n- Added option to store shell_history on disk so that the history can be reused\n between sessions.\n\n Own Id: OTP-14409 Aux Id: PR-1420\n\n- The size of crash reports created by `gen_server`, `gen_statem` and `proc_lib`\n is limited with aid of the Kernel application variable\n `error_logger_format_depth`. The purpose is to limit the size of the messages\n sent to the `error_logger` process when processes with huge message queues or\n states crash.\n\n The crash report generated by `proc_lib` includes the new tag\n `message_queue_len`. The neighbour report also includes the new tag\n `current_stacktrace`. Finally, the neighbour report no longer includes the\n tags `messages` and `dictionary`.\n\n The new function `error_logger:get_format_depth/0` can be used to retrieve the\n value of the Kernel application variable `error_logger_format_depth`.\n\n Own Id: OTP-14417\n\n- One of the ETS tables used by the `global` module is created with\n `{read_concurrency, true}` in order to reduce contention.\n\n Own Id: OTP-14419\n\n- Warnings have been added to the relevant documentation about not using\n un-secure distributed nodes in exposed environments.\n\n Own Id: OTP-14425","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 5.2 - Kernel Release Notes","ref":"notes.html#kernel-5-2"},{"type":"extras","doc":"- Fix a race during cleanup of os:cmd that would cause os:cmd to hang\n indefinitely.\n\n Own Id: OTP-14232 Aux Id: seq13275","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The functions in the '`file`' module that take a list of paths (e.g.\n `file:path_consult/2`) will now continue to search in the path if the path\n contains something that is not a directory.\n\n Own Id: OTP-14191\n\n- Two OTP processes that are known to receive many messages are 'rex' (used by\n 'rpc') and 'error_logger'. Those processes will now store unprocessed messages\n outside the process heap, which will potentially decrease the cost of garbage\n collections.\n\n Own Id: OTP-14192","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 5.1.1 - Kernel Release Notes","ref":"notes.html#kernel-5-1-1"},{"type":"extras","doc":"- `code:add_pathsa/1` and command line option `-pa` both revert the given list\n of directories when adding it at the beginning of the code path. This is now\n documented.\n\n Own Id: OTP-13920 Aux Id: ERL-267\n\n- Add lost runtime dependency to erts-8.1. This should have been done in\n kernel-5.1 (OTP-19.1) as it cannot run without at least erts-8.1 (OTP-19.1).\n\n Own Id: OTP-14003\n\n- Type and doc for gen\\_\\{tcp,udp,sctp\\}:controlling_process/2 has been\n improved.\n\n Own Id: OTP-14022 Aux Id: PR-1208","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 5.1 - Kernel Release Notes","ref":"notes.html#kernel-5-1"},{"type":"extras","doc":"- Fix a memory leak when calling seq_trace:get_system_tracer().\n\n Own Id: OTP-13742\n\n- Fix for the problem that when adding the ebin directory of an application to\n the code path, the `code:priv_dir/1` function returns an incorrect path to the\n priv directory of the same application.\n\n Own Id: OTP-13758 Aux Id: ERL-195\n\n- Fix code_server crash when adding code paths of two levels.\n\n Own Id: OTP-13765 Aux Id: ERL-194\n\n- Respect -proto_dist switch while connection to EPMD\n\n Own Id: OTP-13770 Aux Id: PR-1129\n\n- Fixed a bug where init:stop could deadlock if a process with infinite shutdown\n timeout (e.g. a supervisor) attempted to load code while terminating.\n\n Own Id: OTP-13802\n\n- Close stdin of commands run in os:cmd. This is a backwards compatibility fix\n that restores the behaviour of pre 19.0 os:cmd.\n\n Own Id: OTP-13867 Aux Id: seq13178","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add `net_kernel:setopts/2` and `net_kernel:getopts/2` to control options for\n distribution sockets in runtime.\n\n Own Id: OTP-13564\n\n- Rudimentary support for DSCP has been implemented in the guise of a `tclass`\n socket option for IPv6 sockets.\n\n Own Id: OTP-13582","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 5.0.2 - Kernel Release Notes","ref":"notes.html#kernel-5-0-2"},{"type":"extras","doc":"- When calling os:cmd from a process that has set trap_exit to true an 'EXIT'\n message would be left in the message queue. This bug was introduced in kernel\n vsn 5.0.1.\n\n Own Id: OTP-13813","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 5.0.1 - Kernel Release Notes","ref":"notes.html#kernel-5-0-1"},{"type":"extras","doc":"- Fix a os:cmd bug where creating a background job using & would cause os:cmd to\n hang until the background job terminated or closed its stdout and stderr file\n descriptors. This bug has existed from kernel 5.0.\n\n Own Id: OTP-13741","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 5.0 - Kernel Release Notes","ref":"notes.html#kernel-5-0"},{"type":"extras","doc":"- The handling of `on_load` functions has been improved. The major improvement\n is that if a code upgrade fails because the `on_load` function fails, the\n previous version of the module will now be retained.\n\n Own Id: OTP-12593\n\n- `rpc:call()` and `rpc:block_call()` would sometimes cause an exception (which\n was not mentioned in the documentation). This has been corrected so that\n `{badrpc,Reason}` will be returned instead.\n\n Own Id: OTP-13409\n\n- On Windows, for modules that were loaded early (such as the `lists` module),\n `code:which/1` would return the path with mixed slashes and backslashes, for\n example: `\"C:\\\\Program Files\\\\erl8.0/lib/stdlib-2.7/ebin/lists.beam\"`. This\n has been corrected.\n\n Own Id: OTP-13410\n\n- Make file:datasync use fsync instead of fdatasync on Mac OSX.\n\n Own Id: OTP-13411\n\n- The default chunk size for the fallback sendfile implementation, used on\n platforms that do not have a native sendfile, has been decreased in order to\n reduce connectivity issues.\n\n Own Id: OTP-13444\n\n- Large file writes (2Gb or more) could fail on some Unix platforms (for\n example, OS X and FreeBSD).\n\n Own Id: OTP-13461\n\n- A bug has been fixed where the DNS resolver inet_res did not refresh its view\n of the contents of for example resolv.conf immediately after start and hence\n then failed name resolution. Reported and fix suggested by Michal Ptaszek in\n GitHUB pull req #949.\n\n Own Id: OTP-13470 Aux Id: Pull #969\n\n- Fix process leak from global_group.\n\n Own Id: OTP-13516 Aux Id: PR-1008\n\n- The function `inet:gethostbyname/1` now honors the resolver option `inet6`\n instead of always looking up IPv4 addresses.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-13622 Aux Id: PR-1065\n\n- The `Status` argument to `init:stop/1` is now sanity checked to make sure\n `erlang:halt` does not fail.\n\n Own Id: OTP-13631 Aux Id: PR-911","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add \\{line_delim, byte()\\} option to inet:setopts/2 and decode_packet/3\n\n Own Id: OTP-12837\n\n- Added `os:perf_counter/1`.\n\n The perf_counter is a very very cheap and high resolution timer that can be\n used to timestamp system events. It does not have monoticity guarantees, but\n should on most OS's expose a monotonous time.\n\n Own Id: OTP-12908\n\n- The os:cmd call has been optimized on unix platforms to be scale better with\n the number of schedulers.\n\n Own Id: OTP-13089\n\n- New functions that can load multiple modules at once have been added to the\n '`code`' module. The functions are `code:atomic_load/1`,\n `code:prepare_loading/1`, `code:finish_loading/1`, and\n `code:ensure_modules_loaded/1`.\n\n Own Id: OTP-13111\n\n- The code path cache feature turned out not to be very useful in practice and\n has been removed. If an attempt is made to enable the code path cache, there\n will be a warning report informing the user that the feature has been removed.\n\n Own Id: OTP-13191\n\n- When an attempt is made to start a distributed Erlang node with the same name\n as an existing node, the error message will be much shorter and easier to read\n than before. Example:\n\n `Protocol 'inet_tcp': the name somename@somehost seems to be in use by another Erlang node`\n\n Own Id: OTP-13294\n\n- The output of the default error logger is somewhat prettier and easier to\n read. The default error logger is used during start-up of the OTP system. If\n the start-up fails, the output will be easier to read.\n\n Own Id: OTP-13325\n\n- The functions `rpc:safe_multi_server_call/2,3` that were deprecated in R12B\n have been removed.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-13449\n\n- Update the error reasons in dist_util, and show them in the logs if\n net_kernel:verbose(1) has been called.\n\n Own Id: OTP-13458\n\n- Experimental support for Unix Domain Sockets has been implemented. Read the\n sources if you want to try it out. Example:\n `gen_udp:open(0, [{ifaddr,{local,\"/tmp/socket\"}}])`. Documentation will be\n written after user feedback on the experimental API.\n\n Own Id: OTP-13572 Aux Id: PR-612\n\n- Allow heart to be configured to not kill the previous emulator before calling\n the HEART_COMMAND. This is done by setting the environment variable\n HEART_NO_KILL to TRUE.\n\n Own Id: OTP-13650","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 4.2 - Kernel Release Notes","ref":"notes.html#kernel-4-2"},{"type":"extras","doc":"- `code:load_abs([10100])` would bring down the entire runtime system and create\n a crash dump. Corrected to generate an error exception in the calling process.\n\n Also corrected specs for code loading functions and added more information in\n the documentation about the error reasons returned by code-loading functions.\n\n Own Id: OTP-9375\n\n- `gen_tcp:accept/2` was not\n [time warp safe](`e:erts:time_correction.md#time-warp-safe-code`). This since\n it used the same time as returned by `erlang:now/0` when calculating timeout.\n This has now been fixed.\n\n Own Id: OTP-13254 Aux Id: OTP-11997, OTP-13222\n\n- Correct the contract for `inet:getifaddrs/1`.\n\n Own Id: OTP-13335 Aux Id: ERL-95","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Time warp safety improvements.\n\n Introduced the options `monotonic_timestamp`, and `strict_monotonic_timestamp`\n to the trace, sequential trace, and system profile functionality. This since\n the already existing `timestamp` option is not time warp safe.\n\n Introduced the option `safe_fixed_monotonic_time` to `ets:info/2` and\n `dets:info/2`. This since the already existing `safe_fixed` option is not time\n warp safe.\n\n Own Id: OTP-13222 Aux Id: OTP-11997\n\n- Add validation callback for heart\n\n The erlang heart process may now have a validation callback installed. The\n validation callback will be executed, if present, before any heartbeat to\n heart port program. If the validation fails, or stalls, no heartbeat will be\n sent and the node will go down.\n\n With the option `'check_schedulers'` heart executes a responsiveness check of\n the schedulers before a heartbeat is sent to the port program. If the\n responsiveness check fails, the heartbeat will not be performed (as intended).\n\n Own Id: OTP-13250\n\n- Clarify documentation of `net_kernel:allow/1`\n\n Own Id: OTP-13299\n\n- EPMD supports both IPv4 and IPv6\n\n Also affects oldest supported windows version.\n\n Own Id: OTP-13364","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 4.1.1 - Kernel Release Notes","ref":"notes.html#kernel-4-1-1"},{"type":"extras","doc":"- Host name lookups though inet_res, the Erlang DNS resolver, are now done case\n insensitively according to RFC 4343. Patch by Holger Weiß.\n\n Own Id: OTP-12836\n\n- IPv6 distribution handler has been updated to share code with IPv4 so that all\n features are supported in IPv6 as well. A bug when using an IPv4 address as\n hostname has been fixed.\n\n Own Id: OTP-13040\n\n- Caching of host names in the internal DNS resolver inet_res has been made\n character case insensitive for host names according to RFC 4343.\n\n Own Id: OTP-13083\n\n- Cooked file mode buffering has been fixed so file:position/2 now works\n according to Posix on Posix systems i.e. when file:position/2 returns an error\n the file pointer is unaffected.\n\n The Windows system documentation, however, is unclear on this point so the\n documentation of file:position/2 still does not promise anything.\n\n Cooked file mode file:pread/2,3 and file:pwrite/2,3 have been corrected to\n honor character encoding like the combination of file:position/2 and\n file:read/2 or file:write/2 already does. This is probably not very useful\n since the character representation on the caller's side is latin1, period.\n\n Own Id: OTP-13155 Aux Id: PR#646","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add \\{line_delim, byte()\\} option to inet:setopts/2 and decode_packet/3\n\n Own Id: OTP-12837","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 4.1 - Kernel Release Notes","ref":"notes.html#kernel-4-1"},{"type":"extras","doc":"- A mechanism for limiting the amount of text that the built-in error logger\n events will produce has been introduced. It is useful for limiting both the\n size of log files and the CPU time used to produce them.\n\n This mechanism is experimental in the sense that it may be changed if it turns\n out that it does not solve the problem it is supposed to solve. In that case,\n there may be backward incompatible improvements to this mechanism.\n\n See the documentation for the config parameter `error_logger_format_depth` in\n the Kernel application for information about how to turn on this feature.\n\n Own Id: OTP-12864","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 4.0 - Kernel Release Notes","ref":"notes.html#kernel-4-0"},{"type":"extras","doc":"- Fix error handling in `file:read_line/1` for Unicode contents.\n\n Own Id: OTP-12144\n\n- Introduce `os:getenv/2` which is similar to `os:getenv/1` but returns the\n passed default value if the required environment variable is undefined.\n\n Own Id: OTP-12342\n\n- It is now possible to paste text in JCL mode (using Ctrl-Y) that has been\n copied in the previous shell session. Also a bug that caused the JCL mode to\n crash when pasting text has been fixed.\n\n Own Id: OTP-12673\n\n- Ensure that each segment of an IPv6 address when parsed from a string has a\n maximum of 4 hex digits\n\n Own Id: OTP-12773","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- New BIF: `erlang:get_keys/0`, lists all keys associated with the process\n dictionary. Note: `erlang:get_keys/0` is auto-imported.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-12151 Aux Id: seq12521\n\n- The internal group to user_drv protocol has been changed to be synchronous in\n order to guarantee that output sent to a process implementing the user_drv\n protocol is printed before replying. This protocol is used by the\n standard_output device and the ssh application when acting as a client.\n\n This change changes the previous unlimited buffer when printing to standard_io\n and other devices that end up in user_drv to 1KB.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-12240\n\n- The `inflateInit/2` and `deflateInit/6` functions now accepts a WindowBits\n argument equal to 8 and -8.\n\n Own Id: OTP-12564\n\n- Map error logger warnings to warning messages by default.\n\n Own Id: OTP-12755\n\n- Map beam error logger warnings to warning messages by default. Previously\n these messages were mapped to the error channel by default.\n\n Own Id: OTP-12781\n\n- gen_tcp:shutdown/2 is now asynchronous\n\n This solves the following problems with the old implementation:\n\n It doesn't block when the TCP peer is idle or slow. This is the expected\n behaviour when shutdown() is called: the caller needs to be able to continue\n reading from the socket, not be prevented from doing so.\n\n It doesn't truncate the output. The current version of gen_tcp:shutdown/2 will\n truncate any outbound data in the driver queue after about 10 seconds if the\n TCP peer is idle of slow. Worse yet, it doesn't even inform anyone that the\n data has been truncated: 'ok' is returned to the caller; and a FIN rather than\n an RST is sent to the TCP peer.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-12797\n\n- There are many cases where user code needs to be able to distinguish between a\n socket that was closed normally and one that was aborted. Setting the option\n \\{show_econnreset, true\\} enables the user to receive ECONNRESET errors on\n both active and passive sockets.\n\n Own Id: OTP-12843","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 3.2.0.1 - Kernel Release Notes","ref":"notes.html#kernel-3-2-0-1"},{"type":"extras","doc":"- The 'raw' socket option could not be used multiple times in one call to any\n e.g gen_tcp function because only one of the occurrences were used. This bug\n has been fixed, and also a small bug concerning propagating error codes from\n within inet:setopts/2.\n\n Own Id: OTP-11482 Aux Id: seq12872","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 3.2 - Kernel Release Notes","ref":"notes.html#kernel-3-2"},{"type":"extras","doc":"- A bug causing an infinite loop in hostname resolving has been corrected. To\n trigger this bug you would have to enter an bogus search method from a\n configuration file e.g .inetrc.\n\n Bug pinpointed by Emil Holmström\n\n Own Id: OTP-12133\n\n- The standard_error process now handles the getopts I/O protocol request\n correctly and stores its encoding in the same way as standard_io.\n\n Also, io:put_chars(standard_error, \\[oops]) could previously crash the\n standard_error process. This is now corrected.\n\n Own Id: OTP-12424","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Configuration parameters for the Kernel application that allows setting socket\n options for the distribution sockets have been added. See the application\n Kernel documentation; parameters 'inet_dist_listen_options' and\n 'inet_dist_connect_options'.\n\n Own Id: OTP-12476 Aux Id: OTP-12476","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 3.1 - Kernel Release Notes","ref":"notes.html#kernel-3-1"},{"type":"extras","doc":"- Make sure to install .hrl files when needed\n\n Own Id: OTP-12197\n\n- Removed the undocumented application environment variable 'raw_files' from the\n kernel application. This variable was checked (by call to\n application:get_env/2) each time a raw file was to be opened in the file\n module.\n\n Own Id: OTP-12276\n\n- A bug has been fixed when using the netns option to gen_udp, which\n accidentally only worked if it was the last option.\n\n Own Id: OTP-12314","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Updated documentation for inet buffer size options.\n\n Own Id: OTP-12296\n\n- Introduce new option 'raw' in file_info and link_info functions. This option\n allows the caller not to go through the file server for information about\n files guaranteed to be local.\n\n Own Id: OTP-12325","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 3.0.3 - Kernel Release Notes","ref":"notes.html#kernel-3-0-3"},{"type":"extras","doc":"- Accept inet:ip_address() in net_adm:names/1\n\n Own Id: OTP-12154","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 3.0.2 - Kernel Release Notes","ref":"notes.html#kernel-3-0-2"},{"type":"extras","doc":"- OTP-11850 fixed filelib:wildcard/1 to work with broken symlinks. This\n correction, however, introduced problems since symlinks were no longer\n followed for functions like filelib:ensure_dir/1, filelib:is_dir/1,\n filelib:file_size/1, etc. This is now corrected.\n\n Own Id: OTP-12054 Aux Id: seq12660","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 3.0.1 - Kernel Release Notes","ref":"notes.html#kernel-3-0-1"},{"type":"extras","doc":"- If the Config given to application_controller:change_application_data included\n other config files, it was only expanded for already existing (loaded)\n applications. If an upgrade added a new application which had config data in\n an included config file, the new application did not get correct config data.\n\n This is now changed so config data will be expanded for all applications.\n\n Own Id: OTP-11864\n\n- It was allowed to re-load pre-loaded modules such as `erlang`, but that could\n cause strange and unwanted things to happen, such as call\n [`apply/3`](`apply/3`) to loop. Pre-loaded modules are now sticky by default.\n (Thanks to Loïc Hoguin for reporting this bug.)\n\n `code:add_path(\"/ending/in/slash/\")` removes the trailing slash, adding\n `/ending/in/slash` to the code path. However,\n `code:del_path(\"/ending/in/slash/\")` would fail to remove the path since it\n did not remove the trailing slash. This has been fixed.\n\n Own Id: OTP-11913\n\n- Fix erts_debug:size/1 to handle Map sizes\n\n Own Id: OTP-11923\n\n- The documentation for `file:file_info/1` has been removed. The function itself\n was removed a long time ago.\n\n Own Id: OTP-11982","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 3.0 - Kernel Release Notes","ref":"notes.html#kernel-3-0"},{"type":"extras","doc":"- Fixed a deadlock possibility in terminate application\n\n Own Id: OTP-11171\n\n- Fixed bug where sendfile would return the wrong error code for a remotely\n closed socket if the socket was in passive mode. (Thanks to Vincent Siliakus\n for reporting the bug.)\n\n Own Id: OTP-11614\n\n- The new option `persistent` is added to `application:set_env/4` and\n `application:unset_env/3`. An environment key set with the `persistent` option\n will not be overridden by the ones configured in the application resource file\n on load. This means persistent values will stick after the application is\n loaded and also on application reload. (Thanks to José Valim)\n\n Own Id: OTP-11708\n\n- The spec for file:set_cwd/1 is modified to also accept binaries as arguments.\n This has always been allowed in the code, but it was not reflected in the spec\n since binaries are mostly used for raw file names. Raw file names are names\n that are not encoded according to file:native_name_encoding(), and these are\n not allowed in file:set_cwd/1. The spec is now, however, more allowing in\n order to avoid unnecessary dialyzer warnings. Raw file names will still fail\n in runtime with reason 'no_translation'. (Thanks to José Valim)\n\n Own Id: OTP-11787","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- heart:set_cmd/1 is updated to allow unicode code points > 255 in the given\n heart command\n\n Own Id: OTP-10843\n\n- Dialyzer's `unmatched_return` warnings have been corrected.\n\n Own Id: OTP-10908\n\n- Make erlang:open_port/2 spawn and spawn_executable handle unicode.\n\n Own Id: OTP-11105\n\n- Erlang/OTP has been ported to the realtime operating system OSE. The port\n supports both smp and non-smp emulator. For details around the port and how to\n started see the User's Guide in the ose application.\n\n Note that not all parts of Erlang/OTP has been ported.\n\n Notable things that work are: non-smp and smp emulators, OSE signal\n interaction, crypto, asn1, run_erl/to_erl, tcp, epmd, distribution and most if\n not all non-os specific functionality of Erlang.\n\n Notable things that does not work are: udp/sctp, os_mon, erl_interface,\n binding of schedulers.\n\n Own Id: OTP-11334\n\n- Add the \\{active,N\\} socket option for TCP, UDP, and SCTP, where N is an\n integer in the range -32768..32767, to allow a caller to specify the number of\n data messages to be delivered to the controlling process. Once the socket's\n delivered message count either reaches 0 or is explicitly set to 0 with\n inet:setopts/2 or by including \\{active,0\\} as an option when the socket is\n created, the socket transitions to passive (\\{active, false\\}) mode and the\n socket's controlling process receives a message to inform it of the\n transition. TCP sockets receive \\{tcp_passive,Socket\\}, UDP sockets receive\n \\{udp_passive,Socket\\} and SCTP sockets receive \\{sctp_passive,Socket\\}.\n\n The socket's delivered message counter defaults to 0, but it can be set using\n \\{active,N\\} via any gen_tcp, gen_udp, or gen_sctp function that takes socket\n options as arguments, or via inet:setopts/2. New N values are added to the\n socket's current counter value, and negative numbers can be used to reduce the\n counter value. Specifying a number that would cause the socket's counter value\n to go above 32767 causes an einval error. If a negative number is specified\n such that the counter value would become negative, the socket's counter value\n is set to 0 and the socket transitions to passive mode. If the counter value\n is already 0 and inet:setopts(Socket, \\[\\{active,0\\}]) is specified, the\n counter value remains at 0 but the appropriate passive mode transition message\n is generated for the socket.\n\n Thanks to Steve Vinoski\n\n Own Id: OTP-11368\n\n- A call to either the [`garbage_collect/1`](`garbage_collect/1`) BIF or the\n [`check_process_code/2`](`check_process_code/2`) BIF may trigger garbage\n collection of another processes than the process calling the BIF. The previous\n implementations performed these kinds of garbage collections without\n considering the internal state of the process being garbage collected. In\n order to be able to more easily and more efficiently implement yielding native\n code, these types of garbage collections have been rewritten. A garbage\n collection like this is now triggered by an asynchronous request signal, the\n actual garbage collection is performed by the process being garbage collected\n itself, and finalized by a reply signal to the process issuing the request.\n Using this approach processes can disable garbage collection and yield without\n having to set up the heap in a state that can be garbage collected.\n\n The [`garbage_collect/2`](`erlang:garbage_collect/2`), and\n [`check_process_code/3`](`erlang:check_process_code/3`) BIFs have been\n introduced. Both taking an option list as last argument. Using these, one can\n issue asynchronous requests.\n\n `code:purge/1` and `code:soft_purge/1` have been rewritten to utilize\n asynchronous `check_process_code` requests in order to parallelize work.\n\n Characteristics impact: A call to the\n [`garbage_collect/1`](`garbage_collect/1`) BIF or the\n [`check_process_code/2`](`check_process_code/2`) BIF will normally take longer\n time to complete while the system as a whole won't be as much negatively\n effected by the operation as before. A call to `code:purge/1` and\n `code:soft_purge/1` may complete faster or slower depending on the state of\n the system while the system as a whole won't be as much negatively effected by\n the operation as before.\n\n Own Id: OTP-11388 Aux Id: OTP-11535, OTP-11648\n\n- Add sync option to file:open/2.\n\n The sync option adds the POSIX O_SYNC flag to the open system call on\n platforms that support the flag or its equivalent, e.g.,\n FILE_FLAG_WRITE_THROUGH on Windows. For platforms that don't support it,\n file:open/2 returns \\{error, enotsup\\} if the sync option is passed in. Thank\n to Steve Vinoski and Joseph Blomstedt\n\n Own Id: OTP-11498\n\n- The contract of `inet:ntoa/1` has been corrected.\n\n Thanks to Max Treskin.\n\n Own Id: OTP-11730","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.16.4.1 - Kernel Release Notes","ref":"notes.html#kernel-2-16-4-1"},{"type":"extras","doc":"- When using gen_tcp:connect and the `fd` option with `port` and/or `ip`, the\n `port` and `ip` options were ignored. This has been fixed so that if `port`\n and/or `ip` is specified together with `fd` a bind is requested for that `fd`.\n If `port` and/or `ip` is not specified bind will not be called.\n\n Own Id: OTP-12061","title":"Known Bugs and Problems - Kernel Release Notes","ref":"notes.html#known-bugs-and-problems"},{"type":"extras","doc":"","title":"Kernel 2.16.4 - Kernel Release Notes","ref":"notes.html#kernel-2-16-4"},{"type":"extras","doc":"- Fix the typespec for the inet:ifget/2 and inet:ifget/3 return value. Thanks to\n Ali Sabil.\n\n Own Id: OTP-11377\n\n- Fix various typos in erts, kernel and ssh. Thanks to Martin Hässler.\n\n Own Id: OTP-11414\n\n- Fix rpc multicall sample code. Thanks to Edwin Fine.\n\n Own Id: OTP-11471\n\n- Under rare circumstances a process calling `inet:close/1`, `gen_tcp:close/1`,\n `gen_udp:close/1`, or `gen_sctp:close/1` could hang in the call indefinitely.\n\n Own Id: OTP-11491","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add more SCTP errors as described in RFC 4960. Thanks to Artem Teslenko.\n\n Own Id: OTP-11379\n\n- Add new BIF os:unsetenv/1 which deletes an environment variable. Thanks to\n Martin Hässler.\n\n Own Id: OTP-11446","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.16.3 - Kernel Release Notes","ref":"notes.html#kernel-2-16-3"},{"type":"extras","doc":"- Fix indentation of User switch command help in Erlang shell. Thanks to Sylvain\n Benner.\n\n Own Id: OTP-11209","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The previous undocumented function ntoa/1 has been added to inet docs and\n exported in the inet module.\n\n Own Id: OTP-10676 Aux Id: OTP-10314\n\n- Fix typo in abcast() function comment. Thanks to Johannes Weissl.\n\n Own Id: OTP-11219\n\n- Add application:ensure_all_started/1-2. Thanks to Fred Hebert.\n\n Own Id: OTP-11250\n\n- Make edlin understand a few important control keys. Thanks to Stefan\n Zegenhagen.\n\n Own Id: OTP-11251\n\n- Cleanup of hipe_unified_loader, eliminating uses of is_subtype/2 in specs,\n change module-local void functions to return 'ok' instead of [] and made sure\n there are no dialyzer warnings with --Wunmatched_returns. Thanks to Kostis\n Sagonas.\n\n Own Id: OTP-11301","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.16.2 - Kernel Release Notes","ref":"notes.html#kernel-2-16-2"},{"type":"extras","doc":"- A bug in prim_inet has been corrected. If the port owner was killed at a bad\n time while closing the socket port the port could become orphaned hence\n causing port and socket leaking. Reported by Fred Herbert, Dmitry Belyaev and\n others.\n\n Own Id: OTP-10497 Aux Id: OTP-10562\n\n- A few bugs regarding case sensitivity for hostname resolution while using e.g\n the internal lookup types 'file' and 'dns' has been corrected. When looking up\n hostnames ASCII letters a-z are to be regarded as the same as A-Z according to\n RFC 4343 \"Domain Name System (DNS) Case Insensitivity Clarification\", and this\n was not always the case.\n\n Own Id: OTP-10689 Aux Id: seq12227","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add `application:ensure_started/1,2`. It is equivavlent to\n `application:start/1,2` except it returns `ok` for already started\n applications.\n\n Own Id: OTP-10910\n\n- Optimize communication with file io server. Thanks to Anthony Ramine.\n\n Own Id: OTP-11040\n\n- Erlang source files with non-ASCII characters are now encoded in UTF-8\n (instead of latin1).\n\n Own Id: OTP-11041 Aux Id: OTP-10907\n\n- Optimization of simultaneous `inet_db` operations on the same socket by using\n a lock free implementation.\n\n Impact on the characteristics of the system: Improved performance.\n\n Own Id: OTP-11074\n\n- The `high_msgq_watermark` and `low_msgq_watermark` `inet` socket options\n introduced in OTP-R16A could only be set on TCP sockets. These options are now\n generic and can be set on all types of sockets.\n\n Own Id: OTP-11075 Aux Id: OTP-10336\n\n- Fix deep list argument error under Windows in os:cmd/1. Thanks to Aleksandr\n Vinokurov .\n\n Own Id: OTP-11104","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.16.1 - Kernel Release Notes","ref":"notes.html#kernel-2-16-1"},{"type":"extras","doc":"- A bug that could cause a crash with wrong reason has been corrected in the\n `application_controller` module.\n\n Own Id: OTP-10754\n\n- Fix `code:is_module_native/1` that sometimes in R16A returned false for hipe\n compiled modules containing BIFs such as `lists`.\n\n Own Id: OTP-10870\n\n- Respect `{exit_on_close,false}` option on tcp socket in non-passive mode when\n receiving fails (due to an ill-formed packet for example) by only doing a half\n close and still allow sending on the socket. (Thanks to Anthony Molinaro and\n Steve Vinoski for reporting the problem)\n\n Own Id: OTP-10879","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Slightly nicer error message when node start fails due to duplicate name.\n Thanks to Magnus Henoch.\n\n Own Id: OTP-10797\n\n- Miscellaneous updates due to Unicode support.\n\n Own Id: OTP-10820\n\n- Add a new function code:get_mode() can be used to detect how the code servers\n behaves. Thanks to Vlad Dumitrescu\n\n Own Id: OTP-10823\n\n- Fix type of error Reason on gen_tcp:send/2. Thanks to Sean Cribbs.\n\n Own Id: OTP-10839\n\n- `file:list_dir_all/1` and `file:read_link_all/1` that can handle raw file\n names have been added. See the User Guide for STDLIB for information about raw\n file names.\n\n Own Id: OTP-10852","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.16 - Kernel Release Notes","ref":"notes.html#kernel-2-16"},{"type":"extras","doc":"- It is no longer possible to have `{Mod,Vsn}` in the 'modules' list in a .app\n file.\n\n This was earlier possible, although never documented in the .app file\n reference manual. It was however visible in the documentation of\n `application:load/[1,2]`, where the same term as in a .app file can be used as\n the first argument.\n\n The possibility has been removed since the `Vsn` part was never used.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-10417\n\n- The contract of `erl_ddll:format_error/1` has been corrected. (Thanks to\n Joseph Wayne Norton.)\n\n Own Id: OTP-10473\n\n- Change printout of application crash message on startup to formatted strings\n (Thanks to Serge Aleynikov)\n\n Own Id: OTP-10620\n\n- The type `ascii_string()` in the `base64` module has been corrected. The type\n [`file:file_info()`](`t:file:file_info/0`) has been cleaned up. The type\n [`file:fd()`](`t:file:fd/0`) has been made opaque in the documentation.\n\n Own Id: OTP-10624 Aux Id: kunagi-352 \\[263]","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Inet exported functionality\n\n inet:parse_ipv4_address/1, inet:parse_ipv4strict_address/1,\n inet:parse_ipv6_address/1, inet:parse_ipv6strict_address/1,\n inet:parse_address/1 and inet:parse_strict_address is now exported from the\n inet module.\n\n Own Id: OTP-8067 Aux Id: kunagi-274 \\[185]\n\n- A boolean socket option 'ipv6_v6only' for IPv6 sockets has been added. The\n default value of the option is OS dependent, so applications aiming to be\n portable should consider using `{ipv6_v6only,true}` when creating an `inet6`\n listening/destination socket, and if necessary also create an `inet` socket on\n the same port for IPv4 traffic. See the documentation.\n\n Own Id: OTP-8928 Aux Id: kunagi-193 \\[104]\n\n- Support for Unicode has been implemented.\n\n Own Id: OTP-10302\n\n- The documentation for `global:register_name/3` has been updated to mention\n that the use of `{Module,Function}` as the method argument (resolve function)\n is deprecated.\n\n Own Id: OTP-10419\n\n- Fixed bug where sendfile on oracle solaris would return an error when a\n partial send was done.\n\n Own Id: OTP-10549\n\n- The `error_handler` module will now call `'$handle_undefined_function'/2` if\n an attempt is made to call a non-existing function in a module that exists.\n See the documentation for `error_handler` module for details.\n\n Own Id: OTP-10617 Aux Id: kunagi-340 \\[251]\n\n- Where necessary a comment stating encoding has been added to Erlang files. The\n comment is meant to be removed in Erlang/OTP R17B when UTF-8 becomes the\n default encoding.\n\n Own Id: OTP-10630\n\n- Do not return wrong terms unnecessarily. (Thanks to Kostis Sagonas.)\n\n Own Id: OTP-10662\n\n- Some examples overflowing the width of PDF pages have been corrected.\n\n Own Id: OTP-10665\n\n- Add file:allocate/3 operation\n\n This operation allows pre-allocation of space for files. It succeeds only on\n systems that support such operation. (Thanks to Filipe David Manana)\n\n Own Id: OTP-10680\n\n- Add application:get_key/3. The new function provides a default value for a\n configuration parameter. Thanks to Serge Aleynikov.\n\n Own Id: OTP-10694\n\n- Add search to Erlang shell's history. Thanks to Fred Herbert.\n\n Own Id: OTP-10739","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.15.3 - Kernel Release Notes","ref":"notes.html#kernel-2-15-3"},{"type":"extras","doc":"- Ensure 'erl_crash.dump' when asked for it. This will change erl_crash.dump\n behaviour.\n\n \\* Not setting ERL_CRASH_DUMP_SECONDS will now terminate beam immediately on a\n crash without writing a crash dump file.\n\n \\* Setting ERL_CRASH_DUMP_SECONDS to 0 will also terminate beam immediately on\n a crash without writing a crash dump file, i.e. same as not setting\n ERL_CRASH_DUMP_SECONDS environment variable.\n\n \\* Setting ERL_CRASH_DUMP_SECONDS to a negative value will let the beam wait\n indefinitely on the crash dump file being written.\n\n \\* Setting ERL_CRASH_DUMP_SECONDS to a positive value will let the beam wait\n that many seconds on the crash dump file being written.\n\n A positive value will set an alarm/timeout for restart both in beam and in\n heart if heart is running.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-10422 Aux Id: kunagi-250 \\[161]","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 2.15.2 - Kernel Release Notes","ref":"notes.html#kernel-2-15-2"},{"type":"extras","doc":"- Fixed issue where using controlling_process/2 with self() as the second\n argument caused the port to leak if self() crashes. (Thanks to Ricardo\n Catalinas Jiménez)\n\n Own Id: OTP-10094\n\n- When sending large files using the file:sendfile fallback file:sendfile would\n crash. This is now fixed.\n\n Own Id: OTP-10098\n\n- Fix rpc:call/5 for local calls with a finite Timeout (Thanks to Tomer\n Chachamu)\n\n Own Id: OTP-10149\n\n- fix escript/primary archive reloading\n\n If the mtime of an escript/primary archive file changes after being added to\n the code path, correctly reload the archive and update the cache. (Thanks to\n Tuncer Ayaz)\n\n Own Id: OTP-10151\n\n- Support added for home directories named with non-ASCII characters (codepoints\n above 127) on a system running in Unicode file mode (e.g. on MacOSX or Linux\n with startup arguments +fnu or +fna with the right LOCALE). Also environment\n variables with Unicode content are supported in applicable environments.\n\n Own Id: OTP-10160\n\n- Allow mixed IPv4 and IPv6 addresses to sctp_bindx\n\n Also allow mixed address families to bind, since the first address on a\n multihomed sctp socket must be bound with bind, while the rest are to be bound\n using sctp_bindx. At least Linux supports adding address of mixing families.\n Make inet_set_faddress function available also when HAVE_SCTP is not defined,\n since we use it to find an address for bind to be able to mix ipv4 and ipv6\n addresses. Thanks to Tomas Abrahamsson\n\n Own Id: OTP-10217","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Document inet options: high_watermark, priority, linger and a some other\n options that previously was undocumented.\n\n Own Id: OTP-10053\n\n- Remove bit8 option support from inet\n\n Own Id: OTP-10056\n\n- The type of the disk log header has been corrected. (Thanks to Niclas Eklund.)\n\n Own Id: OTP-10131","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.15.1 - Kernel Release Notes","ref":"notes.html#kernel-2-15-1"},{"type":"extras","doc":"- Driver output has been corrected so output of large binaries (> 4 GiB) now\n does not silently fail or crash the emulator, but either outputs the binary or\n fails the call. This means that writing a binary > 4 Gib to file now works but\n on e.g 64-bit Windows (that has scatter/gather I/O buffer segment lengths of\n 32 bits) fails. The behaviour may change in the future to always write the\n binary, in parts if necessary.\n\n Own Id: OTP-9820 Aux Id: OTP-9795\n\n- erts: minor fix for unnecessary condition erts: change SENDFILE_CHUNK_SIZE\n from signed to unsigned (Thanks to jovi zhang)\n\n Own Id: OTP-9872\n\n- Two contracts in `gen_sctp` have been corrected.\n\n Own Id: OTP-9874\n\n- If a process calls a module with an running on_load handler, the process is\n supposed to be suspended. But if the module with the on_load handler was\n loading used `code:load_binary/3`, the call would instead fail with an `undef`\n exception.\n\n Own Id: OTP-9875\n\n- File name and error reason is now returned if creation of a cookie fails.\n (Thanks to Magnus Henoch)\n\n Own Id: OTP-9954\n\n- Fix port leak in `zlib` when passing invalid data to\n `compress,uncompress,zip,unzip,gzip,gunzip`.\n\n Own Id: OTP-9981\n\n- Various typographical errors corrected in documentation for the global,\n error_logger, etop, lists, ets and supervisor modules and in the c_portdriver\n and kernel_app documentation. (Thanks to Ricardo Catalinas Jiménez)\n\n Own Id: OTP-9987\n\n- Fix returned error from gen_tcp:accept/1,2 when running out of ports.\n\n The \\{error, enfile\\} return value is badly misleading and confusing for this\n case, since the Posix ENFILE errno value has a well-defined meaning that has\n nothing to do with Erlang ports. The fix changes the return value to \\{error,\n system_limit\\}, which is consistent with e.g. various file(3) functions.\n inet:format_error/1 has also been updated to support system_limit in the same\n manner as file:format_error/1. (Thanks to Per Hedeland)\n\n Own Id: OTP-9990\n\n- `erts_debug:size/1` has been corrected to take sharing in the environment of\n funs into account. For funs it used to always give the same result as\n `erts_debug:flat_size/1`.\n\n Own Id: OTP-9991\n\n- In some cases when the process doing file:sendfile crashes while sending the\n file the efile_drv code would not clean up after itself correctly. This has\n now been fixed.\n\n Own Id: OTP-9993\n\n- On BSD based platforms file:sendfile would sometime go into an infinite loop\n when sending big files. This has now been fixed.\n\n Own Id: OTP-9994\n\n- While `disk_log` eagerly collects logged terms for better performance,\n collecting too much data may choke the system and cause huge binaries to be\n written.\n\n The problem was addressed in OTP-9764, but the situation was not improved in\n all cases.\n\n (Thanks to Richard Carlsson.)\n\n Own Id: OTP-9999 Aux Id: OTP-9764\n\n- The documentation of .app files incorrectly said that the default value for\n the `mod` parameter is `undefined`. This is now corrected to `[]`.\n\n Own Id: OTP-10002","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 2.15 - Kernel Release Notes","ref":"notes.html#kernel-2-15"},{"type":"extras","doc":"- Calls to `global:whereis_name/1` have been substituted for calls to\n `global:safe_whereis_name/1` since the latter is not safe at all.\n\n The reason for not doing this earlier is that setting a global lock masked out\n a bug concerning the restart of supervised children. The bug has now been\n fixed by a modification of `global:whereis_name/1`. (Thanks to Ulf Wiger for\n code contribution.)\n\n A minor race conditions in `gen_fsm:start*` has been fixed: if one of these\n functions returned `{error, Reason}` or ignore, the name could still be\n registered (either locally or in `global`. (This is the same modification as\n was done for gen_server in OTP-7669.)\n\n The undocumented function `global:safe_whereis_name/1` has been removed.\n\n Own Id: OTP-9212 Aux Id: seq7117, OTP-4174\n\n- Honor option `packet_size` for http packet parsing by both TCP socket and\n `erlang:decode_packet`. This gives the ability to accept HTTP headers larger\n than the default setting, but also avoid DoS attacks by accepting lines only\n up to whatever length you wish to allow. For consistency, packet type `line`\n also honor option `packet_size`. (Thanks to Steve Vinoski)\n\n Own Id: OTP-9389\n\n- `disk_log:reopen/2,3` and `disk_log:breopen/3` could return the error reason\n from `file:rename/2` rather than the reason `{file_error, Filename, Reason}`.\n This bug has been fixed.\n\n The message `{disk_log, Node, {error, disk_log_stopped}}` which according the\n documentation is sent upon failure to truncate or reopen a disk log was\n sometimes turned into a reply. This bug has been fixed.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-9508\n\n- Environment variable 'shutdown_timeout' is added to kernel application.\n Earlier, application_controller would hang forever if an application top\n supervisor did not terminate upon a shutdown request. If this new environment\n variable is set to a positive integer T, then application controller will now\n give up after T milliseconds and instead brutally kill the application. For\n backwards compatibility, the default value for shutdown_timeout is 'infinity'.\n\n Own Id: OTP-9540\n\n- Add '-callback' attributes in stdlib's behaviours\n\n Replace the behaviour_info(callbacks) export in stdlib's behaviours with\n -callback' attributes for all the callbacks. Update the documentation with\n information on the callback attribute Automatically generate 'behaviour_info'\n function from '-callback' attributes\n\n 'behaviour_info(callbacks)' is a special function that is defined in a module\n which describes a behaviour and returns a list of its callbacks.\n\n This function is now automatically generated using the '-callback' specs. An\n error is returned by lint if user defines both '-callback' attributes and the\n behaviour_info/1 function. If no type info is needed for a callback use a\n generic spec for it. Add '-callback' attribute to language syntax\n\n Behaviours may define specs for their callbacks using the familiar spec\n syntax, replacing the '-spec' keyword with '-callback'. Simple lint checks are\n performed to ensure that no callbacks are defined twice and all types referred\n are declared.\n\n These attributes can be then used by tools to provide documentation to the\n behaviour or find discrepancies in the callback definitions in the callback\n module.\n\n Add callback specs into 'application' module in kernel Add callback specs to\n tftp module following internet documentation Add callback specs to\n inets_service module following possibly deprecated comments\n\n Own Id: OTP-9621\n\n- make tab completion work in remote shells (Thanks to Mats Cronqvist)\n\n Own Id: OTP-9673\n\n- Add missing parenthesis in heart doc.\n\n Add missing spaces in the Reference Manual distributed section.\n\n In the HTML version of the doc those spaces are necessary to separate those\n words.\n\n Own Id: OTP-9693\n\n- Fixes net_kernel:get_net_ticktime() doc\n\n Adds missing description when \\`ignored' is returned. (Thanks to Ricardo\n Catalinas Jiménez )\n\n Own Id: OTP-9713\n\n- While `disk_log` eagerly collects logged terms for better performance,\n collecting too much data may choke the system and cause huge binaries to be\n written. In order to remedy the situation a (small) limit on the amount of\n data that is collected before writing to disk has been introduced.\n\n Own Id: OTP-9764\n\n- - Correct callback spec in application module\n - Refine warning about callback specs with extra ranges\n - Cleanup autoimport compiler directives\n - Fix Dialyzer's warnings in typer\n - Fix Dialyzer's warning for its own code\n - Fix bug in Dialyzer's behaviours analysis\n - Fix crash in Dialyzer\n - Variable substitution was not generalizing any unknown variables.\n\n Own Id: OTP-9776\n\n- Fix a crash when file:change_time/2,3 are called with invalid dates\n\n Calling file:change_time/2,3 with an invalid date tuple (e.g\n file:change_time(\"file.txt\", \\{undefined, undefined\\})) will cause\n file_server_2 to crash. error_logger will shutdown and the whole VM will stop.\n Change behavior to validate given dates on system boundaries. (i.e before\n issuing a server call).(Thanks to Ahmed Omar)\n\n Own Id: OTP-9785","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- An option list argument can now be passed to\n `file:read_file_info/2, file:read_link_info/2` and `file:write_file_info/3`\n and set time type information in the call. Valid options are\n `{time, local}, {time, universal}` and `{time, posix}`. In the case of `posix`\n time no conversions are made which makes the operation a bit faster.\n\n Own Id: OTP-7687\n\n- `file:list_dir/1,2` will now fill an buffer entire with filenames from the\n efile driver before sending it to an erlang process. This will speed up this\n file operation in most cases.\n\n Own Id: OTP-9023\n\n- gen_sctp:open/0-2 may now return \\{error,eprotonosupport\\} if SCTP is not\n supported\n\n gen_sctp:peeloff/1 has been implemented and creates a one-to-one socket which\n also are supported now\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-9239\n\n- Sendfile has been added to the file module's API. sendfile/2 is used to read\n data from a file and send it to a tcp socket using a zero copying mechanism if\n available on that OS.\n\n Thanks to Tuncer Ayaz and Steve Vinovski for original implementation\n\n Own Id: OTP-9240\n\n- Tuple funs (a two-element tuple with a module name and a function) are now\n officially deprecated and will be removed in R16. Use '`fun M:F/A`' instead.\n To make you aware that your system uses tuple funs, the very first time a\n tuple fun is applied, a warning will be sent to the error logger.\n\n Own Id: OTP-9649","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.14.5 - Kernel Release Notes","ref":"notes.html#kernel-2-14-5"},{"type":"extras","doc":"- Fix type of Packet arg of gen_tcp:send/2 and gen_udp:send/4\n\n The type is marked as a binary() or a string() but in practice it can be an\n iodata(). The test suite was updated to confirm the gen_tcp/2 and\n gen_udp:send/4 functions accept iodata() (iolists) packets. (Thanks to Filipe\n David Manana)\n\n Own Id: OTP-9514\n\n- XML files have been corrected.\n\n Own Id: OTP-9550 Aux Id: OTP-9541","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The types and specifications of the inet modules have been improved.\n\n Own Id: OTP-9260\n\n- Types and specifications have been added.\n\n Own Id: OTP-9356\n\n- Contracts in STDLIB and Kernel have been improved and type errors have been\n corrected.\n\n Own Id: OTP-9485\n\n- Update documentation and specifications of some of the zlib functions.\n\n Own Id: OTP-9506","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.14.4 - Kernel Release Notes","ref":"notes.html#kernel-2-14-4"},{"type":"extras","doc":"- The send_timeout option in gen_tcp did not work properly in active mode or\n with \\{active,once\\} options. This is now corrected.\n\n Own Id: OTP-9145\n\n- Fixed various typos across the documentation (Thanks to Tuncer Ayaz)\n\n Own Id: OTP-9154\n\n- Fix typo in doc of rpc:pmap/3 (Thanks to Ricardo Catalinas Jiménez)\n\n Own Id: OTP-9168\n\n- A bug in inet_res, the specialized DNS resolver, has been corrected. A late\n answer with unfortunate timing could cause a runtime exception. Some code\n cleanup and improvements also tagged along. Thanks to Evegeniy Khramtsov for a\n pinpointing bug report and bug fix testing.\n\n Own Id: OTP-9221 Aux Id: OTP-8712","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Types and specifications have been added.\n\n Own Id: OTP-9268\n\n- Erlang types and specifications are used for documentation.\n\n Own Id: OTP-9272\n\n- Two opaque types that could cause warnings when running Dialyzer have been\n modified.\n\n Own Id: OTP-9337","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.14.3 - Kernel Release Notes","ref":"notes.html#kernel-2-14-3"},{"type":"extras","doc":"- `os:find_executable/{1,2}` will no longer return the path of a directory that\n happens to be in the PATH.\n\n Own Id: OTP-8983 Aux Id: seq11749\n\n- Fix -spec for file:write_file/3\n\n Change type for second parameter from binary() to iodata(), since the function\n explicitly takes steps to accept lists as well as binaries. (thanks to Magnus\n Henoch).\n\n Own Id: OTP-9067\n\n- Sanitize the specs of the code module\n\n After the addition of unicode_binary() to the file:filename() type, dialyzer\n started complaining about erroneous or incomplete specs in some functions of\n the 'code' module. The culprit was hard-coded information in erl_bif_types for\n functions of this module, which were not updated. Since these functions have\n proper specs these days and code duplication (pun intended) is never a good\n idea, their type information was removed from erl_bif_types.\n\n While doing this, some erroneous comments were fixed in the code module and\n also made sure that the code now runs without dialyzer warnings even when the\n -Wunmatched_returns option is used.\n\n Some cleanups were applied to erl_bif_types too.\n\n Own Id: OTP-9100\n\n- \\- Add spec for function that does not return - Strengthen spec - Introduce\n types to avoid duplication in specs - Add specs for functions that do not\n return - Add specs for behaviour callbacks - Simplify two specs\n\n Own Id: OTP-9127","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 2.14.2 - Kernel Release Notes","ref":"notes.html#kernel-2-14-2"},{"type":"extras","doc":"- The Erlang VM now supports Unicode filenames. The feature is turned on by\n default on systems where Unicode filenames are mandatory (Windows and MacOSX),\n but can be enabled on other systems with the '+fnu' emulator option. Enabling\n the Unicode filename feature on systems where it is not default is however\n considered experimental and not to be used for production. Together with the\n Unicode file name support, the concept of \"raw filenames\" is introduced, which\n means filenames provided without implicit unicode encoding translation. Raw\n filenames are provided as binaries, not lists. For further information, see\n stdlib users guide and the chapter about using Unicode in Erlang. Also see the\n file module manual page.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8887\n\n- There is now a new function inet:getifaddrs/0 modeled after C library function\n getifaddrs() on BSD and LInux that reports existing interfaces and their\n addresses on the host. This replaces the undocumented and unsupported\n inet:getiflist/0 and inet:ifget/2.\n\n Own Id: OTP-8926","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.14.1.1 - Kernel Release Notes","ref":"notes.html#kernel-2-14-1-1"},{"type":"extras","doc":"- In embedded mode, on_load handlers that called `code:priv_dir/1` or other\n functions in `code` would hang the system. Since the `crypto` application now\n contains an on_loader handler that calls `code:priv_dir/1`, including the\n `crypto` application in the boot file would prevent the system from starting.\n\n Also extended the `-init_debug` option to print information about on_load\n handlers being run to facilitate debugging.\n\n Own Id: OTP-8902 Aux Id: seq11703","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 2.14.1 - Kernel Release Notes","ref":"notes.html#kernel-2-14-1"},{"type":"extras","doc":"- Fixed: inet:setopts(S, \\[\\{linger,\\{true,2\\}\\}]) returned \\{error,einval\\} for\n SCTP sockets. The inet_drv had a bug when checking the option size.\n\n Own Id: OTP-8726 Aux Id: seq11617\n\n- gen_udp:connect/3 was broken for SCTP enabled builds. It did not detect remote\n end errors as it should.\n\n Own Id: OTP-8729\n\n- reference() has been substituted for ref() in the documentation.\n\n Own Id: OTP-8733\n\n- A bug introduced in kernel-2.13.5.3 has been fixed. If running\n `net_kernel:set_net_ticktime/1` twice within the `TransitionPerod` the second\n call caused the net_kernel process to crash with a `badmatch`.\n\n Own Id: OTP-8787 Aux Id: seq11657, OTP-8643\n\n- inet:getsockopt for SCTP sctp_default_send_param had a bug to not initialize\n required feilds causing random answers. It is now corrected.\n\n Own Id: OTP-8795 Aux Id: seq11655\n\n- For a socket in the HTTP packet mode, the return value from `gen_tcp:recv/2,3`\n if there is an error in the header will be `{ok,{http_error,String}}` instead\n of `{error,{http_error,String}}` to be consistent with `ssl:recv/2,3`.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8831","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Even when configuring erlang with --enable-native-libs, the native code for\n modules loaded very early (such as lists) would not get loaded. This has been\n corrected. (Thanks to Paul Guyot.)\n\n Own Id: OTP-8750\n\n- The undocumented function inet:ifget/2 has been improved to return interface\n hardware address (MAC) on platforms supporting getaddrinfo() (such as BSD\n unixes). Note it still does not work on all platforms for example not Windows\n nor Solaris, so the function is still undocumented.\n\n Buffer overflow and field init bugs for inet:ifget/2 and inet:getservbyname/2\n has also been fixed.\n\n Thanks to Michael Santos.\n\n Own Id: OTP-8816\n\n- As a usability improvement the 'inet6' option to functions gen_tcp:listen/2,\n gen_tcp:connect/3-4, gen_udp:open/2 and gen_sctp:open/1-2 is now implicit if\n the address argument or the 'ip' option contain an IPv6 address (8-tuple).\n\n Own Id: OTP-8822","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.14 - Kernel Release Notes","ref":"notes.html#kernel-2-14"},{"type":"extras","doc":"- os:find_executable can now be fed with the complete name of the executable on\n Windows and still find it. I.e os:find_executable(\"werl.exe\") will work as\n os:find_executable(\"werl\").\n\n Own Id: OTP-3626\n\n- The shell's line editing has been improved to more resemble the behaviour of\n readline and other shells. (Thanks to Dave Peticolas)\n\n Own Id: OTP-8635\n\n- Under certain circumstances the net kernel could hang. (Thanks to Scott Lystig\n Fritchie.)\n\n Own Id: OTP-8643 Aux Id: seq11584\n\n- The kernel DNS resolver was leaking one or two ports if the DNS reply could\n not be parsed or if the resolver(s) caused noconnection type errors. Bug now\n fixed. A DNS specification borderline truncated reply triggering the port\n leakage bug has also been fixed.\n\n Own Id: OTP-8652","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- As of this version, the global name server no longer supports nodes running\n Erlang/OTP R11B.\n\n Own Id: OTP-8527\n\n- The file module's functions write,read and read_line now handles named\n io_servers like 'standard_io' and 'standard_error' correctly.\n\n Own Id: OTP-8611\n\n- The functions file:advise/4 and file:datasync/1 have been added. (Thanks to\n Filipe David Manana.)\n\n Own Id: OTP-8637\n\n- When exchanging groups between nodes `pg2` did not remove duplicated members.\n This bug was introduced in R13B03 (kernel-2.13.4).\n\n Own Id: OTP-8653\n\n- There is a new option 'exclusive' to file:open/2 that uses the OS O_EXCL flag\n where supported to open the file in exclusive mode.\n\n Own Id: OTP-8670","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.13.5.3 - Kernel Release Notes","ref":"notes.html#kernel-2-13-5-3"},{"type":"extras","doc":"- A bug introduced in Kernel 2.13.5.2 has been fixed.\n\n Own Id: OTP-8686 Aux Id: OTP-8643","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 2.13.5.2 - Kernel Release Notes","ref":"notes.html#kernel-2-13-5-2"},{"type":"extras","doc":"- Under certain circumstances the net kernel could hang. (Thanks to Scott Lystig\n Fritchie.)\n\n Own Id: OTP-8643 Aux Id: seq11584","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 2.13.5.1 - Kernel Release Notes","ref":"notes.html#kernel-2-13-5-1"},{"type":"extras","doc":"- A race condition in `os:cmd/1` could cause the caller to get stuck in\n `os:cmd/1` forever.\n\n Own Id: OTP-8502","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 2.13.5 - Kernel Release Notes","ref":"notes.html#kernel-2-13-5"},{"type":"extras","doc":"- A race bug affecting `pg2:get_local_members/1` has been fixed. The bug was\n introduced in R13B03.\n\n Own Id: OTP-8358\n\n- The loading of native code was not properly atomic in the SMP emulator, which\n could cause crashes. Also a per-MFA information table for the native code has\n now been protected with a lock since it turns that it could be accessed\n concurrently in the SMP emulator. (Thanks to Mikael Pettersson.)\n\n Own Id: OTP-8397\n\n- user.erl (used in oldshell) is updated to handle unicode in prompt strings\n (io:get_line/\\{1,2\\}). io_lib is also updated to format prompts with the 't'\n modifier (i.e. ~ts instead of ~s).\n\n Own Id: OTP-8418 Aux Id: OTP-8393\n\n- The resolver routines failed to look up the own node name as hostname, if the\n OS native resolver was erroneously configured, bug reported by Yogish Baliga,\n now fixed.\n\n The resolver routines now tries to parse the hostname as an IP string as most\n OS resolvers do, unless the native resolver is used.\n\n The DNS resolver inet_res and file resolver inet_hosts now do not read OS\n configuration files until they are needed. Since the native resolver is\n default, in most cases they are never needed.\n\n The DNS resolver's automatic updating of OS configuration file data\n (/etc/resolv.conf) now uses the 'domain' keyword as default search domain if\n there is no 'search' keyword.\n\n Own Id: OTP-8426 Aux Id: OTP-8381","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The expected return value for an on_load function has been changed. (See the\n section about code loading in the Reference manual.)\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8339\n\n- Explicit top directories in archive files are now optional.\n\n For example, if an archive (app-vsn.ez) just contains an app-vsn/ebin/mod.beam\n file, the file info for the app-vsn and app-vsn/ebin directories are faked\n using the file info from the archive file as origin. The virtual directories\n can also be listed. For short, the top directories are virtual if they does\n not exist.\n\n Own Id: OTP-8387\n\n- `code:clash/0` now looks inside archives (.ez files). (Thanks to Tuncer Ayaz.)\n\n Own Id: OTP-8413\n\n- There are new `gen_sctp:connect_init/*` functions that initiate an SCTP\n connection without blocking for the result. The result is delivered\n asynchronously as an sctp_assoc_change event. (Thanks to Simon Cornish.)\n\n Own Id: OTP-8414","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.13.4 - Kernel Release Notes","ref":"notes.html#kernel-2-13-4"},{"type":"extras","doc":"- A link in `m:pg2` has been fixed. (Thanks to Christophe Romain.)\n\n Own Id: OTP-8198\n\n- A ticker process could potentially be blocked indefinitely trying to send a\n tick to a node not responding. If this happened, the connection would not be\n brought down as it should.\n\n Own Id: OTP-8218\n\n- A bug in `pg2` when members who died did not leave process groups has been\n fixed. (Thanks to Matthew Dempsky.)\n\n Own Id: OTP-8259","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The documentation is now built with open source tools (xsltproc and fop) that\n exists on most platforms. One visible change is that the frames are removed.\n\n Own Id: OTP-8201\n\n- The top directory in archive files does not need to have a `-vsn` suffix\n anymore. For example if the archive file has the name like `mnesia-4.4.7.ez`\n the top directory in the archive can either be named `mnesia` or\n `mnesia-4.4.7`. If the archive file has a name like `mnesia.ez` the top\n directory in the archive must be named `mnesia` as earlier.\n\n Own Id: OTP-8266\n\n- The -on_load() directive can be used to run a function when a module is\n loaded. It is documented in the section about code loading in the Reference\n Manual.\n\n Own Id: OTP-8295","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.13.3 - Kernel Release Notes","ref":"notes.html#kernel-2-13-3"},{"type":"extras","doc":"- The DNS resolver client inet_res has been rewritten, documented and released.\n See inet_res(3) and Erts User's Guide: Inet configuration.\n\n It can formally not be incompatible with respect to earlier versions since\n there was no earlier official version. However it was used before and some\n details have changed.\n\n Configuration now initializes from /etc/resolv.conf and /etc/hosts on all unix\n platforms regardless of which distribution mode the node is started in. The\n directory (/etc) these files are supposed to reside in can be changed via an\n environment variable. These configuration file locations can also be changed\n in the inet configuration. The files are monitored for change and re-read,\n which makes a few resolver configuration variables out of application control.\n The /etc/hosts entries have now their own cache table that is shadowed (with\n lookup method 'file' is used) by the application configured host entries. This\n problem (that inet_res configuration only worked for distribution mode long\n names) was among other reported by Matthew O'Gorman many moons ago.\n\n The lookup methods are still 'native' only per default. Resolver configuration\n is done on all Unix platforms just to get a usable configuration for direct\n calls to inet_res.\n\n The functions `inet_res:nslookup/3..5` and `inet_res:nnslookup/4..4` are no\n longer recommended to use, instead use `inet_res:lookup/3..5` and\n `inet_res:resolve/3..5` which provide clearer argument types and the\n possibility to override options in the call.\n\n Users of previous unsupported versions of inet_res have included internal\n header files to get to the internal record definitions in order to examine DNS\n replies. This is still unsupported and there are access functions in inet_dns\n to use instead. These are documented in inet_res(3).\n\n Bug fix: a compression reference loop would make DNS message decoding loop\n forever. Problem reported by Florian Weimer.\n\n Bug fix and patch suggestion by Sergei Golovan: configuring IPv6 nameservers\n did not work. His patch (as he warned) created many UDP sockets; one per\n nameserver. This has been fixed in the released version.\n\n Improvement: `inet_res` is now EDNS0 capable. The current implementation is\n simple and does not probe and cache EDNS info for nameservers, which a fully\n capable implementation probably should do. EDNS has to be enabled via resolver\n configuration, and if a nameserver replies that it does not support EDNS,\n `inet_res` falls back to a regular DNS query.\n\n Improvement: now `inet_res` automatically falls back to TCP if it gets a\n truncated answer from a nameserver.\n\n Warning: some of the ancient and exotic record types handled by `inet_res` and\n `inet_dns` are not supported by current versions of BIND, so they could not be\n tested after the rewrite, with reasonable effort, e.g MD, MF, NULL, and SPF.\n The risk for bugs in these particular records is still low since their code is\n mostly shared with other tested record types.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-7955 Aux Id: OTP-7107 OTP-6852\n\n- A TCP socket with option `{packet,4}` could crash the emulator if it received\n a packet header with a very large size value (>2Gb). The same bug caused\n `erlang:decode_packet/3` to return faulty values. (Thanks to Georgos Seganos.)\n\n Own Id: OTP-8102\n\n- The file module has now a read_line/1 function similar to the io:get_line/2,\n but with byte oriented semantics. The function file:read_line/1 works for raw\n files as well, but for good performance it is recommended to use it together\n with the 'read_ahead' option for raw file access.\n\n Own Id: OTP-8108","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.13.2 - Kernel Release Notes","ref":"notes.html#kernel-2-13-2"},{"type":"extras","doc":"- A bug when doing io:get_line (among other calls) from a file opened with\n encoding other than latin1, causing false unicode errors to occur, is now\n corrected.\n\n Own Id: OTP-7974","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Added functionality to get higher resolution timestamp from system. The\n erlang:now function returns a timestamp that's not always consistent with the\n actual operating system time (due to resilience against large time changes in\n the operating system). The function os:timestamp/0 is added to get a similar\n timestamp as the one being returned by erlang:now, but untouched by Erlangs\n time correcting and smoothing algorithms. The timestamp returned by\n os:timestamp is always consistent with the operating systems view of time,\n like the calendar functions for getting wall clock time, but with higher\n resolution. Example of usage can be found in the os manual page.\n\n Own Id: OTP-7971","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.13.1 - Kernel Release Notes","ref":"notes.html#kernel-2-13-1"},{"type":"extras","doc":"- Many concurrent calls to `os:cmd/1` will only block one scheduler thread at a\n time, making an smp emulator more responsive if the OS is slow forking\n processes.\n\n Own Id: OTP-7890 Aux Id: seq11219\n\n- Fixed hanging early RPC that did IO operation during node start.\n\n Own Id: OTP-7903 Aux Id: seq11224\n\n- The error behavior of gen_tcp and gen_udp has been corrected.\n gen_tcp:connect/3,4 and gen_udp:send/4 now returns \\{error,eafnosupport\\} for\n conflicting destination address versus socket address family. Other corner\n cases for IP address string host names combined with not using the native (OS)\n resolver (which is not default) has also been changed to return\n \\{error,nxdomain\\} instead of \\{error,einval\\}. Those changes just may\n surprise old existing code. gen_tcp:listen/2 and gen_udp:open/2 now fails for\n conflicting local address versus socket address family instead of trying to\n use an erroneous address. Problem reported by Per Hedeland.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-7929","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Several glitches and performance issues in the Unicode and I/O-system\n implementation of R13A have been corrected.\n\n Own Id: OTP-7896 Aux Id: OTP-7648 OTP-7887\n\n- The unsupported DNS resolver client inet_res has now been improved to handle\n NAPTR queries.\n\n Own Id: OTP-7925 Aux Id: seq11231","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.13 - Kernel Release Notes","ref":"notes.html#kernel-2-13"},{"type":"extras","doc":"- The old Erlang DNS resolver inet_res has been corrected to handle TXT records\n with more than one character string. Patch courtesy of Geoff Cant.\n\n Own Id: OTP-7588\n\n- When chunk reading a disk log opened in read_only mode, bad terms could crash\n the disk log process.\n\n Own Id: OTP-7641 Aux Id: seq11090\n\n- `gen_tcp:send()` did sometimes (only observed on Solaris) return\n `{error,enotconn}` instead of the expected `{error,closed}` as the peer socket\n had been explicitly closed.\n\n Own Id: OTP-7647\n\n- The gen_sctp option sctp_peer_addr_params,\n #sctp_paddrparams\\{address=\\{IP,Port\\} was erroneously decoded in the inet\n driver. This bug has now been corrected.\n\n Own Id: OTP-7755","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Erlang programs can now access STDERR on platforms where such a file\n descriptor is available by using the io_server 'standard_error', i.e.\n io:format(standard_error,\"~s~n\",\\[ErrorMessage]),\n\n Own Id: OTP-6688\n\n- The format of the string returned by `erlang:system_info(system_version)` (as\n well as the first message when Erlang is started) has changed. The string now\n contains the both the OTP version number as well as the erts version number.\n\n Own Id: OTP-7649\n\n- As of this version, the global name server no longer supports nodes running\n Erlang/OTP R10B.\n\n Own Id: OTP-7661\n\n- A `{nodedown, Node}` message passed by the `net_kernel:monitor_nodes/X`\n functionality is now guaranteed to be sent after `Node` has been removed from\n the result returned by `erlang:nodes/Y`.\n\n Own Id: OTP-7725\n\n- The deprecated functions `erlang:fault/1`, `erlang:fault/2`, and\n `file:rawopen/2` have been removed.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-7812\n\n- Nodes belonging to different independent clusters can now co-exist on the same\n host with the help of a new environment variable setting ERL_EPMD_PORT.\n\n Own Id: OTP-7826\n\n- The copyright notices have been updated.\n\n Own Id: OTP-7851","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.12.5.1 - Kernel Release Notes","ref":"notes.html#kernel-2-12-5-1"},{"type":"extras","doc":"- When chunk reading a disk log opened in read_only mode, bad terms could crash\n the disk log process.\n\n Own Id: OTP-7641 Aux Id: seq11090\n\n- Calling `gen_tcp:send()` from several processes on socket with option\n `send_timeout` could lead to much longer timeout than specified. The solution\n is a new socket option `{send_timeout_close,true}` that will do automatic\n close on timeout. Subsequent calls to send will then immediately fail due to\n the closed connection.\n\n Own Id: OTP-7731 Aux Id: seq11161","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 2.12.5 - Kernel Release Notes","ref":"notes.html#kernel-2-12-5"},{"type":"extras","doc":"- The documentation of `rpc:pmap/3` has been corrected. (Thanks to Kirill\n Zaborski.)\n\n Own Id: OTP-7537\n\n- The listen socket used for the distributed Erlang protocol now uses the socket\n option 'reuseaddr', which is useful when you force the listen port number\n using kernel options 'inet_dist_listen_min' and 'inet_dist_listen_max' and\n restarts a node with open connections.\n\n Own Id: OTP-7563\n\n- Fixed memory leak of unclosed TCP-ports. A gen_tcp:send() followed by a\n failing gen_tcp:recv() could in some cases cause the port to linger after\n being closed.\n\n Own Id: OTP-7615","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Processes spawned using `proc_lib` (including `gen_server` and other library\n modules that use `proc_lib`) no longer keep the entire argument list for the\n initial call, but only the arity.\n\n Also, if `proc_lib:spawn/1` is used to spawn a fun, the actual fun is not\n kept, but only module, function name, and arity of the function that\n implements the fun.\n\n The reason for the change is that keeping the initial fun (or a fun in an\n argument list), would prevent upgrading the code for the module. A secondary\n reason is that keeping the fun and function arguments could waste a\n significant amount of memory.\n\n The drawback with the change is that the crash reports will provide less\n precise information about the initial call (only `Module:Function/Arity`\n instead of `Module:Function(Arguments)`). The function\n `proc_lib:initial_call/1` still returns a list, but each argument has been\n replaced with a dummy atom.\n\n Own Id: OTP-7531 Aux Id: seq11036\n\n- `io:get_line/1` when reading from standard input is now substantially faster.\n There are also some minor performance improvements in `io:get_line/1` when\n reading from any file opened in binary mode. (Thanks to Fredrik Svahn.)\n\n Own Id: OTP-7542\n\n- There is now experimental support for loading of code from archive files. See\n the documentation of `code`, `init`, `erl_prim_loader `and `escript` for more\n info.\n\n The error handling of `escripts` has been improved.\n\n An `escript` may now set explicit arguments to the emulator, such as\n `-smp enabled`.\n\n An `escript` may now contain a precompiled beam file.\n\n An `escript` may now contain an archive file containing one or more\n applications (experimental).\n\n The internal module `code_aux` has been removed.\n\n Own Id: OTP-7548 Aux Id: otp-6622\n\n- `code:is_sticky/1` is now documented. (Thanks to Vlad Dumitrescu.)\n\n Own Id: OTP-7561\n\n- In the job control mode, the \"s\" and \"r\" commands now take an optional\n argument to specify which shell to start. (Thanks to Robert Virding.)\n\n Own Id: OTP-7617\n\n- `net_adm:world/0,1` could crash if called in an emulator that has not been\n started with either the `-sname` or `-name` option; now it will return an\n empty list. (Thanks to Edwin Fine.)\n\n Own Id: OTP-7618","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.12.4 - Kernel Release Notes","ref":"notes.html#kernel-2-12-4"},{"type":"extras","doc":"- Large files are now handled on Windows, where the filesystem supports it.\n\n Own Id: OTP-7410","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- New BIF `erlang:decode_packet/3` that extracts a protocol packet from a\n binary. Similar to the socket option `{packet, Type}`. Also documented the\n socket packet type `http` and made it official. _NOTE_: The tuple format for\n `http` packets sent from an active socket has been changed in an incompatible\n way.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-7404\n\n- Setting the `{active,once}` for a socket (using inets:setopts/2) is now\n specially optimized (because the `{active,once}` option is typically used much\n more frequently than other options).\n\n Own Id: OTP-7520","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.12.3 - Kernel Release Notes","ref":"notes.html#kernel-2-12-3"},{"type":"extras","doc":"- SCTP_ADDR_CONFIRMED events are now handled by gen_sctp.\n\n Own Id: OTP-7276\n\n- When leaving a process group with `pg2:leave/2` the process was falsely\n assumed to be a member of the group. This bug has been fixed.\n\n Own Id: OTP-7277\n\n- In the Erlang shell, using up and down arrow keys, the wrong previous command\n could sometimes be retrieved.\n\n Own Id: OTP-7278\n\n- The documentation for `erlang:trace/3` has been corrected.\n\n Own Id: OTP-7279 Aux Id: seq10927\n\n- In the SMP emulator, there was small risk that `code:purge(Mod)` would kill a\n process that was running code in `Mod` and unload the module `Mod` before the\n process had terminated. `code:purge(Mod)` now waits for confirmation (using\n `erlang:monitor/2`) that the process has been killed before proceeding.\n\n Own Id: OTP-7282\n\n- `zlib:inflate` failed when the size of the inflated data was an exact multiple\n of the internal buffer size (4000 bytes by default).\n\n Own Id: OTP-7359","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Additional library directories can now be specified in the environment\n variable ERL_LIBS. See the manual page for the `code` module. (Thanks to Serge\n Aleynikov.)\n\n Own Id: OTP-6940\n\n- crypto and zlib drivers improved to allow concurrent smp access.\n\n Own Id: OTP-7262\n\n- There is a new function `init:stop/1` which can be used to shutdown the system\n cleanly AND generate a non-zero exit status or crash dump. (Thanks to Magnus\n Froberg.)\n\n Own Id: OTP-7308\n\n- The `hide` option for [`open_port/2`](`open_port/2`) is now documented.\n (Thanks to Richard Carlsson.)\n\n Own Id: OTP-7358","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.12.2.1 - Kernel Release Notes","ref":"notes.html#kernel-2-12-2-1"},{"type":"extras","doc":"- `os:cmd/1` on unix platforms now use `/bin/sh` as shell instead of looking for\n `sh` in the `PATH` environment.\n\n Own Id: OTP-7283","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.12.2 - Kernel Release Notes","ref":"notes.html#kernel-2-12-2"},{"type":"extras","doc":"- A bug caused by a race condition involving `disk_log` and `pg2` has been\n fixed.\n\n Own Id: OTP-7209 Aux Id: seq10890\n\n- The beta testing module `gen_sctp` now supports active mode as stated in the\n documentation. Active mode is still rather untested, and there are some issues\n about what should be the right semantics for `gen_sctp:connect/5`. In\n particular: should it be blocking or non-blocking or choosable. There is a\n high probability it will change semantics in a (near) future patch.\n\n Try it, give comments and send in bug reports\\!\n\n Own Id: OTP-7225","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- `erlang:system_info/1` now accepts the `logical_processors`, and\n `debug_compiled` arguments. For more info see the, `m:erlang` documentation.\n\n The scale factor returned by `test_server:timetrap_scale_factor/0` is now also\n effected if the emulator uses a larger amount of scheduler threads than the\n amount of logical processors on the system.\n\n Own Id: OTP-7175\n\n- Updated the documentation for `erlang:function_exported/3` and `io:format/2`\n functions to no longer state that those functions are kept mainly for\n backwards compatibility.\n\n Own Id: OTP-7186\n\n- A process executing the `processes/0` BIF can now be preempted by other\n processes during its execution. This in order to disturb the rest of the\n system as little as possible. The returned result is, of course, still a\n consistent snapshot of existing processes at a time during the call to\n `processes/0`.\n\n The documentation of the `processes/0` BIF and the\n [`is_process_alive/1`](`is_process_alive/1`) BIF have been updated in order to\n clarify the difference between an existing process and a process that is\n alive.\n\n Own Id: OTP-7213\n\n- [`tuple_size/1`](`tuple_size/1`) and [`byte_size/1`](`byte_size/1`) have been\n substituted for [`size/1`](`size/1`) in the documentation.\n\n Own Id: OTP-7244","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.12.1.2 - Kernel Release Notes","ref":"notes.html#kernel-2-12-1-2"},{"type":"extras","doc":"- The `{allocator_sizes, Alloc}` and `alloc_util_allocators` arguments are now\n accepted by `erlang:system_info/1`. For more information see the `m:erlang`\n documentation.\n\n Own Id: OTP-7167","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.12.1.1 - Kernel Release Notes","ref":"notes.html#kernel-2-12-1-1"},{"type":"extras","doc":"- Fixed a problem in group that could cause the ssh server to lose answers or\n hang.\n\n Own Id: OTP-7185 Aux Id: seq10871","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 2.12.1 - Kernel Release Notes","ref":"notes.html#kernel-2-12-1"},{"type":"extras","doc":"- file:read/2 and file:consult_stream/1,3 did not use an empty prompt on I/O\n devices. This bug has now been corrected.\n\n Own Id: OTP-7013\n\n- The sctp driver has been updated to work against newer lksctp packages e.g\n 1.0.7 that uses the API spelling change adaption -> adaptation. Older lksctp\n (1.0.6) still work. The erlang API in gen_sctp.erl and inet_sctp.hrl now\n spells 'adaptation' regardless of the underlying C API.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-7120","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The documentation has been updated so as to reflect the last updates of the\n Erlang shell as well as the minor modifications of the control sequence `p` of\n the `io_lib` module.\n\n Superfluous empty lines have been removed from code examples and from Erlang\n shell examples.\n\n Own Id: OTP-6944 Aux Id: OTP-6554, OTP-6911\n\n- [`tuple_size/1`](`tuple_size/1`) and [`byte_size/1`](`byte_size/1`) have been\n substituted for [`size/1`](`size/1`).\n\n Own Id: OTP-7009","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.12 - Kernel Release Notes","ref":"notes.html#kernel-2-12"},{"type":"extras","doc":"- A bug for raw files when reading 0 bytes returning 'eof' instead of empty data\n has been corrected.\n\n Own Id: OTP-6291 Aux Id: OTP-6967\n\n- A bug in gen_udp:fdopen reported by David Baird and also found by Dialyzer has\n been fixed.\n\n Own Id: OTP-6836 Aux Id: OTP-6594\n\n- Calling `error_logger:tty(true)` multiple times does not give multiple error\n log printouts.\n\n Own Id: OTP-6884 Aux Id: seq10767\n\n- The global name server now ignores `nodeup` messages when the command line\n flag `-connect_all false` has been used. (Thanks to Trevor Woollacott.)\n\n Own Id: OTP-6931\n\n- file:write_file/3, file:write/2 and file:read/2 could crash (contrary to\n documentation) for odd enough file system problems, e.g write to full file\n system. This bug has now been corrected.\n\n In this process the file module has been rewritten to produce better error\n codes. Posix error codes now originate from the OS file system calls or are\n generated only for very similar causes (for example 'enomem' is generated if a\n memory allocation fails, and 'einval' is generated if the file handle in\n Erlang is a file handle but currently invalid).\n\n More Erlang-ish error codes are now generated. For example `{error,badarg}` is\n now returned from `file:close/1` if the argument is not of a file handle type.\n See file(3).\n\n The possibility to write a single byte using `file:write/2` instead of a list\n or binary of one byte, contradictory to the documentation, has been removed.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-6967 Aux Id: OTP-6597 OTP-6291\n\n- Monitor messages produced by the system monitor functionality, and garbage\n collect trace messages could contain erroneous heap and/or stack sizes when\n the actual heaps and/or stacks were huge.\n\n As of erts version 5.6 the `large_heap` option to\n `erlang:system_monitor/[1,2]` has been modified. The monitor message is sent\n if the sum of the sizes of all memory blocks allocated for all heap\n generations is equal to or larger than the specified size. Previously the\n monitor message was sent if the memory block allocated for the youngest\n generation was equal to or larger than the specified size.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-6974 Aux Id: seq10796\n\n- `inet:getopts/2` returned random values on Windows Vista.\n\n Own Id: OTP-7003","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Minor documentation corrections for file:pread/2 and file:pread/3.\n\n Own Id: OTP-6853\n\n- The deprecated functions `file:file_info/1`, `init:get_flag/1`,\n `init:get_flags/0`, and `init:get_args/0` have been removed.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-6886\n\n- Contract directives for modules in Kernel and STDLIB.\n\n Own Id: OTP-6895\n\n- The functions io:columns/0, io:columns/1, io:rows/0 and io:rows/1 are added to\n allow the user to get information about the terminal geometry. The shell takes\n some advantage of this when formatting output. For regular files and other\n io-devices where height and width are not applicable, the functions return\n \\{error,enotsup\\}.\n\n Potential incompatibility: If one has written a custom io-handler, the handler\n has to either return an error or take care of io-requests regarding terminal\n height and width. Usually that is no problem as io-handlers, as a rule of\n thumb, should give an error reply when receiving unknown io-requests, instead\n of crashing.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-6933\n\n- The undocumented and unsupported functions `inet:ip_to_bytes/1`,\n `inet:ip4_to_bytes/1`, `inet:ip6_to_bytes/1`, and `inet:bytes_to_ip6/16` have\n been removed.\n\n Own Id: OTP-6938\n\n- Added new checksum combine functions to `zlib`. And fixed a bug in\n `zlib:deflate`. Thanks Matthew Dempsky.\n\n Own Id: OTP-6970\n\n- The [`spawn_monitor/1`](`spawn_monitor/1`) and\n [`spawn_monitor/3`](`spawn_monitor/3`) BIFs are now auto-imported (i.e. they\n no longer need an `erlang:` prefix).\n\n Own Id: OTP-6975\n\n- All functions in the `code` module now fail with an exception if they are\n called with obviously bad arguments, such as a tuple when an atom was\n expected. Some functions now also fail for undocumented argument types (for\n instance, `ensure_loaded/1` now only accepts an atom as documented; it used to\n accept a string too).\n\n Dialyzer will generally emit warnings for any calls that use undocumented\n argument types. Even if the call happens to still work in R12B, you should\n correct your code. A future release will adhere to the documentation.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-6983","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.11.5.2 - Kernel Release Notes","ref":"notes.html#kernel-2-11-5-2"},{"type":"extras","doc":"- The kernel parameter dist_auto_connect once could fail to block a node if\n massive parallel sends were issued during a transient failure of network\n communication\n\n Own Id: OTP-6893 Aux Id: seq10753","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 2.11.5.1 - Kernel Release Notes","ref":"notes.html#kernel-2-11-5-1"},{"type":"extras","doc":"- The internal (rarely used) DNS resolver has been modified to not use the\n domain search list when asked to resolve an absolute name; a name with a\n terminating dot. There was also a bug causing it to create malformed DNS\n queries for absolute names that has been corrected, correction suggested by\n Scott Lystig Fritchie. The code has also been corrected to look up cached RRs\n in the same search order as non-cached, now allows having the root domain\n among the search domains, and can now actually do a zone transfer request.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-6806 Aux Id: seq10714 EABln35459\n\n- zlib:close/1 would leave an EXIT message in the message queue if the calling\n process had the trap_exit flag enabled.\n\n Own Id: OTP-6811","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The documentation of [`process_flag(priority, Level)`](`process_flag/2`) has\n been updated, see the `m:erlang` documentation.\n\n Own Id: OTP-6745 Aux Id: OTP-6715","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.11.5 - Kernel Release Notes","ref":"notes.html#kernel-2-11-5"},{"type":"extras","doc":"- The shell has been updated to fix the following flaws: Shell process exit left\n you with an unresponsive initial shell if not using oldshell. Starting a\n restricted shell with a nonexisting callback module resulted in a shell where\n no commands could be used, not even init:stop/0. Fun's could not be used as\n parameters to local shell functions (in shell_default or user_default) when\n restricted_shell was active.\n\n Own Id: OTP-6537\n\n- The undocumented feature gen_tcp:fdopen/2 was broken in R11B-4. It is now\n fixed again.\n\n Own Id: OTP-6615\n\n- Corrected cancellation of timers in three places in the inet_res module.\n (Problem found by Dialyzer.)\n\n Own Id: OTP-6676","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Corrected protocol layer flue for socket options SO_LINGER, SO_SNDBUF and\n SO_RCVBUF, for SCTP.\n\n Own Id: OTP-6625 Aux Id: OTP-6336\n\n- The behaviour of the inet option \\{active,once\\} on peer close is improved and\n documented.\n\n Own Id: OTP-6681\n\n- The inet option send_timeout for connection oriented sockets is added to allow\n for timeouts in communicating send requests to the underlying TCP stack.\n\n Own Id: OTP-6684 Aux Id: seq10637 OTP-6681\n\n- Minor Makefile changes.\n\n Own Id: OTP-6689 Aux Id: OTP-6742\n\n- The documentation of [`process_flag(priority, Level)`](`process_flag/2`) has\n been updated, see the `m:erlang` documentation.\n\n Own Id: OTP-6715","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.11.4.2 - Kernel Release Notes","ref":"notes.html#kernel-2-11-4-2"},{"type":"extras","doc":"- process_flag/2 accepts the new flag `sensitive`.\n\n Own Id: OTP-6592 Aux Id: seq10555","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.11.4.1 - Kernel Release Notes","ref":"notes.html#kernel-2-11-4-1"},{"type":"extras","doc":"- A bug in gen_udp:open that broke the 'fd' option has been fixed.\n\n Own Id: OTP-6594 Aux Id: seq10619","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 2.11.4 - Kernel Release Notes","ref":"notes.html#kernel-2-11-4"},{"type":"extras","doc":"- Added a warning to the documentation for the `error_logger` functions\n `error_msg/1,2`, `warning_msg/1,2` and `info_msg/1,2` that calling these\n function with bad arguments can crash the standard event handler.\n\n Own Id: OTP-4575 Aux Id: seq7693\n\n- A bug in `inet_db` concerning getting the resolver option `retry` has been\n corrected.\n\n Own Id: OTP-6380 Aux Id: seq10534\n\n- Names registered by calling `global:register_name()` or\n `global:re_register_name()` were not always unregistered when the registering\n or registered process died. This bug has been fixed.\n\n Own Id: OTP-6428\n\n- When setting the kernel configuration parameter `error_logger` to `false`, the\n documentation stated that \"No error logger handler is installed\". This is\n true, but error logging is not turned off, as the initial, primitive error\n logger event handler is kept, printing raw event messages to tty.\n\n Changing this behavior can be viewed as a backward incompatible change.\n Instead a new value `silent` for the configuration parameter has been added,\n which ensures that error logging is completely turned off.\n\n Own Id: OTP-6445\n\n- Clarified the documentation for `code:lib_dir/1` and `code:priv_dir/1`. The\n functions traverse the names of the code path, they do not search the actual\n directories.\n\n Own Id: OTP-6466\n\n- `io:setopts` returned `{error,badarg}`, when called with only an `expand_fun`\n argument. (Thanks to igwan.)\n\n Own Id: OTP-6508","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- An interface towards the SCTP Socket API Extensions has been implemented.It is\n an Open Source patch courtesy of Serge Aleynikov and Leonid Timochouk. The\n Erlang code parts has been adapted by the OTP team, changing the Erlang API\n somewhat.\n\n The Erlang interface consists of the module `gen_sctp` and an include file\n `-include_lib(\"kernel/include/inet_sctp.hrl\").` for option record definitions.\n The `gen_sctp` module is documented.\n\n The delivered Open Source patch, before the OTP team rewrites, was written\n according to\n [http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13](http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13)\n and was claimed to work fine, tested on Linux Fedora Core 5.0 (kernel\n 2.6.15-2054 or later) and on Solaris 10 and 11. The OTP team rewrites used the\n same standard document but might have accidentally broken some functionality.\n If so, it will soon be patched to working state. The tricky parts in C and the\n general design has essentially not changed. During the rewrites the code was\n hand tested on SuSE Linux Enterprise Server 10, and briefly on Solaris 10.\n Feedbach on code and docs is very much appreciated.\n\n The SCTP interface is in beta state. It has only been hand tested and has no\n automatic test suites in OTP meaning everything is most certainly not tested.\n Socket active mode is broken. IPv6 is not tested. The documentation has been\n reworked due to the API changes, but has not been proofread after this.\n\n Thank you from the OTP team to Serge Aleynikov and Leonid Timochouk for a\n valuable contribution. We hope we have not messed it up too much.\n\n Own Id: OTP-6336\n\n- A `{minor_version,Version}` option is now recognized by\n [`term_to_binary/2`](`term_to_binary/2`). \\{minor_version,1\\} will cause\n floats to be encoded in an exact and more space-efficient way compared to the\n previous encoding.\n\n Own Id: OTP-6434\n\n- Monitoring of nodes has been improved. Now the following properties apply to\n `net_kernel:monitor_nodes/[1,2]`:\n\n - `nodeup` messages will be delivered before delivery of any message from the\n remote node passed through the newly established connection.\n - `nodedown` messages will not be delivered until all messages from the remote\n node that have been passed through the connection have been delivered.\n - Subscriptions can also be made before the `net_kernel` server has been\n started.\n\n Own Id: OTP-6481\n\n- Setting and getting socket options in a \"raw\" fashion is now allowed. Using\n this feature will inevitably produce non portable code, but will allow setting\n ang getting arbitrary uncommon options on TCP stacks that do have them.\n\n Own Id: OTP-6519\n\n- Dialyzer warnings have been eliminated.\n\n Own Id: OTP-6523\n\n- The documentation for `file:delete/1` and `file:set_cwd/1` has been updated to\n clarify what happens if the input arguments are of an incorrect type.\n\n Own Id: OTP-6535","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.11.3.1 - Kernel Release Notes","ref":"notes.html#kernel-2-11-3-1"},{"type":"extras","doc":"- An erroneous packet size could be used for the first messages passed through a\n newly established connection between two Erlang nodes. This could cause\n messages to be discarded, or termination of the connection.\n\n Own Id: OTP-6473","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 2.11.3 - Kernel Release Notes","ref":"notes.html#kernel-2-11-3"},{"type":"extras","doc":"- On Unix, the `unix:cmd/1` function could leave an 'EXIT' message in the\n message queue for the calling process That problem was more likely to happen\n in an SMP emulator.\n\n Own Id: OTP-6368","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- More interfaces are added in erl_ddll, to support different usage scenarios.\n\n Own Id: OTP-6307 Aux Id: OTP-6234\n\n- Locks set by calling `global:set_lock()` were not always deleted when the\n locking process died. This bug has been fixed.\n\n Own Id: OTP-6341 Aux Id: seq10445","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.11.2 - Kernel Release Notes","ref":"notes.html#kernel-2-11-2"},{"type":"extras","doc":"- Behavior in case of disappeared nodes when using he dist_auto_connect once got\n changed in R11B-1. The timeouts regarding normal distributed operations is now\n reverted to the old (pre R11B-1).\n\n Own Id: OTP-6258 Aux Id: OTP-6200, seq10449\n\n- Start-up problems for the internal process used by the `inet:gethostbyname()`\n functions were eliminated. If the internal process (`inet_gethost_native`) had\n not previously been started, and if several processes at the same time called\n one of the `inet:gethostbyname()` functions, the calls could fail.\n\n Own Id: OTP-6286","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Code cleanup: the old internal obsolete file_server has been removed. It was\n only used when communicating with R7 and older nodes.\n\n Own Id: OTP-6245\n\n- Trying to open a non-existent or badly formed disk log no longer results in a\n crash report. In particular, `ets:file2tab/1` reports no error when the\n argument is not a well-formed disk log file. (The return value has not been\n changed, it is still an error tuple.)\n\n Own Id: OTP-6278 Aux Id: seq10421\n\n- There are new BIFs `erlang:spawn_monitor/1,3`, and the new option `monitor`\n for `spawn_opt/2,3,4,5`.\n\n The `observer_backend` module has been updated to handle the new BIFs.\n\n Own Id: OTP-6281\n\n- To help Dialyzer find more bugs, many functions in the Kernel and STDLIB\n applications now only accept arguments of the type that is documented.\n\n For instance, the functions `lists:prefix/2` and `lists:suffix/2` are\n documented to only accept lists as their arguments, but they actually accepted\n anything and returned `false`. That has been changed so that the functions\n cause an exception if one or both arguments are not lists.\n\n Also, the `string:strip/3` function is documented to take a character argument\n that is a character to strip from one or both ends of the string. Given a list\n instead of a character, it used to do nothing, but will now cause an\n exception.\n\n Dialyzer will find most cases where those functions are passed arguments of\n the wrong type.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-6295","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.11.1.1 - Kernel Release Notes","ref":"notes.html#kernel-2-11-1-1"},{"type":"extras","doc":"- There is now an option read_packets for UDP sockets that sets the maximum\n number of UDP packets that will be read for each invocation of the socket\n driver.\n\n Own Id: OTP-6249 Aux Id: seq10452","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.11.1 - Kernel Release Notes","ref":"notes.html#kernel-2-11-1"},{"type":"extras","doc":"- In R11B-0, the erl_ddll server process is always started. Despite that, the\n configuration parameter `start_ddll` for the Kernel application was still\n obeyed, which would cause the erl_ddll server to be started TWICE (and the\n system shutting down as a result). In this release, `start_ddll` is no longer\n used and its documentation has been removed.\n\n Own Id: OTP-6163\n\n- The kernel option \\{dist_auto_connect,once\\} could block out nodes that had\n never been connected, causing persistent partitioning of networks.\n Furthermore, partial restarts of networks could cause inconsistent global name\n databases. Both problems are now solved.\n\n Own Id: OTP-6200 Aux Id: seq10377","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Late arriving tcp_closed and udp_closed messages are now removed from the\n message queue of a process calling gen_tcp:close/1, gen_udp:close/1, and\n inet:close/1.\n\n Own Id: OTP-6197","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.11 - Kernel Release Notes","ref":"notes.html#kernel-2-11"},{"type":"extras","doc":"- When repairing a disk log with a corrupt index file (caused by for instance a\n hard disk failure) the old contents of the index file is kept unmodified. This\n will make repeated attempts to open the disk log fail every time.\n\n Own Id: OTP-5558 Aux Id: seq9823\n\n- Previously [`unlink/1`](`unlink/1`) and `erlang:demonitor/2` behaved\n completely asynchronous. This had one undesirable effect, though. You could\n never know when you were guaranteed _not_ to be affected by a link that you\n had unlinked or a monitor that you had demonitored.\n\n The new behavior of [`unlink/1`](`unlink/1`) and `erlang:demonitor/2` can be\n viewed as two operations performed atomically. Asynchronously send an unlink\n signal or a demonitor signal, and ignore any future results of the link or\n monitor.\n\n _NOTE_: This change can cause some obscure code to fail which previously did\n not. For example, the following code might hang:\n\n ```erlang\n Mon = erlang:monitor(process, Pid),\n %% ...\n exit(Pid, bang),\n erlang:demonitor(Mon),\n receive\n {'DOWN', Mon, process, Pid, _} -> ok\n %% We were previously guaranteed to get a down message\n %% (since we exited the process ourself), so we could\n %% in this case leave out:\n %% after 0 -> ok\n end,\n ```\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-5772\n\n- The behavior when an application fails to start and possibly causes the\n runtime system to halt has been cleaned up, including fixing some minor bugs.\n\n `application_controller` should now always terminate with a non-nested string,\n meaning the slogan in an `erl_crash.dump` should always be easy to read.\n\n `init` now makes sure that the slogan passed to `erlang:halt/1` does not\n exceed the maximum allowed length.\n\n Redundant calls to [`list_to_atom/1`](`list_to_atom/1`) has been removed from\n the primitive `error_logger` event handler. (Thanks Serge Aleynikov for\n pointing this out).\n\n The changes only affects the contents of the error messages and crashdump file\n slogan.\n\n Own Id: OTP-5964\n\n- The `erl_ddll` server is now started when OTP is started and placed under the\n Kernel supervisor. This fixes several minor issues. It used to be started on\n demand.\n\n The documentation for the `start` and `stop` functions in the `erl_ddll`\n module has been removed, as those functions are not meant to be used by other\n applications.\n\n Furthermore, the `erl_ddll:stop/1` function no longer terminates the\n `erl_ddll` server, as that would terminate the entire runtime system.\n\n Own Id: OTP-6033","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Removed some unused functions from `application_master`.\n\n Own Id: OTP-3889\n\n- Global no longer allows the registration of a process under more than one\n name. If the old (buggy) behavior is desired the Kernel application variable\n `global_multi_name_action` can be given the value `allow`.\n\n Own Id: OTP-5640 Aux Id: OTP-5603\n\n- The (slightly misleading) warnings that was shown when the `erlang.erl` file\n was compiled has been eliminated.\n\n Own Id: OTP-5947\n\n- The `auth` module API is deprecated.\n\n Own Id: OTP-6037\n\n- Added `erlang:demonitor/2`, making it possible to at the same time flush a\n received `'DOWN'` message, if there is one. See `m:erlang`.\n\n Own Id: OTP-6100 Aux Id: OTP-5772","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.10.13 - Kernel Release Notes","ref":"notes.html#kernel-2-10-13"},{"type":"extras","doc":"- Large files (more than 2 GBytes) are now handled on Solaris 8.\n\n Own Id: OTP-5849 Aux Id: seq10157\n\n- During startup, a garbage `{'DOWN', ...}` message was left by\n `inet_gethost_native`, that caused problems for the starting code server.\n\n Own Id: OTP-5978 Aux Id: OTP-5974","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- `global` now makes several attempts to connect nodes when maintaining the\n fully connected network. More than one attempt is sometimes needed under very\n heavy load.\n\n Own Id: OTP-5889\n\n- `erl_epmd` now explicitly sets the timeout to `infinity` when calling\n `gen_server:call`. The old timeout of 15 seconds could time out under very\n heavy load.\n\n Own Id: OTP-5959\n\n- Corrected the start of code server to use reference-tagged tuples to ensure\n that an unexpected message sent to the parent process does not cause a halt of\n the system. Also removed the useless `start/*` functions in both `code.erl`\n and `code_server.erl` and no longer exports the `init` function from\n `code_server.erl`.\n\n Own Id: OTP-5974 Aux Id: seq10243, OTP-5978","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.10.12 - Kernel Release Notes","ref":"notes.html#kernel-2-10-12"},{"type":"extras","doc":"- A bug in `global` has been fixed: the locker process added `nonode@nohost` to\n the list of nodes to lock. This could happen before any nodes got known to the\n global name server. Depending on net configuration the symptom was a delay.\n\n Own Id: OTP-5792 Aux Id: OTP-5563\n\n- If an `.app` file is missing, the error reason returned by\n `application:load/1` has been corrected to\n `{\"no such file or directory\", \"FILE.app\"}`, instead of the less informative\n `{\"unknown POSIX error\",\"FILE.app\"}`.\n\n Own Id: OTP-5809\n\n- Bug fixes: `disk_log:accessible_logs/0` no longer reports all `pg2` process\n groups as distributed disk logs; `disk_log:pid2name/1` did not recognize\n processes of distributed disk logs.\n\n Own Id: OTP-5810\n\n- The functions `file:consult/1`, `file:path_consult/2`, `file:eval/1,2`,\n `file:path_eval/2,3`, `file:script/1,2`, `file:path_script/2,3` now return\n correct line numbers in error tuples.\n\n Own Id: OTP-5814\n\n- If there were user-defined variables in the boot script, and their values were\n not provided using the `-boot_var` option, the emulator would refuse to start\n with a confusing error message. Corrected to show a clear, understandable\n message.\n\n The `prim_file` module was modified to not depend on the `lists` module, to\n make it possible to start the emulator using a user-defined loader. (Thanks to\n Martin Bjorklund.)\n\n Own Id: OTP-5828 Aux Id: seq10151\n\n- Minor corrections in the description of open modes. (Thanks to Richard\n Carlsson.)\n\n Own Id: OTP-5856","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- `application_controller` now terminates with the actual error reason, instead\n of `shutdown`. This means that the crash dump now should be somewhat more\n informative, in the case where the runtime system is terminated due to an\n error in an application.\n\n Example: If the (permanent) application `app1` fails to start, the slogan now\n will be:\n \"`Kernel pid terminated (application_controller) ({application_start_failure,app1,{shutdown, {app1,start,[normal,[]]}}})`\"\n\n rather than the previous\n \"`Kernel pid terminated (application_controller) (shutdown)`\".\n\n Own Id: OTP-5811","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.10.11.1 - Kernel Release Notes","ref":"notes.html#kernel-2-10-11-1"},{"type":"extras","doc":"- Timers could sometimes timeout too early. This bug has now been fixed.\n\n Automatic cancellation of timers created by `erlang:send_after(Time,` pid(),\n Msg), and `erlang:start_timer(Time,` pid(), Msg) has been introduced. Timers\n created with the receiver specified by a pid, will automatically be cancelled\n when the receiver exits. For more information see the `m:erlang` man page.\n\n In order to be able to maintain a larger amount of timers without increasing\n the maintenance cost, the internal timer wheel and bif timer table have been\n enlarged.\n\n Also a number of minor bif timer optimizations have been implemented.\n\n Own Id: OTP-5795 Aux Id: OTP-5090, seq8913, seq10139, OTP-5782","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Documentation improvements:\n\n \\- documentation for `erlang:link/1` corrected\n\n \\- command line flag `-code_path_cache` added\n\n \\- `erl` command line flags clarifications\n\n \\- `m:net_kernel` clarifications\n\n Own Id: OTP-5847","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.10.11 - Kernel Release Notes","ref":"notes.html#kernel-2-10-11"},{"type":"extras","doc":"- Several bug fixes and improvements in the global name registration facility\n (see `m:global`):\n\n - the name resolving procedure did not always unlink no longer registered\n processes;\n - the global name could sometimes hang when a `nodedown` was immediately\n followed by a `nodeup`;\n - global names were not always unregistered when a node went down;\n - it is now possible to set and delete locks at the same time as the global\n name server is resolving names--the handling of global locks has been\n separated from registration of global names;\n\n As of this version, `global` no longer supports nodes running Erlang/OTP R7B\n or earlier.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-5563\n\n- The functions `global:set_lock/3` and `global:trans/4` now accept the value\n `0` (zero) of the `Retries` argument.\n\n Own Id: OTP-5737\n\n- The `inet:getaddr(Addr, Family)` no longer validates the `Addr` argument if it\n is a 4 or 8 tuple containing the IP address, except for the size of the tuple\n and that it contains integers in the correct range.\n\n The reason for the change is that validation could cause the following\n sequence of calls to fail:\n\n `{ok,Addr} = inet:getaddr(localhost, inet6), gen_tcp:connect(Addr, 7, [inet6])`\n\n Own Id: OTP-5743","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The previously undocumented and UNSUPPORTED `zlib` module has been updated in\n an incompatible way and many bugs have been corrected. It is now also\n documented.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-5715\n\n- Added `application` interface functions `which_applications/1`, `set_env/4`\n and `unset_env/3`, which take an additional `Timeout` argument. To be used in\n situations where the standard gen_server timeout (5000ms) is not adequate.\n\n Own Id: OTP-5724 Aux Id: seq10083\n\n- Improved documentation regarding synchronized start of applications with\n included applications (using start phases and `application_starter`).\n\n Own Id: OTP-5754\n\n- New socket options `priority` and `tos` for platforms that support them\n (currently only Linux).\n\n Own Id: OTP-5756\n\n- The global name server has been optimized when it comes to maintaining a fully\n connected network.\n\n Own Id: OTP-5770","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.10.10.1 - Kernel Release Notes","ref":"notes.html#kernel-2-10-10-1"},{"type":"extras","doc":"- The native resolver has gotten an control API for extended debugging and soft\n restart. It is: `inet_gethost_native:control(Control)` \n `Control = {debug_level,Level} | soft_restart` \n `Level = integer() in the range 0-4`.\n\n Own Id: OTP-5751 Aux Id: EABln25013","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 2.10.10 - Kernel Release Notes","ref":"notes.html#kernel-2-10-10"},{"type":"extras","doc":"- If several processes (at the same node) simultaneously tried to start the same\n distributed application, this could lead to `application:start` returning an\n erroneous value, or even hang.\n\n Own Id: OTP-5606 Aux Id: seq9838","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The manual pages for most of the Kernel and some of the STDLIB modules have\n been updated, in particular regarding type definitions.\n\n The documentation of the return value for `erts:info/1` has been corrected.\n\n The documentation for `erlang:statistics/1` now lists all possible arguments.\n\n Own Id: OTP-5360\n\n- When the native resolver fails a `gethostbyaddr` lookup, `nxdomain` should be\n returned. There should be no attempt to fallback on a routine that succeeds if\n only the syntax of the IP address is valid. This has been fixed.\n\n Own Id: OTP-5598 Aux Id: OTP-5576\n\n- Replaced some tuple funs with the new `fun M:F/A` construct.\n\n The high-order functions in the `lists` module no longer accept bad funs under\n any circumstances. '`lists:map(bad_fun, [])`' used to return '`[]`' but now\n causes an exception.\n\n Unused, broken compatibility code in the `ets` module was removed. (Thanks to\n Dialyzer.)\n\n Eliminated 5 discrepancies found by Dialyzer in the Appmon application.\n\n Own Id: OTP-5633\n\n- The possibility to have comments following the list of tuples in a config file\n (file specified with the `-config` flag) has been added.\n\n Own Id: OTP-5661 Aux Id: seq10003","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.10.9 - Kernel Release Notes","ref":"notes.html#kernel-2-10-9"},{"type":"extras","doc":"- '`erl -config sys.config`' would fail to start if the `sys.config` file did\n not contain any whitespace at all after the dot. (Thanks to Anders Nygren.)\n\n Own Id: OTP-5543\n\n- A bug regarding tcp sockets which results in hanging `gen_tcp:send/2` has been\n corrected. To encounter this bug you needed one process that read from a\n socket, one that wrote more date than the reader read out so the sender got\n suspended, and then the reader closed the socket. (Reported and diagnosed by\n Alexey Shchepin.)\n\n Corrected a bug in the (undocumented and unsupported) option `{packet,http}`\n for `gen_tcp.` (Thanks to Claes Wikstrom and Luke Gorrie.)\n\n Updated the documentation regarding the second argument to `gen_tcp:recv/2`,\n the `Length` to receive.\n\n Own Id: OTP-5582 Aux Id: seq9839","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- At startup, the Erlang resolver hosts table was used to look up the name of\n the local (and possibly stand alone) host. This was incorrect. The configured\n resolver method is now used for this purpose.\n\n Own Id: OTP-5393\n\n- The `erlang:port_info/1` BIF is now documented. Minor corrections of the\n documentation for `erlang:port_info/2`.\n\n Added a note to the documentation of the `math` module that all functions are\n not available on all platforms.\n\n Added more information about the `+c` option in the `erl` man page in the ERTS\n documentation.\n\n Own Id: OTP-5555\n\n- The new `fun M:F/A` construct creates a fun that refers to the latest version\n of `M:F/A.` This syntax is meant to replace tuple funs `{M,F}` which have many\n problems.\n\n The new type test [`is_function(Fun,A)`](`is_function/2`) (which may be used\n in guards) test whether `Fun` is a fun that can be applied with `A` arguments.\n (Currently, `Fun` can also be a tuple fun.)\n\n Own Id: OTP-5584\n\n- According to the documentation `global` implements the equivalent of\n [`register/2`](`register/2`), which returns `badarg` if a process is already\n registered. As it turns out there is no check in `global` if a process is\n registered under more than one name. If some process is accidentally or by\n design given several names, it is possible that the name registry becomes\n inconsistent due to the way the resolve function is called when name clashes\n are discovered (see `register_name/3` in `m:global`).\n\n In OTP R11B `global` will not allow the registration of a process under more\n than one name. To help finding code where `no` will be returned, a Kernel\n application variable, `global_multi_name_action`, is hereby introduced.\n Depending on its value (`info`, `warning`, or `error`), messages are sent to\n the error logger when `global` discovers that some process is given more than\n one name. The variable only affects the node where it is defined.\n\n Own Id: OTP-5603","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.10.8 - Kernel Release Notes","ref":"notes.html#kernel-2-10-8"},{"type":"extras","doc":"- In case of a DNS lookup loop, `inet_db:getbyname` ends up building an infinite\n list. This has been fixed.\n\n Own Id: OTP-5449\n\n- When doing an `inet6` name lookup on an IPv4 address it was possible to get an\n address on IPv4 format back. This has been corrected. Some other minor\n inconsistencies regarding IPv6 name lookup have also been corrected.\n\n Own Id: OTP-5576","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.10.7 - Kernel Release Notes","ref":"notes.html#kernel-2-10-7"},{"type":"extras","doc":"- Under certain circumstances the `net_kernel` could emit spurious nodedown\n messages. This bug has been fixed.\n\n Own Id: OTP-5396\n\n- Removed description of the `keep_zombies` configuration parameter in the\n `kernel` man page.\n\n Own Id: OTP-5497","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Eliminated Dialyzer warnings (caused by dead code) in the `init` and\n `prim_file` modules.\n\n Own Id: OTP-5496\n\n- `inet_config` now also checks the environment variable `ERL_INETRC` for a\n possible user configuration file. See the ERTS User's Guide for details.\n\n Own Id: OTP-5512","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.10.6 - Kernel Release Notes","ref":"notes.html#kernel-2-10-6"},{"type":"extras","doc":"- The `c` option for the `+B` flag has been introduced which makes it possible\n to use Ctrl-C (Ctrl-Break on Windows) to interrupt the shell process rather\n than to invoke the emulator break handler. All new `+B` options are also\n supported on Windows (werl) as of now. Furthermore, Ctrl-C on Windows has now\n been reserved for copying text (what Ctrl-Ins was used for previously).\n Ctrl-Break should be used for break handling. Lastly, the documentation of the\n system flags has been updated.\n\n Own Id: OTP-5388\n\n- The possibility to start the Erlang shell in parallel with the rest of the\n system was reintroduced for backwards compatibility in STDLIB 1.13.1. The flag\n to be used for this is now called `async_shell_start` and has been documented.\n New shells started from the JCL menu are not synchronized with `init` anymore.\n This makes it possible to start a new shell (e.g. for debugging purposes) even\n if the initial shell has not come up.\n\n Own Id: OTP-5406 Aux Id: OTP-5218","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.10.5 - Kernel Release Notes","ref":"notes.html#kernel-2-10-5"},{"type":"extras","doc":"- Documentation for `erlang:binary_to_float/1` deleted. The BIF itself was\n removed several releases ago.\n\n Updated documentation for [`apply/2`](`apply/2`) and [`apply/3`](`apply/3`).\n\n Own Id: OTP-5391","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- `net_kernel:monitor_nodes/2` which takes a flag and an option list has been\n added. By use of `net_kernel:monitor_nodes/2` one can subscribe for\n `nodeup/nodedown` messages with extra information. It is now possible to\n monitor hidden nodes, and get `nodedown` reason. See the `m:net_kernel`\n documentation for more information.\n\n Own Id: OTP-5374","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.10.4 - Kernel Release Notes","ref":"notes.html#kernel-2-10-4"},{"type":"extras","doc":"- The application master for an application now terminates the application\n faster, which reduces the risk for timeouts in other parts of the system.\n\n Own Id: OTP-5363 Aux Id: EABln19084\n\n- A BIF `erlang:raise/3` has been added. See the manual for details. It is\n intended for internal system programming only, advanced error handling.\n\n Own Id: OTP-5376 Aux Id: OTP-5257","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Kernel 2.10.3 - Kernel Release Notes","ref":"notes.html#kernel-2-10-3"},{"type":"extras","doc":"- With the `-eval` flag (`erl -eval Expr`), an arbitrary expression can be\n evaluated during system initialization. This is documented in `m:init`.\n\n Own Id: OTP-5260\n\n- The unsupported and undocumented modules `socks5`, `socks5_auth`,\n `socks5_tcp`, and `socks5_udp` have been removed.\n\n Own Id: OTP-5266","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Kernel 2.10.1 - Kernel Release Notes","ref":"notes.html#kernel-2-10-1"},{"type":"extras","doc":"- The Pman 'trace shell' functionality was broken and has now been fixed.\n Furthermore, Pman could not correctly find the pid of the active shell if more\n than one shell process was running on the node. This has also been corrected.\n\n Own Id: OTP-5191\n\n- The documentation for the `auth:open/1` function which no longer exists has\n been removed. (Thanks to Miguel Barreiro.)\n\n Own Id: OTP-5208\n\n- Corrected the `crc32/3` function in the undocumented and unsupported `zlib`\n module.\n\n Own Id: OTP-5227","title":"Fixed Bugs and Malfunctions - Kernel Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- You can now start Erlang with the `-rsh` flag which gives you a remote initial\n shell instead of a local one. Example:\n\n ```text\n erl -sname this_node -rsh other_node@other_host\n ```\n\n Own Id: OTP-5210\n\n- If `/etc/hosts` specified two hosts with the same IP address (on separate\n lines), only the last host would be registered by inet_db during inet\n configuration. This has been corrected now so that both aliases are registered\n with the same IP address.\n\n Own Id: OTP-5212 Aux Id: seq7128\n\n- The documentation for BIFs that take I/O lists have been clarified. Those are\n [`list_to_binary/1`](`list_to_binary/1`),\n [`port_command/2`](`port_command/2`), [`port_control/3`](`port_control/3`).\n\n Documentation for all `is_*` BIFs (such as [`is_atom/1`](`is_atom/1`)) has\n been added.\n\n Removed the documentation for `erlang:float_to_binary/2` which was removed\n from the run-time system several releases ago.\n\n Own Id: OTP-5222","title":"Improvements and New Features - Kernel Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"\n# Introduction","title":"Introduction","ref":"introduction_chapter.html"},{"type":"extras","doc":"The Kernel application has all the code necessary to run the Erlang runtime\nsystem: file servers, code servers, and so on.\n\nThe Kernel application is the first application started. It is mandatory in the\nsense that the minimal system based on Erlang/OTP consists of Kernel and STDLIB.\nKernel contains the following functional areas:\n\n- Start, stop, supervision, configuration, and distribution of applications\n- Code loading\n- Logging\n- Global name service\n- Supervision of Erlang/OTP\n- Communication with sockets\n- Operating system interface","title":"Scope - Introduction","ref":"introduction_chapter.html#scope"},{"type":"extras","doc":"It is assumed that the reader is familiar with the Erlang programming language.","title":"Prerequisites - Introduction","ref":"introduction_chapter.html#prerequisites"},{"type":"extras","doc":"\n# Socket Usage","title":"Socket Usage","ref":"socket_usage.html"},{"type":"extras","doc":"The socket interface (module) is basically a \"thin\" layer on top of the OS\nsocket interface. It is assumed that, unless you have special needs,\ngen\\_\\[tcp|udp|sctp] should be sufficient (when they become available).\n\nNote that just because we have a documented and described option, it does _not_\nmean that the OS supports it. So its recommended that the user reads the\nplatform specific documentation for the option used.","title":"Introduction - Socket Usage","ref":"socket_usage.html#introduction"},{"type":"extras","doc":"Some functions allow for an _asynchronous_ call\n([`accept/2`](`m:socket#accept-nowait`),\n[`connect/3`](`m:socket#connect-nowait`), [`recv/3,4`](`m:socket#recv-nowait`),\n[`recvfrom/3,4`](`m:socket#recvfrom-nowait`),\n[`recvmsg/2,3,5`](`m:socket#recvmsg-nowait`),\n[`send/3,4`](`m:socket#send-nowait`), [`sendmsg/3,4`](`m:socket#sendmsg-nowait`)\nand [`sendto/4,5`](`m:socket#sendto-nowait`)). This is achieved by setting the\n`Timeout` argument to `nowait`. For instance, if calling the\n[`recv/3`](`m:socket#recv-nowait`) function with Timeout set to `nowait` (i.e.\n`recv(Sock, 0, nowait)`) when there is actually nothing to read, it will return\nwith:\n\n- **On Unix** - `{select, `[`SelectInfo`](`t:socket:select_info/0`)`}`\n\n `SelectInfo` contains the [`SelectHandle`](`t:socket:select_handle/0`).\n\n- **On Windows** -\n `{completion, `[`CompletionInfo`](`t:socket:completion_info/0`)`}`\n\n `CompletionInfo` contains the\n [`CompletionHandle`](`t:socket:completion_handle/0`).\n\nWhen data eventually arrives a 'select' or 'completion' message will be sent to\nthe caller:\n\n- **On Unix** - `{'$socket', socket(), select, SelectHandle}`\n\n The caller can then make another call to the recv function and now expect\n data.\n\n Note that all other users are _locked out_ until the 'current user' has called\n the function (recv in this case). So either immediately call the function or\n [`cancel`](`socket:cancel/2`).\n\n- **On Windows** -\n `{'$socket', socket(), completion, {CompletionHandle, CompletionStatus}}`\n\n The `CompletionStatus` contains the result of the operation (read).\n\nThe user must also be prepared to receive an abort message:\n\n- `{'$socket', socket(), abort, Info}`\n\nIf the operation is aborted for whatever reason (e.g. if the socket is closed\n\"by someone else\"). The `Info` part contains the abort reason (in this case that\nthe socket has been closed `Info = {SelectHandle, closed}`).\n\nThe general form of the 'socket' message is:\n\n- `{'$socket', Sock :: socket(), Tag :: atom(), Info :: term()}`\n\nWhere the format of `Info` is a function of `Tag`:\n\n| _Tag_ | _Info value type_ |\n| ---------- | ----------------------------------------- |\n| select | select_handle() |\n| completion | \\{completion_handle(), CompletionStatus\\} |\n| abort | \\{select_handle(), Reason :: term()\\} |\n\n_Table: socket message info value type_\n\nThe `select_handle()` is the same as was returned in the\n[`SelectInfo`](`t:socket:select_info/0`).\n\nThe `completion_handle()` is the same as was returned in the\n[`CompletionInfo`](`t:socket:completion_info/0`).","title":"Asynchronous calls - Socket Usage","ref":"socket_usage.html#asynchronous-calls"},{"type":"extras","doc":"The _socket registry_ is how we keep track of sockets. There are two functions\nthat can be used for interaction: `socket:number_of/0` and\n`socket:which_sockets/1`.\n\nIn systems which create and delete _many_ sockets dynamically, it (the socket\nregistry) could become a bottleneck. For such systems, there are a couple of\nways to control the use of the socket registry.\n\nFirstly, its possible to effect the global default value when building OTP from\nsource with the two configure options:\n\n```text\n--enable-esock-socket-registry (default) | --disable-esock-socket-registry\n```\n\nSecond, its possible to effect the global default value by setting the\nenvironment variable `ESOCK_USE_SOCKET_REGISTRY` (boolean) before starting the\nerlang.\n\nThird, its possible to alter the global default value in runtime by calling the\nfunction [`use_registry/1`](`socket:use_registry/1`).\n\nAnd finally, its possible to override the global default when creating a socket\n(with [`open/2`](`socket:open/2`) and [`open/4`](`socket:open/4`)) by providing\nthe attribute `use_registry` (boolean) in the their `Opts` argument (which\neffects _that_ specific socket).","title":"Socket Registry - Socket Usage","ref":"socket_usage.html#socket-registry"},{"type":"extras","doc":"This example is intended to show how to create a simple (echo) server\n(and client).\n\n```erlang\n-module(example).\n\n-export([client/2, client/3]).\n-export([server/0, server/1, server/2]).\n\n\n%% ======================================================================\n\n%% === Client ===\n\nclient(#{family := Family} = ServerSockAddr, Msg)\n when is_list(Msg) orelse is_binary(Msg) ->\n {ok, Sock} = socket:open(Family, stream, default),\n ok = maybe_bind(Sock, Family),\n ok = socket:connect(Sock, ServerSockAddr),\n client_exchange(Sock, Msg);\n\nclient(ServerPort, Msg)\n when is_integer(ServerPort) andalso (ServerPort > 0) ->\n Family = inet, % Default\n Addr = get_local_addr(Family), % Pick an address\n SockAddr = #{family => Family,\n\t\t addr => Addr,\n\t\t port => ServerPort},\n client(SockAddr, Msg).\n\nclient(ServerPort, ServerAddr, Msg)\n when is_integer(ServerPort) andalso (ServerPort > 0) andalso\n is_tuple(ServerAddr) ->\n Family = which_family(ServerAddr),\n SockAddr = #{family => Family,\n\t\t addr => ServerAddr,\n\t\t port => ServerPort},\n client(SockAddr, Msg).\n\n%% Send the message to the (echo) server and wait for the echo to come back.\nclient_exchange(Sock, Msg) when is_list(Msg) ->\n client_exchange(Sock, list_to_binary(Msg));\nclient_exchange(Sock, Msg) when is_binary(Msg) ->\n ok = socket:send(Sock, Msg, infinity),\n {ok, Msg} = socket:recv(Sock, byte_size(Msg), infinity),\n ok.\n\n\n%% ======================================================================\n\n%% === Server ===\n\nserver() ->\n %% Make system choose port (and address)\n server(0).\n\n%% This function return the port and address that it actually uses,\n%% in case server/0 or server/1 (with a port number) was used to start it.\n\nserver(#{family := Family, addr := Addr, port := _} = SockAddr) ->\n {ok, Sock} = socket:open(Family, stream, tcp),\n ok = socket:bind(Sock, SockAddr),\n ok = socket:listen(Sock),\n {ok, #{port := Port}} = socket:sockname(Sock),\n Acceptor = start_acceptor(Sock),\n {ok, {Port, Addr, Acceptor}};\n\nserver(Port) when is_integer(Port) ->\n Family = inet, % Default\n Addr = get_local_addr(Family), % Pick an address\n SockAddr = #{family => Family,\n\t\t addr => Addr,\n\t\t port => Port},\n server(SockAddr).\n\nserver(Port, Addr)\n when is_integer(Port) andalso (Port >= 0) andalso\n is_tuple(Addr) ->\n Family = which_family(Addr),\n SockAddr = #{family => Family,\n\t\t addr => Addr,\n\t\t port => Port},\n server(SockAddr).\n\n\n%% --- Echo Server - Acceptor ---\n\nstart_acceptor(LSock) ->\n Self = self(),\n {Pid, MRef} = spawn_monitor(fun() -> acceptor_init(Self, LSock) end),\n receive\n\t{'DOWN', MRef, process, Pid, Info} ->\n\t erlang:error({failed_starting_acceptor, Info});\n\t{Pid, started} ->\n\t %% Transfer ownership\n\t socket:setopt(LSock, otp, owner, Pid),\n\t Pid ! {self(), continue},\n\t erlang:demonitor(MRef),\n\t Pid\n end.\n \nacceptor_init(Parent, LSock) ->\n Parent ! {self(), started},\n receive\n\t{Parent, continue} ->\n\t ok\n end,\n acceptor_loop(LSock).\n\nacceptor_loop(LSock) ->\n case socket:accept(LSock, infinity) of\n\t{ok, ASock} ->\n\t start_handler(ASock),\n\t acceptor_loop(LSock);\n\t{error, Reason} ->\n\t erlang:error({accept_failed, Reason})\n end.\n\n\n%% --- Echo Server - Handler ---\n\nstart_handler(Sock) ->\n Self = self(),\n {Pid, MRef} = spawn_monitor(fun() -> handler_init(Self, Sock) end),\n receive\n\t{'DOWN', MRef, process, Pid, Info} ->\n\t erlang:error({failed_starting_handler, Info});\n\t{Pid, started} ->\n\t %% Transfer ownership\n\t socket:setopt(Sock, otp, owner, Pid),\n\t Pid ! {self(), continue},\n\t erlang:demonitor(MRef),\n\t Pid\n end.\n\nhandler_init(Parent, Sock) ->\n Parent ! {self(), started},\n receive\n\t{Parent, continue} ->\n\t ok\n end,\n handler_loop(Sock, undefined).\n\n%% No \"ongoing\" reads\n%% The use of 'nowait' here is clearly *overkill* for this use case,\n%% but is intended as an example of how to use it.\nhandler_loop(Sock, undefined) ->\n case socket:recv(Sock, 0, nowait) of\n\t{ok, Data} ->\n\t echo(Sock, Data),\n\t handler_loop(Sock, undefined);\n\n\t{select, SelectInfo} ->\n\t handler_loop(Sock, SelectInfo);\n\n\t{completion, CompletionInfo} ->\n\t handler_loop(Sock, CompletionInfo);\n\n\t{error, Reason} ->\n\t erlang:error({recv_failed, Reason})\n end;\n\n%% This is the standard (asyncronous) behaviour.\nhandler_loop(Sock, {select_info, recv, SelectHandle}) ->\n receive\n\t{'$socket', Sock, select, SelectHandle} ->\n\t case socket:recv(Sock, 0, nowait) of\n\t\t{ok, Data} ->\n\t\t echo(Sock, Data),\n\t\t handler_loop(Sock, undefined);\n\n\t\t{select, NewSelectInfo} ->\n\t\t handler_loop(Sock, NewSelectInfo);\n\n\t\t{error, Reason} ->\n\t\t erlang:error({recv_failed, Reason})\n\t end\n end;\n\n%% This is the (asyncronous) behaviour on platforms that support 'completion',\n%% currently only Windows.\nhandler_loop(Sock, {completion_info, recv, CompletionHandle}) ->\n receive\n\t{'$socket', Sock, completion, {CompletionHandle, CompletionStatus}} ->\n\t case CompletionStatus of\n\t\t{ok, Data} ->\n\t\t echo(Sock, Data),\n\t\t handler_loop(Sock, undefined);\n\t\t{error, Reason} ->\n\t\t erlang:error({recv_failed, Reason})\n\t end\n end.\n\necho(Sock, Data) when is_binary(Data) ->\n ok = socket:send(Sock, Data, infinity),\n io:format(\"** ECHO **\"\n\t \"~n~s~n\", [binary_to_list(Data)]).\n\n\n%% ======================================================================\n\n%% === Utility functions ===\n\nmaybe_bind(Sock, Family) ->\n maybe_bind(Sock, Family, os:type()).\n\nmaybe_bind(Sock, Family, {win32, _}) ->\n Addr = get_local_addr(Family),\n SockAddr = #{family => Family,\n addr => Addr,\n port => 0},\n socket:bind(Sock, SockAddr);\nmaybe_bind(_Sock, _Family, _OS) ->\n ok.\n\n%% The idea with this is extract a \"usable\" local address\n%% that can be used even from *another* host. And doing\n%% so using the net module.\n\nget_local_addr(Family) ->\n Filter =\n\tfun(#{addr := #{family := Fam},\n\t flags := Flags}) ->\n\t\t(Fam =:= Family) andalso (not lists:member(loopback, Flags));\n\t (_) ->\n\t\tfalse\n\tend,\n {ok, [SockAddr|_]} = net:getifaddrs(Filter),\n #{addr := #{addr := Addr}} = SockAddr,\n Addr.\n\nwhich_family(Addr) when is_tuple(Addr) andalso (tuple_size(Addr) =:= 4) ->\n inet;\nwhich_family(Addr) when is_tuple(Addr) andalso (tuple_size(Addr) =:= 8) ->\n inet6.\n```\n\n\n[](){: #socket_options }","title":"Example - Socket Usage","ref":"socket_usage.html#example"},{"type":"extras","doc":"Options for level `otp`:\n\n| _Option Name_ | _Value Type_ | _Set_ | _Get_ | _Other Requirements and comments_ |\n| ------------------- | ------------------------------------------------------------- | ----- | ----- | ---------------------------------------------------------------------------------------------------------------------------------------------- |\n| assoc_id | integer() | no | yes | type = seqpacket, protocol = sctp, is an association |\n| debug | boolean() | yes | yes | none |\n| iow | boolean() | yes | yes | none |\n| controlling_process | pid() | yes | yes | none |\n| rcvbuf | default \\| pos_integer() \\| \\{pos_integer(), pos_ineteger()\\} | yes | yes | The tuple format is _not_ allowed on Windows. 'default' only valid for set. The tuple form is only valid for type 'stream' and protocol 'tcp'. |\n| rcvctrlbuf | default \\| pos_integer() | yes | yes | default only valid for set |\n| sndctrlbuf | default \\| pos_integer() | yes | yes | default only valid for set |\n| fd | integer() | no | yes | none |\n| use_registry | boolean() | no | yes | the value is set when the socket is created, by a call to [`open/2`](`socket:open/2`) or [`open/4`](`socket:open/4`). |\n\n_Table: option levels_\n\nOptions for level `socket`:\n\n| _Option Name_ | _Value Type_ | _Set_ | _Get_ | _Other Requirements and comments_ |\n| ---------------- | ----------------- | ----- | ----- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| acceptconn | boolean() | no | yes | none |\n| bindtodevice | string() | yes | yes | Before Linux 3.8, this socket option could be set, but not get. Only works for some socket types (e.g. `inet`). If empty value is set, the binding is removed. |\n| broadcast | boolean() | yes | yes | type = dgram |\n| bsp_state | map() | no | yes | Windows only |\n| debug | integer() | yes | yes | may require admin capability |\n| domain | domain() | no | yes | _Not_ on FreeBSD (for instance) |\n| dontroute | boolean() | yes | yes | none |\n| exclusiveaddruse | boolean() | yes | yes | Windows only |\n| keepalive | boolean() | yes | yes | none |\n| linger | abort \\| linger() | yes | yes | none |\n| maxdg | integer() | no | yes | Windows only |\n| max_msg_size | integer() | no | yes | Windows only |\n| oobinline | boolean() | yes | yes | none |\n| peek_off | integer() | yes | yes | domain = local (unix). Currently disabled due to a possible infinite loop when calling recv(\\[peek]) the second time. |\n| priority | integer() | yes | yes | none |\n| protocol | protocol() | no | yes | _Not_ on (some) Darwin (for instance) |\n| rcvbuf | non_neg_integer() | yes | yes | none |\n| rcvlowat | non_neg_integer() | yes | yes | none |\n| rcvtimeo | timeval() | yes | yes | This option is not normally supported (see why below). OTP has to be explicitly built with the `--enable-esock-rcvsndtime` configure option for this to be available. Since our implementation is _nonblocking_, its unknown if and how this option works, or even if it may cause malfunctions. Therefore, we do not recommend setting this option. Instead, use the `Timeout` argument to, for instance, the [`recv/3`](`socket:recv/3`) function. |\n| reuseaddr | boolean() | yes | yes | none |\n| reuseport | boolean() | yes | yes | domain = inet \\| inet6 |\n| sndbuf | non_neg_integer() | yes | yes | none |\n| sndlowat | non_neg_integer() | yes | yes | not changeable on Linux |\n| sndtimeo | timeval() | yes | yes | This option is not normally supported (see why below). OTP has to be explicitly built with the `--enable-esock-rcvsndtime` configure option for this to be available. Since our implementation is _nonblocking_, its unknown if and how this option works, or even if it may cause malfunctions. Therefore, we do not recommend setting this option. Instead, use the `Timeout` argument to, for instance, the [`send/3`](`socket:send/3`) function. |\n| timestamp | boolean() | yes | yes | none |\n| type | type() | no | yes | none |\n\n_Table: socket options_\n\nOptions for level `ip`:\n\n| _Option Name_ | _Value Type_ | _Set_ | _Get_ | _Other Requirements and comments_ |\n| ---------------------- | --------------------- | ----- | ----- | ---------------------------------------------------------- |\n| add_membership | ip_mreq() | yes | no | none |\n| add_source_membership | ip_mreq_source() | yes | no | none |\n| block_source | ip_mreq_source() | yes | no | none |\n| drop_membership | ip_mreq() | yes | no | none |\n| drop_source_membership | ip_mreq_source() | yes | no | none |\n| freebind | boolean() | yes | yes | none |\n| hdrincl | boolean() | yes | yes | type = raw |\n| minttl | integer() | yes | yes | type = raw |\n| msfilter | null \\| ip_msfilter() | yes | no | none |\n| mtu | integer() | no | yes | type = raw |\n| mtu_discover | ip_pmtudisc() | yes | yes | none |\n| multicast_all | boolean() | yes | yes | none |\n| multicast_if | any \\| ip4_address() | yes | yes | none |\n| multicast_loop | boolean() | yes | yes | none |\n| multicast_ttl | uint8() | yes | yes | none |\n| nodefrag | boolean() | yes | yes | type = raw |\n| pktinfo | boolean() | yes | yes | type = dgram |\n| recvdstaddr | boolean() | yes | yes | type = dgram |\n| recverr | boolean() | yes | yes | none |\n| recvif | boolean() | yes | yes | type = dgram \\| raw |\n| recvopts | boolean() | yes | yes | type =/= stream |\n| recvorigdstaddr | boolean() | yes | yes | none |\n| recvttl | boolean() | yes | yes | type =/= stream |\n| retopts | boolean() | yes | yes | type =/= stream |\n| router_alert | integer() | yes | yes | type = raw |\n| sendsrcaddr | boolean() | yes | yes | none |\n| tos | ip_tos() | yes | yes | some high-priority levels may require superuser capability |\n| transparent | boolean() | yes | yes | requires admin capability |\n| ttl | integer() | yes | yes | none |\n| unblock_source | ip_mreq_source() | yes | no | none |\n\n_Table: ip options_\n\nOptions for level `ipv6`:\n\n| _Option Name_ | _Value Type_ | _Set_ | _Get_ | _Other Requirements and comments_ |\n| ---------------------- | ------------------ | ----- | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| addrform | inet | yes | no | allowed only for IPv6 sockets that are connected and bound to a v4-mapped-on-v6 address |\n| add_membership | ipv6_mreq() | yes | no | none |\n| authhdr | boolean() | yes | yes | type = dgram \\| raw, obsolete? |\n| drop_membership | ipv6_mreq() | yes | no | none |\n| dstopts | boolean() | yes | yes | type = dgram \\| raw, requires superuser privileges to update |\n| flowinfo | boolean() | yes | yes | type = dgram \\| raw, requires superuser privileges to update |\n| hoplimit | boolean() | yes | yes | type = dgram \\| raw. On some platforms (e.g. FreeBSD) is used to set in order to get `hoplimit` as a control message heeader. On others (e.g. Linux), `recvhoplimit` is set in order to get `hoplimit`. |\n| hopopts | boolean() | yes | yes | type = dgram \\| raw, requires superuser privileges to update |\n| mtu | boolean() | yes | yes | Get: Only after the socket has been connected |\n| mtu_discover | ipv6_pmtudisc() | yes | yes | none |\n| multicast_hops | default \\| uint8() | yes | yes | none |\n| multicast_if | integer() | yes | yes | type = dgram \\| raw |\n| multicast_loop | boolean() | yes | yes | none |\n| recverr | boolean() | yes | yes | none |\n| recvhoplimit | boolean() | yes | yes | type = dgram \\| raw. On some platforms (e.g. Linux), `recvhoplimit` is set in order to get `hoplimit` |\n| recvpktinfo \\| pktinfo | boolean() | yes | yes | type = dgram \\| raw. On some platforms (e.g. FreeBSD) is used to set in order to get `hoplimit` as a control message heeader. On others (e.g. Linux), `recvhoplimit` is set in order to get `hoplimit`. |\n| recvtclass | boolean() | yes | yes | type = dgram \\| raw. On some platforms is used to set (=true) in order to get the `tclass` control message heeader. On others, `tclass` is set in order to get `tclass` control message heeader. |\n| router_alert | integer() | yes | yes | type = raw |\n| rthdr | boolean() | yes | yes | type = dgram \\| raw, requires superuser privileges to update |\n| tclass | integer() | yes | yes | Set the traffic class associated with outgoing packets. RFC3542. |\n| unicast_hops | default \\| uint8() | yes | yes | none |\n| v6only | boolean() | yes | no | none |\n\n_Table: ipv6 options_\n\nOptions for level `tcp`:\n\n| _Option Name_ | _Value Type_ | _Set_ | _Get_ | _Other Requirements and comments_ |\n| ------------- | ------------ | ----- | ----- | -------------------------------------------------------------------------------------------------------- |\n| congestion | string() | yes | yes | none |\n| cork | boolean() | yes | yes | 'nopush' one some platforms (FreeBSD) |\n| keepcnt | integer() | yes | yes | On Windows (at least), it is illegal to set to a value greater than 255. |\n| keepidle | integer() | yes | yes | none |\n| keepintvl | integer() | yes | yes | none |\n| maxseg | integer() | yes | yes | Set not allowed on all platforms. |\n| nodelay | boolean() | yes | yes | none |\n| nopush | boolean() | yes | yes | 'cork' on some platforms (Linux). On Darwin this has a different meaning than on, for instance, FreeBSD. |\n\n_Table: tcp options_\n\nOptions for level `udp`:\n\n| _Option Name_ | _Value Type_ | _Set_ | _Get_ | _Other Requirements and comments_ |\n| ------------- | ------------ | ----- | ----- | --------------------------------- |\n| cork | boolean() | yes | yes | none |\n\n_Table: udp options_\n\nOptions for level `sctp`:\n\n| _Option Name_ | _Value Type_ | _Set_ | _Get_ | _Other Requirements and comments_ |\n| ----------------- | ---------------------- | ----- | ----- | --------------------------------- |\n| associnfo | sctp_assocparams() | yes | yes | none |\n| autoclose | non_neg_integer() | yes | yes | none |\n| disable_fragments | boolean() | yes | yes | none |\n| events | sctp_event_subscribe() | yes | no | none |\n| initmsg | sctp_initmsg() | yes | yes | none |\n| maxseg | non_neg_integer() | yes | yes | none |\n| nodelay | boolean() | yes | yes | none |\n| rtoinfo | sctp_rtoinfo() | yes | yes | none |\n\n_Table: sctp options_","title":"Socket Options - Socket Usage","ref":"socket_usage.html#socket-options"},{"type":"extras","doc":"\n# Logging\n\nErlang provides a standard API for logging through `Logger`, which is part of\nthe Kernel application. Logger consists of the API for issuing log events, and a\ncustomizable backend where log handlers, filters and formatters can be plugged\nin.\n\nBy default, the Kernel application installs one log handler at system start.\nThis handler is named `default`. It receives and processes standard log events\nproduced by the Erlang runtime system, standard behaviours and different\nErlang/OTP applications. The log events are by default written to the terminal.\n\nYou can also configure the system so that the default handler prints log events\nto a single file, or to a set of wrap logs via `m:disk_log`.\n\nBy configuration, you can also modify or disable the default handler, replace it\nby a custom handler, and install additional handlers.","title":"Logging","ref":"logger_chapter.html"},{"type":"extras","doc":"A _log event_ consists of a _log level_, the _message_ to be logged, and\n_metadata_.\n\nThe Logger backend forwards log events from the API, first through a set of\n_primary filters_, then through a set of secondary filters attached to each log\nhandler. The secondary filters are in the following named _handler filters_.\n\nEach filter set consists of a _log level check_, followed by zero or more\n_filter functions_.\n\nThe following figure shows a conceptual overview of Logger. The figure shows two\nlog handlers, but any number of handlers can be installed.\n\n```mermaid\n---\ntitle: Conceptual Overview\n---\nflowchart TD\n DB[(Config DB)]\n API ---> ML[Module Level Global Level Global Filters]\n API -.Update configuration.-> DB\n ML -.-> DB\n ML ---> HL1[Hander Level Handler Filter]\n ML ---> HL2[Hander Level Handler Filter]\n HL1 ---> HC1[Handler Callback]\n HL2 ---> HC2[Handler Callback]\n HL1 -.-> DB\n HL2 -.-> DB\n subgraph Legend\n direction LR\n start1[ ] -->|Log event flow| stop1[ ]\n style start1 height:0px;\n style stop1 height:0px;\n start2[ ] -.->|Look up configuration| stop2[ ]\n style start2 height:0px;\n style stop2 height:0px;\n end\n```\n\nLog levels are expressed as atoms. Internally in Logger, the atoms are mapped to\ninteger values, and a log event passes the log level check if the integer value\nof its log level is less than or equal to the currently configured log level.\nThat is, the check passes if the event is equally or more severe than the\nconfigured level. See section [Log Level](#log-level) for a\nlisting and description of all log levels.\n\nThe primary log level can be overridden by a log level configured per module.\nThis is to, for instance, allow more verbose logging from a specific part of the\nsystem.\n\nFilter functions can be used for more sophisticated filtering than the log level\ncheck provides. A filter function can stop or pass a log event, based on any of\nthe event's contents. It can also modify all parts of the log event. See section\n[Filters](#filters) for more details.\n\nIf a log event passes through all primary filters and all handler filters for a\nspecific handler, Logger forwards the event to the _handler callback_. The\nhandler formats and prints the event to its destination. See section\n[Handlers](#handlers) for more details.\n\nEverything up to and including the call to the handler callbacks is executed on\nthe client process, that is, the process where the log event was issued. It is\nup to the handler implementation if other processes are involved or not.\n\nThe handlers are called in sequence, and the order is not defined.","title":"Overview - Logging","ref":"logger_chapter.html#overview"},{"type":"extras","doc":"The API for logging consists of a set of [macros](`m:logger#module-macros`), and a set\nof functions on the form `logger:Level/1,2,3`, which are all shortcuts for\n[`logger:log(Level,Arg1[,Arg2[,Arg3]])`](`logger:log/2`).\n\nThe macros are defined in `logger.hrl`, which is included in a module with the\ndirective\n\n```erlang\n-include_lib(\"kernel/include/logger.hrl\").\n```\n\nThe difference between using the macros and the exported functions is that\nmacros add location (originator) information to the metadata, and performs lazy\nevaluation by wrapping the logger call in a case statement, so it is only\nevaluated if the log level of the event passes the primary log level check.","title":"Logger API - Logging","ref":"logger_chapter.html#logger-api"},{"type":"extras","doc":"The log level indicates the severity of a event. In accordance with the Syslog\nprotocol, [RFC 5424](https://www.ietf.org/rfc/rfc5424.txt), eight log levels can\nbe specified. The following table lists all possible log levels by name (atom),\ninteger value, and description:\n\n| **Level** | **Integer** | **Description** |\n| --------- | ----------- | --------------------------------- |\n| emergency | 0 | system is unusable |\n| alert | 1 | action must be taken immediately |\n| critical | 2 | critical conditions |\n| error | 3 | error conditions |\n| warning | 4 | warning conditions |\n| notice | 5 | normal but significant conditions |\n| info | 6 | informational messages |\n| debug | 7 | debug-level messages |\n\n_Table: Log Levels_\n\nNotice that the integer value is only used internally in Logger. In the API, you\nmust always use the atom. To compare the severity of two log levels, use\n`logger:compare_levels/2`.","title":"Log Level - Logging","ref":"logger_chapter.html#log-level"},{"type":"extras","doc":"The log message contains the information to be logged. The message can consist\nof a format string and arguments (given as two separate parameters in the Logger\nAPI), a string or a report.\n\nExample, format string and arguments:\n\n```erlang\nlogger:error(\"The file does not exist: ~ts\",[Filename])\n```\n\nExample, string:\n\n```erlang\nlogger:notice(\"Something strange happened!\")\n```\n\nA report, which is either a map or a key-value list, is the preferred way to log\nusing Logger as it makes it possible for different backends to filter and format\nthe log event as it needs to.\n\nExample, report:\n\n```erlang\n?LOG_ERROR(#{ user => joe, filename => Filename, reason => enoent })\n```\n\nReports can be accompanied by a _report callback_ specified in the log event's\n[metadata](#metadata). The report callback is a convenience\nfunction that the [formatter](#formatters) can use to convert\nthe report to a format string and arguments, or directly to a string. The\nformatter can also use its own conversion function, if no callback is provided,\nor if a customized formatting is desired.\n\nThe report callback must be a fun with one or two arguments. If it takes one\nargument, this is the report itself, and the fun returns a format string and\narguments:\n\n```erlang\nfun((logger:report()) -> {io:format(),[term()]})\n```\n\nIf it takes two arguments, the first is the report, and the second is a map\ncontaining extra data that allows direct conversion to a string:\n\n```erlang\nfun((logger:report(),logger:report_cb_config()) -> unicode:chardata())\n```\n\nThe fun must obey the `depth` and `chars_limit` parameters provided in the\nsecond argument, as the formatter cannot do anything useful of these parameters\nwith the returned string. The extra data also contains a field named\n`single_line`, indicating if the printed log message may contain line breaks or\nnot. This variant is used when the formatting of the report depends on the size\nor single line parameters.\n\nExample, report, and metadata with report callback:\n\n```erlang\nlogger:debug(#{got => connection_request, id => Id, state => State},\n #{report_cb => fun(R) -> {\"~p\",[R]} end})\n```\n\nThe log message can also be provided through a fun for lazy evaluation. The fun\nis only evaluated if the primary log level check passes, and is therefore\nrecommended if it is expensive to generate the message. The lazy fun must return\na string, a report, or a tuple with format string and arguments.","title":"Log Message - Logging","ref":"logger_chapter.html#log-message"},{"type":"extras","doc":"Metadata contains additional data associated with a log message. Logger inserts\nsome metadata fields by default, and the client can add custom metadata in three\ndifferent ways:\n\n- **Set primary metadata** - Primary metadata applies is the base metadata given\n to all log events. At startup it can be set using the kernel configuration\n parameter [logger_metadata](kernel_app.md#logger_metadata). At run-time it can\n be set and updated using `logger:set_primary_config/1` and\n `logger:update_primary_config/1` respectively.\n\n- **Set process metadata** - Process metadata is set and updated with\n `logger:set_process_metadata/1` and `logger:update_process_metadata/1`,\n respectively. This metadata applies to the process on which these calls are\n made, and Logger adds the metadata to all log events issued on that process.\n\n- **Add metadata to a specific log event** - Metadata associated with one\n specific log event is given as the last parameter to the log macro or Logger\n API function when the event is issued. For example:\n\n ```text\n ?LOG_ERROR(\"Connection closed\",#{context => server})\n ```\n\nSee the description of the `t:logger:metadata/0` type for information about\nwhich default keys Logger inserts, and how the different metadata maps are\nmerged.","title":"Metadata - Logging","ref":"logger_chapter.html#metadata"},{"type":"extras","doc":"Filters can be primary, or attached to a specific handler. Logger calls the\nprimary filters first, and if they all pass, it calls the handler filters for\neach handler. Logger calls the handler callback only if all filters attached to\nthe handler in question also pass.\n\nA filter is defined as:\n\n```text\n{FilterFun, Extra}\n```\n\nwhere `FilterFun` is a function of arity 2, and `Extra` is any term. When\napplying the filter, Logger calls the function with the log event as the first\nargument, and the value of `Extra` as the second argument. See\n`t:logger:filter/0` for type definitions.\n\nThe filter function can return `stop`, `ignore` or the (possibly modified) log\nevent.\n\nIf `stop` is returned, the log event is immediately discarded. If the filter is\nprimary, no handler filters or callbacks are called. If it is a handler filter,\nthe corresponding handler callback is not called, but the log event is forwarded\nto filters attached to the next handler, if any.\n\nIf the log event is returned, the next filter function is called with the\nreturned value as the first argument. That is, if a filter function modifies the\nlog event, the next filter function receives the modified event. The value\nreturned from the last filter function is the value that the handler callback\nreceives.\n\nIf the filter function returns `ignore`, it means that it did not recognize the\nlog event, and thus leaves to other filters to decide the event's destiny.\n\nThe configuration option `filter_default` specifies the behaviour if all filter\nfunctions return `ignore`, or if no filters exist. `filter_default` is by\ndefault set to `log`, meaning that if all existing filters ignore a log event,\nLogger forwards the event to the handler callback. If `filter_default` is set to\n`stop`, Logger discards such events.\n\nPrimary filters are added with `logger:add_primary_filter/2` and removed with\n`logger:remove_primary_filter/1`. They can also be added at system start via the\nKernel configuration parameter [`logger`](#logger_parameter).\n\nHandler filters are added with `logger:add_handler_filter/3` and removed with\n`logger:remove_handler_filter/2`. They can also be specified directly in the\nconfiguration when adding a handler with `logger:add_handler/3` or via the\nKernel configuration parameter [`logger`](#logger_parameter).\n\nTo see which filters are currently installed in the system, use\n`logger:get_config/0`, or `logger:get_primary_config/0` and\n`logger:get_handler_config/1`. Filters are listed in the order they are applied,\nthat is, the first filter in the list is applied first, and so on.\n\nFor convenience, the following built-in filters exist:\n\n- **`logger_filters:domain/2`** - Provides a way of filtering log events based\n on a `domain` field in `Metadata`.\n\n- **`logger_filters:level/2`** - Provides a way of filtering log events based on\n the log level.\n\n- **`logger_filters:progress/2`** - Stops or allows progress reports from\n `supervisor` and `application_controller`.\n\n- **`logger_filters:remote_gl/2`** - Stops or allows log events originating from\n a process that has its group leader on a remote node.","title":"Filters - Logging","ref":"logger_chapter.html#filters"},{"type":"extras","doc":"A handler is defined as a module exporting at least the following callback\nfunction:\n\n```text\nlog(LogEvent, Config) -> term()\n```\n\nThis function is called when a log event has passed through all primary filters,\nand all handler filters attached to the handler in question. The function call\nis executed on the client process, and it is up to the handler implementation if\nother processes are involved or not.\n\nLogger allows adding multiple instances of a handler callback. That is, if a\ncallback module implementation allows it, you can add multiple handler instances\nusing the same callback module. The different instances are identified by unique\nhandler identities.\n\nIn addition to the mandatory callback function `log/2`, a handler module can\nexport the optional callback functions `adding_handler/1`, `changing_config/3`,\n`filter_config/1`, and `removing_handler/1`. See `m:logger_handler` for more\ninformation about these function.\n\nThe following built-in handlers exist:\n\n- **`logger_std_h`** - This is the default handler used by OTP. Multiple\n instances can be started, and each instance will write log events to a given\n destination, terminal or file.\n\n- **`logger_disk_log_h`** - This handler behaves much like `logger_std_h`,\n except it uses `m:disk_log` as its destination.\n\n- **`error_logger`{: #ErrorLoggerManager }** - This handler is provided for\n backwards compatibility only. It is not started by default, but will be\n automatically started the first time an `error_logger` event handler is added\n with\n [`error_logger:add_report_handler/1,2`](`error_logger:add_report_handler/1`).\n\n The old `error_logger` event handlers in STDLIB and SASL still exist, but they\n are not added by Erlang/OTP 21.0 or later.","title":"Handlers - Logging","ref":"logger_chapter.html#handlers"},{"type":"extras","doc":"A formatter can be used by the handler implementation to do the final formatting\nof a log event, before printing to the handler's destination. The handler\ncallback receives the formatter information as part of the handler\nconfiguration, which is passed as the second argument to\n[`HModule:log/2`](`c:logger_handler:log/2`).\n\nThe formatter information consist of a formatter module, `FModule` and its\nconfiguration, `FConfig`. `FModule` must export the following function, which\ncan be called by the handler:\n\n```text\nformat(LogEvent,FConfig)\n\t-> FormattedLogEntry\n```\n\nThe formatter information for a handler is set as a part of its configuration\nwhen the handler is added. It can also be changed during runtime with\n[`logger:set_handler_config(HandlerId,formatter,{Module,FConfig})` ](`logger:set_handler_config/3`),\nwhich overwrites the current formatter information, or with\n[`logger:update_formatter_config/2,3`](`logger:update_formatter_config/2`),\nwhich only modifies the formatter configuration.\n\nIf the formatter module exports the optional callback function\n[`check_config(FConfig)`](`c:logger_formatter:check_config/1`), Logger calls\nthis function when the formatter information is set or modified, to verify the\nvalidity of the formatter configuration.\n\nIf no formatter information is specified for a handler, Logger uses\n`logger_formatter` as default. See the `m:logger_formatter` manual page for more\ninformation about this module.","title":"Formatters - Logging","ref":"logger_chapter.html#formatters"},{"type":"extras","doc":"At system start, Logger is configured through Kernel configuration parameters.\nThe parameters that apply to Logger are described in section\n[Kernel Configuration Parameters](#kernel-configuration-parameters).\nExamples are found in section\n[Configuration Examples](#configuration-examples).\n\nDuring runtime, Logger configuration is changed via API functions. See section\n[Configuration API Functions](`m:logger#configuration-api-functions`) in the `m:logger`\nmanual page.","title":"Configuration - Logging","ref":"logger_chapter.html#configuration"},{"type":"extras","doc":"Logger API functions that apply to the primary Logger configuration are:\n\n- [`get_primary_config/0`](`logger:get_primary_config/0`)\n- [`set_primary_config/1,2`](`logger:set_primary_config/1`)\n- [`update_primary_config/1`](`logger:update_primary_config/1`)\n- [`add_primary_filter/2`](`logger:add_primary_filter/2`)\n- [`remove_primary_filter/1`](`logger:remove_primary_filter/1`)\n\nThe primary Logger configuration is a map with the following keys:\n\n- **`level = `{: #primary_level }`t:logger:level/0` ` | all | none`** - Specifies\n the primary log level, that is, log event that are equally or more severe than\n this level, are forwarded to the primary filters. Less severe log events are\n immediately discarded.\n\n See section [Log Level](#log-level) for a listing and\n description of possible log levels.\n\n The initial value of this option is set by the Kernel configuration parameter\n [`logger_level`](#logger_level). It is changed during runtime\n with\n [`logger:set_primary_config(level,Level)`](`logger:set_primary_config/2`).\n\n Defaults to `notice`.\n\n- **`filters = [{FilterId,Filter}]`** - Specifies the primary filters.\n\n - `FilterId = ` `t:logger:filter_id/0`\n - `Filter = ` `t:logger:filter/0`\n\n The initial value of this option is set by the Kernel configuration parameter\n [`logger`](#logger_parameter). During runtime, primary\n filters are added and removed with `logger:add_primary_filter/2` and\n `logger:remove_primary_filter/1`, respectively.\n\n See section [Filters](#filters) for more detailed\n information.\n\n Defaults to `[]`.\n\n- **`filter_default = log | stop`** - Specifies what happens to a log event if\n all filters return `ignore`, or if no filters exist.\n\n See section [Filters](#filters) for more information about\n how this option is used.\n\n Defaults to `log`.\n\n- **`metadata = `[`metadata()`](`t:logger:metadata/0`)** - The primary metadata\n to be used for all log calls.\n\n See section [Metadata](#metadata) for more information about\n how this option is used.\n\n Defaults to `#{}`.","title":"Primary Logger Configuration - Logging","ref":"logger_chapter.html#primary-logger-configuration"},{"type":"extras","doc":"Logger API functions that apply to handler configuration are:\n\n- [`get_handler_config/0,1`](`logger:get_handler_config/0`)\n- [`set_handler_config/2,3`](`logger:set_handler_config/2`)\n- [`update_handler_config/2,3`](`logger:update_handler_config/2`)\n- [`add_handler_filter/3`](`logger:add_handler_filter/3`)\n- [`remove_handler_filter/2`](`logger:remove_handler_filter/2`)\n- [`update_formatter_config/2,3`](`logger:update_formatter_config/2`)\n\nThe configuration for a handler is a map with the following keys:\n\n- **`id =` `t:logger_handler:id/0`** - Automatically inserted by Logger. The\n value is the same as the `HandlerId` specified when adding the handler, and it\n cannot be changed.\n\n- **`module = module()`** - Automatically inserted by Logger. The value is the\n same as the `Module` specified when adding the handler, and it cannot be\n changed.\n\n- **`level =` `t:logger:level/0` ` | all | none`** - Specifies the log level for\n the handler, that is, log events that are equally or more severe than this\n level, are forwarded to the handler filters for this handler.\n\n See section [Log Level](#log-level) for a listing and\n description of possible log levels.\n\n The log level is specified when adding the handler, or changed during runtime\n with, for instance,\n [`logger:set_handler_config(HandlerId,level,Level)`](`logger:set_handler_config/3`).\n\n Defaults to `all`.\n\n- **`filters = [{FilterId,Filter}]`** - Specifies the handler filters.\n\n - `FilterId = ` `t:logger:filter_id/0`\n - `Filter = ` `t:logger:filter/0`\n\n Handler filters are specified when adding the handler, or added or removed\n during runtime with `logger:add_handler_filter/3` and\n `logger:remove_handler_filter/2`, respectively.\n\n See [Filters](#filters) for more detailed information.\n\n Defaults to `[]`.\n\n- **`filter_default = log | stop`** - Specifies what happens to a log event if\n all filters return `ignore`, or if no filters exist.\n\n See section [Filters](#filters) for more information about\n how this option is used.\n\n Defaults to `log`.\n\n- **`formatter = {FormatterModule,FormatterConfig}`** - Specifies a formatter\n that the handler can use for converting the log event term to a printable\n string.\n\n - `FormatterModule = module()`\n - `FormatterConfig =` `t:logger:formatter_config/0`\n\n The formatter information is specified when adding the handler. The formatter\n configuration can be changed during runtime with\n [`logger:update_formatter_config/2,3`](`logger:update_formatter_config/2`), or\n the complete formatter information can be overwritten with, for instance,\n `logger:set_handler_config/3`.\n\n See section [Formatters](#formatters) for more detailed\n information.\n\n Defaults to `{logger_formatter,DefaultFormatterConfig}`. See the\n `m:logger_formatter` manual page for information about this formatter and its\n default configuration.\n\n- **`config = term()`** - Handler specific configuration, that is, configuration\n data related to a specific handler implementation.\n\n The configuration for the built-in handlers is described in the\n `m:logger_std_h` and [`logger_disk_log_h` ](`m:logger_disk_log_h`)manual\n pages.\n\nNotice that `level` and `filters` are obeyed by Logger itself before forwarding\nthe log events to each handler, while `formatter` and all handler specific\noptions are left to the handler implementation.","title":"Handler Configuration - Logging","ref":"logger_chapter.html#handler-configuration"},{"type":"extras","doc":"The following Kernel configuration parameters apply to Logger:\n\n- **`logger = [Config]`{: #logger_parameter }** - Specifies the configuration\n for [Logger](`m:logger`), except the primary log level, which is specified\n with [`logger_level`](#logger_level), and the compatibility\n with [SASL Error Logging](`e:sasl:error_logging.md`), which is specified with\n [`logger_sasl_compatible`](#logger_sasl_compatible).\n\n With this parameter, you can modify or disable the default handler, add custom\n handlers and primary logger filters, set log levels per module, and modify the\n [proxy](#logger-proxy) configuration.\n\n `Config` is any (zero or more) of the following:\n\n - **`{handler, default, undefined}`** - Disables the default handler. This\n allows another application to add its own default handler.\n\n Only one entry of this type is allowed.\n\n - **`{handler, HandlerId, Module, HandlerConfig}`** - If `HandlerId` is\n `default`, then this entry modifies the default handler, equivalent to\n calling\n\n ```text\n \t\tlogger:remove_handler(default)\n\n ```\n\n followed by\n\n ```erlang\n \t\tlogger:add_handler(default, Module, HandlerConfig)\n\n ```\n\n For all other values of `HandlerId`, this entry adds a new handler,\n equivalent to calling\n\n ```erlang\n \t\tlogger:add_handler(HandlerId, Module, HandlerConfig)\n\n ```\n\n Multiple entries of this type are allowed.\n\n - **`{filters, FilterDefault, [Filter]}`** - Adds the specified primary\n filters.\n\n - `FilterDefault = log | stop`\n - `Filter = {FilterId, {FilterFun, FilterConfig}}`\n\n Equivalent to calling\n\n ```erlang\n \t\tlogger:add_primary_filter(FilterId, {FilterFun, FilterConfig})\n\n ```\n\n for each `Filter`.\n\n `FilterDefault` specifies the behaviour if all primary filters return\n `ignore`, see section [Filters](#filters).\n\n Only one entry of this type is allowed.\n\n - **`{module_level, Level, [Module]}`** - Sets module log level for the given\n modules. Equivalent to calling\n\n ```erlang\n \t\tlogger:set_module_level(Module, Level)\n ```\n\n for each `Module`.\n\n Multiple entries of this type are allowed.\n\n - **`{proxy, ProxyConfig}`** - Sets the proxy configuration, equivalent to\n calling\n\n ```text\n \t\tlogger:set_proxy_config(ProxyConfig)\n\n ```\n\n Only one entry of this type is allowed.\n\n See section [Configuration Examples](#configuration-examples) for\n examples using the `logger` parameter for system configuration.\n\n- **`logger_metadata = map()`{: #logger_metadata }** - Specifies the primary\n metadata. See the [`kernel(6)`](kernel_app.md#logger_metadata) manual page for\n more information about this parameter.\n\n- **`logger_level = Level`{: #logger_level }** - Specifies the primary log\n level. See the [`kernel(6)`](kernel_app.md#logger_level) manual page for more\n information about this parameter.\n\n- **`logger_sasl_compatible = true | false`{: #logger_sasl_compatible }** -\n Specifies Logger's compatibility with\n [SASL Error Logging](`e:sasl:error_logging.md`). See the\n [`kernel(6)`](kernel_app.md#logger_sasl_compatible) manual page for more\n information about this parameter.","title":"Kernel Configuration Parameters - Logging","ref":"logger_chapter.html#kernel-configuration-parameters"},{"type":"extras","doc":"The value of the Kernel configuration parameter `logger` is a list of tuples. It\nis possible to write the term on the command line when starting an erlang node,\nbut as the term grows, a better approach is to use the system configuration\nfile. See the [`config(4)`](config.md) manual page for more information about\nthis file.\n\nEach of the following examples shows a simple system configuration file that\nconfigures Logger according to the description.\n\nModify the default handler to print to a file instead of\n[`standard_io`](`t:io:standard_io/0`):\n\n```erlang\n[{kernel,\n [{logger,\n [{handler, default, logger_std_h, % {handler, HandlerId, Module,\n #{config => #{file => \"log/erlang.log\"}}} % Config}\n ]}]}].\n```\n\nModify the default handler to print each log event as a single line:\n\n```erlang\n[{kernel,\n [{logger,\n [{handler, default, logger_std_h,\n #{formatter => {logger_formatter, #{single_line => true}}}}\n ]}]}].\n```\n\nModify the default handler to print the pid of the logging process for each log\nevent:\n\n```erlang\n[{kernel,\n [{logger,\n [{handler, default, logger_std_h,\n #{formatter => {logger_formatter,\n #{template => [time,\" \",pid,\" \",msg,\"\\n\"]}}}}\n ]}]}].\n```\n\nModify the default handler to only print errors and more severe log events to\n\"log/erlang.log\", and add another handler to print all log events to\n\"log/debug.log\".\n\n```erlang\n[{kernel,\n [{logger,\n [{handler, default, logger_std_h,\n #{level => error,\n config => #{file => \"log/erlang.log\"}}},\n {handler, info, logger_std_h,\n #{level => debug,\n config => #{file => \"log/debug.log\"}}}\n ]}]}].\n```","title":"Configuration Examples - Logging","ref":"logger_chapter.html#configuration-examples"},{"type":"extras","doc":"Logger provides backwards compatibility with `error_logger` in the following\nways:\n\n- **API for Logging** - The `error_logger` API still exists, but should only be\n used by legacy code. It will be removed in a later release.\n\n Calls to [`error_logger:error_report/1,2`](`error_logger:error_report/1`),\n [`error_logger:error_msg/1,2`](`error_logger:error_msg/1`), and corresponding\n functions for warning and info messages, are all forwarded to Logger as calls\n to [`logger:log(Level,Report,Metadata)`](`logger:log/3`).\n\n `Level = error | warning | info` and is taken from the function name. `Report`\n contains the actual log message, and `Metadata` contains additional\n information which can be used for creating backwards compatible events for\n legacy `error_logger` event handlers, see section\n [Legacy Event Handlers](#legacy_event_handlers).\n\n- **Output Format** - To get log events on the same format as produced by\n `error_logger_tty_h` and `error_logger_file_h`, use the default formatter,\n `logger_formatter`, with configuration parameter `legacy_header` set to\n `true`. This is the default configuration of the `default` handler started by\n Kernel.\n\n- **Default Format of Log Events from OTP** - By default, all log events\n originating from within OTP, except the former so called \"SASL reports\", look\n the same as before.\n\n- **[](){: #sasl_reports } SASL Reports** - By SASL reports we mean supervisor\n reports, crash reports and progress reports.\n\n Prior to Erlang/OTP 21.0, these reports were only logged when the SASL\n application was running, and they were printed through SASL's own event\n handlers `sasl_report_tty_h` and `sasl_report_file_h`.\n\n The destination of these log events was configured by\n [SASL configuration parameters](`e:sasl:sasl_app.md#deprecated_error_logger_config`).\n\n Due to the specific event handlers, the output format slightly differed from\n other log events.\n\n As of Erlang/OTP 21.0, the concept of SASL reports is removed, meaning that\n the default behaviour is as follows:\n\n - Supervisor reports, crash reports, and progress reports are no longer\n connected to the SASL application.\n - Supervisor reports and crash reports are issued as `error` level log events,\n and are logged through the default handler started by Kernel.\n - Progress reports are issued as `info` level log events, and since the\n default primary log level is `notice`, these are not logged by default. To\n enable printing of progress reports, set the\n [primary log level](#primary_level) to `info`.\n - The output format is the same for all log events.\n\n If the old behaviour is preferred, the Kernel configuration parameter\n [`logger_sasl_compatible`](kernel_app.md#logger_sasl_compatible) can be set to\n `true`. The\n [SASL configuration parameters](`e:sasl:sasl_app.md#deprecated_error_logger_config`)\n can then be used as before, and the SASL reports will only be printed if the\n SASL application is running, through a second log handler named `sasl`.\n\n All SASL reports have a metadata field `domain` which is set to `[otp,sasl]`.\n This field can be used by filters to stop or allow the log events.\n\n See section [SASL User's Guide](`e:sasl:error_logging.md`) for more\n information about the old SASL error logging functionality.\n\n- **[](){: #legacy_event_handlers } Legacy Event Handlers** - To use event\n handlers written for `error_logger`, just add your event handler\n with\n\n ```text\n error_logger:add_report_handler/1,2.\n ```\n\n This automatically starts the error logger event manager, and adds\n `error_logger` as a handler to Logger, with the following configuration:\n\n ```erlang\n #{level => info,\n filter_default => log,\n filters => []}.\n ```\n\n > #### Note {: .info }\n >\n > This handler ignores events that do not originate from the `error_logger`\n > API, or from within OTP. This means that if your code uses the Logger API\n > for logging, then your log events will be discarded by this handler.\n >\n > The handler is not overload protected.","title":"Backwards Compatibility with error_logger - Logging","ref":"logger_chapter.html#backwards-compatibility-with-error_logger"},{"type":"extras","doc":"Logger does, to a certain extent, check its input data before forwarding a log\nevent to filters and handlers. It does, however, not evaluate report callbacks,\nor check the validity of format strings and arguments. This means that all\nfilters and handlers must be careful when formatting the data of a log event,\nmaking sure that it does not crash due to bad input data or faulty callbacks.\n\nIf a filter or handler still crashes, Logger will remove the filter or handler\nin question from the configuration, and print a short error message to the\nterminal. A debug event containing the crash reason and other details is also\nissued.\n\nSee section [Log Message](#log-message) for more information\nabout report callbacks and valid forms of log messages.","title":"Error Handling - Logging","ref":"logger_chapter.html#error-handling"},{"type":"extras","doc":"When starting an Erlang node, the default behaviour is that all log events on\nlevel `notice` or more severe, are logged to the terminal via the default\nhandler. To also log info events, you can either change the primary log level to\n`info`:\n\n```text\n1> logger:set_primary_config(level, info).\nok\n```\n\nor set the level for one or a few modules only:\n\n```erlang\n2> logger:set_module_level(mymodule, info).\nok\n```\n\nThis allows info events to pass through to the default handler, and be printed\nto the terminal as well. If there are many info events, it can be useful to\nprint these to a file instead.\n\nFirst, set the log level of the default handler to `notice`, preventing it from\nprinting info events to the terminal:\n\n```erlang\n3> logger:set_handler_config(default, level, notice).\nok\n```\n\nThen, add a new handler which prints to file. You can use the handler module\n`m:logger_std_h`, and configure it to log to file:\n\n```erlang\n4> Config = #{config => #{file => \"./info.log\"}, level => info}.\n#{config => #{file => \"./info.log\"},level => info}\n5> logger:add_handler(myhandler, logger_std_h, Config).\nok\n```\n\nSince `filter_default` defaults to `log`, this handler now receives all log\nevents. If you want info events only in the file, you must add a filter to stop\nall non-info events. The built-in filter `logger_filters:level/2` can do this:\n\n```erlang\n6> logger:add_handler_filter(myhandler, stop_non_info,\n {fun logger_filters:level/2, {stop, neq, info}}).\nok\n```\n\nSee section [Filters](#filters) for more information about the\nfilters and the `filter_default` configuration parameter.","title":"Example: Add a handler to log info events to file - Logging","ref":"logger_chapter.html#example-add-a-handler-to-log-info-events-to-file"},{"type":"extras","doc":"`m:logger_handler` describes the callback functions that can be implemented for\na Logger handler.\n\nA handler callback module must export:\n\n- `log(Log, Config)`\n\nIt can optionally also export some, or all, of the following:\n\n- `adding_handler(Config)`\n- `removing_handler(Config)`\n- `changing_config(SetOrUpdate, OldConfig, NewConfig)`\n- `filter_config(Config)`\n\nWhen a handler is added, by for example a call to\n[`logger:add_handler(Id, HModule, Config)`](`logger:add_handler/3`), Logger\nfirst calls `HModule:adding_handler(Config)`. If this function returns\n`{ok,Config1}`, Logger writes `Config1` to the configuration database, and the\n`logger:add_handler/3` call returns. After this, the handler is installed and\nmust be ready to receive log events as calls to `HModule:log/2`.\n\nA handler can be removed by calling\n[`logger:remove_handler(Id)`](`logger:remove_handler/1`). Logger calls\n`HModule:removing_handler(Config)`, and removes the handler's configuration from\nthe configuration database.\n\nWhen [`logger:set_handler_config/2,3`](`logger:set_handler_config/2`) or\n[`logger:update_handler_config/2,3`](`logger:update_handler_config/2`) is\ncalled, Logger calls\n`HModule:changing_config(SetOrUpdate, OldConfig, NewConfig)`. If this function\nreturns `{ok,NewConfig1}`, Logger writes `NewConfig1` to the configuration\ndatabase.\n\nWhen `logger:get_config/0` or\n[`logger:get_handler_config/0,1`](`logger:get_handler_config/0`) is called,\nLogger calls `HModule:filter_config(Config)`. This function must return the\nhandler configuration where internal data is removed.\n\nA simple handler that prints to the terminal can be implemented as follows:\n\n```erlang\n-module(myhandler1).\n-export([log/2]).\n\nlog(LogEvent, #{formatter := {FModule, FConfig}}) ->\n io:put_chars(FModule:format(LogEvent, FConfig)).\n```\n\nNotice that the above handler does not have any overload protection, and all log\nevents are printed directly from the client process.\n\nFor information and examples of overload protection, please refer to section\n[Protecting the Handler from Overload](#overload_protection),\nand the implementation of `m:logger_std_h` and\n[`logger_disk_log_h` ](`m:logger_disk_log_h`).\n\nThe following is a simpler example of a handler which logs to a file through one\nsingle process:\n\n```erlang\n-module(myhandler2).\n-export([adding_handler/1, removing_handler/1, log/2]).\n-export([init/1, handle_call/3, handle_cast/2, terminate/2]).\n\nadding_handler(Config) ->\n MyConfig = maps:get(config,Config,#{file => \"myhandler2.log\"}),\n {ok, Pid} = gen_server:start(?MODULE, MyConfig, []),\n {ok, Config#{config => MyConfig#{pid => Pid}}}.\n\nremoving_handler(#{config := #{pid := Pid}}) ->\n gen_server:stop(Pid).\n\nlog(LogEvent,#{config := #{pid := Pid}} = Config) ->\n gen_server:cast(Pid, {log, LogEvent, Config}).\n\ninit(#{file := File}) ->\n {ok, Fd} = file:open(File, [append, {encoding, utf8}]),\n {ok, #{file => File, fd => Fd}}.\n\nhandle_call(_, _, State) ->\n {reply, {error, bad_request}, State}.\n\nhandle_cast({log, LogEvent, Config}, #{fd := Fd} = State) ->\n do_log(Fd, LogEvent, Config),\n {noreply, State}.\n\nterminate(_Reason, #{fd := Fd}) ->\n _ = file:close(Fd),\n ok.\n\ndo_log(Fd, LogEvent, #{formatter := {FModule, FConfig}}) ->\n String = FModule:format(LogEvent, FConfig),\n io:put_chars(Fd, String).\n```\n\n[](){: #overload_protection }","title":"Example: Implement a handler - Logging","ref":"logger_chapter.html#example-implement-a-handler"},{"type":"extras","doc":"The default handlers, `m:logger_std_h` and `m:logger_disk_log_h`, feature\nmultiple overload protection mechanisms, which make it possible for the\nhandlers to survive, and stay responsive, during periods of high load\n(when huge numbers of incoming log requests must be handled).\n\nThe mechanisms are as follows:\n* [**message queue length**](#message-queue-length): the handler process tracks\nits message queue length and takes actions depending on its size, from turning\non a sync mode to dropping messages.\n* [**limit the number of logs emitted**](#controlling-bursts-of-log-requests):\nthe handlers will handle a maximum number of log events per time unit,\ndefaulting to 500 per second.\n* [**terminate an overloaded handler**](#terminating-an-overloaded-handler):\na handler can be terminated and restarted automatically if it exceeds message\nqueue length or memory thresholds - this is disabled by default.\n\nThese mechanisms are described in more detail in the following sections.","title":"Protecting the Handler from Overload - Logging","ref":"logger_chapter.html#protecting-the-handler-from-overload"},{"type":"extras","doc":"The handler process keeps track of the length of its message queue and takes\nsome form of action when the current length exceeds a configurable threshold.\nThe purpose is to keep the handler in, or to as quickly as possible get the\nhandler into, a state where it can keep up with the pace of incoming log events.\nThe memory use of the handler must never grow larger and larger, since that will\neventually cause the handler to crash. These three thresholds, with associated\nactions, exist:\n\n- **`sync_mode_qlen`** - As long as the length of the message queue is lower\n than this value, all log events are handled asynchronously. This means that\n the client process sending the log event, by calling a log function in the\n [Logger API](#logger-api), does not wait for a response from\n the handler but continues executing immediately after the event is sent. It is\n not affected by the time it takes the handler to print the event to the log\n device. If the message queue grows larger than this value, the handler starts\n handling log events synchronously instead, meaning that the client process\n sending the event must wait for a response. When the handler reduces the\n message queue to a level below the `sync_mode_qlen` threshold, asynchronous\n operation is resumed. The switch from asynchronous to synchronous mode can\n slow down the logging tempo of one, or a few, busy senders, but cannot protect\n the handler sufficiently in a situation of many busy concurrent senders.\n\n Defaults to `10` messages.\n\n- **`drop_mode_qlen`** - When the message queue grows larger than this\n threshold, the handler switches to a mode in which it drops all new events\n that senders want to log. Dropping an event in this mode means that the call\n to the log function never results in a message being sent to the handler, but\n the function returns without taking any action. The handler keeps logging the\n events that are already in its message queue, and when the length of the\n message queue is reduced to a level below the threshold, synchronous or\n asynchronous mode is resumed. Notice that when the handler activates or\n deactivates drop mode, information about it is printed in the log.\n The emitted log message is on the `:notice` level and looks like this:\n `Handler :default switched from :sync to :drop mode`\n\n Defaults to `200` messages.\n\n- **`flush_qlen`** - If the length of the message queue grows larger than this\n threshold, a flush (delete) operation takes place. To flush events, the\n handler discards the messages in the message queue by receiving them in a loop\n without logging. Client processes waiting for a response from a synchronous\n log request receive a reply from the handler indicating that the request is\n dropped. The handler process increases its priority during the flush loop to\n make sure that no new events are received during the operation. Notice that\n after the flush operation is performed, the handler prints information in the\n log about how many events have been deleted.\n The emitted log message is on the `:notice` level and looks like this:\n `Handler :default flushed 1070 log events`\n\n Defaults to `1000` messages.\n\nFor the overload protection algorithm to work properly, it is required that:\n\n`sync_mode_qlen = 1`\n\nTo disable certain modes, do the following:\n\n- If `sync_mode_qlen` is set to `0`, all log events are handled synchronously.\n That is, asynchronous logging is disabled.\n- If `sync_mode_qlen` is set to the same value as `drop_mode_qlen`, synchronous\n mode is disabled. That is, the handler always runs in asynchronous mode,\n unless dropping or flushing is invoked.\n- If `drop_mode_qlen` is set to the same value as `flush_qlen`, drop mode is\n disabled and can never occur.\n\nDuring high load scenarios, the length of the handler message queue rarely grows\nin a linear and predictable way. Instead, whenever the handler process is\nscheduled in, it can have an almost arbitrary number of messages waiting in the\nmessage queue. It is for this reason that the overload protection mechanism is\nfocused on acting quickly, and quite drastically, such as immediately dropping\nor flushing messages, when a large queue length is detected.\n\nThe values of the previously listed thresholds can be specified by the user.\nThis way, a handler can be configured to, for example, not drop or flush\nmessages unless the message queue length of the handler process grows extremely\nlarge. Notice that large amounts of memory can be required for the node under\nsuch circumstances. Another example of user configuration is when, for\nperformance reasons, the client processes must never be blocked by synchronous\nlog requests. It is possible, perhaps, that dropping or flushing events is still\nacceptable, since it does not affect the performance of the client processes\nsending the log events.\n\nA configuration example:\n\n```erlang\nlogger:add_handler(my_standard_h, logger_std_h,\n #{config => #{file => \"./system_info.log\",\n sync_mode_qlen => 100,\n drop_mode_qlen => 1000,\n flush_qlen => 2000}}).\n```","title":"Message Queue Length - Logging","ref":"logger_chapter.html#message-queue-length"},{"type":"extras","doc":"Large bursts of log events - many events received by the handler under a short\nperiod of time - can potentially cause problems, such as:\n\n- Log files grow very large, very quickly.\n- Circular logs wrap too quickly so that important data is overwritten.\n- Write buffers grow large, which slows down file sync operations.\n\nNote that these examples apply to file-based logging. If you're logging to\nthe console the protections discussed below should be safe to disable or\ntweak, as long as your system can handle the load of them.\n\nFor this reason, both built-in handlers offer the possibility to specify the\nmaximum number of events to be handled within a certain time frame. With this\nburst control feature enabled, the handler can avoid choking the log with\nmassive amounts of printouts. The configuration parameters are:\n\n- **`burst_limit_enable`** - Value `true` enables burst control and `false`\n disables it.\n\n Defaults to `true`.\n\n- **`burst_limit_max_count`** - This is the maximum number of events to handle\n within a `burst_limit_window_time` time frame. After the limit is reached,\n successive events are dropped until the end of the time frame.\n\n Defaults to `500` events.\n\n- **`burst_limit_window_time`** - See the previous description of\n `burst_limit_max_count`.\n\n Defaults to `1000` milliseconds.\n\nA configuration example:\n\n```erlang\nlogger:add_handler(my_disk_log_h, logger_disk_log_h,\n #{config => #{file => \"./my_disk_log\",\n burst_limit_enable => true,\n burst_limit_max_count => 20,\n burst_limit_window_time => 500}}).\n```","title":"Controlling Bursts of Log Requests - Logging","ref":"logger_chapter.html#controlling-bursts-of-log-requests"},{"type":"extras","doc":"It is possible that a handler, even if it can successfully manage peaks of high\nload without crashing, can build up a large message queue, or use a large amount\nof memory. The overload protection mechanism includes an automatic termination\nand restart feature for the purpose of guaranteeing that a handler does not grow\nout of bounds. The feature is configured with the following parameters:\n\n- **`overload_kill_enable`** - Value `true` enables the feature and `false`\n disables it.\n\n Defaults to `false`.\n\n- **`overload_kill_qlen`** - This is the maximum allowed queue length. If the\n message queue grows larger than this, the handler process is terminated.\n\n Defaults to `20000` messages.\n\n- **`overload_kill_mem_size`** - This is the maximum memory size that the\n handler process is allowed to use. If the handler grows larger than this, the\n process is terminated.\n\n Defaults to `3000000` bytes.\n\n- **`overload_kill_restart_after`** - If the handler is terminated, it restarts\n automatically after a delay specified in milliseconds. The value `infinity`\n prevents restarts.\n\n Defaults to `5000` milliseconds.\n\nIf the handler process is terminated because of overload, it prints information\nabout it in the log. It also prints information about when a restart has taken\nplace, and the handler is back in action.\n\n> #### Note {: .info }\n>\n> The sizes of the log events affect the memory needs of the handler. For\n> information about how to limit the size of log events, see the\n> `m:logger_formatter` manual page.","title":"Terminating an Overloaded Handler - Logging","ref":"logger_chapter.html#terminating-an-overloaded-handler"},{"type":"extras","doc":"The Logger proxy is an Erlang process which is part of the Kernel application's\nsupervision tree. During startup, the proxy process registers itself as the\n`system_logger`, meaning that log events produced by the emulator are sent to\nthis process.\n\nWhen a log event is issued on a process which has its group leader on a remote\nnode, Logger automatically forwards the log event to the group leader's node. To\nachieve this, it first sends the log event as an Erlang message from the\noriginal client process to the proxy on the local node, and the proxy in turn\nforwards the event to the proxy on the remote node.\n\nWhen receiving a log event, either from the emulator or from a remote node, the\nproxy calls the Logger API to log the event.\n\nThe proxy process is overload protected in the same way as described in section\n[Protecting the Handler from Overload](#overload_protection),\nbut with the following default values:\n\n```erlang\n #{sync_mode_qlen => 500,\n drop_mode_qlen => 1000,\n flush_qlen => 5000,\n burst_limit_enable => false,\n overload_kill_enable => false}\n```\n\nFor log events from the emulator, synchronous message passing mode is not\napplicable, since all messages are passed asynchronously by the emulator. Drop\nmode is achieved by setting the `system_logger` to `undefined`, forcing the\nemulator to drop events until it is set back to the proxy pid again.\n\nThe proxy uses `erlang:send_nosuspend/2` when sending log events to a remote\nnode. If the message could not be sent without suspending the sender, it is\ndropped. This is to avoid blocking the proxy process.","title":"Logger Proxy - Logging","ref":"logger_chapter.html#logger-proxy"},{"type":"extras","doc":"`m:disk_log`, `m:erlang`, `m:error_logger`, `m:logger`, `m:logger_disk_log_h`,\n`m:logger_filters`, `m:logger_formatter`, `m:logger_std_h`,\n[`sasl(6)`](`e:sasl:sasl_app.md`)","title":"See Also - Logging","ref":"logger_chapter.html#see-also"},{"type":"extras","doc":"\n# Logging Cookbook\n\nUsing and especially configuring Logger can be difficult at times as there are\nmany different options that can be changed and often more than one way to\nachieve the same result. This User's Guide tries to help by giving many\ndifferent examples of how you can use logger.\n\nFor more examples of practical use-cases of using Logger, Fred Hebert's blog\npost\n[Erlang/OTP 21's new logger](https://ferd.ca/erlang-otp-21-s-new-logger.html) is\na great starting point.\n\n> #### Note {: .info }\n>\n> If you find that some common Logger usage is missing from this guide, please\n> open a pull request on github with the suggested addition","title":"Logging Cookbook","ref":"logger_cookbook.html"},{"type":"extras","doc":"","title":"Get Logger information - Logging Cookbook","ref":"logger_cookbook.html#get-logger-information"},{"type":"extras","doc":"```erlang\n1> logger:i(primary).\nPrimary configuration:\n Level: notice\n Filter Default: log\n Filters:\n (none)\n```\n\nIt is also possible to fetch the configuration using\n[`logger:get_primary_config()`](`logger:get_primary_config/0`).\n\n#### See also\n\n- [logger:i()](`logger:i/0`)\n- [Configuration](logger_chapter.md#configuration) in the Logging User's Guide","title":"Print the primary Logger configurations. - Logging Cookbook","ref":"logger_cookbook.html#print-the-primary-logger-configurations"},{"type":"extras","doc":"```erlang\n2> logger:i(handlers).\nHandler configuration:\n Id: default\n Module: logger_std_h\n Level: all\n Formatter:\n Module: logger_formatter\n Config:\n legacy_header: true\n single_line: false\n Filter Default: stop\n Filters:\n Id: remote_gl\n Fun: fun logger_filters:remote_gl/2\n Arg: stop\n Id: domain\n Fun: fun logger_filters:domain/2\n Arg: {log,super,[otp,sasl]}\n Id: no_domain\n Fun: fun logger_filters:domain/2\n Arg: {log,undefined,[]}\n Handler Config:\n burst_limit_enable: true\n burst_limit_max_count: 500\n burst_limit_window_time: 1000\n drop_mode_qlen: 200\n filesync_repeat_interval: no_repeat\n flush_qlen: 1000\n overload_kill_enable: false\n overload_kill_mem_size: 3000000\n overload_kill_qlen: 20000\n overload_kill_restart_after: 5000\n sync_mode_qlen: 10\n type: standard_io\n```\n\nYou can also print the configuration of a specific handler using\n[`logger:i(HandlerName)`](`logger:i/1`), or fetch the configuration using\n[`logger:get_handler_config()`](`logger:get_handler_config/0`), or\n[`logger:get_handler_config(HandlerName)`](`logger:get_handler_config/1`) for a\nspecific handler.\n\n#### See also\n\n- [`logger:i()`](`logger:i/0`)\n- [Configuration](logger_chapter.md#configuration) in the Logging User's Guide","title":"Print the configuration of all handlers. - Logging Cookbook","ref":"logger_cookbook.html#print-the-configuration-of-all-handlers"},{"type":"extras","doc":"","title":"Configure the Logger - Logging Cookbook","ref":"logger_cookbook.html#configure-the-logger"},{"type":"extras","doc":"In OTP-21 the default primary log level is `notice`. The means that many log\nmessages are by default not printed. This includes the progress reports of\nsupervisors. In order to get progress reports you need to raise the primary log\nlevel to `info`\n\n```erlang\n$ erl -kernel logger_level info\n=PROGRESS REPORT==== 4-Nov-2019::16:33:11.742069 ===\n application: kernel\n started_at: nonode@nohost\n=PROGRESS REPORT==== 4-Nov-2019::16:33:11.746546 ===\n application: stdlib\n started_at: nonode@nohost\nEshell V10.5.3 (abort with ^G)\n1>\n```","title":"Where did my progress reports go? - Logging Cookbook","ref":"logger_cookbook.html#where-did-my-progress-reports-go"},{"type":"extras","doc":"In order to fit better into your existing logging infrastructure Logger can\nformat its logging messages any way you want to. Either you can use the built-in\nformatter, or you can build your own.","title":"Configure Logger formatter - Logging Cookbook","ref":"logger_cookbook.html#configure-logger-formatter"},{"type":"extras","doc":"Since single line logging is the default of the built-in formatter you only have\nto provide the empty map as the configuration. The example below uses the\n`sys.config` to change the formatter configuration.\n\n```erlang\n$ cat sys.config\n[{kernel,\n [{logger,\n [{handler, default, logger_std_h,\n #{ formatter => {logger_formatter, #{ }}}}]}]}].\n$ erl -config sys\nEshell V10.5.1 (abort with ^G)\n1> logger:error(\"Oh noes, an error\").\n1962-10-03T11:07:47.466763-04:00 error: Oh noes, an error\n```\n\nHowever, if you just want to change it for the current session you can also do\nthat.\n\n```erlang\n1> logger:set_handler_config(default, formatter, {logger_formatter, #{}}).\nok\n2> logger:error(\"Oh noes, another error\").\n1962-10-04T15:34:02.648713-04:00 error: Oh noes, another error\n```\n\n#### See also\n\n- [logger_formatter's Configuration](`t:logger_formatter:config/0`)\n- [Formatters](logger_chapter.md#formatters) in the Logging User's Guide\n- `logger:set_handler_config/3`","title":"Single line configuration - Logging Cookbook","ref":"logger_cookbook.html#single-line-configuration"},{"type":"extras","doc":"You can change what is printed to the log by using the formatter template:\n\n```erlang\n$ cat sys.config\n[{kernel,\n [{logger,\n [{handler, default, logger_std_h,\n #{ formatter => {logger_formatter,\n #{ template => [time,\" \", file,\":\",line,\" \",level,\": \",msg,\"\\n\"] }}}}]}]}].\n$ erl -config sys\nEshell V10.5.1 (abort with ^G)\n1> logger:error(\"Oh noes, more errors\",#{ file => \"shell.erl\", line => 1 }).\n1962-10-05T07:37:44.104241+02:00 shell.erl:1 error: Oh noes, more errors\n```\n\nNote that file and line have to be added in the metadata by the caller of\n`logger:log/3` as otherwise Logger will not know from where it was called. The\nfile and line number are automatically added if you use the `?LOG_ERROR` macros\nin `kernel/include/logger.hrl`.\n\n#### See also\n\n- [logger_formatter's Configuration](`t:logger_formatter:config/0`)\n- [logger_formatter's Template](`t:logger_formatter:template/0`)\n- [Logger Macros](`m:logger#module-macros`)\n- [Metadata](logger_chapter.md#metadata) in the Logging User's Guide","title":"Add file and line number to log entries - Logging Cookbook","ref":"logger_cookbook.html#add-file-and-line-number-to-log-entries"},{"type":"extras","doc":"","title":"Configuring handlers - Logging Cookbook","ref":"logger_cookbook.html#configuring-handlers"},{"type":"extras","doc":"Instead of printing the logs to stdout we print them to a rotating file log.\n\n```erlang\n$ cat sys.config\n[{kernel,\n [{logger,\n [{handler, default, logger_std_h,\n #{ config => #{ file => \"log/erlang.log\",\n max_no_bytes => 4096,\n max_no_files => 5},\n formatter => {logger_formatter, #{}}}}]}]}].\n$ erl -config sys\nEshell V10.5.1 (abort with ^G)\n1> logger:error(\"Oh noes, even more errors\").\nok\n2> erlang:halt().\n$ cat log/erlang.log\n2019-10-07T11:47:16.837958+02:00 error: Oh noes, even more errors\n```\n\n#### See also\n\n- `m:logger_std_h`\n- [Handlers](logger_chapter.md#handlers) in the Logging User's Guide","title":"Print logs to a file - Logging Cookbook","ref":"logger_cookbook.html#print-logs-to-a-file"},{"type":"extras","doc":"Add a handler that prints `debug` log events to a file, while the default\nhandler prints only up to `notice` level events to standard out.\n\n```erlang\n$ cat sys.config\n[{kernel,\n [{logger_level, all},\n {logger,\n [{handler, default, logger_std_h,\n #{ level => notice }},\n {handler, debug, logger_std_h,\n #{ filters => [{debug,{fun logger_filters:level/2, {stop, neq, debug}}}],\n config => #{ file => \"log/debug.log\" } }}\n ]}]}].\n$ erl -config sys\nEshell V10.5.1 (abort with ^G)\n1> logger:error(\"Oh noes, even more errors\").\n=ERROR REPORT==== 9-Oct-2019::14:40:54.784162 ===\nOh noes, even more errors\nok\n2> logger:debug(\"A debug event\").\nok\n3> erlang:halt().\n$ cat log/debug.log\n2019-10-09T14:41:03.680541+02:00 debug: A debug event\n```\n\nIn the configuration above we first raise the primary log level to max in order\nfor the debug log events to get to the handlers. Then we configure the default\nhandler to only log notice and below events, the default log level for a handler\nis `all`. Then the debug handler is configured with a filter to stop any log\nmessage that is not a debug level message.\n\nIt is also possible to do the same changes in an already running system using\nthe `logger` module. Then you do like this:\n\n```erlang\n$ erl\n1> logger:set_handler_config(default, level, notice).\nok\n2> logger:add_handler(debug, logger_std_h, #{\n filters => [{debug,{fun logger_filters:level/2, {stop, neq, debug}}}],\n config => #{ file => \"log/debug.log\" } }).\nok\n3> logger:set_primary_config(level, all).\nok\n```\n\nIt is important that you do not raise the primary log level before adjusting the\ndefault handler's level as otherwise your standard out may be flooded by debug\nlog messages.\n\n#### See also\n\n- `m:logger_std_h`\n- [Filters](logger_chapter.md#filters) in the Logging User's Guide","title":"Debug only handler - Logging Cookbook","ref":"logger_cookbook.html#debug-only-handler"},{"type":"extras","doc":"","title":"Logging - Logging Cookbook","ref":"logger_cookbook.html#logging"},{"type":"extras","doc":"The simplest way to log something is by using the Logger macros and give a\nreport to the macro. For example if you want to log an error:\n\n```erlang\n?LOG_ERROR(#{ what => http_error, status => 418, src => ClientIP, dst => ServerIP }).\n```\n\nThis will print the following in the default log:\n\n```text\n=ERROR REPORT==== 10-Oct-2019::12:13:10.089073 ===\n dst: {8,8,4,4}\n src: {8,8,8,8}\n status: 418\n what: http_error\n```\n\nor the below if you use a single line formatter:\n\n```text\n2019-10-10T12:14:11.921843+02:00 error: dst: {8,8,4,4}, src: {8,8,8,8}, status: 418, what: http_error\n```\n\n#### See also\n\n- [Log Message](logger_chapter.md#log-message) in the Logging User's Guide","title":"What to log and how - Logging Cookbook","ref":"logger_cookbook.html#what-to-log-and-how"},{"type":"extras","doc":"If you want to do structured logging, but still want to have some control of how\nthe final log message is formatted you can give a `report_cb` as part of the\nmetadata with your log event.\n\n```erlang\nReportCB = fun(#{ what := What, status := Status, src := Src, dst := Dst }) ->\n {ok, #hostent{ h_name = SrcName }} = inet:gethostbyaddr(Src),\n {ok, #hostent{ h_name = DstName }} = inet:gethostbyaddr(Dst),\n {\"What: ~p~nStatus: ~p~nSrc: ~s (~s)~nDst: ~s (~s)~n\",\n [What, Status, inet:ntoa(Src), SrcName, inet:ntoa(Dst), DstName]}\n end,\n?LOG_ERROR(#{ what => http_error, status => 418, src => ClientIP, dst => ServerIP },\n #{ report_cb => ReportCB }).\n```\n\nThis will print the following:\n\n```text\n=ERROR REPORT==== 10-Oct-2019::13:29:02.230863 ===\nWhat: http_error\nStatus: 418\nSrc: 8.8.8.8 (dns.google)\nDst: 192.121.151.106 (erlang.org)\n```\n\nNote that the order that things are printed have changed, and also I added a\nreverse-dns lookup of the IP address. This will not print as nicely when using a\nsingle line formatter, however you can also use a report_cb fun with 2 arguments\nwhere the second argument is the formatting options.\n\n#### See also\n\n- [Log Message](logger_chapter.md#log-message) in the Logging User's Guide\n- [Logger Report Callbacks](`t:logger:report_cb/0`)","title":"Report call-backs and printing of events - Logging Cookbook","ref":"logger_cookbook.html#report-call-backs-and-printing-of-events"},{"type":"extras","doc":"Filters are used to remove or change log events before they reach the handlers.","title":"Filters - Logging Cookbook","ref":"logger_cookbook.html#filters"},{"type":"extras","doc":"If we only want debug messages from a specific process it is possible to do this\nwith a filter like this:\n\n```erlang\n%% Initial setup to use a filter for the level filter instead of the primary level\nPrimaryLevel = maps:get(level, logger:get_primary_config()),\nok = logger:add_primary_filter(primary_level,\n {fun logger_filters:level/2, {log, gteq, PrimaryLevel}}),\nlogger:set_primary_config(filter_default, stop),\nlogger:set_primary_config(level, all),\n\n%% Test that things work as they should\nlogger:notice(\"Notice should be logged\"),\nlogger:debug(\"Should not be logged\"),\n\n%% Add the filter to allow PidToLog to send debug events\nPidToLog = self(),\nPidFilter = fun(LogEvent, _) when PidToLog =:= self() -> LogEvent;\n (_LogEvent, _) -> ignore end,\nok = logger:add_primary_filter(pid, {PidFilter,[]}),\nlogger:debug(\"Debug should be logged\").\n```\n\nThere is a bit of setup needed to allow filters to decide whether a specific\nprocess should be allowed to log. This is because the default primary log level\nis notice and it is enforced before the primary filters. So in order for the pid\nfilter to be useful we have to raise the primary log level to `all` and then add\na level filter that only lets certain messages at or greater than notice\nthrough. When the setup is done, it is simple to add a filter that allows a\ncertain pid through.\n\nNote that doing the primary log level filtering through a filter and not through\nthe level is quite a lot more expensive, so make sure to test that your system\ncan handle the extra load before you enable it on a production node.\n\n#### See also\n\n- [Filters](logger_chapter.md#filters) in the Logging User's Guide\n- `logger_filters:level/2`\n- `logger:set_primary_config/2`","title":"Process filters - Logging Cookbook","ref":"logger_cookbook.html#process-filters"},{"type":"extras","doc":"Domains are used to specify which subsystem a certain log event originates from.\nThe default handler will by default only log events with the domain `[otp]` or\nwithout a domain. If you would like to include SSL log events into the default\nhandler log you could do this:\n\n```erlang\n1> logger:add_handler_filter(default,ssl_domain,\n {fun logger_filters:domain/2,{log,sub,[otp,ssl]}}).\n2> application:ensure_all_started(ssl).\n{ok,[crypto,asn1,public_key,ssl]}\n3> ssl:connect(\"www.erlang.org\",443,[{log_level,debug}]).\n%% lots of text\n```\n\n#### See also\n\n- [Filters](logger_chapter.md#filters) in the Logging User's Guide\n- `logger_filters:domain/2`\n- `logger:set_primary_config/2`","title":"Domains - Logging Cookbook","ref":"logger_cookbook.html#domains"},{"type":"extras","doc":"\n# EEP-48: Documentation storage and format\n\nThis User's Guide describes the documentation storage format initially described\nin [EEP-48](https://www.erlang.org/erlang-enhancement-proposals/eep-0048.html).\nBy standardizing how API documentation is stored, it will be possible to write\ntools that work across languages.\n\nTo fetch the EEP-48 documentation for a module, use `code:get_doc/1`.\n\nTo render the EEP-48 documentation for an Erlang module, use\n`shell_docs:render/2`.","title":"EEP-48: Documentation storage and format","ref":"eep48_chapter.html"},{"type":"extras","doc":"To look for documentation for a module named `example`, a tool should:\n\nLook for `example.beam` in the code path, parse the BEAM file, and retrieve the\n`Docs` chunk. If the chunk is not available, it should look for `\"example.beam\"`\nin the code path and find the `doc/chunks/example.chunk` file in the application\nthat defines the `example` module. If no `.chunk` file exists,\ndocumentation is not available.\n\nThe choice of using a chunk or the filesystem is completely up to the language\nor library. In both cases, the documentation can be added or removed at any\nmoment by stripping the `Docs` chunk (using `m:beam_lib`) or by removing the\n`doc/chunks` directory.\n\nFor example, languages such as Elixir and LFE attach the `Docs` chunk at\ncompilation time, which can be controlled via a compiler flag, while\nother languages might want to generate the documentation separate from\nthe compilation of the source code.","title":"The \"Docs\" storage - EEP-48: Documentation storage and format","ref":"eep48_chapter.html#the-docs-storage"},{"type":"extras","doc":"In both storages, the documentation is written in the exactly same format: an\nErlang term serialized to binary via\n[`term_to_binary/1`](`erlang:term_to_binary/1`). The term can be optionally\ncompressed when serialized. It must follow the type specification below:\n\n```erlang\n{docs_v1,\n Anno :: erl_anno:anno(),\n BeamLanguage :: atom(),\n Format :: binary(),\n ModuleDoc :: #{DocLanguage := DocValue} | none | hidden,\n Metadata :: map(),\n Docs ::\n [{{Kind, Name, Arity},\n Anno :: erl_anno:anno(),\n Signature :: [binary()],\n Doc :: #{DocLanguage := DocValue} | none | hidden,\n Metadata :: map()\n }]} when DocLanguage :: binary(),\n DocValue :: binary() | term()\n```\n\nwhere in the root tuple we have:\n\n- **`Anno`** - annotation (line, column, file) of the definition itself (see\n `m:erl_anno`)\n\n- **`BeamLanguage`** - an atom representing the language, for example: `erlang`,\n `elixir`, `lfe`, `alpaca`, and so on\n\n- **`Format`** - the mime type of the documentation, such as `<<\"text/markdown\">>`\n or `<<\"application/erlang+html\">>`. For details of the format used by Erlang\n see the [`EEP-48 Chapter`](`e:edoc:doc_storage.md`) in EDoc's User's\n Guide.\n\n- **`ModuleDoc`** - a map with the documentation language as key, such as\n `<<\"en\">>` or `<<\"pt_BR\">>`, and the documentation as a binary value. It can\n be atom `none` if no documentation exists or the atom `hidden` if\n documentation has been explicitly disabled for this entry.\n\n- **`Metadata`** - a map of atom keys with any term as value. This can be used to\n add annotations like the `authors` of a module, `deprecated`, or anything else\n a language or documentation tool finds relevant.\n\n- **`Docs`** - a list of documentation for other entities (such as functions and\n types) in the module.\n\nFor each entry in Docs, we have:\n\n- **`{Kind, Name, Arity}`** - the kind, name and arity identifying the function,\n callback, type, and so on. The official entities are: `function`, `type`, and\n `callback`. Other languages will add their own. For instance, Elixir and LFE\n might add `macro`.\n\n- **`Anno`** - annotation (line, column, file) of the module documentation\n (see `m:erl_anno`).\n\n- **`Signature`** - the signature of the entity. It is is a list of binaries.\n Each entry represents a binary in the signature that can be joined with\n whitespace or newline. For example,\n `[<<\"binary_to_atom(Binary, Encoding)\">>, <<\"when is_binary(Binary)\">>]` can\n be rendered as a single line or two lines. It exists exclusively for\n exhibition purposes.\n\n- **`Doc`** - a map with the documentation language as key, such as `<<\"en\">>` or\n `<<\"pt_BR\">>`, and the documentation as a value. The documentation can either be\n a binary or any Erlang term, both described by `Format`. If it is an Erlang\n term, then `Format` must be `<<\"application/erlang+SUFFIX\">>`, such as\n `<<\"application/erlang+html\">>` when the documentation is an Erlang\n representation of an HTML document. `Doc` can also be atom `none`\n if no documentation exists or the atom `hidden` if documentation has been\n explicitly disabled for this entry.\n\n- **`Metadata`** - a map of atom keys with any term as value.\n\nThis shared format is the heart of the EEP as it is what effectively allows\ncross-language collaboration.\n\nThe Metadata field exists to allow languages, tools, and libraries to add custom\ninformation to each entry. This EEP documents the following metadata keys:\n\n- **`authors := [binary()]`** - a list of authors as binaries.\n\n- **`behaviours := [module()]`** - a list of the behaviours implemented by\n this module.\n\n- **`cross_references := [module() | {module(), {Kind, Name, Arity}}]`** - a\n list of modules or module entries that can be used as cross references when\n generating documentation.\n\n- **`deprecated := binary()`** - when present, it means the current entry is\n deprecated with a binary that represents the reason for deprecation and a\n recommendation to replace the deprecated code.\n\n- **`since := binary()`** - a binary representing the version such entry was\n added, such as `<<\"1.3.0\">>` or `<<\"20.0\">>`.\n\n- **`source_path := binary()`** - the absolute location of the source file for\n this module. Applies only to the module metadata.\n\n- **`source_annos := [erl_anno:anno()]`** - a list of source code locations.\n You may either store one for each clause or only for the first clause.\n\nAny key may be added to Metadata at any time. Keys that are frequently used by\nthe community can be standardized in future versions.","title":"The \"Docs\" format - EEP-48: Documentation storage and format","ref":"eep48_chapter.html#the-docs-format"},{"type":"extras","doc":"`m:erl_anno`, `m:shell_docs`,\n[`EEP-48 Chapter in EDoc's User's Guide`](`e:edoc:doc_storage.md`),\n`code:get_doc/1`","title":"See Also - EEP-48: Documentation storage and format","ref":"eep48_chapter.html#see-also"},{"type":"extras","doc":"\n# app\n\nApplication resource file.","title":"app","ref":"app.html"},{"type":"extras","doc":"The _application resource file_ specifies the resources an application uses, and\nhow the application is started. There must always be one application resource\nfile called `Application.app` for each application `Application` in the system.\n\nThe file is read by the application controller when an application is\nloaded/started. It is also used by the functions in `systools`, for example when\ngenerating start scripts.","title":"Description - app","ref":"app.html#description"},{"type":"extras","doc":"The application resource file is to be called `Application.app`, where\n`Application` is the application name. The file is to be located in directory\n`ebin` for the application.\n\nThe file must contain a single Erlang term, which is called an _application\nspecification_:\n\n```erlang\n{application, Application,\n [{description, Description},\n {id, Id},\n {vsn, Vsn},\n {modules, Modules},\n {maxP, MaxP},\n {maxT, MaxT},\n {registered, Names},\n {included_applications, Apps},\n {optional_applications, Apps},\n {applications, Apps},\n {env, Env},\n {mod, Start},\n {start_phases, Phases},\n {runtime_dependencies, RTDeps}]}.\n\n Value Default\n ----- -------\nApplication atom() -\nDescription string() \"\"\nId string() \"\"\nVsn string() \"\"\nModules [Module] []\nMaxP int() infinity\nMaxT int() infinity\nNames [Name] []\nApps [App] []\nEnv [{Par,Val}] []\nStart {Module,StartArgs} []\nPhases [{Phase,PhaseArgs}] undefined\nRTDeps [ApplicationVersion] []\n\nModule = Name = App = Par = Phase = atom()\nVal = StartArgs = PhaseArgs = term()\nApplicationVersion = string()\n```\n\n- **`Application`** - Application name.\n\nFor the application controller, all keys are optional. The respective default\nvalues are used for any omitted keys.\n\nThe functions in `systools` require more information. If they are used, the\nfollowing keys are mandatory:\n\n- `description`\n- `vsn`\n- `modules`\n- `registered`\n- `applications`\n\nThe other keys are ignored by `systools`.\n\n- **`description`** - A one-line description of the application.\n\n- **`id`** - Product identification, or similar.\n\n- **`vsn`** - Version of the application.\n\n- **`modules`** - All modules introduced by this application. `systools` uses\n this list when generating start scripts and tar files. A module can only be\n defined in one application.\n\n- **`maxP`** - _Deprecated - is ignored_\n\n Maximum number of processes allowed in the application.\n\n- **`maxT`** - Maximum time, in milliseconds, that the application is allowed to\n run. After the specified time, the application terminates automatically.\n\n- **`registered`** - All names of registered processes started in this\n application. `systools` uses this list to detect name clashes between\n different applications.\n\n- **`included_applications`** - All applications included by this application.\n When this application is started, all included applications are loaded\n automatically, but not started, by the application controller. It is assumed\n that the top-most supervisor of the included application is started by a\n supervisor of this application.\n\n- **`applications`** - All applications that must be started before this\n application. If an application is also listed in `optional_applications`, then\n the application is not required to exist (but if it exists, it is also\n guaranteed to be started before this one).\n\n `systools` uses this list to generate correct start scripts. Defaults to the\n empty list, but notice that all applications have dependencies to (at least)\n Kernel and STDLIB.\n\n- **`optional_applications`** - A list of `applications` that are optional. Note\n if you want an optional dependency to be automatically started before the\n current application whenever it is available, it must be listed on both\n `applications` and `optional_applications`.\n\n- **`env`** - Configuration parameters used by the application. The value of a\n configuration parameter is retrieved by calling `application:get_env/1,2`. The\n values in the application resource file can be overridden by values in a\n configuration file (see [`config(4)`](config.md)) or by command-line flags\n (see [`erts:erl(1)`](`e:erts:erl_cmd.md`)).\n\n- **`mod`** - Specifies the application callback module and a start argument,\n see `m:application`.\n\n Key `mod` is necessary for an application implemented as a supervision tree,\n otherwise the application controller does not know how to start it. `mod` can\n be omitted for applications without processes, typically code libraries, for\n example, STDLIB.\n\n- **`start_phases`** - A list of start phases and corresponding start arguments\n for the application. If this key is present, the application master, in\n addition to the usual call to `Module:start/2`, also calls\n `Module:start_phase(Phase,Type,PhaseArgs)` for each start phase defined by key\n `start_phases`. Only after this extended start procedure,\n `application:start(Application)` returns.\n\n Start phases can be used to synchronize startup of an application and its\n included applications. In this case, key `mod` must be specified as follows:\n\n ```erlang\n {mod, {application_starter,[Module,StartArgs]}}\n ```\n\n The application master then calls `Module:start/2` for the primary\n application, followed by calls to `Module:start_phase/3` for each start phase\n (as defined for the primary application), both for the primary application and\n for each of its included applications, for which the start phase is defined.\n\n This implies that for an included application, the set of start phases must be\n a subset of the set of phases defined for the primary application. For more\n information, see [OTP Design Principles](`e:system:applications.md`).\n\n- **`runtime_dependencies`{: #runtime_dependencies }** - A list of application\n versions that the application depends on. An example of such an application\n version is `\"kernel-3.0\"`. Application versions specified as runtime\n dependencies are minimum requirements. That is, a larger application version\n than the one specified in the dependency satisfies the requirement. For\n information about how to compare application versions, see section\n [Versions](`e:system:versions.md`) in the System Principles User's Guide.\n\n Notice that the application version specifies a source code version. One more,\n indirect, requirement is that the installed binary application of the\n specified version is built so that it is compatible with the rest of the\n system.\n\n Some dependencies can only be required in specific runtime scenarios. When\n such optional dependencies exist, these are specified and documented in the\n corresponding \"App\" documentation of the specific application.","title":"File Syntax - app","ref":"app.html#file-syntax"},{"type":"extras","doc":"`m:application`, `m:systools`","title":"See Also - app","ref":"app.html#see-also"},{"type":"extras","doc":"\n# config\n\nConfiguration file.","title":"config","ref":"config.html"},{"type":"extras","doc":"A _configuration file_ contains values for configuration parameters for the\napplications in the system. The `erl` command-line argument\n[`-config Name`](`e:erts:erl_cmd.md#config`) tells the system to use data in the\nsystem configuration file `Name.config`.\n\nThe erl command-line argument [`-configfd`](`e:erts:erl_cmd.md#configfd`) works\nthe same way as the `-config` option but specifies a file descriptor to read\nconfiguration data from instead of a file.\n\nThe configuration data from configuration files and file descriptors are read in\nthe same order as they are given on the command line. For example,\n`erl -config a -configfd 3 -config b -configfd 4` would cause the system to read\nconfiguration data in the following order `a.config`, file descriptor `3`,\n`b.config`, and file descriptor `4`. If a configuration parameter is specified\nmore than once in the given files and file descriptors, the last one overrides\nthe previous ones.\n\nConfiguration parameter values in a configuration file or file descriptor\noverride the values in the application resource files (see [`app(4)`](app.md)).\nThe values in the configuration file are always overridden by command-line flags\n(see [`erts:erl(1)`](`e:erts:erl_cmd.md`)).\n\nThe value of a configuration parameter is retrieved by calling\n`application:get_env/1,2`.","title":"Description - config","ref":"config.html#description"},{"type":"extras","doc":"The configuration file is to be called `Name.config`, where `Name` is any name.\n\nFile `.config` contains a single Erlang term and has the following syntax:\n\n```erlang\n[{Application1, [{Par11, Val11}, ...]},\n ...\n {ApplicationN, [{ParN1, ValN1}, ...]}].\n```\n\n- **`Application = atom()`** - Application name.\n\n- **`Par = atom()`** - Name of a configuration parameter.\n\n- **`Val = term()`** - Value of a configuration parameter.","title":"File Syntax - config","ref":"config.html#file-syntax"},{"type":"extras","doc":"When starting Erlang in embedded mode, it is assumed that exactly one system\nconfiguration file is used, named `sys.config`. This file is to be located in\n`$ROOT/releases/Vsn`, where `$ROOT` is the Erlang/OTP root installation\ndirectory and `Vsn` is the release version.\n\nRelease handling relies on this assumption. When installing a new release\nversion, the new `sys.config` is read and used to update the application's\nconfigurations.\n\nThis means that specifying another `.config` file, or more `.config` files,\nleads to an inconsistent update of application configurations. There is,\nhowever, a way to point out other config files from a `sys.config`. How to do\nthis is described in the next section.","title":"sys.config - config","ref":"config.html#sys-config"},{"type":"extras","doc":"There is a way to include other configuration files from a `sys.config` file and\nfrom a configuration that comes from a file descriptor that has been pointed out\nwith the [`-configfd`](`e:erts:erl_cmd.md#configfd`) command-line argument.\n\nThe syntax for including files can be described by the\n[Erlang type language](`e:system:typespec.md`) like this:\n\n```text\n[{Application, [{Par, Val}]} | IncludeFile].\n```\n\n- **`IncludeFile = string()`** - Name of a `.config` file. The extension\n `.config` can be omitted. It is recommended to use absolute paths. If a\n relative path is used in a `sys.config`, `IncludeFile` is searched, first,\n relative to the `sys.config` directory, then relative to the current working\n directory of the emulator. If a relative path is used in a `-configfd`\n configuration, `IncludeFile` is searched, first, relative to the dictionary\n containing the [boot script](`e:sasl:script.md`) (see also the\n [`-boot`](`e:erts:erl_cmd.md#boot`) command-line argument) for the emulator,\n then relative to the current working directory of the emulator. This makes it\n possible to use `sys.config` for pointing out other `.config` files in a\n release or in a node started manually using `-config` or `-configfd` with the\n same result whatever the current working directory is.\n\nWhen traversing the contents of a `sys.config` or a `-configfd` configuration\nand a filename is encountered, its contents are read and merged with the result\nso far. When an application configuration tuple `{Application, Env}` is found,\nit is merged with the result so far. Merging means that new parameters are added\nand existing parameter values are overwritten.\n\n_Example:_\n\n```text\nsys.config:\n\n[\"/home/user/myconfig1\"\n {myapp,[{par1,val1},{par2,val2}]},\n \"/home/user/myconfig2\"].\n\nmyconfig1.config:\n\n[{myapp,[{par0,val0},{par1,val0},{par2,val0}]}].\n\nmyconfig2.config:\n\n[{myapp,[{par2,val3},{par3,val4}]}].\n```\n\nThis yields the following environment for `myapp`:\n\n```text\n[{par0,val0},{par1,val1},{par2,val3},{par3,val4}]\n```\n\nThe run-time system will abort before staring up if an include file specified in\n`sys.config` or a `-configfd` configuration does not exist, or is erroneous.\nHowever, installing a new release version will not fail if there is an error\nwhile loading an include file, but an error message is returned and the\nerroneous file is ignored.","title":"Including Files from sys.config and -configfd Configurations - config","ref":"config.html#including-files-from-sys-config-and-configfd-configurations"},{"type":"extras","doc":"[`app(4)`](app.md), [`erts:erl(1)`](`e:erts:erl_cmd.md`),\n[OTP Design Principles](`e:system:design_principles.md`)","title":"See Also - config","ref":"config.html#see-also"}],"content_type":"text/plain","producer":{"name":"ex_doc","version":[48,46,51,52,46,49]}} \ No newline at end of file diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/eep48_chapter.html b/prs/9045/lib/kernel-10.1.1/doc/html/eep48_chapter.html index 07a749821215..ea2aeab8416f 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/eep48_chapter.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/eep48_chapter.html @@ -160,20 +160,20 @@

                In both storages, the documentation is written in the exactly same format: an Erlang term serialized to binary via term_to_binary/1. The term can be optionally -compressed when serialized. It must follow the type specification below:

                {docs_v1,
                - Anno :: erl_anno:anno(),
                - BeamLanguage :: atom(),
                - Format :: binary(),
                - ModuleDoc :: #{DocLanguage := DocValue} | none | hidden,
                - Metadata :: map(),
                +compressed when serialized. It must follow the type specification below:

                {docs_v1,
                + Anno :: erl_anno:anno(),
                + BeamLanguage :: atom(),
                + Format :: binary(),
                + ModuleDoc :: #{DocLanguage := DocValue} | none | hidden,
                + Metadata :: map(),
                  Docs ::
                -   [{{Kind, Name, Arity},
                -     Anno :: erl_anno:anno(),
                -     Signature :: [binary()],
                -     Doc :: #{DocLanguage := DocValue} | none | hidden,
                -     Metadata :: map()
                -    }]} when DocLanguage :: binary(),
                -             DocValue :: binary() | term()

                where in the root tuple we have:

                • Anno - annotation (line, column, file) of the definition itself (see + [{{Kind, Name, Arity}, + Anno :: erl_anno:anno(), + Signature :: [binary()], + Doc :: #{DocLanguage := DocValue} | none | hidden, + Metadata :: map() + }]} when DocLanguage :: binary(), + DocValue :: binary() | term()

                where in the root tuple we have:

                • Anno - annotation (line, column, file) of the definition itself (see erl_anno)

                • BeamLanguage - an atom representing the language, for example: erlang, elixir, lfe, alpaca, and so on

                • Format - the mime type of the documentation, such as <<"text/markdown">> or <<"application/erlang+html">>. For details of the format used by Erlang diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/erl_epmd.html b/prs/9045/lib/kernel-10.1.1/doc/html/erl_epmd.html index 2004e73fb0bd..abaef7ce2b0b 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/erl_epmd.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/erl_epmd.html @@ -367,8 +367,8 @@

                  names(Host)

                  Called by net_adm:names/0. Host defaults to the localhost. Returns the names and associated port numbers of the Erlang nodes that epmd registered at the specified host. Returns {error, address} if epmd is not -operational.

                  Example:

                  (arne@dunn)1> erl_epmd:names(localhost).
                  -{ok,[{"arne",40262}]}
                  +operational.

                  Example:

                  (arne@dunn)1> erl_epmd:names(localhost).
                  +{ok,[{"arne",40262}]}
                  diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/erpc.html b/prs/9045/lib/kernel-10.1.1/doc/html/erpc.html index c4c5b75c8b55..6be71926a78b 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/erpc.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/erpc.html @@ -1278,20 +1278,20 @@

                  multicall(Nodes, Module, Function, Args, Ti selective receive optimization which removes the need to scan the message queue from the beginning in order to find a matching message. The send_request()/receive_response() combination can, however, not utilize this -optimization.

                  my_multicall(Nodes, Module, Function, Args) ->
                  -  ReqIds = lists:map(fun (Node) ->
                  -                       erpc:send_request(Node, Module, Function, Args)
                  +optimization.

                  my_multicall(Nodes, Module, Function, Args) ->
                  +  ReqIds = lists:map(fun (Node) ->
                  +                       erpc:send_request(Node, Module, Function, Args)
                                        end,
                  -                     Nodes),
                  -  lists:map(fun (ReqId) ->
                  +                     Nodes),
                  +  lists:map(fun (ReqId) ->
                                 try
                  -                {ok, erpc:receive_response(ReqId, infinity)}
                  +                {ok, erpc:receive_response(ReqId, infinity)}
                                 catch
                                   Class:Reason ->
                  -                  {Class, Reason}
                  +                  {Class, Reason}
                                 end
                               end,
                  -            ReqIds).

                  If an erpc operation fails, but it is unknown if the function is/will be + ReqIds).

                  If an erpc operation fails, but it is unknown if the function is/will be applied (that is, a timeout, connection loss, or an improper Nodes list), the caller will not receive any further information about the result if/when the applied function completes. If the applied function communicates with the @@ -1448,9 +1448,9 @@

                  receive_response(RequestId, Timeout)

                  performance. call() can utilize a selective receive optimization which removes the need to scan the message queue from the beginning in order to find a matching message. The send_request()/receive_response() combination can, -however, not utilize this optimization.

                  my_call(Node, Module, Function, Args, Timeout) ->
                  -  RequestId = erpc:send_request(Node, Module, Function, Args),
                  -  erpc:receive_response(RequestId, Timeout).

                  If the erpc operation fails, but it is unknown if the function is/will be +however, not utilize this optimization.

                  my_call(Node, Module, Function, Args, Timeout) ->
                  +  RequestId = erpc:send_request(Node, Module, Function, Args),
                  +  erpc:receive_response(RequestId, Timeout).

                  If the erpc operation fails, but it is unknown if the function is/will be applied (that is, a timeout, or a connection loss), the caller will not receive any further information about the result if/when the applied function completes. If the applied function explicitly communicates with the calling process, such @@ -1752,9 +1752,9 @@

                  send_request/4

                  performance. call() can utilize a selective receive optimization which removes the need to scan the message queue from the beginning in order to find a matching message. The send_request()/receive_response() combination can, -however, not utilize this optimization.

                  my_call(Node, Module, Function, Args, Timeout) ->
                  -  RequestId = erpc:send_request(Node, Module, Function, Args),
                  -  erpc:receive_response(RequestId, Timeout).

                  Fails with an {erpc, badarg} error exception if:

                  • Node is not an atom.
                  • Module is not an atom.
                  • Function is not an atom.
                  • Args is not a list. Note that the list is not verified to be a proper list +however, not utilize this optimization.

                    my_call(Node, Module, Function, Args, Timeout) ->
                    +  RequestId = erpc:send_request(Node, Module, Function, Args),
                    +  erpc:receive_response(RequestId, Timeout).

                    Fails with an {erpc, badarg} error exception if:

                    • Node is not an atom.
                    • Module is not an atom.
                    • Function is not an atom.
                    • Args is not a list. Note that the list is not verified to be a proper list at the client side.

                    Equivalent to erpc:send_request(Node, erlang, apply, [Fun,[]]), Label, RequestIdCollection).

                    Fails with an {erpc, badarg} error exception if:

                    • Node is not an atom.
                    • Fun is not a fun of zero arity.
                    • RequestIdCollection is detected not to be request identifier collection.
                  diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/file.html b/prs/9045/lib/kernel-10.1.1/doc/html/file.html index 67b3d87d9822..61e8fb6eab08 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/file.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/file.html @@ -186,31 +186,31 @@

                  improve performance for small reads and writes. However, the overhead won't disappear completely and it's best to keep the number of file operations to a minimum. As a contrived example, the following function writes 4MB in 2.5 -seconds when tested:

                  create_file_slow(Name) ->
                  -    {ok, Fd} = file:open(Name, [raw, write, delayed_write, binary]),
                  -    create_file_slow_1(Fd, 4 bsl 20),
                  -    file:close(Fd).
                  +seconds when tested:

                  create_file_slow(Name) ->
                  +    {ok, Fd} = file:open(Name, [raw, write, delayed_write, binary]),
                  +    create_file_slow_1(Fd, 4 bsl 20),
                  +    file:close(Fd).
                   
                  -create_file_slow_1(_Fd, 0) ->
                  +create_file_slow_1(_Fd, 0) ->
                       ok;
                  -create_file_slow_1(Fd, M) ->
                  -    ok = file:write(Fd, <<0>>),
                  -    create_file_slow_1(Fd, M - 1).

                  The following functionally equivalent code writes 128 bytes per call to +create_file_slow_1(Fd, M) -> + ok = file:write(Fd, <<0>>), + create_file_slow_1(Fd, M - 1).

                  The following functionally equivalent code writes 128 bytes per call to write/2 and so does the same work in 0.08 seconds, which is roughly 30 times -faster:

                  create_file(Name) ->
                  -    {ok, Fd} = file:open(Name, [raw, write, delayed_write, binary]),
                  -    create_file_1(Fd, 4 bsl 20),
                  -    file:close(Fd),
                  +faster:

                  create_file(Name) ->
                  +    {ok, Fd} = file:open(Name, [raw, write, delayed_write, binary]),
                  +    create_file_1(Fd, 4 bsl 20),
                  +    file:close(Fd),
                       ok.
                   
                  -create_file_1(_Fd, 0) ->
                  +create_file_1(_Fd, 0) ->
                       ok;
                  -create_file_1(Fd, M) when M >= 128 ->
                  -    ok = file:write(Fd, <<0:(128)/unit:8>>),
                  -    create_file_1(Fd, M - 128);
                  -create_file_1(Fd, M) ->
                  -    ok = file:write(Fd, <<0:(M)/unit:8>>),
                  -    create_file_1(Fd, M - 1).

                  When writing data it's generally more efficient to write a list of binaries +create_file_1(Fd, M) when M >= 128 -> + ok = file:write(Fd, <<0:(128)/unit:8>>), + create_file_1(Fd, M - 128); +create_file_1(Fd, M) -> + ok = file:write(Fd, <<0:(M)/unit:8>>), + create_file_1(Fd, M - 1).

                  When writing data it's generally more efficient to write a list of binaries rather than a list of integers. It is not needed to flatten a deep list before writing. On Unix hosts, scatter output, which writes a set of buffers in one operation, is used when possible. In this way @@ -2022,8 +2022,8 @@

                  consult(Filename)

                  For a list of typical error codes, see open/2.

                • {error, {Line, Mod, Term}} - An error occurred when interpreting the Erlang terms in the file. To convert the three-element tuple to an English description of the error, use format_error/1.

                Example:

                f.txt:  {person, "kalle", 25}.
                -        {person, "pelle", 30}.
                1> file:consult("f.txt").
                -{ok,[{person,"kalle",25},{person,"pelle",30}]}

                The encoding of Filename can be set by a comment, as described in + {person, "pelle", 30}.

                1> file:consult("f.txt").
                +{ok,[{person,"kalle",25},{person,"pelle",30}]}

                The encoding of Filename can be set by a comment, as described in epp.

                @@ -3380,7 +3380,7 @@

                read_file_info(File, Opts)

                Retrieves information about a file. Returns {ok, FileInfo} if successful, otherwise {error, Reason}.

                FileInfo is a record file_info, defined in the Kernel include file file.hrl. -Include the following directive in the module from which the function is called:

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

                The time type returned in atime, mtime, and ctime is dependent on the time +Include the following directive in the module from which the function is called:

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

                The time type returned in atime, mtime, and ctime is dependent on the time type set in Opts :: {time, Type} as follows:

                • local - Returns local time.

                • universal - Returns universal time.

                • posix - Returns seconds since or before Unix time epoch, which is 1970-01-01 00:00 UTC.

                Default is {time, local}.

                If the option raw is set, the file server is not called and only information about local files is returned. Note that this will break this module's atomicity @@ -4070,7 +4070,7 @@

                write_file_info(Filename, FileInfo, Opts)Changes file information. Returns ok if successful, otherwise {error, Reason}.

                FileInfo is a record file_info, defined in the Kernel include file file.hrl. Include the following directive in the module from -which the function is called:

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

                The time type set in atime, mtime, and ctime depends on the time type set +which the function is called:

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

                The time type set in atime, mtime, and ctime depends on the time type set in Opts :: {time, Type} as follows:

                • local - Interprets the time set as local.

                • universal - Interprets it as universal time.

                • posix - Must be seconds since or before Unix time epoch, which is 1970-01-01 00:00 UTC.

                Default is {time, local}.

                If the option raw is set, the file server is not called and only information about local files is returned.

                The following fields are used from the record, if they are specified:

                • atime = date_time/0 | non_neg_integer/0 - The last time the file was diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/gen_sctp.html b/prs/9045/lib/kernel-10.1.1/doc/html/gen_sctp.html index c2934aa36999..98583ede1c1d 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/gen_sctp.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/gen_sctp.html @@ -142,7 +142,7 @@

                  lksctp-tools-1.0.6

                • Briefly on Solaris 10
                • SUSE Linux Enterprise Server 10 Service Pack 1 (x86_64) kernel 2.6.16.54-0.2.3-smp with lksctp-tools-1.0.7
                • FreeBSD 8.2

                This module was written for one-to-many style sockets (type seqpacket). With the addition of peeloff/2, one-to-one style sockets (type stream) -were introduced.

                Record definitions for this module can be found using:

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

                These record definitions use the "new" spelling 'adaptation', +were introduced.

                Record definitions for this module can be found using:

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

                These record definitions use the "new" spelling 'adaptation', not the deprecated 'adaption', regardless of which spelling the underlying C API uses.

                @@ -190,31 +190,31 @@

                will instead immediately return with e.g. {error, eagain} if this option has been set to true. Defaults to false.

              • {sctp_module, module()} - Overrides which callback module is used. -Defaults to inet_sctp for IPv4 and inet6_sctp for IPv6.

              • {sctp_rtoinfo, #sctp_rtoinfo{}}

                #sctp_rtoinfo{
                -      assoc_id = assoc_id(),
                -      initial  = integer(),
                -      max      = integer(),
                -      min      = integer()
                -}

                Determines retransmission time-out parameters, in milliseconds, for the +Defaults to inet_sctp for IPv4 and inet6_sctp for IPv6.

              • {sctp_rtoinfo, #sctp_rtoinfo{}}

                #sctp_rtoinfo{
                +      assoc_id = assoc_id(),
                +      initial  = integer(),
                +      max      = integer(),
                +      min      = integer()
                +}

                Determines retransmission time-out parameters, in milliseconds, for the association(s) specified by assoc_id.

                assoc_id = 0 (default) indicates the whole endpoint. See RFC 2960 and Sockets API Extensions for SCTP -for the exact semantics of the field values.

              • {sctp_associnfo, #sctp_assocparams{}}

                #sctp_assocparams{
                -      assoc_id                 = assoc_id(),
                -      asocmaxrxt               = integer(),
                -      number_peer_destinations = integer(),
                -      peer_rwnd                = integer(),
                -      local_rwnd               = integer(),
                -      cookie_life              = integer()
                -}

                Determines association parameters for the association(s) specified by +for the exact semantics of the field values.

              • {sctp_associnfo, #sctp_assocparams{}}

                #sctp_assocparams{
                +      assoc_id                 = assoc_id(),
                +      asocmaxrxt               = integer(),
                +      number_peer_destinations = integer(),
                +      peer_rwnd                = integer(),
                +      local_rwnd               = integer(),
                +      cookie_life              = integer()
                +}

                Determines association parameters for the association(s) specified by assoc_id.

                assoc_id = 0 (default) indicates the whole endpoint. See Sockets API Extensions for SCTP -for the discussion of their semantics. Rarely used.

              • {sctp_initmsg, #sctp_initmsg{}}

                #sctp_initmsg{
                -     num_ostreams   = integer(),
                -     max_instreams  = integer(),
                -     max_attempts   = integer(),
                -     max_init_timeo = integer()
                -}

                Determines the default parameters that this socket tries to negotiate +for the discussion of their semantics. Rarely used.

              • {sctp_initmsg, #sctp_initmsg{}}

                #sctp_initmsg{
                +     num_ostreams   = integer(),
                +     max_instreams  = integer(),
                +     max_attempts   = integer(),
                +     max_init_timeo = integer()
                +}

                Determines the default parameters that this socket tries to negotiate with its peer while establishing an association with it. Is to be set after open/* but before the first connect/*. #sctp_initmsg{} can also be used as ancillary data with the first call of @@ -231,52 +231,52 @@

                performance reasons only.

              • {sctp_i_want_mapped_v4_addr, true|false} - Turns on|off automatic mapping of IPv4 addresses into IPv6 ones (if the socket address family is AF_INET6).

              • {sctp_maxseg, integer()} - Determines the maximum chunk size if message -fragmentation is used. If 0, the chunk size is limited by the Path MTU only.

              • {sctp_primary_addr, #sctp_prim{}}

                #sctp_prim{
                -      assoc_id = assoc_id(),
                -      addr     = {IP, Port}
                -}
                - IP = ip_address()
                - Port = port_number()

                For the association specified by assoc_id, {IP,Port} must be one of the +fragmentation is used. If 0, the chunk size is limited by the Path MTU only.

              • {sctp_primary_addr, #sctp_prim{}}

                #sctp_prim{
                +      assoc_id = assoc_id(),
                +      addr     = {IP, Port}
                +}
                + IP = ip_address()
                + Port = port_number()

                For the association specified by assoc_id, {IP,Port} must be one of the peer addresses. This option determines that the specified address is treated -by the local SCTP stack as the primary address of the peer.

              • {sctp_set_peer_primary_addr, #sctp_setpeerprim{}}

                #sctp_setpeerprim{
                -      assoc_id = assoc_id(),
                -      addr     = {IP, Port}
                -}
                - IP = ip_address()
                - Port = port_number()

                When set, informs the peer to use {IP, Port} as the primary address of the -local endpoint for the association specified by assoc_id.

              • {sctp_adaptation_layer, #sctp_setadaptation{}}

                #sctp_setadaptation{
                -      adaptation_ind = integer()
                -}

                When set, requests that the local endpoint uses the value specified by +by the local SCTP stack as the primary address of the peer.

              • {sctp_set_peer_primary_addr, #sctp_setpeerprim{}}

                #sctp_setpeerprim{
                +      assoc_id = assoc_id(),
                +      addr     = {IP, Port}
                +}
                + IP = ip_address()
                + Port = port_number()

                When set, informs the peer to use {IP, Port} as the primary address of the +local endpoint for the association specified by assoc_id.

              • {sctp_adaptation_layer, #sctp_setadaptation{}}

                #sctp_setadaptation{
                +      adaptation_ind = integer()
                +}

                When set, requests that the local endpoint uses the value specified by adaptation_ind as the Adaptation Indication parameter for establishing new associations. For details, see RFC 2960 and -Sockets API Extensions for SCTP.

              • {sctp_peer_addr_params, #sctp_paddrparams{}}

                #sctp_paddrparams{
                -      assoc_id   = assoc_id(),
                -      address    = {IP, Port},
                -      hbinterval = integer(),
                -      pathmaxrxt = integer(),
                -      pathmtu    = integer(),
                -      sackdelay  = integer(),
                -      flags      = list()
                -}
                -IP = ip_address()
                -Port = port_number()

                Determines various per-address parameters for the association specified by +Sockets API Extensions for SCTP.

              • {sctp_peer_addr_params, #sctp_paddrparams{}}

                #sctp_paddrparams{
                +      assoc_id   = assoc_id(),
                +      address    = {IP, Port},
                +      hbinterval = integer(),
                +      pathmaxrxt = integer(),
                +      pathmtu    = integer(),
                +      sackdelay  = integer(),
                +      flags      = list()
                +}
                +IP = ip_address()
                +Port = port_number()

                Determines various per-address parameters for the association specified by assoc_id and the peer address address (the SCTP protocol supports multi-homing, so more than one address can correspond to a specified association).

                • hbinterval - Heartbeat interval, in milliseconds

                • pathmaxrxt - Maximum number of retransmissions before this address is considered unreachable (and an alternative address is selected)

                • pathmtu - Fixed Path MTU, if automatic discovery is disabled (see flags below)

                • sackdelay - Delay, in milliseconds, for SAC messages (if the delay is -enabled, see flags below)

                • flags - The following flags are available:

                  • hb_enable - Enables heartbeat

                  • hb_disable - Disables heartbeat

                  • hb_demand - Initiates heartbeat immediately

                  • pmtud_enable - Enables automatic Path MTU discovery

                  • pmtud_disable - Disables automatic Path MTU discovery

                  • sackdelay_enable - Enables SAC delay

                  • sackdelay_disable - Disables SAC delay

              • {sctp_default_send_param, #sctp_sndrcvinfo{}}

                #sctp_sndrcvinfo{
                -      stream     = integer(),
                -      ssn        = integer(),
                -      flags      = list(),
                -      ppid       = integer(),
                -      context    = integer(),
                -      timetolive = integer(),
                -      tsn        = integer(),
                -      cumtsn     = integer(),
                -      assoc_id   = assoc_id()
                -}

                #sctp_sndrcvinfo{} is used both in this socket option, and as +enabled, see flags below)

              • flags - The following flags are available:

                • hb_enable - Enables heartbeat

                • hb_disable - Disables heartbeat

                • hb_demand - Initiates heartbeat immediately

                • pmtud_enable - Enables automatic Path MTU discovery

                • pmtud_disable - Disables automatic Path MTU discovery

                • sackdelay_enable - Enables SAC delay

                • sackdelay_disable - Disables SAC delay

            • {sctp_default_send_param, #sctp_sndrcvinfo{}}

              #sctp_sndrcvinfo{
              +      stream     = integer(),
              +      ssn        = integer(),
              +      flags      = list(),
              +      ppid       = integer(),
              +      context    = integer(),
              +      timetolive = integer(),
              +      tsn        = integer(),
              +      cumtsn     = integer(),
              +      assoc_id   = assoc_id()
              +}

              #sctp_sndrcvinfo{} is used both in this socket option, and as ancillary data while sending or receiving SCTP messages. When set as an option, it provides default values for subsequent send calls on the association specified by assoc_id.

              assoc_id = 0 (default) indicates the whole endpoint.

              The following fields typically must be specified by the sender:

              • sinfo_stream - Stream number (0-base) within the association to send @@ -285,7 +285,7 @@

                data

              • eof - Gracefully shuts down the current association, with flushing of unsent data

              Other fields are rarely used. For complete information, see RFC 2960 and -Sockets API Extensions for SCTP.

          • {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,
          @@ -294,42 +294,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(),
    +      outstrms            = integer(),
    +      fragmentation_point = integer(),
    +      primary             = #sctp_paddrinfo{}
    +}

    This option is read-only. It determines the status of the SCTP association specified by assoc_id. The following are the possible values of state (the state designations are mostly self-explanatory):

    • sctp_state_empty - Default. Means that no other state is active.

    • sctp_state_closed

    • sctp_state_cookie_wait

    • sctp_state_cookie_echoed

    • sctp_state_established

    • sctp_state_shutdown_pending

    • sctp_state_shutdown_sent

    • sctp_state_shutdown_received

    • sctp_state_shutdown_ack_sent

    Semantics of the other fields:

    • sstat_rwnd - Current receiver window size of the association

    • sstat_unackdata - Number of unacked data chunks

    • sstat_penddata - Number of data chunks pending receipt

    • sstat_instrms - Number of inbound streams

    • sstat_outstrms - Number of outbound streams

    • sstat_fragmentation_point - Message size at which SCTP fragmentation occurs

    • sstat_primary - Information on the current primary peer address (see -below for the format of #sctp_paddrinfo{})

  • {sctp_get_peer_addr_info, #sctp_paddrinfo{}}

    #sctp_paddrinfo{
    -      assoc_id  = assoc_id(),
    -      address   = {IP, Port},
    +below for the format of #sctp_paddrinfo{})

  • {sctp_get_peer_addr_info, #sctp_paddrinfo{}}

    #sctp_paddrinfo{
    +      assoc_id  = assoc_id(),
    +      address   = {IP, Port},
           state     = inactive | active | unconfirmed,
    -      cwnd      = integer(),
    -      srtt      = integer(),
    -      rto       = integer(),
    -      mtu       = integer()
    -}
    -IP = ip_address()
    -Port = port_number()

    This option is read-only. It determines the parameters specific to + cwnd = integer(), + srtt = integer(), + rto = integer(), + mtu = integer() +} +IP = ip_address() +Port = port_number()

  • This option is read-only. It determines the parameters specific to the peer address specified by address within the association specified by assoc_id. Field address fmust be set by the caller; all other fields are filled in on return. If assoc_id = 0 (default), the address @@ -343,119 +343,119 @@

    SCTP Examples

    Example of an Erlang SCTP server that receives SCTP messages -and prints them on the standard output:

    -module(sctp_server).
    +and prints them on the standard output:

    -module(sctp_server).
     
    --export([server/0,server/1,server/2]).
    --include_lib("kernel/include/inet.hrl").
    --include_lib("kernel/include/inet_sctp.hrl").
    -
    -server() ->
    -    server(any, 2006).
    -
    -server([Host,Port]) when is_list(Host), is_list(Port) ->
    -    {ok, #hostent{h_addr_list = [IP|_]}} = inet:gethostbyname(Host),
    -    io:format("~w -> ~w~n", [Host, IP]),
    -    server([IP, list_to_integer(Port)]).
    -
    -server(IP, Port) when is_tuple(IP) orelse IP == any orelse IP == loopback,
    -                      is_integer(Port) ->
    -    {ok,S} = gen_sctp:open(Port, [{recbuf,65536}, {ip,IP}]),
    -    io:format("Listening on ~w:~w. ~w~n", [IP,Port,S]),
    -    ok     = gen_sctp:listen(S, true),
    -    server_loop(S).
    -
    -server_loop(S) ->
    -    case gen_sctp:recv(S) of
    -    {error, Error} ->
    -        io:format("SCTP RECV ERROR: ~p~n", [Error]);
    +-export([server/0,server/1,server/2]).
    +-include_lib("kernel/include/inet.hrl").
    +-include_lib("kernel/include/inet_sctp.hrl").
    +
    +server() ->
    +    server(any, 2006).
    +
    +server([Host,Port]) when is_list(Host), is_list(Port) ->
    +    {ok, #hostent{h_addr_list = [IP|_]}} = inet:gethostbyname(Host),
    +    io:format("~w -> ~w~n", [Host, IP]),
    +    server([IP, list_to_integer(Port)]).
    +
    +server(IP, Port) when is_tuple(IP) orelse IP == any orelse IP == loopback,
    +                      is_integer(Port) ->
    +    {ok,S} = gen_sctp:open(Port, [{recbuf,65536}, {ip,IP}]),
    +    io:format("Listening on ~w:~w. ~w~n", [IP,Port,S]),
    +    ok     = gen_sctp:listen(S, true),
    +    server_loop(S).
    +
    +server_loop(S) ->
    +    case gen_sctp:recv(S) of
    +    {error, Error} ->
    +        io:format("SCTP RECV ERROR: ~p~n", [Error]);
         Data ->
    -        io:format("Received: ~p~n", [Data])
    +        io:format("Received: ~p~n", [Data])
         end,
    -    server_loop(S).

    Example of an Erlang SCTP client interacting with the above server. + server_loop(S).

    Example of an Erlang SCTP client interacting with the above server. Note that in this example the client creates an association with the server with 5 outbound streams. Therefore, sending of "Test 0" over stream 0 succeeds, but sending of "Test 5" over stream 5 fails. The client then aborts the association, which results in that -the corresponding event is received on the server side.

    -module(sctp_client).
    +the corresponding event is received on the server side.

    -module(sctp_client).
     
    --export([client/0, client/1, client/2]).
    --include_lib("kernel/include/inet.hrl").
    --include_lib("kernel/include/inet_sctp.hrl").
    -
    -client() ->
    -    client([localhost]).
    -
    -client([Host]) ->
    -    client(Host, 2006);
    -
    -client([Host, Port]) when is_list(Host), is_list(Port) ->
    -    client(Host,list_to_integer(Port)),
    -    init:stop().
    -
    -client(Host, Port) when is_integer(Port) ->
    -    {ok,S}     = gen_sctp:open(),
    -    {ok,Assoc} = gen_sctp:connect
    -        (S, Host, Port, [{sctp_initmsg,#sctp_initmsg{num_ostreams=5}}]),
    -    io:format("Connection Successful, Assoc=~p~n", [Assoc]),
    -
    -    io:write(gen_sctp:send(S, Assoc, 0, <<"Test 0">>)),
    -    io:nl(),
    -    timer:sleep(10000),
    -    io:write(gen_sctp:send(S, Assoc, 5, <<"Test 5">>)),
    -    io:nl(),
    -    timer:sleep(10000),
    -    io:write(gen_sctp:abort(S, Assoc)),
    -    io:nl(),
    -
    -    timer:sleep(1000),
    -    gen_sctp:close(S).

    A simple Erlang SCTP client that uses the connect_init API:

    -module(ex3).
    +-export([client/0, client/1, client/2]).
    +-include_lib("kernel/include/inet.hrl").
    +-include_lib("kernel/include/inet_sctp.hrl").
    +
    +client() ->
    +    client([localhost]).
    +
    +client([Host]) ->
    +    client(Host, 2006);
    +
    +client([Host, Port]) when is_list(Host), is_list(Port) ->
    +    client(Host,list_to_integer(Port)),
    +    init:stop().
    +
    +client(Host, Port) when is_integer(Port) ->
    +    {ok,S}     = gen_sctp:open(),
    +    {ok,Assoc} = gen_sctp:connect
    +        (S, Host, Port, [{sctp_initmsg,#sctp_initmsg{num_ostreams=5}}]),
    +    io:format("Connection Successful, Assoc=~p~n", [Assoc]),
    +
    +    io:write(gen_sctp:send(S, Assoc, 0, <<"Test 0">>)),
    +    io:nl(),
    +    timer:sleep(10000),
    +    io:write(gen_sctp:send(S, Assoc, 5, <<"Test 5">>)),
    +    io:nl(),
    +    timer:sleep(10000),
    +    io:write(gen_sctp:abort(S, Assoc)),
    +    io:nl(),
    +
    +    timer:sleep(1000),
    +    gen_sctp:close(S).

    A simple Erlang SCTP client that uses the connect_init API:

    -module(ex3).
     
    --export([client/4]).
    --include_lib("kernel/include/inet.hrl").
    --include_lib("kernel/include/inet_sctp.hrl").
    -
    -client(Peer1, Port1, Peer2, Port2)
    -  when is_tuple(Peer1), is_integer(Port1), is_tuple(Peer2), is_integer(Port2) ->
    -    {ok,S}     = gen_sctp:open(),
    -    SctpInitMsgOpt = {sctp_initmsg,#sctp_initmsg{num_ostreams=5}},
    -    ActiveOpt = {active, true},
    -    Opts = [SctpInitMsgOpt, ActiveOpt],
    -    ok = gen_sctp:connect(S, Peer1, Port1, Opts),
    -    ok = gen_sctp:connect(S, Peer2, Port2, Opts),
    -    io:format("Connections initiated~n", []),
    -    client_loop(S, Peer1, Port1, undefined, Peer2, Port2, undefined).
    -
    -client_loop(S, Peer1, Port1, AssocId1, Peer2, Port2, AssocId2) ->
    +-export([client/4]).
    +-include_lib("kernel/include/inet.hrl").
    +-include_lib("kernel/include/inet_sctp.hrl").
    +
    +client(Peer1, Port1, Peer2, Port2)
    +  when is_tuple(Peer1), is_integer(Port1), is_tuple(Peer2), is_integer(Port2) ->
    +    {ok,S}     = gen_sctp:open(),
    +    SctpInitMsgOpt = {sctp_initmsg,#sctp_initmsg{num_ostreams=5}},
    +    ActiveOpt = {active, true},
    +    Opts = [SctpInitMsgOpt, ActiveOpt],
    +    ok = gen_sctp:connect(S, Peer1, Port1, Opts),
    +    ok = gen_sctp:connect(S, Peer2, Port2, Opts),
    +    io:format("Connections initiated~n", []),
    +    client_loop(S, Peer1, Port1, undefined, Peer2, Port2, undefined).
    +
    +client_loop(S, Peer1, Port1, AssocId1, Peer2, Port2, AssocId2) ->
         receive
    -        {sctp, S, Peer1, Port1, {_Anc, SAC}}
    -          when is_record(SAC, sctp_assoc_change), AssocId1 == undefined ->
    -            io:format("Association 1 connect result: ~p. AssocId: ~p~n",
    -                      [SAC#sctp_assoc_change.state,
    -                       SAC#sctp_assoc_change.assoc_id]),
    -            client_loop(S, Peer1, Port1, SAC#sctp_assoc_change.assoc_id,
    -                        Peer2, Port2, AssocId2);
    -
    -        {sctp, S, Peer2, Port2, {_Anc, SAC}}
    -          when is_record(SAC, sctp_assoc_change), AssocId2 == undefined ->
    -            io:format("Association 2 connect result: ~p. AssocId: ~p~n",
    -                      [SAC#sctp_assoc_change.state, SAC#sctp_assoc_change.assoc_id]),
    -            client_loop(S, Peer1, Port1, AssocId1, Peer2, Port2,
    -                       SAC#sctp_assoc_change.assoc_id);
    -
    -        {sctp, S, Peer1, Port1, Data} ->
    -            io:format("Association 1: received ~p~n", [Data]),
    -            client_loop(S, Peer1, Port1, AssocId1,
    -                        Peer2, Port2, AssocId2);
    -
    -        {sctp, S, Peer2, Port2, Data} ->
    -            io:format("Association 2: received ~p~n", [Data]),
    -            client_loop(S, Peer1, Port1, AssocId1,
    -                        Peer2, Port2, AssocId2);
    +        {sctp, S, Peer1, Port1, {_Anc, SAC}}
    +          when is_record(SAC, sctp_assoc_change), AssocId1 == undefined ->
    +            io:format("Association 1 connect result: ~p. AssocId: ~p~n",
    +                      [SAC#sctp_assoc_change.state,
    +                       SAC#sctp_assoc_change.assoc_id]),
    +            client_loop(S, Peer1, Port1, SAC#sctp_assoc_change.assoc_id,
    +                        Peer2, Port2, AssocId2);
    +
    +        {sctp, S, Peer2, Port2, {_Anc, SAC}}
    +          when is_record(SAC, sctp_assoc_change), AssocId2 == undefined ->
    +            io:format("Association 2 connect result: ~p. AssocId: ~p~n",
    +                      [SAC#sctp_assoc_change.state, SAC#sctp_assoc_change.assoc_id]),
    +            client_loop(S, Peer1, Port1, AssocId1, Peer2, Port2,
    +                       SAC#sctp_assoc_change.assoc_id);
    +
    +        {sctp, S, Peer1, Port1, Data} ->
    +            io:format("Association 1: received ~p~n", [Data]),
    +            client_loop(S, Peer1, Port1, AssocId1,
    +                        Peer2, Port2, AssocId2);
    +
    +        {sctp, S, Peer2, Port2, Data} ->
    +            io:format("Association 2: received ~p~n", [Data]),
    +            client_loop(S, Peer1, Port1, AssocId1,
    +                        Peer2, Port2, AssocId2);
     
             Other ->
    -            io:format("Other ~p~n", [Other]),
    -            client_loop(S, Peer1, Port1, AssocId1,
    -                        Peer2, Port2, AssocId2)
    +            io:format("Other ~p~n", [Other]),
    +            client_loop(S, Peer1, Port1, AssocId1,
    +                        Peer2, Port2, AssocId2)
     
         after 5000 ->
                 ok
    @@ -1456,16 +1456,16 @@ 

    connect(Socket, Addr, Port, Opts, Timeout)<

    The result of connect/* is an #sctp_assoc_change{} event that contains, in particular, the new Association ID: -l

    #sctp_assoc_change{
    -      state             = atom(),
    -      error             = integer(),
    -      outbound_streams  = integer(),
    -      inbound_streams   = integer(),
    -      assoc_id          = assoc_id()
    -}

    The number of outbound and inbound streams for the association -can be set by giving an sctp_initmsg option to connect as in:

    connect(Socket, Ip, Port>,
    -      [{sctp_initmsg,#sctp_initmsg{num_ostreams=OutStreams,
    -                                   max_instreams=MaxInStreams}}])

    All options Opt are set on the socket before the association is attempted. +l

    #sctp_assoc_change{
    +      state             = atom(),
    +      error             = integer(),
    +      outbound_streams  = integer(),
    +      inbound_streams   = integer(),
    +      assoc_id          = assoc_id()
    +}

    The number of outbound and inbound streams for the association +can be set by giving an sctp_initmsg option to connect as in:

    connect(Socket, Ip, Port>,
    +      [{sctp_initmsg,#sctp_initmsg{num_ostreams=OutStreams,
    +                                   max_instreams=MaxInStreams}}])

    All options Opt are set on the socket before the association is attempted. If an option record has undefined field values, the options record is first read from the socket for those values. In effect, Opt option records only need to define field values to change @@ -1949,7 +1949,7 @@

    open/1

    and with reasonably large kernel and driver buffers.

    When the socket is in passive mode, data can be received through the recv/1,2 calls.

    When the socket is in active mode, -data received data is delivered to the controlling process as messages:

    {sctp, Socket, FromIP, FromPort, {AncData, Data}}

    See recv/1,2 for a description of the message fields.

    Note

    This message format unfortunately differs slightly from the +data received data is delivered to the controlling process as messages:

    {sctp, Socket, FromIP, FromPort, {AncData, Data}}

    See recv/1,2 for a description of the message fields.

    Note

    This message format unfortunately differs slightly from the gen_udp message format with ancillary data, and from the recv/1,2 return tuple format.

    @@ -2211,39 +2211,39 @@

    recv(Socket, Timeout)

    Possible SCTP events

    -
    • #sctp_sndrcvinfo{}

    • #sctp_assoc_change{}

    • #sctp_paddr_change{
      -      addr      = {ip_address(),port()},
      -      state     = atom(),
      -      error     = integer(),
      -      assoc_id  = assoc_id()
      -}

      Indicates change of the status of the IP address of the peer specified by +

      • #sctp_sndrcvinfo{}

      • #sctp_assoc_change{}

      • #sctp_paddr_change{
        +      addr      = {ip_address(),port()},
        +      state     = atom(),
        +      error     = integer(),
        +      assoc_id  = assoc_id()
        +}

        Indicates change of the status of the IP address of the peer specified by addr within association assoc_id. Possible values of state (mostly self-explanatory) include:

        • addr_unreachable

        • addr_available

        • addr_removed

        • addr_added

        • addr_made_prim

        • addr_confirmed

        In case of an error (for example, addr_unreachable), the field error provides more diagnostics. In such cases, event #sctp_paddr_change{} is automatically converted into an error term returned by recv. The error field value can be converted -into a string using error_string/1.

      • #sctp_send_failed{
        +into a string using error_string/1.

      • #sctp_send_failed{
               flags     = true | false,
        -      error     = integer(),
        -      info      = #sctp_sndrcvinfo{},
        -      assoc_id  = assoc_id()
        -      data      = binary()
        -}

        The sender can receive this event if a send operation fails.

        • flags - A Boolean specifying if the data has been transmitted + error = integer(), + info = #sctp_sndrcvinfo{}, + assoc_id = assoc_id() + data = binary() +}

    The sender can receive this event if a send operation fails.

    • flags - A Boolean specifying if the data has been transmitted over the wire.

    • error - Provides extended diagnostics, use error_string/1.

    • info - The original #sctp_sndrcvinfo{} record used in the failed send/*.

    • data - The whole original data chunk attempted to be sent.

    In the current implementation of the Erlang/SCTP binding, this event is -internally converted into an error term returned by recv/*.

  • #sctp_adaptation_event{
    -      adaptation_ind = integer(),
    -      assoc_id       = assoc_id()
    -}

    Delivered when a peer sends an adaptation layer indication parameter +internally converted into an error term returned by recv/*.

  • #sctp_adaptation_event{
    +      adaptation_ind = integer(),
    +      assoc_id       = assoc_id()
    +}

    Delivered when a peer sends an adaptation layer indication parameter (configured through option sctp_adaptation_layer). Notie that with the current implementation of the Erlang/SCTP binding, -this event is disabled by default.

  • #sctp_pdapi_event{
    +this event is disabled by default.

  • #sctp_pdapi_event{
           indication = sctp_partial_delivery_aborted,
    -      assoc_id   = assoc_id()
    -}

    A partial delivery failure. In the current implementation + assoc_id = assoc_id() +}

  • A partial delivery failure. In the current implementation of the Erlang/SCTP binding, this event is internally converted into an error term returned by recv/*.

    diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/gen_tcp.html b/prs/9045/lib/kernel-10.1.1/doc/html/gen_tcp.html index 45143a6dac65..dd3e60556946 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/gen_tcp.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/gen_tcp.html @@ -136,27 +136,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 @@ -195,48 +195,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).
    -
    -server(LS) ->
    -    case gen_tcp:accept(LS) of
    -        {ok,S} ->
    -            loop(S),
    -            server(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);
             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 @@ -246,32 +246,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 diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/gen_udp.html b/prs/9045/lib/kernel-10.1.1/doc/html/gen_udp.html index 89cea4a3fc95..ba3123df9996 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/gen_udp.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/gen_udp.html @@ -966,8 +966,8 @@

    open(Port, Opts)

    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 @@ -975,8 +975,8 @@

    open(Port, Opts)

    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, 8192}.

    diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/global_group.html b/prs/9045/lib/kernel-10.1.1/doc/html/global_group.html index 375481979e84..198beafdae76 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/global_group.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/global_group.html @@ -138,7 +138,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 diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/inet.html b/prs/9045/lib/kernel-10.1.1/doc/html/inet.html index eadc8564c5f4..62f05231c765 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/inet.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/inet.html @@ -157,19 +157,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}}

      + {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}}

    @@ -971,7 +971,7 @@

    hostent()

    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").
    @@ -2138,8 +2138,8 @@

    getopts(Socket, Options)

    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}]),
    +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.

    @@ -2491,7 +2491,7 @@

    monitor(Socket)

    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 diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/inet_res.html b/prs/9045/lib/kernel-10.1.1/doc/html/inet_res.html index 33acd3d24b83..80d42457addd 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/inet_res.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/inet_res.html @@ -185,15 +185,15 @@

      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.
    @@ -600,57 +600,57 @@

    dns_msg()

    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.

    diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/kernel.epub b/prs/9045/lib/kernel-10.1.1/doc/html/kernel.epub index 00ed8e7251c1..e061137252c5 100644 Binary files a/prs/9045/lib/kernel-10.1.1/doc/html/kernel.epub and b/prs/9045/lib/kernel-10.1.1/doc/html/kernel.epub differ diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/logger.html b/prs/9045/lib/kernel-10.1.1/doc/html/logger.html index b38f510ded9c..03ccd7afc43b 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/logger.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/logger.html @@ -136,18 +136,18 @@

    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:

    Equivalent to log(Level, FormatOrFun, Args, #{}) if called as log(Level, FormatOrFun, Args).

    @@ -2437,12 +2437,12 @@

    log(Level, FunOrFormat, Args, Metadata)

    %% 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.

    @@ -2765,26 +2765,26 @@

    add_handlers/1

    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, #{}}]}]}].
    @@ -3739,8 +3739,8 @@

    update_formatter_config(HandlerId, Formatte -

    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}).

    @@ -3803,8 +3803,8 @@

    update_handler_config(HandlerId, Config)

    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 .

    @@ -3897,8 +3897,8 @@

    update_primary_config(Config)

    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 .

    @@ -3930,7 +3930,7 @@

    update_process_metadata(Meta)

    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 .

    @@ -3962,8 +3962,8 @@

    update_proxy_config(Config)

    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.

    diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/logger_chapter.html b/prs/9045/lib/kernel-10.1.1/doc/html/logger_chapter.html index e9cb16bf1eb0..2ffdad0d8da7 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/logger_chapter.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/logger_chapter.html @@ -196,7 +196,7 @@

    The API for logging consists of a set of macros, and a set of functions on 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.

    @@ -218,23 +218,23 @@

    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.

    @@ -422,14 +422,14 @@

    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)
    +

    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)
    +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})
    +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 +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 @@ -452,31 +452,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"}}}
    -    ]}]}].

    +"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"}}}
    +    ]}]}].

    @@ -518,9 +518,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.

  • @@ -546,19 +546,19 @@

    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).
    +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.

    @@ -583,48 +583,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}) ->
    -    {ok, Fd} = file:open(File, [append, {encoding, utf8}]),
    -    {ok, #{file => File, fd => Fd}}.
    +init(#{file := File}) ->
    +    {ok, Fd} = file:open(File, [append, {encoding, utf8}]),
    +    {ok, #{file => File, fd => Fd}}.
     
    -handle_call(_, _, State) ->
    -    {reply, {error, bad_request}, State}.
    +handle_call(_, _, State) ->
    +    {reply, {error, bad_request}, State}.
     
    -handle_cast({log, LogEvent, Config}, #{fd := Fd} = State) ->
    -    do_log(Fd, LogEvent, Config),
    -    {noreply, State}.
    +handle_cast({log, LogEvent, Config}, #{fd := Fd} = State) ->
    +    do_log(Fd, LogEvent, Config),
    +    {noreply, State}.
     
    -terminate(_Reason, #{fd := Fd}) ->
    -    _ = file:close(Fd),
    +terminate(_Reason, #{fd := Fd}) ->
    +    _ = file:close(Fd),
         ok.
     
    -do_log(Fd, LogEvent, #{formatter := {FModule, FConfig}}) ->
    -    String = FModule:format(LogEvent, FConfig),
    -    io:put_chars(Fd, String).

    +do_log(Fd, LogEvent, #{formatter := {FModule, FConfig}}) -> + String = FModule:format(LogEvent, FConfig), + io:put_chars(Fd, String).

    @@ -700,11 +700,11 @@

    performance reasons, the client processes must never be blocked by synchronous log requests. It is possible, perhaps, that dropping or flushing events is still acceptable, since it does not affect the performance of the client processes -sending the log events.

    A configuration example:

    logger:add_handler(my_standard_h, logger_std_h,
    -                   #{config => #{file => "./system_info.log",
    +sending the log events.

    A configuration example:

    logger:add_handler(my_standard_h, logger_std_h,
    +                   #{config => #{file => "./system_info.log",
                                      sync_mode_qlen => 100,
                                      drop_mode_qlen => 1000,
    -                                 flush_qlen => 2000}}).

    + flush_qlen => 2000}}).

    @@ -720,11 +720,11 @@

    disables it.

    Defaults to true.

  • burst_limit_max_count - This is the maximum number of events to handle within a burst_limit_window_time time frame. After the limit is reached, successive events are dropped until the end of the time frame.

    Defaults to 500 events.

  • burst_limit_window_time - See the previous description of -burst_limit_max_count.

    Defaults to 1000 milliseconds.

  • A configuration example:

    logger:add_handler(my_disk_log_h, logger_disk_log_h,
    -                   #{config => #{file => "./my_disk_log",
    +burst_limit_max_count.

    Defaults to 1000 milliseconds.

    A configuration example:

    logger:add_handler(my_disk_log_h, logger_disk_log_h,
    +                   #{config => #{file => "./my_disk_log",
                                      burst_limit_enable => true,
                                      burst_limit_max_count => 20,
    -                                 burst_limit_window_time => 500}}).

    + burst_limit_window_time => 500}}).

    @@ -760,11 +760,11 @@

    forwards the event to the proxy on the remote node.

    When receiving a log event, either from the emulator or from a remote node, the proxy calls the Logger API to log the event.

    The proxy process is overload protected in the same way as described in section Protecting the Handler from Overload, -but with the following default values:

        #{sync_mode_qlen => 500,
    +but with the following default values:

        #{sync_mode_qlen => 500,
           drop_mode_qlen => 1000,
           flush_qlen => 5000,
           burst_limit_enable => false,
    -      overload_kill_enable => false}

    For log events from the emulator, synchronous message passing mode is not + overload_kill_enable => false}

    For log events from the emulator, synchronous message passing mode is not applicable, since all messages are passed asynchronously by the emulator. Drop mode is achieved by setting the system_logger to undefined, forcing the emulator to drop events until it is set back to the proxy pid again.

    The proxy uses erlang:send_nosuspend/2 when sending log events to a remote diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/logger_cookbook.html b/prs/9045/lib/kernel-10.1.1/doc/html/logger_cookbook.html index 1a1af3a21896..25c69dfb6130 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/logger_cookbook.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/logger_cookbook.html @@ -150,19 +150,19 @@

    -
    1> logger:i(primary).
    +
    1> logger:i(primary).
     Primary configuration:
         Level: notice
         Filter Default: log
         Filters:
    -        (none)

    It is also possible to fetch the configuration using + (none)

    It is also possible to fetch the configuration using logger:get_primary_config().

    See also

    -
    2> logger:i(handlers).
    +
    2> logger:i(handlers).
     Handler configuration:
         Id: default
             Module: logger_std_h
    @@ -179,10 +179,10 @@ 

    @@ -239,17 +239,17 @@

    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

    @@ -257,14 +257,14 @@

    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 @@ -281,18 +281,18 @@

    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

    @@ -302,24 +302,24 @@

    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 @@ -327,13 +327,13 @@

    See also

    @@ -349,7 +349,7 @@

    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
    @@ -361,14 +361,14 @@ 

    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)
    @@ -389,22 +389,22 @@ 

    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
    -logger:notice("Notice should be logged"),
    -logger:debug("Should not be logged"),
    +logger:notice("Notice should be logged"),
    +logger:debug("Should not be logged"),
     
     %% Add the filter to allow PidToLog to send debug events
    -PidToLog = self(),
    -PidFilter = fun(LogEvent, _) when PidToLog =:= self() -> LogEvent;
    -               (_LogEvent, _) -> ignore end,
    -ok = logger:add_primary_filter(pid, {PidFilter,[]}),
    -logger:debug("Debug should be logged").

    There is a bit of setup needed to allow filters to decide whether a specific +PidToLog = self(), +PidFilter = fun(LogEvent, _) when PidToLog =:= self() -> LogEvent; + (_LogEvent, _) -> ignore end, +ok = logger:add_primary_filter(pid, {PidFilter,[]}), +logger:debug("Debug should be logged").

    There is a bit of setup needed to allow filters to decide whether a specific process should be allowed to log. This is because the default primary log level is notice and it is enforced before the primary filters. So in order for the pid filter to be useful we have to raise the primary log level to all and then add @@ -421,11 +421,11 @@

    Domains are used to specify which subsystem a certain log event originates from. The default handler will by default only log events with the domain [otp] or without a domain. If you would like to include SSL log events into the default -handler log you could do this:

    1> logger:add_handler_filter(default,ssl_domain,
    -  {fun logger_filters:domain/2,{log,sub,[otp,ssl]}}).
    -2> application:ensure_all_started(ssl).
    -{ok,[crypto,asn1,public_key,ssl]}
    -3> ssl:connect("www.erlang.org",443,[{log_level,debug}]).
    +handler log you could do this:

    1> logger:add_handler_filter(default,ssl_domain,
    +  {fun logger_filters:domain/2,{log,sub,[otp,ssl]}}).
    +2> application:ensure_all_started(ssl).
    +{ok,[crypto,asn1,public_key,ssl]}
    +3> ssl:connect("www.erlang.org",443,[{log_level,debug}]).
     %% lots of text

    See also

    diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/logger_disk_log_h.html b/prs/9045/lib/kernel-10.1.1/doc/html/logger_disk_log_h.html index 663fc340b2f7..e0c559db35a7 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/logger_disk_log_h.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/logger_disk_log_h.html @@ -170,12 +170,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"}}}]'

    diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/logger_filters.html b/prs/9045/lib/kernel-10.1.1/doc/html/logger_filters.html index 6465d98ca5be..c8a8974a73dd 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/logger_filters.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/logger_filters.html @@ -257,8 +257,8 @@

    domain(LogEvent, Extra)

    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 @@ -273,11 +273,11 @@

    domain(LogEvent, Extra)

    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
    @@ -322,9 +322,9 @@

    level(LogEvent, Extra)

    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
    diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/logger_std_h.html b/prs/9045/lib/kernel-10.1.1/doc/html/logger_std_h.html index 98d56141d34e..116c5812c94e 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/logger_std_h.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/logger_std_h.html @@ -191,9 +191,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 diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/net.html b/prs/9045/lib/kernel-10.1.1/doc/html/net.html index 3cb136ff433c..afea85aeae5e 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/net.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/net.html @@ -571,13 +571,13 @@

    ifaddrs_filter_fun()

    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).
    diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/net_adm.html b/prs/9045/lib/kernel-10.1.1/doc/html/net_adm.html index 08fccda28ddc..57c250c677f3 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/net_adm.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/net_adm.html @@ -497,8 +497,8 @@

    names(Host)

    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}]}
    diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/net_kernel.html b/prs/9045/lib/kernel-10.1.1/doc/html/net_kernel.html index 7a4dfe4cd0fd..1cea5f772975 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/net_kernel.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/net_kernel.html @@ -138,9 +138,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 @@ -720,13 +720,13 @@

    monitor_nodes(Flag, Options)

    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 @@ -760,23 +760,23 @@

      monitor_nodes(Flag, Options)

      {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>
    diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/notes.html b/prs/9045/lib/kernel-10.1.1/doc/html/notes.html index 680c5cf72fbe..59af1b0c8486 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/notes.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/notes.html @@ -3968,12 +3968,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:
    diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/os.html b/prs/9045/lib/kernel-10.1.1/doc/html/os.html
    index 483947ab0666..c6594b084aad 100644
    --- a/prs/9045/lib/kernel-10.1.1/doc/html/os.html
    +++ b/prs/9045/lib/kernel-10.1.1/doc/html/os.html
    @@ -664,13 +664,13 @@ 

    cmd(Command, Options)

    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.

    The command shell can be set using the kernel configuration parameter, by default the -shell is detected upon system startup.

    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 +shell is detected upon system startup.

    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 call. This option is a safety feature that should be used when the command executed -can return a very large, possibly infinite, result.

      > 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]
    +can return a very large, possibly infinite, result.

    > 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]

    @@ -960,7 +960,7 @@

    perf_counter(Unit)

    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
    @@ -1131,16 +1131,16 @@

    timestamp()

    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.

    diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/pg.html b/prs/9045/lib/kernel-10.1.1/doc/html/pg.html index ff1d6b0e3d40..eaf0c07e5b43 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/pg.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/pg.html @@ -876,7 +876,7 @@

    monitor_scope(Scope)

    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]}
    diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/rpc.html b/prs/9045/lib/kernel-10.1.1/doc/html/rpc.html index 0c8c5eb39489..b67f1bd1a8f0 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/rpc.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/rpc.html @@ -1085,10 +1085,10 @@

    multicall(Nodes, Module, Function, Args, Ti 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 diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/search.html b/prs/9045/lib/kernel-10.1.1/doc/html/search.html index 4f69b798706f..efd7d5e48228 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/search.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/search.html @@ -128,7 +128,7 @@

    - +

    diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/seq_trace.html b/prs/9045/lib/kernel-10.1.1/doc/html/seq_trace.html index 326f2204164b..864c0dc85278 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/seq_trace.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/seq_trace.html @@ -147,9 +147,9 @@

    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 @@ -293,68 +293,68 @@

        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().
        -
        -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}.
        +
        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}.

    @@ -943,11 +943,11 @@

    set_token(Token)

    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.

    diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/socket.html b/prs/9045/lib/kernel-10.1.1/doc/html/socket.html index f498a88501a4..b78c55560171 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/socket.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/socket.html @@ -178,8 +178,8 @@

    completion_info/0 and the received completion message.

    The compiler may then optimize a following receive statement to only scan the messages that arrive after the reference/0 is created. If the message queue is large this is a big optimization.

    The reference/0 has to be unique for the call.

    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 call in progress:

        {select, {select_info, Handle}} = socket:accept(LSock, nowait),
    -    {error, timeout} = socket:accept(LSock, 500),
    +message has been received it replaces the call in progress:

        {select, {select_info, Handle}} = socket:accept(LSock, nowait),
    +    {error, timeout} = socket:accept(LSock, 500),
         :

    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 {error, timeout}, @@ -212,28 +212,28 @@

    Examples

    -
    client(SAddr, SPort) ->
    -   {ok, Sock} = socket:open(inet, stream, tcp),
    -   ok = socket:connect(Sock, #{family => inet,
    +
    client(SAddr, SPort) ->
    +   {ok, Sock} = socket:open(inet, stream, tcp),
    +   ok = socket:connect(Sock, #{family => inet,
                                    addr   => SAddr,
    -                               port   => SPort}),
    +                               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,
    +   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).
    @@ -4857,7 +4857,7 @@

    ioctl/2

    (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),
           :
    @@ -5021,7 +5021,7 @@

    is_supported(Key1)

    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),
    @@ -5052,7 +5052,7 @@

    is_supported(Key1, Key2)

    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),
    @@ -5149,7 +5149,7 @@

    monitor(Socket)

    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.

    diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/socket_usage.html b/prs/9045/lib/kernel-10.1.1/doc/html/socket_usage.html index e98be2129ecb..db3baf3a3df1 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/socket_usage.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/socket_usage.html @@ -192,47 +192,47 @@

    Example

    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) ->
    +client(ServerPort, Msg)
    +  when is_integer(ServerPort) andalso (ServerPort > 0) ->
         Family   = inet, % Default
    -    Addr     = get_local_addr(Family), % Pick an address
    -    SockAddr = #{family => Family,
    +    Addr     = get_local_addr(Family), % Pick an address
    +    SockAddr = #{family => Family,
     		 addr   => Addr,
    -		 port   => ServerPort},
    -    client(SockAddr, Msg).
    -
    -client(ServerPort, ServerAddr, Msg)
    -  when is_integer(ServerPort) andalso (ServerPort > 0) andalso
    -       is_tuple(ServerAddr) ->
    -    Family   = which_family(ServerAddr),
    -    SockAddr = #{family => Family,
    +		 port   => ServerPort},
    +    client(SockAddr, Msg).
    +
    +client(ServerPort, ServerAddr, Msg)
    +  when is_integer(ServerPort) andalso (ServerPort > 0) andalso
    +       is_tuple(ServerAddr) ->
    +    Family   = which_family(ServerAddr),
    +    SockAddr = #{family => Family,
     		 addr   => ServerAddr,
    -		 port   => ServerPort},
    -    client(SockAddr, Msg).
    +		 port   => ServerPort},
    +    client(SockAddr, Msg).
     
     %% Send the message to the (echo) server and wait for the echo to come back.
    -client_exchange(Sock, Msg) when is_list(Msg) ->
    -    client_exchange(Sock, list_to_binary(Msg));
    -client_exchange(Sock, Msg) when is_binary(Msg) ->
    -    ok = socket:send(Sock, Msg, infinity),
    -    {ok, Msg} = socket:recv(Sock, byte_size(Msg), infinity),
    +client_exchange(Sock, Msg) when is_list(Msg) ->
    +    client_exchange(Sock, list_to_binary(Msg));
    +client_exchange(Sock, Msg) when is_binary(Msg) ->
    +    ok = socket:send(Sock, Msg, infinity),
    +    {ok, Msg} = socket:recv(Sock, byte_size(Msg), infinity),
         ok.
     
     
    @@ -240,188 +240,188 @@ 

    %% === Server === -server() -> +server() -> %% Make system choose port (and address) - server(0). + server(0). %% This function return the port and address that it actually uses, %% in case server/0 or server/1 (with a port number) was used to start it. -server(#{family := Family, addr := Addr, port := _} = SockAddr) -> - {ok, Sock} = socket:open(Family, stream, tcp), - ok = socket:bind(Sock, SockAddr), - ok = socket:listen(Sock), - {ok, #{port := Port}} = socket:sockname(Sock), - Acceptor = start_acceptor(Sock), - {ok, {Port, Addr, Acceptor}}; +server(#{family := Family, addr := Addr, port := _} = SockAddr) -> + {ok, Sock} = socket:open(Family, stream, tcp), + ok = socket:bind(Sock, SockAddr), + ok = socket:listen(Sock), + {ok, #{port := Port}} = socket:sockname(Sock), + Acceptor = start_acceptor(Sock), + {ok, {Port, Addr, Acceptor}}; -server(Port) when is_integer(Port) -> +server(Port) when is_integer(Port) -> Family = inet, % Default - Addr = get_local_addr(Family), % Pick an address - SockAddr = #{family => Family, + Addr = get_local_addr(Family), % Pick an address + SockAddr = #{family => Family, addr => Addr, - port => Port}, - server(SockAddr). - -server(Port, Addr) - when is_integer(Port) andalso (Port >= 0) andalso - is_tuple(Addr) -> - Family = which_family(Addr), - SockAddr = #{family => Family, + port => Port}, + server(SockAddr). + +server(Port, Addr) + when is_integer(Port) andalso (Port >= 0) andalso + is_tuple(Addr) -> + Family = which_family(Addr), + SockAddr = #{family => Family, addr => Addr, - port => Port}, - server(SockAddr). + port => Port}, + server(SockAddr). %% --- Echo Server - Acceptor --- -start_acceptor(LSock) -> - Self = self(), - {Pid, MRef} = spawn_monitor(fun() -> acceptor_init(Self, LSock) end), +start_acceptor(LSock) -> + Self = self(), + {Pid, MRef} = spawn_monitor(fun() -> acceptor_init(Self, LSock) end), receive - {'DOWN', MRef, process, Pid, Info} -> - erlang:error({failed_starting_acceptor, Info}); - {Pid, started} -> + {'DOWN', MRef, process, Pid, Info} -> + erlang:error({failed_starting_acceptor, Info}); + {Pid, started} -> %% Transfer ownership - socket:setopt(LSock, otp, owner, Pid), - Pid ! {self(), continue}, - erlang:demonitor(MRef), + socket:setopt(LSock, otp, owner, Pid), + Pid ! {self(), continue}, + erlang:demonitor(MRef), Pid end. -acceptor_init(Parent, LSock) -> - Parent ! {self(), started}, +acceptor_init(Parent, LSock) -> + Parent ! {self(), started}, receive - {Parent, continue} -> + {Parent, continue} -> ok end, - acceptor_loop(LSock). - -acceptor_loop(LSock) -> - case socket:accept(LSock, infinity) of - {ok, ASock} -> - start_handler(ASock), - acceptor_loop(LSock); - {error, Reason} -> - erlang:error({accept_failed, Reason}) + acceptor_loop(LSock). + +acceptor_loop(LSock) -> + case socket:accept(LSock, infinity) of + {ok, ASock} -> + start_handler(ASock), + acceptor_loop(LSock); + {error, Reason} -> + erlang:error({accept_failed, Reason}) end. %% --- Echo Server - Handler --- -start_handler(Sock) -> - Self = self(), - {Pid, MRef} = spawn_monitor(fun() -> handler_init(Self, Sock) end), +start_handler(Sock) -> + Self = self(), + {Pid, MRef} = spawn_monitor(fun() -> handler_init(Self, Sock) end), receive - {'DOWN', MRef, process, Pid, Info} -> - erlang:error({failed_starting_handler, Info}); - {Pid, started} -> + {'DOWN', MRef, process, Pid, Info} -> + erlang:error({failed_starting_handler, Info}); + {Pid, started} -> %% Transfer ownership - socket:setopt(Sock, otp, owner, Pid), - Pid ! {self(), continue}, - erlang:demonitor(MRef), + socket:setopt(Sock, otp, owner, Pid), + Pid ! {self(), continue}, + erlang:demonitor(MRef), Pid end. -handler_init(Parent, Sock) -> - Parent ! {self(), started}, +handler_init(Parent, Sock) -> + Parent ! {self(), started}, receive - {Parent, continue} -> + {Parent, continue} -> ok end, - handler_loop(Sock, undefined). + handler_loop(Sock, undefined). %% No "ongoing" reads %% The use of 'nowait' here is clearly *overkill* for this use case, %% but is intended as an example of how to use it. -handler_loop(Sock, undefined) -> - case socket:recv(Sock, 0, nowait) of - {ok, Data} -> - echo(Sock, Data), - handler_loop(Sock, undefined); +handler_loop(Sock, undefined) -> + case socket:recv(Sock, 0, nowait) of + {ok, Data} -> + echo(Sock, Data), + handler_loop(Sock, undefined); - {select, SelectInfo} -> - handler_loop(Sock, SelectInfo); + {select, SelectInfo} -> + handler_loop(Sock, SelectInfo); - {completion, CompletionInfo} -> - handler_loop(Sock, CompletionInfo); + {completion, CompletionInfo} -> + handler_loop(Sock, CompletionInfo); - {error, Reason} -> - erlang:error({recv_failed, Reason}) + {error, Reason} -> + erlang:error({recv_failed, Reason}) end; %% This is the standard (asyncronous) behaviour. -handler_loop(Sock, {select_info, recv, SelectHandle}) -> +handler_loop(Sock, {select_info, recv, SelectHandle}) -> receive - {'$socket', Sock, select, SelectHandle} -> - case socket:recv(Sock, 0, nowait) of - {ok, Data} -> - echo(Sock, Data), - handler_loop(Sock, undefined); + {'$socket', Sock, select, SelectHandle} -> + case socket:recv(Sock, 0, nowait) of + {ok, Data} -> + echo(Sock, Data), + handler_loop(Sock, undefined); - {select, NewSelectInfo} -> - handler_loop(Sock, NewSelectInfo); + {select, NewSelectInfo} -> + handler_loop(Sock, NewSelectInfo); - {error, Reason} -> - erlang:error({recv_failed, Reason}) + {error, Reason} -> + erlang:error({recv_failed, Reason}) end end; %% This is the (asyncronous) behaviour on platforms that support 'completion', %% currently only Windows. -handler_loop(Sock, {completion_info, recv, CompletionHandle}) -> +handler_loop(Sock, {completion_info, recv, CompletionHandle}) -> receive - {'$socket', Sock, completion, {CompletionHandle, CompletionStatus}} -> + {'$socket', Sock, completion, {CompletionHandle, CompletionStatus}} -> case CompletionStatus of - {ok, Data} -> - echo(Sock, Data), - handler_loop(Sock, undefined); - {error, Reason} -> - erlang:error({recv_failed, Reason}) + {ok, Data} -> + echo(Sock, Data), + handler_loop(Sock, undefined); + {error, Reason} -> + erlang:error({recv_failed, Reason}) end end. -echo(Sock, Data) when is_binary(Data) -> - ok = socket:send(Sock, Data, infinity), - io:format("** ECHO **" - "~n~s~n", [binary_to_list(Data)]). +echo(Sock, Data) when is_binary(Data) -> + ok = socket:send(Sock, Data, infinity), + io:format("** ECHO **" + "~n~s~n", [binary_to_list(Data)]). %% ====================================================================== %% === Utility functions === -maybe_bind(Sock, Family) -> - maybe_bind(Sock, Family, os:type()). +maybe_bind(Sock, Family) -> + maybe_bind(Sock, Family, os:type()). -maybe_bind(Sock, Family, {win32, _}) -> - Addr = get_local_addr(Family), - SockAddr = #{family => Family, +maybe_bind(Sock, Family, {win32, _}) -> + Addr = get_local_addr(Family), + SockAddr = #{family => Family, addr => Addr, - port => 0}, - socket:bind(Sock, SockAddr); -maybe_bind(_Sock, _Family, _OS) -> + port => 0}, + socket:bind(Sock, SockAddr); +maybe_bind(_Sock, _Family, _OS) -> ok. %% The idea with this is extract a "usable" local address %% that can be used even from *another* host. And doing %% so using the net module. -get_local_addr(Family) -> +get_local_addr(Family) -> Filter = - fun(#{addr := #{family := Fam}, - flags := Flags}) -> - (Fam =:= Family) andalso (not lists:member(loopback, Flags)); - (_) -> + fun(#{addr := #{family := Fam}, + flags := Flags}) -> + (Fam =:= Family) andalso (not lists:member(loopback, Flags)); + (_) -> false end, - {ok, [SockAddr|_]} = net:getifaddrs(Filter), - #{addr := #{addr := Addr}} = SockAddr, + {ok, [SockAddr|_]} = net:getifaddrs(Filter), + #{addr := #{addr := Addr}} = SockAddr, Addr. -which_family(Addr) when is_tuple(Addr) andalso (tuple_size(Addr) =:= 4) -> +which_family(Addr) when is_tuple(Addr) andalso (tuple_size(Addr) =:= 4) -> inet; -which_family(Addr) when is_tuple(Addr) andalso (tuple_size(Addr) =:= 8) -> +which_family(Addr) when is_tuple(Addr) andalso (tuple_size(Addr) =:= 8) -> inet6.

    diff --git a/prs/9045/lib/kernel-10.1.1/doc/html/trace.html b/prs/9045/lib/kernel-10.1.1/doc/html/trace.html index 612a84bf574e..00cb797563dd 100644 --- a/prs/9045/lib/kernel-10.1.1/doc/html/trace.html +++ b/prs/9045/lib/kernel-10.1.1/doc/html/trace.html @@ -152,23 +152,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

    @@ -1464,9 +1464,9 @@

    recv(Session, MatchSpec, FlagList)

    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 @@ -1517,10 +1517,10 @@

      send(Session, MatchSpec, FlagList)

      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 diff --git a/prs/9045/lib/megaco-4.6/doc/html/megaco.epub b/prs/9045/lib/megaco-4.6/doc/html/megaco.epub index 771450f21b0a..8274cc700f6f 100644 Binary files a/prs/9045/lib/megaco-4.6/doc/html/megaco.epub and b/prs/9045/lib/megaco-4.6/doc/html/megaco.epub differ diff --git a/prs/9045/lib/megaco-4.6/doc/html/megaco.html b/prs/9045/lib/megaco-4.6/doc/html/megaco.html index 2209d9917536..c125958b2048 100644 --- a/prs/9045/lib/megaco-4.6/doc/html/megaco.html +++ b/prs/9045/lib/megaco-4.6/doc/html/megaco.html @@ -3200,7 +3200,7 @@

      print_version_info(Versions)

      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).
      diff --git a/prs/9045/lib/megaco-4.6/doc/html/megaco_debug.html b/prs/9045/lib/megaco-4.6/doc/html/megaco_debug.html index 4457b7b30bc1..ae76de45f3c3 100644 --- a/prs/9045/lib/megaco-4.6/doc/html/megaco_debug.html +++ b/prs/9045/lib/megaco-4.6/doc/html/megaco_debug.html @@ -178,12 +178,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 @@ -205,10 +205,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 diff --git a/prs/9045/lib/megaco-4.6/doc/html/megaco_encode.html b/prs/9045/lib/megaco-4.6/doc/html/megaco_encode.html index 77d4f052eca8..4673b1d03719 100644 --- a/prs/9045/lib/megaco-4.6/doc/html/megaco_encode.html +++ b/prs/9045/lib/megaco-4.6/doc/html/megaco_encode.html @@ -164,75 +164,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 diff --git a/prs/9045/lib/megaco-4.6/doc/html/megaco_examples.html b/prs/9045/lib/megaco-4.6/doc/html/megaco_examples.html index fe67f5641c75..db2e8821dc9d 100644 --- a/prs/9045/lib/megaco-4.6/doc/html/megaco_examples.html +++ b/prs/9045/lib/megaco-4.6/doc/html/megaco_examples.html @@ -165,10 +165,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 diff --git a/prs/9045/lib/megaco-4.6/doc/html/megaco_performance.html b/prs/9045/lib/megaco-4.6/doc/html/megaco_performance.html index 75c57c99e659..c6a587f1b0ef 100644 --- a/prs/9045/lib/megaco-4.6/doc/html/megaco_performance.html +++ b/prs/9045/lib/megaco-4.6/doc/html/megaco_performance.html @@ -168,19 +168,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"}}}}

    diff --git a/prs/9045/lib/megaco-4.6/doc/html/megaco_user.html b/prs/9045/lib/megaco-4.6/doc/html/megaco_user.html index d01f3594781b..abb688b11b0e 100644 --- a/prs/9045/lib/megaco-4.6/doc/html/megaco_user.html +++ b/prs/9045/lib/megaco-4.6/doc/html/megaco_user.html @@ -137,9 +137,9 @@

    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 @@ -150,10 +150,10 @@

    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" +

    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 diff --git a/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia.epub b/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia.epub index fdc95128537a..aec962796b96 100644 Binary files a/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia.epub and b/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia.epub differ diff --git a/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia.html b/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia.html index 06a641f7bf5f..59eef480571d 100644 --- a/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia.html +++ b/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia.html @@ -172,11 +172,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, @@ -2871,7 +2871,7 @@

    change_table_copy_type(Tab, Node, To)

    -

    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 @@ -3122,22 +3122,22 @@

    create_table(Name, Opts)

    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}]} ]}])
  • {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}]} ]}])
  • {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 overwritten.

    Notice that currently ordered_set is not supported for disc_only_copies.

  • {local_content, Bool}, where Bool is true or false. Default is false.

  • 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 @@ -5387,10 +5387,10 @@

    select(Tab, Spec, LockKind)

    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]}]),
    @@ -5685,9 +5685,9 @@

    snmp_open_table(Tab, Snmp)

    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 @@ -6290,17 +6290,17 @@

    transaction(Fun, Args, Retries)

    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 @@ -6308,17 +6308,17 @@

    transaction(Fun, Args, Retries)

    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 diff --git a/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_app_a.html b/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_app_a.html index 3fccce164280..40e68ab1f707 100644 --- a/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_app_a.html +++ b/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_app_a.html @@ -165,11 +165,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, @@ -180,105 +180,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. @@ -287,30 +287,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} + {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} end. %% Closes the backup media after restore %% %% Returns {ok, ReturnValueToUser} or {error, Reason} -close_read(OpaqueData) -> +close_read(OpaqueData) -> R = OpaqueData, - case disk_log:close(R#restore.file_desc) of - ok -> {ok, R#restore.file}; - {error, Reason} -> {error, Reason} + case disk_log:close(R#restore.file_desc) of + ok -> {ok, R#restore.file}; + {error, Reason} -> {error, Reason} end.

    diff --git a/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_app_b.html b/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_app_b.html index 4e2511421ff4..d84d78ff1761 100644 --- a/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_app_b.html +++ b/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_app_b.html @@ -137,10 +137,10 @@

    mnesia_access Callback Behavior

    -
    -module(mnesia_frag).
    +
    -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,
    @@ -149,230 +149,230 @@ 

    foldl/6, foldr/6, table_info/4, first/3, next/4, prev/4, last/3, clear_table/4 - ]).

    %% Callback functions which provides transparent
    +       ]).
    %% 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).
    +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(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).
    +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).
    +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).
    +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, LockKind) ->
    +    do_select(ActivityId, Opaque, Tab, MatchSpec, LockKind).
     
     
    -select(ActivityId, Opaque, Tab, MatchSpec, Limit, LockKind) ->
    -    init_select(ActivityId, Opaque, Tab, MatchSpec, Limit, LockKind).
    +select(ActivityId, Opaque, Tab, MatchSpec, Limit, LockKind) ->
    +    init_select(ActivityId, Opaque, Tab, MatchSpec, Limit, LockKind).
     
     
    -all_keys(ActivityId, Opaque, Tab, LockKind) ->
    -    Match = [mnesia:all_keys(ActivityId, Opaque, Frag, LockKind)
    -	     || Frag <- frag_names(Tab)],
    -    lists:append(Match).
    +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).
    +	[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)
    +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 ->
    -	    SumFun = fun({_, Size}, Acc) -> Acc + Size end,
    -	    lists:foldl(SumFun, 0, frag_memory(ActivityId, Opaque, Tab));
    +	    SumFun = fun({_, Size}, Acc) -> Acc + Size end,
    +	    lists:foldl(SumFun, 0, frag_memory(ActivityId, Opaque, Tab));
     	base_table ->
    -	    lookup_prop(Tab, base_table);
    +	    lookup_prop(Tab, base_table);
     	node_pool ->
    -	    lookup_prop(Tab, node_pool);
    +	    lookup_prop(Tab, node_pool);
     	n_fragments ->
    -	    FH = lookup_frag_hash(Tab),
    +	    FH = lookup_frag_hash(Tab),
     	    FH#frag_state.n_fragments;
     	foreign_key ->
    -	    FH = lookup_frag_hash(Tab),
    +	    FH = lookup_frag_hash(Tab),
     	    FH#frag_state.foreign_key;
     	foreigners ->
    -	    lookup_foreigners(Tab);
    +	    lookup_foreigners(Tab);
     	n_ram_copies ->
    -	    length(val({Tab, ram_copies}));
    +	    length(val({Tab, ram_copies}));
     	n_disc_copies ->
    -	    length(val({Tab, disc_copies}));
    +	    length(val({Tab, disc_copies}));
     	n_disc_only_copies ->
    -	    length(val({Tab, disc_only_copies}));
    +	    length(val({Tab, disc_only_copies}));
     	n_external_copies ->
    -	    length(val({Tab, external_copies}));
    +	    length(val({Tab, external_copies}));
     
     	frag_names ->
    -	    frag_names(Tab);
    +	    frag_names(Tab);
     	frag_dist ->
    -	    frag_dist(Tab);
    +	    frag_dist(Tab);
     	frag_size ->
    -	    frag_size(ActivityId, Opaque, Tab);
    +	    frag_size(ActivityId, Opaque, Tab);
     	frag_memory ->
    -	    frag_memory(ActivityId, Opaque, Tab);
    +	    frag_memory(ActivityId, Opaque, Tab);
     	_ ->
    -	    mnesia:table_info(ActivityId, Opaque, Frag, Item)
    +	    mnesia:table_info(ActivityId, Opaque, Frag, Item)
         end.
     
    -first(ActivityId, Opaque, Tab) ->
    -    case ?catch_val({Tab, frag_hash}) of
    -	{'EXIT', _} ->
    -	    mnesia:first(ActivityId, Opaque, Tab);
    +first(ActivityId, Opaque, Tab) ->
    +    case ?catch_val({Tab, frag_hash}) of
    +	{'EXIT', _} ->
    +	    mnesia:first(ActivityId, Opaque, Tab);
     	FH ->
     	    FirstFrag = Tab,
    -	    case mnesia:first(ActivityId, Opaque, FirstFrag) of
    +	    case mnesia:first(ActivityId, Opaque, FirstFrag) of
     		'$end_of_table' ->
    -		    search_first(ActivityId, Opaque, Tab, 1, FH);
    +		    search_first(ActivityId, Opaque, Tab, 1, FH);
     		Next ->
     		    Next
     	    end
         end.
     
    -search_first(ActivityId, Opaque, Tab, N, FH) when N < FH#frag_state.n_fragments ->
    +search_first(ActivityId, Opaque, Tab, N, FH) when N < FH#frag_state.n_fragments ->
         NextN = N + 1,
    -    NextFrag = n_to_frag_name(Tab, NextN),
    -    case mnesia:first(ActivityId, Opaque, NextFrag) of
    +    NextFrag = n_to_frag_name(Tab, NextN),
    +    case mnesia:first(ActivityId, Opaque, NextFrag) of
     	'$end_of_table' ->
    -	    search_first(ActivityId, Opaque, Tab, NextN, FH);
    +	    search_first(ActivityId, Opaque, Tab, NextN, FH);
     	Next ->
     	    Next
         end;
    -search_first(_ActivityId, _Opaque, _Tab, _N, _FH) ->
    +search_first(_ActivityId, _Opaque, _Tab, _N, _FH) ->
         '$end_of_table'.
     
    -last(ActivityId, Opaque, Tab) ->
    -    case ?catch_val({Tab, frag_hash}) of
    -	{'EXIT', _} ->
    -	    mnesia:last(ActivityId, Opaque, Tab);
    +last(ActivityId, Opaque, Tab) ->
    +    case ?catch_val({Tab, frag_hash}) of
    +	{'EXIT', _} ->
    +	    mnesia:last(ActivityId, Opaque, Tab);
     	FH ->
     	    LastN = FH#frag_state.n_fragments,
    -	    search_last(ActivityId, Opaque, Tab, LastN, FH)
    +	    search_last(ActivityId, Opaque, Tab, LastN, FH)
         end.
     
    -search_last(ActivityId, Opaque, Tab, N, FH) when N >= 1 ->
    -    Frag = n_to_frag_name(Tab, N),
    -    case mnesia:last(ActivityId, Opaque, Frag) of
    +search_last(ActivityId, Opaque, Tab, N, FH) when N >= 1 ->
    +    Frag = n_to_frag_name(Tab, N),
    +    case mnesia:last(ActivityId, Opaque, Frag) of
     	'$end_of_table' ->
     	    PrevN = N - 1,
    -	    search_last(ActivityId, Opaque, Tab, PrevN, FH);
    +	    search_last(ActivityId, Opaque, Tab, PrevN, FH);
     	Prev ->
     	    Prev
         end;
    -search_last(_ActivityId, _Opaque, _Tab, _N, _FH) ->
    +search_last(_ActivityId, _Opaque, _Tab, _N, _FH) ->
         '$end_of_table'.
     
    -prev(ActivityId, Opaque, Tab, Key) ->
    -    case ?catch_val({Tab, frag_hash}) of
    -	{'EXIT', _} ->
    -	    mnesia:prev(ActivityId, Opaque, Tab, Key);
    +prev(ActivityId, Opaque, Tab, Key) ->
    +    case ?catch_val({Tab, frag_hash}) of
    +	{'EXIT', _} ->
    +	    mnesia:prev(ActivityId, Opaque, Tab, Key);
     	FH ->
    -	    N = key_to_n(FH, Key),
    -	    Frag = n_to_frag_name(Tab, N),
    -	    case mnesia:prev(ActivityId, Opaque, Frag, Key) of
    +	    N = key_to_n(FH, Key),
    +	    Frag = n_to_frag_name(Tab, N),
    +	    case mnesia:prev(ActivityId, Opaque, Frag, Key) of
     		'$end_of_table' ->
    -		    search_prev(ActivityId, Opaque, Tab, N);
    +		    search_prev(ActivityId, Opaque, Tab, N);
     		Prev ->
     		    Prev
     	    end
         end.
     
    -search_prev(ActivityId, Opaque, Tab, N) when N > 1 ->
    +search_prev(ActivityId, Opaque, Tab, N) when N > 1 ->
         PrevN = N - 1,
    -    PrevFrag = n_to_frag_name(Tab, PrevN),
    -    case mnesia:last(ActivityId, Opaque, PrevFrag) of
    +    PrevFrag = n_to_frag_name(Tab, PrevN),
    +    case mnesia:last(ActivityId, Opaque, PrevFrag) of
     	'$end_of_table' ->
    -	    search_prev(ActivityId, Opaque, Tab, PrevN);
    +	    search_prev(ActivityId, Opaque, Tab, PrevN);
     	Prev ->
     	    Prev
         end;
    -search_prev(_ActivityId, _Opaque, _Tab, _N) ->
    +search_prev(_ActivityId, _Opaque, _Tab, _N) ->
         '$end_of_table'.
     
    -next(ActivityId, Opaque, Tab, Key) ->
    -    case ?catch_val({Tab, frag_hash}) of
    -	{'EXIT', _} ->
    -	    mnesia:next(ActivityId, Opaque, Tab, Key);
    +next(ActivityId, Opaque, Tab, Key) ->
    +    case ?catch_val({Tab, frag_hash}) of
    +	{'EXIT', _} ->
    +	    mnesia:next(ActivityId, Opaque, Tab, Key);
     	FH ->
    -	    N = key_to_n(FH, Key),
    -	    Frag = n_to_frag_name(Tab, N),
    -	    case mnesia:next(ActivityId, Opaque, Frag, Key) of
    +	    N = key_to_n(FH, Key),
    +	    Frag = n_to_frag_name(Tab, N),
    +	    case mnesia:next(ActivityId, Opaque, Frag, Key) of
     		'$end_of_table' ->
    -		    search_next(ActivityId, Opaque, Tab, N, FH);
    +		    search_next(ActivityId, Opaque, Tab, N, FH);
     		Prev ->
     		    Prev
     	    end
         end.
     
    -search_next(ActivityId, Opaque, Tab, N, FH) when N < FH#frag_state.n_fragments ->
    +search_next(ActivityId, Opaque, Tab, N, FH) when N < FH#frag_state.n_fragments ->
         NextN = N + 1,
    -    NextFrag = n_to_frag_name(Tab, NextN),
    -    case mnesia:first(ActivityId, Opaque, NextFrag) of
    +    NextFrag = n_to_frag_name(Tab, NextN),
    +    case mnesia:first(ActivityId, Opaque, NextFrag) of
     	'$end_of_table' ->
    -	    search_next(ActivityId, Opaque, Tab, NextN, FH);
    +	    search_next(ActivityId, Opaque, Tab, NextN, FH);
     	Next ->
     	    Next
         end;
    -search_next(_ActivityId, _Opaque, _Tab, _N, _FH) ->
    +search_next(_ActivityId, _Opaque, _Tab, _N, _FH) ->
         '$end_of_table'.
    diff --git a/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_app_c.html b/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_app_c.html index 36819dfd065c..683c3b741ace 100644 --- a/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_app_c.html +++ b/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_app_c.html @@ -137,136 +137,136 @@

    mnesia_frag_hash Callback Behavior

    -
    -module(mnesia_frag_hash).
    --compile([{nowarn_deprecated_function, [{erlang,phash,2}]}]).
    +
    -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;
    -match_spec_to_frag_numbers(OldState, MatchSpec) ->
    -    State = convert_old_state(OldState),
    -    match_spec_to_frag_numbers(State, MatchSpec).
    +match_spec_to_frag_numbers(OldState, MatchSpec) ->
    +    State = convert_old_state(OldState),
    +    match_spec_to_frag_numbers(State, MatchSpec).
     
    -power2(Y) ->
    +power2(Y) ->
         1 bsl Y. % trunc(math:pow(2, Y)).
    diff --git a/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_chap2.html b/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_chap2.html index c72c85dff2ee..5e13b3a5f9fa 100644 --- a/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_chap2.html +++ b/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_chap2.html @@ -143,21 +143,21 @@

    This section provides a simplified demonstration of a Mnesia system startup. The dialogue from the Erlang shell is as follows:

    unix> erl -mnesia dir '"/tmp/funky"'
    -Erlang (BEAM) emulator version 4.9
    +Erlang (BEAM) emulator version 4.9
     
    -Eshell V4.9  (abort with ^G)
    +Eshell V4.9  (abort with ^G)
     1>
    -1> mnesia:create_schema([node()]).
    +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 <---
    ----> Pending (remote) transactions <---
    ----> Active (local) transactions <---
    +---> Pending (remote) transactions <---
    +---> Active (local) transactions <---
     ---> Uncertain transactions <---
     ---> Active tables <---
     funky          : with 0 records occupying 269 words of mem
    @@ -165,17 +165,17 @@ 

    ===> System info in version "1.0", debug level = none <=== opt_disc. Directory "/tmp/funky" is used. use fall-back at restart = false -running db nodes = [nonode@nohost] -stopped db nodes = [] -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 = [] +remote = [] +ram_copies = [funky] +disc_copies = [schema] +disc_only_copies = [] +[{nonode@nohost,disc_copies}] = [schema] +[{nonode@nohost,ram_copies}] = [funky] 1 transactions committed, 0 aborted, 0 restarted, 1 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 @@ -235,28 +235,28 @@

      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, ArgList) 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 @@ -273,28 +273,28 @@

      The following shell interaction starts Mnesia and initializes the schema for the Company database:

      % erl -mnesia dir '"/ldisc/scratch/Mnesia.Company"'
      -Erlang (BEAM) emulator version 4.9
      +Erlang (BEAM) emulator version 4.9
       
      -Eshell V4.9  (abort with ^G)
      -1> mnesia:create_schema([node()]).
      +Eshell V4.9  (abort with ^G)
      +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)}]).

      +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)}]).

    @@ -308,13 +308,13 @@

    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 <---
    ----> Pending (remote) transactions <---
    ----> Active (local) transactions <---
    +---> Pending (remote) transactions <---
    +---> Active (local) transactions <---
     ---> Uncertain transactions <---
     ---> Active tables <---
     in_proj        : with 0 records occuping 269 words of mem
    @@ -327,19 +327,19 @@ 

    ===> System info in version "1.0", debug level = none <=== opt_disc. Directory "/ldisc/scratch/Mnesia.Company" is used. use fall-back at restart = false -running db nodes = [nonode@nohost] -stopped db nodes = [] -remote = [] +running db nodes = [nonode@nohost] +stopped db nodes = [] +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] + [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] 6 transactions committed, 0 aborted, 0 restarted, 6 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, ArgList) creates the required database tables. The options available with ArgList are explained in @@ -353,32 +353,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() ->
    +                  mnesia:write(Emp),
    +                  AtDep = #at_dep{emp = Ename, dept_id = DeptId},
    +                  mnesia:write(AtDep),
    +                  mk_projs(Ename, ProjNames)
               end,
    -    mnesia:transaction(Fun).
    +    mnesia:transaction(Fun).
     
     
    -mk_projs(Ename, [ProjName|Tail]) ->
    -    mnesia:write(#in_proj{emp = Ename, proj_name = ProjName}),
    -    mk_projs(Ename, Tail);
    -mk_projs(_, []) -> ok.
    • The insert_emp/3 arguments are as follows:
      1. Emp is an employee record.
      2. DeptId is the identity of the department where the employee works.
      3. ProjNames is a list of the names of the projects where the employee +mk_projs(Ename, [ProjName|Tail]) -> + mnesia:write(#in_proj{emp = Ename, proj_name = ProjName}), + mk_projs(Ename, Tail); +mk_projs(_, []) -> ok.
    • The insert_emp/3 arguments are as follows:
      1. Emp is an employee record.
      2. DeptId is the identity of the department where the employee works.
      3. ProjNames is a list of the names of the projects where the employee works.

    The function insert_emp/3 creates a Functional Object (Fun). Fun is passed as a single argument to the function mnesia:transaction(Fun). This means that Fun is run as a transaction with the following properties:

    • A Fun either succeeds or fails.
    • Code that manipulates the same data records can be run concurrently without -the different processes interfering with each other.

    The function can be used as follows:

    Emp = #employee{emp_no = 104732,
    +the different processes interfering with each other.

    The function can be used as follows:

    Emp = #employee{emp_no = 104732,
                     name = klacke,
                     salary = 7,
                     sex = male,
                     phone = 98108,
    -                room_no = {221, 015}},
    -insert_emp(Emp, 'B/SFR', [Erlang, mnesia, otp]).

    Note

    For information about Funs, see "Fun Expressions" in section + room_no = {221, 015}}, +insert_emp(Emp, 'B/SFR', [Erlang, mnesia, otp]).

    Note

    For information about Funs, see "Fun Expressions" in section Erlang Reference Manual in System Documentation..

    @@ -406,48 +406,48 @@

    Adding Records and Relationships to Database

    After adding more records to the Company database, the result can be the -following records:

    employees:

    {employee, 104465, "Johnson Torbjorn",   1, male,  99184, {242,038}}.
    -{employee, 107912, "Carlsson Tuula",     2, female,94556, {242,056}}.
    -{employee, 114872, "Dacker Bjarne",      3, male,  99415, {221,035}}.
    -{employee, 104531, "Nilsson Hans",       3, male,  99495, {222,026}}.
    -{employee, 104659, "Tornkvist Torbjorn", 2, male,  99514, {222,022}}.
    -{employee, 104732, "Wikstrom Claes",     2, male,  99586, {221,015}}.
    -{employee, 117716, "Fedoriw Anna",       1, female,99143, {221,031}}.
    -{employee, 115018, "Mattsson Hakan",     3, male,  99251, {203,348}}.

    dept:

    {dept, 'B/SF',  "Open Telecom Platform"}.
    -{dept, 'B/SFP', "OTP - Product Development"}.
    -{dept, 'B/SFR', "Computer Science Laboratory"}.

    projects:

    %% projects
    -{project, erlang, 1}.
    -{project, otp, 2}.
    -{project, beam, 3}.
    -{project, mnesia, 5}.
    -{project, wolf, 6}.
    -{project, documentation, 7}.
    -{project, www, 8}.

    These three tables, employees, dept, and projects, are made up of real +following records:

    employees:

    {employee, 104465, "Johnson Torbjorn",   1, male,  99184, {242,038}}.
    +{employee, 107912, "Carlsson Tuula",     2, female,94556, {242,056}}.
    +{employee, 114872, "Dacker Bjarne",      3, male,  99415, {221,035}}.
    +{employee, 104531, "Nilsson Hans",       3, male,  99495, {222,026}}.
    +{employee, 104659, "Tornkvist Torbjorn", 2, male,  99514, {222,022}}.
    +{employee, 104732, "Wikstrom Claes",     2, male,  99586, {221,015}}.
    +{employee, 117716, "Fedoriw Anna",       1, female,99143, {221,031}}.
    +{employee, 115018, "Mattsson Hakan",     3, male,  99251, {203,348}}.

    dept:

    {dept, 'B/SF',  "Open Telecom Platform"}.
    +{dept, 'B/SFP', "OTP - Product Development"}.
    +{dept, 'B/SFR', "Computer Science Laboratory"}.

    projects:

    %% projects
    +{project, erlang, 1}.
    +{project, otp, 2}.
    +{project, beam, 3}.
    +{project, mnesia, 5}.
    +{project, wolf, 6}.
    +{project, documentation, 7}.
    +{project, www, 8}.

    These three tables, employees, dept, and projects, are made up of real records. The following database content is stored in the tables and is built on -relationships. These tables are manager, at_dep, and in_proj.

    manager:

    {manager, 104465, 'B/SF'}.
    -{manager, 104465, 'B/SFP'}.
    -{manager, 114872, 'B/SFR'}.

    at_dep:

    {at_dep, 104465, 'B/SF'}.
    -{at_dep, 107912, 'B/SF'}.
    -{at_dep, 114872, 'B/SFR'}.
    -{at_dep, 104531, 'B/SFR'}.
    -{at_dep, 104659, 'B/SFR'}.
    -{at_dep, 104732, 'B/SFR'}.
    -{at_dep, 117716, 'B/SFP'}.
    -{at_dep, 115018, 'B/SFP'}.

    in_proj:

    {in_proj, 104465, otp}.
    -{in_proj, 107912, otp}.
    -{in_proj, 114872, otp}.
    -{in_proj, 104531, otp}.
    -{in_proj, 104531, mnesia}.
    -{in_proj, 104545, wolf}.
    -{in_proj, 104659, otp}.
    -{in_proj, 104659, wolf}.
    -{in_proj, 104732, otp}.
    -{in_proj, 104732, mnesia}.
    -{in_proj, 104732, erlang}.
    -{in_proj, 117716, otp}.
    -{in_proj, 117716, documentation}.
    -{in_proj, 115018, otp}.
    -{in_proj, 115018, mnesia}.

    The room number is an attribute of the employee record. This is a structured +relationships. These tables are manager, at_dep, and in_proj.

    manager:

    {manager, 104465, 'B/SF'}.
    +{manager, 104465, 'B/SFP'}.
    +{manager, 114872, 'B/SFR'}.

    at_dep:

    {at_dep, 104465, 'B/SF'}.
    +{at_dep, 107912, 'B/SF'}.
    +{at_dep, 114872, 'B/SFR'}.
    +{at_dep, 104531, 'B/SFR'}.
    +{at_dep, 104659, 'B/SFR'}.
    +{at_dep, 104732, 'B/SFR'}.
    +{at_dep, 117716, 'B/SFP'}.
    +{at_dep, 115018, 'B/SFP'}.

    in_proj:

    {in_proj, 104465, otp}.
    +{in_proj, 107912, otp}.
    +{in_proj, 114872, otp}.
    +{in_proj, 104531, otp}.
    +{in_proj, 104531, mnesia}.
    +{in_proj, 104545, wolf}.
    +{in_proj, 104659, otp}.
    +{in_proj, 104659, wolf}.
    +{in_proj, 104732, otp}.
    +{in_proj, 104732, mnesia}.
    +{in_proj, 104732, erlang}.
    +{in_proj, 117716, otp}.
    +{in_proj, 117716, documentation}.
    +{in_proj, 115018, otp}.
    +{in_proj, 115018, mnesia}.

    The room number is an attribute of the employee record. This is a structured attribute that consists of a tuple. The first element of the tuple identifies a corridor, and the second element identifies the room in that corridor. An alternative is to represent this as a record -record(room, {corr, no}). @@ -459,67 +459,67 @@

    Retrieving data from DBMS is usually to be done with the functions mnesia:read/3 or mnesia:read/1. The following function -raises the salary:

    raise(Eno, Raise) ->
    -    F = fun() ->
    -                [E] = mnesia:read(employee, Eno, write),
    +raises the salary:

    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).

    Since it is desired to update the record using the function mnesia:write/1 + mnesia:transaction(F).

    Since it is desired to update the record using the function mnesia:write/1 after the salary has been increased, a write lock (third argument to read) is acquired when the record from the table is read.

    To read the values from the table directly is not always possible. It can be needed to search one or more tables to get the wanted data, and this is done by writing database queries. Queries are always more expensive operations than direct lookups done with mnesia:read/1. Therefore, avoid queries in performance-critical code.

    Two methods are available for writing database queries:

    • Mnesia functions
    • QLC

    Using Mnesia Functions

    The following function extracts the names of the female employees stored in the -database:

    mnesia:select(employee, [{#employee{sex = female, name = '$1', _ = '_'},[], ['$1']}]).

    select must always run within an activity, such as a transaction. The -following function can be constructed to call from the shell:

    all_females() ->
    -    F = fun() ->
    -		Female = #employee{sex = female, name = '$1', _ = '_'},
    -		mnesia:select(employee, [{Female, [], ['$1']}])
    +database:

    mnesia:select(employee, [{#employee{sex = female, name = '$1', _ = '_'},[], ['$1']}]).

    select must always run within an activity, such as a transaction. The +following function can be constructed to call from the shell:

    all_females() ->
    +    F = fun() ->
    +		Female = #employee{sex = female, name = '$1', _ = '_'},
    +		mnesia:select(employee, [{Female, [], ['$1']}])
             end,
    -    mnesia:transaction(F).

    The select expression matches all entries in table employee with the field -sex set to female.

    This function can be called from the shell as follows:

    (klacke@gin)1> company:all_females().
    -{atomic, ["Carlsson Tuula", "Fedoriw Anna"]}

    For a description of select and its syntax, see + mnesia:transaction(F).

    The select expression matches all entries in table employee with the field +sex set to female.

    This function can be called from the shell as follows:

    (klacke@gin)1> company:all_females().
    +{atomic, ["Carlsson Tuula", "Fedoriw Anna"]}

    For a description of select and its syntax, see Pattern Matching.

    Using QLC

    This section contains simple introductory examples only. For a full description of the QLC query language, see the qlc manual page in STDLIB.

    Using QLC can be more expensive than using Mnesia functions directly but -offers a nice syntax.

    The following function extracts a list of female employees from the database:

    Q = qlc:q([E#employee.name || E <- mnesia:table(employee),
    -                              E#employee.sex == female]),
    -qlc:e(Q),

    Accessing Mnesia tables from a QLC list comprehension must always be done -within a transaction. Consider the following function:

    females() ->
    -    F = fun() ->
    -		Q = qlc:q([E#employee.name || E <- mnesia:table(employee),
    -					      E#employee.sex == female]),
    -		qlc:e(Q)
    +offers a nice syntax.

    The following function extracts a list of female employees from the database:

    Q = qlc:q([E#employee.name || E <- mnesia:table(employee),
    +                              E#employee.sex == female]),
    +qlc:e(Q),

    Accessing Mnesia tables from a QLC list comprehension must always be done +within a transaction. Consider the following function:

    females() ->
    +    F = fun() ->
    +		Q = qlc:q([E#employee.name || E <- mnesia:table(employee),
    +					      E#employee.sex == female]),
    +		qlc:e(Q)
     	end,
    -    mnesia:transaction(F).

    This function can be called from the shell as follows:

    (klacke@gin)1> company:females().
    -{atomic, ["Carlsson Tuula", "Fedoriw Anna"]}

    In traditional relational database terminology, this operation is called a + mnesia:transaction(F).

    This function can be called from the shell as follows:

    (klacke@gin)1> company:females().
    +{atomic, ["Carlsson Tuula", "Fedoriw Anna"]}

    In traditional relational database terminology, this operation is called a selection, followed by a projection.

    The previous list comprehension expression contains a number of syntactical elements:

    • The first [ bracket is read as "build the list".
    • The || "such that" and the arrow <- is read as "taken from".

    Hence, the previous list comprehension demonstrates the formation of the list E#employee.name such that E is taken from the table of employees, and attribute sex of each record is equal to the atom female.

    The whole list comprehension must be given to the function qlc:q/1.

    List comprehensions with low-level Mnesia functions can be combined in the same transaction. To raise the salary of all female employees, execute the -following:

    raise_females(Amount) ->
    -    F = fun() ->
    -                Q = qlc:q([E || E <- mnesia:table(employee),
    -                                E#employee.sex == female]),
    -		Fs = qlc:e(Q),
    -                over_write(Fs, Amount)
    +following:

    raise_females(Amount) ->
    +    F = fun() ->
    +                Q = qlc:q([E || E <- mnesia:table(employee),
    +                                E#employee.sex == female]),
    +		Fs = qlc:e(Q),
    +                over_write(Fs, Amount)
             end,
    -    mnesia:transaction(F).
    +    mnesia:transaction(F).
     
    -over_write([E|Tail], Amount) ->
    +over_write([E|Tail], Amount) ->
         Salary = E#employee.salary + Amount,
    -    New = E#employee{salary = Salary},
    -    mnesia:write(New),
    -    1 + over_write(Tail, Amount);
    -over_write([], _) ->
    +    New = E#employee{salary = Salary},
    +    mnesia:write(New),
    +    1 + over_write(Tail, Amount);
    +over_write([], _) ->
         0.

    The function raise_females/1 returns the tuple {atomic, Number}, where Number is the number of female employees who received a salary increase. If an error occurs, the value {aborted, Reason} is returned, and Mnesia guarantees -that the salary is not raised for any employee.

    Example:

    33> company:raise_females(33).
    -{atomic,2}
    +that the salary is not raised for any employee.

    Example:

    33> company:raise_females(33).
    +{atomic,2}
    diff --git a/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_chap3.html b/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_chap3.html index f37ed68a9ffe..795e54c593b4 100644 --- a/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_chap3.html +++ b/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_chap3.html @@ -181,18 +181,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) @@ -244,29 +244,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, @@ -283,7 +283,7 @@

    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. +

    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, @@ -306,9 +306,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 @@ -334,13 +334,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 @@ -384,11 +384,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, [])
    diff --git a/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_chap4.html b/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_chap4.html index ea7f74f38157..4f0421315fd4 100644 --- a/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_chap4.html +++ b/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_chap4.html @@ -151,14 +151,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 @@ -252,15 +252,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 @@ -307,13 +307,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 @@ -339,8 +339,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).

    @@ -431,78 +431,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),
    -  mnesia:index_match_object(Tab, Pattern, Attr, read).

    +mnesia:index_match_object(Pattern, Attr) -> + Tab = element(1, Pattern), + mnesia:index_match_object(Tab, Pattern, Attr, read).

    @@ -583,28 +583,28 @@

    terminates. So, although a nested transaction returns {atomic, Val}, if the enclosing parent transaction terminates, the entire nested operation terminates.

    The ability to have nested transaction with identical semantics as top-level transaction makes it easier to write library functions that manipulate Mnesia -tables.

    Consider a function that adds a subscriber to a telephony system:

    add_subscriber(S) ->
    -    mnesia:transaction(fun() ->
    -        case mnesia:read( ..........

    This function needs to be called as a transaction. Assume that you wish to write +tables.

    Consider a function that adds a subscriber to a telephony system:

    add_subscriber(S) ->
    +    mnesia:transaction(fun() ->
    +        case mnesia:read( ..........

    This function needs to be called as a transaction. Assume that you wish to write a function that both calls the function add_subscriber/1 and is in itself protected by the context of a transaction. By calling add_subscriber/1 from within another transaction, a nested transaction is created.

    Also, different activity access contexts can be mixed while nesting. However, the dirty ones (async_dirty, sync_dirty, and ets) inherit the transaction semantics if they are called inside a transaction and thus grab locks and use -two or three phase commit.

    Example:

    add_subscriber(S) ->
    -    mnesia:transaction(fun() ->
    +two or three phase commit.

    Example:

    add_subscriber(S) ->
    +    mnesia:transaction(fun() ->
            %% Transaction context
    -       mnesia:read({some_tab, some_data}),
    -       mnesia:sync_dirty(fun() ->
    +       mnesia:read({some_tab, some_data}),
    +       mnesia:sync_dirty(fun() ->
                %% Still in a transaction context.
    -           case mnesia:read( ..) ..end), end).
    -add_subscriber2(S) ->
    -    mnesia:sync_dirty(fun() ->
    +           case mnesia:read( ..) ..end), end).
    +add_subscriber2(S) ->
    +    mnesia:sync_dirty(fun() ->
            %% In dirty context
    -       mnesia:read({some_tab, some_data}),
    -       mnesia:transaction(fun() ->
    +       mnesia:read({some_tab, some_data}),
    +       mnesia:transaction(fun() ->
                %% In a transaction context.
    -           case mnesia:read( ..) ..end), end).

    + case mnesia:read( ..) ..end), end).

    @@ -612,13 +612,13 @@

    When the function mnesia:read/3 cannot be used, Mnesia provides the programmer with several functions for matching records against a pattern. The -most useful ones are the following:

    mnesia:select(Tab, MatchSpecification, LockKind) ->
    -    transaction abort | [ObjectList]
    -mnesia:select(Tab, MatchSpecification, NObjects, Lock) ->
    -    transaction abort | {[Object],Continuation} | '$end_of_table'
    -mnesia:select(Cont) ->
    -    transaction abort | {[Object],Continuation} | '$end_of_table'
    -mnesia:match_object(Tab, Pattern, LockKind) ->
    +most useful ones are the following:

    mnesia:select(Tab, MatchSpecification, LockKind) ->
    +    transaction abort | [ObjectList]
    +mnesia:select(Tab, MatchSpecification, NObjects, Lock) ->
    +    transaction abort | {[Object],Continuation} | '$end_of_table'
    +mnesia:select(Cont) ->
    +    transaction abort | {[Object],Continuation} | '$end_of_table'
    +mnesia:match_object(Tab, Pattern, LockKind) ->
         transaction abort | RecordList

    These functions match a Pattern against all records in table Tab. In a mnesia:select call, Pattern is a part of MatchSpecification described in the following. It is not necessarily performed @@ -633,22 +633,22 @@

    occurrences of that variable against the bound value.

    Use function mnesia:table_info(Tab, wild_pattern) to obtain a basic pattern, which matches all records in a table, or use the default value in record creation. Do not make the pattern hard-coded, as this makes the -code more vulnerable to future changes of the record definition.

    Example:

    Wildpattern = mnesia:table_info(employee, wild_pattern),
    +code more vulnerable to future changes of the record definition.

    Example:

    Wildpattern = mnesia:table_info(employee, wild_pattern),
     %% Or use
    -Wildpattern = #employee{_ = '_'},

    For the employee table, the wild pattern looks as follows:

    {employee, '_', '_', '_', '_', '_',' _'}.

    To constrain the match, it is needed to replace some of the '_' elements. The -code for matching out all female employees looks as follows:

    Pat = #employee{sex = female, _ = '_'},
    -F = fun() -> mnesia:match_object(Pat) end,
    -Females = mnesia:transaction(F).

    The match function can also be used to check the equality of different +Wildpattern = #employee{_ = '_'},

    For the employee table, the wild pattern looks as follows:

    {employee, '_', '_', '_', '_', '_',' _'}.

    To constrain the match, it is needed to replace some of the '_' elements. The +code for matching out all female employees looks as follows:

    Pat = #employee{sex = female, _ = '_'},
    +F = fun() -> mnesia:match_object(Pat) end,
    +Females = mnesia:transaction(F).

    The match function can also be used to check the equality of different attributes. For example, to find all employees with an employee number equal to -their room number:

    Pat = #employee{emp_no = '$1', room_no = '$1', _ = '_'},
    -F = fun() -> mnesia:match_object(Pat) end,
    -Odd = mnesia:transaction(F).

    The function mnesia:match_object/3 lacks some important features that +their room number:

    Pat = #employee{emp_no = '$1', room_no = '$1', _ = '_'},
    +F = fun() -> mnesia:match_object(Pat) end,
    +Odd = mnesia:transaction(F).

    The function mnesia:match_object/3 lacks some important features that mnesia:select/3 have. For example, mnesia:match_object/3 can only return the matching records, and it cannot express constraints other -than equality. To find the names of the male employees on the second floor:

    MatchHead = #employee{name='$1', sex=male, room_no={'$2', '_'}, _='_'},
    -Guard = [{'>=', '$2', 220},{'<', '$2', 230}],
    +than equality. To find the names of the male employees on the second floor:

    MatchHead = #employee{name='$1', sex=male, room_no={'$2', '_'}, _='_'},
    +Guard = [{'>=', '$2', 220},{'<', '$2', 230}],
     Result = '$1',
    -mnesia:select(employee,[{MatchHead, Guard, [Result]}])

    The function select can be used to add more constraints and create output that +mnesia:select(employee,[{MatchHead, Guard, [Result]}])

    The function select can be used to add more constraints and create output that cannot be done with mnesia:match_object/3.

    The second argument to select is a MatchSpecification. A MatchSpecification is a list of MatchFunctions, where each MatchFunction consists of a tuple containing {MatchHead, MatchCondition, MatchBody}:

    • MatchHead is the same pattern as used in mnesia:match_object/3 described @@ -678,8 +678,8 @@

      {traverse, {select, MatchSpecification}} as an option to mnesia:table/2 the user can specify its own view of the table.

    If no options are specified, a read lock is acquired, 100 results are returned -in each chunk, and select is used to traverse the table, that is:

    mnesia:table(Tab) ->
    -    mnesia:table(Tab, [{n_objects, 100},{lock, read}, {traverse, select}]).

    The function mnesia:all_keys(Tab) returns all keys in a +in each chunk, and select is used to traverse the table, that is:

    mnesia:table(Tab) ->
    +    mnesia:table(Tab, [{n_objects, 100},{lock, read}, {traverse, select}]).

    The function mnesia:all_keys(Tab) returns all keys in a table.

    @@ -687,10 +687,10 @@

    Iteration

    Mnesia provides the following functions that iterate over all the records in a -table:

    mnesia:foldl(Fun, Acc0, Tab) -> NewAcc | transaction abort
    -mnesia:foldr(Fun, Acc0, Tab) -> NewAcc | transaction abort
    -mnesia:foldl(Fun, Acc0, Tab, LockType) -> NewAcc | transaction abort
    -mnesia:foldr(Fun, Acc0, Tab, LockType) -> NewAcc | transaction abort

    These functions iterate over the Mnesia table Tab and apply the function +table:

    mnesia:foldl(Fun, Acc0, Tab) -> NewAcc | transaction abort
    +mnesia:foldr(Fun, Acc0, Tab) -> NewAcc | transaction abort
    +mnesia:foldl(Fun, Acc0, Tab, LockType) -> NewAcc | transaction abort
    +mnesia:foldr(Fun, Acc0, Tab, LockType) -> NewAcc | transaction abort

    These functions iterate over the Mnesia table Tab and apply the function Fun to each record. Fun takes two arguments, the first is a record from the table, and the second is the accumulator. Fun returns a new accumulator.

    The first time Fun is applied, Acc0 is the second argument. The next time Fun is called, the return value from the previous call is used as the second @@ -701,35 +701,35 @@

    write lock is to be acquired.

    These functions can be used to find records in a table when it is impossible to write constraints for the function mnesia:match_object/3, or when you want to perform some action on certain records.

    For example, finding all the employees who have a salary less than 10 can look -as follows:

    find_low_salaries() ->
    +as follows:

    find_low_salaries() ->
       Constraint =
    -       fun(Emp, Acc) when Emp#employee.salary < 10 ->
    -              [Emp | Acc];
    -          (_, Acc) ->
    +       fun(Emp, Acc) when Emp#employee.salary < 10 ->
    +              [Emp | Acc];
    +          (_, Acc) ->
                   Acc
            end,
    -  Find = fun() -> mnesia:foldl(Constraint, [], employee) end,
    -  mnesia:transaction(Find).

    To raise the salary to 10 for everyone with a salary less than 10 and return the -sum of all raises:

    increase_low_salaries() ->
    +  Find = fun() -> mnesia:foldl(Constraint, [], employee) end,
    +  mnesia:transaction(Find).

    To raise the salary to 10 for everyone with a salary less than 10 and return the +sum of all raises:

    increase_low_salaries() ->
        Increase =
    -       fun(Emp, Acc) when Emp#employee.salary < 10 ->
    +       fun(Emp, Acc) when Emp#employee.salary < 10 ->
                   OldS = Emp#employee.salary,
    -              ok = mnesia:write(Emp#employee{salary = 10}),
    +              ok = mnesia:write(Emp#employee{salary = 10}),
                   Acc + 10 - OldS;
    -          (_, Acc) ->
    +          (_, Acc) ->
                   Acc
            end,
    -  IncLow = fun() -> mnesia:foldl(Increase, 0, employee, write) end,
    -  mnesia:transaction(IncLow).

    Many nice things can be done with the iterator functions but take some caution + IncLow = fun() -> mnesia:foldl(Increase, 0, employee, write) end, + mnesia:transaction(IncLow).

    Many nice things can be done with the iterator functions but take some caution about performance and memory use for large tables.

    Call these iteration functions on nodes that contain a replica of the table. Each call to the function Fun access the table and if the table resides on another node it generates much unnecessary network traffic.

    Mnesia also provides some functions that make it possible for the user to iterate over the table. The order of the iteration is unspecified if the table -is not of type ordered_set:

    mnesia:first(Tab) ->  Key | transaction abort
    -mnesia:last(Tab)  ->  Key | transaction abort
    -mnesia:next(Tab,Key)  ->  Key | transaction abort
    -mnesia:prev(Tab,Key)  ->  Key | transaction abort
    -mnesia:snmp_get_next_index(Tab,Index) -> {ok, NextIndex} | endOfTable

    The order of first/last and next/prev is only valid for ordered_set +is not of type ordered_set:

    mnesia:first(Tab) ->  Key | transaction abort
    +mnesia:last(Tab)  ->  Key | transaction abort
    +mnesia:next(Tab,Key)  ->  Key | transaction abort
    +mnesia:prev(Tab,Key)  ->  Key | transaction abort
    +mnesia:snmp_get_next_index(Tab,Index) -> {ok, NextIndex} | endOfTable

    The order of first/last and next/prev is only valid for ordered_set tables, they are synonyms for other tables. When the end of the table is reached, the special key '$end_of_table' is returned.

    If records are written and deleted during the traversal, use the function mnesia:foldl/3 or mnesia:foldr/3 with a write lock. Or the function diff --git a/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_chap5.html b/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_chap5.html index 3a876e582ca6..e9b40f858fad 100644 --- a/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_chap5.html +++ b/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_chap5.html @@ -173,9 +173,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.

  • The database can be reconfigured, and tables can be moved between nodes. These operations do not affect the user programs.

  • 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, @@ -228,52 +228,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 V4.7.3.3  (abort with ^G)
      -(a@sam)1> mnesia:start().
      +fragmented table and how more fragments are added later:

      Eshell V4.7.3.3  (abort with ^G)
      +(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},
      - {n_doubles,0},
      - {n_fragments,1},
      - {next_n_to_split,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},
      + {n_doubles,0},
      + {n_fragments,1},
      + {next_n_to_split,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,64},
      - {dictionary_frag2,64},
      - {dictionary_frag3,64},
      - {dictionary_frag4,64}]
      -(a@sam)19>

      +(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,64}, + {dictionary_frag2,64}, + {dictionary_frag3,64}, + {dictionary_frag4,64}] +(a@sam)19>

      @@ -315,64 +315,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 V4.7.3.3  (abort with ^G)
      -(a@sam)1> mnesia:start().
      +Default is undefined.

      Eshell V4.7.3.3  (abort with ^G)
      +(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},
      -(a@sam)5>                      {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},
      +(a@sam)5>                      {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,0},
      - {prim_dict_frag4,1},
      - {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,0},
      - {sec_dict_frag4,1},
      - {sec_dict_frag5,0},
      - {sec_dict_frag6,0},
      - {sec_dict_frag7,0},
      - {sec_dict_frag8,0}]
      -(a@sam)17>

    +(a@sam)15> mnesia:activity(sync_dirty, Info, + [prim_dict, frag_size], mnesia_frag). +[{prim_dict,0}, + {prim_dict_frag2,0}, + {prim_dict_frag3,0}, + {prim_dict_frag4,1}, + {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,0}, + {sec_dict_frag4,1}, + {sec_dict_frag5,0}, + {sec_dict_frag6,0}, + {sec_dict_frag7,0}, + {sec_dict_frag8,0}] +(a@sam)17>

    @@ -502,10 +502,10 @@

    table is ram_copies). The default for the application parameter is opt_disc.

    When schema_location is set to opt_disc, the function mnesia:change_table_copy_type/3 can be used to change the storage type of the -schema. This is illustrated as follows:

    1> mnesia:start().
    +schema. This is illustrated as follows:

    1> mnesia:start().
     ok
    -2> mnesia:change_table_copy_type(schema, node(), disc_copies).
    -{atomic, ok}

    Assuming that the call to mnesia:start/0 does not find any schema to read on +2> mnesia:change_table_copy_type(schema, node(), disc_copies). +{atomic, ok}

    Assuming that the call to mnesia:start/0 does not find any schema to read on the disc, Mnesia starts as a disc-less node, and then change it to a node that use the disc to store the schema locally.

    @@ -729,34 +729,34 @@

    a normal text editor) and later reloaded.

    These functions are much slower than the ordinary store and load functions of Mnesia. However, this is mainly intended for minor experiments and initial prototyping. The major advantage of these functions is that they are easy to -use.

    The format of the text file is as follows:

    {tables, [{Typename, [Options]},
    -{Typename2 ......}]}.
    +use.

    The format of the text file is as follows:

    {tables, [{Typename, [Options]},
    +{Typename2 ......}]}.
     
    -{Typename, Attribute1, Attribute2 ....}.
    -{Typename, Attribute1, Attribute2 ....}.

    Options is a list of {Key,Value} tuples conforming to the options that you +{Typename, Attribute1, Attribute2 ....}. +{Typename, Attribute1, Attribute2 ....}.

    Options is a list of {Key,Value} tuples conforming to the options that you can give to mnesia:create_table/2.

    For example, to start playing with a small database for healthy foods, enter the -following data into file FRUITS:

    {tables,
    - [{fruit, [{attributes, [name, color, taste]}]},
    -  {vegetable, [{attributes, [name, color, taste, price]}]}]}.
    +following data into file FRUITS:

    {tables,
    + [{fruit, [{attributes, [name, color, taste]}]},
    +  {vegetable, [{attributes, [name, color, taste, price]}]}]}.
     
     
    -{fruit, orange, orange, sweet}.
    -{fruit, apple, green, sweet}.
    -{vegetable, carrot, orange, carrotish, 2.55}.
    -{vegetable, potato, yellow, none, 0.45}.

    The following session with the Erlang shell shows how to load the FRUITS +{fruit, orange, orange, sweet}. +{fruit, apple, green, sweet}. +{vegetable, carrot, orange, carrotish, 2.55}. +{vegetable, potato, yellow, none, 0.45}.

    The following session with the Erlang shell shows how to load the FRUITS database:

    % erl
    -Erlang (BEAM) emulator version 4.9
    +Erlang (BEAM) emulator version 4.9
     
    -Eshell V4.9  (abort with ^G)
    -1> mnesia:load_textfile("FRUITS").
    +Eshell V4.9  (abort with ^G)
    +1> mnesia:load_textfile("FRUITS").
     New table fruit
     New table vegetable
    -{atomic,ok}
    -2> mnesia:info().
    +{atomic,ok}
    +2> mnesia:info().
     ---> Processes holding locks <---
     ---> Processes waiting for locks <---
    ----> Pending (remote) transactions <---
    ----> Active (local) transactions <---
    +---> Pending (remote) transactions <---
    +---> Active (local) transactions <---
     ---> Uncertain transactions <---
     ---> Active tables <---
     vegetable      : with 2 records occuping 299 words of mem
    @@ -765,17 +765,17 @@ 

    ===> System info in version "1.1", debug level = none <=== opt_disc. Directory "/var/tmp/Mnesia.nonode@nohost" is used. use fallback at restart = false -running db nodes = [nonode@nohost] -stopped db nodes = [] -remote = [] -ram_copies = [fruit,vegetable] -disc_copies = [schema] -disc_only_copies = [] -[{nonode@nohost,disc_copies}] = [schema] -[{nonode@nohost,ram_copies}] = [fruit,vegetable] +running db nodes = [nonode@nohost] +stopped db nodes = [] +remote = [] +ram_copies = [fruit,vegetable] +disc_copies = [schema] +disc_only_copies = [] +[{nonode@nohost,disc_copies}] = [schema] +[{nonode@nohost,ram_copies}] = [fruit,vegetable] 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 3>

    It can be seen that the DBMS was initiated from a regular text file.

    @@ -789,20 +789,20 @@

    relationships (manager, at_dep, in_proj). This is a normalized data model, which has some advantages over a non-normalized data model.

    It is more efficient to do a generalized search in a normalized database. Some operations are also easier to perform on a normalized data model. For example, -one project can easily be removed, as the following example illustrates:

    remove_proj(ProjName) ->
    -    F = fun() ->
    -                Ip = qlc:e(qlc:q([X || X <- mnesia:table(in_proj),
    -				       X#in_proj.proj_name == ProjName]
    -				)),
    -                mnesia:delete({project, ProjName}),
    -                del_in_projs(Ip)
    +one project can easily be removed, as the following example illustrates:

    remove_proj(ProjName) ->
    +    F = fun() ->
    +                Ip = qlc:e(qlc:q([X || X <- mnesia:table(in_proj),
    +				       X#in_proj.proj_name == ProjName]
    +				)),
    +                mnesia:delete({project, ProjName}),
    +                del_in_projs(Ip)
             end,
    -    mnesia:transaction(F).
    +    mnesia:transaction(F).
     
    -del_in_projs([Ip|Tail]) ->
    -    mnesia:delete_object(Ip),
    -    del_in_projs(Tail);
    -del_in_projs([]) ->
    +del_in_projs([Ip|Tail]) ->
    +    mnesia:delete_object(Ip),
    +    del_in_projs(Tail);
    +del_in_projs([]) ->
         done.

    In reality, data models are seldom fully normalized. A realistic alternative to a normalized database model would be a data model that is not even in first normal form. Mnesia is suitable for applications such as telecommunications, @@ -817,7 +817,7 @@

    this is the case, a drastically different data model without direct relationships can be chosen. You would then have only the records themselves, and different records could contain either direct references to other records, -or contain other records that are not part of the Mnesia schema.

    The following record definitions can be created:

    -record(employee, {emp_no,
    +or contain other records that are not part of the Mnesia schema.

    The following record definitions can be created:

    -record(employee, {emp_no,
     		   name,
     		   salary,
     		   sex,
    @@ -825,23 +825,23 @@ 

    room_no, dept, projects, - manager}). + manager}). --record(dept, {id, - name}). +-record(dept, {id, + name}). --record(project, {name, +-record(project, {name, number, - location}).

    A record that describes an employee can look as follows:

    Me = #employee{emp_no = 104732,
    +                  location}).

    A record that describes an employee can look as follows:

    Me = #employee{emp_no = 104732,
                    name = klacke,
                    salary = 7,
                    sex = male,
                    phone = 99586,
    -               room_no = {221, 015},
    +               room_no = {221, 015},
                    dept = 'B/SFR',
    -               projects = [erlang, mnesia, otp],
    -               manager = 114872},

    This model has only three different tables, and the employee records contain + projects = [erlang, mnesia, otp], + manager = 114872},

    This model has only three different tables, and the employee records contain references to other records. The record has the following references:

    • 'B/SFR' refers to a dept record.
    • [erlang, mnesia, otp] is a list of three direct references to three different projects records.
    • 114872 refers to another employee record.

    The Mnesia record identifiers ({Tab, Key}) can also be used as references. In this case, attribute dept would be set to value {dept, 'B/SFR'} instead @@ -851,14 +851,14 @@

    difficult to ensure that records do not contain dangling pointers to other non-existent, or deleted, records.

    The following code exemplifies a search with a non-normalized data model. To find all employees at department Dep with a salary higher than Salary, use -the following code:

    get_emps(Salary, Dep) ->
    -    Q = qlc:q(
    -          [E || E <- mnesia:table(employee),
    +the following code:

    get_emps(Salary, Dep) ->
    +    Q = qlc:q(
    +          [E || E <- mnesia:table(employee),
                     E#employee.salary > Salary,
    -                E#employee.dept == Dep]
    -	 ),
    -    F = fun() -> qlc:e(Q) end,
    -    transaction(F).

    This code is easier to write and to understand, and it also executes much + E#employee.dept == Dep] + ), + F = fun() -> qlc:e(Q) end, + transaction(F).

    This code is easier to write and to understand, and it also executes much faster.

    It is easy to show examples of code that executes faster if a non-normalized data model is used, instead of a normalized model. The main reason is that fewer tables are required. Therefore, data from different tables can more easily be diff --git a/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_chap7.html b/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_chap7.html index 3dafdc430171..3c52a5ffbacf 100644 --- a/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_chap7.html +++ b/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_chap7.html @@ -239,26 +239,26 @@

    for starting Mnesia:

    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 (BEAM) emulator version 4.9
    +database:

    % erl -sname klacke -mnesia dir '"/ldisc/scratch/klacke"'
    Erlang (BEAM) emulator version 4.9
     
    -Eshell V4.9  (abort with ^G)
    -(klacke@gin)1> mnesia:create_schema([node()]).
    +Eshell V4.9  (abort with ^G)
    +(klacke@gin)1> mnesia:create_schema([node()]).
     ok
    -(klacke@gin)2>
    +(klacke@gin)2>
     ^Z
     Suspended

    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 @@ -302,11 +302,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 @@ -540,40 +540,40 @@

    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, db_nodes, Nodes}, Acc) ->
    -                {[{schema, db_nodes, lists:map(Switch,Nodes)}], Acc};
    -           ({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, db_nodes, Nodes}, Acc) ->
    +                {[{schema, db_nodes, lists:map(Switch,Nodes)}], Acc};
    +           ({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).

    + mnesia:traverse_backup(Source, Mod, dummy, read_only, View, 0).

    diff --git a/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_registry.html b/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_registry.html index 69912684c1b1..f5e7707210e2 100644 --- a/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_registry.html +++ b/prs/9045/lib/mnesia-4.23.2/doc/html/mnesia_registry.html @@ -264,8 +264,8 @@

    create_table(Tab, Opt)

    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)
    diff --git a/prs/9045/lib/observer-2.16/doc/html/observer.epub b/prs/9045/lib/observer-2.16/doc/html/observer.epub index 2ca2b30c52bd..d7974100505f 100644 Binary files a/prs/9045/lib/observer-2.16/doc/html/observer.epub and b/prs/9045/lib/observer-2.16/doc/html/observer.epub differ diff --git a/prs/9045/lib/observer-2.16/doc/html/ttb.html b/prs/9045/lib/observer-2.16/doc/html/ttb.html index 0e844e38fcea..8edb8118b365 100644 --- a/prs/9045/lib/observer-2.16/doc/html/ttb.html +++ b/prs/9045/lib/observer-2.16/doc/html/ttb.html @@ -1936,13 +1936,13 @@

    seq_trigger_ms(Flags)

    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.

    @@ -1981,14 +1981,14 @@

    start_trace(Nodes, Patterns, FlagSpec, Trac

    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).
    diff --git a/prs/9045/lib/observer-2.16/doc/html/ttb_ug.html b/prs/9045/lib/observer-2.16/doc/html/ttb_ug.html index 336e3ca2196f..3c826846a6e3 100644 --- a/prs/9045/lib/observer-2.16/doc/html/ttb_ug.html +++ b/prs/9045/lib/observer-2.16/doc/html/ttb_ug.html @@ -178,56 +178,56 @@

    Tracing Local Node from Erlang Shell

    -

    The following small module is used in the subsequent example:

    -module(m).
    --export([f/0]).
    -f() ->
    +

    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

    @@ -235,65 +235,65 @@

    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 @@ -325,9 +325,9 @@

    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]}

    +with value {local, File}, for example:

    (trace_control@durin)1> ttb:tracer(mynode@diskless,
    +                                   {file,{local,{wrap,"mytrace"}}}).
    +{ok,[mynode@diskless]}

    @@ -347,10 +347,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.

    @@ -367,22 +367,22 @@

    once overload protection is activated in one of the traced nodes. This is to avoid trace setup being inconsistent between nodes.

    Module:Function provided with option overload must handle three calls: init, check, and stop. init and stop allow some setup and teardown -required by the check. An overload check module can look as follows:

    -module(overload).
    --export([check/1]).
    -
    -check(init) ->
    -    Pid = sophisticated_module:start(),
    -    put(pid, Pid);
    -check(check) ->
    -    get(pid) ! is_overloaded,
    +required by the check. An overload check module can look as follows:

    -module(overload).
    +-export([check/1]).
    +
    +check(init) ->
    +    Pid = sophisticated_module:start(),
    +    put(pid, Pid);
    +check(check) ->
    +    get(pid) ! is_overloaded,
         receive
             Reply ->
                 Reply
         after 5000 ->
                 true
         end;
    -check(stop) ->
    -    get(pid) ! stop.

    Note

    check is always called by the same process, so put and get are possible.

    +check(stop) -> + get(pid) ! stop.

    Note

    check is always called by the same process, so put and get are possible.

    @@ -403,24 +403,24 @@

    behaviour (that is, on diskless nodes) by specifying their own module to handle autostart data storage and retrieval (ttb_autostart_module environment variable of runtime_tools). For information about the API, see module ttb. -The following example shows the default handler:

    -module(ttb_autostart).
    --export([read_config/0,
    +The following example shows the default handler:

    -module(ttb_autostart).
    +-export([read_config/0,
              write_config/1,
    -         delete_config/0]).
    +         delete_config/0]).
     
    --define(AUTOSTART_FILENAME, "ttb_autostart.bin").
    +-define(AUTOSTART_FILENAME, "ttb_autostart.bin").
     
    -delete_config() ->
    -    file:delete(?AUTOSTART_FILENAME).
    +delete_config() ->
    +    file:delete(?AUTOSTART_FILENAME).
     
    -read_config() ->
    -    case file:read_file(?AUTOSTART_FILENAME) of
    -        {ok, Data} -> {ok, binary_to_term(Data)};
    +read_config() ->
    +    case file:read_file(?AUTOSTART_FILENAME) of
    +        {ok, Data} -> {ok, binary_to_term(Data)};
             Error      -> Error
         end.
     
    -write_config(Data) ->
    -    file:write_file(?AUTOSTART_FILENAME, term_to_binary(Data)).

    Note

    Remember that file trace ports buffer the data by default. If the node +write_config(Data) -> + file:write_file(?AUTOSTART_FILENAME, term_to_binary(Data)).

    Note

    Remember that file trace ports buffer the data by default. If the node crashes, trace messages are not flushed to the binary log. If the risk of failure is high, it can be a good idea to flush the buffers every now and then automatically. Passing {flush, MSec} as an option of ttb:tracer/2 flushes @@ -489,22 +489,22 @@

    default handler is used, which prints each trace message as a text line.

  • disable_sort - Indicates that the logs are not to be merged according to time-stamp, but processed one file after another (this can be a bit faster).

  • A format handler is a fun taking four arguments. This fun is called for each trace message in the binary log(s). A simple example that only prints each trace -message can be as follows:

    fun(Fd, Trace, _TraceInfo, State) ->
    -   io:format(Fd, "Trace: ~p~n", [Trace]),
    +message can be as follows:

    fun(Fd, Trace, _TraceInfo, State) ->
    +   io:format(Fd, "Trace: ~p~n", [Trace]),
        State
     end.

    Here, Fd is the file descriptor for the destination file, or the atom standard_io. _TraceInfo contains information from the trace information file (see section Trace Information and File .ti). State is a state variable for the format handler fun. The initial value of variable -State is specified with the handler option, for example:

    ttb:format("tiger@durin-ttb", [{handler, {{Mod,Fun}, initial_state}}])
    +State is specified with the handler option, for example:

    ttb:format("tiger@durin-ttb", [{handler, {{Mod,Fun}, initial_state}}])
                                                          ^^^^^^^^^^^^^

    Another format handler can be used to calculate the time spent by the garbage -collector:

    fun(_Fd,{trace_ts,P,gc_start,_Info,StartTs},_TraceInfo,State) ->
    -      [{P,StartTs}|State];
    -   (Fd,{trace_ts,P,gc_end,_Info,EndTs},_TraceInfo,State) ->
    -      {value,{P,StartTs}} = lists:keysearch(P,1,State),
    -      Time = diff(StartTs,EndTs),
    -      io:format("GC in process ~w: ~w milliseconds~n", [P,Time]),
    -      State -- [{P,StartTs}]
    +collector:

    fun(_Fd,{trace_ts,P,gc_start,_Info,StartTs},_TraceInfo,State) ->
    +      [{P,StartTs}|State];
    +   (Fd,{trace_ts,P,gc_end,_Info,EndTs},_TraceInfo,State) ->
    +      {value,{P,StartTs}} = lists:keysearch(P,1,State),
    +      Time = diff(StartTs,EndTs),
    +      io:format("GC in process ~w: ~w milliseconds~n", [P,Time]),
    +      State -- [{P,StartTs}]
     end

    A more refined version of this format handler is function handle_gc/4 in module multitrace.erl included in directory src of the Observer application.

    The trace message is passed as the second argument (Trace). The possible values of Trace are the following:

    • All trace messages described in erlang:trace/3
    • {drop, N} if IP tracer is used (see dbg:trace_port/2)
    • end_of_trace received once when all trace messages are processed

    By giving the format handler ttb:get_et_handler(), @@ -514,19 +514,19 @@

    directory, but analyze single files instead. To do so, a single file (or list of files) must be passed as the first argument to format/1,2.

    Wrap logs can be formatted one by one or all at once. To format one of the wrap logs in a set, specify the exact file name. To format the whole set of wrap -logs, specify the name with * instead of the wrap count.

    Example:

    Start tracing:

    (tiger@durin)1> ttb:tracer(node(),{file,{wrap,"trace"}}).
    -{ok,[tiger@durin]}
    -(tiger@durin)2> ttb:p(...)
    +logs, specify the name with * instead of the wrap count.

    Example:

    Start tracing:

    (tiger@durin)1> ttb:tracer(node(),{file,{wrap,"trace"}}).
    +{ok,[tiger@durin]}
    +(tiger@durin)2> ttb:p(...)
     ...

    This gives a set of binary logs, for example:

    tiger@durin-trace.0.wrp
     tiger@durin-trace.1.wrp
     tiger@durin-trace.2.wrp
    -...

    Format the whole set of logs:

    1> ttb:format("tiger@durin-trace.*.wrp").
    +...

    Format the whole set of logs:

    1> ttb:format("tiger@durin-trace.*.wrp").
     ....
     ok
    -2>

    Format only the first log:

    1> ttb:format("tiger@durin-trace.0.wrp").
    +2>

    Format only the first log:

    1> ttb:format("tiger@durin-trace.0.wrp").
     ....
     ok
    -2>

    To merge all wrap logs from two nodes:

    1> ttb:format(["tiger@durin-trace.*.wrp","lion@durin-trace.*.wrp"]).
    +2>

    To merge all wrap logs from two nodes:

    1> ttb:format(["tiger@durin-trace.*.wrp","lion@durin-trace.*.wrp"]).
     ....
     ok
     2>

    @@ -553,8 +553,8 @@

    obtained using both the call and return_to flags when tracing. Notice that flag return_to only works with local call trace, that is, when trace patterns are set with ttb:tpl.

    The same result can be obtained by using the flag call only and setting a -match specification on local or global function calls as follows:

    1> dbg:fun2ms(fun(_) -> return_trace(),message(caller()) end).
    -[{'_',[],[{return_trace},{message,{caller}}]}]

    This must however be done with care, as function {return_trace} in the match +match specification on local or global function calls as follows:

    1> dbg:fun2ms(fun(_) -> return_trace(),message(caller()) end).
    +[{'_',[],[{return_trace},{message,{caller}}]}]

    This must however be done with care, as function {return_trace} in the match specification destroys tail recursiveness.

    The modules filter shows each module as a vertical line in the sequence diagram. External function calls/returns are shown as interactions between modules, and internal function calls/returns are shown as activities within a @@ -562,42 +562,42 @@

    diagram. A function calling itself is shown as an activity within a function, and all other function calls are shown as interactions between functions.

    The mods_and_procs and funcs_and_procs filters are equivalent to the modules and functions filters respectively, except that each module or -function can have many vertical lines, one for each process it resides on.

    In the following example, modules foo and bar are used:

    -module(foo).
    --export([start/0,go/0]).
    +function can have many vertical lines, one for each process it resides on.

    In the following example, modules foo and bar are used:

    -module(foo).
    +-export([start/0,go/0]).
     
    -start() ->
    -    spawn(?MODULE, go, []).
    +start() ->
    +    spawn(?MODULE, go, []).
     
    -go() ->
    +go() ->
         receive
             stop ->
                 ok;
             go ->
    -            bar:f1(),
    -            go()
    -    end.
    -module(bar).
    --export([f1/0,f3/0]).
    -f1() ->
    -    f2(),
    +            bar:f1(),
    +            go()
    +    end.
    -module(bar).
    +-export([f1/0,f3/0]).
    +f1() ->
    +    f2(),
         ok.
    -f2() ->
    -    spawn(?MODULE,f3,[]).
    -f3() ->
    +f2() ->
    +    spawn(?MODULE,f3,[]).
    +f3() ->
         ok.

    Setting up the trace:

    (tiger@durin)1> %%First we retrieve the Pid to limit traced processes set
    -(tiger@durin)1> Pid = foo:start().
    +(tiger@durin)1> Pid = foo:start().
     (tiger@durin)2> %%Now we set up tracing
    -(tiger@durin)2> ttb:tracer().
    -(tiger@durin)3> ttb:p(Pid, [call, return_to, procs, set_on_spawn]).
    -(tiger@durin)4> ttb:tpl(bar, []).
    +(tiger@durin)2> ttb:tracer().
    +(tiger@durin)3> ttb:p(Pid, [call, return_to, procs, set_on_spawn]).
    +(tiger@durin)4> ttb:tpl(bar, []).
     (tiger@durin)5> %%Invoke our test function and see output with et viewer
     (tiger@durin)5> Pid ! go.
    -(tiger@durin)6> ttb:stop({format, {handler, ttb:get_et_handler()}}).

    This renders a result similar to the following:

    Filter: "processes"

    Filter: "mods_and_procs"

    Notice that function ttb:start_trace/4 can be used as help as follows:

    (tiger@durin)1> Pid = foo:start().
    -(tiger@durin)2> ttb:start_trace([node()],
    -                                [{bar,[]}],
    -                                {Pid, [call, return_to, procs, set_on_spawn]}
    -                                {handler, ttb:get_et_handler()}).
    +(tiger@durin)6> ttb:stop({format, {handler, ttb:get_et_handler()}}).

    This renders a result similar to the following:

    Filter: "processes"

    Filter: "mods_and_procs"

    Notice that function ttb:start_trace/4 can be used as help as follows:

    (tiger@durin)1> Pid = foo:start().
    +(tiger@durin)2> ttb:start_trace([node()],
    +                                [{bar,[]}],
    +                                {Pid, [call, return_to, procs, set_on_spawn]}
    +                                {handler, ttb:get_et_handler()}).
     (tiger@durin)3> Pid ! go.
    -(tiger@durin)4> ttb:stop(format).

    +(tiger@durin)4> ttb:stop(format).

    @@ -638,76 +638,76 @@

    of {Module,Function,Args}.

    Any existing file ConfigFile is deleted and a new file is created when write_config/2 is called. Option append can be used to add something at the end of an existing configuration file, for example, -ttb:write_config(ConfigFile,What,[append]).

    Example:

    See the content of the history buffer:

    (tiger@durin)191> ttb:tracer().
    -{ok,[tiger@durin]}
    -(tiger@durin)192> ttb:p(self(),[garbage_collection,call]).
    -{ok,{[<0.1244.0>],[garbage_collection,call]}}
    -(tiger@durin)193> ttb:tp(ets,new,2,[]).
    -{ok,[{matched,1}]}
    -(tiger@durin)194> ttb:list_history().
    -[{1,{ttb,tracer,[tiger@durin,[]]}},
    - {2,{ttb,p,[<0.1244.0>,[garbage_collection,call]]}},
    - {3,{ttb,tp,[ets,new,2,[]]}}]

    Execute an entry from the history buffer:

    (tiger@durin)195> ttb:ctp(ets,new,2).
    -{ok,[{matched,1}]}
    -(tiger@durin)196> ttb:list_history().
    -[{1,{ttb,tracer,[tiger@durin,[]]}},
    - {2,{ttb,p,[<0.1244.0>,[garbage_collection,call]]}},
    - {3,{ttb,tp,[ets,new,2,[]]}},
    - {4,{ttb,ctp,[ets,new,2]}}]
    -(tiger@durin)197> ttb:run_history(3).
    -ttb:tp(ets,new,2,[]) ->
    -{ok,[{matched,1}]}

    Write the content of the history buffer to a configuration file:

    (tiger@durin)198> ttb:write_config("myconfig",all).
    +ttb:write_config(ConfigFile,What,[append]).

    Example:

    See the content of the history buffer:

    (tiger@durin)191> ttb:tracer().
    +{ok,[tiger@durin]}
    +(tiger@durin)192> ttb:p(self(),[garbage_collection,call]).
    +{ok,{[<0.1244.0>],[garbage_collection,call]}}
    +(tiger@durin)193> ttb:tp(ets,new,2,[]).
    +{ok,[{matched,1}]}
    +(tiger@durin)194> ttb:list_history().
    +[{1,{ttb,tracer,[tiger@durin,[]]}},
    + {2,{ttb,p,[<0.1244.0>,[garbage_collection,call]]}},
    + {3,{ttb,tp,[ets,new,2,[]]}}]

    Execute an entry from the history buffer:

    (tiger@durin)195> ttb:ctp(ets,new,2).
    +{ok,[{matched,1}]}
    +(tiger@durin)196> ttb:list_history().
    +[{1,{ttb,tracer,[tiger@durin,[]]}},
    + {2,{ttb,p,[<0.1244.0>,[garbage_collection,call]]}},
    + {3,{ttb,tp,[ets,new,2,[]]}},
    + {4,{ttb,ctp,[ets,new,2]}}]
    +(tiger@durin)197> ttb:run_history(3).
    +ttb:tp(ets,new,2,[]) ->
    +{ok,[{matched,1}]}

    Write the content of the history buffer to a configuration file:

    (tiger@durin)198> ttb:write_config("myconfig",all).
     ok
    -(tiger@durin)199> ttb:list_config("myconfig").
    -[{1,{ttb,tracer,[tiger@durin,[]]}},
    - {2,{ttb,p,[<0.1244.0>,[garbage_collection,call]]}},
    - {3,{ttb,tp,[ets,new,2,[]]}},
    - {4,{ttb,ctp,[ets,new,2]}},
    - {5,{ttb,tp,[ets,new,2,[]]}}]

    Extend an existing configuration:

    (tiger@durin)200> ttb:write_config("myconfig",[{ttb,tp,[ets,delete,1,[]]}],
    -[append]).
    +(tiger@durin)199> ttb:list_config("myconfig").
    +[{1,{ttb,tracer,[tiger@durin,[]]}},
    + {2,{ttb,p,[<0.1244.0>,[garbage_collection,call]]}},
    + {3,{ttb,tp,[ets,new,2,[]]}},
    + {4,{ttb,ctp,[ets,new,2]}},
    + {5,{ttb,tp,[ets,new,2,[]]}}]

    Extend an existing configuration:

    (tiger@durin)200> ttb:write_config("myconfig",[{ttb,tp,[ets,delete,1,[]]}],
    +[append]).
     ok
    -(tiger@durin)201> ttb:list_config("myconfig").
    -[{1,{ttb,tracer,[tiger@durin,[]]}},
    - {2,{ttb,p,[<0.1244.0>,[garbage_collection,call]]}},
    - {3,{ttb,tp,[ets,new,2,[]]}},
    - {4,{ttb,ctp,[ets,new,2]}},
    - {5,{ttb,tp,[ets,new,2,[]]}},
    - {6,{ttb,tp,[ets,delete,1,[]]}}]

    Go back to a previous configuration after stopping Trace Tool Builder:

    (tiger@durin)202> ttb:stop().
    +(tiger@durin)201> ttb:list_config("myconfig").
    +[{1,{ttb,tracer,[tiger@durin,[]]}},
    + {2,{ttb,p,[<0.1244.0>,[garbage_collection,call]]}},
    + {3,{ttb,tp,[ets,new,2,[]]}},
    + {4,{ttb,ctp,[ets,new,2]}},
    + {5,{ttb,tp,[ets,new,2,[]]}},
    + {6,{ttb,tp,[ets,delete,1,[]]}}]

    Go back to a previous configuration after stopping Trace Tool Builder:

    (tiger@durin)202> ttb:stop().
     ok
    -(tiger@durin)203> ttb:run_config("myconfig").
    -ttb:tracer(tiger@durin,[]) ->
    -{ok,[tiger@durin]}
    +(tiger@durin)203> ttb:run_config("myconfig").
    +ttb:tracer(tiger@durin,[]) ->
    +{ok,[tiger@durin]}
     
    -ttb:p(<0.1244.0>,[garbage_collection,call]) ->
    -{ok,{[<0.1244.0>],[garbage_collection,call]}}
    +ttb:p(<0.1244.0>,[garbage_collection,call]) ->
    +{ok,{[<0.1244.0>],[garbage_collection,call]}}
     
    -ttb:tp(ets,new,2,[]) ->
    -{ok,[{matched,1}]}
    +ttb:tp(ets,new,2,[]) ->
    +{ok,[{matched,1}]}
     
    -ttb:ctp(ets,new,2) ->
    -{ok,[{matched,1}]}
    +ttb:ctp(ets,new,2) ->
    +{ok,[{matched,1}]}
     
    -ttb:tp(ets,new,2,[]) ->
    -{ok,[{matched,1}]}
    +ttb:tp(ets,new,2,[]) ->
    +{ok,[{matched,1}]}
     
    -ttb:tp(ets,delete,1,[]) ->
    -{ok,[{matched,1}]}
    +ttb:tp(ets,delete,1,[]) ->
    +{ok,[{matched,1}]}
     
    -ok

    Write selected entries from the history buffer to a configuration file:

    (tiger@durin)204> ttb:list_history().
    -[{1,{ttb,tracer,[tiger@durin,[]]}},
    - {2,{ttb,p,[<0.1244.0>,[garbage_collection,call]]}},
    - {3,{ttb,tp,[ets,new,2,[]]}},
    - {4,{ttb,ctp,[ets,new,2]}},
    - {5,{ttb,tp,[ets,new,2,[]]}},
    - {6,{ttb,tp,[ets,delete,1,[]]}}]
    -(tiger@durin)205> ttb:write_config("myconfig",[1,2,3,6]).
    +ok

    Write selected entries from the history buffer to a configuration file:

    (tiger@durin)204> ttb:list_history().
    +[{1,{ttb,tracer,[tiger@durin,[]]}},
    + {2,{ttb,p,[<0.1244.0>,[garbage_collection,call]]}},
    + {3,{ttb,tp,[ets,new,2,[]]}},
    + {4,{ttb,ctp,[ets,new,2]}},
    + {5,{ttb,tp,[ets,new,2,[]]}},
    + {6,{ttb,tp,[ets,delete,1,[]]}}]
    +(tiger@durin)205> ttb:write_config("myconfig",[1,2,3,6]).
     ok
    -(tiger@durin)206> ttb:list_config("myconfig").
    -[{1,{ttb,tracer,[tiger@durin,[]]}},
    - {2,{ttb,p,[<0.1244.0>,[garbage_collection,call]]}},
    - {3,{ttb,tp,[ets,new,2,[]]}},
    - {4,{ttb,tp,[ets,delete,1,[]]}}]
    -(tiger@durin)207>

    +(tiger@durin)206> ttb:list_config("myconfig"). +[{1,{ttb,tracer,[tiger@durin,[]]}}, + {2,{ttb,p,[<0.1244.0>,[garbage_collection,call]]}}, + {3,{ttb,tp,[ets,new,2,[]]}}, + {4,{ttb,tp,[ets,delete,1,[]]}}] +(tiger@durin)207>

    @@ -720,40 +720,40 @@

    ttb:tracer/0,1,2. Sequential tracing can then be started in either of the following ways:

    Example 1:

    In the following example, function dbg:get_tracer/0 is used as trigger for -sequential tracing:

    (tiger@durin)110> ttb:tracer().
    -{ok,[tiger@durin]}
    -(tiger@durin)111> ttb:p(self(),call).
    -{ok,{[<0.158.0>],[call]}}
    -(tiger@durin)112> ttb:tp(dbg,get_tracer,0,ttb:seq_trigger_ms(send)).
    -{ok,[{matched,1},{saved,1}]}
    -(tiger@durin)113> dbg:get_tracer(), seq_trace:reset_trace().
    +sequential tracing:

    (tiger@durin)110> ttb:tracer().
    +{ok,[tiger@durin]}
    +(tiger@durin)111> ttb:p(self(),call).
    +{ok,{[<0.158.0>],[call]}}
    +(tiger@durin)112> ttb:tp(dbg,get_tracer,0,ttb:seq_trigger_ms(send)).
    +{ok,[{matched,1},{saved,1}]}
    +(tiger@durin)113> dbg:get_tracer(), seq_trace:reset_trace().
     true
    -(tiger@durin)114> ttb:stop(format).
    -({<0.158.0>,{shell,evaluator,3},tiger@durin}) call dbg:get_tracer()
    -SeqTrace [0]: ({<0.158.0>,{shell,evaluator,3},tiger@durin})
    -{<0.237.0>,dbg,tiger@durin} ! {<0.158.0>,{get_tracer,tiger@durin}}
    -[Serial: {0,1}]
    -SeqTrace [0]: ({<0.237.0>,dbg,tiger@durin})
    -{<0.158.0>,{shell,evaluator,3},tiger@durin} ! {dbg,{ok,#Port<0.222>}}
    -[Serial: {1,2}]
    +(tiger@durin)114> ttb:stop(format).
    +({<0.158.0>,{shell,evaluator,3},tiger@durin}) call dbg:get_tracer()
    +SeqTrace [0]: ({<0.158.0>,{shell,evaluator,3},tiger@durin})
    +{<0.237.0>,dbg,tiger@durin} ! {<0.158.0>,{get_tracer,tiger@durin}}
    +[Serial: {0,1}]
    +SeqTrace [0]: ({<0.237.0>,dbg,tiger@durin})
    +{<0.158.0>,{shell,evaluator,3},tiger@durin} ! {dbg,{ok,#Port<0.222>}}
    +[Serial: {1,2}]
     ok
    -(tiger@durin)116>

    Example 2:

    Starting sequential tracing with a trigger is more useful if the trigger +(tiger@durin)116>

    Example 2:

    Starting sequential tracing with a trigger is more useful if the trigger function is not called directly from the shell, but rather implicitly within a larger system. When calling a function from the shell, it is simpler to start -sequential tracing directly, for example, as follows:

    (tiger@durin)116> ttb:tracer().
    -{ok,[tiger@durin]}
    -(tiger@durin)117> seq_trace:set_token(send,true), dbg:get_tracer(),
    -seq_trace:reset_trace().
    +sequential tracing directly, for example, as follows:

    (tiger@durin)116> ttb:tracer().
    +{ok,[tiger@durin]}
    +(tiger@durin)117> seq_trace:set_token(send,true), dbg:get_tracer(),
    +seq_trace:reset_trace().
     true
    -(tiger@durin)118> ttb:stop(format).
    -SeqTrace [0]: ({<0.158.0>,{shell,evaluator,3},tiger@durin})
    -{<0.246.0>,dbg,tiger@durin} ! {<0.158.0>,{get_tracer,tiger@durin}}
    -[Serial: {0,1}]
    -SeqTrace [0]: ({<0.246.0>,dbg,tiger@durin})
    -{<0.158.0>,{shell,evaluator,3},tiger@durin} ! {dbg,{ok,#Port<0.229>}}
    -[Serial: {1,2}]
    +(tiger@durin)118> ttb:stop(format).
    +SeqTrace [0]: ({<0.158.0>,{shell,evaluator,3},tiger@durin})
    +{<0.246.0>,dbg,tiger@durin} ! {<0.158.0>,{get_tracer,tiger@durin}}
    +[Serial: {0,1}]
    +SeqTrace [0]: ({<0.246.0>,dbg,tiger@durin})
    +{<0.158.0>,{shell,evaluator,3},tiger@durin} ! {dbg,{ok,#Port<0.229>}}
    +[Serial: {1,2}]
     ok
    -(tiger@durin)120>

    In both previous examples, seq_trace:reset_trace/0 resets the trace token +(tiger@durin)120>

    In both previous examples, seq_trace:reset_trace/0 resets the trace token immediately after the traced function to avoid many trace messages because of the printouts in the Erlang shell.

    All functions in module seq_trace, except set_system_tracer/1, can be used after the trace port is started with ttb:tracer/0,1,2.

    diff --git a/prs/9045/lib/odbc-2.15/doc/html/.build b/prs/9045/lib/odbc-2.15/doc/html/.build index 7683f1797640..97e12060d6f2 100644 --- a/prs/9045/lib/odbc-2.15/doc/html/.build +++ b/prs/9045/lib/odbc-2.15/doc/html/.build @@ -21,7 +21,7 @@ dist/lato-latin-ext-300-normal-VPGGJKJL.woff2 dist/lato-latin-ext-400-normal-N27NCBWW.woff2 dist/lato-latin-ext-700-normal-Q2L5DVMW.woff2 dist/remixicon-NKANDIL5.woff2 -dist/search_data-8746A0E5.js +dist/search_data-5F40933F.js dist/sidebar_items-19ECDBA9.js error_handling.html getting_started.html diff --git a/prs/9045/lib/odbc-2.15/doc/html/dist/search_data-5F40933F.js b/prs/9045/lib/odbc-2.15/doc/html/dist/search_data-5F40933F.js new file mode 100644 index 000000000000..69a31e2e4cd3 --- /dev/null +++ b/prs/9045/lib/odbc-2.15/doc/html/dist/search_data-5F40933F.js @@ -0,0 +1 @@ +searchData={"items":[{"type":"module","title":"odbc","doc":"Erlang ODBC application\n\nThis application provides an Erlang interface to communicate with relational\nSQL-databases. It is built on top of Microsofts ODBC interface and therefore\nrequires that you have an ODBC driver to the database that you want to connect\nto.\n\n> #### Note {: .info }\n>\n> The functions `first/[1,2]`, `last/[1,2]`, `next/[1,2]`, `prev[1,2]` and\n> `select/[3,4]` assumes there is a result set associated with the connection to\n> work on. Calling the function `select_count/[2,3]` associates such a result\n> set with the connection. Calling select_count again will remove the current\n> result set association and create a new one. Calling a function which dose not\n> operate on an associated result sets, such as `sql_query/[2,3]`, will remove\n> the current result set association.\n>\n> Alas some drivers only support sequential traversal of the result set, e.i.\n> they do not support what in the ODBC world is known as scrollable cursors.\n> This will have the effect that functions such as `first/[1,2]`, `last/[1,2]`,\n> `prev[1,2]`, etc will return `{error, driver_does_not_support_function}`","ref":"odbc.html"},{"type":"module","title":"Error Handling - odbc","doc":"The error handling strategy and possible errors sources are described in the\nErlang ODBC [User's Guide.](error_handling.md)","ref":"odbc.html#module-error-handling"},{"type":"module","title":"References - odbc","doc":"\\[1]: Microsoft ODBC 3.0, Programmer's Reference and SDK Guide \nSee also http://msdn.microsoft.com/","ref":"odbc.html#module-references"},{"type":"function","title":"odbc.commit/2","doc":"","ref":"odbc.html#commit/2"},{"type":"function","title":"odbc.commit/3","doc":"Commits or rollbacks a transaction. Needed on connections where automatic commit\nis turned off.","ref":"odbc.html#commit/3"},{"type":"function","title":"odbc.connect/2","doc":"Opens a connection to the database. The connection is associated with the\nprocess that created it and can only be accessed through it. This function may\nspawn new processes to handle the connection. These processes will terminate if\nthe process that created the connection dies or if you call disconnect/1.\n\nIf automatic commit mode is turned on, each query will be considered as an\nindividual transaction and will be automatically committed after it has been\nexecuted. If you want more than one query to be part of the same transaction the\nautomatic commit mode should be turned off. Then you will have to call commit/3\nexplicitly to end a transaction.\n\nThe default timeout is infinity\n\nIf the option binary_strings is turned on all strings will be returned as\nbinaries and strings inputted to param_query will be expected to be binaries.\nThe user needs to ensure that the binary is in an encoding that the database\nexpects. By default this option is turned off.\n\nAs default result sets are returned as a lists of tuples. The `TupleMode` option\nstill exists to keep some degree of backwards compatibility. If the option is\nset to off, result sets will be returned as a lists of lists instead of a lists\nof tuples.\n\nScrollable cursors are nice but causes some overhead. For some connections speed\nmight be more important than flexible data access and then you can disable\nscrollable cursor for a connection, limiting the API but gaining speed.\n\n> #### Note {: .info }\n>\n> Turning the scrollable_cursors option off is noted to make old odbc-drivers\n> able to connect that will otherwise fail.\n\nIf trace mode is turned on this tells the ODBC driver to write a trace log to\nthe file SQL.LOG that is placed in the current directory of the erlang emulator.\nThis information may be useful if you suspect there might be a bug in the erlang\nODBC application, and it might be relevant for you to send this file to our\nsupport. Otherwise you will probably not have much use of this.\n\n> #### Note {: .info }\n>\n> For more information about the `ConnectStr` see description of the function\n> SQLDriverConnect in \\[1].\n\nThe `extended_errors` option enables extended ODBC error information when an\noperation fails. Rather than returning `{error, Reason}`, the failing function\nwill return `{error, {ODBCErrorCode, NativeErrorCode, Reason}}`. Note that this\ninformation is probably of little use when writing database-independent code,\nbut can be of assistance in providing more sophisticated error handling when\ndealing with a known underlying database.\n\n- `ODBCErrorCode` is the ODBC error string returned by the ODBC driver.\n- `NativeErrorCode` is the numeric error code returned by the underlying\n database. The possible values and their meanings are dependent on the database\n being used.\n- `Reason` is as per the `Reason` field when extended errors are not enabled.\n\n> #### Note {: .info }\n>\n> The current implementation spawns a port program written in C that utilizes\n> the actual ODBC driver. There is a default timeout of 5000 msec for this port\n> program to connect to the Erlang ODBC application. This timeout can be changed\n> by setting an application specific environment variable 'port_timeout' with\n> the number of milliseconds for the ODBC application. E.g.: \\[\\{odbc,\n> [\\{port_timeout, 60000\\}]\\}] to set it to 60 seconds.","ref":"odbc.html#connect/2"},{"type":"function","title":"odbc.describe_table/2","doc":"","ref":"odbc.html#describe_table/2"},{"type":"function","title":"odbc.describe_table/3","doc":"Queries the database to find out the ODBC data types of the columns of the table\n`Table`.","ref":"odbc.html#describe_table/3"},{"type":"function","title":"odbc.disconnect/1","doc":"Closes a connection to a database. This will also terminate all processes that\nmay have been spawned when the connection was opened. This call will always\nsucceed. If the connection cannot be disconnected gracefully it will be brutally\nkilled. However you may receive an error message as result if you try to\ndisconnect a connection started by another process.[](){: #describe_table }","ref":"odbc.html#disconnect/1"},{"type":"function","title":"odbc.first/1","doc":"","ref":"odbc.html#first/1"},{"type":"function","title":"odbc.first/2","doc":"Returns the first row of the result set and positions a cursor at this row.","ref":"odbc.html#first/2"},{"type":"function","title":"odbc.last/1","doc":"","ref":"odbc.html#last/1"},{"type":"function","title":"odbc.last/2","doc":"Returns the last row of the result set and positions a cursor at this row.","ref":"odbc.html#last/2"},{"type":"function","title":"odbc.next/1","doc":"","ref":"odbc.html#next/1"},{"type":"function","title":"odbc.next/2","doc":"Returns the next row of the result set relative the current cursor position and\npositions the cursor at this row. If the cursor is positioned at the last row of\nthe result set when this function is called the returned value will be\n`{selected, ColNames,[]}` e.i. the list of row values is empty indicating that\nthere is no more data to fetch.[](){: #param_query }","ref":"odbc.html#next/2"},{"type":"function","title":"odbc.param_query/3","doc":"","ref":"odbc.html#param_query/3"},{"type":"function","title":"odbc.param_query/4","doc":"Executes a parameterized SQL query. For an example see the\n[\"Using the Erlang API\"](getting_started.md#param_query) in the Erlang ODBC\nUser's Guide.\n\n> #### Note {: .info }\n>\n> Use the function describe_table/\\[2,3] to find out which ODBC data type that\n> is expected for each column of that table. If a column has a data type that is\n> described with capital letters, alas it is not currently supported by the\n> param_query function. To learn which Erlang data type corresponds to an ODBC\n> data type see the Erlang to ODBC data type [mapping](databases.md#type) in the\n> User's Guide.","ref":"odbc.html#param_query/4"},{"type":"function","title":"odbc.prev/1","doc":"","ref":"odbc.html#prev/1"},{"type":"function","title":"odbc.prev/2","doc":"Returns the previous row of the result set relative the current cursor position\nand positions the cursor at this row.","ref":"odbc.html#prev/2"},{"type":"function","title":"odbc.select/3","doc":"","ref":"odbc.html#select/3"},{"type":"function","title":"odbc.select/4","doc":"Selects `N` consecutive rows of the result set. If `Position` is `next` it is\nsemantically equivalent of calling `next/[1,2]` `N` times. If `Position` is\n`{relative, Pos}`, `Pos` will be used as an offset from the current cursor\nposition to determine the first selected row. If `Position` is\n`{absolute, Pos}`, `Pos` will be the number of the first row selected. After\nthis function has returned the cursor is positioned at the last selected row. If\nthere is less then `N` rows left of the result set the length of `Rows` will be\nless than `N`. If the first row to select happens to be beyond the last row of\nthe result set, the returned value will be `{selected, ColNames,[]}` e.i. the\nlist of row values is empty indicating that there is no more data to fetch.","ref":"odbc.html#select/4"},{"type":"function","title":"odbc.select_count/2","doc":"","ref":"odbc.html#select_count/2"},{"type":"function","title":"odbc.select_count/3","doc":"Executes a SQL SELECT query and associates the result set with the connection. A\ncursor is positioned before the first row in the result set and the tuple\n`{ok, NrRows}` is returned.\n\n> #### Note {: .info }\n>\n> Some drivers may not have the information of the number of rows in the result\n> set, then `NrRows` will have the value `undefined`.","ref":"odbc.html#select_count/3"},{"type":"function","title":"odbc.sql_query/2","doc":"","ref":"odbc.html#sql_query/2"},{"type":"function","title":"odbc.sql_query/3","doc":"Executes a SQL query or a batch of SQL queries. If it is a SELECT query the\nresult set is returned, on the format `{selected, ColNames, Rows}`. For other\nquery types the tuple `{updated, NRows}` is returned, and for batched queries,\nif the driver supports them, this function can also return a list of result\ntuples.\n\n> #### Note {: .info }\n>\n> Some drivers may not have the information of the number of affected rows\n> available and then the return value may be `{updated, undefined} `.\n>\n> The list of column names is ordered in the same way as the list of values of a\n> row, e.g. the first `ColName` is associated with the first `Value` in a `Row`.","ref":"odbc.html#sql_query/3"},{"type":"function","title":"odbc.start/0","doc":"","ref":"odbc.html#start/0"},{"type":"function","title":"odbc.start/1","doc":"Starts the odbc application. Default type is temporary.\n[See application(3)](`m:application`)","ref":"odbc.html#start/1"},{"type":"function","title":"odbc.stop/0","doc":"Stops the odbc application. [See application(3)](`m:application`)","ref":"odbc.html#stop/0"},{"type":"type","title":"odbc.col_name/0","doc":"Name of column in the result set.","ref":"odbc.html#t:col_name/0"},{"type":"type","title":"odbc.common_reason/0","doc":"An explanation of what went wrong. For common errors there will be atom\ndecriptions.","ref":"odbc.html#t:common_reason/0"},{"type":"opaque","title":"odbc.connection_reference/0","doc":"Opaque reference to an ODBC connection as returnded by connect/2.","ref":"odbc.html#t:connection_reference/0"},{"type":"type","title":"odbc.extended_error/0","doc":"extended error type with ODBC and native database error codes, as well as the\nbase reason that would have been returned had extended_errors not been enabled.","ref":"odbc.html#t:extended_error/0"},{"type":"type","title":"odbc.n_rows/0","doc":"The number of affected rows for UPDATE, INSERT, or DELETE queries. For other\nquery types the value is driver defined, and hence should be ignored.","ref":"odbc.html#t:n_rows/0"},{"type":"type","title":"odbc.odbc_data_type/0","doc":"Data type used by ODBC, to learn which Erlang data type corresponds to an ODBC\ndata type see the Erlang to ODBC data type [mapping](databases.md#type) in the\nUser's Guide.","ref":"odbc.html#t:odbc_data_type/0"},{"type":"type","title":"odbc.row/0","doc":"A tuple, with the number of elements selected form columns in a database row,\ncontaing the values of the columns such as `{value(), value() ... value()} `.","ref":"odbc.html#t:row/0"},{"type":"type","title":"odbc.selected/0","doc":"Return value for queries that select data from database tabels.","ref":"odbc.html#t:selected/0"},{"type":"type","title":"odbc.updated/0","doc":"Return value for queries that update database tables.","ref":"odbc.html#t:updated/0"},{"type":"type","title":"odbc.value/0","doc":"Erlang data type that corresponds to the ODBC data type being handled.","ref":"odbc.html#t:value/0"},{"type":"extras","title":"ODBC Release Notes","doc":"\n# ODBC Release Notes\n\nThis document describes the changes made to the odbc application.","ref":"notes.html"},{"type":"extras","title":"ODBC 2.15 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-15"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- Figures in the documentation have been improved.\n\n Own Id: OTP-19130 Aux Id: [PR-7226]\n\n[PR-7226]: https://github.com/erlang/otp/pull/7226","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"ODBC 2.14.3 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-14-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","doc":"- The order of libs in the Makefile has been changed to avoid finding the system's `libei` instead of Erlang's `libei`.\n\n Own Id: OTP-19030 Aux Id: [GH-8244], [PR-8258]\n\n[GH-8244]: https://github.com/erlang/otp/issues/8244\n[PR-8258]: https://github.com/erlang/otp/pull/8258","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- The documentation has been migrated to use Markdown and ExDoc.\n\n Own Id: OTP-18955 Aux Id: [PR-8026]\n\n[PR-8026]: https://github.com/erlang/otp/pull/8026","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"ODBC 2.14.2 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-14-2"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"* Use spec for API doc\n\n Own Id: OTP-18926","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"ODBC 2.14.1 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-14-1"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- Allow larger column sizes than 8001 in case DB supports it.\n\n Own Id: OTP-18539","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"ODBC 2.14 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-14"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- Input for `configure` scripts adapted to `autoconf` 2\\.71.\n\n Own Id: OTP-17414 Aux Id: PR-4967","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"ODBC 2.13.5 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-13-5"},{"type":"extras","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","doc":"- Commit of generated `configure` script.\n\n Own Id: OTP-17420 Aux Id: OTP-17398, GH-4821","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"ODBC 2.13.4 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-13-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","doc":"- Fix compiler warnings produced by the clang compiler.\n\n Own Id: OTP-17105 Aux Id: PR-2872","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"ODBC 2.13.3.1 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-13-3-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","doc":"- Commit of generated `configure` script.\n\n Own Id: OTP-17420 Aux Id: OTP-17398, GH-4821","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"ODBC 2.13.3 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-13-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","doc":"- Make sure odbc c-process exits when erlang process orders it to shutdown.\n\n Own Id: OTP-17188 Aux Id: ERL-1448","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"ODBC 2.13.2 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-13-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","doc":"- Fixed usage of `AC_CONFIG_AUX_DIRS()` macros in configure script sources.\n\n Own Id: OTP-17093 Aux Id: ERL-1447, PR-2948","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"ODBC 2.13.1 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-13-1"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- Changes in order to build on the Haiku operating system.\n\n Thanks to Calvin Buckley\n\n Own Id: OTP-16707 Aux Id: PR-2638","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"ODBC 2.13 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-13"},{"type":"extras","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","doc":"- Fix various compiler warnings on 64-bit Windows.\n\n Own Id: OTP-15800","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- Rewrite due to the removal of `erl_interface` legacy functions.\n\n Own Id: OTP-16544 Aux Id: OTP-16328","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"ODBC 2.12.4.1 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-12-4-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","doc":"- Commit of generated `configure` script.\n\n Own Id: OTP-17420 Aux Id: OTP-17398, GH-4821","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"ODBC 2.12.4 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-12-4"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- Minor adjustments made to build system for parallel configure.\n\n Own Id: OTP-15340 Aux Id: OTP-14625","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"ODBC 2.12.3 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-12-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","doc":"- Enhance error handling to avoid stack corruption\n\n Own Id: OTP-15667 Aux Id: ERL-808, PR-2065","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"ODBC 2.12.2 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-12-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","doc":"- Improved documentation.\n\n Own Id: OTP-15190","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"ODBC 2.12.1 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-12-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","doc":"- Removed all old unused files in the documentation.\n\n Own Id: OTP-14475 Aux Id: ERL-409, PR-1493","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"ODBC 2.12 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-12"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- Change configure to skip odbc for old MACs, the change in PR-1227 is not\n backwards compatible with old MACs, and we do not see a need to continue\n support for such old versions. However it is still possible to make it work on\n such machines using the --with-odbc configure option.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-14083","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"ODBC 2.11.3 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-11-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","doc":"- ODBC build configure has been updated to accept Mac OS X El Capitan. Fixed by\n Lee Bannard.\n\n Own Id: OTP-13781","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"ODBC 2.11.2 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-11-2"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- Configure enhancement for better handling program paths used in the build\n process\n\n Own Id: OTP-13559","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"ODBC 2.11.1 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-11-1"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- New application variable to set timeout of internal communication setup\n between the erlang code and the c-port program that interfaces the odbc\n driver. This can be useful if you have an underlying system that is slow due\n to heavy load at startup.\n\n With this environment variable you can easily bypass and tailor odbc to the\n needs of the underlying actual system without changing the configuration.\n Which is a good thing because this value is very system specific.\n\n Own Id: OTP-12935","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"ODBC 2.11 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-11"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- Change license text from Erlang Public License to Apache Public License v2\n\n Own Id: OTP-12845","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"ODBC 2.10.22 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-10-22"},{"type":"extras","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","doc":"- OS X Mavericks is based on Darwin version 13.x, and Yosemite on 14.x. Change\n the ODBC configure.in script to recognize these versions.\n\n Own Id: OTP-12260","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- The commands longer than 127 chars sent to odbc server crashed it, e.g. a\n connection string with driver path and some additional parameters.\n\n Own Id: OTP-12346\n\n- Distribute `autoconf` helpers to applications at build time instead of having\n multiple identical copies committed in the repository.\n\n Own Id: OTP-12348","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"ODBC 2.10.21 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-10-21"},{"type":"extras","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","doc":"- Fix compiler warnings reported by LLVM\n\n Own Id: OTP-12138\n\n- Implement --enable-sanitizers\\[=sanitizers]. Similar to debugging with\n Valgrind, it's very useful to enable -fsanitize= switches to catch bugs at\n runtime.\n\n Own Id: OTP-12153","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"ODBC 2.10.20 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-10-20"},{"type":"extras","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","doc":"- Application upgrade (appup) files are corrected for the following\n applications:\n\n `asn1, common_test, compiler, crypto, debugger, dialyzer, edoc, eldap, erl_docgen, et, eunit, gs, hipe, inets, observer, odbc, os_mon, otp_mibs, parsetools, percept, public_key, reltool, runtime_tools, ssh, syntax_tools, test_server, tools, typer, webtool, wx, xmerl`\n\n A new test utility for testing appup files is added to test_server. This is\n now used by most applications in OTP.\n\n (Thanks to Tobias Schlager)\n\n Own Id: OTP-11744","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- Removed warnings at compile time by adding missing include file (Thanks to\n Anthony Ramine)\n\n Own Id: OTP-11569\n\n- Apple has removed iODBC in OS X 10.9 Mavericks, but forgot to remove all\n binaries, adopt configure so that will be possible to build odbc with own\n installation.\n\n Own Id: OTP-11630","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"ODBC 2.10.19 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-10-19"},{"type":"extras","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","doc":"- Updated configure test for header files sql.h and sqlext.h to function\n correctly on windows.\n\n Own Id: OTP-11574","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"ODBC 2.10.18 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-10-18"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- Configure now also checks for the existence of the sql.h header file\n\n Own Id: OTP-11483","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"ODBC 2.10.17 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-10-17"},{"type":"extras","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","doc":"- The format of the xml source for documentation is corrected in order to\n conform to the DTDs and to pass xmllint without errors.\n\n Own Id: OTP-11193","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- Introduced functionality for inspection of system and build configuration.\n\n Own Id: OTP-11196\n\n- Prevent odbcserver crash if it's executed and supplied incorrect data to\n stdin. Thanks to Sergei Golovan.\n\n Own Id: OTP-11233","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"ODBC 2.10.16 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-10-16"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- Fix a 64bit related bug in odbcserver. Thanks to Satoshi Kinoshita.\n\n Own Id: OTP-10993\n\n- Postscript files no longer needed for the generation of PDF files have been\n removed.\n\n Own Id: OTP-11016\n\n- Fix checking for odbc in standard locations when \"with-odbc\" flag present.\n Thanks to Alexey Saltanov.\n\n Own Id: OTP-11126","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"ODBC 2.10.15 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-10-15"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- Fixed calling odbc:param_query/3 and odbc:param_query/4 with unparameterized\n query string and empty parameters list. Thanks to Danil Onishchenko.\n\n Own Id: OTP-10798","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"ODBC 2.10.14 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-10-14"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- Under Unix enable TCP_NODELAY to disable Nagel's socket algorithm. Thanks to\n Andy Richards\n\n Impact: Performance gain on Unix systems\n\n Own Id: OTP-10506\n\n- Added extended_errors option to ODBC\n\n When enabled, this option alters the return code of ODBC operations that\n produce errors to include the ODBC error code as well as the native error\n code, in addition to the ODBC reason field which is returned by default.\n Thanks to Bernard Duggan.\n\n Own Id: OTP-10603\n\n- Where necessary a comment stating encoding has been added to Erlang files. The\n comment is meant to be removed in Erlang/OTP R17B when UTF-8 becomes the\n default encoding.\n\n Own Id: OTP-10630\n\n- Some examples overflowing the width of PDF pages have been corrected.\n\n Own Id: OTP-10665\n\n- Fix aotocommit for Oracle ODBC driver in Linux. Thanks to Danil Onishchenko.\n\n Own Id: OTP-10735","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"ODBC 2.10.13 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-10-13"},{"type":"extras","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","doc":"- Add support for NULL value in odbc:param_query\n\n Support atom 'null' in odbc:param_query as database NULL value Fix \"ODBC:\n received unexpected info:\\{tcp_closed, ...\\}\" when connection is terminated.\n Fix possible access violation with 64bit ODBC. Thanks to Maxim Zrazhevskiy\n\n Own Id: OTP-10206","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"ODBC 2.10.12 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-10-12"},{"type":"extras","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","doc":"- An ODBC process should exit normally if its client exits with 'shutdown'\n\n There is nothing strange about the client shutting down, so the ODBC process\n should exit normally to avoid generating a crash report for a non-problem.\n (Thanks to Magnus Henoch)\n\n Own Id: OTP-9716","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- Erlang/OTP can now be built using parallel make if you limit the number of\n jobs, for instance using '`make -j6`' or '`make -j10`'. '`make -j`' does not\n work at the moment because of some missing dependencies.\n\n Own Id: OTP-9451","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"ODBC 2.10.11 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-10-11"},{"type":"extras","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","doc":"- When using output parameters the internal odbc state was not correctly cleaned\n causing the next call to param_query to misbehave.\n\n Own Id: OTP-9444\n\n- XML files have been corrected.\n\n Own Id: OTP-9550 Aux Id: OTP-9541","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- Add code to handle old ODBC drivers on solaris. Also adds tests with MySQL.\n\n Own Id: OTP-8407\n\n- Odbc now supports SQL_WLONGVARCHAR, thanks to Hanfei Shen for the patch.\n\n Own Id: OTP-8493","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"ODBC 2.10.10 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-10-10"},{"type":"extras","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","doc":"- Better error messages for connection issues.\n\n Own Id: OTP-9111","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"ODBC 2.10.9 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-10-9"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- Ipv6 is now supported on Windows as well as on UNIX for internal socket\n communication. (ODBC uses sockets instead of the \"Erlang port pipes\" as some\n ODBC-drivers are known to mess with stdin/stdout.)\n\n Loopback address constants are used when connecting the c-side to the\n erlang-side over local socket API avoiding getaddrinfo problems, and the \\{ip,\n loopback\\} option is added as a listen option on the erlang-side. Also cleaned\n up the TIME_STAMP contribution.\n\n Own Id: OTP-8917","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"ODBC 2.10.8 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-10-8"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- ODBC now handles the types SQL_WCHAR and SQL_WVARCHAR. Thanks to Juhani\n Ränkimies. ODBC also has a new connection option to return all strings as\n binaries and also expect strings to be binaries in the param_query function.\n These changes provides some unicode support.\n\n Own Id: OTP-7452\n\n- Now supports SQL_TYPE_TIMESTAMP on the format \\{\\{YY, MM, DD\\}, \\{HH, MM,\n SS\\}\\}. Thanks to Juhani Ränkimies.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8511","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"ODBC 2.10.7 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-10-7"},{"type":"extras","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","doc":"- The odbc application can now be compiled on FreeBSD. (Thanks to Kenji\n Rikitake.)\n\n Own Id: OTP-8444","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- Cross compilation improvements and other build system improvements.\n\n Most notable:\n\n - Lots of cross compilation improvements. The old cross compilation support\n was more or less non-existing as well as broken. Please, note that the cross\n compilation support should still be considered as experimental. Also note\n that old cross compilation configurations cannot be used without\n modifications. For more information on cross compiling Erlang/OTP see the\n `$ERL_TOP/INSTALL-CROSS.md` file.\n - Support for staged install using\n [DESTDIR](http://www.gnu.org/prep/standards/html_node/DESTDIR.html). The old\n broken `INSTALL_PREFIX` has also been fixed. For more information see the\n `$ERL_TOP/INSTALL.md` file.\n - Documentation of the `release` target of the top `Makefile`. For more\n information see the `$ERL_TOP/INSTALL.md` file.\n - `make install` now by default creates relative symbolic links instead of\n absolute ones. For more information see the `$ERL_TOP/INSTALL.md` file.\n - `$ERL_TOP/configure --help=recursive` now works and prints help for all\n applications with `configure` scripts.\n - Doing `make install`, or `make release` directly after `make all` no longer\n triggers miscellaneous rebuilds.\n - Existing bootstrap system is now used when doing `make install`, or\n `make release` without a preceding `make all`.\n - The `crypto` and `ssl` applications use the same runtime library path when\n dynamically linking against `libssl.so` and `libcrypto.so`. The runtime\n library search path has also been extended.\n - The `configure` scripts of `erl_interface` and `odbc` now search for thread\n libraries and thread library quirks the same way as ERTS do.\n - The `configure` script of the `odbc` application now also looks for odbc\n libraries in `lib64` and `lib/64` directories when building on a 64-bit\n system.\n - The `config.h.in` file in the `erl_interface` application is now\n automatically generated in instead of statically updated which reduces the\n risk of `configure` tests without any effect.\n\n (Thanks to Henrik Riomar for suggestions and testing)\n\n (Thanks to Winston Smith for the AVR32-Linux cross configuration and testing)\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8323\n\n- The documentation is now possible to build in an open source environment after\n a number of bugs are fixed and some features are added in the documentation\n build process.\n\n \\- The arity calculation is updated.\n\n \\- The module prefix used in the function names for bif's are removed in the\n generated links so the links will look like\n \"http://www.erlang.org/doc/man/erlang.html#append_element-2\" instead of\n \"http://www.erlang.org/doc/man/erlang.html#erlang:append_element-2\".\n\n \\- Enhanced the menu positioning in the html documentation when a new page is\n loaded.\n\n \\- A number of corrections in the generation of man pages (thanks to Sergei\n Golovan)\n\n \\- The legal notice is taken from the xml book file so OTP's build process can\n be used for non OTP applications.\n\n Own Id: OTP-8343\n\n- odbc:param_query() now properly indicates if nothing was updated. (Thanks to\n Paul Oliver.)\n\n Own Id: OTP-8347","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Known Bugs and Problems - ODBC Release Notes","doc":"- The ODBC test cases are failing for linux and MacOSX There is problems with\n setting of options on odbc-connections, and the odbcserver just exits with an\n exit code.\n\n Own Id: OTP-8407","ref":"notes.html#known-bugs-and-problems"},{"type":"extras","title":"ODBC 2.10.6 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-10-6"},{"type":"extras","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","doc":"- Applied a patch from Andrew Thompson, which fixes some error cases.\n\n Own Id: OTP-8291","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- The documentation is now built with open source tools (xsltproc and fop) that\n exists on most platforms. One visible change is that the frames are removed.\n\n Own Id: OTP-8250","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"ODBC 2.10.5 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-10-5"},{"type":"extras","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","doc":"- A missing return statement in a non void function has been fixed in `odbc`.\n (Thanks to Nico Kruber)\n\n Own Id: OTP-7978","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"ODBC 2.10.4 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-10-4"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- param_query now handles the in_or_out parameter correctly.\n\n Own Id: OTP-7720\n\n- Changed the internal socket use so that it will become more robust to\n non-functional ipv6 and fallback on ipv4.\n\n Own Id: OTP-7721","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"ODBC 2.10.3 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-10-3"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- Configure update for mac.\n\n Own Id: OTP-7418","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Known Bugs and Problems - ODBC Release Notes","doc":"- describe_table/\\[2,3] on mac gives an empty result\n\n Own Id: OTP-7478","ref":"notes.html#known-bugs-and-problems"},{"type":"extras","title":"ODBC 2.10.2 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-10-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","doc":"- SQLINTEGERs where not retrieved correctly on 64 bit platforms as an SQLINTEGER\n is defined to be a 32 bit integer and not a true long.\n\n Own Id: OTP-7297","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"ODBC 2.10.1 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-10-1"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- Now supports out and input parameters for stored procedures.\n\n Own Id: OTP-7019\n\n- ODBC is now prebuilt for SLES10 in the commercial build and parameters to\n error_logger:error_report/1 has been corrected.\n\n Own Id: OTP-7294\n\n- Parametrized queries will now work correctly when using Erlang R12B-2 on Linux\n (SuSE 10.3), MySQL 5.0.45, myodbc 3.51 and unixODBC 2.2.12. Earlier it could\n happen that an error was returned even though data was correctly inserted into\n the database.\n\n Own Id: OTP-7307","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Known Bugs and Problems - ODBC Release Notes","doc":"- SQLINTEGERs are not retrieved correctly on 64 bit platforms as an SQLINTEGER\n seems to be defined to be a 32 bit integer and not a true long.\n\n Own Id: OTP-7297","ref":"notes.html#known-bugs-and-problems"},{"type":"extras","title":"ODBC 2.10 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-10"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- Enhanced configure to among other things work better when there is a library\n found but it is not usable e.i. 32 bit library in 64 bit build.\n\n Own Id: OTP-7062","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"ODBC 2.0.9 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-0-9"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- The odbc application now has to be explicitly started and stopped e.i. it will\n not automatically be started as a temporary application as it did before.\n Although a practical feature when testing things in the shell, it is not\n desirable that people take advantage of this and not start the odbc\n application in a correct way in their products. Added functions to the odbc\n API that calls application:start/stop.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-6984\n\n- Changed Makefile.in so that odbc is not disabled on 64-bits architectures. It\n was earlier disabled due to that it had never been tested in that environment.\n\n Own Id: OTP-6987","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"ODBC 2.0.8 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-0-8"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- Minor Makefile changes.\n\n Own Id: OTP-6689","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"ODBC 2.0.7 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-0-7"},{"type":"extras","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","doc":"- When using a parameterized query on a windows platform the data was inserted\n in the table on the sql-server but the connection was lost, this seems to be\n due to a compiler error that has now been worked around, but further\n investigation is ongoing to verify that that really was the problem.\n\n Own Id: OTP-5504\n\n- param_query/\\[3,4] could return an unexpected row count for some drivers, in\n this case a postgresdriver.\n\n Own Id: OTP-6363","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"ODBC 2.0.6 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-0-6"},{"type":"extras","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","doc":"- pthread header and library mismatch on linux systems (at least some SuSE and\n Debian) with both NPTL and Linuxthreads libraries installed.\n\n Own Id: OTP-5981","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- Changed configure to find odbc in /usr/local too\n\n Own Id: OTP-5966","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Known Bugs and Problems - ODBC Release Notes","doc":"- When using a parameterized query on a windows platform the data is inserted in\n the table on the sql-server but for some reason the connection is lost.\n\n Own Id: OTP-5504","ref":"notes.html#known-bugs-and-problems"},{"type":"extras","title":"ODBC 2.0.5 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-0-5"},{"type":"extras","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","doc":"- Fixed bug, reported error when deleting nonexisting rows, thanks to Laura M.\n Castro for reporting this.\n\n Own Id: OTP-5759","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Known Bugs and Problems - ODBC Release Notes","doc":"- When using a parameterized query on a windows platform the data is inserted in\n the table on the sql-server but for some reason the connection is lost.\n\n Own Id: OTP-5504","ref":"notes.html#known-bugs-and-problems"},{"type":"extras","title":"Odbc 2.0.4 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-0-4"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- /usr was added as a default place for configure to look for the odbc library\n on unix/linux platforms.\n\n Own Id: OTP-5501\n\n- A legacy timer in the c port program was set to infinity. All timeout handling\n is handled by the erlang code and a extra timeout in the c code will just lead\n to confusion if it is released.\n\n Own Id: OTP-5502","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Known Bugs and Problems - ODBC Release Notes","doc":"- When using a parameterized query on a windows platform the data is inserted in\n the table on the sql-server but for some reason the connection is lost.\n\n Own Id: OTP-5504","ref":"notes.html#known-bugs-and-problems"},{"type":"extras","title":"Odbc 2.0.3 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-0-3"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- odbc now uses configure as all \"normal\" applications instead of providing\n special Makefiles for each commercial supported platform. This also makes it\n easier to build odbc on non supported platforms.\n\n Own Id: OTP-5437","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"odbc 2.0.2 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-0-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","doc":"- When issuing a batch of queries and one of the queries fail the odbc port\n program crashed. This is no longer the case.\n\n Own Id: OTP-5176","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"odbc 2.0.1 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-0-1"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- Added use of the socket option TCP_NODELAY, as in the case of Erlang odbc the\n Nagel algorithm will never help, but always cause an unnecessary delay.\n\n Own Id: OTP-5100","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"odbc 2.0 - ODBC Release Notes","doc":"","ref":"notes.html#odbc-2-0"},{"type":"extras","title":"Improvements and New Features - ODBC Release Notes","doc":"- Erlang ODBC now handles batches of queries and can return multiple result\n sets.\n\n Own Id: OTP-4642 Aux Id: seq7766\n\n- The old interface that became deprecated in odbc 1.0 has now been removed.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-4794\n\n- The port program now sends different exit codes to Erlang when it exits due to\n failure. This instead of sending the same exit code and then trying to write\n to stderr. Erlang encodes the exit code to a descriptive atom.\n\n Own Id: OTP-4813\n\n- Erlang ODBC now supports parameterized queries for the most common ODBC data\n types.\n\n Own Id: OTP-4821\n\n- SQL_NUMERIC and SQL_DECIMAL columns are converted to integer and float values\n if possible.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-4826\n\n- Result sets are now by default returned as a list of tuples which is the most\n intuitive and useful mapping. To keep some degree of backwards compatibility\n you may turn this off to get the old behavior that result sets are returned as\n lists of lists. However do not use this in new code as it is considered a\n deprecated feature that eventually will disappear.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-4850\n\n- The odbc implementation now mostly uses sockets to communicate between the c\n and the erlang process, this is to avoid a lot of problems arising from\n different odbc-drivers doing strange things that disturbed the port-program\n communication mechanism.\n\n Own Id: OTP-4875","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Overview","doc":"\n# Overview","ref":"introduction.html"},{"type":"extras","title":"Purpose - Overview","doc":"The purpose of the Erlang ODBC application is to provide the programmer with an\nODBC interface that has a Erlang/OTP touch and feel. So that the programmer may\nconcentrate on solving his/her actual problem instead of struggling with\npointers and memory allocation which is not very relevant for Erlang. This user\nguide will give you some information about technical issues and provide some\nexamples of how to use the Erlang ODBC interface.","ref":"introduction.html#purpose"},{"type":"extras","title":"About ODBC - Overview","doc":"Open Database Connectivity (ODBC) is a Microsoft standard for accessing\nrelational databases that has become widely used. The ODBC standard provides a\nc-level application programming interface (API) for database access. It uses\nStructured Query Language (SQL) as its database access language.","ref":"introduction.html#about-odbc"},{"type":"extras","title":"About the Erlang ODBC application - Overview","doc":"Provides an Erlang interface to communicate with relational SQL-databases. It is\nbuilt on top of Microsofts ODBC interface and therefore requires that you have\nan ODBC driver to the database that you want to connect to. The Erlang ODBC\napplication is designed using the version 3.0 of the ODBC-standard, however\nusing the option `{scrollable_cursors, off} `for a connection has been known to\nmake it work for at least some 2.X drivers.","ref":"introduction.html#about-the-erlang-odbc-application"},{"type":"extras","title":"Examples","doc":"\n# Examples","ref":"getting_started.html"},{"type":"extras","title":"Setting things up - Examples","doc":"As the Erlang ODBC application is dependent on third party products there are a\nfew administrative things that needs to be done before you can get things up and\nrunning.\n\n- The first thing you need to do, is to make sure you have an ODBC driver\n installed for the database that you want to access. Both the client machine\n where you plan to run your erlang node and the server machine running the\n database needs the the ODBC driver. (In some cases the client and the server\n may be the same machine).\n- Secondly you might need to set environment variables and paths to appropriate\n values. This may differ a lot between different os's, databases and ODBC\n drivers. This is a configuration problem related to the third party product\n and hence we cannot give you a standard solution in this guide.\n- The Erlang ODBC application consists of both `Erlang` and `C` code. The `C`\n code is delivered as a precompiled executable for windows, solaris and linux\n (SLES10) in the commercial build. In the open source distribution it is built\n the same way as all other application using configure and make. You may want\n to provide the the path to your ODBC libraries using --with-odbc=PATH.\n\n> #### Note {: .info }\n>\n> The Erlang ODBC application should run on all Unix dialects including Linux,\n> Windows 2000, Windows XP and NT. But currently it is only tested for Solaris,\n> Windows 2000, Windows XP and NT.","ref":"getting_started.html#setting-things-up"},{"type":"extras","title":"Using the Erlang API - Examples","doc":"The following dialog within the Erlang shell illustrates the functionality of\nthe Erlang ODBC interface. The table used in the example does not have any\nrelevance to anything that exist in reality, it is just a simple example. The\nexample was created using `sqlserver 7.0 with servicepack 1` as database and the\nODBC driver for `sqlserver` with version `2000.80.194.00`.\n\n```text\n 1 > odbc:start().\n ok\n```\n\nConnect to the database\n\n```erlang\n 2 > {ok, Ref} = odbc:connect(\"DSN=sql-server;UID=aladdin;PWD=sesame\", []).\n {ok,<0.342.0>}\n```\n\nCreate a table\n\n```text\n 3 > odbc:sql_query(Ref, \"CREATE TABLE EMPLOYEE (NR integer,\n FIRSTNAME char varying(20), LASTNAME char varying(20), GENDER char(1),\n PRIMARY KEY(NR))\").\n {updated,undefined}\n```\n\nInsert some data\n\n```text\n 4 > odbc:sql_query(Ref, \"INSERT INTO EMPLOYEE VALUES(1, 'Jane', 'Doe', 'F')\").\n {updated,1}\n```\n\nCheck what data types the database assigned for the columns. Hopefully this is\nnot a surprise, some times it can be\\! These are the data types that you should\nuse if you want to do a parameterized query.\n\n```erlang\n 5 > odbc:describe_table(Ref, \"EMPLOYEE\").\n {ok, [{\"NR\", sql_integer},\n {\"FIRSTNAME\", {sql_varchar, 20}},\n {\"LASTNAME\", {sql_varchar, 20}}\n {\"GENDER\", {sql_char, 1}}]}\n```\n\n[](){: #param_query } Use a parameterized query to insert many rows in one go.\n\n```erlang\n 6 > odbc:param_query(Ref,\"INSERT INTO EMPLOYEE (NR, FIRSTNAME, \"\n \"LASTNAME, GENDER) VALUES(?, ?, ?, ?)\",\n [{sql_integer,[2,3,4,5,6,7,8]},\n {{sql_varchar, 20},\n [\"John\", \"Monica\", \"Ross\", \"Rachel\",\n \"Piper\", \"Prue\", \"Louise\"]},\n {{sql_varchar, 20},\n [\"Doe\",\"Geller\",\"Geller\", \"Green\",\n \"Halliwell\", \"Halliwell\", \"Lane\"]},\n {{sql_char, 1}, [\"M\",\"F\",\"M\",\"F\",\"F\",\"F\",\"F\"]}]).\n {updated, 7}\n```\n\nFetch all data in the table employee\n\n```erlang\n 7> odbc:sql_query(Ref, \"SELECT * FROM EMPLOYEE\").\n {selected,[\"NR\",\"FIRSTNAME\",\"LASTNAME\",\"GENDER\"],\n [{1,\"Jane\",\"Doe\",\"F\"},\n {2,\"John\",\"Doe\",\"M\"},\n {3,\"Monica\",\"Geller\",\"F\"},\n {4,\"Ross\",\"Geller\",\"M\"},\n {5,\"Rachel\",\"Green\",\"F\"},\n {6,\"Piper\",\"Halliwell\",\"F\"},\n {7,\"Prue\",\"Halliwell\",\"F\"},\n {8,\"Louise\",\"Lane\",\"F\"}]]}\n```\n\nAssociate a result set containing the whole table `EMPLOYEE` to the connection.\nThe number of rows in the result set is returned.\n\n```erlang\n 8 > odbc:select_count(Ref, \"SELECT * FROM EMPLOYEE\").\n {ok,8}\n```\n\nYou can always traverse the result set sequential by using next\n\n```erlang\n 9 > odbc:next(Ref).\n {selected,[\"NR\",\"FIRSTNAME\",\"LASTNAME\",\"GENDER\"],[{1,\"Jane\",\"Doe\",\"F\"}]}\n```\n\n```erlang\n 10 > odbc:next(Ref).\n {selected,[\"NR\",\"FIRSTNAME\",\"LASTNAME\",\"GENDER\"],[{2,\"John\",\"Doe\",\"M\"}]}\n```\n\nIf your driver supports scrollable cursors you have a little more freedom, and\ncan do things like this.\n\n```erlang\n 11 > odbc:last(Ref).\n {selected,[\"NR\",\"FIRSTNAME\",\"LASTNAME\",\"GENDER\"],[{8,\"Louise\",\"Lane\",\"F\"}]}\n```\n\n```erlang\n 12 > odbc:prev(Ref).\n {selected,[\"NR\",\"FIRSTNAME\",\"LASTNAME\",\"GENDER\"],[{7,\"Prue\",\"Halliwell\",\"F\"}]}\n```\n\n```erlang\n 13 > odbc:first(Ref).\n {selected,[\"NR\",\"FIRSTNAME\",\"LASTNAME\",\"GENDER\"],[{1,\"Jane\",\"Doe\",\"F\"}]}\n```\n\n```erlang\n 14 > odbc:next(Ref).\n {selected,[\"NR\",\"FIRSTNAME\",\"LASTNAME\",\"GENDER\"],[{2,\"John\",\"Doe\",\"M\"}]}\n```\n\nFetch the fields `FIRSTNAME `and `NR `for all female employees\n\n```erlang\n 15 > odbc:sql_query(Ref, \"SELECT FIRSTNAME, NR FROM EMPLOYEE WHERE GENDER = 'F'\").\n {selected,[\"FIRSTNAME\",\"NR\"],\n [{\"Jane\",1},\n {\"Monica\",3},\n {\"Rachel\",5},\n {\"Piper\",6},\n {\"Prue\",7},\n {\"Louise\",8}]}\n```\n\nFetch the fields `FIRSTNAME `and `NR `for all female employees and sort them on\nthe field `FIRSTNAME `.\n\n```erlang\n 16 > odbc:sql_query(Ref, \"SELECT FIRSTNAME, NR FROM EMPLOYEE WHERE GENDER = 'F'\n ORDER BY FIRSTNAME\").\n {selected,[\"FIRSTNAME\",\"NR\"],\n [{\"Jane\",1},\n {\"Louise\",8},\n {\"Monica\",3},\n {\"Piper\",6},\n {\"Prue\",7},\n {\"Rachel\",5}]}\n```\n\nAssociate a result set that contains the fields `FIRSTNAME` and `NR `for all\nfemale employees to the connection. The number of rows in the result set is\nreturned.\n\n```erlang\n 17 > odbc:select_count(Ref, \"SELECT FIRSTNAME, NR FROM EMPLOYEE WHERE GENDER = 'F'\").\n {ok,6}\n```\n\nA few more ways of retrieving parts of the result set when the driver supports\nscrollable cursors. Note that next will work even without support for scrollable\ncursors.\n\n```erlang\n 18 > odbc:select(Ref, {relative, 2}, 3).\n {selected,[\"FIRSTNAME\",\"NR\"],[{\"Monica\",3},{\"Rachel\",5},{\"Piper\",6}]}\n```\n\n```erlang\n 19 > odbc:select(Ref, next, 2).\n {selected,[\"FIRSTNAME\",\"NR\"],[{\"Prue\",7},{\"Louise\",8}]}\n```\n\n```erlang\n 20 > odbc:select(Ref, {absolute, 1}, 2).\n {selected,[\"FIRSTNAME\",\"NR\"],[{\"Jane\",1},{\"Monica\",3}]}\n```\n\n```erlang\n 21 > odbc:select(Ref, next, 2).\n {selected,[\"FIRSTNAME\",\"NR\"],[{\"Rachel\",5},{\"Piper\",6}]}\n```\n\n```erlang\n 22 > odbc:select(Ref, {absolute, 1}, 4).\n {selected,[\"FIRSTNAME\",\"NR\"],\n [{\"Jane\",1},{\"Monica\",3},{\"Rachel\",5},{\"Piper\",6}]}\n```\n\nSelect, using a parameterized query.\n\n```erlang\n 23 > odbc:param_query(Ref, \"SELECT * FROM EMPLOYEE WHERE GENDER=?\",\n [{{sql_char, 1}, [\"M\"]}]).\n {selected,[\"NR\",\"FIRSTNAME\",\"LASTNAME\",\"GENDER\"],\n [{2,\"John\", \"Doe\", \"M\"},{4,\"Ross\",\"Geller\",\"M\"}]}\n```\n\nDelete the table `EMPLOYEE`.\n\n```text\n 24 > odbc:sql_query(Ref, \"DROP TABLE EMPLOYEE\").\n {updated,undefined}\n```\n\nShut down the connection.\n\n```erlang\n 25 > odbc:disconnect(Ref).\n ok\n```\n\nShut down the application.\n\n```text\n 26 > odbc:stop().\n =INFO REPORT==== 7-Jan-2004::17:00:59 ===\n application: odbc\n exited: stopped\n type: temporary\n\n ok\n```","ref":"getting_started.html#using-the-erlang-api"},{"type":"extras","title":"Databases","doc":"\n# Databases","ref":"databases.html"},{"type":"extras","title":"Databases - Databases","doc":"If you need to access a relational database such as `sqlserver`, `mysql`,\n`postgres`, `oracle`, `cybase` etc. from your erlang application using the\nErlang ODBC interface is a good way to go about it.\n\nThe Erlang ODBC application should work for any relational database that has an\nODBC driver. But currently it is only regularly tested for `sqlserver` and\n`postgres`.","ref":"databases.html#databases"},{"type":"extras","title":"Database independence - Databases","doc":"The Erlang ODBC interface is in principal database independent, e.i. an erlang\nprogram using the interface could be run without changes towards different\ndatabases. But as SQL is used it is alas possible to write database dependent\nprograms. Even though SQL is an ANSI-standard meant to be database independent,\ndifferent databases have proprietary extensions to SQL defining their own data\ntypes. If you keep to the ANSI data types you will minimize the problem. But\nunfortunately there is no guarantee that all databases actually treats the ANSI\ndata types equivalently. For instance an installation of\n`Oracle Enterprise release 8.0.5.0.0 for unix` will accept that you create a\ntable column with the ANSI data type `integer`, but when retrieving values from\nthis column the driver reports that it is of type `SQL_DECIMAL(0, 38)` and not\n`SQL_INTEGER` as you may have expected.\n\nAnother obstacle is that some drivers do not support scrollable cursors which\nhas the effect that the only way to traverse the result set is sequentially,\nwith next, from the first row to the last, and once you pass a row you cannot go\nback. This means that some functions in the interface will not work together\nwith certain drivers. A similar problem is that not all drivers support \"row\ncount\" for select queries, hence resulting in that the function\n`select_count/[3,4]` will return `{ok, undefined}` instead of `{ok, NrRows}`\nwhere `NrRows` is the number of rows in the result set.","ref":"databases.html#database-independence"},{"type":"extras","title":"Data types - Databases","doc":"The following is a list of the ANSI data types. For details turn to the ANSI\nstandard documentation. Usage of other data types is of course possible, but you\nshould be aware that this makes your application dependent on the database you\nare using at the moment.\n\n- CHARACTER (size), CHAR (size)\n- NUMERIC (precision, scale), DECIMAL (precision, scale), DEC (precision, scale\n ) precision - total number of digits, scale - total number of decimal places\n- INTEGER, INT, SMALLINT\n- FLOAT (precision)\n- REAL\n- DOUBLE PRECISION\n- CHARACTER VARYING(size), CHAR VARYING(size)\n\nWhen inputting data using sql_query/\\[2,3] the values will always be in string\nformat as they are part of an SQL-query. Example:\n\n```text\n odbc:sql_query(Ref, \"INSERT INTO TEST VALUES(1, 2, 3)\").\n```\n\n> #### Note {: .info }\n>\n> Note that when the value of the data to input is a string, it has to be quoted\n> with `'`. Example:\n>\n> ```text\n> odbc:sql_query(Ref, \"INSERT INTO EMPLOYEE VALUES(1, 'Jane', 'Doe', 'F')\").\n> ```\n\nYou may also input data using [param_query/3,4](`m:odbc#param_query`) and\nthen the input data will have the Erlang type corresponding to the ODBC type of\nthe column.[See ODBC to Erlang mapping](databases.md#type)\n\n[](){: #type } When selecting data from a table, all data types are returned\nfrom the database to the ODBC driver as an ODBC data type. The tables below\nshows the mapping between those data types and what is returned by the Erlang\nAPI.\n\n| ODBC Data Type | Erlang Data Type |\n| ----------------------------------------------------------------------------- | ---------------------------------------------- |\n| SQL_CHAR(size) | String \\| Binary (configurable) |\n| SQL_WCHAR(size) | Unicode binary encoded as UTF16 little endian. |\n| SQL_NUMERIC(p,s) when (p >= 0 and p <= 9 and s == 0) | Integer |\n| SQL_NUMERIC(p,s) when (p >= 10 and p <= 15 and s == 0) or (s <= 15 and s > 0) | Float |\n| SQL_NUMERIC(p,s) when p >= 16 | String |\n| SQL_DECIMAL(p,s) when (p >= 0 and p <= 9 and s == 0) | Integer |\n| SQL_DECIMAL(p,s) when (p >= 10 and p <= 15 and s == 0) or (s <= 15 and s > 0) | Float |\n| SQL_DECIMAL(p,s) when p >= 16 | String |\n| SQL_INTEGER | Integer |\n| SQL_SMALLINT | Integer |\n| SQL_FLOAT | Float |\n| SQL_REAL | Float |\n| SQL_DOUBLE | Float |\n| SQL_VARCHAR(size) | String \\| Binary (configurable) |\n| SQL_WVARCHAR(size) | Unicode binary encoded as UTF16 little endian. |\n\n_Table: Mapping of ODBC data types to the Erlang data types returned to the\nErlang application._\n\n| ODBC Data Type | Erlang Data Type |\n| ---------------------- | ---------------------------------------------- |\n| SQL_TYPE_DATE | String |\n| SQL_TYPE_TIME | String |\n| SQL_TYPE_TIMESTAMP | \\{\\{YY, MM, DD\\}, \\{HH, MM, SS\\}\\} |\n| SQL_LONGVARCHAR | String \\| Binary (configurable) |\n| SQL_WLONGVARCHAR(size) | Unicode binary encoded as UTF16 little endian. |\n| SQL_BINARY | String \\| Binary (configurable) |\n| SQL_VARBINARY | String \\| Binary (configurable) |\n| SQL_LONGVARBINARY | String \\| Binary (configurable) |\n| SQL_TINYINT | Integer |\n| SQL_BIT | Boolean |\n\n_Table: Mapping of extended ODBC data types to the Erlang data types returned to\nthe Erlang application._\n\n> #### Note {: .info }\n>\n> To find out which data types will be returned for the columns in a table use\n> the function [describe_table/2,3](`m:odbc#describe_table`)","ref":"databases.html#data-types"},{"type":"extras","title":"Batch handling - Databases","doc":"Grouping of SQL queries can be desirable in order to reduce network traffic.\nAnother benefit can be that the data source sometimes can optimize execution of\na batch of SQL queries.\n\nExplicit batches an procedures described below will result in multiple results\nbeing returned from sql_query/\\[2,3]. while with parameterized queries only one\nresult will be returned from param_query/\\[2,3].","ref":"databases.html#batch-handling"},{"type":"extras","title":"Explicit batches - Databases","doc":"The most basic form of a batch is created by semicolons separated SQL queries,\nfor example:\n\n```text\n\"SELECT * FROM FOO; SELECT * FROM BAR\" or\n\"INSERT INTO FOO VALUES(1,'bar'); SELECT * FROM FOO\"\n```","ref":"databases.html#explicit-batches"},{"type":"extras","title":"Procedures - Databases","doc":"Different databases may also support creating of procedures that contains more\nthan one SQL query. For example, the following SQLServer-specific statement\ncreates a procedure that returns a result set containing information about\nemployees that work at the department and a result set listing the customers of\nthat department.\n\n```text\n CREATE PROCEDURE DepartmentInfo (@DepartmentID INT) AS\n SELECT * FROM Employee WHERE department = @DepartmentID\n SELECT * FROM Customers WHERE department = @DepartmentID\n```","ref":"databases.html#procedures"},{"type":"extras","title":"Parameterized queries - Databases","doc":"To effectively perform a batch of similar queries, you can use parameterized\nqueries. This means that you in your SQL query string will mark the places that\nusually would contain values with question marks and then provide lists of\nvalues for each parameter. For instance you can use this to insert multiple rows\ninto the `EMPLOYEE` table while executing only a single SQL statement, for\nexample code see [\"Using the Erlang API\"](getting_started.md#param_query)\nsection in the \"Getting Started\" chapter.","ref":"databases.html#parameterized-queries"},{"type":"extras","title":"Error handling","doc":"\n# Error handling","ref":"error_handling.html"},{"type":"extras","title":"Strategy - Error handling","doc":"On a conceptual level starting a database connection using the Erlang ODBC API\nis a basic client server application. The client process uses the API to start\nand communicate with the server process that manages the connection. The\nstrategy of the Erlang ODBC application is that programming faults in the\napplication itself will cause the connection process to terminate\nabnormally.(When a process terminates abnormally its supervisor will log\nrelevant error reports.) Calls to API functions during or after termination of\nthe connection process, will return `{error, connection_closed}`. Contextual\nerrors on the other hand will not terminate the connection it will only return\n`{error, Reason} `to the client, where `Reason` may be any erlang term.","ref":"error_handling.html#strategy"},{"type":"extras","title":"Clients - Error handling","doc":"The connection is associated with the process that created it and can only be\naccessed through it. The reason for this is to preserve the semantics of result\nsets and transactions when select_count/\\[2,3] is called or auto_commit is\nturned off. Attempts to use the connection from another process will fail. This\nwill not effect the connection. On the other hand, if the client process dies\nthe connection will be terminated.","ref":"error_handling.html#clients"},{"type":"extras","title":"Timeouts - Error handling","doc":"All request made by the client to the connection are synchronous. If the timeout\nis used and expires the client process will exit with reason timeout. Probably\nthe right thing to do is let the client die and perhaps be restarted by its\nsupervisor. But if the client chooses to catch this timeout, it is a good idea\nto wait a little while before trying again. If there are too many consecutive\ntimeouts that are caught the connection process will conclude that there is\nsomething radically wrong and terminate the connection.","ref":"error_handling.html#timeouts"},{"type":"extras","title":"Guards - Error handling","doc":"All API-functions are guarded and if you pass an argument of the wrong type a\nruntime error will occur. All input parameters to internal functions are trusted\nto be correct. It is a good programming practise to only distrust input from\ntruly external sources. You are not supposed to catch these errors, it will only\nmake the code very messy and much more complex, which introduces more bugs and\nin the worst case also covers up the actual faults. Put your effort on testing\ninstead, you should trust your own input.","ref":"error_handling.html#guards"},{"type":"extras","title":"The whole picture - Error handling","doc":"As the Erlang ODBC application relies on third party products and communicates\nwith a database that probably runs on another computer in the network there are\nplenty of things that might go wrong. To fully understand the things that might\nhappen it facilitate to know the design of the Erlang ODBC application, hence\nhere follows a short description of the current design.\n\n> #### Note {: .info }\n>\n> Please note that design is something, that not necessarily will, but might\n> change in future releases. While the semantics of the API will not change as\n> it is independent of the implementation.\n\n![Architecture of the Erlang odbc application](assets/odbc_app_arc.gif \"Architecture of the Erlang odbc application\")\n\nWhen you do application:start(odbc) the only thing that happens is that a\nsupervisor process is started. For each call to the API function connect/2 a\nprocess is spawned and added as a child to the Erlang ODBC supervisor. The\nsupervisors only tasks are to provide error-log reports, if a child process\nshould die abnormally, and the possibility to do a code change. Only the client\nprocess has the knowledge to decide if this connection managing process should\nbe restarted.\n\nThe erlang connection process spawned by connect/2, will open a port to a\nc-process that handles the communication with the database through Microsoft's\nODBC API. The erlang port will be kept open for exit signal propagation, if\nsomething goes wrong in the c-process and it exits we want know as mush as\npossible about the reason. The main communication with the c-process is done\nthrough sockets. The C-process consists of two threads, the supervisor thread\nand the database handler thread. The supervisor thread checks for shutdown\nmessages on the supervisor socket and the database handler thread receives\nrequests and sends answers on the database socket. If the database thread seems\nto hang on some database call, the erlang control process will send a shutdown\nmessage on the supervisor socket, in this case the c-process will exit. If the\nc-process crashes/exits it will bring the erlang-process down too and vice versa\ni.e. the connection is terminated.","ref":"error_handling.html#the-whole-picture"},{"type":"extras","title":"Error types - Error handling","doc":"The types of errors that may occur can be divide into the following categories.\n\n- Configuration problems - Everything from that the database was not set up\n right to that the c-program that should be run through the erlang port was not\n compiled for your platform.\n- Errors discovered by the ODBC driver - If calls to the ODBC-driver fails due\n to circumstances that cannot be controlled by the Erlang ODBC application\n programmer, an error string will be dug up from the driver. This string will\n be the `Reason` in the `{error, Reason} `return value. How good this error\n message is will of course be driver dependent. Examples of such circumstances\n are trying to insert the same key twice, invalid SQL-queries and that the\n database has gone off line.\n- Connection termination - If a connection is terminated in an abnormal way, or\n if you try to use a connection that you have already terminated in a normal\n way by calling disconnect/1, the return value will\n be`{error, connection_closed}`. A connection could end abnormally because of\n an programming error in the Erlang ODBC application, but also if the ODBC\n driver crashes.\n- Contextual errors - If API functions are used in the wrong context, the\n `Reason` in the error tuple will be a descriptive atom. For instance if you\n try to call the function `last/[1,2] `without first calling\n `select_count/[2,3] `to associate a result set with the connection. If the\n ODBC-driver does not support some functions, or if you disabled some\n functionality for a connection and then try to use it.","ref":"error_handling.html#error-types"}],"content_type":"text/plain","producer":{"name":"ex_doc","version":[48,46,51,52,46,49]}} \ No newline at end of file diff --git a/prs/9045/lib/odbc-2.15/doc/html/dist/search_data-8746A0E5.js b/prs/9045/lib/odbc-2.15/doc/html/dist/search_data-8746A0E5.js deleted file mode 100644 index 5244908ab229..000000000000 --- a/prs/9045/lib/odbc-2.15/doc/html/dist/search_data-8746A0E5.js +++ /dev/null @@ -1 +0,0 @@ -searchData={"items":[{"type":"module","doc":"Erlang ODBC application\n\nThis application provides an Erlang interface to communicate with relational\nSQL-databases. It is built on top of Microsofts ODBC interface and therefore\nrequires that you have an ODBC driver to the database that you want to connect\nto.\n\n> #### Note {: .info }\n>\n> The functions `first/[1,2]`, `last/[1,2]`, `next/[1,2]`, `prev[1,2]` and\n> `select/[3,4]` assumes there is a result set associated with the connection to\n> work on. Calling the function `select_count/[2,3]` associates such a result\n> set with the connection. Calling select_count again will remove the current\n> result set association and create a new one. Calling a function which dose not\n> operate on an associated result sets, such as `sql_query/[2,3]`, will remove\n> the current result set association.\n>\n> Alas some drivers only support sequential traversal of the result set, e.i.\n> they do not support what in the ODBC world is known as scrollable cursors.\n> This will have the effect that functions such as `first/[1,2]`, `last/[1,2]`,\n> `prev[1,2]`, etc will return `{error, driver_does_not_support_function}`","title":"odbc","ref":"odbc.html"},{"type":"module","doc":"The error handling strategy and possible errors sources are described in the\nErlang ODBC [User's Guide.](error_handling.md)","title":"Error Handling - odbc","ref":"odbc.html#module-error-handling"},{"type":"module","doc":"\\[1]: Microsoft ODBC 3.0, Programmer's Reference and SDK Guide \nSee also http://msdn.microsoft.com/","title":"References - odbc","ref":"odbc.html#module-references"},{"type":"function","doc":"","title":"odbc.commit/2","ref":"odbc.html#commit/2"},{"type":"function","doc":"Commits or rollbacks a transaction. Needed on connections where automatic commit\nis turned off.","title":"odbc.commit/3","ref":"odbc.html#commit/3"},{"type":"function","doc":"Opens a connection to the database. The connection is associated with the\nprocess that created it and can only be accessed through it. This function may\nspawn new processes to handle the connection. These processes will terminate if\nthe process that created the connection dies or if you call disconnect/1.\n\nIf automatic commit mode is turned on, each query will be considered as an\nindividual transaction and will be automatically committed after it has been\nexecuted. If you want more than one query to be part of the same transaction the\nautomatic commit mode should be turned off. Then you will have to call commit/3\nexplicitly to end a transaction.\n\nThe default timeout is infinity\n\nIf the option binary_strings is turned on all strings will be returned as\nbinaries and strings inputted to param_query will be expected to be binaries.\nThe user needs to ensure that the binary is in an encoding that the database\nexpects. By default this option is turned off.\n\nAs default result sets are returned as a lists of tuples. The `TupleMode` option\nstill exists to keep some degree of backwards compatibility. If the option is\nset to off, result sets will be returned as a lists of lists instead of a lists\nof tuples.\n\nScrollable cursors are nice but causes some overhead. For some connections speed\nmight be more important than flexible data access and then you can disable\nscrollable cursor for a connection, limiting the API but gaining speed.\n\n> #### Note {: .info }\n>\n> Turning the scrollable_cursors option off is noted to make old odbc-drivers\n> able to connect that will otherwise fail.\n\nIf trace mode is turned on this tells the ODBC driver to write a trace log to\nthe file SQL.LOG that is placed in the current directory of the erlang emulator.\nThis information may be useful if you suspect there might be a bug in the erlang\nODBC application, and it might be relevant for you to send this file to our\nsupport. Otherwise you will probably not have much use of this.\n\n> #### Note {: .info }\n>\n> For more information about the `ConnectStr` see description of the function\n> SQLDriverConnect in \\[1].\n\nThe `extended_errors` option enables extended ODBC error information when an\noperation fails. Rather than returning `{error, Reason}`, the failing function\nwill return `{error, {ODBCErrorCode, NativeErrorCode, Reason}}`. Note that this\ninformation is probably of little use when writing database-independent code,\nbut can be of assistance in providing more sophisticated error handling when\ndealing with a known underlying database.\n\n- `ODBCErrorCode` is the ODBC error string returned by the ODBC driver.\n- `NativeErrorCode` is the numeric error code returned by the underlying\n database. The possible values and their meanings are dependent on the database\n being used.\n- `Reason` is as per the `Reason` field when extended errors are not enabled.\n\n> #### Note {: .info }\n>\n> The current implementation spawns a port program written in C that utilizes\n> the actual ODBC driver. There is a default timeout of 5000 msec for this port\n> program to connect to the Erlang ODBC application. This timeout can be changed\n> by setting an application specific environment variable 'port_timeout' with\n> the number of milliseconds for the ODBC application. E.g.: \\[\\{odbc,\n> [\\{port_timeout, 60000\\}]\\}] to set it to 60 seconds.","title":"odbc.connect/2","ref":"odbc.html#connect/2"},{"type":"function","doc":"","title":"odbc.describe_table/2","ref":"odbc.html#describe_table/2"},{"type":"function","doc":"Queries the database to find out the ODBC data types of the columns of the table\n`Table`.","title":"odbc.describe_table/3","ref":"odbc.html#describe_table/3"},{"type":"function","doc":"Closes a connection to a database. This will also terminate all processes that\nmay have been spawned when the connection was opened. This call will always\nsucceed. If the connection cannot be disconnected gracefully it will be brutally\nkilled. However you may receive an error message as result if you try to\ndisconnect a connection started by another process.[](){: #describe_table }","title":"odbc.disconnect/1","ref":"odbc.html#disconnect/1"},{"type":"function","doc":"","title":"odbc.first/1","ref":"odbc.html#first/1"},{"type":"function","doc":"Returns the first row of the result set and positions a cursor at this row.","title":"odbc.first/2","ref":"odbc.html#first/2"},{"type":"function","doc":"","title":"odbc.last/1","ref":"odbc.html#last/1"},{"type":"function","doc":"Returns the last row of the result set and positions a cursor at this row.","title":"odbc.last/2","ref":"odbc.html#last/2"},{"type":"function","doc":"","title":"odbc.next/1","ref":"odbc.html#next/1"},{"type":"function","doc":"Returns the next row of the result set relative the current cursor position and\npositions the cursor at this row. If the cursor is positioned at the last row of\nthe result set when this function is called the returned value will be\n`{selected, ColNames,[]}` e.i. the list of row values is empty indicating that\nthere is no more data to fetch.[](){: #param_query }","title":"odbc.next/2","ref":"odbc.html#next/2"},{"type":"function","doc":"","title":"odbc.param_query/3","ref":"odbc.html#param_query/3"},{"type":"function","doc":"Executes a parameterized SQL query. For an example see the\n[\"Using the Erlang API\"](getting_started.md#param_query) in the Erlang ODBC\nUser's Guide.\n\n> #### Note {: .info }\n>\n> Use the function describe_table/\\[2,3] to find out which ODBC data type that\n> is expected for each column of that table. If a column has a data type that is\n> described with capital letters, alas it is not currently supported by the\n> param_query function. To learn which Erlang data type corresponds to an ODBC\n> data type see the Erlang to ODBC data type [mapping](databases.md#type) in the\n> User's Guide.","title":"odbc.param_query/4","ref":"odbc.html#param_query/4"},{"type":"function","doc":"","title":"odbc.prev/1","ref":"odbc.html#prev/1"},{"type":"function","doc":"Returns the previous row of the result set relative the current cursor position\nand positions the cursor at this row.","title":"odbc.prev/2","ref":"odbc.html#prev/2"},{"type":"function","doc":"","title":"odbc.select/3","ref":"odbc.html#select/3"},{"type":"function","doc":"Selects `N` consecutive rows of the result set. If `Position` is `next` it is\nsemantically equivalent of calling `next/[1,2]` `N` times. If `Position` is\n`{relative, Pos}`, `Pos` will be used as an offset from the current cursor\nposition to determine the first selected row. If `Position` is\n`{absolute, Pos}`, `Pos` will be the number of the first row selected. After\nthis function has returned the cursor is positioned at the last selected row. If\nthere is less then `N` rows left of the result set the length of `Rows` will be\nless than `N`. If the first row to select happens to be beyond the last row of\nthe result set, the returned value will be `{selected, ColNames,[]}` e.i. the\nlist of row values is empty indicating that there is no more data to fetch.","title":"odbc.select/4","ref":"odbc.html#select/4"},{"type":"function","doc":"","title":"odbc.select_count/2","ref":"odbc.html#select_count/2"},{"type":"function","doc":"Executes a SQL SELECT query and associates the result set with the connection. A\ncursor is positioned before the first row in the result set and the tuple\n`{ok, NrRows}` is returned.\n\n> #### Note {: .info }\n>\n> Some drivers may not have the information of the number of rows in the result\n> set, then `NrRows` will have the value `undefined`.","title":"odbc.select_count/3","ref":"odbc.html#select_count/3"},{"type":"function","doc":"","title":"odbc.sql_query/2","ref":"odbc.html#sql_query/2"},{"type":"function","doc":"Executes a SQL query or a batch of SQL queries. If it is a SELECT query the\nresult set is returned, on the format `{selected, ColNames, Rows}`. For other\nquery types the tuple `{updated, NRows}` is returned, and for batched queries,\nif the driver supports them, this function can also return a list of result\ntuples.\n\n> #### Note {: .info }\n>\n> Some drivers may not have the information of the number of affected rows\n> available and then the return value may be `{updated, undefined} `.\n>\n> The list of column names is ordered in the same way as the list of values of a\n> row, e.g. the first `ColName` is associated with the first `Value` in a `Row`.","title":"odbc.sql_query/3","ref":"odbc.html#sql_query/3"},{"type":"function","doc":"","title":"odbc.start/0","ref":"odbc.html#start/0"},{"type":"function","doc":"Starts the odbc application. Default type is temporary.\n[See application(3)](`m:application`)","title":"odbc.start/1","ref":"odbc.html#start/1"},{"type":"function","doc":"Stops the odbc application. [See application(3)](`m:application`)","title":"odbc.stop/0","ref":"odbc.html#stop/0"},{"type":"type","doc":"Name of column in the result set.","title":"odbc.col_name/0","ref":"odbc.html#t:col_name/0"},{"type":"type","doc":"An explanation of what went wrong. For common errors there will be atom\ndecriptions.","title":"odbc.common_reason/0","ref":"odbc.html#t:common_reason/0"},{"type":"opaque","doc":"Opaque reference to an ODBC connection as returnded by connect/2.","title":"odbc.connection_reference/0","ref":"odbc.html#t:connection_reference/0"},{"type":"type","doc":"extended error type with ODBC and native database error codes, as well as the\nbase reason that would have been returned had extended_errors not been enabled.","title":"odbc.extended_error/0","ref":"odbc.html#t:extended_error/0"},{"type":"type","doc":"The number of affected rows for UPDATE, INSERT, or DELETE queries. For other\nquery types the value is driver defined, and hence should be ignored.","title":"odbc.n_rows/0","ref":"odbc.html#t:n_rows/0"},{"type":"type","doc":"Data type used by ODBC, to learn which Erlang data type corresponds to an ODBC\ndata type see the Erlang to ODBC data type [mapping](databases.md#type) in the\nUser's Guide.","title":"odbc.odbc_data_type/0","ref":"odbc.html#t:odbc_data_type/0"},{"type":"type","doc":"A tuple, with the number of elements selected form columns in a database row,\ncontaing the values of the columns such as `{value(), value() ... value()} `.","title":"odbc.row/0","ref":"odbc.html#t:row/0"},{"type":"type","doc":"Return value for queries that select data from database tabels.","title":"odbc.selected/0","ref":"odbc.html#t:selected/0"},{"type":"type","doc":"Return value for queries that update database tables.","title":"odbc.updated/0","ref":"odbc.html#t:updated/0"},{"type":"type","doc":"Erlang data type that corresponds to the ODBC data type being handled.","title":"odbc.value/0","ref":"odbc.html#t:value/0"},{"type":"extras","doc":"\n# ODBC Release Notes\n\nThis document describes the changes made to the odbc application.","title":"ODBC Release Notes","ref":"notes.html"},{"type":"extras","doc":"","title":"ODBC 2.15 - ODBC Release Notes","ref":"notes.html#odbc-2-15"},{"type":"extras","doc":"- Figures in the documentation have been improved.\n\n Own Id: OTP-19130 Aux Id: [PR-7226]\n\n[PR-7226]: https://github.com/erlang/otp/pull/7226","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"ODBC 2.14.3 - ODBC Release Notes","ref":"notes.html#odbc-2-14-3"},{"type":"extras","doc":"- The order of libs in the Makefile has been changed to avoid finding the system's `libei` instead of Erlang's `libei`.\n\n Own Id: OTP-19030 Aux Id: [GH-8244], [PR-8258]\n\n[GH-8244]: https://github.com/erlang/otp/issues/8244\n[PR-8258]: https://github.com/erlang/otp/pull/8258","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The documentation has been migrated to use Markdown and ExDoc.\n\n Own Id: OTP-18955 Aux Id: [PR-8026]\n\n[PR-8026]: https://github.com/erlang/otp/pull/8026","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"ODBC 2.14.2 - ODBC Release Notes","ref":"notes.html#odbc-2-14-2"},{"type":"extras","doc":"* Use spec for API doc\n\n Own Id: OTP-18926","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"ODBC 2.14.1 - ODBC Release Notes","ref":"notes.html#odbc-2-14-1"},{"type":"extras","doc":"- Allow larger column sizes than 8001 in case DB supports it.\n\n Own Id: OTP-18539","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"ODBC 2.14 - ODBC Release Notes","ref":"notes.html#odbc-2-14"},{"type":"extras","doc":"- Input for `configure` scripts adapted to `autoconf` 2\\.71.\n\n Own Id: OTP-17414 Aux Id: PR-4967","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"ODBC 2.13.5 - ODBC Release Notes","ref":"notes.html#odbc-2-13-5"},{"type":"extras","doc":"- Commit of generated `configure` script.\n\n Own Id: OTP-17420 Aux Id: OTP-17398, GH-4821","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"ODBC 2.13.4 - ODBC Release Notes","ref":"notes.html#odbc-2-13-4"},{"type":"extras","doc":"- Fix compiler warnings produced by the clang compiler.\n\n Own Id: OTP-17105 Aux Id: PR-2872","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"ODBC 2.13.3.1 - ODBC Release Notes","ref":"notes.html#odbc-2-13-3-1"},{"type":"extras","doc":"- Commit of generated `configure` script.\n\n Own Id: OTP-17420 Aux Id: OTP-17398, GH-4821","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"ODBC 2.13.3 - ODBC Release Notes","ref":"notes.html#odbc-2-13-3"},{"type":"extras","doc":"- Make sure odbc c-process exits when erlang process orders it to shutdown.\n\n Own Id: OTP-17188 Aux Id: ERL-1448","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"ODBC 2.13.2 - ODBC Release Notes","ref":"notes.html#odbc-2-13-2"},{"type":"extras","doc":"- Fixed usage of `AC_CONFIG_AUX_DIRS()` macros in configure script sources.\n\n Own Id: OTP-17093 Aux Id: ERL-1447, PR-2948","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"ODBC 2.13.1 - ODBC Release Notes","ref":"notes.html#odbc-2-13-1"},{"type":"extras","doc":"- Changes in order to build on the Haiku operating system.\n\n Thanks to Calvin Buckley\n\n Own Id: OTP-16707 Aux Id: PR-2638","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"ODBC 2.13 - ODBC Release Notes","ref":"notes.html#odbc-2-13"},{"type":"extras","doc":"- Fix various compiler warnings on 64-bit Windows.\n\n Own Id: OTP-15800","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Rewrite due to the removal of `erl_interface` legacy functions.\n\n Own Id: OTP-16544 Aux Id: OTP-16328","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"ODBC 2.12.4.1 - ODBC Release Notes","ref":"notes.html#odbc-2-12-4-1"},{"type":"extras","doc":"- Commit of generated `configure` script.\n\n Own Id: OTP-17420 Aux Id: OTP-17398, GH-4821","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"ODBC 2.12.4 - ODBC Release Notes","ref":"notes.html#odbc-2-12-4"},{"type":"extras","doc":"- Minor adjustments made to build system for parallel configure.\n\n Own Id: OTP-15340 Aux Id: OTP-14625","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"ODBC 2.12.3 - ODBC Release Notes","ref":"notes.html#odbc-2-12-3"},{"type":"extras","doc":"- Enhance error handling to avoid stack corruption\n\n Own Id: OTP-15667 Aux Id: ERL-808, PR-2065","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"ODBC 2.12.2 - ODBC Release Notes","ref":"notes.html#odbc-2-12-2"},{"type":"extras","doc":"- Improved documentation.\n\n Own Id: OTP-15190","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"ODBC 2.12.1 - ODBC Release Notes","ref":"notes.html#odbc-2-12-1"},{"type":"extras","doc":"- Removed all old unused files in the documentation.\n\n Own Id: OTP-14475 Aux Id: ERL-409, PR-1493","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"ODBC 2.12 - ODBC Release Notes","ref":"notes.html#odbc-2-12"},{"type":"extras","doc":"- Change configure to skip odbc for old MACs, the change in PR-1227 is not\n backwards compatible with old MACs, and we do not see a need to continue\n support for such old versions. However it is still possible to make it work on\n such machines using the --with-odbc configure option.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-14083","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"ODBC 2.11.3 - ODBC Release Notes","ref":"notes.html#odbc-2-11-3"},{"type":"extras","doc":"- ODBC build configure has been updated to accept Mac OS X El Capitan. Fixed by\n Lee Bannard.\n\n Own Id: OTP-13781","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"ODBC 2.11.2 - ODBC Release Notes","ref":"notes.html#odbc-2-11-2"},{"type":"extras","doc":"- Configure enhancement for better handling program paths used in the build\n process\n\n Own Id: OTP-13559","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"ODBC 2.11.1 - ODBC Release Notes","ref":"notes.html#odbc-2-11-1"},{"type":"extras","doc":"- New application variable to set timeout of internal communication setup\n between the erlang code and the c-port program that interfaces the odbc\n driver. This can be useful if you have an underlying system that is slow due\n to heavy load at startup.\n\n With this environment variable you can easily bypass and tailor odbc to the\n needs of the underlying actual system without changing the configuration.\n Which is a good thing because this value is very system specific.\n\n Own Id: OTP-12935","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"ODBC 2.11 - ODBC Release Notes","ref":"notes.html#odbc-2-11"},{"type":"extras","doc":"- Change license text from Erlang Public License to Apache Public License v2\n\n Own Id: OTP-12845","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"ODBC 2.10.22 - ODBC Release Notes","ref":"notes.html#odbc-2-10-22"},{"type":"extras","doc":"- OS X Mavericks is based on Darwin version 13.x, and Yosemite on 14.x. Change\n the ODBC configure.in script to recognize these versions.\n\n Own Id: OTP-12260","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The commands longer than 127 chars sent to odbc server crashed it, e.g. a\n connection string with driver path and some additional parameters.\n\n Own Id: OTP-12346\n\n- Distribute `autoconf` helpers to applications at build time instead of having\n multiple identical copies committed in the repository.\n\n Own Id: OTP-12348","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"ODBC 2.10.21 - ODBC Release Notes","ref":"notes.html#odbc-2-10-21"},{"type":"extras","doc":"- Fix compiler warnings reported by LLVM\n\n Own Id: OTP-12138\n\n- Implement --enable-sanitizers\\[=sanitizers]. Similar to debugging with\n Valgrind, it's very useful to enable -fsanitize= switches to catch bugs at\n runtime.\n\n Own Id: OTP-12153","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"ODBC 2.10.20 - ODBC Release Notes","ref":"notes.html#odbc-2-10-20"},{"type":"extras","doc":"- Application upgrade (appup) files are corrected for the following\n applications:\n\n `asn1, common_test, compiler, crypto, debugger, dialyzer, edoc, eldap, erl_docgen, et, eunit, gs, hipe, inets, observer, odbc, os_mon, otp_mibs, parsetools, percept, public_key, reltool, runtime_tools, ssh, syntax_tools, test_server, tools, typer, webtool, wx, xmerl`\n\n A new test utility for testing appup files is added to test_server. This is\n now used by most applications in OTP.\n\n (Thanks to Tobias Schlager)\n\n Own Id: OTP-11744","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Removed warnings at compile time by adding missing include file (Thanks to\n Anthony Ramine)\n\n Own Id: OTP-11569\n\n- Apple has removed iODBC in OS X 10.9 Mavericks, but forgot to remove all\n binaries, adopt configure so that will be possible to build odbc with own\n installation.\n\n Own Id: OTP-11630","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"ODBC 2.10.19 - ODBC Release Notes","ref":"notes.html#odbc-2-10-19"},{"type":"extras","doc":"- Updated configure test for header files sql.h and sqlext.h to function\n correctly on windows.\n\n Own Id: OTP-11574","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"ODBC 2.10.18 - ODBC Release Notes","ref":"notes.html#odbc-2-10-18"},{"type":"extras","doc":"- Configure now also checks for the existence of the sql.h header file\n\n Own Id: OTP-11483","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"ODBC 2.10.17 - ODBC Release Notes","ref":"notes.html#odbc-2-10-17"},{"type":"extras","doc":"- The format of the xml source for documentation is corrected in order to\n conform to the DTDs and to pass xmllint without errors.\n\n Own Id: OTP-11193","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Introduced functionality for inspection of system and build configuration.\n\n Own Id: OTP-11196\n\n- Prevent odbcserver crash if it's executed and supplied incorrect data to\n stdin. Thanks to Sergei Golovan.\n\n Own Id: OTP-11233","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"ODBC 2.10.16 - ODBC Release Notes","ref":"notes.html#odbc-2-10-16"},{"type":"extras","doc":"- Fix a 64bit related bug in odbcserver. Thanks to Satoshi Kinoshita.\n\n Own Id: OTP-10993\n\n- Postscript files no longer needed for the generation of PDF files have been\n removed.\n\n Own Id: OTP-11016\n\n- Fix checking for odbc in standard locations when \"with-odbc\" flag present.\n Thanks to Alexey Saltanov.\n\n Own Id: OTP-11126","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"ODBC 2.10.15 - ODBC Release Notes","ref":"notes.html#odbc-2-10-15"},{"type":"extras","doc":"- Fixed calling odbc:param_query/3 and odbc:param_query/4 with unparameterized\n query string and empty parameters list. Thanks to Danil Onishchenko.\n\n Own Id: OTP-10798","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"ODBC 2.10.14 - ODBC Release Notes","ref":"notes.html#odbc-2-10-14"},{"type":"extras","doc":"- Under Unix enable TCP_NODELAY to disable Nagel's socket algorithm. Thanks to\n Andy Richards\n\n Impact: Performance gain on Unix systems\n\n Own Id: OTP-10506\n\n- Added extended_errors option to ODBC\n\n When enabled, this option alters the return code of ODBC operations that\n produce errors to include the ODBC error code as well as the native error\n code, in addition to the ODBC reason field which is returned by default.\n Thanks to Bernard Duggan.\n\n Own Id: OTP-10603\n\n- Where necessary a comment stating encoding has been added to Erlang files. The\n comment is meant to be removed in Erlang/OTP R17B when UTF-8 becomes the\n default encoding.\n\n Own Id: OTP-10630\n\n- Some examples overflowing the width of PDF pages have been corrected.\n\n Own Id: OTP-10665\n\n- Fix aotocommit for Oracle ODBC driver in Linux. Thanks to Danil Onishchenko.\n\n Own Id: OTP-10735","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"ODBC 2.10.13 - ODBC Release Notes","ref":"notes.html#odbc-2-10-13"},{"type":"extras","doc":"- Add support for NULL value in odbc:param_query\n\n Support atom 'null' in odbc:param_query as database NULL value Fix \"ODBC:\n received unexpected info:\\{tcp_closed, ...\\}\" when connection is terminated.\n Fix possible access violation with 64bit ODBC. Thanks to Maxim Zrazhevskiy\n\n Own Id: OTP-10206","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"ODBC 2.10.12 - ODBC Release Notes","ref":"notes.html#odbc-2-10-12"},{"type":"extras","doc":"- An ODBC process should exit normally if its client exits with 'shutdown'\n\n There is nothing strange about the client shutting down, so the ODBC process\n should exit normally to avoid generating a crash report for a non-problem.\n (Thanks to Magnus Henoch)\n\n Own Id: OTP-9716","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Erlang/OTP can now be built using parallel make if you limit the number of\n jobs, for instance using '`make -j6`' or '`make -j10`'. '`make -j`' does not\n work at the moment because of some missing dependencies.\n\n Own Id: OTP-9451","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"ODBC 2.10.11 - ODBC Release Notes","ref":"notes.html#odbc-2-10-11"},{"type":"extras","doc":"- When using output parameters the internal odbc state was not correctly cleaned\n causing the next call to param_query to misbehave.\n\n Own Id: OTP-9444\n\n- XML files have been corrected.\n\n Own Id: OTP-9550 Aux Id: OTP-9541","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add code to handle old ODBC drivers on solaris. Also adds tests with MySQL.\n\n Own Id: OTP-8407\n\n- Odbc now supports SQL_WLONGVARCHAR, thanks to Hanfei Shen for the patch.\n\n Own Id: OTP-8493","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"ODBC 2.10.10 - ODBC Release Notes","ref":"notes.html#odbc-2-10-10"},{"type":"extras","doc":"- Better error messages for connection issues.\n\n Own Id: OTP-9111","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"ODBC 2.10.9 - ODBC Release Notes","ref":"notes.html#odbc-2-10-9"},{"type":"extras","doc":"- Ipv6 is now supported on Windows as well as on UNIX for internal socket\n communication. (ODBC uses sockets instead of the \"Erlang port pipes\" as some\n ODBC-drivers are known to mess with stdin/stdout.)\n\n Loopback address constants are used when connecting the c-side to the\n erlang-side over local socket API avoiding getaddrinfo problems, and the \\{ip,\n loopback\\} option is added as a listen option on the erlang-side. Also cleaned\n up the TIME_STAMP contribution.\n\n Own Id: OTP-8917","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"ODBC 2.10.8 - ODBC Release Notes","ref":"notes.html#odbc-2-10-8"},{"type":"extras","doc":"- ODBC now handles the types SQL_WCHAR and SQL_WVARCHAR. Thanks to Juhani\n Ränkimies. ODBC also has a new connection option to return all strings as\n binaries and also expect strings to be binaries in the param_query function.\n These changes provides some unicode support.\n\n Own Id: OTP-7452\n\n- Now supports SQL_TYPE_TIMESTAMP on the format \\{\\{YY, MM, DD\\}, \\{HH, MM,\n SS\\}\\}. Thanks to Juhani Ränkimies.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8511","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"ODBC 2.10.7 - ODBC Release Notes","ref":"notes.html#odbc-2-10-7"},{"type":"extras","doc":"- The odbc application can now be compiled on FreeBSD. (Thanks to Kenji\n Rikitake.)\n\n Own Id: OTP-8444","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Cross compilation improvements and other build system improvements.\n\n Most notable:\n\n - Lots of cross compilation improvements. The old cross compilation support\n was more or less non-existing as well as broken. Please, note that the cross\n compilation support should still be considered as experimental. Also note\n that old cross compilation configurations cannot be used without\n modifications. For more information on cross compiling Erlang/OTP see the\n `$ERL_TOP/INSTALL-CROSS.md` file.\n - Support for staged install using\n [DESTDIR](http://www.gnu.org/prep/standards/html_node/DESTDIR.html). The old\n broken `INSTALL_PREFIX` has also been fixed. For more information see the\n `$ERL_TOP/INSTALL.md` file.\n - Documentation of the `release` target of the top `Makefile`. For more\n information see the `$ERL_TOP/INSTALL.md` file.\n - `make install` now by default creates relative symbolic links instead of\n absolute ones. For more information see the `$ERL_TOP/INSTALL.md` file.\n - `$ERL_TOP/configure --help=recursive` now works and prints help for all\n applications with `configure` scripts.\n - Doing `make install`, or `make release` directly after `make all` no longer\n triggers miscellaneous rebuilds.\n - Existing bootstrap system is now used when doing `make install`, or\n `make release` without a preceding `make all`.\n - The `crypto` and `ssl` applications use the same runtime library path when\n dynamically linking against `libssl.so` and `libcrypto.so`. The runtime\n library search path has also been extended.\n - The `configure` scripts of `erl_interface` and `odbc` now search for thread\n libraries and thread library quirks the same way as ERTS do.\n - The `configure` script of the `odbc` application now also looks for odbc\n libraries in `lib64` and `lib/64` directories when building on a 64-bit\n system.\n - The `config.h.in` file in the `erl_interface` application is now\n automatically generated in instead of statically updated which reduces the\n risk of `configure` tests without any effect.\n\n (Thanks to Henrik Riomar for suggestions and testing)\n\n (Thanks to Winston Smith for the AVR32-Linux cross configuration and testing)\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8323\n\n- The documentation is now possible to build in an open source environment after\n a number of bugs are fixed and some features are added in the documentation\n build process.\n\n \\- The arity calculation is updated.\n\n \\- The module prefix used in the function names for bif's are removed in the\n generated links so the links will look like\n \"http://www.erlang.org/doc/man/erlang.html#append_element-2\" instead of\n \"http://www.erlang.org/doc/man/erlang.html#erlang:append_element-2\".\n\n \\- Enhanced the menu positioning in the html documentation when a new page is\n loaded.\n\n \\- A number of corrections in the generation of man pages (thanks to Sergei\n Golovan)\n\n \\- The legal notice is taken from the xml book file so OTP's build process can\n be used for non OTP applications.\n\n Own Id: OTP-8343\n\n- odbc:param_query() now properly indicates if nothing was updated. (Thanks to\n Paul Oliver.)\n\n Own Id: OTP-8347","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"- The ODBC test cases are failing for linux and MacOSX There is problems with\n setting of options on odbc-connections, and the odbcserver just exits with an\n exit code.\n\n Own Id: OTP-8407","title":"Known Bugs and Problems - ODBC Release Notes","ref":"notes.html#known-bugs-and-problems"},{"type":"extras","doc":"","title":"ODBC 2.10.6 - ODBC Release Notes","ref":"notes.html#odbc-2-10-6"},{"type":"extras","doc":"- Applied a patch from Andrew Thompson, which fixes some error cases.\n\n Own Id: OTP-8291","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The documentation is now built with open source tools (xsltproc and fop) that\n exists on most platforms. One visible change is that the frames are removed.\n\n Own Id: OTP-8250","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"ODBC 2.10.5 - ODBC Release Notes","ref":"notes.html#odbc-2-10-5"},{"type":"extras","doc":"- A missing return statement in a non void function has been fixed in `odbc`.\n (Thanks to Nico Kruber)\n\n Own Id: OTP-7978","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"ODBC 2.10.4 - ODBC Release Notes","ref":"notes.html#odbc-2-10-4"},{"type":"extras","doc":"- param_query now handles the in_or_out parameter correctly.\n\n Own Id: OTP-7720\n\n- Changed the internal socket use so that it will become more robust to\n non-functional ipv6 and fallback on ipv4.\n\n Own Id: OTP-7721","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"ODBC 2.10.3 - ODBC Release Notes","ref":"notes.html#odbc-2-10-3"},{"type":"extras","doc":"- Configure update for mac.\n\n Own Id: OTP-7418","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"- describe_table/\\[2,3] on mac gives an empty result\n\n Own Id: OTP-7478","title":"Known Bugs and Problems - ODBC Release Notes","ref":"notes.html#known-bugs-and-problems"},{"type":"extras","doc":"","title":"ODBC 2.10.2 - ODBC Release Notes","ref":"notes.html#odbc-2-10-2"},{"type":"extras","doc":"- SQLINTEGERs where not retrieved correctly on 64 bit platforms as an SQLINTEGER\n is defined to be a 32 bit integer and not a true long.\n\n Own Id: OTP-7297","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"ODBC 2.10.1 - ODBC Release Notes","ref":"notes.html#odbc-2-10-1"},{"type":"extras","doc":"- Now supports out and input parameters for stored procedures.\n\n Own Id: OTP-7019\n\n- ODBC is now prebuilt for SLES10 in the commercial build and parameters to\n error_logger:error_report/1 has been corrected.\n\n Own Id: OTP-7294\n\n- Parametrized queries will now work correctly when using Erlang R12B-2 on Linux\n (SuSE 10.3), MySQL 5.0.45, myodbc 3.51 and unixODBC 2.2.12. Earlier it could\n happen that an error was returned even though data was correctly inserted into\n the database.\n\n Own Id: OTP-7307","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"- SQLINTEGERs are not retrieved correctly on 64 bit platforms as an SQLINTEGER\n seems to be defined to be a 32 bit integer and not a true long.\n\n Own Id: OTP-7297","title":"Known Bugs and Problems - ODBC Release Notes","ref":"notes.html#known-bugs-and-problems"},{"type":"extras","doc":"","title":"ODBC 2.10 - ODBC Release Notes","ref":"notes.html#odbc-2-10"},{"type":"extras","doc":"- Enhanced configure to among other things work better when there is a library\n found but it is not usable e.i. 32 bit library in 64 bit build.\n\n Own Id: OTP-7062","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"ODBC 2.0.9 - ODBC Release Notes","ref":"notes.html#odbc-2-0-9"},{"type":"extras","doc":"- The odbc application now has to be explicitly started and stopped e.i. it will\n not automatically be started as a temporary application as it did before.\n Although a practical feature when testing things in the shell, it is not\n desirable that people take advantage of this and not start the odbc\n application in a correct way in their products. Added functions to the odbc\n API that calls application:start/stop.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-6984\n\n- Changed Makefile.in so that odbc is not disabled on 64-bits architectures. It\n was earlier disabled due to that it had never been tested in that environment.\n\n Own Id: OTP-6987","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"ODBC 2.0.8 - ODBC Release Notes","ref":"notes.html#odbc-2-0-8"},{"type":"extras","doc":"- Minor Makefile changes.\n\n Own Id: OTP-6689","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"ODBC 2.0.7 - ODBC Release Notes","ref":"notes.html#odbc-2-0-7"},{"type":"extras","doc":"- When using a parameterized query on a windows platform the data was inserted\n in the table on the sql-server but the connection was lost, this seems to be\n due to a compiler error that has now been worked around, but further\n investigation is ongoing to verify that that really was the problem.\n\n Own Id: OTP-5504\n\n- param_query/\\[3,4] could return an unexpected row count for some drivers, in\n this case a postgresdriver.\n\n Own Id: OTP-6363","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"ODBC 2.0.6 - ODBC Release Notes","ref":"notes.html#odbc-2-0-6"},{"type":"extras","doc":"- pthread header and library mismatch on linux systems (at least some SuSE and\n Debian) with both NPTL and Linuxthreads libraries installed.\n\n Own Id: OTP-5981","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Changed configure to find odbc in /usr/local too\n\n Own Id: OTP-5966","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"- When using a parameterized query on a windows platform the data is inserted in\n the table on the sql-server but for some reason the connection is lost.\n\n Own Id: OTP-5504","title":"Known Bugs and Problems - ODBC Release Notes","ref":"notes.html#known-bugs-and-problems"},{"type":"extras","doc":"","title":"ODBC 2.0.5 - ODBC Release Notes","ref":"notes.html#odbc-2-0-5"},{"type":"extras","doc":"- Fixed bug, reported error when deleting nonexisting rows, thanks to Laura M.\n Castro for reporting this.\n\n Own Id: OTP-5759","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- When using a parameterized query on a windows platform the data is inserted in\n the table on the sql-server but for some reason the connection is lost.\n\n Own Id: OTP-5504","title":"Known Bugs and Problems - ODBC Release Notes","ref":"notes.html#known-bugs-and-problems"},{"type":"extras","doc":"","title":"Odbc 2.0.4 - ODBC Release Notes","ref":"notes.html#odbc-2-0-4"},{"type":"extras","doc":"- /usr was added as a default place for configure to look for the odbc library\n on unix/linux platforms.\n\n Own Id: OTP-5501\n\n- A legacy timer in the c port program was set to infinity. All timeout handling\n is handled by the erlang code and a extra timeout in the c code will just lead\n to confusion if it is released.\n\n Own Id: OTP-5502","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"- When using a parameterized query on a windows platform the data is inserted in\n the table on the sql-server but for some reason the connection is lost.\n\n Own Id: OTP-5504","title":"Known Bugs and Problems - ODBC Release Notes","ref":"notes.html#known-bugs-and-problems"},{"type":"extras","doc":"","title":"Odbc 2.0.3 - ODBC Release Notes","ref":"notes.html#odbc-2-0-3"},{"type":"extras","doc":"- odbc now uses configure as all \"normal\" applications instead of providing\n special Makefiles for each commercial supported platform. This also makes it\n easier to build odbc on non supported platforms.\n\n Own Id: OTP-5437","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"odbc 2.0.2 - ODBC Release Notes","ref":"notes.html#odbc-2-0-2"},{"type":"extras","doc":"- When issuing a batch of queries and one of the queries fail the odbc port\n program crashed. This is no longer the case.\n\n Own Id: OTP-5176","title":"Fixed Bugs and Malfunctions - ODBC Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"odbc 2.0.1 - ODBC Release Notes","ref":"notes.html#odbc-2-0-1"},{"type":"extras","doc":"- Added use of the socket option TCP_NODELAY, as in the case of Erlang odbc the\n Nagel algorithm will never help, but always cause an unnecessary delay.\n\n Own Id: OTP-5100","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"odbc 2.0 - ODBC Release Notes","ref":"notes.html#odbc-2-0"},{"type":"extras","doc":"- Erlang ODBC now handles batches of queries and can return multiple result\n sets.\n\n Own Id: OTP-4642 Aux Id: seq7766\n\n- The old interface that became deprecated in odbc 1.0 has now been removed.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-4794\n\n- The port program now sends different exit codes to Erlang when it exits due to\n failure. This instead of sending the same exit code and then trying to write\n to stderr. Erlang encodes the exit code to a descriptive atom.\n\n Own Id: OTP-4813\n\n- Erlang ODBC now supports parameterized queries for the most common ODBC data\n types.\n\n Own Id: OTP-4821\n\n- SQL_NUMERIC and SQL_DECIMAL columns are converted to integer and float values\n if possible.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-4826\n\n- Result sets are now by default returned as a list of tuples which is the most\n intuitive and useful mapping. To keep some degree of backwards compatibility\n you may turn this off to get the old behavior that result sets are returned as\n lists of lists. However do not use this in new code as it is considered a\n deprecated feature that eventually will disappear.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-4850\n\n- The odbc implementation now mostly uses sockets to communicate between the c\n and the erlang process, this is to avoid a lot of problems arising from\n different odbc-drivers doing strange things that disturbed the port-program\n communication mechanism.\n\n Own Id: OTP-4875","title":"Improvements and New Features - ODBC Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"\n# Overview","title":"Overview","ref":"introduction.html"},{"type":"extras","doc":"The purpose of the Erlang ODBC application is to provide the programmer with an\nODBC interface that has a Erlang/OTP touch and feel. So that the programmer may\nconcentrate on solving his/her actual problem instead of struggling with\npointers and memory allocation which is not very relevant for Erlang. This user\nguide will give you some information about technical issues and provide some\nexamples of how to use the Erlang ODBC interface.","title":"Purpose - Overview","ref":"introduction.html#purpose"},{"type":"extras","doc":"Open Database Connectivity (ODBC) is a Microsoft standard for accessing\nrelational databases that has become widely used. The ODBC standard provides a\nc-level application programming interface (API) for database access. It uses\nStructured Query Language (SQL) as its database access language.","title":"About ODBC - Overview","ref":"introduction.html#about-odbc"},{"type":"extras","doc":"Provides an Erlang interface to communicate with relational SQL-databases. It is\nbuilt on top of Microsofts ODBC interface and therefore requires that you have\nan ODBC driver to the database that you want to connect to. The Erlang ODBC\napplication is designed using the version 3.0 of the ODBC-standard, however\nusing the option `{scrollable_cursors, off} `for a connection has been known to\nmake it work for at least some 2.X drivers.","title":"About the Erlang ODBC application - Overview","ref":"introduction.html#about-the-erlang-odbc-application"},{"type":"extras","doc":"\n# Examples","title":"Examples","ref":"getting_started.html"},{"type":"extras","doc":"As the Erlang ODBC application is dependent on third party products there are a\nfew administrative things that needs to be done before you can get things up and\nrunning.\n\n- The first thing you need to do, is to make sure you have an ODBC driver\n installed for the database that you want to access. Both the client machine\n where you plan to run your erlang node and the server machine running the\n database needs the the ODBC driver. (In some cases the client and the server\n may be the same machine).\n- Secondly you might need to set environment variables and paths to appropriate\n values. This may differ a lot between different os's, databases and ODBC\n drivers. This is a configuration problem related to the third party product\n and hence we cannot give you a standard solution in this guide.\n- The Erlang ODBC application consists of both `Erlang` and `C` code. The `C`\n code is delivered as a precompiled executable for windows, solaris and linux\n (SLES10) in the commercial build. In the open source distribution it is built\n the same way as all other application using configure and make. You may want\n to provide the the path to your ODBC libraries using --with-odbc=PATH.\n\n> #### Note {: .info }\n>\n> The Erlang ODBC application should run on all Unix dialects including Linux,\n> Windows 2000, Windows XP and NT. But currently it is only tested for Solaris,\n> Windows 2000, Windows XP and NT.","title":"Setting things up - Examples","ref":"getting_started.html#setting-things-up"},{"type":"extras","doc":"The following dialog within the Erlang shell illustrates the functionality of\nthe Erlang ODBC interface. The table used in the example does not have any\nrelevance to anything that exist in reality, it is just a simple example. The\nexample was created using `sqlserver 7.0 with servicepack 1` as database and the\nODBC driver for `sqlserver` with version `2000.80.194.00`.\n\n```text\n 1 > odbc:start().\n ok\n```\n\nConnect to the database\n\n```erlang\n 2 > {ok, Ref} = odbc:connect(\"DSN=sql-server;UID=aladdin;PWD=sesame\", []).\n {ok,<0.342.0>}\n```\n\nCreate a table\n\n```text\n 3 > odbc:sql_query(Ref, \"CREATE TABLE EMPLOYEE (NR integer,\n FIRSTNAME char varying(20), LASTNAME char varying(20), GENDER char(1),\n PRIMARY KEY(NR))\").\n {updated,undefined}\n```\n\nInsert some data\n\n```text\n 4 > odbc:sql_query(Ref, \"INSERT INTO EMPLOYEE VALUES(1, 'Jane', 'Doe', 'F')\").\n {updated,1}\n```\n\nCheck what data types the database assigned for the columns. Hopefully this is\nnot a surprise, some times it can be\\! These are the data types that you should\nuse if you want to do a parameterized query.\n\n```erlang\n 5 > odbc:describe_table(Ref, \"EMPLOYEE\").\n {ok, [{\"NR\", sql_integer},\n {\"FIRSTNAME\", {sql_varchar, 20}},\n {\"LASTNAME\", {sql_varchar, 20}}\n {\"GENDER\", {sql_char, 1}}]}\n```\n\n[](){: #param_query } Use a parameterized query to insert many rows in one go.\n\n```erlang\n 6 > odbc:param_query(Ref,\"INSERT INTO EMPLOYEE (NR, FIRSTNAME, \"\n \"LASTNAME, GENDER) VALUES(?, ?, ?, ?)\",\n [{sql_integer,[2,3,4,5,6,7,8]},\n {{sql_varchar, 20},\n [\"John\", \"Monica\", \"Ross\", \"Rachel\",\n \"Piper\", \"Prue\", \"Louise\"]},\n {{sql_varchar, 20},\n [\"Doe\",\"Geller\",\"Geller\", \"Green\",\n \"Halliwell\", \"Halliwell\", \"Lane\"]},\n {{sql_char, 1}, [\"M\",\"F\",\"M\",\"F\",\"F\",\"F\",\"F\"]}]).\n {updated, 7}\n```\n\nFetch all data in the table employee\n\n```erlang\n 7> odbc:sql_query(Ref, \"SELECT * FROM EMPLOYEE\").\n {selected,[\"NR\",\"FIRSTNAME\",\"LASTNAME\",\"GENDER\"],\n [{1,\"Jane\",\"Doe\",\"F\"},\n {2,\"John\",\"Doe\",\"M\"},\n {3,\"Monica\",\"Geller\",\"F\"},\n {4,\"Ross\",\"Geller\",\"M\"},\n {5,\"Rachel\",\"Green\",\"F\"},\n {6,\"Piper\",\"Halliwell\",\"F\"},\n {7,\"Prue\",\"Halliwell\",\"F\"},\n {8,\"Louise\",\"Lane\",\"F\"}]]}\n```\n\nAssociate a result set containing the whole table `EMPLOYEE` to the connection.\nThe number of rows in the result set is returned.\n\n```erlang\n 8 > odbc:select_count(Ref, \"SELECT * FROM EMPLOYEE\").\n {ok,8}\n```\n\nYou can always traverse the result set sequential by using next\n\n```erlang\n 9 > odbc:next(Ref).\n {selected,[\"NR\",\"FIRSTNAME\",\"LASTNAME\",\"GENDER\"],[{1,\"Jane\",\"Doe\",\"F\"}]}\n```\n\n```erlang\n 10 > odbc:next(Ref).\n {selected,[\"NR\",\"FIRSTNAME\",\"LASTNAME\",\"GENDER\"],[{2,\"John\",\"Doe\",\"M\"}]}\n```\n\nIf your driver supports scrollable cursors you have a little more freedom, and\ncan do things like this.\n\n```erlang\n 11 > odbc:last(Ref).\n {selected,[\"NR\",\"FIRSTNAME\",\"LASTNAME\",\"GENDER\"],[{8,\"Louise\",\"Lane\",\"F\"}]}\n```\n\n```erlang\n 12 > odbc:prev(Ref).\n {selected,[\"NR\",\"FIRSTNAME\",\"LASTNAME\",\"GENDER\"],[{7,\"Prue\",\"Halliwell\",\"F\"}]}\n```\n\n```erlang\n 13 > odbc:first(Ref).\n {selected,[\"NR\",\"FIRSTNAME\",\"LASTNAME\",\"GENDER\"],[{1,\"Jane\",\"Doe\",\"F\"}]}\n```\n\n```erlang\n 14 > odbc:next(Ref).\n {selected,[\"NR\",\"FIRSTNAME\",\"LASTNAME\",\"GENDER\"],[{2,\"John\",\"Doe\",\"M\"}]}\n```\n\nFetch the fields `FIRSTNAME `and `NR `for all female employees\n\n```erlang\n 15 > odbc:sql_query(Ref, \"SELECT FIRSTNAME, NR FROM EMPLOYEE WHERE GENDER = 'F'\").\n {selected,[\"FIRSTNAME\",\"NR\"],\n [{\"Jane\",1},\n {\"Monica\",3},\n {\"Rachel\",5},\n {\"Piper\",6},\n {\"Prue\",7},\n {\"Louise\",8}]}\n```\n\nFetch the fields `FIRSTNAME `and `NR `for all female employees and sort them on\nthe field `FIRSTNAME `.\n\n```erlang\n 16 > odbc:sql_query(Ref, \"SELECT FIRSTNAME, NR FROM EMPLOYEE WHERE GENDER = 'F'\n ORDER BY FIRSTNAME\").\n {selected,[\"FIRSTNAME\",\"NR\"],\n [{\"Jane\",1},\n {\"Louise\",8},\n {\"Monica\",3},\n {\"Piper\",6},\n {\"Prue\",7},\n {\"Rachel\",5}]}\n```\n\nAssociate a result set that contains the fields `FIRSTNAME` and `NR `for all\nfemale employees to the connection. The number of rows in the result set is\nreturned.\n\n```erlang\n 17 > odbc:select_count(Ref, \"SELECT FIRSTNAME, NR FROM EMPLOYEE WHERE GENDER = 'F'\").\n {ok,6}\n```\n\nA few more ways of retrieving parts of the result set when the driver supports\nscrollable cursors. Note that next will work even without support for scrollable\ncursors.\n\n```erlang\n 18 > odbc:select(Ref, {relative, 2}, 3).\n {selected,[\"FIRSTNAME\",\"NR\"],[{\"Monica\",3},{\"Rachel\",5},{\"Piper\",6}]}\n```\n\n```erlang\n 19 > odbc:select(Ref, next, 2).\n {selected,[\"FIRSTNAME\",\"NR\"],[{\"Prue\",7},{\"Louise\",8}]}\n```\n\n```erlang\n 20 > odbc:select(Ref, {absolute, 1}, 2).\n {selected,[\"FIRSTNAME\",\"NR\"],[{\"Jane\",1},{\"Monica\",3}]}\n```\n\n```erlang\n 21 > odbc:select(Ref, next, 2).\n {selected,[\"FIRSTNAME\",\"NR\"],[{\"Rachel\",5},{\"Piper\",6}]}\n```\n\n```erlang\n 22 > odbc:select(Ref, {absolute, 1}, 4).\n {selected,[\"FIRSTNAME\",\"NR\"],\n [{\"Jane\",1},{\"Monica\",3},{\"Rachel\",5},{\"Piper\",6}]}\n```\n\nSelect, using a parameterized query.\n\n```erlang\n 23 > odbc:param_query(Ref, \"SELECT * FROM EMPLOYEE WHERE GENDER=?\",\n [{{sql_char, 1}, [\"M\"]}]).\n {selected,[\"NR\",\"FIRSTNAME\",\"LASTNAME\",\"GENDER\"],\n [{2,\"John\", \"Doe\", \"M\"},{4,\"Ross\",\"Geller\",\"M\"}]}\n```\n\nDelete the table `EMPLOYEE`.\n\n```text\n 24 > odbc:sql_query(Ref, \"DROP TABLE EMPLOYEE\").\n {updated,undefined}\n```\n\nShut down the connection.\n\n```erlang\n 25 > odbc:disconnect(Ref).\n ok\n```\n\nShut down the application.\n\n```text\n 26 > odbc:stop().\n =INFO REPORT==== 7-Jan-2004::17:00:59 ===\n application: odbc\n exited: stopped\n type: temporary\n\n ok\n```","title":"Using the Erlang API - Examples","ref":"getting_started.html#using-the-erlang-api"},{"type":"extras","doc":"\n# Databases","title":"Databases","ref":"databases.html"},{"type":"extras","doc":"If you need to access a relational database such as `sqlserver`, `mysql`,\n`postgres`, `oracle`, `cybase` etc. from your erlang application using the\nErlang ODBC interface is a good way to go about it.\n\nThe Erlang ODBC application should work for any relational database that has an\nODBC driver. But currently it is only regularly tested for `sqlserver` and\n`postgres`.","title":"Databases - Databases","ref":"databases.html#databases"},{"type":"extras","doc":"The Erlang ODBC interface is in principal database independent, e.i. an erlang\nprogram using the interface could be run without changes towards different\ndatabases. But as SQL is used it is alas possible to write database dependent\nprograms. Even though SQL is an ANSI-standard meant to be database independent,\ndifferent databases have proprietary extensions to SQL defining their own data\ntypes. If you keep to the ANSI data types you will minimize the problem. But\nunfortunately there is no guarantee that all databases actually treats the ANSI\ndata types equivalently. For instance an installation of\n`Oracle Enterprise release 8.0.5.0.0 for unix` will accept that you create a\ntable column with the ANSI data type `integer`, but when retrieving values from\nthis column the driver reports that it is of type `SQL_DECIMAL(0, 38)` and not\n`SQL_INTEGER` as you may have expected.\n\nAnother obstacle is that some drivers do not support scrollable cursors which\nhas the effect that the only way to traverse the result set is sequentially,\nwith next, from the first row to the last, and once you pass a row you cannot go\nback. This means that some functions in the interface will not work together\nwith certain drivers. A similar problem is that not all drivers support \"row\ncount\" for select queries, hence resulting in that the function\n`select_count/[3,4]` will return `{ok, undefined}` instead of `{ok, NrRows}`\nwhere `NrRows` is the number of rows in the result set.","title":"Database independence - Databases","ref":"databases.html#database-independence"},{"type":"extras","doc":"The following is a list of the ANSI data types. For details turn to the ANSI\nstandard documentation. Usage of other data types is of course possible, but you\nshould be aware that this makes your application dependent on the database you\nare using at the moment.\n\n- CHARACTER (size), CHAR (size)\n- NUMERIC (precision, scale), DECIMAL (precision, scale), DEC (precision, scale\n ) precision - total number of digits, scale - total number of decimal places\n- INTEGER, INT, SMALLINT\n- FLOAT (precision)\n- REAL\n- DOUBLE PRECISION\n- CHARACTER VARYING(size), CHAR VARYING(size)\n\nWhen inputting data using sql_query/\\[2,3] the values will always be in string\nformat as they are part of an SQL-query. Example:\n\n```text\n odbc:sql_query(Ref, \"INSERT INTO TEST VALUES(1, 2, 3)\").\n```\n\n> #### Note {: .info }\n>\n> Note that when the value of the data to input is a string, it has to be quoted\n> with `'`. Example:\n>\n> ```text\n> odbc:sql_query(Ref, \"INSERT INTO EMPLOYEE VALUES(1, 'Jane', 'Doe', 'F')\").\n> ```\n\nYou may also input data using [param_query/3,4](`m:odbc#param_query`) and\nthen the input data will have the Erlang type corresponding to the ODBC type of\nthe column.[See ODBC to Erlang mapping](databases.md#type)\n\n[](){: #type } When selecting data from a table, all data types are returned\nfrom the database to the ODBC driver as an ODBC data type. The tables below\nshows the mapping between those data types and what is returned by the Erlang\nAPI.\n\n| ODBC Data Type | Erlang Data Type |\n| ----------------------------------------------------------------------------- | ---------------------------------------------- |\n| SQL_CHAR(size) | String \\| Binary (configurable) |\n| SQL_WCHAR(size) | Unicode binary encoded as UTF16 little endian. |\n| SQL_NUMERIC(p,s) when (p >= 0 and p <= 9 and s == 0) | Integer |\n| SQL_NUMERIC(p,s) when (p >= 10 and p <= 15 and s == 0) or (s <= 15 and s > 0) | Float |\n| SQL_NUMERIC(p,s) when p >= 16 | String |\n| SQL_DECIMAL(p,s) when (p >= 0 and p <= 9 and s == 0) | Integer |\n| SQL_DECIMAL(p,s) when (p >= 10 and p <= 15 and s == 0) or (s <= 15 and s > 0) | Float |\n| SQL_DECIMAL(p,s) when p >= 16 | String |\n| SQL_INTEGER | Integer |\n| SQL_SMALLINT | Integer |\n| SQL_FLOAT | Float |\n| SQL_REAL | Float |\n| SQL_DOUBLE | Float |\n| SQL_VARCHAR(size) | String \\| Binary (configurable) |\n| SQL_WVARCHAR(size) | Unicode binary encoded as UTF16 little endian. |\n\n_Table: Mapping of ODBC data types to the Erlang data types returned to the\nErlang application._\n\n| ODBC Data Type | Erlang Data Type |\n| ---------------------- | ---------------------------------------------- |\n| SQL_TYPE_DATE | String |\n| SQL_TYPE_TIME | String |\n| SQL_TYPE_TIMESTAMP | \\{\\{YY, MM, DD\\}, \\{HH, MM, SS\\}\\} |\n| SQL_LONGVARCHAR | String \\| Binary (configurable) |\n| SQL_WLONGVARCHAR(size) | Unicode binary encoded as UTF16 little endian. |\n| SQL_BINARY | String \\| Binary (configurable) |\n| SQL_VARBINARY | String \\| Binary (configurable) |\n| SQL_LONGVARBINARY | String \\| Binary (configurable) |\n| SQL_TINYINT | Integer |\n| SQL_BIT | Boolean |\n\n_Table: Mapping of extended ODBC data types to the Erlang data types returned to\nthe Erlang application._\n\n> #### Note {: .info }\n>\n> To find out which data types will be returned for the columns in a table use\n> the function [describe_table/2,3](`m:odbc#describe_table`)","title":"Data types - Databases","ref":"databases.html#data-types"},{"type":"extras","doc":"Grouping of SQL queries can be desirable in order to reduce network traffic.\nAnother benefit can be that the data source sometimes can optimize execution of\na batch of SQL queries.\n\nExplicit batches an procedures described below will result in multiple results\nbeing returned from sql_query/\\[2,3]. while with parameterized queries only one\nresult will be returned from param_query/\\[2,3].","title":"Batch handling - Databases","ref":"databases.html#batch-handling"},{"type":"extras","doc":"The most basic form of a batch is created by semicolons separated SQL queries,\nfor example:\n\n```text\n\"SELECT * FROM FOO; SELECT * FROM BAR\" or\n\"INSERT INTO FOO VALUES(1,'bar'); SELECT * FROM FOO\"\n```","title":"Explicit batches - Databases","ref":"databases.html#explicit-batches"},{"type":"extras","doc":"Different databases may also support creating of procedures that contains more\nthan one SQL query. For example, the following SQLServer-specific statement\ncreates a procedure that returns a result set containing information about\nemployees that work at the department and a result set listing the customers of\nthat department.\n\n```text\n CREATE PROCEDURE DepartmentInfo (@DepartmentID INT) AS\n SELECT * FROM Employee WHERE department = @DepartmentID\n SELECT * FROM Customers WHERE department = @DepartmentID\n```","title":"Procedures - Databases","ref":"databases.html#procedures"},{"type":"extras","doc":"To effectively perform a batch of similar queries, you can use parameterized\nqueries. This means that you in your SQL query string will mark the places that\nusually would contain values with question marks and then provide lists of\nvalues for each parameter. For instance you can use this to insert multiple rows\ninto the `EMPLOYEE` table while executing only a single SQL statement, for\nexample code see [\"Using the Erlang API\"](getting_started.md#param_query)\nsection in the \"Getting Started\" chapter.","title":"Parameterized queries - Databases","ref":"databases.html#parameterized-queries"},{"type":"extras","doc":"\n# Error handling","title":"Error handling","ref":"error_handling.html"},{"type":"extras","doc":"On a conceptual level starting a database connection using the Erlang ODBC API\nis a basic client server application. The client process uses the API to start\nand communicate with the server process that manages the connection. The\nstrategy of the Erlang ODBC application is that programming faults in the\napplication itself will cause the connection process to terminate\nabnormally.(When a process terminates abnormally its supervisor will log\nrelevant error reports.) Calls to API functions during or after termination of\nthe connection process, will return `{error, connection_closed}`. Contextual\nerrors on the other hand will not terminate the connection it will only return\n`{error, Reason} `to the client, where `Reason` may be any erlang term.","title":"Strategy - Error handling","ref":"error_handling.html#strategy"},{"type":"extras","doc":"The connection is associated with the process that created it and can only be\naccessed through it. The reason for this is to preserve the semantics of result\nsets and transactions when select_count/\\[2,3] is called or auto_commit is\nturned off. Attempts to use the connection from another process will fail. This\nwill not effect the connection. On the other hand, if the client process dies\nthe connection will be terminated.","title":"Clients - Error handling","ref":"error_handling.html#clients"},{"type":"extras","doc":"All request made by the client to the connection are synchronous. If the timeout\nis used and expires the client process will exit with reason timeout. Probably\nthe right thing to do is let the client die and perhaps be restarted by its\nsupervisor. But if the client chooses to catch this timeout, it is a good idea\nto wait a little while before trying again. If there are too many consecutive\ntimeouts that are caught the connection process will conclude that there is\nsomething radically wrong and terminate the connection.","title":"Timeouts - Error handling","ref":"error_handling.html#timeouts"},{"type":"extras","doc":"All API-functions are guarded and if you pass an argument of the wrong type a\nruntime error will occur. All input parameters to internal functions are trusted\nto be correct. It is a good programming practise to only distrust input from\ntruly external sources. You are not supposed to catch these errors, it will only\nmake the code very messy and much more complex, which introduces more bugs and\nin the worst case also covers up the actual faults. Put your effort on testing\ninstead, you should trust your own input.","title":"Guards - Error handling","ref":"error_handling.html#guards"},{"type":"extras","doc":"As the Erlang ODBC application relies on third party products and communicates\nwith a database that probably runs on another computer in the network there are\nplenty of things that might go wrong. To fully understand the things that might\nhappen it facilitate to know the design of the Erlang ODBC application, hence\nhere follows a short description of the current design.\n\n> #### Note {: .info }\n>\n> Please note that design is something, that not necessarily will, but might\n> change in future releases. While the semantics of the API will not change as\n> it is independent of the implementation.\n\n![Architecture of the Erlang odbc application](assets/odbc_app_arc.gif \"Architecture of the Erlang odbc application\")\n\nWhen you do application:start(odbc) the only thing that happens is that a\nsupervisor process is started. For each call to the API function connect/2 a\nprocess is spawned and added as a child to the Erlang ODBC supervisor. The\nsupervisors only tasks are to provide error-log reports, if a child process\nshould die abnormally, and the possibility to do a code change. Only the client\nprocess has the knowledge to decide if this connection managing process should\nbe restarted.\n\nThe erlang connection process spawned by connect/2, will open a port to a\nc-process that handles the communication with the database through Microsoft's\nODBC API. The erlang port will be kept open for exit signal propagation, if\nsomething goes wrong in the c-process and it exits we want know as mush as\npossible about the reason. The main communication with the c-process is done\nthrough sockets. The C-process consists of two threads, the supervisor thread\nand the database handler thread. The supervisor thread checks for shutdown\nmessages on the supervisor socket and the database handler thread receives\nrequests and sends answers on the database socket. If the database thread seems\nto hang on some database call, the erlang control process will send a shutdown\nmessage on the supervisor socket, in this case the c-process will exit. If the\nc-process crashes/exits it will bring the erlang-process down too and vice versa\ni.e. the connection is terminated.","title":"The whole picture - Error handling","ref":"error_handling.html#the-whole-picture"},{"type":"extras","doc":"The types of errors that may occur can be divide into the following categories.\n\n- Configuration problems - Everything from that the database was not set up\n right to that the c-program that should be run through the erlang port was not\n compiled for your platform.\n- Errors discovered by the ODBC driver - If calls to the ODBC-driver fails due\n to circumstances that cannot be controlled by the Erlang ODBC application\n programmer, an error string will be dug up from the driver. This string will\n be the `Reason` in the `{error, Reason} `return value. How good this error\n message is will of course be driver dependent. Examples of such circumstances\n are trying to insert the same key twice, invalid SQL-queries and that the\n database has gone off line.\n- Connection termination - If a connection is terminated in an abnormal way, or\n if you try to use a connection that you have already terminated in a normal\n way by calling disconnect/1, the return value will\n be`{error, connection_closed}`. A connection could end abnormally because of\n an programming error in the Erlang ODBC application, but also if the ODBC\n driver crashes.\n- Contextual errors - If API functions are used in the wrong context, the\n `Reason` in the error tuple will be a descriptive atom. For instance if you\n try to call the function `last/[1,2] `without first calling\n `select_count/[2,3] `to associate a result set with the connection. If the\n ODBC-driver does not support some functions, or if you disabled some\n functionality for a connection and then try to use it.","title":"Error types - Error handling","ref":"error_handling.html#error-types"}],"content_type":"text/plain","producer":{"name":"ex_doc","version":[48,46,51,52,46,49]}} \ No newline at end of file diff --git a/prs/9045/lib/odbc-2.15/doc/html/getting_started.html b/prs/9045/lib/odbc-2.15/doc/html/getting_started.html index 779f3cdcc87b..348183e8af4c 100644 --- a/prs/9045/lib/odbc-2.15/doc/html/getting_started.html +++ b/prs/9045/lib/odbc-2.15/doc/html/getting_started.html @@ -163,77 +163,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
    diff --git a/prs/9045/lib/odbc-2.15/doc/html/odbc.epub b/prs/9045/lib/odbc-2.15/doc/html/odbc.epub
    index f86d2523900f..f5a3a60cd10c 100644
    Binary files a/prs/9045/lib/odbc-2.15/doc/html/odbc.epub and b/prs/9045/lib/odbc-2.15/doc/html/odbc.epub differ
    diff --git a/prs/9045/lib/odbc-2.15/doc/html/search.html b/prs/9045/lib/odbc-2.15/doc/html/search.html
    index 83843f014efb..97aad9004211 100644
    --- a/prs/9045/lib/odbc-2.15/doc/html/search.html
    +++ b/prs/9045/lib/odbc-2.15/doc/html/search.html
    @@ -128,7 +128,7 @@ 

    - +

    diff --git a/prs/9045/lib/os_mon-2.10/doc/html/os_mon.epub b/prs/9045/lib/os_mon-2.10/doc/html/os_mon.epub index 28c894873d71..65a343594af4 100644 Binary files a/prs/9045/lib/os_mon-2.10/doc/html/os_mon.epub and b/prs/9045/lib/os_mon-2.10/doc/html/os_mon.epub differ diff --git a/prs/9045/lib/parsetools-2.6/doc/html/.build b/prs/9045/lib/parsetools-2.6/doc/html/.build index f295f304f03a..05ba0ff72aad 100644 --- a/prs/9045/lib/parsetools-2.6/doc/html/.build +++ b/prs/9045/lib/parsetools-2.6/doc/html/.build @@ -18,7 +18,7 @@ dist/lato-latin-ext-300-normal-VPGGJKJL.woff2 dist/lato-latin-ext-400-normal-N27NCBWW.woff2 dist/lato-latin-ext-700-normal-Q2L5DVMW.woff2 dist/remixicon-NKANDIL5.woff2 -dist/search_data-8BDC4DA6.js +dist/search_data-F08ECED6.js dist/sidebar_items-E70C9F62.js index.html leex.html diff --git a/prs/9045/lib/parsetools-2.6/doc/html/dist/search_data-8BDC4DA6.js b/prs/9045/lib/parsetools-2.6/doc/html/dist/search_data-8BDC4DA6.js deleted file mode 100644 index e5f1b7427bbf..000000000000 --- a/prs/9045/lib/parsetools-2.6/doc/html/dist/search_data-8BDC4DA6.js +++ /dev/null @@ -1 +0,0 @@ -searchData={"items":[{"type":"module","doc":"Lexical analyzer generator for Erlang\n\nA regular expression based lexical analyzer generator for Erlang, similar to\n`lex` or `flex`.\n\n> #### Note {: .info }\n>\n> The `leex` module was considered experimental when it was introduced.","title":"leex","ref":"leex.html"},{"type":"module","doc":"The (host operating system) environment variable `ERL_COMPILER_OPTIONS` can be\nused to give default Leex options. Its value must be a valid Erlang term. If the\nvalue is a list, it is used as is. If it is not a list, it is put into a list.\n\nThe list is appended to any options given to `file/2`.\n\nThe list can be retrieved with `compile:env_compiler_options/0`.","title":"Default Leex Options - leex","ref":"leex.html#module-default-leex-options"},{"type":"module","doc":"Erlang style comments starting with a `%` are allowed in scanner files. A\ndefinition file has the following format:\n\n```text\n \n\nDefinitions.\n\n \n\nRules.\n\n \n\nErlang code.\n\n \n```\n\nThe `Definitions.`, `Rules.`, and `Erlang code` headings are mandatory\nand must start at the beginning of a source line. The ` `,\n` `, and ` ` sections are allowed to be\nempty, but there must be at least one rule.\n\nMacro definitions have the following format:\n\n```text\nNAME = VALUE\n```\n\nand there must be spaces around `=`. Macros can be used in the regular\nexpressions of rules by writing `{NAME}`.\n\n> #### Note {: .info }\n>\n> When macros are expanded in expressions, the macro calls are replaced by the\n> macro value without any form of quoting or enclosing in parentheses.\n\nRules have the following format:\n\n```text\n : .\n```\n\nThe ` ` must occur at the start of a line and not include any blanks; use\n`\\t` and `\\s` to include TAB and SPACE characters in the regular expression. If\n` ` matches then the corresponding ` ` is evaluated to generate a\ntoken. With the Erlang code the following predefined variables are available:\n\n- **`TokenChars`** - A list of the characters in the matched token.\n\n- **`TokenLen`** - The number of characters in the matched token.\n\n- **`TokenLine`** - The line number where the token occurred.\n\n- **`TokenCol`** - The column number where the token occurred (column of the\n first character included in the token).\n\n- **`TokenLoc`** - Token location. Expands to `{TokenLine,TokenCol}` (even when\n `error_location` is set to `line`).\n\nThe code must return:\n\n- **`{token,Token}`** - Return `Token` to the caller.\n\n- **`{end_token,Token}`** - Return `Token` and is last token in a tokens call.\n\n- **`skip_token`** - Skip this token completely.\n\n- **`{error,ErrString}`** - An error in the token, `ErrString` is a string\n describing the error.\n\nIt is also possible to push back characters into the input characters with the\nfollowing returns:\n\n- `{token,Token,PushBackList}`\n- `{end_token,Token,PushBackList}`\n- `{skip_token,PushBackList}`\n\nThese have the same meanings as the normal returns but the characters in\n`PushBackList` will be prepended to the input characters and scanned for the\nnext token. Note that pushing back a newline will mean the line numbering will\nno longer be correct.\n\n> #### Note {: .info }\n>\n> Pushing back characters gives you unexpected possibilities to cause the\n> scanner to loop\\!\n\nThe following example would match a simple Erlang integer or float and return a\ntoken which could be sent to the Erlang parser:\n\n```erlang\nD = [0-9]\n\n{D}+ :\n {token,{integer,TokenLine,list_to_integer(TokenChars)}}.\n\n{D}+\\.{D}+((E|e)(\\+|\\-)?{D}+)? :\n {token,{float,TokenLine,list_to_float(TokenChars)}}.\n```\n\nThe Erlang code in the `Erlang code.` section is written into the output file\ndirectly after the module declaration and predefined exports declaration, making\nit possible to add extra exports, define imports, and other attributes, which are\nvisible in the whole file.","title":"Input File Format - leex","ref":"leex.html#module-input-file-format"},{"type":"module","doc":"The regular expressions allowed here is a subset of the set found in `egrep` and\nin the AWK programming language, as defined in the book _The AWK Programming\nLanguage_ by A. V. Aho, B. W. Kernighan, and P. J. Weinberger. They are composed of\nthe following characters:\n\n- **`c`** - Matches the non-metacharacter c.\n\n- **`\\c`** - Matches the escape sequence or literal character c.\n\n- **`.`** - Matches any character.\n\n- **`^`** - Matches the beginning of a string.\n\n- **`$`** - Matches the end of a string.\n\n- **`[abc...]`** - Character class, which matches any of the characters\n `abc...`. Character ranges are specified by a pair of characters separated by\n a `-`.\n\n- **`[^abc...]`** - Negated character class, which matches any character except\n `abc...`.\n\n- **`r1 | r2`** - Alternation. It matches either `r1` or `r2`.\n\n- **`r1r2`** - Concatenation. It matches `r1` and then `r2`.\n\n- **`r+`** - Matches one or more `r`s.\n\n- **`r*`** - Matches zero or more `r`s.\n\n- **`r?`** - Matches zero or one `r`s.\n\n- **`(r)`** - Grouping. It matches `r`.\n\nThe escape sequences allowed are the same as for Erlang strings:\n\n- **`\\b`** - Backspace.\n\n- **`\\f`** - Form feed.\n\n- **`\\n`** - Newline (line feed).\n\n- **`\\r`** - Carriage return.\n\n- **`\\t`** - Tab.\n\n- **`\\e`** - Escape.\n\n- **`\\v`** - Vertical tab.\n\n- **`\\s`** - Space.\n\n- **`\\d`** - Delete.\n\n- **`\\ddd`** - The octal value `ddd`.\n\n- **`\\xhh`** - The hexadecimal value `hh`.\n\n- **`\\x{h...}`** - The hexadecimal value `h...`.\n\n- **`\\c`** - Any other character literally, for example `\\\\` for backslash, `\\\"`\n for `\"`.\n\nThe following examples define simplified versions of a few Erlang data types:\n\n```text\nAtoms [a-z][0-9a-zA-Z_]*\n\nVariables [A-Z_][0-9a-zA-Z_]*\n\nFloats (\\+|-)?[0-9]+\\.[0-9]+((E|e)(\\+|-)?[0-9]+)?\n```\n\n> #### Note {: .info }\n>\n> Anchoring a regular expression with `^` and `$` is not implemented in the\n> current version of `leex` and generates a parse error.","title":"Regular Expressions - leex","ref":"leex.html#module-regular-expressions"},{"type":"function","doc":"","title":"leex.file/1","ref":"leex.html#file/1"},{"type":"function","doc":"Generates a lexical analyzer from the definition in the input file.\n\nThe input file has the extension `.xrl`. This is added to the filename\nif it is not given. The resulting module is the Xrl filename without\nthe `.xrl` extension.\n\nThe current options are:\n\n- **`dfa_graph`** - Generates a `.dot` file which contains a description of the\n DFA in a format which can be viewed with Graphviz, `www.graphviz.com`.\n\n- **`{includefile,Includefile}`** - Uses a specific or customised prologue file\n instead of default `lib/parsetools/include/leexinc.hrl` which is otherwise\n included.\n\n- **`{report_errors, boolean()}`** - Causes errors to be printed as they occur.\n Default is `true`.\n\n- **`{report_warnings, boolean()}`** - Causes warnings to be printed as they\n occur. Default is `true`.\n\n- **`{report, boolean()}`** - This is a short form for both `report_errors` and\n `report_warnings`.\n\n- **`{return_errors, boolean()}`** - If this flag is set,\n `{error, Errors, Warnings}` is returned when there are errors. Default is\n `false`.\n\n- **`{return_warnings, boolean()}`** - If this flag is set, an extra field\n containing `Warnings` is added to the tuple returned upon success. Default is\n `false`.\n\n- **`{return, boolean()}`** - This is a short form for both `return_errors` and\n `return_warnings`.\n\n- **`{scannerfile, Scannerfile}`** - `Scannerfile` is the name of the file that\n will contain the Erlang scanner code that is generated. The default (`\"\"`) is\n to add the extension `.erl` to `FileName` stripped of the `.xrl` extension.\n\n- **`{verbose, boolean()}`** - Outputs information from parsing the input file\n and generating the internal tables.\n\n- **`{warnings_as_errors, boolean()}`** - Causes warnings to be treated as\n errors.\n\n- **`{deterministic, boolean()}`** - Causes generated `-file()` attributes to only\n include the basename of the file path.\n\n- **`{error_location, line | column}`** - If set to `column`, error location\n will be `{Line,Column}` tuple instead of just `Line`. Also, `StartLoc` and\n `EndLoc` in [`string/2`](`string/2`), [`token/3`](`token/3`), and\n [`tokens/3`](`tokens/3`) functions will be `{Line,Column}` tuple instead of\n just `Line`. Default is `line`. Note that you can use `TokenLoc` for token\n location independently, even if the `error_location` is set to `line`.\n\n Unicode characters are counted as many columns as they use bytes to represent.\n\n- **`{tab_size, pos_integer()}`** - Sets the width of `\\t` character (only\n relevant if `error_location` is set to `column`). Default is `8`.\n\nAny of the Boolean options can be set to `true` by stating the name of the\noption. For example, `verbose` is equivalent to `{verbose, true}`.\n\nLeex will add the extension `.hrl` to the `Includefile` name and the extension\n`.erl` to the `Scannerfile` name, unless the extension is already there.","title":"leex.file/2","ref":"leex.html#file/2"},{"type":"function","doc":"Returns a descriptive string in English of an error reason `ErrorDescriptor`\nreturned by [`leex:file/1,2`](`file/1`) when there is an error in a regular\nexpression.","title":"leex.format_error/1","ref":"leex.html#format_error/1"},{"type":"function","doc":"","title":"leex.string/1","ref":"leex.html#string/1"},{"type":"function","doc":"Scans `String` and returns either all the tokens in it or an `error` tuple.\n\n`StartLoc` and `EndLoc` are either [`erl_anno:line()`](`t:erl_anno:line/0`)\nor [`erl_anno:location()`](`t:erl_anno:location/0`), depending on the\n`error_location` option.\n\n> #### Note {: .info }\n>\n> It is an error if not all of the characters in `String` are consumed.","title":"leex.string/2","ref":"leex.html#string/2"},{"type":"function","doc":"","title":"leex.token/2","ref":"leex.html#token/2"},{"type":"function","doc":"This is a re-entrant call to try and scan a single token from `Chars`.\n\nIf there are enough characters in `Chars` to either scan a token or\ndetect an error then this will be returned with\n`{done,...}`. Otherwise `{cont,Cont}` will be returned where `Cont` is\nused in the next call to `token()` with more characters to try an scan\nthe token. This is continued until a token has been scanned. `Cont` is\ninitially `[]`.\n\nIt is not designed to be called directly by an application, but is\nused through the I/O system where it can typically be called in an\napplication by:\n\n```erlang\nio:request(InFile, {get_until,unicode,Prompt,Module,token,[Loc]})\n -> TokenRet\n```","title":"leex.token/3","ref":"leex.html#token/3"},{"type":"function","doc":"","title":"leex.tokens/2","ref":"leex.html#tokens/2"},{"type":"function","doc":"This is a re-entrant call to try and scan tokens from `Chars`.\n\nIf there are enough characters in `Chars` to either scan tokens or\ndetect an error then this will be returned with\n`{done,...}`. Otherwise `{cont,Cont}` will be returned where `Cont` is\nused in the next call to `tokens()` with more characters to try an\nscan the tokens. This is continued until all tokens have been\nscanned. `Cont` is initially `[]`.\n\nThis functions differs from `token` in that it will continue to scan tokens up\nto and including an `{end_token,Token}` has been scanned (see next section). It\nwill then return all the tokens. This is typically used for scanning grammars\nlike Erlang where there is an explicit end token, `'.'`. If no end token is\nfound then the whole file will be scanned and returned. If an error occurs then\nall tokens up to and including the next end token will be skipped.\n\nIt is not designed to be called directly by an application, but used through the\nI/O system where it can typically be called in an application by:\n\n```erlang\nio:request(InFile, {get_until,unicode,Prompt,Module,tokens,[Loc]})\n -> TokensRet\n```","title":"leex.tokens/3","ref":"leex.html#tokens/3"},{"type":"type","doc":"The standard `t:error_info/0` structure that is returned from all I/O modules.\n`ErrorDescriptor` is formattable by `format_error/1`.","title":"leex.error_info/0","ref":"leex.html#t:error_info/0"},{"type":"type","doc":"","title":"leex.error_ret/0","ref":"leex.html#t:error_ret/0"},{"type":"type","doc":"","title":"leex.errors/0","ref":"leex.html#t:errors/0"},{"type":"type","doc":"","title":"leex.leex_ret/0","ref":"leex.html#t:leex_ret/0"},{"type":"type","doc":"","title":"leex.ok_ret/0","ref":"leex.html#t:ok_ret/0"},{"type":"type","doc":"","title":"leex.warnings/0","ref":"leex.html#t:warnings/0"},{"type":"module","doc":"LALR-1 Parser Generator\n\nAn LALR-1 parser generator for Erlang, similar to `yacc`. Takes a BNF grammar\ndefinition as input, and produces Erlang code for a parser.\n\nTo understand this text, you also have to look at the `yacc` documentation in\nthe UNIX(TM) manual. This is most probably necessary in order to understand the\nidea of a parser generator, and the principle and problems of LALR parsing with\nfinite look-ahead.\n\nAn nice introduction to `yacc` can be found in chapter 8 of \"The UNIX\nProgramming Environment\" by Brian W. Kernighan and Rob Pike.","title":"yecc","ref":"yecc.html"},{"type":"module","doc":"The (host operating system) environment variable `ERL_COMPILER_OPTIONS` can be\nused to give default Yecc options. Its value must be a valid Erlang term. If the\nvalue is a list, it is used as is. If it is not a list, it is put into a list.\n\nThe list is appended to any options given to `file/2`.\n\nThe list can be retrieved with `compile:env_compiler_options/0`.","title":"Default Yecc Options - yecc","ref":"yecc.html#module-default-yecc-options"},{"type":"module","doc":"A `scanner` to pre-process the text (program) to be parsed is not provided\nin the `yecc` module. The scanner serves as a kind of lexicon look-up routine.\nIt is possible to write a grammar that uses only character tokens as terminal\nsymbols, thereby eliminating the need for a scanner, but this would make the\nparser larger and slower.\n\nThe user should implement a scanner that segments the input text, and turns it\ninto one or more lists of tokens. Each token should be a tuple containing\ninformation about syntactic category, position in the text (for example\nline number), and the actual terminal symbol found in the text:\n`{Category, Position, Symbol}`.\n\nIf a terminal symbol is the only member of a category, and the symbol name is\nidentical to the category name, the token format can be `{Symbol, Position}`.\n\nA list of tokens produced by the scanner should end with a special\n`end_of_input` tuple which the parser is looking for. The format of this tuple\nshould be `{Endsymbol, EndPosition}`, where `Endsymbol` is an identifier that is\ndistinguished from all the terminal and non-terminal categories of the syntax\nrules. The `Endsymbol` can be declared in the grammar file.\n\nThe simplest case is to segment the input string into a list of identifiers\n(atoms) and use those atoms both as categories and values of the tokens. For\nexample, the input string `aaa bbb 777, X` may be scanned (tokenized) as:\n\n```erlang\n[{aaa, 1}, {bbb, 1}, {777, 1}, {',' , 1}, {'X', 1},\n {'$end', 1}].\n```\n\nThis assumes that this is the first line of the input text, and that `'$end'` is\nthe distinguished `end_of_input` symbol.\n\nThe Erlang scanner in the `io` module can be used as a starting point when\nwriting a new scanner. Study `yeccscan.erl` in order to see how a filter can be\nadded on top of `io:scan_erl_form/3` to provide a scanner for Yecc that\ntokenizes grammar files before parsing them with the Yecc parser. A more general\napproach to scanner implementation is to use a scanner generator such as\n`m:leex`.","title":"Pre-Processing - yecc","ref":"yecc.html#module-pre-processing"},{"type":"module","doc":"Erlang style `comments`, starting with a `'%'`, are allowed in grammar files.\n\nEach `declaration` or `rule` ends with a dot (the character `'.'`).\n\nThe grammar starts with an optional `header` section. The header is put first in\nthe generated file, before the module declaration. The purpose of the header is\nto provide a means to make the documentation generated by [EDoc](`e:edoc:edoc.md`)\nlook nicer. Each header line should be enclosed in double quotes, and newlines\nwill be inserted between the lines. For example:\n\n```erlang\nHeader \"%% Copyright (C)\"\n\"%% @private\"\n\"%% @Author John\".\n```\n\nNext comes a declaration of the `nonterminal categories` to be used in the\nrules. For example:\n\n```text\nNonterminals sentence nounphrase verbphrase.\n```\n\nA non-terminal category can be used at the left-hand side (= `lhs`, or `head`)\nof a grammar rule. It can also appear at the right-hand side of rules.\n\nNext comes a declaration of the `terminal categories`, which are the categories\nof tokens produced by the scanner. For example:\n\n```text\nTerminals article adjective noun verb.\n```\n\nTerminal categories may only appear in the right hand sides (= `rhs`) of grammar\nrules.\n\nNext comes a declaration of the `rootsymbol`, or start category of the grammar.\nFor example:\n\n```text\nRootsymbol sentence.\n```\n\nThis symbol should appear in the lhs of at least one grammar rule. This is the\nmost general syntactic category which the parser ultimately will parse every\ninput string into.\n\nAfter the rootsymbol declaration comes an optional declaration of the\n`end_of_input` symbol that your scanner is expected to use. For example:\n\n```text\nEndsymbol '$end'.\n```\n\nNext comes one or more declarations of *operator precedences*, if needed. These\nare used to resolve shift/reduce conflicts (see `yacc` documentation).\n\nExamples of operator declarations:\n\n```text\nRight 100 '='.\nNonassoc 200 '==' '=/='.\nLeft 300 '+'.\nLeft 400 '*'.\nUnary 500 '-'.\n```\n\nThese declarations mean that `'='` is defined as a `right associative binary`\noperator with precedence 100, `'=='` and `'=/='` are operators with\n`no associativity`, `'+'` and `'*'` are `left associative binary` operators,\nwhere `'*'` takes precedence over `'+'` (the normal case), and `'-'` is a\n`unary` operator of higher precedence than `'*'`. The fact that '==' has no\nassociativity means that an expression like `a == b == c` is considered a syntax\nerror.\n\nCertain rules are assigned precedence: each rule gets its precedence from the\nlast terminal symbol mentioned in the right hand side of the rule. It is also\npossible to declare precedence for non-terminals, \"one level up\". This is\npractical when an operator is overloaded (see also example 3 below).\n\nNext come the *grammar rules*. Each rule has the general form\n\n```erlang\nLeft_hand_side -> Right_hand_side : Associated_code.\n```\n\nThe left hand side is a non-terminal category. The right hand side is a sequence\nof one or more non-terminal or terminal symbols with spaces between. The\nassociated code is a sequence of zero or more Erlang expressions (with commas\n`','` as separators). If the associated code is empty, the separating colon\n`':'` is also omitted. A final dot marks the end of the rule.\n\nSymbols such as `'{'`, `'.'`, and so on, have to be enclosed in single quotes\nwhen used as terminal or non-terminal symbols in grammar rules. The use of the\nsymbols `'$empty'`, `'$end'`, and `'$undefined'` should be avoided.\n\nThe last part of the grammar file is an optional section with Erlang code (=\nfunction definitions) which is included 'as is' in the resulting parser file.\nThis section must start with the pseudo declaration, or key words\n\n```text\nErlang code.\n```\n\nNo syntax rule definitions or other declarations must follow this section. To\navoid conflicts with internal variables, do not use variable names beginning\nwith two underscore characters (`'__'`) in the Erlang code in this section, or\nin the code associated with the individual syntax rules.\n\nThe optional `expect` declaration can be placed anywhere before the last\noptional section with Erlang code. It is used for suppressing the warning about\nconflicts that is ordinarily given if the grammar is ambiguous. An example:\n\n```text\nExpect 2.\n```\n\nThe warning is given if the number of shift/reduce conflicts differs from 2, or\nif there are reduce/reduce conflicts.","title":"Grammar Definition Format - yecc","ref":"yecc.html#module-grammar-definition-format"},{"type":"module","doc":"A grammar to parse list expressions (with empty associated code):\n\n```text\nNonterminals list elements element.\nTerminals atom '(' ')'.\nRootsymbol list.\nlist -> '(' ')'.\nlist -> '(' elements ')'.\nelements -> element.\nelements -> element elements.\nelement -> atom.\nelement -> list.\n```\n\nThis grammar can be used to generate a parser which parses list expressions,\nsuch as `(), (a), (peter charles), (a (b c) d (())), ...` provided that your\nscanner tokenizes, for example, the input `(peter charles)` as follows:\n\n```erlang\n[{'(', 1} , {atom, 1, peter}, {atom, 1, charles}, {')', 1},\n {'$end', 1}]\n```\n\nWhen a grammar rule is used by the parser to parse (part of) the input string as\na grammatical phrase, the associated code is evaluated, and the value of the\nlast expression becomes the value of the parsed phrase. This value may be used\nby the parser later to build structures that are values of higher phrases of\nwhich the current phrase is a part. The values initially associated with\nterminal category phrases, i.e. input tokens, are the token tuples themselves.\n\nBelow is an example of the grammar above with structure building code added:\n\n```text\nlist -> '(' ')' : nil.\nlist -> '(' elements ')' : '$2'.\nelements -> element : {cons, '$1', nil}.\nelements -> element elements : {cons, '$1', '$2'}.\nelement -> atom : '$1'.\nelement -> list : '$1'.\n```\n\nWith this code added to the grammar rules, the parser produces the following\nvalue (structure) when parsing the input string `(a b c).`. This still assumes\nthat this was the first input line that the scanner tokenized:\n\n```erlang\n{cons, {atom, 1, a}, {cons, {atom, 1, b},\n {cons, {atom, 1, c}, nil}}}\n```\n\nThe associated code contains `pseudo variables` `'$1'`, `'$2'`,\n`'$3'`, and so on. which refer to (are bound to) the values\nassociated previously by the parser with the symbols of the right-hand\nside of the rule. When these symbols are terminal categories, the\nvalues are token tuples of the input string (see above).\n\nThe associated code may not only be used to build structures\nassociated with phrases, but may also be used for syntactic and\nsemantic tests, printout actions (for example for tracing), and so on\nduring the parsing process. Since tokens contain positional (line\nnumber) information, it is possible to produce error messages which\ncontain line numbers. If there is no associated code after the\nright-hand side of the rule, the value `'$undefined'` is associated\nwith the phrase.\n\nThe right-hand side of a grammar rule can be empty. This is indicated by using\nthe special symbol `'$empty'` as rhs. Then the list grammar above can be\nsimplified to:\n\n```text\nlist -> '(' elements ')' : '$2'.\nelements -> element elements : {cons, '$1', '$2'}.\nelements -> '$empty' : nil.\nelement -> atom : '$1'.\nelement -> list : '$1'.\n```","title":"Examples - yecc","ref":"yecc.html#module-examples"},{"type":"module","doc":"To call the parser generator, use the following command:\n\n```erlang\nyecc:file(Grammarfile).\n```\n\nAn error message from Yecc will be shown if the grammar is not of the LALR type\n(for example too ambiguous). Shift/reduce conflicts are resolved in favor of\nshifting if there are no operator precedence declarations. Refer to the `yacc`\ndocumentation on the use of operator precedence.\n\nThe output file contains Erlang source code for a parser module with module name\nequal to the `Parserfile` parameter. After compilation, the parser can be called\nas follows (the module name is assumed to be `myparser`):\n\n```erlang\nmyparser:parse(myscanner:scan(Inport))\n```\n\nThe call format can be different if a customized prologue file has been included\nwhen generating the parser instead of the default file\n`lib/parsetools/include/yeccpre.hrl`.\n\nWith the standard prologue, this call will return either `{ok, Result}`, where\n`Result` is a structure that the Erlang code of the grammar file has built, or\n`{error, {Position, Module, Message}}` if there was a syntax error in the input.\n\n`Message` is something which may be converted into a string by calling\n`Module:format_error(Message)` and printed with `io:format/3`.\n\n> #### Note {: .info }\n>\n> By default, the parser that was generated will not print out error messages to\n> the screen. The user will have to do this either by printing the returned\n> error messages, or by inserting tests and print instructions in the Erlang\n> code associated with the syntax rules of the grammar file.\n\nIt is also possible to make the parser ask for more input tokens when needed if\nthe following call format is used:\n\n```erlang\nmyparser:parse_and_scan({Function, Args})\nmyparser:parse_and_scan({Mod, Tokenizer, Args})\n```\n\nThe tokenizer `Function` is either a fun or a tuple `{Mod, Tokenizer}`. The call\n[`apply(Function, Args)`](`apply/2`) or\n[`apply({Mod, Tokenizer}, Args)`](`apply/2`) is executed whenever a new token is\nneeded. This, for example, makes it possible to parse from a file, token by\ntoken.\n\nThe tokenizer used above has to be implemented so as to return one of the\nfollowing:\n\n```erlang\n{ok, Tokens, EndPosition}\n{eof, EndPosition}\n{error, Error_description, EndPosition}\n```\n\nThis conforms to the format used by the scanner in the Erlang `io` library\nmodule.\n\nIf `{eof, EndPosition}` is returned immediately, the call to `parse_and_scan/1`\nreturns `{ok, eof}`. If `{eof, EndPosition}` is returned before the parser\nexpects end of input, `parse_and_scan/1` will, of course, return an error\nmessage (see above). Otherwise `{ok, Result}` is returned.","title":"Generating a Parser - yecc","ref":"yecc.html#module-generating-a-parser"},{"type":"module","doc":"1\\. A grammar for parsing infix arithmetic expressions into prefix notation,\nwithout operator precedence:\n\n```text\nNonterminals E T F.\nTerminals '+' '*' '(' ')' number.\nRootsymbol E.\nE -> E '+' T: {'$2', '$1', '$3'}.\nE -> T : '$1'.\nT -> T '*' F: {'$2', '$1', '$3'}.\nT -> F : '$1'.\nF -> '(' E ')' : '$2'.\nF -> number : '$1'.\n```\n\n2\\. The same with operator precedence becomes simpler:\n\n```text\nNonterminals E.\nTerminals '+' '*' '(' ')' number.\nRootsymbol E.\nLeft 100 '+'.\nLeft 200 '*'.\nE -> E '+' E : {'$2', '$1', '$3'}.\nE -> E '*' E : {'$2', '$1', '$3'}.\nE -> '(' E ')' : '$2'.\nE -> number : '$1'.\n```\n\n3\\. An overloaded minus operator:\n\n```text\nNonterminals E uminus.\nTerminals '*' '-' number.\nRootsymbol E.\n\nLeft 100 '-'.\nLeft 200 '*'.\nUnary 300 uminus.\n\nE -> E '-' E.\nE -> E '*' E.\nE -> uminus.\nE -> number.\n\numinus -> '-' E.\n```\n\n4\\. The Yecc grammar that is used for parsing grammar files, including itself:\n\n```erlang\nNonterminals\ngrammar declaration rule head symbol symbols attached_code\ntoken tokens.\nTerminals\natom float integer reserved_symbol reserved_word string char var\n'->' ':' dot.\nRootsymbol grammar.\nEndsymbol '$end'.\ngrammar -> declaration : '$1'.\ngrammar -> rule : '$1'.\ndeclaration -> symbol symbols dot: {'$1', '$2'}.\nrule -> head '->' symbols attached_code dot: {rule, ['$1' | '$3'],\n '$4'}.\nhead -> symbol : '$1'.\nsymbols -> symbol : ['$1'].\nsymbols -> symbol symbols : ['$1' | '$2'].\nattached_code -> ':' tokens : {erlang_code, '$2'}.\nattached_code -> '$empty' : {erlang_code,\n [{atom, 0, '$undefined'}]}.\ntokens -> token : ['$1'].\ntokens -> token tokens : ['$1' | '$2'].\nsymbol -> var : value_of('$1').\nsymbol -> atom : value_of('$1').\nsymbol -> integer : value_of('$1').\nsymbol -> reserved_word : value_of('$1').\ntoken -> var : '$1'.\ntoken -> atom : '$1'.\ntoken -> float : '$1'.\ntoken -> integer : '$1'.\ntoken -> string : '$1'.\ntoken -> char : '$1'.\ntoken -> reserved_symbol : {value_of('$1'), line_of('$1')}.\ntoken -> reserved_word : {value_of('$1'), line_of('$1')}.\ntoken -> '->' : {'->', line_of('$1')}.\ntoken -> ':' : {':', line_of('$1')}.\nErlang code.\nvalue_of(Token) ->\n element(3, Token).\nline_of(Token) ->\n element(2, Token).\n```\n\n> #### Note {: .info }\n>\n> The symbols `'->'`, and `':'` have to be treated in a special way, as they are\n> meta symbols of the grammar notation, as well as terminal symbols of the Yecc\n> grammar.\n\n5\\. The file `erl_parse.yrl` in the `lib/stdlib/src` directory contains the\ngrammar for Erlang.\n\n> #### Note {: .info }\n>\n> Syntactic tests are used in the code associated with some rules, and an error\n> is thrown (and caught by the generated parser to produce an error message)\n> when a test fails. The same effect can be achieved with a call to\n> `return_error(ErrorPosition, Message_string)`, which is defined in the\n> `yeccpre.hrl` default header file.","title":"More Examples - yecc","ref":"yecc.html#module-more-examples"},{"type":"module","doc":"```text\nlib/parsetools/include/yeccpre.hrl\n```","title":"Files - yecc","ref":"yecc.html#module-files"},{"type":"module","doc":"* Aho & Johnson: 'LR Parsing', ACM Computing Surveys, vol. 6:2, 1974.\n\n* Kernighan & Pike: The UNIX programming environment, 1984.","title":"See Also - yecc","ref":"yecc.html#module-see-also"},{"type":"function","doc":"","title":"yecc.file/1","ref":"yecc.html#file/1"},{"type":"function","doc":"Generates an Erlang file with the parser for the language described by `GrammarFile`.\n\n`Grammarfile` is the file of declarations and grammar rules. Returns `ok` upon\nsuccess, or `error` if there are errors. An Erlang file containing the parser is\ncreated if there are no errors.\n\nThe options are:\n\n- **`{includefile, Includefile}`.** - Indicates a customized prologue file which\n the user may want to use instead of the default file\n `lib/parsetools/include/yeccpre.hrl` which is otherwise included at the\n beginning of the resulting parser file. Note taht `Includefile` is included\n as is in the parser file, so it must not have a module declaration of its\n own, and it should not be compiled. It must, however, contain the necessary\n export declarations. The default is indicated by `\"\"`.\n\n- **`{parserfile, Parserfile}`.** - `Parserfile` is the name of the file that\n will contain the Erlang parser code that is generated. The default (`\"\"`) is\n to add the extension `.erl` to `Grammarfile` stripped of the `.yrl` extension.\n\n- **`{report_errors, boolean()}`.** - Causes errors to be printed as they occur.\n Default is `true`.\n\n- **`{report_warnings, boolean()}`.** - Causes warnings to be printed as they\n occur. Default is `true`.\n\n- **`{report, boolean()}`.** - This is a short form for both `report_errors` and\n `report_warnings`.\n\n- **`{return_errors, boolean()}`.** - If this flag is set,\n `{error, Errors, Warnings}` is returned when there are errors. Default is\n `false`.\n\n- **`{return_warnings, boolean()}`.** - If this flag is set, an extra field\n containing `Warnings` is added to the tuple returned upon success. Default is\n `false`.\n\n- **`{return, boolean()}`.** - This is a short form for both `return_errors` and\n `return_warnings`.\n\n- **`{verbose, boolean()}`.** - Determines whether the parser generator should\n give full information about resolved and unresolved parse action conflicts\n (`true`), or only about those conflicts that prevent a parser from being\n generated from the input grammar (`false`, the default).\n\n- **`{warnings_as_errors, boolean()}`** - Causes warnings to be treated as\n errors.\n\n- **`{error_location, column | line}`.** - If the value of this flag is `line`,\n the location of warnings and errors is a line number. If the value is\n `column`, the location includes a line number and a column number. Default is\n `column`.\n\n- **`{deterministic, boolean()}`** - Causes generated `-file()` attributes to only\n include the basename of the file path.\n\nAny of the Boolean options can be set to `true` by stating the name of the\noption. For example, `verbose` is equivalent to `{verbose, true}`.\n\nThe value of the `Parserfile` option stripped of the `.erl` extension is used by\nYecc as the module name of the generated parser file.\n\nYecc will add the extension `.yrl` to the `Grammarfile` name, the extension\n`.hrl` to the `Includefile` name, and the extension `.erl` to the `Parserfile`\nname, unless the extension is already there.","title":"yecc.file/2","ref":"yecc.html#file/2"},{"type":"function","doc":"Returns a descriptive string in English of an error reason `ErrorDescriptor`\nreturned by `yecc:file/1,2`.\n\nThis function is mainly used by the compiler invoking Yecc.","title":"yecc.format_error/1","ref":"yecc.html#format_error/1"},{"type":"type","doc":"The standard `t:error_info/0` structure that is returned from all I/O modules.\n\n`ErrorDescriptor` is formattable by `format_error/1`.","title":"yecc.error_info/0","ref":"yecc.html#t:error_info/0"},{"type":"type","doc":"","title":"yecc.error_ret/0","ref":"yecc.html#t:error_ret/0"},{"type":"type","doc":"","title":"yecc.errors/0","ref":"yecc.html#t:errors/0"},{"type":"type","doc":"","title":"yecc.ok_ret/0","ref":"yecc.html#t:ok_ret/0"},{"type":"type","doc":"","title":"yecc.option/0","ref":"yecc.html#t:option/0"},{"type":"type","doc":"","title":"yecc.warnings/0","ref":"yecc.html#t:warnings/0"},{"type":"type","doc":"","title":"yecc.yecc_ret/0","ref":"yecc.html#t:yecc_ret/0"},{"type":"extras","doc":"\n# Parsetools Release Notes\n\nThis document describes the changes made to the Parsetools application.","title":"Parsetools Release Notes","ref":"notes.html"},{"type":"extras","doc":"","title":"Parsetools 2.6 - Parsetools Release Notes","ref":"notes.html#parsetools-2-6"},{"type":"extras","doc":"- The `leex` documentation has been updated to use specs for documenting the generated interface.\n\n Own Id: OTP-18796 Aux Id: [PR-7703]\n\n- yecc now wraps the `-module` attribute with `-file` to indicate the `.yrl` source file.\n\n Own Id: OTP-18912 Aux Id: [PR-7963]\n\n- The documentation has been migrated to use Markdown and ExDoc.\n\n Own Id: OTP-18955 Aux Id: [PR-8026]\n\n[PR-7703]: https://github.com/erlang/otp/pull/7703\n[PR-7963]: https://github.com/erlang/otp/pull/7963\n[PR-8026]: https://github.com/erlang/otp/pull/8026","title":"Improvements and New Features - Parsetools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Parsetools 2.5 - Parsetools Release Notes","ref":"notes.html#parsetools-2-5"},{"type":"extras","doc":"- Leex has been extended with optional column number support.\n\n Own Id: OTP-18491 Aux Id: PR-6882","title":"Improvements and New Features - Parsetools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Parsetools 2.4.1 - Parsetools Release Notes","ref":"notes.html#parsetools-2-4-1"},{"type":"extras","doc":"- There is a new configure option, `--enable-deterministic-build`, which will\n apply the `deterministic` compiler option when building Erlang/OTP. The\n `deterministic` option has been improved to eliminate more sources of\n non-determinism in several applications.\n\n Own Id: OTP-18165 Aux Id: PR-5965","title":"Improvements and New Features - Parsetools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Parsetools 2.4 - Parsetools Release Notes","ref":"notes.html#parsetools-2-4"},{"type":"extras","doc":"- In the generated code, `yecc` will now quote all atoms coming from terminals\n in the grammar, in order to avoid conflicts with future reserved words.\n\n Own Id: OTP-17755","title":"Improvements and New Features - Parsetools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Parsetools 2.3.2 - Parsetools Release Notes","ref":"notes.html#parsetools-2-3-2"},{"type":"extras","doc":"- The default parser include file for yecc (`yeccpre`) will no longer crash when\n attempting to print tokens when reporting an error.\n\n Own Id: OTP-17721","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Parsetools 2.3.1 - Parsetools Release Notes","ref":"notes.html#parsetools-2-3-1"},{"type":"extras","doc":"- Fix a bug in Leex which caused the Erlang Compiler to generate warnings.\n\n Own Id: OTP-17499 Aux Id: GH-4918\n\n- Fix a bug in Yecc which caused the Erlang Compiler to generate warnings.\n\n Own Id: OTP-17535 Aux Id: GH-5067","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Parsetools 2.3 - Parsetools Release Notes","ref":"notes.html#parsetools-2-3"},{"type":"extras","doc":"- Add types and specifications for documentation.\n\n Own Id: OTP-16957\n\n- Let Leex and Yecc recognize the environment variable ERL_COMPILER_OPTIONS. Add\n Yecc option `{error_location, column | line}`.\n\n Own Id: OTP-17023","title":"Improvements and New Features - Parsetools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Parsetools 2.2 - Parsetools Release Notes","ref":"notes.html#parsetools-2-2"},{"type":"extras","doc":"- Remove usage and documentation of old requests of the I/O-protocol.\n\n Own Id: OTP-15695","title":"Improvements and New Features - Parsetools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Parsetools 2.1.8 - Parsetools Release Notes","ref":"notes.html#parsetools-2-1-8"},{"type":"extras","doc":"- Improved documentation.\n\n Own Id: OTP-15190","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Parsetools 2.1.7 - Parsetools Release Notes","ref":"notes.html#parsetools-2-1-7"},{"type":"extras","doc":"- Calls to `erlang:get_stacktrace()` are removed.\n\n Own Id: OTP-14861","title":"Improvements and New Features - Parsetools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Parsetools 2.1.6 - Parsetools Release Notes","ref":"notes.html#parsetools-2-1-6"},{"type":"extras","doc":"- Warnings about unused functions in `leexinc.hrl` are suppressed.\n\n Own Id: OTP-14697","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Parsetools 2.1.5 - Parsetools Release Notes","ref":"notes.html#parsetools-2-1-5"},{"type":"extras","doc":"- Minor documentation fixes\n\n Own Id: OTP-14276 Aux Id: PR-1357","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Miscellaneous updates due to atoms containing arbitrary Unicode characters.\n\n Own Id: OTP-14285","title":"Improvements and New Features - Parsetools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Parsetools 2.1.4 - Parsetools Release Notes","ref":"notes.html#parsetools-2-1-4"},{"type":"extras","doc":"- Correct counting of newlines when rules with newlines are used in Leex.\n\n Own Id: OTP-13916 Aux Id: ERL-263\n\n- Correct handling of Unicode in Leex.\n\n Own Id: OTP-13919","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Parsetools 2.1.3 - Parsetools Release Notes","ref":"notes.html#parsetools-2-1-3"},{"type":"extras","doc":"- Yecc generates Dialyzer suppressions to avoid warnings when operator\n precedence declarations are used.\n\n Own Id: OTP-13681","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Parsetools 2.1.2 - Parsetools Release Notes","ref":"notes.html#parsetools-2-1-2"},{"type":"extras","doc":"- Internal changes\n\n Own Id: OTP-13551","title":"Improvements and New Features - Parsetools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Parsetools 2.1.1 - Parsetools Release Notes","ref":"notes.html#parsetools-2-1-1"},{"type":"extras","doc":"- Correct the documentation of the error tuple returned by Yecc and Leex.\n\n Own Id: OTP-13031","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Parsetools 2.1 - Parsetools Release Notes","ref":"notes.html#parsetools-2-1"},{"type":"extras","doc":"- The new `-dialyzer()` attribute is used for suppressing Dialyzer warnings in\n generated code.\n\n Own Id: OTP-12271","title":"Improvements and New Features - Parsetools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Parsetools 2.0.12 - Parsetools Release Notes","ref":"notes.html#parsetools-2-0-12"},{"type":"extras","doc":"- The line counter becomes invalid when rules with linewrap are used. This issue\n appears because the parsing FSM does not roll back the line counter after\n attempting such a rule.\n\n Own Id: OTP-12238","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Parsetools 2.0.11 - Parsetools Release Notes","ref":"notes.html#parsetools-2-0-11"},{"type":"extras","doc":"- Application upgrade (appup) files are corrected for the following\n applications:\n\n `asn1, common_test, compiler, crypto, debugger, dialyzer, edoc, eldap, erl_docgen, et, eunit, gs, hipe, inets, observer, odbc, os_mon, otp_mibs, parsetools, percept, public_key, reltool, runtime_tools, ssh, syntax_tools, test_server, tools, typer, webtool, wx, xmerl`\n\n A new test utility for testing appup files is added to test_server. This is\n now used by most applications in OTP.\n\n (Thanks to Tobias Schlager)\n\n Own Id: OTP-11744\n\n- A Yecc example has been updated in the documentation (Thanks to Pierre\n Fenoll.)\n\n Own Id: OTP-11749","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Parsetools 2.0.10 - Parsetools Release Notes","ref":"notes.html#parsetools-2-0-10"},{"type":"extras","doc":"- A bug causing Yecc to generate badly formed parsers when encountering very\n simple recursive rules has been fixed. (Thanks to Eric Pailleau.)\n\n Own Id: OTP-11269\n\n- A bug where Unicode filenames combined with Latin-1 encoding could crash Yecc\n and Leex has been fixed.\n\n Own Id: OTP-11286","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Fix leex module\\`s inability to build unicode-aware lexers. Thanks to Pierre\n Fenoll.\n\n Own Id: OTP-11313","title":"Improvements and New Features - Parsetools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Parsetools 2.0.9 - Parsetools Release Notes","ref":"notes.html#parsetools-2-0-9"},{"type":"extras","doc":"- Miscellaneous updates due to Unicode support.\n\n Own Id: OTP-10820","title":"Improvements and New Features - Parsetools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Parsetools 2.0.8 - Parsetools Release Notes","ref":"notes.html#parsetools-2-0-8"},{"type":"extras","doc":"- Support for Unicode has been implemented.\n\n Own Id: OTP-10302\n\n- The file `esyntax.yrl` has been removed.\n\n Own Id: OTP-10660","title":"Improvements and New Features - Parsetools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Parsetools 2.0.7 - Parsetools Release Notes","ref":"notes.html#parsetools-2-0-7"},{"type":"extras","doc":"- Tuple funs (a two-element tuple with a module name and a function) are now\n officially deprecated and will be removed in R16. Use '`fun M:F/A`' instead.\n To make you aware that your system uses tuple funs, the very first time a\n tuple fun is applied, a warning will be sent to the error logger.\n\n Own Id: OTP-9649","title":"Improvements and New Features - Parsetools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Parsetools 2.0.6 - Parsetools Release Notes","ref":"notes.html#parsetools-2-0-6"},{"type":"extras","doc":"- Dialyzer warnings have been removed.\n\n Own Id: OTP-8318\n\n- yecc: add warnings_as_errors option(Thanks to Tuncer ayaz)\n\n Own Id: OTP-9376\n\n- Fix incorrect order of pseudo variables in yecc example\n\n The example is for converting from infix to prefix. This change uses to\n correct ordering of the triplet. (Thanks to Garret Smith)\n\n Own Id: OTP-9484\n\n- Implement or fix -Werror option\n\n If -Werror is enabled and there are warnings no output file is written. Also\n make sure that error/warning reporting is consistent. (Thanks to Tuncer Ayaz)\n\n Own Id: OTP-9536\n\n- XML files have been corrected.\n\n Own Id: OTP-9550 Aux Id: OTP-9541","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Parsetools 2.0.5 - Parsetools Release Notes","ref":"notes.html#parsetools-2-0-5"},{"type":"extras","doc":"- The formatting of Yecc's error messages has been improved. (Thanks to Joe\n Armstrong.)\n\n Own Id: OTP-8919","title":"Improvements and New Features - Parsetools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Parsetools 2.0.4 - Parsetools Release Notes","ref":"notes.html#parsetools-2-0-4"},{"type":"extras","doc":"- Running HiPE-compiled Yecc parsers no longer results in a `function_clause`\n error.\n\n Own Id: OTP-8771","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Parsetools 2.0.3 - Parsetools Release Notes","ref":"notes.html#parsetools-2-0-3"},{"type":"extras","doc":"- Yecc failed to report reduce/reduce conflicts where one of the reductions\n involved the root symbol. This bug has been fixed. (Thanks to Manolis\n Papadakis.)\n\n Own Id: OTP-8483\n\n- A bug introduced in Parsetools 1.4.4 (R12B-2) has been fixed. (Thanks to\n Manolis Papadakis.)\n\n Own Id: OTP-8486","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Parsetools 2.0.2 - Parsetools Release Notes","ref":"notes.html#parsetools-2-0-2"},{"type":"extras","doc":"- Cleanups suggested by tidier and modernization of types and specs.\n\n Own Id: OTP-8455","title":"Improvements and New Features - Parsetools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Parsetools 2.0.1 - Parsetools Release Notes","ref":"notes.html#parsetools-2-0-1"},{"type":"extras","doc":"- Leex no longer uses the deprecated `regexp` module. (Thanks to Robert\n Virding.).\n\n Own Id: OTP-8231","title":"Improvements and New Features - Parsetools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"- A minor bug in `m:leex` has been fixed.\n\n Own Id: OTP-8197","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Parsetools 2.0 - Parsetools Release Notes","ref":"notes.html#parsetools-2-0"},{"type":"extras","doc":"- Leex, a lexical analyzer generator for Erlang, has been added to Parsetools.\n This initial version should be considered experimental; it is known that there\n will be changes and additions. (Thanks to Robert Virding.).\n\n Own Id: OTP-8013","title":"Improvements and New Features - Parsetools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"- The parsers generated by Yecc now report correct error lines when possible.\n\n Own Id: OTP-7969","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Parsetools 1.4.7 - Parsetools Release Notes","ref":"notes.html#parsetools-1-4-7"},{"type":"extras","doc":"- A bug in yeccpre.hrl introduced in R13A has been fixed.\n\n Own Id: OTP-7945","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Parsetools 1.4.6 - Parsetools Release Notes","ref":"notes.html#parsetools-1-4-6"},{"type":"extras","doc":"- Updated file headers.\n\n Own Id: OTP-7798","title":"Improvements and New Features - Parsetools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Parsetools 1.4.5 - Parsetools Release Notes","ref":"notes.html#parsetools-1-4-5"},{"type":"extras","doc":"- The `yecc` grammar has been augmented with an optional header section. (Thanks\n to Richard Carlsson.)\n\n Own Id: OTP-7292","title":"Improvements and New Features - Parsetools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Parsetools 1.4.4 - Parsetools Release Notes","ref":"notes.html#parsetools-1-4-4"},{"type":"extras","doc":"- The size of the code generated by Yecc has been reduced. The code is also\n faster.\n\n Macros can now be used in actions.\n\n Own Id: OTP-7224","title":"Improvements and New Features - Parsetools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Parsetools 1.4.3 - Parsetools Release Notes","ref":"notes.html#parsetools-1-4-3"},{"type":"extras","doc":"- [`tuple_size/1`](`tuple_size/1`) and [`byte_size/1`](`byte_size/1`) have been\n substituted for [`size/1`](`size/1`).\n\n Own Id: OTP-7009","title":"Improvements and New Features - Parsetools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Parsetools 1.4.2 - Parsetools Release Notes","ref":"notes.html#parsetools-1-4-2"},{"type":"extras","doc":"- The size of the code generated by yecc has been reduced.\n\n A note regarding the `includefile` option: although yecc can cope with\n includefiles based on some earlier `yeccpre.hrl` it is recommended for\n efficiency reasons to update includefiles as to follow the pattern in the\n latest `yeccpre.hrl`.\n\n Own Id: OTP-6851","title":"Improvements and New Features - Parsetools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Parsetools 1.4.1.1 - Parsetools Release Notes","ref":"notes.html#parsetools-1-4-1-1"},{"type":"extras","doc":"- Minor Makefile changes.\n\n Own Id: OTP-6689","title":"Improvements and New Features - Parsetools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Parsetools 1.4.1 - Parsetools Release Notes","ref":"notes.html#parsetools-1-4-1"},{"type":"extras","doc":"- A bug concerning precedence declarations of non-terminals \"one level up\" has\n been fixed in yecc.\n\n Own Id: OTP-6362","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Parsetools 1.4 - Parsetools Release Notes","ref":"notes.html#parsetools-1-4"},{"type":"extras","doc":"Several modifications of Yecc have been made:\n\n- The new functions `file/1,2` take the role of the old functions `yecc/2,3,4`.\n The latter functions are no longer documented but are kept for backward\n compatibility.\n- More checks of the grammar file have been implemented. Examples are warnings\n for unused non-terminals and duplicated declarations.\n- Invalid pseudo variables are no longer replaced by `'$undefined'` but cause a\n failure.\n- Reserved words no longer need to be quoted when used as terminals or\n non-terminals.\n- When compiling the generated parser file errors and warnings concerning user\n code refer to the grammar file, not the parser file.\n- Yecc emits a warning if there are conflicts in the grammar. The new\n declaration `Expect` can be used to suppress this warning.\n- The new operator precedence declaration `Nonassoc` can be used to declare\n operators with no associativity.\n- Precedence can be given to more than one operator with one single operator\n precedence declaration.\n- The function `parse_and_scan/1` in the default includefile accepts\n `{Function, A}` as well as \\{\\{M,F\\}, A\\} as tokenizer function. Exceptions in\n the tokenizer are never caught.\n- The functions `yecc:file/1,2` can be accessed from the Erlang shell via the\n new functions `c:y/1,2` in STDLIB.\n\nSee yecc(3) for further details.\n\nOwn Id: OTP-5366","title":"Improvements and Fixed Bugs - Parsetools Release Notes","ref":"notes.html#improvements-and-fixed-bugs"},{"type":"extras","doc":"","title":"Parsetools 1.3.2 - Parsetools Release Notes","ref":"notes.html#parsetools-1-3-2"},{"type":"extras","doc":"- A bug in `Yecc` that was introduced in R9B has been removed. Another bug\n concerning precedence declaration \"one level up\" has been fixed.\n\n Own Id: OTP-5461","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Parsetools 1.3.1 - Parsetools Release Notes","ref":"notes.html#parsetools-1-3-1"},{"type":"extras","doc":"- A bug in the file `parsetools/include/yeccpre.hrl` caused\n `yecc:parse_and_scan/1` to always report a parse failure when the lexer\n reported end-of-file. This problem has been fixed.\n\n Own Id: OTP-5369","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"}],"content_type":"text/plain","producer":{"name":"ex_doc","version":[48,46,51,52,46,49]}} \ No newline at end of file diff --git a/prs/9045/lib/parsetools-2.6/doc/html/dist/search_data-F08ECED6.js b/prs/9045/lib/parsetools-2.6/doc/html/dist/search_data-F08ECED6.js new file mode 100644 index 000000000000..35ce7ec72184 --- /dev/null +++ b/prs/9045/lib/parsetools-2.6/doc/html/dist/search_data-F08ECED6.js @@ -0,0 +1 @@ +searchData={"items":[{"type":"module","title":"leex","doc":"Lexical analyzer generator for Erlang\n\nA regular expression based lexical analyzer generator for Erlang, similar to\n`lex` or `flex`.\n\n> #### Note {: .info }\n>\n> The `leex` module was considered experimental when it was introduced.","ref":"leex.html"},{"type":"module","title":"Default Leex Options - leex","doc":"The (host operating system) environment variable `ERL_COMPILER_OPTIONS` can be\nused to give default Leex options. Its value must be a valid Erlang term. If the\nvalue is a list, it is used as is. If it is not a list, it is put into a list.\n\nThe list is appended to any options given to `file/2`.\n\nThe list can be retrieved with `compile:env_compiler_options/0`.","ref":"leex.html#module-default-leex-options"},{"type":"module","title":"Input File Format - leex","doc":"Erlang style comments starting with a `%` are allowed in scanner files. A\ndefinition file has the following format:\n\n```text\n \n\nDefinitions.\n\n \n\nRules.\n\n \n\nErlang code.\n\n \n```\n\nThe `Definitions.`, `Rules.`, and `Erlang code` headings are mandatory\nand must start at the beginning of a source line. The ` `,\n` `, and ` ` sections are allowed to be\nempty, but there must be at least one rule.\n\nMacro definitions have the following format:\n\n```text\nNAME = VALUE\n```\n\nand there must be spaces around `=`. Macros can be used in the regular\nexpressions of rules by writing `{NAME}`.\n\n> #### Note {: .info }\n>\n> When macros are expanded in expressions, the macro calls are replaced by the\n> macro value without any form of quoting or enclosing in parentheses.\n\nRules have the following format:\n\n```text\n : .\n```\n\nThe ` ` must occur at the start of a line and not include any blanks; use\n`\\t` and `\\s` to include TAB and SPACE characters in the regular expression. If\n` ` matches then the corresponding ` ` is evaluated to generate a\ntoken. With the Erlang code the following predefined variables are available:\n\n- **`TokenChars`** - A list of the characters in the matched token.\n\n- **`TokenLen`** - The number of characters in the matched token.\n\n- **`TokenLine`** - The line number where the token occurred.\n\n- **`TokenCol`** - The column number where the token occurred (column of the\n first character included in the token).\n\n- **`TokenLoc`** - Token location. Expands to `{TokenLine,TokenCol}` (even when\n `error_location` is set to `line`).\n\nThe code must return:\n\n- **`{token,Token}`** - Return `Token` to the caller.\n\n- **`{end_token,Token}`** - Return `Token` and is last token in a tokens call.\n\n- **`skip_token`** - Skip this token completely.\n\n- **`{error,ErrString}`** - An error in the token, `ErrString` is a string\n describing the error.\n\nIt is also possible to push back characters into the input characters with the\nfollowing returns:\n\n- `{token,Token,PushBackList}`\n- `{end_token,Token,PushBackList}`\n- `{skip_token,PushBackList}`\n\nThese have the same meanings as the normal returns but the characters in\n`PushBackList` will be prepended to the input characters and scanned for the\nnext token. Note that pushing back a newline will mean the line numbering will\nno longer be correct.\n\n> #### Note {: .info }\n>\n> Pushing back characters gives you unexpected possibilities to cause the\n> scanner to loop\\!\n\nThe following example would match a simple Erlang integer or float and return a\ntoken which could be sent to the Erlang parser:\n\n```erlang\nD = [0-9]\n\n{D}+ :\n {token,{integer,TokenLine,list_to_integer(TokenChars)}}.\n\n{D}+\\.{D}+((E|e)(\\+|\\-)?{D}+)? :\n {token,{float,TokenLine,list_to_float(TokenChars)}}.\n```\n\nThe Erlang code in the `Erlang code.` section is written into the output file\ndirectly after the module declaration and predefined exports declaration, making\nit possible to add extra exports, define imports, and other attributes, which are\nvisible in the whole file.","ref":"leex.html#module-input-file-format"},{"type":"module","title":"Regular Expressions - leex","doc":"The regular expressions allowed here is a subset of the set found in `egrep` and\nin the AWK programming language, as defined in the book _The AWK Programming\nLanguage_ by A. V. Aho, B. W. Kernighan, and P. J. Weinberger. They are composed of\nthe following characters:\n\n- **`c`** - Matches the non-metacharacter c.\n\n- **`\\c`** - Matches the escape sequence or literal character c.\n\n- **`.`** - Matches any character.\n\n- **`^`** - Matches the beginning of a string.\n\n- **`$`** - Matches the end of a string.\n\n- **`[abc...]`** - Character class, which matches any of the characters\n `abc...`. Character ranges are specified by a pair of characters separated by\n a `-`.\n\n- **`[^abc...]`** - Negated character class, which matches any character except\n `abc...`.\n\n- **`r1 | r2`** - Alternation. It matches either `r1` or `r2`.\n\n- **`r1r2`** - Concatenation. It matches `r1` and then `r2`.\n\n- **`r+`** - Matches one or more `r`s.\n\n- **`r*`** - Matches zero or more `r`s.\n\n- **`r?`** - Matches zero or one `r`s.\n\n- **`(r)`** - Grouping. It matches `r`.\n\nThe escape sequences allowed are the same as for Erlang strings:\n\n- **`\\b`** - Backspace.\n\n- **`\\f`** - Form feed.\n\n- **`\\n`** - Newline (line feed).\n\n- **`\\r`** - Carriage return.\n\n- **`\\t`** - Tab.\n\n- **`\\e`** - Escape.\n\n- **`\\v`** - Vertical tab.\n\n- **`\\s`** - Space.\n\n- **`\\d`** - Delete.\n\n- **`\\ddd`** - The octal value `ddd`.\n\n- **`\\xhh`** - The hexadecimal value `hh`.\n\n- **`\\x{h...}`** - The hexadecimal value `h...`.\n\n- **`\\c`** - Any other character literally, for example `\\\\` for backslash, `\\\"`\n for `\"`.\n\nThe following examples define simplified versions of a few Erlang data types:\n\n```text\nAtoms [a-z][0-9a-zA-Z_]*\n\nVariables [A-Z_][0-9a-zA-Z_]*\n\nFloats (\\+|-)?[0-9]+\\.[0-9]+((E|e)(\\+|-)?[0-9]+)?\n```\n\n> #### Note {: .info }\n>\n> Anchoring a regular expression with `^` and `$` is not implemented in the\n> current version of `leex` and generates a parse error.","ref":"leex.html#module-regular-expressions"},{"type":"function","title":"leex.file/1","doc":"","ref":"leex.html#file/1"},{"type":"function","title":"leex.file/2","doc":"Generates a lexical analyzer from the definition in the input file.\n\nThe input file has the extension `.xrl`. This is added to the filename\nif it is not given. The resulting module is the Xrl filename without\nthe `.xrl` extension.\n\nThe current options are:\n\n- **`dfa_graph`** - Generates a `.dot` file which contains a description of the\n DFA in a format which can be viewed with Graphviz, `www.graphviz.com`.\n\n- **`{includefile,Includefile}`** - Uses a specific or customised prologue file\n instead of default `lib/parsetools/include/leexinc.hrl` which is otherwise\n included.\n\n- **`{report_errors, boolean()}`** - Causes errors to be printed as they occur.\n Default is `true`.\n\n- **`{report_warnings, boolean()}`** - Causes warnings to be printed as they\n occur. Default is `true`.\n\n- **`{report, boolean()}`** - This is a short form for both `report_errors` and\n `report_warnings`.\n\n- **`{return_errors, boolean()}`** - If this flag is set,\n `{error, Errors, Warnings}` is returned when there are errors. Default is\n `false`.\n\n- **`{return_warnings, boolean()}`** - If this flag is set, an extra field\n containing `Warnings` is added to the tuple returned upon success. Default is\n `false`.\n\n- **`{return, boolean()}`** - This is a short form for both `return_errors` and\n `return_warnings`.\n\n- **`{scannerfile, Scannerfile}`** - `Scannerfile` is the name of the file that\n will contain the Erlang scanner code that is generated. The default (`\"\"`) is\n to add the extension `.erl` to `FileName` stripped of the `.xrl` extension.\n\n- **`{verbose, boolean()}`** - Outputs information from parsing the input file\n and generating the internal tables.\n\n- **`{warnings_as_errors, boolean()}`** - Causes warnings to be treated as\n errors.\n\n- **`{deterministic, boolean()}`** - Causes generated `-file()` attributes to only\n include the basename of the file path.\n\n- **`{error_location, line | column}`** - If set to `column`, error location\n will be `{Line,Column}` tuple instead of just `Line`. Also, `StartLoc` and\n `EndLoc` in [`string/2`](`string/2`), [`token/3`](`token/3`), and\n [`tokens/3`](`tokens/3`) functions will be `{Line,Column}` tuple instead of\n just `Line`. Default is `line`. Note that you can use `TokenLoc` for token\n location independently, even if the `error_location` is set to `line`.\n\n Unicode characters are counted as many columns as they use bytes to represent.\n\n- **`{tab_size, pos_integer()}`** - Sets the width of `\\t` character (only\n relevant if `error_location` is set to `column`). Default is `8`.\n\nAny of the Boolean options can be set to `true` by stating the name of the\noption. For example, `verbose` is equivalent to `{verbose, true}`.\n\nLeex will add the extension `.hrl` to the `Includefile` name and the extension\n`.erl` to the `Scannerfile` name, unless the extension is already there.","ref":"leex.html#file/2"},{"type":"function","title":"leex.format_error/1","doc":"Returns a descriptive string in English of an error reason `ErrorDescriptor`\nreturned by [`leex:file/1,2`](`file/1`) when there is an error in a regular\nexpression.","ref":"leex.html#format_error/1"},{"type":"function","title":"leex.string/1","doc":"","ref":"leex.html#string/1"},{"type":"function","title":"leex.string/2","doc":"Scans `String` and returns either all the tokens in it or an `error` tuple.\n\n`StartLoc` and `EndLoc` are either [`erl_anno:line()`](`t:erl_anno:line/0`)\nor [`erl_anno:location()`](`t:erl_anno:location/0`), depending on the\n`error_location` option.\n\n> #### Note {: .info }\n>\n> It is an error if not all of the characters in `String` are consumed.","ref":"leex.html#string/2"},{"type":"function","title":"leex.token/2","doc":"","ref":"leex.html#token/2"},{"type":"function","title":"leex.token/3","doc":"This is a re-entrant call to try and scan a single token from `Chars`.\n\nIf there are enough characters in `Chars` to either scan a token or\ndetect an error then this will be returned with\n`{done,...}`. Otherwise `{cont,Cont}` will be returned where `Cont` is\nused in the next call to `token()` with more characters to try an scan\nthe token. This is continued until a token has been scanned. `Cont` is\ninitially `[]`.\n\nIt is not designed to be called directly by an application, but is\nused through the I/O system where it can typically be called in an\napplication by:\n\n```erlang\nio:request(InFile, {get_until,unicode,Prompt,Module,token,[Loc]})\n -> TokenRet\n```","ref":"leex.html#token/3"},{"type":"function","title":"leex.tokens/2","doc":"","ref":"leex.html#tokens/2"},{"type":"function","title":"leex.tokens/3","doc":"This is a re-entrant call to try and scan tokens from `Chars`.\n\nIf there are enough characters in `Chars` to either scan tokens or\ndetect an error then this will be returned with\n`{done,...}`. Otherwise `{cont,Cont}` will be returned where `Cont` is\nused in the next call to `tokens()` with more characters to try an\nscan the tokens. This is continued until all tokens have been\nscanned. `Cont` is initially `[]`.\n\nThis functions differs from `token` in that it will continue to scan tokens up\nto and including an `{end_token,Token}` has been scanned (see next section). It\nwill then return all the tokens. This is typically used for scanning grammars\nlike Erlang where there is an explicit end token, `'.'`. If no end token is\nfound then the whole file will be scanned and returned. If an error occurs then\nall tokens up to and including the next end token will be skipped.\n\nIt is not designed to be called directly by an application, but used through the\nI/O system where it can typically be called in an application by:\n\n```erlang\nio:request(InFile, {get_until,unicode,Prompt,Module,tokens,[Loc]})\n -> TokensRet\n```","ref":"leex.html#tokens/3"},{"type":"type","title":"leex.error_info/0","doc":"The standard `t:error_info/0` structure that is returned from all I/O modules.\n`ErrorDescriptor` is formattable by `format_error/1`.","ref":"leex.html#t:error_info/0"},{"type":"type","title":"leex.error_ret/0","doc":"","ref":"leex.html#t:error_ret/0"},{"type":"type","title":"leex.errors/0","doc":"","ref":"leex.html#t:errors/0"},{"type":"type","title":"leex.leex_ret/0","doc":"","ref":"leex.html#t:leex_ret/0"},{"type":"type","title":"leex.ok_ret/0","doc":"","ref":"leex.html#t:ok_ret/0"},{"type":"type","title":"leex.warnings/0","doc":"","ref":"leex.html#t:warnings/0"},{"type":"module","title":"yecc","doc":"LALR-1 Parser Generator\n\nAn LALR-1 parser generator for Erlang, similar to `yacc`. Takes a BNF grammar\ndefinition as input, and produces Erlang code for a parser.\n\nTo understand this text, you also have to look at the `yacc` documentation in\nthe UNIX(TM) manual. This is most probably necessary in order to understand the\nidea of a parser generator, and the principle and problems of LALR parsing with\nfinite look-ahead.\n\nAn nice introduction to `yacc` can be found in chapter 8 of \"The UNIX\nProgramming Environment\" by Brian W. Kernighan and Rob Pike.","ref":"yecc.html"},{"type":"module","title":"Default Yecc Options - yecc","doc":"The (host operating system) environment variable `ERL_COMPILER_OPTIONS` can be\nused to give default Yecc options. Its value must be a valid Erlang term. If the\nvalue is a list, it is used as is. If it is not a list, it is put into a list.\n\nThe list is appended to any options given to `file/2`.\n\nThe list can be retrieved with `compile:env_compiler_options/0`.","ref":"yecc.html#module-default-yecc-options"},{"type":"module","title":"Pre-Processing - yecc","doc":"A `scanner` to pre-process the text (program) to be parsed is not provided\nin the `yecc` module. The scanner serves as a kind of lexicon look-up routine.\nIt is possible to write a grammar that uses only character tokens as terminal\nsymbols, thereby eliminating the need for a scanner, but this would make the\nparser larger and slower.\n\nThe user should implement a scanner that segments the input text, and turns it\ninto one or more lists of tokens. Each token should be a tuple containing\ninformation about syntactic category, position in the text (for example\nline number), and the actual terminal symbol found in the text:\n`{Category, Position, Symbol}`.\n\nIf a terminal symbol is the only member of a category, and the symbol name is\nidentical to the category name, the token format can be `{Symbol, Position}`.\n\nA list of tokens produced by the scanner should end with a special\n`end_of_input` tuple which the parser is looking for. The format of this tuple\nshould be `{Endsymbol, EndPosition}`, where `Endsymbol` is an identifier that is\ndistinguished from all the terminal and non-terminal categories of the syntax\nrules. The `Endsymbol` can be declared in the grammar file.\n\nThe simplest case is to segment the input string into a list of identifiers\n(atoms) and use those atoms both as categories and values of the tokens. For\nexample, the input string `aaa bbb 777, X` may be scanned (tokenized) as:\n\n```erlang\n[{aaa, 1}, {bbb, 1}, {777, 1}, {',' , 1}, {'X', 1},\n {'$end', 1}].\n```\n\nThis assumes that this is the first line of the input text, and that `'$end'` is\nthe distinguished `end_of_input` symbol.\n\nThe Erlang scanner in the `io` module can be used as a starting point when\nwriting a new scanner. Study `yeccscan.erl` in order to see how a filter can be\nadded on top of `io:scan_erl_form/3` to provide a scanner for Yecc that\ntokenizes grammar files before parsing them with the Yecc parser. A more general\napproach to scanner implementation is to use a scanner generator such as\n`m:leex`.","ref":"yecc.html#module-pre-processing"},{"type":"module","title":"Grammar Definition Format - yecc","doc":"Erlang style `comments`, starting with a `'%'`, are allowed in grammar files.\n\nEach `declaration` or `rule` ends with a dot (the character `'.'`).\n\nThe grammar starts with an optional `header` section. The header is put first in\nthe generated file, before the module declaration. The purpose of the header is\nto provide a means to make the documentation generated by [EDoc](`e:edoc:edoc.md`)\nlook nicer. Each header line should be enclosed in double quotes, and newlines\nwill be inserted between the lines. For example:\n\n```erlang\nHeader \"%% Copyright (C)\"\n\"%% @private\"\n\"%% @Author John\".\n```\n\nNext comes a declaration of the `nonterminal categories` to be used in the\nrules. For example:\n\n```text\nNonterminals sentence nounphrase verbphrase.\n```\n\nA non-terminal category can be used at the left-hand side (= `lhs`, or `head`)\nof a grammar rule. It can also appear at the right-hand side of rules.\n\nNext comes a declaration of the `terminal categories`, which are the categories\nof tokens produced by the scanner. For example:\n\n```text\nTerminals article adjective noun verb.\n```\n\nTerminal categories may only appear in the right hand sides (= `rhs`) of grammar\nrules.\n\nNext comes a declaration of the `rootsymbol`, or start category of the grammar.\nFor example:\n\n```text\nRootsymbol sentence.\n```\n\nThis symbol should appear in the lhs of at least one grammar rule. This is the\nmost general syntactic category which the parser ultimately will parse every\ninput string into.\n\nAfter the rootsymbol declaration comes an optional declaration of the\n`end_of_input` symbol that your scanner is expected to use. For example:\n\n```text\nEndsymbol '$end'.\n```\n\nNext comes one or more declarations of *operator precedences*, if needed. These\nare used to resolve shift/reduce conflicts (see `yacc` documentation).\n\nExamples of operator declarations:\n\n```text\nRight 100 '='.\nNonassoc 200 '==' '=/='.\nLeft 300 '+'.\nLeft 400 '*'.\nUnary 500 '-'.\n```\n\nThese declarations mean that `'='` is defined as a `right associative binary`\noperator with precedence 100, `'=='` and `'=/='` are operators with\n`no associativity`, `'+'` and `'*'` are `left associative binary` operators,\nwhere `'*'` takes precedence over `'+'` (the normal case), and `'-'` is a\n`unary` operator of higher precedence than `'*'`. The fact that '==' has no\nassociativity means that an expression like `a == b == c` is considered a syntax\nerror.\n\nCertain rules are assigned precedence: each rule gets its precedence from the\nlast terminal symbol mentioned in the right hand side of the rule. It is also\npossible to declare precedence for non-terminals, \"one level up\". This is\npractical when an operator is overloaded (see also example 3 below).\n\nNext come the *grammar rules*. Each rule has the general form\n\n```erlang\nLeft_hand_side -> Right_hand_side : Associated_code.\n```\n\nThe left hand side is a non-terminal category. The right hand side is a sequence\nof one or more non-terminal or terminal symbols with spaces between. The\nassociated code is a sequence of zero or more Erlang expressions (with commas\n`','` as separators). If the associated code is empty, the separating colon\n`':'` is also omitted. A final dot marks the end of the rule.\n\nSymbols such as `'{'`, `'.'`, and so on, have to be enclosed in single quotes\nwhen used as terminal or non-terminal symbols in grammar rules. The use of the\nsymbols `'$empty'`, `'$end'`, and `'$undefined'` should be avoided.\n\nThe last part of the grammar file is an optional section with Erlang code (=\nfunction definitions) which is included 'as is' in the resulting parser file.\nThis section must start with the pseudo declaration, or key words\n\n```text\nErlang code.\n```\n\nNo syntax rule definitions or other declarations must follow this section. To\navoid conflicts with internal variables, do not use variable names beginning\nwith two underscore characters (`'__'`) in the Erlang code in this section, or\nin the code associated with the individual syntax rules.\n\nThe optional `expect` declaration can be placed anywhere before the last\noptional section with Erlang code. It is used for suppressing the warning about\nconflicts that is ordinarily given if the grammar is ambiguous. An example:\n\n```text\nExpect 2.\n```\n\nThe warning is given if the number of shift/reduce conflicts differs from 2, or\nif there are reduce/reduce conflicts.","ref":"yecc.html#module-grammar-definition-format"},{"type":"module","title":"Examples - yecc","doc":"A grammar to parse list expressions (with empty associated code):\n\n```text\nNonterminals list elements element.\nTerminals atom '(' ')'.\nRootsymbol list.\nlist -> '(' ')'.\nlist -> '(' elements ')'.\nelements -> element.\nelements -> element elements.\nelement -> atom.\nelement -> list.\n```\n\nThis grammar can be used to generate a parser which parses list expressions,\nsuch as `(), (a), (peter charles), (a (b c) d (())), ...` provided that your\nscanner tokenizes, for example, the input `(peter charles)` as follows:\n\n```erlang\n[{'(', 1} , {atom, 1, peter}, {atom, 1, charles}, {')', 1},\n {'$end', 1}]\n```\n\nWhen a grammar rule is used by the parser to parse (part of) the input string as\na grammatical phrase, the associated code is evaluated, and the value of the\nlast expression becomes the value of the parsed phrase. This value may be used\nby the parser later to build structures that are values of higher phrases of\nwhich the current phrase is a part. The values initially associated with\nterminal category phrases, i.e. input tokens, are the token tuples themselves.\n\nBelow is an example of the grammar above with structure building code added:\n\n```text\nlist -> '(' ')' : nil.\nlist -> '(' elements ')' : '$2'.\nelements -> element : {cons, '$1', nil}.\nelements -> element elements : {cons, '$1', '$2'}.\nelement -> atom : '$1'.\nelement -> list : '$1'.\n```\n\nWith this code added to the grammar rules, the parser produces the following\nvalue (structure) when parsing the input string `(a b c).`. This still assumes\nthat this was the first input line that the scanner tokenized:\n\n```erlang\n{cons, {atom, 1, a}, {cons, {atom, 1, b},\n {cons, {atom, 1, c}, nil}}}\n```\n\nThe associated code contains `pseudo variables` `'$1'`, `'$2'`,\n`'$3'`, and so on. which refer to (are bound to) the values\nassociated previously by the parser with the symbols of the right-hand\nside of the rule. When these symbols are terminal categories, the\nvalues are token tuples of the input string (see above).\n\nThe associated code may not only be used to build structures\nassociated with phrases, but may also be used for syntactic and\nsemantic tests, printout actions (for example for tracing), and so on\nduring the parsing process. Since tokens contain positional (line\nnumber) information, it is possible to produce error messages which\ncontain line numbers. If there is no associated code after the\nright-hand side of the rule, the value `'$undefined'` is associated\nwith the phrase.\n\nThe right-hand side of a grammar rule can be empty. This is indicated by using\nthe special symbol `'$empty'` as rhs. Then the list grammar above can be\nsimplified to:\n\n```text\nlist -> '(' elements ')' : '$2'.\nelements -> element elements : {cons, '$1', '$2'}.\nelements -> '$empty' : nil.\nelement -> atom : '$1'.\nelement -> list : '$1'.\n```","ref":"yecc.html#module-examples"},{"type":"module","title":"Generating a Parser - yecc","doc":"To call the parser generator, use the following command:\n\n```erlang\nyecc:file(Grammarfile).\n```\n\nAn error message from Yecc will be shown if the grammar is not of the LALR type\n(for example too ambiguous). Shift/reduce conflicts are resolved in favor of\nshifting if there are no operator precedence declarations. Refer to the `yacc`\ndocumentation on the use of operator precedence.\n\nThe output file contains Erlang source code for a parser module with module name\nequal to the `Parserfile` parameter. After compilation, the parser can be called\nas follows (the module name is assumed to be `myparser`):\n\n```erlang\nmyparser:parse(myscanner:scan(Inport))\n```\n\nThe call format can be different if a customized prologue file has been included\nwhen generating the parser instead of the default file\n`lib/parsetools/include/yeccpre.hrl`.\n\nWith the standard prologue, this call will return either `{ok, Result}`, where\n`Result` is a structure that the Erlang code of the grammar file has built, or\n`{error, {Position, Module, Message}}` if there was a syntax error in the input.\n\n`Message` is something which may be converted into a string by calling\n`Module:format_error(Message)` and printed with `io:format/3`.\n\n> #### Note {: .info }\n>\n> By default, the parser that was generated will not print out error messages to\n> the screen. The user will have to do this either by printing the returned\n> error messages, or by inserting tests and print instructions in the Erlang\n> code associated with the syntax rules of the grammar file.\n\nIt is also possible to make the parser ask for more input tokens when needed if\nthe following call format is used:\n\n```erlang\nmyparser:parse_and_scan({Function, Args})\nmyparser:parse_and_scan({Mod, Tokenizer, Args})\n```\n\nThe tokenizer `Function` is either a fun or a tuple `{Mod, Tokenizer}`. The call\n[`apply(Function, Args)`](`apply/2`) or\n[`apply({Mod, Tokenizer}, Args)`](`apply/2`) is executed whenever a new token is\nneeded. This, for example, makes it possible to parse from a file, token by\ntoken.\n\nThe tokenizer used above has to be implemented so as to return one of the\nfollowing:\n\n```erlang\n{ok, Tokens, EndPosition}\n{eof, EndPosition}\n{error, Error_description, EndPosition}\n```\n\nThis conforms to the format used by the scanner in the Erlang `io` library\nmodule.\n\nIf `{eof, EndPosition}` is returned immediately, the call to `parse_and_scan/1`\nreturns `{ok, eof}`. If `{eof, EndPosition}` is returned before the parser\nexpects end of input, `parse_and_scan/1` will, of course, return an error\nmessage (see above). Otherwise `{ok, Result}` is returned.","ref":"yecc.html#module-generating-a-parser"},{"type":"module","title":"More Examples - yecc","doc":"1\\. A grammar for parsing infix arithmetic expressions into prefix notation,\nwithout operator precedence:\n\n```text\nNonterminals E T F.\nTerminals '+' '*' '(' ')' number.\nRootsymbol E.\nE -> E '+' T: {'$2', '$1', '$3'}.\nE -> T : '$1'.\nT -> T '*' F: {'$2', '$1', '$3'}.\nT -> F : '$1'.\nF -> '(' E ')' : '$2'.\nF -> number : '$1'.\n```\n\n2\\. The same with operator precedence becomes simpler:\n\n```text\nNonterminals E.\nTerminals '+' '*' '(' ')' number.\nRootsymbol E.\nLeft 100 '+'.\nLeft 200 '*'.\nE -> E '+' E : {'$2', '$1', '$3'}.\nE -> E '*' E : {'$2', '$1', '$3'}.\nE -> '(' E ')' : '$2'.\nE -> number : '$1'.\n```\n\n3\\. An overloaded minus operator:\n\n```text\nNonterminals E uminus.\nTerminals '*' '-' number.\nRootsymbol E.\n\nLeft 100 '-'.\nLeft 200 '*'.\nUnary 300 uminus.\n\nE -> E '-' E.\nE -> E '*' E.\nE -> uminus.\nE -> number.\n\numinus -> '-' E.\n```\n\n4\\. The Yecc grammar that is used for parsing grammar files, including itself:\n\n```erlang\nNonterminals\ngrammar declaration rule head symbol symbols attached_code\ntoken tokens.\nTerminals\natom float integer reserved_symbol reserved_word string char var\n'->' ':' dot.\nRootsymbol grammar.\nEndsymbol '$end'.\ngrammar -> declaration : '$1'.\ngrammar -> rule : '$1'.\ndeclaration -> symbol symbols dot: {'$1', '$2'}.\nrule -> head '->' symbols attached_code dot: {rule, ['$1' | '$3'],\n '$4'}.\nhead -> symbol : '$1'.\nsymbols -> symbol : ['$1'].\nsymbols -> symbol symbols : ['$1' | '$2'].\nattached_code -> ':' tokens : {erlang_code, '$2'}.\nattached_code -> '$empty' : {erlang_code,\n [{atom, 0, '$undefined'}]}.\ntokens -> token : ['$1'].\ntokens -> token tokens : ['$1' | '$2'].\nsymbol -> var : value_of('$1').\nsymbol -> atom : value_of('$1').\nsymbol -> integer : value_of('$1').\nsymbol -> reserved_word : value_of('$1').\ntoken -> var : '$1'.\ntoken -> atom : '$1'.\ntoken -> float : '$1'.\ntoken -> integer : '$1'.\ntoken -> string : '$1'.\ntoken -> char : '$1'.\ntoken -> reserved_symbol : {value_of('$1'), line_of('$1')}.\ntoken -> reserved_word : {value_of('$1'), line_of('$1')}.\ntoken -> '->' : {'->', line_of('$1')}.\ntoken -> ':' : {':', line_of('$1')}.\nErlang code.\nvalue_of(Token) ->\n element(3, Token).\nline_of(Token) ->\n element(2, Token).\n```\n\n> #### Note {: .info }\n>\n> The symbols `'->'`, and `':'` have to be treated in a special way, as they are\n> meta symbols of the grammar notation, as well as terminal symbols of the Yecc\n> grammar.\n\n5\\. The file `erl_parse.yrl` in the `lib/stdlib/src` directory contains the\ngrammar for Erlang.\n\n> #### Note {: .info }\n>\n> Syntactic tests are used in the code associated with some rules, and an error\n> is thrown (and caught by the generated parser to produce an error message)\n> when a test fails. The same effect can be achieved with a call to\n> `return_error(ErrorPosition, Message_string)`, which is defined in the\n> `yeccpre.hrl` default header file.","ref":"yecc.html#module-more-examples"},{"type":"module","title":"Files - yecc","doc":"```text\nlib/parsetools/include/yeccpre.hrl\n```","ref":"yecc.html#module-files"},{"type":"module","title":"See Also - yecc","doc":"* Aho & Johnson: 'LR Parsing', ACM Computing Surveys, vol. 6:2, 1974.\n\n* Kernighan & Pike: The UNIX programming environment, 1984.","ref":"yecc.html#module-see-also"},{"type":"function","title":"yecc.file/1","doc":"","ref":"yecc.html#file/1"},{"type":"function","title":"yecc.file/2","doc":"Generates an Erlang file with the parser for the language described by `GrammarFile`.\n\n`Grammarfile` is the file of declarations and grammar rules. Returns `ok` upon\nsuccess, or `error` if there are errors. An Erlang file containing the parser is\ncreated if there are no errors.\n\nThe options are:\n\n- **`{includefile, Includefile}`.** - Indicates a customized prologue file which\n the user may want to use instead of the default file\n `lib/parsetools/include/yeccpre.hrl` which is otherwise included at the\n beginning of the resulting parser file. Note taht `Includefile` is included\n as is in the parser file, so it must not have a module declaration of its\n own, and it should not be compiled. It must, however, contain the necessary\n export declarations. The default is indicated by `\"\"`.\n\n- **`{parserfile, Parserfile}`.** - `Parserfile` is the name of the file that\n will contain the Erlang parser code that is generated. The default (`\"\"`) is\n to add the extension `.erl` to `Grammarfile` stripped of the `.yrl` extension.\n\n- **`{report_errors, boolean()}`.** - Causes errors to be printed as they occur.\n Default is `true`.\n\n- **`{report_warnings, boolean()}`.** - Causes warnings to be printed as they\n occur. Default is `true`.\n\n- **`{report, boolean()}`.** - This is a short form for both `report_errors` and\n `report_warnings`.\n\n- **`{return_errors, boolean()}`.** - If this flag is set,\n `{error, Errors, Warnings}` is returned when there are errors. Default is\n `false`.\n\n- **`{return_warnings, boolean()}`.** - If this flag is set, an extra field\n containing `Warnings` is added to the tuple returned upon success. Default is\n `false`.\n\n- **`{return, boolean()}`.** - This is a short form for both `return_errors` and\n `return_warnings`.\n\n- **`{verbose, boolean()}`.** - Determines whether the parser generator should\n give full information about resolved and unresolved parse action conflicts\n (`true`), or only about those conflicts that prevent a parser from being\n generated from the input grammar (`false`, the default).\n\n- **`{warnings_as_errors, boolean()}`** - Causes warnings to be treated as\n errors.\n\n- **`{error_location, column | line}`.** - If the value of this flag is `line`,\n the location of warnings and errors is a line number. If the value is\n `column`, the location includes a line number and a column number. Default is\n `column`.\n\n- **`{deterministic, boolean()}`** - Causes generated `-file()` attributes to only\n include the basename of the file path.\n\nAny of the Boolean options can be set to `true` by stating the name of the\noption. For example, `verbose` is equivalent to `{verbose, true}`.\n\nThe value of the `Parserfile` option stripped of the `.erl` extension is used by\nYecc as the module name of the generated parser file.\n\nYecc will add the extension `.yrl` to the `Grammarfile` name, the extension\n`.hrl` to the `Includefile` name, and the extension `.erl` to the `Parserfile`\nname, unless the extension is already there.","ref":"yecc.html#file/2"},{"type":"function","title":"yecc.format_error/1","doc":"Returns a descriptive string in English of an error reason `ErrorDescriptor`\nreturned by `yecc:file/1,2`.\n\nThis function is mainly used by the compiler invoking Yecc.","ref":"yecc.html#format_error/1"},{"type":"type","title":"yecc.error_info/0","doc":"The standard `t:error_info/0` structure that is returned from all I/O modules.\n\n`ErrorDescriptor` is formattable by `format_error/1`.","ref":"yecc.html#t:error_info/0"},{"type":"type","title":"yecc.error_ret/0","doc":"","ref":"yecc.html#t:error_ret/0"},{"type":"type","title":"yecc.errors/0","doc":"","ref":"yecc.html#t:errors/0"},{"type":"type","title":"yecc.ok_ret/0","doc":"","ref":"yecc.html#t:ok_ret/0"},{"type":"type","title":"yecc.option/0","doc":"","ref":"yecc.html#t:option/0"},{"type":"type","title":"yecc.warnings/0","doc":"","ref":"yecc.html#t:warnings/0"},{"type":"type","title":"yecc.yecc_ret/0","doc":"","ref":"yecc.html#t:yecc_ret/0"},{"type":"extras","title":"Parsetools Release Notes","doc":"\n# Parsetools Release Notes\n\nThis document describes the changes made to the Parsetools application.","ref":"notes.html"},{"type":"extras","title":"Parsetools 2.6 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-2-6"},{"type":"extras","title":"Improvements and New Features - Parsetools Release Notes","doc":"- The `leex` documentation has been updated to use specs for documenting the generated interface.\n\n Own Id: OTP-18796 Aux Id: [PR-7703]\n\n- yecc now wraps the `-module` attribute with `-file` to indicate the `.yrl` source file.\n\n Own Id: OTP-18912 Aux Id: [PR-7963]\n\n- The documentation has been migrated to use Markdown and ExDoc.\n\n Own Id: OTP-18955 Aux Id: [PR-8026]\n\n[PR-7703]: https://github.com/erlang/otp/pull/7703\n[PR-7963]: https://github.com/erlang/otp/pull/7963\n[PR-8026]: https://github.com/erlang/otp/pull/8026","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Parsetools 2.5 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-2-5"},{"type":"extras","title":"Improvements and New Features - Parsetools Release Notes","doc":"- Leex has been extended with optional column number support.\n\n Own Id: OTP-18491 Aux Id: PR-6882","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Parsetools 2.4.1 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-2-4-1"},{"type":"extras","title":"Improvements and New Features - Parsetools Release Notes","doc":"- There is a new configure option, `--enable-deterministic-build`, which will\n apply the `deterministic` compiler option when building Erlang/OTP. The\n `deterministic` option has been improved to eliminate more sources of\n non-determinism in several applications.\n\n Own Id: OTP-18165 Aux Id: PR-5965","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Parsetools 2.4 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-2-4"},{"type":"extras","title":"Improvements and New Features - Parsetools Release Notes","doc":"- In the generated code, `yecc` will now quote all atoms coming from terminals\n in the grammar, in order to avoid conflicts with future reserved words.\n\n Own Id: OTP-17755","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Parsetools 2.3.2 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-2-3-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","doc":"- The default parser include file for yecc (`yeccpre`) will no longer crash when\n attempting to print tokens when reporting an error.\n\n Own Id: OTP-17721","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Parsetools 2.3.1 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-2-3-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","doc":"- Fix a bug in Leex which caused the Erlang Compiler to generate warnings.\n\n Own Id: OTP-17499 Aux Id: GH-4918\n\n- Fix a bug in Yecc which caused the Erlang Compiler to generate warnings.\n\n Own Id: OTP-17535 Aux Id: GH-5067","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Parsetools 2.3 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-2-3"},{"type":"extras","title":"Improvements and New Features - Parsetools Release Notes","doc":"- Add types and specifications for documentation.\n\n Own Id: OTP-16957\n\n- Let Leex and Yecc recognize the environment variable ERL_COMPILER_OPTIONS. Add\n Yecc option `{error_location, column | line}`.\n\n Own Id: OTP-17023","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Parsetools 2.2 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-2-2"},{"type":"extras","title":"Improvements and New Features - Parsetools Release Notes","doc":"- Remove usage and documentation of old requests of the I/O-protocol.\n\n Own Id: OTP-15695","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Parsetools 2.1.8 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-2-1-8"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","doc":"- Improved documentation.\n\n Own Id: OTP-15190","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Parsetools 2.1.7 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-2-1-7"},{"type":"extras","title":"Improvements and New Features - Parsetools Release Notes","doc":"- Calls to `erlang:get_stacktrace()` are removed.\n\n Own Id: OTP-14861","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Parsetools 2.1.6 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-2-1-6"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","doc":"- Warnings about unused functions in `leexinc.hrl` are suppressed.\n\n Own Id: OTP-14697","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Parsetools 2.1.5 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-2-1-5"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","doc":"- Minor documentation fixes\n\n Own Id: OTP-14276 Aux Id: PR-1357","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Parsetools Release Notes","doc":"- Miscellaneous updates due to atoms containing arbitrary Unicode characters.\n\n Own Id: OTP-14285","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Parsetools 2.1.4 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-2-1-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","doc":"- Correct counting of newlines when rules with newlines are used in Leex.\n\n Own Id: OTP-13916 Aux Id: ERL-263\n\n- Correct handling of Unicode in Leex.\n\n Own Id: OTP-13919","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Parsetools 2.1.3 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-2-1-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","doc":"- Yecc generates Dialyzer suppressions to avoid warnings when operator\n precedence declarations are used.\n\n Own Id: OTP-13681","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Parsetools 2.1.2 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-2-1-2"},{"type":"extras","title":"Improvements and New Features - Parsetools Release Notes","doc":"- Internal changes\n\n Own Id: OTP-13551","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Parsetools 2.1.1 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-2-1-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","doc":"- Correct the documentation of the error tuple returned by Yecc and Leex.\n\n Own Id: OTP-13031","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Parsetools 2.1 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-2-1"},{"type":"extras","title":"Improvements and New Features - Parsetools Release Notes","doc":"- The new `-dialyzer()` attribute is used for suppressing Dialyzer warnings in\n generated code.\n\n Own Id: OTP-12271","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Parsetools 2.0.12 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-2-0-12"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","doc":"- The line counter becomes invalid when rules with linewrap are used. This issue\n appears because the parsing FSM does not roll back the line counter after\n attempting such a rule.\n\n Own Id: OTP-12238","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Parsetools 2.0.11 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-2-0-11"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","doc":"- Application upgrade (appup) files are corrected for the following\n applications:\n\n `asn1, common_test, compiler, crypto, debugger, dialyzer, edoc, eldap, erl_docgen, et, eunit, gs, hipe, inets, observer, odbc, os_mon, otp_mibs, parsetools, percept, public_key, reltool, runtime_tools, ssh, syntax_tools, test_server, tools, typer, webtool, wx, xmerl`\n\n A new test utility for testing appup files is added to test_server. This is\n now used by most applications in OTP.\n\n (Thanks to Tobias Schlager)\n\n Own Id: OTP-11744\n\n- A Yecc example has been updated in the documentation (Thanks to Pierre\n Fenoll.)\n\n Own Id: OTP-11749","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Parsetools 2.0.10 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-2-0-10"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","doc":"- A bug causing Yecc to generate badly formed parsers when encountering very\n simple recursive rules has been fixed. (Thanks to Eric Pailleau.)\n\n Own Id: OTP-11269\n\n- A bug where Unicode filenames combined with Latin-1 encoding could crash Yecc\n and Leex has been fixed.\n\n Own Id: OTP-11286","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Parsetools Release Notes","doc":"- Fix leex module\\`s inability to build unicode-aware lexers. Thanks to Pierre\n Fenoll.\n\n Own Id: OTP-11313","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Parsetools 2.0.9 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-2-0-9"},{"type":"extras","title":"Improvements and New Features - Parsetools Release Notes","doc":"- Miscellaneous updates due to Unicode support.\n\n Own Id: OTP-10820","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Parsetools 2.0.8 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-2-0-8"},{"type":"extras","title":"Improvements and New Features - Parsetools Release Notes","doc":"- Support for Unicode has been implemented.\n\n Own Id: OTP-10302\n\n- The file `esyntax.yrl` has been removed.\n\n Own Id: OTP-10660","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Parsetools 2.0.7 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-2-0-7"},{"type":"extras","title":"Improvements and New Features - Parsetools Release Notes","doc":"- Tuple funs (a two-element tuple with a module name and a function) are now\n officially deprecated and will be removed in R16. Use '`fun M:F/A`' instead.\n To make you aware that your system uses tuple funs, the very first time a\n tuple fun is applied, a warning will be sent to the error logger.\n\n Own Id: OTP-9649","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Parsetools 2.0.6 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-2-0-6"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","doc":"- Dialyzer warnings have been removed.\n\n Own Id: OTP-8318\n\n- yecc: add warnings_as_errors option(Thanks to Tuncer ayaz)\n\n Own Id: OTP-9376\n\n- Fix incorrect order of pseudo variables in yecc example\n\n The example is for converting from infix to prefix. This change uses to\n correct ordering of the triplet. (Thanks to Garret Smith)\n\n Own Id: OTP-9484\n\n- Implement or fix -Werror option\n\n If -Werror is enabled and there are warnings no output file is written. Also\n make sure that error/warning reporting is consistent. (Thanks to Tuncer Ayaz)\n\n Own Id: OTP-9536\n\n- XML files have been corrected.\n\n Own Id: OTP-9550 Aux Id: OTP-9541","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Parsetools 2.0.5 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-2-0-5"},{"type":"extras","title":"Improvements and New Features - Parsetools Release Notes","doc":"- The formatting of Yecc's error messages has been improved. (Thanks to Joe\n Armstrong.)\n\n Own Id: OTP-8919","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Parsetools 2.0.4 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-2-0-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","doc":"- Running HiPE-compiled Yecc parsers no longer results in a `function_clause`\n error.\n\n Own Id: OTP-8771","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Parsetools 2.0.3 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-2-0-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","doc":"- Yecc failed to report reduce/reduce conflicts where one of the reductions\n involved the root symbol. This bug has been fixed. (Thanks to Manolis\n Papadakis.)\n\n Own Id: OTP-8483\n\n- A bug introduced in Parsetools 1.4.4 (R12B-2) has been fixed. (Thanks to\n Manolis Papadakis.)\n\n Own Id: OTP-8486","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Parsetools 2.0.2 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-2-0-2"},{"type":"extras","title":"Improvements and New Features - Parsetools Release Notes","doc":"- Cleanups suggested by tidier and modernization of types and specs.\n\n Own Id: OTP-8455","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Parsetools 2.0.1 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-2-0-1"},{"type":"extras","title":"Improvements and New Features - Parsetools Release Notes","doc":"- Leex no longer uses the deprecated `regexp` module. (Thanks to Robert\n Virding.).\n\n Own Id: OTP-8231","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","doc":"- A minor bug in `m:leex` has been fixed.\n\n Own Id: OTP-8197","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Parsetools 2.0 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-2-0"},{"type":"extras","title":"Improvements and New Features - Parsetools Release Notes","doc":"- Leex, a lexical analyzer generator for Erlang, has been added to Parsetools.\n This initial version should be considered experimental; it is known that there\n will be changes and additions. (Thanks to Robert Virding.).\n\n Own Id: OTP-8013","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","doc":"- The parsers generated by Yecc now report correct error lines when possible.\n\n Own Id: OTP-7969","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Parsetools 1.4.7 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-1-4-7"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","doc":"- A bug in yeccpre.hrl introduced in R13A has been fixed.\n\n Own Id: OTP-7945","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Parsetools 1.4.6 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-1-4-6"},{"type":"extras","title":"Improvements and New Features - Parsetools Release Notes","doc":"- Updated file headers.\n\n Own Id: OTP-7798","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Parsetools 1.4.5 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-1-4-5"},{"type":"extras","title":"Improvements and New Features - Parsetools Release Notes","doc":"- The `yecc` grammar has been augmented with an optional header section. (Thanks\n to Richard Carlsson.)\n\n Own Id: OTP-7292","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Parsetools 1.4.4 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-1-4-4"},{"type":"extras","title":"Improvements and New Features - Parsetools Release Notes","doc":"- The size of the code generated by Yecc has been reduced. The code is also\n faster.\n\n Macros can now be used in actions.\n\n Own Id: OTP-7224","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Parsetools 1.4.3 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-1-4-3"},{"type":"extras","title":"Improvements and New Features - Parsetools Release Notes","doc":"- [`tuple_size/1`](`tuple_size/1`) and [`byte_size/1`](`byte_size/1`) have been\n substituted for [`size/1`](`size/1`).\n\n Own Id: OTP-7009","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Parsetools 1.4.2 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-1-4-2"},{"type":"extras","title":"Improvements and New Features - Parsetools Release Notes","doc":"- The size of the code generated by yecc has been reduced.\n\n A note regarding the `includefile` option: although yecc can cope with\n includefiles based on some earlier `yeccpre.hrl` it is recommended for\n efficiency reasons to update includefiles as to follow the pattern in the\n latest `yeccpre.hrl`.\n\n Own Id: OTP-6851","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Parsetools 1.4.1.1 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-1-4-1-1"},{"type":"extras","title":"Improvements and New Features - Parsetools Release Notes","doc":"- Minor Makefile changes.\n\n Own Id: OTP-6689","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Parsetools 1.4.1 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-1-4-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","doc":"- A bug concerning precedence declarations of non-terminals \"one level up\" has\n been fixed in yecc.\n\n Own Id: OTP-6362","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Parsetools 1.4 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-1-4"},{"type":"extras","title":"Improvements and Fixed Bugs - Parsetools Release Notes","doc":"Several modifications of Yecc have been made:\n\n- The new functions `file/1,2` take the role of the old functions `yecc/2,3,4`.\n The latter functions are no longer documented but are kept for backward\n compatibility.\n- More checks of the grammar file have been implemented. Examples are warnings\n for unused non-terminals and duplicated declarations.\n- Invalid pseudo variables are no longer replaced by `'$undefined'` but cause a\n failure.\n- Reserved words no longer need to be quoted when used as terminals or\n non-terminals.\n- When compiling the generated parser file errors and warnings concerning user\n code refer to the grammar file, not the parser file.\n- Yecc emits a warning if there are conflicts in the grammar. The new\n declaration `Expect` can be used to suppress this warning.\n- The new operator precedence declaration `Nonassoc` can be used to declare\n operators with no associativity.\n- Precedence can be given to more than one operator with one single operator\n precedence declaration.\n- The function `parse_and_scan/1` in the default includefile accepts\n `{Function, A}` as well as \\{\\{M,F\\}, A\\} as tokenizer function. Exceptions in\n the tokenizer are never caught.\n- The functions `yecc:file/1,2` can be accessed from the Erlang shell via the\n new functions `c:y/1,2` in STDLIB.\n\nSee yecc(3) for further details.\n\nOwn Id: OTP-5366","ref":"notes.html#improvements-and-fixed-bugs"},{"type":"extras","title":"Parsetools 1.3.2 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-1-3-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","doc":"- A bug in `Yecc` that was introduced in R9B has been removed. Another bug\n concerning precedence declaration \"one level up\" has been fixed.\n\n Own Id: OTP-5461","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Parsetools 1.3.1 - Parsetools Release Notes","doc":"","ref":"notes.html#parsetools-1-3-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Parsetools Release Notes","doc":"- A bug in the file `parsetools/include/yeccpre.hrl` caused\n `yecc:parse_and_scan/1` to always report a parse failure when the lexer\n reported end-of-file. This problem has been fixed.\n\n Own Id: OTP-5369","ref":"notes.html#fixed-bugs-and-malfunctions"}],"content_type":"text/plain","producer":{"name":"ex_doc","version":[48,46,51,52,46,49]}} \ No newline at end of file diff --git a/prs/9045/lib/parsetools-2.6/doc/html/leex.html b/prs/9045/lib/parsetools-2.6/doc/html/leex.html index f877d333f7f8..2dd0088d2758 100644 --- a/prs/9045/lib/parsetools-2.6/doc/html/leex.html +++ b/prs/9045/lib/parsetools-2.6/doc/html/leex.html @@ -179,13 +179,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.

    @@ -737,7 +737,7 @@

    token(Cont, Chars, StartLoc)

    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
    @@ -826,7 +826,7 @@

    tokens(Cont, Chars, StartLoc)

    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
    diff --git a/prs/9045/lib/parsetools-2.6/doc/html/parsetools.epub b/prs/9045/lib/parsetools-2.6/doc/html/parsetools.epub index 4b663946b69d..569d4aeaf2ea 100644 Binary files a/prs/9045/lib/parsetools-2.6/doc/html/parsetools.epub and b/prs/9045/lib/parsetools-2.6/doc/html/parsetools.epub differ diff --git a/prs/9045/lib/parsetools-2.6/doc/html/search.html b/prs/9045/lib/parsetools-2.6/doc/html/search.html index 4c0789215d4c..c6c33f123a85 100644 --- a/prs/9045/lib/parsetools-2.6/doc/html/search.html +++ b/prs/9045/lib/parsetools-2.6/doc/html/search.html @@ -128,7 +128,7 @@

    - +

    diff --git a/prs/9045/lib/parsetools-2.6/doc/html/yecc.html b/prs/9045/lib/parsetools-2.6/doc/html/yecc.html index d34d34a4c958..7153232e4fa2 100644 --- a/prs/9045/lib/parsetools-2.6/doc/html/yecc.html +++ b/prs/9045/lib/parsetools-2.6/doc/html/yecc.html @@ -168,8 +168,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 @@ -239,8 +239,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 @@ -252,8 +252,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 @@ -276,12 +276,12 @@

    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 +

    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 @@ -290,15 +290,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 @@ -348,36 +348,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 diff --git a/prs/9045/lib/public_key-1.16.3/doc/html/.build b/prs/9045/lib/public_key-1.16.3/doc/html/.build index 36f08bb6abfb..dbd287ca67df 100644 --- a/prs/9045/lib/public_key-1.16.3/doc/html/.build +++ b/prs/9045/lib/public_key-1.16.3/doc/html/.build @@ -18,7 +18,7 @@ dist/lato-latin-ext-300-normal-VPGGJKJL.woff2 dist/lato-latin-ext-400-normal-N27NCBWW.woff2 dist/lato-latin-ext-700-normal-Q2L5DVMW.woff2 dist/remixicon-NKANDIL5.woff2 -dist/search_data-E7E84476.js +dist/search_data-96A9C547.js dist/sidebar_items-FE10E3DB.js index.html notes.html diff --git a/prs/9045/lib/public_key-1.16.3/doc/html/dist/search_data-96A9C547.js b/prs/9045/lib/public_key-1.16.3/doc/html/dist/search_data-96A9C547.js new file mode 100644 index 000000000000..12cead0959c0 --- /dev/null +++ b/prs/9045/lib/public_key-1.16.3/doc/html/dist/search_data-96A9C547.js @@ -0,0 +1 @@ +searchData={"items":[{"type":"module","title":"public_key","doc":"API module for public-key infrastructure.\n\nProvides functions to handle public-key infrastructure, for details see\n[public_key application](public_key_app.md).\n\n> #### Note {: .info }\n>\n> All records used in this Reference Manual are generated from ASN.1\n> specifications and are documented in the User's Guide. See\n> [Public-key Records](public_key_records.md).\n\nUse the following include directive to get access to the records and constant\nmacros described here and in the User's Guide:\n\n```text\n -include_lib(\"public_key/include/public_key.hrl\").\n```","ref":"public_key.html"},{"type":"function","title":"public_key.cacerts_clear/0","doc":"Clears any loaded CA certificates, returns true if any was loaded.","ref":"public_key.html#cacerts_clear/0"},{"type":"function","title":"public_key.cacerts_get/0","doc":"Returns the trusted CA certificates if any are loaded, otherwise uses\n`cacerts_load/0` to load them. The function fails if no `cacerts` could be\nloaded.","ref":"public_key.html#cacerts_get/0"},{"type":"function","title":"public_key.cacerts_load/0","doc":"Loads the OS supplied trusted CA certificates.\n\nThis can be overridden by setting the `cacerts_path`\nenvironment key of the `public_key` application with\nthe location of an alternative certificate.\nYou can set it via the command line as:\n\n erl -public_key cacerts_path '\"/path/to/certs.pem\"'\n\nUse it with care. It is your responsibility to ensure\nthat the certificates found in this alternative path\ncan be trusted by the running system.","ref":"public_key.html#cacerts_load/0"},{"type":"function","title":"public_key.cacerts_load/1","doc":"Loads the trusted CA certificates from a file.","ref":"public_key.html#cacerts_load/1"},{"type":"function","title":"public_key.compute_key/2","doc":"Computes shared secret.","ref":"public_key.html#compute_key/2"},{"type":"function","title":"public_key.compute_key/3","doc":"Computes shared secret.","ref":"public_key.html#compute_key/3"},{"type":"function","title":"public_key.decrypt_private/2","doc":"","ref":"public_key.html#decrypt_private/2"},{"type":"function","title":"public_key.decrypt_private/3","doc":"Public-key decryption using the private key. See also `crypto:private_decrypt/4`\n\n> #### Warning {: .warning }\n>\n> This is a legacy function, for security reasons do not use with rsa_pkcs1_padding.","ref":"public_key.html#decrypt_private/3"},{"type":"function","title":"public_key.decrypt_public/2","doc":"","ref":"public_key.html#decrypt_public/2"},{"type":"function","title":"public_key.decrypt_public/3","doc":"Public-key decryption using the public key. See also `crypto:public_decrypt/4`\n\n> #### Warning {: .warning }\n>\n> This is a legacy function, for security reasons do not use with rsa_pkcs1_padding.\n> For digital signatures the use of [`verify/4`](`verify/4`) together\n> with [`sign/3`](`sign/3`) is a prefered solution.","ref":"public_key.html#decrypt_public/3"},{"type":"function","title":"public_key.der_decode/2","doc":"Decodes a public-key ASN.1 DER encoded entity.","ref":"public_key.html#der_decode/2"},{"type":"function","title":"public_key.der_encode/2","doc":"Encodes a public-key entity with ASN.1 DER encoding.","ref":"public_key.html#der_encode/2"},{"type":"function","title":"public_key.dh_gex_group/4","doc":"Selects a group for Diffie-Hellman key exchange with the key size in the range\n`MinSize...MaxSize` and as close to `SuggestedSize` as possible. If\n`Groups == undefined` a default set will be used, otherwise the group is\nselected from `Groups`.\n\nFirst a size, as close as possible to SuggestedSize, is selected. Then one group\nwith that key size is randomly selected from the specified set of groups. If no\nsize within the limits of `MinSize` and `MaxSize` is available,\n`{error,no_group_found}` is returned.\n\nThe default set of groups is listed in `lib/public_key/priv/moduli`. This file\nmay be regenerated like this:\n\n```text\n\t$> cd $ERL_TOP/lib/public_key/priv/\n\t$> generate\n ---- wait until all background jobs has finished. It may take several days !\n\t$> cat moduli-* > moduli\n\t$> cd ..; make\n```","ref":"public_key.html#dh_gex_group/4"},{"type":"function","title":"public_key.encrypt_private/2","doc":"","ref":"public_key.html#encrypt_private/2"},{"type":"function","title":"public_key.encrypt_private/3","doc":"Public-key encryption using the private key.\n\nSee also `crypto:private_encrypt/4`. The key, can besides a standard\nRSA key, be a map specifing the key algorithm `rsa` and a fun to\nhandle the encryption operation. This may be used for customized the\nencryption operation with for instance hardware security modules (HSM)\nor trusted platform modules (TPM).\n\n> #### Warning {: .warning }\n>\n> This is a legacy function, for security reasons do not use with rsa_pkcs1_padding.\n> For digital signatures use of [`sign/3`](`sign/3`) together with [`verify/4`](`verify/4`) is\n> the prefered solution.","ref":"public_key.html#encrypt_private/3"},{"type":"function","title":"public_key.encrypt_public/2","doc":"","ref":"public_key.html#encrypt_public/2"},{"type":"function","title":"public_key.encrypt_public/3","doc":"Public-key encryption using the public key. See also `crypto:public_encrypt/4`.\n\n> #### Warning {: .warning }\n>\n> This is a legacy function, for security reasons do not use with rsa_pkcs1_padding.","ref":"public_key.html#encrypt_public/3"},{"type":"function","title":"public_key.generate_key/1","doc":"Generates a new key pair. Note that except for Diffie-Hellman the public key is\nincluded in the private key structure. See also `crypto:generate_key/2`","ref":"public_key.html#generate_key/1"},{"type":"function","title":"public_key.pem_decode/1","doc":"Decodes PEM binary data and returns entries as ASN.1 DER encoded entities.\n\nExample\n`{ok, PemBin} = file:read_file(\"cert.pem\"). PemEntries = public_key:pem_decode(PemBin).`","ref":"public_key.html#pem_decode/1"},{"type":"function","title":"public_key.pem_encode/1","doc":"Creates a PEM binary.","ref":"public_key.html#pem_encode/1"},{"type":"function","title":"public_key.pem_entry_decode/1","doc":"","ref":"public_key.html#pem_entry_decode/1"},{"type":"function","title":"public_key.pem_entry_decode/2","doc":"Decodes a PEM entry. [`pem_decode/1`](`pem_decode/1`) returns a list of PEM\nentries. Notice that if the PEM entry is of type 'SubjectPublickeyInfo', it is\nfurther decoded to an `t:rsa_public_key/0` or `t:dsa_public_key/0`.\n\nPassword can be either an octet string or function which returns same type.","ref":"public_key.html#pem_entry_decode/2"},{"type":"function","title":"public_key.pem_entry_encode/2","doc":"","ref":"public_key.html#pem_entry_encode/2"},{"type":"function","title":"public_key.pem_entry_encode/3","doc":"Creates a PEM entry that can be feed to [`pem_encode/1`](`pem_encode/1`).\n\nIf `Asn1Type` is `'SubjectPublicKeyInfo'`, `Entity` must be either an\n`t:rsa_public_key/0`, `t:dsa_public_key/0` or an `t:ecdsa_public_key/0` and this\nfunction creates the appropriate `'SubjectPublicKeyInfo'` entry.","ref":"public_key.html#pem_entry_encode/3"},{"type":"function","title":"public_key.pkix_crl_issuer/1","doc":"Returns the issuer of the `CRL`.","ref":"public_key.html#pkix_crl_issuer/1"},{"type":"function","title":"public_key.pkix_crl_verify/2","doc":"Verify that `Cert` is the `CRL` signer.","ref":"public_key.html#pkix_crl_verify/2"},{"type":"function","title":"public_key.pkix_crls_validate/3","doc":"Performs CRL validation. It is intended to be called from the verify fun of\n[pkix_path_validation/3 ](`pkix_path_validation/3`).\n\nAvailable options:\n\n- **\\{update_crl, fun()\\}** - The fun has the following type specification:\n\n ```erlang\n fun(#'DistributionPoint'{}, #'CertificateList'{}) ->\n #'CertificateList'{}\n ```\n\n The fun uses the information in the distribution point to access the latest\n possible version of the CRL. If this fun is not specified, Public Key uses the\n default implementation:\n\n ```text\n fun(_DP, CRL) -> CRL end\n ```\n\n- **\\{issuer_fun, \\{fun(), UserState::term()\\}\\}** - The fun has the following type\n specification:\n\n ```erlang\n fun(#'DistributionPoint'{}, #'CertificateList'{},\n {rdnSequence,[#'AttributeTypeAndValue'{}]}, UserState::term()) ->\n \t{ok, #'OTPCertificate'{}, [der_encoded]}\n ```\n\n The fun returns the root certificate and certificate chain that has signed the\n CRL.\n\n ```erlang\n fun(DP, CRL, Issuer, UserState) -> {ok, RootCert, CertChain}\n ```\n\n- **\\{undetermined_details, boolean()\\}** - Defaults to false. When revocation\n status cannot be determined, and this option is set to true, details of why no\n CRLs where accepted are included in the return value.","ref":"public_key.html#pkix_crls_validate/3"},{"type":"function","title":"public_key.pkix_decode_cert/2","doc":"Decodes an ASN.1 DER-encoded PKIX certificate.\n\nOption `otp` uses the customized ASN.1 specification OTP-PKIX.asn1 for\ndecoding and also recursively decode most of the standard parts.","ref":"public_key.html#pkix_decode_cert/2"},{"type":"function","title":"public_key.pkix_dist_point/1","doc":"Creates a distribution point for CRLs issued by the same issuer as `Cert`. Can\nbe used as input to `pkix_crls_validate/3`","ref":"public_key.html#pkix_dist_point/1"},{"type":"function","title":"public_key.pkix_dist_points/1","doc":"Extracts distribution points from the certificates extensions.","ref":"public_key.html#pkix_dist_points/1"},{"type":"function","title":"public_key.pkix_encode/3","doc":"DER encodes a PKIX x509 certificate or part of such a certificate.\n\nThis function must be used for encoding certificates or parts of\ncertificates that are decoded/created in the `otp` format, whereas for\nthe plain format this function directly calls\n[`der_encode/2`](`der_encode/2`).\n\n> #### Note {: .info }\n>\n> Subtle ASN-1 encoding errors in certificates may be worked around when\n> decoding, this may have the affect that the encoding a certificate back to DER\n> may generate different bytes then the supplied original.","ref":"public_key.html#pkix_encode/3"},{"type":"function","title":"public_key.pkix_hash_type/1","doc":"Translates OID to Erlang digest type","ref":"public_key.html#pkix_hash_type/1"},{"type":"function","title":"public_key.pkix_is_fixed_dh_cert/1","doc":"Checks if a certificate is a fixed Diffie-Hellman certificate.","ref":"public_key.html#pkix_is_fixed_dh_cert/1"},{"type":"function","title":"public_key.pkix_is_issuer/2","doc":"Checks if `IssuerCert` issued `Cert`.","ref":"public_key.html#pkix_is_issuer/2"},{"type":"function","title":"public_key.pkix_is_self_signed/1","doc":"Checks if a certificate is self-signed.","ref":"public_key.html#pkix_is_self_signed/1"},{"type":"function","title":"public_key.pkix_issuer_id/2","doc":"Returns the x509 certificate issuer id, if it can be determined.","ref":"public_key.html#pkix_issuer_id/2"},{"type":"function","title":"public_key.pkix_match_dist_point/2","doc":"Checks whether the given distribution point matches the Issuing Distribution\nPoint of the CRL, as described in RFC 5280.\n\nIf the CRL doesn't have an Issuing\nDistribution Point extension, the distribution point always matches.","ref":"public_key.html#pkix_match_dist_point/2"},{"type":"function","title":"public_key.pkix_normalize_name/1","doc":"Normalizes an issuer name so that it can be easily compared to another issuer\nname.","ref":"public_key.html#pkix_normalize_name/1"},{"type":"function","title":"public_key.pkix_ocsp_validate/5","doc":"Perform OCSP response validation according to RFC 6960. Returns {'ok', Details} when OCSP\nresponse is successfully validated and \\{error, \\{bad_cert, Reason\\}\\}\notherwise.\n\nAvailable options:\n\n- **\\{is_trusted_responder_fun, fun()\\}** - The fun has the following type\n specification:\n\n ```text\n fun(#cert{}) ->\n \t boolean()\n ```\n\n The fun returns the `true` if certificate in the argument is trusted. If this\n fun is not specified, Public Key uses the default implementation:\n\n ```text\n fun(_) -> false end\n ```\n\n> #### Note {: .info }\n>\n> OCSP response can be provided without a nonce value - even if it was requested\n> by the client. In such cases {missing, ocsp_nonce} will be returned\n> in Details list.","ref":"public_key.html#pkix_ocsp_validate/5"},{"type":"function","title":"public_key.pkix_path_validation/3","doc":"Performs a basic path validation according to\n[RFC 5280.](http://www.ietf.org/rfc/rfc5280.txt)\n\nHowever, CRL validation is done separately by [pkix_crls_validate/3\n](`pkix_crls_validate/3`)and is to be called from the supplied\n`verify_fun`. The policy tree check was added in OTP-26.2 and if the\ncertificates include policies the constrained policy set with\npotential qualifiers will be returned, these values are derived from\nthe policy tree created as part of the path validation algorithm. The\nconstrained set can be constrained only by the Certificate Authorities\nor also by the user when the option `policy_set` is provided to this\nfunction. The qualifiers convey information about the valid policy and\nis intended as information to end users.\n\nAvailable options:\n\n- **\\{verify_fun, \\{fun(), UserState::term()\\}** - The fun must be\n defined as:\n\n ```erlang\n fun(OtpCert :: #'OTPCertificate'{},\n Event :: {bad_cert, Reason :: atom() | {revoked, atom()}} |\n {extension, #'Extension'{}},\n UserState :: term()) ->\n \t{valid, UserState :: term()} |\n \t{valid_peer, UserState :: term()} |\n \t{fail, Reason :: term()} |\n \t{unknown, UserState :: term()}.\n ```\n\n or as:\n\n ```erlang\n fun(OtpCert :: #'OTPCertificate'{},\n DerCert :: der_encoded(),\n Event :: {bad_cert, Reason :: atom() | {revoked, atom()}} |\n {extension, #'Extension'{}},\n UserState :: term()) ->\n\t{valid, UserState :: term()} |\n\t{valid_peer, UserState :: term()} |\n\t{fail, Reason :: term()} |\n\t{unknown, UserState :: term()}.\n ```\n\n The verify callback can have 3 or 4 arguments in case the DER encoded\n version is needed by the callback.\n\n If the verify callback fun returns `{fail, Reason}`, the verification process\n is immediately stopped. If the verify callback fun returns\n `{valid, UserState}`, the verification process is continued. This can be used\n to accept specific path validation errors, such as `selfsigned_peer`, as well\n as verifying application-specific extensions. If called with an extension\n unknown to the user application, the return value `{unknown, UserState}` is to\n be used.\n\n > #### Note {: .note }\n > If you need the DER encoded version of the certificate and have\n > the OTP decoded version encoding it back can fail to give the correct result,\n > due to work arounds for common misbehaving encoders. So it is recommended\n > to call `pkix_path_validation` with `Cert` and `CertChain` arguments as\n > `der_encoded() | #cert{}` and `[der_encoded() | #cert{}]`. Also note\n > that the path validation itself needs both the encoded and the\n > decoded version of the certificate.\n\n > #### Warning {: .warning }\n >\n > Note that user defined custom `verify_fun` may alter original path\n > validation error (e.g `selfsigned_peer`). Use with caution.\n\n- **\\{max_path_length, integer()\\}** - The `max_path_length` is the maximum\n number of non-self-issued intermediate certificates that can follow the peer\n certificate in a valid certification path. So, if `max_path_length` is 0, the\n PEER must be signed by the trusted ROOT-CA directly, if it is 1, the path can\n be PEER, CA, ROOT-CA, if it is 2, the path can be PEER, CA, CA, ROOT-CA, and\n so on.\n\n- **\\{policy_set, \\[oid()]\\}**(Since OTP 26.2) \n The set of policies that will be accepted, defaults to the special value\n `[?anyPolicy]` that will accept all policies.\n\n- **\\{explicit_policy, boolean()\\}**(Since OTP 26.2) \n Explicitly require that each certificate in the path must include at least one\n of the certificate policies in the `policy_set`.\n\n- **\\{inhibit_policy_mapping, boolean()\\}**(Since OTP 26.2) \n Prevent policies to be mapped to other policies.\n\n- **\\{inhibit_any_policy, boolean()\\}**(Since OTP 26.2) \n Prevent the special policy `?anyPolicy` from being accepted.\n\nExplanations of reasons for a bad certificate:\n\n- **cert_expired** - Certificate is no longer valid as its expiration date has\n passed.\n\n- **invalid_issuer** - Certificate issuer name does not match the name of the\n issuer certificate in the chain.\n\n- **invalid_signature** - Certificate was not signed by its issuer certificate\n in the chain.\n\n- **name_not_permitted** - Invalid Subject Alternative Name extension.\n\n- **missing_basic_constraint** - Certificate, required to have the basic\n constraints extension, does not have a basic constraints extension.\n\n- **invalid_key_usage** - Certificate key is used in an invalid way according to\n the key-usage extension.\n\n- **\\{revoked, crl_reason()\\}** - Certificate has been revoked.\n\n- **invalid_validity_dates** - The validity section of the X.509 certificate(s)\n contains invalid date formats not matching the RFC.\n\n- **atom()** - Application-specific error reason that is to be checked by the\n `verify_fun`.","ref":"public_key.html#pkix_path_validation/3"},{"type":"function","title":"public_key.pkix_sign/2","doc":"Signs an 'OTPTBSCertificate'. Returns the corresponding DER-encoded certificate.","ref":"public_key.html#pkix_sign/2"},{"type":"function","title":"public_key.pkix_sign_types/1","doc":"Translates signature algorithm OID to Erlang digest and signature types.\n\nThe `AlgorithmId` is the signature OID from a certificate or a certificate\nrevocation list.","ref":"public_key.html#pkix_sign_types/1"},{"type":"function","title":"public_key.pkix_subject_id/1","doc":"Returns the X509 certificate subject id.","ref":"public_key.html#pkix_subject_id/1"},{"type":"function","title":"public_key.pkix_test_data/1","doc":"Creates certificate configuration(s) consisting of certificate and its private\nkey plus CA certificate bundle, for a client and a server, intended to\nfacilitate automated testing of applications using X509-certificates, often\nthrough SSL/TLS. The test data can be used when you have control over both the\nclient and the server in a test scenario.\n\nWhen this function is called with a map containing client and server chain\nspecifications; it generates both a client and a server certificate chain where\nthe `cacerts` returned for the server contains the root cert the server should\ntrust and the intermediate certificates the server should present to connecting\nclients. The root cert the server should trust is the one used as root of the\nclient certificate chain. Vice versa applies to the `cacerts` returned for the\nclient. The root cert(s) can either be pre-generated with\n[pkix_test_root_cert/2 ](`pkix_test_root_cert/2`), or if options are specified;\nit is (they are) generated.\n\nWhen this function is called with a list of certificate options; it generates a\nconfiguration with just one node certificate where `cacerts` contains the root\ncert and the intermediate certs that should be presented to a peer. In this case\nthe same root cert must be used for all peers. This is useful in for example an\nErlang distributed cluster where any node, towards another node, acts either as\na server or as a client depending on who connects to whom. The generated\ncertificate contains a subject altname, which is not needed in a client\ncertificate, but makes the certificate useful for both roles.\n\nExplanation of the options used to customize certificates in the generated\nchains:\n\n- **\\{digest, digest_type()\\}** - Hash algorithm to be used for signing the\n certificate together with the key option. Defaults to sha that is sha1.\n\n- **\\{key, ec_params()| {rsa, Size:pos_integer(), Prime::pos_integer()} | private_key()\\}** - Parameters to be used to call\n public_key:generate_key/1, to generate a key, or an existing key. Defaults to\n generating an ECDSA key. Note this could fail if Erlang/OTP is compiled with a\n very old cryptolib.\n\n- **\\{validity, \\{From::erlang:timestamp(), To::erlang:timestamp()\\}\\}** - The\n validity period of the certificate.\n\n- **\\{extensions, \\[#'Extension'\\{\\}]\\}** - Extensions to include in the\n certificate.\n\n Default extensions included in CA certificates if not otherwise specified are:\n\n ```erlang\n [#'Extension'{extnID = ?'id-ce-keyUsage',\n extnValue = [keyCertSign, cRLSign],\n critical = false},\n #'Extension'{extnID = ?'id-ce-basicConstraints',\n extnValue = #'BasicConstraints'{cA = true},\n critical = true}]\n ```\n\n Default extensions included in the server peer cert if not otherwise specified\n are:\n\n ```erlang\n [#'Extension'{extnID = ?'id-ce-keyUsage',\n extnValue = [digitalSignature, keyAgreement],\n critical = false},\n #'Extension'{extnID = ?'id-ce-subjectAltName',\n extnValue = [{dNSName, Hostname}],\n critical = false}]\n ```\n\n Hostname is the result of calling net_adm:localhost() in the Erlang node where\n this function is called.\n\n> #### Note {: .info }\n>\n> Note that the generated certificates and keys does not provide a formally\n> correct PKIX-trust-chain and they cannot be used to achieve real security.\n> This function is provided for testing purposes only.","ref":"public_key.html#pkix_test_data/1"},{"type":"function","title":"public_key.pkix_test_root_cert/2","doc":"Generates a root certificate that can be used in multiple calls to\n`pkix_test_data/1` when you want the same root certificate for several generated\ncertificates.","ref":"public_key.html#pkix_test_root_cert/2"},{"type":"function","title":"public_key.pkix_verify/2","doc":"Verifies PKIX x.509 certificate signature.","ref":"public_key.html#pkix_verify/2"},{"type":"function","title":"public_key.pkix_verify_hostname/2","doc":"","ref":"public_key.html#pkix_verify_hostname/2"},{"type":"function","title":"public_key.pkix_verify_hostname/3","doc":"This function checks that the _Presented Identifier_ (e.g hostname) in a peer\ncertificate is in agreement with at least one of the _Reference Identifier_ that\nthe client expects to be connected to.\n\nThe function is intended to be added as an extra client check of the\npeer certificate when performing\n[public_key:pkix_path_validation/3](`pkix_path_validation/3`)\n\nSee [RFC 6125](https://tools.ietf.org/html/rfc6125) for detailed information\nabout hostname verification. The\n[User's Guide](using_public_key.md#verify_hostname) and\n[code examples](using_public_key.md#verify_hostname_examples) describes this\nfunction more detailed.\n\nThe option funs are described here:\n\n- **`match_fun`**\n\n ```erlang\n fun(ReferenceId::ReferenceId() | FQDN::string(),\n PresentedId::{dNSName,string()} | {uniformResourceIdentifier,string() |\n {iPAddress,list(byte())} | {OtherId::atom()|oid(),term()}})\n ```\n\n This function replaces the default host name matching rules. The fun should\n return a boolean to tell if the Reference ID and Presented ID matches or not.\n The match fun can also return a third value, value, the atom `default`, if the\n default matching rules shall apply. This makes it possible to augment the\n tests with a special case:\n\n ```text\n fun(....) -> true; % My special case\n (_, _) -> default % all others falls back to the inherit tests\n end\n ```\n\n See `pkix_verify_hostname_match_fun/1` for a function that takes a protocol\n name as argument and returns a `fun/2` suitable for this option and\n [Re-defining the match operation](using_public_key.md#redefining_match_op) in\n the User's Guide for an example.\n\n > #### Note {: .info }\n >\n > Reference Id values given as binaries will be converted to strings, and ip\n > references may be given in string format that is \"10.0.1.1\" or\n > \"1234::5678:9012\" as well as on the format `t:inet:ip_address/0`\n\n- **`fail_callback`** - If a matching fails, there could be circumstances when\n the certificate should be accepted anyway. Think for example of a web browser\n where you choose to accept an outdated certificate. This option enables\n implementation of such an exception but for hostnames. This `fun/1` is called\n when no `ReferenceID` matches. The return value of the fun (a `t:boolean/0`)\n decides the outcome. If `true` the the certificate is accepted otherwise it is\n rejected. See\n [\"Pinning\" a Certificate](using_public_key.md#pinning-a-certificate) in the\n User's Guide.\n\n- **`fqdn_fun`** - This option augments the host name extraction from URIs and\n other Reference IDs. It could for example be a very special URI that is not\n standardised. The fun takes a Reference ID as argument and returns one of:\n\n - the hostname\n - the atom `default`: the default host name extract function will be used\n - the atom `undefined`: a host name could not be extracted. The\n pkix_verify_hostname/3 will return `false`.\n\n For an example, see\n [Hostname extraction](using_public_key.md#hostname_extraction) in the User's\n Guide.","ref":"public_key.html#pkix_verify_hostname/3"},{"type":"function","title":"public_key.pkix_verify_hostname_match_fun/1","doc":"The return value of calling this function is intended to be used in the\n`match_fun` option in `pkix_verify_hostname/3`.\n\nThe returned fun augments the verify hostname matching according to the specific\nrules for the protocol in the argument.\n\n> #### Note {: .info }\n>\n> Currently supported https fun will allow wildcard certificate matching as\n> specified by the HTTP standard. Note that for instance LDAP have a different\n> set of wildcard matching rules. If you do not want to allow wildcard\n> certificates (recommended from a security perspective) or otherwise customize\n> the hostname match the default match function used by ssl application will be\n> sufficient.","ref":"public_key.html#pkix_verify_hostname_match_fun/1"},{"type":"function","title":"public_key.short_name_hash/1","doc":"Generates a short hash of an issuer name. The hash is returned as a string\ncontaining eight hexadecimal digits.\n\nThe return value of this function is the same as the result of the commands\n`openssl crl -hash` and `openssl x509 -issuer_hash`, when passed the issuer name\nof a CRL or a certificate, respectively. This hash is used by the `c_rehash`\ntool to maintain a directory of symlinks to CRL files, in order to facilitate\nlooking up a CRL by its issuer name.","ref":"public_key.html#short_name_hash/1"},{"type":"function","title":"public_key.sign/3","doc":"","ref":"public_key.html#sign/3"},{"type":"function","title":"public_key.sign/4","doc":"Creates a digital signature.\n\nThe `Msg` is either the binary \"plain text\" data to be signed or it is the\nhashed value of \"plain text\", that is, the digest. The key, can besides a\nstandard key, be a map specifing a key algorithm and a fun that should handle\nthe signing. This may be used for customized signing with for instance hardware\nsecurity modules (HSM) or trusted platform modules (TPM).","ref":"public_key.html#sign/4"},{"type":"function","title":"public_key.verify/4","doc":"","ref":"public_key.html#verify/4"},{"type":"function","title":"public_key.verify/5","doc":"Verifies a digital signature.\n\nThe `Msg` is either the binary \"plain text\" data or it is the hashed value of\n\"plain text\", that is, the digest.","ref":"public_key.html#verify/5"},{"type":"type","title":"public_key.asn1_type/0","doc":"ASN.1 type present in the Public Key applications ASN.1 specifications.","ref":"public_key.html#t:asn1_type/0"},{"type":"type","title":"public_key.bad_cert_reason/0","doc":"The reason that a certifcate gets rejected by the certificate path validation.","ref":"public_key.html#t:bad_cert_reason/0"},{"type":"type","title":"public_key.cert/0","doc":"An encoded or decode certificate.","ref":"public_key.html#t:cert/0"},{"type":"type","title":"public_key.cert_id/0","doc":"A certificate is identified by its serial-number and Issuer Name.","ref":"public_key.html#t:cert_id/0"},{"type":"type","title":"public_key.cert_opt/0","doc":"Options to customize generated test certificates","ref":"public_key.html#t:cert_opt/0"},{"type":"type","title":"public_key.chain_opts/0","doc":"Certificate customize options for diffrent parts of the certificate test chain.","ref":"public_key.html#t:chain_opts/0"},{"type":"type","title":"public_key.combined_cert/0","doc":"A record that can be used to provide the certificate on both the DER encoded and the OTP decode format.\n\nSuch a construct can be useful to avoid conversions and problems that can arise due to relaxed decoding rules.","ref":"public_key.html#t:combined_cert/0"},{"type":"type","title":"public_key.conf_opt/0","doc":"Configuration options for the generated certificate test chain.","ref":"public_key.html#t:conf_opt/0"},{"type":"type","title":"public_key.crl_reason/0","doc":"The reason that a certifcate has been revoked as define by RFC 5280.","ref":"public_key.html#t:crl_reason/0"},{"type":"type","title":"public_key.custom_key_opts/0","doc":"Can be provided together with a custom private key, that specifies a key fun, to\nprovide additional options understood by the fun.","ref":"public_key.html#t:custom_key_opts/0"},{"type":"type","title":"public_key.der_encoded/0","doc":"ASN.1 DER encoded entity.","ref":"public_key.html#t:der_encoded/0"},{"type":"type","title":"public_key.digest_type/0","doc":"Hash function used to create a message digest","ref":"public_key.html#t:digest_type/0"},{"type":"type","title":"public_key.dsa_private_key/0","doc":"ASN.1 defined private key format for the DSA algorithm.","ref":"public_key.html#t:dsa_private_key/0"},{"type":"type","title":"public_key.dsa_public_key/0","doc":"ASN.1 defined public key format for the DSA algorithm.","ref":"public_key.html#t:dsa_public_key/0"},{"type":"type","title":"public_key.dss_public_key/0","doc":"ASN.1 defined public key format for the DSS algorithm (part of DSA key).","ref":"public_key.html#t:dss_public_key/0"},{"type":"type","title":"public_key.ecdsa_private_key/0","doc":"ASN.1 defined private key format for the ECDSA algorithm.","ref":"public_key.html#t:ecdsa_private_key/0"},{"type":"type","title":"public_key.ecdsa_public_key/0","doc":"ASN.1 defined public key format for the ECDSA algorithm.","ref":"public_key.html#t:ecdsa_public_key/0"},{"type":"type","title":"public_key.eddsa_private_key/0","doc":"ASN.1 defined private key format for the EDDSA algorithm, possible oids: ?'id-Ed25519' | ?'id-Ed448'","ref":"public_key.html#t:eddsa_private_key/0"},{"type":"type","title":"public_key.eddsa_public_key/0","doc":"ASN.1 defined public key format for the EDDSA algorithm, possible oids: ?'id-Ed25519' | ?'id-Ed448'","ref":"public_key.html#t:eddsa_public_key/0"},{"type":"type","title":"public_key.issuer_name/0","doc":"The value of the issuer part of a certificate.","ref":"public_key.html#t:issuer_name/0"},{"type":"type","title":"public_key.key_params/0","doc":"ASN.1 defined parameters for public key algorithms.","ref":"public_key.html#t:key_params/0"},{"type":"type","title":"public_key.oid/0","doc":"Object identifier, a tuple of integers as generated by the `ASN.1` compiler.","ref":"public_key.html#t:oid/0"},{"type":"type","title":"public_key.pem_entry/0","doc":"Possible `Ciphers` are \"RC2-CBC\" | \"DES-CBC\" | \"DES-EDE3-CBC\" `Salt` could be generated with\n[`crypto:strong_rand_bytes(8)`](`crypto:strong_rand_bytes/1`).","ref":"public_key.html#t:pem_entry/0"},{"type":"type","title":"public_key.pki_asn1_type/0","doc":"ASN.1 type that can be found in PEM files that can be decode by the public_key application.","ref":"public_key.html#t:pki_asn1_type/0"},{"type":"type","title":"public_key.policy_node/0","doc":"Certificate policy information.","ref":"public_key.html#t:policy_node/0"},{"type":"type","title":"public_key.private_key/0","doc":"Supported private keys","ref":"public_key.html#t:private_key/0"},{"type":"type","title":"public_key.public_key/0","doc":"Supported public keys","ref":"public_key.html#t:public_key/0"},{"type":"type","title":"public_key.public_key_info/0","doc":"Information a certificates public key.\n\nPossible oids: ?'rsaEncryption' | ?'id-RSASSA-PSS' | ?'id-ecPublicKey' | ?'id-Ed25519' | ?'id-Ed448' | ?'id-dsa'","ref":"public_key.html#t:public_key_info/0"},{"type":"type","title":"public_key.rsa_private_key/0","doc":"ASN.1 defined private key format plain RSA algorithm or customization fun.","ref":"public_key.html#t:rsa_private_key/0"},{"type":"type","title":"public_key.rsa_pss_private_key/0","doc":"ASN.1 defined private key format the RSSASSA-PSS algorithm or customization fun.","ref":"public_key.html#t:rsa_pss_private_key/0"},{"type":"type","title":"public_key.rsa_pss_public_key/0","doc":"ASN.1 defined public key format for the RSSASSA-PSS algorithm.","ref":"public_key.html#t:rsa_pss_public_key/0"},{"type":"type","title":"public_key.rsa_public_key/0","doc":"ASN.1 defined public key format for plain RSA algorithm.","ref":"public_key.html#t:rsa_public_key/0"},{"type":"extras","title":"Public_Key Application","doc":"\n# Public_Key Application\n\nThe Public Key application deals with public-key related file formats,\ndigital signatures, and [X-509\ncertificates](http://www.ietf.org/rfc/rfc5280.txt). It handles\nvalidation of certificate paths and certificate revocation lists\n(CRLs) and other functions for handling of certificates, keys and\nCRLs. It is a library application that does not read or write files,\nit expects or returns file contents or partial file contents as\nbinaries. Except for the functions `public-key:cacerts_load/0`,\n`public-key:cacerts_load/1`, and `public-key:cacerts_get/0`\nthat reads files.","ref":"public_key_app.html"},{"type":"extras","title":"Supported PKIX functionality - Public_Key Application","doc":"- Supports [RFC 5280 ](http://www.ietf.org/rfc/rfc5280.txt)\\- Internet X.509\n Public-Key Infrastructure Certificate and Certificate Revocation List (CRL)\n Profile. Certificate policies supported since OTP-26.2\n- Supports [PKCS-1 ](http://www.ietf.org/rfc/rfc3447.txt)\\- RSA Cryptography\n Standard\n- Supports\n [DSS](http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf) \\-\n Digital Signature Standard (DSA - Digital Signature Algorithm)\n- Supports\n [PKCS-3 ](https://web.archive.org/web/20170417091930/https://www.emc.com/emc-plus/rsa-labs/standards-initiatives/pkcs-3-diffie-hellman-key-agreement-standar.htm)\\-\n Diffie-Hellman Key Agreement Standard\n- Supports [PKCS-5](http://www.ietf.org/rfc/rfc2898.txt) \\- Password-Based\n Cryptography Standard\n- Supports [AES ](http://www.ietf.org/rfc/fc3565.txt)\\- Use of the Advanced\n Encryption Standard (AES) Algorithm in Cryptographic Message Syntax (CMS)\n- Supports [PKCS-8](http://www.ietf.org/rfc/rfc5208.txt) \\- Private-Key\n Information Syntax Standard\n- Supports [PKCS-10](http://www.ietf.org/rfc/rfc5967.txt) \\- Certification\n Request Syntax Standard","ref":"public_key_app.html#supported-pkix-functionality"},{"type":"extras","title":"Dependencies - Public_Key Application","doc":"The `public_key` application uses the Crypto application to perform\ncryptographic operations and the ASN-1 application to handle PKIX-ASN-1\nspecifications, hence these applications must be loaded for the `public_key`\napplication to work. In an embedded environment this means they must be started\nwith `application:start/[1,2]` before the `public_key` application is started.","ref":"public_key_app.html#dependencies"},{"type":"extras","title":"Error Logger and Event Handlers - Public_Key Application","doc":"The `public_key` application is a library application and does not use the error\nlogger. The functions will either succeed or fail with a runtime error.","ref":"public_key_app.html#error-logger-and-event-handlers"},{"type":"extras","title":"See Also - Public_Key Application","doc":"`m:application`","ref":"public_key_app.html#see-also"},{"type":"extras","title":"Public_Key Release Notes","doc":"\n# Public_Key Release Notes","ref":"notes.html"},{"type":"extras","title":"Public_Key 1.16.3 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-16-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- Introduction of verify_fun/4 unfortunately introduced an argument switch for some specific path validation errors so that verify_fun/3 could under these circumstances be called with a DER cert instead of a decod cert, also in this situation the verify_fun/4 would have the certificates in reverse order.\n\n Own Id: OTP-19245 Aux Id: Gh-8832","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Do not hide crypto badarg reason, this error handling enhancement facilitates debugging. These kind of runtime errors are not documented and should never be relied on for matching, they are intended for catching input errors early.\n\n Own Id: OTP-19238","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.16.2 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-16-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- For completeness handle rsa_pss implicit default value, although this will probably not be commonly used as it provides very weak security.\n\n Own Id: OTP-19179\n\n- The `public_key:cacerts_load()` function could in some error cases return `undefined` instead of `{error, Reason}`.\n\n Own Id: OTP-19183 Aux Id: [GH-8604]\n\n- Added support for DragonFly.\n\n Own Id: OTP-19191 Aux Id: [PR-8703]\n\n[GH-8604]: https://github.com/erlang/otp/issues/8604\n[PR-8703]: https://github.com/erlang/otp/pull/8703","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Deprecation of RSA encryption functions has been reverted, as there still exists legitimate use cases with other padding modes than PKCS-1.\n \n While use PCKS-1 padding with some versions of cryptolib could be considered secure, we still recommend using other algorithms that are less sensitive to oracle attacks.\n\n Own Id: OTP-19163\n\n- It is now possible to use a verification fun of arity 4, giving the user fun access to both encoded and decoded versions of the certificate. This is desirable as a workaround for encoding errors preventing re-encoding from being reliable. This also saves some work load if the encoded version is needed.\n \n Note that calling `public_key:pkix_path_validation/3` with only decoded certs is not recommended, due to the decoding workarounds, although it will work as long as the workarounds are not needed.\n \n If the decoded version is needed before thecall to `m:public_key` it is recommend to use the combined_cert- type to avoid double decoding. Note that the path validation algorithm itself always needs both the encoded and decoded versions of the certs.\n \n The ssl implementation will now benefit from using this function instead of emulating the verify_fun/4.\n\n Own Id: OTP-19169","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.16.1 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-16-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- Fix bug in dnsName constraint check, could cause valid cert to be considered bad\n during path validation.\n\n Own Id: OTP-19100 Aux Id: [GH-8482], [PR-8508]\n\n[GH-8482]: https://github.com/erlang/otp/issues/8482\n[PR-8508]: https://github.com/erlang/otp/pull/8508","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Public_Key 1.16 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-16"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- The `ssl` client can negotiate and handle certificate status request (OCSP stapling support on the client side).\n \n Thanks to voltone for interop testing and related discussions.\n\n Own Id: OTP-18606 Aux Id: OTP-16875,OTP-16448\n\n- The exception reason when `public_key:cacerts_get/0` failed has been improved.\n\n Own Id: OTP-18609 Aux Id: [GH-7295], [PR-7302]\n\n- Key customization support has been extended to allow flexibility for implementers of for instance hardware security modules (HSM) or trusted platform modules (TPM).\n\n Own Id: OTP-18876 Aux Id: [PR-7898], [PR-7475]\n\n- The documentation has been migrated to use Markdown and ExDoc.\n\n Own Id: OTP-18955 Aux Id: [PR-8026]\n\n- The existing function `ssl:key_exporter_materials/4` is now documented and supported.\n\n *** POTENTIAL INCOMPATIBILITY ***\n\n Own Id: OTP-19016 Aux Id: [PR-8233]\n\n- Due to another attack on PKCS #1 v1.5 padding, known as the Marvin attack, about which we were alerted by Hubert Kario from Red Hat. You can find more details about the attack at\n https://people.redhat.com/~hkario/marvin/\n Functions that may be vulnerable are now deprecated. \n \n Note that you might mitigate the problem \n by using appropriate versions of OpenSSL together with our software, but we recommend not using them at all. \n \n Also avoid using TLS versions prior to TLS-1.2 (not supported by default) and\n do not enable RSA-key exchange cipher suites (not supported by default).\n\n *** POTENTIAL INCOMPATIBILITY ***\n\n Own Id: OTP-19075\n\n[GH-7295]: https://github.com/erlang/otp/issues/7295\n[PR-7302]: https://github.com/erlang/otp/pull/7302\n[PR-7898]: https://github.com/erlang/otp/pull/7898\n[PR-7475]: https://github.com/erlang/otp/pull/7475\n[PR-8026]: https://github.com/erlang/otp/pull/8026\n[PR-8233]: https://github.com/erlang/otp/pull/8233","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.15.1.3 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-15-1-3"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"* Do not hide crypto badarg reason, this error handling enhancement facilitates debugging. These kind of runtime errors are not documented and should never be relied on for matching, they are intended for catching input errors early.\n\n Own Id: OTP-19238 Aux Id: PR-8831","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.15.1.2 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-15-1-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"* For completeness handle rsa_pss implicit default value, although this will probably not be commonly used as it provides very weak security.\n\n Own Id: OTP-19179","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Public_Key 1.15.1.1 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-15-1-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"* Fix bug in dnsName constraint check, could cause valid cert to be considered bad during path validation.\n\n Own Id: OTP-19100 Aux Id: GH-8482, PR-8508","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Public_Key 1.15.1 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-15-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"* Hostname prefix with X number of dots should not be accepted.\n\n Own Id: OTP-18935 Aux Id: GH-8021","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Public_Key 1.15 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-15"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- ssl application will validate id-kp-serverAuth and id-kp-clientAuth extended\n key usage only in end entity certificates. public_key application will\n disallow \"anyExtendedKeyUsage\" for CA certificates that includes the extended\n key usage extension and marks it critical.\n\n Own Id: OTP-18739\n\n- Modernize ECC handling so that crypto FIPS support works as expected.\n\n Own Id: OTP-18854","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Support certificate policies in path_validation - as described by RFC 5280.\n\n Own Id: OTP-17844 Aux Id: ERIERL-738\n\n- Add more search paths for cacerts on Illumos.\n\n Own Id: OTP-18814 Aux Id: PR-7435\n\n- Make it possible to handle invalid date formats in the verify_fun for\n pkix_path_validation/3\n\n Own Id: OTP-18867 Aux Id: GH-7515","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.14.1 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-14-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- Country name comparison shall be case insensitive\n\n Own Id: OTP-18718 Aux Id: GH-7546\n\n- Add check to disallow duplicate certs in a path\n\n Own Id: OTP-18723 Aux Id: GH-6394","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Public_Key 1.14 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-14"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Handling of `on_load` modules during boot has been improved by adding an extra\n step in the boot order for embedded mode that runs all `on_load` handlers,\n instead of relying on explicit invocation of them, later, when the kernel\n supervision tree starts.\n\n This is mostly a code improvement and OTP internal simplification to avoid\n future bugs and to simplify code maintenance.\n\n Own Id: OTP-18447","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.13.3.4 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-13-3-4"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"* Do not hide crypto badarg reason, this error handling enhancement facilitates debugging. These kind of runtime errors are not documented and should never be relied on for matching, they are intended for catching input errors early.\n\n Own Id: OTP-19238 Aux Id: PR-8831","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.13.3.3 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-13-3-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"* For completeness handle rsa_pss implicit default value, although this will probably not be commonly used as it provides very weak security.\n\n Own Id: OTP-19179","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Public_Key 1.13.3.2 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-13-3-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- ssl application will validate id-kp-serverAuth and id-kp-clientAuth extended\n key usage only in end entity certificates. public_key application will\n disallow \"anyExtendedKeyUsage\" for CA certificates that includes the extended\n key usage extension and marks it critical.\n\n Own Id: OTP-18739","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Public_Key 1.13.3.1 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-13-3-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- Country name comparison shall be case insensitive\n\n Own Id: OTP-18718 Aux Id: GH-7546","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Public_Key 1.13.3 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-13-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- As different solutions of verifying certificate revocation exists move the\n decode of 'CRLDistributionPoints' so that it will only be decode. When it is\n actually used in the verification process. This would enable interoperability\n with systems that use certificates with an invalid empty CRLDistributionPoints\n extension that they want to ignore and make verification by other means.\n\n Own Id: OTP-18316 Aux Id: GH-6402, PR-6883\n\n- public_key:pkix_path_validation validates certificates expiring after 2050\n\n Own Id: OTP-18356 Aux Id: GH-6403\n\n- Do not leave exit message in message queue after calling `cacerts_load()` on\n MacOS.\n\n Own Id: OTP-18392 Aux Id: GH-6656","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Replace size/1 with either tuple_size/1 or byte_size/1\n\n The [`size/1`](`size/1`) BIF is not optimized by the JIT, and its use can\n result in worse types for Dialyzer.\n\n When one knows that the value being tested must be a tuple,\n [`tuple_size/1`](`tuple_size/1`) should always be preferred.\n\n When one knows that the value being tested must be a binary,\n [`byte_size/1`](`byte_size/1`) should be preferred. However,\n [`byte_size/1`](`byte_size/1`) also accepts a bitstring (rounding up size to a\n whole number of bytes), so one must make sure that the call to `byte_size/` is\n preceded by a call to [`is_binary/1`](`is_binary/1`) to ensure that bitstrings\n are rejected. Note that the compiler removes redundant calls to\n [`is_binary/1`](`is_binary/1`), so if one is not sure whether previous code\n had made sure that the argument is a binary, it does not harm to add an\n [`is_binary/1`](`is_binary/1`) test immediately before the call to\n [`byte_size/1`](`byte_size/1`).\n\n Own Id: OTP-18432 Aux Id:\n GH-6672,PR-6793,PR-6784,PR-6787,PR-6785,PR-6682,PR-6800,PR-6797,PR-6798,PR-6799,PR-6796,PR-6813,PR-6671,PR-6673,PR-6684,PR-6694,GH-6677,PR-6696,PR-6670,PR-6674","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.13.2 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-13-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- Disregard LDAP URIs when HTTP URIs are expected.\n\n Own Id: OTP-18333 Aux Id: GH-6363","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Public_Key 1.13.1 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-13-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- Support more Linux distributions in cacerts_load/0.\n\n Own Id: OTP-18154 Aux Id: PR-6002\n\n- Correct asn1 typenames available in type pki_asn1_type()\n\n Own Id: OTP-18189 Aux Id: ERIERL-829\n\n- Sign/verify does now behave as in OTP-24 and earlier for eddsa.\n\n Own Id: OTP-18205 Aux Id: GH-6219","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Public_Key 1.13 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-13"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Added functions to retrieve OS provided CA-certs.\n\n Own Id: OTP-17798 Aux Id: GH-5760\n\n- Allow key file passwords to be input as a single binary, that is we change the\n data type to be the more for the purpose logical data type iodata() instead of\n string().\n\n Own Id: OTP-17890\n\n- The deprecated public_key functions ssh_decode/2, ssh_encode/2,\n ssh_hostkey_fingerprint/1 and ssh_hostkey_fingerprint/2 are removed.\n\n They are replaced by ssh_file:decode/2, ssh_file:encode/2,\n ssh:hostkey_fingerprint/1 and ssh:hostkey_fingerprint/2 respectively.\n\n Note that the decode/2 and encode/2 are not exact replacement functions, some\n minor changes may be needed. Se the manual for more information.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17921","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.12.0.2 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-12-0-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- Country name comparison shall be case insensitive\n\n Own Id: OTP-18718 Aux Id: GH-7546","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Public_Key 1.12.0.1 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-12-0-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- Correct asn1 typenames available in type pki_asn1_type()\n\n Own Id: OTP-18189 Aux Id: ERIERL-829","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Public_Key 1.12 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-12"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Support password fun for protected keyfiles in ssl:connect function.\n\n Own Id: OTP-17816 Aux Id: PR-5607","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.11.3 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-11-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- Avoid re-encoding of decoded certificates. This could cause unexpected\n failures as some subtle encoding errors can be tolerated when decoding but\n hence creating another sequence of bytes if the decoded value is re-encoded.\n\n Own Id: OTP-17657","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Public_Key 1.11.2 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-11-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- public_key:pkix_sign/2 now honors the salt length from the provided input\n parameters. Earlier this could result in incorrect signatures if not using\n recommended defaults.\n\n Own Id: OTP-17534 Aux Id: GH-5054, PR-5057","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- When decoding an 'ECPrivateKey' unwrap the private key. For more precise\n information see RFC 8410, section 7.\n\n Own Id: OTP-17609 Aux Id: GH-5157, GH-5156","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.11.1 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-11-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- Handle cross-signed root certificates when old root expired as reported in\n GH-4877.\n\n Own Id: OTP-17475 Aux Id: GH-4877","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Public_Key 1.11 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-11"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- TLS connections now support EdDSA certificates.\n\n Own Id: OTP-17142 Aux Id: PR-4756, GH-4637, GH-4650\n\n- The functions public_key:ssh_encode/2, public_key:ssh_decode/2,\n public_key:ssh_hostkey_fingerprint/1 and public_key:ssh_hostkey_fingerprint/2\n are deprecated.\n\n Replacement functions are available in SSH, see the\n [Deprecations](`e:general_info:deprecations.md#otp-24`) chapter in the\n Erlang/OTP documentation.\n\n Own Id: OTP-17352\n\n- Enhance documentation and logging of certificate handling.\n\n Own Id: OTP-17384 Aux Id: GH-4800","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.10.0.1 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-10-0-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- Handle cross-signed root certificates when old root expired as reported in\n GH-4877.\n\n Own Id: OTP-17475 Aux Id: GH-4877","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Public_Key 1.10 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-10"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- Fixed case insensitive hostname check.\n\n Own Id: OTP-17242 Aux Id: GH-4500","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Add sanity check of trusted anchor certificate expiration to\n pkix_path_validation/3. Although the anchor is considered a trusted input this\n sanity check does provide extra security for the users of the public_key\n application as this property needs to be checked at time of usage and fits\n very well with the other checks performed here.\n\n Own Id: OTP-16907\n\n- Adjust generation of test certificates to conform to RFC 5280 rules for\n formatting of the certificates validity\n\n Own Id: OTP-17111","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.9.2 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-9-2"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Corrected dialyzer spec for pkix_path_validation/3\n\n Own Id: OTP-17069","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.9.1 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-9-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- Fix the issue that pem_decode will crash with an invalid input.\n\n Own Id: OTP-16902 Aux Id: ERIERL-534","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Public_Key 1.9 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-9"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- Fixed an insignificant whitespace issue when decoding PEM file.\n\n Own Id: OTP-16801 Aux Id: ERL-1309","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Experimental OCSP client support.\n\n Own Id: OTP-16448\n\n- Use user returned path validation error for selfsigned cert. It allows users\n of the ssl application to customize the generated TLS alert, within the range\n of defined alerts.\n\n Own Id: OTP-16592\n\n- add API function to retrieve the subject-ID of an X509 certificate\n\n Own Id: OTP-16705","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.8 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-8"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Added support for RSA-PSS signature schemes\n\n Own Id: OTP-15247\n\n- Calls of deprecated functions in the\n [Old Crypto API](`e:crypto:new_api.md#the-old-api`) are replaced by calls of\n their [substitutions](`e:crypto:new_api.md#the-new-api`).\n\n Own Id: OTP-16346","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.7.2 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-7-2"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Add support for key exchange with Edward curves and PSS-RSA padding in\n signature verification.\n\n Own Id: OTP-16528","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.7.1 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-7-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- Corrected CRL handling which could cause CRL verification to fail. This could\n happen when the CRL distribution point explicitly specifies the CRL issuer,\n that is not using the fallback.\n\n Own Id: OTP-16156 Aux Id: ERL-1030","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Public_Key 1.7 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-7"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- Support Password based encryption with AES\n\n Own Id: OTP-15870 Aux Id: ERL-952","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Change dialyzer spec to avoid confusion\n\n Own Id: OTP-15843 Aux Id: ERL-915","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.6.7 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-6-7"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- RSA options passed to crypto for encrypt and decrypt with public or private\n key.\n\n Own Id: OTP-15754 Aux Id: ERL-878\n\n- Fix dialyzer warnings caused by a faulty type specification for digest_type().\n\n This change updates digest_type() and the functions operating with this\n argument type to accept both 'sha1' and 'sha' as digest_type().\n\n Own Id: OTP-15776","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Add possibility to read PEM files encrypted with old PEM encryption using\n AES-256\n\n Own Id: OTP-13726\n\n- Relax decoding of certificates to so that \"harmless\" third party encoding\n errors may be accepted but not created by the public_key application. This\n adds acceptance of using an incorrect three character country code, the PKIX\n standard use two character country codes. It is also accepted that the country\n code is utf8 encoded but the specification says it should be ASCII.\n\n Own Id: OTP-15687 Aux Id: PR-2162","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.6.6.1 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-6-6-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- Support Password based encryption with AES\n\n Own Id: OTP-15870 Aux Id: ERL-952","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Public_Key 1.6.6 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-6-6"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Back port of bug fix ERL-893 from OTP-22 and document enhancements that will\n solve dialyzer warnings for users of the ssl application.\n\n This change also affects public_key, eldap (and inet doc).\n\n Own Id: OTP-15785 Aux Id: ERL-929, ERL-893, PR-2215","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.6.5 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-6-5"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Add export of dialyzer type\n\n Own Id: OTP-15624","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.6.4 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-6-4"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Added ed25519 and ed448 sign/verify.\n\n Requires OpenSSL 1.1.1 or higher as cryptolib under the OTP application\n `crypto`.\n\n Own Id: OTP-15419 Aux Id: OTP-15094","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.6.3 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-6-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- Add DSA SHA2 oids in public_keys ASN1-spec and public_key:pkix_sign_types/1\n\n Own Id: OTP-15367","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Public_Key 1.6.2 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-6-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- Removed `#DSAPrivateKey{}` as acceptable input to `public_key:verify/5`.\n\n Own Id: OTP-15284","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- The typing in the CRYPTO and PUBLIC_KEY applications are reworked and a few\n mistakes are corrected.\n\n The documentation is now generated from the typing and some clarifications are\n made.\n\n A new chapter on Algorithm Details such as key sizes and availability is added\n to the CRYPTO User's Guide.\n\n Own Id: OTP-15134","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.6.1 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-6-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- Some of the keylengths in the newly generated moduli file in public_key are\n not universally supported. This could cause the SSH key exchange\n diffie-hellman-group-exchange-sha\\* to fail.\n\n Those keylengths are now removed.\n\n Own Id: OTP-15151 Aux Id: OTP-15113","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Public_Key 1.6 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-6"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- Update calls to the base64 module to conform to that module's type\n specifications.\n\n Own Id: OTP-14788 Aux Id: OTP-14624","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Use uri_string module instead of http_uri.\n\n Own Id: OTP-14902\n\n- A new function - `public_key:pkix_verify_hostname_match_fun/1` \\- returns a\n fun to be given as option `match_fun` to `public_key:pkix_verify_hostname/3`\n or via ssl.\n\n The fun makes the verify hostname matching according to the specific rules for\n the protocol in the argument. Presently only `https` is supported.\n\n Own Id: OTP-14962 Aux Id: ERL-542, OTP-15102\n\n- Complete PKCS-8 encoding support and enhance the decoding of 'PrivateKeyInfo'\n to conform to the rest of Erlang public_key API.\n\n Own Id: OTP-15093\n\n- A new moduli file is generated. This file is used for the recommended\n `diffie-hellman-group-exchange-sha256` key exchange algorithm in SSH.\n\n Own Id: OTP-15113","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.5.2 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-5-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- Fixed a bug in `public_key:ssh_encode/2` that made it possible to erroneously\n encode e.g. an RSA key with another type e.g. ECDSA in the resulting binary.\n\n Own Id: OTP-14570 Aux Id: ERIERL-52, OTP-14676\n\n- Corrected handling of parameterized EC keys in public_key:generate_key/1 so\n that it will work as expected instead of causing a runtime error in crypto.\n\n Own Id: OTP-14620","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Public_Key 1.5.1 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-5-1"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Hostname verification: Add handling of the general name `iPAddress` in\n certificate's subject alternative name extension (`subjAltName`).\n\n Own Id: OTP-14653\n\n- Correct key handling in pkix_test_data/1 and use a generic example mail\n address instead of an existing one.\n\n Own Id: OTP-14766","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.5 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-5"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- public_key now handles elliptic curve parameters in a consistent way so that\n decoded ECDSA keys can be correctly re-encoded.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-14621 Aux Id: ERL-480, ERL-481","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Extend crypto:sign, crypto:verify, public_key:sign and public_key:verify with:\n\n \\* support for RSASSA-PS padding for signatures and for saltlength setting \n \\* X9.31 RSA padding. \n \\* sha, sha224, sha256, sha384, and sha512 for dss signatures as mentioned in\n NIST SP 800-57 Part 1. \n \\* ripemd160 to be used for RSA signatures.\n\n This is a manual merge of half of the pull request 838 by potatosalad from\n Sept 2015.\n\n Own Id: OTP-13704 Aux Id: PR838\n\n- Add API function pkix_test_data/1 for facilitating automated testing. This is\n useful for applications that perform X509-certifcate path validation of so\n called certificate chains, such as TLS.\n\n Own Id: OTP-14181\n\n- Improved error propagation and reports\n\n Own Id: OTP-14236\n\n- RSAPrivateKey version is set to 'two-prime' instead of using the underlying\n enumeration value directly.\n\n Own Id: OTP-14534\n\n- Deprecated function `crypto:rand_uniform/2` is replaced by `rand:uniform/1`.\n\n Own Id: OTP-14608","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.4.1 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-4-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- Bug for `public_key:generate_key({namedCurve,OID})` fixed.\n\n Own Id: OTP-14258","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Modernized internal representation used for crl validation by use of maps.\n\n Own Id: OTP-14111\n\n- Support EC key in pkix_sign/2\n\n Own Id: OTP-14294","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.4 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-4"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- New function `pkix_verify_hostname/2,3` Implements certificate hostname\n checking. See the manual and RFC 6125.\n\n Own Id: OTP-13009\n\n- The ssh host key fingerprint generation now also takes a list of algorithms\n and returns a list of corresponding fingerprints. See\n `public_key:ssh_hostkey_fingerprint/2` and the option `silently_accept_hosts`\n in `ssh:connect`.\n\n Own Id: OTP-14223","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.3 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-3"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- New function `public_key:ssh_hostkey_fingerprint/1,2` to calculate the SSH\n host key fingerprint string.\n\n Own Id: OTP-13888 Aux Id: OTP-13887","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.2 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- The ASN-1 type GeneralName can have more values, then the most common\n directory name, the code now handles this.\n\n Own Id: OTP-13554","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Handle PEM encoded EC public keys\n\n Own Id: OTP-13408","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.1.1 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-1-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- An encapsulated PEM header shall be followed by a blank line\n\n Own Id: OTP-13381 Aux Id: seq13070","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Public_Key 1.1 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-1"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- The 'ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384' and 'ecdsa-sha2-nistp521'\n signature algorithms for ssh are implemented. See RFC 5656.\n\n Own Id: OTP-12936\n\n- There is now a file (public_key/priv/moduli) which lists\n size-generator-modulus triples. The purpose is to give servers the possibility\n to select the crypto primes randomly among a list of pregenerated triples.\n This reduces the risk for some attacks on diffie-hellman negotiation.\n\n See the reference manual for public_key:dh_gex_group/4 where the handling of\n this is described.\n\n The ssh server (ssh:daemon) uses this.\n\n Own Id: OTP-13054 Aux Id: OTP-13052\n\n- Add different upper bounds for different string types as suggested by comment\n in PKIX1Explicit88.\n\n Own Id: OTP-13132","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.0.1 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-0-1"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Document enhancements\n\n Own Id: OTP-12986","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 1.0 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-1-0"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- public_key: Remove legacy switch compact_bit_string\n\n E.i bitstrings will not be decode as \\{Unused, Binary\\}, they are now Erlang\n bitstrings.\n\n Also the compact_bit_string implies the legacy_erlang_types switch So removing\n the switch will also make OCTET STRING values be represented as binaries.\n\n Undecoded open type will now be wrapped in a asn1_OPENTYPE tuple.\n\n This will change some values in records returned by the public_key API making\n this change a potentiall incompatibility.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-12110","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 0.23 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-0-23"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Improve/extend support for CRL handling.\n\n Own Id: OTP-12547 Aux Id: OTP-10362","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 0.22.1 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-0-22-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- Added missing encoding support for PBES2, and also completed support for PBES1\n that was incomplete.\n\n Own Id: OTP-11915","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Public_Key 0.22 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-0-22"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- Fix incorrect dialyzer spec and types, also enhance documentation.\n\n Thanks to Ayaz Tuncer.\n\n Own Id: OTP-11627\n\n- Application upgrade (appup) files are corrected for the following\n applications:\n\n `asn1, common_test, compiler, crypto, debugger, dialyzer, edoc, eldap, erl_docgen, et, eunit, gs, hipe, inets, observer, odbc, os_mon, otp_mibs, parsetools, percept, public_key, reltool, runtime_tools, ssh, syntax_tools, test_server, tools, typer, webtool, wx, xmerl`\n\n A new test utility for testing appup files is added to test_server. This is\n now used by most applications in OTP.\n\n (Thanks to Tobias Schlager)\n\n Own Id: OTP-11744","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Moved elliptic curve definition from the crypto NIF/OpenSSL into Erlang code,\n adds the RFC-5639 brainpool curves and makes TLS use them (RFC-7027).\n\n Thanks to Andreas Schultz\n\n Own Id: OTP-11578\n\n- Handle v1 CRLs, with no extensions and fixes issues with IDP (Issuing\n Distribution Point) comparison during CRL validation.\n\n Thanks to Andrew Thompson\n\n Own Id: OTP-11761","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 0.21 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-0-21"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Fixed a little typo in public_key documentation. Thanks to Tomas Morstein.\n\n Own Id: OTP-11380\n\n- public_key: Workaround for incorrectly encoded utf8 emailAddress. Thanks to\n Andrew Bennett.\n\n Own Id: OTP-11470","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 0.20 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-0-20"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Extend PKCS-7 to support SCEP (Simple Certificate Enrollment Protocol).\n\n Own Id: OTP-10874\n\n- public_key:pem_entry_decode/2 now handles AES-128-CBC ciphered keys. Thanks to\n Simon Cornish.\n\n Own Id: OTP-11281","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 0.19 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-0-19"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Add support for ISO oids 1.3.14.3.2.29 and 1.3.14.3.2.27 that are sometimes\n used instead of the PKCS defined oids 1.2.840.113549.1.1.5 and\n 1.2.840.10040.4.3. Add function pkix_sign_types:/1 that translates oids to to\n algorithm atoms ex:\n\n > public_key:pkix_sign_types(\\{1,3,14,3,2,29\\}). \\{sha,rsa\\}\n\n Own Id: OTP-10873\n\n- Integrate elliptic curve contribution from Andreas Schultz\n\n In order to be able to support elliptic curve cipher suites in SSL/TLS,\n additions to handle elliptic curve infrastructure has been added to public_key\n and crypto.\n\n This also has resulted in a rewrite of the crypto API to gain consistency and\n remove unnecessary overhead. All OTP applications using crypto has been\n updated to use the new API.\n\n Impact: Elliptic curve cryptography (ECC) offers equivalent security with\n smaller key sizes than other public key algorithms. Smaller key sizes result\n in savings for power, memory, bandwidth, and computational cost that make ECC\n especially attractive for constrained environments.\n\n Own Id: OTP-11009","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 0.18 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-0-18"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- Fix subjectPublicKeyInfo type comment in public_key. Thanks to Ryosuke Nakai.\n\n Own Id: OTP-10670","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- public_key now supports CRL validation and documents the function\n public_key:pkix_path_validation/3\n\n Own Id: OTP-7045\n\n- Some examples overflowing the width of PDF pages have been corrected.\n\n Own Id: OTP-10665\n\n- Fixed typo's in public_key spec.\n\n Own Id: OTP-10723\n\n- Corrected PKCS-10 documentation and added some PKCS-9 support that is fairly\n commonly used by PKCS-10. Full support for PKCS-9 will be added later.\n\n Own Id: OTP-10767","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 0.17 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-0-17"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- ssh_decode now handles comments, at the end of the line, containing with\n spaces correctly\n\n Own Id: OTP-9361\n\n- Add missing references to sha224 and sha384\n\n Own Id: OTP-9362 Aux Id: seq12116","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- public_key now supports PKCS-10 and includes experimental support for PKCS-7\n\n Own Id: OTP-10509 Aux Id: kunagi-291 \\[202]","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 0.16 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-0-16"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Add crypto and public_key support for the hash functions SHA224, SHA256,\n SHA384 and SHA512 and also hmac and rsa_sign/verify support using these hash\n functions. Thanks to Andreas Schultz for making a prototype.\n\n Own Id: OTP-9908\n\n- Optimize RSA private key handling in `crypto` and `public_key`.\n\n Own Id: OTP-10065","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 0.15 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-0-15"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Changed ssh implementation to use the public_key application for all public\n key handling. This is also a first step for enabling a callback API for\n supplying public keys and handling keys protected with password phrases.\n\n Additionally the test suites where improved so that they do not copy the users\n keys to test server directories as this is a security liability. Also ipv6 and\n file access issues found in the process has been fixed.\n\n This change also solves OTP-7677 and OTP-7235\n\n This changes also involves some updates to public_keys ssh-functions.\n\n Own Id: OTP-9911","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 0.14 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-0-14"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- public_key, ssl and crypto now supports PKCS-8\n\n Own Id: OTP-9312\n\n- The asn1 decoder/encoder now uses a runtime nif from the asn1 application if\n it is available.\n\n Own Id: OTP-9414","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 0.13 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-0-13"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- replace \"a ssl\" with \"an ssl\" reindent pkix_path_validation/3 Trivial\n documentation fixes (Thanks to Christian von Roques )\n\n Own Id: OTP-9464","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Public_Key 0.12 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-0-12"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- The public_key application now supports encode/decode of ssh public-key files.\n\n Own Id: OTP-9144","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 0.11 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-0-11"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Allows the public_key module to decode and encode RSA and DSA keys encoded\n using the SubjectPublicKeyInfo format. When pem_entry_encode is called on an\n RSA or DSA public key type, the key is wrapped in the SubjectPublicKeyInfo\n format.\n\n Own Id: OTP-9061","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 0.10 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-0-10"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Improved dialyzer specs.\n\n Own Id: OTP-8964","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 0.9 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-0-9"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Updated ssl to ignore CA certs that violate the asn1-spec for a certificate,\n and updated public key asn1 spec to handle inherited DSS-params.\n\n Own Id: OTP-7884\n\n- Changed ssl implementation to retain backwards compatibility for old option\n \\{verify, 0\\} that shall be equivalent to \\{verify, verify_none\\}, also\n separate the cases unknown ca and selfsigned peer cert, and restored return\n value of deprecated function public_key:pem_to_der/1.\n\n Own Id: OTP-8858\n\n- Better handling of v1 and v2 certificates. V1 and v2 certificates does not\n have any extensions so then validate_extensions should just accept that there\n are none and not end up in missing_basic_constraints clause.\n\n Own Id: OTP-8867\n\n- Changed the verify fun so that it differentiate between the peer certificate\n and CA certificates by using valid_peer or valid as the second argument to the\n verify fun. It may not always be trivial or even possible to know when the\n peer certificate is reached otherwise.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8873","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 0.8 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-0-8"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- Handling of unknown CA certificates was changed in ssl and public_key to work\n as intended.\n\n Own Id: OTP-8788","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Revise the public_key API - Cleaned up and documented the public_key API to\n make it useful for general use, also changed ssl to use the new API.\n\n Own Id: OTP-8722\n\n- Added the functionality so that the verification fun will be called when a\n certificate is considered valid by the path validation to allow access to each\n certificate in the path to the user application. Also try to verify\n subject-AltName, if unable to verify it let the application verify it.\n\n Own Id: OTP-8825","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 0.7 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-0-7"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- Certificates without any extensions could not be handled by public_key.\n\n Own Id: OTP-8626","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Code cleanup and minor bugfixes.\n\n Own Id: OTP-8649","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 0.6 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-0-6"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Support for Diffie-Hellman. ssl-3.11 requires public_key-0.6.\n\n Own Id: OTP-7046\n\n- Moved extended key usage test for ssl values to ssl.\n\n Own Id: OTP-8553 Aux Id: seq11541, OTP-8554","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 0.5 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-0-5"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Added `public_key:pkix_transform/2` to enable ssl to send CA list during\n Certificate Request.\n\n `NOTE`: SSL (new_ssl) requires public_key-0.5. ssl usage.\n\n Own Id: OTP-8372","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 0.4 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-0-4"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- The documentation is now built with open source tools (xsltproc and fop) that\n exists on most platforms. One visible change is that the frames are removed.\n\n Own Id: OTP-8250","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 0.3 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-0-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","doc":"- Unknown attributes in certificates are left encoded instead of crashing. Patch\n by Will \"wglozer\" thanks.\n\n Own Id: OTP-8100","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- Allow public_key:pem_to_der/\\[1,2] to take a binary as argument in addition to\n a filename. Patch by Geoff Cant, thanks.\n\n Own Id: OTP-8142","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 0.2 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-0-2"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- X509 certificate handling has been extended and improved as a result of more\n extensive testing of both the ssl and public_key application. Even more\n extensions of the certificate handling is yet to be implemented.\n\n Own Id: OTP-7860","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public_Key 0.1 - Public_Key Release Notes","doc":"","ref":"notes.html#public_key-0-1"},{"type":"extras","title":"Improvements and New Features - Public_Key Release Notes","doc":"- First version.\n\n Own Id: OTP-7637","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Public-Key Records","doc":"\n# Public-Key Records\n\nThis chapter briefly describes Erlang records derived from ASN.1 specifications\nused to handle public key infrastructure. The scope is to describe the data\ntypes of each component, not the semantics. For information on the semantics,\nrefer to the relevant standards and RFCs linked in the sections below.\n\nUse the following include directive to get access to the records and constant\nmacros described in the following sections:\n\n```erlang\n -include_lib(\"public_key/include/public_key.hrl\").\n```","ref":"public_key_records.html"},{"type":"extras","title":"Data Types - Public-Key Records","doc":"Common non-standard Erlang data types used to describe the record fields in the\nfollowing sections and which are not defined in the Public Key\n[Reference Manual](`m:public_key`) follows here:\n\n```erlang\ntime() = utc_time() | general_time()\n\nutc_time() = {utcTime, \"YYMMDDHHMMSSZ\"}\n\ngeneral_time() = {generalTime, \"YYYYMMDDHHMMSSZ\"}\n\ngeneral_name() = {rfc822Name, string()} |\n\n {dNSName, string()} |\n\n {x400Address, string() |\n\n {directoryName, {rdnSequence, [#'AttributeTypeAndValue'{}]}} |\n\n {ediPartyName, special_string()} |\n\n {ediPartyName, special_string(), special_string()} |\n\n {uniformResourceIdentifier, string()} |\n\n {iPAddress, string()} |\n\n {registeredId, oid()} |\n\n {otherName, term()}\n\nspecial_string() = {teletexString, string()} |\n \n {printableString, string()} |\n\n {universalString, string()} |\n\n {utf8String, binary()} |\n\n {bmpString, string()}\n\ndist_reason() = unused | keyCompromise | cACompromise | affiliationChanged |\n cessationOfOperation | certificateHold | privilegeWithdrawn | aACompromise\n\nOID_macro() = ?OID_name()\n\nOID_name() = atom()\n```","ref":"public_key_records.html#data-types"},{"type":"extras","title":"RSA - Public-Key Records","doc":"Erlang representation of\n[Rivest-Shamir-Adleman cryptosystem (RSA)](http://www.ietf.org/rfc/rfc3447.txt)\nkeys follows:\n\n```erlang\n#'RSAPublicKey'{\n modulus, % pos_integer()\n publicExponent % pos_integer()\n }.\n\n#'RSAPrivateKey'{\n version, % two-prime | multi\n modulus, % pos_integer()\n publicExponent, % pos_integer()\n privateExponent, % pos_integer()\n prime1, % pos_integer()\n prime2, % pos_integer()\n exponent1, % pos_integer()\n exponent2, % pos_integer()\n coefficient, % pos_integer()\n otherPrimeInfos % [#OtherPrimeInfo{}] | asn1_NOVALUE\n }.\n\n#'OtherPrimeInfo'{\n prime, % pos_integer()\n exponent, % pos_integer()\n coefficient % pos_integer()\n }.\n\n#'RSASSA-PSS-params'{\n hashAlgorithm, % #'HashAlgorithm'{}},\n maskGenAlgorithm, % #'MaskGenAlgorithm'{}},\n saltLength, % pos_integer(),\n trailerField, % pos_integer()\n }.\n\n#'HashAlgorithm'{\n algorithm, % oid()\n parameters % defaults to asn1_NOVALUE\n }.\n\n#'MaskGenAlgorithm'{\n algorithm, % oid()\n parameters, % defaults to asn1_NOVALUE\n }.\n```","ref":"public_key_records.html#rsa"},{"type":"extras","title":"DSA - Public-Key Records","doc":"Erlang representation of\n[Digital Signature Algorithm (DSA)](http://www.ietf.org/rfc/rfc6979.txt) keys\n\n```erlang\n#'DSAPrivateKey'{\n version, % pos_integer()\n p, % pos_integer()\n q, % pos_integer()\n g, % pos_integer()\n y, % pos_integer()\n x % pos_integer()\n }.\n\n#'Dss-Parms'{\n p, % pos_integer()\n q, % pos_integer()\n g % pos_integer()\n }.\n```","ref":"public_key_records.html#dsa"},{"type":"extras","title":"ECDSA and EDDSA - Public-Key Records","doc":"Erlang representation of\n[Elliptic Curve Digital Signature Algorithm (ECDSA)](http://www.ietf.org/rfc/rfc6979.txt)\nand\n[Edwards-Curve Digital Signature Algorithm (EDDSA)](https://tools.ietf.org/html/rfc8032)\nwhere parameters in the private key will be\n`{namedCurve, ?'id-Ed25519' | ?'id-Ed448'}`.\n\n```erlang\n#'ECPrivateKey'{\n version, % pos_integer()\n privateKey, % binary()\n parameters, % {ecParameters, #'ECParameters'{}} |\n % {namedCurve, Oid::tuple()} |\n % {implicitlyCA, 'NULL'}\n publicKey % bitstring()\n }.\n\n#'ECParameters'{\n version, % pos_integer()\n fieldID, % #'FieldID'{}\n curve, % #'Curve'{}\n base, % binary()\n order, % pos_integer()\n cofactor % pos_integer()\n }.\n\n#'Curve'{\n a, % binary()\n b, % binary()\n seed % bitstring() - optional\n }.\n\n#'FieldID'{\n fieldType, % oid()\n parameters % Depending on fieldType\n }.\n\n#'ECPoint'{\n point % binary() - the public key\n }.\n```","ref":"public_key_records.html#ecdsa-and-eddsa"},{"type":"extras","title":"PKIX Certificates - Public-Key Records","doc":"Erlang representation of PKIX certificates derived from ASN.1 specifications see\nalso [X509 certificates (RFC 5280)](http://www.ietf.org/rfc/rfc5280.txt), also\nreferred to as `plain` type, are as follows:\n\n```erlang\n#'Certificate'{\n tbsCertificate, % #'TBSCertificate'{}\n signatureAlgorithm, % #'AlgorithmIdentifier'{}\n signature % bitstring()\n }.\n\n#'TBSCertificate'{\n version, % v1 | v2 | v3\n serialNumber, % pos_integer()\n signature, % #'AlgorithmIdentifier'{}\n issuer, % {rdnSequence, [#AttributeTypeAndValue'{}]\n validity, % #'Validity'{}\n subject, % {rdnSequence, [#AttributeTypeAndValue'{}]}\n subjectPublicKeyInfo, % #'SubjectPublicKeyInfo'{}\n issuerUniqueID, % binary() | asn1_novalue\n subjectUniqueID, % binary() | asn1_novalue\n extensions % [#'Extension'{}]\n }.\n\n#'AlgorithmIdentifier'{\n algorithm, % oid()\n parameters % der_encoded()\n }.\n```\n\nErlang alternate representation of PKIX certificate, also referred to as `otp`\ntype\n\n```erlang\n#'OTPCertificate'{\n tbsCertificate, % #'OTPTBSCertificate'{}\n signatureAlgorithm, % #'SignatureAlgorithm'\n signature % bitstring()\n }.\n\n#'OTPTBSCertificate'{\n version, % v1 | v2 | v3\n serialNumber, % pos_integer()\n signature, % #'SignatureAlgorithm'\n issuer, % {rdnSequence, [#AttributeTypeAndValue'{}]}\n validity, % #'Validity'{}\n subject, % {rdnSequence, [#AttributeTypeAndValue'{}]}\n subjectPublicKeyInfo, % #'OTPSubjectPublicKeyInfo'{}\n issuerUniqueID, % binary() | asn1_novalue\n subjectUniqueID, % binary() | asn1_novalue\n extensions % [#'Extension'{}]\n }.\n\n#'SignatureAlgorithm'{\n algorithm, % id_signature_algorithm()\n parameters % asn1_novalue | #'Dss-Parms'{}\n }.\n```\n\n`id_signature_algorithm() = OID_macro()`\n\nThe available OID names are as follows:\n\n| _OID Name_ |\n| -------------------------------------------- |\n| id-dsa-with-sha1 |\n| id-dsaWithSHA1 (ISO or OID to above) |\n| md2WithRSAEncryption |\n| md5WithRSAEncryption |\n| sha1WithRSAEncryption |\n| sha-1WithRSAEncryption (ISO or OID to above) |\n| sha224WithRSAEncryption |\n| sha256WithRSAEncryption |\n| sha512WithRSAEncryption |\n| ecdsa-with-SHA1 |\n\n_Table: Signature Algorithm OIDs_\n\nThe data type `'AttributeTypeAndValue'`, is represented as the following erlang\nrecord:\n\n```erlang\n#'AttributeTypeAndValue'{\n type, % id_attributes()\n value % term()\n }.\n```\n\nThe attribute OID name atoms and their corresponding value types are as follows:\n\n| _OID Name_ | _Value Type_ |\n| ------------------------- | ----------------------------- |\n| id-at-name | special_string() |\n| id-at-surname | special_string() |\n| id-at-givenName | special_string() |\n| id-at-initials | special_string() |\n| id-at-generationQualifier | special_string() |\n| id-at-commonName | special_string() |\n| id-at-localityName | special_string() |\n| id-at-stateOrProvinceName | special_string() |\n| id-at-organizationName | special_string() |\n| id-at-title | special_string() |\n| id-at-dnQualifier | \\{printableString, string()\\} |\n| id-at-countryName | \\{printableString, string()\\} |\n| id-at-serialNumber | \\{printableString, string()\\} |\n| id-at-pseudonym | special_string() |\n\n_Table: Attribute OIDs_\n\nThe data types `'Validity'`, `'SubjectPublicKeyInfo'`, and\n`'SubjectPublicKeyInfoAlgorithm'` are represented as the following Erlang\nrecords:\n\n```erlang\n#'Validity'{\n notBefore, % time()\n notAfter % time()\n }.\n\n#'SubjectPublicKeyInfo'{\n algorithm, % #AlgorithmIdentifier{}\n subjectPublicKey % binary()\n }.\n\n#'SubjectPublicKeyInfoAlgorithm'{\n algorithm, % id_public_key_algorithm()\n parameters % public_key_params()\n }.\n```\n\nThe public-key algorithm OID name atoms are as follows:\n\n| _OID Name_ |\n| ----------------------- |\n| rsaEncryption |\n| id-dsa |\n| dhpublicnumber |\n| id-keyExchangeAlgorithm |\n| id-ecPublicKey |\n\n_Table: Public-Key Algorithm OIDs_\n\n```erlang\n#'Extension'{\n extnID, % id_extensions() | oid()\n critical, % boolean()\n extnValue % der_encoded()\n }.\n```\n\n`id_extensions()`\n[Standard Certificate Extensions](public_key_records.md#StdCertExt),\n[Private Internet Extensions](public_key_records.md#PrivIntExt),\n[CRL Extensions](public_key_records.md#CRLCertExt) and\n[CRL Entry Extensions](public_key_records.md#CRLEntryExt).\n\n[](){: #StdCertExt }","ref":"public_key_records.html#pkix-certificates"},{"type":"extras","title":"Standard Certificate Extensions - Public-Key Records","doc":"The standard certificate extensions OID name atoms and their corresponding value\ntypes are as follows:\n\n| _OID Name_ | _Value Type_ |\n| -------------------------------- | ------------------------------ |\n| id-ce-authorityKeyIdentifier | \\#'AuthorityKeyIdentifier'\\{\\} |\n| id-ce-subjectKeyIdentifier | oid() |\n| id-ce-keyUsage | \\[key_usage()] |\n| id-ce-privateKeyUsagePeriod | \\#'PrivateKeyUsagePeriod'\\{\\} |\n| id-ce-certificatePolicies | \\#'PolicyInformation'\\{\\} |\n| id-ce-policyMappings | \\#'PolicyMappings_SEQOF'\\{\\} |\n| id-ce-subjectAltName | general_name() |\n| id-ce-issuerAltName | general_name() |\n| id-ce-subjectDirectoryAttributes | \\[#'Attribute'\\{\\}] |\n| id-ce-basicConstraints | \\#'BasicConstraints'\\{\\} |\n| id-ce-nameConstraints | \\#'NameConstraints'\\{\\} |\n| id-ce-policyConstraints | \\#'PolicyConstraints'\\{\\} |\n| id-ce-extKeyUsage | \\[id_key_purpose()] |\n| id-ce-cRLDistributionPoints | \\[#'DistributionPoint'\\{\\}] |\n| id-ce-inhibitAnyPolicy | pos_integer() |\n| id-ce-freshestCRL | \\[#'DistributionPoint'\\{\\}] |\n\n_Table: Standard Certificate Extensions_\n\nHere:\n\n```erlang\nkey_usage() = digitalSignature | nonRepudiation | keyEncipherment\n | dataEncipherment | keyAgreement | keyCertSign\n | cRLSign | encipherOnly | decipherOnly\n```\nAnd for `id_key_purpose()`:\n\n| _OID Name_ |\n| --------------------- |\n| id-kp-serverAuth |\n| id-kp-clientAuth |\n| id-kp-codeSigning |\n| id-kp-emailProtection |\n| id-kp-timeStamping |\n| id-kp-OCSPSigning |\n\n_Table: Key Purpose OIDs_\n\n```erlang\n#'AuthorityKeyIdentifier'{\n keyIdentifier, % oid()\n authorityCertIssuer, % general_name()\n authorityCertSerialNumber % pos_integer()\n }.\n\n#'PrivateKeyUsagePeriod'{\n notBefore, % general_time()\n notAfter % general_time()\n }.\n\n#'PolicyInformation'{\n policyIdentifier, % oid()\n policyQualifiers % [#PolicyQualifierInfo{}]\n }.\n\n#'PolicyQualifierInfo'{\n policyQualifierId, % oid()\n qualifier % string() | #'UserNotice'{}\n }.\n\n#'UserNotice'{\n noticeRef, % #'NoticeReference'{}\n explicitText % string()\n }.\n\n#'NoticeReference'{\n organization, % string()\n noticeNumbers % [pos_integer()]\n }.\n\n#'PolicyMappings_SEQOF'{\n issuerDomainPolicy, % oid()\n subjectDomainPolicy % oid()\n }.\n\n#'Attribute'{\n type, % oid()\n values % [der_encoded()]\n }).\n\n#'BasicConstraints'{\n cA, % boolean()\n pathLenConstraint % pos_integer()\n }).\n\n#'NameConstraints'{\n permittedSubtrees, % [#'GeneralSubtree'{}]\n excludedSubtrees % [#'GeneralSubtree'{}]\n }).\n\n#'GeneralSubtree'{\n base, % general_name()\n minimum, % pos_integer()\n maximum % pos_integer()\n }).\n\n#'PolicyConstraints'{\n requireExplicitPolicy, % pos_integer()\n inhibitPolicyMapping % pos_integer()\n }).\n\n#'DistributionPoint'{\n distributionPoint, % {fullName, [general_name()]} | {nameRelativeToCRLIssuer,[#AttributeTypeAndValue{}]}\n reasons, % [dist_reason()]\n cRLIssuer % [general_name()]\n }).\n```\n\n[](){: #PrivIntExt }","ref":"public_key_records.html#standard-certificate-extensions"},{"type":"extras","title":"Private Internet Extensions - Public-Key Records","doc":"The private internet extensions OID name atoms and their corresponding value\ntypes are as follows:\n\n| _OID Name_ | _Value Type_ |\n| ------------------------- | --------------------------- |\n| id-pe-authorityInfoAccess | \\[#'AccessDescription'\\{\\}] |\n| id-pe-subjectInfoAccess | \\[#'AccessDescription'\\{\\}] |\n\n_Table: Private Internet Extensions_\n\n```erlang\n#'AccessDescription'{\n accessMethod, % oid()\n accessLocation % general_name()\n }).\n```","ref":"public_key_records.html#private-internet-extensions"},{"type":"extras","title":"CRL and CRL Extensions Profile - Public-Key Records","doc":"Erlang representation of CRL and CRL extensions profile derived from ASN.1\nspecifications and RFC 5280 are as follows:\n\n```erlang\n#'CertificateList'{\n tbsCertList, % #'TBSCertList{}\n signatureAlgorithm, % #'AlgorithmIdentifier'{}\n signature % bitstring()\n }).\n\n#'TBSCertList'{\n version, % v2 (if defined)\n signature, % #AlgorithmIdentifier{}\n issuer, % {rdnSequence, [#AttributeTypeAndValue'{}]}\n thisUpdate, % time()\n nextUpdate, % time()\n revokedCertificates, % [#'TBSCertList_revokedCertificates_SEQOF'{}]\n crlExtensions % [#'Extension'{}]\n }).\n\n#'TBSCertList_revokedCertificates_SEQOF'{\n userCertificate, % pos_integer()\n revocationDate, % timer()\n crlEntryExtensions % [#'Extension'{}]\n }).\n```\n\n[](){: #CRLCertExt }","ref":"public_key_records.html#crl-and-crl-extensions-profile"},{"type":"extras","title":"CRL Extensions - Public-Key Records","doc":"The CRL extensions OID name atoms and their corresponding value types are as\nfollows:\n\n| _OID Name_ | _Value Type_ |\n| ------------------------------ | ----------------------------------------------- |\n| id-ce-authorityKeyIdentifier | \\#'AuthorityKeyIdentifier\\{\\} |\n| id-ce-issuerAltName | \\{rdnSequence, \\[#AttributeTypeAndValue'\\{\\}]\\} |\n| id-ce-cRLNumber | pos_integer() |\n| id-ce-deltaCRLIndicator | pos_integer() |\n| id-ce-issuingDistributionPoint | \\#'IssuingDistributionPoint'\\{\\} |\n| id-ce-freshestCRL | \\[#'Distributionpoint'\\{\\}] |\n\n_Table: CRL Extensions_\n\nHere, the data type `'IssuingDistributionPoint'` is represented as the following\nErlang record:\n\n```erlang\n#'IssuingDistributionPoint'{\n distributionPoint, % {fullName, [general_name()]} | {nameRelativeToCRLIssuer, [#'AttributeTypeAndValue'{}]}\n onlyContainsUserCerts, % boolean()\n onlyContainsCACerts, % boolean()\n onlySomeReasons, % [dist_reason()]\n indirectCRL, % boolean()\n onlyContainsAttributeCerts % boolean()\n }).\n```\n\n[](){: #CRLEntryExt }","ref":"public_key_records.html#crl-extensions"},{"type":"extras","title":"CRL Entry Extensions - Public-Key Records","doc":"The CRL entry extensions OID name atoms and their corresponding value types are\nas follows:\n\n| _OID Name_ | _Value Type_ |\n| ------------------------- | -------------- |\n| id-ce-cRLReason | crl_reason() |\n| id-ce-holdInstructionCode | oid() |\n| id-ce-invalidityDate | general_time() |\n| id-ce-certificateIssuer | general_name() |\n\n_Table: CRL Entry Extensions_\n\nHere:\n\n```erlang\n crl_reason() = unspecified | keyCompromise | cACompromise\n | affiliationChanged | superseded | cessationOfOperation\n | certificateHold | removeFromCRL\n | privilegeWithdrawn | aACompromise\n```","ref":"public_key_records.html#crl-entry-extensions"},{"type":"extras","title":"PKCS#10 Certification Request - Public-Key Records","doc":"Erlang representation of a PKCS#10 certification request derived from ASN.1\nspecifications and RFC 5280 are as follows:\n\n```erlang\n#'CertificationRequest'{\n certificationRequestInfo, % #'CertificationRequestInfo'{},\n signatureAlgorithm, % #'CertificationRequest_signatureAlgorithm'{}}.\n signature % bitstring()\n }.\n\n#'CertificationRequestInfo'{\n version, % atom(),\n subject, % {rdnSequence, [#AttributeTypeAndValue'{}]} ,\n subjectPKInfo, % #'CertificationRequestInfo_subjectPKInfo'{},\n attributes % [#'AttributePKCS-10' {}]\n }.\n\n#'CertificationRequestInfo_subjectPKInfo'{\n algorithm, % #'CertificationRequestInfo_subjectPKInfo_algorithm'{}\n subjectPublicKey % bitstring()\n }.\n\n#'CertificationRequestInfo_subjectPKInfo_algorithm'{\n algorithm, % oid(),\n parameters % der_encoded()\n }.\n\n#'CertificationRequest_signatureAlgorithm'{\n algorithm, % oid(),\n parameters % der_encoded()\n }.\n\n#'AttributePKCS-10'{\n type, % oid(),\n values % [der_encoded()]\n }.\n```\n[](){: #PKCS10}","ref":"public_key_records.html#pkcs-10-certification-request"},{"type":"extras","title":"Examples","doc":"\n# Examples\n\nThis section describes examples of how to use the Public Key API. Keys and\ncertificates used in the following sections are generated only for testing the\nPublic Key application.\n\nSome shell printouts in the following examples are abbreviated for increased\nreadability.","ref":"using_public_key.html"},{"type":"extras","title":"PEM Files - Examples","doc":"Public-key data (keys, certificates, and so on) can be stored in Privacy\nEnhanced Mail (PEM) format. The PEM files have the following structure:\n\n```text\n \n -----BEGIN -----\n : \n \n -----END -----\n \n```\n\nA file can contain several `BEGIN/END` blocks. Text lines between blocks are\nignored. Attributes, if present, are ignored except for `Proc-Type` and\n`DEK-Info`, which are used when `DER` data is encrypted.","ref":"using_public_key.html#pem-files"},{"type":"extras","title":"DSA Private Key - Examples","doc":"A DSA private key can look as follows:\n\n> #### Note {: .info }\n>\n> File handling is not done by the Public Key application.\n\n```erlang\n1> {ok, PemBin} = file:read_file(\"dsa.pem\").\n{ok,<<\"-----BEGIN DSA PRIVATE KEY-----\\nMIIBuw\"...>>}\n```\n\nThe following PEM file has only one entry, a private DSA key:\n\n```erlang\n2>[DSAEntry] = public_key:pem_decode(PemBin).\n[{'DSAPrivateKey',<<48,130,1,187,2,1,0,2,129,129,0,183,\n 179,230,217,37,99,144,157,21,228,204,\n 162,207,61,246,...>>,\n not_encrypted}]\n```\n\n```erlang\n3> Key = public_key:pem_entry_decode(DSAEntry).\n#'DSAPrivateKey'{version = 0,\n p = 12900045185019966618...6593,\n q = 1216700114794736143432235288305776850295620488937,\n g = 10442040227452349332...47213,\n y = 87256807980030509074...403143,\n x = 510968529856012146351317363807366575075645839654}\n```","ref":"using_public_key.html#dsa-private-key"},{"type":"extras","title":"RSA Private Key with Password - Examples","doc":"An RSA private key encrypted with a password can look as follows:\n\n```erlang\n1> {ok, PemBin} = file:read_file(\"rsa.pem\").\n{ok,<<\"Bag Attribute\"...>>}\n```\n\nThe following PEM file has only one entry, a private RSA key:\n\n```erlang\n2>[RSAEntry] = public_key:pem_decode(PemBin).\n[{'RSAPrivateKey',<<224,108,117,203,152,40,15,77,128,126,\n 221,195,154,249,85,208,202,251,109,\n 119,120,57,29,89,19,9,...>>,\n {\"DES-EDE3-CBC\",<<\"kÙeø¼pµL\">>}}]\n```\n\nIn this following example, the password is `\"abcd1234\"`:\n\n```erlang\n3> Key = public_key:pem_entry_decode(RSAEntry, \"abcd1234\").\n#'RSAPrivateKey'{version = 'two-prime',\n modulus = 1112355156729921663373...2737107,\n publicExponent = 65537,\n privateExponent = 58064406231183...2239766033,\n prime1 = 11034766614656598484098...7326883017,\n prime2 = 10080459293561036618240...77738643771,\n exponent1 = 77928819327425934607...22152984217,\n exponent2 = 36287623121853605733...20588523793,\n coefficient = 924840412626098444...41820968343,\n otherPrimeInfos = asn1_NOVALUE}\n```","ref":"using_public_key.html#rsa-private-key-with-password"},{"type":"extras","title":"X509 Certificates - Examples","doc":"The following is an example of X509 certificates:\n\n```erlang\n1> {ok, PemBin} = file:read_file(\"cacerts.pem\").\n{ok,<<\"-----BEGIN CERTIFICATE-----\\nMIIC7jCCAl\"...>>}\n```\n\nThe following file includes two certificates:\n\n```erlang\n2> [CertEntry1, CertEntry2] = public_key:pem_decode(PemBin).\n[{'Certificate',<<48,130,2,238,48,130,2,87,160,3,2,1,2,2,\n 9,0,230,145,97,214,191,2,120,150,48,13,\n ...>>,\n not_encrypted},\n {'Certificate',<<48,130,3,200,48,130,3,49,160,3,2,1,2,2,1,\n 1,48,13,6,9,42,134,72,134,247,...>>,\n not_encrypted}]\n```\n\nCertificates can be decoded as usual:\n\n```erlang\n2> Cert = public_key:pem_entry_decode(CertEntry1).\n#'Certificate'{\n tbsCertificate =\n #'TBSCertificate'{\n version = v3,serialNumber = 16614168075301976214,\n signature =\n #'AlgorithmIdentifier'{\n algorithm = {1,2,840,113549,1,1,5},\n parameters = <<5,0>>},\n issuer =\n {rdnSequence,\n [[#'AttributeTypeAndValue'{\n type = {2,5,4,3},\n value = <<19,8,101,114,108,97,110,103,67,65>>}],\n [#'AttributeTypeAndValue'{\n type = {2,5,4,11},\n value = <<19,10,69,114,108,97,110,103,32,79,84,80>>}],\n [#'AttributeTypeAndValue'{\n type = {2,5,4,10},\n value = <<19,11,69,114,105,99,115,115,111,110,32,65,66>>}],\n [#'AttributeTypeAndValue'{\n type = {2,5,4,7},\n value = <<19,9,83,116,111,99,107,104,111,108,109>>}],\n [#'AttributeTypeAndValue'{\n type = {2,5,4,6},\n value = <<19,2,83,69>>}],\n [#'AttributeTypeAndValue'{\n type = {1,2,840,113549,1,9,1},\n value = <<22,22,112,101,116,101,114,64,101,114,...>>}]]},\n validity =\n #'Validity'{\n notBefore = {utcTime,\"080109082929Z\"},\n notAfter = {utcTime,\"080208082929Z\"}},\n subject =\n {rdnSequence,\n [[#'AttributeTypeAndValue'{\n type = {2,5,4,3},\n value = <<19,8,101,114,108,97,110,103,67,65>>}],\n [#'AttributeTypeAndValue'{\n type = {2,5,4,11},\n value = <<19,10,69,114,108,97,110,103,32,79,84,80>>}],\n [#'AttributeTypeAndValue'{\n type = {2,5,4,10},\n value = <<19,11,69,114,105,99,115,115,111,110,32,...>>}],\n [#'AttributeTypeAndValue'{\n type = {2,5,4,7},\n value = <<19,9,83,116,111,99,107,104,111,108,...>>}],\n [#'AttributeTypeAndValue'{\n type = {2,5,4,6},\n value = <<19,2,83,69>>}],\n [#'AttributeTypeAndValue'{\n type = {1,2,840,113549,1,9,1},\n value = <<22,22,112,101,116,101,114,64,...>>}]]},\n subjectPublicKeyInfo =\n #'SubjectPublicKeyInfo'{\n algorithm =\n #'AlgorithmIdentifier'{\n algorithm = {1,2,840,113549,1,1,1},\n parameters = <<5,0>>},\n subjectPublicKey =\n {0,<<48,129,137,2,129,129,0,203,209,187,77,73,231,90,...>>}},\n issuerUniqueID = asn1_NOVALUE,\n subjectUniqueID = asn1_NOVALUE,\n extensions =\n [#'Extension'{\n extnID = {2,5,29,19},\n critical = true,\n extnValue = [48,3,1,1,255]},\n #'Extension'{\n extnID = {2,5,29,15},\n critical = false,\n extnValue = [3,2,1,6]},\n #'Extension'{\n extnID = {2,5,29,14},\n critical = false,\n extnValue = [4,20,27,217,65,152,6,30,142|...]},\n #'Extension'{\n extnID = {2,5,29,17},\n critical = false,\n extnValue = [48,24,129,22,112,101,116,101|...]}]},\n signatureAlgorithm =\n #'AlgorithmIdentifier'{\n algorithm = {1,2,840,113549,1,1,5},\n parameters = <<5,0>>},\n signature =\n <<163,186,7,163,216,152,63,47,154,234,139,73,154,96,120,\n 165,2,52,196,195,109,167,192,...>>}\n```\n\nParts of certificates can be decoded with `public_key:der_decode/2`, using the\nASN.1 type of that part. However, an application-specific certificate extension\nrequires application-specific ASN.1 decode/encode-functions. In the recent\nexample, the first value of `rdnSequence` is of ASN.1 type\n`'X520CommonName'. ({2,5,4,3} = ?id-at-commonName)`:\n\n```erlang\npublic_key:der_decode('X520CommonName', <<19,8,101,114,108,97,110,103,67,65>>).\n{printableString,\"erlangCA\"}\n```\n\nHowever, certificates can also be decoded using `pkix_decode_cert/2`, which can\ncustomize and recursively decode standard parts of a certificate:\n\n```erlang\n3> {_, DerCert, _} = CertEntry1.\n```\n\n```erlang\n4> public_key:pkix_decode_cert(DerCert, otp).\n#'OTPCertificate'{\n tbsCertificate =\n #'OTPTBSCertificate'{\n version = v3,serialNumber = 16614168075301976214,\n signature =\n #'SignatureAlgorithm'{\n algorithm = {1,2,840,113549,1,1,5},\n parameters = 'NULL'},\n issuer =\n {rdnSequence,\n [[#'AttributeTypeAndValue'{\n type = {2,5,4,3},\n value = {printableString,\"erlangCA\"}}],\n [#'AttributeTypeAndValue'{\n type = {2,5,4,11},\n value = {printableString,\"Erlang OTP\"}}],\n [#'AttributeTypeAndValue'{\n type = {2,5,4,10},\n value = {printableString,\"Ericsson AB\"}}],\n [#'AttributeTypeAndValue'{\n type = {2,5,4,7},\n value = {printableString,\"Stockholm\"}}],\n [#'AttributeTypeAndValue'{type = {2,5,4,6},value = \"SE\"}],\n [#'AttributeTypeAndValue'{\n type = {1,2,840,113549,1,9,1},\n value = \"peter@erix.ericsson.se\"}]]},\n validity =\n #'Validity'{\n notBefore = {utcTime,\"080109082929Z\"},\n notAfter = {utcTime,\"080208082929Z\"}},\n subject =\n {rdnSequence,\n [[#'AttributeTypeAndValue'{\n type = {2,5,4,3},\n value = {printableString,\"erlangCA\"}}],\n [#'AttributeTypeAndValue'{\n type = {2,5,4,11},\n value = {printableString,\"Erlang OTP\"}}],\n [#'AttributeTypeAndValue'{\n type = {2,5,4,10},\n value = {printableString,\"Ericsson AB\"}}],\n [#'AttributeTypeAndValue'{\n type = {2,5,4,7},\n value = {printableString,\"Stockholm\"}}],\n [#'AttributeTypeAndValue'{type = {2,5,4,6},value = \"SE\"}],\n [#'AttributeTypeAndValue'{\n type = {1,2,840,113549,1,9,1},\n value = \"peter@erix.ericsson.se\"}]]},\n subjectPublicKeyInfo =\n #'OTPSubjectPublicKeyInfo'{\n algorithm =\n #'PublicKeyAlgorithm'{\n algorithm = {1,2,840,113549,1,1,1},\n parameters = 'NULL'},\n subjectPublicKey =\n #'RSAPublicKey'{\n modulus =\n 1431267547247997...37419,\n publicExponent = 65537}},\n issuerUniqueID = asn1_NOVALUE,\n subjectUniqueID = asn1_NOVALUE,\n extensions =\n [#'Extension'{\n extnID = {2,5,29,19},\n critical = true,\n extnValue =\n #'BasicConstraints'{\n cA = true,pathLenConstraint = asn1_NOVALUE}},\n #'Extension'{\n extnID = {2,5,29,15},\n critical = false,\n extnValue = [keyCertSign,cRLSign]},\n #'Extension'{\n extnID = {2,5,29,14},\n critical = false,\n extnValue = [27,217,65,152,6,30,142,132,245|...]},\n #'Extension'{\n extnID = {2,5,29,17},\n critical = false,\n extnValue = [{rfc822Name,\"peter@erix.ericsson.se\"}]}]},\n signatureAlgorithm =\n #'SignatureAlgorithm'{\n algorithm = {1,2,840,113549,1,1,5},\n parameters = 'NULL'},\n signature =\n <<163,186,7,163,216,152,63,47,154,234,139,73,154,96,120,\n 165,2,52,196,195,109,167,192,...>>}\n```\n\nThis call is equivalent to `public_key:pem_entry_decode(CertEntry1)`:\n\n```erlang\n5> public_key:pkix_decode_cert(DerCert, plain).\n#'Certificate'{ ...}\n```","ref":"using_public_key.html#x509-certificates"},{"type":"extras","title":"Encoding Public-Key Data to PEM Format - Examples","doc":"If you have public-key data and want to create a PEM file this can be done by\ncalling functions `public_key:pem_entry_encode/2` and `pem_encode/1` and saving\nthe result to a file. For example, assume that you have\n`PubKey = 'RSAPublicKey'{}`. Then you can create a PEM-\"RSA PUBLIC KEY\" file\n(ASN.1 type `'RSAPublicKey'`) or a PEM-\"PUBLIC KEY\" file\n(`'SubjectPublicKeyInfo'` ASN.1 type).\n\nThe second element of the PEM-entry is the ASN.1 `DER` encoded key data:\n\n```erlang\n1> PemEntry = public_key:pem_entry_encode('RSAPublicKey', RSAPubKey).\n{'RSAPublicKey', <<48,72,...>>, not_encrypted}\n\n2> PemBin = public_key:pem_encode([PemEntry]).\n<<\"-----BEGIN RSA PUBLIC KEY-----\\nMEgC...>>\n\n3> file:write_file(\"rsa_pub_key.pem\", PemBin).\nok\n```\n\nor:\n\n```erlang\n1> PemEntry = public_key:pem_entry_encode('SubjectPublicKeyInfo', RSAPubKey).\n{'SubjectPublicKeyInfo', <<48,92...>>, not_encrypted}\n\n2> PemBin = public_key:pem_encode([PemEntry]).\n<<\"-----BEGIN PUBLIC KEY-----\\nMFw...>>\n\n3> file:write_file(\"pub_key.pem\", PemBin).\nok\n```","ref":"using_public_key.html#encoding-public-key-data-to-pem-format"},{"type":"extras","title":"RSA Public-Key Cryptography - Examples","doc":"Suppose you have the following private key and a corresponding public key:\n\n- `PrivateKey = #'RSAPrivateKey{}'` and the plaintext `Msg = binary()`\n- `PublicKey = #'RSAPublicKey'{}`\n\nThen you can proceed as follows:\n\nEncrypt with the private key:\n\n```erlang\nRsaEncrypted = public_key:encrypt_private(Msg, PrivateKey),\nMsg = public_key:decrypt_public(RsaEncrypted, PublicKey),\n```\n\nEncrypt with the public key:\n\n```erlang\nRsaEncrypted = public_key:encrypt_public(Msg, PublicKey),\nMsg = public_key:decrypt_private(RsaEncrypted, PrivateKey),\n```\n\n> #### Note {: .info }\n>\n> You normally do only one of the encrypt or decrypt operations, and the peer\n> does the other. This normally used in legacy applications as a primitive\n> digital signature.\n\n> #### Warning {: .warning }\n>\n> This legacy algorithm is broken although there exists a software prevention\n> when using appropriate OpenSSL cryptolib with Erlang/OTP it is hard to\n> guarantee security and we strongly recommend not using it.","ref":"using_public_key.html#rsa-public-key-cryptography"},{"type":"extras","title":"Digital Signatures - Examples","doc":"Suppose you have the following private key and a corresponding public key:\n\n- `PrivateKey = #'RSAPrivateKey{}'` or `#'DSAPrivateKey'{}` and the plaintext\n `Msg = binary()`\n- `PublicKey = #'RSAPublicKey'{}` or `{integer(), #'DssParams'{}}`\n\nThen you can proceed as follows:\n\n```erlang\nSignature = public_key:sign(Msg, sha, PrivateKey),\ntrue = public_key:verify(Msg, sha, Signature, PublicKey),\n```\n\n> #### Note {: .info }\n>\n> You normally do only one of the sign or verify operations, and the peer does\n> the other.\n\nIt can be appropriate to calculate the message digest before calling `sign` or\n`verify`, and then use `none` as second argument:\n\n```erlang\nDigest = crypto:sha(Msg),\nSignature = public_key:sign(Digest, none, PrivateKey),\ntrue = public_key:verify(Digest, none, Signature, PublicKey),\n```\n\n[](){: #verify_hostname }","ref":"using_public_key.html#digital-signatures"},{"type":"extras","title":"Verifying a certificate hostname - Examples","doc":"","ref":"using_public_key.html#verifying-a-certificate-hostname"},{"type":"extras","title":"Background - Examples","doc":"When a client checks a server certificate there are a number of checks available\nlike checks that the certificate is not revoked, not forged or not out-of-date.\n\nThere are however attacks that are not detected by those checks. Suppose a bad\nguy has succeeded with a DNS infection. Then the client could believe it is\nconnecting to one host but ends up at another but evil one. Though it is evil,\nit could have a perfectly legal certificate\\! The certificate has a valid\nsignature, it is not revoked, the certificate chain is not faked and has a\ntrusted root and so on.\n\nTo detect that the server is not the intended one, the client must additionally\nperform a _hostname verification_. This procedure is described in\n[RFC 6125](https://tools.ietf.org/html/rfc6125). The idea is that the\ncertificate lists the hostnames it could be fetched from. This is checked by the\ncertificate issuer when the certificate is signed. So if the certificate is\nissued by a trusted root the client could trust the host names signed in it.\n\nThere is a default hostname matching procedure defined in\n[RFC 6125, section 6](https://tools.ietf.org/html/rfc6125#section/6) as well as\nprotocol dependent variations defined in\n[RFC 6125 appendix B](https://tools.ietf.org/html/rfc6125#appendix-B). The\ndefault procedure is implemented in\n[public_key:pkix_verify_hostname/2,3](`public_key:pkix_verify_hostname/2`). It\nis possible for a client to hook in modified rules using the options list.\n\nSome terminology is needed: the certificate presents hostname(s) on which it is\nvalid. Those are called _Presented IDs_. The hostname(s) the client believes it\nconnects to are called _Reference IDs_. The matching rules aims to verify that\nthere is at least one of the Reference IDs that matches one of the Presented\nIDs. If not, the verification fails.\n\nThe IDs contains normal fully qualified domain names like e.g `foo.example.com`,\nbut IP addresses are not recommended. The rfc describes why this is not\nrecommended as well as security considerations about how to acquire the\nReference IDs.\n\nInternationalized domain names are not supported.","ref":"using_public_key.html#background"},{"type":"extras","title":"The verification process - Examples","doc":"Traditionally the Presented IDs were found in the `Subject` certificate field as\n`CN` names. This is still quite common. When printing a certificate they show up\nas:\n\n```text\n $ openssl x509 -text < cert.pem\n ...\n Subject: C=SE, CN=example.com, CN=*.example.com, O=erlang.org\n ...\n```\n\nThe example `Subject` field has one C, two CN and one O part. It is only the CN\n(Common Name) that is used by hostname verification. The two other (C and O) is\nnot used here even when they contain a domain name like the O part. The C and O\nparts are defined elsewhere and meaningful only for other functions.\n\nIn the example the Presented IDs are `example.com` as well as hostnames matching\n`*.example.com`. For example `foo.example.com` and `bar.example.com` both\nmatches but not `foo.bar.example.com`. The name `erlang.org` matches neither\nsince it is not a CN.\n\nIn case where the Presented IDs are fetched from the `Subject` certificate\nfield, the names may contain wildcard characters. The function handles this as\ndefined in\n[chapter 6.4.3 in RFC 6125](https://tools.ietf.org/html/rfc6125#section-6.4.3).\n\nThere may only be one wildcard character and that is in the first label, for\nexample: `*.example.com`. This matches `foo.example.com` but neither\n`example.com` nor `foo.bar.example.com`.\n\nThere may be label characters before or/and after the wildcard. For example:\n`a*d.example.com` matches `abcd.example.com` and `ad.example.com`, but not\n`ab.cd.example.com`.\n\nIn the previous example there is no indication of which protocols are expected.\nSo a client has no indication of whether it is a web server, an ldap server or\nmaybe a sip server it is connected to. There are fields in the certificate that\ncan indicate this. To be more exact, the rfc introduces the usage of the\n`X509v3 Subject Alternative Name` in the `X509v3 extensions` field:\n\n```text\n $ openssl x509 -text < cert.pem\n ...\n X509v3 extensions:\n X509v3 Subject Alternative Name:\n DNS:kb.example.org, URI:https://www.example.org\n ...\n```\n\nHere `kb.example.org` serves any protocol while `www.example.org` presents a\nsecure web server.\n\nThe next example has both `Subject` and `Subject Alternate Name` present:\n\n```text\n $ openssl x509 -text < cert.pem\n ...\n Subject: C=SE, CN=example.com, CN=*.example.com, O=erlang.org\n ...\n X509v3 extensions:\n X509v3 Subject Alternative Name:\n DNS:kb.example.org, URI:https://www.example.org\n ...\n```\n\nThe RFC states that if a certificate defines Reference IDs in a\n`Subject Alternate Name` field, the `Subject` field MUST NOT be used for host\nname checking, even if it contains valid CN names. Therefore only\n`kb.example.org` and `https://www.example.org` matches. The match fails both for\n`example.com` and `foo.example.com` because they are in the `Subject` field\nwhich is not checked because the `Subject Alternate Name` field is present.\n\n[](){: #verify_hostname_examples }","ref":"using_public_key.html#the-verification-process"},{"type":"extras","title":"Function call examples - Examples","doc":"> #### Note {: .info }\n>\n> Other applications like ssl/tls or https might have options that are passed\n> down to the `public_key:pkix_verify_hostname`. You will probably not have to\n> call it directly\n\nSuppose our client expects to connect to the web server https://www.example.net.\nThis URI is therefore the Reference IDs of the client. The call will be:\n\n```erlang\n public_key:pkix_verify_hostname(CertFromHost,\n [{uri_id, \"https://www.example.net\"}\n ]).\n```\n\nThe call will return `true` or `false` depending on the check. The caller do not\nneed to handle the matching rules in the rfc. The matching will proceed as:\n\n- If there is a `Subject Alternate Name` field, the `{uri_id,string()}` in the\n function call will be compared to any `{uniformResourceIdentifier,string()}`\n in the Certificate field. If the two `strings()` are equal (case insensitive),\n there is a match. The same applies for any `{dns_id,string()}` in the call\n which is compared with all `{dNSName,string()}` in the Certificate field.\n- If there is NO `Subject Alternate Name` field, the `Subject` field will be\n checked. All `CN` names will be compared to all hostnames _extracted_ from\n `{uri_id,string()}` and from `{dns_id,string()}`.","ref":"using_public_key.html#function-call-examples"},{"type":"extras","title":"Extending the search mechanism - Examples","doc":"The caller can use own extraction and matching rules. This is done with the two\noptions `fqdn_fun` and `match_fun`.\n\n[](){: #hostname_extraction }\n\n#### Hostname extraction\n\nThe `fqdn_fun` extracts hostnames (Fully Qualified Domain Names) from uri_id or\nother ReferenceIDs that are not pre-defined in the public_key function. Suppose\nyou have some URI with a very special protocol-part: `myspecial://example.com\"`.\nSince this a non-standard URI there will be no hostname extracted for matching\nCN-names in the `Subject`.\n\nTo \"teach\" the function how to extract, you can give a fun which replaces the\ndefault extraction function. The `fqdn_fun` takes one argument and returns\neither a `t:string/0` to be matched to each CN-name or the atom `default` which\nwill invoke the default fqdn extraction function. The return value `undefined`\nremoves the current URI from the fqdn extraction.\n\n```erlang\n ...\n Extract = fun({uri_id, \"myspecial://\"++HostName}) -> HostName;\n (_Else) -> default\n end,\n ...\n public_key:pkix_verify_hostname(CertFromHost, RefIDs,\n [{fqdn_fun, Extract}])\n ...\n```\n\n[](){: #redefining_match_op }\n\n#### Re-defining the match operation\n\nThe default matching handles dns_id and uri_id. In an uri_id the value is tested\nfor equality with a value from the `Subject Alternate Name`. If some other kind\nof matching is needed, use the `match_fun` option.\n\nThe `match_fun` takes two arguments and returns either `true`, `false` or\n`default`. The value `default` will invoke the default match function.\n\n```erlang\n ...\n Match = fun({uri_id,\"myspecial://\"++A},\n {uniformResourceIdentifier,\"myspecial://\"++B}) ->\n my_match(A,B);\n (_RefID, _PresentedID) ->\n default\n end,\n ...\n public_key:pkix_verify_hostname(CertFromHost, RefIDs,\n [{match_fun, Match}]),\n ...\n```\n\nIn case of a match operation between a ReferenceID and a CN value from the\n`Subject` field, the first argument to the fun is the extracted hostname from\nthe ReferenceID, and the second argument is the tuple `{cn, string()}` taken\nfrom the `Subject` field. That makes it possible to have separate matching rules\nfor Presented IDs from the `Subject` field and from the `Subject Alternate Name`\nfield.\n\nThe default matching transformes the ascii values in strings to lowercase before\ncomparing. The `match_fun` is however called without any transformation applied\nto the strings. The reason is to enable the user to do unforeseen handling of\nthe strings where the original format is needed.\n\n### \"Pinning\" a Certificate\n\nThe [RFC 6125](https://tools.ietf.org/html/rfc6125) defines _pinning_ as:\n\n> \"The act of establishing a cached name association between the application\n> service's certificate and one of the client's reference identifiers, despite\n> the fact that none of the presented identifiers matches the given reference\n> identifier. ...\"\n\nThe purpose is to have a mechanism for a human to accept an otherwise faulty\nCertificate. In for example a web browser, you could get a question like\n\n> Warning: you wanted to visit the site www.example.com, but the certificate is\n> for shop.example.com. Accept anyway (yes/no)?\"\n\nThis could be accomplished with the option `fail_callback` which will be called\nif the hostname verification fails:\n\n```erlang\n -include_lib(\"public_key/include/public_key.hrl\"). % Record def\n ...\n Fail = fun(#'OTPCertificate'{}=C) ->\n case in_my_cache(C) orelse my_accept(C) of\n true ->\n enter_my_cache(C),\n true;\n false ->\n false\n end,\n ...\n public_key:pkix_verify_hostname(CertFromHost, RefIDs,\n [{fail_callback, Fail}]),\n ...\n```","ref":"using_public_key.html#extending-the-search-mechanism"}],"content_type":"text/plain","producer":{"name":"ex_doc","version":[48,46,51,52,46,49]}} \ No newline at end of file diff --git a/prs/9045/lib/public_key-1.16.3/doc/html/dist/search_data-E7E84476.js b/prs/9045/lib/public_key-1.16.3/doc/html/dist/search_data-E7E84476.js deleted file mode 100644 index 5f174fddf688..000000000000 --- a/prs/9045/lib/public_key-1.16.3/doc/html/dist/search_data-E7E84476.js +++ /dev/null @@ -1 +0,0 @@ -searchData={"items":[{"type":"module","doc":"API module for public-key infrastructure.\n\nProvides functions to handle public-key infrastructure, for details see\n[public_key application](public_key_app.md).\n\n> #### Note {: .info }\n>\n> All records used in this Reference Manual are generated from ASN.1\n> specifications and are documented in the User's Guide. See\n> [Public-key Records](public_key_records.md).\n\nUse the following include directive to get access to the records and constant\nmacros described here and in the User's Guide:\n\n```text\n -include_lib(\"public_key/include/public_key.hrl\").\n```","title":"public_key","ref":"public_key.html"},{"type":"function","doc":"Clears any loaded CA certificates, returns true if any was loaded.","title":"public_key.cacerts_clear/0","ref":"public_key.html#cacerts_clear/0"},{"type":"function","doc":"Returns the trusted CA certificates if any are loaded, otherwise uses\n`cacerts_load/0` to load them. The function fails if no `cacerts` could be\nloaded.","title":"public_key.cacerts_get/0","ref":"public_key.html#cacerts_get/0"},{"type":"function","doc":"Loads the OS supplied trusted CA certificates.\n\nThis can be overridden by setting the `cacerts_path`\nenvironment key of the `public_key` application with\nthe location of an alternative certificate.\nYou can set it via the command line as:\n\n erl -public_key cacerts_path '\"/path/to/certs.pem\"'\n\nUse it with care. It is your responsibility to ensure\nthat the certificates found in this alternative path\ncan be trusted by the running system.","title":"public_key.cacerts_load/0","ref":"public_key.html#cacerts_load/0"},{"type":"function","doc":"Loads the trusted CA certificates from a file.","title":"public_key.cacerts_load/1","ref":"public_key.html#cacerts_load/1"},{"type":"function","doc":"Computes shared secret.","title":"public_key.compute_key/2","ref":"public_key.html#compute_key/2"},{"type":"function","doc":"Computes shared secret.","title":"public_key.compute_key/3","ref":"public_key.html#compute_key/3"},{"type":"function","doc":"","title":"public_key.decrypt_private/2","ref":"public_key.html#decrypt_private/2"},{"type":"function","doc":"Public-key decryption using the private key. See also `crypto:private_decrypt/4`\n\n> #### Warning {: .warning }\n>\n> This is a legacy function, for security reasons do not use with rsa_pkcs1_padding.","title":"public_key.decrypt_private/3","ref":"public_key.html#decrypt_private/3"},{"type":"function","doc":"","title":"public_key.decrypt_public/2","ref":"public_key.html#decrypt_public/2"},{"type":"function","doc":"Public-key decryption using the public key. See also `crypto:public_decrypt/4`\n\n> #### Warning {: .warning }\n>\n> This is a legacy function, for security reasons do not use with rsa_pkcs1_padding.\n> For digital signatures the use of [`verify/4`](`verify/4`) together\n> with [`sign/3`](`sign/3`) is a prefered solution.","title":"public_key.decrypt_public/3","ref":"public_key.html#decrypt_public/3"},{"type":"function","doc":"Decodes a public-key ASN.1 DER encoded entity.","title":"public_key.der_decode/2","ref":"public_key.html#der_decode/2"},{"type":"function","doc":"Encodes a public-key entity with ASN.1 DER encoding.","title":"public_key.der_encode/2","ref":"public_key.html#der_encode/2"},{"type":"function","doc":"Selects a group for Diffie-Hellman key exchange with the key size in the range\n`MinSize...MaxSize` and as close to `SuggestedSize` as possible. If\n`Groups == undefined` a default set will be used, otherwise the group is\nselected from `Groups`.\n\nFirst a size, as close as possible to SuggestedSize, is selected. Then one group\nwith that key size is randomly selected from the specified set of groups. If no\nsize within the limits of `MinSize` and `MaxSize` is available,\n`{error,no_group_found}` is returned.\n\nThe default set of groups is listed in `lib/public_key/priv/moduli`. This file\nmay be regenerated like this:\n\n```text\n\t$> cd $ERL_TOP/lib/public_key/priv/\n\t$> generate\n ---- wait until all background jobs has finished. It may take several days !\n\t$> cat moduli-* > moduli\n\t$> cd ..; make\n```","title":"public_key.dh_gex_group/4","ref":"public_key.html#dh_gex_group/4"},{"type":"function","doc":"","title":"public_key.encrypt_private/2","ref":"public_key.html#encrypt_private/2"},{"type":"function","doc":"Public-key encryption using the private key.\n\nSee also `crypto:private_encrypt/4`. The key, can besides a standard\nRSA key, be a map specifing the key algorithm `rsa` and a fun to\nhandle the encryption operation. This may be used for customized the\nencryption operation with for instance hardware security modules (HSM)\nor trusted platform modules (TPM).\n\n> #### Warning {: .warning }\n>\n> This is a legacy function, for security reasons do not use with rsa_pkcs1_padding.\n> For digital signatures use of [`sign/3`](`sign/3`) together with [`verify/4`](`verify/4`) is\n> the prefered solution.","title":"public_key.encrypt_private/3","ref":"public_key.html#encrypt_private/3"},{"type":"function","doc":"","title":"public_key.encrypt_public/2","ref":"public_key.html#encrypt_public/2"},{"type":"function","doc":"Public-key encryption using the public key. See also `crypto:public_encrypt/4`.\n\n> #### Warning {: .warning }\n>\n> This is a legacy function, for security reasons do not use with rsa_pkcs1_padding.","title":"public_key.encrypt_public/3","ref":"public_key.html#encrypt_public/3"},{"type":"function","doc":"Generates a new key pair. Note that except for Diffie-Hellman the public key is\nincluded in the private key structure. See also `crypto:generate_key/2`","title":"public_key.generate_key/1","ref":"public_key.html#generate_key/1"},{"type":"function","doc":"Decodes PEM binary data and returns entries as ASN.1 DER encoded entities.\n\nExample\n`{ok, PemBin} = file:read_file(\"cert.pem\"). PemEntries = public_key:pem_decode(PemBin).`","title":"public_key.pem_decode/1","ref":"public_key.html#pem_decode/1"},{"type":"function","doc":"Creates a PEM binary.","title":"public_key.pem_encode/1","ref":"public_key.html#pem_encode/1"},{"type":"function","doc":"","title":"public_key.pem_entry_decode/1","ref":"public_key.html#pem_entry_decode/1"},{"type":"function","doc":"Decodes a PEM entry. [`pem_decode/1`](`pem_decode/1`) returns a list of PEM\nentries. Notice that if the PEM entry is of type 'SubjectPublickeyInfo', it is\nfurther decoded to an `t:rsa_public_key/0` or `t:dsa_public_key/0`.\n\nPassword can be either an octet string or function which returns same type.","title":"public_key.pem_entry_decode/2","ref":"public_key.html#pem_entry_decode/2"},{"type":"function","doc":"","title":"public_key.pem_entry_encode/2","ref":"public_key.html#pem_entry_encode/2"},{"type":"function","doc":"Creates a PEM entry that can be feed to [`pem_encode/1`](`pem_encode/1`).\n\nIf `Asn1Type` is `'SubjectPublicKeyInfo'`, `Entity` must be either an\n`t:rsa_public_key/0`, `t:dsa_public_key/0` or an `t:ecdsa_public_key/0` and this\nfunction creates the appropriate `'SubjectPublicKeyInfo'` entry.","title":"public_key.pem_entry_encode/3","ref":"public_key.html#pem_entry_encode/3"},{"type":"function","doc":"Returns the issuer of the `CRL`.","title":"public_key.pkix_crl_issuer/1","ref":"public_key.html#pkix_crl_issuer/1"},{"type":"function","doc":"Verify that `Cert` is the `CRL` signer.","title":"public_key.pkix_crl_verify/2","ref":"public_key.html#pkix_crl_verify/2"},{"type":"function","doc":"Performs CRL validation. It is intended to be called from the verify fun of\n[pkix_path_validation/3 ](`pkix_path_validation/3`).\n\nAvailable options:\n\n- **\\{update_crl, fun()\\}** - The fun has the following type specification:\n\n ```erlang\n fun(#'DistributionPoint'{}, #'CertificateList'{}) ->\n #'CertificateList'{}\n ```\n\n The fun uses the information in the distribution point to access the latest\n possible version of the CRL. If this fun is not specified, Public Key uses the\n default implementation:\n\n ```text\n fun(_DP, CRL) -> CRL end\n ```\n\n- **\\{issuer_fun, \\{fun(), UserState::term()\\}\\}** - The fun has the following type\n specification:\n\n ```erlang\n fun(#'DistributionPoint'{}, #'CertificateList'{},\n {rdnSequence,[#'AttributeTypeAndValue'{}]}, UserState::term()) ->\n \t{ok, #'OTPCertificate'{}, [der_encoded]}\n ```\n\n The fun returns the root certificate and certificate chain that has signed the\n CRL.\n\n ```erlang\n fun(DP, CRL, Issuer, UserState) -> {ok, RootCert, CertChain}\n ```\n\n- **\\{undetermined_details, boolean()\\}** - Defaults to false. When revocation\n status cannot be determined, and this option is set to true, details of why no\n CRLs where accepted are included in the return value.","title":"public_key.pkix_crls_validate/3","ref":"public_key.html#pkix_crls_validate/3"},{"type":"function","doc":"Decodes an ASN.1 DER-encoded PKIX certificate.\n\nOption `otp` uses the customized ASN.1 specification OTP-PKIX.asn1 for\ndecoding and also recursively decode most of the standard parts.","title":"public_key.pkix_decode_cert/2","ref":"public_key.html#pkix_decode_cert/2"},{"type":"function","doc":"Creates a distribution point for CRLs issued by the same issuer as `Cert`. Can\nbe used as input to `pkix_crls_validate/3`","title":"public_key.pkix_dist_point/1","ref":"public_key.html#pkix_dist_point/1"},{"type":"function","doc":"Extracts distribution points from the certificates extensions.","title":"public_key.pkix_dist_points/1","ref":"public_key.html#pkix_dist_points/1"},{"type":"function","doc":"DER encodes a PKIX x509 certificate or part of such a certificate.\n\nThis function must be used for encoding certificates or parts of\ncertificates that are decoded/created in the `otp` format, whereas for\nthe plain format this function directly calls\n[`der_encode/2`](`der_encode/2`).\n\n> #### Note {: .info }\n>\n> Subtle ASN-1 encoding errors in certificates may be worked around when\n> decoding, this may have the affect that the encoding a certificate back to DER\n> may generate different bytes then the supplied original.","title":"public_key.pkix_encode/3","ref":"public_key.html#pkix_encode/3"},{"type":"function","doc":"Translates OID to Erlang digest type","title":"public_key.pkix_hash_type/1","ref":"public_key.html#pkix_hash_type/1"},{"type":"function","doc":"Checks if a certificate is a fixed Diffie-Hellman certificate.","title":"public_key.pkix_is_fixed_dh_cert/1","ref":"public_key.html#pkix_is_fixed_dh_cert/1"},{"type":"function","doc":"Checks if `IssuerCert` issued `Cert`.","title":"public_key.pkix_is_issuer/2","ref":"public_key.html#pkix_is_issuer/2"},{"type":"function","doc":"Checks if a certificate is self-signed.","title":"public_key.pkix_is_self_signed/1","ref":"public_key.html#pkix_is_self_signed/1"},{"type":"function","doc":"Returns the x509 certificate issuer id, if it can be determined.","title":"public_key.pkix_issuer_id/2","ref":"public_key.html#pkix_issuer_id/2"},{"type":"function","doc":"Checks whether the given distribution point matches the Issuing Distribution\nPoint of the CRL, as described in RFC 5280.\n\nIf the CRL doesn't have an Issuing\nDistribution Point extension, the distribution point always matches.","title":"public_key.pkix_match_dist_point/2","ref":"public_key.html#pkix_match_dist_point/2"},{"type":"function","doc":"Normalizes an issuer name so that it can be easily compared to another issuer\nname.","title":"public_key.pkix_normalize_name/1","ref":"public_key.html#pkix_normalize_name/1"},{"type":"function","doc":"Perform OCSP response validation according to RFC 6960. Returns {'ok', Details} when OCSP\nresponse is successfully validated and \\{error, \\{bad_cert, Reason\\}\\}\notherwise.\n\nAvailable options:\n\n- **\\{is_trusted_responder_fun, fun()\\}** - The fun has the following type\n specification:\n\n ```text\n fun(#cert{}) ->\n \t boolean()\n ```\n\n The fun returns the `true` if certificate in the argument is trusted. If this\n fun is not specified, Public Key uses the default implementation:\n\n ```text\n fun(_) -> false end\n ```\n\n> #### Note {: .info }\n>\n> OCSP response can be provided without a nonce value - even if it was requested\n> by the client. In such cases {missing, ocsp_nonce} will be returned\n> in Details list.","title":"public_key.pkix_ocsp_validate/5","ref":"public_key.html#pkix_ocsp_validate/5"},{"type":"function","doc":"Performs a basic path validation according to\n[RFC 5280.](http://www.ietf.org/rfc/rfc5280.txt)\n\nHowever, CRL validation is done separately by [pkix_crls_validate/3\n](`pkix_crls_validate/3`)and is to be called from the supplied\n`verify_fun`. The policy tree check was added in OTP-26.2 and if the\ncertificates include policies the constrained policy set with\npotential qualifiers will be returned, these values are derived from\nthe policy tree created as part of the path validation algorithm. The\nconstrained set can be constrained only by the Certificate Authorities\nor also by the user when the option `policy_set` is provided to this\nfunction. The qualifiers convey information about the valid policy and\nis intended as information to end users.\n\nAvailable options:\n\n- **\\{verify_fun, \\{fun(), UserState::term()\\}** - The fun must be\n defined as:\n\n ```erlang\n fun(OtpCert :: #'OTPCertificate'{},\n Event :: {bad_cert, Reason :: atom() | {revoked, atom()}} |\n {extension, #'Extension'{}},\n UserState :: term()) ->\n \t{valid, UserState :: term()} |\n \t{valid_peer, UserState :: term()} |\n \t{fail, Reason :: term()} |\n \t{unknown, UserState :: term()}.\n ```\n\n or as:\n\n ```erlang\n fun(OtpCert :: #'OTPCertificate'{},\n DerCert :: der_encoded(),\n Event :: {bad_cert, Reason :: atom() | {revoked, atom()}} |\n {extension, #'Extension'{}},\n UserState :: term()) ->\n\t{valid, UserState :: term()} |\n\t{valid_peer, UserState :: term()} |\n\t{fail, Reason :: term()} |\n\t{unknown, UserState :: term()}.\n ```\n\n The verify callback can have 3 or 4 arguments in case the DER encoded\n version is needed by the callback.\n\n If the verify callback fun returns `{fail, Reason}`, the verification process\n is immediately stopped. If the verify callback fun returns\n `{valid, UserState}`, the verification process is continued. This can be used\n to accept specific path validation errors, such as `selfsigned_peer`, as well\n as verifying application-specific extensions. If called with an extension\n unknown to the user application, the return value `{unknown, UserState}` is to\n be used.\n\n > #### Note {: .note }\n > If you need the DER encoded version of the certificate and have\n > the OTP decoded version encoding it back can fail to give the correct result,\n > due to work arounds for common misbehaving encoders. So it is recommended\n > to call `pkix_path_validation` with `Cert` and `CertChain` arguments as\n > `der_encoded() | #cert{}` and `[der_encoded() | #cert{}]`. Also note\n > that the path validation itself needs both the encoded and the\n > decoded version of the certificate.\n\n > #### Warning {: .warning }\n >\n > Note that user defined custom `verify_fun` may alter original path\n > validation error (e.g `selfsigned_peer`). Use with caution.\n\n- **\\{max_path_length, integer()\\}** - The `max_path_length` is the maximum\n number of non-self-issued intermediate certificates that can follow the peer\n certificate in a valid certification path. So, if `max_path_length` is 0, the\n PEER must be signed by the trusted ROOT-CA directly, if it is 1, the path can\n be PEER, CA, ROOT-CA, if it is 2, the path can be PEER, CA, CA, ROOT-CA, and\n so on.\n\n- **\\{policy_set, \\[oid()]\\}**(Since OTP 26.2) \n The set of policies that will be accepted, defaults to the special value\n `[?anyPolicy]` that will accept all policies.\n\n- **\\{explicit_policy, boolean()\\}**(Since OTP 26.2) \n Explicitly require that each certificate in the path must include at least one\n of the certificate policies in the `policy_set`.\n\n- **\\{inhibit_policy_mapping, boolean()\\}**(Since OTP 26.2) \n Prevent policies to be mapped to other policies.\n\n- **\\{inhibit_any_policy, boolean()\\}**(Since OTP 26.2) \n Prevent the special policy `?anyPolicy` from being accepted.\n\nExplanations of reasons for a bad certificate:\n\n- **cert_expired** - Certificate is no longer valid as its expiration date has\n passed.\n\n- **invalid_issuer** - Certificate issuer name does not match the name of the\n issuer certificate in the chain.\n\n- **invalid_signature** - Certificate was not signed by its issuer certificate\n in the chain.\n\n- **name_not_permitted** - Invalid Subject Alternative Name extension.\n\n- **missing_basic_constraint** - Certificate, required to have the basic\n constraints extension, does not have a basic constraints extension.\n\n- **invalid_key_usage** - Certificate key is used in an invalid way according to\n the key-usage extension.\n\n- **\\{revoked, crl_reason()\\}** - Certificate has been revoked.\n\n- **invalid_validity_dates** - The validity section of the X.509 certificate(s)\n contains invalid date formats not matching the RFC.\n\n- **atom()** - Application-specific error reason that is to be checked by the\n `verify_fun`.","title":"public_key.pkix_path_validation/3","ref":"public_key.html#pkix_path_validation/3"},{"type":"function","doc":"Signs an 'OTPTBSCertificate'. Returns the corresponding DER-encoded certificate.","title":"public_key.pkix_sign/2","ref":"public_key.html#pkix_sign/2"},{"type":"function","doc":"Translates signature algorithm OID to Erlang digest and signature types.\n\nThe `AlgorithmId` is the signature OID from a certificate or a certificate\nrevocation list.","title":"public_key.pkix_sign_types/1","ref":"public_key.html#pkix_sign_types/1"},{"type":"function","doc":"Returns the X509 certificate subject id.","title":"public_key.pkix_subject_id/1","ref":"public_key.html#pkix_subject_id/1"},{"type":"function","doc":"Creates certificate configuration(s) consisting of certificate and its private\nkey plus CA certificate bundle, for a client and a server, intended to\nfacilitate automated testing of applications using X509-certificates, often\nthrough SSL/TLS. The test data can be used when you have control over both the\nclient and the server in a test scenario.\n\nWhen this function is called with a map containing client and server chain\nspecifications; it generates both a client and a server certificate chain where\nthe `cacerts` returned for the server contains the root cert the server should\ntrust and the intermediate certificates the server should present to connecting\nclients. The root cert the server should trust is the one used as root of the\nclient certificate chain. Vice versa applies to the `cacerts` returned for the\nclient. The root cert(s) can either be pre-generated with\n[pkix_test_root_cert/2 ](`pkix_test_root_cert/2`), or if options are specified;\nit is (they are) generated.\n\nWhen this function is called with a list of certificate options; it generates a\nconfiguration with just one node certificate where `cacerts` contains the root\ncert and the intermediate certs that should be presented to a peer. In this case\nthe same root cert must be used for all peers. This is useful in for example an\nErlang distributed cluster where any node, towards another node, acts either as\na server or as a client depending on who connects to whom. The generated\ncertificate contains a subject altname, which is not needed in a client\ncertificate, but makes the certificate useful for both roles.\n\nExplanation of the options used to customize certificates in the generated\nchains:\n\n- **\\{digest, digest_type()\\}** - Hash algorithm to be used for signing the\n certificate together with the key option. Defaults to sha that is sha1.\n\n- **\\{key, ec_params()| {rsa, Size:pos_integer(), Prime::pos_integer()} | private_key()\\}** - Parameters to be used to call\n public_key:generate_key/1, to generate a key, or an existing key. Defaults to\n generating an ECDSA key. Note this could fail if Erlang/OTP is compiled with a\n very old cryptolib.\n\n- **\\{validity, \\{From::erlang:timestamp(), To::erlang:timestamp()\\}\\}** - The\n validity period of the certificate.\n\n- **\\{extensions, \\[#'Extension'\\{\\}]\\}** - Extensions to include in the\n certificate.\n\n Default extensions included in CA certificates if not otherwise specified are:\n\n ```erlang\n [#'Extension'{extnID = ?'id-ce-keyUsage',\n extnValue = [keyCertSign, cRLSign],\n critical = false},\n #'Extension'{extnID = ?'id-ce-basicConstraints',\n extnValue = #'BasicConstraints'{cA = true},\n critical = true}]\n ```\n\n Default extensions included in the server peer cert if not otherwise specified\n are:\n\n ```erlang\n [#'Extension'{extnID = ?'id-ce-keyUsage',\n extnValue = [digitalSignature, keyAgreement],\n critical = false},\n #'Extension'{extnID = ?'id-ce-subjectAltName',\n extnValue = [{dNSName, Hostname}],\n critical = false}]\n ```\n\n Hostname is the result of calling net_adm:localhost() in the Erlang node where\n this function is called.\n\n> #### Note {: .info }\n>\n> Note that the generated certificates and keys does not provide a formally\n> correct PKIX-trust-chain and they cannot be used to achieve real security.\n> This function is provided for testing purposes only.","title":"public_key.pkix_test_data/1","ref":"public_key.html#pkix_test_data/1"},{"type":"function","doc":"Generates a root certificate that can be used in multiple calls to\n`pkix_test_data/1` when you want the same root certificate for several generated\ncertificates.","title":"public_key.pkix_test_root_cert/2","ref":"public_key.html#pkix_test_root_cert/2"},{"type":"function","doc":"Verifies PKIX x.509 certificate signature.","title":"public_key.pkix_verify/2","ref":"public_key.html#pkix_verify/2"},{"type":"function","doc":"","title":"public_key.pkix_verify_hostname/2","ref":"public_key.html#pkix_verify_hostname/2"},{"type":"function","doc":"This function checks that the _Presented Identifier_ (e.g hostname) in a peer\ncertificate is in agreement with at least one of the _Reference Identifier_ that\nthe client expects to be connected to.\n\nThe function is intended to be added as an extra client check of the\npeer certificate when performing\n[public_key:pkix_path_validation/3](`pkix_path_validation/3`)\n\nSee [RFC 6125](https://tools.ietf.org/html/rfc6125) for detailed information\nabout hostname verification. The\n[User's Guide](using_public_key.md#verify_hostname) and\n[code examples](using_public_key.md#verify_hostname_examples) describes this\nfunction more detailed.\n\nThe option funs are described here:\n\n- **`match_fun`**\n\n ```erlang\n fun(ReferenceId::ReferenceId() | FQDN::string(),\n PresentedId::{dNSName,string()} | {uniformResourceIdentifier,string() |\n {iPAddress,list(byte())} | {OtherId::atom()|oid(),term()}})\n ```\n\n This function replaces the default host name matching rules. The fun should\n return a boolean to tell if the Reference ID and Presented ID matches or not.\n The match fun can also return a third value, value, the atom `default`, if the\n default matching rules shall apply. This makes it possible to augment the\n tests with a special case:\n\n ```text\n fun(....) -> true; % My special case\n (_, _) -> default % all others falls back to the inherit tests\n end\n ```\n\n See `pkix_verify_hostname_match_fun/1` for a function that takes a protocol\n name as argument and returns a `fun/2` suitable for this option and\n [Re-defining the match operation](using_public_key.md#redefining_match_op) in\n the User's Guide for an example.\n\n > #### Note {: .info }\n >\n > Reference Id values given as binaries will be converted to strings, and ip\n > references may be given in string format that is \"10.0.1.1\" or\n > \"1234::5678:9012\" as well as on the format `t:inet:ip_address/0`\n\n- **`fail_callback`** - If a matching fails, there could be circumstances when\n the certificate should be accepted anyway. Think for example of a web browser\n where you choose to accept an outdated certificate. This option enables\n implementation of such an exception but for hostnames. This `fun/1` is called\n when no `ReferenceID` matches. The return value of the fun (a `t:boolean/0`)\n decides the outcome. If `true` the the certificate is accepted otherwise it is\n rejected. See\n [\"Pinning\" a Certificate](using_public_key.md#pinning-a-certificate) in the\n User's Guide.\n\n- **`fqdn_fun`** - This option augments the host name extraction from URIs and\n other Reference IDs. It could for example be a very special URI that is not\n standardised. The fun takes a Reference ID as argument and returns one of:\n\n - the hostname\n - the atom `default`: the default host name extract function will be used\n - the atom `undefined`: a host name could not be extracted. The\n pkix_verify_hostname/3 will return `false`.\n\n For an example, see\n [Hostname extraction](using_public_key.md#hostname_extraction) in the User's\n Guide.","title":"public_key.pkix_verify_hostname/3","ref":"public_key.html#pkix_verify_hostname/3"},{"type":"function","doc":"The return value of calling this function is intended to be used in the\n`match_fun` option in `pkix_verify_hostname/3`.\n\nThe returned fun augments the verify hostname matching according to the specific\nrules for the protocol in the argument.\n\n> #### Note {: .info }\n>\n> Currently supported https fun will allow wildcard certificate matching as\n> specified by the HTTP standard. Note that for instance LDAP have a different\n> set of wildcard matching rules. If you do not want to allow wildcard\n> certificates (recommended from a security perspective) or otherwise customize\n> the hostname match the default match function used by ssl application will be\n> sufficient.","title":"public_key.pkix_verify_hostname_match_fun/1","ref":"public_key.html#pkix_verify_hostname_match_fun/1"},{"type":"function","doc":"Generates a short hash of an issuer name. The hash is returned as a string\ncontaining eight hexadecimal digits.\n\nThe return value of this function is the same as the result of the commands\n`openssl crl -hash` and `openssl x509 -issuer_hash`, when passed the issuer name\nof a CRL or a certificate, respectively. This hash is used by the `c_rehash`\ntool to maintain a directory of symlinks to CRL files, in order to facilitate\nlooking up a CRL by its issuer name.","title":"public_key.short_name_hash/1","ref":"public_key.html#short_name_hash/1"},{"type":"function","doc":"","title":"public_key.sign/3","ref":"public_key.html#sign/3"},{"type":"function","doc":"Creates a digital signature.\n\nThe `Msg` is either the binary \"plain text\" data to be signed or it is the\nhashed value of \"plain text\", that is, the digest. The key, can besides a\nstandard key, be a map specifing a key algorithm and a fun that should handle\nthe signing. This may be used for customized signing with for instance hardware\nsecurity modules (HSM) or trusted platform modules (TPM).","title":"public_key.sign/4","ref":"public_key.html#sign/4"},{"type":"function","doc":"","title":"public_key.verify/4","ref":"public_key.html#verify/4"},{"type":"function","doc":"Verifies a digital signature.\n\nThe `Msg` is either the binary \"plain text\" data or it is the hashed value of\n\"plain text\", that is, the digest.","title":"public_key.verify/5","ref":"public_key.html#verify/5"},{"type":"type","doc":"ASN.1 type present in the Public Key applications ASN.1 specifications.","title":"public_key.asn1_type/0","ref":"public_key.html#t:asn1_type/0"},{"type":"type","doc":"The reason that a certifcate gets rejected by the certificate path validation.","title":"public_key.bad_cert_reason/0","ref":"public_key.html#t:bad_cert_reason/0"},{"type":"type","doc":"An encoded or decode certificate.","title":"public_key.cert/0","ref":"public_key.html#t:cert/0"},{"type":"type","doc":"A certificate is identified by its serial-number and Issuer Name.","title":"public_key.cert_id/0","ref":"public_key.html#t:cert_id/0"},{"type":"type","doc":"Options to customize generated test certificates","title":"public_key.cert_opt/0","ref":"public_key.html#t:cert_opt/0"},{"type":"type","doc":"Certificate customize options for diffrent parts of the certificate test chain.","title":"public_key.chain_opts/0","ref":"public_key.html#t:chain_opts/0"},{"type":"type","doc":"A record that can be used to provide the certificate on both the DER encoded and the OTP decode format.\n\nSuch a construct can be useful to avoid conversions and problems that can arise due to relaxed decoding rules.","title":"public_key.combined_cert/0","ref":"public_key.html#t:combined_cert/0"},{"type":"type","doc":"Configuration options for the generated certificate test chain.","title":"public_key.conf_opt/0","ref":"public_key.html#t:conf_opt/0"},{"type":"type","doc":"The reason that a certifcate has been revoked as define by RFC 5280.","title":"public_key.crl_reason/0","ref":"public_key.html#t:crl_reason/0"},{"type":"type","doc":"Can be provided together with a custom private key, that specifies a key fun, to\nprovide additional options understood by the fun.","title":"public_key.custom_key_opts/0","ref":"public_key.html#t:custom_key_opts/0"},{"type":"type","doc":"ASN.1 DER encoded entity.","title":"public_key.der_encoded/0","ref":"public_key.html#t:der_encoded/0"},{"type":"type","doc":"Hash function used to create a message digest","title":"public_key.digest_type/0","ref":"public_key.html#t:digest_type/0"},{"type":"type","doc":"ASN.1 defined private key format for the DSA algorithm.","title":"public_key.dsa_private_key/0","ref":"public_key.html#t:dsa_private_key/0"},{"type":"type","doc":"ASN.1 defined public key format for the DSA algorithm.","title":"public_key.dsa_public_key/0","ref":"public_key.html#t:dsa_public_key/0"},{"type":"type","doc":"ASN.1 defined public key format for the DSS algorithm (part of DSA key).","title":"public_key.dss_public_key/0","ref":"public_key.html#t:dss_public_key/0"},{"type":"type","doc":"ASN.1 defined private key format for the ECDSA algorithm.","title":"public_key.ecdsa_private_key/0","ref":"public_key.html#t:ecdsa_private_key/0"},{"type":"type","doc":"ASN.1 defined public key format for the ECDSA algorithm.","title":"public_key.ecdsa_public_key/0","ref":"public_key.html#t:ecdsa_public_key/0"},{"type":"type","doc":"ASN.1 defined private key format for the EDDSA algorithm, possible oids: ?'id-Ed25519' | ?'id-Ed448'","title":"public_key.eddsa_private_key/0","ref":"public_key.html#t:eddsa_private_key/0"},{"type":"type","doc":"ASN.1 defined public key format for the EDDSA algorithm, possible oids: ?'id-Ed25519' | ?'id-Ed448'","title":"public_key.eddsa_public_key/0","ref":"public_key.html#t:eddsa_public_key/0"},{"type":"type","doc":"The value of the issuer part of a certificate.","title":"public_key.issuer_name/0","ref":"public_key.html#t:issuer_name/0"},{"type":"type","doc":"ASN.1 defined parameters for public key algorithms.","title":"public_key.key_params/0","ref":"public_key.html#t:key_params/0"},{"type":"type","doc":"Object identifier, a tuple of integers as generated by the `ASN.1` compiler.","title":"public_key.oid/0","ref":"public_key.html#t:oid/0"},{"type":"type","doc":"Possible `Ciphers` are \"RC2-CBC\" | \"DES-CBC\" | \"DES-EDE3-CBC\" `Salt` could be generated with\n[`crypto:strong_rand_bytes(8)`](`crypto:strong_rand_bytes/1`).","title":"public_key.pem_entry/0","ref":"public_key.html#t:pem_entry/0"},{"type":"type","doc":"ASN.1 type that can be found in PEM files that can be decode by the public_key application.","title":"public_key.pki_asn1_type/0","ref":"public_key.html#t:pki_asn1_type/0"},{"type":"type","doc":"Certificate policy information.","title":"public_key.policy_node/0","ref":"public_key.html#t:policy_node/0"},{"type":"type","doc":"Supported private keys","title":"public_key.private_key/0","ref":"public_key.html#t:private_key/0"},{"type":"type","doc":"Supported public keys","title":"public_key.public_key/0","ref":"public_key.html#t:public_key/0"},{"type":"type","doc":"Information a certificates public key.\n\nPossible oids: ?'rsaEncryption' | ?'id-RSASSA-PSS' | ?'id-ecPublicKey' | ?'id-Ed25519' | ?'id-Ed448' | ?'id-dsa'","title":"public_key.public_key_info/0","ref":"public_key.html#t:public_key_info/0"},{"type":"type","doc":"ASN.1 defined private key format plain RSA algorithm or customization fun.","title":"public_key.rsa_private_key/0","ref":"public_key.html#t:rsa_private_key/0"},{"type":"type","doc":"ASN.1 defined private key format the RSSASSA-PSS algorithm or customization fun.","title":"public_key.rsa_pss_private_key/0","ref":"public_key.html#t:rsa_pss_private_key/0"},{"type":"type","doc":"ASN.1 defined public key format for the RSSASSA-PSS algorithm.","title":"public_key.rsa_pss_public_key/0","ref":"public_key.html#t:rsa_pss_public_key/0"},{"type":"type","doc":"ASN.1 defined public key format for plain RSA algorithm.","title":"public_key.rsa_public_key/0","ref":"public_key.html#t:rsa_public_key/0"},{"type":"extras","doc":"\n# Public_Key Application\n\nThe Public Key application deals with public-key related file formats,\ndigital signatures, and [X-509\ncertificates](http://www.ietf.org/rfc/rfc5280.txt). It handles\nvalidation of certificate paths and certificate revocation lists\n(CRLs) and other functions for handling of certificates, keys and\nCRLs. It is a library application that does not read or write files,\nit expects or returns file contents or partial file contents as\nbinaries. Except for the functions `public-key:cacerts_load/0`,\n`public-key:cacerts_load/1`, and `public-key:cacerts_get/0`\nthat reads files.","title":"Public_Key Application","ref":"public_key_app.html"},{"type":"extras","doc":"- Supports [RFC 5280 ](http://www.ietf.org/rfc/rfc5280.txt)\\- Internet X.509\n Public-Key Infrastructure Certificate and Certificate Revocation List (CRL)\n Profile. Certificate policies supported since OTP-26.2\n- Supports [PKCS-1 ](http://www.ietf.org/rfc/rfc3447.txt)\\- RSA Cryptography\n Standard\n- Supports\n [DSS](http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf) \\-\n Digital Signature Standard (DSA - Digital Signature Algorithm)\n- Supports\n [PKCS-3 ](https://web.archive.org/web/20170417091930/https://www.emc.com/emc-plus/rsa-labs/standards-initiatives/pkcs-3-diffie-hellman-key-agreement-standar.htm)\\-\n Diffie-Hellman Key Agreement Standard\n- Supports [PKCS-5](http://www.ietf.org/rfc/rfc2898.txt) \\- Password-Based\n Cryptography Standard\n- Supports [AES ](http://www.ietf.org/rfc/fc3565.txt)\\- Use of the Advanced\n Encryption Standard (AES) Algorithm in Cryptographic Message Syntax (CMS)\n- Supports [PKCS-8](http://www.ietf.org/rfc/rfc5208.txt) \\- Private-Key\n Information Syntax Standard\n- Supports [PKCS-10](http://www.ietf.org/rfc/rfc5967.txt) \\- Certification\n Request Syntax Standard","title":"Supported PKIX functionality - Public_Key Application","ref":"public_key_app.html#supported-pkix-functionality"},{"type":"extras","doc":"The `public_key` application uses the Crypto application to perform\ncryptographic operations and the ASN-1 application to handle PKIX-ASN-1\nspecifications, hence these applications must be loaded for the `public_key`\napplication to work. In an embedded environment this means they must be started\nwith `application:start/[1,2]` before the `public_key` application is started.","title":"Dependencies - Public_Key Application","ref":"public_key_app.html#dependencies"},{"type":"extras","doc":"The `public_key` application is a library application and does not use the error\nlogger. The functions will either succeed or fail with a runtime error.","title":"Error Logger and Event Handlers - Public_Key Application","ref":"public_key_app.html#error-logger-and-event-handlers"},{"type":"extras","doc":"`m:application`","title":"See Also - Public_Key Application","ref":"public_key_app.html#see-also"},{"type":"extras","doc":"\n# Public_Key Release Notes","title":"Public_Key Release Notes","ref":"notes.html"},{"type":"extras","doc":"","title":"Public_Key 1.16.3 - Public_Key Release Notes","ref":"notes.html#public_key-1-16-3"},{"type":"extras","doc":"- Introduction of verify_fun/4 unfortunately introduced an argument switch for some specific path validation errors so that verify_fun/3 could under these circumstances be called with a DER cert instead of a decod cert, also in this situation the verify_fun/4 would have the certificates in reverse order.\n\n Own Id: OTP-19245 Aux Id: Gh-8832","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Do not hide crypto badarg reason, this error handling enhancement facilitates debugging. These kind of runtime errors are not documented and should never be relied on for matching, they are intended for catching input errors early.\n\n Own Id: OTP-19238","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.16.2 - Public_Key Release Notes","ref":"notes.html#public_key-1-16-2"},{"type":"extras","doc":"- For completeness handle rsa_pss implicit default value, although this will probably not be commonly used as it provides very weak security.\n\n Own Id: OTP-19179\n\n- The `public_key:cacerts_load()` function could in some error cases return `undefined` instead of `{error, Reason}`.\n\n Own Id: OTP-19183 Aux Id: [GH-8604]\n\n- Added support for DragonFly.\n\n Own Id: OTP-19191 Aux Id: [PR-8703]\n\n[GH-8604]: https://github.com/erlang/otp/issues/8604\n[PR-8703]: https://github.com/erlang/otp/pull/8703","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Deprecation of RSA encryption functions has been reverted, as there still exists legitimate use cases with other padding modes than PKCS-1.\n \n While use PCKS-1 padding with some versions of cryptolib could be considered secure, we still recommend using other algorithms that are less sensitive to oracle attacks.\n\n Own Id: OTP-19163\n\n- It is now possible to use a verification fun of arity 4, giving the user fun access to both encoded and decoded versions of the certificate. This is desirable as a workaround for encoding errors preventing re-encoding from being reliable. This also saves some work load if the encoded version is needed.\n \n Note that calling `public_key:pkix_path_validation/3` with only decoded certs is not recommended, due to the decoding workarounds, although it will work as long as the workarounds are not needed.\n \n If the decoded version is needed before thecall to `m:public_key` it is recommend to use the combined_cert- type to avoid double decoding. Note that the path validation algorithm itself always needs both the encoded and decoded versions of the certs.\n \n The ssl implementation will now benefit from using this function instead of emulating the verify_fun/4.\n\n Own Id: OTP-19169","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.16.1 - Public_Key Release Notes","ref":"notes.html#public_key-1-16-1"},{"type":"extras","doc":"- Fix bug in dnsName constraint check, could cause valid cert to be considered bad\n during path validation.\n\n Own Id: OTP-19100 Aux Id: [GH-8482], [PR-8508]\n\n[GH-8482]: https://github.com/erlang/otp/issues/8482\n[PR-8508]: https://github.com/erlang/otp/pull/8508","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Public_Key 1.16 - Public_Key Release Notes","ref":"notes.html#public_key-1-16"},{"type":"extras","doc":"- The `ssl` client can negotiate and handle certificate status request (OCSP stapling support on the client side).\n \n Thanks to voltone for interop testing and related discussions.\n\n Own Id: OTP-18606 Aux Id: OTP-16875,OTP-16448\n\n- The exception reason when `public_key:cacerts_get/0` failed has been improved.\n\n Own Id: OTP-18609 Aux Id: [GH-7295], [PR-7302]\n\n- Key customization support has been extended to allow flexibility for implementers of for instance hardware security modules (HSM) or trusted platform modules (TPM).\n\n Own Id: OTP-18876 Aux Id: [PR-7898], [PR-7475]\n\n- The documentation has been migrated to use Markdown and ExDoc.\n\n Own Id: OTP-18955 Aux Id: [PR-8026]\n\n- The existing function `ssl:key_exporter_materials/4` is now documented and supported.\n\n *** POTENTIAL INCOMPATIBILITY ***\n\n Own Id: OTP-19016 Aux Id: [PR-8233]\n\n- Due to another attack on PKCS #1 v1.5 padding, known as the Marvin attack, about which we were alerted by Hubert Kario from Red Hat. You can find more details about the attack at\n https://people.redhat.com/~hkario/marvin/\n Functions that may be vulnerable are now deprecated. \n \n Note that you might mitigate the problem \n by using appropriate versions of OpenSSL together with our software, but we recommend not using them at all. \n \n Also avoid using TLS versions prior to TLS-1.2 (not supported by default) and\n do not enable RSA-key exchange cipher suites (not supported by default).\n\n *** POTENTIAL INCOMPATIBILITY ***\n\n Own Id: OTP-19075\n\n[GH-7295]: https://github.com/erlang/otp/issues/7295\n[PR-7302]: https://github.com/erlang/otp/pull/7302\n[PR-7898]: https://github.com/erlang/otp/pull/7898\n[PR-7475]: https://github.com/erlang/otp/pull/7475\n[PR-8026]: https://github.com/erlang/otp/pull/8026\n[PR-8233]: https://github.com/erlang/otp/pull/8233","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.15.1.3 - Public_Key Release Notes","ref":"notes.html#public_key-1-15-1-3"},{"type":"extras","doc":"* Do not hide crypto badarg reason, this error handling enhancement facilitates debugging. These kind of runtime errors are not documented and should never be relied on for matching, they are intended for catching input errors early.\n\n Own Id: OTP-19238 Aux Id: PR-8831","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.15.1.2 - Public_Key Release Notes","ref":"notes.html#public_key-1-15-1-2"},{"type":"extras","doc":"* For completeness handle rsa_pss implicit default value, although this will probably not be commonly used as it provides very weak security.\n\n Own Id: OTP-19179","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Public_Key 1.15.1.1 - Public_Key Release Notes","ref":"notes.html#public_key-1-15-1-1"},{"type":"extras","doc":"* Fix bug in dnsName constraint check, could cause valid cert to be considered bad during path validation.\n\n Own Id: OTP-19100 Aux Id: GH-8482, PR-8508","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Public_Key 1.15.1 - Public_Key Release Notes","ref":"notes.html#public_key-1-15-1"},{"type":"extras","doc":"* Hostname prefix with X number of dots should not be accepted.\n\n Own Id: OTP-18935 Aux Id: GH-8021","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Public_Key 1.15 - Public_Key Release Notes","ref":"notes.html#public_key-1-15"},{"type":"extras","doc":"- ssl application will validate id-kp-serverAuth and id-kp-clientAuth extended\n key usage only in end entity certificates. public_key application will\n disallow \"anyExtendedKeyUsage\" for CA certificates that includes the extended\n key usage extension and marks it critical.\n\n Own Id: OTP-18739\n\n- Modernize ECC handling so that crypto FIPS support works as expected.\n\n Own Id: OTP-18854","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Support certificate policies in path_validation - as described by RFC 5280.\n\n Own Id: OTP-17844 Aux Id: ERIERL-738\n\n- Add more search paths for cacerts on Illumos.\n\n Own Id: OTP-18814 Aux Id: PR-7435\n\n- Make it possible to handle invalid date formats in the verify_fun for\n pkix_path_validation/3\n\n Own Id: OTP-18867 Aux Id: GH-7515","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.14.1 - Public_Key Release Notes","ref":"notes.html#public_key-1-14-1"},{"type":"extras","doc":"- Country name comparison shall be case insensitive\n\n Own Id: OTP-18718 Aux Id: GH-7546\n\n- Add check to disallow duplicate certs in a path\n\n Own Id: OTP-18723 Aux Id: GH-6394","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Public_Key 1.14 - Public_Key Release Notes","ref":"notes.html#public_key-1-14"},{"type":"extras","doc":"- Handling of `on_load` modules during boot has been improved by adding an extra\n step in the boot order for embedded mode that runs all `on_load` handlers,\n instead of relying on explicit invocation of them, later, when the kernel\n supervision tree starts.\n\n This is mostly a code improvement and OTP internal simplification to avoid\n future bugs and to simplify code maintenance.\n\n Own Id: OTP-18447","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.13.3.4 - Public_Key Release Notes","ref":"notes.html#public_key-1-13-3-4"},{"type":"extras","doc":"* Do not hide crypto badarg reason, this error handling enhancement facilitates debugging. These kind of runtime errors are not documented and should never be relied on for matching, they are intended for catching input errors early.\n\n Own Id: OTP-19238 Aux Id: PR-8831","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.13.3.3 - Public_Key Release Notes","ref":"notes.html#public_key-1-13-3-3"},{"type":"extras","doc":"* For completeness handle rsa_pss implicit default value, although this will probably not be commonly used as it provides very weak security.\n\n Own Id: OTP-19179","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Public_Key 1.13.3.2 - Public_Key Release Notes","ref":"notes.html#public_key-1-13-3-2"},{"type":"extras","doc":"- ssl application will validate id-kp-serverAuth and id-kp-clientAuth extended\n key usage only in end entity certificates. public_key application will\n disallow \"anyExtendedKeyUsage\" for CA certificates that includes the extended\n key usage extension and marks it critical.\n\n Own Id: OTP-18739","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Public_Key 1.13.3.1 - Public_Key Release Notes","ref":"notes.html#public_key-1-13-3-1"},{"type":"extras","doc":"- Country name comparison shall be case insensitive\n\n Own Id: OTP-18718 Aux Id: GH-7546","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Public_Key 1.13.3 - Public_Key Release Notes","ref":"notes.html#public_key-1-13-3"},{"type":"extras","doc":"- As different solutions of verifying certificate revocation exists move the\n decode of 'CRLDistributionPoints' so that it will only be decode. When it is\n actually used in the verification process. This would enable interoperability\n with systems that use certificates with an invalid empty CRLDistributionPoints\n extension that they want to ignore and make verification by other means.\n\n Own Id: OTP-18316 Aux Id: GH-6402, PR-6883\n\n- public_key:pkix_path_validation validates certificates expiring after 2050\n\n Own Id: OTP-18356 Aux Id: GH-6403\n\n- Do not leave exit message in message queue after calling `cacerts_load()` on\n MacOS.\n\n Own Id: OTP-18392 Aux Id: GH-6656","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Replace size/1 with either tuple_size/1 or byte_size/1\n\n The [`size/1`](`size/1`) BIF is not optimized by the JIT, and its use can\n result in worse types for Dialyzer.\n\n When one knows that the value being tested must be a tuple,\n [`tuple_size/1`](`tuple_size/1`) should always be preferred.\n\n When one knows that the value being tested must be a binary,\n [`byte_size/1`](`byte_size/1`) should be preferred. However,\n [`byte_size/1`](`byte_size/1`) also accepts a bitstring (rounding up size to a\n whole number of bytes), so one must make sure that the call to `byte_size/` is\n preceded by a call to [`is_binary/1`](`is_binary/1`) to ensure that bitstrings\n are rejected. Note that the compiler removes redundant calls to\n [`is_binary/1`](`is_binary/1`), so if one is not sure whether previous code\n had made sure that the argument is a binary, it does not harm to add an\n [`is_binary/1`](`is_binary/1`) test immediately before the call to\n [`byte_size/1`](`byte_size/1`).\n\n Own Id: OTP-18432 Aux Id:\n GH-6672,PR-6793,PR-6784,PR-6787,PR-6785,PR-6682,PR-6800,PR-6797,PR-6798,PR-6799,PR-6796,PR-6813,PR-6671,PR-6673,PR-6684,PR-6694,GH-6677,PR-6696,PR-6670,PR-6674","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.13.2 - Public_Key Release Notes","ref":"notes.html#public_key-1-13-2"},{"type":"extras","doc":"- Disregard LDAP URIs when HTTP URIs are expected.\n\n Own Id: OTP-18333 Aux Id: GH-6363","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Public_Key 1.13.1 - Public_Key Release Notes","ref":"notes.html#public_key-1-13-1"},{"type":"extras","doc":"- Support more Linux distributions in cacerts_load/0.\n\n Own Id: OTP-18154 Aux Id: PR-6002\n\n- Correct asn1 typenames available in type pki_asn1_type()\n\n Own Id: OTP-18189 Aux Id: ERIERL-829\n\n- Sign/verify does now behave as in OTP-24 and earlier for eddsa.\n\n Own Id: OTP-18205 Aux Id: GH-6219","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Public_Key 1.13 - Public_Key Release Notes","ref":"notes.html#public_key-1-13"},{"type":"extras","doc":"- Added functions to retrieve OS provided CA-certs.\n\n Own Id: OTP-17798 Aux Id: GH-5760\n\n- Allow key file passwords to be input as a single binary, that is we change the\n data type to be the more for the purpose logical data type iodata() instead of\n string().\n\n Own Id: OTP-17890\n\n- The deprecated public_key functions ssh_decode/2, ssh_encode/2,\n ssh_hostkey_fingerprint/1 and ssh_hostkey_fingerprint/2 are removed.\n\n They are replaced by ssh_file:decode/2, ssh_file:encode/2,\n ssh:hostkey_fingerprint/1 and ssh:hostkey_fingerprint/2 respectively.\n\n Note that the decode/2 and encode/2 are not exact replacement functions, some\n minor changes may be needed. Se the manual for more information.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17921","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.12.0.2 - Public_Key Release Notes","ref":"notes.html#public_key-1-12-0-2"},{"type":"extras","doc":"- Country name comparison shall be case insensitive\n\n Own Id: OTP-18718 Aux Id: GH-7546","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Public_Key 1.12.0.1 - Public_Key Release Notes","ref":"notes.html#public_key-1-12-0-1"},{"type":"extras","doc":"- Correct asn1 typenames available in type pki_asn1_type()\n\n Own Id: OTP-18189 Aux Id: ERIERL-829","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Public_Key 1.12 - Public_Key Release Notes","ref":"notes.html#public_key-1-12"},{"type":"extras","doc":"- Support password fun for protected keyfiles in ssl:connect function.\n\n Own Id: OTP-17816 Aux Id: PR-5607","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.11.3 - Public_Key Release Notes","ref":"notes.html#public_key-1-11-3"},{"type":"extras","doc":"- Avoid re-encoding of decoded certificates. This could cause unexpected\n failures as some subtle encoding errors can be tolerated when decoding but\n hence creating another sequence of bytes if the decoded value is re-encoded.\n\n Own Id: OTP-17657","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Public_Key 1.11.2 - Public_Key Release Notes","ref":"notes.html#public_key-1-11-2"},{"type":"extras","doc":"- public_key:pkix_sign/2 now honors the salt length from the provided input\n parameters. Earlier this could result in incorrect signatures if not using\n recommended defaults.\n\n Own Id: OTP-17534 Aux Id: GH-5054, PR-5057","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- When decoding an 'ECPrivateKey' unwrap the private key. For more precise\n information see RFC 8410, section 7.\n\n Own Id: OTP-17609 Aux Id: GH-5157, GH-5156","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.11.1 - Public_Key Release Notes","ref":"notes.html#public_key-1-11-1"},{"type":"extras","doc":"- Handle cross-signed root certificates when old root expired as reported in\n GH-4877.\n\n Own Id: OTP-17475 Aux Id: GH-4877","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Public_Key 1.11 - Public_Key Release Notes","ref":"notes.html#public_key-1-11"},{"type":"extras","doc":"- TLS connections now support EdDSA certificates.\n\n Own Id: OTP-17142 Aux Id: PR-4756, GH-4637, GH-4650\n\n- The functions public_key:ssh_encode/2, public_key:ssh_decode/2,\n public_key:ssh_hostkey_fingerprint/1 and public_key:ssh_hostkey_fingerprint/2\n are deprecated.\n\n Replacement functions are available in SSH, see the\n [Deprecations](`e:general_info:deprecations.md#otp-24`) chapter in the\n Erlang/OTP documentation.\n\n Own Id: OTP-17352\n\n- Enhance documentation and logging of certificate handling.\n\n Own Id: OTP-17384 Aux Id: GH-4800","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.10.0.1 - Public_Key Release Notes","ref":"notes.html#public_key-1-10-0-1"},{"type":"extras","doc":"- Handle cross-signed root certificates when old root expired as reported in\n GH-4877.\n\n Own Id: OTP-17475 Aux Id: GH-4877","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Public_Key 1.10 - Public_Key Release Notes","ref":"notes.html#public_key-1-10"},{"type":"extras","doc":"- Fixed case insensitive hostname check.\n\n Own Id: OTP-17242 Aux Id: GH-4500","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add sanity check of trusted anchor certificate expiration to\n pkix_path_validation/3. Although the anchor is considered a trusted input this\n sanity check does provide extra security for the users of the public_key\n application as this property needs to be checked at time of usage and fits\n very well with the other checks performed here.\n\n Own Id: OTP-16907\n\n- Adjust generation of test certificates to conform to RFC 5280 rules for\n formatting of the certificates validity\n\n Own Id: OTP-17111","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.9.2 - Public_Key Release Notes","ref":"notes.html#public_key-1-9-2"},{"type":"extras","doc":"- Corrected dialyzer spec for pkix_path_validation/3\n\n Own Id: OTP-17069","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.9.1 - Public_Key Release Notes","ref":"notes.html#public_key-1-9-1"},{"type":"extras","doc":"- Fix the issue that pem_decode will crash with an invalid input.\n\n Own Id: OTP-16902 Aux Id: ERIERL-534","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Public_Key 1.9 - Public_Key Release Notes","ref":"notes.html#public_key-1-9"},{"type":"extras","doc":"- Fixed an insignificant whitespace issue when decoding PEM file.\n\n Own Id: OTP-16801 Aux Id: ERL-1309","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Experimental OCSP client support.\n\n Own Id: OTP-16448\n\n- Use user returned path validation error for selfsigned cert. It allows users\n of the ssl application to customize the generated TLS alert, within the range\n of defined alerts.\n\n Own Id: OTP-16592\n\n- add API function to retrieve the subject-ID of an X509 certificate\n\n Own Id: OTP-16705","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.8 - Public_Key Release Notes","ref":"notes.html#public_key-1-8"},{"type":"extras","doc":"- Added support for RSA-PSS signature schemes\n\n Own Id: OTP-15247\n\n- Calls of deprecated functions in the\n [Old Crypto API](`e:crypto:new_api.md#the-old-api`) are replaced by calls of\n their [substitutions](`e:crypto:new_api.md#the-new-api`).\n\n Own Id: OTP-16346","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.7.2 - Public_Key Release Notes","ref":"notes.html#public_key-1-7-2"},{"type":"extras","doc":"- Add support for key exchange with Edward curves and PSS-RSA padding in\n signature verification.\n\n Own Id: OTP-16528","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.7.1 - Public_Key Release Notes","ref":"notes.html#public_key-1-7-1"},{"type":"extras","doc":"- Corrected CRL handling which could cause CRL verification to fail. This could\n happen when the CRL distribution point explicitly specifies the CRL issuer,\n that is not using the fallback.\n\n Own Id: OTP-16156 Aux Id: ERL-1030","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Public_Key 1.7 - Public_Key Release Notes","ref":"notes.html#public_key-1-7"},{"type":"extras","doc":"- Support Password based encryption with AES\n\n Own Id: OTP-15870 Aux Id: ERL-952","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Change dialyzer spec to avoid confusion\n\n Own Id: OTP-15843 Aux Id: ERL-915","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.6.7 - Public_Key Release Notes","ref":"notes.html#public_key-1-6-7"},{"type":"extras","doc":"- RSA options passed to crypto for encrypt and decrypt with public or private\n key.\n\n Own Id: OTP-15754 Aux Id: ERL-878\n\n- Fix dialyzer warnings caused by a faulty type specification for digest_type().\n\n This change updates digest_type() and the functions operating with this\n argument type to accept both 'sha1' and 'sha' as digest_type().\n\n Own Id: OTP-15776","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add possibility to read PEM files encrypted with old PEM encryption using\n AES-256\n\n Own Id: OTP-13726\n\n- Relax decoding of certificates to so that \"harmless\" third party encoding\n errors may be accepted but not created by the public_key application. This\n adds acceptance of using an incorrect three character country code, the PKIX\n standard use two character country codes. It is also accepted that the country\n code is utf8 encoded but the specification says it should be ASCII.\n\n Own Id: OTP-15687 Aux Id: PR-2162","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.6.6.1 - Public_Key Release Notes","ref":"notes.html#public_key-1-6-6-1"},{"type":"extras","doc":"- Support Password based encryption with AES\n\n Own Id: OTP-15870 Aux Id: ERL-952","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Public_Key 1.6.6 - Public_Key Release Notes","ref":"notes.html#public_key-1-6-6"},{"type":"extras","doc":"- Back port of bug fix ERL-893 from OTP-22 and document enhancements that will\n solve dialyzer warnings for users of the ssl application.\n\n This change also affects public_key, eldap (and inet doc).\n\n Own Id: OTP-15785 Aux Id: ERL-929, ERL-893, PR-2215","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.6.5 - Public_Key Release Notes","ref":"notes.html#public_key-1-6-5"},{"type":"extras","doc":"- Add export of dialyzer type\n\n Own Id: OTP-15624","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.6.4 - Public_Key Release Notes","ref":"notes.html#public_key-1-6-4"},{"type":"extras","doc":"- Added ed25519 and ed448 sign/verify.\n\n Requires OpenSSL 1.1.1 or higher as cryptolib under the OTP application\n `crypto`.\n\n Own Id: OTP-15419 Aux Id: OTP-15094","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.6.3 - Public_Key Release Notes","ref":"notes.html#public_key-1-6-3"},{"type":"extras","doc":"- Add DSA SHA2 oids in public_keys ASN1-spec and public_key:pkix_sign_types/1\n\n Own Id: OTP-15367","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Public_Key 1.6.2 - Public_Key Release Notes","ref":"notes.html#public_key-1-6-2"},{"type":"extras","doc":"- Removed `#DSAPrivateKey{}` as acceptable input to `public_key:verify/5`.\n\n Own Id: OTP-15284","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The typing in the CRYPTO and PUBLIC_KEY applications are reworked and a few\n mistakes are corrected.\n\n The documentation is now generated from the typing and some clarifications are\n made.\n\n A new chapter on Algorithm Details such as key sizes and availability is added\n to the CRYPTO User's Guide.\n\n Own Id: OTP-15134","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.6.1 - Public_Key Release Notes","ref":"notes.html#public_key-1-6-1"},{"type":"extras","doc":"- Some of the keylengths in the newly generated moduli file in public_key are\n not universally supported. This could cause the SSH key exchange\n diffie-hellman-group-exchange-sha\\* to fail.\n\n Those keylengths are now removed.\n\n Own Id: OTP-15151 Aux Id: OTP-15113","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Public_Key 1.6 - Public_Key Release Notes","ref":"notes.html#public_key-1-6"},{"type":"extras","doc":"- Update calls to the base64 module to conform to that module's type\n specifications.\n\n Own Id: OTP-14788 Aux Id: OTP-14624","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Use uri_string module instead of http_uri.\n\n Own Id: OTP-14902\n\n- A new function - `public_key:pkix_verify_hostname_match_fun/1` \\- returns a\n fun to be given as option `match_fun` to `public_key:pkix_verify_hostname/3`\n or via ssl.\n\n The fun makes the verify hostname matching according to the specific rules for\n the protocol in the argument. Presently only `https` is supported.\n\n Own Id: OTP-14962 Aux Id: ERL-542, OTP-15102\n\n- Complete PKCS-8 encoding support and enhance the decoding of 'PrivateKeyInfo'\n to conform to the rest of Erlang public_key API.\n\n Own Id: OTP-15093\n\n- A new moduli file is generated. This file is used for the recommended\n `diffie-hellman-group-exchange-sha256` key exchange algorithm in SSH.\n\n Own Id: OTP-15113","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.5.2 - Public_Key Release Notes","ref":"notes.html#public_key-1-5-2"},{"type":"extras","doc":"- Fixed a bug in `public_key:ssh_encode/2` that made it possible to erroneously\n encode e.g. an RSA key with another type e.g. ECDSA in the resulting binary.\n\n Own Id: OTP-14570 Aux Id: ERIERL-52, OTP-14676\n\n- Corrected handling of parameterized EC keys in public_key:generate_key/1 so\n that it will work as expected instead of causing a runtime error in crypto.\n\n Own Id: OTP-14620","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Public_Key 1.5.1 - Public_Key Release Notes","ref":"notes.html#public_key-1-5-1"},{"type":"extras","doc":"- Hostname verification: Add handling of the general name `iPAddress` in\n certificate's subject alternative name extension (`subjAltName`).\n\n Own Id: OTP-14653\n\n- Correct key handling in pkix_test_data/1 and use a generic example mail\n address instead of an existing one.\n\n Own Id: OTP-14766","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.5 - Public_Key Release Notes","ref":"notes.html#public_key-1-5"},{"type":"extras","doc":"- public_key now handles elliptic curve parameters in a consistent way so that\n decoded ECDSA keys can be correctly re-encoded.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-14621 Aux Id: ERL-480, ERL-481","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Extend crypto:sign, crypto:verify, public_key:sign and public_key:verify with:\n\n \\* support for RSASSA-PS padding for signatures and for saltlength setting \n \\* X9.31 RSA padding. \n \\* sha, sha224, sha256, sha384, and sha512 for dss signatures as mentioned in\n NIST SP 800-57 Part 1. \n \\* ripemd160 to be used for RSA signatures.\n\n This is a manual merge of half of the pull request 838 by potatosalad from\n Sept 2015.\n\n Own Id: OTP-13704 Aux Id: PR838\n\n- Add API function pkix_test_data/1 for facilitating automated testing. This is\n useful for applications that perform X509-certifcate path validation of so\n called certificate chains, such as TLS.\n\n Own Id: OTP-14181\n\n- Improved error propagation and reports\n\n Own Id: OTP-14236\n\n- RSAPrivateKey version is set to 'two-prime' instead of using the underlying\n enumeration value directly.\n\n Own Id: OTP-14534\n\n- Deprecated function `crypto:rand_uniform/2` is replaced by `rand:uniform/1`.\n\n Own Id: OTP-14608","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.4.1 - Public_Key Release Notes","ref":"notes.html#public_key-1-4-1"},{"type":"extras","doc":"- Bug for `public_key:generate_key({namedCurve,OID})` fixed.\n\n Own Id: OTP-14258","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Modernized internal representation used for crl validation by use of maps.\n\n Own Id: OTP-14111\n\n- Support EC key in pkix_sign/2\n\n Own Id: OTP-14294","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.4 - Public_Key Release Notes","ref":"notes.html#public_key-1-4"},{"type":"extras","doc":"- New function `pkix_verify_hostname/2,3` Implements certificate hostname\n checking. See the manual and RFC 6125.\n\n Own Id: OTP-13009\n\n- The ssh host key fingerprint generation now also takes a list of algorithms\n and returns a list of corresponding fingerprints. See\n `public_key:ssh_hostkey_fingerprint/2` and the option `silently_accept_hosts`\n in `ssh:connect`.\n\n Own Id: OTP-14223","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.3 - Public_Key Release Notes","ref":"notes.html#public_key-1-3"},{"type":"extras","doc":"- New function `public_key:ssh_hostkey_fingerprint/1,2` to calculate the SSH\n host key fingerprint string.\n\n Own Id: OTP-13888 Aux Id: OTP-13887","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.2 - Public_Key Release Notes","ref":"notes.html#public_key-1-2"},{"type":"extras","doc":"- The ASN-1 type GeneralName can have more values, then the most common\n directory name, the code now handles this.\n\n Own Id: OTP-13554","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Handle PEM encoded EC public keys\n\n Own Id: OTP-13408","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.1.1 - Public_Key Release Notes","ref":"notes.html#public_key-1-1-1"},{"type":"extras","doc":"- An encapsulated PEM header shall be followed by a blank line\n\n Own Id: OTP-13381 Aux Id: seq13070","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Public_Key 1.1 - Public_Key Release Notes","ref":"notes.html#public_key-1-1"},{"type":"extras","doc":"- The 'ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384' and 'ecdsa-sha2-nistp521'\n signature algorithms for ssh are implemented. See RFC 5656.\n\n Own Id: OTP-12936\n\n- There is now a file (public_key/priv/moduli) which lists\n size-generator-modulus triples. The purpose is to give servers the possibility\n to select the crypto primes randomly among a list of pregenerated triples.\n This reduces the risk for some attacks on diffie-hellman negotiation.\n\n See the reference manual for public_key:dh_gex_group/4 where the handling of\n this is described.\n\n The ssh server (ssh:daemon) uses this.\n\n Own Id: OTP-13054 Aux Id: OTP-13052\n\n- Add different upper bounds for different string types as suggested by comment\n in PKIX1Explicit88.\n\n Own Id: OTP-13132","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.0.1 - Public_Key Release Notes","ref":"notes.html#public_key-1-0-1"},{"type":"extras","doc":"- Document enhancements\n\n Own Id: OTP-12986","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 1.0 - Public_Key Release Notes","ref":"notes.html#public_key-1-0"},{"type":"extras","doc":"- public_key: Remove legacy switch compact_bit_string\n\n E.i bitstrings will not be decode as \\{Unused, Binary\\}, they are now Erlang\n bitstrings.\n\n Also the compact_bit_string implies the legacy_erlang_types switch So removing\n the switch will also make OCTET STRING values be represented as binaries.\n\n Undecoded open type will now be wrapped in a asn1_OPENTYPE tuple.\n\n This will change some values in records returned by the public_key API making\n this change a potentiall incompatibility.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-12110","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 0.23 - Public_Key Release Notes","ref":"notes.html#public_key-0-23"},{"type":"extras","doc":"- Improve/extend support for CRL handling.\n\n Own Id: OTP-12547 Aux Id: OTP-10362","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 0.22.1 - Public_Key Release Notes","ref":"notes.html#public_key-0-22-1"},{"type":"extras","doc":"- Added missing encoding support for PBES2, and also completed support for PBES1\n that was incomplete.\n\n Own Id: OTP-11915","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Public_Key 0.22 - Public_Key Release Notes","ref":"notes.html#public_key-0-22"},{"type":"extras","doc":"- Fix incorrect dialyzer spec and types, also enhance documentation.\n\n Thanks to Ayaz Tuncer.\n\n Own Id: OTP-11627\n\n- Application upgrade (appup) files are corrected for the following\n applications:\n\n `asn1, common_test, compiler, crypto, debugger, dialyzer, edoc, eldap, erl_docgen, et, eunit, gs, hipe, inets, observer, odbc, os_mon, otp_mibs, parsetools, percept, public_key, reltool, runtime_tools, ssh, syntax_tools, test_server, tools, typer, webtool, wx, xmerl`\n\n A new test utility for testing appup files is added to test_server. This is\n now used by most applications in OTP.\n\n (Thanks to Tobias Schlager)\n\n Own Id: OTP-11744","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Moved elliptic curve definition from the crypto NIF/OpenSSL into Erlang code,\n adds the RFC-5639 brainpool curves and makes TLS use them (RFC-7027).\n\n Thanks to Andreas Schultz\n\n Own Id: OTP-11578\n\n- Handle v1 CRLs, with no extensions and fixes issues with IDP (Issuing\n Distribution Point) comparison during CRL validation.\n\n Thanks to Andrew Thompson\n\n Own Id: OTP-11761","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 0.21 - Public_Key Release Notes","ref":"notes.html#public_key-0-21"},{"type":"extras","doc":"- Fixed a little typo in public_key documentation. Thanks to Tomas Morstein.\n\n Own Id: OTP-11380\n\n- public_key: Workaround for incorrectly encoded utf8 emailAddress. Thanks to\n Andrew Bennett.\n\n Own Id: OTP-11470","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 0.20 - Public_Key Release Notes","ref":"notes.html#public_key-0-20"},{"type":"extras","doc":"- Extend PKCS-7 to support SCEP (Simple Certificate Enrollment Protocol).\n\n Own Id: OTP-10874\n\n- public_key:pem_entry_decode/2 now handles AES-128-CBC ciphered keys. Thanks to\n Simon Cornish.\n\n Own Id: OTP-11281","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 0.19 - Public_Key Release Notes","ref":"notes.html#public_key-0-19"},{"type":"extras","doc":"- Add support for ISO oids 1.3.14.3.2.29 and 1.3.14.3.2.27 that are sometimes\n used instead of the PKCS defined oids 1.2.840.113549.1.1.5 and\n 1.2.840.10040.4.3. Add function pkix_sign_types:/1 that translates oids to to\n algorithm atoms ex:\n\n > public_key:pkix_sign_types(\\{1,3,14,3,2,29\\}). \\{sha,rsa\\}\n\n Own Id: OTP-10873\n\n- Integrate elliptic curve contribution from Andreas Schultz\n\n In order to be able to support elliptic curve cipher suites in SSL/TLS,\n additions to handle elliptic curve infrastructure has been added to public_key\n and crypto.\n\n This also has resulted in a rewrite of the crypto API to gain consistency and\n remove unnecessary overhead. All OTP applications using crypto has been\n updated to use the new API.\n\n Impact: Elliptic curve cryptography (ECC) offers equivalent security with\n smaller key sizes than other public key algorithms. Smaller key sizes result\n in savings for power, memory, bandwidth, and computational cost that make ECC\n especially attractive for constrained environments.\n\n Own Id: OTP-11009","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 0.18 - Public_Key Release Notes","ref":"notes.html#public_key-0-18"},{"type":"extras","doc":"- Fix subjectPublicKeyInfo type comment in public_key. Thanks to Ryosuke Nakai.\n\n Own Id: OTP-10670","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- public_key now supports CRL validation and documents the function\n public_key:pkix_path_validation/3\n\n Own Id: OTP-7045\n\n- Some examples overflowing the width of PDF pages have been corrected.\n\n Own Id: OTP-10665\n\n- Fixed typo's in public_key spec.\n\n Own Id: OTP-10723\n\n- Corrected PKCS-10 documentation and added some PKCS-9 support that is fairly\n commonly used by PKCS-10. Full support for PKCS-9 will be added later.\n\n Own Id: OTP-10767","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 0.17 - Public_Key Release Notes","ref":"notes.html#public_key-0-17"},{"type":"extras","doc":"- ssh_decode now handles comments, at the end of the line, containing with\n spaces correctly\n\n Own Id: OTP-9361\n\n- Add missing references to sha224 and sha384\n\n Own Id: OTP-9362 Aux Id: seq12116","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- public_key now supports PKCS-10 and includes experimental support for PKCS-7\n\n Own Id: OTP-10509 Aux Id: kunagi-291 \\[202]","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 0.16 - Public_Key Release Notes","ref":"notes.html#public_key-0-16"},{"type":"extras","doc":"- Add crypto and public_key support for the hash functions SHA224, SHA256,\n SHA384 and SHA512 and also hmac and rsa_sign/verify support using these hash\n functions. Thanks to Andreas Schultz for making a prototype.\n\n Own Id: OTP-9908\n\n- Optimize RSA private key handling in `crypto` and `public_key`.\n\n Own Id: OTP-10065","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 0.15 - Public_Key Release Notes","ref":"notes.html#public_key-0-15"},{"type":"extras","doc":"- Changed ssh implementation to use the public_key application for all public\n key handling. This is also a first step for enabling a callback API for\n supplying public keys and handling keys protected with password phrases.\n\n Additionally the test suites where improved so that they do not copy the users\n keys to test server directories as this is a security liability. Also ipv6 and\n file access issues found in the process has been fixed.\n\n This change also solves OTP-7677 and OTP-7235\n\n This changes also involves some updates to public_keys ssh-functions.\n\n Own Id: OTP-9911","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 0.14 - Public_Key Release Notes","ref":"notes.html#public_key-0-14"},{"type":"extras","doc":"- public_key, ssl and crypto now supports PKCS-8\n\n Own Id: OTP-9312\n\n- The asn1 decoder/encoder now uses a runtime nif from the asn1 application if\n it is available.\n\n Own Id: OTP-9414","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 0.13 - Public_Key Release Notes","ref":"notes.html#public_key-0-13"},{"type":"extras","doc":"- replace \"a ssl\" with \"an ssl\" reindent pkix_path_validation/3 Trivial\n documentation fixes (Thanks to Christian von Roques )\n\n Own Id: OTP-9464","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Public_Key 0.12 - Public_Key Release Notes","ref":"notes.html#public_key-0-12"},{"type":"extras","doc":"- The public_key application now supports encode/decode of ssh public-key files.\n\n Own Id: OTP-9144","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 0.11 - Public_Key Release Notes","ref":"notes.html#public_key-0-11"},{"type":"extras","doc":"- Allows the public_key module to decode and encode RSA and DSA keys encoded\n using the SubjectPublicKeyInfo format. When pem_entry_encode is called on an\n RSA or DSA public key type, the key is wrapped in the SubjectPublicKeyInfo\n format.\n\n Own Id: OTP-9061","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 0.10 - Public_Key Release Notes","ref":"notes.html#public_key-0-10"},{"type":"extras","doc":"- Improved dialyzer specs.\n\n Own Id: OTP-8964","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 0.9 - Public_Key Release Notes","ref":"notes.html#public_key-0-9"},{"type":"extras","doc":"- Updated ssl to ignore CA certs that violate the asn1-spec for a certificate,\n and updated public key asn1 spec to handle inherited DSS-params.\n\n Own Id: OTP-7884\n\n- Changed ssl implementation to retain backwards compatibility for old option\n \\{verify, 0\\} that shall be equivalent to \\{verify, verify_none\\}, also\n separate the cases unknown ca and selfsigned peer cert, and restored return\n value of deprecated function public_key:pem_to_der/1.\n\n Own Id: OTP-8858\n\n- Better handling of v1 and v2 certificates. V1 and v2 certificates does not\n have any extensions so then validate_extensions should just accept that there\n are none and not end up in missing_basic_constraints clause.\n\n Own Id: OTP-8867\n\n- Changed the verify fun so that it differentiate between the peer certificate\n and CA certificates by using valid_peer or valid as the second argument to the\n verify fun. It may not always be trivial or even possible to know when the\n peer certificate is reached otherwise.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8873","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 0.8 - Public_Key Release Notes","ref":"notes.html#public_key-0-8"},{"type":"extras","doc":"- Handling of unknown CA certificates was changed in ssl and public_key to work\n as intended.\n\n Own Id: OTP-8788","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Revise the public_key API - Cleaned up and documented the public_key API to\n make it useful for general use, also changed ssl to use the new API.\n\n Own Id: OTP-8722\n\n- Added the functionality so that the verification fun will be called when a\n certificate is considered valid by the path validation to allow access to each\n certificate in the path to the user application. Also try to verify\n subject-AltName, if unable to verify it let the application verify it.\n\n Own Id: OTP-8825","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 0.7 - Public_Key Release Notes","ref":"notes.html#public_key-0-7"},{"type":"extras","doc":"- Certificates without any extensions could not be handled by public_key.\n\n Own Id: OTP-8626","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Code cleanup and minor bugfixes.\n\n Own Id: OTP-8649","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 0.6 - Public_Key Release Notes","ref":"notes.html#public_key-0-6"},{"type":"extras","doc":"- Support for Diffie-Hellman. ssl-3.11 requires public_key-0.6.\n\n Own Id: OTP-7046\n\n- Moved extended key usage test for ssl values to ssl.\n\n Own Id: OTP-8553 Aux Id: seq11541, OTP-8554","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 0.5 - Public_Key Release Notes","ref":"notes.html#public_key-0-5"},{"type":"extras","doc":"- Added `public_key:pkix_transform/2` to enable ssl to send CA list during\n Certificate Request.\n\n `NOTE`: SSL (new_ssl) requires public_key-0.5. ssl usage.\n\n Own Id: OTP-8372","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 0.4 - Public_Key Release Notes","ref":"notes.html#public_key-0-4"},{"type":"extras","doc":"- The documentation is now built with open source tools (xsltproc and fop) that\n exists on most platforms. One visible change is that the frames are removed.\n\n Own Id: OTP-8250","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 0.3 - Public_Key Release Notes","ref":"notes.html#public_key-0-3"},{"type":"extras","doc":"- Unknown attributes in certificates are left encoded instead of crashing. Patch\n by Will \"wglozer\" thanks.\n\n Own Id: OTP-8100","title":"Fixed Bugs and Malfunctions - Public_Key Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Allow public_key:pem_to_der/\\[1,2] to take a binary as argument in addition to\n a filename. Patch by Geoff Cant, thanks.\n\n Own Id: OTP-8142","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 0.2 - Public_Key Release Notes","ref":"notes.html#public_key-0-2"},{"type":"extras","doc":"- X509 certificate handling has been extended and improved as a result of more\n extensive testing of both the ssl and public_key application. Even more\n extensions of the certificate handling is yet to be implemented.\n\n Own Id: OTP-7860","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Public_Key 0.1 - Public_Key Release Notes","ref":"notes.html#public_key-0-1"},{"type":"extras","doc":"- First version.\n\n Own Id: OTP-7637","title":"Improvements and New Features - Public_Key Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"\n# Public-Key Records\n\nThis chapter briefly describes Erlang records derived from ASN.1 specifications\nused to handle public key infrastructure. The scope is to describe the data\ntypes of each component, not the semantics. For information on the semantics,\nrefer to the relevant standards and RFCs linked in the sections below.\n\nUse the following include directive to get access to the records and constant\nmacros described in the following sections:\n\n```erlang\n -include_lib(\"public_key/include/public_key.hrl\").\n```","title":"Public-Key Records","ref":"public_key_records.html"},{"type":"extras","doc":"Common non-standard Erlang data types used to describe the record fields in the\nfollowing sections and which are not defined in the Public Key\n[Reference Manual](`m:public_key`) follows here:\n\n```erlang\ntime() = utc_time() | general_time()\n\nutc_time() = {utcTime, \"YYMMDDHHMMSSZ\"}\n\ngeneral_time() = {generalTime, \"YYYYMMDDHHMMSSZ\"}\n\ngeneral_name() = {rfc822Name, string()} |\n\n {dNSName, string()} |\n\n {x400Address, string() |\n\n {directoryName, {rdnSequence, [#'AttributeTypeAndValue'{}]}} |\n\n {ediPartyName, special_string()} |\n\n {ediPartyName, special_string(), special_string()} |\n\n {uniformResourceIdentifier, string()} |\n\n {iPAddress, string()} |\n\n {registeredId, oid()} |\n\n {otherName, term()}\n\nspecial_string() = {teletexString, string()} |\n \n {printableString, string()} |\n\n {universalString, string()} |\n\n {utf8String, binary()} |\n\n {bmpString, string()}\n\ndist_reason() = unused | keyCompromise | cACompromise | affiliationChanged |\n cessationOfOperation | certificateHold | privilegeWithdrawn | aACompromise\n\nOID_macro() = ?OID_name()\n\nOID_name() = atom()\n```","title":"Data Types - Public-Key Records","ref":"public_key_records.html#data-types"},{"type":"extras","doc":"Erlang representation of\n[Rivest-Shamir-Adleman cryptosystem (RSA)](http://www.ietf.org/rfc/rfc3447.txt)\nkeys follows:\n\n```erlang\n#'RSAPublicKey'{\n modulus, % pos_integer()\n publicExponent % pos_integer()\n }.\n\n#'RSAPrivateKey'{\n version, % two-prime | multi\n modulus, % pos_integer()\n publicExponent, % pos_integer()\n privateExponent, % pos_integer()\n prime1, % pos_integer()\n prime2, % pos_integer()\n exponent1, % pos_integer()\n exponent2, % pos_integer()\n coefficient, % pos_integer()\n otherPrimeInfos % [#OtherPrimeInfo{}] | asn1_NOVALUE\n }.\n\n#'OtherPrimeInfo'{\n prime, % pos_integer()\n exponent, % pos_integer()\n coefficient % pos_integer()\n }.\n\n#'RSASSA-PSS-params'{\n hashAlgorithm, % #'HashAlgorithm'{}},\n maskGenAlgorithm, % #'MaskGenAlgorithm'{}},\n saltLength, % pos_integer(),\n trailerField, % pos_integer()\n }.\n\n#'HashAlgorithm'{\n algorithm, % oid()\n parameters % defaults to asn1_NOVALUE\n }.\n\n#'MaskGenAlgorithm'{\n algorithm, % oid()\n parameters, % defaults to asn1_NOVALUE\n }.\n```","title":"RSA - Public-Key Records","ref":"public_key_records.html#rsa"},{"type":"extras","doc":"Erlang representation of\n[Digital Signature Algorithm (DSA)](http://www.ietf.org/rfc/rfc6979.txt) keys\n\n```erlang\n#'DSAPrivateKey'{\n version, % pos_integer()\n p, % pos_integer()\n q, % pos_integer()\n g, % pos_integer()\n y, % pos_integer()\n x % pos_integer()\n }.\n\n#'Dss-Parms'{\n p, % pos_integer()\n q, % pos_integer()\n g % pos_integer()\n }.\n```","title":"DSA - Public-Key Records","ref":"public_key_records.html#dsa"},{"type":"extras","doc":"Erlang representation of\n[Elliptic Curve Digital Signature Algorithm (ECDSA)](http://www.ietf.org/rfc/rfc6979.txt)\nand\n[Edwards-Curve Digital Signature Algorithm (EDDSA)](https://tools.ietf.org/html/rfc8032)\nwhere parameters in the private key will be\n`{namedCurve, ?'id-Ed25519' | ?'id-Ed448'}`.\n\n```erlang\n#'ECPrivateKey'{\n version, % pos_integer()\n privateKey, % binary()\n parameters, % {ecParameters, #'ECParameters'{}} |\n % {namedCurve, Oid::tuple()} |\n % {implicitlyCA, 'NULL'}\n publicKey % bitstring()\n }.\n\n#'ECParameters'{\n version, % pos_integer()\n fieldID, % #'FieldID'{}\n curve, % #'Curve'{}\n base, % binary()\n order, % pos_integer()\n cofactor % pos_integer()\n }.\n\n#'Curve'{\n a, % binary()\n b, % binary()\n seed % bitstring() - optional\n }.\n\n#'FieldID'{\n fieldType, % oid()\n parameters % Depending on fieldType\n }.\n\n#'ECPoint'{\n point % binary() - the public key\n }.\n```","title":"ECDSA and EDDSA - Public-Key Records","ref":"public_key_records.html#ecdsa-and-eddsa"},{"type":"extras","doc":"Erlang representation of PKIX certificates derived from ASN.1 specifications see\nalso [X509 certificates (RFC 5280)](http://www.ietf.org/rfc/rfc5280.txt), also\nreferred to as `plain` type, are as follows:\n\n```erlang\n#'Certificate'{\n tbsCertificate, % #'TBSCertificate'{}\n signatureAlgorithm, % #'AlgorithmIdentifier'{}\n signature % bitstring()\n }.\n\n#'TBSCertificate'{\n version, % v1 | v2 | v3\n serialNumber, % pos_integer()\n signature, % #'AlgorithmIdentifier'{}\n issuer, % {rdnSequence, [#AttributeTypeAndValue'{}]\n validity, % #'Validity'{}\n subject, % {rdnSequence, [#AttributeTypeAndValue'{}]}\n subjectPublicKeyInfo, % #'SubjectPublicKeyInfo'{}\n issuerUniqueID, % binary() | asn1_novalue\n subjectUniqueID, % binary() | asn1_novalue\n extensions % [#'Extension'{}]\n }.\n\n#'AlgorithmIdentifier'{\n algorithm, % oid()\n parameters % der_encoded()\n }.\n```\n\nErlang alternate representation of PKIX certificate, also referred to as `otp`\ntype\n\n```erlang\n#'OTPCertificate'{\n tbsCertificate, % #'OTPTBSCertificate'{}\n signatureAlgorithm, % #'SignatureAlgorithm'\n signature % bitstring()\n }.\n\n#'OTPTBSCertificate'{\n version, % v1 | v2 | v3\n serialNumber, % pos_integer()\n signature, % #'SignatureAlgorithm'\n issuer, % {rdnSequence, [#AttributeTypeAndValue'{}]}\n validity, % #'Validity'{}\n subject, % {rdnSequence, [#AttributeTypeAndValue'{}]}\n subjectPublicKeyInfo, % #'OTPSubjectPublicKeyInfo'{}\n issuerUniqueID, % binary() | asn1_novalue\n subjectUniqueID, % binary() | asn1_novalue\n extensions % [#'Extension'{}]\n }.\n\n#'SignatureAlgorithm'{\n algorithm, % id_signature_algorithm()\n parameters % asn1_novalue | #'Dss-Parms'{}\n }.\n```\n\n`id_signature_algorithm() = OID_macro()`\n\nThe available OID names are as follows:\n\n| _OID Name_ |\n| -------------------------------------------- |\n| id-dsa-with-sha1 |\n| id-dsaWithSHA1 (ISO or OID to above) |\n| md2WithRSAEncryption |\n| md5WithRSAEncryption |\n| sha1WithRSAEncryption |\n| sha-1WithRSAEncryption (ISO or OID to above) |\n| sha224WithRSAEncryption |\n| sha256WithRSAEncryption |\n| sha512WithRSAEncryption |\n| ecdsa-with-SHA1 |\n\n_Table: Signature Algorithm OIDs_\n\nThe data type `'AttributeTypeAndValue'`, is represented as the following erlang\nrecord:\n\n```erlang\n#'AttributeTypeAndValue'{\n type, % id_attributes()\n value % term()\n }.\n```\n\nThe attribute OID name atoms and their corresponding value types are as follows:\n\n| _OID Name_ | _Value Type_ |\n| ------------------------- | ----------------------------- |\n| id-at-name | special_string() |\n| id-at-surname | special_string() |\n| id-at-givenName | special_string() |\n| id-at-initials | special_string() |\n| id-at-generationQualifier | special_string() |\n| id-at-commonName | special_string() |\n| id-at-localityName | special_string() |\n| id-at-stateOrProvinceName | special_string() |\n| id-at-organizationName | special_string() |\n| id-at-title | special_string() |\n| id-at-dnQualifier | \\{printableString, string()\\} |\n| id-at-countryName | \\{printableString, string()\\} |\n| id-at-serialNumber | \\{printableString, string()\\} |\n| id-at-pseudonym | special_string() |\n\n_Table: Attribute OIDs_\n\nThe data types `'Validity'`, `'SubjectPublicKeyInfo'`, and\n`'SubjectPublicKeyInfoAlgorithm'` are represented as the following Erlang\nrecords:\n\n```erlang\n#'Validity'{\n notBefore, % time()\n notAfter % time()\n }.\n\n#'SubjectPublicKeyInfo'{\n algorithm, % #AlgorithmIdentifier{}\n subjectPublicKey % binary()\n }.\n\n#'SubjectPublicKeyInfoAlgorithm'{\n algorithm, % id_public_key_algorithm()\n parameters % public_key_params()\n }.\n```\n\nThe public-key algorithm OID name atoms are as follows:\n\n| _OID Name_ |\n| ----------------------- |\n| rsaEncryption |\n| id-dsa |\n| dhpublicnumber |\n| id-keyExchangeAlgorithm |\n| id-ecPublicKey |\n\n_Table: Public-Key Algorithm OIDs_\n\n```erlang\n#'Extension'{\n extnID, % id_extensions() | oid()\n critical, % boolean()\n extnValue % der_encoded()\n }.\n```\n\n`id_extensions()`\n[Standard Certificate Extensions](public_key_records.md#StdCertExt),\n[Private Internet Extensions](public_key_records.md#PrivIntExt),\n[CRL Extensions](public_key_records.md#CRLCertExt) and\n[CRL Entry Extensions](public_key_records.md#CRLEntryExt).\n\n[](){: #StdCertExt }","title":"PKIX Certificates - Public-Key Records","ref":"public_key_records.html#pkix-certificates"},{"type":"extras","doc":"The standard certificate extensions OID name atoms and their corresponding value\ntypes are as follows:\n\n| _OID Name_ | _Value Type_ |\n| -------------------------------- | ------------------------------ |\n| id-ce-authorityKeyIdentifier | \\#'AuthorityKeyIdentifier'\\{\\} |\n| id-ce-subjectKeyIdentifier | oid() |\n| id-ce-keyUsage | \\[key_usage()] |\n| id-ce-privateKeyUsagePeriod | \\#'PrivateKeyUsagePeriod'\\{\\} |\n| id-ce-certificatePolicies | \\#'PolicyInformation'\\{\\} |\n| id-ce-policyMappings | \\#'PolicyMappings_SEQOF'\\{\\} |\n| id-ce-subjectAltName | general_name() |\n| id-ce-issuerAltName | general_name() |\n| id-ce-subjectDirectoryAttributes | \\[#'Attribute'\\{\\}] |\n| id-ce-basicConstraints | \\#'BasicConstraints'\\{\\} |\n| id-ce-nameConstraints | \\#'NameConstraints'\\{\\} |\n| id-ce-policyConstraints | \\#'PolicyConstraints'\\{\\} |\n| id-ce-extKeyUsage | \\[id_key_purpose()] |\n| id-ce-cRLDistributionPoints | \\[#'DistributionPoint'\\{\\}] |\n| id-ce-inhibitAnyPolicy | pos_integer() |\n| id-ce-freshestCRL | \\[#'DistributionPoint'\\{\\}] |\n\n_Table: Standard Certificate Extensions_\n\nHere:\n\n```erlang\nkey_usage() = digitalSignature | nonRepudiation | keyEncipherment\n | dataEncipherment | keyAgreement | keyCertSign\n | cRLSign | encipherOnly | decipherOnly\n```\nAnd for `id_key_purpose()`:\n\n| _OID Name_ |\n| --------------------- |\n| id-kp-serverAuth |\n| id-kp-clientAuth |\n| id-kp-codeSigning |\n| id-kp-emailProtection |\n| id-kp-timeStamping |\n| id-kp-OCSPSigning |\n\n_Table: Key Purpose OIDs_\n\n```erlang\n#'AuthorityKeyIdentifier'{\n keyIdentifier, % oid()\n authorityCertIssuer, % general_name()\n authorityCertSerialNumber % pos_integer()\n }.\n\n#'PrivateKeyUsagePeriod'{\n notBefore, % general_time()\n notAfter % general_time()\n }.\n\n#'PolicyInformation'{\n policyIdentifier, % oid()\n policyQualifiers % [#PolicyQualifierInfo{}]\n }.\n\n#'PolicyQualifierInfo'{\n policyQualifierId, % oid()\n qualifier % string() | #'UserNotice'{}\n }.\n\n#'UserNotice'{\n noticeRef, % #'NoticeReference'{}\n explicitText % string()\n }.\n\n#'NoticeReference'{\n organization, % string()\n noticeNumbers % [pos_integer()]\n }.\n\n#'PolicyMappings_SEQOF'{\n issuerDomainPolicy, % oid()\n subjectDomainPolicy % oid()\n }.\n\n#'Attribute'{\n type, % oid()\n values % [der_encoded()]\n }).\n\n#'BasicConstraints'{\n cA, % boolean()\n pathLenConstraint % pos_integer()\n }).\n\n#'NameConstraints'{\n permittedSubtrees, % [#'GeneralSubtree'{}]\n excludedSubtrees % [#'GeneralSubtree'{}]\n }).\n\n#'GeneralSubtree'{\n base, % general_name()\n minimum, % pos_integer()\n maximum % pos_integer()\n }).\n\n#'PolicyConstraints'{\n requireExplicitPolicy, % pos_integer()\n inhibitPolicyMapping % pos_integer()\n }).\n\n#'DistributionPoint'{\n distributionPoint, % {fullName, [general_name()]} | {nameRelativeToCRLIssuer,[#AttributeTypeAndValue{}]}\n reasons, % [dist_reason()]\n cRLIssuer % [general_name()]\n }).\n```\n\n[](){: #PrivIntExt }","title":"Standard Certificate Extensions - Public-Key Records","ref":"public_key_records.html#standard-certificate-extensions"},{"type":"extras","doc":"The private internet extensions OID name atoms and their corresponding value\ntypes are as follows:\n\n| _OID Name_ | _Value Type_ |\n| ------------------------- | --------------------------- |\n| id-pe-authorityInfoAccess | \\[#'AccessDescription'\\{\\}] |\n| id-pe-subjectInfoAccess | \\[#'AccessDescription'\\{\\}] |\n\n_Table: Private Internet Extensions_\n\n```erlang\n#'AccessDescription'{\n accessMethod, % oid()\n accessLocation % general_name()\n }).\n```","title":"Private Internet Extensions - Public-Key Records","ref":"public_key_records.html#private-internet-extensions"},{"type":"extras","doc":"Erlang representation of CRL and CRL extensions profile derived from ASN.1\nspecifications and RFC 5280 are as follows:\n\n```erlang\n#'CertificateList'{\n tbsCertList, % #'TBSCertList{}\n signatureAlgorithm, % #'AlgorithmIdentifier'{}\n signature % bitstring()\n }).\n\n#'TBSCertList'{\n version, % v2 (if defined)\n signature, % #AlgorithmIdentifier{}\n issuer, % {rdnSequence, [#AttributeTypeAndValue'{}]}\n thisUpdate, % time()\n nextUpdate, % time()\n revokedCertificates, % [#'TBSCertList_revokedCertificates_SEQOF'{}]\n crlExtensions % [#'Extension'{}]\n }).\n\n#'TBSCertList_revokedCertificates_SEQOF'{\n userCertificate, % pos_integer()\n revocationDate, % timer()\n crlEntryExtensions % [#'Extension'{}]\n }).\n```\n\n[](){: #CRLCertExt }","title":"CRL and CRL Extensions Profile - Public-Key Records","ref":"public_key_records.html#crl-and-crl-extensions-profile"},{"type":"extras","doc":"The CRL extensions OID name atoms and their corresponding value types are as\nfollows:\n\n| _OID Name_ | _Value Type_ |\n| ------------------------------ | ----------------------------------------------- |\n| id-ce-authorityKeyIdentifier | \\#'AuthorityKeyIdentifier\\{\\} |\n| id-ce-issuerAltName | \\{rdnSequence, \\[#AttributeTypeAndValue'\\{\\}]\\} |\n| id-ce-cRLNumber | pos_integer() |\n| id-ce-deltaCRLIndicator | pos_integer() |\n| id-ce-issuingDistributionPoint | \\#'IssuingDistributionPoint'\\{\\} |\n| id-ce-freshestCRL | \\[#'Distributionpoint'\\{\\}] |\n\n_Table: CRL Extensions_\n\nHere, the data type `'IssuingDistributionPoint'` is represented as the following\nErlang record:\n\n```erlang\n#'IssuingDistributionPoint'{\n distributionPoint, % {fullName, [general_name()]} | {nameRelativeToCRLIssuer, [#'AttributeTypeAndValue'{}]}\n onlyContainsUserCerts, % boolean()\n onlyContainsCACerts, % boolean()\n onlySomeReasons, % [dist_reason()]\n indirectCRL, % boolean()\n onlyContainsAttributeCerts % boolean()\n }).\n```\n\n[](){: #CRLEntryExt }","title":"CRL Extensions - Public-Key Records","ref":"public_key_records.html#crl-extensions"},{"type":"extras","doc":"The CRL entry extensions OID name atoms and their corresponding value types are\nas follows:\n\n| _OID Name_ | _Value Type_ |\n| ------------------------- | -------------- |\n| id-ce-cRLReason | crl_reason() |\n| id-ce-holdInstructionCode | oid() |\n| id-ce-invalidityDate | general_time() |\n| id-ce-certificateIssuer | general_name() |\n\n_Table: CRL Entry Extensions_\n\nHere:\n\n```erlang\n crl_reason() = unspecified | keyCompromise | cACompromise\n | affiliationChanged | superseded | cessationOfOperation\n | certificateHold | removeFromCRL\n | privilegeWithdrawn | aACompromise\n```","title":"CRL Entry Extensions - Public-Key Records","ref":"public_key_records.html#crl-entry-extensions"},{"type":"extras","doc":"Erlang representation of a PKCS#10 certification request derived from ASN.1\nspecifications and RFC 5280 are as follows:\n\n```erlang\n#'CertificationRequest'{\n certificationRequestInfo, % #'CertificationRequestInfo'{},\n signatureAlgorithm, % #'CertificationRequest_signatureAlgorithm'{}}.\n signature % bitstring()\n }.\n\n#'CertificationRequestInfo'{\n version, % atom(),\n subject, % {rdnSequence, [#AttributeTypeAndValue'{}]} ,\n subjectPKInfo, % #'CertificationRequestInfo_subjectPKInfo'{},\n attributes % [#'AttributePKCS-10' {}]\n }.\n\n#'CertificationRequestInfo_subjectPKInfo'{\n algorithm, % #'CertificationRequestInfo_subjectPKInfo_algorithm'{}\n subjectPublicKey % bitstring()\n }.\n\n#'CertificationRequestInfo_subjectPKInfo_algorithm'{\n algorithm, % oid(),\n parameters % der_encoded()\n }.\n\n#'CertificationRequest_signatureAlgorithm'{\n algorithm, % oid(),\n parameters % der_encoded()\n }.\n\n#'AttributePKCS-10'{\n type, % oid(),\n values % [der_encoded()]\n }.\n```\n[](){: #PKCS10}","title":"PKCS#10 Certification Request - Public-Key Records","ref":"public_key_records.html#pkcs-10-certification-request"},{"type":"extras","doc":"\n# Examples\n\nThis section describes examples of how to use the Public Key API. Keys and\ncertificates used in the following sections are generated only for testing the\nPublic Key application.\n\nSome shell printouts in the following examples are abbreviated for increased\nreadability.","title":"Examples","ref":"using_public_key.html"},{"type":"extras","doc":"Public-key data (keys, certificates, and so on) can be stored in Privacy\nEnhanced Mail (PEM) format. The PEM files have the following structure:\n\n```text\n \n -----BEGIN -----\n : \n \n -----END -----\n \n```\n\nA file can contain several `BEGIN/END` blocks. Text lines between blocks are\nignored. Attributes, if present, are ignored except for `Proc-Type` and\n`DEK-Info`, which are used when `DER` data is encrypted.","title":"PEM Files - Examples","ref":"using_public_key.html#pem-files"},{"type":"extras","doc":"A DSA private key can look as follows:\n\n> #### Note {: .info }\n>\n> File handling is not done by the Public Key application.\n\n```erlang\n1> {ok, PemBin} = file:read_file(\"dsa.pem\").\n{ok,<<\"-----BEGIN DSA PRIVATE KEY-----\\nMIIBuw\"...>>}\n```\n\nThe following PEM file has only one entry, a private DSA key:\n\n```erlang\n2>[DSAEntry] = public_key:pem_decode(PemBin).\n[{'DSAPrivateKey',<<48,130,1,187,2,1,0,2,129,129,0,183,\n 179,230,217,37,99,144,157,21,228,204,\n 162,207,61,246,...>>,\n not_encrypted}]\n```\n\n```erlang\n3> Key = public_key:pem_entry_decode(DSAEntry).\n#'DSAPrivateKey'{version = 0,\n p = 12900045185019966618...6593,\n q = 1216700114794736143432235288305776850295620488937,\n g = 10442040227452349332...47213,\n y = 87256807980030509074...403143,\n x = 510968529856012146351317363807366575075645839654}\n```","title":"DSA Private Key - Examples","ref":"using_public_key.html#dsa-private-key"},{"type":"extras","doc":"An RSA private key encrypted with a password can look as follows:\n\n```erlang\n1> {ok, PemBin} = file:read_file(\"rsa.pem\").\n{ok,<<\"Bag Attribute\"...>>}\n```\n\nThe following PEM file has only one entry, a private RSA key:\n\n```erlang\n2>[RSAEntry] = public_key:pem_decode(PemBin).\n[{'RSAPrivateKey',<<224,108,117,203,152,40,15,77,128,126,\n 221,195,154,249,85,208,202,251,109,\n 119,120,57,29,89,19,9,...>>,\n {\"DES-EDE3-CBC\",<<\"kÙeø¼pµL\">>}}]\n```\n\nIn this following example, the password is `\"abcd1234\"`:\n\n```erlang\n3> Key = public_key:pem_entry_decode(RSAEntry, \"abcd1234\").\n#'RSAPrivateKey'{version = 'two-prime',\n modulus = 1112355156729921663373...2737107,\n publicExponent = 65537,\n privateExponent = 58064406231183...2239766033,\n prime1 = 11034766614656598484098...7326883017,\n prime2 = 10080459293561036618240...77738643771,\n exponent1 = 77928819327425934607...22152984217,\n exponent2 = 36287623121853605733...20588523793,\n coefficient = 924840412626098444...41820968343,\n otherPrimeInfos = asn1_NOVALUE}\n```","title":"RSA Private Key with Password - Examples","ref":"using_public_key.html#rsa-private-key-with-password"},{"type":"extras","doc":"The following is an example of X509 certificates:\n\n```erlang\n1> {ok, PemBin} = file:read_file(\"cacerts.pem\").\n{ok,<<\"-----BEGIN CERTIFICATE-----\\nMIIC7jCCAl\"...>>}\n```\n\nThe following file includes two certificates:\n\n```erlang\n2> [CertEntry1, CertEntry2] = public_key:pem_decode(PemBin).\n[{'Certificate',<<48,130,2,238,48,130,2,87,160,3,2,1,2,2,\n 9,0,230,145,97,214,191,2,120,150,48,13,\n ...>>,\n not_encrypted},\n {'Certificate',<<48,130,3,200,48,130,3,49,160,3,2,1,2,2,1,\n 1,48,13,6,9,42,134,72,134,247,...>>,\n not_encrypted}]\n```\n\nCertificates can be decoded as usual:\n\n```erlang\n2> Cert = public_key:pem_entry_decode(CertEntry1).\n#'Certificate'{\n tbsCertificate =\n #'TBSCertificate'{\n version = v3,serialNumber = 16614168075301976214,\n signature =\n #'AlgorithmIdentifier'{\n algorithm = {1,2,840,113549,1,1,5},\n parameters = <<5,0>>},\n issuer =\n {rdnSequence,\n [[#'AttributeTypeAndValue'{\n type = {2,5,4,3},\n value = <<19,8,101,114,108,97,110,103,67,65>>}],\n [#'AttributeTypeAndValue'{\n type = {2,5,4,11},\n value = <<19,10,69,114,108,97,110,103,32,79,84,80>>}],\n [#'AttributeTypeAndValue'{\n type = {2,5,4,10},\n value = <<19,11,69,114,105,99,115,115,111,110,32,65,66>>}],\n [#'AttributeTypeAndValue'{\n type = {2,5,4,7},\n value = <<19,9,83,116,111,99,107,104,111,108,109>>}],\n [#'AttributeTypeAndValue'{\n type = {2,5,4,6},\n value = <<19,2,83,69>>}],\n [#'AttributeTypeAndValue'{\n type = {1,2,840,113549,1,9,1},\n value = <<22,22,112,101,116,101,114,64,101,114,...>>}]]},\n validity =\n #'Validity'{\n notBefore = {utcTime,\"080109082929Z\"},\n notAfter = {utcTime,\"080208082929Z\"}},\n subject =\n {rdnSequence,\n [[#'AttributeTypeAndValue'{\n type = {2,5,4,3},\n value = <<19,8,101,114,108,97,110,103,67,65>>}],\n [#'AttributeTypeAndValue'{\n type = {2,5,4,11},\n value = <<19,10,69,114,108,97,110,103,32,79,84,80>>}],\n [#'AttributeTypeAndValue'{\n type = {2,5,4,10},\n value = <<19,11,69,114,105,99,115,115,111,110,32,...>>}],\n [#'AttributeTypeAndValue'{\n type = {2,5,4,7},\n value = <<19,9,83,116,111,99,107,104,111,108,...>>}],\n [#'AttributeTypeAndValue'{\n type = {2,5,4,6},\n value = <<19,2,83,69>>}],\n [#'AttributeTypeAndValue'{\n type = {1,2,840,113549,1,9,1},\n value = <<22,22,112,101,116,101,114,64,...>>}]]},\n subjectPublicKeyInfo =\n #'SubjectPublicKeyInfo'{\n algorithm =\n #'AlgorithmIdentifier'{\n algorithm = {1,2,840,113549,1,1,1},\n parameters = <<5,0>>},\n subjectPublicKey =\n {0,<<48,129,137,2,129,129,0,203,209,187,77,73,231,90,...>>}},\n issuerUniqueID = asn1_NOVALUE,\n subjectUniqueID = asn1_NOVALUE,\n extensions =\n [#'Extension'{\n extnID = {2,5,29,19},\n critical = true,\n extnValue = [48,3,1,1,255]},\n #'Extension'{\n extnID = {2,5,29,15},\n critical = false,\n extnValue = [3,2,1,6]},\n #'Extension'{\n extnID = {2,5,29,14},\n critical = false,\n extnValue = [4,20,27,217,65,152,6,30,142|...]},\n #'Extension'{\n extnID = {2,5,29,17},\n critical = false,\n extnValue = [48,24,129,22,112,101,116,101|...]}]},\n signatureAlgorithm =\n #'AlgorithmIdentifier'{\n algorithm = {1,2,840,113549,1,1,5},\n parameters = <<5,0>>},\n signature =\n <<163,186,7,163,216,152,63,47,154,234,139,73,154,96,120,\n 165,2,52,196,195,109,167,192,...>>}\n```\n\nParts of certificates can be decoded with `public_key:der_decode/2`, using the\nASN.1 type of that part. However, an application-specific certificate extension\nrequires application-specific ASN.1 decode/encode-functions. In the recent\nexample, the first value of `rdnSequence` is of ASN.1 type\n`'X520CommonName'. ({2,5,4,3} = ?id-at-commonName)`:\n\n```erlang\npublic_key:der_decode('X520CommonName', <<19,8,101,114,108,97,110,103,67,65>>).\n{printableString,\"erlangCA\"}\n```\n\nHowever, certificates can also be decoded using `pkix_decode_cert/2`, which can\ncustomize and recursively decode standard parts of a certificate:\n\n```erlang\n3> {_, DerCert, _} = CertEntry1.\n```\n\n```erlang\n4> public_key:pkix_decode_cert(DerCert, otp).\n#'OTPCertificate'{\n tbsCertificate =\n #'OTPTBSCertificate'{\n version = v3,serialNumber = 16614168075301976214,\n signature =\n #'SignatureAlgorithm'{\n algorithm = {1,2,840,113549,1,1,5},\n parameters = 'NULL'},\n issuer =\n {rdnSequence,\n [[#'AttributeTypeAndValue'{\n type = {2,5,4,3},\n value = {printableString,\"erlangCA\"}}],\n [#'AttributeTypeAndValue'{\n type = {2,5,4,11},\n value = {printableString,\"Erlang OTP\"}}],\n [#'AttributeTypeAndValue'{\n type = {2,5,4,10},\n value = {printableString,\"Ericsson AB\"}}],\n [#'AttributeTypeAndValue'{\n type = {2,5,4,7},\n value = {printableString,\"Stockholm\"}}],\n [#'AttributeTypeAndValue'{type = {2,5,4,6},value = \"SE\"}],\n [#'AttributeTypeAndValue'{\n type = {1,2,840,113549,1,9,1},\n value = \"peter@erix.ericsson.se\"}]]},\n validity =\n #'Validity'{\n notBefore = {utcTime,\"080109082929Z\"},\n notAfter = {utcTime,\"080208082929Z\"}},\n subject =\n {rdnSequence,\n [[#'AttributeTypeAndValue'{\n type = {2,5,4,3},\n value = {printableString,\"erlangCA\"}}],\n [#'AttributeTypeAndValue'{\n type = {2,5,4,11},\n value = {printableString,\"Erlang OTP\"}}],\n [#'AttributeTypeAndValue'{\n type = {2,5,4,10},\n value = {printableString,\"Ericsson AB\"}}],\n [#'AttributeTypeAndValue'{\n type = {2,5,4,7},\n value = {printableString,\"Stockholm\"}}],\n [#'AttributeTypeAndValue'{type = {2,5,4,6},value = \"SE\"}],\n [#'AttributeTypeAndValue'{\n type = {1,2,840,113549,1,9,1},\n value = \"peter@erix.ericsson.se\"}]]},\n subjectPublicKeyInfo =\n #'OTPSubjectPublicKeyInfo'{\n algorithm =\n #'PublicKeyAlgorithm'{\n algorithm = {1,2,840,113549,1,1,1},\n parameters = 'NULL'},\n subjectPublicKey =\n #'RSAPublicKey'{\n modulus =\n 1431267547247997...37419,\n publicExponent = 65537}},\n issuerUniqueID = asn1_NOVALUE,\n subjectUniqueID = asn1_NOVALUE,\n extensions =\n [#'Extension'{\n extnID = {2,5,29,19},\n critical = true,\n extnValue =\n #'BasicConstraints'{\n cA = true,pathLenConstraint = asn1_NOVALUE}},\n #'Extension'{\n extnID = {2,5,29,15},\n critical = false,\n extnValue = [keyCertSign,cRLSign]},\n #'Extension'{\n extnID = {2,5,29,14},\n critical = false,\n extnValue = [27,217,65,152,6,30,142,132,245|...]},\n #'Extension'{\n extnID = {2,5,29,17},\n critical = false,\n extnValue = [{rfc822Name,\"peter@erix.ericsson.se\"}]}]},\n signatureAlgorithm =\n #'SignatureAlgorithm'{\n algorithm = {1,2,840,113549,1,1,5},\n parameters = 'NULL'},\n signature =\n <<163,186,7,163,216,152,63,47,154,234,139,73,154,96,120,\n 165,2,52,196,195,109,167,192,...>>}\n```\n\nThis call is equivalent to `public_key:pem_entry_decode(CertEntry1)`:\n\n```erlang\n5> public_key:pkix_decode_cert(DerCert, plain).\n#'Certificate'{ ...}\n```","title":"X509 Certificates - Examples","ref":"using_public_key.html#x509-certificates"},{"type":"extras","doc":"If you have public-key data and want to create a PEM file this can be done by\ncalling functions `public_key:pem_entry_encode/2` and `pem_encode/1` and saving\nthe result to a file. For example, assume that you have\n`PubKey = 'RSAPublicKey'{}`. Then you can create a PEM-\"RSA PUBLIC KEY\" file\n(ASN.1 type `'RSAPublicKey'`) or a PEM-\"PUBLIC KEY\" file\n(`'SubjectPublicKeyInfo'` ASN.1 type).\n\nThe second element of the PEM-entry is the ASN.1 `DER` encoded key data:\n\n```erlang\n1> PemEntry = public_key:pem_entry_encode('RSAPublicKey', RSAPubKey).\n{'RSAPublicKey', <<48,72,...>>, not_encrypted}\n\n2> PemBin = public_key:pem_encode([PemEntry]).\n<<\"-----BEGIN RSA PUBLIC KEY-----\\nMEgC...>>\n\n3> file:write_file(\"rsa_pub_key.pem\", PemBin).\nok\n```\n\nor:\n\n```erlang\n1> PemEntry = public_key:pem_entry_encode('SubjectPublicKeyInfo', RSAPubKey).\n{'SubjectPublicKeyInfo', <<48,92...>>, not_encrypted}\n\n2> PemBin = public_key:pem_encode([PemEntry]).\n<<\"-----BEGIN PUBLIC KEY-----\\nMFw...>>\n\n3> file:write_file(\"pub_key.pem\", PemBin).\nok\n```","title":"Encoding Public-Key Data to PEM Format - Examples","ref":"using_public_key.html#encoding-public-key-data-to-pem-format"},{"type":"extras","doc":"Suppose you have the following private key and a corresponding public key:\n\n- `PrivateKey = #'RSAPrivateKey{}'` and the plaintext `Msg = binary()`\n- `PublicKey = #'RSAPublicKey'{}`\n\nThen you can proceed as follows:\n\nEncrypt with the private key:\n\n```erlang\nRsaEncrypted = public_key:encrypt_private(Msg, PrivateKey),\nMsg = public_key:decrypt_public(RsaEncrypted, PublicKey),\n```\n\nEncrypt with the public key:\n\n```erlang\nRsaEncrypted = public_key:encrypt_public(Msg, PublicKey),\nMsg = public_key:decrypt_private(RsaEncrypted, PrivateKey),\n```\n\n> #### Note {: .info }\n>\n> You normally do only one of the encrypt or decrypt operations, and the peer\n> does the other. This normally used in legacy applications as a primitive\n> digital signature.\n\n> #### Warning {: .warning }\n>\n> This legacy algorithm is broken although there exists a software prevention\n> when using appropriate OpenSSL cryptolib with Erlang/OTP it is hard to\n> guarantee security and we strongly recommend not using it.","title":"RSA Public-Key Cryptography - Examples","ref":"using_public_key.html#rsa-public-key-cryptography"},{"type":"extras","doc":"Suppose you have the following private key and a corresponding public key:\n\n- `PrivateKey = #'RSAPrivateKey{}'` or `#'DSAPrivateKey'{}` and the plaintext\n `Msg = binary()`\n- `PublicKey = #'RSAPublicKey'{}` or `{integer(), #'DssParams'{}}`\n\nThen you can proceed as follows:\n\n```erlang\nSignature = public_key:sign(Msg, sha, PrivateKey),\ntrue = public_key:verify(Msg, sha, Signature, PublicKey),\n```\n\n> #### Note {: .info }\n>\n> You normally do only one of the sign or verify operations, and the peer does\n> the other.\n\nIt can be appropriate to calculate the message digest before calling `sign` or\n`verify`, and then use `none` as second argument:\n\n```erlang\nDigest = crypto:sha(Msg),\nSignature = public_key:sign(Digest, none, PrivateKey),\ntrue = public_key:verify(Digest, none, Signature, PublicKey),\n```\n\n[](){: #verify_hostname }","title":"Digital Signatures - Examples","ref":"using_public_key.html#digital-signatures"},{"type":"extras","doc":"","title":"Verifying a certificate hostname - Examples","ref":"using_public_key.html#verifying-a-certificate-hostname"},{"type":"extras","doc":"When a client checks a server certificate there are a number of checks available\nlike checks that the certificate is not revoked, not forged or not out-of-date.\n\nThere are however attacks that are not detected by those checks. Suppose a bad\nguy has succeeded with a DNS infection. Then the client could believe it is\nconnecting to one host but ends up at another but evil one. Though it is evil,\nit could have a perfectly legal certificate\\! The certificate has a valid\nsignature, it is not revoked, the certificate chain is not faked and has a\ntrusted root and so on.\n\nTo detect that the server is not the intended one, the client must additionally\nperform a _hostname verification_. This procedure is described in\n[RFC 6125](https://tools.ietf.org/html/rfc6125). The idea is that the\ncertificate lists the hostnames it could be fetched from. This is checked by the\ncertificate issuer when the certificate is signed. So if the certificate is\nissued by a trusted root the client could trust the host names signed in it.\n\nThere is a default hostname matching procedure defined in\n[RFC 6125, section 6](https://tools.ietf.org/html/rfc6125#section/6) as well as\nprotocol dependent variations defined in\n[RFC 6125 appendix B](https://tools.ietf.org/html/rfc6125#appendix-B). The\ndefault procedure is implemented in\n[public_key:pkix_verify_hostname/2,3](`public_key:pkix_verify_hostname/2`). It\nis possible for a client to hook in modified rules using the options list.\n\nSome terminology is needed: the certificate presents hostname(s) on which it is\nvalid. Those are called _Presented IDs_. The hostname(s) the client believes it\nconnects to are called _Reference IDs_. The matching rules aims to verify that\nthere is at least one of the Reference IDs that matches one of the Presented\nIDs. If not, the verification fails.\n\nThe IDs contains normal fully qualified domain names like e.g `foo.example.com`,\nbut IP addresses are not recommended. The rfc describes why this is not\nrecommended as well as security considerations about how to acquire the\nReference IDs.\n\nInternationalized domain names are not supported.","title":"Background - Examples","ref":"using_public_key.html#background"},{"type":"extras","doc":"Traditionally the Presented IDs were found in the `Subject` certificate field as\n`CN` names. This is still quite common. When printing a certificate they show up\nas:\n\n```text\n $ openssl x509 -text < cert.pem\n ...\n Subject: C=SE, CN=example.com, CN=*.example.com, O=erlang.org\n ...\n```\n\nThe example `Subject` field has one C, two CN and one O part. It is only the CN\n(Common Name) that is used by hostname verification. The two other (C and O) is\nnot used here even when they contain a domain name like the O part. The C and O\nparts are defined elsewhere and meaningful only for other functions.\n\nIn the example the Presented IDs are `example.com` as well as hostnames matching\n`*.example.com`. For example `foo.example.com` and `bar.example.com` both\nmatches but not `foo.bar.example.com`. The name `erlang.org` matches neither\nsince it is not a CN.\n\nIn case where the Presented IDs are fetched from the `Subject` certificate\nfield, the names may contain wildcard characters. The function handles this as\ndefined in\n[chapter 6.4.3 in RFC 6125](https://tools.ietf.org/html/rfc6125#section-6.4.3).\n\nThere may only be one wildcard character and that is in the first label, for\nexample: `*.example.com`. This matches `foo.example.com` but neither\n`example.com` nor `foo.bar.example.com`.\n\nThere may be label characters before or/and after the wildcard. For example:\n`a*d.example.com` matches `abcd.example.com` and `ad.example.com`, but not\n`ab.cd.example.com`.\n\nIn the previous example there is no indication of which protocols are expected.\nSo a client has no indication of whether it is a web server, an ldap server or\nmaybe a sip server it is connected to. There are fields in the certificate that\ncan indicate this. To be more exact, the rfc introduces the usage of the\n`X509v3 Subject Alternative Name` in the `X509v3 extensions` field:\n\n```text\n $ openssl x509 -text < cert.pem\n ...\n X509v3 extensions:\n X509v3 Subject Alternative Name:\n DNS:kb.example.org, URI:https://www.example.org\n ...\n```\n\nHere `kb.example.org` serves any protocol while `www.example.org` presents a\nsecure web server.\n\nThe next example has both `Subject` and `Subject Alternate Name` present:\n\n```text\n $ openssl x509 -text < cert.pem\n ...\n Subject: C=SE, CN=example.com, CN=*.example.com, O=erlang.org\n ...\n X509v3 extensions:\n X509v3 Subject Alternative Name:\n DNS:kb.example.org, URI:https://www.example.org\n ...\n```\n\nThe RFC states that if a certificate defines Reference IDs in a\n`Subject Alternate Name` field, the `Subject` field MUST NOT be used for host\nname checking, even if it contains valid CN names. Therefore only\n`kb.example.org` and `https://www.example.org` matches. The match fails both for\n`example.com` and `foo.example.com` because they are in the `Subject` field\nwhich is not checked because the `Subject Alternate Name` field is present.\n\n[](){: #verify_hostname_examples }","title":"The verification process - Examples","ref":"using_public_key.html#the-verification-process"},{"type":"extras","doc":"> #### Note {: .info }\n>\n> Other applications like ssl/tls or https might have options that are passed\n> down to the `public_key:pkix_verify_hostname`. You will probably not have to\n> call it directly\n\nSuppose our client expects to connect to the web server https://www.example.net.\nThis URI is therefore the Reference IDs of the client. The call will be:\n\n```erlang\n public_key:pkix_verify_hostname(CertFromHost,\n [{uri_id, \"https://www.example.net\"}\n ]).\n```\n\nThe call will return `true` or `false` depending on the check. The caller do not\nneed to handle the matching rules in the rfc. The matching will proceed as:\n\n- If there is a `Subject Alternate Name` field, the `{uri_id,string()}` in the\n function call will be compared to any `{uniformResourceIdentifier,string()}`\n in the Certificate field. If the two `strings()` are equal (case insensitive),\n there is a match. The same applies for any `{dns_id,string()}` in the call\n which is compared with all `{dNSName,string()}` in the Certificate field.\n- If there is NO `Subject Alternate Name` field, the `Subject` field will be\n checked. All `CN` names will be compared to all hostnames _extracted_ from\n `{uri_id,string()}` and from `{dns_id,string()}`.","title":"Function call examples - Examples","ref":"using_public_key.html#function-call-examples"},{"type":"extras","doc":"The caller can use own extraction and matching rules. This is done with the two\noptions `fqdn_fun` and `match_fun`.\n\n[](){: #hostname_extraction }\n\n#### Hostname extraction\n\nThe `fqdn_fun` extracts hostnames (Fully Qualified Domain Names) from uri_id or\nother ReferenceIDs that are not pre-defined in the public_key function. Suppose\nyou have some URI with a very special protocol-part: `myspecial://example.com\"`.\nSince this a non-standard URI there will be no hostname extracted for matching\nCN-names in the `Subject`.\n\nTo \"teach\" the function how to extract, you can give a fun which replaces the\ndefault extraction function. The `fqdn_fun` takes one argument and returns\neither a `t:string/0` to be matched to each CN-name or the atom `default` which\nwill invoke the default fqdn extraction function. The return value `undefined`\nremoves the current URI from the fqdn extraction.\n\n```erlang\n ...\n Extract = fun({uri_id, \"myspecial://\"++HostName}) -> HostName;\n (_Else) -> default\n end,\n ...\n public_key:pkix_verify_hostname(CertFromHost, RefIDs,\n [{fqdn_fun, Extract}])\n ...\n```\n\n[](){: #redefining_match_op }\n\n#### Re-defining the match operation\n\nThe default matching handles dns_id and uri_id. In an uri_id the value is tested\nfor equality with a value from the `Subject Alternate Name`. If some other kind\nof matching is needed, use the `match_fun` option.\n\nThe `match_fun` takes two arguments and returns either `true`, `false` or\n`default`. The value `default` will invoke the default match function.\n\n```erlang\n ...\n Match = fun({uri_id,\"myspecial://\"++A},\n {uniformResourceIdentifier,\"myspecial://\"++B}) ->\n my_match(A,B);\n (_RefID, _PresentedID) ->\n default\n end,\n ...\n public_key:pkix_verify_hostname(CertFromHost, RefIDs,\n [{match_fun, Match}]),\n ...\n```\n\nIn case of a match operation between a ReferenceID and a CN value from the\n`Subject` field, the first argument to the fun is the extracted hostname from\nthe ReferenceID, and the second argument is the tuple `{cn, string()}` taken\nfrom the `Subject` field. That makes it possible to have separate matching rules\nfor Presented IDs from the `Subject` field and from the `Subject Alternate Name`\nfield.\n\nThe default matching transformes the ascii values in strings to lowercase before\ncomparing. The `match_fun` is however called without any transformation applied\nto the strings. The reason is to enable the user to do unforeseen handling of\nthe strings where the original format is needed.\n\n### \"Pinning\" a Certificate\n\nThe [RFC 6125](https://tools.ietf.org/html/rfc6125) defines _pinning_ as:\n\n> \"The act of establishing a cached name association between the application\n> service's certificate and one of the client's reference identifiers, despite\n> the fact that none of the presented identifiers matches the given reference\n> identifier. ...\"\n\nThe purpose is to have a mechanism for a human to accept an otherwise faulty\nCertificate. In for example a web browser, you could get a question like\n\n> Warning: you wanted to visit the site www.example.com, but the certificate is\n> for shop.example.com. Accept anyway (yes/no)?\"\n\nThis could be accomplished with the option `fail_callback` which will be called\nif the hostname verification fails:\n\n```erlang\n -include_lib(\"public_key/include/public_key.hrl\"). % Record def\n ...\n Fail = fun(#'OTPCertificate'{}=C) ->\n case in_my_cache(C) orelse my_accept(C) of\n true ->\n enter_my_cache(C),\n true;\n false ->\n false\n end,\n ...\n public_key:pkix_verify_hostname(CertFromHost, RefIDs,\n [{fail_callback, Fail}]),\n ...\n```","title":"Extending the search mechanism - Examples","ref":"using_public_key.html#extending-the-search-mechanism"}],"content_type":"text/plain","producer":{"name":"ex_doc","version":[48,46,51,52,46,49]}} \ No newline at end of file diff --git a/prs/9045/lib/public_key-1.16.3/doc/html/public_key.epub b/prs/9045/lib/public_key-1.16.3/doc/html/public_key.epub index a2f7ad0680d7..4faa214e9122 100644 Binary files a/prs/9045/lib/public_key-1.16.3/doc/html/public_key.epub and b/prs/9045/lib/public_key-1.16.3/doc/html/public_key.epub differ diff --git a/prs/9045/lib/public_key-1.16.3/doc/html/public_key.html b/prs/9045/lib/public_key-1.16.3/doc/html/public_key.html index 2070c970dfc1..4bff16d96207 100644 --- a/prs/9045/lib/public_key-1.16.3/doc/html/public_key.html +++ b/prs/9045/lib/public_key-1.16.3/doc/html/public_key.html @@ -3319,22 +3319,22 @@

    pkix_path_validation(Cert, CertChain, Optio 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 :: atom() | {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 :: atom() | {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 :: atom() | {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 :: atom() | {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 @@ -3506,9 +3506,9 @@

      pkix_verify_hostname(Cert, ReferenceIDs, Op 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 @@ -3708,14 +3708,14 @@

          pkix_crls_validate(OTPcertificate, DPandCRL

          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.

            @@ -4063,18 +4063,18 @@

            pkix_test_data(ChainConf)

            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.

          diff --git a/prs/9045/lib/public_key-1.16.3/doc/html/public_key_records.html b/prs/9045/lib/public_key-1.16.3/doc/html/public_key_records.html index 613e5d20aa19..c23f99efb13d 100644 --- a/prs/9045/lib/public_key-1.16.3/doc/html/public_key_records.html +++ b/prs/9045/lib/public_key-1.16.3/doc/html/public_key_records.html @@ -135,7 +135,7 @@

          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").

          +macros described in the following sections:

           -include_lib("public_key/include/public_key.hrl").

          @@ -143,48 +143,48 @@

          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()

          +OID_name() = atom()

          @@ -192,12 +192,12 @@

          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()
          @@ -208,50 +208,50 @@ 

          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'{
          +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()
          -  }.

          + }.

          @@ -262,38 +262,38 @@

          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()
              privateKey,    % binary()
              parameters,    % {ecParameters, #'ECParameters'{}} |
                             % {namedCurve, Oid::tuple()} |
                             % {implicitlyCA, 'NULL'}
              publicKey      % bitstring()
          -  }.
          +  }.
           
          -#'ECParameters'{
          +#'ECParameters'{
              version,    % pos_integer()
              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
          -  }.

          + }.

          @@ -301,13 +301,13 @@

          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()
              signature,            % #'AlgorithmIdentifier'{}
          @@ -318,19 +318,19 @@ 

          issuerUniqueID, % binary() | asn1_novalue subjectUniqueID, % binary() | asn1_novalue extensions % [#'Extension'{}] - }. + }. -#'AlgorithmIdentifier'{ +#'AlgorithmIdentifier'{ algorithm, % oid() parameters % der_encoded() - }.

          Erlang alternate representation of PKIX certificate, also referred to as otp -type

          #'OTPCertificate'{
          +  }.

          Erlang alternate representation of PKIX certificate, also referred to as otp +type

          #'OTPCertificate'{
              tbsCertificate,        % #'OTPTBSCertificate'{}
              signatureAlgorithm,    % #'SignatureAlgorithm'
              signature              % bitstring()
          -  }.
          +  }.
           
          -#'OTPTBSCertificate'{
          +#'OTPTBSCertificate'{
              version,              % v1 | v2 | v3
              serialNumber,         % pos_integer()
              signature,            % #'SignatureAlgorithm'
          @@ -341,35 +341,35 @@ 

          issuerUniqueID, % binary() | asn1_novalue subjectUniqueID, % binary() | asn1_novalue extensions % [#'Extension'{}] - }. + }. -#'SignatureAlgorithm'{ +#'SignatureAlgorithm'{ algorithm, % id_signature_algorithm() parameters % asn1_novalue | #'Dss-Parms'{} - }.

          id_signature_algorithm() = OID_macro()

          The available OID names are as follows:

          OID Name
          id-dsa-with-sha1
          id-dsaWithSHA1 (ISO or OID to above)
          md2WithRSAEncryption
          md5WithRSAEncryption
          sha1WithRSAEncryption
          sha-1WithRSAEncryption (ISO or OID to above)
          sha224WithRSAEncryption
          sha256WithRSAEncryption
          sha512WithRSAEncryption
          ecdsa-with-SHA1

          Table: Signature Algorithm OIDs

          The data type 'AttributeTypeAndValue', is represented as the following erlang -record:

          #'AttributeTypeAndValue'{
          +  }.

          id_signature_algorithm() = OID_macro()

          The available OID names are as follows:

          OID Name
          id-dsa-with-sha1
          id-dsaWithSHA1 (ISO or OID to above)
          md2WithRSAEncryption
          md5WithRSAEncryption
          sha1WithRSAEncryption
          sha-1WithRSAEncryption (ISO or OID to above)
          sha224WithRSAEncryption
          sha256WithRSAEncryption
          sha512WithRSAEncryption
          ecdsa-with-SHA1

          Table: Signature Algorithm OIDs

          The data type 'AttributeTypeAndValue', is represented as the following erlang +record:

          #'AttributeTypeAndValue'{
              type,   % id_attributes()
              value   % term()
          -  }.

          The attribute OID name atoms and their corresponding value types are as follows:

          OID NameValue Type
          id-at-namespecial_string()
          id-at-surnamespecial_string()
          id-at-givenNamespecial_string()
          id-at-initialsspecial_string()
          id-at-generationQualifierspecial_string()
          id-at-commonNamespecial_string()
          id-at-localityNamespecial_string()
          id-at-stateOrProvinceNamespecial_string()
          id-at-organizationNamespecial_string()
          id-at-titlespecial_string()
          id-at-dnQualifier{printableString, string()}
          id-at-countryName{printableString, string()}
          id-at-serialNumber{printableString, string()}
          id-at-pseudonymspecial_string()

          Table: Attribute OIDs

          The data types 'Validity', 'SubjectPublicKeyInfo', and + }.

          The attribute OID name atoms and their corresponding value types are as follows:

          OID NameValue Type
          id-at-namespecial_string()
          id-at-surnamespecial_string()
          id-at-givenNamespecial_string()
          id-at-initialsspecial_string()
          id-at-generationQualifierspecial_string()
          id-at-commonNamespecial_string()
          id-at-localityNamespecial_string()
          id-at-stateOrProvinceNamespecial_string()
          id-at-organizationNamespecial_string()
          id-at-titlespecial_string()
          id-at-dnQualifier{printableString, string()}
          id-at-countryName{printableString, string()}
          id-at-serialNumber{printableString, string()}
          id-at-pseudonymspecial_string()

          Table: Attribute OIDs

          The data types 'Validity', 'SubjectPublicKeyInfo', and 'SubjectPublicKeyInfoAlgorithm' are represented as the following Erlang -records:

          #'Validity'{
          +records:

          #'Validity'{
              notBefore, % time()
              notAfter   % time()
          -  }.
          +  }.
           
          -#'SubjectPublicKeyInfo'{
          +#'SubjectPublicKeyInfo'{
              algorithm,       % #AlgorithmIdentifier{}
              subjectPublicKey % binary()
          -  }.
          +  }.
           
          -#'SubjectPublicKeyInfoAlgorithm'{
          +#'SubjectPublicKeyInfoAlgorithm'{
              algorithm,  % id_public_key_algorithm()
              parameters  % public_key_params()
          -  }.

          The public-key algorithm OID name atoms are as follows:

          OID Name
          rsaEncryption
          id-dsa
          dhpublicnumber
          id-keyExchangeAlgorithm
          id-ecPublicKey

          Table: Public-Key Algorithm OIDs

          #'Extension'{
          +  }.

          The public-key algorithm OID name atoms are as follows:

          OID Name
          rsaEncryption
          id-dsa
          dhpublicnumber
          id-keyExchangeAlgorithm
          id-ecPublicKey

          Table: Public-Key Algorithm OIDs

          #'Extension'{
              extnID,    % id_extensions() | oid()
              critical,  % boolean()
              extnValue  % der_encoded()
          -  }.

          id_extensions() + }.

          id_extensions() Standard Certificate Extensions, Private Internet Extensions, CRL Extensions and @@ -380,98 +380,98 @@

          Standard Certificate Extensions

          The standard certificate extensions OID name atoms and their corresponding value -types are as follows:

          OID NameValue Type
          id-ce-authorityKeyIdentifier#'AuthorityKeyIdentifier'{}
          id-ce-subjectKeyIdentifieroid()
          id-ce-keyUsage[key_usage()]
          id-ce-privateKeyUsagePeriod#'PrivateKeyUsagePeriod'{}
          id-ce-certificatePolicies#'PolicyInformation'{}
          id-ce-policyMappings#'PolicyMappings_SEQOF'{}
          id-ce-subjectAltNamegeneral_name()
          id-ce-issuerAltNamegeneral_name()
          id-ce-subjectDirectoryAttributes[#'Attribute'{}]
          id-ce-basicConstraints#'BasicConstraints'{}
          id-ce-nameConstraints#'NameConstraints'{}
          id-ce-policyConstraints#'PolicyConstraints'{}
          id-ce-extKeyUsage[id_key_purpose()]
          id-ce-cRLDistributionPoints[#'DistributionPoint'{}]
          id-ce-inhibitAnyPolicypos_integer()
          id-ce-freshestCRL[#'DistributionPoint'{}]

          Table: Standard Certificate Extensions

          Here:

          key_usage() = digitalSignature | nonRepudiation | keyEncipherment
          +types are as follows:

          OID NameValue Type
          id-ce-authorityKeyIdentifier#'AuthorityKeyIdentifier'{}
          id-ce-subjectKeyIdentifieroid()
          id-ce-keyUsage[key_usage()]
          id-ce-privateKeyUsagePeriod#'PrivateKeyUsagePeriod'{}
          id-ce-certificatePolicies#'PolicyInformation'{}
          id-ce-policyMappings#'PolicyMappings_SEQOF'{}
          id-ce-subjectAltNamegeneral_name()
          id-ce-issuerAltNamegeneral_name()
          id-ce-subjectDirectoryAttributes[#'Attribute'{}]
          id-ce-basicConstraints#'BasicConstraints'{}
          id-ce-nameConstraints#'NameConstraints'{}
          id-ce-policyConstraints#'PolicyConstraints'{}
          id-ce-extKeyUsage[id_key_purpose()]
          id-ce-cRLDistributionPoints[#'DistributionPoint'{}]
          id-ce-inhibitAnyPolicypos_integer()
          id-ce-freshestCRL[#'DistributionPoint'{}]

          Table: Standard Certificate Extensions

          Here:

          key_usage() = digitalSignature | nonRepudiation | keyEncipherment
                       | dataEncipherment | keyAgreement | keyCertSign
          -            | cRLSign | encipherOnly | decipherOnly

          And for id_key_purpose():

          OID Name
          id-kp-serverAuth
          id-kp-clientAuth
          id-kp-codeSigning
          id-kp-emailProtection
          id-kp-timeStamping
          id-kp-OCSPSigning

          Table: Key Purpose OIDs

          #'AuthorityKeyIdentifier'{
          +            | cRLSign | encipherOnly | decipherOnly

          And for id_key_purpose():

          OID Name
          id-kp-serverAuth
          id-kp-clientAuth
          id-kp-codeSigning
          id-kp-emailProtection
          id-kp-timeStamping
          id-kp-OCSPSigning

          Table: Key Purpose OIDs

          #'AuthorityKeyIdentifier'{
              keyIdentifier,            % oid()
              authorityCertIssuer,      % general_name()
              authorityCertSerialNumber % pos_integer()
          -  }.
          +  }.
           
          -#'PrivateKeyUsagePeriod'{
          +#'PrivateKeyUsagePeriod'{
              notBefore,   % general_time()
              notAfter     % general_time()
          -  }.
          +  }.
           
          -#'PolicyInformation'{
          +#'PolicyInformation'{
              policyIdentifier,  % oid()
              policyQualifiers   % [#PolicyQualifierInfo{}]
          -  }.
          +  }.
           
          -#'PolicyQualifierInfo'{
          +#'PolicyQualifierInfo'{
              policyQualifierId,   % oid()
              qualifier            % string() | #'UserNotice'{}
          -  }.
          +  }.
           
          -#'UserNotice'{
          +#'UserNotice'{
              noticeRef,   % #'NoticeReference'{}
              explicitText % string()
          -  }.
          +  }.
           
          -#'NoticeReference'{
          +#'NoticeReference'{
              organization,    % string()
              noticeNumbers    % [pos_integer()]
          -  }.
          +  }.
           
          -#'PolicyMappings_SEQOF'{
          +#'PolicyMappings_SEQOF'{
              issuerDomainPolicy,  % oid()
              subjectDomainPolicy  % oid()
          -  }.
          +  }.
           
          -#'Attribute'{
          +#'Attribute'{
              type,  % oid()
              values % [der_encoded()]
          -  }).
          +  }).
           
          -#'BasicConstraints'{
          +#'BasicConstraints'{
              cA,               % boolean()
              pathLenConstraint % pos_integer()
          -  }).
          +  }).
           
          -#'NameConstraints'{
          +#'NameConstraints'{
              permittedSubtrees, % [#'GeneralSubtree'{}]
              excludedSubtrees   % [#'GeneralSubtree'{}]
          -  }).
          +  }).
           
          -#'GeneralSubtree'{
          +#'GeneralSubtree'{
              base,    % general_name()
              minimum, % pos_integer()
              maximum  % pos_integer()
          -  }).
          +  }).
           
          -#'PolicyConstraints'{
          +#'PolicyConstraints'{
              requireExplicitPolicy, % pos_integer()
              inhibitPolicyMapping   % pos_integer()
          -  }).
          +  }).
           
          -#'DistributionPoint'{
          +#'DistributionPoint'{
              distributionPoint, % {fullName, [general_name()]} | {nameRelativeToCRLIssuer,[#AttributeTypeAndValue{}]}
              reasons,           % [dist_reason()]
              cRLIssuer          % [general_name()]
          -  }).

          + }).

          Private Internet Extensions

          The private internet extensions OID name atoms and their corresponding value -types are as follows:

          OID NameValue Type
          id-pe-authorityInfoAccess[#'AccessDescription'{}]
          id-pe-subjectInfoAccess[#'AccessDescription'{}]

          Table: Private Internet Extensions

          #'AccessDescription'{
          +types are as follows:

          OID NameValue Type
          id-pe-authorityInfoAccess[#'AccessDescription'{}]
          id-pe-subjectInfoAccess[#'AccessDescription'{}]

          Table: Private Internet Extensions

          #'AccessDescription'{
              accessMethod,    % oid()
              accessLocation   % general_name()
          -  }).

          + }).

          CRL and CRL Extensions Profile

          Erlang representation of CRL and CRL extensions profile derived from ASN.1 -specifications and RFC 5280 are as follows:

          #'CertificateList'{
          +specifications and RFC 5280 are as follows:

          #'CertificateList'{
              tbsCertList,        % #'TBSCertList{}
              signatureAlgorithm, % #'AlgorithmIdentifier'{}
              signature           % bitstring()
          -  }).
          +  }).
           
          -#'TBSCertList'{
          +#'TBSCertList'{
              version,             % v2 (if defined)
              signature,           % #AlgorithmIdentifier{}
              issuer,              % {rdnSequence, [#AttributeTypeAndValue'{}]}
          @@ -479,13 +479,13 @@ 

          nextUpdate, % time() revokedCertificates, % [#'TBSCertList_revokedCertificates_SEQOF'{}] crlExtensions % [#'Extension'{}] - }). + }). -#'TBSCertList_revokedCertificates_SEQOF'{ +#'TBSCertList_revokedCertificates_SEQOF'{ userCertificate, % pos_integer() revocationDate, % timer() crlEntryExtensions % [#'Extension'{}] - }).

          + }).

          @@ -493,21 +493,21 @@

          The CRL extensions OID name atoms and their corresponding value types are as follows:

          OID NameValue Type
          id-ce-authorityKeyIdentifier#'AuthorityKeyIdentifier{}
          id-ce-issuerAltName{rdnSequence, [#AttributeTypeAndValue'{}]}
          id-ce-cRLNumberpos_integer()
          id-ce-deltaCRLIndicatorpos_integer()
          id-ce-issuingDistributionPoint#'IssuingDistributionPoint'{}
          id-ce-freshestCRL[#'Distributionpoint'{}]

          Table: CRL Extensions

          Here, the data type 'IssuingDistributionPoint' is represented as the following -Erlang record:

          #'IssuingDistributionPoint'{
          +Erlang record:

          #'IssuingDistributionPoint'{
              distributionPoint,         % {fullName, [general_name()]} | {nameRelativeToCRLIssuer, [#'AttributeTypeAndValue'{}]}
              onlyContainsUserCerts,     % boolean()
              onlyContainsCACerts,       % boolean()
              onlySomeReasons,           % [dist_reason()]
              indirectCRL,               % boolean()
              onlyContainsAttributeCerts % boolean()
          -  }).

          + }).

          CRL Entry Extensions

          The CRL entry extensions OID name atoms and their corresponding value types are -as follows:

          OID NameValue Type
          id-ce-cRLReasoncrl_reason()
          id-ce-holdInstructionCodeoid()
          id-ce-invalidityDategeneral_time()
          id-ce-certificateIssuergeneral_name()

          Table: CRL Entry Extensions

          Here:

              crl_reason() = unspecified | keyCompromise | cACompromise
          +as follows:

          OID NameValue Type
          id-ce-cRLReasoncrl_reason()
          id-ce-holdInstructionCodeoid()
          id-ce-invalidityDategeneral_time()
          id-ce-certificateIssuergeneral_name()

          Table: CRL Entry Extensions

          Here:

              crl_reason() = unspecified | keyCompromise | cACompromise
                            | affiliationChanged | superseded | cessationOfOperation
                            | certificateHold | removeFromCRL
                            | privilegeWithdrawn | aACompromise

          @@ -517,38 +517,38 @@

          PKCS#10 Certification Request

          Erlang representation of a PKCS#10 certification request derived from ASN.1 -specifications and RFC 5280 are as follows:

          #'CertificationRequest'{
          +specifications and RFC 5280 are as follows:

          #'CertificationRequest'{
              certificationRequestInfo, % #'CertificationRequestInfo'{},
              signatureAlgorithm,       % #'CertificationRequest_signatureAlgorithm'{}}.
              signature                 % bitstring()
          -  }.
          +  }.
           
          -#'CertificationRequestInfo'{
          +#'CertificationRequestInfo'{
              version,       % atom(),
              subject,       % {rdnSequence, [#AttributeTypeAndValue'{}]} ,
              subjectPKInfo, % #'CertificationRequestInfo_subjectPKInfo'{},
              attributes     % [#'AttributePKCS-10' {}]
          -  }.
          +  }.
           
          -#'CertificationRequestInfo_subjectPKInfo'{
          +#'CertificationRequestInfo_subjectPKInfo'{
              algorithm,        % #'CertificationRequestInfo_subjectPKInfo_algorithm'{}
              subjectPublicKey  %  bitstring()
          -  }.
          +  }.
           
          -#'CertificationRequestInfo_subjectPKInfo_algorithm'{
          +#'CertificationRequestInfo_subjectPKInfo_algorithm'{
              algorithm,  % oid(),
              parameters  % der_encoded()
          -  }.
          +  }.
           
          -#'CertificationRequest_signatureAlgorithm'{
          +#'CertificationRequest_signatureAlgorithm'{
              algorithm,  % oid(),
              parameters  % der_encoded()
          -  }.
          +  }.
           
          -#'AttributePKCS-10'{
          +#'AttributePKCS-10'{
              type,   % oid(),
              values  % [der_encoded()]
          -  }.

          +
          }.

          diff --git a/prs/9045/lib/public_key-1.16.3/doc/html/search.html b/prs/9045/lib/public_key-1.16.3/doc/html/search.html index 4bf725169991..0b20bf471b45 100644 --- a/prs/9045/lib/public_key-1.16.3/doc/html/search.html +++ b/prs/9045/lib/public_key-1.16.3/doc/html/search.html @@ -128,7 +128,7 @@

          - +

          diff --git a/prs/9045/lib/public_key-1.16.3/doc/html/using_public_key.html b/prs/9045/lib/public_key-1.16.3/doc/html/using_public_key.html index 2e0429a6ae39..e0b23199ff72 100644 --- a/prs/9045/lib/public_key-1.16.3/doc/html/using_public_key.html +++ b/prs/9045/lib/public_key-1.16.3/doc/html/using_public_key.html @@ -154,30 +154,30 @@

          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,
          +

          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,
          +                    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}

          + 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,
          +

          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',
          +                  {"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,
          @@ -186,201 +186,201 @@ 

          exponent1 = 77928819327425934607...22152984217, exponent2 = 36287623121853605733...20588523793, coefficient = 924840412626098444...41820968343, - otherPrimeInfos = asn1_NOVALUE}

          + 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,
          +

          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,
          +                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}]

          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,
          -                     extnValue = [48,24,129,22,112,101,116,101|...]}]},
          +                     extnValue = [48,24,129,22,112,101,116,101|...]}]},
               signatureAlgorithm =
          -        #'AlgorithmIdentifier'{
          -            algorithm = {1,2,840,113549,1,1,5},
          -            parameters = <<5,0>>},
          +        #'AlgorithmIdentifier'{
          +            algorithm = {1,2,840,113549,1,1,5},
          +            parameters = <<5,0>>},
               signature =
               <<163,186,7,163,216,152,63,47,154,234,139,73,154,96,120,
          -    165,2,52,196,195,109,167,192,...>>}

          Parts of certificates can be decoded with public_key:der_decode/2, using the + 165,2,52,196,195,109,167,192,...>>}

          Parts of certificates can be decoded with public_key:der_decode/2, using the ASN.1 type of that part. However, an application-specific certificate extension requires application-specific ASN.1 decode/encode-functions. In the recent example, the first value of rdnSequence is of ASN.1 type -'X520CommonName'. ({2,5,4,3} = ?id-at-commonName):

          public_key:der_decode('X520CommonName', <<19,8,101,114,108,97,110,103,67,65>>).
          -{printableString,"erlangCA"}

          However, certificates can also be decoded using pkix_decode_cert/2, which can -customize and recursively decode standard parts of a certificate:

          3> {_, DerCert, _} = CertEntry1.
          4> public_key:pkix_decode_cert(DerCert, otp).
          -#'OTPCertificate'{
          +'X520CommonName'. ({2,5,4,3} = ?id-at-commonName):

          public_key:der_decode('X520CommonName', <<19,8,101,114,108,97,110,103,67,65>>).
          +{printableString,"erlangCA"}

          However, certificates can also be decoded using pkix_decode_cert/2, which can +customize and recursively decode standard parts of a certificate:

          3> {_, DerCert, _} = CertEntry1.
          4> public_key:pkix_decode_cert(DerCert, otp).
          +#'OTPCertificate'{
               tbsCertificate =
          -        #'OTPTBSCertificate'{
          +        #'OTPTBSCertificate'{
                       version = v3,serialNumber = 16614168075301976214,
                       signature =
          -                #'SignatureAlgorithm'{
          -                    algorithm = {1,2,840,113549,1,1,5},
          -                    parameters = 'NULL'},
          +                #'SignatureAlgorithm'{
          +                    algorithm = {1,2,840,113549,1,1,5},
          +                    parameters = 'NULL'},
                       issuer =
          -                {rdnSequence,
          -                    [[#'AttributeTypeAndValue'{
          -                          type = {2,5,4,3},
          -                          value = {printableString,"erlangCA"}}],
          -                     [#'AttributeTypeAndValue'{
          -                          type = {2,5,4,11},
          -                          value = {printableString,"Erlang OTP"}}],
          -                     [#'AttributeTypeAndValue'{
          -                          type = {2,5,4,10},
          -                          value = {printableString,"Ericsson AB"}}],
          -                     [#'AttributeTypeAndValue'{
          -                          type = {2,5,4,7},
          -                          value = {printableString,"Stockholm"}}],
          -                     [#'AttributeTypeAndValue'{type = {2,5,4,6},value = "SE"}],
          -                     [#'AttributeTypeAndValue'{
          -                          type = {1,2,840,113549,1,9,1},
          -                          value = "peter@erix.ericsson.se"}]]},
          +                {rdnSequence,
          +                    [[#'AttributeTypeAndValue'{
          +                          type = {2,5,4,3},
          +                          value = {printableString,"erlangCA"}}],
          +                     [#'AttributeTypeAndValue'{
          +                          type = {2,5,4,11},
          +                          value = {printableString,"Erlang OTP"}}],
          +                     [#'AttributeTypeAndValue'{
          +                          type = {2,5,4,10},
          +                          value = {printableString,"Ericsson AB"}}],
          +                     [#'AttributeTypeAndValue'{
          +                          type = {2,5,4,7},
          +                          value = {printableString,"Stockholm"}}],
          +                     [#'AttributeTypeAndValue'{type = {2,5,4,6},value = "SE"}],
          +                     [#'AttributeTypeAndValue'{
          +                          type = {1,2,840,113549,1,9,1},
          +                          value = "peter@erix.ericsson.se"}]]},
                       validity =
          -                #'Validity'{
          -                    notBefore = {utcTime,"080109082929Z"},
          -                    notAfter = {utcTime,"080208082929Z"}},
          +                #'Validity'{
          +                    notBefore = {utcTime,"080109082929Z"},
          +                    notAfter = {utcTime,"080208082929Z"}},
                       subject =
          -                {rdnSequence,
          -                    [[#'AttributeTypeAndValue'{
          -                          type = {2,5,4,3},
          -                          value = {printableString,"erlangCA"}}],
          -                     [#'AttributeTypeAndValue'{
          -                          type = {2,5,4,11},
          -                          value = {printableString,"Erlang OTP"}}],
          -                     [#'AttributeTypeAndValue'{
          -                          type = {2,5,4,10},
          -                          value = {printableString,"Ericsson AB"}}],
          -                     [#'AttributeTypeAndValue'{
          -                          type = {2,5,4,7},
          -                          value = {printableString,"Stockholm"}}],
          -                     [#'AttributeTypeAndValue'{type = {2,5,4,6},value = "SE"}],
          -                     [#'AttributeTypeAndValue'{
          -                          type = {1,2,840,113549,1,9,1},
          -                          value = "peter@erix.ericsson.se"}]]},
          +                {rdnSequence,
          +                    [[#'AttributeTypeAndValue'{
          +                          type = {2,5,4,3},
          +                          value = {printableString,"erlangCA"}}],
          +                     [#'AttributeTypeAndValue'{
          +                          type = {2,5,4,11},
          +                          value = {printableString,"Erlang OTP"}}],
          +                     [#'AttributeTypeAndValue'{
          +                          type = {2,5,4,10},
          +                          value = {printableString,"Ericsson AB"}}],
          +                     [#'AttributeTypeAndValue'{
          +                          type = {2,5,4,7},
          +                          value = {printableString,"Stockholm"}}],
          +                     [#'AttributeTypeAndValue'{type = {2,5,4,6},value = "SE"}],
          +                     [#'AttributeTypeAndValue'{
          +                          type = {1,2,840,113549,1,9,1},
          +                          value = "peter@erix.ericsson.se"}]]},
                       subjectPublicKeyInfo =
          -                #'OTPSubjectPublicKeyInfo'{
          +                #'OTPSubjectPublicKeyInfo'{
                               algorithm =
          -                        #'PublicKeyAlgorithm'{
          -                            algorithm = {1,2,840,113549,1,1,1},
          -                            parameters = 'NULL'},
          +                        #'PublicKeyAlgorithm'{
          +                            algorithm = {1,2,840,113549,1,1,1},
          +                            parameters = 'NULL'},
                               subjectPublicKey =
          -                        #'RSAPublicKey'{
          +                        #'RSAPublicKey'{
                                       modulus =
                                           1431267547247997...37419,
          -                            publicExponent = 65537}},
          +                            publicExponent = 65537}},
                       issuerUniqueID = asn1_NOVALUE,
                       subjectUniqueID = asn1_NOVALUE,
                       extensions =
          -                [#'Extension'{
          -                     extnID = {2,5,29,19},
          +                [#'Extension'{
          +                     extnID = {2,5,29,19},
                                critical = true,
                                extnValue =
          -                         #'BasicConstraints'{
          -                             cA = true,pathLenConstraint = asn1_NOVALUE}},
          -                 #'Extension'{
          -                     extnID = {2,5,29,15},
          +                         #'BasicConstraints'{
          +                             cA = true,pathLenConstraint = asn1_NOVALUE}},
          +                 #'Extension'{
          +                     extnID = {2,5,29,15},
                                critical = false,
          -                     extnValue = [keyCertSign,cRLSign]},
          -                 #'Extension'{
          -                     extnID = {2,5,29,14},
          +                     extnValue = [keyCertSign,cRLSign]},
          +                 #'Extension'{
          +                     extnID = {2,5,29,14},
                                critical = false,
          -                     extnValue = [27,217,65,152,6,30,142,132,245|...]},
          -                 #'Extension'{
          -                     extnID = {2,5,29,17},
          +                     extnValue = [27,217,65,152,6,30,142,132,245|...]},
          +                 #'Extension'{
          +                     extnID = {2,5,29,17},
                                critical = false,
          -                     extnValue = [{rfc822Name,"peter@erix.ericsson.se"}]}]},
          +                     extnValue = [{rfc822Name,"peter@erix.ericsson.se"}]}]},
               signatureAlgorithm =
          -        #'SignatureAlgorithm'{
          -            algorithm = {1,2,840,113549,1,1,5},
          -            parameters = 'NULL'},
          +        #'SignatureAlgorithm'{
          +            algorithm = {1,2,840,113549,1,1,5},
          +            parameters = 'NULL'},
               signature =
                    <<163,186,7,163,216,152,63,47,154,234,139,73,154,96,120,
          -           165,2,52,196,195,109,167,192,...>>}

          This call is equivalent to public_key:pem_entry_decode(CertEntry1):

          5> public_key:pkix_decode_cert(DerCert, plain).
          -#'Certificate'{ ...}

          + 165,2,52,196,195,109,167,192,...>>}

          This call is equivalent to public_key:pem_entry_decode(CertEntry1):

          5> public_key:pkix_decode_cert(DerCert, plain).
          +#'Certificate'{ ...}

          @@ -391,17 +391,17 @@

          the result to a file. For example, assume that you have PubKey = 'RSAPublicKey'{}. Then you can create a PEM-"RSA PUBLIC KEY" file (ASN.1 type 'RSAPublicKey') or a PEM-"PUBLIC KEY" file -('SubjectPublicKeyInfo' ASN.1 type).

          The second element of the PEM-entry is the ASN.1 DER encoded key data:

          1> PemEntry = public_key:pem_entry_encode('RSAPublicKey', RSAPubKey).
          -{'RSAPublicKey', <<48,72,...>>, not_encrypted}
          +('SubjectPublicKeyInfo' ASN.1 type).

          The second element of the PEM-entry is the ASN.1 DER encoded key data:

          1> PemEntry = public_key:pem_entry_encode('RSAPublicKey', RSAPubKey).
          +{'RSAPublicKey', <<48,72,...>>, not_encrypted}
           
          -2> PemBin = public_key:pem_encode([PemEntry]).
          +2> PemBin = public_key:pem_encode([PemEntry]).
           <<"-----BEGIN RSA PUBLIC KEY-----\nMEgC...>>
           
           3> file:write_file("rsa_pub_key.pem", PemBin).
          -ok

          or:

          1> PemEntry = public_key:pem_entry_encode('SubjectPublicKeyInfo', RSAPubKey).
          -{'SubjectPublicKeyInfo', <<48,92...>>, not_encrypted}
          +ok

          or:

          1> PemEntry = public_key:pem_entry_encode('SubjectPublicKeyInfo', RSAPubKey).
          +{'SubjectPublicKeyInfo', <<48,92...>>, not_encrypted}
           
          -2> PemBin = public_key:pem_encode([PemEntry]).
          +2> PemBin = public_key:pem_encode([PemEntry]).
           <<"-----BEGIN PUBLIC KEY-----\nMFw...>>
           
           3> file:write_file("pub_key.pem", PemBin).
          @@ -411,9 +411,9 @@ 

          RSA Public-Key Cryptography

          -

          Suppose you have the following private key and a corresponding public key:

          • PrivateKey = #'RSAPrivateKey{}' and the plaintext Msg = binary()
          • PublicKey = #'RSAPublicKey'{}

          Then you can proceed as follows:

          Encrypt with the private key:

          RsaEncrypted = public_key:encrypt_private(Msg, PrivateKey),
          -Msg = public_key:decrypt_public(RsaEncrypted, PublicKey),

          Encrypt with the public key:

          RsaEncrypted = public_key:encrypt_public(Msg, PublicKey),
          -Msg = public_key:decrypt_private(RsaEncrypted, PrivateKey),

          Note

          You normally do only one of the encrypt or decrypt operations, and the peer +

          Suppose you have the following private key and a corresponding public key:

          • PrivateKey = #'RSAPrivateKey{}' and the plaintext Msg = binary()
          • PublicKey = #'RSAPublicKey'{}

          Then you can proceed as follows:

          Encrypt with the private key:

          RsaEncrypted = public_key:encrypt_private(Msg, PrivateKey),
          +Msg = public_key:decrypt_public(RsaEncrypted, PublicKey),

          Encrypt with the public key:

          RsaEncrypted = public_key:encrypt_public(Msg, PublicKey),
          +Msg = public_key:decrypt_private(RsaEncrypted, PrivateKey),

          Note

          You normally do only one of the encrypt or decrypt operations, and the peer does the other. This normally used in legacy applications as a primitive digital signature.

          Warning

          This legacy algorithm is broken although there exists a software prevention when using appropriate OpenSSL cryptolib with Erlang/OTP it is hard to @@ -424,12 +424,12 @@

          Digital Signatures

          Suppose you have the following private key and a corresponding public key:

          • PrivateKey = #'RSAPrivateKey{}' or #'DSAPrivateKey'{} and the plaintext -Msg = binary()
          • PublicKey = #'RSAPublicKey'{} or {integer(), #'DssParams'{}}

          Then you can proceed as follows:

          Signature = public_key:sign(Msg, sha, PrivateKey),
          -true = public_key:verify(Msg, sha, Signature, PublicKey),

          Note

          You normally do only one of the sign or verify operations, and the peer does +Msg = binary()

        • PublicKey = #'RSAPublicKey'{} or {integer(), #'DssParams'{}}

        Then you can proceed as follows:

        Signature = public_key:sign(Msg, sha, PrivateKey),
        +true = public_key:verify(Msg, sha, Signature, PublicKey),

        Note

        You normally do only one of the sign or verify operations, and the peer does the other.

        It can be appropriate to calculate the message digest before calling sign or -verify, and then use none as second argument:

        Digest = crypto:sha(Msg),
        -Signature = public_key:sign(Digest, none, PrivateKey),
        -true = public_key:verify(Digest, none, Signature, PublicKey),

        +verify, and then use none as second argument:

        Digest = crypto:sha(Msg),
        +Signature = public_key:sign(Digest, none, PrivateKey),
        +true = public_key:verify(Digest, none, Signature, PublicKey),

        @@ -520,9 +520,9 @@

        Note

        Other applications like ssl/tls or https might have options that are passed down to the public_key:pkix_verify_hostname. You will probably not have to call it directly

        Suppose our client expects to connect to the web server https://www.example.net. -This URI is therefore the Reference IDs of the client. The call will be:

         public_key:pkix_verify_hostname(CertFromHost,
        -                                 [{uri_id, "https://www.example.net"}
        -                                 ]).

        The call will return true or false depending on the check. The caller do not +This URI is therefore the Reference IDs of the client. The call will be:

         public_key:pkix_verify_hostname(CertFromHost,
        +                                 [{uri_id, "https://www.example.net"}
        +                                 ]).

        The call will return true or false depending on the check. The caller do not need to handle the matching rules in the rfc. The matching will proceed as:

        • If there is a Subject Alternate Name field, the {uri_id,string()} in the function call will be compared to any {uniformResourceIdentifier,string()} in the Certificate field. If the two strings() are equal (case insensitive), @@ -545,25 +545,25 @@

          either a string/0 to be matched to each CN-name or the atom default which will invoke the default fqdn extraction function. The return value undefined removes the current URI from the fqdn extraction.

           ...
          - Extract = fun({uri_id, "myspecial://"++HostName}) -> HostName;
          -              (_Else) -> default
          + Extract = fun({uri_id, "myspecial://"++HostName}) -> HostName;
          +              (_Else) -> default
                      end,
            ...
          - public_key:pkix_verify_hostname(CertFromHost, RefIDs,
          -                                 [{fqdn_fun, Extract}])
          + public_key:pkix_verify_hostname(CertFromHost, RefIDs,
          +                                 [{fqdn_fun, Extract}])
            ...

          Re-defining the match operation

          The default matching handles dns_id and uri_id. In an uri_id the value is tested for equality with a value from the Subject Alternate Name. If some other kind of matching is needed, use the match_fun option.

          The match_fun takes two arguments and returns either true, false or default. The value default will invoke the default match function.

           ...
          - Match = fun({uri_id,"myspecial://"++A},
          -             {uniformResourceIdentifier,"myspecial://"++B}) ->
          -                                                    my_match(A,B);
          -            (_RefID, _PresentedID) ->
          + Match = fun({uri_id,"myspecial://"++A},
          +             {uniformResourceIdentifier,"myspecial://"++B}) ->
          +                                                    my_match(A,B);
          +            (_RefID, _PresentedID) ->
                                           default
                    end,
            ...
          - public_key:pkix_verify_hostname(CertFromHost, RefIDs,
          -                                 [{match_fun, Match}]),
          + public_key:pkix_verify_hostname(CertFromHost, RefIDs,
          +                                 [{match_fun, Match}]),
            ...

          In case of a match operation between a ReferenceID and a CN value from the Subject field, the first argument to the fun is the extracted hostname from the ReferenceID, and the second argument is the tuple {cn, string()} taken @@ -584,19 +584,19 @@

          identifier. ..."

    The purpose is to have a mechanism for a human to accept an otherwise faulty Certificate. In for example a web browser, you could get a question like

    Warning: you wanted to visit the site www.example.com, but the certificate is for shop.example.com. Accept anyway (yes/no)?"

    This could be accomplished with the option fail_callback which will be called -if the hostname verification fails:

     -include_lib("public_key/include/public_key.hrl"). % Record def
    +if the hostname verification fails:

     -include_lib("public_key/include/public_key.hrl"). % Record def
      ...
    - Fail = fun(#'OTPCertificate'{}=C) ->
    -              case in_my_cache(C) orelse my_accept(C) of
    + Fail = fun(#'OTPCertificate'{}=C) ->
    +              case in_my_cache(C) orelse my_accept(C) of
                       true ->
    -                       enter_my_cache(C),
    +                       enter_my_cache(C),
                            true;
                       false ->
                            false
              end,
      ...
    - public_key:pkix_verify_hostname(CertFromHost, RefIDs,
    -                                 [{fail_callback, Fail}]),
    + public_key:pkix_verify_hostname(CertFromHost, RefIDs,
    +                                 [{fail_callback, Fail}]),
      ...
    diff --git a/prs/9045/lib/reltool-1.0.1/doc/html/reltool.epub b/prs/9045/lib/reltool-1.0.1/doc/html/reltool.epub index a55ba09b202f..b941ec8fe43b 100644 Binary files a/prs/9045/lib/reltool-1.0.1/doc/html/reltool.epub and b/prs/9045/lib/reltool-1.0.1/doc/html/reltool.epub differ diff --git a/prs/9045/lib/reltool-1.0.1/doc/html/reltool_examples.html b/prs/9045/lib/reltool-1.0.1/doc/html/reltool_examples.html index 1c0621a8f8c1..57e45f112639 100644 --- a/prs/9045/lib/reltool-1.0.1/doc/html/reltool_examples.html +++ b/prs/9045/lib/reltool-1.0.1/doc/html/reltool_examples.html @@ -141,500 +141,500 @@

    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).
    +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)
    +
    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,[]}]},
    -          {app,hipe,
    -               [{vsn,"3.15.4"},
    -                {lib_dir,"/usr/local/lib/erlang/lib/hipe-3.15.4"},
    -                {mod,cerl_cconv,[]},
    -                {mod,cerl_closurean,[]},
    -                {mod,cerl_hipeify,[]},
    -                {mod,cerl_lib,[]},
    -                {mod,cerl_messagean,[]},
    -                {mod,cerl_pmatch,[]},
    -                {mod,cerl_prettypr,[]},
    -                {mod,cerl_to_icode,[]},
    -                {mod,cerl_typean,...},
    -                {mod,...},
    -                {...}|...]},
    -          {app,inets,
    -               [{incl_cond,include},
    -                {vsn,"6.3.9"},
    -                {lib_dir,"/usr/local/lib/erlang/lib/inets-6.3.9"},
    -                {mod,ftp,[]},
    -                {mod,ftp_progress,[]},
    -                {mod,ftp_response,[]},
    -                {mod,ftp_sup,[]},
    -                {mod,http_chunk,[]},
    -                {mod,http_request,[]},
    -                {mod,http_response,...},
    -                {mod,...},
    -                {...}|...]},
    -          {app,kernel,
    -               [{vsn,"5.2"},
    -                {lib_dir,"/usr/local/lib/erlang/lib/kernel-5.2"},
    -                {mod,application,[]},
    -                {mod,application_controller,[]},
    -                {mod,application_master,[]},
    -                {mod,application_starter,[]},
    -                {mod,auth,[]},
    -                {mod,code,[]},
    -                {mod,code_server,...},
    -                {mod,...},
    -                {...}|...]},
    -          {app,mnesia,[{incl_cond,exclude}]},
    -          {app,runtime_tools,[{incl_cond,exclude}]},
    -          {app,sasl,
    -               [{vsn,"3.0.3"},
    -                {lib_dir,"/usr/local/lib/erlang/lib/sasl-3.0.3"},
    -                {mod,alarm_handler,[]},
    -                {mod,erlsrv,[]},
    -                {mod,format_lib_supp,[]},
    -                {mod,misc_supp,...},
    -                {mod,...},
    -                {...}|...]},
    -          {app,ssl,[{incl_cond,exclude}]},
    -          {app,stdlib,
    -               [{vsn,"3.3"},
    -                {lib_dir,"/usr/local/lib/erlang/lib/stdlib-3.3"},
    -                {mod,array,[]},
    -                {mod,base64,...},
    -                {mod,...},
    -                {...}|...]},
    -          {app,syntax_tools,[{incl_cond,exclude}]},
    -          {app,tools,
    -               [{vsn,"2.9.1"},{lib_dir,[...]},{mod,...},{...}|...]},
    -          {boot_rel,"start_clean"},
    -          {rel,"start_clean","1.0",[]},
    -          {rel,"start_sasl","1.0",[...]},
    -          {emu_name,"beam"},
    -          {relocatable,true},
    -          {profile,...},
    -          {...}|...]}}
    +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,[]}]},
    +          {app,hipe,
    +               [{vsn,"3.15.4"},
    +                {lib_dir,"/usr/local/lib/erlang/lib/hipe-3.15.4"},
    +                {mod,cerl_cconv,[]},
    +                {mod,cerl_closurean,[]},
    +                {mod,cerl_hipeify,[]},
    +                {mod,cerl_lib,[]},
    +                {mod,cerl_messagean,[]},
    +                {mod,cerl_pmatch,[]},
    +                {mod,cerl_prettypr,[]},
    +                {mod,cerl_to_icode,[]},
    +                {mod,cerl_typean,...},
    +                {mod,...},
    +                {...}|...]},
    +          {app,inets,
    +               [{incl_cond,include},
    +                {vsn,"6.3.9"},
    +                {lib_dir,"/usr/local/lib/erlang/lib/inets-6.3.9"},
    +                {mod,ftp,[]},
    +                {mod,ftp_progress,[]},
    +                {mod,ftp_response,[]},
    +                {mod,ftp_sup,[]},
    +                {mod,http_chunk,[]},
    +                {mod,http_request,[]},
    +                {mod,http_response,...},
    +                {mod,...},
    +                {...}|...]},
    +          {app,kernel,
    +               [{vsn,"5.2"},
    +                {lib_dir,"/usr/local/lib/erlang/lib/kernel-5.2"},
    +                {mod,application,[]},
    +                {mod,application_controller,[]},
    +                {mod,application_master,[]},
    +                {mod,application_starter,[]},
    +                {mod,auth,[]},
    +                {mod,code,[]},
    +                {mod,code_server,...},
    +                {mod,...},
    +                {...}|...]},
    +          {app,mnesia,[{incl_cond,exclude}]},
    +          {app,runtime_tools,[{incl_cond,exclude}]},
    +          {app,sasl,
    +               [{vsn,"3.0.3"},
    +                {lib_dir,"/usr/local/lib/erlang/lib/sasl-3.0.3"},
    +                {mod,alarm_handler,[]},
    +                {mod,erlsrv,[]},
    +                {mod,format_lib_supp,[]},
    +                {mod,misc_supp,...},
    +                {mod,...},
    +                {...}|...]},
    +          {app,ssl,[{incl_cond,exclude}]},
    +          {app,stdlib,
    +               [{vsn,"3.3"},
    +                {lib_dir,"/usr/local/lib/erlang/lib/stdlib-3.3"},
    +                {mod,array,[]},
    +                {mod,base64,...},
    +                {mod,...},
    +                {...}|...]},
    +          {app,syntax_tools,[{incl_cond,exclude}]},
    +          {app,tools,
    +               [{vsn,"2.9.1"},{lib_dir,[...]},{mod,...},{...}|...]},
    +          {boot_rel,"start_clean"},
    +          {rel,"start_clean","1.0",[]},
    +          {rel,"start_sasl","1.0",[...]},
    +          {emu_name,"beam"},
    +          {relocatable,true},
    +          {profile,...},
    +          {...}|...]}}
     7>
    -7> reltool:get_config([{sys, [{profile, embedded}]}], true, false).
    -{ok,{sys,[{root_dir,"/usr/local/lib/erlang"},
    -          {lib_dirs,[]},
    -          {mod_cond,all},
    -          {incl_cond,derived},
    -          {boot_rel,"start_clean"},
    -          {rel,"start_clean","1.0",[]},
    -          {rel,"start_sasl","1.0",[sasl]},
    -          {emu_name,"beam"},
    -          {relocatable,true},
    -          {profile,embedded},
    -          {incl_sys_filters,["^bin","^erts","^lib","^releases"]},
    -          {excl_sys_filters,["^bin/(erlc|dialyzer|typer)(|\\.exe)$",
    +7> reltool:get_config([{sys, [{profile, embedded}]}], true, false).
    +{ok,{sys,[{root_dir,"/usr/local/lib/erlang"},
    +          {lib_dirs,[]},
    +          {mod_cond,all},
    +          {incl_cond,derived},
    +          {boot_rel,"start_clean"},
    +          {rel,"start_clean","1.0",[]},
    +          {rel,"start_sasl","1.0",[sasl]},
    +          {emu_name,"beam"},
    +          {relocatable,true},
    +          {profile,embedded},
    +          {incl_sys_filters,["^bin","^erts","^lib","^releases"]},
    +          {excl_sys_filters,["^bin/(erlc|dialyzer|typer)(|\\.exe)$",
                                  "^erts.*/bin/(erlc|dialyzer|typer)(|\\.exe)$",
    -                             "^erts.*/bin/.*(debug|pdb)"]},
    -          {incl_app_filters,["^ebin","^include","^priv"]},
    -          {excl_app_filters,[]},
    -          {rel_app_type,permanent},
    -          {embedded_app_type,load},
    -          {app_file,keep},
    -          {debug_info,keep}]}}
    +                             "^erts.*/bin/.*(debug|pdb)"]},
    +          {incl_app_filters,["^ebin","^include","^priv"]},
    +          {excl_app_filters,[]},
    +          {rel_app_type,permanent},
    +          {embedded_app_type,load},
    +          {app_file,keep},
    +          {debug_info,keep}]}}
     8>
    -8> reltool:get_config([{sys, [{profile, standalone}]}], true, false).
    -{ok,{sys,[{root_dir,"/usr/local/lib/erlang"},
    -          {lib_dirs,[]},
    -          {mod_cond,all},
    -          {incl_cond,derived},
    -          {boot_rel,"start_clean"},
    -          {rel,"start_clean","1.0",[]},
    -          {rel,"start_sasl","1.0",[sasl]},
    -          {emu_name,"beam"},
    -          {relocatable,true},
    -          {profile,standalone},
    -          {incl_sys_filters,["^bin/(erl|epmd)(|\\.exe|\\.ini)$",
    -                             "^bin/start(|_clean).boot$","^erts.*/bin","^lib$"]},
    -          {excl_sys_filters,["^erts.*/bin/(erlc|dialyzer|typer)(|\\.exe)$",
    +8> reltool:get_config([{sys, [{profile, standalone}]}], true, false).
    +{ok,{sys,[{root_dir,"/usr/local/lib/erlang"},
    +          {lib_dirs,[]},
    +          {mod_cond,all},
    +          {incl_cond,derived},
    +          {boot_rel,"start_clean"},
    +          {rel,"start_clean","1.0",[]},
    +          {rel,"start_sasl","1.0",[sasl]},
    +          {emu_name,"beam"},
    +          {relocatable,true},
    +          {profile,standalone},
    +          {incl_sys_filters,["^bin/(erl|epmd)(|\\.exe|\\.ini)$",
    +                             "^bin/start(|_clean).boot$","^erts.*/bin","^lib$"]},
    +          {excl_sys_filters,["^erts.*/bin/(erlc|dialyzer|typer)(|\\.exe)$",
                                  "^erts.*/bin/(start|escript|to_erl|run_erl)(|\\.exe)$",
    -                             "^erts.*/bin/.*(debug|pdb)"]},
    -          {incl_app_filters,["^ebin","^priv"]},
    -          {excl_app_filters,["^ebin/.*\\.appup$"]},
    -          {rel_app_type,permanent},
    -          {app_file,keep},
    -          {debug_info,keep}]}}

    + "^erts.*/bin/.*(debug|pdb)"]}, + {incl_app_filters,["^ebin","^priv"]}, + {excl_app_filters,["^ebin/.*\\.appup$"]}, + {rel_app_type,permanent}, + {app_file,keep}, + {debug_info,keep}]}}

    Generate release and script files

    -
    Erlang/OTP 20 [erts-10.0] [source-c13b302] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10]
    -[hipe] [kernel-poll:false]
    -Eshell V10.0  (abort with ^G)
    +
    Erlang/OTP 20 [erts-10.0] [source-c13b302] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10]
    +[hipe] [kernel-poll:false]
    +Eshell V10.0  (abort with ^G)
     1>
    -1> {ok, Server} = reltool:start_server([{config,
    -                                         {sys,
    -                                          [{boot_rel, "NAME"},
    -                                           {rel, "NAME", "VSN",
    -                                            [sasl],
    -                                            [{load_dot_erlang, false}]}]}}]).
    -{ok,<0.1288.0>}
    +1> {ok, Server} = reltool:start_server([{config,
    +                                         {sys,
    +                                          [{boot_rel, "NAME"},
    +                                           {rel, "NAME", "VSN",
    +                                            [sasl],
    +                                            [{load_dot_erlang, false}]}]}}]).
    +{ok,<0.1288.0>}
     2>
    -2> reltool:get_config(Server).
    -{ok,{sys,[{boot_rel,"NAME"},
    -          {rel,"NAME","VSN",[sasl]}]}}
    +2> reltool:get_config(Server).
    +{ok,{sys,[{boot_rel,"NAME"},
    +          {rel,"NAME","VSN",[sasl]}]}}
     3>
    -3> reltool:get_rel(Server, "NAME").
    -{ok,{release,{"NAME","VSN"},
    -             {erts,"10.0"},
    -             [{kernel,"5.2"},{stdlib,"3.3"},{sasl,"3.0.3"}]}}
    +3> reltool:get_rel(Server, "NAME").
    +{ok,{release,{"NAME","VSN"},
    +             {erts,"10.0"},
    +             [{kernel,"5.2"},{stdlib,"3.3"},{sasl,"3.0.3"}]}}
     4>
    -4> reltool:get_script(Server, "NAME").
    -{ok,{script,{"NAME","VSN"},
    -            [{preLoaded,[erl_prim_loader,erl_tracer,erlang,
    +4> reltool:get_script(Server, "NAME").
    +{ok,{script,{"NAME","VSN"},
    +            [{preLoaded,[erl_prim_loader,erl_tracer,erlang,
                              erts_code_purger,erts_dirty_process_signal_handler,
                              erts_internal,erts_literal_area_collector,init,erl_init,
    -                         prim_eval,prim_file,prim_inet,prim_zip,zlib]},
    -             {progress,preloaded},
    -             {path,["$ROOT/lib/kernel-5.2/ebin",
    -                    "$ROOT/lib/stdlib-3.3/ebin"]},
    -             {primLoad,[error_handler]},
    -             {kernel_load_completed},
    -             {progress,kernel_load_completed},
    -             {path,["$ROOT/lib/kernel-5.2/ebin"]},
    -             {primLoad,[application,application_controller,
    +                         prim_eval,prim_file,prim_inet,prim_zip,zlib]},
    +             {progress,preloaded},
    +             {path,["$ROOT/lib/kernel-5.2/ebin",
    +                    "$ROOT/lib/stdlib-3.3/ebin"]},
    +             {primLoad,[error_handler]},
    +             {kernel_load_completed},
    +             {progress,kernel_load_completed},
    +             {path,["$ROOT/lib/kernel-5.2/ebin"]},
    +             {primLoad,[application,application_controller,
                             application_master,application_starter,auth,code,
                             code_server,disk_log,disk_log_1,disk_log_server,
    -                        disk_log_sup,dist_ac,dist_util,erl_boot_server|...]},
    -             {path,["$ROOT/lib/stdlib-3.3/ebin"]},
    -             {primLoad,[array,base64,beam_lib,binary,c,calendar,dets,
    -                        dets_server,dets_sup,dets_utils,dets_v9,dict|...]},
    -             {path,["$ROOT/lib/sasl-3.0.3/ebin"]},
    -             {primLoad,[alarm_handler,erlsrv,format_lib_supp,misc_supp,
    +                        disk_log_sup,dist_ac,dist_util,erl_boot_server|...]},
    +             {path,["$ROOT/lib/stdlib-3.3/ebin"]},
    +             {primLoad,[array,base64,beam_lib,binary,c,calendar,dets,
    +                        dets_server,dets_sup,dets_utils,dets_v9,dict|...]},
    +             {path,["$ROOT/lib/sasl-3.0.3/ebin"]},
    +             {primLoad,[alarm_handler,erlsrv,format_lib_supp,misc_supp,
                             rb,rb_format_supp,release_handler,release_handler_1,sasl,
    -                        sasl_report|...]},
    -             {progress,modules_loaded},
    -             {path,["$ROOT/lib/kernel-5.2/ebin",
    -                    "$ROOT/lib/stdlib-3.3/ebin","$ROOT/lib/sasl-3.0.3/ebin"]},
    -             {kernelProcess,heart,{heart,start,[]}},
    -             {kernelProcess,error_logger,{error_logger,start_link,[]}},
    -             {kernelProcess,application_controller,
    -                            {application_controller,start,[{...}]}},
    -             {progress,init_kernel_started},
    -             {apply,{application,load,[...]}},
    -             {apply,{application,load,...}},
    -             {progress,applications_loaded},
    -             {apply,{...}},
    -             {apply,...},
    -             {...}|...]}}
    +                        sasl_report|...]},
    +             {progress,modules_loaded},
    +             {path,["$ROOT/lib/kernel-5.2/ebin",
    +                    "$ROOT/lib/stdlib-3.3/ebin","$ROOT/lib/sasl-3.0.3/ebin"]},
    +             {kernelProcess,heart,{heart,start,[]}},
    +             {kernelProcess,error_logger,{error_logger,start_link,[]}},
    +             {kernelProcess,application_controller,
    +                            {application_controller,start,[{...}]}},
    +             {progress,init_kernel_started},
    +             {apply,{application,load,[...]}},
    +             {apply,{application,load,...}},
    +             {progress,applications_loaded},
    +             {apply,{...}},
    +             {apply,...},
    +             {...}|...]}}
     5>
    -5> reltool:stop(Server).
    +5> reltool:stop(Server).
     ok

    Create a target system

    -
    Erlang/OTP 20 [erts-10.0] [source-c13b302] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10]
    -[hipe] [kernel-poll:false]
    -Eshell V10.0  (abort with ^G)
    +
    Erlang/OTP 20 [erts-10.0] [source-c13b302] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10]
    +[hipe] [kernel-poll:false]
    +Eshell V10.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, Spec} = reltool:get_target_spec([Config]).
    -{ok,[{create_dir,"releases",
    -         [{write_file,"start_erl.data","10.0 1.0\n"},
    -          {create_dir,"1.0",
    -              [{write_file,"start_clean.rel",
    -                   [37,37,32,114,101,108,32,103,101,110,101,114,97,116|...]},
    -               {write_file,"start_clean.script",
    -                   [37,37,32,115,99,114,105,112,116,32,103,101,110|...]},
    -               {write_file,"start_clean.boot",
    -                   <<131,104,3,119,6,115,99,114,105,112,116,104,...>>},
    -               {write_file,"start_sasl.rel",
    -                   [37,37,32,114,101,108,32,103,101,110,101|...]},
    -               {write_file,"start_sasl.script",
    -                   [37,37,32,115,99,114,105,112,116,32|...]},
    -               {write_file,"start_sasl.boot",
    -                   <<131,104,3,119,6,115,99,114,105,...>>}]}]},
    -     {create_dir,"bin",
    -         [{copy_file,"display_args.escript",
    -              "/usr/local/lib/erlang/lib/reltool-0.7.3/examples/display_args"},
    -          {copy_file,"display_args","erts-10.0/bin/escript"},
    -          {copy_file,"start","erts-10.0/bin/start"},
    -          {copy_file,"ct_run","erts-10.0/bin/ct_run"},
    -          {copy_file,"dialyzer","erts-10.0/bin/dialyzer"},
    -          {copy_file,"run_erl","erts-10.0/bin/run_erl"},
    -          {copy_file,"erl","erts-10.0/bin/dyn_erl"},
    -          {copy_file,"to_erl","erts-10.0/bin/to_erl"},
    -          {copy_file,"epmd","erts-10.0/bin/epmd"},
    -          {copy_file,"erlc","erts-10.0/bin/erlc"},
    -          {copy_file,"typer","erts-10.0/bin/typer"},
    -          {copy_file,"escript","erts-10.0/bin/escript"},
    -          {write_file,"start_clean.boot",<<131,104,3,119,6,115,...>>},
    -          {write_file,"start_sasl.boot",<<131,104,3,119,6,...>>},
    -          {write_file,"start.boot",<<131,104,3,119,...>>}]},
    -     {copy_file,"Install"},
    -     {create_dir,"misc",
    -         [{copy_file,"format_man_pages"}]},
    -     {create_dir,"usr",
    -         [{create_dir,"lib",
    -              [{copy_file,"liberl_interface_st.a"},
    -               {copy_file,"libic.a"},
    -               {copy_file,"liberl_interface.a"},
    -               {copy_file,"libei_st.a"},
    -               {copy_file,"libei.a"}]},
    -          {create_dir,"include",
    -              [{copy_file,"driver_int.h"},
    -               {copy_file,"ei_connect.h"},
    -               {copy_file,"ei.h"},
    -               {copy_file,"erl_nif_api_funcs.h"},
    -               {copy_file,"erl_fixed_size_int_types.h"},
    -               {copy_file,"erl_int_sizes_config.h"},
    -               {copy_file,"erl_interface.h"},
    -               {copy_file,"eicode.h"},
    -               {copy_file,"erl_driver.h"},
    -               {copy_file,"erlang.idl"},
    -               {copy_file,[...]},
    -               {copy_file,...},
    -               {...}]}]},
    -     {create_dir,"erts-10.0",
    -         [{create_dir,"bin",
    -              [{copy_file,"start"},
    -               {copy_file,"ct_run"},
    -               {copy_file,"erlexec"},
    -               {copy_file,"dialyzer"},
    -               {copy_file,"beam.smp"},
    -               {copy_file,"run_erl"},
    -               {copy_file,"erl","erts-10.0/bin/dyn_erl"},
    -               {copy_file,"to_erl"},
    -               {copy_file,"epmd"},
    -               {copy_file,"erl_child_setup"},
    -               {copy_file,"heart"},
    -               {copy_file,[...]},
    -               {copy_file,...},
    -               {...}|...]},
    -          {create_dir,"lib",
    -              [{create_dir,"internal",
    -                   [{copy_file,"liberts_internal.a"},
    -                    {copy_file,"liberts_internal_r.a"},
    -                    {copy_file,"libethread.a"},
    -                    {copy_file,"README"}]},
    -               ]},
    -          {create_dir,"src",[{copy_file,"setuid_socket_wrap.c"}]},
    -          {create_dir,"doc",[]},
    -          {create_dir,"man",[]},
    -          {create_dir,"include",
    -              [{create_dir,"internal",
    -                   [{create_dir,"i386",[{...}|...]},
    -                    {copy_file,"erl_errno.h"},
    -                    {copy_file,[...]},
    -                    {copy_file,...},
    -                    {...}|...]},
    -               {copy_file,"driver_int.h"},
    -               {copy_file,"erl_nif_api_funcs.h"},
    -               {copy_file,"erl_fixed_size_int_types.h"},
    -               {copy_file,"erl_int_sizes_config.h"},
    -               {copy_file,[...]},
    -               {copy_file,...},
    -               {...}]}]},
    -     {create_dir,"lib",
    -         [{create_dir,"compiler-7.0.4",
    -              [{create_dir,"src",
    -                   [{copy_file,"beam_flatten.erl"},
    -                    {copy_file,[...]},
    -                    {copy_file,...},
    -                    {...}|...]},
    -               {create_dir,"ebin",
    -                   [{copy_file,[...]},{copy_file,...},{...}|...]}]},
    -          {create_dir,"crypto-3.7.4",
    -              [{create_dir,"src",[{copy_file,[...]},{copy_file,...}]},
    -               {create_dir,"ebin",[{copy_file,...},{...}|...]}]},
    -          {create_dir,"crypto-3.7.4",
    -              [{create_dir,"priv",
    -                   [{create_dir,"lib",[{copy_file,[...]},{copy_file,...}]},
    -                    {create_dir,"obj",[{copy_file,...},{...}|...]}]}]},
    -          {create_dir,"erts-10.0",
    -              [{create_dir,"src",[{...}|...]},
    -               {create_dir,"ebin",[...]}]},
    -          {create_dir,"hipe-3.15.4",
    -              [{create_dir,"flow",[...]},
    -               {copy_file,[...]},
    -               {create_dir,...},
    -               {...}|...]},
    -          {create_dir,"inets-6.3.9",
    -              [{create_dir,[...],...},{create_dir,...},{...}]},
    -          {create_dir,"inets-6.3.9",
    -              [{create_dir,"priv",[{create_dir,[...],...}]},
    -               {create_dir,"include",[{copy_file,...},{...}]}]},
    -          {create_dir,"kernel-5.2",[{...}|...]},
    -          {create_dir,"kernel-5.2",
    -              [{create_dir,"include",[{...}|...]}]},
    -          {create_dir,[...],...},
    -          {create_dir,...},
    -          {create_dir,"stdlib-3.3",[{create_dir,...}]},
    -          ...]}]}
    +2> {ok, Spec} = reltool:get_target_spec([Config]).
    +{ok,[{create_dir,"releases",
    +         [{write_file,"start_erl.data","10.0 1.0\n"},
    +          {create_dir,"1.0",
    +              [{write_file,"start_clean.rel",
    +                   [37,37,32,114,101,108,32,103,101,110,101,114,97,116|...]},
    +               {write_file,"start_clean.script",
    +                   [37,37,32,115,99,114,105,112,116,32,103,101,110|...]},
    +               {write_file,"start_clean.boot",
    +                   <<131,104,3,119,6,115,99,114,105,112,116,104,...>>},
    +               {write_file,"start_sasl.rel",
    +                   [37,37,32,114,101,108,32,103,101,110,101|...]},
    +               {write_file,"start_sasl.script",
    +                   [37,37,32,115,99,114,105,112,116,32|...]},
    +               {write_file,"start_sasl.boot",
    +                   <<131,104,3,119,6,115,99,114,105,...>>}]}]},
    +     {create_dir,"bin",
    +         [{copy_file,"display_args.escript",
    +              "/usr/local/lib/erlang/lib/reltool-0.7.3/examples/display_args"},
    +          {copy_file,"display_args","erts-10.0/bin/escript"},
    +          {copy_file,"start","erts-10.0/bin/start"},
    +          {copy_file,"ct_run","erts-10.0/bin/ct_run"},
    +          {copy_file,"dialyzer","erts-10.0/bin/dialyzer"},
    +          {copy_file,"run_erl","erts-10.0/bin/run_erl"},
    +          {copy_file,"erl","erts-10.0/bin/dyn_erl"},
    +          {copy_file,"to_erl","erts-10.0/bin/to_erl"},
    +          {copy_file,"epmd","erts-10.0/bin/epmd"},
    +          {copy_file,"erlc","erts-10.0/bin/erlc"},
    +          {copy_file,"typer","erts-10.0/bin/typer"},
    +          {copy_file,"escript","erts-10.0/bin/escript"},
    +          {write_file,"start_clean.boot",<<131,104,3,119,6,115,...>>},
    +          {write_file,"start_sasl.boot",<<131,104,3,119,6,...>>},
    +          {write_file,"start.boot",<<131,104,3,119,...>>}]},
    +     {copy_file,"Install"},
    +     {create_dir,"misc",
    +         [{copy_file,"format_man_pages"}]},
    +     {create_dir,"usr",
    +         [{create_dir,"lib",
    +              [{copy_file,"liberl_interface_st.a"},
    +               {copy_file,"libic.a"},
    +               {copy_file,"liberl_interface.a"},
    +               {copy_file,"libei_st.a"},
    +               {copy_file,"libei.a"}]},
    +          {create_dir,"include",
    +              [{copy_file,"driver_int.h"},
    +               {copy_file,"ei_connect.h"},
    +               {copy_file,"ei.h"},
    +               {copy_file,"erl_nif_api_funcs.h"},
    +               {copy_file,"erl_fixed_size_int_types.h"},
    +               {copy_file,"erl_int_sizes_config.h"},
    +               {copy_file,"erl_interface.h"},
    +               {copy_file,"eicode.h"},
    +               {copy_file,"erl_driver.h"},
    +               {copy_file,"erlang.idl"},
    +               {copy_file,[...]},
    +               {copy_file,...},
    +               {...}]}]},
    +     {create_dir,"erts-10.0",
    +         [{create_dir,"bin",
    +              [{copy_file,"start"},
    +               {copy_file,"ct_run"},
    +               {copy_file,"erlexec"},
    +               {copy_file,"dialyzer"},
    +               {copy_file,"beam.smp"},
    +               {copy_file,"run_erl"},
    +               {copy_file,"erl","erts-10.0/bin/dyn_erl"},
    +               {copy_file,"to_erl"},
    +               {copy_file,"epmd"},
    +               {copy_file,"erl_child_setup"},
    +               {copy_file,"heart"},
    +               {copy_file,[...]},
    +               {copy_file,...},
    +               {...}|...]},
    +          {create_dir,"lib",
    +              [{create_dir,"internal",
    +                   [{copy_file,"liberts_internal.a"},
    +                    {copy_file,"liberts_internal_r.a"},
    +                    {copy_file,"libethread.a"},
    +                    {copy_file,"README"}]},
    +               ]},
    +          {create_dir,"src",[{copy_file,"setuid_socket_wrap.c"}]},
    +          {create_dir,"doc",[]},
    +          {create_dir,"man",[]},
    +          {create_dir,"include",
    +              [{create_dir,"internal",
    +                   [{create_dir,"i386",[{...}|...]},
    +                    {copy_file,"erl_errno.h"},
    +                    {copy_file,[...]},
    +                    {copy_file,...},
    +                    {...}|...]},
    +               {copy_file,"driver_int.h"},
    +               {copy_file,"erl_nif_api_funcs.h"},
    +               {copy_file,"erl_fixed_size_int_types.h"},
    +               {copy_file,"erl_int_sizes_config.h"},
    +               {copy_file,[...]},
    +               {copy_file,...},
    +               {...}]}]},
    +     {create_dir,"lib",
    +         [{create_dir,"compiler-7.0.4",
    +              [{create_dir,"src",
    +                   [{copy_file,"beam_flatten.erl"},
    +                    {copy_file,[...]},
    +                    {copy_file,...},
    +                    {...}|...]},
    +               {create_dir,"ebin",
    +                   [{copy_file,[...]},{copy_file,...},{...}|...]}]},
    +          {create_dir,"crypto-3.7.4",
    +              [{create_dir,"src",[{copy_file,[...]},{copy_file,...}]},
    +               {create_dir,"ebin",[{copy_file,...},{...}|...]}]},
    +          {create_dir,"crypto-3.7.4",
    +              [{create_dir,"priv",
    +                   [{create_dir,"lib",[{copy_file,[...]},{copy_file,...}]},
    +                    {create_dir,"obj",[{copy_file,...},{...}|...]}]}]},
    +          {create_dir,"erts-10.0",
    +              [{create_dir,"src",[{...}|...]},
    +               {create_dir,"ebin",[...]}]},
    +          {create_dir,"hipe-3.15.4",
    +              [{create_dir,"flow",[...]},
    +               {copy_file,[...]},
    +               {create_dir,...},
    +               {...}|...]},
    +          {create_dir,"inets-6.3.9",
    +              [{create_dir,[...],...},{create_dir,...},{...}]},
    +          {create_dir,"inets-6.3.9",
    +              [{create_dir,"priv",[{create_dir,[...],...}]},
    +               {create_dir,"include",[{copy_file,...},{...}]}]},
    +          {create_dir,"kernel-5.2",[{...}|...]},
    +          {create_dir,"kernel-5.2",
    +              [{create_dir,"include",[{...}|...]}]},
    +          {create_dir,[...],...},
    +          {create_dir,...},
    +          {create_dir,"stdlib-3.3",[{create_dir,...}]},
    +          ...]}]}
     3>
     3> TargetDir = "/tmp/my_target_dir".
     "/tmp/my_target_dir"
     4>
    -4> reltool:eval_target_spec(Spec, code:root_dir(), TargetDir).
    -{error,"/tmp/my_target_dir: no such file or directory"}
    +4> reltool:eval_target_spec(Spec, code:root_dir(), TargetDir).
    +{error,"/tmp/my_target_dir: no such file or directory"}
     5>
    -5> file:make_dir(TargetDir).
    +5> file:make_dir(TargetDir).
     ok
     6>
    -6> reltool:eval_target_spec(Spec, code:root_dir(), TargetDir).
    +6> reltool:eval_target_spec(Spec, code:root_dir(), TargetDir).
     ok
     7>
    -7> file:list_dir(TargetDir).
    -{ok,["bin","Install","lib","misc","usr","erts-10.0",
    -     "releases"]}
    +7> file:list_dir(TargetDir).
    +{ok,["bin","Install","lib","misc","usr","erts-10.0",
    +     "releases"]}
     8>
    -8> file:list_dir(filename:join([TargetDir,"lib"])).
    -{ok,["tools-2.9.1","inets-6.3.9",
    +8> file:list_dir(filename:join([TargetDir,"lib"])).
    +{ok,["tools-2.9.1","inets-6.3.9",
          "kernel-5.2","sasl-3.0.3",
          "crypto-3.7.4","erts-10.0",
    -     "stdlib-3.3","compiler-7.0.4"]}
    +     "stdlib-3.3","compiler-7.0.4"]}
     9>
    -9> file:make_dir("/tmp/yet_another_target_dir").
    +9> file:make_dir("/tmp/yet_another_target_dir").
     ok
     10>
    -10> reltool:create_target([Config], "/tmp/yet_another_target_dir").
    +10> reltool:create_target([Config], "/tmp/yet_another_target_dir").
     ok
     11>
    -11> file:list_dir("/tmp/yet_another_target_dir").
    -{ok,["bin","Install","lib","misc","usr","erts-10.0",
    -     "releases"]}
    +11>
    file:list_dir("/tmp/yet_another_target_dir"). +{ok,["bin","Install","lib","misc","usr","erts-10.0", + "releases"]}
    diff --git a/prs/9045/lib/runtime_tools-2.1.1/doc/html/dbg.html b/prs/9045/lib/runtime_tools-2.1.1/doc/html/dbg.html index 7a88734f6203..84abd2bebf80 100644 --- a/prs/9045/lib/runtime_tools-2.1.1/doc/html/dbg.html +++ b/prs/9045/lib/runtime_tools-2.1.1/doc/html/dbg.html @@ -137,16 +137,16 @@

    The Text Based Trace Facility

    This module implements a text based interface to the trace:process/4, trace:port/4, and trace:function/4 BIFs, simplifying tracing of functions, processes, ports, and messages.

    To quickly get started on tracing function calls you can use the -following code in the Erlang shell:

    1> dbg:tracer().  % Start the default trace message receiver
    -{ok,<0.90.0>}
    -2> dbg:p(all, c). % Set upp call tracing on all processes
    -{ok,[{matched,nonode@nohost,49}]}
    -3> dbg:tp(lists, seq, cx). %  Set up call and exception tracing on lists:seq/2,3
    -{ok,[{matched,nonode@nohost,2},{saved,cx}]}
    -4> lists:seq(1, 10).
    -(<0.88.0>) call lists:seq(1,10) ({erl_eval,do_apply,7,{"erl_eval.erl",904}})
    -[1,2,3,4,5,6,7,8,9,10]
    -(<0.88.0>) returned from lists:seq/2 -> [1,2,3,4,5,6,7,8,9,10]

    The utilities are also suitable to use in system testing on large systems, where +following code in the Erlang shell:

    1> dbg:tracer().  % Start the default trace message receiver
    +{ok,<0.90.0>}
    +2> dbg:p(all, c). % Set upp call tracing on all processes
    +{ok,[{matched,nonode@nohost,49}]}
    +3> dbg:tp(lists, seq, cx). %  Set up call and exception tracing on lists:seq/2,3
    +{ok,[{matched,nonode@nohost,2},{saved,cx}]}
    +4> lists:seq(1, 10).
    +(<0.88.0>) call lists:seq(1,10) ({erl_eval,do_apply,7,{"erl_eval.erl",904}})
    +[1,2,3,4,5,6,7,8,9,10]
    +(<0.88.0>) returned from lists:seq/2 -> [1,2,3,4,5,6,7,8,9,10]

    The utilities are also suitable to use in system testing on large systems, where other tools have too severe impact on the system performance. Some primitive support for sequential tracing is also included; see the advanced topics section.

    @@ -158,36 +158,36 @@

    To trace a call to a function with minimal fuss, call dbg:c(Module, Name, Arguments). dbg:c/3 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"}]

    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"}]

    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 the application_controller process.

    The dbg:c/4 function has a fourth argument for specifying the trace flags. -Here is how to only show message sending and receiving:

    2> dbg:c(application, which_applications, [], m).
    -(<0.96.0>) <0.45.0> ! {'$gen_call',{<0.96.0>,
    -                                    [alias|
    -                                     #Ref<0.0.12291.270031856.1478295555.230496>]},
    -                                   which_applications}
    -(<0.96.0>) << {[alias|#Ref<0.0.12291.270031856.1478295555.230496>],
    -               [{stdlib,"ERTS  CXC 138 10","5.2.1"},
    -                {kernel,"ERTS  CXC 138 10","9.2.2"}]}
    -[{stdlib,"ERTS  CXC 138 10","5.2.1"},
    - {kernel,"ERTS  CXC 138 10","9.2.2"}]

    +Here is how to only show message sending and receiving:

    2> dbg:c(application, which_applications, [], m).
    +(<0.96.0>) <0.45.0> ! {'$gen_call',{<0.96.0>,
    +                                    [alias|
    +                                     #Ref<0.0.12291.270031856.1478295555.230496>]},
    +                                   which_applications}
    +(<0.96.0>) << {[alias|#Ref<0.0.12291.270031856.1478295555.230496>],
    +               [{stdlib,"ERTS  CXC 138 10","5.2.1"},
    +                {kernel,"ERTS  CXC 138 10","9.2.2"}]}
    +[{stdlib,"ERTS  CXC 138 10","5.2.1"},
    + {kernel,"ERTS  CXC 138 10","9.2.2"}]

    @@ -195,35 +195,35 @@

    Another way of tracing from the shell is to explicitly start a tracer and set the trace flags of your choice on the processes you want to trace. -For example, here is how to trace messages and process events:

    1> Pid = spawn(fun() -> receive {From,Msg} -> From ! Msg end end).
    +For example, here is how to trace messages and process events:

    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]).
    -{ok,[{matched,nonode@nohost,1}]}
    -4> Pid ! {self(),hello}.
    -(<0.90.0>) << {<0.88.0>,hello}
    -{<0.88.0>,hello}
    -(<0.90.0>) <0.88.0> ! hello
    -(<0.90.0>) exit normal
    -5> flush().
    +2> dbg:tracer().
    +{ok,<0.92.0>}
    +3> dbg:p(Pid, [m,procs]).
    +{ok,[{matched,nonode@nohost,1}]}
    +4> Pid ! {self(),hello}.
    +(<0.90.0>) << {<0.88.0>,hello}
    +{<0.88.0>,hello}
    +(<0.90.0>) <0.88.0> ! hello
    +(<0.90.0>) exit normal
    +5> flush().
     Shell got hello
     ok

    In order to trace functions call, in addition to enabling the call trace flag for the process, it is also necessary to set a trace pattern for the functions -to trace.

    Example:

    1> dbg:tracer().
    -{ok,<0.90.0>}
    -2> dbg:p(all, call).
    -{ok,[{matched,nonode@nohost,49}]}
    -3> dbg:tp(lists, last, 1, []).
    -{ok,[{matched,nonode@nohost,1}]}
    -4> lists:last([a,b,c,d,e]).
    -(<0.88.0>) call lists:last([a,b,c,d,e])
    +to trace.

    Example:

    1> dbg:tracer().
    +{ok,<0.90.0>}
    +2> dbg:p(all, call).
    +{ok,[{matched,nonode@nohost,49}]}
    +3> dbg:tp(lists, last, 1, []).
    +{ok,[{matched,nonode@nohost,1}]}
    +4> lists:last([a,b,c,d,e]).
    +(<0.88.0>) call lists:last([a,b,c,d,e])
     e
    -5> dbg:tp(lists, last, 1, [{'_',[],[{return_trace}]}]).
    -{ok,[{matched,nonode@nohost,1},{saved,1}]}
    -6> lists:last([a,b,c,d,e]).
    -(<0.88.0>) call lists:last([a,b,c,d,e])
    -(<0.88.0>) returned from lists:last/1 -> e
    +5> dbg:tp(lists, last, 1, [{'_',[],[{return_trace}]}]).
    +{ok,[{matched,nonode@nohost,1},{saved,1}]}
    +6> lists:last([a,b,c,d,e]).
    +(<0.88.0>) call lists:last([a,b,c,d,e])
    +(<0.88.0>) returned from lists:last/1 -> e
     e

    @@ -237,21 +237,21 @@

    seq_trace and the same tracer function for both types of tracing can be used. The seq_trace messages can also be sent to a trace port for further analysis.

    As a match specification can turn on sequential tracing, the combination of dbg and seq_trace can be powerful. This brief example shows a session -where sequential tracing is used to trace the dbg module and the trace itself:

    1> dbg:tracer().
    -{ok,<0.30.0>}
    -2> {ok, Tracer} = dbg:get_tracer().
    -{ok,<0.31.0>}
    -3> seq_trace:set_system_tracer(Tracer).
    +where sequential tracing is used to trace the dbg module and the trace itself:

    1> dbg:tracer().
    +{ok,<0.30.0>}
    +2> {ok, Tracer} = dbg:get_tracer().
    +{ok,<0.31.0>}
    +3> seq_trace:set_system_tracer(Tracer).
     false
    -4> dbg:tp(dbg, get_tracer, 0, [{[],[],[{set_seq_token, send, true}]}]).
    -{ok,[{matched,nonode@nohost,1},{saved,1}]}
    -5> dbg:p(all,call).
    -{ok,[{matched,nonode@nohost,22}]}
    -6> dbg:get_tracer(), seq_trace:set_token([]).
    -(<0.25.0>) call dbg:get_tracer()
    -SeqTrace [0]: (<0.25.0>) <0.30.0> ! {<0.25.0>,get_tracer} [Serial: {2,4}]
    -SeqTrace [0]: (<0.30.0>) <0.25.0> ! {dbg,{ok,<0.31.0>}} [Serial: {4,5}]
    -{1,0,5,<0.30.0>,4}

    This session sets the system_tracer to the same process as the +4> dbg:tp(dbg, get_tracer, 0, [{[],[],[{set_seq_token, send, true}]}]). +{ok,[{matched,nonode@nohost,1},{saved,1}]} +5> dbg:p(all,call). +{ok,[{matched,nonode@nohost,22}]} +6> dbg:get_tracer(), seq_trace:set_token([]). +(<0.25.0>) call dbg:get_tracer() +SeqTrace [0]: (<0.25.0>) <0.30.0> ! {<0.25.0>,get_tracer} [Serial: {2,4}] +SeqTrace [0]: (<0.30.0>) <0.25.0> ! {dbg,{ok,<0.31.0>}} [Serial: {4,5}] +{1,0,5,<0.30.0>,4}

    This session sets the system_tracer to the same process as the ordinary tracer process (i. e. <0.31.0>) and sets the trace pattern for the function dbg:get_tracer to one that has the action of setting a sequential token. When the function is called by a traced @@ -273,20 +273,20 @@

    trace handler prints to the tty using an io function such as format/2. Note that when dbg:p(all, call) is called, IO processes are also traced. Here is an example:

    %% Using a default line editing shell
    -1> dbg:tracer(process, {fun(Msg,_) -> io:format("~p~n", [Msg]), 0 end, 0}).
    -{ok,<0.37.0>}
    -2> dbg:p(all, [call]).
    -{ok,[{matched,nonode@nohost,25}]}
    -3> dbg:tp(mymod,[{'_',[],[]}]).
    -{ok,[{matched,nonode@nohost,0},{saved,1}]}
    +1> dbg:tracer(process, {fun(Msg,_) -> io:format("~p~n", [Msg]), 0 end, 0}).
    +{ok,<0.37.0>}
    +2> dbg:p(all, [call]).
    +{ok,[{matched,nonode@nohost,25}]}
    +3> dbg:tp(mymod,[{'_',[],[]}]).
    +{ok,[{matched,nonode@nohost,0},{saved,1}]}
     4> mymod: % TAB pressed here
     %% -- Deadlock --

    Here is another example:

    %% Using a shell without line editing (oldshell)
    -1> dbg:tracer(process).
    -{ok,<0.31.0>}
    -2> dbg:p(all, [call]).
    -{ok,[{matched,nonode@nohost,25}]}
    -3> dbg:tp(lists,[{'_',[],[]}]).
    -{ok,[{matched,nonode@nohost,0},{saved,1}]}
    +1> dbg:tracer(process).
    +{ok,<0.31.0>}
    +2> dbg:p(all, [call]).
    +{ok,[{matched,nonode@nohost,25}]}
    +3> dbg:tp(lists,[{'_',[],[]}]).
    +{ok,[{matched,nonode@nohost,0},{saved,1}]}
     % -- Deadlock --

    The reason we get a deadlock in the first example is because when TAB is pressed to expand the function name, the group leader (which handles character input) calls mymod:module_info(). This generates a trace message which, in turn, @@ -2101,40 +2101,40 @@

    fun2ms(LiteralFun)

    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.

    @@ -2342,16 +2342,16 @@

    ltp()

    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]
    @@ -2549,37 +2549,37 @@

    session(Session, Fun)

    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.

    @@ -2753,11 +2753,11 @@

    tp(ModuleOrMFA, MatchSpec)

    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."}]}
    @@ -3008,17 +3008,17 @@

    trace_client(Type, Parameters)

    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.

    @@ -3102,7 +3102,7 @@

    trace_port(Type, Parameters)

    Creates a trace-port-generating fun that is suitable as the -second argument to tracer/2.

    Example:

    dbg:tracer(port, dbg:trace_port(ip, 4711)).

    A trace port is an Erlang port to a dynamically linked-in driver that +second argument to tracer/2.

    Example:

    dbg:tracer(port, dbg:trace_port(ip, 4711)).

    A trace port is an Erlang port to a dynamically linked-in driver that handles trace messages directly, without the overhead of sending them as messages to an Erlang process. Using a trace port significantly lowers the overhead imposed by tracing.

    Two trace drivers are currently implemented: the file and the ip diff --git a/prs/9045/lib/runtime_tools-2.1.1/doc/html/dyntrace.html b/prs/9045/lib/runtime_tools-2.1.1/doc/html/dyntrace.html index 96b463b95db1..a35cf2c9b8b6 100644 --- a/prs/9045/lib/runtime_tools-2.1.1/doc/html/dyntrace.html +++ b/prs/9045/lib/runtime_tools-2.1.1/doc/html/dyntrace.html @@ -863,14 +863,14 @@

    restore_tag(TagData)

    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 @@ -917,12 +917,12 @@

    spread_tag(boolean())

    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.

    diff --git a/prs/9045/lib/runtime_tools-2.1.1/doc/html/instrument.html b/prs/9045/lib/runtime_tools-2.1.1/doc/html/instrument.html index eead74dab987..bff5701ff2c6 100644 --- a/prs/9045/lib/runtime_tools-2.1.1/doc/html/instrument.html +++ b/prs/9045/lib/runtime_tools-2.1.1/doc/html/instrument.html @@ -361,8 +361,8 @@

    block_histogram()

    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}, ... } }}
    @@ -502,30 +502,30 @@

    allocations(Options)

    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}}}}}
    @@ -602,15 +602,15 @@

    carriers(Options)

    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}},
    +      {...}|...]}}
    diff --git a/prs/9045/lib/runtime_tools-2.1.1/doc/html/lttng.html b/prs/9045/lib/runtime_tools-2.1.1/doc/html/lttng.html index 721b258280ab..6ec86dd658f0 100644 --- a/prs/9045/lib/runtime_tools-2.1.1/doc/html/lttng.html +++ b/prs/9045/lib/runtime_tools-2.1.1/doc/html/lttng.html @@ -156,42 +156,42 @@

    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_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 +

      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 }

      +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 }

    @@ -204,10 +204,10 @@

    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
    diff --git a/prs/9045/lib/runtime_tools-2.1.1/doc/html/msacc.html b/prs/9045/lib/runtime_tools-2.1.1/doc/html/msacc.html
    index 9e8cf1d2e19a..a4ddf910c984 100644
    --- a/prs/9045/lib/runtime_tools-2.1.1/doc/html/msacc.html
    +++ b/prs/9045/lib/runtime_tools-2.1.1/doc/html/msacc.html
    @@ -137,9 +137,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
    @@ -147,11 +147,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% @@ -951,7 +951,7 @@

    print(DataOrStats, Options)

    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.
      diff --git a/prs/9045/lib/runtime_tools-2.1.1/doc/html/runtime_tools.epub b/prs/9045/lib/runtime_tools-2.1.1/doc/html/runtime_tools.epub index d5a03ce1e35d..76e836ee4826 100644 Binary files a/prs/9045/lib/runtime_tools-2.1.1/doc/html/runtime_tools.epub and b/prs/9045/lib/runtime_tools-2.1.1/doc/html/runtime_tools.epub differ diff --git a/prs/9045/lib/runtime_tools-2.1.1/doc/html/scheduler.html b/prs/9045/lib/runtime_tools-2.1.1/doc/html/scheduler.html index 8e8638655b96..7065ef8e2d4a 100644 --- a/prs/9045/lib/runtime_tools-2.1.1/doc/html/scheduler.html +++ b/prs/9045/lib/runtime_tools-2.1.1/doc/html/scheduler.html @@ -619,7 +619,7 @@

      utilization/1

      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.

      diff --git a/prs/9045/lib/sasl-4.2.2/doc/html/appup.html b/prs/9045/lib/sasl-4.2.2/doc/html/appup.html index b919b6f7899f..cf52bdc18e05 100644 --- a/prs/9045/lib/sasl-4.2.2/doc/html/appup.html +++ b/prs/9045/lib/sasl-4.2.2/doc/html/appup.html @@ -149,9 +149,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 @@ -227,21 +227,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}
        @@ -268,9 +268,9 @@ 

        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 +

        {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 @@ -284,38 +284,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 diff --git a/prs/9045/lib/sasl-4.2.2/doc/html/error_logging.html b/prs/9045/lib/sasl-4.2.2/doc/html/error_logging.html index 22287c2d0e0e..a5ce5f3bbb1b 100644 --- a/prs/9045/lib/sasl-4.2.2/doc/html/error_logging.html +++ b/prs/9045/lib/sasl-4.2.2/doc/html/error_logging.html @@ -314,42 +314,42 @@

    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
    diff --git a/prs/9045/lib/sasl-4.2.2/doc/html/rel.html b/prs/9045/lib/sasl-4.2.2/doc/html/rel.html
    index d129fd28c43f..06421a5bef31 100644
    --- a/prs/9045/lib/sasl-4.2.2/doc/html/rel.html
    +++ b/prs/9045/lib/sasl-4.2.2/doc/html/rel.html
    @@ -146,11 +146,11 @@ 

    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 diff --git a/prs/9045/lib/sasl-4.2.2/doc/html/release_handler.html b/prs/9045/lib/sasl-4.2.2/doc/html/release_handler.html index afafc67bba82..f868f224ae94 100644 --- a/prs/9045/lib/sasl-4.2.2/doc/html/release_handler.html +++ b/prs/9045/lib/sasl-4.2.2/doc/html/release_handler.html @@ -1090,8 +1090,8 @@

        install_release(Vsn, [Opt])

        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 diff --git a/prs/9045/lib/sasl-4.2.2/doc/html/relup.html b/prs/9045/lib/sasl-4.2.2/doc/html/relup.html index bbe2978d67e3..26f4f5816aac 100644 --- a/prs/9045/lib/sasl-4.2.2/doc/html/relup.html +++ b/prs/9045/lib/sasl-4.2.2/doc/html/relup.html @@ -149,9 +149,9 @@

      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 diff --git a/prs/9045/lib/sasl-4.2.2/doc/html/sasl.epub b/prs/9045/lib/sasl-4.2.2/doc/html/sasl.epub index 854b9ef9816b..75fefb699d89 100644 Binary files a/prs/9045/lib/sasl-4.2.2/doc/html/sasl.epub and b/prs/9045/lib/sasl-4.2.2/doc/html/sasl.epub differ diff --git a/prs/9045/lib/sasl-4.2.2/doc/html/script.html b/prs/9045/lib/sasl-4.2.2/doc/html/script.html index 0b4ac21610b5..b3e652e9fc3a 100644 --- a/prs/9045/lib/sasl-4.2.2/doc/html/script.html +++ b/prs/9045/lib/sasl-4.2.2/doc/html/script.html @@ -148,20 +148,20 @@

          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 diff --git a/prs/9045/lib/snmp-5.17/doc/html/snmp.epub b/prs/9045/lib/snmp-5.17/doc/html/snmp.epub index 9c991a8872b5..f5e62c13c41d 100644 Binary files a/prs/9045/lib/snmp-5.17/doc/html/snmp.epub and b/prs/9045/lib/snmp-5.17/doc/html/snmp.epub differ diff --git a/prs/9045/lib/snmp-5.17/doc/html/snmp.html b/prs/9045/lib/snmp-5.17/doc/html/snmp.html index a8b5ceab4e61..c0bc36f4c2fe 100644 --- a/prs/9045/lib/snmp-5.17/doc/html/snmp.html +++ b/prs/9045/lib/snmp-5.17/doc/html/snmp.html @@ -3349,8 +3349,8 @@

            print_version_info(Prefix)

            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).
            @@ -3548,17 +3548,17 @@

            set_trace(Targets, TraceOpts)

            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(),
            diff --git a/prs/9045/lib/snmp-5.17/doc/html/snmp_advanced_agent.html b/prs/9045/lib/snmp-5.17/doc/html/snmp_advanced_agent.html index 5a5c651c2030..baaf904119fe 100644 --- a/prs/9045/lib/snmp-5.17/doc/html/snmp_advanced_agent.html +++ b/prs/9045/lib/snmp-5.17/doc/html/snmp_advanced_agent.html @@ -335,16 +335,16 @@

            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 + }

    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 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.

    @@ -356,11 +356,11 @@

    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.

    @@ -373,28 +373,28 @@

    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}).
    -
    -is_row_created(Name, Cols) ->
    -  case snmp_generic:get_status_col(Name, Cols) of
    -    {ok, ?createAndGo} -> true;
    -    {ok, ?createAndWait} -> true;
    +  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;
         _ -> false
       end.

    If a row is created, we always set the internal column to "internal".

    diff --git a/prs/9045/lib/snmp-5.17/doc/html/snmp_agent_config_files.html b/prs/9045/lib/snmp-5.17/doc/html/snmp_agent_config_files.html index 50f33d059000..b8fd97112251 100644 --- a/prs/9045/lib/snmp-5.17/doc/html/snmp_agent_config_files.html +++ b/prs/9045/lib/snmp-5.17/doc/html/snmp_agent_config_files.html @@ -156,19 +156,19 @@

    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}.

    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 +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}.

    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 @@ -194,12 +194,12 @@

    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}.

    A value must be provided for all variables, which lack default values in the +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}.

    A value must be provided for all variables, which lack default values in the MIB.

    diff --git a/prs/9045/lib/snmp-5.17/doc/html/snmp_agent_funct_descr.html b/prs/9045/lib/snmp-5.17/doc/html/snmp_agent_funct_descr.html index 22de3d9f93f3..931f581ea780 100644 --- a/prs/9045/lib/snmp-5.17/doc/html/snmp_agent_funct_descr.html +++ b/prs/9045/lib/snmp-5.17/doc/html/snmp_agent_funct_descr.html @@ -314,7 +314,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.

    @@ -475,9 +475,9 @@

    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 diff --git a/prs/9045/lib/snmp-5.17/doc/html/snmp_app.html b/prs/9045/lib/snmp-5.17/doc/html/snmp_app.html index e338cc5d0e10..123de457cb3b 100644 --- a/prs/9045/lib/snmp-5.17/doc/html/snmp_app.html +++ b/prs/9045/lib/snmp-5.17/doc/html/snmp_app.html @@ -146,51 +146,51 @@

    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. diff --git a/prs/9045/lib/snmp-5.17/doc/html/snmp_app_b.html b/prs/9045/lib/snmp-5.17/doc/html/snmp_app_b.html index 16d7924c739d..baea4181be67 100644 --- a/prs/9045/lib/snmp-5.17/doc/html/snmp_app_b.html +++ b/prs/9045/lib/snmp-5.17/doc/html/snmp_app_b.html @@ -592,23 +592,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) + }

    diff --git a/prs/9045/lib/snmp-5.17/doc/html/snmp_config.html b/prs/9045/lib/snmp-5.17/doc/html/snmp_config.html index 2d71f8a2ef30..dc5b10b6b1c7 100644 --- a/prs/9045/lib/snmp-5.17/doc/html/snmp_config.html +++ b/prs/9045/lib/snmp-5.17/doc/html/snmp_config.html @@ -151,41 +151,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. @@ -562,34 +562,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 - diff --git a/prs/9045/lib/snmp-5.17/doc/html/snmp_generic.html b/prs/9045/lib/snmp-5.17/doc/html/snmp_generic.html index 136d27d60fe2..a4e045c18417 100644 --- a/prs/9045/lib/snmp-5.17/doc/html/snmp_generic.html +++ b/prs/9045/lib/snmp-5.17/doc/html/snmp_generic.html @@ -146,9 +146,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 @@ -156,7 +156,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, @@ -168,41 +168,41 @@

        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]}}.

        +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).
        +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}]}}.

    diff --git a/prs/9045/lib/snmp-5.17/doc/html/snmp_impl_example_agent.html b/prs/9045/lib/snmp-5.17/doc/html/snmp_impl_example_agent.html index 81409ae9847a..ff8be87e8107 100644 --- a/prs/9045/lib/snmp-5.17/doc/html/snmp_impl_example_agent.html +++ b/prs/9045/lib/snmp-5.17/doc/html/snmp_impl_example_agent.html @@ -236,54 +236,54 @@

    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>

    @@ -301,55 +301,55 @@

    Code

    -
    -module(ex1).
    --author('dummy@flop.org').
    +
    -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;
     %%----------------------------------------------------------------
    @@ -360,158 +360,158 @@ 

    %% *) 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, - {inconsistentName, Col} + [{Col, _NewVal} | _Cols] = Cols, + {inconsistentName, Col} end; -friends_table(set, RowIndex, Cols) -> - case is_row_status_col_changed(Cols) of - {true, ?destroy} -> - ex1_server ! {self(), {delete_row, RowIndex}}; - {true, ?createAndGo} -> - NewRow = make_row(RowIndex, Cols), - ex1_server ! {self(), {add_row, NewRow}}; +friends_table(set, RowIndex, Cols) -> + case is_row_status_col_changed(Cols) of + {true, ?destroy} -> + ex1_server ! {self(), {delete_row, RowIndex}}; + {true, ?createAndGo} -> + NewRow = make_row(RowIndex, Cols), + ex1_server ! {self(), {add_row, NewRow}}; false -> - {ok, Row} = get_row(RowIndex), - NewRow = merge_rows(Row, Cols), - ex1_server ! {self(), {delete_row, RowIndex}}, - ex1_server ! {self(), {add_row, NewRow}} + {ok, Row} = get_row(RowIndex), + NewRow = merge_rows(Row, Cols), + ex1_server ! {self(), {delete_row, RowIndex}}, + ex1_server ! {self(), {add_row, NewRow}} end, - {noError, 0}. + {noError, 0}. %%---------------------------------------------------------------- %% Make a list of {value, Val} of the Row and Cols list. %%---------------------------------------------------------------- -get_cols([Col | Cols], Row) -> - [{value, element(Col, Row)} | get_cols(Cols, Row)]; -get_cols([], _Row) -> - []. +get_cols([Col | Cols], Row) -> + [{value, element(Col, Row)} | get_cols(Cols, Row)]; +get_cols([], _Row) -> + []. %%---------------------------------------------------------------- %% As get_cols, but the Cols list may contain invalid column %% numbers. If it does, we must find the next valid column, %% or return endOfTable. %%---------------------------------------------------------------- -get_next_cols([Col | Cols], Row) when Col < 2 -> - [{[2, element(1, Row)], element(2, Row)} | - get_next_cols(Cols, Row)]; -get_next_cols([Col | Cols], Row) when Col > 4 -> - [endOfTable | - get_next_cols(Cols, Row)]; -get_next_cols([Col | Cols], Row) -> - [{[Col, element(1, Row)], element(Col, Row)} | - get_next_cols(Cols, Row)]; -get_next_cols([], _Row) -> - []. +get_next_cols([Col | Cols], Row) when Col < 2 -> + [{[2, element(1, Row)], element(2, Row)} | + get_next_cols(Cols, Row)]; +get_next_cols([Col | Cols], Row) when Col > 4 -> + [endOfTable | + get_next_cols(Cols, Row)]; +get_next_cols([Col | Cols], Row) -> + [{[Col, element(1, Row)], element(Col, Row)} | + get_next_cols(Cols, Row)]; +get_next_cols([], _Row) -> + []. %%---------------------------------------------------------------- %% Make a list of endOfTable with as many elems as Cols list. %%---------------------------------------------------------------- -end_of_table([Col | Cols]) -> - [endOfTable | end_of_table(Cols)]; -end_of_table([]) -> - []. -add_one_to_cols([Col | Cols]) -> - [Col + 1 | add_one_to_cols(Cols)]; -add_one_to_cols([]) -> - []. -is_row_status_col_changed(Cols) -> - case lists:keysearch(?status_col, 1, Cols) of - {value, {?status_col, StatusVal}} -> - {true, StatusVal}; +end_of_table([Col | Cols]) -> + [endOfTable | end_of_table(Cols)]; +end_of_table([]) -> + []. +add_one_to_cols([Col | Cols]) -> + [Col + 1 | add_one_to_cols(Cols)]; +add_one_to_cols([]) -> + []. +is_row_status_col_changed(Cols) -> + case lists:keysearch(?status_col, 1, Cols) of + {value, {?status_col, StatusVal}} -> + {true, StatusVal}; _ -> false end. -get_row(RowIndex) -> - ex1_server ! {self(), {get_row, RowIndex}}, - wait_answer(). -get_next_row(RowIndex) -> - ex1_server ! {self(), {get_next_row, RowIndex}}, - wait_answer(). -wait_answer() -> +get_row(RowIndex) -> + ex1_server ! {self(), {get_row, RowIndex}}, + wait_answer(). +get_next_row(RowIndex) -> + ex1_server ! {self(), {get_next_row, RowIndex}}, + wait_answer(). +wait_answer() -> receive - {ex1_server, Answer} -> + {ex1_server, Answer} -> Answer end. %%%--------------------------------------------------------------- %%% Server code follows %%%--------------------------------------------------------------- -init() -> - register(ex1_server, self()), - loop("", []). +init() -> + register(ex1_server, self()), + loop("", []). -loop(MyName, Table) -> +loop(MyName, Table) -> receive - {From, get_my_name} -> - From ! {ex1_server, MyName}, - loop(MyName, Table); - {From, {set_my_name, NewName}} -> - loop(NewName, Table); - {From, {get_row, RowIndex}} -> - Res = table_get_row(Table, RowIndex), - From ! {ex1_server, Res}, - loop(MyName, Table); - {From, {get_next_row, RowIndex}} -> - Res = table_get_next_row(Table, RowIndex), - From ! {ex1_server, Res}, - loop(MyName, Table); - {From, {delete_row, RowIndex}} -> - NewTable = table_delete_row(Table, RowIndex), - loop(MyName, NewTable); - {From, {add_row, NewRow}} -> - NewTable = table_add_row(Table, NewRow), - loop(MyName, NewTable) + {From, get_my_name} -> + From ! {ex1_server, MyName}, + loop(MyName, Table); + {From, {set_my_name, NewName}} -> + loop(NewName, Table); + {From, {get_row, RowIndex}} -> + Res = table_get_row(Table, RowIndex), + From ! {ex1_server, Res}, + loop(MyName, Table); + {From, {get_next_row, RowIndex}} -> + Res = table_get_next_row(Table, RowIndex), + From ! {ex1_server, Res}, + loop(MyName, Table); + {From, {delete_row, RowIndex}} -> + NewTable = table_delete_row(Table, RowIndex), + loop(MyName, NewTable); + {From, {add_row, NewRow}} -> + NewTable = table_add_row(Table, NewRow), + loop(MyName, NewTable) end. %%%--------------------------------------------------------------- %%% Functions for table operations. The table is represented as %%% a list of rows. %%%--------------------------------------------------------------- -table_get_row([{Index, Name, Address, Status} | _], [Index]) -> - {ok, {Index, Name, Address, Status}}; -table_get_row([H | T], RowIndex) -> - table_get_row(T, RowIndex); -table_get_row([], _RowIndex) -> +table_get_row([{Index, Name, Address, Status} | _], [Index]) -> + {ok, {Index, Name, Address, Status}}; +table_get_row([H | T], RowIndex) -> + table_get_row(T, RowIndex); +table_get_row([], _RowIndex) -> no_such_row. -table_get_next_row([Row | T], []) -> - {ok, Row}; -table_get_next_row([Row | T], [Index | _]) -when element(1, Row) > Index -> - {ok, Row}; -table_get_next_row([Row | T], RowIndex) -> - table_get_next_row(T, RowIndex); -table_get_next_row([], RowIndex) -> +table_get_next_row([Row | T], []) -> + {ok, Row}; +table_get_next_row([Row | T], [Index | _]) +when element(1, Row) > Index -> + {ok, Row}; +table_get_next_row([Row | T], RowIndex) -> + table_get_next_row(T, RowIndex); +table_get_next_row([], RowIndex) -> endOfTable. -table_delete_row([{Index, _, _, _} | T], [Index]) -> +table_delete_row([{Index, _, _, _} | T], [Index]) -> T; -table_delete_row([H | T], RowIndex) -> - [H | table_delete_row(T, RowIndex)]; -table_delete_row([], _RowIndex) -> - []. -table_add_row([Row | T], NewRow) - when element(1, Row) > element(1, NewRow) -> - [NewRow, Row | T]; -table_add_row([H | T], NewRow) -> - [H | table_add_row(T, NewRow)]; -table_add_row([], NewRow) -> - [NewRow]. -make_row([Index], [{2, Name}, {3, Address} | _]) -> - {Index, Name, Address, ?active}. -merge_rows(Row, [{Col, NewVal} | T]) -> - merge_rows(setelement(Col, Row, NewVal), T); -merge_rows(Row, []) -> +table_delete_row([H | T], RowIndex) -> + [H | table_delete_row(T, RowIndex)]; +table_delete_row([], _RowIndex) -> + []. +table_add_row([Row | T], NewRow) + when element(1, Row) > element(1, NewRow) -> + [NewRow, Row | T]; +table_add_row([H | T], NewRow) -> + [H | table_add_row(T, NewRow)]; +table_add_row([], NewRow) -> + [NewRow]. +make_row([Index], [{2, Name}, {3, Address} | _]) -> + {Index, Name, Address, ?active}. +merge_rows(Row, [{Col, NewVal} | T]) -> + merge_rows(setelement(Col, Row, NewVal), T); +merge_rows(Row, []) -> Row.

    @@ -519,21 +519,21 @@

    Association File

    The association file EX1-MIB.funcs for the real implementation looks as -follows:

    {myName, {ex1, my_name, []}}.
    -{friendsTable, {ex1, friends_table, []}}.

    +follows:

    {myName, {ex1, my_name, []}}.
    +{friendsTable, {ex1, friends_table, []}}.

    Transcript

    To use the real implementation, we must recompile the MIB and load it into the -agent.

    1> application:start(snmp).
    +agent.

    1> application:start(snmp).
     ok
    -2> snmpc:compile("EX1-MIB").
    -{ok,"EX1-MIB.bin"}
    -3> snmpa:load_mibs(snmp_master_agent, ["EX1-MIB"]).
    +2> snmpc:compile("EX1-MIB").
    +{ok,"EX1-MIB.bin"}
    +3> snmpa:load_mibs(snmp_master_agent, ["EX1-MIB"]).
     ok
    -4> ex1:start().
    +4> ex1:start().
     <0.115.0>
     %% Now all requests operates on this "real" implementation.
     %% The output from the manager requests will *look* exactly the
    @@ -549,35 +549,35 @@ 

    trap, myName and fIndex. fIndex is a table column, so we must provide its value and the index for the row in the call to snmpa:send_notification2/3. In the example below, we assume that the row in question is indexed by 2 (the row with -fIndex 2).

    we use a simple Erlang SNMP manager, which can receive traps.

    [MANAGER]
    -1> snmp_test_mgr:start_link([{agent,"dront.ericsson.se"},{community,"public"}
    +fIndex 2).

    we use a simple Erlang SNMP manager, which can receive traps.

    [MANAGER]
    +1> snmp_test_mgr:start_link([{agent,"dront.ericsson.se"},{community,"public"}
      %% does not have write-access
    -1>{mibs,["EX1-MIB","STANDARD-MIB"]}]).
    -{ok, <0.100.0>}
    -2> snmp_test_mgr:s([{[myName,0], "Klas"}]).
    +1>{mibs,["EX1-MIB","STANDARD-MIB"]}]).
    +{ok, <0.100.0>}
    +2> snmp_test_mgr:s([{[myName,0], "Klas"}]).
     ok
     * Got PDU:
     Received a trap:
           Generic: 4       %% authenticationFailure
    -   Enterprise: [iso,2,3]
    +   Enterprise: [iso,2,3]
          Specific: 0
    -   Agent addr: [123,12,12,21]
    +   Agent addr: [123,12,12,21]
         TimeStamp: 42993
     2>
    -[AGENT]
    -3> SendOpts = [{receiver, no_receiver}, {varbinds, [{fIndex,[2],2}]}, {name, "standard trap"}, {context, ""}],
    -4> snmpa:send_notification2(snmp_master_agent, fTrap, SendOpts).
    -[MANAGER]
    +[AGENT]
    +3> SendOpts = [{receiver, no_receiver}, {varbinds, [{fIndex,[2],2}]}, {name, "standard trap"}, {context, ""}],
    +4> snmpa:send_notification2(snmp_master_agent, fTrap, SendOpts).
    +[MANAGER]
     2>
     * Got PDU:
     Received a trap:
           Generic: 6
    -   Enterprise: [example1]
    +   Enterprise: [example1]
          Specific: 1
    -   Agent addr: [123,12,12,21]
    +   Agent addr: [123,12,12,21]
         TimeStamp: 69649
    -[myName,0] = "Martin"
    -[fIndex,2] = 2
    +[myName,0] = "Martin"
    +[fIndex,2] = 2
     2>
    diff --git a/prs/9045/lib/snmp-5.17/doc/html/snmp_index.html b/prs/9045/lib/snmp-5.17/doc/html/snmp_index.html index 16e76d4b4f7d..a310ac600b6a 100644 --- a/prs/9045/lib/snmp-5.17/doc/html/snmp_index.html +++ b/prs/9045/lib/snmp-5.17/doc/html/snmp_index.html @@ -141,13 +141,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.

    diff --git a/prs/9045/lib/snmp-5.17/doc/html/snmp_instr_functions.html b/prs/9045/lib/snmp-5.17/doc/html/snmp_instr_functions.html index 54246c1c45ef..06ba99329cb3 100644 --- a/prs/9045/lib/snmp-5.17/doc/html/snmp_instr_functions.html +++ b/prs/9045/lib/snmp-5.17/doc/html/snmp_instr_functions.html @@ -159,8 +159,8 @@

    New / Delete Operations

    -

    For scalar variables:

    variable_access(new [, ExtraArg1, ...])
    -variable_access(delete [, ExtraArg1, ...])

    For tables:

    table_access(new [, ExtraArg1, ...])
    +

    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.

    @@ -220,9 +220,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 @@ -239,17 +239,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]}}.

    +{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]}}.

    diff --git a/prs/9045/lib/snmp-5.17/doc/html/snmp_manager_config_files.html b/prs/9045/lib/snmp-5.17/doc/html/snmp_manager_config_files.html index 8ef896638b4f..47e8eedfbde2 100644 --- a/prs/9045/lib/snmp-5.17/doc/html/snmp_manager_config_files.html +++ b/prs/9045/lib/snmp-5.17/doc/html/snmp_manager_config_files.html @@ -155,10 +155,10 @@

    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.

    diff --git a/prs/9045/lib/snmp-5.17/doc/html/snmp_mib_compiler.html b/prs/9045/lib/snmp-5.17/doc/html/snmp_mib_compiler.html index d9d0c8bf8825..b7df1c8bb790 100644 --- a/prs/9045/lib/snmp-5.17/doc/html/snmp_mib_compiler.html +++ b/prs/9045/lib/snmp-5.17/doc/html/snmp_mib_compiler.html @@ -147,7 +147,7 @@

    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.

    @@ -159,10 +159,10 @@

    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.

    diff --git a/prs/9045/lib/snmp-5.17/doc/html/snmp_pdus.html b/prs/9045/lib/snmp-5.17/doc/html/snmp_pdus.html index 4dd4f3713c62..4f78f609d600 100644 --- a/prs/9045/lib/snmp-5.17/doc/html/snmp_pdus.html +++ b/prs/9045/lib/snmp-5.17/doc/html/snmp_pdus.html @@ -140,8 +140,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.

    diff --git a/prs/9045/lib/snmp-5.17/doc/html/snmpa.html b/prs/9045/lib/snmp-5.17/doc/html/snmpa.html index 8b9f8ea4aa88..0459d964f578 100644 --- a/prs/9045/lib/snmp-5.17/doc/html/snmpa.html +++ b/prs/9045/lib/snmp-5.17/doc/html/snmpa.html @@ -3341,8 +3341,8 @@

    load_mib(Agent, Mib)

    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").
    @@ -3458,8 +3458,8 @@

    load_mibs(Agent, Mibs, Force)

    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.

    @@ -4485,8 +4485,8 @@

    register_notification_filter/4

    -

    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}.
    @@ -4559,8 +4559,8 @@

    register_subagent(Agent, SubTree, SubAgent)

    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.

    @@ -5005,20 +5005,20 @@

    send_notification(Agent, Notification, Rece 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 diff --git a/prs/9045/lib/snmp-5.17/doc/html/snmpc_cmd.html b/prs/9045/lib/snmp-5.17/doc/html/snmpc_cmd.html index 000991b4caa8..98766c81e7e6 100644 --- a/prs/9045/lib/snmp-5.17/doc/html/snmpc_cmd.html +++ b/prs/9045/lib/snmp-5.17/doc/html/snmpc_cmd.html @@ -137,7 +137,7 @@

    Synopsis

    -
    snmpc [options] file.mib | file.bin

    +
    snmpc [options] file.mib | file.bin

    diff --git a/prs/9045/lib/snmp-5.17/doc/html/snmpm.html b/prs/9045/lib/snmp-5.17/doc/html/snmpm.html index e82d0f50add2..cef77bf29d75 100644 --- a/prs/9045/lib/snmp-5.17/doc/html/snmpm.html +++ b/prs/9045/lib/snmp-5.17/doc/html/snmpm.html @@ -2014,8 +2014,8 @@

    load_mib(MibName)

    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").
    @@ -3594,8 +3594,8 @@

    unload_mib(MibName)

    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").
    diff --git a/prs/9045/lib/ssh-5.2.3/doc/html/configurations.html b/prs/9045/lib/ssh-5.2.3/doc/html/configurations.html index 9dada7c557fa..7485e552844e 100644 --- a/prs/9045/lib/ssh-5.2.3/doc/html/configurations.html +++ b/prs/9045/lib/ssh-5.2.3/doc/html/configurations.html @@ -148,23 +148,23 @@

    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.

    @@ -235,17 +235,17 @@

    'hmac-sha1']}]}, {compression,[{client2server,[none,'zlib@openssh.com',zlib]}, {server2client,[none,'zlib@openssh.com',zlib]}]}]

    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',zlib]},
    -               {server2client,[none,'zlib@openssh.com',zlib]}]}]
    +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',zlib]},
    +               {server2client,[none,'zlib@openssh.com',zlib]}]}]
     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 @@ -258,65 +258,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 diff --git a/prs/9045/lib/ssh-5.2.3/doc/html/configure_algos.html b/prs/9045/lib/ssh-5.2.3/doc/html/configure_algos.html index 2464488cd68d..2e877bf83781 100644 --- a/prs/9045/lib/ssh-5.2.3/doc/html/configure_algos.html +++ b/prs/9045/lib/ssh-5.2.3/doc/html/configure_algos.html @@ -176,29 +176,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',zlib]},
    -               {server2client,[none,'zlib@openssh.com',zlib]}]}]

    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',zlib]}, + {server2client,[none,'zlib@openssh.com',zlib]}]}]

    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 @@ -221,28 +221,28 @@

    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',zlib]},
    -               {server2client,[none,'zlib@openssh.com',zlib]}]}]

    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',zlib]}, + {server2client,[none,'zlib@openssh.com',zlib]}]}]

    Note that the unmentioned lists (public_key, cipher, mac and compression) are unchanged.

    @@ -250,30 +250,30 @@

    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',zlib]},
    -               {server2client,[none,'zlib@openssh.com',zlib]}]}]

    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',zlib]}, + {server2client,[none,'zlib@openssh.com',zlib]}]}]

    Note that both lists in cipher has been changed to the provided value ('aes128-ctr').

    @@ -281,56 +281,56 @@

    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',zlib]},
    -               {server2client,[none,'zlib@openssh.com',zlib]}]}]

    + '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',zlib]}, + {server2client,[none,'zlib@openssh.com',zlib]}]}]

    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.

    +

    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.

    @@ -344,10 +344,10 @@

    ssh:default_algorithms() and then do changes in the lists.

    To facilitate addition or removal of algorithms the option modify_algorithms is available. See the Reference Manual for details.

    The option takes a list with instructions to append, prepend or remove -algorithms:

    {modify_algorithms, [{append,  ...},
    -                     {prepend, ...},
    -		     {rm,      ...}
    -		    ]}

    Each of the ... can be a algs_list() as the argument to the +algorithms:

    {modify_algorithms, [{append,  ...},
    +                     {prepend, ...},
    +		     {rm,      ...}
    +		    ]}

    Each of the ... can be a algs_list() as the argument to the preferred_algorithms option.

    @@ -355,37 +355,37 @@

    Example 5

    As an example let's add the Diffie-Hellman Group1 first in the kex list. It is -supported according to Supported algorithms.

    5> ssh:chk_algos_opts(
    -         [{modify_algorithms,
    -	       [{prepend,
    -	           [{kex,['diffie-hellman-group1-sha1']}]
    -		   }
    -	       ]
    -          }
    -        ]).
    -[{kex,['diffie-hellman-group1-sha1','ecdh-sha2-nistp384',
    +supported according to Supported algorithms.

    5> ssh:chk_algos_opts(
    +         [{modify_algorithms,
    +	       [{prepend,
    +	           [{kex,['diffie-hellman-group1-sha1']}]
    +		   }
    +	       ]
    +          }
    +        ]).
    +[{kex,['diffie-hellman-group1-sha1','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',zlib]},
    -               {server2client,[none,'zlib@openssh.com',zlib]}]}]

    And the result shows that the Diffie-Hellman Group1 is added at the head of the + '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',zlib]}, + {server2client,[none,'zlib@openssh.com',zlib]}]}]

    And the result shows that the Diffie-Hellman Group1 is added at the head of the kex list

    @@ -393,27 +393,27 @@

    Example 6

    In this example, we in put the 'diffie-hellman-group1-sha1' first and also move -the 'ecdh-sha2-nistp521' to the end in the kex list, that is, append it.

    6> ssh:chk_algos_opts(
    -         [{modify_algorithms,
    -	       [{prepend,
    -	           [{kex, ['diffie-hellman-group1-sha1']}
    -		   ]},
    -		{append,
    -                   [{kex, ['ecdh-sha2-nistp521']}
    -                   ]}
    -	       ]
    -          }
    -        ]).
    -[{kex,['diffie-hellman-group1-sha1','ecdh-sha2-nistp384',
    +the 'ecdh-sha2-nistp521' to the end in the kex list, that is, append it.

    6> ssh:chk_algos_opts(
    +         [{modify_algorithms,
    +	       [{prepend,
    +	           [{kex, ['diffie-hellman-group1-sha1']}
    +		   ]},
    +		{append,
    +                   [{kex, ['ecdh-sha2-nistp521']}
    +                   ]}
    +	       ]
    +          }
    +        ]).
    +[{kex,['diffie-hellman-group1-sha1','ecdh-sha2-nistp384',
            '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','ecdh-sha2-nistp521']},
    - {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
    +       'diffie-hellman-group-exchange-sha1','ecdh-sha2-nistp521']},
    + {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
        .....
    -]

    Note that the appended algorithm is removed from its original place and then +]

    Note that the appended algorithm is removed from its original place and then appended to the same list.

    @@ -422,34 +422,34 @@

    In this example, we use both options (preferred_algorithms and modify_algorithms) and also try to prepend an unsupported algorithm. Any -unsupported algorithm is quietly removed.

    7> 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]}]}
    -               ]
    -           },
    -          {modify_algorithms,
    -	       [{prepend,
    -	           [{kex, ['some unsupported algorithm']}
    -		   ]},
    -		{append,
    -                   [{kex, ['diffie-hellman-group1-sha1']}
    -                   ]}
    -	       ]
    -          }
    -        ]).
    -[{kex,['ecdh-sha2-nistp384','diffie-hellman-group1-sha1']},
    - {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]}]}]

    It is of course questionable why anyone would like to use the both these options +unsupported algorithm is quietly removed.

    7> 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]}]}
    +               ]
    +           },
    +          {modify_algorithms,
    +	       [{prepend,
    +	           [{kex, ['some unsupported algorithm']}
    +		   ]},
    +		{append,
    +                   [{kex, ['diffie-hellman-group1-sha1']}
    +                   ]}
    +	       ]
    +          }
    +        ]).
    +[{kex,['ecdh-sha2-nistp384','diffie-hellman-group1-sha1']},
    + {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]}]}]

    It is of course questionable why anyone would like to use the both these options together, but it is possible if an unforeseen need should arise.

    @@ -458,7 +458,7 @@

    In this example, we need to use a diffie-hellman-group1-sha1 key exchange algorithm although it is unsafe and disabled by default.

    We use the modify_algorithms -option, because we want to keep all other algorithm definitions.

    We add the option:

      {modify_algorithms, [{append, [{kex,['diffie-hellman-group1-sha1']}]}]}

    either to the Options list in a function call, in the ssh.app file or in a +option, because we want to keep all other algorithm definitions.

    We add the option:

      {modify_algorithms, [{append, [{kex,['diffie-hellman-group1-sha1']}]}]}

    either to the Options list in a function call, in the ssh.app file or in a .config file for the erl command. See the chapter Configuration in SSH in the SSH User's Guide.

    @@ -470,7 +470,7 @@

    either as a user's key, a host's key or both.

    To do that, we enable the 'ssh-dss' algorithm that is disabled by default by security reasons. We use the modify_algorithms option, because -we want to keep all other algorithm definitions.

    We add the option:

      {modify_algorithms, [{append, [{public_key,['ssh-dss']}]}]}

    either to the Options list in a function call, in the ssh.app file or in a +we want to keep all other algorithm definitions.

    We add the option:

      {modify_algorithms, [{append, [{public_key,['ssh-dss']}]}]}

    either to the Options list in a function call, in the ssh.app file or in a .config file for the erl command. See the chapter Configuration in SSH in the SSH User's Guide.

    diff --git a/prs/9045/lib/ssh-5.2.3/doc/html/hardening.html b/prs/9045/lib/ssh-5.2.3/doc/html/hardening.html index fa60b1891030..7ecb29a53b26 100644 --- a/prs/9045/lib/ssh-5.2.3/doc/html/hardening.html +++ b/prs/9045/lib/ssh-5.2.3/doc/html/hardening.html @@ -220,16 +220,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 @@ -298,7 +298,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.

    diff --git a/prs/9045/lib/ssh-5.2.3/doc/html/ssh.epub b/prs/9045/lib/ssh-5.2.3/doc/html/ssh.epub index fb191acc25ec..7bd4e3b3e970 100644 Binary files a/prs/9045/lib/ssh-5.2.3/doc/html/ssh.epub and b/prs/9045/lib/ssh-5.2.3/doc/html/ssh.epub differ diff --git a/prs/9045/lib/ssh-5.2.3/doc/html/ssh.html b/prs/9045/lib/ssh-5.2.3/doc/html/ssh.html index 36639c8cc2ef..7323c456cd52 100644 --- a/prs/9045/lib/ssh-5.2.3/doc/html/ssh.html +++ b/prs/9045/lib/ssh-5.2.3/doc/html/ssh.html @@ -3492,14 +3492,14 @@

    double_algs(AlgType)

    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 @@ -5342,21 +5342,21 @@

    hostkey_fingerprint(TypeOrTypes, Key)

    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"]
    diff --git a/prs/9045/lib/ssh-5.2.3/doc/html/ssh_agent.html b/prs/9045/lib/ssh-5.2.3/doc/html/ssh_agent.html index 3182eb9d5c20..6511d58bf463 100644 --- a/prs/9045/lib/ssh-5.2.3/doc/html/ssh_agent.html +++ b/prs/9045/lib/ssh-5.2.3/doc/html/ssh_agent.html @@ -141,11 +141,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!

    diff --git a/prs/9045/lib/ssh-5.2.3/doc/html/using_ssh.html b/prs/9045/lib/ssh-5.2.3/doc/html/using_ssh.html index b7d0cb5a6914..c82da6434ff5 100644 --- a/prs/9045/lib/ssh-5.2.3/doc/html/using_ssh.html +++ b/prs/9045/lib/ssh-5.2.3/doc/html/using_ssh.html @@ -146,9 +146,9 @@

    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
    @@ -167,11 +167,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
    @@ -182,10 +182,10 @@ 

    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>

    @@ -201,35 +201,35 @@

    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 @@ -244,23 +244,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.

    @@ -281,36 +281,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>

    @@ -327,44 +327,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"},
    +                                  {exec, disabled}
    +                                 ]).
    +{ok,<0.54.0>}
     3>

    A call to that daemon will return the text "Prohibited." on stderr (depending on the client and OS), and the exit status 255:

    $bash> ssh ssh.example.com -p 8989 "test."
     Prohibited.
     $bash> echo $?
     255
     $bash>

    And the Erlang client library also returns the text "Prohibited." on data type 1 -instead of the normal 0 and exit status 255:

    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, "test."
    +instead of the normal 0 and exit status 255:

    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, "test."
     success
    -5> flush().
    -Shell got {ssh_cm,<0.106.0>,{data,0,1,<<"Prohibited.">>}}
    -Shell got {ssh_cm,<0.106.0>,{exit_status,0,255}}
    -Shell got {ssh_cm,<0.106.0>,{eof,0}}
    -Shell got {ssh_cm,<0.106.0>,{closed,0}}
    +5> flush().
    +Shell got {ssh_cm,<0.106.0>,{data,0,1,<<"Prohibited.">>}}
    +Shell got {ssh_cm,<0.106.0>,{exit_status,0,255}}
    +Shell got {ssh_cm,<0.106.0>,{eof,0}}
    +Shell got {ssh_cm,<0.106.0>,{closed,0}}
     ok
    -6>
    1. Install an alternative evaluator.
      Start the damon with a reference to a fun() that handles the evaluation:
    1> ssh:start().
    +6>
    1. Install an alternative evaluator.
      Start the damon with a reference to a fun() that handles the evaluation:
    1> ssh:start().
     ok
    -2> MyEvaluator = fun("1") -> {ok, some_value};
    -                    ("2") -> {ok, some_other_value};
    -                    ("3") -> {ok, V} = io:read("input erlang term>> "),
    -                             {ok, V};
    -                    (Err) -> {error,{bad_input,Err}}
    +2> MyEvaluator = fun("1") -> {ok, some_value};
    +                    ("2") -> {ok, some_other_value};
    +                    ("3") -> {ok, V} = io:read("input erlang term>> "),
    +                             {ok, V};
    +                    (Err) -> {error,{bad_input,Err}}
                      end.
    -3> {ok, Sshd} = ssh:daemon(1234, [{system_dir, "/tmp/ssh_daemon"},
    -                                  {user_dir, "/tmp/otptest_user/.ssh"},
    -                                  {exec, {direct,MyEvaluator}}
    -                                 ]).
    -{ok,<0.275.0>}
    +3> {ok, Sshd} = ssh:daemon(1234, [{system_dir, "/tmp/ssh_daemon"},
    +                                  {user_dir, "/tmp/otptest_user/.ssh"},
    +                                  {exec, {direct,MyEvaluator}}
    +                                 ]).
    +{ok,<0.275.0>}
     4>

    and call it:

    $bash> ssh localhost -p 1234 1
     some_value
     $bash> ssh localhost -p 1234 2
    @@ -378,17 +378,17 @@ 

    **Error** {bad_input,"1+ 2."} $bash>

    Note that spaces are preserved and that no point (.) is needed at the end - that was required by the default evaluator.

    The error return in the Erlang client (The text as data type 1 and exit_status -255):

    2> {ok, ConnectionRef} = ssh:connect(loopback, 1234, []).
    -{ok,<0.92.0>}
    -3> {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity).
    -{ok,0}
    -4> success = ssh_connection:exec(ConnectionRef, ChannelId, "1+ 2.").
    +255):

    2> {ok, ConnectionRef} = ssh:connect(loopback, 1234, []).
    +{ok,<0.92.0>}
    +3> {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity).
    +{ok,0}
    +4> success = ssh_connection:exec(ConnectionRef, ChannelId, "1+ 2.").
     success
    -5> flush().
    -Shell got {ssh_cm,<0.106.0>,{data,0,1,<<"**Error** {bad_input,\"1+ 2.\"}">>}}
    -Shell got {ssh_cm,<0.106.0>,{exit_status,0,255}}
    -Shell got {ssh_cm,<0.106.0>,{eof,0}}
    -Shell got {ssh_cm,<0.106.0>,{closed,0}}
    +5> flush().
    +Shell got {ssh_cm,<0.106.0>,{data,0,1,<<"**Error** {bad_input,\"1+ 2.\"}">>}}
    +Shell got {ssh_cm,<0.106.0>,{exit_status,0,255}}
    +Shell got {ssh_cm,<0.106.0>,{eof,0}}
    +Shell got {ssh_cm,<0.106.0>,{closed,0}}
     ok
     6>

    The fun() in the exec option could take up to three arguments (Cmd, User and ClientAddress). See the @@ -400,14 +400,14 @@

    SFTP Server

    -

    Start the Erlang ssh daemon with the SFTP subsystem:

    1> ssh:start().
    +

    Start the Erlang ssh daemon with the SFTP subsystem:

    1> ssh:start().
     ok
    -2> ssh:daemon(8989, [{system_dir, "/tmp/ssh_daemon"},
    -                     {user_dir, "/tmp/otptest_user/.ssh"},
    -                     {subsystems, [ssh_sftpd:subsystem_spec(
    -                                            [{cwd, "/tmp/sftp/example"}])
    -                                  ]}]).
    -{ok,<0.54.0>}
    +2> ssh:daemon(8989, [{system_dir, "/tmp/ssh_daemon"},
    +                     {user_dir, "/tmp/otptest_user/.ssh"},
    +                     {subsystems, [ssh_sftpd:subsystem_spec(
    +                                            [{cwd, "/tmp/sftp/example"}])
    +                                  ]}]).
    +{ok,<0.54.0>}
     3>

    Run the OpenSSH SFTP client:

    $bash> sftp -oPort=8989 -o IdentityFile=/tmp/otptest_user/.ssh/id_rsa \
                 -o UserKnownHostsFile=/tmp/otptest_user/.ssh/known_hosts ssh.example.com
     Connecting to ssh.example.com...
    @@ -419,12 +419,12 @@ 

    SFTP Client

    -

    Fetch a file with the Erlang SFTP client:

    1> ssh:start().
    +

    Fetch a file with the Erlang SFTP client:

    1> ssh:start().
     ok
    -2> {ok, ChannelPid, Connection} = ssh_sftp:start_channel("ssh.example.com", []).
    -{ok,<0.57.0>,<0.51.0>}
    -3> ssh_sftp:read_file(ChannelPid, "/home/otptest/test.txt").
    -{ok,<<"This is a test file\n">>}

    +2> {ok, ChannelPid, Connection} = ssh_sftp:start_channel("ssh.example.com", []). +{ok,<0.57.0>,<0.51.0>} +3> ssh_sftp:read_file(ChannelPid, "/home/otptest/test.txt"). +{ok,<<"This is a test file\n">>}

    @@ -436,17 +436,17 @@

    Basic example

    -

    This is an example of writing and then reading a tar file:

    {ok,HandleWrite} = ssh_sftp:open_tar(ChannelPid, ?tar_file_name, [write]),
    -ok = erl_tar:add(HandleWrite, .... ),
    -ok = erl_tar:add(HandleWrite, .... ),
    +

    This is an example of writing and then reading a tar file:

    {ok,HandleWrite} = ssh_sftp:open_tar(ChannelPid, ?tar_file_name, [write]),
    +ok = erl_tar:add(HandleWrite, .... ),
    +ok = erl_tar:add(HandleWrite, .... ),
     ...
    -ok = erl_tar:add(HandleWrite, .... ),
    -ok = erl_tar:close(HandleWrite),
    +ok = erl_tar:add(HandleWrite, .... ),
    +ok = erl_tar:close(HandleWrite),
     
     %% And for reading
    -{ok,HandleRead} = ssh_sftp:open_tar(ChannelPid, ?tar_file_name, [read]),
    -{ok,NameValueList} = erl_tar:extract(HandleRead,[memory]),
    -ok = erl_tar:close(HandleRead),

    +{ok,HandleRead} = ssh_sftp:open_tar(ChannelPid, ?tar_file_name, [read]), +{ok,NameValueList} = erl_tar:extract(HandleRead,[memory]), +ok = erl_tar:close(HandleRead),

    @@ -455,123 +455,123 @@

    The previous Basic example can be extended with encryption and decryption as follows:

    %% First three parameters depending on which crypto type we select:
     Key = <<"This is a 256 bit key. abcdefghi">>,
    -Ivec0 = crypto:strong_rand_bytes(16),
    +Ivec0 = crypto:strong_rand_bytes(16),
     DataSize = 1024,  % DataSize rem 16 = 0 for aes_cbc
     
     %% Initialization of the CryptoState, in this case it is the Ivector.
    -InitFun = fun() -> {ok, Ivec0, DataSize} end,
    +InitFun = fun() -> {ok, Ivec0, DataSize} end,
     
     %% How to encrypt:
     EncryptFun =
    -    fun(PlainBin,Ivec) ->
    -        EncryptedBin = crypto:block_encrypt(aes_cbc256, Key, Ivec, PlainBin),
    -        {ok, EncryptedBin, crypto:next_iv(aes_cbc,EncryptedBin)}
    +    fun(PlainBin,Ivec) ->
    +        EncryptedBin = crypto:block_encrypt(aes_cbc256, Key, Ivec, PlainBin),
    +        {ok, EncryptedBin, crypto:next_iv(aes_cbc,EncryptedBin)}
         end,
     
     %% What to do with the very last block:
     CloseFun =
    -    fun(PlainBin, Ivec) ->
    -        EncryptedBin = crypto:block_encrypt(aes_cbc256, Key, Ivec,
    -                                            pad(16,PlainBin) %% Last chunk
    -                                           ),
    -       {ok, EncryptedBin}
    +    fun(PlainBin, Ivec) ->
    +        EncryptedBin = crypto:block_encrypt(aes_cbc256, Key, Ivec,
    +                                            pad(16,PlainBin) %% Last chunk
    +                                           ),
    +       {ok, EncryptedBin}
         end,
     
    -Cw = {InitFun,EncryptFun,CloseFun},
    -{ok,HandleWrite} = ssh_sftp:open_tar(ChannelPid, ?tar_file_name, [write,{crypto,Cw}]),
    -ok = erl_tar:add(HandleWrite, .... ),
    -ok = erl_tar:add(HandleWrite, .... ),
    +Cw = {InitFun,EncryptFun,CloseFun},
    +{ok,HandleWrite} = ssh_sftp:open_tar(ChannelPid, ?tar_file_name, [write,{crypto,Cw}]),
    +ok = erl_tar:add(HandleWrite, .... ),
    +ok = erl_tar:add(HandleWrite, .... ),
     ...
    -ok = erl_tar:add(HandleWrite, .... ),
    -ok = erl_tar:close(HandleWrite),
    +ok = erl_tar:add(HandleWrite, .... ),
    +ok = erl_tar:close(HandleWrite),
     
     %% And for decryption (in this crypto example we could use the same InitFun
     %% as for encryption):
     DecryptFun =
    -    fun(EncryptedBin,Ivec) ->
    -        PlainBin = crypto:block_decrypt(aes_cbc256, Key, Ivec, EncryptedBin),
    -       {ok, PlainBin, crypto:next_iv(aes_cbc,EncryptedBin)}
    +    fun(EncryptedBin,Ivec) ->
    +        PlainBin = crypto:block_decrypt(aes_cbc256, Key, Ivec, EncryptedBin),
    +       {ok, PlainBin, crypto:next_iv(aes_cbc,EncryptedBin)}
         end,
     
    -Cr = {InitFun,DecryptFun},
    -{ok,HandleRead} = ssh_sftp:open_tar(ChannelPid, ?tar_file_name, [read,{crypto,Cw}]),
    -{ok,NameValueList} = erl_tar:extract(HandleRead,[memory]),
    -ok = erl_tar:close(HandleRead),

    +Cr = {InitFun,DecryptFun}, +{ok,HandleRead} = ssh_sftp:open_tar(ChannelPid, ?tar_file_name, [read,{crypto,Cw}]), +{ok,NameValueList} = erl_tar:extract(HandleRead,[memory]), +ok = erl_tar:close(HandleRead),

    Creating a Subsystem

    A small ssh subsystem that echoes N bytes can be implemented as shown in the -following example:

    -module(ssh_echo_server).
    --behaviour(ssh_server_channel). % replaces ssh_daemon_channel
    --record(state, {
    +following example:

    -module(ssh_echo_server).
    +-behaviour(ssh_server_channel). % replaces ssh_daemon_channel
    +-record(state, {
     	  n,
     	  id,
     	  cm
    -	 }).
    --export([init/1, handle_msg/2, handle_ssh_msg/2, terminate/2]).
    +	 }).
    +-export([init/1, handle_msg/2, handle_ssh_msg/2, terminate/2]).
     
    -init([N]) ->
    -    {ok, #state{n = N}}.
    +init([N]) ->
    +    {ok, #state{n = N}}.
     
    -handle_msg({ssh_channel_up, ChannelId, ConnectionManager}, State) ->
    -    {ok, State#state{id = ChannelId,
    -		     cm = ConnectionManager}}.
    +handle_msg({ssh_channel_up, ChannelId, ConnectionManager}, State) ->
    +    {ok, State#state{id = ChannelId,
    +		     cm = ConnectionManager}}.
     
    -handle_ssh_msg({ssh_cm, CM, {data, ChannelId, 0, Data}}, #state{n = N} = State) ->
    -    M = N - size(Data),
    +handle_ssh_msg({ssh_cm, CM, {data, ChannelId, 0, Data}}, #state{n = N} = State) ->
    +    M = N - size(Data),
         case M > 0 of
     	true ->
    -	   ssh_connection:send(CM, ChannelId, Data),
    -	   {ok, State#state{n = M}};
    +	   ssh_connection:send(CM, ChannelId, Data),
    +	   {ok, State#state{n = M}};
     	false ->
     	   <<SendData:N/binary, _/binary>> = Data,
    -           ssh_connection:send(CM, ChannelId, SendData),
    -           ssh_connection:send_eof(CM, ChannelId),
    -	   {stop, ChannelId, State}
    +           ssh_connection:send(CM, ChannelId, SendData),
    +           ssh_connection:send_eof(CM, ChannelId),
    +	   {stop, ChannelId, State}
         end;
    -handle_ssh_msg({ssh_cm, _ConnectionManager,
    -		{data, _ChannelId, 1, Data}}, State) ->
    -    error_logger:format(standard_error, " ~p~n", [binary_to_list(Data)]),
    -    {ok, State};
    +handle_ssh_msg({ssh_cm, _ConnectionManager,
    +		{data, _ChannelId, 1, Data}}, State) ->
    +    error_logger:format(standard_error, " ~p~n", [binary_to_list(Data)]),
    +    {ok, State};
     
    -handle_ssh_msg({ssh_cm, _ConnectionManager, {eof, _ChannelId}}, State) ->
    -    {ok, State};
    +handle_ssh_msg({ssh_cm, _ConnectionManager, {eof, _ChannelId}}, State) ->
    +    {ok, State};
     
    -handle_ssh_msg({ssh_cm, _, {signal, _, _}}, State) ->
    +handle_ssh_msg({ssh_cm, _, {signal, _, _}}, State) ->
         %% Ignore signals according to RFC 4254 section 6.9.
    -    {ok, State};
    +    {ok, State};
     
    -handle_ssh_msg({ssh_cm, _, {exit_signal, ChannelId, _, _Error, _}},
    -	       State) ->
    -    {stop, ChannelId,  State};
    +handle_ssh_msg({ssh_cm, _, {exit_signal, ChannelId, _, _Error, _}},
    +	       State) ->
    +    {stop, ChannelId,  State};
     
    -handle_ssh_msg({ssh_cm, _, {exit_status, ChannelId, _Status}}, State) ->
    -    {stop, ChannelId, State}.
    +handle_ssh_msg({ssh_cm, _, {exit_status, ChannelId, _Status}}, State) ->
    +    {stop, ChannelId, State}.
     
    -terminate(_Reason, _State) ->
    +terminate(_Reason, _State) ->
         ok.

    The subsystem can be run on the host ssh.example.com with the generated keys, as described in Section -Running an Erlang ssh Daemon:

    1> ssh:start().
    +Running an Erlang ssh Daemon:

    1> ssh:start().
     ok
    -2> ssh:daemon(8989, [{system_dir, "/tmp/ssh_daemon"},
    -                     {user_dir, "/tmp/otptest_user/.ssh"}
    -                     {subsystems, [{"echo_n", {ssh_echo_server, [10]}}]}]).
    -{ok,<0.54.0>}
    -3>
    1> ssh:start().
    +2> ssh:daemon(8989, [{system_dir, "/tmp/ssh_daemon"},
    +                     {user_dir, "/tmp/otptest_user/.ssh"}
    +                     {subsystems, [{"echo_n", {ssh_echo_server, [10]}}]}]).
    +{ok,<0.54.0>}
    +3>
    1> ssh:start().
     ok
    -2> {ok, ConnectionRef} = ssh:connect("ssh.example.com", 8989,
    -                                    [{user_dir, "/tmp/otptest_user/.ssh"}]).
    - {ok,<0.57.0>}
    -3> {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity).
    -4> success = ssh_connection:subsystem(ConnectionRef, ChannelId, "echo_n", infinity).
    -5> ok = ssh_connection:send(ConnectionRef, ChannelId, "0123456789", infinity).
    -6> flush().
    -{ssh_msg, <0.57.0>, {data, 0, 1, "0123456789"}}
    -{ssh_msg, <0.57.0>, {eof, 0}}
    -{ssh_msg, <0.57.0>, {closed, 0}}
    -7> {error, closed} = ssh_connection:send(ConnectionRef, ChannelId, "10", infinity).

    See also ssh_client_channel (replaces ssh_channel(3)).

    +2>
    {ok, ConnectionRef} = ssh:connect("ssh.example.com", 8989, + [{user_dir, "/tmp/otptest_user/.ssh"}]). + {ok,<0.57.0>} +3> {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity). +4> success = ssh_connection:subsystem(ConnectionRef, ChannelId, "echo_n", infinity). +5> ok = ssh_connection:send(ConnectionRef, ChannelId, "0123456789", infinity). +6> flush(). +{ssh_msg, <0.57.0>, {data, 0, 1, "0123456789"}} +{ssh_msg, <0.57.0>, {eof, 0}} +{ssh_msg, <0.57.0>, {closed, 0}} +7> {error, closed} = ssh_connection:send(ConnectionRef, ChannelId, "10", infinity).

    See also ssh_client_channel (replaces ssh_channel(3)).

    diff --git a/prs/9045/lib/ssl-11.2.4/doc/html/.build b/prs/9045/lib/ssl-11.2.4/doc/html/.build index 48f048b0503d..f26afc55e983 100644 --- a/prs/9045/lib/ssl-11.2.4/doc/html/.build +++ b/prs/9045/lib/ssl-11.2.4/doc/html/.build @@ -18,7 +18,7 @@ dist/lato-latin-ext-300-normal-VPGGJKJL.woff2 dist/lato-latin-ext-400-normal-N27NCBWW.woff2 dist/lato-latin-ext-700-normal-Q2L5DVMW.woff2 dist/remixicon-NKANDIL5.woff2 -dist/search_data-CD9C6F07.js +dist/search_data-10404591.js dist/sidebar_items-9D99C4AF.js index.html notes.html diff --git a/prs/9045/lib/ssl-11.2.4/doc/html/dist/search_data-10404591.js b/prs/9045/lib/ssl-11.2.4/doc/html/dist/search_data-10404591.js new file mode 100644 index 000000000000..8cb1e893f873 --- /dev/null +++ b/prs/9045/lib/ssl-11.2.4/doc/html/dist/search_data-10404591.js @@ -0,0 +1 @@ +searchData={"items":[{"type":"module","title":"ssl","doc":"Interface functions for TLS (Transport Layer Security)\nand DTLS (Datagram Transport Layer Security).\n\n> #### Note {: .info }\nThe application's name is still SSL because the first versions of the\nTLS protocol were named SSL (Secure Socket Layer). However, no version\nof the old SSL protocol is supported by this application.\n\nExample:\n```erlang\n1> ssl:start(), ssl:connect(\"google.com\", 443, [{verify, verify_peer},\n {cacerts, public_key:cacerts_get()}]).\n{ok,{sslsocket, [...]}}\n```\n\nSee [Examples](using_ssl.md) for detailed usage and more examples of\nthis API.\n\nSpecial Erlang node configuration for the application can be found in\n[SSL Application](ssl_app.md).","ref":"ssl.html"},{"type":"function","title":"ssl.append_cipher_suites/2","doc":"Make `Deferred` suites become the least preferred suites.\n\nThe `Deferred` suites will be put at the end of the cipher suite list\n`Suites` after removing them from `Suites` if present. `Deferred` can\nbe a list of cipher suites or a list of filters in which case the\nfilters are used on `Suites` to extract the deferred cipher list.","ref":"ssl.html#append_cipher_suites/2"},{"type":"function","title":"ssl.cipher_suites/2","doc":"Lists all available cipher suites corresponding to `Description`.\n\nThe `exclusive` and `exclusive_anonymous` option will exclusively\nlist cipher suites first supported in `Version`, whereas the other options are\ninclusive from the lowest possible version to `Version`. The `all` option\nincludes all suites except anonymous suites. No anonymous suites are supported\nby default.\n\n> #### Note {: .info }\n>\n> TLS-1.3 has no overlapping cipher suites with previous TLS versions, meaning that\n> the result of [`cipher_suites(all, 'tlsv1.3')`](`cipher_suites/2`) contains a separate\n> set of suites that can be used with TLS-1.3 and another set that can be used if a lower\n> version is negotiated. The so-called `PSK` and `SRP` suites (prior to TLS-1.3)\n> need extra configuration to work; namely the option `user_lookup_function`. No\n> anonymous suites are supported by TLS-1.3.\n>\n> Also note that the cipher suites returned by this function are the cipher\n> suites that the OTP SSL application can support provided that they are\n> supported by the crypto library linked with the OTP Crypto application. Use\n> [`ssl:filter_cipher_suites(Suites, [])`](`filter_cipher_suites/2`) to filter\n> the list for the current crypto library. Note that cipher suites may be filtered\n> out because they are too old or too new depending on the crypto library.","ref":"ssl.html#cipher_suites/2"},{"type":"function","title":"ssl.cipher_suites/3","doc":"Equivalent to `cipher_suites/2`, but lists RFC or OpenSSL string names instead of\n[`erl_cipher_suite()`](`t:erl_cipher_suite/0`).","ref":"ssl.html#cipher_suites/3"},{"type":"function","title":"ssl.clear_pem_cache/0","doc":"Clears the PEM cache.\n\nPEM files, used by SSL API-functions, are cached for performance\nreasons. The cache is automatically checked at regular intervals to\ndetermine whether any cache entries should be invalidated.\n\nThis function provides a way to unconditionally clear the entire cache, thereby\nforcing a reload of previously cached PEM files.","ref":"ssl.html#clear_pem_cache/0"},{"type":"function","title":"ssl.close/1","doc":"Closes a TLS/DTLS connection.","ref":"ssl.html#close/1"},{"type":"function","title":"ssl.close/2","doc":"Closes or downgrades a TLS connection.\n\nIn the latter case the transport connection will be handed over to the\n`NewController` process after receiving the TLS close alert from the\npeer. The returned transport socket will have the following options\nset: `[{active, false}, {packet, 0}, {mode, binary}]`.\n\nIn case of downgrade, the close function might return some binary data that\nshould be treated by the user as the first bytes received on the downgraded\nconnection.","ref":"ssl.html#close/2"},{"type":"function","title":"ssl.connect/2","doc":"","ref":"ssl.html#connect/2"},{"type":"function","title":"ssl.connect/3","doc":"Opens a TLS/DTLS connection.\n\n```erlang\nconnect(TCPSocket, TLSOptions, Timeout).\n```\n\nUpgrades a `gen_tcp` (or equivalent) connected socket to a TLS socket by\nperforming the client-side TLS handshake.\n\n\n```erlang\nconnect(Host, Port, TLSOptions).\n```\n\nOpens a TLS/DTLS connection to `Host`, `Port`. This call is equivalent to:\n\n```erlang\nconnect(Host, Port, TLSOptions, infinity).\n```","ref":"ssl.html#connect/3"},{"type":"function","title":"ssl.connect/4","doc":"Opens a TLS/DTLS connection to `Host`, `Port`.\n\nWhen the `verify` option is set to `verify_peer`, the\n`public_key:pkix_verify_hostname/2` check will be performed in addition to the usual\nX.509-path validation checks. If the check fails, the error `{bad_cert,\nhostname_check_failed}` will be propagated to the path validation fun,\nwhere it is possible to do customized checks\nby using the full possibilities of the `public_key:pkix_verify_hostname/3` API.\nWhen the `server_name_indication` option is provided, its value (the DNS name)\nwill be used as `ReferenceID` to `public_key:pkix_verify_hostname/2`. When no\n`server_name_indication` option is given, the `Host` argument will be used as\nServer Name Indication extension. The `Host` argument will also be used for the\n`public_key:pkix_verify_hostname/2` check. If the `Host` argument is an\n[`inet:ip_address()`](`t:inet:ip_address/0`) the `ReferenceID` used for the\ncheck will be `{ip, Host}`; otherwise `dns_id` will be assumed with a fallback to\n`ip` if that fails.\n\n> #### Note {: .info }\n>\n> According to good practices, certificates should not use IP addresses as\n> \"server names\", especially outside a closed network.\n\nIf the `{handshake, hello}` option is used, the handshake is paused after\nreceiving the server hello message and the success response is\n`{ok, SslSocket, Ext}` instead of `{ok, SslSocket}`. Thereafter the handshake is\ncontinued or canceled by calling `handshake_continue/3` or `handshake_cancel/1`.\n\nIf the `active` option is set to `once`, `true`, or an integer value, the process\nowning the SSL socket will receive messages of type\n[`active_msgs()`](`t:active_msgs/0`).","ref":"ssl.html#connect/4"},{"type":"function","title":"ssl.connection_information/1","doc":"Returns the most relevant information about the connection.\n\nSome items that are undefined will be filtered out. No values\nthat affect the security of the connection will be returned.\n\n> #### Note {: .info }\n>\n> The legacy `cipher_suite` item was removed in OTP 23. Previously it returned\n> the cipher suite in its (undocumented) legacy format. It is replaced by\n> `selected_cipher_suite`.","ref":"ssl.html#connection_information/1"},{"type":"function","title":"ssl.connection_information/2","doc":"Returns the requested information items about the connection if they are\ndefined.\n\nNote that the values for `client_random`, `server_random`, `master_secret`, and `keylog`\naffect the security of connection.\n\nIn order to retrieve `keylog` and other secret information from a TLS 1.3\nconnection, the `keep_secrets` option must be configured in advance and\nset to `true`.\n\n> #### Note {: .info }\n>\n> If only undefined options are requested the resulting list can be empty.","ref":"ssl.html#connection_information/2"},{"type":"function","title":"ssl.controlling_process/2","doc":"Assigns a new controlling process to the SSL socket.\n\nA controlling process is the owner of an SSL socket and receives all\nmessages from the socket.","ref":"ssl.html#controlling_process/2"},{"type":"function","title":"ssl.eccs/0","doc":"Returns a list of all supported elliptic curves, including legacy\ncurves, for all TLS/DTLS versions prior to TLS-1.3.","ref":"ssl.html#eccs/0"},{"type":"function","title":"ssl.eccs/1","doc":"Returns the elliptic curves supported by default for `Version`.\n\nThis is a subset of what `eccs/0` returns.","ref":"ssl.html#eccs/1"},{"type":"function","title":"ssl.export_key_materials/4","doc":"","ref":"ssl.html#export_key_materials/4"},{"type":"function","title":"ssl.export_key_materials/5","doc":"Uses a Pseudo-Random Function (PRF prior to TLS-1.3) or a Key\nDerivation Function (HKDF in TLS-1.3) for a TLS connection to\ngenerate and export keying materials.\n\nIn TLS-1.3, using `no_context` is equivalent to specifying an empty\ncontext (an empty binary). Prior to TLS-1.3, `no_context` and an empty\ncontext will produce different results.\n\nThe `ConsumeSecret` argument is relevant only in TLS-1.3, causing the\nTLS-1.3 `exporter_master_secret` to be consumed, thereby making it\nunavailable and increasing security. Further attempts to call this\nfunction will fail.","ref":"ssl.html#export_key_materials/5"},{"type":"function","title":"ssl.filter_cipher_suites/2","doc":"Removes cipher suites if any of the filter functions returns `false` for any part\nof the cipher suite.\n\nIf no filter function is supplied for some part, the default behavior\ntreats it as a filter function that returns `true`. For\nexamples, see [Customizing cipher suites\n](using_ssl.md#customizing-cipher-suites). Additionally, this function\nalso filters the cipher suites to exclude cipher suites not supported\nby the crypto library used by the OTP Crypto application, meaning that\n[`ssl:filter_cipher_suites(Suites, [])`](`filter_cipher_suites/2`)\nis equivalent to applying only the filters for crypto library support.","ref":"ssl.html#filter_cipher_suites/2"},{"type":"function","title":"ssl.format_error/1","doc":"Presents the error returned by an SSL function as a printable string.","ref":"ssl.html#format_error/1"},{"type":"function","title":"ssl.getopts/2","doc":"Gets the values of the specified socket options.","ref":"ssl.html#getopts/2"},{"type":"function","title":"ssl.getstat/1","doc":"Get statistics for the underlying socket.","ref":"ssl.html#getstat/1"},{"type":"function","title":"ssl.getstat/2","doc":"Get one or more statistic values for the underlying socket.\n\nSee `inet:getstat/2` for further details.","ref":"ssl.html#getstat/2"},{"type":"function","title":"ssl.groups/0","doc":"Returns all supported groups in TLS 1.3.\n\nExisted since OTP 22.0; documented as of OTP 27.","ref":"ssl.html#groups/0"},{"type":"function","title":"ssl.groups/1","doc":"Returns default supported groups in TLS 1.3.\n\nExisted since OTP 22.0; documented as of OTP 27.","ref":"ssl.html#groups/1"},{"type":"function","title":"ssl.handshake/1","doc":"","ref":"ssl.html#handshake/1"},{"type":"function","title":"ssl.handshake/2","doc":"Performs the TLS/DTLS server-side handshake.\n\nIf the second argument is a timeout value:\n\n```erlang\nhandshake(HsSocket, Timeout).\n```\n\nthis call is equivalent to:\n\n```erlang\nhandshake(HsSocket, [], Timeout).\n```\n\nOtherwise, if the second argument is a list of options:\n\n\n```erlang\nhandshake(HsSocket, Options).\n```\nthis call is equivalent to:\n\n```erlang\nhandshake(HsSocket, Options, infinity).\n```","ref":"ssl.html#handshake/2"},{"type":"function","title":"ssl.handshake/3","doc":"Performs the TLS/DTLS server-side handshake.\n\nReturns a new TLS/DTLS socket if the handshake is successful.\n\nIf `Socket` is a ordinary [`socket()`](`t:socket/0`), upgrades a\n`gen_tcp` or equivalent socket to an SSL socket by performing the\nTLS server-side handshake and returning a TLS socket.\n\n> #### Note {: .info }\nThe ordinary `Socket` must be in passive mode (`{active, false}`)\nbefore calling this function and before the client tries to connect\nwith TLS; otherwise, the behavior of this function is undefined. The\nbest way to ensure this is to create the ordinary listen socket in\npassive mode.\n\nIf `Socket` is an [`sslsocket()`](`t:sslsocket/0`), provides extra\nTLS/DTLS options to those specified in `listen/2` and then performs\nthe TLS/DTLS handshake. Returns a new TLS/DTLS socket if the handshake\nis successful.\n\n> #### Warning {: .warning }\nNot setting the timeout makes the server more vulnerable to Denial of\nService (DoS) attacks.\n\nIf option `{handshake, hello}` is specified the handshake is paused after\nreceiving the client hello message and the success response is\n`{ok, SslSocket, Ext}` instead of `{ok, SslSocket}`. Thereafter the handshake is\ncontinued or canceled by calling `handshake_continue/3` or `handshake_cancel/1`.\n\nIf option `active` is set to `once`, `true`, or an integer value, the process\nowning the [`sslsocket()`](`t:sslsocket/0`) will receive messages of type\n[`active_msgs()`](`t:active_msgs/0`).","ref":"ssl.html#handshake/3"},{"type":"function","title":"ssl.handshake_cancel/1","doc":"Cancel the handshake with a fatal `USER_CANCELED` alert.","ref":"ssl.html#handshake_cancel/1"},{"type":"function","title":"ssl.handshake_continue/2","doc":"","ref":"ssl.html#handshake_continue/2"},{"type":"function","title":"ssl.handshake_continue/3","doc":"Continue the TLS handshake, possibly with new, additional, or changed options.","ref":"ssl.html#handshake_continue/3"},{"type":"function","title":"ssl.listen/2","doc":"Creates an SSL listen socket.","ref":"ssl.html#listen/2"},{"type":"function","title":"ssl.negotiated_protocol/1","doc":"Returns the protocol negotiated through ALPN or NPN extensions.","ref":"ssl.html#negotiated_protocol/1"},{"type":"function","title":"ssl.peercert/1","doc":"The peer certificate is returned as a DER-encoded binary.\n\nThe certificate can be\ndecoded with `public_key:pkix_decode_cert/2`. Suggested further reading about\ncertificates is [Public_Key User's Guide](`e:public_key:public_key_records.md`)\nand [SSL User's Guide](standards_compliance.md).","ref":"ssl.html#peercert/1"},{"type":"function","title":"ssl.peername/1","doc":"Returns the address and port number of the peer.","ref":"ssl.html#peername/1"},{"type":"function","title":"ssl.prepend_cipher_suites/2","doc":"Make `Preferred` suites become the most preferred suites.\n\nThe `Preferred` suites will be put at the head of the cipher suite\nlist `Suites` after removing them from `Suites` if\npresent. `Preferred` can be a list of cipher suites or a list of\nfilters in which case the filters are used on `Suites` to extract the\npreferred cipher list.","ref":"ssl.html#prepend_cipher_suites/2"},{"type":"function","title":"ssl.prf/5","doc":"Uses the Pseudo-Random Function (PRF) of a TLS session to generate extra key\nmaterial.\n\nIt either takes user-generated values for `Secret` and `Seed` or atoms\ndirecting it to use a specific value from the session security parameters.\n\n> #### Note {: .info }\n\nThis function is replaced by `export_key_materials/4`, the officially\ndocumented API function since OTP 27, which is equivalent to\n[`prf(TLSSocket, master_secret, Label, [client_random, server_random,\nContext], WantedLength)`](`prf/5`). Other ways of calling this\nfunction were for testing purposes only and has no use case. When\ncalled in a TLS-1.3 context it will now behave as\n[`export_key_materials(TLSSocket, [Label], [Context],\n[WantedLength])`](`export_key_materials/4`).","ref":"ssl.html#prf/5"},{"type":"function","title":"ssl.recv/2","doc":"","ref":"ssl.html#recv/2"},{"type":"function","title":"ssl.recv/3","doc":"Receives a packet from a socket in passive mode.\n\nA closed socket is indicated by return value `{error, closed}`.\nArgument `Length` is meaningful only when the socket is in mode `raw`\nand denotes the number of bytes to read. If `Length` is zero, all\navailable bytes are returned. If `Length` is greater than zero,\nexactly `Length` bytes are returned, or an error; possibly discarding\nless than `Length` bytes of data when the socket gets closed from\nthe other side.\n\nOptional argument `Timeout` specifies a time-out in milliseconds. The default\nvalue is `infinity`.","ref":"ssl.html#recv/3"},{"type":"function","title":"ssl.renegotiate/1","doc":"Initiates a new handshake.\n\nA notable return value is `{error, renegotiation_rejected}` indicating\nthat the peer refused to go through with the renegotiation, but the\nconnection is still active using the previously negotiated session.\n\nTLS-1.3 has removed the renegotiation feature from earlier TLS\nversions and instead adds a new feature called key update, which\nreplaces the most important part of renegotiation: the refreshing of\nsession keys. This is triggered automatically after reaching a\nplaintext limit and can be configured using the `key_update_at` option\nin `t:common_option_tls13/0`.","ref":"ssl.html#renegotiate/1"},{"type":"function","title":"ssl.send/2","doc":"Writes `Data` to `SslSocket`.\n\nA notable return value is `{error, closed}` indicating that the socket is\nclosed.","ref":"ssl.html#send/2"},{"type":"function","title":"ssl.setopts/2","doc":"Sets options according to `Options` for socket `SslSocket`.","ref":"ssl.html#setopts/2"},{"type":"function","title":"ssl.shutdown/2","doc":"Immediately closes a socket in one or two directions.\n\n`How == write` means closing the socket for writing, but reading from\nit is still possible.\n\nTo handle siutations where the peer has performed a shutdown on the\nwrite side, option `{exit_on_close, false}` is useful.","ref":"ssl.html#shutdown/2"},{"type":"function","title":"ssl.signature_algs/2","doc":"Lists all available signature algorithms corresponding to `Description`.\n\nThe `exclusive` option will exclusively list algorithms or algorithm schemes for\nthat protocol version, whereas the `default` and `all` options lists the\ncombined list to support the range of protocols from (D)TLS-1.2, the first\nversion to support configuration of the signature algorithms, to `Version`.\n\nExample:\n\n```erlang\n1> ssl:signature_algs(default, 'tlsv1.3').\n[eddsa_ed25519,eddsa_ed448,ecdsa_secp521r1_sha512,\necdsa_secp384r1_sha384,ecdsa_secp256r1_sha256,\nrsa_pss_pss_sha512,rsa_pss_pss_sha384,rsa_pss_pss_sha256,\nrsa_pss_rsae_sha512,rsa_pss_rsae_sha384,rsa_pss_rsae_sha256,\nrsa_pkcs1_sha512,rsa_pkcs1_sha384,rsa_pkcs1_sha256,\n{sha512,ecdsa},\n{sha384,ecdsa},\n{sha256,ecdsa}]\n\n2> ssl:signature_algs(all, 'tlsv1.3').\n[eddsa_ed25519,eddsa_ed448,ecdsa_secp521r1_sha512,\necdsa_secp384r1_sha384,ecdsa_secp256r1_sha256,\nrsa_pss_pss_sha512,rsa_pss_pss_sha384,rsa_pss_pss_sha256,\nrsa_pss_rsae_sha512,rsa_pss_rsae_sha384,rsa_pss_rsae_sha256,\nrsa_pkcs1_sha512,rsa_pkcs1_sha384,rsa_pkcs1_sha256,\n{sha512,ecdsa},\n{sha384,ecdsa},\n{sha256,ecdsa},\n{sha224,ecdsa},\n{sha224,rsa},\n{sha,rsa},\n{sha,dsa}]\n\n3> ssl:signature_algs(exclusive, 'tlsv1.3').\n[eddsa_ed25519,eddsa_ed448,ecdsa_secp521r1_sha512,\necdsa_secp384r1_sha384,ecdsa_secp256r1_sha256,\nrsa_pss_pss_sha512,rsa_pss_pss_sha384,rsa_pss_pss_sha256,\nrsa_pss_rsae_sha512,rsa_pss_rsae_sha384,rsa_pss_rsae_sha256]\n```\n\n> #### Note {: .info }\n>\n> Some TLS-1-3 scheme names overlap with TLS-1.2 algorithm-tuple-pair-names and\n> then TLS-1.3 names will be used, for example `rsa_pkcs1_sha256` instead of\n> `{sha256, rsa}`. These are legacy algorithms in TLS-1.3 that apply only to\n> certificate signatures in this version of the protocol.","ref":"ssl.html#signature_algs/2"},{"type":"function","title":"ssl.sockname/1","doc":"Returns the local address and port number of socket `SslSocket`.","ref":"ssl.html#sockname/1"},{"type":"function","title":"ssl.start/0","doc":"","ref":"ssl.html#start/0"},{"type":"function","title":"ssl.start/1","doc":"Starts the SSL application.","ref":"ssl.html#start/1"},{"type":"function","title":"ssl.stop/0","doc":"Stops the SSL application.","ref":"ssl.html#stop/0"},{"type":"function","title":"ssl.str_to_suite/1","doc":"Converts an RFC or OpenSSL name string to an `t:erl_cipher_suite/0`\n\nReturns an error if the cipher suite is not supported or the name is\nnot a valid cipher suite name.","ref":"ssl.html#str_to_suite/1"},{"type":"function","title":"ssl.suite_to_openssl_str/1","doc":"Converts an [`erl_cipher_suite()`](`t:erl_cipher_suite/0`) value to\nan OpenSSL name string.\n\nPRE TLS-1.3 these names differ for RFC names","ref":"ssl.html#suite_to_openssl_str/1"},{"type":"function","title":"ssl.suite_to_str/1","doc":"Converts an [`erl_cipher_suite()`](`t:erl_cipher_suite/0`) value to an RFC\nname string.","ref":"ssl.html#suite_to_str/1"},{"type":"function","title":"ssl.transport_accept/1","doc":"","ref":"ssl.html#transport_accept/1"},{"type":"function","title":"ssl.transport_accept/2","doc":"Accepts an incoming connection request on a listen socket.\n\n`ListenSocket` must be a socket returned from `listen/2`. The socket\nreturned is to be passed to [`handshake/1,2,3`](`handshake/3`) to\ncomplete the handshake and establish the TLS/DTLS connection.\n\n> #### Warning {: .warning }\n>\n> Most API functions require that the TLS/DTLS connection is established to work\n> as expected.\n\nThe accepted socket inherits the options set for `ListenSocket` in `listen/2`.\n\nThe default value for `Timeout` is `infinity`. If `Timeout` is specified and no\nconnection is accepted within the given time, `{error, timeout}` is returned.","ref":"ssl.html#transport_accept/2"},{"type":"function","title":"ssl.update_keys/2","doc":"Create new session keys.\n\nThere are cryptographic limits on the amount of plaintext which can be safely\nencrypted under a given set of keys. If the amount of data surpasses those\nlimits, a key update is triggered and a new set of keys are installed. See also\nthe `key_update_at` option in `t:common_option_tls13/0`.\n\nThis function can be used to explicitly start a key update on a TLS-1.3\nconnection. There are two types of key updates: if `Type` is `write`,\nonly the writing key is updated; if `Type` is `read_write`, both the\nreading and writing keys are updated.","ref":"ssl.html#update_keys/2"},{"type":"function","title":"ssl.versions/0","doc":"Lists information, mainly concerning TLS/DTLS versions, in runtime for debugging\nand testing purposes.\n\n- **`app_vsn`** - The application version of the SSL application.\n\n- **`supported`** - TLS versions supported with current application environment\n and crypto library configuration. Overridden by a version option on\n [`connect/2,3,4`](`connect/2`), `listen/2`, and\n [`handshake/2,3`](`handshake/2`). For the negotiated TLS version, see\n [`connection_information/1`](`connection_information/1`).\n\n- **`supported_dtls`** - DTLS versions supported with current application\n environment and crypto library configuration. Overridden by a version option\n on [`connect/2,3,4`](`connect/2`), `listen/2`, and\n [`handshake/2,3`](`handshake/2`). For the negotiated DTLS version, see\n [`connection_information/1`](`connection_information/1`).\n\n- **`available`** - All TLS versions supported with the linked crypto library.\n\n- **`available_dtls`** - All DTLS versions supported with the linked crypto\n library.\n\n- **`implemented`** - All TLS versions supported by the SSL application if\n linked with a crypto library with the necessary support.\n\n- **`implemented_dtls`** - All DTLS versions supported by the SSL application if\n linked with a crypto library with the necessary support.","ref":"ssl.html#versions/0"},{"type":"type","title":"ssl.active_msgs/0","doc":"The type for the messages that are delivered to the owner of a\nTLS/DTLS socket in active mode.\n\nThe `ssl_error` reason may convey a TLS protocol alert if such an event occurs\nafter the connection has been established. The most common case when this will\nhappen is on the client side when a TLS-1.3 server requests a client certificate\nand the provided certificate is not accepted by the server, as it will be\nverified after the server has sent its last handshake message.\n\nThe `ssl_passive` message is sent only when the socket is in `{active, N}` mode\nand the counter has dropped to 0. It indicates that the socket has transitioned\nto passive (`{active, false}`) mode.","ref":"ssl.html#t:active_msgs/0"},{"type":"type","title":"ssl.anchor_fun/0","doc":"Claim an intermediate CA in the chain as trusted.\n\n```erlang\nfun(Chain::[public_key:der_encoded()]) ->\n {trusted_ca, DerCert::public_key:der_encoded()} | unknown_ca.\n```\n\nTLS then uses `public_key:pkix_path_validation/3` with the selected CA\nas the trusted anchor and verifies the rest of the chain.","ref":"ssl.html#t:anchor_fun/0"},{"type":"type","title":"ssl.cert_key_conf/0","doc":"Configuration of the entity certificate and its corresponding key.\n\nA certificate (or possibly a list including the certificate and its\nchain certificates, where the entity certificate must be the first\nelement in the list or the first entry in the file) and its associated\nkey. For the PEM file format, there can also be a password associated\nwith the file containing the key.\n\nFor maximum interoperability, the certificates in the chain should be\nin the correct order, as the chain will be sent as-is to the peer. If\nchain certificates are not provided, certificates from the configured\ntrusted CA certificates will be used to construct the chain. See\n[`client_option_cert()`](`t:client_option_cert/0`) and\n[`server_option_cert()`](`t:server_option_cert/0`) for more\ninformation.","ref":"ssl.html#t:cert_key_conf/0"},{"type":"type","title":"ssl.cipher/0","doc":"Cipher algorithms that can be used for payload encryption.","ref":"ssl.html#t:cipher/0"},{"type":"type","title":"ssl.cipher_filters/0","doc":"Filter that allows you to customize cipher suite list.","ref":"ssl.html#t:cipher_filters/0"},{"type":"type","title":"ssl.cipher_suites/0","doc":"A list of cipher suites that should be supported.\n\nFunction [ssl:cipher_suites/2 ](`cipher_suites/2`) can be used to find all\ncipher suites that are supported by default and all cipher suites that can be\nconfigured.\n\nIf you compose your own `t:cipher_suites/0` make sure they are\nfiltered for crypto library support using [ssl:filter_cipher_suites/2\n](`filter_cipher_suites/2`).\n\nThe following function can help creating customized cipher suite lists:\n\n- [ssl:append_cipher_suites/2 ](`append_cipher_suites/2`)\n- [ssl:prepend_cipher_suites/2](`prepend_cipher_suites/2`)\n- [ssl:suite_to_str/1](`suite_to_str/1`)\n- [ssl:str_to_suite/1](`str_to_suite/1`)\n- [ssl:suite_to_openssl_str/1](`suite_to_openssl_str/1`)\n\n> #### Note {: .info }\nNote that TLS-1.3 and TLS-1.2 use different sets of cipher suites. To\nsupport both versions, cipher suites from both sets need to be\nincluded. If the supplied list does not comply with the configured\nversions or crypto library, that is, resulting in an empty list, the option\nwill fall back to its appropriate default value for the configured\nversions.\n\nNon-default cipher suites, including anonymous cipher suites (prior to\nTLS 1.3), are supported for interoperability and testing\npurposes. These can be used by adding them to your cipher suite\nlist. Note that they also need to be supported and enabled by the peer\nto be actually used, and they may require additional configuration;\nsee [`srp_param_type()`](`t:srp_param_type/0`).","ref":"ssl.html#t:cipher_suites/0"},{"type":"type","title":"ssl.ciphers/0","doc":"Cipher suite formats.\n\nFor backwards compatibility, cipher suites can be configured as a\ncolon-separated string of cipher suite RFC names (or even old OpenSSL\nnames). However, a more flexible approach is to use utility functions\ntogether with [`cipher_filters()`](`t:cipher_filters/0`) if a customized\ncipher suite option is needed.","ref":"ssl.html#t:ciphers/0"},{"type":"type","title":"ssl.client_option/0","doc":"The following options are specific to the client side, or have\ndifferent semantics for the client and server:\n\n- **`{alpn_advertised_protocols, AppProtocols}`** - Application layer protocol\n\n The list of protocols supported by the client to be sent to the server to be\n used for an Application-Layer Protocol Negotiation (ALPN). If the server\n supports ALPN, it will choose a protocol from this list; otherwise it will\n fail the connection with a `no_application_protocol` alert. A server that does\n not support ALPN will ignore this value. The list of protocols must not contain\n an empty binary.\n\n- **`{max_fragment_length, MaxLen}`** - Max fragment length extension\n\n Specifies the maximum fragment length the client is prepared to accept from the\n server. See [RFC 6066](http://www.ietf.org/rfc/rfc6066.txt).","ref":"ssl.html#t:client_option/0"},{"type":"type","title":"ssl.client_option_cert/0","doc":"Certificate-related options specific to the client side, or with\ndifferent semantics for the client and server.\n\n- **`{verify, Verify}`** - Verification of certificates\n\n This option specifies whether certificates are to be verified.\n\n If `Verify` is `verify_peer`, which is the default, it is required\n to also provide one of the options `cacerts` or `cacertfile` in\n order for the certificate verification to succeed. For example, an\n HTTPS client can use option `{cacerts, public_key:cacerts_get()}` to\n use the trusted CA certificates provided by the operating system.\n\n If `Verify` is `verify_none`, all X.509-certificate path\n validation errors will be ignored.\n\n > #### Change {: .info }\n >\n > The default for `Verify` was changed to `verify_peer` in\n > Erlang/OTP 26.\n\n- **`{cacerts, CACerts}`** - Trusted certificates\n\n The DER-encoded trusted certificates. If this option is supplied it overrides\n option `cacertfile`.\n\n Function `public_key:cacerts_get/0` can be used to retrieve to the\n trusted CA certificates provided by the operating system.\n\n- **`{cacertfile, CertFile}`** - End entity certificate\n\n Path to a file containing PEM-encoded CA certificates. The CA certificates are\n used during server authentication and when building the client certificate\n chain.\n\n > #### Note {: .info }\n >\n > When PEM caching is enabled, files provided with this option will be checked\n > for updates at fixed time intervals specified by the\n > [ssl_pem_cache_clean](ssl_app.md#configuration) environment parameter.\n\n\n- **`{server_name_indication, SNI}`** - Server Name Indication extension\n\n Specify the hostname to be used in TLS Server Name Indication extension. If not\n specified it will default to the `Host` argument of\n [connect/3,4](`connect/3`) unless it is of type [`inet:ip_address()`](`t:inet:ip_address/0`).\n The hostname will also be used in the hostname verification of the peer\n certificate using `public_key:pkix_verify_hostname/2`.\n The special value `disable` prevents the Server Name Indication extension from\n being sent and disables the hostname verification check.\n\n- **`{customize_hostname_check, HostNameCheckOpts}`** - Customization option\n\n Customizes the hostname verification of the peer certificate, as various\n protocols that use TLS, such as HTTP or LDAP, may require different approaches. For\n example, here is how to use standard hostname checking for HTTPS implemented in\n [Public_Key](`e:public_key:public_key_app.md`):\n\n ```erlang\n {customize_hostname_check, [{match_fun, public_key:pkix_verify_hostname_match_fun(https)}]}\n ```\n\n For futher description of the customize options, see\n `public_key:pkix_verify_hostname/3`.\n\n- **`{client_certificate_authorities, UseCertAuth}`** - Inter-op hint option\n\n If `UseCertAuth` is set to `true`, sends the certificate authorities\n extension in the TLS-1.3 client hello. The default is `false`. Note\n that setting `UseCertAuth` to `true` can result in a significant\n overhead if there exists many trusted CA certificates. (Since\n Erlang/OTP 24.3.)\n\n- **`{stapling, Stapling}`** - Certificate revocation check option\n\n If `Stapling` is atom `staple` or a map, OCSP stapling will be\n enabled, meaning that an extension of type \"status_request\" will be\n included in the client hello to indicate the desire to receive\n certificate status information.\n\n If `Stapling` is set to `no_staple` (the default), OCSP stapling will be disabled.\n\n > #### Note {: .info }\n >\n > Even if requested by the client, the OCSP response might not be\n > provided by the server. In such event, SSL will proceed with\n > the handshake and generate a `{missing, stapling_response}` logger\n > event.\n\n When `Stapling` is given as a map, boolean `ocsp_nonce` key can\n indicate whether an OCSP nonce should be requested by the client\n (default is `false`).\n\n > #### Note {: .info }\n >\n > The OCSP response can be provided without a nonce value — even if it was requested\n > by the client. In such cases SSL will proceed with the handshake and generate\n > a `{missing, ocsp_nonce}` logger event.","ref":"ssl.html#t:client_option_cert/0"},{"type":"type","title":"ssl.client_option_legacy/0","doc":"Legacy client options.\n\n- **`{client_preferred_next_protocols, NextAppProtocols}`** - Next Protocol Negotiation\n\n ALPN (Application-Layer Protocol Negotiation)\n deprecates NPN (Next Protocol Negotiation) and this option.\n\n Indicates that the client wants to perform Next Protocol Negotiation.\n\n If `Precedence` is `server`, the negotiated protocol is the first protocol to be\n shown on the server advertised list that is also on the client preference\n list.\n\n If `Precedence` is `client`, the negotiated protocol is the first protocol to be\n shown on the client preference list that is also on the server advertised\n list.\n\n If the client does not support any of the server advertised protocols or the\n server does not advertise any protocols, the client falls back to the first\n protocol in its list or to the default protocol (if a default is supplied). If\n the server does not support Next Protocol Negotiation, the connection terminates\n if no default protocol is supplied.","ref":"ssl.html#t:client_option_legacy/0"},{"type":"type","title":"ssl.client_option_pre_tls13/0","doc":"Options only relevant to TLS versions prior to TLS-1.3.\n\n- **`{reuse_session, SessionRef}`** - Explicit session reuse\n\n Reuses a specific session.\n\n Since Erlang/OTP 21.3, if the session was saved earlier using option\n `{reuse_sessions, save}`, the session can be referred by its session ID.\n\n Since Erlang/OTP 22.3, the session can be explicitly specified by\n its session ID and associated data.\n\n See also\n [SSL User's Guide, Session Reuse pre TLS 1.3.](using_ssl.md#session-reuse-prior-to-tls-1-3)\n\n- **`{reuse_sessions, Reuse}`** - Enables later session reuse\n\n When `Reuse` is set to `save`, a new connection will be negotiated and saved for later\n reuse. The session ID can be fetched with `connection_information/2` and used\n with the client option `reuse_session`.\n\n When `Reuse` is set to `true`, automated session reuse will be\n performed, if possible. If a new session is created, and is unique in regard to previous\n stored sessions, it will be saved for possible later reuse.\n\n Since: OTP 21.3.\n\n- **`{psk_identity, PskID}`** - Option for use with PSK cipher suites\n\n Specifies the identity the client presents to the server. The matching secret is\n found by the fun given in the `user_lookup_fun` option.\n\n- **`{srp_identity, SrpID}`** - Option for use SRP cipher suites\n\n Specifies the username and password to use to authenticate to the server.\n\n- **`{fallback, LegacyFallback}`** - Inter-op legacy client option\n\n Send special cipher suite TLS_FALLBACK_SCSV to avoid an undesired TLS version\n downgrade. Defaults to `false`.\n\n > #### Warning {: .warning }\n >\n > This option is not needed in normal TLS usage and must not be used to\n > implement new clients. However, legacy clients that retries connections in the\n > following manner:\n >\n > `ssl:connect(Host, Port, [...{versions, ['tlsv2', 'tlsv1.1', 'tlsv1']}])`\n >\n > `ssl:connect(Host, Port, [...{versions, [tlsv1.1', 'tlsv1']}, {fallback, true}])`\n >\n > `ssl:connect(Host, Port, [...{versions, ['tlsv1']}, {fallback, true}])`\n >\n > can use it to avoid undesired TLS version downgrade. Note that\n > TLS_FALLBACK_SCSV must also be supported by the server for the prevention to\n > work.","ref":"ssl.html#t:client_option_pre_tls13/0"},{"type":"type","title":"ssl.client_option_tls13/0","doc":"Options only relevant for TLS-1.3.\n\n- **`{session_tickets, SessionTickets}`** - Use of session tickets\n\n Configures the session ticket functionality. Allowed values are `disabled`,\n `manual`, and `auto`. If it is set to `manual` the client will send the ticket\n information to user process in a 3-tuple:\n\n ```erlang\n {ssl, session_ticket, {SNI, TicketData}}\n ```\n\n where `SNI` is the ServerNameIndication and `TicketData` is the extended ticket\n data that can be used in subsequent session resumptions.\n\n If it is set to `auto`, the client automatically handles received tickets and\n tries to use them when making new TLS connections (session resumption with\n pre-shared keys).\n\n Ticket lifetime, the number of tickets sent by the server, and the\n maximum number of tickets stored by the server in stateful mode are configured\n by [application variables](ssl_app.md#configuration).\n\n See also\n [SSL User's Guide, Session Tickets and Session Resumption in TLS 1.3](using_ssl.md#session-tickets-and-session-resumption-in-tls-1-3).\n\n- **`{use_ticket, Tickets}`**\n\n Configures the session tickets to be used for session resumption. It is a\n mandatory option in `manual` mode (`{session_tickets, manual}`).\n\n > #### Note {: .info }\n >\n > Session tickets are only sent to the user if option `session_tickets` is set to\n > `manual`\n >\n > This option is supported by TLS-1.3. See also\n > [SSL User's Guide, Session Tickets and Session Resumption in TLS 1.3](using_ssl.md#session-tickets-and-session-resumption-in-tls-1-3).\n\n- **`{early_data, EarlyData}`**\n\n Configures the early data to be sent by the client.\n\n To verify that the server has the intention to process the early\n data, the following tuple is sent to the user process:\n\n ```erlang\n {ssl, SslSocket, {early_data, Result}}\n ```\n\n where `Result` is either `accepted` or `rejected`.\n\n > #### Warning {: .warning }\n >\n > It is the responsibility of the user to handle rejected `EarlyData` and to\n > resend when appropriate.\n\n- **`{middlebox_comp_mode, MiddleBoxMode}`**\n\n Configures the middlebox compatibility mode for a TLS-1.3 connection.\n\n A significant number of middleboxes misbehave when a TLS-1.3\n connection is negotiated. Implementations can increase the chance of\n making connections through those middleboxes by adapting the TLS-1.3\n handshake to resemble that of a TLS-1.2 handshake.\n\n The middlebox compatibility mode is enabled (`true`) by default.","ref":"ssl.html#t:client_option_tls13/0"},{"type":"type","title":"ssl.common_option/0","doc":"Options common to both client and server side.\n\n- **`{protocol, Protocol}`** - Choose TLS or DTLS protocol for the transport layer security.\n\n Defaults to `tls`.\n\n- **`{handshake, Completion}`** - Possibly pause handshake at hello stage.\n\n Defaults to `full`. If `hello` is specified the handshake will pause\n after the hello message, allowing the user to make decisions based\n on hello extensions before continuing or aborting the handshake by\n calling `handshake_continue/3` or `handshake_cancel/1`.\n\n- **`{keep_secrets, KeepSecrets}`** - Configures a TLS 1.3 connection for keylogging.\n\n In order to retrieve keylog information on a TLS 1.3 connection, it must be\n configured in advance to keep `client_random` and various handshake secrets.\n\n The `keep_secrets` functionality is disabled (`false`) by default.\n\n Added in OTP 23.2.\n\n- **`{max_handshake_size, HandshakeSize}`** - Limit the acceptable handshake packet size.\n\n Used to limit the size of valid TLS handshake packets to avoid DoS\n attacks.\n\n Integer (24 bits, unsigned). Defaults to `256*1024`.\n\n- **`{hibernate_after, HibernateTimeout}`** - Hibernate inactive connection processes.\n\n When an integer-value is specified, the TLS/DTLS connection goes into hibernation\n after the specified number of milliseconds of inactivity, thus reducing its\n memory footprint. When not specified the process never goes into hibernation.\n\n- **`{log_level, Level}`** - Specifies the log level for a TLS/DTLS connection.\n\n Alerts are logged on `notice`\n level, which is the default level. The level `debug` triggers verbose logging of\n TLS/DTLS protocol messages. See also [SSL Application](ssl_app.md)\n\n- **`{receiver|sender_spawn_opts, SpawnOpts}`** - Configure erlang spawn opts.\n\n Configures spawn options of TLS sender and receiver processes.\n\n Setting up garbage collection options can be helpful for trade-offs between CPU\n usage and memory usage. See `erlang:spawn_opt/2`.\n\n For connections using Erlang distribution, the default sender option\n is `[...{priority, max}]`; this priority option cannot be changed. For all\n connections, `...link` is added to receiver and cannot be changed.","ref":"ssl.html#t:common_option/0"},{"type":"type","title":"ssl.common_option_cert/0","doc":"Common certificate related options to both client and server.\n\n- **`{certs_keys, CertsKeys}`** - At least one certificate and key pair.\n\n A list of a certificate (or possible a certificate and its chain)\n and the associated key of the certificate that can be used to\n authenticate the client or the server. The certificate key pair that\n is considered best and matches negotiated parameters for the\n connection will be selected.\n\n The different signature algorithms are prioritized in the following\n order: `eddsa`, `ecdsa`, `rsa_pss_pss`, `rsa`, and `dsa`. If more\n than one key is supplied for the same signature algorithm, they will\n be prioritized by strength (except for _engine keys_; see the next\n paragraph). This offers flexibility to, for instance, configure a\n newer certificate that is expected to be used in most cases, and an\n older but acceptable certificate that will only be used to\n communicate with legacy systems. Note that there is a trade off\n between the induced overhead and the flexibility; thus, alternatives\n should be chosen for good reasons.\n\n _Engine keys_ will be favored over other keys. As engine keys cannot\n be inspected, supplying more than one engine key makes no sense.\n\n When this option is specified it overrides all single certificate\n and key options. For examples, see the [User's Guide](using_ssl.md).\n\n > #### Note {: .info }\n >\n > `eddsa` certificates are only supported by TLS-1.3 implementations that do not support `dsa`\n > certificates. `rsa_pss_pss` (RSA certificates using Probabilistic Signature\n > Scheme) are supported in TLS-1.2 and TLS-1.3, but some TLS-1.2 implementations\n > do not support `rsa_pss_pss`.\n\n- **`{depth, AllowedCertChainLen}`** - Limits the accepted number of certificates in the certificate chain.\n\n Maximum number of non-self-issued intermediate certificates that can follow the\n peer certificate in a valid certification path. So, if depth is 0 the PEER must\n be signed by the trusted ROOT-CA directly; if 1 the path can be PEER, CA,\n ROOT-CA; if 2 the path can be PEER, CA, CA, ROOT-CA, and so on. The default\n value is 10. Used to mitigate DoS attack possibilities.\n\n- **`{verify_fun, Verify}`** - Customize certificate path validation\n\n The verification fun is to be defined as follows:\n\n ```erlang\n fun(OtpCert :: #'OTPCertificate'{},\n Event, InitialUserState :: term()) ->\n\t{valid, UserState :: term()} |\n\t{fail, Reason :: term()} | {unknown, UserState :: term()}.\n\n fun(OtpCert :: #'OTPCertificate'{}, DerCert :: public_key:der_encoded(),\n Event, InitialUserState :: term()) ->\n\t{valid, UserState :: term()} |\n\t{fail, Reason :: term()} | {unknown, UserState :: term()}.\n\n Types:\n Event = {bad_cert, Reason :: atom() |\n {revoked, atom()}} |\n\t\t{extension, #'Extension'{}} |\n valid |\n valid_peer\n ```\n\n The verification fun is called during the X.509-path validation when\n an error occurs or an extension unknown to the SSL application is\n encountered. It is also called when a certificate is considered\n valid by the path validation to allow access to each certificate in\n the path to the user application. It differentiates between the peer\n certificate and the CA certificates by using `valid_peer` or `valid`\n as `Event` argument to the verification fun. See the [Public_Key\n User's Guide](`e:public_key:public_key_records.md`) for definition\n of `#'OTPCertificate'{}` and `#'Extension'{}`.\n\n - If the verify callback fun returns `{fail, Reason}`, the verification process\n is immediately stopped, an alert is sent to the peer, and the TLS/DTLS\n handshake terminates.\n - If the verify callback fun returns `{valid, UserState}`, the verification\n process continues.\n - If the verify callback fun always returns `{valid, UserState}`, the TLS/DTLS\n handshake does not terminate regardless of verification failures, and the\n connection is established.\n - If called with an extension unknown to the user application, the fun is to\n return `{unknown, UserState}`.\n\n Note that if the fun returns `unknown` for an extension marked as critical,\n validation will fail.\n\n Default option `verify_fun` in `verify_peer mode`:\n\n ```erlang\n {fun(_, _, {bad_cert, _} = Reason, _) ->\n\t {fail, Reason};\n (_, _, {extension, _}, UserState) ->\n\t {unknown, UserState};\n (_, _, valid, UserState) ->\n\t {valid, UserState};\n (_, _, valid_peer, UserState) ->\n {valid, UserState}\n end, []}\n ```\n\n Default option `verify_fun` in mode `verify_none`:\n\n ```erlang\n {fun(_, _, {bad_cert, _}, UserState) ->\n\t {valid, UserState};\n (_, _, {extension, #'Extension'{critical = true}}, UserState) ->\n\t {valid, UserState};\n (_, _, {extension, _}, UserState) ->\n\t {unknown, UserState};\n (_, _, valid, UserState) ->\n\t {valid, UserState};\n (_, _, valid_peer, UserState) ->\n {valid, UserState}\n end, []}\n ```\n\n The possible path validation errors are given in the form `{bad_cert, Reason}`,\n where `Reason` is:\n\n - **`unknown_ca`**\n\n No trusted CA was found in the trusted store. The trusted\n CA is normally a so-called ROOT CA, which is a self-signed certificate. Trust\n can be claimed for an intermediate CA (the trusted anchor does not have to be\n self-signed according to X-509) by using option `partial_chain`.\n\n - **`selfsigned_peer`**\n\n The chain consisted only of one self-signed certificate.\n\n - **`PKIX X-509-path validation error`**\n\n For possible reasons, see `public_key:pkix_path_validation/3`.\n\n- **`{cert_policy_opts, PolicyOpts}`** - Handle certificate policies.\n\n Configure X.509 certificate policy handling for the certificate path validation process;\n see [public_key:pkix_path_validation/3](`public_key:pkix_path_validation/3`) for\n more details.\n\n- **`{cerl_check, Check}`** - Handle certificate revocation lists.\n\n Perform CRL (Certificate Revocation List) verification\n [(public_key:pkix_crls_validate/3)](`public_key:pkix_crls_validate/3`) on all\n the certificates during the path validation\n [(public_key:pkix_path_validation/3) ](`public_key:pkix_path_validation/3`)of\n the certificate chain. `Check` defaults to `false`.\n\n The meaning of `Check` is as follows:\n\n - **`false`**\n\n No checks are performed.\n\n - **`peer`**\n\n Check is only performed on the peer certificate.\n\n - **`best_effort`**\n\n If certificate revocation status cannot be determined it will be accepted as valid.\n\n The CA certificates specified for the connection will be used to construct the\n certificate chain validating the CRLs.\n\n The CRLs will be fetched from a local or external cache. See\n `m:ssl_crl_cache_api`.","ref":"ssl.html#t:common_option_cert/0"},{"type":"type","title":"ssl.common_option_dtls/0","doc":"Common options to client and server only valid for DTLS.\n\n- **`{use_srtp, UseSrtp}`** - Configures the `use_srtp` DTLS hello extension.\n\n In order to negotiate the use of SRTP data protection, clients include an\n extension of type \"use_srtp\" in the DTLS extended client hello. This extension\n MUST only be used when the data being transported is RTP or RTCP.\n\n The value is a map with a mandatory `protection_profiles` parameter\n and an optional `mki` parameter.\n\n `protection_profiles` configures the list of the client's acceptable SRTP\n Protection Profiles. Each profile is a 2-byte binary. Example:\n `#{protection_profiles => [<<0,2>>, <<0,5>>]}`\n\n `mki` configures the SRTP Master Key Identifier chosen by the client.\n\n The `srtp_mki` field contains the value of the SRTP MKI which is associated with\n the SRTP master keys derived from this handshake. Each SRTP session MUST have\n exactly one master key that is used to protect packets at any given time. The\n client MUST choose the MKI value so that it is distinct from the last MKI value\n that was used, and it SHOULD make these values unique for the duration of the\n TLS session.\n\n > #### Note {: .info }\n >\n > OTP does not handle SRTP, so an external implementations of SRTP\n > encoder/decoder and a packet demultiplexer are needed to make use of the\n > `use_srtp` extension. See also option [transport_option](`t:transport_option/0`).\n\n Servers that receive an extended hello containing a \"use_srtp\" extension can\n agree to use SRTP by including an extension of type \"use_srtp\", with the chosen\n protection profile in the extended server hello. This extension MUST only be\n used when the data being transported is RTP or RTCP.","ref":"ssl.html#t:common_option_dtls/0"},{"type":"type","title":"ssl.common_option_legacy/0","doc":"Legacy options considered deprecated in favor of other options,\ninsecure to use, or plainly not relevant anymore.\n\n- **`{cert, Certs}`**\n\n Use option `certs_keys` instead.\n\n- **`{certfile, CertPem}`**\n\n Use option `certs_keys` instead.\n\n- **`{keyfile, KeyPem}`**\n\n Use option `certs_keys` instead.\n\n- **`{password, KeyPemPasswd}`**\n\n Use option `certs_keys` instead.\n\n- **`{log_alert, LogAlert}`**\n\n If `LogAlert` is `false`, TLS/DTLS Alert reports are not displayed. Deprecated in OTP\n 22; use `{log_level, Level}` instead.\n\n- **`{padding_check, PaddingCheck}`** - Inter-op trade-off option\n\n Affects TLS-1.0 connections only. If set to `false`, it disables the block\n cipher padding check to be able to interoperate with legacy software.\n\n > #### Warning {: .warning }\n >\n > Using `{padding_check, false}` makes TLS vulnerable to the Poodle attack.\n\n- **`{beast_mitigation, BeastMitigation}`** - Inter-op trade-off option\n\n Affects TLS-1.0 connections only. Used to change the BEAST mitigation strategy\n to interoperate with legacy software. Defaults to `one_n_minus_one`.\n\n `one_n_minus_one` - Perform `1/n-1` BEAST mitigation.\n\n `zero_n` - Perform `0/n` BEAST mitigation.\n\n `disabled` - Disable BEAST mitigation.\n\n > #### Warning {: .warning }\n >\n > Using `{beast_mitigation, disabled}` makes TLS-1.0 vulnerable to the BEAST\n > attack.\n\n- **`{ssl_imp, Imp}`**\n\n Deprecated since OTP 17; has no effect.","ref":"ssl.html#t:common_option_legacy/0"},{"type":"type","title":"ssl.common_option_pre_tls13/0","doc":"Options common to client and server side prior to TLS-1.3.\n\n- **`{eccs, NamedCurves}`** - Named Elliptic Curves\n\n Elliptic curves that can be used in pre TLS-1.3 key exchange.\n\n- **`{secure_renegotiate, SecureRenegotiate}`** - Inter-operate trade-off option\n\n Specifies whether to reject renegotiation attempt that does not live\n up to [RFC 5746](http://www.ietf.org/rfc/rfc5746.txt). By default,\n `SecureRenegotiate` is `true`, meaning that secure renegotiation is\n enforced. If `SecureRenegotiate` is `false` secure renegotiation\n will still be used if possible, but it falls back to insecure\n renegotiation if the peer does not support if [RFC\n 5746](http://www.ietf.org/rfc/rfc5746.txt).\n\n- **`{user_lookup_fun, {LookupFun, UserState}}`** - PSK/SRP cipher suite option\n\n The lookup fun is to be defined as follows:\n\n ```erlang\n fun(psk, PSKIdentity :: binary(), UserState :: term()) ->\n\t{ok, SharedSecret :: binary()} | error;\n fun(srp, Username :: binary(), UserState :: term()) ->\n\t{ok, {SRPParams :: srp_param_type(), Salt :: binary(),\n\t DerivedKey :: binary()}} | error.\n ```\n\n For Pre-Shared Key (PSK) cipher suites, the lookup fun is called by the client\n and server to determine the shared secret. When called by the client,\n `PSKIdentity` is the hint presented by the server or `undefined`. When\n called by the server, `PSKIdentity` is the identity presented by the client.\n\n For Secure Remote Password (SRP), the fun is only used by the server to obtain\n parameters that it uses to generate its session keys. `DerivedKey` is to be\n derived according to [RFC 2945](http://tools.ietf.org/html/rfc2945#section/3)\n and [RFC 5054](http://tools.ietf.org/html/rfc5054#section-2.4):\n `crypto:sha([Salt, crypto:sha([Username, <<$:>>, Password])])`","ref":"ssl.html#t:common_option_pre_tls13/0"},{"type":"type","title":"ssl.common_option_tls13/0","doc":"Common options to both client and server for TLS-1.3.\n\n- **`{supported_groups, Groups}`** - Key exchange option\n\n TLS 1.3 introduces the \"supported_groups\" extension, which is used for negotiating\n the Diffie-Hellman parameters in a TLS 1.3 handshake. Both client and server can\n specify a list of parameters that they are willing to use.\n\n If not specified it will use a default list (`[x25519, x448, secp256r1,\n secp384r1]`) that is filtered based on the installed crypto library version.\n\n- **`{key_update_at, KeyUpdateAt}`** - Session key renewal\n\n Configures the maximum amount of bytes that can be sent on a TLS 1.3 connection\n before an automatic key update is performed.\n\n There are cryptographic limits on the amount of plaintext which can be safely\n encrypted under a given set of keys. The current default ensures that data\n integrity will not be breached with probability greater than `1/2^57`. For more\n information see\n [Limits on Authenticated Encryption Use in TLS](https://eprint.iacr.org/2024/051.pdf).","ref":"ssl.html#t:common_option_tls13/0"},{"type":"type","title":"ssl.connection_info/0","doc":"Key value list convening some information about the established connection.","ref":"ssl.html#t:connection_info/0"},{"type":"type","title":"ssl.connection_info_keys/0","doc":"TLS connection keys for which information can be retrieved.","ref":"ssl.html#t:connection_info_keys/0"},{"type":"type","title":"ssl.connection_info_pre_tls13/0","doc":"TLS connection information relevant prior to TLS-1.3.","ref":"ssl.html#t:connection_info_pre_tls13/0"},{"type":"type","title":"ssl.crl_cache_opts/0","doc":"Options for using built-in CRL cache support.\n\nSpecify how to perform lookup and caching of certificate revocation\nlists (CRLs). `Module` defaults to `m:ssl_crl_cache` with `DbHandle`\nbeing `internal`, and `Args` being `[]`.\n\nThere are two implementations available:\n\n- **`ssl_crl_cache`** - Implementation 1\n\n This module maintains a cache of CRLs. CRLs can be added to the\n cache using `ssl_crl_cache:insert/1`, and can optionally be\n automatically fetched through HTTP if the following argument is\n specified:\n\n- **`{http, timeout()}`**\n\n Enables fetching of CRLs specified as http URIs in [X.509 certificate\n extensions](`e:public_key:public_key_records.md`). Requires the\n [Inets](`e:inets:introduction.md`) application.\n\n- **`ssl_crl_hash_dir`** - Implementation 2\n\n This module makes use of a directory where CRLs are\n stored in files named by the hash of the issuer name.\n\n The file names consist of eight hexadecimal digits followed by `.rN`, where\n `N` is an integer, for example `1a2b3c4d.r0`. For the first version of the CRL, `N`\n starts at zero, and for each new version, `N` is incremented by one. The\n OpenSSL utility `c_rehash` creates symlinks according to this pattern.\n\n For a given hash value, this module finds all consecutive `.r*`\n files starting from zero, and those files taken together make up the\n revocation list. CRL files with `nextUpdate` fields in the past or\n issued by a different CA that happens to have the same name hash\n are excluded.\n\n The following argument is required:\n\n - **`{dir, string()}`**\n\n Specifies the directory in which the CRLs can be found.","ref":"ssl.html#t:crl_cache_opts/0"},{"type":"type","title":"ssl.dtls_legacy_version/0","doc":"A DTLS protocol version that are no longer supported by default for security reasons.","ref":"ssl.html#t:dtls_legacy_version/0"},{"type":"type","title":"ssl.dtls_version/0","doc":"DTLS protocol version.","ref":"ssl.html#t:dtls_version/0"},{"type":"type","title":"ssl.erl_cipher_suite/0","doc":"Erlang cipher suite representation\n\n> #### Warning {: .warning }\nEnabling cipher suites using RSA as a key exchange algorithm is\nstrongly discouraged (only available prior to TLS-1.3). For some\nconfigurations software preventions may exist, and can make them\nusable if they work, but relying on them to work is risky. There\nexists more reliable cipher suites that can be used instead.","ref":"ssl.html#t:erl_cipher_suite/0"},{"type":"type","title":"ssl.error_alert/0","doc":"If a TLS connection fails a TLS protocol ALERT will be sent/received.\n\nAn atom reflecting the raised alert, according to the TLS protocol, and a description string\nwith some further details will be returned.","ref":"ssl.html#t:error_alert/0"},{"type":"type","title":"ssl.group/0","doc":"TLS-1.3 key exchange configuration.","ref":"ssl.html#t:group/0"},{"type":"type","title":"ssl.hash/0","doc":"Hash algorithms used together with signing and encryption functions.","ref":"ssl.html#t:hash/0"},{"type":"type","title":"ssl.host/0","doc":"A name or address to a host.","ref":"ssl.html#t:host/0"},{"type":"type","title":"ssl.kex_algo/0","doc":"Cipher Suite Key Exchange Algorithm will be `any`\nin TLS-1.3 as key exchange is no longer part of cipher suite\nconfiguration in TLS-1.3.","ref":"ssl.html#t:kex_algo/0"},{"type":"type","title":"ssl.key/0","doc":"The user's private key.\n\nThe key can be provided either directly as a DER-encoded entity,\nindirectly using a crypto engine/provider (with key reference\ninformation), or as an Erlang fun (with possible custom options).\nThe latter two options can be used for customized signing with\nhardware security modules (HSM) or trusted platform modules (TPM).\n\n- A DER encoded key will need to specify the ASN-1 type used to create the\n encoding.\n- An engine/provider needs to specify specific information to support this\n concept and can optionally be password protected; see also\n [crypto:engine_load/3 ](`crypto:engine_load/3`) and\n [Crypto User's Guide](`e:crypto:engine_load.md`).\n- A fun option should include a fun that mimics `public_key:sign/4` and possibly\n [public_key:private_encrypt/4](`public_key:encrypt_private/3`) if legacy\n versions TLS-1.0 and TLS-1.1 must be supported.","ref":"ssl.html#t:key/0"},{"type":"type","title":"ssl.legacy_cipher/0","doc":"Cipher algorithms that are no longer supported by default for security reasons.","ref":"ssl.html#t:legacy_cipher/0"},{"type":"type","title":"ssl.legacy_hash/0","doc":"Hash algorithms that are no longer supported by default for security reasons.","ref":"ssl.html#t:legacy_hash/0"},{"type":"type","title":"ssl.legacy_named_curve/0","doc":"Key exchange configuration prior to TLS-1.3.\n\nThese curves have been deprecated by RFC 8422.","ref":"ssl.html#t:legacy_named_curve/0"},{"type":"type","title":"ssl.legacy_sign_algo/0","doc":"Signature algorithms that are no longer supported by default for security reasons.","ref":"ssl.html#t:legacy_sign_algo/0"},{"type":"type","title":"ssl.legacy_sign_scheme/0","doc":"This is only used for certificate signatures if TLS-1.2 is negotiated,\nmeaning that the peer only supports TLS-1.2, but we also support\nTLS-1.3.","ref":"ssl.html#t:legacy_sign_scheme/0"},{"type":"type","title":"ssl.named_curve/0","doc":"Key exchange configuration prior to TLS-1.3.","ref":"ssl.html#t:named_curve/0"},{"type":"type","title":"ssl.old_cipher_suite/0","doc":"For backwards compatibility only; do not use.","ref":"ssl.html#t:old_cipher_suite/0"},{"type":"type","title":"ssl.prf_random/0","doc":"","ref":"ssl.html#t:prf_random/0"},{"type":"type","title":"ssl.protocol_extensions/0","doc":"Client hello extensions.","ref":"ssl.html#t:protocol_extensions/0"},{"type":"type","title":"ssl.protocol_version/0","doc":"TLS or DTLS protocol version.","ref":"ssl.html#t:protocol_version/0"},{"type":"type","title":"ssl.reason/0","doc":"Error reason for debug purposes.\n\nNot to be matched.","ref":"ssl.html#t:reason/0"},{"type":"type","title":"ssl.rsassa_pss_scheme/0","doc":"Supported in TLS-1.3 and TLS-1.2.","ref":"ssl.html#t:rsassa_pss_scheme/0"},{"type":"type","title":"ssl.security_info/0","doc":"TLS connection information that can be used for NSS key logging.","ref":"ssl.html#t:security_info/0"},{"type":"type","title":"ssl.server_option/0","doc":"Options specific to the server side, or with different semantics for the client and server.\n\n- **`{alpn_preferred_protocols, AppProtocols}`** - Application Layer Protocol Negotiation\n\n Indicates that the server will try to perform Application-Layer\n Protocol Negotiation (ALPN).\n\n The list of protocols is in order of preference. The protocol negotiated will be\n the first in the list that matches one of the protocols advertised by the\n client. If no protocol matches, the server will fail the connection with a\n `no_application_protocol` alert.\n\n The negotiated protocol can be retrieved using the\n [`negotiated_protocol/1`](`negotiated_protocol/1`) function.\n\n- **`{sni_fun, SNIFun}`**\n\n If the server receives a SNI (Server Name Indication) from the\n client, the given fun `SNIFun` will be called to retrieve\n [`server_option()`](`t:server_option/0`) for the indicated\n hosts. These options will override previously specified options for\n that host.\n\n > #### Note {: .info }\n The options `sni_fun` and `sni_hosts` are mutually exclusive.\n\n- **`{sni_hosts, SNIHosts}`**\n\n If the server receives a SNI (Server Name Indication) from the client matching a\n host listed in the `sni_hosts` option, the specific options for that host will\n override previously specified options.\n\n > #### Note {: .info }\n The options `sni_fun` and `sni_hosts` are mutually exclusive.","ref":"ssl.html#t:server_option/0"},{"type":"type","title":"ssl.server_option_cert/0","doc":"Certificate related options for a server.\n\n- **`{cacerts, CACerts}`** - Trusted certificates.\n\n The DER-encoded trusted certificates. If this option is supplied, it overrides\n the `cacertfile` option.\n\n- **`{verify, Verify}`** - Verify certificates.\n\n Client certificates are an optional part of the TLS protocol. A server performs\n X.509 certificate path validation only in `verify_peer` mode. By default the server\n is in `verify_none` mode and, hence, will not send an certificate request to the\n client. When using `verify_peer` you may also want to specify the options\n `fail_if_no_peer_cert` and `certificate_authorities`.\n\n- **`{fail_if_no_peer_cert, FailNoPeerCert}`** - Legacy trade-off option\n\n Used together with `{verify, verify_peer}` by an TLS/DTLS server. If set to\n `true`, the server fails if the client does not have a certificate to send, that\n is, sends an empty certificate. If set to `false`, it fails only if the client\n sends an invalid certificate (an empty certificate is considered valid).\n Defaults to `false`.\n\n- **`{certificate_authorities, ServerCertAuth}`** - Inter-operate hint option\n\n Determines whether a TLS-1.3 server should include the authorities extension in its\n certificate request message that is sent when the option `verify` is set to\n `verify_peer`. Defaults to `true`.\n\n If set to `false` for older TLS versions its corresponding certificate authorities\n definition in its certificate request will be set to the empty list instead of\n including the appropriate certificate authorities. This has the same affect\n as excluding the TLS-1.3 extension.\n\n A reason to exclude the extension would be if the server wants to communicate\n with clients incapable of sending complete certificate chains that adhere to the\n extension, but the server still has the capability to recreate a chain that it\n can verify.","ref":"ssl.html#t:server_option_cert/0"},{"type":"type","title":"ssl.server_option_legacy/0","doc":"Legacy server options.\n\n- **`{next_protocols_advertised, NextAppProtocols}`**\n\n ALPN (Application-Layer Protocol Negotiation)\n deprecates NPN (Next Protocol Negotiation) described here.\n\n List of protocols to send to the client if the client indicates that it supports\n the Next Protocol extension. The client can select a protocol that is not on\n this list. The list of protocols must not contain an empty binary. If the server\n negotiates a Next Protocol, it can be accessed using the\n `negotiated_protocol/1` method.","ref":"ssl.html#t:server_option_legacy/0"},{"type":"type","title":"ssl.server_option_pre_tls13/0","doc":"Options only relevant to TLS versions prior to TLS-1.3.\n\n- **`{client_renegotiation, ClientRengotiation}`** - DoS attack avoidance option\n\n In protocols that support client-initiated renegotiation, the resource cost\n of such an operation is higher for the server than the client. This can act as a\n vector for denial-of-service (DoS) attacks. The SSL application already takes measures\n to counter-act such attempts, but client-initiated renegotiation can be completely\n disabled by setting this option to `false`. The default value is `true`. Note\n that disabling renegotiation can result in long-lived connections becoming\n unusable due to limits on the number of messages the underlying cipher suite can\n encipher.\n\n- **`{reuse_sessions, ReuseSessions}`** - Enable session reuse\n\n The boolean value `true` specifies that the server will agree to reuse sessions.\n Setting it to `false` will result in an empty session table, meaning that no sessions\n will be reused.\n\n- **`{reuse_session, ReuseSession}`** - Local server reuse policy\n\n Enables the TLS/DTLS server to have a local policy for deciding whether a session\n is to be reused. Meaningful only if `reuse_sessions` is set to `true`.\n\n `ReuseSession` should be a fun:\n\n `fun(SuggestedSessionId, PeerCert, Compression, CipherSuite)`\n\n `SuggestedSessionId` is a [`binary()`](`t:binary/0`),\n `PeerCert` is a DER-encoded certificate,\n `Compression` is an enumeration integer, and `CipherSuite` is of type\n [`erl_cipher_suite()`](`t:erl_cipher_suite/0`).\n\n- **`{psk_identity, PSKHint}`** - Inter-operate hint option\n\n Specifies the server identity hint that the server presents to the client.\n\n- **`{honor_cipher_order, HonorServerCipherOrder}`** - Trade-off option alters protocol defined behavior\n\n If `true`, use the server's preference for ECC curve selection. If `false` (the\n default), use the client's preference.\n\n- **`{honor_ecc_order, HonorServerECCOrder}`** - Trade-off option alters protocol defined behavior\n\n If `true`, use the server's preference for ECC curve selection. If `false` (the\n default), use the client's preference.\n\n- **`{dh, DHder}`** - Affects DH key exchange cipher suites\n\n The DER-encoded Diffie-Hellman parameters. If specified, it overrides option\n `dhfile`.\n\n- **`{dh_file, DHfile}`** - Affects DH key exchange cipher suites\n\n Path to a file containing PEM-encoded Diffie Hellman parameters to be used by\n the server if a cipher suite using Diffie Hellman key exchange is negotiated. If\n not specified, default parameters are used.","ref":"ssl.html#t:server_option_pre_tls13/0"},{"type":"type","title":"ssl.server_option_tls13/0","doc":"Options only relevant for TLS-1.3.\n\n- **`{session_tickets, SessionTickets}`**\n\n Configures the session ticket functionality. Allowed values for `SessionTickets` are:\n\n * `disabled`\n * `stateful`\n * `stateless`\n * `stateful_with_cert`\n * `stateless_with_cert`\n\n If `SessionTickets` is not set to `disabled`, session resumption with pre-shared\n keys is enabled and the server will send stateful or stateless session tickets to the\n client after successful connections.\n\n > #### Note {: .info }\n In pre-shared key session ticket resumption, there is no certificate\n exchange involved. Therefore, `ssl:peercert/1` will not return the\n peer certificate, as it is only communicated during the initial\n handshake. To associate the client certificate from the original\n handshake with the tickets it issues, the server options\n `stateful_with_cert` or `stateless_with_cert` can be used.\n\n A stateful session ticket is a database reference to internal state information.\n A stateless session ticket is a self-encrypted binary that contains both\n cryptographic keying material and state data.\n\n > #### Warning {: .warning }\n When `SessionTickets` is set to `stateful_with_cert`, the client\n certificate is stored along with the internal state information,\n leading to increased memory consumption. Conversely, when it is set\n to `stateless_with_cert`, the client certificate is encoded in the\n self-encrypted binary sent to the client, resulting in an increase\n in payload size.\n\n See also [SSL User's Guide, Session Tickets and Session Resumption in TLS 1.3](using_ssl.md#session-tickets-and-session-resumption-in-tls-1-3).\n\n- **`{stateless_tickets_seed, TicketSeed}`** - Option for statless tickets\n\n Configures the seed used for the encryption of stateless session tickets.\n Allowed values are any randomly generated `t:binary/0`. If this option is not\n configured, an encryption seed will be randomly generated.\n\n > #### Warning {: .warning }\n >\n > Reusing the ticket encryption seed between multiple server instances enables\n > stateless session tickets to work across multiple server instances, but it\n > breaks anti-replay protection across instances.\n >\n > Inaccurate time synchronization between server instances can also affect\n > session ticket freshness checks, potentially causing false negatives as well\n > as false positives.\n\n- **`{anti_replay, AntiReplay}`** - Option for statless tickets\n\n Configures the server's built-in anti replay feature based on Bloom filters.\n\n Allowed values for `AntiReplay` are the pre-defined `'10k'`,\n `'100k'`, or a custom 3-tuple that defines the properties of the\n bloom filters:\n `{WindowSize, HashFunctions, Bits}`. `WindowSize` is the number of seconds after\n the current Bloom filter is rotated and also the window size used for freshness\n checks of ClientHello. `HashFunctions` is the number hash functions and `Bits`\n is the number of bits in the bit vector. `'10k'` and `'100k'` are simple\n defaults with the following properties:\n\n - `'10k'`: Bloom filters can hold 10000 elements with 3% probability of false\n positives. `WindowSize`: 10, `HashFunctions`: 5, `Bits:` 72985 (8.91 KiB).\n - `'100k'`: Bloom filters can hold 100000 elements with 3% probability of false\n positives. `WindowSize`: 10, `HashFunctions`: 5, `Bits`: 729845 (89.09 KiB).\n\n See also [SSL User's Guide, Anti-Replay Protection in TLS\n 1.3](using_ssl.md#anti-replay-protection-in-tls-1-3).\n\n- **`{cookie, Cookie}`** - Option for `HelloRetryRequest` behavior\n\n If `Cookie` is `true`, which is the default, the server sends a\n cookie extension in its `HelloRetryRequest` messages.\n\n The cookie extension has two main purposes. It allows the server to force the\n client to demonstrate reachability at their apparent network address (thus\n providing a measure of DoS protection). This is primarily useful for\n non-connection-oriented transports. It also allows offloading the server's\n state to the client. The cookie extension is enabled by default as it is a\n mandatory extension in RFC8446.\n\n- **`{early_data, EarlyData}`** - Option for accepting or rejecting Early Data\n\n Configures if the server accepts (`enabled`) or rejects (`disabled`) early data\n sent by a client. The default value is `disabled`.","ref":"ssl.html#t:server_option_tls13/0"},{"type":"type","title":"ssl.session_id/0","doc":"Identifies a TLS session prior to TLS-1.3.","ref":"ssl.html#t:session_id/0"},{"type":"type","title":"ssl.sha2/0","doc":"SHA2 hash algorithms.","ref":"ssl.html#t:sha2/0"},{"type":"type","title":"ssl.sign_algo/0","doc":"Signature algorithms.","ref":"ssl.html#t:sign_algo/0"},{"type":"type","title":"ssl.sign_scheme/0","doc":"Signature schemes, defined by TLS-1.3, and replacing signature algorithms from TLS-1.2.\n\nExplicitly list acceptable signature schemes in the preferred\norder.\n\nOverrides the algorithms supplied in\n[`signature_algs`](`t:signature_algs/0`) option for certificates.\nIn addition to the `signature_algorithms` extension from TLS 1.2,\n[TLS 1.3 (RFC 5246 Section 4.2.3)](http://www.ietf.org/rfc/rfc8446.txt#section-4.2.3)\nadds the `signature_algorithms_cert` extension which enables having special\nrequirements on the signatures used in the certificates that differs from the\nrequirements on digital signatures as a whole. If this is not required this\nextension is not needed.\n\nThe client will send a `signature_algorithms_cert` extension (in the\nclient hello message), if TLS version 1.2 (back-ported to TLS 1.2 in\n24.1) or later is used, and the signature_algs_cert option is\nexplicitly specified. By default, only the\n[signature_algs](`t:signature_algs/0`) extension is sent with the\nexception of when signature_algs option is not explicitly specified,\nin which case it will append the rsa_pkcs1_sha1 algorithm to the\ndefault value of signature_algs and use it as value for\nsignature_algs_cert to allow certificates to have this signature but\nstill disallow sha1 use in the TLS protocol, since 27.0.1 and 26.2.5.2.\n\n> #### Note {: .info }\n>\n> Note that supported signature schemes for TLS-1.2 are\n[`legacy_sign_scheme()`](`t:legacy_sign_scheme/0`)\n> and [`rsassa_pss_scheme()`](`t:rsassa_pss_scheme/0`).","ref":"ssl.html#t:sign_scheme/0"},{"type":"type","title":"ssl.signature_algs/0","doc":"Explicitly list acceptable signature algorithms for certificates and handshake\nmessages in the preferred order.\n\nThe client will send its list as the client hello\n`signature_algorithm` extension introduced in TLS-1.2; see [Section\n7.4.1.4.1 in RFC 5246](http://www.ietf.org/rfc/rfc5246.txt). Before\nTLS-1.2, these algorithms where implicitly chosen and partly derived\nfrom the cipher suite.\n\nIn TLS-1.2 a somewhat more explicit negotiation is made possible using a list of\n`{HashAlgo, SignAlgo}` tuples.\n\nIn TLS-1.3, these algorithm pairs are replaced by [signature\nschemes](`t:sign_scheme/0`) that are completely decoupled from the\ncipher suite.\n\nSignature algorithms used for certificates can be overridden by the\n[signature schemes](`t:sign_scheme/0`) supplied by the\n`signature_algs_cert` option.\n\nThe TLS-1.2 default is `Default_TLS_12_Alg_Pairs` interleaved with\n`rsa_pss_schemes` since ssl-11.0 (Erlang/OTP 25). `pss_pss` is\npreferred over `pss_rsae`, which in turn is preferred over `rsa`.\n\nThe list for `Default_TLS_12_Alg_Pairs` is defined as follows:\n\n```erlang\n[\n{sha512, ecdsa},\n{sha512, rsa},\n{sha384, ecdsa},\n{sha384, rsa},\n{sha256, ecdsa},\n{sha256, rsa}\n]\n```\n\n> #### Change {: .info }\n>\n> - Support for `{md5, rsa}` was removed from the TLS-1.2 default in\n> ssl-8.0 (Erlang/OTP 22).\n> - Support for `{sha, _}` (SHA1) and `{sha224, _}` was removed\n> from the TLS-1.2 default in ssl-11.0 (Erlang/OTP 26).\n\nThe list for `rsa_pss_schemes` is defined as follows:\n\n\n```erlang\n[rsa_pss_pss_sha512,\nrsa_pss_pss_sha384,\nrsa_pss_pss_sha256,\nrsa_pss_rsae_sha512,\nrsa_pss_rsae_sha384,\nrsa_pss_rsae_sha256]\n```\n\nThe list of `TLS_13_Legacy_Schemes` is defined as follows:\n\n```erlang\n[\n%% Legacy algorithms only applicable to certificate signatures\nrsa_pkcs1_sha512, %% Corresponds to {sha512, rsa}\nrsa_pkcs1_sha384, %% Corresponds to {sha384, rsa}\nrsa_pkcs1_sha256, %% Corresponds to {sha256, rsa}\n]\n```\n\nThe list of `Default_TLS_13_Schemes` is defined as follows:\n\n```text\n[\n%% EDDSA\neddsa_ed25519,\neddsa_ed448\n\n%% ECDSA\necdsa_secp521r1_sha512,\necdsa_secp384r1_sha384,\necdsa_secp256r1_sha256] ++\n\n%% RSASSA-PSS\nrsa_pss_schemes()\n```\n\n> #### Change {: .info }\n>\n> EDDSA was made highest priority in ssl-10.8 (Erlang/OTP 25).\n\nThe TLS-1.3 default is `Default_TLS_13_Schemes`.\n\nIf both TLS-1.3 and TLS-1.2 are supported the default is:\n\n```erlang\nDefault_TLS_13_Schemes ++ TLS_13_Legacy_Schemes ++\nDefault_TLS_12_Alg_Pairs %% not represented in TLS_13_Legacy_Schemes\n```\n\nto ensure that appropriate algorithms can be chosen for the negotiated\nversion.\n\n> #### Note {: .info }\nTLS-1.2 algorithms will not be negotiated for TLS-1.3, but the TLS-1.3\nRSASSA-PSS ([`rsassa_pss_scheme()`](`t:rsassa_pss_scheme/0`))\nsignature schemes can be negotiated also for TLS-1.2 from Erlang/OTP\n24.1 (fully working from Erlang/OTP 24.1.3). However, if both TLS 1.3\nand TLS 1.2 are supported using defaults, and TLS 1.3 is negotiated,\nthe corresponding TLS 1.2 algorithms for TLS 1.3 legacy signature\nschemes will be treated as legacy schemes and applied only to\ncertificate signatures.","ref":"ssl.html#t:signature_algs/0"},{"type":"type","title":"ssl.socket/0","doc":"A socket that can be used to perform a so-called \"START-TLS\", which\nmeans using an already connected socket previously used for plain TCP\ntraffic and upgrading it to use TLS.\n\nBoth sides needs to agree on the upgrade.","ref":"ssl.html#t:socket/0"},{"type":"type","title":"ssl.socket_option/0","doc":"Options for the transport socket.\n\nThe default socket options are\n`[{mode, list}, {packet, 0}, {header, 0}, {active, true}]`.\n\nFor valid options, see `m:inet`, `m:gen_tcp`, and `m:gen_udp`\nin Kernel. Note that stream-oriented options such as `packet` are\nonly relevant for TLS and not DTLS.","ref":"ssl.html#t:socket_option/0"},{"type":"type","title":"ssl.srp_param_type/0","doc":"SRP cipher suite configuration prior to TLS-1.3.","ref":"ssl.html#t:srp_param_type/0"},{"type":"type","title":"ssl.sslsocket/0","doc":"An opaque reference to the TLS/DTLS connection.\n\nNote that despite being opaque, matching `sslsocket()` instances is allowed.","ref":"ssl.html#t:sslsocket/0"},{"type":"type","title":"ssl.tls_alert/0","doc":"TLS Alert Protocol reasons.","ref":"ssl.html#t:tls_alert/0"},{"type":"type","title":"ssl.tls_client_option/0","doc":"An option that can be supplied to a TLS client.","ref":"ssl.html#t:tls_client_option/0"},{"type":"type","title":"ssl.tls_legacy_version/0","doc":"A TLS protocol version that are no longer supported by default for security reasons.","ref":"ssl.html#t:tls_legacy_version/0"},{"type":"type","title":"ssl.tls_option/0","doc":"An option related to the TLS/DTLS protocol.","ref":"ssl.html#t:tls_option/0"},{"type":"type","title":"ssl.tls_server_option/0","doc":"An option that can be supplied to a TLS server.","ref":"ssl.html#t:tls_server_option/0"},{"type":"type","title":"ssl.tls_version/0","doc":"TLS protocol version.","ref":"ssl.html#t:tls_version/0"},{"type":"type","title":"ssl.transport_option/0","doc":"Transport option defines a callback module and message tags to handle the underlying transport socket.\n\nCan be used to customize the transport layer. The tag\nvalues should be the values used by the underlying transport in its active mode\nmessages.\n\nDefaults to `{gen_tcp, tcp, tcp_closed, tcp_error, tcp_passive}` for TLS.\n\n> #### Note {: .info }\nFor backward compatibility a tuple of size four will be converted to a\ntuple of size five, where `PassiveTag` is the `DataTag` element with\n`_passive` appended.\n\nFor TLS the callback module must implement a reliable transport\nprotocol, behave as `m:gen_tcp`, and have functions corresponding to\n`inet:setopts/2`, `inet:getopts/2`, `inet:peername/1`, `inet:sockname/1`, and\n`inet:port/1`. The callback `m:gen_tcp` is treated specially and calls `m:inet`\ndirectly. For DTLS this feature is considered experimental.","ref":"ssl.html#t:transport_option/0"},{"type":"module","title":"ssl_crl_cache","doc":"CRL cache\n\nImplements an internal CRL (Certificate Revocation List) cache. In addition to\nimplementing the `m:ssl_crl_cache_api` behaviour the following functions are\navailable.","ref":"ssl_crl_cache.html"},{"type":"function","title":"ssl_crl_cache.delete/1","doc":"Delete CRLs from the ssl applications local cache.","ref":"ssl_crl_cache.html#delete/1"},{"type":"function","title":"ssl_crl_cache.insert/1","doc":"","ref":"ssl_crl_cache.html#insert/1"},{"type":"function","title":"ssl_crl_cache.insert/2","doc":"Insert CRLs into the ssl applications local cache, with or without a\ndistribution point reference URI","ref":"ssl_crl_cache.html#insert/2"},{"type":"type","title":"ssl_crl_cache.crl_src/0","doc":"A source to input CRLs","ref":"ssl_crl_cache.html#t:crl_src/0"},{"type":"behaviour","title":"ssl_crl_cache_api","doc":"API for a TLS CRL (Certificate Revocation List) cache.\n\nWhen TLS performs certificate path validation according to\n[RFC 5280 ](http://www.ietf.org/rfc/rfc5280.txt)it should also perform CRL\nvalidation checks. To enable the CRL checks the application needs access to\nCRLs. A database of CRLs can be set up in many different ways. This module\nprovides the behavior of the API needed to integrate an arbitrary CRL cache with\nthe erlang ssl application. It is also used by the application itself to provide\na simple default implementation of a CRL cache.","ref":"ssl_crl_cache_api.html"},{"type":"callback","title":"ssl_crl_cache_api.fresh_crl/2","doc":"`fun fresh_crl/2` will be used as input option `update_crl` to\n`public_key:pkix_crls_validate/3`.\n\nIt is possible to return logger info, since OTP 22.2, that will be used by the TLS connection to\nproduce log events.","ref":"ssl_crl_cache_api.html#c:fresh_crl/2"},{"type":"callback","title":"ssl_crl_cache_api.lookup/2","doc":"Backwards compatibility, replaced by lookup/3","ref":"ssl_crl_cache_api.html#c:lookup/2"},{"type":"callback","title":"ssl_crl_cache_api.lookup/3","doc":"Lookup the CRLs belonging to the distribution point `Distributionpoint`. This\nfunction may choose to only look in the cache or to follow distribution point\nlinks depending on how the cache is administrated.\n\nThe `Issuer` argument contains the issuer name of the certificate to\nbe checked. Normally the returned CRL should be issued by this\nissuer, except if the `cRLIssuer` field of `DistributionPoint` has a\nvalue, in which case that value should be used instead.\n\nIn an earlier version of this API, the `lookup` function received two\narguments, omitting `Issuer`. For compatibility, this is still\nsupported: if there is no [`lookup/3`](`c:lookup/3`) function in the\ncallback module,[`lookup/2`](`c:lookup/2`) is called instead.\n\nIt is possible to return logger info, since OTP 22.2, that will be used by the TLS connection to\nproduce log events.","ref":"ssl_crl_cache_api.html#c:lookup/3"},{"type":"callback","title":"ssl_crl_cache_api.select/2","doc":"Select the CRLs in the cache that are issued by `Issuer` unless the value is a\nlist of so called general names, see\n[X509 certificates records](`e:public_key:public_key_records.md`), originating\nform `#'DistributionPoint'.cRLissuer` and representing different mechanism to\nobtain the CRLs. The cache callback needs to use the appropriate entry to\nretrieve the CRLs or return an empty list if it does not exist.\n\nIt is possible to return logger info, since OTP 22.2, that will be used by the TLS connection to\nproduce log events.","ref":"ssl_crl_cache_api.html#c:select/2"},{"type":"type","title":"ssl_crl_cache_api.crl_cache_ref/0","doc":"Reference to the CRL cache.","ref":"ssl_crl_cache_api.html#t:crl_cache_ref/0"},{"type":"type","title":"ssl_crl_cache_api.dist_point/0","doc":"For description see\n[X509 certificates records](`e:public_key:public_key_records.md`)","ref":"ssl_crl_cache_api.html#t:dist_point/0"},{"type":"type","title":"ssl_crl_cache_api.logger_info/0","doc":"Information for ssl applications use of [Logger(3)](`m:logger`)","ref":"ssl_crl_cache_api.html#t:logger_info/0"},{"type":"behaviour","title":"ssl_session_cache_api","doc":"TLS session cache API\n\nDefines the API for the TLS session cache (pre TLS-1.3) so that the data storage\nscheme can be replaced by defining a new callback module implementing this API.","ref":"ssl_session_cache_api.html"},{"type":"callback","title":"ssl_session_cache_api.delete/2","doc":"Deletes a cache entry.\n\nIs only called from the cache handling process.","ref":"ssl_session_cache_api.html#c:delete/2"},{"type":"callback","title":"ssl_session_cache_api.foldl/3","doc":"Calls `Fun(Elem, AccIn)` on successive elements of the cache, starting with\n `AccIn == Acc0`.\n\n`Fun/2` must return a new accumulator, which is passed to the\nnext call. The function returns the final value of the accumulator. `Acc0` is\nreturned if the cache is empty.\n\n> #### Note {: .info }\n>\n> Since OTP-23.3 this functions is only used on the client side and does not\n> need to implemented for a server cache.","ref":"ssl_session_cache_api.html#c:foldl/3"},{"type":"callback","title":"ssl_session_cache_api.init/1","doc":"Performs possible initializations of the cache and returns a reference to it\nthat is used as parameter to the other API functions. \n\nIs called by the cache handling processes `init` function, hence\nputting the same requirements on it as a normal process `init`\nfunction. This function is called twice when starting the SSL\napplication, once with the role client and once with the role server,\nas the SSL application must be prepared to take on both roles.\n\nIncludes property `{role, client | server}` in init argument list. \nCurrently this is the only predefined property, there can also be\nuser-defined properties. See also application environment variable\n[session_cb_init_args](ssl_app.md).","ref":"ssl_session_cache_api.html#c:init/1"},{"type":"callback","title":"ssl_session_cache_api.lookup/2","doc":"Looks up a cache entry. Is to be callable from any process.","ref":"ssl_session_cache_api.html#c:lookup/2"},{"type":"callback","title":"ssl_session_cache_api.select_session/2","doc":"Selects sessions that can be reused, that is sessions that include `PartialKey`\nin its key. Is to be callable from any process.\n\n> #### Note {: .info }\n>\n> Since OTP-23.3 This functions is only used on the client side and does not\n> need to implemented for a server cache.","ref":"ssl_session_cache_api.html#c:select_session/2"},{"type":"callback","title":"ssl_session_cache_api.size/1","doc":"Returns the number of sessions in the cache.\n\nIf size exceeds the maximum number of sessions, the current cache\nentries will be invalidated regardless of their remaining lifetime. Is\nto be callable from any process.","ref":"ssl_session_cache_api.html#c:size/1"},{"type":"callback","title":"ssl_session_cache_api.terminate/1","doc":"Takes care of possible cleanup that is needed when the cache handling process\nterminates.","ref":"ssl_session_cache_api.html#c:terminate/1"},{"type":"callback","title":"ssl_session_cache_api.update/3","doc":"Caches a new session or updates an already cached one.\n\nIs only called from the cache handling process.","ref":"ssl_session_cache_api.html#c:update/3"},{"type":"opaque","title":"ssl_session_cache_api.partial_key/0","doc":"The opaque part of the key. Does not need to be handled by the callback.","ref":"ssl_session_cache_api.html#t:partial_key/0"},{"type":"opaque","title":"ssl_session_cache_api.session/0","doc":"The session data that is stored for each session.","ref":"ssl_session_cache_api.html#t:session/0"},{"type":"type","title":"ssl_session_cache_api.session_cache_key/0","doc":"A key to an entry in the session cache.","ref":"ssl_session_cache_api.html#t:session_cache_key/0"},{"type":"type","title":"ssl_session_cache_api.session_cache_ref/0","doc":"A term that can be used to reference the cache.","ref":"ssl_session_cache_api.html#t:session_cache_ref/0"},{"type":"extras","title":"SSL Application","doc":"\n# SSL Application\n\nThe ssl application provides secure communication over sockets.","ref":"ssl_app.html"},{"type":"extras","title":"Description - SSL Application","doc":"The ssl application is an implementation of the TLS (previously known as SSL) and DTLS protocols in\nErlang.\n\nFor current statement of standards compliance see the\n[User's Guide](standards_compliance.md).","ref":"ssl_app.html#description"},{"type":"extras","title":"Dependencies - SSL Application","doc":"The SSL application uses the `Public_Key`, `Asn1` and `Crypto` application to\nhandle public keys and encryption, hence these applications must be loaded for\nthe SSL application to work. In an embedded environment this means they must be\nstarted with `application:start/1,2` before the SSL application is started.","ref":"ssl_app.html#dependencies"},{"type":"extras","title":"Configuration - SSL Application","doc":"The application environment configuration parameters in this section are defined\nfor the SSL application. For more information about configuration parameters,\nsee the `m:application` manual page in Kernel.\n\n> #### Note {: .info }\nAll parameters including the wording 'session_ticket' are TLS-1.3 only configuration\nand other session parameters are prior to TLS-1.3 only configuration. DTLS versions\nare based on TLS versions see [standard compliance](standards_compliance.md) for mapping.\n\nThe environment parameters can be set on the command line, for example:\n\n`erl -ssl protocol_version \"['tlsv1.2', 'tlsv1.1']\"`\n\n- **`protocol_version = ` `t:ssl:tls_version/0` | [`t:ssl:tls_version/0`]\n ` `** - Protocol supported by started clients and servers. If this\n option is not set, it defaults to all TLS protocols currently supported, more\n might be configurable, by the SSL application. This option can be overridden\n by the version option to `ssl:connect/2,3` and `ssl:listen/2`.\n\n- **`dtls_protocol_version = ` `t:ssl:dtls_version/0` | [`t:ssl:dtls_version/0`]\n ` `** - Protocol supported by started clients and servers. If this\n option is not set, it defaults to all DTLS protocols currently supported, more\n might be configurable, by the SSL application. This option can be overridden\n by the version option to `ssl:connect/2,3` and `ssl:listen/2`.\n\n- **`session_lifetime = integer() `** - Maximum lifetime of the\n session data in seconds. Defaults to 24 hours which is the maximum recommended\n lifetime by [RFC 5246](http://www.ietf.org/rfc/5246rfc.txt). However sessions\n may be invalidated earlier due to the maximum limitation of the session cache\n table.\n\n- **`session_cb = atom() `** - Deprecated Since OTP-23.3 replaced by\n `client_session_cb` and `server_session_cb`\n\n- **`client_session_cb = atom() `** - Since OTP-23.3 Name client of\n the session cache callback module that implements the `ssl_session_cache_api`\n behavior. Defaults to `ssl_client_session_cache_db`.\n\n- **`server_session_cb = atom() `** - Since OTP-23.3 Name of the\n server session cache callback module that implements the\n `ssl_session_cache_api` behavior. Defaults to `ssl_server_session_cache_db`.\n\n- **`session_cb_init_args = proplist:proplist() `** - Deprecated Since\n OTP-23.3 replaced by `client_session_cb_init_args` and\n `server_session_cb_init_args`\n\n- **`client_session_cb_init_args = proplist:proplist() `** - List of\n extra user-defined arguments to the `init` function in the session cache\n callback module. Defaults to `[]`.\n\n- **`server_session_cb_init_args = proplist:proplist() `** - List of\n extra user-defined arguments to the `init` function in the session cache\n callback module. Defaults to `[]`.\n\n- **`session_cache_client_max = integer() ` \n ** \n Limits the growth of the clients session cache, that is how many sessions\n towards servers that are cached to be used by new client connections. If the\n maximum number of sessions is reached, the current cache entries will be\n invalidated regardless of their remaining lifetime. Defaults to 1000.\n Recommended ssl-8.2.1 or later for this option to work as intended.\n\n- **`session_cache_server_max = integer() `** - Limits the growth of\n the servers session cache, that is how many client sessions are cached by the\n server. If the maximum number of sessions is reached, the current cache\n entries will be invalidated regardless of their remaining lifetime. Defaults\n to 1000. Recommended ssl-8.2.1 or later for this option to work as intended.\n\n- **`ssl_pem_cache_clean = integer() `** - Number of milliseconds\n between PEM cache validations. Defaults to 2 minutes.\n\n Note: The cache can be reloaded by calling `ssl:clear_pem_cache/0`.\n\n- **`bypass_pem_cache = boolean() `** - Introduced in ssl-8.0.2.\n Disables the PEM-cache. Can be used as a workaround for the PEM-cache\n bottleneck before ssl-8.1.1. Defaults to false.\n\n- **`alert_timeout = integer() `** - Number of milliseconds between\n sending of a fatal alert and closing the connection. Waiting a little while\n improves the peers chances to properly receiving the alert so it may shutdown\n gracefully. Defaults to 5000 milliseconds.\n\n- **`internal_active_n = integer() `** - For TLS connections this\n value is used to handle the internal socket. As the implementation was changed\n from an active once to an active N behavior (N = 100), for performance\n reasons, this option exist for possible tweaking or restoring of the old\n behavior (internal_active_n = 1) in unforeseen scenarios. The option will not\n affect erlang distribution over TLS that will always run in active N mode.\n Added in ssl-9.1 (OTP-21.2).\n\n- **`server_session_tickets_amount = integer() `** - Number of session\n tickets sent by the server. It must be greater than 0. Defaults to 3.\n\n- **`server_session_ticket_lifetime = integer() `** - Lifetime of\n session tickets sent by the server. Servers must not use any value greater\n than 604800 seconds (7 days). Expired tickets are automatically removed.\n Defaults to 7200 seconds (2 hours).\n\n- **`server_session_ticket_store_size = integer() `** - Sets the\n maximum size of the server session ticket store (stateful tickets). Defaults\n to 1000. Size limit is enforced by dropping old tickets.\n\n- **`server_session_ticket_max_early_data = integer() `** - Sets the\n maximum size of the early data that the server accepts and also configures its\n NewSessionTicket messages to include this same size limit in their\n early_data_indication extension. Defaults to 16384. Size limit is enforced by\n both client and server.\n\n- **`client_session_ticket_lifetime = integer() `** - Lifetime of\n session tickets in the client ticket store. Expired tickets are automatically\n removed. Defaults to 7200 seconds (2 hours).\n\n- **`client_session_ticket_store_size = integer() `** - Sets the\n maximum size of the client session ticket store. Defaults to 1000. Size limit\n is enforced by dropping old tickets.","ref":"ssl_app.html#configuration"},{"type":"extras","title":"Error Logger and Event Handlers - SSL Application","doc":"The SSL application uses [OTP logger](`m:logger`). TLS/DTLS alerts are logged on\nnotice level. Unexpected errors are logged on error level. These log entries\nwill by default end up in the default Erlang log. The option `log_level` may be\nused to in run-time to set the log level of a specific TLS connection, which is\nhandy when you want to use level debug to inspect the TLS handshake setup.","ref":"ssl_app.html#error-logger-and-event-handlers"},{"type":"extras","title":"See Also - SSL Application","doc":"`m:application`","ref":"ssl_app.html#see-also"},{"type":"extras","title":"SSL Release Notes","doc":"\n# SSL Release Notes\n\nThis document describes the changes made to the SSL application.","ref":"notes.html"},{"type":"extras","title":"SSL 11.2.4 - SSL Release Notes","doc":"","ref":"notes.html#ssl-11-2-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Refactor trying to also make some optimizations introduced a bug in signature algorithms checks in OTP-26.2.1. This could manifest itself in not being able to negotiate connections using certificates needing to use some TLS-1.2 compatibility legacy signature schemes.\n\n Own Id: OTP-19249 Aux Id: ERIERL-1137, [PR-8866]\n\n- Correct timeout handling for termination code run for own alerts, so that intended timeout is used instead of falling back to OS TCP-stack timeout that is unreasonably long on some platforms.\n\n Own Id: OTP-19274 Aux Id: [PR-8901]\n\n- Fix assertion so that works as intended.\n This could result in that some TLS-1.2 clients would fail to connect to the the erlang server. Bug introduced in OTP-27.1.1\n\n Own Id: OTP-19288 Aux Id: [GH-8908], [PR-8916]\n\n[PR-8866]: https://github.com/erlang/otp/pull/8866\n[PR-8901]: https://github.com/erlang/otp/pull/8901\n[GH-8908]: https://github.com/erlang/otp/issues/8908\n[PR-8916]: https://github.com/erlang/otp/pull/8916","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 11.2.3 - SSL Release Notes","doc":"","ref":"notes.html#ssl-11-2-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Starting from TLS-1.3 some server handshake alerts might arrive after ssl:connection/2,3,4 has returned. If the socket is in active mode the controlling process will get the alert message, but passive sockets would only get {error, closed} on next call to ssl:recv/2,3 or ssl/setopts/2. Passive sockets calls will now return {error, error_alert()} instead.\n\n Own Id: OTP-19236 Aux Id: [PR-8261]\n\n- Servers configured to support only version (pre TLS-1.2) should ignore hello version extension, as it is an unknown extension to them, this will result in that new clients that do not support the old server version will get an insufficient security alert from the server and not a protocol version alert, this is consistent with how old servers not able to support higher protocol versions work.\n\n Own Id: OTP-19257\n\n[PR-8261]: https://github.com/erlang/otp/pull/8261","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 11.2.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-11-2-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- 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.\n\n Own Id: OTP-19175 Aux Id: [GH-8561], [PR-8690]\n\n[GH-8561]: https://github.com/erlang/otp/issues/8561\n[PR-8690]: https://github.com/erlang/otp/pull/8690","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- All TLS-1.3 terminations are now graceful (previous TLS version terminations already were).\n\n Own Id: OTP-17848\n\n- It is now possible to use a verification fun of arity 4, giving the user fun access to both encoded and decoded versions of the certificate. This is desirable as a workaround for encoding errors preventing re-encoding from being reliable. This also saves some work load if the encoded version is needed.\n \n Note that calling `public_key:pkix_path_validation/3` with only decoded certs is not recommended, due to the decoding workarounds, although it will work as long as the workarounds are not needed.\n \n If the decoded version is needed before thecall to `m:public_key` it is recommend to use the combined_cert- type to avoid double decoding. Note that the path validation algorithm itself always needs both the encoded and decoded versions of the certs.\n \n The ssl implementation will now benefit from using this function instead of emulating the verify_fun/4.\n\n Own Id: OTP-19169\n\n- Compiler warnings for some removed functions have been corrected to point out the correct replacement functions.\n\n Own Id: OTP-19186 Aux Id: [PR-8709]\n\n- Include more information in logging of SNI (Server Name Indication) mismatch error.\n\n Own Id: OTP-19187\n\n[PR-8709]: https://github.com/erlang/otp/pull/8709","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 11.2.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-11-2-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Check for TLS-1.3 support should check minimum requirements.\n\n Own Id: OTP-19094 Aux Id: [GH-8489]\n\n- If both TLS-1.3 and TLS-1.2 is supported\n and TLS-1.2 negotiated convert TLS-1.3 ECDSA schemes to TLS-1.2 hash and signature pairs for increased interoperability.\n\n Own Id: OTP-19107 Aux Id: [GH-8376]\n\n- TLS-1.3 negotiation now uses SNI based options correctly instead of ignoring them.\n\n Own Id: OTP-19140\n\n[GH-8489]: https://github.com/erlang/otp/issues/8489\n[GH-8376]: https://github.com/erlang/otp/issues/8376","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Make it easier to distinguish between a invalid signature and unsupported signature.\n\n Own Id: OTP-19091\n\n- Enhance ALERT logs to help understand what causes the alert.\n\n Own Id: OTP-19092 Aux Id: [GH-8482]\n\n- When the default value for signature_algs is used, default the signature_algs_cert to the default value + rsa_pkcs1_sha1 to allow this algorithms for certificates but not for the TLS protocol. This is for better interoperability. If signature_algs is set explicitly signature_algs_cert must also be set explicitly if they should be different.\n\n Own Id: OTP-19152 Aux Id: [GH-8588]\n\n[GH-8482]: https://github.com/erlang/otp/issues/8482\n[GH-8588]: https://github.com/erlang/otp/issues/8588","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 11.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-11-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Starting a TLS server without sufficient credentials (certificate or anonymous cipher) would work, but it was impossible to connect to it.\n \n This has been corrected to return an error instead of starting the server.\n\n Own Id: OTP-18887 Aux Id: [GH-7493], [PR-7918]\n\n- ASN.1 decoding errors are handled in more places to ensure that errors are returned instead of cause a crash.\n\n Own Id: OTP-18969 Aux Id: [GH-8058], [PR-8256]\n\n- Improved error checking on the API functions.\n\n Own Id: OTP-18992 Aux Id: [GH-8066], [PR-8156]\n\n[GH-7493]: https://github.com/erlang/otp/issues/7493\n[PR-7918]: https://github.com/erlang/otp/pull/7918\n[GH-8058]: https://github.com/erlang/otp/issues/8058\n[PR-8256]: https://github.com/erlang/otp/pull/8256\n[GH-8066]: https://github.com/erlang/otp/issues/8066\n[PR-8156]: https://github.com/erlang/otp/pull/8156","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- The `ssl` client can negotiate and handle certificate status request (OCSP stapling support on the client side).\n \n Thanks to voltone for interop testing and related discussions.\n\n Own Id: OTP-18606 Aux Id: OTP-16875,OTP-16448\n\n- Memory consumption has been reduced and performance increased by refactoring internal data structures and their usage.\n\n Own Id: OTP-18665 Aux Id: [PR-7447]\n\n- Added `c:ssl_crl_cache_api:lookup/2` as an optional `-callback` attribute.\n\n Own Id: OTP-18788 Aux Id: [PR-7700]\n\n- Key customization support has been extended to allow flexibility for implementers of for instance hardware security modules (HSM) or trusted platform modules (TPM).\n\n Own Id: OTP-18876 Aux Id: [PR-7898], [PR-7475]\n\n- The `proc_lib:set_label/1` function is now used to increase observability of `ssl` processes.\n\n Own Id: OTP-18879\n\n- Brainpool elliptic curves are now supported in TLS-1.3.\n\n Own Id: OTP-18884 Aux Id: [PR-8056]\n\n- The documentation has been migrated to use Markdown and ExDoc.\n\n Own Id: OTP-18955 Aux Id: [PR-8026]\n\n- For security reasons, the CBC ciphers are now longer included in the list of default ciphers for TLS-1.2.\n\n *** POTENTIAL INCOMPATIBILITY ***\n\n Own Id: OTP-19025 Aux Id: [PR-8250]\n\n- There is a new `cert_policy_opts` option to configure certificate policy options for the certificate path validation.\n\n Own Id: OTP-19027 Aux Id: [PR-8255]\n\n[PR-7447]: https://github.com/erlang/otp/pull/7447\n[PR-7700]: https://github.com/erlang/otp/pull/7700\n[PR-7898]: https://github.com/erlang/otp/pull/7898\n[PR-7475]: https://github.com/erlang/otp/pull/7475\n[PR-8056]: https://github.com/erlang/otp/pull/8056\n[PR-8026]: https://github.com/erlang/otp/pull/8026\n[PR-8250]: https://github.com/erlang/otp/pull/8250\n[PR-8255]: https://github.com/erlang/otp/pull/8255","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 11.1.4.5 - SSL Release Notes","doc":"","ref":"notes.html#ssl-11-1-4-5"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"* Avoid generating an internal alert for case that should have been an orderly shutdown by the supervisor.\n\n Own Id: OTP-19311 Aux Id: PR-8980","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"* Back port certificate_authorities option for TLS-1.3 servers to pre TLS-1.3 servers to enable them to disable the sending of certificate authorities in their certificate request. This will have same affect as the the TLS-1.3 server option although it is handled by a different mechanism in these versions, where the functionality is described to be more of a guidance, although some pre TLS clients have proven to make it mandatory as in TLS-1.3 extension handling.\n\n Own Id: OTP-19325 Aux Id: PR-9001, ERIERL-1147","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 11.1.4.4 - SSL Release Notes","doc":"","ref":"notes.html#ssl-11-1-4-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"* Starting from TLS-1.3 some server handshake alerts might arrive after ssl:connection/2,3,4 has returned. If the socket is in active mode the controlling process will get the alert message, but passive sockets would only get \\{error, closed\\} on next call to ssl:recv/2,3 or ssl/setopts/2. Passive sockets calls will now return \\{error, error_alert()\\} instead.\n\n Own Id: OTP-19236 Aux Id: PR-8261\n* Refactor trying to also make some optimizations introduced a bug in signature algorithms checks in OTP-26.2.1. This could manifest itself in not being able to negotiate connections using certificates needing to use some TLS-1.2 compatibility legacy signature schemes.\n\n Own Id: OTP-19249 Aux Id: ERIERL-1137, PR-8866\n* Servers configured to support only version (pre TLS-1.2) should ignore hello version extension, as it is an unknown extension to them, this will result in that new clients that do not support the old server version will get an insufficient security alert from the server and not a protocol version alert, this is consistent with how old servers not able to support higher protocol versions work.\n\n Own Id: OTP-19257 Aux Id: ERIERL-1131\n* Correct timeout handling for termination code run for own alerts, so that intended timeout is used instead of falling back to OS TCP-stack timeout that is unreasonably long on some platforms.\n\n Own Id: OTP-19274 Aux Id: PR-8901","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 11.1.4.3 - SSL Release Notes","doc":"","ref":"notes.html#ssl-11-1-4-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"* A race in the kTLS flavour of SSL distribution has been fixed so 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.\n\n Own Id: OTP-19175 Aux Id: GH-8561, PR-8690","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"* Make sure all TLS-1.3 terminations are graceful (previous TLS version terminations already are).\n\n Own Id: OTP-17848\n* Include more information in logging of SNI (Server Name Indication) mismatch error.\n\n Own Id: OTP-19187","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 11.1.4.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-11-1-4-2"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"* When the default value for signature_algs is used, default the signature_algs_cert to the default value + rsa_pkcs1_sha1 to allow this algorithms for certificates but not for the TLS protocol. This is for better interoperability. If signature_algs is set explicitly signature_algs_cert must also be set explicitly if they should be different.\n\n Own Id: OTP-19152 Aux Id: GH-8588","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 11.1.4.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-11-1-4-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"* Check for TLS-1.3 support should check minimum requirements.\n\n Own Id: OTP-19094 Aux Id: GH-8489\n* If both TLS-1.3 and TLS-1.2 is supported and TLS-1.2 negotiated convert TLS-1.3 ECDSA schemes to TLS-1.2 hash and signature pairs for increased interoperability.\n\n Own Id: OTP-19107 Aux Id: GH-8376\n* TLS-1.3 negotiation now uses SNI based options correctly instead of ignoring them.\n\n Own Id: OTP-19140","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"* Make it easier to distinguish between a invalid signature and unsupported signature.\n\n Own Id: OTP-19091\n* Enhance ALERT logs to help understand what causes the alert.\n\n Own Id: OTP-19092 Aux Id: GH-8482","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 11.1.4 - SSL Release Notes","doc":"","ref":"notes.html#ssl-11-1-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"* Fix certificate authorities check so that CA closest to peer is not lost. It could manifest itself in a failed connection as the client failed to realize it had a valid certificate chain to send to the server.\n\n Own Id: OTP-19065 Aux Id: GH-8356, PR-8367\n* ssl:signature_algs/2 did not list some legacy algorithm schemes correctly when listing all algorithms available.\n\n Own Id: OTP-19067 Aux Id: PR-8379","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 11.1.3 - SSL Release Notes","doc":"","ref":"notes.html#ssl-11-1-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"* Cleanup and close all connections in DTLS when the listen socket owner dies.\n\n Improved IPv6 handling in DTLS.\n\n Own Id: OTP-19037 Aux Id: GH-7951 GH-7955\n* Fixed a crash in dtls accept.\n\n Own Id: OTP-19059 Aux Id: GH-8338","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 11.1.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-11-1-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"* ssl:prf/5, will start working instead of hanging in a TLS-1.3 context if called appropriately. Note that the implementation has changed and in OTP-27 a more adequate API will be documented.\n\n Own Id: OTP-18890 Aux Id: GH-7911\n* Server name verification didn't work if a connection was made with IP-address as a string.\n\n Own Id: OTP-18909 Aux Id: GH-7968\n* The fallback after \"dh\" ssl option was undefined was to get \"dh\" from ssl options again. This is clearly wrong and now changed to the documented fallback \"dhfile\" ssl option.\n\n Own Id: OTP-18919 Aux Id: PR-7984\n* Correct default value selection for DTLS. Will only affect users linked with really old version of cryptolib library.\n\n Own Id: OTP-18962 Aux Id: GH-8079\n* Adhere elliptic curves with RFC 8422 pre TLS-1.3, that is Edwards curves are added to curves that can be used for key exchange, and documentation and implementation of eccs/0,1 are aligned.\n\n Own Id: OTP-18991","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"* Improve alert reason when ecdhe_rsa key_exchange does not have any common curves to use\n\n Own Id: OTP-18985","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 11.1.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-11-1-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"* Legacy name handling could cause interop problems between TLS-1.3/1.2 client and TLS-1.2 server.\n\n Own Id: OTP-18917 Aux Id: GH-7978","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 11.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-11-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- ssl application will validate id-kp-serverAuth and id-kp-clientAuth extended\n key usage only in end entity certificates. public_key application will\n disallow \"anyExtendedKeyUsage\" for CA certificates that includes the extended\n key usage extension and marks it critical.\n\n Own Id: OTP-18739\n\n- Replaced unintentional Erlang Public License 1.1 headers in some files with\n the intended Apache License 2.0 header.\n\n Own Id: OTP-18815 Aux Id: PR-7780\n\n- Correct handling of TLS-1.3 legacy scheme names, could cause interop failures\n for TLS-1.2 clients.\n\n Own Id: OTP-18817\n\n- Add missing export for connection_info() API type.\n\n Own Id: OTP-18886","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Fixed `server name indication` which was not handled properly.\n\n Own Id: OTP-18836 Aux Id: GH-7795\n\n- Align documentation and implementation\n\n Own Id: OTP-18853 Aux Id: PR-7841\n\n- Improve connection setup by optimizing certificate lookup.\n\n Own Id: OTP-18893 Aux Id: PR-7920 PR-7921","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 11.0.3 - SSL Release Notes","doc":"","ref":"notes.html#ssl-11-0-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Avoid function clause error in ssl:getopts/2 by handling that inet:getopts may\n return an empty list during some circumstances, such as the socket being in a\n closing state.\n\n Own Id: OTP-18697 Aux Id: GH-7506\n\n- The API function \\`ssl:recv/3\\` has been tightened to disallow negative\n length, which has never been documented to work, but was passed through and\n caused strange errors.\n\n Own Id: OTP-18700 Aux Id: GH-7507\n\n- When a client initiated renegotiation was rejected and the client socket was\n in active mode the expected error message to the controlling process was not\n sent.\n\n Own Id: OTP-18712 Aux Id: GH-7431","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Add some guidance for signature algorithms configuration in ssl applications\n users guide.\n\n Own Id: OTP-18631","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 11.0.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-11-0-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Added keylog information to all protocol versions in\n `ssl:connection_information/2`.\n\n Own Id: OTP-18643 Aux Id: ERIERL-932","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Add RFC-6083 considerations for DTLS to enable gen_sctp based callback for the\n transport.\n\n Own Id: OTP-18618 Aux Id: ERIERL-932","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 11.0.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-11-0-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Make sure that selection of client certificates handle both TLS-1.3 and\n TLS-1.2 names correctly. Could cause valid client certificate to not be\n selected, and an empty client certificate message to be sent to server.\n\n Own Id: OTP-18588 Aux Id: GH-7264, PR-7277\n\n- Improved `ssl:format_error/1` to handle more error tuples.\n\n Own Id: OTP-18596 Aux Id: GH-7247\n\n- Fixed hanging `ssl:connect` when ssl application is not started.\n\n Own Id: OTP-18603 Aux Id: GH-7297\n\n- Correct handling of retransmission timers, current behavior could cause\n unwanted delays.\n\n Own Id: OTP-18632 Aux Id: PR-7300, GH-7301","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 11.0 - SSL Release Notes","doc":"","ref":"notes.html#ssl-11-0"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Remove less that 256 bit ECC from default supported ECC pre TLS-1.3\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-14771\n\n- Improved error checking and handling of ssl options.\n\n Own Id: OTP-15903\n\n- With this change, stateless tickets generated by server with anti_replay\n option enabled can be used for creating ClientHello throughout ticket\n lifetime. Without this change, usability was limited to WindowSize number of\n seconds configured for anti_replay option.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18168 Aux Id: PR-6019, GH-6014\n\n- Support for Kernel TLS (kTLS), has been added to the SSL application, for TLS\n distribution (`-proto_dist inet_tls`), the SSL option `{ktls, true}`. Using\n this for general SSL sockets is uncomfortable, undocumented and not\n recommended since it requires very platform dependent raw options.\n\n This, for now, only works for some not too old Linux distributions. Roughly, a\n kernel 5.2.0 or later with support for UserLand Protocols and the kernel\n module `tls` is required.\n\n Own Id: OTP-18235 Aux Id: PR-6104, PR-5840\n\n- With this change, TLS 1.3 server can be configured to include client\n certificate in session ticket.\n\n Own Id: OTP-18253\n\n- With this change, it is possible to configure encryption seed to be used with\n TLS1.3 stateless tickets. This enables using tickets on different server\n instances.\n\n Own Id: OTP-18254 Aux Id: PR-5982\n\n- Debugging enhancements.\n\n Own Id: OTP-18312\n\n- With this change, maybe keyword atom is not used as function name in ssl code.\n\n Own Id: OTP-18335\n\n- Replace size/1 with either tuple_size/1 or byte_size/1\n\n The [`size/1`](`size/1`) BIF is not optimized by the JIT, and its use can\n result in worse types for Dialyzer.\n\n When one knows that the value being tested must be a tuple,\n [`tuple_size/1`](`tuple_size/1`) should always be preferred.\n\n When one knows that the value being tested must be a binary,\n [`byte_size/1`](`byte_size/1`) should be preferred. However,\n [`byte_size/1`](`byte_size/1`) also accepts a bitstring (rounding up size to a\n whole number of bytes), so one must make sure that the call to `byte_size/` is\n preceded by a call to [`is_binary/1`](`is_binary/1`) to ensure that bitstrings\n are rejected. Note that the compiler removes redundant calls to\n [`is_binary/1`](`is_binary/1`), so if one is not sure whether previous code\n had made sure that the argument is a binary, it does not harm to add an\n [`is_binary/1`](`is_binary/1`) test immediately before the call to\n [`byte_size/1`](`byte_size/1`).\n\n Own Id: OTP-18405 Aux Id:\n GH-6672,PR-6702,PR-6768,PR-6700,PR-6769,PR-6812,PR-6814\n\n- For security reasons remove support for SHA1 and DSA algorithms from default\n values.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18438 Aux Id: GH-6679\n\n- Mitigate memory usage from large certificate chains by lowering the maximum\n handshake size. This should not effect the common cases, if needed it can be\n configured to a higher value.\n\n Own Id: OTP-18453\n\n- Change the client default verify option to verify_peer. Note that this makes\n it mandatory to also supply trusted CA certificates or explicitly set verify\n to verify_none. This also applies when using the so called anonymous test\n cipher suites defined in TLS versions pre TLS-1.3.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18455 Aux Id: GH-5899\n\n- Erlang distribution code in Kernel and SSL has been refactored a bit to\n facilitate debugging and re-usability, which shouldn't have any noticeable\n effects on behaviour or performance.\n\n Own Id: OTP-18456\n\n- Add encoding and decoding of use_srtp hello extension to facilitate for DTLS\n users to implement SRTP functionality.\n\n Own Id: OTP-18459\n\n- Refactors the (`ssl` application to use macros for TLS and DTLS versions\n instead of hard-coded tuple numbers. This change improves the maintainability\n of `ssl`\n\n Own Id: OTP-18465 Aux Id: GH-7065\n\n- If the function ssl:renegotiate/1 is called on connection that is running\n TLS-1.3 return an error instead of hanging or timing out.\n\n Own Id: OTP-18507\n\n- If a user cancel alert with level warning is received during handshake make it\n be handled the same regardless of TLS version. If it is received in connection\n in TLS-1.3 regard it as an error as it is inappropriate.\n\n In TLS-1.3 all error alerts are considered FATAL regardless of legacy alert\n type. But make sure legacy type is printed in logs to not confuse users that\n are expecting the same legacy type as sent by peer.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18531\n\n- Make `fail_if_no_peer_cert` default true if verify_peer is set on the server,\n otherwise the server will accept the connection if verify_peer is set and the\n user have forgot to set the fail_if_no_peer_cert and the client did not send a\n certificate.\n\n Own Id: OTP-18567\n\n- To make it easier to configure signature algorithms with algorithms that are\n moved from the default add the API function signature_algs/2 that lists\n possible values. Also make sha224 a non default value.\n\n Own Id: OTP-18572","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 10.9.1.6 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-9-1-6"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"* Starting from TLS-1.3 some server handshake alerts might arrive after ssl:connection/2,3,4 has returned. If the socket is in active mode the controlling process will get the alert message, but passive sockets would only get \\{error, closed\\} on next call to ssl:recv/2,3 or ssl/setopts/2. Passive sockets calls will now return \\{error, error_alert()\\} instead.\n\n Own Id: OTP-19236 Aux Id: PR-8261\n* Servers configured to support only version (pre TLS-1.2) should ignore hello version extension, as it is an unknown extension to them, this will result in that new clients that do not support the old server version will get an insufficient security alert from the server and not a protocol version alert, this is consistent with how old servers not able to support higher protocol versions work.\n\n Own Id: OTP-19257 Aux Id: ERIERL-1131\n* Correct timeout handling for termination code run for own alerts, so that intended timeout is used instead of falling back to OS TCP-stack timeout that is unreasonably long on some platforms.\n\n Own Id: OTP-19274 Aux Id: PR-8901","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.9.1.5 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-9-1-5"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"* TLS-1.3 negotiation now uses SNI based options correctly instead of ignoring them.\n\n Own Id: OTP-19140","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.9.1.4 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-9-1-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"* Fix certificate authorities check so that CA closest to peer is not lost. It could manifest itself in a failed connection as the client failed to realize it had a valid certificate chain to send to the server.\n\n Own Id: OTP-19065 Aux Id: GH-8356, PR-8367","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.9.1.3 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-9-1-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- ssl application will validate id-kp-serverAuth and id-kp-clientAuth extended\n key usage only in end entity certificates. public_key application will\n disallow \"anyExtendedKeyUsage\" for CA certificates that includes the extended\n key usage extension and marks it critical.\n\n Own Id: OTP-18739\n\n- Add missing export for connection_info() API type.\n\n Own Id: OTP-18886","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.9.1.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-9-1-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- The API function \\`ssl:recv/3\\` has been tightened to disallow negative\n length, which has never been documented to work, but was passed through and\n caused strange errors.\n\n Own Id: OTP-18700 Aux Id: GH-7507\n\n- When a client initiated renegotiation was rejected and the client socket was\n in active mode the expected error message to the controlling process was not\n sent.\n\n Own Id: OTP-18712 Aux Id: GH-7431","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.9.1.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-9-1-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Added keylog information to all protocol versions in\n `ssl:connection_information/2`.\n\n Own Id: OTP-18643 Aux Id: ERIERL-932","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Add RFC-6083 considerations for DTLS to enable gen_sctp based callback for the\n transport.\n\n Own Id: OTP-18618 Aux Id: ERIERL-932","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 10.9.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-9-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- With this change, ssl:connection_information/2 returns correct keylog data\n after TLS1.3 key update.\n\n Own Id: OTP-18489\n\n- Client signature algorithm list input order is now honored again , it was\n accidently reversed by a previous fix.\n\n Own Id: OTP-18550","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.9 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-9"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Fixed that new `dtls` connections from the same client ip port combination\n works. If there is a process waiting for accept the new connection will\n connect to that, otherwise it will try to re-connect to the old server\n connection.\n\n Own Id: OTP-18371 Aux Id: GH-6160\n\n- When shutting down a node that uses SSL distribution (`-proto_dist inet_tls`),\n a confusing error message about an unexpected process exit was printed. This\n particular message is no longer generated.\n\n Own Id: OTP-18443 Aux Id: PR-6810","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- fixes the type spec for ssl:format_error/1\n\n Own Id: OTP-18366 Aux Id: PR-6565, GH-6506\n\n- Replace size/1 with either tuple_size/1 or byte_size/1\n\n The [`size/1`](`size/1`) BIF is not optimized by the JIT, and its use can\n result in worse types for Dialyzer.\n\n When one knows that the value being tested must be a tuple,\n [`tuple_size/1`](`tuple_size/1`) should always be preferred.\n\n When one knows that the value being tested must be a binary,\n [`byte_size/1`](`byte_size/1`) should be preferred. However,\n [`byte_size/1`](`byte_size/1`) also accepts a bitstring (rounding up size to a\n whole number of bytes), so one must make sure that the call to `byte_size/` is\n preceded by a call to [`is_binary/1`](`is_binary/1`) to ensure that bitstrings\n are rejected. Note that the compiler removes redundant calls to\n [`is_binary/1`](`is_binary/1`), so if one is not sure whether previous code\n had made sure that the argument is a binary, it does not harm to add an\n [`is_binary/1`](`is_binary/1`) test immediately before the call to\n [`byte_size/1`](`byte_size/1`).\n\n Own Id: OTP-18432 Aux Id:\n GH-6672,PR-6793,PR-6784,PR-6787,PR-6785,PR-6682,PR-6800,PR-6797,PR-6798,PR-6799,PR-6796,PR-6813,PR-6671,PR-6673,PR-6684,PR-6694,GH-6677,PR-6696,PR-6670,PR-6674","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 10.8.7 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-8-7"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Maximize compatibility by ignoring change_cipher_spec during handshake even if\n middle_box_mode is not negotiated (mandated by client)\n\n Own Id: OTP-18433 Aux Id: GH-6772\n\n- Move assert of middlebox message after an hello_retry_request to maximize\n interoperability. Does not changes semantics of the protocol only allows\n unexpected message delay from server.\n\n Own Id: OTP-18467 Aux Id: GH-6807","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 10.8.6 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-8-6"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- With this change, tls_sender process is hibernated after sufficient\n inactivity.\n\n Own Id: OTP-18314 Aux Id: GH-6373\n\n- Correct handling of legacy schemes so that ECDSA certs using sha1 may be used\n for some TLS-1.3 configurations.\n\n Own Id: OTP-18332 Aux Id: GH-6435, PR-6435, ERL-6435\n\n- With this change, tls_sender does not cause logger crash upon key update.\n\n Own Id: OTP-18349","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Enhance warning message\n\n Own Id: OTP-18257 Aux Id: GH-6307\n\n- Provide server option to make certificate_authorities extension in the TLS-1.3\n servers certificate request optional. This will allow clients to send\n incomplete chains that may be reconstructable and thereby verifiable by the\n server, but that would not adhere to the certificate_authorities extension.\n\n Own Id: OTP-18267 Aux Id: PR-6228, GH-6106\n\n- If the `verify_fun` handles four arguments the DER cert will be supplied as\n one of the arguments.\n\n Own Id: OTP-18302 Aux Id: ERIERL-867","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 10.8.5 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-8-5"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Fixes handling of symlinks in cacertfile option.\n\n Own Id: OTP-18266 Aux Id: GH-6328","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.8.4 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-8-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Reject unexpected application data in all relevant places for all TLS\n versions. Also, handle TLS-1.3 middlebox compatibility with more care. This\n will make malicious connections fail early and further, mitigate possible DoS\n attacks, that would be caught by the handshake timeout.\n\n Thanks to Aina Toky Rasoamanana and Olivier Levillain from Télécom SudParis\n for alerting us of the issues in our implementation.\n\n Own Id: OTP-18044\n\n- With this change, value of cacertfile option will be adjusted before loading\n certs from the file. Adjustments include converting relative paths to absolute\n and converting symlinks to actual file path.\n\n Thanks to Marcus Johansson\n\n Own Id: OTP-18099 Aux Id: PR-6287\n\n- In TLS-1.3, if chain certs are missing (so server auth domain adherence can\n not be determined) send peer cert and hope the server is able to recreate a\n chain in its auth domain.\n\n Own Id: OTP-18191 Aux Id: GH-6105\n\n- Make sure periodical refresh of CA certificate files repopulates cache\n properly.\n\n Own Id: OTP-18195\n\n- Correct internal CRL cache functions to use internal format consistently.\n\n Own Id: OTP-18203 Aux Id: PR-5996\n\n- Incorrect handling of client middlebox negotiation for TLS-1.3 could result in\n that a TLS-1.3 server would not use middlebox mode although the client was\n expecting it too and failing the negotiation with unexpected message.\n\n Own Id: OTP-18219 Aux Id: GH-6241, PR-6249\n\n- If the \"User\" process, the process starting the TLS connection, gets killed in\n the middle of spawning the dynamic connection tree make sure we do not leave\n any processes behind.\n\n Own Id: OTP-18233 Aux Id: GH-6244, PR-6270","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- A vulnerability has been discovered and corrected. It is registered as\n CVE-2022-37026 \"Client Authentication Bypass\". Corrections have been released\n on the supported tracks with patches 23.3.4.15, 24.3.4.2, and 25.0.2. The\n vulnerability might also exist in older OTP versions. We recommend that\n impacted users upgrade to one of these versions or later on the respective\n tracks. OTP 25.1 would be an even better choice. Impacted are those who are\n running an ssl/tls/dtls server using the ssl application either directly or\n indirectly via other applications. For example via inets (httpd), cowboy, etc.\n Note that the vulnerability only affects servers that request client\n certification, that is sets the option \\{verify, verify_peer\\}.\n\n Own Id: OTP-18241","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 10.8.3 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-8-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- The link to crypto:engine_load refered the function with wrong arity.\n\n Own Id: OTP-18173","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.8.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-8-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Improved handling of unexpected messages during the handshake, taking the\n right action for unexpected messages.\n\n Own Id: OTP-18145","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.8.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-8-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- When a TLS-1.3 enabled client tried to talk to a TLS-1.2 server that coalesces\n TLS-1.2 handshake message over one TLS record, the connection could fail due\n to some message being handled in the wrong state, this has been fixed.\n\n Own Id: OTP-18087 Aux Id: GH-5961\n\n- Correctly handles supported protocol version change from default to something\n else by sni_fun supplied to ssl:handshake/\\[2,3] together with a TCP-socket\n (so called upgrade).\n\n Own Id: OTP-18100 Aux Id: GH-5985\n\n- Also, TLS-1.3 should respond with a protocol version alert if previous\n versions, that are supported but not configured, are attempted.\n\n Own Id: OTP-18129 Aux Id: GH-5950","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.8 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-8"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- When a TLS-1.3 enabled client tried to talk to a TLS-1.2 server that coalesces\n TLS-1.2 handshake message over one TLS record, the connection could fail due\n to some message being handled in the wrong state, this has been fixed.\n\n Own Id: OTP-18087 Aux Id: GH-5961\n\n- Fixed tls-1.3 session ticket lifetime which was discarded to quickly before.\n\n Own Id: OTP-18092 Aux Id: PR-5959","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- With this change, it is possible to provide several certificates. Most\n appropriate will be selected based on negotiated properties.\n\n Own Id: OTP-15993 Aux Id: GH-4143\n\n- Add options for users to be able to set spawn_opts for TLS processes (sender\n and receiver) this may be useful for tuning trade-offs between CPU and Memory\n usage.\n\n Own Id: OTP-17855 Aux Id: PR-5328\n\n- Allow key file passwords to be input as a single binary, that is we change the\n data type to be the more for the purpose logical data type iodata() instead of\n string().\n\n Own Id: OTP-17890\n\n- Logging enhancement, add location information to the warning log message.\n\n Own Id: OTP-18000 Aux Id: PR-5790\n\n- Now also accepts the signature_algs_cert option in TLS-1.2 configuration.\n\n Own Id: OTP-18014\n\n- Handle certificate selection correctly for server fallback and certificate\n authorities considerations.\n\n Own Id: OTP-18045 Aux Id: ERIERL-792, OTP-15993\n\n- Enhance handling of handshake decoding errors, especially for certificate\n authorities extension to ensure graceful termination.\n\n Own Id: OTP-18085","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 10.7.3.9 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-7-3-9"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- When a client initiated renegotiation was rejected and the client socket was\n in active mode the expected error message to the controlling process was not\n sent.\n\n Own Id: OTP-18712 Aux Id: GH-7431","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.7.3.8 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-7-3-8"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Added keylog information to all protocol versions in\n `ssl:connection_information/2`.\n\n Own Id: OTP-18643 Aux Id: ERIERL-932","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Add RFC-6083 considerations for DTLS to enable gen_sctp based callback for the\n transport.\n\n Own Id: OTP-18618 Aux Id: ERIERL-932","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 10.7.3.7 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-7-3-7"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Client signature algorithm list input order is now honored again , it was\n accidently reversed by a previous fix.\n\n Own Id: OTP-18550","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.7.3.6 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-7-3-6"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Maximize compatibility by ignoring change_cipher_spec during handshake even if\n middle_box_mode is not negotiated (mandated by client)\n\n Own Id: OTP-18433 Aux Id: GH-6772\n\n- Move assert of middlebox message after an hello_retry_request to maximize\n interoperability. Does not changes semantics of the protocol only allows\n unexpected message delay from server.\n\n Own Id: OTP-18467 Aux Id: GH-6807","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 10.7.3.5 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-7-3-5"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Fixes handling of symlinks in cacertfile option.\n\n Own Id: OTP-18266 Aux Id: GH-6328","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.7.3.4 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-7-3-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- With this change, value of cacertfile option will be adjusted before loading\n certs from the file. Adjustments include converting relative paths to absolute\n and converting symlinks to actual file path.\n\n Thanks to Marcus Johansson\n\n Own Id: OTP-18099 Aux Id: PR-6287\n\n- Incorrect handling of client middlebox negotiation for TLS-1.3 could result in\n that a TLS-1.3 server would not use middlebox mode although the client was\n expecting it too and failing the negotiation with unexpected message.\n\n Own Id: OTP-18219 Aux Id: GH-6241, PR-6249\n\n- If the \"User\" process, the process starting the TLS connection, gets killed in\n the middle of spawning the dynamic connection tree make sure we do not leave\n any processes behind.\n\n Own Id: OTP-18233 Aux Id: GH-6244, PR-6270","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.7.3.3 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-7-3-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Reject unexpected application data in all relevant places for all TLS\n versions. Also, handle TLS-1.3 middlebox compatibility with more care. This\n will make malicious connections fail early and further, mitigate possible DoS\n attacks, that would be caught by the handshake timeout.\n\n Thanks to Aina Toky Rasoamanana and Olivier Levillain from Télécom SudParis\n for alerting us of the issues in our implementation.\n\n Own Id: OTP-18044\n\n- The link to crypto:engine_load refered the function with wrong arity.\n\n Own Id: OTP-18173\n\n- Make sure periodical refresh of CA certificate files repopulates cache\n properly.\n\n Own Id: OTP-18195","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.7.3.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-7-3-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Improved handling of unexpected messages during the handshake, taking the\n right action for unexpected messages.\n\n Own Id: OTP-18145","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.7.3.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-7-3-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- When a TLS-1.3 enabled client tried to talk to a TLS-1.2 server that coalesces\n TLS-1.2 handshake message over one TLS record, the connection could fail due\n to some message being handled in the wrong state, this has been fixed.\n\n Own Id: OTP-18087 Aux Id: GH-5961\n\n- Fixed tls-1.3 session ticket lifetime which was discarded to quickly before.\n\n Own Id: OTP-18092 Aux Id: PR-5959\n\n- Correctly handles supported protocol version change from default to something\n else by sni_fun supplied to ssl:handshake/\\[2,3] together with a TCP-socket\n (so called upgrade).\n\n Own Id: OTP-18100 Aux Id: GH-5985\n\n- Also, TLS-1.3 should respond with a protocol version alert if previous\n versions, that are supported but not configured, are attempted.\n\n Own Id: OTP-18129 Aux Id: GH-5950","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Enhance handling of handshake decoding errors, especially for certificate\n authorities extension to ensure graceful termination.\n\n Own Id: OTP-18085","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 10.7.3 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-7-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Client certification could fail if TLS-1.3 enabled client negotiated TLS-1.2\n connection with the server, this is due to the wrong version being used when\n decoding the certificate request message from the server.\n\n Own Id: OTP-18028 Aux Id: GH-5835\n\n- socket option packet_size was not handled in ssl:setops/2 and ssl:getotps/2\n\n Own Id: OTP-18062 Aux Id: GH-5898\n\n- Remove legacy code to fix interoperability with new socket inet_backend.\n\n Own Id: OTP-18071 Aux Id: GH-5930","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.7.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-7-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- With this change, potential hanging of pre TLS1.3 client receiving OSCP staple\n message is avoided.\n\n Own Id: OTP-17994","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.7.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-7-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Client certification could fail for TLS-1.3 servers that did not include the\n certificate_authorities extension in its certificate request message.\n\n Own Id: OTP-17971 Aux Id: GH-5783","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.7 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-7"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Improved error handling.\n\n Own Id: OTP-17759 Aux Id: GH-5367\n\n- Before this change, net_kernel used with TLS distribution might be leaking\n processes in case of connectivity issues.\n\n Own Id: OTP-17815 Aux Id: GH-5332\n\n- Fix makefile dependency bugs.\n\n Own Id: OTP-17847 Aux Id: PR-5574 GH-5548\n\n- Make sure the TLS sender process handles explicit calls to\n erlang:disconnect_node properly, avoiding potential hanging problems in\n net_kernel.\n\n Own Id: OTP-17929 Aux Id: GH-5708","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Add support for TLS-1.3 certificate_authorities extension. And process\n certificate_authorities field in pre-TLS-1.3 certificate requests.\n\n Own Id: OTP-15719\n\n- Support password fun for protected keyfiles in ssl:connect function.\n\n Own Id: OTP-17816 Aux Id: PR-5607\n\n- Add in some cases earlier detection of possible DoS attacks by malicious\n clients sending unexpected TLS messages instead of the client hello. Note that\n such attacks are already mitigated by providing a timeout for the TLS\n handshake.\n\n Own Id: OTP-17903","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 10.6.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-6-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Improve SNI (server name indication) handling so that protocol version can be\n selected with regards to SNI. Also, make sure that\n ssl:connection_information/1 returns the correct SNI value.\n\n Own Id: OTP-17794 Aux Id: GH-5341, GH-4450\n\n- Fixed cipher suite listing functions so that the listing of all cipher suites\n will be complete. Another fix for cipher suite handling in OTP-24.1\n accidentally excludes a few cipher suites from the listing of all cipher\n suites.\n\n Own Id: OTP-17829 Aux Id: ERIERL-708\n\n- Reenable legacy cipher suite TLS_RSA_WITH_3DES_EDE_CBC_SHA for explicit\n configuration in TLS-1.2, not supported by default.\n\n Own Id: OTP-17879 Aux Id: GH-5624","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Avoid unnecessary logs by better adjusting the tls_sender process to the new\n supervisor structure in OTP-24.2\n\n Own Id: OTP-17831","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 10.6 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-6"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Allow re-connect on DTLS sockets\n\n Can happen when a computer reboots and connects from the same client port\n without the server noticing should be allowed according to RFC.\n\n Own Id: OTP-17411 Aux Id: ERL-1203, GH-4393\n\n- Fix tls and non-tls distribution to use erl_epmd:address_please to figure out\n if IPv4 or IPv6 addresses should be used when connecting to the remote node.\n\n Before this fix, a dns lookup of the remote node hostname determined which IP\n version was to be used which meant that the hostname had to resolve to a valid\n ip address.\n\n Own Id: OTP-17809 Aux Id: PR-5337 GH-5334","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Use supervisor significant child to manage tls connection process and tls\n sender process dependency.\n\n Own Id: OTP-17417\n\n- Random generation adjustment for TLS1.3\n\n Own Id: OTP-17699\n\n- Allow any \\{03,XX\\} TLS record version in the client hello for maximum\n interoperability\n\n Own Id: OTP-17761 Aux Id: GH-5380","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 10.5.3 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-5-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Correct typo of ECC curve name in signature algorithm handling. Will make the\n signature algorithm ecdsa_secp521r1_sha512 succeed.\n\n Own Id: OTP-17756 Aux Id: GH-5383, PR-5397\n\n- Suppress authenticity warning when option verify_none is explicitly supplied.\n\n Own Id: OTP-17757 Aux Id: GH-5352, PR-5395","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.5.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-5-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Fix TLS-1.2 RSA-PSS negotiation and also fix broken certificate request\n message for pre-TLS-1.3 servers.\n\n Own Id: OTP-17688 Aux Id: GH-5255\n\n- Fix CRL issuer verification that under some circumstances could fail with a\n function_clause error.\n\n Own Id: OTP-17723 Aux Id: GH-5300","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.5.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-5-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Before that change, TLS downgrade could occasionally fail when data intended\n for downgraded socket were delivered together with CLOSE_NOTIFY alert to ssl\n app.\n\n Own Id: OTP-17393\n\n- Avoid re-encoding of decoded certificates. This could cause unexpected\n failures as some subtle encoding errors can be tolerated when decoding but\n hence creating another sequence of bytes if the decoded value is re-encoded.\n\n Own Id: OTP-17657\n\n- Fix possible process leak when the process doing ssl:transport_accept dies\n before initiating the TLS handshake.\n\n Own Id: OTP-17666 Aux Id: GH-5239\n\n- Fix dtls memory leak, the replay window code was broken.\n\n Own Id: OTP-17670 Aux Id: GH-5224","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.5 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-5"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Fix Makefile dependency generation to work no matter what the `ERL_TOP` folder\n is called.\n\n Own Id: OTP-17423 Aux Id: GH-4823 PR-4829\n\n- If trying to downgrade a TLS-1.3 connection to a plain TCP connection,\n possible TLS-1.3 session ticket messages will be ignored in the \"downgrade\"\n state while waiting for the close notify alert.\n\n Own Id: OTP-17517 Aux Id: GH-5009\n\n- Corrected error handling to correctly generate an insufficient security alert\n when there are no suitable groups that can be negotiated in TLS-1.3 instead of\n crashing resulting in an internal error alert.\n\n Own Id: OTP-17521\n\n- Properly handle default session data storage.\n\n When a client tries to reuse an expired session the default server storage\n handling would crash losing other session data. This would cause a error\n report and possible loss of abbreviated handshakes.\n\n Own Id: OTP-17635 Aux Id: GH-5192","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Add support for RSA-PSS-PSS signatures and signature_algorithms_cert in\n TLS-1.2. This is a TLS-1.3 RFC requirement to backport this functionality.\n\n Own Id: OTP-16590 Aux Id: ERL-625, GH-5029\n\n- Use inet:monitor/1 to monitor listen-sockets so that we are compatible with\n the new socket backend for gen_tcp.\n\n Own Id: OTP-17392 Aux Id: PR-5050\n\n- Enhance ssl:prf/4 handling and testing\n\n Own Id: OTP-17464\n\n- Enhanced cipher suite filtering functionality, making sure TLS-1.3 and TLS-1.2\n cipher suites can be supported correctly together even when TLS-1.2 anonymous\n ciphers are included.\n\n Own Id: OTP-17501 Aux Id: GH-4978\n\n- Enhance gracefulness especially in TLS-1.3\n\n Own Id: OTP-17530","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 10.4.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-4-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Handle cross-signed root certificates when old root expired as reported in\n GH-4877.\n\n Own Id: OTP-17475 Aux Id: GH-4877\n\n- The signature selection algorithm has been changed to also verify if the\n client supports signatures using the elliptic curve of the server's\n public/private key pair. This change fixes #4958.\n\n Own Id: OTP-17529 Aux Id: PR-4979, GH-4958","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Slight optimization of certificate decoding.\n\n Own Id: OTP-17150 Aux Id: GH-4877","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 10.4.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-4-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Fix cache invalidation problem for CA certs provided by the cacertfile option.\n\n Own Id: OTP-17435 Aux Id: ERIERL-653","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.4 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Missing runtime dependencies has been added to this application.\n\n Own Id: OTP-17243 Aux Id: PR-4557\n\n- TLS handshake should fail if OCSP staple is requested but missing. Note that\n OCSP support is still considered experimental and only partially implemented.\n\n Own Id: OTP-17343","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Removed ssl:ssl_accept/1,2,3 and ssl:cipher:suites/0,1 use ssl:handshake/1,2,3\n and ssl:cipher_suites/2,3 instead.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-16974\n\n- Make TLS handshakes in Erlang distribution concurrent.\n\n Own Id: OTP-17044 Aux Id: PR-2654\n\n- Randomize internal `{active,n}` optimization when running Erlang distribution\n over TLS to spread RAM/CPU spike that may occur when starting up a big\n cluster.\n\n Own Id: OTP-17117 Aux Id: PR-2933\n\n- TLS connections now support EdDSA certificates.\n\n Own Id: OTP-17142 Aux Id: PR-4756, GH-4637, GH-4650\n\n- Enhance documentation and logging of certificate handling.\n\n Own Id: OTP-17384 Aux Id: GH-4800","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 10.3.1.5 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-3-1-5"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Correct corner case of unexpected message handling for pre TLS-1.3 versions,\n could cause \"late failure\" and make the server dependent on its handshake\n timeout to prevent possible DoS attacks.\n\n Own Id: OTP-18224","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.3.1.4 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-3-1-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- The link to crypto:engine_load refered the function with wrong arity.\n\n Own Id: OTP-18173","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.3.1.3 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-3-1-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Improved handling of unexpected messages during the handshake, taking the\n right action for unexpected messages.\n\n Own Id: OTP-18145","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.3.1.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-3-1-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Handle cross-signed root certificates when old root expired as reported in\n GH-4877.\n\n Own Id: OTP-17475 Aux Id: GH-4877\n\n- The signature selection algorithm has been changed to also verify if the\n client supports signatures using the elliptic curve of the server's\n public/private key pair. This change fixes #4958.\n\n Own Id: OTP-17529 Aux Id: PR-4979, GH-4958","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Slight optimization of certificate decoding.\n\n Own Id: OTP-17150 Aux Id: GH-4877","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 10.3.1.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-3-1-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Fix cache invalidation problem for CA certs provided by the cacertfile option.\n\n Own Id: OTP-17435 Aux Id: ERIERL-653","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.3.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-3-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Retain backwards compatible behavior of verify_fun when handling incomplete\n chains that are not verifiable.\n\n Own Id: OTP-17296 Aux Id: GH-4682\n\n- Avoid server session handler crash, this will increase session ruse\n opportunities.\n\n Own Id: OTP-17348 Aux Id: ERIERL-641","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.3 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Fix CRL handling that previously could fail to find the issuer cert under some\n circumstances.\n\n Own Id: OTP-17261 Aux Id: GH-4589\n\n- TLS-1.3 client could, under some circumstances, select an incorrect algorithm\n to sign the certificate verification message causing a TLS Decrypt Alert being\n issued by the server.\n\n Own Id: OTP-17281 Aux Id: GH-4620\n\n- Correct handling of default values for emulated socket options and retain the\n order of the ssl options list to ensure backwards compatible behavior if\n options should be set more than once.\n\n Own Id: OTP-17282","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Enhance pre TLS-1.3 session handling so the client and server side handling is\n completely separated and client disregards oldest session when reaching max\n limit of the session table.\n\n Own Id: OTP-16876\n\n- This change implements the early data feature for TLS 1.3 clients.\n\n TLS 1.3 allows clients to send data in the first flight using a Pre-Shared Key\n to authenticate the server and to encrypt the early data.\n\n Own Id: OTP-16985\n\n- This change implements the early data feature for TLS 1.3 servers.\n\n Own Id: OTP-17042","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 10.2.4.4 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-2-4-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Improved handling of unexpected messages during the handshake, taking the\n right action for unexpected messages.\n\n Own Id: OTP-18145","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.2.4.3 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-2-4-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Fix cache invalidation problem for CA certs provided by the cacertfile option.\n\n Own Id: OTP-17435 Aux Id: ERIERL-653","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.2.4.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-2-4-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Fix handling of emulated socket options, the previous patch was incomplete,\n\n Own Id: OTP-17305","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.2.4.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-2-4-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Backport of OTP-17282\n\n Correct handling of default values for emulated socket options and retain the\n order of the ssl options list to ensure backwards compatible behavior if\n options should be set more than once.\n\n Own Id: OTP-17289 Aux Id: GH-4585","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.2.4 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-2-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Enhance logging option log_level to support none and all, also restore\n backwards compatibility for log_alert option.\n\n Own Id: OTP-17228 Aux Id: ERIERL-614","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.2.3 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-2-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Avoid race when the first two upgrade server handshakes (that is servers that\n use a gen_tcp socket as input to ssl:handshake/2,3) start close to each other.\n Could lead to that one of the handshakes would fail.\n\n Own Id: OTP-17190 Aux Id: ERIERL-606","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 10.2.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-2-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Avoid that upgrade (from TCP to TLS) servers starts multiple session cache\n handlers for the same server. This applies to Erlang distribution over TLS\n servers.\n\n Own Id: OTP-17139 Aux Id: ERL-1458, OTP-16239\n\n- Legacy cipher suites defined before TLS-1.2 (but still supported) should be\n possible to use in TLS-1.2. They where accidentally excluded for available\n cipher suites for TLS-1.2 in OTP-23.2.2.\n\n Own Id: OTP-17174 Aux Id: ERIERL-597","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Enable Erlang distribution over TLS to run TLS-1.3, although TLS-1.2 will\n still be default.\n\n Own Id: OTP-16239 Aux Id: ERL-1458, OTP-17139","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 10.2.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-2-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Fix CVE-2020-35733 this only affects ssl-10.2 (OTP-23.2). This vulnerability\n could enable a man in the middle attack using a fake chain to a known trusted\n ROOT. Also limits alternative chain handling, for handling of possibly\n extraneous certs, to improve memory management.\n\n Own Id: OTP-17098","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Add support for AES CCM based cipher suites defined in RFC 7251\n\n Also Correct cipher suite name conversion to OpenSSL names. A few names where\n corrected earlier in OTP-16267 For backwards compatible reasons we support\n usage of openSSL names for cipher suites. Mostly anonymous suites names where\n incorrect, but also some legacy suites.\n\n Own Id: OTP-17100","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 10.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- SSL's Erlang Distribution Protocol modules inet_tls_dist and inet6_tls_dist\n lacked a callback function, so the start flag \"-dist_listen false\" did not\n work, which has now been fixed.\n\n Own Id: OTP-15126 Aux Id: ERL-1375\n\n- Correct OpenSSL names for newer cipher suites using DHE in their name that\n accidentally got the wrong value when fixing other older names using EDH\n instead.\n\n Own Id: OTP-16267 Aux Id: ERIERL-571, ERIERL-477\n\n- This change improves the handling of DTLS listening dockets, making it\n possible to open multiple listeners on the same port with different IP\n addresses.\n\n Own Id: OTP-16849 Aux Id: ERL-1339\n\n- Fix a bug that causes cross-build failure.\n\n This change excludes the ssl.d dependency file from the source tarballs.\n\n Own Id: OTP-16921\n\n- This change fixes ssl:peername/1 when called on a DTLS client socket.\n\n Own Id: OTP-16923 Aux Id: ERL-1341, PR-2786\n\n- Retain emulation of active once on a closed socket to behave as before 23.1\n\n Own Id: OTP-17018 Aux Id: ERL-1409\n\n- Corrected server session cache entry deletion pre TLS-1.3. May increase\n session reuse.\n\n Own Id: OTP-17019 Aux Id: ERL-1412","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Handle extraneous certs in certificate chains as well as chains that are\n incomplete but can be reconstructed or unordered chains. The cert and certfile\n options will now accept a list of certificates so that the user may specify\n the chain explicitly.\n\n Also, the default value of the depth option has been increased to allow longer\n chains by default.\n\n Own Id: OTP-16277\n\n- This change implements optional NSS-style keylog in\n ssl:connection_information/2 for debugging purposes.\n\n The keylog contains various TLS secrets that can be loaded in Wireshark to\n decrypt TLS packets.\n\n Own Id: OTP-16445 Aux Id: PR-2823\n\n- Use new gen_statem feature of changing callback mode to improve code\n maintainability.\n\n Own Id: OTP-16529\n\n- The handling of Service Name Indication has been aligned with RFC8446.\n\n Own Id: OTP-16762\n\n- Add explicit session reuse option to TLS clients for pre TLS-1.3 sessions.\n Also, add documentation to Users Guide for such sessions.\n\n Own Id: OTP-16893","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 10.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- If a passive socket is created, ssl:recv/2,3 is never called and then the peer\n closes the socket the controlling process will no longer receive an active\n close message.\n\n Own Id: OTP-16697 Aux Id: ERIERL-496\n\n- Data deliver with ssl:recv/2,3 could fail for when using packet mode. This has\n been fixed by correcting the flow control handling of passive sockets when\n packet mode is used.\n\n Own Id: OTP-16764\n\n- This change fixes a potential man-in-the-middle vulnerability when the ssl\n client is configured to automatically handle session tickets\n (\\{session_tickets, auto\\}).\n\n Own Id: OTP-16765\n\n- Fix the internal handling of options 'verify' and 'verify_fun'.\n\n This change fixes a vulnerability when setting the ssl option 'verify' to\n verify_peer in a continued handshake won't take any effect resulting in the\n acceptance of expired peer certificates.\n\n Own Id: OTP-16767 Aux Id: ERIERL-512\n\n- This change fixes the handling of stateless session tickets when anti-replay\n is enabled.\n\n Own Id: OTP-16776 Aux Id: ERL-1316\n\n- Fix a crash due to the faulty handling of stateful session tickets received by\n servers expecting stateless session tickets.\n\n This change also improves the handling of faulty/invalid tickets.\n\n Own Id: OTP-16777 Aux Id: ERL-1317\n\n- Correct flow ctrl checks from OTP-16764 to work as intended. Probably will not\n have a noticeable affect but will make connections more well behaved under\n some circumstances.\n\n Own Id: OTP-16837 Aux Id: ERL-1319, OTP-16764\n\n- Distribution over TLS could exhibit livelock-like behaviour when there is a\n constant stream of distribution messages. Distribution data is now chunked\n every 16 Mb to avoid that.\n\n Own Id: OTP-16851 Aux Id: PR-2703","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Implement the cookie extension for TLS 1.3.\n\n Own Id: OTP-15855\n\n- Experimental OCSP client support.\n\n Own Id: OTP-16448\n\n- TLS 1.0 -TLS-1.2 sessions tables now have a absolute max value instead of\n using a shrinking mechanism when reaching the limit. To avoid out of memory\n problems under heavy load situations. Note that this change infers that\n implementations of ssl_session_cache_api needs to implement the size function\n (introduce in OTP 19) for session reuse to be optimally utilized.\n\n Own Id: OTP-16802 Aux Id: ERIERL-516","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 10.0 - SSL Release Notes","doc":"","ref":"notes.html#ssl-10-0"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Fix a bug that causes cross-build failure.\n\n This change excludes the ssl.d dependency file from the source tar balls.\n\n Own Id: OTP-16562 Aux Id: ERL-1168\n\n- Correct translation of OpenSSL legacy names for two legacy cipher suites\n\n Own Id: OTP-16573 Aux Id: ERIERL-477\n\n- Correct documentation for PSK identity and SRP username.\n\n Own Id: OTP-16585\n\n- Make sure client hostname check is run when client uses its own verify_fun\n\n Own Id: OTP-16626 Aux Id: ERL-1232\n\n- Improved signature selection mechanism in TLS 1.3 for increased\n interoperability.\n\n Own Id: OTP-16638 Aux Id: ERL-1206","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Drop support for SSL-3.0. Support for this legacy TLS version has not been\n enabled by default since OTP 19. Now all code to support it has been removed,\n that is SSL-3.0 protocol version can not be used and is considered invalid.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-14790\n\n- Added support for RSA-PSS signature schemes\n\n Own Id: OTP-15247\n\n- Improve interoperability by implementing the middlebox compatibility mode.\n\n The middlebox compatibility mode makes the TLS 1.3 handshake look more like a\n TLS 1.2 handshake and increases the chance of successfully establishing TLS\n 1.3 connections through legacy middleboxes.\n\n Own Id: OTP-15589\n\n- Utilize new properties of\n [`erlang:dist_ctrl_get_data()`](`erlang:dist_ctrl_get_data/1`) for performance\n improvement of Erlang distribution over TLS.\n\n Own Id: OTP-16127 Aux Id: OTP-15618\n\n- Calls of deprecated functions in the\n [Old Crypto API](`e:crypto:new_api.md#the-old-api`) are replaced by calls of\n their [substitutions](`e:crypto:new_api.md#the-new-api`).\n\n Own Id: OTP-16346\n\n- Implement cipher suite TLS_AES_128_CCM_8_SHA256.\n\n Own Id: OTP-16391\n\n- This change adds TLS-1.3 to the list of default supported versions. That is,\n TLS-1.3 and TLS-1.2 are configured when ssl option 'versions' is not\n explicitly set.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-16400\n\n- Refactored the internal handling of deprecated and removed functions.\n\n Own Id: OTP-16469\n\n- Extended ssl:versions so that it lists supported, available and implemented\n TLS/DTLS versions.\n\n Own Id: OTP-16519\n\n- Added new option exclusive for ssl:cipher_suites/2,3\n\n Own Id: OTP-16532\n\n- Avoid DoS attack against stateful session_tickets by making session ticket ids\n unpredictable.\n\n Own Id: OTP-16533\n\n- Add support for the max_fragment_length extension (RFC 6066).\n\n Own Id: OTP-16547 Aux Id: PR-2547\n\n- Add srp_username in ssl:connection_info, update the document with types of\n this function.\n\n Own Id: OTP-16584","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 9.6.2.3 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-6-2-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Correct flow ctrl checks from OTP-16764 to work as intended. Probably will not\n have a noticeable affect but will make connections more well behaved under\n some circumstances.\n\n Own Id: OTP-16837 Aux Id: ERL-1319, OTP-16764\n\n- Fix a bug that causes cross-build failure.\n\n This change excludes the ssl.d dependency file from the source tar balls.\n\n Own Id: OTP-16921","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 9.6.2.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-6-2-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Data deliver with ssl:recv/2,3 could fail for when using packet mode. This has\n been fixed by correcting the flow control handling of passive sockets when\n packet mode is used.\n\n Own Id: OTP-16764\n\n- Fix the internal handling of options 'verify' and 'verify_fun'.\n\n This change fixes a vulnerability when setting the ssl option 'verify' to\n verify_peer in a continued handshake won't take any effect resulting in the\n acceptance of expired peer certificates.\n\n Own Id: OTP-16767 Aux Id: ERIERL-512","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 9.6.2.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-6-2-1"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- If a passive socket is created, ssl:recv/2,3 is never called and then the peer\n closes the socket the controlling process will no longer receive an active\n close message.\n\n Own Id: OTP-16697 Aux Id: ERIERL-496","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 9.6.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-6-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Fix timing bug that could cause ssl sockets to become unresponsive after an\n ssl:recv/3 call timed out\n\n Own Id: OTP-16619 Aux Id: ERL-1213","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 9.6.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-6-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Correct error handling when the partial_chain fun claims a certificate to be\n the trusted cert that is not part of the chain. This bug would hide the\n appropriate alert generating an \"INTERNAL_ERROR\" alert instead.\n\n Own Id: OTP-16567 Aux Id: ERIERL-481","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 9.6 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-6"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Correct handling of TLS record limit in TLS-1.3. The max value differs from\n previous versions. Also the payload data max record check was broken, that is\n record overflow problems could occur if user sent large amounts of data.\n\n Own Id: OTP-16258\n\n- Correct close handling for DTLS\n\n Own Id: OTP-16348 Aux Id: ERL-1110\n\n- Fix ssl:getstat/1-2 to also work for DTLS sockets\n\n Own Id: OTP-16352 Aux Id: ERL-1099\n\n- Correct internal handling och socket active mode to avoid reviving TCP data\n aimed for a downgraded TLS socket.\n\n Own Id: OTP-16425\n\n- When using the host name as fallback for SNI (server name indication) strip a\n possible trailing dot that is allowed in a host name but not in the SNI. Also\n if the server receives a SNI with a trailing dot send an UNRECOGNIZED_NAME\n alert.\n\n Own Id: OTP-16437 Aux Id: ERL-1135\n\n- Immediately remove session entries if handshake is abruptly closed at\n transport level.\n\n Own Id: OTP-16479","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Implementation of the key and initialization vector update feature, and\n general hardening of TLS 1.3.\n\n There are cryptographic limits on the amount of plaintext which can be safely\n encrypted under a given set of keys.\n\n This change enforces those limits by triggering automatic key updates on TLS\n 1.3 connections.\n\n Own Id: OTP-15856\n\n- Add support for TLS 1.3 Session Tickets (stateful and stateless). This allows\n session resumption using keying material from a previous successful handshake.\n\n Own Id: OTP-16253\n\n- Add support for key exchange with Edward curves and PSS-RSA padding in\n signature verification.\n\n Own Id: OTP-16528","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 9.5.3 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-5-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Enhance error handling, all ALERTS shall be handled gracefully and not cause a\n crash.\n\n Own Id: OTP-16413 Aux Id: ERL-1136\n\n- Enhance alert logging, in some places the role indication of the alert origin\n was missing. So the log would say undefined instead of client or server.\n\n Own Id: OTP-16424\n\n- Two different optimizations did not work together and resulted in the possible\n breakage of connections using stream ciphers (that is RC4). Reworked the\n implementation to avoid this.\n\n Own Id: OTP-16426 Aux Id: ERL-1136","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 9.5.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-5-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Fix the handling of GREASE values sent by web browsers when establishing TLS\n 1.3 connections. This change improves handling of GREASE values in various\n protocol elements sent in a TLS 1.3 ClientHello.\n\n Own Id: OTP-16388 Aux Id: ERL-1130\n\n- Correct DTLS listen emulation, could cause problems with opening a new DTLS\n listen socket for a port previously used by a now closed DTLS listen socket.\n\n Own Id: OTP-16396 Aux Id: ERL-1118","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 9.5.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-5-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Add missing alert handling clause for TLS record handling. Could sometimes\n cause confusing error behaviors of TLS connections.\n\n Own Id: OTP-16357 Aux Id: ERL-1166\n\n- Fix handling of ssl:recv that happens during a renegotiation. Using the\n passive receive function ssl:recv/\\[2,3] during a renegotiation would fail the\n connection with unexpected msg.\n\n Own Id: OTP-16361","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 9.5 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-5"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Corrected CRL handling which could cause CRL verification to fail. This could\n happen when the CRL distribution point explicitly specifies the CRL issuer,\n that is not using the fallback.\n\n Own Id: OTP-16156 Aux Id: ERL-1030\n\n- Correct handling of unordered chains so that it works as expected\n\n Own Id: OTP-16293\n\n- Fix bug causing ssl application to crash when handshake is paused and\n ClientHello contains extensions for session resumption\n (psk_key_exchange_modes, pre_shared_key).\n\n Own Id: OTP-16295 Aux Id: ERL-1095\n\n- Fix connectivity problems with legacy servers when client is configured to\n support a range of protocol versions including TLS 1.3.\n\n Own Id: OTP-16303","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Improve session handling for TLS-1.3 compatibility mode and cleaner internal\n handling so that removal of old session data can be more efficient, hopefully\n mitigating problems with big session tables during heavy load.\n\n Own Id: OTP-15524 Aux Id: OTP-15352\n\n- Correct handling of DTLS listen socket emulation. Could cause failure to\n create new listen socket after process that owned previous listen socket died.\n\n Own Id: OTP-15809 Aux Id: ERL-917\n\n- Add detailed info in ALERT description when client does not send a requested\n cert.\n\n Own Id: OTP-16266","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 9.4 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Handling of zero size fragments in TLS could cause an infinite loop. This has\n now been corrected.\n\n Own Id: OTP-15328 Aux Id: ERIERL-379\n\n- DTLS record check needs to consider that a resent hello message can have a\n different version than the negotiated.\n\n Own Id: OTP-15807 Aux Id: ERL-920","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Basic support for TLS 1.3 Client for experimental use. For more information\n see the Standards Compliance chapter of the User's Guide.\n\n Own Id: OTP-15431\n\n- Correct solution for retaining tcp flow control OTP-15802 (ERL-934) as to not\n break ssl:recv as reported in (ERL-938)\n\n Own Id: OTP-15823 Aux Id: ERL-934, ERL-938\n\n- Enhance dialyzer specs to reflect implementation better and avoid dialyzer\n warnings for the user that wants to use TLS with unix domain sockets.\n\n Own Id: OTP-15851 Aux Id: PR-2235\n\n- Add support for ECDSA signature algorithms in TLS 1.3.\n\n Own Id: OTP-15854\n\n- Correct error handling of TLS downgrade, possible return values form\n ssl:close/2 when downgrading is \\{ok, Port\\} or \\{error, Reason\\}, it could\n happen that only ok was returned instead of \\{error, closed\\} when downgrade\n failed due to that the peer closed the TCP connection.\n\n Own Id: OTP-16027","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 9.3.5 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-3-5"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Enhance error handling for erroneous alerts from the peer.\n\n Own Id: OTP-15943","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 9.3.4 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-3-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Fix handling of certificate decoding problems in TLS 1.3 similarly as in TLS\n 1.2.\n\n Own Id: OTP-15900\n\n- Hibernation now works as expected in all cases, was accidentally broken by\n optimization efforts.\n\n Own Id: OTP-15910\n\n- Fix interoperability problems with openssl when the TLS 1.3 server is\n configured with the option signature_algs_cert.\n\n Own Id: OTP-15913","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 9.3.3 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-3-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Correct handshake handling, might cause strange symptoms such as ASN.1\n certificate decoding issues.\n\n Own Id: OTP-15879 Aux Id: ERL-968\n\n- Fix handling of the signature_algorithms_cert extension in the ClientHello\n handshake message.\n\n Own Id: OTP-15887 Aux Id: ERL-973\n\n- Handle new ClientHello extensions when handshake is paused by the \\{handshake,\n hello\\} ssl option.\n\n Own Id: OTP-15888 Aux Id: ERL-975","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 9.3.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-3-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Returned \"alert error string\" is now same as logged alert string\n\n Own Id: OTP-15844\n\n- Fix returned extension map fields to follow the documentation.\n\n Own Id: OTP-15862 Aux Id: ERL-951\n\n- Avoid DTLS crash due to missing gen_server return value in DTLS packet demux\n process.\n\n Own Id: OTP-15864 Aux Id: ERL-962","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 9.3.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-3-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Missing check of size of user_data_buffer made internal socket behave as an\n active socket instead of active N. This could cause memory problems.\n\n Own Id: OTP-15825 Aux Id: ERL-934, OTP-15823","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 9.3 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- The distribution handshake with TLS distribution (`inet_tls_dist`) does now\n utilize the socket option `{nodelay, true}`, which decreases the distribution\n setup time significantly.\n\n Own Id: OTP-14792\n\n- Correct shutdown reason to avoid an incorrect crash report\n\n Own Id: OTP-15710 Aux Id: ERL-893\n\n- Enhance documentation and type specifications.\n\n Own Id: OTP-15746 Aux Id: ERIERL-333","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- TLS-1.0, TLS-1.1 and DTLS-1.0 are now considered legacy and not supported by\n default\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-14865\n\n- Use new logger API in ssl. Introduce log levels and verbose debug logging for\n SSL.\n\n Own Id: OTP-15055\n\n- Add new API function str_to_suite/1, cipher_suites/3 (list cipher suites as\n rfc or OpenSSL name strings) and suite_to_openssl_str/1\n\n Own Id: OTP-15483 Aux Id: ERL-924\n\n- Basic support for TLS 1.3 Server for experimental use. The client is not yet\n functional, for more information see the Standards Compliance chapter of the\n User's Guide.\n\n Own Id: OTP-15591\n\n- Add support for PSK CCM ciphers from RFC 6655\n\n Own Id: OTP-15626","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 9.2.3.7 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-2-3-7"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Data deliver with ssl:recv/2,3 could fail for when using packet mode. This has\n been fixed by correcting the flow control handling of passive sockets when\n packet mode is used.\n\n Own Id: OTP-16764","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 9.2.3.6 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-2-3-6"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Fix timing bug that could cause ssl sockets to become unresponsive after an\n ssl:recv/3 call timed out\n\n Own Id: OTP-16619 Aux Id: ERL-1213","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 9.2.3.5 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-2-3-5"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Handling of zero size fragments in TLS could cause an infinite loop. This has\n now been corrected.\n\n Own Id: OTP-15328 Aux Id: ERIERL-379","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 9.2.3.4 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-2-3-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Hibernation now works as expected in all cases, was accidentally broken by\n optimization efforts.\n\n Own Id: OTP-15910","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 9.2.3.3 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-2-3-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Correct handshake handling, might cause strange symptoms such as ASN.1\n certificate decoding issues.\n\n Own Id: OTP-15879 Aux Id: ERL-968","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 9.2.3.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-2-3-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Returned \"alert error string\" is now same as logged alert string\n\n Own Id: OTP-15844","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 9.2.3.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-2-3-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Correct solution for retaining tcp flow control OTP-15802 (ERL-934) as to not\n break ssl:recv as reported in (ERL-938)\n\n Own Id: OTP-15823 Aux Id: ERL-934, ERL-938","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 9.2.3 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-2-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Missing check of size of user_data_buffer made internal socket behave as an\n active socket instead of active N. This could cause memory problems.\n\n Own Id: OTP-15802 Aux Id: ERL-934","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Back port of bug fix ERL-893 from OTP-22 and document enhancements that will\n solve dialyzer warnings for users of the ssl application.\n\n This change also affects public_key, eldap (and inet doc).\n\n Own Id: OTP-15785 Aux Id: ERL-929, ERL-893, PR-2215","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 9.2.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-2-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- With the default BEAST Mitigation strategy for TLS 1.0 an empty TLS fragment\n could be sent after a one-byte fragment. This glitch has been fixed.\n\n Own Id: OTP-15054 Aux Id: ERIERL-346","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 9.2.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-2-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- The timeout for a passive receive was sometimes not cancelled and later caused\n a server crash. This bug has now been corrected.\n\n Own Id: OTP-14701 Aux Id: ERL-883, ERL-884\n\n- Add tag for passive message (active N) in cb_info to retain transport\n transparency.\n\n Own Id: OTP-15679 Aux Id: ERL-861","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 9.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Fix bug that an incorrect return value for gen_statem could be created when\n alert was a result of handling renegotiation info extension\n\n Own Id: OTP-15502\n\n- Correct check for 3des_ede_cbc, could cause ssl to claim to support\n 3des_ede_cbc when cryptolib does not.\n\n Own Id: OTP-15539\n\n- Improved DTLS error handling, avoids unexpected connection failure in rare\n cases.\n\n Own Id: OTP-15561\n\n- Corrected active once emulation bug that could cause the ssl_closed meassage\n to not be sent. Bug introduced by OTP-15449\n\n Own Id: OTP-15666 Aux Id: ERIERL-316,","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Add client option \\{reuse_session, SessionID::binary()\\} that can be used\n together with new option value \\{reuse_sessions, save\\}. This makes it\n possible to reuse a session from a specific connection establishment.\n\n Own Id: OTP-15369\n\n- The Reason part of of the error return from the functions connect and\n handshake has a better and documented format. This will sometimes differ from\n previous returned reasons, however those where only documented as term() and\n should for that reason not be relied on.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15423\n\n- Refactor of state handling to improve TLS application data throughput and\n reduce CPU overhead\n\n Own Id: OTP-15445\n\n- The SSL code has been optimized in many small ways to reduce CPU load for\n encryption/decryption, especially for Erlang's distribution protocol over TLS.\n\n Own Id: OTP-15529\n\n- Add support for active N\n\n Own Id: OTP-15665 Aux Id: ERL-811, PR-2072","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 9.1.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-1-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Fix encoding of the SRP extension length field in ssl. The old encoding of the\n SRP extension length could cause interoperability problems with third party\n SSL implementations when SRP was used.\n\n Own Id: OTP-15477 Aux Id: ERL-790\n\n- Guarantee active once data delivery, handling TCP stream properly.\n\n Own Id: OTP-15504 Aux Id: ERL-371\n\n- Correct gen_statem returns for some error cases\n\n Own Id: OTP-15505","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 9.1.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-1-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Fixed renegotiation bug. Client did not handle server initiated renegotiation\n correctly after rewrite to two connection processes, due to ERL-622 commit\n d87ac1c55188f5ba5cdf72384125d94d42118c18. This could manifest it self as a \"\n bad_record_mac\" alert.\n\n Also included are some optimizations\n\n Own Id: OTP-15489 Aux Id: ERL-308","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 9.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- PEM cache was not evicting expired entries due to due to timezone confusion.\n\n Own Id: OTP-15368\n\n- Make sure an error is returned if a \"transport_accept socket\" is used in some\n other call than ssl:handshake\\* or ssl:controlling_process\n\n Own Id: OTP-15384 Aux Id: ERL-756\n\n- Fix timestamp handling in the PEM-cache could cause entries to not be\n invalidated at the correct time.\n\n Own Id: OTP-15402\n\n- Extend check for undelivered data at closing, could under some circumstances\n fail to deliver all data that was actually received.\n\n Own Id: OTP-15412 Aux Id: ERL-731\n\n- Correct signature check for TLS-1.2 that allows different algorithms for\n signature of peer cert and peer cert key. Not all allowed combinations where\n accepted.\n\n Own Id: OTP-15415 Aux Id: ERL-763\n\n- Correct gen_statem return value, could cause renegotiation to fail.\n\n Own Id: OTP-15418 Aux Id: ERL-770","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Add engine support for RSA key exchange\n\n Own Id: OTP-15420 Aux Id: ERIERL-268\n\n- ssl now uses active n internally to boost performance. Old active once\n behavior can be restored by setting application variable see manual page for\n ssl application (man 6).\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15449","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 9.0.3 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-0-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Correct alert handling with new TLS sender process, from ssl-9.0.2. CLOSE\n ALERTS could under some circumstances be encoded using an incorrect cipher\n state. This would cause the peer to regard them as unknown messages.\n\n Own Id: OTP-15337 Aux Id: ERL-738\n\n- Correct handling of socket packet option with new TLS sender process, from\n ssl-9.0.2. When changing the socket option \\{packet, 1|2|3|4\\} with\n ssl:setopts/2 the option must internally be propagated to the sender process\n as well as the reader process as this particular option also affects the data\n to be sent.\n\n Own Id: OTP-15348 Aux Id: ERL-747","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 9.0.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-0-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Use separate processes for sending and receiving application data for TLS\n connections to avoid potential deadlock that was most likely to occur when\n using TLS for Erlang distribution. Note does not change the API.\n\n Own Id: OTP-15122\n\n- Correct handling of empty server SNI extension\n\n Own Id: OTP-15168\n\n- Correct PSK cipher suite handling and add selected_cipher_suite to connection\n information\n\n Own Id: OTP-15172\n\n- Adopt to the fact that cipher suite sign restriction are relaxed in TLS-1.2\n\n Own Id: OTP-15173\n\n- Enhance error handling of non existing PEM files\n\n Own Id: OTP-15174\n\n- Correct close handling of transport accepted sockets in the error state\n\n Own Id: OTP-15216\n\n- Correct PEM cache to not add references to empty entries when PEM file does\n not exist.\n\n Own Id: OTP-15224\n\n- Correct handling of all PSK cipher suites\n\n Before only some PSK suites would be correctly negotiated and most PSK ciphers\n suites would fail the connection.\n\n Own Id: OTP-15285","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- TLS will now try to order certificate chains if they appear to be unordered.\n That is prior to TLS 1.3, “certificate_list” ordering was required to be\n strict, however some implementations already allowed for some flexibility. For\n maximum compatibility, all implementations SHOULD be prepared to handle\n potentially extraneous certificates and arbitrary orderings from any TLS\n version.\n\n Own Id: OTP-12983\n\n- TLS will now try to reconstructed an incomplete certificate chains from its\n local CA-database and use that data for the certificate path validation. This\n especially makes sense for partial chains as then the peer might not send an\n intermediate CA as it is considered the trusted root in that case.\n\n Own Id: OTP-15060\n\n- Option keyfile defaults to certfile and should be trumped with key. This\n failed for engine keys.\n\n Own Id: OTP-15193\n\n- Error message improvement when own certificate has decoding issues, see also\n issue ERL-668.\n\n Own Id: OTP-15234\n\n- Correct dialyzer spec for key option\n\n Own Id: OTP-15281","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 9.0.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-0-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Correct cipher suite handling for ECDHE\\_\\*, the incorrect handling could\n cause an incorrrect suite to be selected and most likely fail the handshake.\n\n Own Id: OTP-15203","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 9.0 - SSL Release Notes","doc":"","ref":"notes.html#ssl-9-0"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Correct handling of ECDH suites.\n\n Own Id: OTP-14974\n\n- Proper handling of clients that choose to send an empty answer to a\n certificate request\n\n Own Id: OTP-15050","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Distribution over SSL (inet_tls) has, to improve performance, been rewritten\n to not use intermediate processes and ports.\n\n Own Id: OTP-14465\n\n- Add support for ECDHE_PSK cipher suites\n\n Own Id: OTP-14547\n\n- For security reasons no longer support 3-DES cipher suites by default\n\n \\*** INCOMPATIBILITY with possibly \\***\n\n Own Id: OTP-14768\n\n- For security reasons RSA-key exchange cipher suites are no longer supported by\n default\n\n \\*** INCOMPATIBILITY with possible \\***\n\n Own Id: OTP-14769\n\n- The interoperability option to fallback to insecure renegotiation now has to\n be explicitly turned on.\n\n \\*** INCOMPATIBILITY with possibly \\***\n\n Own Id: OTP-14789\n\n- Drop support for SSLv2 enabled clients. SSLv2 has been broken for decades and\n never supported by the Erlang SSL/TLS implementation. This option was by\n default disabled and enabling it has proved to sometimes break connections not\n using SSLv2 enabled clients.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-14824\n\n- Remove CHACHA20_POLY1305 ciphers form default for now. We have discovered\n interoperability problems, ERL-538, that we believe needs to be solved in\n crypto.\n\n \\*** INCOMPATIBILITY with possibly \\***\n\n Own Id: OTP-14882\n\n- Generalize DTLS packet multiplexing to make it easier to add future DTLS\n features and uses.\n\n Own Id: OTP-14888\n\n- Use uri_string module instead of http_uri.\n\n Own Id: OTP-14902\n\n- The SSL distribution protocol `-proto inet_tls` has stopped setting the SSL\n option `server_name_indication`. New verify funs for client and server in\n `inet_tls_dist` has been added, not documented yet, that checks node name if\n present in peer certificate. Usage is still also yet to be documented.\n\n Own Id: OTP-14969 Aux Id: OTP-14465, ERL-598\n\n- Deprecate ssl:ssl_accept/\\[1,2,3] in favour of ssl:handshake/\\[1,2,3]\n\n Own Id: OTP-15056\n\n- Customizes the hostname verification of the peer certificate, as different\n protocols that use TLS such as HTTP or LDAP may want to do it differently\n\n Own Id: OTP-15102 Aux Id: ERL-542, OTP-14962\n\n- Add utility function for converting erlang cipher suites to a string\n representation (ERL-600).\n\n Own Id: OTP-15106\n\n- First version with support for DTLS\n\n Own Id: OTP-15142","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 8.2.6.4 - SSL Release Notes","doc":"","ref":"notes.html#ssl-8-2-6-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Add engine support for RSA key exchange\n\n Own Id: OTP-15420","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 8.2.6.3 - SSL Release Notes","doc":"","ref":"notes.html#ssl-8-2-6-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Extend check for undelivered data at closing, could under some circumstances\n fail to deliverd all data that was acctualy recivied.\n\n Own Id: OTP-15412","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 8.2.6.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-8-2-6-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Correct handling of empty server SNI extension\n\n Own Id: OTP-15168\n\n- Correct cipher suite handling for ECDHE\\_\\*, the incorrect handling could\n cause an incorrrect suite to be selected and most likely fail the handshake.\n\n Own Id: OTP-15203","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 8.2.6.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-8-2-6-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Improve cipher suite handling correcting ECC and TLS-1.2 requierments.\n Backport of solution for ERL-641\n\n Own Id: OTP-15178","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Option keyfile defaults to certfile and should be trumped with key. This\n failed for engine keys.\n\n Own Id: OTP-15193","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 8.2.6 - SSL Release Notes","doc":"","ref":"notes.html#ssl-8-2-6"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Proper handling of clients that choose to send an empty answer to a\n certificate request\n\n Own Id: OTP-15050","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 8.2.5 - SSL Release Notes","doc":"","ref":"notes.html#ssl-8-2-5"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Fix filter function to not incorrectly exclude AEAD cipher suites\n\n Own Id: OTP-14981","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 8.2.4 - SSL Release Notes","doc":"","ref":"notes.html#ssl-8-2-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Optimization of bad merge conflict resolution causing dubble decode\n\n Own Id: OTP-14843\n\n- Restore error propagation to OTP-19.3 behaviour, in OTP-20.2 implementation\n adjustments to gen_statem needed some further adjustments to avoid a race\n condition. This could cause a TLS server to not always report file path errors\n correctly.\n\n Own Id: OTP-14852\n\n- Corrected RC4 suites listing function to regard TLS version\n\n Own Id: OTP-14871\n\n- Fix alert handling so that unexpected messages are logged and alerted\n correctly\n\n Own Id: OTP-14919\n\n- Correct handling of anonymous cipher suites\n\n Own Id: OTP-14952","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Added new API functions to facilitate cipher suite handling\n\n Own Id: OTP-14760\n\n- Correct TLS_FALLBACK_SCSV handling so that this special flag suite is always\n placed last in the cipher suite list in accordance with the specs. Also make\n sure this functionality is used in DTLS.\n\n Own Id: OTP-14828\n\n- Add TLS record version sanity check for early as possible error detection and\n consistency in ALERT codes generated\n\n Own Id: OTP-14892","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 8.2.3 - SSL Release Notes","doc":"","ref":"notes.html#ssl-8-2-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Packet options cannot be supported for unreliable transports, that is, packet\n option for DTLS over udp will not be supported.\n\n Own Id: OTP-14664\n\n- Ensure data delivery before close if possible. This fix is related to fix in\n PR-1479.\n\n Own Id: OTP-14794","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- The crypto API is extended to use private/public keys stored in an Engine for\n sign/verify or encrypt/decrypt operations.\n\n The ssl application provides an API to use this new engine concept in TLS.\n\n Own Id: OTP-14448\n\n- Implemented renegotiation for DTLS\n\n Own Id: OTP-14563\n\n- A new command line option `-ssl_dist_optfile` has been added to facilitate\n specifying the many options needed when using SSL as the distribution\n protocol.\n\n Own Id: OTP-14657","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 8.2.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-8-2-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- TLS sessions must be registered with SNI if provided, so that sessions where\n client hostname verification would fail cannot connect reusing a session\n created when the server name verification succeeded.\n\n Own Id: OTP-14632\n\n- An erlang TLS server configured with cipher suites using rsa key exchange, may\n be vulnerable to an Adaptive Chosen Ciphertext attack (AKA Bleichenbacher\n attack) against RSA, which when exploited, may result in plaintext recovery of\n encrypted messages and/or a Man-in-the-middle (MiTM) attack, despite the\n attacker not having gained access to the server’s private key itself.\n [CVE-2017-1000385](https://nvd.nist.gov/vuln/detail/CVE-2017-1000385)\n\n Exploiting this vulnerability to perform plaintext recovery of encrypted\n messages will, in most practical cases, allow an attacker to read the\n plaintext only after the session has completed. Only TLS sessions established\n using RSA key exchange are vulnerable to this attack.\n\n Exploiting this vulnerability to conduct a MiTM attack requires the attacker\n to complete the initial attack, which may require thousands of server\n requests, during the handshake phase of the targeted session within the window\n of the configured handshake timeout. This attack may be conducted against any\n TLS session using RSA signatures, but only if cipher suites using RSA key\n exchange are also enabled on the server. The limited window of opportunity,\n limitations in bandwidth, and latency make this attack significantly more\n difficult to execute.\n\n RSA key exchange is enabled by default although least prioritized if server\n order is honored. For such a cipher suite to be chosen it must also be\n supported by the client and probably the only shared cipher suite.\n\n Captured TLS sessions encrypted with ephemeral cipher suites (DHE or ECDHE)\n are not at risk for subsequent decryption due to this vulnerability.\n\n As a workaround if default cipher suite configuration was used you can\n configure the server to not use vulnerable suites with the ciphers option like\n this:\n\n `{ciphers, [Suite || Suite <- ssl:cipher_suites(), element(1,Suite) =/= rsa]}`\n\n that is your code will look somethingh like this:\n\n `ssl:listen(Port, [{ciphers, [Suite || Suite <- ssl:cipher_suites(), element(1,S) =/= rsa]} | Options]).`\n\n Thanks to Hanno Böck, Juraj Somorovsky and Craig Young for reporting this\n vulnerability.\n\n Own Id: OTP-14748","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- If no SNI is available and the hostname is an IP-address also check for\n IP-address match. This check is not as good as a DNS hostname check and\n certificates using IP-address are not recommended.\n\n Own Id: OTP-14655","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 8.2.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-8-2-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Max session table works correctly again\n\n Own Id: OTP-14556","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Customize alert handling for DTLS over UDP to mitigate DoS attacks\n\n Own Id: OTP-14078\n\n- Improved error propagation and reports\n\n Own Id: OTP-14236","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 8.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-8-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- ECDH-ECDSA key exchange supported, was accidentally dismissed in earlier\n versions.\n\n Own Id: OTP-14421\n\n- Correct close semantics for active once connections. This was a timing\n dependent bug the resulted in the close message not always reaching the ssl\n user process.\n\n Own Id: OTP-14443","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- TLS-1.2 clients will now always send hello messages on its own format, as\n opposed to earlier versions that will send the hello on the lowest supported\n version, this is a change supported by the latest RFC.\n\n This will make interoperability with some newer servers smoother. Potentially,\n but unlikely, this could cause a problem with older servers if they do not\n adhere to the RFC and ignore unknown extensions.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-13820\n\n- Allow Erlang/OTP to use OpenSSL in FIPS-140 mode, in order to satisfy specific\n security requirements (mostly by different parts of the US federal\n government).\n\n See the new crypto users guide \"FIPS mode\" chapter about building and using\n the FIPS support which is disabled by default.\n\n (Thanks to dszoboszlay and legoscia)\n\n Own Id: OTP-13921 Aux Id: PR-1180\n\n- Implemented DTLS cookie generation, required by spec, instead of using a\n hardcoded value.\n\n Own Id: OTP-14076\n\n- Implement sliding window replay protection of DTLS records.\n\n Own Id: OTP-14077\n\n- TLS client processes will by default call public_key:pkix_verify_hostname/2 to\n verify the hostname of the connection with the server certificates specified\n hostname during certificate path validation. The user may explicitly disables\n it. Also if the hostname cannot be derived from the first argument to connect\n or is not supplied by the server name indication option, the check will not be\n performed.\n\n Own Id: OTP-14197\n\n- Extend connection_information/\\[1,2] . The values session_id, master_secret,\n client_random and server_random can no be accessed by\n connection_information/2. Note only session_id will be added to\n connection_information/1. The rational is that values concerning the\n connection security should have to be explicitly requested.\n\n Own Id: OTP-14291\n\n- Chacha cipher suites are currently not tested enough to be most preferred ones\n\n Own Id: OTP-14382\n\n- Basic support for DTLS that been tested together with OpenSSL.\n\n Test by providing the option \\{protocol, dtls\\} to the ssl API functions\n connect and listen.\n\n Own Id: OTP-14388","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 8.1.3.1.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-8-1-3-1-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Fix alert handling so that unexpected messages are logged and alerted\n correctly\n\n Own Id: OTP-14929","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 8.1.3.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-8-1-3-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- An erlang TLS server configured with cipher suites using rsa key exchange, may\n be vulnerable to an Adaptive Chosen Ciphertext attack (AKA Bleichenbacher\n attack) against RSA, which when exploited, may result in plaintext recovery of\n encrypted messages and/or a Man-in-the-middle (MiTM) attack, despite the\n attacker not having gained access to the server’s private key itself.\n [CVE-2017-1000385](https://nvd.nist.gov/vuln/detail/CVE-2017-1000385)\n\n Exploiting this vulnerability to perform plaintext recovery of encrypted\n messages will, in most practical cases, allow an attacker to read the\n plaintext only after the session has completed. Only TLS sessions established\n using RSA key exchange are vulnerable to this attack.\n\n Exploiting this vulnerability to conduct a MiTM attack requires the attacker\n to complete the initial attack, which may require thousands of server\n requests, during the handshake phase of the targeted session within the window\n of the configured handshake timeout. This attack may be conducted against any\n TLS session using RSA signatures, but only if cipher suites using RSA key\n exchange are also enabled on the server. The limited window of opportunity,\n limitations in bandwidth, and latency make this attack significantly more\n difficult to execute.\n\n RSA key exchange is enabled by default although least prioritized if server\n order is honored. For such a cipher suite to be chosen it must also be\n supported by the client and probably the only shared cipher suite.\n\n Captured TLS sessions encrypted with ephemeral cipher suites (DHE or ECDHE)\n are not at risk for subsequent decryption due to this vulnerability.\n\n As a workaround if default cipher suite configuration was used you can\n configure the server to not use vulnerable suites with the ciphers option like\n this:\n\n `{ciphers, [Suite || Suite <- ssl:cipher_suites(), element(1,Suite) =/= rsa]}`\n\n that is your code will look somethingh like this:\n\n `ssl:listen(Port, [{ciphers, [Suite || Suite <- ssl:cipher_suites(), element(1,S) =/= rsa]} | Options]).`\n\n Thanks to Hanno Böck, Juraj Somorovsky and Craig Young for reporting this\n vulnerability.\n\n Own Id: OTP-14748","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 8.1.3 - SSL Release Notes","doc":"","ref":"notes.html#ssl-8-1-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Remove debug printout\n\n Own Id: OTP-14396","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 8.1.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-8-1-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Correct active once emulation, for TLS. Now all data received by the\n connection process will be delivered through active once, even when the active\n once arrives after that the gen_tcp socket is closed by the peer.\n\n Own Id: OTP-14300","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 8.1.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-8-1-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Corrected termination behavior, that caused a PEM cache bug and sometimes\n resulted in connection failures.\n\n Own Id: OTP-14100\n\n- Fix bug that could hang ssl connection processes when failing to require more\n data for very large handshake packages. Add option max_handshake_size to\n mitigate DoS attacks.\n\n Own Id: OTP-14138\n\n- Improved support for CRL handling that could fail to work as intended when an\n id-ce-extKeyUsage was present in the certificate. Also improvements where\n needed to distributionpoint handling so that all revocations actually are\n found and not deemed to be not determinable.\n\n Own Id: OTP-14141\n\n- A TLS handshake might accidentally match old sslv2 format and ssl application\n would incorrectly aborted TLS handshake with ssl_v2_client_hello_no_supported.\n Parsing was altered to avoid this problem.\n\n Own Id: OTP-14222\n\n- Correct default cipher list to prefer AES 128 before 3DES\n\n Own Id: OTP-14235","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Move PEM cache to a dedicated process, to avoid making the SSL manager process\n a bottleneck. This improves scalability of TLS connections.\n\n Own Id: OTP-13874","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 8.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-8-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- List of possible anonymous suites, never supported by default, where incorrect\n for some TLS versions.\n\n Own Id: OTP-13926","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Experimental version of DTLS. It is runnable but not complete and cannot be\n considered reliable for production usage.\n\n Own Id: OTP-12982\n\n- Add API options to handle ECC curve selection.\n\n Own Id: OTP-13959","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 8.0.3 - SSL Release Notes","doc":"","ref":"notes.html#ssl-8-0-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- A timing related bug in event handling could cause interoperability problems\n between an erlang TLS server and some TLS clients, especially noticed with\n Firefox as TLS client.\n\n Own Id: OTP-13917\n\n- Correct ECC curve selection, the error could cause the default to always be\n selected.\n\n Own Id: OTP-13918","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 8.0.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-8-0-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Correctly formed handshake messages received out of order will now correctly\n fail the connection with unexpected message.\n\n Own Id: OTP-13853\n\n- Correct handling of signature algorithm selection\n\n Own Id: OTP-13711","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- ssl application now behaves gracefully also on partially incorrect input from\n peer.\n\n Own Id: OTP-13834\n\n- Add application environment configuration bypass_pem_cache. This can be used\n as a workaround for the current implementation of the PEM-cache that has\n proven to be a bottleneck.\n\n Own Id: OTP-13883","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 8.0.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-8-0-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- The TLS/SSL protocol version selection for the SSL server has been corrected\n to follow RFC 5246 Appendix E.1 especially in case where the list of supported\n versions has gaps. Now the server selects the highest protocol version it\n supports that is not higher than what the client supports.\n\n Own Id: OTP-13753 Aux Id: seq13150","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 8.0 - SSL Release Notes","doc":"","ref":"notes.html#ssl-8-0"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Server now rejects, a not requested client cert, as an incorrect handshake\n message and ends the connection.\n\n Own Id: OTP-13651","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Remove default support for DES cipher suites\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-13195\n\n- Deprecate the function `crypto:rand_bytes` and make sure that\n `crypto:strong_rand_bytes` is used in all places that are cryptographically\n significant.\n\n Own Id: OTP-13214\n\n- Better error handling of user error during TLS upgrade. ERL-69 is solved by\n gen_statem rewrite of ssl application.\n\n Own Id: OTP-13255\n\n- Provide user friendly error message when crypto rejects a key\n\n Own Id: OTP-13256\n\n- Add ssl:getstat/1 and ssl:getstat/2\n\n Own Id: OTP-13415\n\n- TLS distribution connections now allow specifying the options `verify_fun`,\n `crl_check` and `crl_cache`. See the documentation. GitHub pull req #956\n contributed by Magnus Henoch.\n\n Own Id: OTP-13429 Aux Id: Pull#956\n\n- Remove confusing error message when closing a distributed erlang node running\n over TLS\n\n Own Id: OTP-13431\n\n- Remove default support for use of md5 in TLS 1.2 signature algorithms\n\n Own Id: OTP-13463\n\n- ssl now uses gen_statem instead of gen_fsm to implement the ssl connection\n process, this solves some timing issues in addition to making the code more\n intuitive as the behaviour can be used cleanly instead of having a lot of\n workaround for shortcomings of the behaviour.\n\n Own Id: OTP-13464\n\n- Phase out interoperability with clients that offer SSLv2. By default they are\n no longer supported, but an option to provide interoperability is offered.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-13465\n\n- OpenSSL has functions to generate short (eight hex digits) hashes of issuers\n of certificates and CRLs. These hashes are used by the \"c_rehash\" script to\n populate directories of CA certificates and CRLs, e.g. in the Apache web\n server. Add functionality to let an Erlang program find the right CRL for a\n given certificate in such a directory.\n\n Own Id: OTP-13530\n\n- Some legacy TLS 1.0 software does not tolerate the 1/n-1 content split BEAST\n mitigation technique. Add a beast_mitigation SSL option (defaulting to\n one_n_minus_one) to select or disable the BEAST mitigation technique.\n\n Own Id: OTP-13629\n\n- Enhance error log messages to facilitate for users to understand the error\n\n Own Id: OTP-13632\n\n- Increased default DH params to 2048-bit\n\n Own Id: OTP-13636\n\n- Propagate CRL unknown CA error so that public_key validation process continues\n correctly and determines what should happen.\n\n Own Id: OTP-13656\n\n- Introduce a flight concept for handshake packages. This is a preparation for\n enabling DTLS, however it can also have a positive effects for TLS on slow and\n unreliable networks.\n\n Own Id: OTP-13678","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 7.3.3.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-7-3-3-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- An erlang TLS server configured with cipher suites using rsa key exchange, may\n be vulnerable to an Adaptive Chosen Ciphertext attack (AKA Bleichenbacher\n attack) against RSA, which when exploited, may result in plaintext recovery of\n encrypted messages and/or a Man-in-the-middle (MiTM) attack, despite the\n attacker not having gained access to the server’s private key itself.\n [CVE-2017-1000385](https://nvd.nist.gov/vuln/detail/CVE-2017-1000385)\n\n Exploiting this vulnerability to perform plaintext recovery of encrypted\n messages will, in most practical cases, allow an attacker to read the\n plaintext only after the session has completed. Only TLS sessions established\n using RSA key exchange are vulnerable to this attack.\n\n Exploiting this vulnerability to conduct a MiTM attack requires the attacker\n to complete the initial attack, which may require thousands of server\n requests, during the handshake phase of the targeted session within the window\n of the configured handshake timeout. This attack may be conducted against any\n TLS session using RSA signatures, but only if cipher suites using RSA key\n exchange are also enabled on the server. The limited window of opportunity,\n limitations in bandwidth, and latency make this attack significantly more\n difficult to execute.\n\n RSA key exchange is enabled by default although least prioritized if server\n order is honored. For such a cipher suite to be chosen it must also be\n supported by the client and probably the only shared cipher suite.\n\n Captured TLS sessions encrypted with ephemeral cipher suites (DHE or ECDHE)\n are not at risk for subsequent decryption due to this vulnerability.\n\n As a workaround if default cipher suite configuration was used you can\n configure the server to not use vulnerable suites with the ciphers option like\n this:\n\n `{ciphers, [Suite || Suite <- ssl:cipher_suites(), element(1,Suite) =/= rsa]}`\n\n that is your code will look somethingh like this:\n\n `ssl:listen(Port, [{ciphers, [Suite || Suite <- ssl:cipher_suites(), element(1,S) =/= rsa]} | Options]).`\n\n Thanks to Hanno Böck, Juraj Somorovsky and Craig Young for reporting this\n vulnerability.\n\n Own Id: OTP-14748","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 7.3.3 - SSL Release Notes","doc":"","ref":"notes.html#ssl-7-3-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Correct ssl:prf/5 to use the negotiated cipher suite's prf function in\n ssl:prf/5 instead of the default prf.\n\n Own Id: OTP-13546\n\n- Timeouts may have the value 0, guards have been corrected to allow this\n\n Own Id: OTP-13635\n\n- Change of internal handling of hash sign pairs as the used one enforced to\n much restrictions making some valid combinations unavailable.\n\n Own Id: OTP-13670","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 7.3.3.0.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-7-3-3-0-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- An erlang TLS server configured with cipher suites using rsa key exchange, may\n be vulnerable to an Adaptive Chosen Ciphertext attack (AKA Bleichenbacher\n attack) against RSA, which when exploited, may result in plaintext recovery of\n encrypted messages and/or a Man-in-the-middle (MiTM) attack, despite the\n attacker not having gained access to the server’s private key itself.\n [CVE-2017-1000385](https://nvd.nist.gov/vuln/detail/CVE-2017-1000385)\n\n Exploiting this vulnerability to perform plaintext recovery of encrypted\n messages will, in most practical cases, allow an attacker to read the\n plaintext only after the session has completed. Only TLS sessions established\n using RSA key exchange are vulnerable to this attack.\n\n Exploiting this vulnerability to conduct a MiTM attack requires the attacker\n to complete the initial attack, which may require thousands of server\n requests, during the handshake phase of the targeted session within the window\n of the configured handshake timeout. This attack may be conducted against any\n TLS session using RSA signatures, but only if cipher suites using RSA key\n exchange are also enabled on the server. The limited window of opportunity,\n limitations in bandwidth, and latency make this attack significantly more\n difficult to execute.\n\n RSA key exchange is enabled by default although least prioritized if server\n order is honored. For such a cipher suite to be chosen it must also be\n supported by the client and probably the only shared cipher suite.\n\n Captured TLS sessions encrypted with ephemeral cipher suites (DHE or ECDHE)\n are not at risk for subsequent decryption due to this vulnerability.\n\n As a workaround if default cipher suite configuration was used you can\n configure the server to not use vulnerable suites with the ciphers option like\n this:\n\n `{ciphers, [Suite || Suite <- ssl:cipher_suites(), element(1,Suite) =/= rsa]}`\n\n that is your code will look somethingh like this:\n\n `ssl:listen(Port, [{ciphers, [Suite || Suite <- ssl:cipher_suites(), element(1,S) =/= rsa]} | Options]).`\n\n Thanks to Hanno Böck, Juraj Somorovsky and Craig Young for reporting this\n vulnerability.\n\n Own Id: OTP-14748","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Create a little randomness in sending of session invalidation messages, to\n mitigate load when whole table is invalidated.\n\n Own Id: OTP-13490","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 7.3.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-7-3-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Correct cipher suites conversion and guard expression. Caused problems with\n GCM cipher suites and client side option to set signature_algorithms extension\n values.\n\n Own Id: OTP-13525","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 7.3.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-7-3-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Corrections to cipher suite handling using the 3 and 4 tuple format in\n addition to commit 89d7e21cf4ae988c57c8ef047bfe85127875c70c\n\n Own Id: OTP-13511","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Make values for the TLS-1.2 signature_algorithms extension configurable\n\n Own Id: OTP-13261","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 7.3 - SSL Release Notes","doc":"","ref":"notes.html#ssl-7-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Make sure there is only one poller validator at a time for validating the\n session cache.\n\n Own Id: OTP-13185\n\n- A timing related issue could cause ssl to hang, especially happened with newer\n versions of OpenSSL in combination with ECC ciphers.\n\n Own Id: OTP-13253\n\n- Work around a race condition in the TLS distribution start.\n\n Own Id: OTP-13268\n\n- Big handshake messages are now correctly fragmented in the TLS record layer.\n\n Own Id: OTP-13306\n\n- Improve portability of ECC tests in Crypto and SSL for \"exotic\" OpenSSL\n versions.\n\n Own Id: OTP-13311\n\n- Certificate extensions marked as critical are ignored when using verify_none\n\n Own Id: OTP-13377\n\n- If a certificate doesn't contain a CRL Distribution Points extension, and the\n relevant CRL is not in the cache, and the `crl_check` option is not set to\n `best_effort` , the revocation check should fail.\n\n Own Id: OTP-13378\n\n- Enable TLS distribution over IPv6\n\n Own Id: OTP-13391","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Improve error reporting for TLS distribution\n\n Own Id: OTP-13219\n\n- Include options from connect, listen and accept in\n `connection_information/1,2`\n\n Own Id: OTP-13232\n\n- Allow adding extra options for outgoing TLS distribution connections, as\n supported for plain TCP connections.\n\n Own Id: OTP-13285\n\n- Use loopback as server option in TLS-distribution module\n\n Own Id: OTP-13300\n\n- Verify certificate signature against original certificate binary.\n\n This avoids bugs due to encoding errors when re-encoding a decode certificate.\n As there exists several decode step and using of different ASN.1 specification\n this is a risk worth avoiding.\n\n Own Id: OTP-13334\n\n- Use `application:ensure_all_started/2` instead of hard-coding dependencies\n\n Own Id: OTP-13363","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 7.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-7-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Honor distribution port range options\n\n Own Id: OTP-12838\n\n- Correct supervisor specification in TLS distribution.\n\n Own Id: OTP-13134\n\n- Correct cache timeout\n\n Own Id: OTP-13141\n\n- Avoid crash and restart of ssl process when key file does not exist.\n\n Own Id: OTP-13144\n\n- Enable passing of raw socket options on the format \\{raw,_,_,\\_\\} to the\n underlying socket.\n\n Own Id: OTP-13166\n\n- Hibernation with small or a zero timeout will now work as expected\n\n Own Id: OTP-13189","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Add upper limit for session cache, configurable on ssl application level.\n\n If upper limit is reached, invalidate the current cache entries, e.i the\n session lifetime is the max time a session will be kept, but it may be\n invalidated earlier if the max limit for the table is reached. This will keep\n the ssl manager process well behaved, not exhusting memory. Invalidating the\n entries will incrementally empty the cache to make room for fresh sessions\n entries.\n\n Own Id: OTP-12392\n\n- Use new time functions to measure passed time.\n\n Own Id: OTP-12457\n\n- Improved error handling in TLS distribution\n\n Own Id: OTP-13142\n\n- Distribution over TLS now honors the nodelay distribution flag\n\n Own Id: OTP-13143","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 7.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-7-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Add DER encoded ECPrivateKey as valid input format for key option.\n\n Own Id: OTP-12974\n\n- Correct return value of default session callback module\n\n This error had the symptom that the client check for unique session would\n always fail, potentially making the client session table grow a lot and\n causing long setup times.\n\n Own Id: OTP-12980","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Add possibility to downgrade an SSL/TLS connection to a tcp connection, and\n give back the socket control to a user process.\n\n This also adds the possibility to specify a timeout to the ssl:close function.\n\n Own Id: OTP-11397\n\n- Add application setting to be able to change fatal alert shutdown timeout,\n also shorten the default timeout. The fatal alert timeout is the number of\n milliseconds between sending of a fatal alert and closing the connection.\n Waiting a little while improves the peers chances to properly receiving the\n alert so it may shutdown gracefully.\n\n Own Id: OTP-12832","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 7.0 - SSL Release Notes","doc":"","ref":"notes.html#ssl-7-0"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Ignore signature_algorithm (TLS 1.2 extension) sent to TLS 1.0 or TLS 1.1\n server\n\n Own Id: OTP-12670\n\n- Improve error handling in TLS distribution module to avoid lingering sockets.\n\n Own Id: OTP-12799 Aux Id: Tom Briden\n\n- Add option \\{client_renegotiation, boolean()\\} option to the server-side of\n the SSL application.\n\n Own Id: OTP-12815","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Add new API functions to handle CRL-verification\n\n Own Id: OTP-10362 Aux Id: kunagi-215 \\[126]\n\n- Remove default support for SSL-3.0, due to Poodle vunrability in protocol\n specification.\n\n Add padding check for TLS-1.0 to remove Poodle vunrability from TLS 1.0, also\n add the option padding_check. This option only affects TLS-1.0 connections and\n if set to false it disables the block cipher padding check to be able to\n interoperate with legacy software.\n\n Remove default support for RC4 cipher suites, as they are consider too weak.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-12390\n\n- Add support for TLS ALPN (Application-Layer Protocol Negotiation) extension.\n\n Own Id: OTP-12580\n\n- Add SNI (Server Name Indication) support for the server side.\n\n Own Id: OTP-12736","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 6.0.1.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-6-0-1-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Gracefully ignore proprietary hash_sign algorithms\n\n Own Id: OTP-12829","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 6.0.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-6-0-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Terminate gracefully when receiving bad input to premaster secret calculation\n\n Own Id: OTP-12783","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 6.0 - SSL Release Notes","doc":"","ref":"notes.html#ssl-6-0"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Exclude self-signed trusted anchor certificates from certificate prospective\n certification path according to RFC 3280.\n\n This will avoid some unnecessary certificate processing.\n\n Own Id: OTP-12449","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Separate client and server session cache internally.\n\n Avoid session table growth when client starts many connections in such a\n manner that many connections are started before session reuse is possible.\n Only save a new session in client if there is no equivalent session already\n stored.\n\n Own Id: OTP-11365\n\n- The PEM cache is now validated by a background process, instead of always\n keeping it if it is small enough and clearing it otherwise. That strategy\n required that small caches where cleared by API function if a file changes on\n disk.\n\n However export the API function to clear the cache as it may still be useful.\n\n Own Id: OTP-12391\n\n- Add padding check for TLS-1.0 to remove Poodle vulnerability from TLS 1.0,\n also add the option padding_check. This option only affects TLS-1.0\n connections and if set to false it disables the block cipher padding check to\n be able to interoperate with legacy software.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-12420\n\n- Add support for TLS_FALLBACK_SCSV used to prevent undesired TLS version\n downgrades. If used by a client that is vulnerable to the POODLE attack, and\n the server also supports TLS_FALLBACK_SCSV, the attack can be prevented.\n\n Own Id: OTP-12458","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 5.3.8 - SSL Release Notes","doc":"","ref":"notes.html#ssl-5-3-8"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Make sure the clean rule for ssh, ssl, eunit and otp_mibs actually removes\n generated files.\n\n Own Id: OTP-12200","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Change code to reflect that state data may be secret to avoid breaking\n dialyzer contracts.\n\n Own Id: OTP-12341","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 5.3.7 - SSL Release Notes","doc":"","ref":"notes.html#ssl-5-3-7"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Handle the fact that servers may send an empty SNI extension to the client.\n\n Own Id: OTP-12198","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 5.3.6 - SSL Release Notes","doc":"","ref":"notes.html#ssl-5-3-6"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Corrected handling of ECC certificates, there where several small issues with\n the handling of such certificates in the ssl and public_key application. Now\n ECC signed ECC certificates shall work and not only RSA signed ECC\n certificates.\n\n Own Id: OTP-12026\n\n- Check that the certificate chain ends with a trusted ROOT CA e.i. a\n self-signed certificate, but provide an option partial_chain to enable the\n application to define an intermediat CA as trusted.\n\n Own Id: OTP-12149","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Add decode functions for SNI (Server Name Indication)\n\n Own Id: OTP-12048","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 5.3.5 - SSL Release Notes","doc":"","ref":"notes.html#ssl-5-3-5"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- ssl:recv now returns \\{error, einval\\} if applied to a non passive socket, the\n same as gen_tcp:recv.\n\n Thanks to Danil Zagoskin for reporting this issue\n\n Own Id: OTP-11878\n\n- Corrected handling of default values for signature_algorithms extension in\n TLS-1.2 and corresponding values used in previous versions that does not\n support this extension.\n\n Thanks to Danil Zagoskin\n\n Own Id: OTP-11886\n\n- Handle socket option inheritance when pooling of accept sockets is used\n\n Own Id: OTP-11897\n\n- Make sure that the list of versions, possibly supplied in the versions option,\n is not order dependent.\n\n Thanks to Ransom Richardson for reporting this issue\n\n Own Id: OTP-11912\n\n- Reject connection if the next_protocol message is sent twice.\n\n Own Id: OTP-11926\n\n- Correct options handling when ssl:ssl_accept/3 is called with new ssl options\n after calling ssl:listen/2\n\n Own Id: OTP-11950","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Gracefully handle unknown alerts\n\n Thanks to Atul Atri for reporting this issue\n\n Own Id: OTP-11874\n\n- Gracefully ignore cipher suites sent by client not supported by the SSL/TLS\n version that the client has negotiated.\n\n Thanks to Danil Zagoskin for reporting this issue\n\n Own Id: OTP-11875\n\n- Gracefully handle structured garbage, i.e a client sends some garbage in a ssl\n record instead of a valid fragment.\n\n Thanks to Danil Zagoskin\n\n Own Id: OTP-11880\n\n- Gracefully handle invalid alerts\n\n Own Id: OTP-11890\n\n- Generalize handling of default ciphers\n\n Thanks to Andreas Schultz\n\n Own Id: OTP-11966\n\n- Make sure change cipher spec is correctly handled\n\n Own Id: OTP-11975","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 5.3.4 - SSL Release Notes","doc":"","ref":"notes.html#ssl-5-3-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Fix incorrect dialyzer spec and types, also enhance documentation.\n\n Thanks to Ayaz Tuncer.\n\n Own Id: OTP-11627\n\n- Fix possible mismatch between SSL/TLS version and default ciphers. Could\n happen when you specified SSL/TLS-version in optionlist to listen or accept.\n\n Own Id: OTP-11712\n\n- Application upgrade (appup) files are corrected for the following\n applications:\n\n `asn1, common_test, compiler, crypto, debugger, dialyzer, edoc, eldap, erl_docgen, et, eunit, gs, hipe, inets, observer, odbc, os_mon, otp_mibs, parsetools, percept, public_key, reltool, runtime_tools, ssh, syntax_tools, test_server, tools, typer, webtool, wx, xmerl`\n\n A new test utility for testing appup files is added to test_server. This is\n now used by most applications in OTP.\n\n (Thanks to Tobias Schlager)\n\n Own Id: OTP-11744","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Moved elliptic curve definition from the crypto NIF/OpenSSL into Erlang code,\n adds the RFC-5639 brainpool curves and makes TLS use them (RFC-7027).\n\n Thanks to Andreas Schultz\n\n Own Id: OTP-11578\n\n- Unicode adaptations\n\n Own Id: OTP-11620\n\n- Added option honor_cipher_order. This instructs the server to prefer its own\n cipher ordering rather than the client's and can help protect against things\n like BEAST while maintaining compatibility with clients which only support\n older ciphers.\n\n Thanks to Andrew Thompson for the implementation, and Andreas Schultz for the\n test cases.\n\n Own Id: OTP-11621\n\n- Replace boolean checking in validate_option with is_boolean guard.\n\n Thanks to Andreas Schultz.\n\n Own Id: OTP-11634\n\n- Some function specs are corrected or moved and some edoc comments are\n corrected in order to allow use of edoc. (Thanks to Pierre Fenoll)\n\n Own Id: OTP-11702\n\n- Correct clean up of certificate database when certs are inputted in pure DER\n format.The incorrect code could cause a memory leek when certs where inputted\n in DER. Thanks to Bernard Duggan for reporting this.\n\n Own Id: OTP-11733\n\n- Improved documentation of the cacertfile option\n\n Own Id: OTP-11759 Aux Id: seq12535\n\n- Avoid next protocol negotiation failure due to incorrect option format.\n\n Own Id: OTP-11760\n\n- Handle v1 CRLs, with no extensions and fixes issues with IDP (Issuing\n Distribution Point) comparison during CRL validation.\n\n Thanks to Andrew Thompson\n\n Own Id: OTP-11761\n\n- Server now ignores client ECC curves that it does not support instead of\n crashing.\n\n Thanks to Danil Zagoskin for reporting the issue and suggesting a solution.\n\n Own Id: OTP-11780\n\n- Handle SNI (Server Name Indication) alert unrecognized_name and gracefully\n deal with unexpected alerts.\n\n Thanks to Masatake Daimon for reporting this.\n\n Own Id: OTP-11815\n\n- Add possibility to specify ssl options when calling ssl:ssl_accept\n\n Own Id: OTP-11837","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 5.3.3 - SSL Release Notes","doc":"","ref":"notes.html#ssl-5-3-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Add missing validation of the server_name_indication option and test for its\n explicit use. It was not possible to set or disable the default\n server_name_indication as the validation of the option was missing.\n\n Own Id: OTP-11567\n\n- Elliptic curve selection in server mode now properly selects a curve suggested\n by the client, if possible, and the fallback alternative is changed to a more\n widely supported curve.\n\n Own Id: OTP-11575\n\n- Bug in the TLS hello extension handling caused the server to behave as it did\n not understand secure renegotiation.\n\n Own Id: OTP-11595","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 5.3.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-5-3-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Honors the clients advertised support of elliptic curves and no longer sends\n incorrect elliptic curve extension in server hello.\n\n Own Id: OTP-11370\n\n- Fix initialization of DTLS fragment reassembler, in previously contributed\n code, for future support of DTLS . Thanks to Andreas Schultz.\n\n Own Id: OTP-11376\n\n- Corrected type error in client_preferred_next_protocols documentation. Thanks\n to Julien Barbot.\n\n Own Id: OTP-11457","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- TLS code has been refactored to prepare for future DTLS support. Also some\n DTLS code is in place but not yet runnable, some of it contributed by Andreas\n Schultz and some of it written by the OTP team. Thanks to to Andreas for his\n participation.\n\n Own Id: OTP-11292\n\n- Remove extraneous dev debug code left in the close function. Thanks to Ken\n Key.\n\n Own Id: OTP-11447\n\n- Add SSL Server Name Indication (SNI) client support. Thanks to Julien Barbot.\n\n Own Id: OTP-11460","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 5.3.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-5-3-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Setopts during renegotiation caused the renegotiation to be unsuccessful.\n\n If calling setopts during a renegotiation the FSM state might change during\n the handling of the setopts messages, this is now handled correctly.\n\n Own Id: OTP-11228\n\n- Now handles signature_algorithm field in digitally_signed properly with proper\n defaults. Prior to this change some elliptic curve cipher suites could fail\n reporting the error \"bad certificate\".\n\n Own Id: OTP-11229\n\n- The code emulating the inet header option was changed in the belief that it\n made it inet compatible. However the testing is a bit hairy as the inet option\n is actually broken, now the tests are corrected and the header option should\n work in the same broken way as inet again, preferably use the bitsyntax\n instead.\n\n Own Id: OTP-11230","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Make the ssl manager name for erlang distribution over SSL/TLS relative to the\n module name of the ssl_manager.\n\n This can be beneficial when making tools that rename modules for internal\n processing in the tool.\n\n Own Id: OTP-11255\n\n- Add documentation regarding log_alert option.\n\n Own Id: OTP-11271","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 5.3 - SSL Release Notes","doc":"","ref":"notes.html#ssl-5-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Honor the versions option to ssl:connect and ssl:listen.\n\n Own Id: OTP-10905\n\n- Next protocol negotiation with reused sessions will now succeed\n\n Own Id: OTP-10909","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Add support for PSK (Pre Shared Key) and SRP (Secure Remote Password) cipher\n suites, thanks to Andreas Schultz.\n\n Own Id: OTP-10450 Aux Id: kunagi-269 \\[180]\n\n- Fix SSL Next Protocol Negotiation documentation. Thanks to Julien Barbot.\n\n Own Id: OTP-10955\n\n- Fix ssl_connection to support reading proxy/chain certificates. Thanks to\n Valentin Kuznetsov.\n\n Own Id: OTP-10980\n\n- Integrate elliptic curve contribution from Andreas Schultz\n\n In order to be able to support elliptic curve cipher suites in SSL/TLS,\n additions to handle elliptic curve infrastructure has been added to public_key\n and crypto.\n\n This also has resulted in a rewrite of the crypto API to gain consistency and\n remove unnecessary overhead. All OTP applications using crypto has been\n updated to use the new API.\n\n Impact: Elliptic curve cryptography (ECC) offers equivalent security with\n smaller key sizes than other public key algorithms. Smaller key sizes result\n in savings for power, memory, bandwidth, and computational cost that make ECC\n especially attractive for constrained environments.\n\n Own Id: OTP-11009","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 5.2.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-5-2-1"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Transport callback handling is changed so that gen_tcp is treated as a special\n case where inet will be called directly for functions such as setopts, as\n gen_tcp does not have its own setopts. This will enable users to use the\n transport callback for other customizations such as websockets.\n\n Own Id: OTP-10847\n\n- Follow up to OTP-10451 solved in ssl-5.2 R16A. Make sure format_error return\n good strings. Replace confusing legacy atoms with more descriptive atoms.\n\n Own Id: OTP-10864","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 5.1.2.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-5-1-2-1"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Make log_alert configurable as option in ssl, SSLLogLevel added as option to\n inets conf file\n\n Own Id: OTP-11259","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 5.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-5-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- SSL: TLS 1.2, advertise sha224 support, thanks to Andreas Schultz.\n\n Own Id: OTP-10586\n\n- If an ssl server is restarted with new options and a client tries to reuse a\n session the server must make sure that it complies to the new options before\n agreeing to reuse it.\n\n Own Id: OTP-10595\n\n- Now handles cleaning of CA-certificate database correctly so that there will\n be no memory leek, bug was introduced in ssl- 5.1 when changing implementation\n to increase parallel execution.\n\n Impact: Improved memory usage, especially if you have many different\n certificates and upgrade tcp-connections to TLS-connections.\n\n Own Id: OTP-10710","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Support Next Protocol Negotiation in TLS, thanks to Ben Murphy for the\n contribution.\n\n Impact: Could give performance benefit if used as it saves a round trip.\n\n Own Id: OTP-10361 Aux Id: kunagi-214 \\[125]\n\n- TLS 1.2 will now be the default TLS version if sufficient crypto support is\n available otherwise TLS 1.1 will be default.\n\n Impact: A default TLS connection will have higher security and hence it may be\n perceived as slower then before.\n\n Own Id: OTP-10425 Aux Id: kunagi-275 \\[186]\n\n- It is now possible to call controlling_process on a listen socket, same as in\n gen_tcp.\n\n Own Id: OTP-10447\n\n- Remove filter mechanisms that made error messages backwards compatible with\n old ssl but hid information about what actually happened.\n\n This does not break the documented API however other reason terms may be\n returned, so code that matches on the reason part of \\{error, Reason\\} may\n fail.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-10451 Aux Id: kunagi-270 \\[181]\n\n- Added missing dependencies to Makefile\n\n Own Id: OTP-10594\n\n- Removed deprecated function ssl:pid/0, it has been pointless since R14 but has\n been keep for backwards compatibility.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-10613 Aux Id: kunagi-331 \\[242]\n\n- Refactor to simplify addition of key exchange methods, thanks to Andreas\n Schultz.\n\n Own Id: OTP-10709","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 5.1.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-5-1-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- ssl:ssl_accept/2 timeout is no longer ignored\n\n Own Id: OTP-10600","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 5.1.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-5-1-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- ssl:recv/3 could \"loose\" data when the timeout occurs. If the timeout in\n ssl:connect or ssl:ssl_accept expired the ssl connection process was not\n terminated as it should, this due to gen_fsm:send_all_state_event timeout is a\n client side time out. These timouts are now handled by the gen_fsm-procss\n instead.\n\n Own Id: OTP-10569","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Better termination handling that avoids hanging.\n\n Own Id: OTP-10574","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 5.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-5-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Sometimes the client process could receive an extra \\{error, closed\\} message\n after ssl:recv had returned \\{error, closed\\}.\n\n Own Id: OTP-10118\n\n- ssl v3 alert number 41 (no_certificate_RESERVED) is now recognized\n\n Own Id: OTP-10196","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Experimental support for TLS 1.1 is now available, will be officially\n supported from OTP-R16. Thanks to Andreas Schultz for implementing the first\n version.\n\n Own Id: OTP-8871\n\n- Experimental support for TLS 1.2 is now available, will be officially\n supported from OTP-R16. Thanks to Andreas Schultz for implementing the first\n version.\n\n Own Id: OTP-8872\n\n- Removed some bottlenecks increasing the applications parallelism especially\n for the client side.\n\n Own Id: OTP-10113\n\n- Workaround for handling certificates that wrongly encode X509countryname in\n utf-8 when the actual value is a valid ASCCI value of length 2. Such\n certificates are accepted by many browsers such as Chrome and Fierfox so for\n interoperability reasons we will too.\n\n Own Id: OTP-10222","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 5.0.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-5-0-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Robustness and improvement to distribution over SSL\n\n Fix a bug where ssl_tls_dist_proxy would crash at caller timeout. Fix a bug\n where a timeout from the SSL layer would block the distribution indefinitely.\n Run the proxy exclusively on the loopback interface. (Thanks to Paul Guyot)\n\n Own Id: OTP-9915\n\n- Fix setup loop of SSL TLS dist proxy\n\n Fix potential leak of processes waiting indefinitely for data from closed\n sockets during socket setup phase. (Thanks to Paul Guyot)\n\n Own Id: OTP-9916\n\n- Correct spelling of registered (Thanks to Richard Carlsson)\n\n Own Id: OTP-9925\n\n- Added TLS PRF function to the SSL API for generation of additional key\n material from a TLS session. (Thanks to Andreas Schultz)\n\n Own Id: OTP-10024","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 5.0 - SSL Release Notes","doc":"","ref":"notes.html#ssl-5-0"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Invalidation handling of sessions could cause the time_stamp field in the\n session record to be set to undefined crashing the session clean up process.\n This did not affect the connections but would result in that the session table\n would grow.\n\n Own Id: OTP-9696 Aux Id: seq11947\n\n- Changed code to use ets:foldl and throw instead of ets:next traversal,\n avoiding the need to explicitly call ets:safe_fixtable. It was possible to get\n a badarg-crash under special circumstances.\n\n Own Id: OTP-9703 Aux Id: seq11947\n\n- Send ssl_closed notification to active ssl user when a tcp error occurs.\n\n Own Id: OTP-9734 Aux Id: seq11946\n\n- If a passive receive was ongoing during a renegotiation the process evaluating\n ssl:recv could be left hanging for ever.\n\n Own Id: OTP-9744","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Support for the old ssl implementation is dropped and the code is removed.\n\n Own Id: OTP-7048\n\n- The erlang distribution can now be run over the new ssl implementation. All\n options can currently not be set but it is enough to replace to old ssl\n implementation.\n\n Own Id: OTP-7053\n\n- public_key, ssl and crypto now supports PKCS-8\n\n Own Id: OTP-9312\n\n- Implements a CBC timing attack counter measure. Thanks to Andreas Schultz for\n providing the patch.\n\n Own Id: OTP-9683\n\n- Mitigates an SSL/TLS Computational DoS attack by disallowing the client to\n renegotiate many times in a row in a short time interval, thanks to Tuncer\n Ayaz for alerting us about this.\n\n Own Id: OTP-9739\n\n- Implements the 1/n-1 splitting countermeasure to the Rizzo Duong BEAST attack,\n affects SSL 3.0 and TLS 1.0. Thanks to Tuncer Ayaz for alerting us about this.\n\n Own Id: OTP-9750","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 4.1.6 - SSL Release Notes","doc":"","ref":"notes.html#ssl-4-1-6"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- replace \"a ssl\" with \"an ssl\" reindent pkix_path_validation/3 Trivial\n documentation fixes (Thanks to Christian von Roques )\n\n Own Id: OTP-9464","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Adds function clause to avoid denial of service attack. Thanks to Vinod for\n reporting this vulnerability.\n\n Own Id: OTP-9364\n\n- Error handling code now takes care of inet:getopts/2 and inets:setopts/2\n crashes. Thanks to Richard Jones for reporting this.\n\n Own Id: OTP-9382\n\n- Support explicit use of packet option httph and httph_bin\n\n Own Id: OTP-9461\n\n- Decoding of hello extensions could fail to come to the correct conclusion due\n to an error in a binary match pattern. Thanks to Ben Murphy.\n\n Own Id: OTP-9589","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 4.1.5 - SSL Release Notes","doc":"","ref":"notes.html#ssl-4-1-5"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Calling gen_tcp:connect with option \\{ip, \\{127,0,0,1\\}\\} results in an exit\n with reason badarg. Neither SSL nor INETS This was not caught, resulting in\n crashes with incomprehensible reasons.\n\n Own Id: OTP-9289 Aux Id: seq11845","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 4.1.3 - SSL Release Notes","doc":"","ref":"notes.html#ssl-4-1-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Fixed error in cache-handling fix from ssl-4.1.2\n\n Own Id: OTP-9018 Aux Id: seq11739\n\n- Verification of a critical extended_key_usage-extension corrected\n\n Own Id: OTP-9029 Aux Id: seq11541","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 4.1.2 - SSL Release Notes","doc":"","ref":"notes.html#ssl-4-1-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- The ssl application caches certificate files, it will now invalidate cache\n entries if the diskfile is changed.\n\n Own Id: OTP-8965 Aux Id: seq11739\n\n- Now runs the terminate function before returning from the call made by\n ssl:close/1, as before the caller of ssl:close/1 could get problems with the\n reuseaddr option.\n\n Own Id: OTP-8992","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"SSL 4.1.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-4-1-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- Correct handling of client certificate verify message When checking the client\n certificate verify message the server used the wrong algorithm identifier to\n determine the signing algorithm, causing a function clause error in the\n public_key application when the key-exchange algorithm and the public key\n algorithm of the client certificate happen to differ.\n\n Own Id: OTP-8897","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- For testing purposes ssl now also support some anonymous cipher suites when\n explicitly configured to do so.\n\n Own Id: OTP-8870\n\n- Sends an error alert instead of crashing if a crypto function for the selected\n cipher suite fails.\n\n Own Id: OTP-8930 Aux Id: seq11720","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 4.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-4-1"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Updated ssl to ignore CA certs that violate the asn1-spec for a certificate,\n and updated public key asn1 spec to handle inherited DSS-params.\n\n Own Id: OTP-7884\n\n- Changed ssl implementation to retain backwards compatibility for old option\n \\{verify, 0\\} that shall be equivalent to \\{verify, verify_none\\}, also\n separate the cases unknown ca and selfsigned peer cert, and restored return\n value of deprecated function public_key:pem_to_der/1.\n\n Own Id: OTP-8858\n\n- Changed the verify fun so that it differentiate between the peer certificate\n and CA certificates by using valid_peer or valid as the second argument to the\n verify fun. It may not always be trivial or even possible to know when the\n peer certificate is reached otherwise.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8873","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 4.0.1 - SSL Release Notes","doc":"","ref":"notes.html#ssl-4-0-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - SSL Release Notes","doc":"- The server now verifies the client certificate verify message correctly,\n instead of causing a case-clause.\n\n Own Id: OTP-8721\n\n- The client hello message now always include ALL available cipher suites (or\n those specified by the ciphers option). Previous implementation would filter\n them based on the client certificate key usage extension (such filtering only\n makes sense for the server certificate).\n\n Own Id: OTP-8772\n\n- Fixed handling of the option \\{mode, list\\} that was broken for some packet\n types for instance line.\n\n Own Id: OTP-8785\n\n- Empty packets were not delivered to the client.\n\n Own Id: OTP-8790\n\n- Building in a source tree without prebuilt platform independent build results\n failed on the SSL examples when:\n\n - cross building. This has been solved by not building the SSL examples during\n a cross build.\n - building on Windows.\n\n Own Id: OTP-8791\n\n- Fixed a handshake error which occurred on some ssl implementations.\n\n Own Id: OTP-8793","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- Revise the public_key API - Cleaned up and documented the public_key API to\n make it useful for general use, also changed ssl to use the new API.\n\n Own Id: OTP-8722\n\n- Added support for inputing certificates and keys directly in DER format these\n options will override the pem-file options if specified.\n\n Own Id: OTP-8723\n\n- To gain interoperability ssl will not check for padding errors when using TLS\n 1.0. It is first in TLS 1.1 that checking the padding is an requirement.\n\n Own Id: OTP-8740\n\n- Changed the semantics of the verify_fun option in the ssl-application so that\n it takes care of both application handling of path validation errors and\n verification of application specific extensions. This means that it is now\n possible for the server application in verify_peer mode to handle path\n validation errors. This change moved some functionality earlier in ssl to the\n public_key application.\n\n Own Id: OTP-8770\n\n- Added the functionality so that the verification fun will be called when a\n certificate is considered valid by the path validation to allow access to each\n certificate in the path to the user application. Also try to verify\n subject-AltName, if unable to verify it let the application verify it.\n\n Own Id: OTP-8825","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"SSL 4.0 - SSL Release Notes","doc":"","ref":"notes.html#ssl-4-0"},{"type":"extras","title":"Improvements and New Features - SSL Release Notes","doc":"- New ssl now support client/server-certificates signed by dsa keys.\n\n Own Id: OTP-8587\n\n- Ssl has now switched default implementation and removed deprecated certificate\n handling. All certificate handling is done by the public_key application.\n\n Own Id: OTP-8695","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"TLS/DTLS Protocol Overview","doc":"\n\n# TLS/DTLS Protocol Overview","ref":"ssl_protocol.html"},{"type":"extras","title":"Purpose - TLS/DTLS Protocol Overview","doc":"Transport Layer Security (TLS) and its predecessor, the Secure Sockets Layer\n(SSL), are cryptographic protocols designed to provide communications security\nover a computer network. The protocols use X.509 certificates and hence public\nkey (asymmetric) cryptography to authenticate the counterpart with whom they\ncommunicate, and to exchange a symmetric key for payload encryption. The\nprotocol provides data/message confidentiality (encryption), integrity (through\nmessage authentication code checks) and host verification (through certificate\npath validation). DTLS (Datagram Transport Layer Security) that is based on TLS\nbut datagram oriented instead of stream oriented.\n\n# Erlang Support\n\nThe Erlang SSL application implements the TLS/DTLS protocol for the currently\nsupported versions, see the `m:ssl` manual page.\n\nBy default TLS is run over the TCP/IP protocol even though you can plug in any\nother reliable transport protocol with the same Application Programming\nInterface (API) as the `gen_tcp` module in Kernel. DTLS is by default run over\nUDP/IP, which means that application data has no delivery guarantees. Other\ntransports, such as SCTP, may be supported in future releases.\n\nIf a client and a server wants to use an upgrade mechanism, such as defined by\nRFC 2817, to upgrade a regular TCP/IP connection to a TLS connection, this is\nsupported by the Erlang SSL application API. This can be useful for, for\nexample, supporting HTTP and HTTPS on the same port and implementing virtual\nhosting. Note this is a TLS feature only.","ref":"ssl_protocol.html#purpose"},{"type":"extras","title":"Security Overview - TLS/DTLS Protocol Overview","doc":"To achieve authentication and privacy, the client and server perform a TLS/DTLS\nhandshake procedure before transmitting or receiving any data. During the\nhandshake, they agree on a protocol version and cryptographic algorithms,\ngenerate shared secrets using public key cryptographies, and optionally\nauthenticate each other with digital certificates.","ref":"ssl_protocol.html#security-overview"},{"type":"extras","title":"Data Privacy and Integrity - TLS/DTLS Protocol Overview","doc":"A _symmetric key_ algorithm has one key only. The key is used for both\nencryption and decryption. These algorithms are fast, compared to public key\nalgorithms (using two keys, one public and one private) and are therefore\ntypically used for encrypting bulk data.\n\nThe keys for the symmetric encryption are generated uniquely for each connection\nand are based on a secret negotiated in the TLS/DTLS handshake.\n\nThe TLS/DTLS handshake protocol and data transfer is run on top of the TLS/DTLS\nRecord Protocol, which uses a keyed-hash Message Authenticity Code (MAC), or a\nHash-based MAC (HMAC), to protect the message data integrity. From the TLS RFC:\n\"A Message Authentication Code is a one-way hash computed from a message and\nsome secret data. It is difficult to forge without knowing the secret data. Its\npurpose is to detect if the message has been altered.\"","ref":"ssl_protocol.html#data-privacy-and-integrity"},{"type":"extras","title":"Digital Certificates - TLS/DTLS Protocol Overview","doc":"A certificate is similar to a driver's license, or a passport. The holder of the\ncertificate is called the _subject_. The certificate is signed with the private\nkey of the issuer of the certificate. A chain of trust is built by having the\nissuer in its turn being certified by another certificate, and so on, until you\nreach the so called root certificate, which is self-signed, that is, issued by\nitself.\n\nCertificates are issued by Certification Authorities (CAs) only. A handful of\ntop CAs in the world issue root certificates. You can examine several of these\ncertificates by clicking through the menus of your web browser.","ref":"ssl_protocol.html#digital-certificates"},{"type":"extras","title":"Peer Authentication - TLS/DTLS Protocol Overview","doc":"Authentication of the peer is done by public key path validation as defined in\nRFC 3280. This means basically the following:\n\n- Each certificate in the certificate chain is issued by the previous one.\n- The certificates attributes are valid.\n- The root certificate is a trusted certificate that is present in the trusted\n certificate database kept by the peer.\n\nThe server always sends a certificate chain as part of the TLS handshake, but\nthe client only sends one if requested by the server. If the client does not\nhave an appropriate certificate, it can send an \"empty\" certificate to the\nserver.\n\nThe client can choose to accept some path evaluation errors, for example, a web\nbrowser can ask the user whether to accept an unknown CA root certificate. The\nserver, if it requests a certificate, does however not accept any path\nvalidation errors. It is configurable if the server is to accept or reject an\n\"empty\" certificate as response to a certificate request.","ref":"ssl_protocol.html#peer-authentication"},{"type":"extras","title":"TLS Sessions - Prior to TLS-1.3 - TLS/DTLS Protocol Overview","doc":"From the TLS RFC: \"A TLS session is an association between a client and a\nserver. Sessions are created by the handshake protocol. Sessions define a set of\ncryptographic security parameters, which can be shared among multiple\nconnections. Sessions are used to avoid the expensive negotiation of new\nsecurity parameters for each connection.\"\n\nSession data is by default kept by the SSL application in a memory storage,\nhence session data is lost at application restart or takeover. Users can define\ntheir own callback module to handle session data storage if persistent data\nstorage is required. Session data is also invalidated when session database\nexceeds its limit or 24 hours after being saved (RFC max lifetime\nrecommendation). The amount of time the session data is to be saved can be\nconfigured.\n\nBy default the TLS/DTLS clients try to reuse an available session and by default\nthe TLS/DTLS servers agree to reuse sessions when clients ask for it. See also\n[Session Reuse Prior to TLS-1.3](using_ssl.md#session-reuse-prior-to-tls-1-3)","ref":"ssl_protocol.html#tls-sessions-prior-to-tls-1-3"},{"type":"extras","title":"TLS-1.3 session tickets - TLS/DTLS Protocol Overview","doc":"In TLS 1.3 the session reuse is replaced by a new session tickets mechanism\nbased on the prior to shared key concept. This mechanism also obsoletes the session\ntickets from RFC5077, not implemented by this application. See also\n[Session Tickets and Session Resumption in TLS-1.3](using_ssl.md#session-tickets-and-session-resumption-in-tls-1-3)","ref":"ssl_protocol.html#tls-1-3-session-tickets"},{"type":"extras","title":"Examples","doc":"\n# Examples\n\nTo see relevant version information for ssl, call `ssl:versions/0` .\n\nTo see all supported cipher suites, call\n[`ssl:cipher_suites(all, 'tlsv1.3')`](`ssl:cipher_suites/2`). The available\ncipher suites for a connection depend on the TLS version and prior to TLS-1.3 also on\nthe certificate. To see the default cipher suite list change `all` to `default`.\nNote that TLS 1.3 and previous versions do not have any cipher suites in common,\nfor listing cipher suites for a specific version use\n[`ssl:cipher_suites(exclusive, 'tlsv1.3')`](`ssl:cipher_suites/2`). Specific\ncipher suites that you want your connection to use can also be specified.\nDefault is to use the strongest available.\n\n\n> #### Warning {: .warning }\n>Enabling cipher suites using RSA as a key exchange algorithm is\n>strongly discouraged (only available prior to TLS-1.3). For some\n>configurations software preventions may exist, and can make them usable if they work,\n>but relying on them to work is risky and there are many more reliable\n>cipher suites that can be used instead.\n\nThe following sections shows small examples of how to set up client/server\nconnections using the Erlang shell. The returned value of the `sslsocket` is\nabbreviated with `[...]` as it can be fairly large and is opaque to the user\nexcept for the purpose of pattern matching.\n\n> #### Note {: .info }\n>\n> Note that client certificate verification is optional for the server and needs\n> additional conguration on both sides to work. The Certificate and keys, in the\n> examples, are provided using the `t:ssl:cert_key_conf/0` supplied in the `certs_keys`\n> introduced in OTP 25.","ref":"using_ssl.html"},{"type":"extras","title":"Basic Client - Examples","doc":"```erlang\n 1 > ssl:start(), ssl:connect(\"google.com\", 443, [{verify, verify_peer},\n {cacerts, public_key:cacerts_get()}]).\n {ok,{sslsocket, [...]}}\n```","ref":"using_ssl.html#basic-client"},{"type":"extras","title":"Basic Connection - Examples","doc":"_Step 1:_ Start the server side:\n\n```erlang\n1 server> ssl:start().\nok\n```\n\n_Step 2:_ with alternative certificates, in this example the EDDSA certificate\nwill be preferred if TLS-1.3 is negotiated and the RSA certificate will always\nbe used for TLS-1.2 as it does not support the EDDSA algorithm:\n\n```erlang\n2 server> {ok, ListenSocket} =\nssl:listen(9999, [{certs_keys, [#{certfile => \"eddsacert.pem\",\n keyfile => \"eddsakey.pem\"},\n #{certfile => \"rsacert.pem\",\n keyfile => \"rsakey.pem\",\n password => \"foobar\"}\n ]},{reuseaddr, true}]).\n{ok,{sslsocket, [...]}}\n```\n\n_Step 3:_ Do a transport accept on the TLS listen socket:\n\n```erlang\n3 server> {ok, TLSTransportSocket} = ssl:transport_accept(ListenSocket).\n{ok,{sslsocket, [...]}}\n```\n\n> #### Note {: .info }\n>\n> `ssl:transport_accept/1` and `ssl:handshake/2` are separate functions so that the\n> handshake part can be called in a new Erlang process dedicated to handling the\n> connection\n\n_Step 4:_ Start the client side:\n\n```erlang\n1 client> ssl:start().\nok\n```\n\nBe sure to configure trusted certificates to use for server certificate\nverification.\n\n```erlang\n2 client> {ok, Socket} = ssl:connect(\"localhost\", 9999,\n [{verify, verify_peer},\n {cacertfile, \"cacerts.pem\"}, {active, once}], infinity).\n{ok,{sslsocket, [...]}}\n```\n\n_Step 5:_ Do the TLS handshake:\n\n```erlang\n4 server> {ok, Socket} = ssl:handshake(TLSTransportSocket).\n{ok,{sslsocket, [...]}}\n```\n\n> #### Note {: .info }\n>\n> A real server should use `ssl:handshake/2`, which accepts a timeout, to avoid DoS\n> attacks. In the example the timeout defaults to `infinity`.\n\n_Step 6:_ Send a message over TLS:\n\n```erlang\n5 server> ssl:send(Socket, \"foo\").\nok\n```\n\n_Step 7:_ Flush the shell message queue to see that the message sent on the\nserver side is recived by the client side:\n\n```erlang\n3 client> flush().\nShell got {ssl,{sslsocket,[...]},\"foo\"}\nok\n```","ref":"using_ssl.html#basic-connection"},{"type":"extras","title":"Upgrade Example - TLS only - Examples","doc":"Upgrading a a TCP/IP connection to a TLS connections is mostly used when there\nis a desire have unencrypted communication first and then later secure the\ncommunication channel by using TLS. Note that the client and server need to\nagree to do the upgrade in the protocol doing the communication. This is concept\nis often referenced as `STARTLS` and used in many protocols such as `SMTP`,\n`FTPS` and `HTTPS` via a proxy.\n\n> #### Warning {: .warning }\n>\n> Maximum security recommendations are however moving away from such solutions.\n\nTo upgrade to a TLS connection:\n\n_Step 1:_ Start the server side:\n\n```erlang\n1 server> ssl:start().\n ok\n```\n\n_Step 2:_ Create a normal TCP listen socket and ensure `active` is set to\n`false` and not set to any active mode otherwise TLS handshake messages can be\ndelivered to the wrong process.\n\n```erlang\n2 server> {ok, ListenSocket} = gen_tcp:listen(9999, [{reuseaddr, true},\n {active, false}]).\n {ok, #Port<0.475>}\n```\n\n_Step 3:_ Accept client connection:\n\n```erlang\n3 server> {ok, Socket} = gen_tcp:accept(ListenSocket).\n {ok, #Port<0.476>}\n```\n\n_Step 4:_ Start the client side:\n\n```erlang\n1 client> ssl:start().\n ok\n```\n\n```erlang\n2 client> {ok, Socket} = gen_tcp:connect(\"localhost\", 9999, [], infinity).\n```\n\n_Step 5:_ Do the TLS handshake:\n\n```erlang\n4 server> {ok, TLSSocket} = ssl:handshake(Socket, [{verify, verify_peer},\n {fail_if_no_peer_cert, true},\n {cacertfile, \"cacerts.pem\"},\n {certs_keys, [#{certfile => \"cert.pem\", keyfile => \"key.pem\"}]}]).\n {ok,{sslsocket,[...]}}\n```\n\n_Step 6:_ Upgrade to a TLS connection. The client and server must agree upon the\nupgrade. The server must be prepared to be a TLS server before the client can do\na successful connect.\n\n```erlang\n3 client>{ok, TLSSocket} = ssl:connect(Socket, [{verify, verify_peer},\n {cacertfile, \"cacerts.pem\"},\n {certs_keys, [#{certfile => \"cert.pem\", keyfile => \"key.pem\"}]}], infinity).\n{ok,{sslsocket,[...]}}\n```\n\n_Step 7:_ Send a message over TLS:\n\n```erlang\n4 client> ssl:send(TLSSocket, \"foo\").\n ok\n```\n\n_Step 8:_ Set `active once` on the TLS socket:\n\n```erlang\n5 server> ssl:setopts(TLSSocket, [{active, once}]).\n ok\n```\n\n_Step 9:_ Flush the shell message queue to see that the message sent on the\nclient side is recived by the server side:\n\n```erlang\n5 server> flush().\n Shell got {ssl,{sslsocket,[...]},\"foo\"}\n ok\n```","ref":"using_ssl.html#upgrade-example-tls-only"},{"type":"extras","title":"Customizing cipher suites - Examples","doc":"Fetch default cipher suite list for a TLS/DTLS version. Change default to all to\nget all possible cipher suites.\n\n```erlang\n1> Default = ssl:cipher_suites(default, 'tlsv1.2').\n [#{cipher => aes_256_gcm,key_exchange => ecdhe_ecdsa,\n mac => aead,prf => sha384}, ....]\n```\n\nIn OTP 20 it is desirable to remove all cipher suites that uses rsa key exchange\n(removed from default in 21)\n\n```erlang\n2> NoRSA =\n ssl:filter_cipher_suites(Default,\n [{key_exchange, fun(rsa) -> false;\n (_) -> true\n end}]).\n [...]\n```\n\nPick just a few suites\n\n```erlang\n 3> Suites =\n ssl:filter_cipher_suites(Default,\n [{key_exchange, fun(ecdh_ecdsa) -> true;\n (_) -> false\n end},\n {cipher, fun(aes_128_cbc) -> true;\n (_) ->false\n end}]).\n\n[#{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,\n mac => sha256,prf => sha256},\n #{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,mac => sha,\n prf => default_prf}]\n```\n\nMake some particular suites the most preferred, or least preferred by changing\nprepend to append.\n\n```erlang\n 4>ssl:prepend_cipher_suites(Suites, Default).\n [#{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,\n mac => sha256,prf => sha256},\n #{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,mac => sha,\n prf => default_prf},\n #{cipher => aes_256_cbc,key_exchange => ecdhe_ecdsa,\n mac => sha384,prf => sha384}, ...]\n```","ref":"using_ssl.html#customizing-cipher-suites"},{"type":"extras","title":"Customizing signature algorithms(TLS-1.2)/schemes(TLS-1.3) - Examples","doc":"Starting from TLS-1.2 signature algorithms (called signature schemes in TLS-1.3)\nis something that can be negotiated and hence also configured. These\nalgorithms/schemes will be used for digital signatures in protocol messages and\nin certificates.\n\n> #### Note {: .info }\n>\n> TLS-1.3 schemes have atom names whereas TLS-1.2 configuration is two element\n> tuples composed by one hash algorithm and one signature algorithm. When both\n> versions are supported the configuration can be a mix of these as both\n> versions might be negotiated. All `rsa_pss` based schemes are back ported to\n> TLS-1.2 and can be used also in a TLS-1.2 configuration. In TLS-1.2 the\n> signature algorithms chosen by the server will also be affected by the chiper\n> suite that is chosen, which is not the case in TLS-1.3.\n\nUsing the function `ssl:signature_algs/2` will let you inspect different aspects\nof possible configurations for your system. For example if TLS-1.3 and TLS-1.2\nis supported the default signature_algorithm list in OTP-26 and cryptolib from\nOpenSSL 3.0.2 would look like:\n\n```erlang\n 1> ssl:signature_algs(default, 'tlsv1.3').\n %% TLS-1.3 schemes\n [eddsa_ed25519,eddsa_ed448,ecdsa_secp521r1_sha512,\n ecdsa_secp384r1_sha384,ecdsa_secp256r1_sha256,\n rsa_pss_pss_sha512,rsa_pss_pss_sha384,rsa_pss_pss_sha256,\n rsa_pss_rsae_sha512,rsa_pss_rsae_sha384,rsa_pss_rsae_sha256,\n %% Legacy schemes only valid for certificate signatures in TLS-1.3\n %% (would have a tuple name in TLS-1.2 only configuration)\n rsa_pkcs1_sha512,rsa_pkcs1_sha384,rsa_pkcs1_sha256\n %% TLS 1.2 algorithms\n {sha512,ecdsa},\n {sha384,ecdsa},\n {sha256,ecdsa}]\n```\n\nIf you want to add support for non default supported algorithms you should\nappend them to the default list as the configuration is in prefered order,\nsomething like this:\n\n```erlang\n MySignatureAlgs = ssl:signature_algs(default, 'tlsv1.3') ++ [{sha, rsa}, {sha, dsa}],\n ssl:connect(Host,Port,[{signature_algs, MySignatureAlgs,...]}),\n ...\n```\n\nSee also `ssl:signature_algs/2` and [sign_algo()](`t:ssl:signature_algs/0`)","ref":"using_ssl.html#customizing-signature-algorithms-tls-1-2-schemes-tls-1-3"},{"type":"extras","title":"Using an Engine Stored Key - Examples","doc":"Erlang ssl application is able to use private keys provided by OpenSSL engines\nusing the following mechanism:\n\n```erlang\n1> ssl:start().\nok\n```\n\nLoad a crypto engine, should be done once per engine used. For example\ndynamically load the engine called `MyEngine`:\n\n```erlang\n2> {ok, EngineRef} =\ncrypto:engine_load(<<\"dynamic\">>,\n[{<<\"SO_PATH\">>, \"/tmp/user/engines/MyEngine\"},<<\"LOAD\">>],\n[]).\n{ok,#Ref<0.2399045421.3028942852.173962>}\n```\n\nCreate a map with the engine information and the algorithm used by the engine:\n\n```erlang\n3> PrivKey =\n #{algorithm => rsa,\n engine => EngineRef,\n key_id => \"id of the private key in Engine\"}.\n```\n\nUse the map in the ssl key option:\n\n```erlang\n4> {ok, SSLSocket} =\n ssl:connect(\"localhost\", 9999,\n [{cacertfile, \"cacerts.pem\"},\n {certs_keys, [#{certfile => \"cert.pem\", key => PrivKey}]}\n ], infinity).\n\n```\n\nSee also [crypto documentation](`e:crypto:engine_load.md#engine_load`)","ref":"using_ssl.html#using-an-engine-stored-key"},{"type":"extras","title":"NSS keylog - Examples","doc":"The NSS keylog debug feature can be used by authorized users to for instance\nenable wireshark to decrypt TLS packets.\n\n_Server (with NSS key logging)_\n\n```erlang\n server() ->\n application:load(ssl),\n {ok, _} = application:ensure_all_started(ssl),\n Port = 11029,\n LOpts = [{certs_keys, [#{certfile => \"cert.pem\", keyfile => \"key.pem\"}]},\n {reuseaddr, true},\n {versions, ['tlsv1.2','tlsv1.3']},\n {keep_secrets, true} %% Enable NSS key log (debug option)\n ],\n {ok, LSock} = ssl:listen(Port, LOpts),\n {ok, ASock} = ssl:transport_accept(LSock),\n {ok, CSock} = ssl:handshake(ASock).\n```\n\n_Exporting the secrets_\n\n```erlang\n {ok, [{keylog, KeylogItems}]} = ssl:connection_information(CSock, [keylog]).\n file:write_file(\"key.log\", [[KeylogItem,$\\n] || KeylogItem <- KeylogItems]).\n```","ref":"using_ssl.html#nss-keylog"},{"type":"extras","title":"Session Reuse Prior to TLS 1.3 - Examples","doc":"Clients can request to reuse a session established by a previous full handshake\nbetween that client and server by sending the id of the session in the initial\nhandshake message. The server may or may not agree to reuse it. If agreed the\nserver will send back the id and if not it will send a new id. The ssl\napplication has several options for handling session reuse.\n\nOn the client side the ssl application will save session data to try to automate\nsession reuse on behalf of the client processes on the Erlang node. Note that\nonly verified sessions will be saved for security reasons, that is session\nresumption relies on the certificate validation to have been run in the original\nhandshake. To minimize memory consumption only unique sessions will be saved\nunless the special `save` value is specified for the following option\n`{reuse_sessions, boolean() | save}` in which case a full handshake will be\nperformed and that specific session will have been saved before the handshake\nreturns. The session id and even an opaque binary containing the session data\ncan be retrieved using `ssl:connection_information/1` function. A saved session\n(guaranteed by the save option) can be explicitly reused using\n`{reuse_session, SessionId}`. Also it is possible for the client to reuse a\nsession that is not saved by the ssl application using\n`{reuse_session, {SessionId, SessionData}}`.\n\n> #### Note {: .info }\n>\n> When using explicit session reuse, it is up to the client to make sure that\n> the session being reused is for the correct server and has been verified.\n\nHere follows a client side example, divide into several steps for readability.\n\nStep 1 - Automated Session Reuse\n\n```erlang\n1> ssl:start().\nok\n\n2>{ok, C1} = ssl:connect(\"localhost\", 9999, [{verify, verify_peer},\n {versions, ['tlsv1.2']},\n {cacertfile, \"cacerts.pem\"}]).\n{ok,{sslsocket,{gen_tcp,#Port<0.7>,tls_connection,undefined}, ...}}\n\n3> ssl:connection_information(C1, [session_id]).\n{ok,[{session_id,<<95,32,43,22,35,63,249,22,26,36,106,\n 152,49,52,124,56,130,192,137,161,\n 146,145,164,232,...>>}]}\n\n%% Reuse session if possible, note that if C2 is really fast the session\n%% data might not be available for reuse.\n4>{ok, C2} = ssl:connect(\"localhost\", 9999, [{verify, verify_peer},\n {versions, ['tlsv1.2']},\n {cacertfile, \"cacerts.pem\"},\n {reuse_sessions, true}]).\n{ok,{sslsocket,{gen_tcp,#Port<0.8>,tls_connection,undefined}, ...]}}\n\n%% C2 got same session ID as client one, session was automatically reused.\n5> ssl:connection_information(C2, [session_id]).\n{ok,[{session_id,<<95,32,43,22,35,63,249,22,26,36,106,\n 152,49,52,124,56,130,192,137,161,\n 146,145,164,232,...>>}]}\n```\n\nStep 2- Using `save` Option\n\n```erlang\n%% We want save this particular session for\n%% reuse although it has the same basis as C1\n6> {ok, C3} = ssl:connect(\"localhost\", 9999, [{verify, verify_peer},\n {versions, ['tlsv1.2']},\n {cacertfile, \"cacerts.pem\"},\n {reuse_sessions, save}]).\n\n{ok,{sslsocket,{gen_tcp,#Port<0.9>,tls_connection,undefined}, ...]}}\n\n%% A full handshake is performed and we get a new session ID\n7> {ok, [{session_id, ID}]} = ssl:connection_information(C3, [session_id]).\n{ok,[{session_id,<<91,84,27,151,183,39,84,90,143,141,\n 121,190,66,192,10,1,27,192,33,95,78,\n 8,34,180,...>>}]}\n\n%% Use automatic session reuse\n8> {ok, C4} = ssl:connect(\"localhost\", 9999, [{verify, verify_peer},\n {versions, ['tlsv1.2']},\n {cacertfile, \"cacerts.pem\"},\n {reuse_sessions, true}]).\n\n{ok,{sslsocket,{gen_tcp,#Port<0.10>,tls_connection,\n undefined}, ...]}}\n\n%% The \"saved\" one happened to be selected, but this is not a guarantee\n9> ssl:connection_information(C4, [session_id]).\n{ok,[{session_id,<<91,84,27,151,183,39,84,90,143,141,\n 121,190,66,192,10,1,27,192,33,95,78,\n 8,34,180,...>>}]}\n\n%% Make sure to reuse the \"saved\" session\n10> {ok, C5} = ssl:connect(\"localhost\", 9999, [{verify, verify_peer},\n {versions, ['tlsv1.2']},\n {cacertfile, \"cacerts.pem\"},\n {reuse_session, ID}]).\n{ok,{sslsocket,{gen_tcp,#Port<0.11>,tls_connection,\n undefined}, ...]}}\n\n11> ssl:connection_information(C5, [session_id]).\n{ok,[{session_id,<<91,84,27,151,183,39,84,90,143,141,\n 121,190,66,192,10,1,27,192,33,95,78,\n 8,34,180,...>>}]}\n```\n\nStep 3 - Explicit Session Reuse\n\n```erlang\n%% Perform a full handshake and the session will not be saved for reuse\n12> {ok, C9} =\nssl:connect(\"localhost\", 9999, [{verify, verify_peer},\n {versions, ['tlsv1.2']},\n {cacertfile, \"cacerts.pem\"},\n {reuse_sessions, false},\n {server_name_indication, disable}]).\n{ok,{sslsocket,{gen_tcp,#Port<0.14>,tls_connection, ...}}\n\n%% Fetch session ID and data for C9 connection\n12> {ok, [{session_id, ID1}, {session_data, SessData}]} =\n ssl:connection_information(C9, [session_id, session_data]).\n{ok,[{session_id,<<9,233,4,54,170,88,170,180,17,96,202,\n 85,85,99,119,47,9,68,195,50,120,52,\n 130,239,...>>},\n {session_data,<<131,104,13,100,0,7,115,101,115,115,105,\n 111,110,109,0,0,0,32,9,233,4,54,170,...>>}]}\n\n%% Explicitly reuse the session from C9\n13> {ok, C10} = ssl:connect(\"localhost\", 9999, [{verify, verify_peer},\n {versions, ['tlsv1.2']},\n {cacertfile, \"cacerts.pem\"},\n {reuse_session, {ID1, SessData}}]).\n{ok,{sslsocket,{gen_tcp,#Port<0.15>,tls_connection,\n undefined}, ...}}\n\n14> ssl:connection_information(C10, [session_id]).\n{ok,[{session_id,<<9,233,4,54,170,88,170,180,17,96,202,\n 85,85,99,119,47,9,68,195,50,120,52,\n 130,239,...>>}]}\n```\n\nStep 4 - Not Possible to Reuse Explicit Session by ID Only\n\n```erlang\n%% Try to reuse the session from C9 using only the id\n15> {ok, E} = ssl:connect(\"localhost\", 9999, [{verify, verify_peer},\n {versions, ['tlsv1.2']},\n {cacertfile, \"cacerts.pem\"},\n {reuse_session, ID1}]).\n{ok,{sslsocket,{gen_tcp,#Port<0.18>,tls_connection,\n undefined}, ...}}\n\n%% This will fail (as it is not saved for reuse)\n%% and a full handshake will be performed, we get a new id.\n16> ssl:connection_information(E, [session_id]).\n{ok,[{session_id,<<87,46,43,126,175,68,160,153,37,29,\n 196,240,65,160,254,88,65,224,18,63,\n 18,17,174,39,...>>}]}\n```\n\nOn the server side the the `{reuse_sessions, boolean()}` option determines if\nthe server will save session data and allow session reuse or not. This can be\nfurther customized by the option `{reuse_session, fun()}` that may introduce a\nlocal policy for session reuse.","ref":"using_ssl.html#session-reuse-prior-to-tls-1-3"},{"type":"extras","title":"Session Tickets and Session Resumption in TLS 1.3 - Examples","doc":"TLS 1.3 introduces a new secure way of resuming sessions by using session\ntickets. A session ticket is an opaque data structure that is sent in the\npre_shared_key extension of a ClientHello, when a client attempts to resume a\nsession with keying material from a previous successful handshake.\n\nSession tickets can be stateful or stateless. A stateful session ticket is a\ndatabase reference (session ticket store) and used with stateful servers, while\na stateless ticket is a self-encrypted and self-authenticated data structure\nwith cryptographic keying material and state data, enabling session resumption\nwith stateless servers.\n\nThe choice between stateful or stateless depends on the server requirements as\nthe session tickets are opaque for the clients. Generally, stateful tickets are\nsmaller and the server can guarantee that tickets are only used once. Stateless\ntickets contain additional data, require less storage on the server side, but\nthey offer different guarantees against anti-replay. See also\n[Anti-Replay Protection in TLS 1.3](using_ssl.md#anti-replay-protection-in-tls-1-3)\n\nSession tickets are sent by servers on newly established TLS connections. The\nnumber of tickets sent and their lifetime are configurable by application\nvariables. See also [SSL's configuration](ssl_app.md#configuration).\n\nSession tickets are protected by application traffic keys, and in stateless\ntickets, the opaque data structure itself is self-encrypted.\n\nAn example with automatic and manual session resumption:\n\n```erlang\n {ok, _} = application:ensure_all_started(ssl).\n LOpts = [{certs_keys, [#{certfile => \"cert.pem\",\n keyfile => \"key.pem\"}]},\n {versions, ['tlsv1.2','tlsv1.3']},\n {session_tickets, stateless}].\n {ok, LSock} = ssl:listen(8001, LOpts).\n {ok, ASock} = ssl:transport_accept(LSock).\n```\n\n_Step 2 (client):_ Start the client and connect to server:\n\n```erlang\n {ok, _} = application:ensure_all_started(ssl).\n COpts = [{cacertfile, \"cert.pem\"},\n {versions, ['tlsv1.2','tlsv1.3']},\n {log_level, debug},\n {session_tickets, auto}].\n ssl:connect(\"localhost\", 8001, COpts).\n```\n\n_Step 3 (server):_ Start the TLS handshake:\n\n```erlang\n {ok, CSocket} = ssl:handshake(ASock).\n```\n\nA connection is established using a full handshake. Below is a summary of the\nexchanged messages:\n\n```erlang\n >>> TLS 1.3 Handshake, ClientHello ...\n << >> Handshake, Finished ...\n << >> TLS 1.3 Handshake, ClientHello ...\n << >> Handshake, Finished ...\n << TicketData end.\n```\n\n_Step 11 (server):_ Accept a new connection on the server:\n\n```erlang\n {ok, ASock4} = ssl:transport_accept(LSock).\n```\n\n_Step 12 (client):_ Initiate a new connection to the server with the session\nticket received in Step 10:\n\n```erlang\n {ok, _} = application:ensure_all_started(ssl).\n COpts2 = [{cacertfile, \"cert.pem\"},\n {versions, ['tlsv1.2','tlsv1.3']},\n {log_level, debug},\n {session_tickets, manual},\n {use_ticket, [Ticket]}].\n ssl:connect(\"localhost\", 8001, COpts).\n```\n\n_Step 13 (server):_ Start the handshake:\n\n```erlang\n {ok, CSock4} = ssl:handshake(ASock4).\n```","ref":"using_ssl.html#session-tickets-and-session-resumption-in-tls-1-3"},{"type":"extras","title":"Early Data in TLS-1.3 - Examples","doc":"TLS 1.3 allows clients to send data on the first flight if the endpoints have a\nshared crypographic secret (pre-shared key). This means that clients can send\nearly data if they have a valid session ticket received in a previous successful\nhandshake. For more information about session resumption see\n[Session Tickets and Session Resumption in TLS 1.3](using_ssl.md#session-tickets-and-session-resumption-in-tls-1-3).\n\nThe security properties of Early Data are weaker than other kinds of TLS data.\nThis data is not forward secret, and it is vulnerable to replay attacks. For\navailable mitigation strategies see\n[Anti-Replay Protection in TLS 1.3](using_ssl.md#anti-replay-protection-in-tls-1-3).\n\nIn normal operation, clients will not know which, if any, of the available\nmitigation strategies servers actually implement, and hence must only send early\ndata which they deem safe to be replayed. For example, idempotent HTTP\noperations, such as HEAD and GET, can usually be regarded as safe but even they\ncan be exploited by a large number of replays causing resource limit exhaustion\nand other similar problems.\n\nAn example of sending early data with automatic and manual session ticket\nhandling:\n\n_Server_\n\n```erlang\nearly_data_server() ->\n application:load(ssl),\n {ok, _} = application:ensure_all_started(ssl),\n Port = 11029,\n LOpts = [{certs_keys, [#{certfile => \"cert.pem\", keyfile => \"key.pem\"}]},\n {reuseaddr, true},\n {versions, ['tlsv1.2','tlsv1.3']},\n {session_tickets, stateless},\n {early_data, enabled},\n ],\n {ok, LSock} = ssl:listen(Port, LOpts),\n %% Accept first connection\n {ok, ASock0} = ssl:transport_accept(LSock),\n {ok, CSock0} = ssl:handshake(ASock0),\n %% Accept second connection\n {ok, ASock1} = ssl:transport_accept(LSock),\n {ok, CSock1} = ssl:handshake(ASock1),\n Sock.\n```\n\n_Client (automatic ticket handling):_\n\n```erlang\nearly_data_auto() ->\n %% First handshake 1-RTT - get session tickets\n application:load(ssl),\n {ok, _} = application:ensure_all_started(ssl),\n Port = 11029,\n Data = <<\"HEAD / HTTP/1.1\\r\\nHost: \\r\\nConnection: close\\r\\n\">>,\n COpts0 = [{cacertfile, \"cacerts.pem\"},\n {versions, ['tlsv1.2', 'tlsv1.3']},\n {session_tickets, auto}],\n {ok, Sock0} = ssl:connect(\"localhost\", Port, COpts0),\n\n %% Wait for session tickets\n timer:sleep(500),\n %% Close socket if server cannot handle multiple\n %% connections e.g. openssl s_server\n ssl:close(Sock0),\n\n %% Second handshake 0-RTT\n COpts1 = [{cacertfile, \"cacerts.pem\"},\n {versions, ['tlsv1.2', 'tlsv1.3']},\n {session_tickets, auto},\n {early_data, Data}],\n {ok, Sock} = ssl:connect(\"localhost\", Port, COpts1),\n Sock.\n\n```\n\n_Client (manual ticket handling):_\n\n```erlang\nearly_data_manual() ->\n %% First handshake 1-RTT - get session tickets\n application:load(ssl),\n {ok, _} = application:ensure_all_started(ssl),\n Port = 11029,\n Data = <<\"HEAD / HTTP/1.1\\r\\nHost: \\r\\nConnection: close\\r\\n\">>,\n COpts0 = [{cacertfile, \"cacerts.pem\"},\n {versions, ['tlsv1.2', 'tlsv1.3']},\n {session_tickets, manual}],\n {ok, Sock0} = ssl:connect(\"localhost\", Port, COpts0),\n\n %% Wait for session tickets\n Ticket =\n receive\n {ssl, session_ticket, Ticket0} ->\n Ticket0\n end,\n\n %% Close socket if server cannot handle multiple connections\n %% e.g. openssl s_server\n ssl:close(Sock0),\n\n %% Second handshake 0-RTT\n COpts1 = [{cacertfile, \"cacerts.pem\"},\n {versions, ['tlsv1.2', 'tlsv1.3']},\n {session_tickets, manual},\n {use_ticket, [Ticket]},\n {early_data, Data}],\n {ok, Sock} = ssl:connect(\"localhost\", Port, COpts1),\n Sock.\n```","ref":"using_ssl.html#early-data-in-tls-1-3"},{"type":"extras","title":"Anti-Replay Protection in TLS 1.3 - Examples","doc":"The TLS 1.3 protocol does not provide inherent protection for replay of 0-RTT\ndata but describes mechanisms that SHOULD be implemented by compliant server\nimplementations. The implementation of TLS 1.3 in the SSL application employs\nall standard methods to prevent potential threats.\n\n_Single-use tickets_\n\nThis mechanism is available with stateful session tickets. Session tickets can\nonly be used once, subsequent use of the same ticket results in a full\nhandshake. Stateful servers enforce this rule by maintaining a database of\noutstanding valid tickets.\n\n_Client Hello Recording_\n\nThis mechanism is available with stateless session tickets. The server records a\nunique value derived from the ClientHello (PSK binder) in a given time window.\nThe ticket's age is verified by using both the \"obsfuscated_ticket_age\" and an\nadditional timestamp encrypted in the ticket data. As the used datastore allows\nfalse positives, apparent replays will be answered by doing a full 1-RTT\nhandshake.\n\n_Freshness Checks_\n\nThis mechanism is available with the stateless session tickets. As the ticket\ndata has an embedded timestamp, the server can determine if a ClientHello was\nsent reasonably recently and accept the 0-RTT handshake, otherwise if falls back\nto a full 1-RTT handshake. This mechanism is tightly coupled with the previous\none, it prevents storing an unlimited number of ClientHellos.\n\nThe current implementation uses a pair of Bloom filters to implement the last\ntwo mechanisms. Bloom filters are fast, memory-efficient, probabilistic data\nstructures that can tell if an element may be in a set or if it is definitely\nnot in the set.\n\nIf the option `anti_replay` is defined in the server, a\npair of Bloom filters (_current_ and _old_) are used to record incoming\nClientHello messages (it is the unique binder value that is actually stored).\nThe _current_ Bloom filter is used for `WindowSize` seconds to store new\nelements. At the end of the time window the Bloom filters are rotated (the\n_current_ Bloom filter becomes the _old_ and an empty Bloom filter is set as\n_current_.\n\nThe Anti-Replay protection feature in stateless servers executes in the\nfollowing steps when a new ClientHello is received:\n\n- Reported ticket age (obfuscated ticket age) shall be less than ticket\n lifetime.\n- Actual ticket age shall be less than the ticket lifetime (stateless session\n tickets contain the servers timestamp when the ticket was issued).\n- ClientHello created with the ticket shall be sent relatively recently\n (freshness checks).\n- If all above checks passed both _current_ and _old_ Bloom filters are checked\n to detect if binder was already seen. Being a probabilistic data structure,\n false positives can occur and they trigger a full handshake.\n- If the binder is not seen, the binder is validated. If the binder is valid,\n the server proceeds with the 0-RTT handshake.","ref":"using_ssl.html#anti-replay-protection-in-tls-1-3"},{"type":"extras","title":"Using DTLS - Examples","doc":"Using DTLS has basically the same API as TLS. You need to add the option\n\\{protocol, dtls\\} to the connect and listen functions. For example\n\n```erlang\n client>{ok, Socket} = ssl:connect(\"localhost\", 9999, [{protocol, dtls},\n {verify, verify_peer},\n {cacertfile, \"cacerts.pem\"}],\n infinity).\n{ok,{sslsocket, [...]}}\n\n```","ref":"using_ssl.html#using-dtls"},{"type":"extras","title":"Erlang Distribution over TLS","doc":"\n# Erlang Distribution over TLS\n\nThis section describes how the Erlang distribution can use TLS to get extra\nverification and security.\n\nThe Erlang distribution can in theory use almost any connection-based protocol\nas bearer. However, a module that implements the protocol-specific parts of the\nconnection setup is needed. The default distribution module is `inet_tcp_dist`\nin the Kernel application. When starting an Erlang node distributed,\n`net_kernel` uses this module to set up listen ports and connections.\n\nIn the SSL application, an extra distribution module, `inet_tls_dist`, can be\nused as an alternative. All distribution connections will use TLS and all\nparticipating Erlang nodes in a distributed system must use this distribution\nmodule.\n\nThe security level depends on the parameters provided to the TLS connection\nsetup. Erlang node cookies are however always used, as they can be used to\ndifferentiate between two different Erlang networks.\n\nTo set up Erlang distribution over TLS:\n\n- _Step 1:_ Build boot scripts including the SSL application.\n- _Step 2:_ Specify the distribution module for `net_kernel`.\n- _Step 3:_ Specify the security options and other SSL options.\n- _Step 4:_ Set up the environment to always use TLS.\n\nThe following sections describe these steps.","ref":"ssl_distribution.html"},{"type":"extras","title":"Building Boot Scripts Including the SSL Application - Erlang Distribution over TLS","doc":"Boot scripts are built using the `systools` utility in the SASL application. For\nmore information on `systools`, see the SASL documentation. This is only an\nexample of what can be done.\n\nThe simplest boot script possible includes only the Kernel and STDLIB\napplications. Such a script is located in the `bin` directory of the Erlang\ndistribution. The source for the script is found under the Erlang installation\ntop directory under `releases/ /start_clean.rel`.\n\nDo the following:\n\n- Copy that script to another location (and preferably another name).\n- Add the applications Crypto, Public Key, and SSL with their current version\n numbers after the STDLIB application.\n\nThe following shows an example `.rel` file with TLS added:\n\n```erlang\n {release, {\"OTP APN 181 01\",\"R15A\"}, {erts, \"5.9\"},\n [{kernel,\"2.15\"},\n {stdlib,\"1.18\"},\n {crypto, \"2.0.3\"},\n {public_key, \"0.12\"},\n {asn1, \"4.0\"},\n {ssl, \"5.0\"}\n ]}.\n```\n\nThe version numbers differ in your system. Whenever one of the applications\nincluded in the script is upgraded, change the script.\n\nDo the following:\n\n- Build the boot script.\n\n Assuming the `.rel file` is stored in a file `start_ssl.rel` in the current\n directory, a boot script can be built as follows:\n\n```text\n 1> systools:make_script(\"start_ssl\",[]).\n```\n\nThere is now a `start_ssl.boot` file in the current directory.\n\nDo the following:\n\n- Test the boot script. To do this, start Erlang with the `-boot` command-line\n parameter specifying this boot script (with its full path, but without the\n `.boot` suffix). In UNIX it can look as follows:\n\n```text\n$ erl -boot /home/me/ssl/start_ssl\nErlang (BEAM) emulator version 5.0\n\nEshell V5.0 (abort with ^G)\n1> whereis(ssl_manager).\n<0.41.0>\n```\n\nThe `whereis` function-call verifies that the SSL application is started.\n\nAs an alternative to building a bootscript, you can explicitly add the path to\nthe SSL `ebin` directory on the command line. This is done with command-line\noption `-pa`. This works as the SSL application does not need to be started for\nthe distribution to come up, as a clone of the SSL application is hooked into\nthe Kernel application. So, as long as the SSL application code can be reached,\nthe distribution starts. The `-pa` method is only recommended for testing\npurposes.\n\n> #### Note {: .info }\n>\n> The clone of the SSL application must enable the use of the SSL code in such\n> an early bootstage as needed to set up the distribution. However, this makes\n> it impossible to soft upgrade the SSL application.","ref":"ssl_distribution.html#building-boot-scripts-including-the-ssl-application"},{"type":"extras","title":"Specifying Distribution Module for net_kernel - Erlang Distribution over TLS","doc":"The distribution module for TLS is named `inet_tls_dist` and is specified on the\ncommand line with option `-proto_dist`. The argument to `-proto_dist` is to be\nthe module name without suffix `_dist`. So, this distribution module is\nspecified with `-proto_dist inet_tls` on the command line.\n\nExtending the command line gives the following:\n\n```text\n$ erl -boot /home/me/ssl/start_ssl -proto_dist inet_tls\n```\n\nFor the distribution to be started, give the emulator a name as well:\n\n```text\n$ erl -boot /home/me/ssl/start_ssl -proto_dist inet_tls -sname ssl_test\nErlang (BEAM) emulator version 5.0 [source]\n\nEshell V5.0 (abort with ^G)\n(ssl_test@myhost)1>\n```\n\nHowever, a node started in this way refuses to talk to other nodes, as no TLS\nparameters are supplied (see the next section).","ref":"ssl_distribution.html#specifying-distribution-module-for-net_kernel"},{"type":"extras","title":"Specifying TLS Options - Erlang Distribution over TLS","doc":"The TLS distribution options can be written into a file that is consulted when\nthe node is started. This file name is then specified with the command line\nargument `-ssl_dist_optfile`.\n\nAny available TLS option can be specified in an options file.\n\n> #### Note {: .info }\nOptions that take a `fun()` has to use the syntax `fun Mod:Func/Arity` since a\nfunction body cannot be compiled when consulting a file. Also the encoding\nof the file can be specified as defined by module `m:epp`.\n\n> #### Warning {: .warning }\nDo not tamper with the socket options `list`, `binary`, `active`, `packet`,\n`nodelay` and `deliver` since they are used by the distribution protocol handler\nitself. Other raw socket options such as `packet_size` may interfere severely,\nso beware\\!\n\nFor TLS to work, at least a public key and a certificate must be specified for\nthe server side and the client needs to specify CAs that it trusts (client certification\nis optional and requires more configuration).\n\nIn the following example (to keep it simple), the PEM file `\"/home/me/ssl/erlserver.pem\"`\ncontains both the server certificate and its private key .\n\nCreate a file named for example `\"/home/me/ssl/ssl_test@myhost.conf\"`:\n\n```erlang\n[{server,\n [{certfile, \"/home/me/ssl/erlserver.pem\"}]},\n {client,\n [{cacertfile, \"/home/me/ssl/client_trusted.pem\"}]}].\n```\n\nAnd then start the node like this (line breaks in the command are for\nreadability, and shall not be there when typed):\n\n```text\n$ erl -boot /home/me/ssl/start_ssl -proto_dist inet_tls\n -ssl_dist_optfile \"/home/me/ssl/ssl_test@myhost.conf\"\n -sname ssl_test\n```\n\nThe options in the `{server, Opts}` tuple are used when calling\n`ssl:handshake/3`, and the options in the `{client, Opts}` tuple are used when\ncalling `ssl:connect/4`.\n\nFor the client, the option `{server_name_indication, atom_to_list(TargetNode)}`\nis added when connecting. This makes it possible to use the client option\n`{verify, verify_peer}`, and the client will verify that the certificate matches\nthe node name you are connecting to. This only works if the the server\ncertificate is issued to the name\n[`atom_to_list(TargetNode)`](`atom_to_list/1`).\n\nFor the server it is also possible to use the option `{verify, verify_peer}` and\nthe server will only accept client connections with certificates that are\ntrusted by a root certificate that the server knows. A client that presents an\nuntrusted certificate will be rejected. This option is preferably combined with\n`{fail_if_no_peer_cert, true}` or a client will still be accepted if it does not\npresent any certificate.\n\nA node started in this way is fully functional, using TLS as the distribution\nprotocol.","ref":"ssl_distribution.html#specifying-tls-options"},{"type":"extras","title":"Using TLS distribution over IPv6 - Erlang Distribution over TLS","doc":"It is possible to use TLS distribution over IPv6 instead of IPv4. To do this,\npass the option `-proto_dist inet6_tls` instead of `-proto_dist inet_tls` when\nstarting Erlang, either on the command line or in the `ERL_FLAGS` environment\nvariable.\n\nAn example command line with this option would look like this:\n\n```text\n$ erl -boot /home/me/ssl/start_ssl -proto_dist inet6_tls\n -ssl_dist_optfile \"/home/me/ssl/ssl_test@myhost.conf\"\n -sname ssl_test\n```\n\nA node started in this way will only be able to communicate with other nodes\nusing TLS distribution over IPv6.","ref":"ssl_distribution.html#using-tls-distribution-over-ipv6"},{"type":"extras","title":"Specifying TLS Options (Legacy) - Erlang Distribution over TLS","doc":"> #### Note {: .info }\n> The following section describes TLS Option handling prior to OTP 20.2\n> and can only handle a small subset of the actual available options.\n> It is here only for the sake of backwards compatibility .\n\nAs in the previous section the PEM file `\"/home/me/ssl/erlserver.pem\"` contains\nboth the server certificate and its private key.\n\nOn the `erl` command line you can specify options that the TLS distribution adds\nwhen creating a socket.\n\nThe simplest TLS options in the following list can be specified by adding the\nprefix `server_` or `client_` to the option name:\n\n- `certfile`\n- `keyfile`\n- `password`\n- `cacertfile`\n- `verify`\n- `verify_fun` (write as `{Module, Function, InitialUserState}`)\n- `crl_check`\n- `crl_cache` (write as Erlang term)\n- `reuse_sessions`\n- `secure_renegotiate`\n- `depth`\n- `hibernate_after`\n- `ciphers` (use old string format)\n\nNote that `verify_fun` needs to be written in a different form than the\ncorresponding TLS option, since funs are not accepted on the command line.\n\nThe server can also take the options `dhfile` and `fail_if_no_peer_cert` (also\nprefixed).\n\n`client_`\\-prefixed options are used when the distribution initiates a\nconnection to another node. `server_`\\-prefixed options are used when accepting\na connection from a remote node.\n\nRaw socket options, such as `packet` and `size` must not be specified on the\ncommand line.\n\nThe command-line argument for specifying the TLS options is named\n`-ssl_dist_opt` and is to be followed by pairs of SSL options and their values.\nArgument `-ssl_dist_opt` can be repeated any number of times.\n\nAn example command line doing the same as the example in the previous section\ncan now look as follows (line breaks in the command are for readability, and\nshall not be there when typed):\n\n```text\n$ erl -boot /home/me/ssl/start_ssl -proto_dist inet_tls\n -ssl_dist_opt server_certfile \"/home/me/ssl/erlserver.pem\"\n -ssl_dist_opt server_secure_renegotiate true client_secure_renegotiate true\n -sname ssl_test\nErlang (BEAM) emulator version 5.0 [source]\n\nEshell V5.0 (abort with ^G)\n(ssl_test@myhost)1>\n```","ref":"ssl_distribution.html#specifying-tls-options-legacy"},{"type":"extras","title":"Setting up Environment to Always Use TLS - Erlang Distribution over TLS","doc":"A convenient way to specify arguments to Erlang is to use environment variable\n`ERL_FLAGS`. All the flags needed to use the TLS distribution can be specified\nin that variable and are then interpreted as command-line arguments for all\nsubsequent invocations of Erlang.\n\nIn a Unix (Bourne) shell, it can look as follows (line breaks are for\nreadability, they are not to be there when typed):\n\n```erlang\n$ ERL_FLAGS=\"-boot /home/me/ssl/start_ssl -proto_dist inet_tls\n -ssl_dist_opt server_certfile /home/me/ssl/erlserver.pem\n -ssl_dist_opt server_secure_renegotiate true client_secure_renegotiate true\"\n$ export ERL_FLAGS\n$ erl -sname ssl_test\nErlang (BEAM) emulator version 5.0 [source]\n\nEshell V5.0 (abort with ^G)\n(ssl_test@myhost)1> init:get_arguments().\n[{root,[\"/usr/local/erlang\"]},\n {progname,[\"erl \"]},\n {sname,[\"ssl_test\"]},\n {boot,[\"/home/me/ssl/start_ssl\"]},\n {proto_dist,[\"inet_tls\"]},\n {ssl_dist_opt,[\"server_certfile\",\"/home/me/ssl/erlserver.pem\"]},\n {ssl_dist_opt,[\"server_secure_renegotiate\",\"true\",\n \"client_secure_renegotiate\",\"true\"]\n {home,[\"/home/me\"]}]\n```\n\nThe `init:get_arguments()` call verifies that the correct arguments are supplied\nto the emulator.","ref":"ssl_distribution.html#setting-up-environment-to-always-use-tls"},{"type":"extras","title":"Standards Compliance","doc":"\n# Standards Compliance","ref":"standards_compliance.html"},{"type":"extras","title":"Purpose - Standards Compliance","doc":"This section describes the current state of standards compliance of the ssl\napplication.","ref":"standards_compliance.html#purpose"},{"type":"extras","title":"Common (prior to TLS 1.3) - Standards Compliance","doc":"- For security reasons RSA key exchange cipher suites are no longer supported by\n default, but can be configured. (OTP 21)\n- For security reasons DES cipher suites are no longer supported by default, but\n can be configured. (OTP 20)\n- For security reasons 3DES cipher suites are no longer supported by default,\n but can be configured. (OTP 21)\n- Renegotiation Indication Extension\n [RFC 5746](http://www.ietf.org/rfc/rfc5746.txt) is supported\n- Ephemeral Diffie-Hellman cipher suites are supported, but not Diffie Hellman\n Certificates cipher suites.\n- Elliptic Curve cipher suites are supported if the Crypto application supports\n it and named curves are used.\n- Export cipher suites are not supported as the U.S. lifted its export\n restrictions in early 2000.\n- IDEA cipher suites are not supported as they have become deprecated by the TLS\n 1.2 specification so it is not motivated to implement them.\n- Compression is not supported.\n- It is possible to use Pre-Shared Key (PSK) and Secure Remote Password (SRP)\n cipher suites, but they are not enabled by default and need addition configuration.","ref":"standards_compliance.html#common-prior-to-tls-1-3"},{"type":"extras","title":"Common - Standards Compliance","doc":"- CRL validation is supported.\n- Policy certificate extensions are supported. (OTP 27)\n- 'Server Name Indication' extension\n ([RFC 6066](http://www.ietf.org/rfc/rfc6066.txt)) is supported.\n- Application Layer Protocol Negotiation (ALPN) and its successor Next Protocol\n Negotiation (NPN) are supported.","ref":"standards_compliance.html#common"},{"type":"extras","title":"SSL 2.0 - Standards Compliance","doc":"For security reasons SSL-2.0 is not supported. Interoperability with SSL-2.0\nenabled clients dropped. (OTP 21)","ref":"standards_compliance.html#ssl-2-0"},{"type":"extras","title":"SSL 3.0 - Standards Compliance","doc":"For security reasons SSL-3.0 is no longer supported at all. (OTP 23)\n\nFor security reasons SSL-3.0 is no longer supported by default, but can be\nconfigured. (OTP 19)","ref":"standards_compliance.html#ssl-3-0"},{"type":"extras","title":"TLS 1.0 - Standards Compliance","doc":"For security reasons TLS-1.0 is no longer supported by default, but can be\nconfigured. (OTP 22)","ref":"standards_compliance.html#tls-1-0"},{"type":"extras","title":"TLS 1.1 - Standards Compliance","doc":"For security reasons TLS-1.1 is no longer supported by default, but can be\nconfigured. (OTP 22)","ref":"standards_compliance.html#tls-1-1"},{"type":"extras","title":"TLS 1.2 - Standards Compliance","doc":"Supported","ref":"standards_compliance.html#tls-1-2"},{"type":"extras","title":"DTLS 1.0 - Standards Compliance","doc":"For security reasons DTLS-1.0 (based on TLS 1.1) is no longer supported by\ndefault, but can be configured. (OTP 22)","ref":"standards_compliance.html#dtls-1-0"},{"type":"extras","title":"DTLS 1.2 - Standards Compliance","doc":"Supported (based on TLS 1.2)","ref":"standards_compliance.html#dtls-1-2"},{"type":"extras","title":"DTLS 1.3 - Standards Compliance","doc":"Not yet supported","ref":"standards_compliance.html#dtls-1-3"},{"type":"extras","title":"TLS 1.3 - Standards Compliance","doc":"OTP-22 introduces support for TLS 1.3. The current implementation supports a\nselective set of cryptographic algorithms:\n\n- Key Exchange: ECDHE groups supported by default\n- Groups: all standard groups supported for the Diffie-Hellman key exchange\n- Groups: Support brainpool groups from RFC 8734\n- Ciphers: all mandatory cipher suites are supported\n- Signature Algorithms: All algorithms form RFC 8446\n- Certificates: RSA, ECDSA and EDDSA keys\n\nOther notable features:\n\n- PSK and session resumption is supported (stateful and stateless tickets)\n- Anti-replay protection using Bloom-filters with stateless tickets\n- Early data and 0-RTT is supported\n- Key and Initialization Vector Update is supported\n\nFor more detailed information see the\n[Standards Compliance](standards_compliance.md#soc_table) below.\n\nThe following table describes the current state of standards compliance for TLS\n1.3.\n\n(_C_ = Compliant, _NC_ = Non-Compliant, _PC_ = Partially-Compliant, _NA_ = Not\nApplicable)\n\n[](){: #soc_table }\n\n| _Section_ | _Feature_ | _State_ | _Since_ |\n| --------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------- |\n| [1\\.3. Updates Affecting TLS 1.2](https://tools.ietf.org/html/rfc8446#section-1.2) | | _C_ | _24\\.1_ |\n| | Version downgrade protection mechanism | _C_ | _22_ |\n| | RSASSA-PSS signature schemes | _C_ | _24\\.1_ |\n| | supported_versions (ClientHello) extension | _C_ | _22_ |\n| | signature_algorithms_cert extension | _C_ | _24\\.1_ |\n| [2\\. Protocol Overview](https://tools.ietf.org/html/rfc8446#section/2) | | _PC_ | _22_ |\n| | (EC)DHE | _C_ | _22_ |\n| | PSK-only | _NC_ | |\n| | PSK with (EC)DHE | _C_ | _22\\.2_ |\n| [2\\.1. Incorrect DHE share](https://tools.ietf.org/html/rfc8446#section-2.1) | HelloRetryRequest | _C_ | _22_ |\n| [2\\.2. Resumption and Pre-Shared Key (PSK)](https://tools.ietf.org/html/rfc8446#section-2.2) | | _C_ | _22\\.2_ |\n| [2\\.3. 0-RTT Data](https://tools.ietf.org/html/rfc8446#section-2.3) | | _PC_ | _23\\.3_ |\n| [4\\.1.1. Cryptographic Negotiation](https://tools.ietf.org/html/rfc8446#section-4.1.1) | | _C_ | _22\\.2_ |\n| | supported_groups extension | _C_ | _22_ |\n| | signature_algorithms extension | _C_ | _22_ |\n| | pre_shared_key extension | _C_ | _22\\.2_ |\n| [4\\.1.2. Client Hello](https://tools.ietf.org/html/rfc8446#section-4.1.2) | _Client_ | _PC_ | _22\\.1_ |\n| | server_name (RFC6066) | _C_ | _23\\.2_ |\n| | max_fragment_length (RFC6066) | _C_ | _23\\.0_ |\n| | status_request (RFC6066) | _C_ | _27\\.0_ |\n| | supported_groups (RFC7919) | _C_ | _22\\.1_ |\n| | signature_algorithms (RFC8446) | _C_ | _22\\.1_ |\n| | use_srtp (RFC5764) | _C_ | 26\\.0 |\n| | heartbeat (RFC6520) | _NC_ | |\n| | application_layer_protocol_negotiation (RFC7301) | _C_ | _22\\.1_ |\n| | signed_certificate_timestamp (RFC6962) | _NC_ | |\n| | client_certificate_type (RFC7250) | _NC_ | |\n| | server_certificate_type (RFC7250) | _NC_ | |\n| | padding (RFC7685) | _NC_ | |\n| | key_share (RFC8446) | _C_ | _22\\.1_ |\n| | pre_shared_key (RFC8446) | _C_ | _22\\.2_ |\n| | psk_key_exchange_modes (RFC8446) | _C_ | _22\\.2_ |\n| | early_data (RFC8446) | _C_ | _23\\.3_ |\n| | cookie (RFC8446) | _C_ | _23\\.1_ |\n| | supported_versions (RFC8446) | _C_ | _22\\.1_ |\n| | certificate_authorities (RFC8446) | _C_ | 24\\.3 |\n| | oid_filters (RFC8446) | _NC_ | |\n| | post_handshake_auth (RFC8446) | _NC_ | |\n| | signature_algorithms_cert (RFC8446) | _C_ | _22\\.1_ |\n| | _Server_ | _PC_ | _22_ |\n| | server_name (RFC6066) | _C_ | _23\\.2_ |\n| | max_fragment_length (RFC6066) | _C_ | _23\\.0_ |\n| | status_request (RFC6066) | _NC_ | |\n| | supported_groups (RFC7919) | _C_ | _22_ |\n| | signature_algorithms (RFC8446) | _C_ | _22_ |\n| | use_srtp (RFC5764) | _C_ | 26\\.0 |\n| | heartbeat (RFC6520) | _NC_ | |\n| | application_layer_protocol_negotiation (RFC7301) | _C_ | _22\\.1_ |\n| | signed_certificate_timestamp (RFC6962) | _NC_ | |\n| | client_certificate_type (RFC7250) | _NC_ | |\n| | server_certificate_type (RFC7250) | _NC_ | |\n| | padding (RFC7685) | _NC_ | |\n| | key_share (RFC8446) | _C_ | _22_ |\n| | pre_shared_key (RFC8446) | _C_ | _22\\.2_ |\n| | psk_key_exchange_modes (RFC8446) | _C_ | _22\\.2_ |\n| | early_data (RFC8446) | _C_ | _23\\.3_ |\n| | cookie (RFC8446) | _C_ | _23\\.1_ |\n| | supported_versions (RFC8446) | _C_ | _22_ |\n| | oid_filters (RFC8446) | _NC_ | |\n| | post_handshake_auth (RFC8446) | _NC_ | |\n| | signature_algorithms_cert (RFC8446) | _C_ | _22_ |\n| [4\\.1.3. Server Hello](https://tools.ietf.org/html/rfc8446#section-4.1.3) | _Client_ | _C_ | _22\\.2_ |\n| | Version downgrade protection | _C_ | _22\\.1_ |\n| | key_share (RFC8446) | _C_ | _22\\.1_ |\n| | pre_shared_key (RFC8446) | _C_ | _22\\.2_ |\n| | supported_versions (RFC8446) | _C_ | _22\\.1_ |\n| | use_srtp (RFC5764) | _C_ | 26\\.0 |\n| | _Server_ | _C_ | _22\\.2_ |\n| | Version downgrade protection | _C_ | _22_ |\n| | key_share (RFC8446) | _C_ | _22_ |\n| | pre_shared_key (RFC8446) | _C_ | _22\\.2_ |\n| | supported_versions (RFC8446) | _C_ | _22_ |\n| | use_srtp (RFC5764) | _C_ | 26\\.0 |\n| [4\\.1.4. Hello Retry Request](https://tools.ietf.org/html/rfc8446#section-4.1.4) | _Server_ | _C_ | _22_ |\n| | key_share (RFC8446) | _C_ | _22_ |\n| | cookie (RFC8446) | _C_ | _23\\.1_ |\n| | supported_versions (RFC8446) | _C_ | _22_ |\n| [4\\.2.1. Supported Versions](https://tools.ietf.org/html/rfc8446#section-4.2.1) | _Client_ | _C_ | _22\\.1_ |\n| | _Server_ | _C_ | _22_ |\n| [4\\.2.2. Cookie](https://tools.ietf.org/html/rfc8446#section-4.2.2) | _Client_ | _C_ | _23\\.1_ |\n| | _Server_ | _C_ | _23\\.1_ |\n| [4\\.2.3. Signature Algorithms](https://tools.ietf.org/html/rfc8446#section-4.2.3) | _Client_ | _C_ | _24_ |\n| | rsa_pkcs1_sha256 | _C_ | _22\\.1_ |\n| | rsa_pkcs1_sha384 | _C_ | _22\\.1_ |\n| | rsa_pkcs1_sha512 | _C_ | _22\\.1_ |\n| | ecdsa_secp256r1_sha256 | _C_ | _22\\.1_ |\n| | ecdsa_secp384r1_sha384 | _C_ | _22\\.1_ |\n| | ecdsa_secp521r1_sha512 | _C_ | _22\\.1_ |\n| | rsa_pss_rsae_sha256 | _C_ | _22\\.1_ |\n| | rsa_pss_rsae_sha384 | _C_ | _22\\.1_ |\n| | rsa_pss_rsae_sha512 | _C_ | _22\\.1_ |\n| | ed25519 | _C_ | _24_ |\n| | ed448 | _C_ | _24_ |\n| | rsa_pss_pss_sha256 | _C_ | _23_ |\n| | rsa_pss_pss_sha384 | _C_ | _23_ |\n| | rsa_pss_pss_sha512 | _C_ | _23_ |\n| | rsa_pkcs1_sha1 | _C_ | _22\\.1_ |\n| | ecdsa_sha1 | _C_ | _22\\.1_ |\n| | _Server_ | _C_ | _24_ |\n| | rsa_pkcs1_sha256 | _C_ | _22_ |\n| | rsa_pkcs1_sha384 | _C_ | _22_ |\n| | rsa_pkcs1_sha512 | _C_ | _22_ |\n| | ecdsa_secp256r1_sha256 | _C_ | _22\\.1_ |\n| | ecdsa_secp384r1_sha384 | _C_ | _22\\.1_ |\n| | ecdsa_secp521r1_sha512 | _C_ | _22\\.1_ |\n| | rsa_pss_rsae_sha256 | _C_ | _22_ |\n| | rsa_pss_rsae_sha384 | _C_ | _22_ |\n| | rsa_pss_rsae_sha512 | _C_ | _22_ |\n| | ed25519 | _C_ | _24_ |\n| | ed448 | _C_ | _24_ |\n| | rsa_pss_pss_sha256 | _C_ | _23_ |\n| | rsa_pss_pss_sha384 | _C_ | _23_ |\n| | rsa_pss_pss_sha512 | _C_ | _23_ |\n| | rsa_pkcs1_sha1 | _C_ | _22_ |\n| | ecdsa_sha1 | _C_ | _22_ |\n| [4\\.2.4. Certificate Authorities](https://tools.ietf.org/html/rfc8446#section-4.2.4) | _Client_ | _C_ | 24\\.3 |\n| | _Server_ | _C_ | _24\\.3_ |\n| [4\\.2.5. OID Filters](https://tools.ietf.org/html/rfc8446#section-4.2.5) | _Client_ | _NC_ | |\n| | _Server_ | _NC_ | |\n| [4\\.2.6. Post-Handshake Client Authentication](https://tools.ietf.org/html/rfc8446#section-4.2.6) | _Client_ | _NC_ | |\n| | _Server_ | _NC_ | |\n| [4\\.2.7. Supported Groups](https://tools.ietf.org/html/rfc8446#section-4.2.7) | _Client_ | _C_ | _22\\.1_ |\n| | secp256r1 | _C_ | _22\\.1_ |\n| | secp384r1 | _C_ | _22\\.1_ |\n| | secp521r1 | _C_ | _22\\.1_ |\n| | x25519 | _C_ | _22\\.1_ |\n| | x448 | _C_ | _22\\.1_ |\n| | ffdhe2048 | _C_ | _22\\.1_ |\n| | ffdhe3072 | _C_ | _22\\.1_ |\n| | ffdhe4096 | _C_ | _22\\.1_ |\n| | ffdhe6144 | _C_ | _22\\.1_ |\n| | ffdhe8192 | _C_ | _22\\.1_ |\n| | _Server_ | _C_ | _22_ |\n| | secp256r1 | _C_ | _22_ |\n| | secp384r1 | _C_ | _22_ |\n| | secp521r1 | _C_ | _22_ |\n| | x25519 | _C_ | _22_ |\n| | x448 | _C_ | _22_ |\n| | ffdhe2048 | _C_ | _22_ |\n| | ffdhe3072 | _C_ | _22_ |\n| | ffdhe4096 | _C_ | _22_ |\n| | ffdhe6144 | _C_ | _22_ |\n| | ffdhe8192 | _C_ | _22_ |\n| [4\\.2.8. Key Share](https://tools.ietf.org/html/rfc8446#section-4.2.8) | _Client_ | _C_ | _22\\.1_ |\n| | _Server_ | _C_ | _22_ |\n| [4\\.2.9. Pre-Shared Key Exchange Modes](https://tools.ietf.org/html/rfc8446#section-4.2.9) | _Client_ | _C_ | _22\\.2_ |\n| | _Server_ | _C_ | _22\\.2_ |\n| [4\\.2.10. Early Data Indication](https://tools.ietf.org/html/rfc8446#section-4.2.10) | _Client_ | _C_ | _23\\.3_ |\n| | _Server_ | _C_ | _23\\.3_ |\n| [4\\.2.11. Pre-Shared Key Extension](https://tools.ietf.org/html/rfc8446#section-4.2.11) | _Client_ | _C_ | _22\\.2_ |\n| | _Server_ | _C_ | _22\\.2_ |\n| [4\\.2.11.1. Ticket Age](https://tools.ietf.org/html/rfc8446#section-4.2.11.1) | _Client_ | _C_ | _22\\.2_ |\n| | _Server_ | _C_ | _22\\.2_ |\n| [4\\.2.11.2. PSK Binder](https://tools.ietf.org/html/rfc8446#section-4.2.11.2) | _Client_ | _C_ | _22\\.2_ |\n| | _Server_ | _C_ | _22\\.2_ |\n| [4\\.2.11.3. Processing Order](https://tools.ietf.org/html/rfc8446#section-4.2.11.3) | _Client_ | _NC_ | |\n| | _Server_ | _NC_ | |\n| [4\\.3.1. Encrypted Extensions](https://tools.ietf.org/html/rfc8446#section-4.3.1) | _Client_ | _PC_ | _22\\.1_ |\n| | server_name (RFC6066) | _C_ | _23\\.2_ |\n| | max_fragment_length (RFC6066) | _C_ | _23\\.0_ |\n| | supported_groups (RFC7919) | _NC_ | |\n| | use_srtp (RFC5764) | _NC_ | |\n| | heartbeat (RFC6520) | _NC_ | |\n| | application_layer_protocol_negotiation (RFC7301) | _C_ | 23\\.0 |\n| | client_certificate_type (RFC7250) | _NC_ | |\n| | server_certificate_type (RFC7250) | _NC_ | |\n| | early_data (RFC8446) | _C_ | _23\\.3_ |\n| | _Server_ | _PC_ | _22_ |\n| | server_name (RFC6066) | _C_ | _23\\.2_ |\n| | max_fragment_length (RFC6066) | _C_ | _23\\.0_ |\n| | supported_groups (RFC7919) | _NC_ | |\n| | use_srtp (RFC5764) | _NC_ | |\n| | heartbeat (RFC6520) | _NC_ | |\n| | application_layer_protocol_negotiation (RFC7301) | _C_ | 23\\.0 |\n| | client_certificate_type (RFC7250) | _NC_ | |\n| | server_certificate_type (RFC7250) | _NC_ | |\n| | early_data (RFC8446) | _C_ | _23\\.3_ |\n| [4\\.3.2. Certificate Request](https://tools.ietf.org/html/rfc8446#section-4.3.2) | _Client_ | _PC_ | _22\\.1_ |\n| | status_request (RFC6066) | _NC_ | |\n| | signature_algorithms (RFC8446) | _C_ | _22\\.1_ |\n| | signed_certificate_timestamp (RFC6962) | _NC_ | |\n| | certificate_authorities (RFC8446) | _C_ | 24\\.3 |\n| | oid_filters (RFC8446) | _NC_ | |\n| | signature_algorithms_cert (RFC8446) | _C_ | _22\\.1_ |\n| | _Server_ | _PC_ | _22_ |\n| | status_request (RFC6066) | _NC_ | |\n| | signature_algorithms (RFC8446) | _C_ | _22_ |\n| | signed_certificate_timestamp (RFC6962) | _NC_ | |\n| | certificate_authorities (RFC8446) | _C_ | 24\\.3 |\n| | oid_filters (RFC8446) | _NC_ | |\n| | signature_algorithms_cert (RFC8446) | _C_ | _22_ |\n| [4\\.4.1. The Transcript Hash](https://tools.ietf.org/html/rfc8446#section-4.4.1) | | _C_ | _22_ |\n| [4\\.4.2. Certificate](https://tools.ietf.org/html/rfc8446#section-4.4.2) | _Client_ | _PC_ | _22\\.1_ |\n| | Arbitrary certificate chain orderings | _C_ | _22\\.2_ |\n| | Extraneous certificates in chain | _C_ | _23\\.2_ |\n| | status_request (RFC6066) | _C_ | 27\\.0 |\n| | signed_certificate_timestamp (RFC6962) | _NC_ | |\n| | _Server_ | _PC_ | _22_ |\n| | status_request (RFC6066) | _NC_ | |\n| | signed_certificate_timestamp (RFC6962) | _NC_ | |\n| [4\\.4.2.1. OCSP Status and SCT Extensions](https://tools.ietf.org/html/rfc8446#section-4.4.2.1) | _Client_ | _PC_ | _27\\.0_ |\n| | _Server_ | _NC_ | |\n| [4\\.4.2.2. Server Certificate Selection](https://tools.ietf.org/html/rfc8446#section-4.4.2.2) | | _C_ | _24\\.3_ |\n| | The certificate type MUST be X.509v3, unless explicitly negotiated otherwise | _C_ | _22_ |\n| | The server's end-entity certificate's public key (and associated restrictions) MUST be compatible with the selected authentication algorithm from the client's \"signature_algorithms\" extension (currently RSA, ECDSA, or EdDSA). | _C_ | _22_ |\n| | The certificate MUST allow the key to be used for signing with a signature scheme indicated in the client's \"signature_algorithms\"/\"signature_algorithms_cert\" extensions | _C_ | _22_ |\n| | The \"server_name\" and \"certificate_authorities\" extensions are used to guide certificate selection. As servers MAY require the presence of the \"server_name\" extension, clients SHOULD send this extension, when applicable. | _C_ | _24\\.3_ |\n| [4\\.4.2.3. Client Certificate Selection](https://tools.ietf.org/html/rfc8446#section-4.4.2.3) | | _PC_ | _22\\.1_ |\n| | The certificate type MUST be X.509v3, unless explicitly negotiated otherwise | _C_ | _22\\.1_ |\n| | If the \"certificate_authorities\" extension in the CertificateRequest message was present, at least one of the certificates in the certificate chain SHOULD be issued by one of the listed CAs. | _C_ | _24\\.3_ |\n| | The certificates MUST be signed using an acceptable signature algorithm | _C_ | _22\\.1_ |\n| | If the CertificateRequest message contained a non-empty \"oid_filters\" extension, the end-entity certificate MUST match the extension OIDs that are recognized by the client | _NC_ | |\n| [4\\.4.2.4. Receiving a Certificate Message](https://tools.ietf.org/html/rfc8446#section-4.4.2.4) | _Client_ | _C_ | _22\\.1_ |\n| | _Server_ | _C_ | _22_ |\n| [4\\.4.3. Certificate Verify](https://tools.ietf.org/html/rfc8446#section-4.4.3) | _Client_ | _C_ | _22\\.1_ |\n| | _Server_ | _C_ | _22_ |\n| [4\\.4.4. Finished](https://tools.ietf.org/html/rfc8446#section-4.4.4) | _Client_ | _C_ | _22\\.1_ |\n| | _Server_ | _C_ | _22_ |\n| [4\\.5. End of Early Data](https://tools.ietf.org/html/rfc8446#section-4.5) | _Client_ | _C_ | _23\\.3_ |\n| | _Server_ | _C_ | _23\\.3_ |\n| [4\\.6.1. New Session Ticket Message](https://tools.ietf.org/html/rfc8446#section-4.6.1) | _Client_ | _C_ | _23\\.3_ |\n| | early_data (RFC8446) | _C_ | _23\\.3_ |\n| | _Server_ | _C_ | _23\\.3_ |\n| | early_data (RFC8446) | _C_ | _23\\.3_ |\n| [4\\.6.2. Post-Handshake Authentication](https://tools.ietf.org/html/rfc8446#section-4.6.2) | _Client_ | _NC_ | |\n| | _Server_ | _NC_ | |\n| [4\\.6.3. Key and Initialization Vector Update](https://tools.ietf.org/html/rfc8446#section-4.6.3) | _Client_ | _C_ | _22\\.3_ |\n| | _Server_ | _C_ | _22\\.3_ |\n| [5\\.1. Record Layer](https://tools.ietf.org/html/rfc8446#section-5.1) | | _C_ | _22_ |\n| | MUST NOT be interleaved with other record types | _C_ | _22_ |\n| | MUST NOT span key changes | _C_ | _22_ |\n| | MUST NOT send zero-length fragments | _C_ | _22_ |\n| | Alert messages MUST NOT be fragmented | _C_ | _22_ |\n| [5\\.2. Record Payload Protection](https://tools.ietf.org/html/rfc8446#section-5.2) | | _C_ | _22_ |\n| [5\\.3. Per-Record Nonce](https://tools.ietf.org/html/rfc8446#section-5.3) | | _C_ | _22_ |\n| [5\\.4. Record Padding](https://tools.ietf.org/html/rfc8446#section-5.4) | | _PC_ | _22_ |\n| | MAY choose to pad | _NC_ | |\n| | MUST NOT send Handshake and Alert records that have a zero-length TLSInnerPlaintext.content | _NC_ | |\n| | The padding sent is automatically verified | _C_ | _22_ |\n| [5\\.5. Limits on Key Usage](https://tools.ietf.org/html/rfc8446#section-5.5) | | _C_ | _22\\.3_ |\n| [6\\.1. Closure Alerts](https://tools.ietf.org/html/rfc8446#section-6.1) | | _22_ | |\n| | close_notify | _C_ | _22_ | |\n| | user_cancelled | _C_ | _22_ | |\n| [6\\.2. Error Alerts](https://tools.ietf.org/html/rfc8446#section-6.2) | | _PC_ | _22_ |\n| [7\\.1. Key Schedule](https://tools.ietf.org/html/rfc8446#section-7.1) | | _C_ | _22_ |\n| [7\\.2. Updating Traffic Secrets](https://tools.ietf.org/html/rfc8446#section-7.2) | | _C_ | _22_ |\n| [7\\.3. Traffic Key Calculation](https://tools.ietf.org/html/rfc8446#section-7.3) | | _C_ | _22_ |\n| [7\\.5. Exporters](https://tools.ietf.org/html/rfc8446#section-7.5) | | _PC_ | _26\\.3_ |\n| [8\\. 0-RTT and Anti-Replay](https://tools.ietf.org/html/rfc8446#section/8) | | _C_ | _22\\.2_ |\n| [8\\.1. Single-Use Tickets](https://tools.ietf.org/html/rfc8446#section-8.1) | | _C_ | _22\\.2_ |\n| [8\\.2. Client Hello Recording](https://tools.ietf.org/html/rfc8446#section-8.2) | | _C_ | _22\\.2_ |\n| [8\\.3. Freshness Checks](https://tools.ietf.org/html/rfc8446#section-8.3) | | _C_ | _22\\.2_ |\n| [9\\.1. Mandatory-to-Implement Cipher Suites](https://tools.ietf.org/html/rfc8446#section-9.1) | | _C_ | _22\\.1_ |\n| | MUST implement the TLS_AES_128_GCM_SHA256 | _C_ | _22_ |\n| | SHOULD implement the TLS_AES_256_GCM_SHA384 | _C_ | _22_ |\n| | SHOULD implement the TLS_CHACHA20_POLY1305_SHA256 | _C_ | _22_ |\n| | _Digital signatures_ | _C_ | _22\\.1_ |\n| | MUST support rsa_pkcs1_sha256 (for certificates) | _C_ | _22_ |\n| | MUST support rsa_pss_rsae_sha256 (for CertificateVerify and certificates) | _C_ | _22_ |\n| | MUST support ecdsa_secp256r1_sha256 | _C_ | _22\\.1_ |\n| | _Key Exchange_ | _C_ | _22_ |\n| | MUST support key exchange with secp256r1 | _C_ | _22_ |\n| | SHOULD support key exchange with X25519 | _C_ | _22_ |\n| [9\\.2. Mandatory-to-Implement Extensions](https://tools.ietf.org/html/rfc8446#section-9.2) | | _C_ | _23\\.2_ |\n| | Supported Versions | _C_ | _22_ |\n| | Cookie | _C_ | _23\\.1_ |\n| | Signature Algorithms | _C_ | _22_ |\n| | Signature Algorithms Certificate | _C_ | _22_ |\n| | Negotiated Groups | _C_ | _22_ |\n| | Key Share | _C_ | _22_ |\n| | Server Name Indication | _C_ | _23\\.2_ |\n| | _MUST send and use these extensions_ | _C_ | _22\\.2_ |\n| | \"supported_versions\" is REQUIRED for ClientHello, ServerHello and HelloRetryRequest | _C_ | _22\\.1_ |\n| | \"signature_algorithms\" is REQUIRED for certificate authentication | _C_ | _22_ |\n| | \"supported_groups\" is REQUIRED for ClientHello messages using (EC)DHE key exchange | _C_ | _22_ |\n| | \"key_share\" is REQUIRED for (EC)DHE key exchange | _C_ | _22_ |\n| | \"pre_shared_key\" is REQUIRED for PSK key agreement | _C_ | _22\\.2_ |\n| | \"psk_key_exchange_modes\" is REQUIRED for PSK key agreement | _C_ | _22\\.2_ |\n| | _TLS 1.3 ClientHello_ | _C_ | _22\\.1_ |\n| | If not containing a \"pre_shared_key\" extension, it MUST contain both a \"signature_algorithms\" extension and a \"supported_groups\" extension. | _C_ | _22\\.1_ |\n| | If containing a \"supported_groups\" extension, it MUST also contain a \"key_share\" extension, and vice versa. An empty KeyShare.client_shares vector is permitted. | _C_ | _22\\.1_ |\n| | _TLS 1.3 ServerHello_ | _C_ | _23\\.2_ |\n| | MUST support the use of the \"server_name\" extension | _C_ | _23\\.2_ |\n| [9\\.3. Protocol Invariants](https://tools.ietf.org/html/rfc8446#section-9.3) | | _C_ | _22\\.1_ |\n| | _MUST correctly handle extensible fields_ | _C_ | _22\\.1_ |\n| | A client sending a ClientHello MUST support all parameters advertised in it. Otherwise, the server may fail to interoperate by selecting one of those parameters. | _C_ | _22\\.1_ |\n| | A server receiving a ClientHello MUST correctly ignore all unrecognized cipher suites, extensions, and other parameters. Otherwise, it may fail to interoperate with newer clients. In TLS 1.3, a client receiving a CertificateRequest or NewSessionTicket MUST also ignore all unrecognized extensions. | _C_ | _22\\.1_ |\n| | A middlebox which terminates a TLS connection MUST behave as a compliant TLS server | _NA_ | |\n| | A middlebox which forwards ClientHello parameters it does not understand MUST NOT process any messages beyond that ClientHello. It MUST forward all subsequent traffic unmodified. Otherwise, it may fail to interoperate with newer clients and servers. | _NA_ | |\n| [B.4. Cipher Suites](https://tools.ietf.org/html/rfc8446#section-B.4) | | _C_ | _23_ |\n| | TLS_AES_128_GCM_SHA256 | _C_ | _22_ |\n| | TLS_AES_256_GCM_SHA384 | _C_ | _22_ |\n| | TLS_CHACHA20_POLY1305_SHA256 | _C_ | _22_ |\n| | TLS_AES_128_CCM_SHA256 | _C_ | _22_ |\n| | TLS_AES_128_CCM_8_SHA256 | _C_ | _23_ |\n| [C.1. Random Number Generation and Seeding](https://tools.ietf.org/html/rfc8446#section-C.1) | | _C_ | _22_ |\n| [C.2. Certificates and Authentication](https://tools.ietf.org/html/rfc8446#section-C.2) | | _C_ | _22_ |\n| [C.3. Implementation Pitfalls](https://tools.ietf.org/html/rfc8446#section-C.3) | | _PC_ | _22_ |\n| [C.4. Client Tracking Prevention](https://tools.ietf.org/html/rfc8446#section-C.4) | | _C_ | _22\\.2_ |\n| [C.5. Unauthenticated Operation](https://tools.ietf.org/html/rfc8446#section-C.5) | | _C_ | _22_ |\n| [D.1. Negotiating with an Older Server](https://tools.ietf.org/html/rfc8446#section-D.1) | | _C_ | _22\\.2_ |\n| [D.2. Negotiating with an Older Client](https://tools.ietf.org/html/rfc8446#section-D.2) | | _C_ | _22_ |\n| [D.3. 0-RTT Backward Compatibility](https://tools.ietf.org/html/rfc8446#section-D.3) | | _NC_ | |\n| [D.4. Middlebox Compatibility Mode](https://tools.ietf.org/html/rfc8446#section-D.4) | | _C_ | _23_ |\n| [D.5. Security Restrictions Related to Backward Compatibility](https://tools.ietf.org/html/rfc8446#section-D.5) | | _C_ | _22_ |\n\n_Table: Standards Compliance_","ref":"standards_compliance.html#tls-1-3"}],"content_type":"text/plain","producer":{"name":"ex_doc","version":[48,46,51,52,46,49]}} \ No newline at end of file diff --git a/prs/9045/lib/ssl-11.2.4/doc/html/dist/search_data-CD9C6F07.js b/prs/9045/lib/ssl-11.2.4/doc/html/dist/search_data-CD9C6F07.js deleted file mode 100644 index 14eb32761ecb..000000000000 --- a/prs/9045/lib/ssl-11.2.4/doc/html/dist/search_data-CD9C6F07.js +++ /dev/null @@ -1 +0,0 @@ -searchData={"items":[{"type":"module","doc":"Interface functions for TLS (Transport Layer Security)\nand DTLS (Datagram Transport Layer Security).\n\n> #### Note {: .info }\nThe application's name is still SSL because the first versions of the\nTLS protocol were named SSL (Secure Socket Layer). However, no version\nof the old SSL protocol is supported by this application.\n\nExample:\n```erlang\n1> ssl:start(), ssl:connect(\"google.com\", 443, [{verify, verify_peer},\n {cacerts, public_key:cacerts_get()}]).\n{ok,{sslsocket, [...]}}\n```\n\nSee [Examples](using_ssl.md) for detailed usage and more examples of\nthis API.\n\nSpecial Erlang node configuration for the application can be found in\n[SSL Application](ssl_app.md).","title":"ssl","ref":"ssl.html"},{"type":"function","doc":"Make `Deferred` suites become the least preferred suites.\n\nThe `Deferred` suites will be put at the end of the cipher suite list\n`Suites` after removing them from `Suites` if present. `Deferred` can\nbe a list of cipher suites or a list of filters in which case the\nfilters are used on `Suites` to extract the deferred cipher list.","title":"ssl.append_cipher_suites/2","ref":"ssl.html#append_cipher_suites/2"},{"type":"function","doc":"Lists all available cipher suites corresponding to `Description`.\n\nThe `exclusive` and `exclusive_anonymous` option will exclusively\nlist cipher suites first supported in `Version`, whereas the other options are\ninclusive from the lowest possible version to `Version`. The `all` option\nincludes all suites except anonymous suites. No anonymous suites are supported\nby default.\n\n> #### Note {: .info }\n>\n> TLS-1.3 has no overlapping cipher suites with previous TLS versions, meaning that\n> the result of [`cipher_suites(all, 'tlsv1.3')`](`cipher_suites/2`) contains a separate\n> set of suites that can be used with TLS-1.3 and another set that can be used if a lower\n> version is negotiated. The so-called `PSK` and `SRP` suites (prior to TLS-1.3)\n> need extra configuration to work; namely the option `user_lookup_function`. No\n> anonymous suites are supported by TLS-1.3.\n>\n> Also note that the cipher suites returned by this function are the cipher\n> suites that the OTP SSL application can support provided that they are\n> supported by the crypto library linked with the OTP Crypto application. Use\n> [`ssl:filter_cipher_suites(Suites, [])`](`filter_cipher_suites/2`) to filter\n> the list for the current crypto library. Note that cipher suites may be filtered\n> out because they are too old or too new depending on the crypto library.","title":"ssl.cipher_suites/2","ref":"ssl.html#cipher_suites/2"},{"type":"function","doc":"Equivalent to `cipher_suites/2`, but lists RFC or OpenSSL string names instead of\n[`erl_cipher_suite()`](`t:erl_cipher_suite/0`).","title":"ssl.cipher_suites/3","ref":"ssl.html#cipher_suites/3"},{"type":"function","doc":"Clears the PEM cache.\n\nPEM files, used by SSL API-functions, are cached for performance\nreasons. The cache is automatically checked at regular intervals to\ndetermine whether any cache entries should be invalidated.\n\nThis function provides a way to unconditionally clear the entire cache, thereby\nforcing a reload of previously cached PEM files.","title":"ssl.clear_pem_cache/0","ref":"ssl.html#clear_pem_cache/0"},{"type":"function","doc":"Closes a TLS/DTLS connection.","title":"ssl.close/1","ref":"ssl.html#close/1"},{"type":"function","doc":"Closes or downgrades a TLS connection.\n\nIn the latter case the transport connection will be handed over to the\n`NewController` process after receiving the TLS close alert from the\npeer. The returned transport socket will have the following options\nset: `[{active, false}, {packet, 0}, {mode, binary}]`.\n\nIn case of downgrade, the close function might return some binary data that\nshould be treated by the user as the first bytes received on the downgraded\nconnection.","title":"ssl.close/2","ref":"ssl.html#close/2"},{"type":"function","doc":"","title":"ssl.connect/2","ref":"ssl.html#connect/2"},{"type":"function","doc":"Opens a TLS/DTLS connection.\n\n```erlang\nconnect(TCPSocket, TLSOptions, Timeout).\n```\n\nUpgrades a `gen_tcp` (or equivalent) connected socket to a TLS socket by\nperforming the client-side TLS handshake.\n\n\n```erlang\nconnect(Host, Port, TLSOptions).\n```\n\nOpens a TLS/DTLS connection to `Host`, `Port`. This call is equivalent to:\n\n```erlang\nconnect(Host, Port, TLSOptions, infinity).\n```","title":"ssl.connect/3","ref":"ssl.html#connect/3"},{"type":"function","doc":"Opens a TLS/DTLS connection to `Host`, `Port`.\n\nWhen the `verify` option is set to `verify_peer`, the\n`public_key:pkix_verify_hostname/2` check will be performed in addition to the usual\nX.509-path validation checks. If the check fails, the error `{bad_cert,\nhostname_check_failed}` will be propagated to the path validation fun,\nwhere it is possible to do customized checks\nby using the full possibilities of the `public_key:pkix_verify_hostname/3` API.\nWhen the `server_name_indication` option is provided, its value (the DNS name)\nwill be used as `ReferenceID` to `public_key:pkix_verify_hostname/2`. When no\n`server_name_indication` option is given, the `Host` argument will be used as\nServer Name Indication extension. The `Host` argument will also be used for the\n`public_key:pkix_verify_hostname/2` check. If the `Host` argument is an\n[`inet:ip_address()`](`t:inet:ip_address/0`) the `ReferenceID` used for the\ncheck will be `{ip, Host}`; otherwise `dns_id` will be assumed with a fallback to\n`ip` if that fails.\n\n> #### Note {: .info }\n>\n> According to good practices, certificates should not use IP addresses as\n> \"server names\", especially outside a closed network.\n\nIf the `{handshake, hello}` option is used, the handshake is paused after\nreceiving the server hello message and the success response is\n`{ok, SslSocket, Ext}` instead of `{ok, SslSocket}`. Thereafter the handshake is\ncontinued or canceled by calling `handshake_continue/3` or `handshake_cancel/1`.\n\nIf the `active` option is set to `once`, `true`, or an integer value, the process\nowning the SSL socket will receive messages of type\n[`active_msgs()`](`t:active_msgs/0`).","title":"ssl.connect/4","ref":"ssl.html#connect/4"},{"type":"function","doc":"Returns the most relevant information about the connection.\n\nSome items that are undefined will be filtered out. No values\nthat affect the security of the connection will be returned.\n\n> #### Note {: .info }\n>\n> The legacy `cipher_suite` item was removed in OTP 23. Previously it returned\n> the cipher suite in its (undocumented) legacy format. It is replaced by\n> `selected_cipher_suite`.","title":"ssl.connection_information/1","ref":"ssl.html#connection_information/1"},{"type":"function","doc":"Returns the requested information items about the connection if they are\ndefined.\n\nNote that the values for `client_random`, `server_random`, `master_secret`, and `keylog`\naffect the security of connection.\n\nIn order to retrieve `keylog` and other secret information from a TLS 1.3\nconnection, the `keep_secrets` option must be configured in advance and\nset to `true`.\n\n> #### Note {: .info }\n>\n> If only undefined options are requested the resulting list can be empty.","title":"ssl.connection_information/2","ref":"ssl.html#connection_information/2"},{"type":"function","doc":"Assigns a new controlling process to the SSL socket.\n\nA controlling process is the owner of an SSL socket and receives all\nmessages from the socket.","title":"ssl.controlling_process/2","ref":"ssl.html#controlling_process/2"},{"type":"function","doc":"Returns a list of all supported elliptic curves, including legacy\ncurves, for all TLS/DTLS versions prior to TLS-1.3.","title":"ssl.eccs/0","ref":"ssl.html#eccs/0"},{"type":"function","doc":"Returns the elliptic curves supported by default for `Version`.\n\nThis is a subset of what `eccs/0` returns.","title":"ssl.eccs/1","ref":"ssl.html#eccs/1"},{"type":"function","doc":"","title":"ssl.export_key_materials/4","ref":"ssl.html#export_key_materials/4"},{"type":"function","doc":"Uses a Pseudo-Random Function (PRF prior to TLS-1.3) or a Key\nDerivation Function (HKDF in TLS-1.3) for a TLS connection to\ngenerate and export keying materials.\n\nIn TLS-1.3, using `no_context` is equivalent to specifying an empty\ncontext (an empty binary). Prior to TLS-1.3, `no_context` and an empty\ncontext will produce different results.\n\nThe `ConsumeSecret` argument is relevant only in TLS-1.3, causing the\nTLS-1.3 `exporter_master_secret` to be consumed, thereby making it\nunavailable and increasing security. Further attempts to call this\nfunction will fail.","title":"ssl.export_key_materials/5","ref":"ssl.html#export_key_materials/5"},{"type":"function","doc":"Removes cipher suites if any of the filter functions returns `false` for any part\nof the cipher suite.\n\nIf no filter function is supplied for some part, the default behavior\ntreats it as a filter function that returns `true`. For\nexamples, see [Customizing cipher suites\n](using_ssl.md#customizing-cipher-suites). Additionally, this function\nalso filters the cipher suites to exclude cipher suites not supported\nby the crypto library used by the OTP Crypto application, meaning that\n[`ssl:filter_cipher_suites(Suites, [])`](`filter_cipher_suites/2`)\nis equivalent to applying only the filters for crypto library support.","title":"ssl.filter_cipher_suites/2","ref":"ssl.html#filter_cipher_suites/2"},{"type":"function","doc":"Presents the error returned by an SSL function as a printable string.","title":"ssl.format_error/1","ref":"ssl.html#format_error/1"},{"type":"function","doc":"Gets the values of the specified socket options.","title":"ssl.getopts/2","ref":"ssl.html#getopts/2"},{"type":"function","doc":"Get statistics for the underlying socket.","title":"ssl.getstat/1","ref":"ssl.html#getstat/1"},{"type":"function","doc":"Get one or more statistic values for the underlying socket.\n\nSee `inet:getstat/2` for further details.","title":"ssl.getstat/2","ref":"ssl.html#getstat/2"},{"type":"function","doc":"Returns all supported groups in TLS 1.3.\n\nExisted since OTP 22.0; documented as of OTP 27.","title":"ssl.groups/0","ref":"ssl.html#groups/0"},{"type":"function","doc":"Returns default supported groups in TLS 1.3.\n\nExisted since OTP 22.0; documented as of OTP 27.","title":"ssl.groups/1","ref":"ssl.html#groups/1"},{"type":"function","doc":"","title":"ssl.handshake/1","ref":"ssl.html#handshake/1"},{"type":"function","doc":"Performs the TLS/DTLS server-side handshake.\n\nIf the second argument is a timeout value:\n\n```erlang\nhandshake(HsSocket, Timeout).\n```\n\nthis call is equivalent to:\n\n```erlang\nhandshake(HsSocket, [], Timeout).\n```\n\nOtherwise, if the second argument is a list of options:\n\n\n```erlang\nhandshake(HsSocket, Options).\n```\nthis call is equivalent to:\n\n```erlang\nhandshake(HsSocket, Options, infinity).\n```","title":"ssl.handshake/2","ref":"ssl.html#handshake/2"},{"type":"function","doc":"Performs the TLS/DTLS server-side handshake.\n\nReturns a new TLS/DTLS socket if the handshake is successful.\n\nIf `Socket` is a ordinary [`socket()`](`t:socket/0`), upgrades a\n`gen_tcp` or equivalent socket to an SSL socket by performing the\nTLS server-side handshake and returning a TLS socket.\n\n> #### Note {: .info }\nThe ordinary `Socket` must be in passive mode (`{active, false}`)\nbefore calling this function and before the client tries to connect\nwith TLS; otherwise, the behavior of this function is undefined. The\nbest way to ensure this is to create the ordinary listen socket in\npassive mode.\n\nIf `Socket` is an [`sslsocket()`](`t:sslsocket/0`), provides extra\nTLS/DTLS options to those specified in `listen/2` and then performs\nthe TLS/DTLS handshake. Returns a new TLS/DTLS socket if the handshake\nis successful.\n\n> #### Warning {: .warning }\nNot setting the timeout makes the server more vulnerable to Denial of\nService (DoS) attacks.\n\nIf option `{handshake, hello}` is specified the handshake is paused after\nreceiving the client hello message and the success response is\n`{ok, SslSocket, Ext}` instead of `{ok, SslSocket}`. Thereafter the handshake is\ncontinued or canceled by calling `handshake_continue/3` or `handshake_cancel/1`.\n\nIf option `active` is set to `once`, `true`, or an integer value, the process\nowning the [`sslsocket()`](`t:sslsocket/0`) will receive messages of type\n[`active_msgs()`](`t:active_msgs/0`).","title":"ssl.handshake/3","ref":"ssl.html#handshake/3"},{"type":"function","doc":"Cancel the handshake with a fatal `USER_CANCELED` alert.","title":"ssl.handshake_cancel/1","ref":"ssl.html#handshake_cancel/1"},{"type":"function","doc":"","title":"ssl.handshake_continue/2","ref":"ssl.html#handshake_continue/2"},{"type":"function","doc":"Continue the TLS handshake, possibly with new, additional, or changed options.","title":"ssl.handshake_continue/3","ref":"ssl.html#handshake_continue/3"},{"type":"function","doc":"Creates an SSL listen socket.","title":"ssl.listen/2","ref":"ssl.html#listen/2"},{"type":"function","doc":"Returns the protocol negotiated through ALPN or NPN extensions.","title":"ssl.negotiated_protocol/1","ref":"ssl.html#negotiated_protocol/1"},{"type":"function","doc":"The peer certificate is returned as a DER-encoded binary.\n\nThe certificate can be\ndecoded with `public_key:pkix_decode_cert/2`. Suggested further reading about\ncertificates is [Public_Key User's Guide](`e:public_key:public_key_records.md`)\nand [SSL User's Guide](standards_compliance.md).","title":"ssl.peercert/1","ref":"ssl.html#peercert/1"},{"type":"function","doc":"Returns the address and port number of the peer.","title":"ssl.peername/1","ref":"ssl.html#peername/1"},{"type":"function","doc":"Make `Preferred` suites become the most preferred suites.\n\nThe `Preferred` suites will be put at the head of the cipher suite\nlist `Suites` after removing them from `Suites` if\npresent. `Preferred` can be a list of cipher suites or a list of\nfilters in which case the filters are used on `Suites` to extract the\npreferred cipher list.","title":"ssl.prepend_cipher_suites/2","ref":"ssl.html#prepend_cipher_suites/2"},{"type":"function","doc":"Uses the Pseudo-Random Function (PRF) of a TLS session to generate extra key\nmaterial.\n\nIt either takes user-generated values for `Secret` and `Seed` or atoms\ndirecting it to use a specific value from the session security parameters.\n\n> #### Note {: .info }\n\nThis function is replaced by `export_key_materials/4`, the officially\ndocumented API function since OTP 27, which is equivalent to\n[`prf(TLSSocket, master_secret, Label, [client_random, server_random,\nContext], WantedLength)`](`prf/5`). Other ways of calling this\nfunction were for testing purposes only and has no use case. When\ncalled in a TLS-1.3 context it will now behave as\n[`export_key_materials(TLSSocket, [Label], [Context],\n[WantedLength])`](`export_key_materials/4`).","title":"ssl.prf/5","ref":"ssl.html#prf/5"},{"type":"function","doc":"","title":"ssl.recv/2","ref":"ssl.html#recv/2"},{"type":"function","doc":"Receives a packet from a socket in passive mode.\n\nA closed socket is indicated by return value `{error, closed}`.\nArgument `Length` is meaningful only when the socket is in mode `raw`\nand denotes the number of bytes to read. If `Length` is zero, all\navailable bytes are returned. If `Length` is greater than zero,\nexactly `Length` bytes are returned, or an error; possibly discarding\nless than `Length` bytes of data when the socket gets closed from\nthe other side.\n\nOptional argument `Timeout` specifies a time-out in milliseconds. The default\nvalue is `infinity`.","title":"ssl.recv/3","ref":"ssl.html#recv/3"},{"type":"function","doc":"Initiates a new handshake.\n\nA notable return value is `{error, renegotiation_rejected}` indicating\nthat the peer refused to go through with the renegotiation, but the\nconnection is still active using the previously negotiated session.\n\nTLS-1.3 has removed the renegotiation feature from earlier TLS\nversions and instead adds a new feature called key update, which\nreplaces the most important part of renegotiation: the refreshing of\nsession keys. This is triggered automatically after reaching a\nplaintext limit and can be configured using the `key_update_at` option\nin `t:common_option_tls13/0`.","title":"ssl.renegotiate/1","ref":"ssl.html#renegotiate/1"},{"type":"function","doc":"Writes `Data` to `SslSocket`.\n\nA notable return value is `{error, closed}` indicating that the socket is\nclosed.","title":"ssl.send/2","ref":"ssl.html#send/2"},{"type":"function","doc":"Sets options according to `Options` for socket `SslSocket`.","title":"ssl.setopts/2","ref":"ssl.html#setopts/2"},{"type":"function","doc":"Immediately closes a socket in one or two directions.\n\n`How == write` means closing the socket for writing, but reading from\nit is still possible.\n\nTo handle siutations where the peer has performed a shutdown on the\nwrite side, option `{exit_on_close, false}` is useful.","title":"ssl.shutdown/2","ref":"ssl.html#shutdown/2"},{"type":"function","doc":"Lists all available signature algorithms corresponding to `Description`.\n\nThe `exclusive` option will exclusively list algorithms or algorithm schemes for\nthat protocol version, whereas the `default` and `all` options lists the\ncombined list to support the range of protocols from (D)TLS-1.2, the first\nversion to support configuration of the signature algorithms, to `Version`.\n\nExample:\n\n```erlang\n1> ssl:signature_algs(default, 'tlsv1.3').\n[eddsa_ed25519,eddsa_ed448,ecdsa_secp521r1_sha512,\necdsa_secp384r1_sha384,ecdsa_secp256r1_sha256,\nrsa_pss_pss_sha512,rsa_pss_pss_sha384,rsa_pss_pss_sha256,\nrsa_pss_rsae_sha512,rsa_pss_rsae_sha384,rsa_pss_rsae_sha256,\nrsa_pkcs1_sha512,rsa_pkcs1_sha384,rsa_pkcs1_sha256,\n{sha512,ecdsa},\n{sha384,ecdsa},\n{sha256,ecdsa}]\n\n2> ssl:signature_algs(all, 'tlsv1.3').\n[eddsa_ed25519,eddsa_ed448,ecdsa_secp521r1_sha512,\necdsa_secp384r1_sha384,ecdsa_secp256r1_sha256,\nrsa_pss_pss_sha512,rsa_pss_pss_sha384,rsa_pss_pss_sha256,\nrsa_pss_rsae_sha512,rsa_pss_rsae_sha384,rsa_pss_rsae_sha256,\nrsa_pkcs1_sha512,rsa_pkcs1_sha384,rsa_pkcs1_sha256,\n{sha512,ecdsa},\n{sha384,ecdsa},\n{sha256,ecdsa},\n{sha224,ecdsa},\n{sha224,rsa},\n{sha,rsa},\n{sha,dsa}]\n\n3> ssl:signature_algs(exclusive, 'tlsv1.3').\n[eddsa_ed25519,eddsa_ed448,ecdsa_secp521r1_sha512,\necdsa_secp384r1_sha384,ecdsa_secp256r1_sha256,\nrsa_pss_pss_sha512,rsa_pss_pss_sha384,rsa_pss_pss_sha256,\nrsa_pss_rsae_sha512,rsa_pss_rsae_sha384,rsa_pss_rsae_sha256]\n```\n\n> #### Note {: .info }\n>\n> Some TLS-1-3 scheme names overlap with TLS-1.2 algorithm-tuple-pair-names and\n> then TLS-1.3 names will be used, for example `rsa_pkcs1_sha256` instead of\n> `{sha256, rsa}`. These are legacy algorithms in TLS-1.3 that apply only to\n> certificate signatures in this version of the protocol.","title":"ssl.signature_algs/2","ref":"ssl.html#signature_algs/2"},{"type":"function","doc":"Returns the local address and port number of socket `SslSocket`.","title":"ssl.sockname/1","ref":"ssl.html#sockname/1"},{"type":"function","doc":"","title":"ssl.start/0","ref":"ssl.html#start/0"},{"type":"function","doc":"Starts the SSL application.","title":"ssl.start/1","ref":"ssl.html#start/1"},{"type":"function","doc":"Stops the SSL application.","title":"ssl.stop/0","ref":"ssl.html#stop/0"},{"type":"function","doc":"Converts an RFC or OpenSSL name string to an `t:erl_cipher_suite/0`\n\nReturns an error if the cipher suite is not supported or the name is\nnot a valid cipher suite name.","title":"ssl.str_to_suite/1","ref":"ssl.html#str_to_suite/1"},{"type":"function","doc":"Converts an [`erl_cipher_suite()`](`t:erl_cipher_suite/0`) value to\nan OpenSSL name string.\n\nPRE TLS-1.3 these names differ for RFC names","title":"ssl.suite_to_openssl_str/1","ref":"ssl.html#suite_to_openssl_str/1"},{"type":"function","doc":"Converts an [`erl_cipher_suite()`](`t:erl_cipher_suite/0`) value to an RFC\nname string.","title":"ssl.suite_to_str/1","ref":"ssl.html#suite_to_str/1"},{"type":"function","doc":"","title":"ssl.transport_accept/1","ref":"ssl.html#transport_accept/1"},{"type":"function","doc":"Accepts an incoming connection request on a listen socket.\n\n`ListenSocket` must be a socket returned from `listen/2`. The socket\nreturned is to be passed to [`handshake/1,2,3`](`handshake/3`) to\ncomplete the handshake and establish the TLS/DTLS connection.\n\n> #### Warning {: .warning }\n>\n> Most API functions require that the TLS/DTLS connection is established to work\n> as expected.\n\nThe accepted socket inherits the options set for `ListenSocket` in `listen/2`.\n\nThe default value for `Timeout` is `infinity`. If `Timeout` is specified and no\nconnection is accepted within the given time, `{error, timeout}` is returned.","title":"ssl.transport_accept/2","ref":"ssl.html#transport_accept/2"},{"type":"function","doc":"Create new session keys.\n\nThere are cryptographic limits on the amount of plaintext which can be safely\nencrypted under a given set of keys. If the amount of data surpasses those\nlimits, a key update is triggered and a new set of keys are installed. See also\nthe `key_update_at` option in `t:common_option_tls13/0`.\n\nThis function can be used to explicitly start a key update on a TLS-1.3\nconnection. There are two types of key updates: if `Type` is `write`,\nonly the writing key is updated; if `Type` is `read_write`, both the\nreading and writing keys are updated.","title":"ssl.update_keys/2","ref":"ssl.html#update_keys/2"},{"type":"function","doc":"Lists information, mainly concerning TLS/DTLS versions, in runtime for debugging\nand testing purposes.\n\n- **`app_vsn`** - The application version of the SSL application.\n\n- **`supported`** - TLS versions supported with current application environment\n and crypto library configuration. Overridden by a version option on\n [`connect/2,3,4`](`connect/2`), `listen/2`, and\n [`handshake/2,3`](`handshake/2`). For the negotiated TLS version, see\n [`connection_information/1`](`connection_information/1`).\n\n- **`supported_dtls`** - DTLS versions supported with current application\n environment and crypto library configuration. Overridden by a version option\n on [`connect/2,3,4`](`connect/2`), `listen/2`, and\n [`handshake/2,3`](`handshake/2`). For the negotiated DTLS version, see\n [`connection_information/1`](`connection_information/1`).\n\n- **`available`** - All TLS versions supported with the linked crypto library.\n\n- **`available_dtls`** - All DTLS versions supported with the linked crypto\n library.\n\n- **`implemented`** - All TLS versions supported by the SSL application if\n linked with a crypto library with the necessary support.\n\n- **`implemented_dtls`** - All DTLS versions supported by the SSL application if\n linked with a crypto library with the necessary support.","title":"ssl.versions/0","ref":"ssl.html#versions/0"},{"type":"type","doc":"The type for the messages that are delivered to the owner of a\nTLS/DTLS socket in active mode.\n\nThe `ssl_error` reason may convey a TLS protocol alert if such an event occurs\nafter the connection has been established. The most common case when this will\nhappen is on the client side when a TLS-1.3 server requests a client certificate\nand the provided certificate is not accepted by the server, as it will be\nverified after the server has sent its last handshake message.\n\nThe `ssl_passive` message is sent only when the socket is in `{active, N}` mode\nand the counter has dropped to 0. It indicates that the socket has transitioned\nto passive (`{active, false}`) mode.","title":"ssl.active_msgs/0","ref":"ssl.html#t:active_msgs/0"},{"type":"type","doc":"Claim an intermediate CA in the chain as trusted.\n\n```erlang\nfun(Chain::[public_key:der_encoded()]) ->\n {trusted_ca, DerCert::public_key:der_encoded()} | unknown_ca.\n```\n\nTLS then uses `public_key:pkix_path_validation/3` with the selected CA\nas the trusted anchor and verifies the rest of the chain.","title":"ssl.anchor_fun/0","ref":"ssl.html#t:anchor_fun/0"},{"type":"type","doc":"Configuration of the entity certificate and its corresponding key.\n\nA certificate (or possibly a list including the certificate and its\nchain certificates, where the entity certificate must be the first\nelement in the list or the first entry in the file) and its associated\nkey. For the PEM file format, there can also be a password associated\nwith the file containing the key.\n\nFor maximum interoperability, the certificates in the chain should be\nin the correct order, as the chain will be sent as-is to the peer. If\nchain certificates are not provided, certificates from the configured\ntrusted CA certificates will be used to construct the chain. See\n[`client_option_cert()`](`t:client_option_cert/0`) and\n[`server_option_cert()`](`t:server_option_cert/0`) for more\ninformation.","title":"ssl.cert_key_conf/0","ref":"ssl.html#t:cert_key_conf/0"},{"type":"type","doc":"Cipher algorithms that can be used for payload encryption.","title":"ssl.cipher/0","ref":"ssl.html#t:cipher/0"},{"type":"type","doc":"Filter that allows you to customize cipher suite list.","title":"ssl.cipher_filters/0","ref":"ssl.html#t:cipher_filters/0"},{"type":"type","doc":"A list of cipher suites that should be supported.\n\nFunction [ssl:cipher_suites/2 ](`cipher_suites/2`) can be used to find all\ncipher suites that are supported by default and all cipher suites that can be\nconfigured.\n\nIf you compose your own `t:cipher_suites/0` make sure they are\nfiltered for crypto library support using [ssl:filter_cipher_suites/2\n](`filter_cipher_suites/2`).\n\nThe following function can help creating customized cipher suite lists:\n\n- [ssl:append_cipher_suites/2 ](`append_cipher_suites/2`)\n- [ssl:prepend_cipher_suites/2](`prepend_cipher_suites/2`)\n- [ssl:suite_to_str/1](`suite_to_str/1`)\n- [ssl:str_to_suite/1](`str_to_suite/1`)\n- [ssl:suite_to_openssl_str/1](`suite_to_openssl_str/1`)\n\n> #### Note {: .info }\nNote that TLS-1.3 and TLS-1.2 use different sets of cipher suites. To\nsupport both versions, cipher suites from both sets need to be\nincluded. If the supplied list does not comply with the configured\nversions or crypto library, that is, resulting in an empty list, the option\nwill fall back to its appropriate default value for the configured\nversions.\n\nNon-default cipher suites, including anonymous cipher suites (prior to\nTLS 1.3), are supported for interoperability and testing\npurposes. These can be used by adding them to your cipher suite\nlist. Note that they also need to be supported and enabled by the peer\nto be actually used, and they may require additional configuration;\nsee [`srp_param_type()`](`t:srp_param_type/0`).","title":"ssl.cipher_suites/0","ref":"ssl.html#t:cipher_suites/0"},{"type":"type","doc":"Cipher suite formats.\n\nFor backwards compatibility, cipher suites can be configured as a\ncolon-separated string of cipher suite RFC names (or even old OpenSSL\nnames). However, a more flexible approach is to use utility functions\ntogether with [`cipher_filters()`](`t:cipher_filters/0`) if a customized\ncipher suite option is needed.","title":"ssl.ciphers/0","ref":"ssl.html#t:ciphers/0"},{"type":"type","doc":"The following options are specific to the client side, or have\ndifferent semantics for the client and server:\n\n- **`{alpn_advertised_protocols, AppProtocols}`** - Application layer protocol\n\n The list of protocols supported by the client to be sent to the server to be\n used for an Application-Layer Protocol Negotiation (ALPN). If the server\n supports ALPN, it will choose a protocol from this list; otherwise it will\n fail the connection with a `no_application_protocol` alert. A server that does\n not support ALPN will ignore this value. The list of protocols must not contain\n an empty binary.\n\n- **`{max_fragment_length, MaxLen}`** - Max fragment length extension\n\n Specifies the maximum fragment length the client is prepared to accept from the\n server. See [RFC 6066](http://www.ietf.org/rfc/rfc6066.txt).","title":"ssl.client_option/0","ref":"ssl.html#t:client_option/0"},{"type":"type","doc":"Certificate-related options specific to the client side, or with\ndifferent semantics for the client and server.\n\n- **`{verify, Verify}`** - Verification of certificates\n\n This option specifies whether certificates are to be verified.\n\n If `Verify` is `verify_peer`, which is the default, it is required\n to also provide one of the options `cacerts` or `cacertfile` in\n order for the certificate verification to succeed. For example, an\n HTTPS client can use option `{cacerts, public_key:cacerts_get()}` to\n use the trusted CA certificates provided by the operating system.\n\n If `Verify` is `verify_none`, all X.509-certificate path\n validation errors will be ignored.\n\n > #### Change {: .info }\n >\n > The default for `Verify` was changed to `verify_peer` in\n > Erlang/OTP 26.\n\n- **`{cacerts, CACerts}`** - Trusted certificates\n\n The DER-encoded trusted certificates. If this option is supplied it overrides\n option `cacertfile`.\n\n Function `public_key:cacerts_get/0` can be used to retrieve to the\n trusted CA certificates provided by the operating system.\n\n- **`{cacertfile, CertFile}`** - End entity certificate\n\n Path to a file containing PEM-encoded CA certificates. The CA certificates are\n used during server authentication and when building the client certificate\n chain.\n\n > #### Note {: .info }\n >\n > When PEM caching is enabled, files provided with this option will be checked\n > for updates at fixed time intervals specified by the\n > [ssl_pem_cache_clean](ssl_app.md#configuration) environment parameter.\n\n\n- **`{server_name_indication, SNI}`** - Server Name Indication extension\n\n Specify the hostname to be used in TLS Server Name Indication extension. If not\n specified it will default to the `Host` argument of\n [connect/3,4](`connect/3`) unless it is of type [`inet:ip_address()`](`t:inet:ip_address/0`).\n The hostname will also be used in the hostname verification of the peer\n certificate using `public_key:pkix_verify_hostname/2`.\n The special value `disable` prevents the Server Name Indication extension from\n being sent and disables the hostname verification check.\n\n- **`{customize_hostname_check, HostNameCheckOpts}`** - Customization option\n\n Customizes the hostname verification of the peer certificate, as various\n protocols that use TLS, such as HTTP or LDAP, may require different approaches. For\n example, here is how to use standard hostname checking for HTTPS implemented in\n [Public_Key](`e:public_key:public_key_app.md`):\n\n ```erlang\n {customize_hostname_check, [{match_fun, public_key:pkix_verify_hostname_match_fun(https)}]}\n ```\n\n For futher description of the customize options, see\n `public_key:pkix_verify_hostname/3`.\n\n- **`{client_certificate_authorities, UseCertAuth}`** - Inter-op hint option\n\n If `UseCertAuth` is set to `true`, sends the certificate authorities\n extension in the TLS-1.3 client hello. The default is `false`. Note\n that setting `UseCertAuth` to `true` can result in a significant\n overhead if there exists many trusted CA certificates. (Since\n Erlang/OTP 24.3.)\n\n- **`{stapling, Stapling}`** - Certificate revocation check option\n\n If `Stapling` is atom `staple` or a map, OCSP stapling will be\n enabled, meaning that an extension of type \"status_request\" will be\n included in the client hello to indicate the desire to receive\n certificate status information.\n\n If `Stapling` is set to `no_staple` (the default), OCSP stapling will be disabled.\n\n > #### Note {: .info }\n >\n > Even if requested by the client, the OCSP response might not be\n > provided by the server. In such event, SSL will proceed with\n > the handshake and generate a `{missing, stapling_response}` logger\n > event.\n\n When `Stapling` is given as a map, boolean `ocsp_nonce` key can\n indicate whether an OCSP nonce should be requested by the client\n (default is `false`).\n\n > #### Note {: .info }\n >\n > The OCSP response can be provided without a nonce value — even if it was requested\n > by the client. In such cases SSL will proceed with the handshake and generate\n > a `{missing, ocsp_nonce}` logger event.","title":"ssl.client_option_cert/0","ref":"ssl.html#t:client_option_cert/0"},{"type":"type","doc":"Legacy client options.\n\n- **`{client_preferred_next_protocols, NextAppProtocols}`** - Next Protocol Negotiation\n\n ALPN (Application-Layer Protocol Negotiation)\n deprecates NPN (Next Protocol Negotiation) and this option.\n\n Indicates that the client wants to perform Next Protocol Negotiation.\n\n If `Precedence` is `server`, the negotiated protocol is the first protocol to be\n shown on the server advertised list that is also on the client preference\n list.\n\n If `Precedence` is `client`, the negotiated protocol is the first protocol to be\n shown on the client preference list that is also on the server advertised\n list.\n\n If the client does not support any of the server advertised protocols or the\n server does not advertise any protocols, the client falls back to the first\n protocol in its list or to the default protocol (if a default is supplied). If\n the server does not support Next Protocol Negotiation, the connection terminates\n if no default protocol is supplied.","title":"ssl.client_option_legacy/0","ref":"ssl.html#t:client_option_legacy/0"},{"type":"type","doc":"Options only relevant to TLS versions prior to TLS-1.3.\n\n- **`{reuse_session, SessionRef}`** - Explicit session reuse\n\n Reuses a specific session.\n\n Since Erlang/OTP 21.3, if the session was saved earlier using option\n `{reuse_sessions, save}`, the session can be referred by its session ID.\n\n Since Erlang/OTP 22.3, the session can be explicitly specified by\n its session ID and associated data.\n\n See also\n [SSL User's Guide, Session Reuse pre TLS 1.3.](using_ssl.md#session-reuse-prior-to-tls-1-3)\n\n- **`{reuse_sessions, Reuse}`** - Enables later session reuse\n\n When `Reuse` is set to `save`, a new connection will be negotiated and saved for later\n reuse. The session ID can be fetched with `connection_information/2` and used\n with the client option `reuse_session`.\n\n When `Reuse` is set to `true`, automated session reuse will be\n performed, if possible. If a new session is created, and is unique in regard to previous\n stored sessions, it will be saved for possible later reuse.\n\n Since: OTP 21.3.\n\n- **`{psk_identity, PskID}`** - Option for use with PSK cipher suites\n\n Specifies the identity the client presents to the server. The matching secret is\n found by the fun given in the `user_lookup_fun` option.\n\n- **`{srp_identity, SrpID}`** - Option for use SRP cipher suites\n\n Specifies the username and password to use to authenticate to the server.\n\n- **`{fallback, LegacyFallback}`** - Inter-op legacy client option\n\n Send special cipher suite TLS_FALLBACK_SCSV to avoid an undesired TLS version\n downgrade. Defaults to `false`.\n\n > #### Warning {: .warning }\n >\n > This option is not needed in normal TLS usage and must not be used to\n > implement new clients. However, legacy clients that retries connections in the\n > following manner:\n >\n > `ssl:connect(Host, Port, [...{versions, ['tlsv2', 'tlsv1.1', 'tlsv1']}])`\n >\n > `ssl:connect(Host, Port, [...{versions, [tlsv1.1', 'tlsv1']}, {fallback, true}])`\n >\n > `ssl:connect(Host, Port, [...{versions, ['tlsv1']}, {fallback, true}])`\n >\n > can use it to avoid undesired TLS version downgrade. Note that\n > TLS_FALLBACK_SCSV must also be supported by the server for the prevention to\n > work.","title":"ssl.client_option_pre_tls13/0","ref":"ssl.html#t:client_option_pre_tls13/0"},{"type":"type","doc":"Options only relevant for TLS-1.3.\n\n- **`{session_tickets, SessionTickets}`** - Use of session tickets\n\n Configures the session ticket functionality. Allowed values are `disabled`,\n `manual`, and `auto`. If it is set to `manual` the client will send the ticket\n information to user process in a 3-tuple:\n\n ```erlang\n {ssl, session_ticket, {SNI, TicketData}}\n ```\n\n where `SNI` is the ServerNameIndication and `TicketData` is the extended ticket\n data that can be used in subsequent session resumptions.\n\n If it is set to `auto`, the client automatically handles received tickets and\n tries to use them when making new TLS connections (session resumption with\n pre-shared keys).\n\n Ticket lifetime, the number of tickets sent by the server, and the\n maximum number of tickets stored by the server in stateful mode are configured\n by [application variables](ssl_app.md#configuration).\n\n See also\n [SSL User's Guide, Session Tickets and Session Resumption in TLS 1.3](using_ssl.md#session-tickets-and-session-resumption-in-tls-1-3).\n\n- **`{use_ticket, Tickets}`**\n\n Configures the session tickets to be used for session resumption. It is a\n mandatory option in `manual` mode (`{session_tickets, manual}`).\n\n > #### Note {: .info }\n >\n > Session tickets are only sent to the user if option `session_tickets` is set to\n > `manual`\n >\n > This option is supported by TLS-1.3. See also\n > [SSL User's Guide, Session Tickets and Session Resumption in TLS 1.3](using_ssl.md#session-tickets-and-session-resumption-in-tls-1-3).\n\n- **`{early_data, EarlyData}`**\n\n Configures the early data to be sent by the client.\n\n To verify that the server has the intention to process the early\n data, the following tuple is sent to the user process:\n\n ```erlang\n {ssl, SslSocket, {early_data, Result}}\n ```\n\n where `Result` is either `accepted` or `rejected`.\n\n > #### Warning {: .warning }\n >\n > It is the responsibility of the user to handle rejected `EarlyData` and to\n > resend when appropriate.\n\n- **`{middlebox_comp_mode, MiddleBoxMode}`**\n\n Configures the middlebox compatibility mode for a TLS-1.3 connection.\n\n A significant number of middleboxes misbehave when a TLS-1.3\n connection is negotiated. Implementations can increase the chance of\n making connections through those middleboxes by adapting the TLS-1.3\n handshake to resemble that of a TLS-1.2 handshake.\n\n The middlebox compatibility mode is enabled (`true`) by default.","title":"ssl.client_option_tls13/0","ref":"ssl.html#t:client_option_tls13/0"},{"type":"type","doc":"Options common to both client and server side.\n\n- **`{protocol, Protocol}`** - Choose TLS or DTLS protocol for the transport layer security.\n\n Defaults to `tls`.\n\n- **`{handshake, Completion}`** - Possibly pause handshake at hello stage.\n\n Defaults to `full`. If `hello` is specified the handshake will pause\n after the hello message, allowing the user to make decisions based\n on hello extensions before continuing or aborting the handshake by\n calling `handshake_continue/3` or `handshake_cancel/1`.\n\n- **`{keep_secrets, KeepSecrets}`** - Configures a TLS 1.3 connection for keylogging.\n\n In order to retrieve keylog information on a TLS 1.3 connection, it must be\n configured in advance to keep `client_random` and various handshake secrets.\n\n The `keep_secrets` functionality is disabled (`false`) by default.\n\n Added in OTP 23.2.\n\n- **`{max_handshake_size, HandshakeSize}`** - Limit the acceptable handshake packet size.\n\n Used to limit the size of valid TLS handshake packets to avoid DoS\n attacks.\n\n Integer (24 bits, unsigned). Defaults to `256*1024`.\n\n- **`{hibernate_after, HibernateTimeout}`** - Hibernate inactive connection processes.\n\n When an integer-value is specified, the TLS/DTLS connection goes into hibernation\n after the specified number of milliseconds of inactivity, thus reducing its\n memory footprint. When not specified the process never goes into hibernation.\n\n- **`{log_level, Level}`** - Specifies the log level for a TLS/DTLS connection.\n\n Alerts are logged on `notice`\n level, which is the default level. The level `debug` triggers verbose logging of\n TLS/DTLS protocol messages. See also [SSL Application](ssl_app.md)\n\n- **`{receiver|sender_spawn_opts, SpawnOpts}`** - Configure erlang spawn opts.\n\n Configures spawn options of TLS sender and receiver processes.\n\n Setting up garbage collection options can be helpful for trade-offs between CPU\n usage and memory usage. See `erlang:spawn_opt/2`.\n\n For connections using Erlang distribution, the default sender option\n is `[...{priority, max}]`; this priority option cannot be changed. For all\n connections, `...link` is added to receiver and cannot be changed.","title":"ssl.common_option/0","ref":"ssl.html#t:common_option/0"},{"type":"type","doc":"Common certificate related options to both client and server.\n\n- **`{certs_keys, CertsKeys}`** - At least one certificate and key pair.\n\n A list of a certificate (or possible a certificate and its chain)\n and the associated key of the certificate that can be used to\n authenticate the client or the server. The certificate key pair that\n is considered best and matches negotiated parameters for the\n connection will be selected.\n\n The different signature algorithms are prioritized in the following\n order: `eddsa`, `ecdsa`, `rsa_pss_pss`, `rsa`, and `dsa`. If more\n than one key is supplied for the same signature algorithm, they will\n be prioritized by strength (except for _engine keys_; see the next\n paragraph). This offers flexibility to, for instance, configure a\n newer certificate that is expected to be used in most cases, and an\n older but acceptable certificate that will only be used to\n communicate with legacy systems. Note that there is a trade off\n between the induced overhead and the flexibility; thus, alternatives\n should be chosen for good reasons.\n\n _Engine keys_ will be favored over other keys. As engine keys cannot\n be inspected, supplying more than one engine key makes no sense.\n\n When this option is specified it overrides all single certificate\n and key options. For examples, see the [User's Guide](using_ssl.md).\n\n > #### Note {: .info }\n >\n > `eddsa` certificates are only supported by TLS-1.3 implementations that do not support `dsa`\n > certificates. `rsa_pss_pss` (RSA certificates using Probabilistic Signature\n > Scheme) are supported in TLS-1.2 and TLS-1.3, but some TLS-1.2 implementations\n > do not support `rsa_pss_pss`.\n\n- **`{depth, AllowedCertChainLen}`** - Limits the accepted number of certificates in the certificate chain.\n\n Maximum number of non-self-issued intermediate certificates that can follow the\n peer certificate in a valid certification path. So, if depth is 0 the PEER must\n be signed by the trusted ROOT-CA directly; if 1 the path can be PEER, CA,\n ROOT-CA; if 2 the path can be PEER, CA, CA, ROOT-CA, and so on. The default\n value is 10. Used to mitigate DoS attack possibilities.\n\n- **`{verify_fun, Verify}`** - Customize certificate path validation\n\n The verification fun is to be defined as follows:\n\n ```erlang\n fun(OtpCert :: #'OTPCertificate'{},\n Event, InitialUserState :: term()) ->\n\t{valid, UserState :: term()} |\n\t{fail, Reason :: term()} | {unknown, UserState :: term()}.\n\n fun(OtpCert :: #'OTPCertificate'{}, DerCert :: public_key:der_encoded(),\n Event, InitialUserState :: term()) ->\n\t{valid, UserState :: term()} |\n\t{fail, Reason :: term()} | {unknown, UserState :: term()}.\n\n Types:\n Event = {bad_cert, Reason :: atom() |\n {revoked, atom()}} |\n\t\t{extension, #'Extension'{}} |\n valid |\n valid_peer\n ```\n\n The verification fun is called during the X.509-path validation when\n an error occurs or an extension unknown to the SSL application is\n encountered. It is also called when a certificate is considered\n valid by the path validation to allow access to each certificate in\n the path to the user application. It differentiates between the peer\n certificate and the CA certificates by using `valid_peer` or `valid`\n as `Event` argument to the verification fun. See the [Public_Key\n User's Guide](`e:public_key:public_key_records.md`) for definition\n of `#'OTPCertificate'{}` and `#'Extension'{}`.\n\n - If the verify callback fun returns `{fail, Reason}`, the verification process\n is immediately stopped, an alert is sent to the peer, and the TLS/DTLS\n handshake terminates.\n - If the verify callback fun returns `{valid, UserState}`, the verification\n process continues.\n - If the verify callback fun always returns `{valid, UserState}`, the TLS/DTLS\n handshake does not terminate regardless of verification failures, and the\n connection is established.\n - If called with an extension unknown to the user application, the fun is to\n return `{unknown, UserState}`.\n\n Note that if the fun returns `unknown` for an extension marked as critical,\n validation will fail.\n\n Default option `verify_fun` in `verify_peer mode`:\n\n ```erlang\n {fun(_, _, {bad_cert, _} = Reason, _) ->\n\t {fail, Reason};\n (_, _, {extension, _}, UserState) ->\n\t {unknown, UserState};\n (_, _, valid, UserState) ->\n\t {valid, UserState};\n (_, _, valid_peer, UserState) ->\n {valid, UserState}\n end, []}\n ```\n\n Default option `verify_fun` in mode `verify_none`:\n\n ```erlang\n {fun(_, _, {bad_cert, _}, UserState) ->\n\t {valid, UserState};\n (_, _, {extension, #'Extension'{critical = true}}, UserState) ->\n\t {valid, UserState};\n (_, _, {extension, _}, UserState) ->\n\t {unknown, UserState};\n (_, _, valid, UserState) ->\n\t {valid, UserState};\n (_, _, valid_peer, UserState) ->\n {valid, UserState}\n end, []}\n ```\n\n The possible path validation errors are given in the form `{bad_cert, Reason}`,\n where `Reason` is:\n\n - **`unknown_ca`**\n\n No trusted CA was found in the trusted store. The trusted\n CA is normally a so-called ROOT CA, which is a self-signed certificate. Trust\n can be claimed for an intermediate CA (the trusted anchor does not have to be\n self-signed according to X-509) by using option `partial_chain`.\n\n - **`selfsigned_peer`**\n\n The chain consisted only of one self-signed certificate.\n\n - **`PKIX X-509-path validation error`**\n\n For possible reasons, see `public_key:pkix_path_validation/3`.\n\n- **`{cert_policy_opts, PolicyOpts}`** - Handle certificate policies.\n\n Configure X.509 certificate policy handling for the certificate path validation process;\n see [public_key:pkix_path_validation/3](`public_key:pkix_path_validation/3`) for\n more details.\n\n- **`{cerl_check, Check}`** - Handle certificate revocation lists.\n\n Perform CRL (Certificate Revocation List) verification\n [(public_key:pkix_crls_validate/3)](`public_key:pkix_crls_validate/3`) on all\n the certificates during the path validation\n [(public_key:pkix_path_validation/3) ](`public_key:pkix_path_validation/3`)of\n the certificate chain. `Check` defaults to `false`.\n\n The meaning of `Check` is as follows:\n\n - **`false`**\n\n No checks are performed.\n\n - **`peer`**\n\n Check is only performed on the peer certificate.\n\n - **`best_effort`**\n\n If certificate revocation status cannot be determined it will be accepted as valid.\n\n The CA certificates specified for the connection will be used to construct the\n certificate chain validating the CRLs.\n\n The CRLs will be fetched from a local or external cache. See\n `m:ssl_crl_cache_api`.","title":"ssl.common_option_cert/0","ref":"ssl.html#t:common_option_cert/0"},{"type":"type","doc":"Common options to client and server only valid for DTLS.\n\n- **`{use_srtp, UseSrtp}`** - Configures the `use_srtp` DTLS hello extension.\n\n In order to negotiate the use of SRTP data protection, clients include an\n extension of type \"use_srtp\" in the DTLS extended client hello. This extension\n MUST only be used when the data being transported is RTP or RTCP.\n\n The value is a map with a mandatory `protection_profiles` parameter\n and an optional `mki` parameter.\n\n `protection_profiles` configures the list of the client's acceptable SRTP\n Protection Profiles. Each profile is a 2-byte binary. Example:\n `#{protection_profiles => [<<0,2>>, <<0,5>>]}`\n\n `mki` configures the SRTP Master Key Identifier chosen by the client.\n\n The `srtp_mki` field contains the value of the SRTP MKI which is associated with\n the SRTP master keys derived from this handshake. Each SRTP session MUST have\n exactly one master key that is used to protect packets at any given time. The\n client MUST choose the MKI value so that it is distinct from the last MKI value\n that was used, and it SHOULD make these values unique for the duration of the\n TLS session.\n\n > #### Note {: .info }\n >\n > OTP does not handle SRTP, so an external implementations of SRTP\n > encoder/decoder and a packet demultiplexer are needed to make use of the\n > `use_srtp` extension. See also option [transport_option](`t:transport_option/0`).\n\n Servers that receive an extended hello containing a \"use_srtp\" extension can\n agree to use SRTP by including an extension of type \"use_srtp\", with the chosen\n protection profile in the extended server hello. This extension MUST only be\n used when the data being transported is RTP or RTCP.","title":"ssl.common_option_dtls/0","ref":"ssl.html#t:common_option_dtls/0"},{"type":"type","doc":"Legacy options considered deprecated in favor of other options,\ninsecure to use, or plainly not relevant anymore.\n\n- **`{cert, Certs}`**\n\n Use option `certs_keys` instead.\n\n- **`{certfile, CertPem}`**\n\n Use option `certs_keys` instead.\n\n- **`{keyfile, KeyPem}`**\n\n Use option `certs_keys` instead.\n\n- **`{password, KeyPemPasswd}`**\n\n Use option `certs_keys` instead.\n\n- **`{log_alert, LogAlert}`**\n\n If `LogAlert` is `false`, TLS/DTLS Alert reports are not displayed. Deprecated in OTP\n 22; use `{log_level, Level}` instead.\n\n- **`{padding_check, PaddingCheck}`** - Inter-op trade-off option\n\n Affects TLS-1.0 connections only. If set to `false`, it disables the block\n cipher padding check to be able to interoperate with legacy software.\n\n > #### Warning {: .warning }\n >\n > Using `{padding_check, false}` makes TLS vulnerable to the Poodle attack.\n\n- **`{beast_mitigation, BeastMitigation}`** - Inter-op trade-off option\n\n Affects TLS-1.0 connections only. Used to change the BEAST mitigation strategy\n to interoperate with legacy software. Defaults to `one_n_minus_one`.\n\n `one_n_minus_one` - Perform `1/n-1` BEAST mitigation.\n\n `zero_n` - Perform `0/n` BEAST mitigation.\n\n `disabled` - Disable BEAST mitigation.\n\n > #### Warning {: .warning }\n >\n > Using `{beast_mitigation, disabled}` makes TLS-1.0 vulnerable to the BEAST\n > attack.\n\n- **`{ssl_imp, Imp}`**\n\n Deprecated since OTP 17; has no effect.","title":"ssl.common_option_legacy/0","ref":"ssl.html#t:common_option_legacy/0"},{"type":"type","doc":"Options common to client and server side prior to TLS-1.3.\n\n- **`{eccs, NamedCurves}`** - Named Elliptic Curves\n\n Elliptic curves that can be used in pre TLS-1.3 key exchange.\n\n- **`{secure_renegotiate, SecureRenegotiate}`** - Inter-operate trade-off option\n\n Specifies whether to reject renegotiation attempt that does not live\n up to [RFC 5746](http://www.ietf.org/rfc/rfc5746.txt). By default,\n `SecureRenegotiate` is `true`, meaning that secure renegotiation is\n enforced. If `SecureRenegotiate` is `false` secure renegotiation\n will still be used if possible, but it falls back to insecure\n renegotiation if the peer does not support if [RFC\n 5746](http://www.ietf.org/rfc/rfc5746.txt).\n\n- **`{user_lookup_fun, {LookupFun, UserState}}`** - PSK/SRP cipher suite option\n\n The lookup fun is to be defined as follows:\n\n ```erlang\n fun(psk, PSKIdentity :: binary(), UserState :: term()) ->\n\t{ok, SharedSecret :: binary()} | error;\n fun(srp, Username :: binary(), UserState :: term()) ->\n\t{ok, {SRPParams :: srp_param_type(), Salt :: binary(),\n\t DerivedKey :: binary()}} | error.\n ```\n\n For Pre-Shared Key (PSK) cipher suites, the lookup fun is called by the client\n and server to determine the shared secret. When called by the client,\n `PSKIdentity` is the hint presented by the server or `undefined`. When\n called by the server, `PSKIdentity` is the identity presented by the client.\n\n For Secure Remote Password (SRP), the fun is only used by the server to obtain\n parameters that it uses to generate its session keys. `DerivedKey` is to be\n derived according to [RFC 2945](http://tools.ietf.org/html/rfc2945#section/3)\n and [RFC 5054](http://tools.ietf.org/html/rfc5054#section-2.4):\n `crypto:sha([Salt, crypto:sha([Username, <<$:>>, Password])])`","title":"ssl.common_option_pre_tls13/0","ref":"ssl.html#t:common_option_pre_tls13/0"},{"type":"type","doc":"Common options to both client and server for TLS-1.3.\n\n- **`{supported_groups, Groups}`** - Key exchange option\n\n TLS 1.3 introduces the \"supported_groups\" extension, which is used for negotiating\n the Diffie-Hellman parameters in a TLS 1.3 handshake. Both client and server can\n specify a list of parameters that they are willing to use.\n\n If not specified it will use a default list (`[x25519, x448, secp256r1,\n secp384r1]`) that is filtered based on the installed crypto library version.\n\n- **`{key_update_at, KeyUpdateAt}`** - Session key renewal\n\n Configures the maximum amount of bytes that can be sent on a TLS 1.3 connection\n before an automatic key update is performed.\n\n There are cryptographic limits on the amount of plaintext which can be safely\n encrypted under a given set of keys. The current default ensures that data\n integrity will not be breached with probability greater than `1/2^57`. For more\n information see\n [Limits on Authenticated Encryption Use in TLS](https://eprint.iacr.org/2024/051.pdf).","title":"ssl.common_option_tls13/0","ref":"ssl.html#t:common_option_tls13/0"},{"type":"type","doc":"Key value list convening some information about the established connection.","title":"ssl.connection_info/0","ref":"ssl.html#t:connection_info/0"},{"type":"type","doc":"TLS connection keys for which information can be retrieved.","title":"ssl.connection_info_keys/0","ref":"ssl.html#t:connection_info_keys/0"},{"type":"type","doc":"TLS connection information relevant prior to TLS-1.3.","title":"ssl.connection_info_pre_tls13/0","ref":"ssl.html#t:connection_info_pre_tls13/0"},{"type":"type","doc":"Options for using built-in CRL cache support.\n\nSpecify how to perform lookup and caching of certificate revocation\nlists (CRLs). `Module` defaults to `m:ssl_crl_cache` with `DbHandle`\nbeing `internal`, and `Args` being `[]`.\n\nThere are two implementations available:\n\n- **`ssl_crl_cache`** - Implementation 1\n\n This module maintains a cache of CRLs. CRLs can be added to the\n cache using `ssl_crl_cache:insert/1`, and can optionally be\n automatically fetched through HTTP if the following argument is\n specified:\n\n- **`{http, timeout()}`**\n\n Enables fetching of CRLs specified as http URIs in [X.509 certificate\n extensions](`e:public_key:public_key_records.md`). Requires the\n [Inets](`e:inets:introduction.md`) application.\n\n- **`ssl_crl_hash_dir`** - Implementation 2\n\n This module makes use of a directory where CRLs are\n stored in files named by the hash of the issuer name.\n\n The file names consist of eight hexadecimal digits followed by `.rN`, where\n `N` is an integer, for example `1a2b3c4d.r0`. For the first version of the CRL, `N`\n starts at zero, and for each new version, `N` is incremented by one. The\n OpenSSL utility `c_rehash` creates symlinks according to this pattern.\n\n For a given hash value, this module finds all consecutive `.r*`\n files starting from zero, and those files taken together make up the\n revocation list. CRL files with `nextUpdate` fields in the past or\n issued by a different CA that happens to have the same name hash\n are excluded.\n\n The following argument is required:\n\n - **`{dir, string()}`**\n\n Specifies the directory in which the CRLs can be found.","title":"ssl.crl_cache_opts/0","ref":"ssl.html#t:crl_cache_opts/0"},{"type":"type","doc":"A DTLS protocol version that are no longer supported by default for security reasons.","title":"ssl.dtls_legacy_version/0","ref":"ssl.html#t:dtls_legacy_version/0"},{"type":"type","doc":"DTLS protocol version.","title":"ssl.dtls_version/0","ref":"ssl.html#t:dtls_version/0"},{"type":"type","doc":"Erlang cipher suite representation\n\n> #### Warning {: .warning }\nEnabling cipher suites using RSA as a key exchange algorithm is\nstrongly discouraged (only available prior to TLS-1.3). For some\nconfigurations software preventions may exist, and can make them\nusable if they work, but relying on them to work is risky. There\nexists more reliable cipher suites that can be used instead.","title":"ssl.erl_cipher_suite/0","ref":"ssl.html#t:erl_cipher_suite/0"},{"type":"type","doc":"If a TLS connection fails a TLS protocol ALERT will be sent/received.\n\nAn atom reflecting the raised alert, according to the TLS protocol, and a description string\nwith some further details will be returned.","title":"ssl.error_alert/0","ref":"ssl.html#t:error_alert/0"},{"type":"type","doc":"TLS-1.3 key exchange configuration.","title":"ssl.group/0","ref":"ssl.html#t:group/0"},{"type":"type","doc":"Hash algorithms used together with signing and encryption functions.","title":"ssl.hash/0","ref":"ssl.html#t:hash/0"},{"type":"type","doc":"A name or address to a host.","title":"ssl.host/0","ref":"ssl.html#t:host/0"},{"type":"type","doc":"Cipher Suite Key Exchange Algorithm will be `any`\nin TLS-1.3 as key exchange is no longer part of cipher suite\nconfiguration in TLS-1.3.","title":"ssl.kex_algo/0","ref":"ssl.html#t:kex_algo/0"},{"type":"type","doc":"The user's private key.\n\nThe key can be provided either directly as a DER-encoded entity,\nindirectly using a crypto engine/provider (with key reference\ninformation), or as an Erlang fun (with possible custom options).\nThe latter two options can be used for customized signing with\nhardware security modules (HSM) or trusted platform modules (TPM).\n\n- A DER encoded key will need to specify the ASN-1 type used to create the\n encoding.\n- An engine/provider needs to specify specific information to support this\n concept and can optionally be password protected; see also\n [crypto:engine_load/3 ](`crypto:engine_load/3`) and\n [Crypto User's Guide](`e:crypto:engine_load.md`).\n- A fun option should include a fun that mimics `public_key:sign/4` and possibly\n [public_key:private_encrypt/4](`public_key:encrypt_private/3`) if legacy\n versions TLS-1.0 and TLS-1.1 must be supported.","title":"ssl.key/0","ref":"ssl.html#t:key/0"},{"type":"type","doc":"Cipher algorithms that are no longer supported by default for security reasons.","title":"ssl.legacy_cipher/0","ref":"ssl.html#t:legacy_cipher/0"},{"type":"type","doc":"Hash algorithms that are no longer supported by default for security reasons.","title":"ssl.legacy_hash/0","ref":"ssl.html#t:legacy_hash/0"},{"type":"type","doc":"Key exchange configuration prior to TLS-1.3.\n\nThese curves have been deprecated by RFC 8422.","title":"ssl.legacy_named_curve/0","ref":"ssl.html#t:legacy_named_curve/0"},{"type":"type","doc":"Signature algorithms that are no longer supported by default for security reasons.","title":"ssl.legacy_sign_algo/0","ref":"ssl.html#t:legacy_sign_algo/0"},{"type":"type","doc":"This is only used for certificate signatures if TLS-1.2 is negotiated,\nmeaning that the peer only supports TLS-1.2, but we also support\nTLS-1.3.","title":"ssl.legacy_sign_scheme/0","ref":"ssl.html#t:legacy_sign_scheme/0"},{"type":"type","doc":"Key exchange configuration prior to TLS-1.3.","title":"ssl.named_curve/0","ref":"ssl.html#t:named_curve/0"},{"type":"type","doc":"For backwards compatibility only; do not use.","title":"ssl.old_cipher_suite/0","ref":"ssl.html#t:old_cipher_suite/0"},{"type":"type","doc":"","title":"ssl.prf_random/0","ref":"ssl.html#t:prf_random/0"},{"type":"type","doc":"Client hello extensions.","title":"ssl.protocol_extensions/0","ref":"ssl.html#t:protocol_extensions/0"},{"type":"type","doc":"TLS or DTLS protocol version.","title":"ssl.protocol_version/0","ref":"ssl.html#t:protocol_version/0"},{"type":"type","doc":"Error reason for debug purposes.\n\nNot to be matched.","title":"ssl.reason/0","ref":"ssl.html#t:reason/0"},{"type":"type","doc":"Supported in TLS-1.3 and TLS-1.2.","title":"ssl.rsassa_pss_scheme/0","ref":"ssl.html#t:rsassa_pss_scheme/0"},{"type":"type","doc":"TLS connection information that can be used for NSS key logging.","title":"ssl.security_info/0","ref":"ssl.html#t:security_info/0"},{"type":"type","doc":"Options specific to the server side, or with different semantics for the client and server.\n\n- **`{alpn_preferred_protocols, AppProtocols}`** - Application Layer Protocol Negotiation\n\n Indicates that the server will try to perform Application-Layer\n Protocol Negotiation (ALPN).\n\n The list of protocols is in order of preference. The protocol negotiated will be\n the first in the list that matches one of the protocols advertised by the\n client. If no protocol matches, the server will fail the connection with a\n `no_application_protocol` alert.\n\n The negotiated protocol can be retrieved using the\n [`negotiated_protocol/1`](`negotiated_protocol/1`) function.\n\n- **`{sni_fun, SNIFun}`**\n\n If the server receives a SNI (Server Name Indication) from the\n client, the given fun `SNIFun` will be called to retrieve\n [`server_option()`](`t:server_option/0`) for the indicated\n hosts. These options will override previously specified options for\n that host.\n\n > #### Note {: .info }\n The options `sni_fun` and `sni_hosts` are mutually exclusive.\n\n- **`{sni_hosts, SNIHosts}`**\n\n If the server receives a SNI (Server Name Indication) from the client matching a\n host listed in the `sni_hosts` option, the specific options for that host will\n override previously specified options.\n\n > #### Note {: .info }\n The options `sni_fun` and `sni_hosts` are mutually exclusive.","title":"ssl.server_option/0","ref":"ssl.html#t:server_option/0"},{"type":"type","doc":"Certificate related options for a server.\n\n- **`{cacerts, CACerts}`** - Trusted certificates.\n\n The DER-encoded trusted certificates. If this option is supplied, it overrides\n the `cacertfile` option.\n\n- **`{verify, Verify}`** - Verify certificates.\n\n Client certificates are an optional part of the TLS protocol. A server performs\n X.509 certificate path validation only in `verify_peer` mode. By default the server\n is in `verify_none` mode and, hence, will not send an certificate request to the\n client. When using `verify_peer` you may also want to specify the options\n `fail_if_no_peer_cert` and `certificate_authorities`.\n\n- **`{fail_if_no_peer_cert, FailNoPeerCert}`** - Legacy trade-off option\n\n Used together with `{verify, verify_peer}` by an TLS/DTLS server. If set to\n `true`, the server fails if the client does not have a certificate to send, that\n is, sends an empty certificate. If set to `false`, it fails only if the client\n sends an invalid certificate (an empty certificate is considered valid).\n Defaults to `false`.\n\n- **`{certificate_authorities, ServerCertAuth}`** - Inter-operate hint option\n\n Determines whether a TLS-1.3 server should include the authorities extension in its\n certificate request message that is sent when the option `verify` is set to\n `verify_peer`. Defaults to `true`.\n\n If set to `false` for older TLS versions its corresponding certificate authorities\n definition in its certificate request will be set to the empty list instead of\n including the appropriate certificate authorities. This has the same affect\n as excluding the TLS-1.3 extension.\n\n A reason to exclude the extension would be if the server wants to communicate\n with clients incapable of sending complete certificate chains that adhere to the\n extension, but the server still has the capability to recreate a chain that it\n can verify.","title":"ssl.server_option_cert/0","ref":"ssl.html#t:server_option_cert/0"},{"type":"type","doc":"Legacy server options.\n\n- **`{next_protocols_advertised, NextAppProtocols}`**\n\n ALPN (Application-Layer Protocol Negotiation)\n deprecates NPN (Next Protocol Negotiation) described here.\n\n List of protocols to send to the client if the client indicates that it supports\n the Next Protocol extension. The client can select a protocol that is not on\n this list. The list of protocols must not contain an empty binary. If the server\n negotiates a Next Protocol, it can be accessed using the\n `negotiated_protocol/1` method.","title":"ssl.server_option_legacy/0","ref":"ssl.html#t:server_option_legacy/0"},{"type":"type","doc":"Options only relevant to TLS versions prior to TLS-1.3.\n\n- **`{client_renegotiation, ClientRengotiation}`** - DoS attack avoidance option\n\n In protocols that support client-initiated renegotiation, the resource cost\n of such an operation is higher for the server than the client. This can act as a\n vector for denial-of-service (DoS) attacks. The SSL application already takes measures\n to counter-act such attempts, but client-initiated renegotiation can be completely\n disabled by setting this option to `false`. The default value is `true`. Note\n that disabling renegotiation can result in long-lived connections becoming\n unusable due to limits on the number of messages the underlying cipher suite can\n encipher.\n\n- **`{reuse_sessions, ReuseSessions}`** - Enable session reuse\n\n The boolean value `true` specifies that the server will agree to reuse sessions.\n Setting it to `false` will result in an empty session table, meaning that no sessions\n will be reused.\n\n- **`{reuse_session, ReuseSession}`** - Local server reuse policy\n\n Enables the TLS/DTLS server to have a local policy for deciding whether a session\n is to be reused. Meaningful only if `reuse_sessions` is set to `true`.\n\n `ReuseSession` should be a fun:\n\n `fun(SuggestedSessionId, PeerCert, Compression, CipherSuite)`\n\n `SuggestedSessionId` is a [`binary()`](`t:binary/0`),\n `PeerCert` is a DER-encoded certificate,\n `Compression` is an enumeration integer, and `CipherSuite` is of type\n [`erl_cipher_suite()`](`t:erl_cipher_suite/0`).\n\n- **`{psk_identity, PSKHint}`** - Inter-operate hint option\n\n Specifies the server identity hint that the server presents to the client.\n\n- **`{honor_cipher_order, HonorServerCipherOrder}`** - Trade-off option alters protocol defined behavior\n\n If `true`, use the server's preference for ECC curve selection. If `false` (the\n default), use the client's preference.\n\n- **`{honor_ecc_order, HonorServerECCOrder}`** - Trade-off option alters protocol defined behavior\n\n If `true`, use the server's preference for ECC curve selection. If `false` (the\n default), use the client's preference.\n\n- **`{dh, DHder}`** - Affects DH key exchange cipher suites\n\n The DER-encoded Diffie-Hellman parameters. If specified, it overrides option\n `dhfile`.\n\n- **`{dh_file, DHfile}`** - Affects DH key exchange cipher suites\n\n Path to a file containing PEM-encoded Diffie Hellman parameters to be used by\n the server if a cipher suite using Diffie Hellman key exchange is negotiated. If\n not specified, default parameters are used.","title":"ssl.server_option_pre_tls13/0","ref":"ssl.html#t:server_option_pre_tls13/0"},{"type":"type","doc":"Options only relevant for TLS-1.3.\n\n- **`{session_tickets, SessionTickets}`**\n\n Configures the session ticket functionality. Allowed values for `SessionTickets` are:\n\n * `disabled`\n * `stateful`\n * `stateless`\n * `stateful_with_cert`\n * `stateless_with_cert`\n\n If `SessionTickets` is not set to `disabled`, session resumption with pre-shared\n keys is enabled and the server will send stateful or stateless session tickets to the\n client after successful connections.\n\n > #### Note {: .info }\n In pre-shared key session ticket resumption, there is no certificate\n exchange involved. Therefore, `ssl:peercert/1` will not return the\n peer certificate, as it is only communicated during the initial\n handshake. To associate the client certificate from the original\n handshake with the tickets it issues, the server options\n `stateful_with_cert` or `stateless_with_cert` can be used.\n\n A stateful session ticket is a database reference to internal state information.\n A stateless session ticket is a self-encrypted binary that contains both\n cryptographic keying material and state data.\n\n > #### Warning {: .warning }\n When `SessionTickets` is set to `stateful_with_cert`, the client\n certificate is stored along with the internal state information,\n leading to increased memory consumption. Conversely, when it is set\n to `stateless_with_cert`, the client certificate is encoded in the\n self-encrypted binary sent to the client, resulting in an increase\n in payload size.\n\n See also [SSL User's Guide, Session Tickets and Session Resumption in TLS 1.3](using_ssl.md#session-tickets-and-session-resumption-in-tls-1-3).\n\n- **`{stateless_tickets_seed, TicketSeed}`** - Option for statless tickets\n\n Configures the seed used for the encryption of stateless session tickets.\n Allowed values are any randomly generated `t:binary/0`. If this option is not\n configured, an encryption seed will be randomly generated.\n\n > #### Warning {: .warning }\n >\n > Reusing the ticket encryption seed between multiple server instances enables\n > stateless session tickets to work across multiple server instances, but it\n > breaks anti-replay protection across instances.\n >\n > Inaccurate time synchronization between server instances can also affect\n > session ticket freshness checks, potentially causing false negatives as well\n > as false positives.\n\n- **`{anti_replay, AntiReplay}`** - Option for statless tickets\n\n Configures the server's built-in anti replay feature based on Bloom filters.\n\n Allowed values for `AntiReplay` are the pre-defined `'10k'`,\n `'100k'`, or a custom 3-tuple that defines the properties of the\n bloom filters:\n `{WindowSize, HashFunctions, Bits}`. `WindowSize` is the number of seconds after\n the current Bloom filter is rotated and also the window size used for freshness\n checks of ClientHello. `HashFunctions` is the number hash functions and `Bits`\n is the number of bits in the bit vector. `'10k'` and `'100k'` are simple\n defaults with the following properties:\n\n - `'10k'`: Bloom filters can hold 10000 elements with 3% probability of false\n positives. `WindowSize`: 10, `HashFunctions`: 5, `Bits:` 72985 (8.91 KiB).\n - `'100k'`: Bloom filters can hold 100000 elements with 3% probability of false\n positives. `WindowSize`: 10, `HashFunctions`: 5, `Bits`: 729845 (89.09 KiB).\n\n See also [SSL User's Guide, Anti-Replay Protection in TLS\n 1.3](using_ssl.md#anti-replay-protection-in-tls-1-3).\n\n- **`{cookie, Cookie}`** - Option for `HelloRetryRequest` behavior\n\n If `Cookie` is `true`, which is the default, the server sends a\n cookie extension in its `HelloRetryRequest` messages.\n\n The cookie extension has two main purposes. It allows the server to force the\n client to demonstrate reachability at their apparent network address (thus\n providing a measure of DoS protection). This is primarily useful for\n non-connection-oriented transports. It also allows offloading the server's\n state to the client. The cookie extension is enabled by default as it is a\n mandatory extension in RFC8446.\n\n- **`{early_data, EarlyData}`** - Option for accepting or rejecting Early Data\n\n Configures if the server accepts (`enabled`) or rejects (`disabled`) early data\n sent by a client. The default value is `disabled`.","title":"ssl.server_option_tls13/0","ref":"ssl.html#t:server_option_tls13/0"},{"type":"type","doc":"Identifies a TLS session prior to TLS-1.3.","title":"ssl.session_id/0","ref":"ssl.html#t:session_id/0"},{"type":"type","doc":"SHA2 hash algorithms.","title":"ssl.sha2/0","ref":"ssl.html#t:sha2/0"},{"type":"type","doc":"Signature algorithms.","title":"ssl.sign_algo/0","ref":"ssl.html#t:sign_algo/0"},{"type":"type","doc":"Signature schemes, defined by TLS-1.3, and replacing signature algorithms from TLS-1.2.\n\nExplicitly list acceptable signature schemes in the preferred\norder.\n\nOverrides the algorithms supplied in\n[`signature_algs`](`t:signature_algs/0`) option for certificates.\nIn addition to the `signature_algorithms` extension from TLS 1.2,\n[TLS 1.3 (RFC 5246 Section 4.2.3)](http://www.ietf.org/rfc/rfc8446.txt#section-4.2.3)\nadds the `signature_algorithms_cert` extension which enables having special\nrequirements on the signatures used in the certificates that differs from the\nrequirements on digital signatures as a whole. If this is not required this\nextension is not needed.\n\nThe client will send a `signature_algorithms_cert` extension (in the\nclient hello message), if TLS version 1.2 (back-ported to TLS 1.2 in\n24.1) or later is used, and the signature_algs_cert option is\nexplicitly specified. By default, only the\n[signature_algs](`t:signature_algs/0`) extension is sent with the\nexception of when signature_algs option is not explicitly specified,\nin which case it will append the rsa_pkcs1_sha1 algorithm to the\ndefault value of signature_algs and use it as value for\nsignature_algs_cert to allow certificates to have this signature but\nstill disallow sha1 use in the TLS protocol, since 27.0.1 and 26.2.5.2.\n\n> #### Note {: .info }\n>\n> Note that supported signature schemes for TLS-1.2 are\n[`legacy_sign_scheme()`](`t:legacy_sign_scheme/0`)\n> and [`rsassa_pss_scheme()`](`t:rsassa_pss_scheme/0`).","title":"ssl.sign_scheme/0","ref":"ssl.html#t:sign_scheme/0"},{"type":"type","doc":"Explicitly list acceptable signature algorithms for certificates and handshake\nmessages in the preferred order.\n\nThe client will send its list as the client hello\n`signature_algorithm` extension introduced in TLS-1.2; see [Section\n7.4.1.4.1 in RFC 5246](http://www.ietf.org/rfc/rfc5246.txt). Before\nTLS-1.2, these algorithms where implicitly chosen and partly derived\nfrom the cipher suite.\n\nIn TLS-1.2 a somewhat more explicit negotiation is made possible using a list of\n`{HashAlgo, SignAlgo}` tuples.\n\nIn TLS-1.3, these algorithm pairs are replaced by [signature\nschemes](`t:sign_scheme/0`) that are completely decoupled from the\ncipher suite.\n\nSignature algorithms used for certificates can be overridden by the\n[signature schemes](`t:sign_scheme/0`) supplied by the\n`signature_algs_cert` option.\n\nThe TLS-1.2 default is `Default_TLS_12_Alg_Pairs` interleaved with\n`rsa_pss_schemes` since ssl-11.0 (Erlang/OTP 25). `pss_pss` is\npreferred over `pss_rsae`, which in turn is preferred over `rsa`.\n\nThe list for `Default_TLS_12_Alg_Pairs` is defined as follows:\n\n```erlang\n[\n{sha512, ecdsa},\n{sha512, rsa},\n{sha384, ecdsa},\n{sha384, rsa},\n{sha256, ecdsa},\n{sha256, rsa}\n]\n```\n\n> #### Change {: .info }\n>\n> - Support for `{md5, rsa}` was removed from the TLS-1.2 default in\n> ssl-8.0 (Erlang/OTP 22).\n> - Support for `{sha, _}` (SHA1) and `{sha224, _}` was removed\n> from the TLS-1.2 default in ssl-11.0 (Erlang/OTP 26).\n\nThe list for `rsa_pss_schemes` is defined as follows:\n\n\n```erlang\n[rsa_pss_pss_sha512,\nrsa_pss_pss_sha384,\nrsa_pss_pss_sha256,\nrsa_pss_rsae_sha512,\nrsa_pss_rsae_sha384,\nrsa_pss_rsae_sha256]\n```\n\nThe list of `TLS_13_Legacy_Schemes` is defined as follows:\n\n```erlang\n[\n%% Legacy algorithms only applicable to certificate signatures\nrsa_pkcs1_sha512, %% Corresponds to {sha512, rsa}\nrsa_pkcs1_sha384, %% Corresponds to {sha384, rsa}\nrsa_pkcs1_sha256, %% Corresponds to {sha256, rsa}\n]\n```\n\nThe list of `Default_TLS_13_Schemes` is defined as follows:\n\n```text\n[\n%% EDDSA\neddsa_ed25519,\neddsa_ed448\n\n%% ECDSA\necdsa_secp521r1_sha512,\necdsa_secp384r1_sha384,\necdsa_secp256r1_sha256] ++\n\n%% RSASSA-PSS\nrsa_pss_schemes()\n```\n\n> #### Change {: .info }\n>\n> EDDSA was made highest priority in ssl-10.8 (Erlang/OTP 25).\n\nThe TLS-1.3 default is `Default_TLS_13_Schemes`.\n\nIf both TLS-1.3 and TLS-1.2 are supported the default is:\n\n```erlang\nDefault_TLS_13_Schemes ++ TLS_13_Legacy_Schemes ++\nDefault_TLS_12_Alg_Pairs %% not represented in TLS_13_Legacy_Schemes\n```\n\nto ensure that appropriate algorithms can be chosen for the negotiated\nversion.\n\n> #### Note {: .info }\nTLS-1.2 algorithms will not be negotiated for TLS-1.3, but the TLS-1.3\nRSASSA-PSS ([`rsassa_pss_scheme()`](`t:rsassa_pss_scheme/0`))\nsignature schemes can be negotiated also for TLS-1.2 from Erlang/OTP\n24.1 (fully working from Erlang/OTP 24.1.3). However, if both TLS 1.3\nand TLS 1.2 are supported using defaults, and TLS 1.3 is negotiated,\nthe corresponding TLS 1.2 algorithms for TLS 1.3 legacy signature\nschemes will be treated as legacy schemes and applied only to\ncertificate signatures.","title":"ssl.signature_algs/0","ref":"ssl.html#t:signature_algs/0"},{"type":"type","doc":"A socket that can be used to perform a so-called \"START-TLS\", which\nmeans using an already connected socket previously used for plain TCP\ntraffic and upgrading it to use TLS.\n\nBoth sides needs to agree on the upgrade.","title":"ssl.socket/0","ref":"ssl.html#t:socket/0"},{"type":"type","doc":"Options for the transport socket.\n\nThe default socket options are\n`[{mode, list}, {packet, 0}, {header, 0}, {active, true}]`.\n\nFor valid options, see `m:inet`, `m:gen_tcp`, and `m:gen_udp`\nin Kernel. Note that stream-oriented options such as `packet` are\nonly relevant for TLS and not DTLS.","title":"ssl.socket_option/0","ref":"ssl.html#t:socket_option/0"},{"type":"type","doc":"SRP cipher suite configuration prior to TLS-1.3.","title":"ssl.srp_param_type/0","ref":"ssl.html#t:srp_param_type/0"},{"type":"type","doc":"An opaque reference to the TLS/DTLS connection.\n\nNote that despite being opaque, matching `sslsocket()` instances is allowed.","title":"ssl.sslsocket/0","ref":"ssl.html#t:sslsocket/0"},{"type":"type","doc":"TLS Alert Protocol reasons.","title":"ssl.tls_alert/0","ref":"ssl.html#t:tls_alert/0"},{"type":"type","doc":"An option that can be supplied to a TLS client.","title":"ssl.tls_client_option/0","ref":"ssl.html#t:tls_client_option/0"},{"type":"type","doc":"A TLS protocol version that are no longer supported by default for security reasons.","title":"ssl.tls_legacy_version/0","ref":"ssl.html#t:tls_legacy_version/0"},{"type":"type","doc":"An option related to the TLS/DTLS protocol.","title":"ssl.tls_option/0","ref":"ssl.html#t:tls_option/0"},{"type":"type","doc":"An option that can be supplied to a TLS server.","title":"ssl.tls_server_option/0","ref":"ssl.html#t:tls_server_option/0"},{"type":"type","doc":"TLS protocol version.","title":"ssl.tls_version/0","ref":"ssl.html#t:tls_version/0"},{"type":"type","doc":"Transport option defines a callback module and message tags to handle the underlying transport socket.\n\nCan be used to customize the transport layer. The tag\nvalues should be the values used by the underlying transport in its active mode\nmessages.\n\nDefaults to `{gen_tcp, tcp, tcp_closed, tcp_error, tcp_passive}` for TLS.\n\n> #### Note {: .info }\nFor backward compatibility a tuple of size four will be converted to a\ntuple of size five, where `PassiveTag` is the `DataTag` element with\n`_passive` appended.\n\nFor TLS the callback module must implement a reliable transport\nprotocol, behave as `m:gen_tcp`, and have functions corresponding to\n`inet:setopts/2`, `inet:getopts/2`, `inet:peername/1`, `inet:sockname/1`, and\n`inet:port/1`. The callback `m:gen_tcp` is treated specially and calls `m:inet`\ndirectly. For DTLS this feature is considered experimental.","title":"ssl.transport_option/0","ref":"ssl.html#t:transport_option/0"},{"type":"module","doc":"CRL cache\n\nImplements an internal CRL (Certificate Revocation List) cache. In addition to\nimplementing the `m:ssl_crl_cache_api` behaviour the following functions are\navailable.","title":"ssl_crl_cache","ref":"ssl_crl_cache.html"},{"type":"function","doc":"Delete CRLs from the ssl applications local cache.","title":"ssl_crl_cache.delete/1","ref":"ssl_crl_cache.html#delete/1"},{"type":"function","doc":"","title":"ssl_crl_cache.insert/1","ref":"ssl_crl_cache.html#insert/1"},{"type":"function","doc":"Insert CRLs into the ssl applications local cache, with or without a\ndistribution point reference URI","title":"ssl_crl_cache.insert/2","ref":"ssl_crl_cache.html#insert/2"},{"type":"type","doc":"A source to input CRLs","title":"ssl_crl_cache.crl_src/0","ref":"ssl_crl_cache.html#t:crl_src/0"},{"type":"behaviour","doc":"API for a TLS CRL (Certificate Revocation List) cache.\n\nWhen TLS performs certificate path validation according to\n[RFC 5280 ](http://www.ietf.org/rfc/rfc5280.txt)it should also perform CRL\nvalidation checks. To enable the CRL checks the application needs access to\nCRLs. A database of CRLs can be set up in many different ways. This module\nprovides the behavior of the API needed to integrate an arbitrary CRL cache with\nthe erlang ssl application. It is also used by the application itself to provide\na simple default implementation of a CRL cache.","title":"ssl_crl_cache_api","ref":"ssl_crl_cache_api.html"},{"type":"callback","doc":"`fun fresh_crl/2` will be used as input option `update_crl` to\n`public_key:pkix_crls_validate/3`.\n\nIt is possible to return logger info, since OTP 22.2, that will be used by the TLS connection to\nproduce log events.","title":"ssl_crl_cache_api.fresh_crl/2","ref":"ssl_crl_cache_api.html#c:fresh_crl/2"},{"type":"callback","doc":"Backwards compatibility, replaced by lookup/3","title":"ssl_crl_cache_api.lookup/2","ref":"ssl_crl_cache_api.html#c:lookup/2"},{"type":"callback","doc":"Lookup the CRLs belonging to the distribution point `Distributionpoint`. This\nfunction may choose to only look in the cache or to follow distribution point\nlinks depending on how the cache is administrated.\n\nThe `Issuer` argument contains the issuer name of the certificate to\nbe checked. Normally the returned CRL should be issued by this\nissuer, except if the `cRLIssuer` field of `DistributionPoint` has a\nvalue, in which case that value should be used instead.\n\nIn an earlier version of this API, the `lookup` function received two\narguments, omitting `Issuer`. For compatibility, this is still\nsupported: if there is no [`lookup/3`](`c:lookup/3`) function in the\ncallback module,[`lookup/2`](`c:lookup/2`) is called instead.\n\nIt is possible to return logger info, since OTP 22.2, that will be used by the TLS connection to\nproduce log events.","title":"ssl_crl_cache_api.lookup/3","ref":"ssl_crl_cache_api.html#c:lookup/3"},{"type":"callback","doc":"Select the CRLs in the cache that are issued by `Issuer` unless the value is a\nlist of so called general names, see\n[X509 certificates records](`e:public_key:public_key_records.md`), originating\nform `#'DistributionPoint'.cRLissuer` and representing different mechanism to\nobtain the CRLs. The cache callback needs to use the appropriate entry to\nretrieve the CRLs or return an empty list if it does not exist.\n\nIt is possible to return logger info, since OTP 22.2, that will be used by the TLS connection to\nproduce log events.","title":"ssl_crl_cache_api.select/2","ref":"ssl_crl_cache_api.html#c:select/2"},{"type":"type","doc":"Reference to the CRL cache.","title":"ssl_crl_cache_api.crl_cache_ref/0","ref":"ssl_crl_cache_api.html#t:crl_cache_ref/0"},{"type":"type","doc":"For description see\n[X509 certificates records](`e:public_key:public_key_records.md`)","title":"ssl_crl_cache_api.dist_point/0","ref":"ssl_crl_cache_api.html#t:dist_point/0"},{"type":"type","doc":"Information for ssl applications use of [Logger(3)](`m:logger`)","title":"ssl_crl_cache_api.logger_info/0","ref":"ssl_crl_cache_api.html#t:logger_info/0"},{"type":"behaviour","doc":"TLS session cache API\n\nDefines the API for the TLS session cache (pre TLS-1.3) so that the data storage\nscheme can be replaced by defining a new callback module implementing this API.","title":"ssl_session_cache_api","ref":"ssl_session_cache_api.html"},{"type":"callback","doc":"Deletes a cache entry.\n\nIs only called from the cache handling process.","title":"ssl_session_cache_api.delete/2","ref":"ssl_session_cache_api.html#c:delete/2"},{"type":"callback","doc":"Calls `Fun(Elem, AccIn)` on successive elements of the cache, starting with\n `AccIn == Acc0`.\n\n`Fun/2` must return a new accumulator, which is passed to the\nnext call. The function returns the final value of the accumulator. `Acc0` is\nreturned if the cache is empty.\n\n> #### Note {: .info }\n>\n> Since OTP-23.3 this functions is only used on the client side and does not\n> need to implemented for a server cache.","title":"ssl_session_cache_api.foldl/3","ref":"ssl_session_cache_api.html#c:foldl/3"},{"type":"callback","doc":"Performs possible initializations of the cache and returns a reference to it\nthat is used as parameter to the other API functions. \n\nIs called by the cache handling processes `init` function, hence\nputting the same requirements on it as a normal process `init`\nfunction. This function is called twice when starting the SSL\napplication, once with the role client and once with the role server,\nas the SSL application must be prepared to take on both roles.\n\nIncludes property `{role, client | server}` in init argument list. \nCurrently this is the only predefined property, there can also be\nuser-defined properties. See also application environment variable\n[session_cb_init_args](ssl_app.md).","title":"ssl_session_cache_api.init/1","ref":"ssl_session_cache_api.html#c:init/1"},{"type":"callback","doc":"Looks up a cache entry. Is to be callable from any process.","title":"ssl_session_cache_api.lookup/2","ref":"ssl_session_cache_api.html#c:lookup/2"},{"type":"callback","doc":"Selects sessions that can be reused, that is sessions that include `PartialKey`\nin its key. Is to be callable from any process.\n\n> #### Note {: .info }\n>\n> Since OTP-23.3 This functions is only used on the client side and does not\n> need to implemented for a server cache.","title":"ssl_session_cache_api.select_session/2","ref":"ssl_session_cache_api.html#c:select_session/2"},{"type":"callback","doc":"Returns the number of sessions in the cache.\n\nIf size exceeds the maximum number of sessions, the current cache\nentries will be invalidated regardless of their remaining lifetime. Is\nto be callable from any process.","title":"ssl_session_cache_api.size/1","ref":"ssl_session_cache_api.html#c:size/1"},{"type":"callback","doc":"Takes care of possible cleanup that is needed when the cache handling process\nterminates.","title":"ssl_session_cache_api.terminate/1","ref":"ssl_session_cache_api.html#c:terminate/1"},{"type":"callback","doc":"Caches a new session or updates an already cached one.\n\nIs only called from the cache handling process.","title":"ssl_session_cache_api.update/3","ref":"ssl_session_cache_api.html#c:update/3"},{"type":"opaque","doc":"The opaque part of the key. Does not need to be handled by the callback.","title":"ssl_session_cache_api.partial_key/0","ref":"ssl_session_cache_api.html#t:partial_key/0"},{"type":"opaque","doc":"The session data that is stored for each session.","title":"ssl_session_cache_api.session/0","ref":"ssl_session_cache_api.html#t:session/0"},{"type":"type","doc":"A key to an entry in the session cache.","title":"ssl_session_cache_api.session_cache_key/0","ref":"ssl_session_cache_api.html#t:session_cache_key/0"},{"type":"type","doc":"A term that can be used to reference the cache.","title":"ssl_session_cache_api.session_cache_ref/0","ref":"ssl_session_cache_api.html#t:session_cache_ref/0"},{"type":"extras","doc":"\n# SSL Application\n\nThe ssl application provides secure communication over sockets.","title":"SSL Application","ref":"ssl_app.html"},{"type":"extras","doc":"The ssl application is an implementation of the TLS (previously known as SSL) and DTLS protocols in\nErlang.\n\nFor current statement of standards compliance see the\n[User's Guide](standards_compliance.md).","title":"Description - SSL Application","ref":"ssl_app.html#description"},{"type":"extras","doc":"The SSL application uses the `Public_Key`, `Asn1` and `Crypto` application to\nhandle public keys and encryption, hence these applications must be loaded for\nthe SSL application to work. In an embedded environment this means they must be\nstarted with `application:start/1,2` before the SSL application is started.","title":"Dependencies - SSL Application","ref":"ssl_app.html#dependencies"},{"type":"extras","doc":"The application environment configuration parameters in this section are defined\nfor the SSL application. For more information about configuration parameters,\nsee the `m:application` manual page in Kernel.\n\n> #### Note {: .info }\nAll parameters including the wording 'session_ticket' are TLS-1.3 only configuration\nand other session parameters are prior to TLS-1.3 only configuration. DTLS versions\nare based on TLS versions see [standard compliance](standards_compliance.md) for mapping.\n\nThe environment parameters can be set on the command line, for example:\n\n`erl -ssl protocol_version \"['tlsv1.2', 'tlsv1.1']\"`\n\n- **`protocol_version = ` `t:ssl:tls_version/0` | [`t:ssl:tls_version/0`]\n ` `** - Protocol supported by started clients and servers. If this\n option is not set, it defaults to all TLS protocols currently supported, more\n might be configurable, by the SSL application. This option can be overridden\n by the version option to `ssl:connect/2,3` and `ssl:listen/2`.\n\n- **`dtls_protocol_version = ` `t:ssl:dtls_version/0` | [`t:ssl:dtls_version/0`]\n ` `** - Protocol supported by started clients and servers. If this\n option is not set, it defaults to all DTLS protocols currently supported, more\n might be configurable, by the SSL application. This option can be overridden\n by the version option to `ssl:connect/2,3` and `ssl:listen/2`.\n\n- **`session_lifetime = integer() `** - Maximum lifetime of the\n session data in seconds. Defaults to 24 hours which is the maximum recommended\n lifetime by [RFC 5246](http://www.ietf.org/rfc/5246rfc.txt). However sessions\n may be invalidated earlier due to the maximum limitation of the session cache\n table.\n\n- **`session_cb = atom() `** - Deprecated Since OTP-23.3 replaced by\n `client_session_cb` and `server_session_cb`\n\n- **`client_session_cb = atom() `** - Since OTP-23.3 Name client of\n the session cache callback module that implements the `ssl_session_cache_api`\n behavior. Defaults to `ssl_client_session_cache_db`.\n\n- **`server_session_cb = atom() `** - Since OTP-23.3 Name of the\n server session cache callback module that implements the\n `ssl_session_cache_api` behavior. Defaults to `ssl_server_session_cache_db`.\n\n- **`session_cb_init_args = proplist:proplist() `** - Deprecated Since\n OTP-23.3 replaced by `client_session_cb_init_args` and\n `server_session_cb_init_args`\n\n- **`client_session_cb_init_args = proplist:proplist() `** - List of\n extra user-defined arguments to the `init` function in the session cache\n callback module. Defaults to `[]`.\n\n- **`server_session_cb_init_args = proplist:proplist() `** - List of\n extra user-defined arguments to the `init` function in the session cache\n callback module. Defaults to `[]`.\n\n- **`session_cache_client_max = integer() ` \n ** \n Limits the growth of the clients session cache, that is how many sessions\n towards servers that are cached to be used by new client connections. If the\n maximum number of sessions is reached, the current cache entries will be\n invalidated regardless of their remaining lifetime. Defaults to 1000.\n Recommended ssl-8.2.1 or later for this option to work as intended.\n\n- **`session_cache_server_max = integer() `** - Limits the growth of\n the servers session cache, that is how many client sessions are cached by the\n server. If the maximum number of sessions is reached, the current cache\n entries will be invalidated regardless of their remaining lifetime. Defaults\n to 1000. Recommended ssl-8.2.1 or later for this option to work as intended.\n\n- **`ssl_pem_cache_clean = integer() `** - Number of milliseconds\n between PEM cache validations. Defaults to 2 minutes.\n\n Note: The cache can be reloaded by calling `ssl:clear_pem_cache/0`.\n\n- **`bypass_pem_cache = boolean() `** - Introduced in ssl-8.0.2.\n Disables the PEM-cache. Can be used as a workaround for the PEM-cache\n bottleneck before ssl-8.1.1. Defaults to false.\n\n- **`alert_timeout = integer() `** - Number of milliseconds between\n sending of a fatal alert and closing the connection. Waiting a little while\n improves the peers chances to properly receiving the alert so it may shutdown\n gracefully. Defaults to 5000 milliseconds.\n\n- **`internal_active_n = integer() `** - For TLS connections this\n value is used to handle the internal socket. As the implementation was changed\n from an active once to an active N behavior (N = 100), for performance\n reasons, this option exist for possible tweaking or restoring of the old\n behavior (internal_active_n = 1) in unforeseen scenarios. The option will not\n affect erlang distribution over TLS that will always run in active N mode.\n Added in ssl-9.1 (OTP-21.2).\n\n- **`server_session_tickets_amount = integer() `** - Number of session\n tickets sent by the server. It must be greater than 0. Defaults to 3.\n\n- **`server_session_ticket_lifetime = integer() `** - Lifetime of\n session tickets sent by the server. Servers must not use any value greater\n than 604800 seconds (7 days). Expired tickets are automatically removed.\n Defaults to 7200 seconds (2 hours).\n\n- **`server_session_ticket_store_size = integer() `** - Sets the\n maximum size of the server session ticket store (stateful tickets). Defaults\n to 1000. Size limit is enforced by dropping old tickets.\n\n- **`server_session_ticket_max_early_data = integer() `** - Sets the\n maximum size of the early data that the server accepts and also configures its\n NewSessionTicket messages to include this same size limit in their\n early_data_indication extension. Defaults to 16384. Size limit is enforced by\n both client and server.\n\n- **`client_session_ticket_lifetime = integer() `** - Lifetime of\n session tickets in the client ticket store. Expired tickets are automatically\n removed. Defaults to 7200 seconds (2 hours).\n\n- **`client_session_ticket_store_size = integer() `** - Sets the\n maximum size of the client session ticket store. Defaults to 1000. Size limit\n is enforced by dropping old tickets.","title":"Configuration - SSL Application","ref":"ssl_app.html#configuration"},{"type":"extras","doc":"The SSL application uses [OTP logger](`m:logger`). TLS/DTLS alerts are logged on\nnotice level. Unexpected errors are logged on error level. These log entries\nwill by default end up in the default Erlang log. The option `log_level` may be\nused to in run-time to set the log level of a specific TLS connection, which is\nhandy when you want to use level debug to inspect the TLS handshake setup.","title":"Error Logger and Event Handlers - SSL Application","ref":"ssl_app.html#error-logger-and-event-handlers"},{"type":"extras","doc":"`m:application`","title":"See Also - SSL Application","ref":"ssl_app.html#see-also"},{"type":"extras","doc":"\n# SSL Release Notes\n\nThis document describes the changes made to the SSL application.","title":"SSL Release Notes","ref":"notes.html"},{"type":"extras","doc":"","title":"SSL 11.2.4 - SSL Release Notes","ref":"notes.html#ssl-11-2-4"},{"type":"extras","doc":"- Refactor trying to also make some optimizations introduced a bug in signature algorithms checks in OTP-26.2.1. This could manifest itself in not being able to negotiate connections using certificates needing to use some TLS-1.2 compatibility legacy signature schemes.\n\n Own Id: OTP-19249 Aux Id: ERIERL-1137, [PR-8866]\n\n- Correct timeout handling for termination code run for own alerts, so that intended timeout is used instead of falling back to OS TCP-stack timeout that is unreasonably long on some platforms.\n\n Own Id: OTP-19274 Aux Id: [PR-8901]\n\n- Fix assertion so that works as intended.\n This could result in that some TLS-1.2 clients would fail to connect to the the erlang server. Bug introduced in OTP-27.1.1\n\n Own Id: OTP-19288 Aux Id: [GH-8908], [PR-8916]\n\n[PR-8866]: https://github.com/erlang/otp/pull/8866\n[PR-8901]: https://github.com/erlang/otp/pull/8901\n[GH-8908]: https://github.com/erlang/otp/issues/8908\n[PR-8916]: https://github.com/erlang/otp/pull/8916","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 11.2.3 - SSL Release Notes","ref":"notes.html#ssl-11-2-3"},{"type":"extras","doc":"- Starting from TLS-1.3 some server handshake alerts might arrive after ssl:connection/2,3,4 has returned. If the socket is in active mode the controlling process will get the alert message, but passive sockets would only get {error, closed} on next call to ssl:recv/2,3 or ssl/setopts/2. Passive sockets calls will now return {error, error_alert()} instead.\n\n Own Id: OTP-19236 Aux Id: [PR-8261]\n\n- Servers configured to support only version (pre TLS-1.2) should ignore hello version extension, as it is an unknown extension to them, this will result in that new clients that do not support the old server version will get an insufficient security alert from the server and not a protocol version alert, this is consistent with how old servers not able to support higher protocol versions work.\n\n Own Id: OTP-19257\n\n[PR-8261]: https://github.com/erlang/otp/pull/8261","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 11.2.2 - SSL Release Notes","ref":"notes.html#ssl-11-2-2"},{"type":"extras","doc":"- 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.\n\n Own Id: OTP-19175 Aux Id: [GH-8561], [PR-8690]\n\n[GH-8561]: https://github.com/erlang/otp/issues/8561\n[PR-8690]: https://github.com/erlang/otp/pull/8690","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- All TLS-1.3 terminations are now graceful (previous TLS version terminations already were).\n\n Own Id: OTP-17848\n\n- It is now possible to use a verification fun of arity 4, giving the user fun access to both encoded and decoded versions of the certificate. This is desirable as a workaround for encoding errors preventing re-encoding from being reliable. This also saves some work load if the encoded version is needed.\n \n Note that calling `public_key:pkix_path_validation/3` with only decoded certs is not recommended, due to the decoding workarounds, although it will work as long as the workarounds are not needed.\n \n If the decoded version is needed before thecall to `m:public_key` it is recommend to use the combined_cert- type to avoid double decoding. Note that the path validation algorithm itself always needs both the encoded and decoded versions of the certs.\n \n The ssl implementation will now benefit from using this function instead of emulating the verify_fun/4.\n\n Own Id: OTP-19169\n\n- Compiler warnings for some removed functions have been corrected to point out the correct replacement functions.\n\n Own Id: OTP-19186 Aux Id: [PR-8709]\n\n- Include more information in logging of SNI (Server Name Indication) mismatch error.\n\n Own Id: OTP-19187\n\n[PR-8709]: https://github.com/erlang/otp/pull/8709","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 11.2.1 - SSL Release Notes","ref":"notes.html#ssl-11-2-1"},{"type":"extras","doc":"- Check for TLS-1.3 support should check minimum requirements.\n\n Own Id: OTP-19094 Aux Id: [GH-8489]\n\n- If both TLS-1.3 and TLS-1.2 is supported\n and TLS-1.2 negotiated convert TLS-1.3 ECDSA schemes to TLS-1.2 hash and signature pairs for increased interoperability.\n\n Own Id: OTP-19107 Aux Id: [GH-8376]\n\n- TLS-1.3 negotiation now uses SNI based options correctly instead of ignoring them.\n\n Own Id: OTP-19140\n\n[GH-8489]: https://github.com/erlang/otp/issues/8489\n[GH-8376]: https://github.com/erlang/otp/issues/8376","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Make it easier to distinguish between a invalid signature and unsupported signature.\n\n Own Id: OTP-19091\n\n- Enhance ALERT logs to help understand what causes the alert.\n\n Own Id: OTP-19092 Aux Id: [GH-8482]\n\n- When the default value for signature_algs is used, default the signature_algs_cert to the default value + rsa_pkcs1_sha1 to allow this algorithms for certificates but not for the TLS protocol. This is for better interoperability. If signature_algs is set explicitly signature_algs_cert must also be set explicitly if they should be different.\n\n Own Id: OTP-19152 Aux Id: [GH-8588]\n\n[GH-8482]: https://github.com/erlang/otp/issues/8482\n[GH-8588]: https://github.com/erlang/otp/issues/8588","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 11.2 - SSL Release Notes","ref":"notes.html#ssl-11-2"},{"type":"extras","doc":"- Starting a TLS server without sufficient credentials (certificate or anonymous cipher) would work, but it was impossible to connect to it.\n \n This has been corrected to return an error instead of starting the server.\n\n Own Id: OTP-18887 Aux Id: [GH-7493], [PR-7918]\n\n- ASN.1 decoding errors are handled in more places to ensure that errors are returned instead of cause a crash.\n\n Own Id: OTP-18969 Aux Id: [GH-8058], [PR-8256]\n\n- Improved error checking on the API functions.\n\n Own Id: OTP-18992 Aux Id: [GH-8066], [PR-8156]\n\n[GH-7493]: https://github.com/erlang/otp/issues/7493\n[PR-7918]: https://github.com/erlang/otp/pull/7918\n[GH-8058]: https://github.com/erlang/otp/issues/8058\n[PR-8256]: https://github.com/erlang/otp/pull/8256\n[GH-8066]: https://github.com/erlang/otp/issues/8066\n[PR-8156]: https://github.com/erlang/otp/pull/8156","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The `ssl` client can negotiate and handle certificate status request (OCSP stapling support on the client side).\n \n Thanks to voltone for interop testing and related discussions.\n\n Own Id: OTP-18606 Aux Id: OTP-16875,OTP-16448\n\n- Memory consumption has been reduced and performance increased by refactoring internal data structures and their usage.\n\n Own Id: OTP-18665 Aux Id: [PR-7447]\n\n- Added `c:ssl_crl_cache_api:lookup/2` as an optional `-callback` attribute.\n\n Own Id: OTP-18788 Aux Id: [PR-7700]\n\n- Key customization support has been extended to allow flexibility for implementers of for instance hardware security modules (HSM) or trusted platform modules (TPM).\n\n Own Id: OTP-18876 Aux Id: [PR-7898], [PR-7475]\n\n- The `proc_lib:set_label/1` function is now used to increase observability of `ssl` processes.\n\n Own Id: OTP-18879\n\n- Brainpool elliptic curves are now supported in TLS-1.3.\n\n Own Id: OTP-18884 Aux Id: [PR-8056]\n\n- The documentation has been migrated to use Markdown and ExDoc.\n\n Own Id: OTP-18955 Aux Id: [PR-8026]\n\n- For security reasons, the CBC ciphers are now longer included in the list of default ciphers for TLS-1.2.\n\n *** POTENTIAL INCOMPATIBILITY ***\n\n Own Id: OTP-19025 Aux Id: [PR-8250]\n\n- There is a new `cert_policy_opts` option to configure certificate policy options for the certificate path validation.\n\n Own Id: OTP-19027 Aux Id: [PR-8255]\n\n[PR-7447]: https://github.com/erlang/otp/pull/7447\n[PR-7700]: https://github.com/erlang/otp/pull/7700\n[PR-7898]: https://github.com/erlang/otp/pull/7898\n[PR-7475]: https://github.com/erlang/otp/pull/7475\n[PR-8056]: https://github.com/erlang/otp/pull/8056\n[PR-8026]: https://github.com/erlang/otp/pull/8026\n[PR-8250]: https://github.com/erlang/otp/pull/8250\n[PR-8255]: https://github.com/erlang/otp/pull/8255","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 11.1.4.5 - SSL Release Notes","ref":"notes.html#ssl-11-1-4-5"},{"type":"extras","doc":"* Avoid generating an internal alert for case that should have been an orderly shutdown by the supervisor.\n\n Own Id: OTP-19311 Aux Id: PR-8980","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"* Back port certificate_authorities option for TLS-1.3 servers to pre TLS-1.3 servers to enable them to disable the sending of certificate authorities in their certificate request. This will have same affect as the the TLS-1.3 server option although it is handled by a different mechanism in these versions, where the functionality is described to be more of a guidance, although some pre TLS clients have proven to make it mandatory as in TLS-1.3 extension handling.\n\n Own Id: OTP-19325 Aux Id: PR-9001, ERIERL-1147","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 11.1.4.4 - SSL Release Notes","ref":"notes.html#ssl-11-1-4-4"},{"type":"extras","doc":"* Starting from TLS-1.3 some server handshake alerts might arrive after ssl:connection/2,3,4 has returned. If the socket is in active mode the controlling process will get the alert message, but passive sockets would only get \\{error, closed\\} on next call to ssl:recv/2,3 or ssl/setopts/2. Passive sockets calls will now return \\{error, error_alert()\\} instead.\n\n Own Id: OTP-19236 Aux Id: PR-8261\n* Refactor trying to also make some optimizations introduced a bug in signature algorithms checks in OTP-26.2.1. This could manifest itself in not being able to negotiate connections using certificates needing to use some TLS-1.2 compatibility legacy signature schemes.\n\n Own Id: OTP-19249 Aux Id: ERIERL-1137, PR-8866\n* Servers configured to support only version (pre TLS-1.2) should ignore hello version extension, as it is an unknown extension to them, this will result in that new clients that do not support the old server version will get an insufficient security alert from the server and not a protocol version alert, this is consistent with how old servers not able to support higher protocol versions work.\n\n Own Id: OTP-19257 Aux Id: ERIERL-1131\n* Correct timeout handling for termination code run for own alerts, so that intended timeout is used instead of falling back to OS TCP-stack timeout that is unreasonably long on some platforms.\n\n Own Id: OTP-19274 Aux Id: PR-8901","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 11.1.4.3 - SSL Release Notes","ref":"notes.html#ssl-11-1-4-3"},{"type":"extras","doc":"* A race in the kTLS flavour of SSL distribution has been fixed so 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.\n\n Own Id: OTP-19175 Aux Id: GH-8561, PR-8690","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"* Make sure all TLS-1.3 terminations are graceful (previous TLS version terminations already are).\n\n Own Id: OTP-17848\n* Include more information in logging of SNI (Server Name Indication) mismatch error.\n\n Own Id: OTP-19187","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 11.1.4.2 - SSL Release Notes","ref":"notes.html#ssl-11-1-4-2"},{"type":"extras","doc":"* When the default value for signature_algs is used, default the signature_algs_cert to the default value + rsa_pkcs1_sha1 to allow this algorithms for certificates but not for the TLS protocol. This is for better interoperability. If signature_algs is set explicitly signature_algs_cert must also be set explicitly if they should be different.\n\n Own Id: OTP-19152 Aux Id: GH-8588","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 11.1.4.1 - SSL Release Notes","ref":"notes.html#ssl-11-1-4-1"},{"type":"extras","doc":"* Check for TLS-1.3 support should check minimum requirements.\n\n Own Id: OTP-19094 Aux Id: GH-8489\n* If both TLS-1.3 and TLS-1.2 is supported and TLS-1.2 negotiated convert TLS-1.3 ECDSA schemes to TLS-1.2 hash and signature pairs for increased interoperability.\n\n Own Id: OTP-19107 Aux Id: GH-8376\n* TLS-1.3 negotiation now uses SNI based options correctly instead of ignoring them.\n\n Own Id: OTP-19140","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"* Make it easier to distinguish between a invalid signature and unsupported signature.\n\n Own Id: OTP-19091\n* Enhance ALERT logs to help understand what causes the alert.\n\n Own Id: OTP-19092 Aux Id: GH-8482","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 11.1.4 - SSL Release Notes","ref":"notes.html#ssl-11-1-4"},{"type":"extras","doc":"* Fix certificate authorities check so that CA closest to peer is not lost. It could manifest itself in a failed connection as the client failed to realize it had a valid certificate chain to send to the server.\n\n Own Id: OTP-19065 Aux Id: GH-8356, PR-8367\n* ssl:signature_algs/2 did not list some legacy algorithm schemes correctly when listing all algorithms available.\n\n Own Id: OTP-19067 Aux Id: PR-8379","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 11.1.3 - SSL Release Notes","ref":"notes.html#ssl-11-1-3"},{"type":"extras","doc":"* Cleanup and close all connections in DTLS when the listen socket owner dies.\n\n Improved IPv6 handling in DTLS.\n\n Own Id: OTP-19037 Aux Id: GH-7951 GH-7955\n* Fixed a crash in dtls accept.\n\n Own Id: OTP-19059 Aux Id: GH-8338","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 11.1.2 - SSL Release Notes","ref":"notes.html#ssl-11-1-2"},{"type":"extras","doc":"* ssl:prf/5, will start working instead of hanging in a TLS-1.3 context if called appropriately. Note that the implementation has changed and in OTP-27 a more adequate API will be documented.\n\n Own Id: OTP-18890 Aux Id: GH-7911\n* Server name verification didn't work if a connection was made with IP-address as a string.\n\n Own Id: OTP-18909 Aux Id: GH-7968\n* The fallback after \"dh\" ssl option was undefined was to get \"dh\" from ssl options again. This is clearly wrong and now changed to the documented fallback \"dhfile\" ssl option.\n\n Own Id: OTP-18919 Aux Id: PR-7984\n* Correct default value selection for DTLS. Will only affect users linked with really old version of cryptolib library.\n\n Own Id: OTP-18962 Aux Id: GH-8079\n* Adhere elliptic curves with RFC 8422 pre TLS-1.3, that is Edwards curves are added to curves that can be used for key exchange, and documentation and implementation of eccs/0,1 are aligned.\n\n Own Id: OTP-18991","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"* Improve alert reason when ecdhe_rsa key_exchange does not have any common curves to use\n\n Own Id: OTP-18985","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 11.1.1 - SSL Release Notes","ref":"notes.html#ssl-11-1-1"},{"type":"extras","doc":"* Legacy name handling could cause interop problems between TLS-1.3/1.2 client and TLS-1.2 server.\n\n Own Id: OTP-18917 Aux Id: GH-7978","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 11.1 - SSL Release Notes","ref":"notes.html#ssl-11-1"},{"type":"extras","doc":"- ssl application will validate id-kp-serverAuth and id-kp-clientAuth extended\n key usage only in end entity certificates. public_key application will\n disallow \"anyExtendedKeyUsage\" for CA certificates that includes the extended\n key usage extension and marks it critical.\n\n Own Id: OTP-18739\n\n- Replaced unintentional Erlang Public License 1.1 headers in some files with\n the intended Apache License 2.0 header.\n\n Own Id: OTP-18815 Aux Id: PR-7780\n\n- Correct handling of TLS-1.3 legacy scheme names, could cause interop failures\n for TLS-1.2 clients.\n\n Own Id: OTP-18817\n\n- Add missing export for connection_info() API type.\n\n Own Id: OTP-18886","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Fixed `server name indication` which was not handled properly.\n\n Own Id: OTP-18836 Aux Id: GH-7795\n\n- Align documentation and implementation\n\n Own Id: OTP-18853 Aux Id: PR-7841\n\n- Improve connection setup by optimizing certificate lookup.\n\n Own Id: OTP-18893 Aux Id: PR-7920 PR-7921","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 11.0.3 - SSL Release Notes","ref":"notes.html#ssl-11-0-3"},{"type":"extras","doc":"- Avoid function clause error in ssl:getopts/2 by handling that inet:getopts may\n return an empty list during some circumstances, such as the socket being in a\n closing state.\n\n Own Id: OTP-18697 Aux Id: GH-7506\n\n- The API function \\`ssl:recv/3\\` has been tightened to disallow negative\n length, which has never been documented to work, but was passed through and\n caused strange errors.\n\n Own Id: OTP-18700 Aux Id: GH-7507\n\n- When a client initiated renegotiation was rejected and the client socket was\n in active mode the expected error message to the controlling process was not\n sent.\n\n Own Id: OTP-18712 Aux Id: GH-7431","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add some guidance for signature algorithms configuration in ssl applications\n users guide.\n\n Own Id: OTP-18631","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 11.0.2 - SSL Release Notes","ref":"notes.html#ssl-11-0-2"},{"type":"extras","doc":"- Added keylog information to all protocol versions in\n `ssl:connection_information/2`.\n\n Own Id: OTP-18643 Aux Id: ERIERL-932","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add RFC-6083 considerations for DTLS to enable gen_sctp based callback for the\n transport.\n\n Own Id: OTP-18618 Aux Id: ERIERL-932","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 11.0.1 - SSL Release Notes","ref":"notes.html#ssl-11-0-1"},{"type":"extras","doc":"- Make sure that selection of client certificates handle both TLS-1.3 and\n TLS-1.2 names correctly. Could cause valid client certificate to not be\n selected, and an empty client certificate message to be sent to server.\n\n Own Id: OTP-18588 Aux Id: GH-7264, PR-7277\n\n- Improved `ssl:format_error/1` to handle more error tuples.\n\n Own Id: OTP-18596 Aux Id: GH-7247\n\n- Fixed hanging `ssl:connect` when ssl application is not started.\n\n Own Id: OTP-18603 Aux Id: GH-7297\n\n- Correct handling of retransmission timers, current behavior could cause\n unwanted delays.\n\n Own Id: OTP-18632 Aux Id: PR-7300, GH-7301","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 11.0 - SSL Release Notes","ref":"notes.html#ssl-11-0"},{"type":"extras","doc":"- Remove less that 256 bit ECC from default supported ECC pre TLS-1.3\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-14771\n\n- Improved error checking and handling of ssl options.\n\n Own Id: OTP-15903\n\n- With this change, stateless tickets generated by server with anti_replay\n option enabled can be used for creating ClientHello throughout ticket\n lifetime. Without this change, usability was limited to WindowSize number of\n seconds configured for anti_replay option.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18168 Aux Id: PR-6019, GH-6014\n\n- Support for Kernel TLS (kTLS), has been added to the SSL application, for TLS\n distribution (`-proto_dist inet_tls`), the SSL option `{ktls, true}`. Using\n this for general SSL sockets is uncomfortable, undocumented and not\n recommended since it requires very platform dependent raw options.\n\n This, for now, only works for some not too old Linux distributions. Roughly, a\n kernel 5.2.0 or later with support for UserLand Protocols and the kernel\n module `tls` is required.\n\n Own Id: OTP-18235 Aux Id: PR-6104, PR-5840\n\n- With this change, TLS 1.3 server can be configured to include client\n certificate in session ticket.\n\n Own Id: OTP-18253\n\n- With this change, it is possible to configure encryption seed to be used with\n TLS1.3 stateless tickets. This enables using tickets on different server\n instances.\n\n Own Id: OTP-18254 Aux Id: PR-5982\n\n- Debugging enhancements.\n\n Own Id: OTP-18312\n\n- With this change, maybe keyword atom is not used as function name in ssl code.\n\n Own Id: OTP-18335\n\n- Replace size/1 with either tuple_size/1 or byte_size/1\n\n The [`size/1`](`size/1`) BIF is not optimized by the JIT, and its use can\n result in worse types for Dialyzer.\n\n When one knows that the value being tested must be a tuple,\n [`tuple_size/1`](`tuple_size/1`) should always be preferred.\n\n When one knows that the value being tested must be a binary,\n [`byte_size/1`](`byte_size/1`) should be preferred. However,\n [`byte_size/1`](`byte_size/1`) also accepts a bitstring (rounding up size to a\n whole number of bytes), so one must make sure that the call to `byte_size/` is\n preceded by a call to [`is_binary/1`](`is_binary/1`) to ensure that bitstrings\n are rejected. Note that the compiler removes redundant calls to\n [`is_binary/1`](`is_binary/1`), so if one is not sure whether previous code\n had made sure that the argument is a binary, it does not harm to add an\n [`is_binary/1`](`is_binary/1`) test immediately before the call to\n [`byte_size/1`](`byte_size/1`).\n\n Own Id: OTP-18405 Aux Id:\n GH-6672,PR-6702,PR-6768,PR-6700,PR-6769,PR-6812,PR-6814\n\n- For security reasons remove support for SHA1 and DSA algorithms from default\n values.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18438 Aux Id: GH-6679\n\n- Mitigate memory usage from large certificate chains by lowering the maximum\n handshake size. This should not effect the common cases, if needed it can be\n configured to a higher value.\n\n Own Id: OTP-18453\n\n- Change the client default verify option to verify_peer. Note that this makes\n it mandatory to also supply trusted CA certificates or explicitly set verify\n to verify_none. This also applies when using the so called anonymous test\n cipher suites defined in TLS versions pre TLS-1.3.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18455 Aux Id: GH-5899\n\n- Erlang distribution code in Kernel and SSL has been refactored a bit to\n facilitate debugging and re-usability, which shouldn't have any noticeable\n effects on behaviour or performance.\n\n Own Id: OTP-18456\n\n- Add encoding and decoding of use_srtp hello extension to facilitate for DTLS\n users to implement SRTP functionality.\n\n Own Id: OTP-18459\n\n- Refactors the (`ssl` application to use macros for TLS and DTLS versions\n instead of hard-coded tuple numbers. This change improves the maintainability\n of `ssl`\n\n Own Id: OTP-18465 Aux Id: GH-7065\n\n- If the function ssl:renegotiate/1 is called on connection that is running\n TLS-1.3 return an error instead of hanging or timing out.\n\n Own Id: OTP-18507\n\n- If a user cancel alert with level warning is received during handshake make it\n be handled the same regardless of TLS version. If it is received in connection\n in TLS-1.3 regard it as an error as it is inappropriate.\n\n In TLS-1.3 all error alerts are considered FATAL regardless of legacy alert\n type. But make sure legacy type is printed in logs to not confuse users that\n are expecting the same legacy type as sent by peer.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18531\n\n- Make `fail_if_no_peer_cert` default true if verify_peer is set on the server,\n otherwise the server will accept the connection if verify_peer is set and the\n user have forgot to set the fail_if_no_peer_cert and the client did not send a\n certificate.\n\n Own Id: OTP-18567\n\n- To make it easier to configure signature algorithms with algorithms that are\n moved from the default add the API function signature_algs/2 that lists\n possible values. Also make sha224 a non default value.\n\n Own Id: OTP-18572","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 10.9.1.6 - SSL Release Notes","ref":"notes.html#ssl-10-9-1-6"},{"type":"extras","doc":"* Starting from TLS-1.3 some server handshake alerts might arrive after ssl:connection/2,3,4 has returned. If the socket is in active mode the controlling process will get the alert message, but passive sockets would only get \\{error, closed\\} on next call to ssl:recv/2,3 or ssl/setopts/2. Passive sockets calls will now return \\{error, error_alert()\\} instead.\n\n Own Id: OTP-19236 Aux Id: PR-8261\n* Servers configured to support only version (pre TLS-1.2) should ignore hello version extension, as it is an unknown extension to them, this will result in that new clients that do not support the old server version will get an insufficient security alert from the server and not a protocol version alert, this is consistent with how old servers not able to support higher protocol versions work.\n\n Own Id: OTP-19257 Aux Id: ERIERL-1131\n* Correct timeout handling for termination code run for own alerts, so that intended timeout is used instead of falling back to OS TCP-stack timeout that is unreasonably long on some platforms.\n\n Own Id: OTP-19274 Aux Id: PR-8901","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.9.1.5 - SSL Release Notes","ref":"notes.html#ssl-10-9-1-5"},{"type":"extras","doc":"* TLS-1.3 negotiation now uses SNI based options correctly instead of ignoring them.\n\n Own Id: OTP-19140","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.9.1.4 - SSL Release Notes","ref":"notes.html#ssl-10-9-1-4"},{"type":"extras","doc":"* Fix certificate authorities check so that CA closest to peer is not lost. It could manifest itself in a failed connection as the client failed to realize it had a valid certificate chain to send to the server.\n\n Own Id: OTP-19065 Aux Id: GH-8356, PR-8367","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.9.1.3 - SSL Release Notes","ref":"notes.html#ssl-10-9-1-3"},{"type":"extras","doc":"- ssl application will validate id-kp-serverAuth and id-kp-clientAuth extended\n key usage only in end entity certificates. public_key application will\n disallow \"anyExtendedKeyUsage\" for CA certificates that includes the extended\n key usage extension and marks it critical.\n\n Own Id: OTP-18739\n\n- Add missing export for connection_info() API type.\n\n Own Id: OTP-18886","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.9.1.2 - SSL Release Notes","ref":"notes.html#ssl-10-9-1-2"},{"type":"extras","doc":"- The API function \\`ssl:recv/3\\` has been tightened to disallow negative\n length, which has never been documented to work, but was passed through and\n caused strange errors.\n\n Own Id: OTP-18700 Aux Id: GH-7507\n\n- When a client initiated renegotiation was rejected and the client socket was\n in active mode the expected error message to the controlling process was not\n sent.\n\n Own Id: OTP-18712 Aux Id: GH-7431","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.9.1.1 - SSL Release Notes","ref":"notes.html#ssl-10-9-1-1"},{"type":"extras","doc":"- Added keylog information to all protocol versions in\n `ssl:connection_information/2`.\n\n Own Id: OTP-18643 Aux Id: ERIERL-932","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add RFC-6083 considerations for DTLS to enable gen_sctp based callback for the\n transport.\n\n Own Id: OTP-18618 Aux Id: ERIERL-932","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 10.9.1 - SSL Release Notes","ref":"notes.html#ssl-10-9-1"},{"type":"extras","doc":"- With this change, ssl:connection_information/2 returns correct keylog data\n after TLS1.3 key update.\n\n Own Id: OTP-18489\n\n- Client signature algorithm list input order is now honored again , it was\n accidently reversed by a previous fix.\n\n Own Id: OTP-18550","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.9 - SSL Release Notes","ref":"notes.html#ssl-10-9"},{"type":"extras","doc":"- Fixed that new `dtls` connections from the same client ip port combination\n works. If there is a process waiting for accept the new connection will\n connect to that, otherwise it will try to re-connect to the old server\n connection.\n\n Own Id: OTP-18371 Aux Id: GH-6160\n\n- When shutting down a node that uses SSL distribution (`-proto_dist inet_tls`),\n a confusing error message about an unexpected process exit was printed. This\n particular message is no longer generated.\n\n Own Id: OTP-18443 Aux Id: PR-6810","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- fixes the type spec for ssl:format_error/1\n\n Own Id: OTP-18366 Aux Id: PR-6565, GH-6506\n\n- Replace size/1 with either tuple_size/1 or byte_size/1\n\n The [`size/1`](`size/1`) BIF is not optimized by the JIT, and its use can\n result in worse types for Dialyzer.\n\n When one knows that the value being tested must be a tuple,\n [`tuple_size/1`](`tuple_size/1`) should always be preferred.\n\n When one knows that the value being tested must be a binary,\n [`byte_size/1`](`byte_size/1`) should be preferred. However,\n [`byte_size/1`](`byte_size/1`) also accepts a bitstring (rounding up size to a\n whole number of bytes), so one must make sure that the call to `byte_size/` is\n preceded by a call to [`is_binary/1`](`is_binary/1`) to ensure that bitstrings\n are rejected. Note that the compiler removes redundant calls to\n [`is_binary/1`](`is_binary/1`), so if one is not sure whether previous code\n had made sure that the argument is a binary, it does not harm to add an\n [`is_binary/1`](`is_binary/1`) test immediately before the call to\n [`byte_size/1`](`byte_size/1`).\n\n Own Id: OTP-18432 Aux Id:\n GH-6672,PR-6793,PR-6784,PR-6787,PR-6785,PR-6682,PR-6800,PR-6797,PR-6798,PR-6799,PR-6796,PR-6813,PR-6671,PR-6673,PR-6684,PR-6694,GH-6677,PR-6696,PR-6670,PR-6674","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 10.8.7 - SSL Release Notes","ref":"notes.html#ssl-10-8-7"},{"type":"extras","doc":"- Maximize compatibility by ignoring change_cipher_spec during handshake even if\n middle_box_mode is not negotiated (mandated by client)\n\n Own Id: OTP-18433 Aux Id: GH-6772\n\n- Move assert of middlebox message after an hello_retry_request to maximize\n interoperability. Does not changes semantics of the protocol only allows\n unexpected message delay from server.\n\n Own Id: OTP-18467 Aux Id: GH-6807","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 10.8.6 - SSL Release Notes","ref":"notes.html#ssl-10-8-6"},{"type":"extras","doc":"- With this change, tls_sender process is hibernated after sufficient\n inactivity.\n\n Own Id: OTP-18314 Aux Id: GH-6373\n\n- Correct handling of legacy schemes so that ECDSA certs using sha1 may be used\n for some TLS-1.3 configurations.\n\n Own Id: OTP-18332 Aux Id: GH-6435, PR-6435, ERL-6435\n\n- With this change, tls_sender does not cause logger crash upon key update.\n\n Own Id: OTP-18349","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Enhance warning message\n\n Own Id: OTP-18257 Aux Id: GH-6307\n\n- Provide server option to make certificate_authorities extension in the TLS-1.3\n servers certificate request optional. This will allow clients to send\n incomplete chains that may be reconstructable and thereby verifiable by the\n server, but that would not adhere to the certificate_authorities extension.\n\n Own Id: OTP-18267 Aux Id: PR-6228, GH-6106\n\n- If the `verify_fun` handles four arguments the DER cert will be supplied as\n one of the arguments.\n\n Own Id: OTP-18302 Aux Id: ERIERL-867","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 10.8.5 - SSL Release Notes","ref":"notes.html#ssl-10-8-5"},{"type":"extras","doc":"- Fixes handling of symlinks in cacertfile option.\n\n Own Id: OTP-18266 Aux Id: GH-6328","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.8.4 - SSL Release Notes","ref":"notes.html#ssl-10-8-4"},{"type":"extras","doc":"- Reject unexpected application data in all relevant places for all TLS\n versions. Also, handle TLS-1.3 middlebox compatibility with more care. This\n will make malicious connections fail early and further, mitigate possible DoS\n attacks, that would be caught by the handshake timeout.\n\n Thanks to Aina Toky Rasoamanana and Olivier Levillain from Télécom SudParis\n for alerting us of the issues in our implementation.\n\n Own Id: OTP-18044\n\n- With this change, value of cacertfile option will be adjusted before loading\n certs from the file. Adjustments include converting relative paths to absolute\n and converting symlinks to actual file path.\n\n Thanks to Marcus Johansson\n\n Own Id: OTP-18099 Aux Id: PR-6287\n\n- In TLS-1.3, if chain certs are missing (so server auth domain adherence can\n not be determined) send peer cert and hope the server is able to recreate a\n chain in its auth domain.\n\n Own Id: OTP-18191 Aux Id: GH-6105\n\n- Make sure periodical refresh of CA certificate files repopulates cache\n properly.\n\n Own Id: OTP-18195\n\n- Correct internal CRL cache functions to use internal format consistently.\n\n Own Id: OTP-18203 Aux Id: PR-5996\n\n- Incorrect handling of client middlebox negotiation for TLS-1.3 could result in\n that a TLS-1.3 server would not use middlebox mode although the client was\n expecting it too and failing the negotiation with unexpected message.\n\n Own Id: OTP-18219 Aux Id: GH-6241, PR-6249\n\n- If the \"User\" process, the process starting the TLS connection, gets killed in\n the middle of spawning the dynamic connection tree make sure we do not leave\n any processes behind.\n\n Own Id: OTP-18233 Aux Id: GH-6244, PR-6270","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- A vulnerability has been discovered and corrected. It is registered as\n CVE-2022-37026 \"Client Authentication Bypass\". Corrections have been released\n on the supported tracks with patches 23.3.4.15, 24.3.4.2, and 25.0.2. The\n vulnerability might also exist in older OTP versions. We recommend that\n impacted users upgrade to one of these versions or later on the respective\n tracks. OTP 25.1 would be an even better choice. Impacted are those who are\n running an ssl/tls/dtls server using the ssl application either directly or\n indirectly via other applications. For example via inets (httpd), cowboy, etc.\n Note that the vulnerability only affects servers that request client\n certification, that is sets the option \\{verify, verify_peer\\}.\n\n Own Id: OTP-18241","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 10.8.3 - SSL Release Notes","ref":"notes.html#ssl-10-8-3"},{"type":"extras","doc":"- The link to crypto:engine_load refered the function with wrong arity.\n\n Own Id: OTP-18173","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.8.2 - SSL Release Notes","ref":"notes.html#ssl-10-8-2"},{"type":"extras","doc":"- Improved handling of unexpected messages during the handshake, taking the\n right action for unexpected messages.\n\n Own Id: OTP-18145","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.8.1 - SSL Release Notes","ref":"notes.html#ssl-10-8-1"},{"type":"extras","doc":"- When a TLS-1.3 enabled client tried to talk to a TLS-1.2 server that coalesces\n TLS-1.2 handshake message over one TLS record, the connection could fail due\n to some message being handled in the wrong state, this has been fixed.\n\n Own Id: OTP-18087 Aux Id: GH-5961\n\n- Correctly handles supported protocol version change from default to something\n else by sni_fun supplied to ssl:handshake/\\[2,3] together with a TCP-socket\n (so called upgrade).\n\n Own Id: OTP-18100 Aux Id: GH-5985\n\n- Also, TLS-1.3 should respond with a protocol version alert if previous\n versions, that are supported but not configured, are attempted.\n\n Own Id: OTP-18129 Aux Id: GH-5950","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.8 - SSL Release Notes","ref":"notes.html#ssl-10-8"},{"type":"extras","doc":"- When a TLS-1.3 enabled client tried to talk to a TLS-1.2 server that coalesces\n TLS-1.2 handshake message over one TLS record, the connection could fail due\n to some message being handled in the wrong state, this has been fixed.\n\n Own Id: OTP-18087 Aux Id: GH-5961\n\n- Fixed tls-1.3 session ticket lifetime which was discarded to quickly before.\n\n Own Id: OTP-18092 Aux Id: PR-5959","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- With this change, it is possible to provide several certificates. Most\n appropriate will be selected based on negotiated properties.\n\n Own Id: OTP-15993 Aux Id: GH-4143\n\n- Add options for users to be able to set spawn_opts for TLS processes (sender\n and receiver) this may be useful for tuning trade-offs between CPU and Memory\n usage.\n\n Own Id: OTP-17855 Aux Id: PR-5328\n\n- Allow key file passwords to be input as a single binary, that is we change the\n data type to be the more for the purpose logical data type iodata() instead of\n string().\n\n Own Id: OTP-17890\n\n- Logging enhancement, add location information to the warning log message.\n\n Own Id: OTP-18000 Aux Id: PR-5790\n\n- Now also accepts the signature_algs_cert option in TLS-1.2 configuration.\n\n Own Id: OTP-18014\n\n- Handle certificate selection correctly for server fallback and certificate\n authorities considerations.\n\n Own Id: OTP-18045 Aux Id: ERIERL-792, OTP-15993\n\n- Enhance handling of handshake decoding errors, especially for certificate\n authorities extension to ensure graceful termination.\n\n Own Id: OTP-18085","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 10.7.3.9 - SSL Release Notes","ref":"notes.html#ssl-10-7-3-9"},{"type":"extras","doc":"- When a client initiated renegotiation was rejected and the client socket was\n in active mode the expected error message to the controlling process was not\n sent.\n\n Own Id: OTP-18712 Aux Id: GH-7431","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.7.3.8 - SSL Release Notes","ref":"notes.html#ssl-10-7-3-8"},{"type":"extras","doc":"- Added keylog information to all protocol versions in\n `ssl:connection_information/2`.\n\n Own Id: OTP-18643 Aux Id: ERIERL-932","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add RFC-6083 considerations for DTLS to enable gen_sctp based callback for the\n transport.\n\n Own Id: OTP-18618 Aux Id: ERIERL-932","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 10.7.3.7 - SSL Release Notes","ref":"notes.html#ssl-10-7-3-7"},{"type":"extras","doc":"- Client signature algorithm list input order is now honored again , it was\n accidently reversed by a previous fix.\n\n Own Id: OTP-18550","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.7.3.6 - SSL Release Notes","ref":"notes.html#ssl-10-7-3-6"},{"type":"extras","doc":"- Maximize compatibility by ignoring change_cipher_spec during handshake even if\n middle_box_mode is not negotiated (mandated by client)\n\n Own Id: OTP-18433 Aux Id: GH-6772\n\n- Move assert of middlebox message after an hello_retry_request to maximize\n interoperability. Does not changes semantics of the protocol only allows\n unexpected message delay from server.\n\n Own Id: OTP-18467 Aux Id: GH-6807","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 10.7.3.5 - SSL Release Notes","ref":"notes.html#ssl-10-7-3-5"},{"type":"extras","doc":"- Fixes handling of symlinks in cacertfile option.\n\n Own Id: OTP-18266 Aux Id: GH-6328","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.7.3.4 - SSL Release Notes","ref":"notes.html#ssl-10-7-3-4"},{"type":"extras","doc":"- With this change, value of cacertfile option will be adjusted before loading\n certs from the file. Adjustments include converting relative paths to absolute\n and converting symlinks to actual file path.\n\n Thanks to Marcus Johansson\n\n Own Id: OTP-18099 Aux Id: PR-6287\n\n- Incorrect handling of client middlebox negotiation for TLS-1.3 could result in\n that a TLS-1.3 server would not use middlebox mode although the client was\n expecting it too and failing the negotiation with unexpected message.\n\n Own Id: OTP-18219 Aux Id: GH-6241, PR-6249\n\n- If the \"User\" process, the process starting the TLS connection, gets killed in\n the middle of spawning the dynamic connection tree make sure we do not leave\n any processes behind.\n\n Own Id: OTP-18233 Aux Id: GH-6244, PR-6270","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.7.3.3 - SSL Release Notes","ref":"notes.html#ssl-10-7-3-3"},{"type":"extras","doc":"- Reject unexpected application data in all relevant places for all TLS\n versions. Also, handle TLS-1.3 middlebox compatibility with more care. This\n will make malicious connections fail early and further, mitigate possible DoS\n attacks, that would be caught by the handshake timeout.\n\n Thanks to Aina Toky Rasoamanana and Olivier Levillain from Télécom SudParis\n for alerting us of the issues in our implementation.\n\n Own Id: OTP-18044\n\n- The link to crypto:engine_load refered the function with wrong arity.\n\n Own Id: OTP-18173\n\n- Make sure periodical refresh of CA certificate files repopulates cache\n properly.\n\n Own Id: OTP-18195","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.7.3.2 - SSL Release Notes","ref":"notes.html#ssl-10-7-3-2"},{"type":"extras","doc":"- Improved handling of unexpected messages during the handshake, taking the\n right action for unexpected messages.\n\n Own Id: OTP-18145","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.7.3.1 - SSL Release Notes","ref":"notes.html#ssl-10-7-3-1"},{"type":"extras","doc":"- When a TLS-1.3 enabled client tried to talk to a TLS-1.2 server that coalesces\n TLS-1.2 handshake message over one TLS record, the connection could fail due\n to some message being handled in the wrong state, this has been fixed.\n\n Own Id: OTP-18087 Aux Id: GH-5961\n\n- Fixed tls-1.3 session ticket lifetime which was discarded to quickly before.\n\n Own Id: OTP-18092 Aux Id: PR-5959\n\n- Correctly handles supported protocol version change from default to something\n else by sni_fun supplied to ssl:handshake/\\[2,3] together with a TCP-socket\n (so called upgrade).\n\n Own Id: OTP-18100 Aux Id: GH-5985\n\n- Also, TLS-1.3 should respond with a protocol version alert if previous\n versions, that are supported but not configured, are attempted.\n\n Own Id: OTP-18129 Aux Id: GH-5950","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Enhance handling of handshake decoding errors, especially for certificate\n authorities extension to ensure graceful termination.\n\n Own Id: OTP-18085","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 10.7.3 - SSL Release Notes","ref":"notes.html#ssl-10-7-3"},{"type":"extras","doc":"- Client certification could fail if TLS-1.3 enabled client negotiated TLS-1.2\n connection with the server, this is due to the wrong version being used when\n decoding the certificate request message from the server.\n\n Own Id: OTP-18028 Aux Id: GH-5835\n\n- socket option packet_size was not handled in ssl:setops/2 and ssl:getotps/2\n\n Own Id: OTP-18062 Aux Id: GH-5898\n\n- Remove legacy code to fix interoperability with new socket inet_backend.\n\n Own Id: OTP-18071 Aux Id: GH-5930","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.7.2 - SSL Release Notes","ref":"notes.html#ssl-10-7-2"},{"type":"extras","doc":"- With this change, potential hanging of pre TLS1.3 client receiving OSCP staple\n message is avoided.\n\n Own Id: OTP-17994","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.7.1 - SSL Release Notes","ref":"notes.html#ssl-10-7-1"},{"type":"extras","doc":"- Client certification could fail for TLS-1.3 servers that did not include the\n certificate_authorities extension in its certificate request message.\n\n Own Id: OTP-17971 Aux Id: GH-5783","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.7 - SSL Release Notes","ref":"notes.html#ssl-10-7"},{"type":"extras","doc":"- Improved error handling.\n\n Own Id: OTP-17759 Aux Id: GH-5367\n\n- Before this change, net_kernel used with TLS distribution might be leaking\n processes in case of connectivity issues.\n\n Own Id: OTP-17815 Aux Id: GH-5332\n\n- Fix makefile dependency bugs.\n\n Own Id: OTP-17847 Aux Id: PR-5574 GH-5548\n\n- Make sure the TLS sender process handles explicit calls to\n erlang:disconnect_node properly, avoiding potential hanging problems in\n net_kernel.\n\n Own Id: OTP-17929 Aux Id: GH-5708","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add support for TLS-1.3 certificate_authorities extension. And process\n certificate_authorities field in pre-TLS-1.3 certificate requests.\n\n Own Id: OTP-15719\n\n- Support password fun for protected keyfiles in ssl:connect function.\n\n Own Id: OTP-17816 Aux Id: PR-5607\n\n- Add in some cases earlier detection of possible DoS attacks by malicious\n clients sending unexpected TLS messages instead of the client hello. Note that\n such attacks are already mitigated by providing a timeout for the TLS\n handshake.\n\n Own Id: OTP-17903","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 10.6.1 - SSL Release Notes","ref":"notes.html#ssl-10-6-1"},{"type":"extras","doc":"- Improve SNI (server name indication) handling so that protocol version can be\n selected with regards to SNI. Also, make sure that\n ssl:connection_information/1 returns the correct SNI value.\n\n Own Id: OTP-17794 Aux Id: GH-5341, GH-4450\n\n- Fixed cipher suite listing functions so that the listing of all cipher suites\n will be complete. Another fix for cipher suite handling in OTP-24.1\n accidentally excludes a few cipher suites from the listing of all cipher\n suites.\n\n Own Id: OTP-17829 Aux Id: ERIERL-708\n\n- Reenable legacy cipher suite TLS_RSA_WITH_3DES_EDE_CBC_SHA for explicit\n configuration in TLS-1.2, not supported by default.\n\n Own Id: OTP-17879 Aux Id: GH-5624","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Avoid unnecessary logs by better adjusting the tls_sender process to the new\n supervisor structure in OTP-24.2\n\n Own Id: OTP-17831","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 10.6 - SSL Release Notes","ref":"notes.html#ssl-10-6"},{"type":"extras","doc":"- Allow re-connect on DTLS sockets\n\n Can happen when a computer reboots and connects from the same client port\n without the server noticing should be allowed according to RFC.\n\n Own Id: OTP-17411 Aux Id: ERL-1203, GH-4393\n\n- Fix tls and non-tls distribution to use erl_epmd:address_please to figure out\n if IPv4 or IPv6 addresses should be used when connecting to the remote node.\n\n Before this fix, a dns lookup of the remote node hostname determined which IP\n version was to be used which meant that the hostname had to resolve to a valid\n ip address.\n\n Own Id: OTP-17809 Aux Id: PR-5337 GH-5334","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Use supervisor significant child to manage tls connection process and tls\n sender process dependency.\n\n Own Id: OTP-17417\n\n- Random generation adjustment for TLS1.3\n\n Own Id: OTP-17699\n\n- Allow any \\{03,XX\\} TLS record version in the client hello for maximum\n interoperability\n\n Own Id: OTP-17761 Aux Id: GH-5380","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 10.5.3 - SSL Release Notes","ref":"notes.html#ssl-10-5-3"},{"type":"extras","doc":"- Correct typo of ECC curve name in signature algorithm handling. Will make the\n signature algorithm ecdsa_secp521r1_sha512 succeed.\n\n Own Id: OTP-17756 Aux Id: GH-5383, PR-5397\n\n- Suppress authenticity warning when option verify_none is explicitly supplied.\n\n Own Id: OTP-17757 Aux Id: GH-5352, PR-5395","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.5.2 - SSL Release Notes","ref":"notes.html#ssl-10-5-2"},{"type":"extras","doc":"- Fix TLS-1.2 RSA-PSS negotiation and also fix broken certificate request\n message for pre-TLS-1.3 servers.\n\n Own Id: OTP-17688 Aux Id: GH-5255\n\n- Fix CRL issuer verification that under some circumstances could fail with a\n function_clause error.\n\n Own Id: OTP-17723 Aux Id: GH-5300","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.5.1 - SSL Release Notes","ref":"notes.html#ssl-10-5-1"},{"type":"extras","doc":"- Before that change, TLS downgrade could occasionally fail when data intended\n for downgraded socket were delivered together with CLOSE_NOTIFY alert to ssl\n app.\n\n Own Id: OTP-17393\n\n- Avoid re-encoding of decoded certificates. This could cause unexpected\n failures as some subtle encoding errors can be tolerated when decoding but\n hence creating another sequence of bytes if the decoded value is re-encoded.\n\n Own Id: OTP-17657\n\n- Fix possible process leak when the process doing ssl:transport_accept dies\n before initiating the TLS handshake.\n\n Own Id: OTP-17666 Aux Id: GH-5239\n\n- Fix dtls memory leak, the replay window code was broken.\n\n Own Id: OTP-17670 Aux Id: GH-5224","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.5 - SSL Release Notes","ref":"notes.html#ssl-10-5"},{"type":"extras","doc":"- Fix Makefile dependency generation to work no matter what the `ERL_TOP` folder\n is called.\n\n Own Id: OTP-17423 Aux Id: GH-4823 PR-4829\n\n- If trying to downgrade a TLS-1.3 connection to a plain TCP connection,\n possible TLS-1.3 session ticket messages will be ignored in the \"downgrade\"\n state while waiting for the close notify alert.\n\n Own Id: OTP-17517 Aux Id: GH-5009\n\n- Corrected error handling to correctly generate an insufficient security alert\n when there are no suitable groups that can be negotiated in TLS-1.3 instead of\n crashing resulting in an internal error alert.\n\n Own Id: OTP-17521\n\n- Properly handle default session data storage.\n\n When a client tries to reuse an expired session the default server storage\n handling would crash losing other session data. This would cause a error\n report and possible loss of abbreviated handshakes.\n\n Own Id: OTP-17635 Aux Id: GH-5192","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add support for RSA-PSS-PSS signatures and signature_algorithms_cert in\n TLS-1.2. This is a TLS-1.3 RFC requirement to backport this functionality.\n\n Own Id: OTP-16590 Aux Id: ERL-625, GH-5029\n\n- Use inet:monitor/1 to monitor listen-sockets so that we are compatible with\n the new socket backend for gen_tcp.\n\n Own Id: OTP-17392 Aux Id: PR-5050\n\n- Enhance ssl:prf/4 handling and testing\n\n Own Id: OTP-17464\n\n- Enhanced cipher suite filtering functionality, making sure TLS-1.3 and TLS-1.2\n cipher suites can be supported correctly together even when TLS-1.2 anonymous\n ciphers are included.\n\n Own Id: OTP-17501 Aux Id: GH-4978\n\n- Enhance gracefulness especially in TLS-1.3\n\n Own Id: OTP-17530","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 10.4.2 - SSL Release Notes","ref":"notes.html#ssl-10-4-2"},{"type":"extras","doc":"- Handle cross-signed root certificates when old root expired as reported in\n GH-4877.\n\n Own Id: OTP-17475 Aux Id: GH-4877\n\n- The signature selection algorithm has been changed to also verify if the\n client supports signatures using the elliptic curve of the server's\n public/private key pair. This change fixes #4958.\n\n Own Id: OTP-17529 Aux Id: PR-4979, GH-4958","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Slight optimization of certificate decoding.\n\n Own Id: OTP-17150 Aux Id: GH-4877","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 10.4.1 - SSL Release Notes","ref":"notes.html#ssl-10-4-1"},{"type":"extras","doc":"- Fix cache invalidation problem for CA certs provided by the cacertfile option.\n\n Own Id: OTP-17435 Aux Id: ERIERL-653","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.4 - SSL Release Notes","ref":"notes.html#ssl-10-4"},{"type":"extras","doc":"- Missing runtime dependencies has been added to this application.\n\n Own Id: OTP-17243 Aux Id: PR-4557\n\n- TLS handshake should fail if OCSP staple is requested but missing. Note that\n OCSP support is still considered experimental and only partially implemented.\n\n Own Id: OTP-17343","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Removed ssl:ssl_accept/1,2,3 and ssl:cipher:suites/0,1 use ssl:handshake/1,2,3\n and ssl:cipher_suites/2,3 instead.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-16974\n\n- Make TLS handshakes in Erlang distribution concurrent.\n\n Own Id: OTP-17044 Aux Id: PR-2654\n\n- Randomize internal `{active,n}` optimization when running Erlang distribution\n over TLS to spread RAM/CPU spike that may occur when starting up a big\n cluster.\n\n Own Id: OTP-17117 Aux Id: PR-2933\n\n- TLS connections now support EdDSA certificates.\n\n Own Id: OTP-17142 Aux Id: PR-4756, GH-4637, GH-4650\n\n- Enhance documentation and logging of certificate handling.\n\n Own Id: OTP-17384 Aux Id: GH-4800","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 10.3.1.5 - SSL Release Notes","ref":"notes.html#ssl-10-3-1-5"},{"type":"extras","doc":"- Correct corner case of unexpected message handling for pre TLS-1.3 versions,\n could cause \"late failure\" and make the server dependent on its handshake\n timeout to prevent possible DoS attacks.\n\n Own Id: OTP-18224","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.3.1.4 - SSL Release Notes","ref":"notes.html#ssl-10-3-1-4"},{"type":"extras","doc":"- The link to crypto:engine_load refered the function with wrong arity.\n\n Own Id: OTP-18173","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.3.1.3 - SSL Release Notes","ref":"notes.html#ssl-10-3-1-3"},{"type":"extras","doc":"- Improved handling of unexpected messages during the handshake, taking the\n right action for unexpected messages.\n\n Own Id: OTP-18145","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.3.1.2 - SSL Release Notes","ref":"notes.html#ssl-10-3-1-2"},{"type":"extras","doc":"- Handle cross-signed root certificates when old root expired as reported in\n GH-4877.\n\n Own Id: OTP-17475 Aux Id: GH-4877\n\n- The signature selection algorithm has been changed to also verify if the\n client supports signatures using the elliptic curve of the server's\n public/private key pair. This change fixes #4958.\n\n Own Id: OTP-17529 Aux Id: PR-4979, GH-4958","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Slight optimization of certificate decoding.\n\n Own Id: OTP-17150 Aux Id: GH-4877","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 10.3.1.1 - SSL Release Notes","ref":"notes.html#ssl-10-3-1-1"},{"type":"extras","doc":"- Fix cache invalidation problem for CA certs provided by the cacertfile option.\n\n Own Id: OTP-17435 Aux Id: ERIERL-653","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.3.1 - SSL Release Notes","ref":"notes.html#ssl-10-3-1"},{"type":"extras","doc":"- Retain backwards compatible behavior of verify_fun when handling incomplete\n chains that are not verifiable.\n\n Own Id: OTP-17296 Aux Id: GH-4682\n\n- Avoid server session handler crash, this will increase session ruse\n opportunities.\n\n Own Id: OTP-17348 Aux Id: ERIERL-641","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.3 - SSL Release Notes","ref":"notes.html#ssl-10-3"},{"type":"extras","doc":"- Fix CRL handling that previously could fail to find the issuer cert under some\n circumstances.\n\n Own Id: OTP-17261 Aux Id: GH-4589\n\n- TLS-1.3 client could, under some circumstances, select an incorrect algorithm\n to sign the certificate verification message causing a TLS Decrypt Alert being\n issued by the server.\n\n Own Id: OTP-17281 Aux Id: GH-4620\n\n- Correct handling of default values for emulated socket options and retain the\n order of the ssl options list to ensure backwards compatible behavior if\n options should be set more than once.\n\n Own Id: OTP-17282","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Enhance pre TLS-1.3 session handling so the client and server side handling is\n completely separated and client disregards oldest session when reaching max\n limit of the session table.\n\n Own Id: OTP-16876\n\n- This change implements the early data feature for TLS 1.3 clients.\n\n TLS 1.3 allows clients to send data in the first flight using a Pre-Shared Key\n to authenticate the server and to encrypt the early data.\n\n Own Id: OTP-16985\n\n- This change implements the early data feature for TLS 1.3 servers.\n\n Own Id: OTP-17042","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 10.2.4.4 - SSL Release Notes","ref":"notes.html#ssl-10-2-4-4"},{"type":"extras","doc":"- Improved handling of unexpected messages during the handshake, taking the\n right action for unexpected messages.\n\n Own Id: OTP-18145","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.2.4.3 - SSL Release Notes","ref":"notes.html#ssl-10-2-4-3"},{"type":"extras","doc":"- Fix cache invalidation problem for CA certs provided by the cacertfile option.\n\n Own Id: OTP-17435 Aux Id: ERIERL-653","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.2.4.2 - SSL Release Notes","ref":"notes.html#ssl-10-2-4-2"},{"type":"extras","doc":"- Fix handling of emulated socket options, the previous patch was incomplete,\n\n Own Id: OTP-17305","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.2.4.1 - SSL Release Notes","ref":"notes.html#ssl-10-2-4-1"},{"type":"extras","doc":"- Backport of OTP-17282\n\n Correct handling of default values for emulated socket options and retain the\n order of the ssl options list to ensure backwards compatible behavior if\n options should be set more than once.\n\n Own Id: OTP-17289 Aux Id: GH-4585","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.2.4 - SSL Release Notes","ref":"notes.html#ssl-10-2-4"},{"type":"extras","doc":"- Enhance logging option log_level to support none and all, also restore\n backwards compatibility for log_alert option.\n\n Own Id: OTP-17228 Aux Id: ERIERL-614","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.2.3 - SSL Release Notes","ref":"notes.html#ssl-10-2-3"},{"type":"extras","doc":"- Avoid race when the first two upgrade server handshakes (that is servers that\n use a gen_tcp socket as input to ssl:handshake/2,3) start close to each other.\n Could lead to that one of the handshakes would fail.\n\n Own Id: OTP-17190 Aux Id: ERIERL-606","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 10.2.2 - SSL Release Notes","ref":"notes.html#ssl-10-2-2"},{"type":"extras","doc":"- Avoid that upgrade (from TCP to TLS) servers starts multiple session cache\n handlers for the same server. This applies to Erlang distribution over TLS\n servers.\n\n Own Id: OTP-17139 Aux Id: ERL-1458, OTP-16239\n\n- Legacy cipher suites defined before TLS-1.2 (but still supported) should be\n possible to use in TLS-1.2. They where accidentally excluded for available\n cipher suites for TLS-1.2 in OTP-23.2.2.\n\n Own Id: OTP-17174 Aux Id: ERIERL-597","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Enable Erlang distribution over TLS to run TLS-1.3, although TLS-1.2 will\n still be default.\n\n Own Id: OTP-16239 Aux Id: ERL-1458, OTP-17139","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 10.2.1 - SSL Release Notes","ref":"notes.html#ssl-10-2-1"},{"type":"extras","doc":"- Fix CVE-2020-35733 this only affects ssl-10.2 (OTP-23.2). This vulnerability\n could enable a man in the middle attack using a fake chain to a known trusted\n ROOT. Also limits alternative chain handling, for handling of possibly\n extraneous certs, to improve memory management.\n\n Own Id: OTP-17098","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add support for AES CCM based cipher suites defined in RFC 7251\n\n Also Correct cipher suite name conversion to OpenSSL names. A few names where\n corrected earlier in OTP-16267 For backwards compatible reasons we support\n usage of openSSL names for cipher suites. Mostly anonymous suites names where\n incorrect, but also some legacy suites.\n\n Own Id: OTP-17100","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 10.2 - SSL Release Notes","ref":"notes.html#ssl-10-2"},{"type":"extras","doc":"- SSL's Erlang Distribution Protocol modules inet_tls_dist and inet6_tls_dist\n lacked a callback function, so the start flag \"-dist_listen false\" did not\n work, which has now been fixed.\n\n Own Id: OTP-15126 Aux Id: ERL-1375\n\n- Correct OpenSSL names for newer cipher suites using DHE in their name that\n accidentally got the wrong value when fixing other older names using EDH\n instead.\n\n Own Id: OTP-16267 Aux Id: ERIERL-571, ERIERL-477\n\n- This change improves the handling of DTLS listening dockets, making it\n possible to open multiple listeners on the same port with different IP\n addresses.\n\n Own Id: OTP-16849 Aux Id: ERL-1339\n\n- Fix a bug that causes cross-build failure.\n\n This change excludes the ssl.d dependency file from the source tarballs.\n\n Own Id: OTP-16921\n\n- This change fixes ssl:peername/1 when called on a DTLS client socket.\n\n Own Id: OTP-16923 Aux Id: ERL-1341, PR-2786\n\n- Retain emulation of active once on a closed socket to behave as before 23.1\n\n Own Id: OTP-17018 Aux Id: ERL-1409\n\n- Corrected server session cache entry deletion pre TLS-1.3. May increase\n session reuse.\n\n Own Id: OTP-17019 Aux Id: ERL-1412","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Handle extraneous certs in certificate chains as well as chains that are\n incomplete but can be reconstructed or unordered chains. The cert and certfile\n options will now accept a list of certificates so that the user may specify\n the chain explicitly.\n\n Also, the default value of the depth option has been increased to allow longer\n chains by default.\n\n Own Id: OTP-16277\n\n- This change implements optional NSS-style keylog in\n ssl:connection_information/2 for debugging purposes.\n\n The keylog contains various TLS secrets that can be loaded in Wireshark to\n decrypt TLS packets.\n\n Own Id: OTP-16445 Aux Id: PR-2823\n\n- Use new gen_statem feature of changing callback mode to improve code\n maintainability.\n\n Own Id: OTP-16529\n\n- The handling of Service Name Indication has been aligned with RFC8446.\n\n Own Id: OTP-16762\n\n- Add explicit session reuse option to TLS clients for pre TLS-1.3 sessions.\n Also, add documentation to Users Guide for such sessions.\n\n Own Id: OTP-16893","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 10.1 - SSL Release Notes","ref":"notes.html#ssl-10-1"},{"type":"extras","doc":"- If a passive socket is created, ssl:recv/2,3 is never called and then the peer\n closes the socket the controlling process will no longer receive an active\n close message.\n\n Own Id: OTP-16697 Aux Id: ERIERL-496\n\n- Data deliver with ssl:recv/2,3 could fail for when using packet mode. This has\n been fixed by correcting the flow control handling of passive sockets when\n packet mode is used.\n\n Own Id: OTP-16764\n\n- This change fixes a potential man-in-the-middle vulnerability when the ssl\n client is configured to automatically handle session tickets\n (\\{session_tickets, auto\\}).\n\n Own Id: OTP-16765\n\n- Fix the internal handling of options 'verify' and 'verify_fun'.\n\n This change fixes a vulnerability when setting the ssl option 'verify' to\n verify_peer in a continued handshake won't take any effect resulting in the\n acceptance of expired peer certificates.\n\n Own Id: OTP-16767 Aux Id: ERIERL-512\n\n- This change fixes the handling of stateless session tickets when anti-replay\n is enabled.\n\n Own Id: OTP-16776 Aux Id: ERL-1316\n\n- Fix a crash due to the faulty handling of stateful session tickets received by\n servers expecting stateless session tickets.\n\n This change also improves the handling of faulty/invalid tickets.\n\n Own Id: OTP-16777 Aux Id: ERL-1317\n\n- Correct flow ctrl checks from OTP-16764 to work as intended. Probably will not\n have a noticeable affect but will make connections more well behaved under\n some circumstances.\n\n Own Id: OTP-16837 Aux Id: ERL-1319, OTP-16764\n\n- Distribution over TLS could exhibit livelock-like behaviour when there is a\n constant stream of distribution messages. Distribution data is now chunked\n every 16 Mb to avoid that.\n\n Own Id: OTP-16851 Aux Id: PR-2703","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Implement the cookie extension for TLS 1.3.\n\n Own Id: OTP-15855\n\n- Experimental OCSP client support.\n\n Own Id: OTP-16448\n\n- TLS 1.0 -TLS-1.2 sessions tables now have a absolute max value instead of\n using a shrinking mechanism when reaching the limit. To avoid out of memory\n problems under heavy load situations. Note that this change infers that\n implementations of ssl_session_cache_api needs to implement the size function\n (introduce in OTP 19) for session reuse to be optimally utilized.\n\n Own Id: OTP-16802 Aux Id: ERIERL-516","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 10.0 - SSL Release Notes","ref":"notes.html#ssl-10-0"},{"type":"extras","doc":"- Fix a bug that causes cross-build failure.\n\n This change excludes the ssl.d dependency file from the source tar balls.\n\n Own Id: OTP-16562 Aux Id: ERL-1168\n\n- Correct translation of OpenSSL legacy names for two legacy cipher suites\n\n Own Id: OTP-16573 Aux Id: ERIERL-477\n\n- Correct documentation for PSK identity and SRP username.\n\n Own Id: OTP-16585\n\n- Make sure client hostname check is run when client uses its own verify_fun\n\n Own Id: OTP-16626 Aux Id: ERL-1232\n\n- Improved signature selection mechanism in TLS 1.3 for increased\n interoperability.\n\n Own Id: OTP-16638 Aux Id: ERL-1206","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Drop support for SSL-3.0. Support for this legacy TLS version has not been\n enabled by default since OTP 19. Now all code to support it has been removed,\n that is SSL-3.0 protocol version can not be used and is considered invalid.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-14790\n\n- Added support for RSA-PSS signature schemes\n\n Own Id: OTP-15247\n\n- Improve interoperability by implementing the middlebox compatibility mode.\n\n The middlebox compatibility mode makes the TLS 1.3 handshake look more like a\n TLS 1.2 handshake and increases the chance of successfully establishing TLS\n 1.3 connections through legacy middleboxes.\n\n Own Id: OTP-15589\n\n- Utilize new properties of\n [`erlang:dist_ctrl_get_data()`](`erlang:dist_ctrl_get_data/1`) for performance\n improvement of Erlang distribution over TLS.\n\n Own Id: OTP-16127 Aux Id: OTP-15618\n\n- Calls of deprecated functions in the\n [Old Crypto API](`e:crypto:new_api.md#the-old-api`) are replaced by calls of\n their [substitutions](`e:crypto:new_api.md#the-new-api`).\n\n Own Id: OTP-16346\n\n- Implement cipher suite TLS_AES_128_CCM_8_SHA256.\n\n Own Id: OTP-16391\n\n- This change adds TLS-1.3 to the list of default supported versions. That is,\n TLS-1.3 and TLS-1.2 are configured when ssl option 'versions' is not\n explicitly set.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-16400\n\n- Refactored the internal handling of deprecated and removed functions.\n\n Own Id: OTP-16469\n\n- Extended ssl:versions so that it lists supported, available and implemented\n TLS/DTLS versions.\n\n Own Id: OTP-16519\n\n- Added new option exclusive for ssl:cipher_suites/2,3\n\n Own Id: OTP-16532\n\n- Avoid DoS attack against stateful session_tickets by making session ticket ids\n unpredictable.\n\n Own Id: OTP-16533\n\n- Add support for the max_fragment_length extension (RFC 6066).\n\n Own Id: OTP-16547 Aux Id: PR-2547\n\n- Add srp_username in ssl:connection_info, update the document with types of\n this function.\n\n Own Id: OTP-16584","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 9.6.2.3 - SSL Release Notes","ref":"notes.html#ssl-9-6-2-3"},{"type":"extras","doc":"- Correct flow ctrl checks from OTP-16764 to work as intended. Probably will not\n have a noticeable affect but will make connections more well behaved under\n some circumstances.\n\n Own Id: OTP-16837 Aux Id: ERL-1319, OTP-16764\n\n- Fix a bug that causes cross-build failure.\n\n This change excludes the ssl.d dependency file from the source tar balls.\n\n Own Id: OTP-16921","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 9.6.2.2 - SSL Release Notes","ref":"notes.html#ssl-9-6-2-2"},{"type":"extras","doc":"- Data deliver with ssl:recv/2,3 could fail for when using packet mode. This has\n been fixed by correcting the flow control handling of passive sockets when\n packet mode is used.\n\n Own Id: OTP-16764\n\n- Fix the internal handling of options 'verify' and 'verify_fun'.\n\n This change fixes a vulnerability when setting the ssl option 'verify' to\n verify_peer in a continued handshake won't take any effect resulting in the\n acceptance of expired peer certificates.\n\n Own Id: OTP-16767 Aux Id: ERIERL-512","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 9.6.2.1 - SSL Release Notes","ref":"notes.html#ssl-9-6-2-1"},{"type":"extras","doc":"- If a passive socket is created, ssl:recv/2,3 is never called and then the peer\n closes the socket the controlling process will no longer receive an active\n close message.\n\n Own Id: OTP-16697 Aux Id: ERIERL-496","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 9.6.2 - SSL Release Notes","ref":"notes.html#ssl-9-6-2"},{"type":"extras","doc":"- Fix timing bug that could cause ssl sockets to become unresponsive after an\n ssl:recv/3 call timed out\n\n Own Id: OTP-16619 Aux Id: ERL-1213","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 9.6.1 - SSL Release Notes","ref":"notes.html#ssl-9-6-1"},{"type":"extras","doc":"- Correct error handling when the partial_chain fun claims a certificate to be\n the trusted cert that is not part of the chain. This bug would hide the\n appropriate alert generating an \"INTERNAL_ERROR\" alert instead.\n\n Own Id: OTP-16567 Aux Id: ERIERL-481","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 9.6 - SSL Release Notes","ref":"notes.html#ssl-9-6"},{"type":"extras","doc":"- Correct handling of TLS record limit in TLS-1.3. The max value differs from\n previous versions. Also the payload data max record check was broken, that is\n record overflow problems could occur if user sent large amounts of data.\n\n Own Id: OTP-16258\n\n- Correct close handling for DTLS\n\n Own Id: OTP-16348 Aux Id: ERL-1110\n\n- Fix ssl:getstat/1-2 to also work for DTLS sockets\n\n Own Id: OTP-16352 Aux Id: ERL-1099\n\n- Correct internal handling och socket active mode to avoid reviving TCP data\n aimed for a downgraded TLS socket.\n\n Own Id: OTP-16425\n\n- When using the host name as fallback for SNI (server name indication) strip a\n possible trailing dot that is allowed in a host name but not in the SNI. Also\n if the server receives a SNI with a trailing dot send an UNRECOGNIZED_NAME\n alert.\n\n Own Id: OTP-16437 Aux Id: ERL-1135\n\n- Immediately remove session entries if handshake is abruptly closed at\n transport level.\n\n Own Id: OTP-16479","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Implementation of the key and initialization vector update feature, and\n general hardening of TLS 1.3.\n\n There are cryptographic limits on the amount of plaintext which can be safely\n encrypted under a given set of keys.\n\n This change enforces those limits by triggering automatic key updates on TLS\n 1.3 connections.\n\n Own Id: OTP-15856\n\n- Add support for TLS 1.3 Session Tickets (stateful and stateless). This allows\n session resumption using keying material from a previous successful handshake.\n\n Own Id: OTP-16253\n\n- Add support for key exchange with Edward curves and PSS-RSA padding in\n signature verification.\n\n Own Id: OTP-16528","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 9.5.3 - SSL Release Notes","ref":"notes.html#ssl-9-5-3"},{"type":"extras","doc":"- Enhance error handling, all ALERTS shall be handled gracefully and not cause a\n crash.\n\n Own Id: OTP-16413 Aux Id: ERL-1136\n\n- Enhance alert logging, in some places the role indication of the alert origin\n was missing. So the log would say undefined instead of client or server.\n\n Own Id: OTP-16424\n\n- Two different optimizations did not work together and resulted in the possible\n breakage of connections using stream ciphers (that is RC4). Reworked the\n implementation to avoid this.\n\n Own Id: OTP-16426 Aux Id: ERL-1136","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 9.5.2 - SSL Release Notes","ref":"notes.html#ssl-9-5-2"},{"type":"extras","doc":"- Fix the handling of GREASE values sent by web browsers when establishing TLS\n 1.3 connections. This change improves handling of GREASE values in various\n protocol elements sent in a TLS 1.3 ClientHello.\n\n Own Id: OTP-16388 Aux Id: ERL-1130\n\n- Correct DTLS listen emulation, could cause problems with opening a new DTLS\n listen socket for a port previously used by a now closed DTLS listen socket.\n\n Own Id: OTP-16396 Aux Id: ERL-1118","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 9.5.1 - SSL Release Notes","ref":"notes.html#ssl-9-5-1"},{"type":"extras","doc":"- Add missing alert handling clause for TLS record handling. Could sometimes\n cause confusing error behaviors of TLS connections.\n\n Own Id: OTP-16357 Aux Id: ERL-1166\n\n- Fix handling of ssl:recv that happens during a renegotiation. Using the\n passive receive function ssl:recv/\\[2,3] during a renegotiation would fail the\n connection with unexpected msg.\n\n Own Id: OTP-16361","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 9.5 - SSL Release Notes","ref":"notes.html#ssl-9-5"},{"type":"extras","doc":"- Corrected CRL handling which could cause CRL verification to fail. This could\n happen when the CRL distribution point explicitly specifies the CRL issuer,\n that is not using the fallback.\n\n Own Id: OTP-16156 Aux Id: ERL-1030\n\n- Correct handling of unordered chains so that it works as expected\n\n Own Id: OTP-16293\n\n- Fix bug causing ssl application to crash when handshake is paused and\n ClientHello contains extensions for session resumption\n (psk_key_exchange_modes, pre_shared_key).\n\n Own Id: OTP-16295 Aux Id: ERL-1095\n\n- Fix connectivity problems with legacy servers when client is configured to\n support a range of protocol versions including TLS 1.3.\n\n Own Id: OTP-16303","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Improve session handling for TLS-1.3 compatibility mode and cleaner internal\n handling so that removal of old session data can be more efficient, hopefully\n mitigating problems with big session tables during heavy load.\n\n Own Id: OTP-15524 Aux Id: OTP-15352\n\n- Correct handling of DTLS listen socket emulation. Could cause failure to\n create new listen socket after process that owned previous listen socket died.\n\n Own Id: OTP-15809 Aux Id: ERL-917\n\n- Add detailed info in ALERT description when client does not send a requested\n cert.\n\n Own Id: OTP-16266","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 9.4 - SSL Release Notes","ref":"notes.html#ssl-9-4"},{"type":"extras","doc":"- Handling of zero size fragments in TLS could cause an infinite loop. This has\n now been corrected.\n\n Own Id: OTP-15328 Aux Id: ERIERL-379\n\n- DTLS record check needs to consider that a resent hello message can have a\n different version than the negotiated.\n\n Own Id: OTP-15807 Aux Id: ERL-920","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Basic support for TLS 1.3 Client for experimental use. For more information\n see the Standards Compliance chapter of the User's Guide.\n\n Own Id: OTP-15431\n\n- Correct solution for retaining tcp flow control OTP-15802 (ERL-934) as to not\n break ssl:recv as reported in (ERL-938)\n\n Own Id: OTP-15823 Aux Id: ERL-934, ERL-938\n\n- Enhance dialyzer specs to reflect implementation better and avoid dialyzer\n warnings for the user that wants to use TLS with unix domain sockets.\n\n Own Id: OTP-15851 Aux Id: PR-2235\n\n- Add support for ECDSA signature algorithms in TLS 1.3.\n\n Own Id: OTP-15854\n\n- Correct error handling of TLS downgrade, possible return values form\n ssl:close/2 when downgrading is \\{ok, Port\\} or \\{error, Reason\\}, it could\n happen that only ok was returned instead of \\{error, closed\\} when downgrade\n failed due to that the peer closed the TCP connection.\n\n Own Id: OTP-16027","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 9.3.5 - SSL Release Notes","ref":"notes.html#ssl-9-3-5"},{"type":"extras","doc":"- Enhance error handling for erroneous alerts from the peer.\n\n Own Id: OTP-15943","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 9.3.4 - SSL Release Notes","ref":"notes.html#ssl-9-3-4"},{"type":"extras","doc":"- Fix handling of certificate decoding problems in TLS 1.3 similarly as in TLS\n 1.2.\n\n Own Id: OTP-15900\n\n- Hibernation now works as expected in all cases, was accidentally broken by\n optimization efforts.\n\n Own Id: OTP-15910\n\n- Fix interoperability problems with openssl when the TLS 1.3 server is\n configured with the option signature_algs_cert.\n\n Own Id: OTP-15913","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 9.3.3 - SSL Release Notes","ref":"notes.html#ssl-9-3-3"},{"type":"extras","doc":"- Correct handshake handling, might cause strange symptoms such as ASN.1\n certificate decoding issues.\n\n Own Id: OTP-15879 Aux Id: ERL-968\n\n- Fix handling of the signature_algorithms_cert extension in the ClientHello\n handshake message.\n\n Own Id: OTP-15887 Aux Id: ERL-973\n\n- Handle new ClientHello extensions when handshake is paused by the \\{handshake,\n hello\\} ssl option.\n\n Own Id: OTP-15888 Aux Id: ERL-975","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 9.3.2 - SSL Release Notes","ref":"notes.html#ssl-9-3-2"},{"type":"extras","doc":"- Returned \"alert error string\" is now same as logged alert string\n\n Own Id: OTP-15844\n\n- Fix returned extension map fields to follow the documentation.\n\n Own Id: OTP-15862 Aux Id: ERL-951\n\n- Avoid DTLS crash due to missing gen_server return value in DTLS packet demux\n process.\n\n Own Id: OTP-15864 Aux Id: ERL-962","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 9.3.1 - SSL Release Notes","ref":"notes.html#ssl-9-3-1"},{"type":"extras","doc":"- Missing check of size of user_data_buffer made internal socket behave as an\n active socket instead of active N. This could cause memory problems.\n\n Own Id: OTP-15825 Aux Id: ERL-934, OTP-15823","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 9.3 - SSL Release Notes","ref":"notes.html#ssl-9-3"},{"type":"extras","doc":"- The distribution handshake with TLS distribution (`inet_tls_dist`) does now\n utilize the socket option `{nodelay, true}`, which decreases the distribution\n setup time significantly.\n\n Own Id: OTP-14792\n\n- Correct shutdown reason to avoid an incorrect crash report\n\n Own Id: OTP-15710 Aux Id: ERL-893\n\n- Enhance documentation and type specifications.\n\n Own Id: OTP-15746 Aux Id: ERIERL-333","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- TLS-1.0, TLS-1.1 and DTLS-1.0 are now considered legacy and not supported by\n default\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-14865\n\n- Use new logger API in ssl. Introduce log levels and verbose debug logging for\n SSL.\n\n Own Id: OTP-15055\n\n- Add new API function str_to_suite/1, cipher_suites/3 (list cipher suites as\n rfc or OpenSSL name strings) and suite_to_openssl_str/1\n\n Own Id: OTP-15483 Aux Id: ERL-924\n\n- Basic support for TLS 1.3 Server for experimental use. The client is not yet\n functional, for more information see the Standards Compliance chapter of the\n User's Guide.\n\n Own Id: OTP-15591\n\n- Add support for PSK CCM ciphers from RFC 6655\n\n Own Id: OTP-15626","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 9.2.3.7 - SSL Release Notes","ref":"notes.html#ssl-9-2-3-7"},{"type":"extras","doc":"- Data deliver with ssl:recv/2,3 could fail for when using packet mode. This has\n been fixed by correcting the flow control handling of passive sockets when\n packet mode is used.\n\n Own Id: OTP-16764","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 9.2.3.6 - SSL Release Notes","ref":"notes.html#ssl-9-2-3-6"},{"type":"extras","doc":"- Fix timing bug that could cause ssl sockets to become unresponsive after an\n ssl:recv/3 call timed out\n\n Own Id: OTP-16619 Aux Id: ERL-1213","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 9.2.3.5 - SSL Release Notes","ref":"notes.html#ssl-9-2-3-5"},{"type":"extras","doc":"- Handling of zero size fragments in TLS could cause an infinite loop. This has\n now been corrected.\n\n Own Id: OTP-15328 Aux Id: ERIERL-379","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 9.2.3.4 - SSL Release Notes","ref":"notes.html#ssl-9-2-3-4"},{"type":"extras","doc":"- Hibernation now works as expected in all cases, was accidentally broken by\n optimization efforts.\n\n Own Id: OTP-15910","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 9.2.3.3 - SSL Release Notes","ref":"notes.html#ssl-9-2-3-3"},{"type":"extras","doc":"- Correct handshake handling, might cause strange symptoms such as ASN.1\n certificate decoding issues.\n\n Own Id: OTP-15879 Aux Id: ERL-968","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 9.2.3.2 - SSL Release Notes","ref":"notes.html#ssl-9-2-3-2"},{"type":"extras","doc":"- Returned \"alert error string\" is now same as logged alert string\n\n Own Id: OTP-15844","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 9.2.3.1 - SSL Release Notes","ref":"notes.html#ssl-9-2-3-1"},{"type":"extras","doc":"- Correct solution for retaining tcp flow control OTP-15802 (ERL-934) as to not\n break ssl:recv as reported in (ERL-938)\n\n Own Id: OTP-15823 Aux Id: ERL-934, ERL-938","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 9.2.3 - SSL Release Notes","ref":"notes.html#ssl-9-2-3"},{"type":"extras","doc":"- Missing check of size of user_data_buffer made internal socket behave as an\n active socket instead of active N. This could cause memory problems.\n\n Own Id: OTP-15802 Aux Id: ERL-934","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Back port of bug fix ERL-893 from OTP-22 and document enhancements that will\n solve dialyzer warnings for users of the ssl application.\n\n This change also affects public_key, eldap (and inet doc).\n\n Own Id: OTP-15785 Aux Id: ERL-929, ERL-893, PR-2215","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 9.2.2 - SSL Release Notes","ref":"notes.html#ssl-9-2-2"},{"type":"extras","doc":"- With the default BEAST Mitigation strategy for TLS 1.0 an empty TLS fragment\n could be sent after a one-byte fragment. This glitch has been fixed.\n\n Own Id: OTP-15054 Aux Id: ERIERL-346","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 9.2.1 - SSL Release Notes","ref":"notes.html#ssl-9-2-1"},{"type":"extras","doc":"- The timeout for a passive receive was sometimes not cancelled and later caused\n a server crash. This bug has now been corrected.\n\n Own Id: OTP-14701 Aux Id: ERL-883, ERL-884\n\n- Add tag for passive message (active N) in cb_info to retain transport\n transparency.\n\n Own Id: OTP-15679 Aux Id: ERL-861","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 9.2 - SSL Release Notes","ref":"notes.html#ssl-9-2"},{"type":"extras","doc":"- Fix bug that an incorrect return value for gen_statem could be created when\n alert was a result of handling renegotiation info extension\n\n Own Id: OTP-15502\n\n- Correct check for 3des_ede_cbc, could cause ssl to claim to support\n 3des_ede_cbc when cryptolib does not.\n\n Own Id: OTP-15539\n\n- Improved DTLS error handling, avoids unexpected connection failure in rare\n cases.\n\n Own Id: OTP-15561\n\n- Corrected active once emulation bug that could cause the ssl_closed meassage\n to not be sent. Bug introduced by OTP-15449\n\n Own Id: OTP-15666 Aux Id: ERIERL-316,","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add client option \\{reuse_session, SessionID::binary()\\} that can be used\n together with new option value \\{reuse_sessions, save\\}. This makes it\n possible to reuse a session from a specific connection establishment.\n\n Own Id: OTP-15369\n\n- The Reason part of of the error return from the functions connect and\n handshake has a better and documented format. This will sometimes differ from\n previous returned reasons, however those where only documented as term() and\n should for that reason not be relied on.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15423\n\n- Refactor of state handling to improve TLS application data throughput and\n reduce CPU overhead\n\n Own Id: OTP-15445\n\n- The SSL code has been optimized in many small ways to reduce CPU load for\n encryption/decryption, especially for Erlang's distribution protocol over TLS.\n\n Own Id: OTP-15529\n\n- Add support for active N\n\n Own Id: OTP-15665 Aux Id: ERL-811, PR-2072","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 9.1.2 - SSL Release Notes","ref":"notes.html#ssl-9-1-2"},{"type":"extras","doc":"- Fix encoding of the SRP extension length field in ssl. The old encoding of the\n SRP extension length could cause interoperability problems with third party\n SSL implementations when SRP was used.\n\n Own Id: OTP-15477 Aux Id: ERL-790\n\n- Guarantee active once data delivery, handling TCP stream properly.\n\n Own Id: OTP-15504 Aux Id: ERL-371\n\n- Correct gen_statem returns for some error cases\n\n Own Id: OTP-15505","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 9.1.1 - SSL Release Notes","ref":"notes.html#ssl-9-1-1"},{"type":"extras","doc":"- Fixed renegotiation bug. Client did not handle server initiated renegotiation\n correctly after rewrite to two connection processes, due to ERL-622 commit\n d87ac1c55188f5ba5cdf72384125d94d42118c18. This could manifest it self as a \"\n bad_record_mac\" alert.\n\n Also included are some optimizations\n\n Own Id: OTP-15489 Aux Id: ERL-308","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 9.1 - SSL Release Notes","ref":"notes.html#ssl-9-1"},{"type":"extras","doc":"- PEM cache was not evicting expired entries due to due to timezone confusion.\n\n Own Id: OTP-15368\n\n- Make sure an error is returned if a \"transport_accept socket\" is used in some\n other call than ssl:handshake\\* or ssl:controlling_process\n\n Own Id: OTP-15384 Aux Id: ERL-756\n\n- Fix timestamp handling in the PEM-cache could cause entries to not be\n invalidated at the correct time.\n\n Own Id: OTP-15402\n\n- Extend check for undelivered data at closing, could under some circumstances\n fail to deliver all data that was actually received.\n\n Own Id: OTP-15412 Aux Id: ERL-731\n\n- Correct signature check for TLS-1.2 that allows different algorithms for\n signature of peer cert and peer cert key. Not all allowed combinations where\n accepted.\n\n Own Id: OTP-15415 Aux Id: ERL-763\n\n- Correct gen_statem return value, could cause renegotiation to fail.\n\n Own Id: OTP-15418 Aux Id: ERL-770","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add engine support for RSA key exchange\n\n Own Id: OTP-15420 Aux Id: ERIERL-268\n\n- ssl now uses active n internally to boost performance. Old active once\n behavior can be restored by setting application variable see manual page for\n ssl application (man 6).\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15449","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 9.0.3 - SSL Release Notes","ref":"notes.html#ssl-9-0-3"},{"type":"extras","doc":"- Correct alert handling with new TLS sender process, from ssl-9.0.2. CLOSE\n ALERTS could under some circumstances be encoded using an incorrect cipher\n state. This would cause the peer to regard them as unknown messages.\n\n Own Id: OTP-15337 Aux Id: ERL-738\n\n- Correct handling of socket packet option with new TLS sender process, from\n ssl-9.0.2. When changing the socket option \\{packet, 1|2|3|4\\} with\n ssl:setopts/2 the option must internally be propagated to the sender process\n as well as the reader process as this particular option also affects the data\n to be sent.\n\n Own Id: OTP-15348 Aux Id: ERL-747","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 9.0.2 - SSL Release Notes","ref":"notes.html#ssl-9-0-2"},{"type":"extras","doc":"- Use separate processes for sending and receiving application data for TLS\n connections to avoid potential deadlock that was most likely to occur when\n using TLS for Erlang distribution. Note does not change the API.\n\n Own Id: OTP-15122\n\n- Correct handling of empty server SNI extension\n\n Own Id: OTP-15168\n\n- Correct PSK cipher suite handling and add selected_cipher_suite to connection\n information\n\n Own Id: OTP-15172\n\n- Adopt to the fact that cipher suite sign restriction are relaxed in TLS-1.2\n\n Own Id: OTP-15173\n\n- Enhance error handling of non existing PEM files\n\n Own Id: OTP-15174\n\n- Correct close handling of transport accepted sockets in the error state\n\n Own Id: OTP-15216\n\n- Correct PEM cache to not add references to empty entries when PEM file does\n not exist.\n\n Own Id: OTP-15224\n\n- Correct handling of all PSK cipher suites\n\n Before only some PSK suites would be correctly negotiated and most PSK ciphers\n suites would fail the connection.\n\n Own Id: OTP-15285","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- TLS will now try to order certificate chains if they appear to be unordered.\n That is prior to TLS 1.3, “certificate_list” ordering was required to be\n strict, however some implementations already allowed for some flexibility. For\n maximum compatibility, all implementations SHOULD be prepared to handle\n potentially extraneous certificates and arbitrary orderings from any TLS\n version.\n\n Own Id: OTP-12983\n\n- TLS will now try to reconstructed an incomplete certificate chains from its\n local CA-database and use that data for the certificate path validation. This\n especially makes sense for partial chains as then the peer might not send an\n intermediate CA as it is considered the trusted root in that case.\n\n Own Id: OTP-15060\n\n- Option keyfile defaults to certfile and should be trumped with key. This\n failed for engine keys.\n\n Own Id: OTP-15193\n\n- Error message improvement when own certificate has decoding issues, see also\n issue ERL-668.\n\n Own Id: OTP-15234\n\n- Correct dialyzer spec for key option\n\n Own Id: OTP-15281","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 9.0.1 - SSL Release Notes","ref":"notes.html#ssl-9-0-1"},{"type":"extras","doc":"- Correct cipher suite handling for ECDHE\\_\\*, the incorrect handling could\n cause an incorrrect suite to be selected and most likely fail the handshake.\n\n Own Id: OTP-15203","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 9.0 - SSL Release Notes","ref":"notes.html#ssl-9-0"},{"type":"extras","doc":"- Correct handling of ECDH suites.\n\n Own Id: OTP-14974\n\n- Proper handling of clients that choose to send an empty answer to a\n certificate request\n\n Own Id: OTP-15050","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Distribution over SSL (inet_tls) has, to improve performance, been rewritten\n to not use intermediate processes and ports.\n\n Own Id: OTP-14465\n\n- Add support for ECDHE_PSK cipher suites\n\n Own Id: OTP-14547\n\n- For security reasons no longer support 3-DES cipher suites by default\n\n \\*** INCOMPATIBILITY with possibly \\***\n\n Own Id: OTP-14768\n\n- For security reasons RSA-key exchange cipher suites are no longer supported by\n default\n\n \\*** INCOMPATIBILITY with possible \\***\n\n Own Id: OTP-14769\n\n- The interoperability option to fallback to insecure renegotiation now has to\n be explicitly turned on.\n\n \\*** INCOMPATIBILITY with possibly \\***\n\n Own Id: OTP-14789\n\n- Drop support for SSLv2 enabled clients. SSLv2 has been broken for decades and\n never supported by the Erlang SSL/TLS implementation. This option was by\n default disabled and enabling it has proved to sometimes break connections not\n using SSLv2 enabled clients.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-14824\n\n- Remove CHACHA20_POLY1305 ciphers form default for now. We have discovered\n interoperability problems, ERL-538, that we believe needs to be solved in\n crypto.\n\n \\*** INCOMPATIBILITY with possibly \\***\n\n Own Id: OTP-14882\n\n- Generalize DTLS packet multiplexing to make it easier to add future DTLS\n features and uses.\n\n Own Id: OTP-14888\n\n- Use uri_string module instead of http_uri.\n\n Own Id: OTP-14902\n\n- The SSL distribution protocol `-proto inet_tls` has stopped setting the SSL\n option `server_name_indication`. New verify funs for client and server in\n `inet_tls_dist` has been added, not documented yet, that checks node name if\n present in peer certificate. Usage is still also yet to be documented.\n\n Own Id: OTP-14969 Aux Id: OTP-14465, ERL-598\n\n- Deprecate ssl:ssl_accept/\\[1,2,3] in favour of ssl:handshake/\\[1,2,3]\n\n Own Id: OTP-15056\n\n- Customizes the hostname verification of the peer certificate, as different\n protocols that use TLS such as HTTP or LDAP may want to do it differently\n\n Own Id: OTP-15102 Aux Id: ERL-542, OTP-14962\n\n- Add utility function for converting erlang cipher suites to a string\n representation (ERL-600).\n\n Own Id: OTP-15106\n\n- First version with support for DTLS\n\n Own Id: OTP-15142","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 8.2.6.4 - SSL Release Notes","ref":"notes.html#ssl-8-2-6-4"},{"type":"extras","doc":"- Add engine support for RSA key exchange\n\n Own Id: OTP-15420","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 8.2.6.3 - SSL Release Notes","ref":"notes.html#ssl-8-2-6-3"},{"type":"extras","doc":"- Extend check for undelivered data at closing, could under some circumstances\n fail to deliverd all data that was acctualy recivied.\n\n Own Id: OTP-15412","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 8.2.6.2 - SSL Release Notes","ref":"notes.html#ssl-8-2-6-2"},{"type":"extras","doc":"- Correct handling of empty server SNI extension\n\n Own Id: OTP-15168\n\n- Correct cipher suite handling for ECDHE\\_\\*, the incorrect handling could\n cause an incorrrect suite to be selected and most likely fail the handshake.\n\n Own Id: OTP-15203","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 8.2.6.1 - SSL Release Notes","ref":"notes.html#ssl-8-2-6-1"},{"type":"extras","doc":"- Improve cipher suite handling correcting ECC and TLS-1.2 requierments.\n Backport of solution for ERL-641\n\n Own Id: OTP-15178","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Option keyfile defaults to certfile and should be trumped with key. This\n failed for engine keys.\n\n Own Id: OTP-15193","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 8.2.6 - SSL Release Notes","ref":"notes.html#ssl-8-2-6"},{"type":"extras","doc":"- Proper handling of clients that choose to send an empty answer to a\n certificate request\n\n Own Id: OTP-15050","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 8.2.5 - SSL Release Notes","ref":"notes.html#ssl-8-2-5"},{"type":"extras","doc":"- Fix filter function to not incorrectly exclude AEAD cipher suites\n\n Own Id: OTP-14981","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 8.2.4 - SSL Release Notes","ref":"notes.html#ssl-8-2-4"},{"type":"extras","doc":"- Optimization of bad merge conflict resolution causing dubble decode\n\n Own Id: OTP-14843\n\n- Restore error propagation to OTP-19.3 behaviour, in OTP-20.2 implementation\n adjustments to gen_statem needed some further adjustments to avoid a race\n condition. This could cause a TLS server to not always report file path errors\n correctly.\n\n Own Id: OTP-14852\n\n- Corrected RC4 suites listing function to regard TLS version\n\n Own Id: OTP-14871\n\n- Fix alert handling so that unexpected messages are logged and alerted\n correctly\n\n Own Id: OTP-14919\n\n- Correct handling of anonymous cipher suites\n\n Own Id: OTP-14952","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Added new API functions to facilitate cipher suite handling\n\n Own Id: OTP-14760\n\n- Correct TLS_FALLBACK_SCSV handling so that this special flag suite is always\n placed last in the cipher suite list in accordance with the specs. Also make\n sure this functionality is used in DTLS.\n\n Own Id: OTP-14828\n\n- Add TLS record version sanity check for early as possible error detection and\n consistency in ALERT codes generated\n\n Own Id: OTP-14892","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 8.2.3 - SSL Release Notes","ref":"notes.html#ssl-8-2-3"},{"type":"extras","doc":"- Packet options cannot be supported for unreliable transports, that is, packet\n option for DTLS over udp will not be supported.\n\n Own Id: OTP-14664\n\n- Ensure data delivery before close if possible. This fix is related to fix in\n PR-1479.\n\n Own Id: OTP-14794","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The crypto API is extended to use private/public keys stored in an Engine for\n sign/verify or encrypt/decrypt operations.\n\n The ssl application provides an API to use this new engine concept in TLS.\n\n Own Id: OTP-14448\n\n- Implemented renegotiation for DTLS\n\n Own Id: OTP-14563\n\n- A new command line option `-ssl_dist_optfile` has been added to facilitate\n specifying the many options needed when using SSL as the distribution\n protocol.\n\n Own Id: OTP-14657","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 8.2.2 - SSL Release Notes","ref":"notes.html#ssl-8-2-2"},{"type":"extras","doc":"- TLS sessions must be registered with SNI if provided, so that sessions where\n client hostname verification would fail cannot connect reusing a session\n created when the server name verification succeeded.\n\n Own Id: OTP-14632\n\n- An erlang TLS server configured with cipher suites using rsa key exchange, may\n be vulnerable to an Adaptive Chosen Ciphertext attack (AKA Bleichenbacher\n attack) against RSA, which when exploited, may result in plaintext recovery of\n encrypted messages and/or a Man-in-the-middle (MiTM) attack, despite the\n attacker not having gained access to the server’s private key itself.\n [CVE-2017-1000385](https://nvd.nist.gov/vuln/detail/CVE-2017-1000385)\n\n Exploiting this vulnerability to perform plaintext recovery of encrypted\n messages will, in most practical cases, allow an attacker to read the\n plaintext only after the session has completed. Only TLS sessions established\n using RSA key exchange are vulnerable to this attack.\n\n Exploiting this vulnerability to conduct a MiTM attack requires the attacker\n to complete the initial attack, which may require thousands of server\n requests, during the handshake phase of the targeted session within the window\n of the configured handshake timeout. This attack may be conducted against any\n TLS session using RSA signatures, but only if cipher suites using RSA key\n exchange are also enabled on the server. The limited window of opportunity,\n limitations in bandwidth, and latency make this attack significantly more\n difficult to execute.\n\n RSA key exchange is enabled by default although least prioritized if server\n order is honored. For such a cipher suite to be chosen it must also be\n supported by the client and probably the only shared cipher suite.\n\n Captured TLS sessions encrypted with ephemeral cipher suites (DHE or ECDHE)\n are not at risk for subsequent decryption due to this vulnerability.\n\n As a workaround if default cipher suite configuration was used you can\n configure the server to not use vulnerable suites with the ciphers option like\n this:\n\n `{ciphers, [Suite || Suite <- ssl:cipher_suites(), element(1,Suite) =/= rsa]}`\n\n that is your code will look somethingh like this:\n\n `ssl:listen(Port, [{ciphers, [Suite || Suite <- ssl:cipher_suites(), element(1,S) =/= rsa]} | Options]).`\n\n Thanks to Hanno Böck, Juraj Somorovsky and Craig Young for reporting this\n vulnerability.\n\n Own Id: OTP-14748","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- If no SNI is available and the hostname is an IP-address also check for\n IP-address match. This check is not as good as a DNS hostname check and\n certificates using IP-address are not recommended.\n\n Own Id: OTP-14655","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 8.2.1 - SSL Release Notes","ref":"notes.html#ssl-8-2-1"},{"type":"extras","doc":"- Max session table works correctly again\n\n Own Id: OTP-14556","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Customize alert handling for DTLS over UDP to mitigate DoS attacks\n\n Own Id: OTP-14078\n\n- Improved error propagation and reports\n\n Own Id: OTP-14236","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 8.2 - SSL Release Notes","ref":"notes.html#ssl-8-2"},{"type":"extras","doc":"- ECDH-ECDSA key exchange supported, was accidentally dismissed in earlier\n versions.\n\n Own Id: OTP-14421\n\n- Correct close semantics for active once connections. This was a timing\n dependent bug the resulted in the close message not always reaching the ssl\n user process.\n\n Own Id: OTP-14443","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- TLS-1.2 clients will now always send hello messages on its own format, as\n opposed to earlier versions that will send the hello on the lowest supported\n version, this is a change supported by the latest RFC.\n\n This will make interoperability with some newer servers smoother. Potentially,\n but unlikely, this could cause a problem with older servers if they do not\n adhere to the RFC and ignore unknown extensions.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-13820\n\n- Allow Erlang/OTP to use OpenSSL in FIPS-140 mode, in order to satisfy specific\n security requirements (mostly by different parts of the US federal\n government).\n\n See the new crypto users guide \"FIPS mode\" chapter about building and using\n the FIPS support which is disabled by default.\n\n (Thanks to dszoboszlay and legoscia)\n\n Own Id: OTP-13921 Aux Id: PR-1180\n\n- Implemented DTLS cookie generation, required by spec, instead of using a\n hardcoded value.\n\n Own Id: OTP-14076\n\n- Implement sliding window replay protection of DTLS records.\n\n Own Id: OTP-14077\n\n- TLS client processes will by default call public_key:pkix_verify_hostname/2 to\n verify the hostname of the connection with the server certificates specified\n hostname during certificate path validation. The user may explicitly disables\n it. Also if the hostname cannot be derived from the first argument to connect\n or is not supplied by the server name indication option, the check will not be\n performed.\n\n Own Id: OTP-14197\n\n- Extend connection_information/\\[1,2] . The values session_id, master_secret,\n client_random and server_random can no be accessed by\n connection_information/2. Note only session_id will be added to\n connection_information/1. The rational is that values concerning the\n connection security should have to be explicitly requested.\n\n Own Id: OTP-14291\n\n- Chacha cipher suites are currently not tested enough to be most preferred ones\n\n Own Id: OTP-14382\n\n- Basic support for DTLS that been tested together with OpenSSL.\n\n Test by providing the option \\{protocol, dtls\\} to the ssl API functions\n connect and listen.\n\n Own Id: OTP-14388","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 8.1.3.1.1 - SSL Release Notes","ref":"notes.html#ssl-8-1-3-1-1"},{"type":"extras","doc":"- Fix alert handling so that unexpected messages are logged and alerted\n correctly\n\n Own Id: OTP-14929","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 8.1.3.1 - SSL Release Notes","ref":"notes.html#ssl-8-1-3-1"},{"type":"extras","doc":"- An erlang TLS server configured with cipher suites using rsa key exchange, may\n be vulnerable to an Adaptive Chosen Ciphertext attack (AKA Bleichenbacher\n attack) against RSA, which when exploited, may result in plaintext recovery of\n encrypted messages and/or a Man-in-the-middle (MiTM) attack, despite the\n attacker not having gained access to the server’s private key itself.\n [CVE-2017-1000385](https://nvd.nist.gov/vuln/detail/CVE-2017-1000385)\n\n Exploiting this vulnerability to perform plaintext recovery of encrypted\n messages will, in most practical cases, allow an attacker to read the\n plaintext only after the session has completed. Only TLS sessions established\n using RSA key exchange are vulnerable to this attack.\n\n Exploiting this vulnerability to conduct a MiTM attack requires the attacker\n to complete the initial attack, which may require thousands of server\n requests, during the handshake phase of the targeted session within the window\n of the configured handshake timeout. This attack may be conducted against any\n TLS session using RSA signatures, but only if cipher suites using RSA key\n exchange are also enabled on the server. The limited window of opportunity,\n limitations in bandwidth, and latency make this attack significantly more\n difficult to execute.\n\n RSA key exchange is enabled by default although least prioritized if server\n order is honored. For such a cipher suite to be chosen it must also be\n supported by the client and probably the only shared cipher suite.\n\n Captured TLS sessions encrypted with ephemeral cipher suites (DHE or ECDHE)\n are not at risk for subsequent decryption due to this vulnerability.\n\n As a workaround if default cipher suite configuration was used you can\n configure the server to not use vulnerable suites with the ciphers option like\n this:\n\n `{ciphers, [Suite || Suite <- ssl:cipher_suites(), element(1,Suite) =/= rsa]}`\n\n that is your code will look somethingh like this:\n\n `ssl:listen(Port, [{ciphers, [Suite || Suite <- ssl:cipher_suites(), element(1,S) =/= rsa]} | Options]).`\n\n Thanks to Hanno Böck, Juraj Somorovsky and Craig Young for reporting this\n vulnerability.\n\n Own Id: OTP-14748","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 8.1.3 - SSL Release Notes","ref":"notes.html#ssl-8-1-3"},{"type":"extras","doc":"- Remove debug printout\n\n Own Id: OTP-14396","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 8.1.2 - SSL Release Notes","ref":"notes.html#ssl-8-1-2"},{"type":"extras","doc":"- Correct active once emulation, for TLS. Now all data received by the\n connection process will be delivered through active once, even when the active\n once arrives after that the gen_tcp socket is closed by the peer.\n\n Own Id: OTP-14300","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 8.1.1 - SSL Release Notes","ref":"notes.html#ssl-8-1-1"},{"type":"extras","doc":"- Corrected termination behavior, that caused a PEM cache bug and sometimes\n resulted in connection failures.\n\n Own Id: OTP-14100\n\n- Fix bug that could hang ssl connection processes when failing to require more\n data for very large handshake packages. Add option max_handshake_size to\n mitigate DoS attacks.\n\n Own Id: OTP-14138\n\n- Improved support for CRL handling that could fail to work as intended when an\n id-ce-extKeyUsage was present in the certificate. Also improvements where\n needed to distributionpoint handling so that all revocations actually are\n found and not deemed to be not determinable.\n\n Own Id: OTP-14141\n\n- A TLS handshake might accidentally match old sslv2 format and ssl application\n would incorrectly aborted TLS handshake with ssl_v2_client_hello_no_supported.\n Parsing was altered to avoid this problem.\n\n Own Id: OTP-14222\n\n- Correct default cipher list to prefer AES 128 before 3DES\n\n Own Id: OTP-14235","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Move PEM cache to a dedicated process, to avoid making the SSL manager process\n a bottleneck. This improves scalability of TLS connections.\n\n Own Id: OTP-13874","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 8.1 - SSL Release Notes","ref":"notes.html#ssl-8-1"},{"type":"extras","doc":"- List of possible anonymous suites, never supported by default, where incorrect\n for some TLS versions.\n\n Own Id: OTP-13926","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Experimental version of DTLS. It is runnable but not complete and cannot be\n considered reliable for production usage.\n\n Own Id: OTP-12982\n\n- Add API options to handle ECC curve selection.\n\n Own Id: OTP-13959","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 8.0.3 - SSL Release Notes","ref":"notes.html#ssl-8-0-3"},{"type":"extras","doc":"- A timing related bug in event handling could cause interoperability problems\n between an erlang TLS server and some TLS clients, especially noticed with\n Firefox as TLS client.\n\n Own Id: OTP-13917\n\n- Correct ECC curve selection, the error could cause the default to always be\n selected.\n\n Own Id: OTP-13918","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 8.0.2 - SSL Release Notes","ref":"notes.html#ssl-8-0-2"},{"type":"extras","doc":"- Correctly formed handshake messages received out of order will now correctly\n fail the connection with unexpected message.\n\n Own Id: OTP-13853\n\n- Correct handling of signature algorithm selection\n\n Own Id: OTP-13711","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- ssl application now behaves gracefully also on partially incorrect input from\n peer.\n\n Own Id: OTP-13834\n\n- Add application environment configuration bypass_pem_cache. This can be used\n as a workaround for the current implementation of the PEM-cache that has\n proven to be a bottleneck.\n\n Own Id: OTP-13883","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 8.0.1 - SSL Release Notes","ref":"notes.html#ssl-8-0-1"},{"type":"extras","doc":"- The TLS/SSL protocol version selection for the SSL server has been corrected\n to follow RFC 5246 Appendix E.1 especially in case where the list of supported\n versions has gaps. Now the server selects the highest protocol version it\n supports that is not higher than what the client supports.\n\n Own Id: OTP-13753 Aux Id: seq13150","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 8.0 - SSL Release Notes","ref":"notes.html#ssl-8-0"},{"type":"extras","doc":"- Server now rejects, a not requested client cert, as an incorrect handshake\n message and ends the connection.\n\n Own Id: OTP-13651","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Remove default support for DES cipher suites\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-13195\n\n- Deprecate the function `crypto:rand_bytes` and make sure that\n `crypto:strong_rand_bytes` is used in all places that are cryptographically\n significant.\n\n Own Id: OTP-13214\n\n- Better error handling of user error during TLS upgrade. ERL-69 is solved by\n gen_statem rewrite of ssl application.\n\n Own Id: OTP-13255\n\n- Provide user friendly error message when crypto rejects a key\n\n Own Id: OTP-13256\n\n- Add ssl:getstat/1 and ssl:getstat/2\n\n Own Id: OTP-13415\n\n- TLS distribution connections now allow specifying the options `verify_fun`,\n `crl_check` and `crl_cache`. See the documentation. GitHub pull req #956\n contributed by Magnus Henoch.\n\n Own Id: OTP-13429 Aux Id: Pull#956\n\n- Remove confusing error message when closing a distributed erlang node running\n over TLS\n\n Own Id: OTP-13431\n\n- Remove default support for use of md5 in TLS 1.2 signature algorithms\n\n Own Id: OTP-13463\n\n- ssl now uses gen_statem instead of gen_fsm to implement the ssl connection\n process, this solves some timing issues in addition to making the code more\n intuitive as the behaviour can be used cleanly instead of having a lot of\n workaround for shortcomings of the behaviour.\n\n Own Id: OTP-13464\n\n- Phase out interoperability with clients that offer SSLv2. By default they are\n no longer supported, but an option to provide interoperability is offered.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-13465\n\n- OpenSSL has functions to generate short (eight hex digits) hashes of issuers\n of certificates and CRLs. These hashes are used by the \"c_rehash\" script to\n populate directories of CA certificates and CRLs, e.g. in the Apache web\n server. Add functionality to let an Erlang program find the right CRL for a\n given certificate in such a directory.\n\n Own Id: OTP-13530\n\n- Some legacy TLS 1.0 software does not tolerate the 1/n-1 content split BEAST\n mitigation technique. Add a beast_mitigation SSL option (defaulting to\n one_n_minus_one) to select or disable the BEAST mitigation technique.\n\n Own Id: OTP-13629\n\n- Enhance error log messages to facilitate for users to understand the error\n\n Own Id: OTP-13632\n\n- Increased default DH params to 2048-bit\n\n Own Id: OTP-13636\n\n- Propagate CRL unknown CA error so that public_key validation process continues\n correctly and determines what should happen.\n\n Own Id: OTP-13656\n\n- Introduce a flight concept for handshake packages. This is a preparation for\n enabling DTLS, however it can also have a positive effects for TLS on slow and\n unreliable networks.\n\n Own Id: OTP-13678","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 7.3.3.2 - SSL Release Notes","ref":"notes.html#ssl-7-3-3-2"},{"type":"extras","doc":"- An erlang TLS server configured with cipher suites using rsa key exchange, may\n be vulnerable to an Adaptive Chosen Ciphertext attack (AKA Bleichenbacher\n attack) against RSA, which when exploited, may result in plaintext recovery of\n encrypted messages and/or a Man-in-the-middle (MiTM) attack, despite the\n attacker not having gained access to the server’s private key itself.\n [CVE-2017-1000385](https://nvd.nist.gov/vuln/detail/CVE-2017-1000385)\n\n Exploiting this vulnerability to perform plaintext recovery of encrypted\n messages will, in most practical cases, allow an attacker to read the\n plaintext only after the session has completed. Only TLS sessions established\n using RSA key exchange are vulnerable to this attack.\n\n Exploiting this vulnerability to conduct a MiTM attack requires the attacker\n to complete the initial attack, which may require thousands of server\n requests, during the handshake phase of the targeted session within the window\n of the configured handshake timeout. This attack may be conducted against any\n TLS session using RSA signatures, but only if cipher suites using RSA key\n exchange are also enabled on the server. The limited window of opportunity,\n limitations in bandwidth, and latency make this attack significantly more\n difficult to execute.\n\n RSA key exchange is enabled by default although least prioritized if server\n order is honored. For such a cipher suite to be chosen it must also be\n supported by the client and probably the only shared cipher suite.\n\n Captured TLS sessions encrypted with ephemeral cipher suites (DHE or ECDHE)\n are not at risk for subsequent decryption due to this vulnerability.\n\n As a workaround if default cipher suite configuration was used you can\n configure the server to not use vulnerable suites with the ciphers option like\n this:\n\n `{ciphers, [Suite || Suite <- ssl:cipher_suites(), element(1,Suite) =/= rsa]}`\n\n that is your code will look somethingh like this:\n\n `ssl:listen(Port, [{ciphers, [Suite || Suite <- ssl:cipher_suites(), element(1,S) =/= rsa]} | Options]).`\n\n Thanks to Hanno Böck, Juraj Somorovsky and Craig Young for reporting this\n vulnerability.\n\n Own Id: OTP-14748","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 7.3.3 - SSL Release Notes","ref":"notes.html#ssl-7-3-3"},{"type":"extras","doc":"- Correct ssl:prf/5 to use the negotiated cipher suite's prf function in\n ssl:prf/5 instead of the default prf.\n\n Own Id: OTP-13546\n\n- Timeouts may have the value 0, guards have been corrected to allow this\n\n Own Id: OTP-13635\n\n- Change of internal handling of hash sign pairs as the used one enforced to\n much restrictions making some valid combinations unavailable.\n\n Own Id: OTP-13670","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 7.3.3.0.1 - SSL Release Notes","ref":"notes.html#ssl-7-3-3-0-1"},{"type":"extras","doc":"- An erlang TLS server configured with cipher suites using rsa key exchange, may\n be vulnerable to an Adaptive Chosen Ciphertext attack (AKA Bleichenbacher\n attack) against RSA, which when exploited, may result in plaintext recovery of\n encrypted messages and/or a Man-in-the-middle (MiTM) attack, despite the\n attacker not having gained access to the server’s private key itself.\n [CVE-2017-1000385](https://nvd.nist.gov/vuln/detail/CVE-2017-1000385)\n\n Exploiting this vulnerability to perform plaintext recovery of encrypted\n messages will, in most practical cases, allow an attacker to read the\n plaintext only after the session has completed. Only TLS sessions established\n using RSA key exchange are vulnerable to this attack.\n\n Exploiting this vulnerability to conduct a MiTM attack requires the attacker\n to complete the initial attack, which may require thousands of server\n requests, during the handshake phase of the targeted session within the window\n of the configured handshake timeout. This attack may be conducted against any\n TLS session using RSA signatures, but only if cipher suites using RSA key\n exchange are also enabled on the server. The limited window of opportunity,\n limitations in bandwidth, and latency make this attack significantly more\n difficult to execute.\n\n RSA key exchange is enabled by default although least prioritized if server\n order is honored. For such a cipher suite to be chosen it must also be\n supported by the client and probably the only shared cipher suite.\n\n Captured TLS sessions encrypted with ephemeral cipher suites (DHE or ECDHE)\n are not at risk for subsequent decryption due to this vulnerability.\n\n As a workaround if default cipher suite configuration was used you can\n configure the server to not use vulnerable suites with the ciphers option like\n this:\n\n `{ciphers, [Suite || Suite <- ssl:cipher_suites(), element(1,Suite) =/= rsa]}`\n\n that is your code will look somethingh like this:\n\n `ssl:listen(Port, [{ciphers, [Suite || Suite <- ssl:cipher_suites(), element(1,S) =/= rsa]} | Options]).`\n\n Thanks to Hanno Böck, Juraj Somorovsky and Craig Young for reporting this\n vulnerability.\n\n Own Id: OTP-14748","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Create a little randomness in sending of session invalidation messages, to\n mitigate load when whole table is invalidated.\n\n Own Id: OTP-13490","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 7.3.2 - SSL Release Notes","ref":"notes.html#ssl-7-3-2"},{"type":"extras","doc":"- Correct cipher suites conversion and guard expression. Caused problems with\n GCM cipher suites and client side option to set signature_algorithms extension\n values.\n\n Own Id: OTP-13525","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 7.3.1 - SSL Release Notes","ref":"notes.html#ssl-7-3-1"},{"type":"extras","doc":"- Corrections to cipher suite handling using the 3 and 4 tuple format in\n addition to commit 89d7e21cf4ae988c57c8ef047bfe85127875c70c\n\n Own Id: OTP-13511","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Make values for the TLS-1.2 signature_algorithms extension configurable\n\n Own Id: OTP-13261","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 7.3 - SSL Release Notes","ref":"notes.html#ssl-7-3"},{"type":"extras","doc":"- Make sure there is only one poller validator at a time for validating the\n session cache.\n\n Own Id: OTP-13185\n\n- A timing related issue could cause ssl to hang, especially happened with newer\n versions of OpenSSL in combination with ECC ciphers.\n\n Own Id: OTP-13253\n\n- Work around a race condition in the TLS distribution start.\n\n Own Id: OTP-13268\n\n- Big handshake messages are now correctly fragmented in the TLS record layer.\n\n Own Id: OTP-13306\n\n- Improve portability of ECC tests in Crypto and SSL for \"exotic\" OpenSSL\n versions.\n\n Own Id: OTP-13311\n\n- Certificate extensions marked as critical are ignored when using verify_none\n\n Own Id: OTP-13377\n\n- If a certificate doesn't contain a CRL Distribution Points extension, and the\n relevant CRL is not in the cache, and the `crl_check` option is not set to\n `best_effort` , the revocation check should fail.\n\n Own Id: OTP-13378\n\n- Enable TLS distribution over IPv6\n\n Own Id: OTP-13391","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Improve error reporting for TLS distribution\n\n Own Id: OTP-13219\n\n- Include options from connect, listen and accept in\n `connection_information/1,2`\n\n Own Id: OTP-13232\n\n- Allow adding extra options for outgoing TLS distribution connections, as\n supported for plain TCP connections.\n\n Own Id: OTP-13285\n\n- Use loopback as server option in TLS-distribution module\n\n Own Id: OTP-13300\n\n- Verify certificate signature against original certificate binary.\n\n This avoids bugs due to encoding errors when re-encoding a decode certificate.\n As there exists several decode step and using of different ASN.1 specification\n this is a risk worth avoiding.\n\n Own Id: OTP-13334\n\n- Use `application:ensure_all_started/2` instead of hard-coding dependencies\n\n Own Id: OTP-13363","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 7.2 - SSL Release Notes","ref":"notes.html#ssl-7-2"},{"type":"extras","doc":"- Honor distribution port range options\n\n Own Id: OTP-12838\n\n- Correct supervisor specification in TLS distribution.\n\n Own Id: OTP-13134\n\n- Correct cache timeout\n\n Own Id: OTP-13141\n\n- Avoid crash and restart of ssl process when key file does not exist.\n\n Own Id: OTP-13144\n\n- Enable passing of raw socket options on the format \\{raw,_,_,\\_\\} to the\n underlying socket.\n\n Own Id: OTP-13166\n\n- Hibernation with small or a zero timeout will now work as expected\n\n Own Id: OTP-13189","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add upper limit for session cache, configurable on ssl application level.\n\n If upper limit is reached, invalidate the current cache entries, e.i the\n session lifetime is the max time a session will be kept, but it may be\n invalidated earlier if the max limit for the table is reached. This will keep\n the ssl manager process well behaved, not exhusting memory. Invalidating the\n entries will incrementally empty the cache to make room for fresh sessions\n entries.\n\n Own Id: OTP-12392\n\n- Use new time functions to measure passed time.\n\n Own Id: OTP-12457\n\n- Improved error handling in TLS distribution\n\n Own Id: OTP-13142\n\n- Distribution over TLS now honors the nodelay distribution flag\n\n Own Id: OTP-13143","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 7.1 - SSL Release Notes","ref":"notes.html#ssl-7-1"},{"type":"extras","doc":"- Add DER encoded ECPrivateKey as valid input format for key option.\n\n Own Id: OTP-12974\n\n- Correct return value of default session callback module\n\n This error had the symptom that the client check for unique session would\n always fail, potentially making the client session table grow a lot and\n causing long setup times.\n\n Own Id: OTP-12980","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add possibility to downgrade an SSL/TLS connection to a tcp connection, and\n give back the socket control to a user process.\n\n This also adds the possibility to specify a timeout to the ssl:close function.\n\n Own Id: OTP-11397\n\n- Add application setting to be able to change fatal alert shutdown timeout,\n also shorten the default timeout. The fatal alert timeout is the number of\n milliseconds between sending of a fatal alert and closing the connection.\n Waiting a little while improves the peers chances to properly receiving the\n alert so it may shutdown gracefully.\n\n Own Id: OTP-12832","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 7.0 - SSL Release Notes","ref":"notes.html#ssl-7-0"},{"type":"extras","doc":"- Ignore signature_algorithm (TLS 1.2 extension) sent to TLS 1.0 or TLS 1.1\n server\n\n Own Id: OTP-12670\n\n- Improve error handling in TLS distribution module to avoid lingering sockets.\n\n Own Id: OTP-12799 Aux Id: Tom Briden\n\n- Add option \\{client_renegotiation, boolean()\\} option to the server-side of\n the SSL application.\n\n Own Id: OTP-12815","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add new API functions to handle CRL-verification\n\n Own Id: OTP-10362 Aux Id: kunagi-215 \\[126]\n\n- Remove default support for SSL-3.0, due to Poodle vunrability in protocol\n specification.\n\n Add padding check for TLS-1.0 to remove Poodle vunrability from TLS 1.0, also\n add the option padding_check. This option only affects TLS-1.0 connections and\n if set to false it disables the block cipher padding check to be able to\n interoperate with legacy software.\n\n Remove default support for RC4 cipher suites, as they are consider too weak.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-12390\n\n- Add support for TLS ALPN (Application-Layer Protocol Negotiation) extension.\n\n Own Id: OTP-12580\n\n- Add SNI (Server Name Indication) support for the server side.\n\n Own Id: OTP-12736","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 6.0.1.1 - SSL Release Notes","ref":"notes.html#ssl-6-0-1-1"},{"type":"extras","doc":"- Gracefully ignore proprietary hash_sign algorithms\n\n Own Id: OTP-12829","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 6.0.1 - SSL Release Notes","ref":"notes.html#ssl-6-0-1"},{"type":"extras","doc":"- Terminate gracefully when receiving bad input to premaster secret calculation\n\n Own Id: OTP-12783","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 6.0 - SSL Release Notes","ref":"notes.html#ssl-6-0"},{"type":"extras","doc":"- Exclude self-signed trusted anchor certificates from certificate prospective\n certification path according to RFC 3280.\n\n This will avoid some unnecessary certificate processing.\n\n Own Id: OTP-12449","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Separate client and server session cache internally.\n\n Avoid session table growth when client starts many connections in such a\n manner that many connections are started before session reuse is possible.\n Only save a new session in client if there is no equivalent session already\n stored.\n\n Own Id: OTP-11365\n\n- The PEM cache is now validated by a background process, instead of always\n keeping it if it is small enough and clearing it otherwise. That strategy\n required that small caches where cleared by API function if a file changes on\n disk.\n\n However export the API function to clear the cache as it may still be useful.\n\n Own Id: OTP-12391\n\n- Add padding check for TLS-1.0 to remove Poodle vulnerability from TLS 1.0,\n also add the option padding_check. This option only affects TLS-1.0\n connections and if set to false it disables the block cipher padding check to\n be able to interoperate with legacy software.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-12420\n\n- Add support for TLS_FALLBACK_SCSV used to prevent undesired TLS version\n downgrades. If used by a client that is vulnerable to the POODLE attack, and\n the server also supports TLS_FALLBACK_SCSV, the attack can be prevented.\n\n Own Id: OTP-12458","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 5.3.8 - SSL Release Notes","ref":"notes.html#ssl-5-3-8"},{"type":"extras","doc":"- Make sure the clean rule for ssh, ssl, eunit and otp_mibs actually removes\n generated files.\n\n Own Id: OTP-12200","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Change code to reflect that state data may be secret to avoid breaking\n dialyzer contracts.\n\n Own Id: OTP-12341","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 5.3.7 - SSL Release Notes","ref":"notes.html#ssl-5-3-7"},{"type":"extras","doc":"- Handle the fact that servers may send an empty SNI extension to the client.\n\n Own Id: OTP-12198","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 5.3.6 - SSL Release Notes","ref":"notes.html#ssl-5-3-6"},{"type":"extras","doc":"- Corrected handling of ECC certificates, there where several small issues with\n the handling of such certificates in the ssl and public_key application. Now\n ECC signed ECC certificates shall work and not only RSA signed ECC\n certificates.\n\n Own Id: OTP-12026\n\n- Check that the certificate chain ends with a trusted ROOT CA e.i. a\n self-signed certificate, but provide an option partial_chain to enable the\n application to define an intermediat CA as trusted.\n\n Own Id: OTP-12149","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add decode functions for SNI (Server Name Indication)\n\n Own Id: OTP-12048","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 5.3.5 - SSL Release Notes","ref":"notes.html#ssl-5-3-5"},{"type":"extras","doc":"- ssl:recv now returns \\{error, einval\\} if applied to a non passive socket, the\n same as gen_tcp:recv.\n\n Thanks to Danil Zagoskin for reporting this issue\n\n Own Id: OTP-11878\n\n- Corrected handling of default values for signature_algorithms extension in\n TLS-1.2 and corresponding values used in previous versions that does not\n support this extension.\n\n Thanks to Danil Zagoskin\n\n Own Id: OTP-11886\n\n- Handle socket option inheritance when pooling of accept sockets is used\n\n Own Id: OTP-11897\n\n- Make sure that the list of versions, possibly supplied in the versions option,\n is not order dependent.\n\n Thanks to Ransom Richardson for reporting this issue\n\n Own Id: OTP-11912\n\n- Reject connection if the next_protocol message is sent twice.\n\n Own Id: OTP-11926\n\n- Correct options handling when ssl:ssl_accept/3 is called with new ssl options\n after calling ssl:listen/2\n\n Own Id: OTP-11950","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Gracefully handle unknown alerts\n\n Thanks to Atul Atri for reporting this issue\n\n Own Id: OTP-11874\n\n- Gracefully ignore cipher suites sent by client not supported by the SSL/TLS\n version that the client has negotiated.\n\n Thanks to Danil Zagoskin for reporting this issue\n\n Own Id: OTP-11875\n\n- Gracefully handle structured garbage, i.e a client sends some garbage in a ssl\n record instead of a valid fragment.\n\n Thanks to Danil Zagoskin\n\n Own Id: OTP-11880\n\n- Gracefully handle invalid alerts\n\n Own Id: OTP-11890\n\n- Generalize handling of default ciphers\n\n Thanks to Andreas Schultz\n\n Own Id: OTP-11966\n\n- Make sure change cipher spec is correctly handled\n\n Own Id: OTP-11975","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 5.3.4 - SSL Release Notes","ref":"notes.html#ssl-5-3-4"},{"type":"extras","doc":"- Fix incorrect dialyzer spec and types, also enhance documentation.\n\n Thanks to Ayaz Tuncer.\n\n Own Id: OTP-11627\n\n- Fix possible mismatch between SSL/TLS version and default ciphers. Could\n happen when you specified SSL/TLS-version in optionlist to listen or accept.\n\n Own Id: OTP-11712\n\n- Application upgrade (appup) files are corrected for the following\n applications:\n\n `asn1, common_test, compiler, crypto, debugger, dialyzer, edoc, eldap, erl_docgen, et, eunit, gs, hipe, inets, observer, odbc, os_mon, otp_mibs, parsetools, percept, public_key, reltool, runtime_tools, ssh, syntax_tools, test_server, tools, typer, webtool, wx, xmerl`\n\n A new test utility for testing appup files is added to test_server. This is\n now used by most applications in OTP.\n\n (Thanks to Tobias Schlager)\n\n Own Id: OTP-11744","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Moved elliptic curve definition from the crypto NIF/OpenSSL into Erlang code,\n adds the RFC-5639 brainpool curves and makes TLS use them (RFC-7027).\n\n Thanks to Andreas Schultz\n\n Own Id: OTP-11578\n\n- Unicode adaptations\n\n Own Id: OTP-11620\n\n- Added option honor_cipher_order. This instructs the server to prefer its own\n cipher ordering rather than the client's and can help protect against things\n like BEAST while maintaining compatibility with clients which only support\n older ciphers.\n\n Thanks to Andrew Thompson for the implementation, and Andreas Schultz for the\n test cases.\n\n Own Id: OTP-11621\n\n- Replace boolean checking in validate_option with is_boolean guard.\n\n Thanks to Andreas Schultz.\n\n Own Id: OTP-11634\n\n- Some function specs are corrected or moved and some edoc comments are\n corrected in order to allow use of edoc. (Thanks to Pierre Fenoll)\n\n Own Id: OTP-11702\n\n- Correct clean up of certificate database when certs are inputted in pure DER\n format.The incorrect code could cause a memory leek when certs where inputted\n in DER. Thanks to Bernard Duggan for reporting this.\n\n Own Id: OTP-11733\n\n- Improved documentation of the cacertfile option\n\n Own Id: OTP-11759 Aux Id: seq12535\n\n- Avoid next protocol negotiation failure due to incorrect option format.\n\n Own Id: OTP-11760\n\n- Handle v1 CRLs, with no extensions and fixes issues with IDP (Issuing\n Distribution Point) comparison during CRL validation.\n\n Thanks to Andrew Thompson\n\n Own Id: OTP-11761\n\n- Server now ignores client ECC curves that it does not support instead of\n crashing.\n\n Thanks to Danil Zagoskin for reporting the issue and suggesting a solution.\n\n Own Id: OTP-11780\n\n- Handle SNI (Server Name Indication) alert unrecognized_name and gracefully\n deal with unexpected alerts.\n\n Thanks to Masatake Daimon for reporting this.\n\n Own Id: OTP-11815\n\n- Add possibility to specify ssl options when calling ssl:ssl_accept\n\n Own Id: OTP-11837","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 5.3.3 - SSL Release Notes","ref":"notes.html#ssl-5-3-3"},{"type":"extras","doc":"- Add missing validation of the server_name_indication option and test for its\n explicit use. It was not possible to set or disable the default\n server_name_indication as the validation of the option was missing.\n\n Own Id: OTP-11567\n\n- Elliptic curve selection in server mode now properly selects a curve suggested\n by the client, if possible, and the fallback alternative is changed to a more\n widely supported curve.\n\n Own Id: OTP-11575\n\n- Bug in the TLS hello extension handling caused the server to behave as it did\n not understand secure renegotiation.\n\n Own Id: OTP-11595","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 5.3.2 - SSL Release Notes","ref":"notes.html#ssl-5-3-2"},{"type":"extras","doc":"- Honors the clients advertised support of elliptic curves and no longer sends\n incorrect elliptic curve extension in server hello.\n\n Own Id: OTP-11370\n\n- Fix initialization of DTLS fragment reassembler, in previously contributed\n code, for future support of DTLS . Thanks to Andreas Schultz.\n\n Own Id: OTP-11376\n\n- Corrected type error in client_preferred_next_protocols documentation. Thanks\n to Julien Barbot.\n\n Own Id: OTP-11457","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- TLS code has been refactored to prepare for future DTLS support. Also some\n DTLS code is in place but not yet runnable, some of it contributed by Andreas\n Schultz and some of it written by the OTP team. Thanks to to Andreas for his\n participation.\n\n Own Id: OTP-11292\n\n- Remove extraneous dev debug code left in the close function. Thanks to Ken\n Key.\n\n Own Id: OTP-11447\n\n- Add SSL Server Name Indication (SNI) client support. Thanks to Julien Barbot.\n\n Own Id: OTP-11460","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 5.3.1 - SSL Release Notes","ref":"notes.html#ssl-5-3-1"},{"type":"extras","doc":"- Setopts during renegotiation caused the renegotiation to be unsuccessful.\n\n If calling setopts during a renegotiation the FSM state might change during\n the handling of the setopts messages, this is now handled correctly.\n\n Own Id: OTP-11228\n\n- Now handles signature_algorithm field in digitally_signed properly with proper\n defaults. Prior to this change some elliptic curve cipher suites could fail\n reporting the error \"bad certificate\".\n\n Own Id: OTP-11229\n\n- The code emulating the inet header option was changed in the belief that it\n made it inet compatible. However the testing is a bit hairy as the inet option\n is actually broken, now the tests are corrected and the header option should\n work in the same broken way as inet again, preferably use the bitsyntax\n instead.\n\n Own Id: OTP-11230","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Make the ssl manager name for erlang distribution over SSL/TLS relative to the\n module name of the ssl_manager.\n\n This can be beneficial when making tools that rename modules for internal\n processing in the tool.\n\n Own Id: OTP-11255\n\n- Add documentation regarding log_alert option.\n\n Own Id: OTP-11271","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 5.3 - SSL Release Notes","ref":"notes.html#ssl-5-3"},{"type":"extras","doc":"- Honor the versions option to ssl:connect and ssl:listen.\n\n Own Id: OTP-10905\n\n- Next protocol negotiation with reused sessions will now succeed\n\n Own Id: OTP-10909","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add support for PSK (Pre Shared Key) and SRP (Secure Remote Password) cipher\n suites, thanks to Andreas Schultz.\n\n Own Id: OTP-10450 Aux Id: kunagi-269 \\[180]\n\n- Fix SSL Next Protocol Negotiation documentation. Thanks to Julien Barbot.\n\n Own Id: OTP-10955\n\n- Fix ssl_connection to support reading proxy/chain certificates. Thanks to\n Valentin Kuznetsov.\n\n Own Id: OTP-10980\n\n- Integrate elliptic curve contribution from Andreas Schultz\n\n In order to be able to support elliptic curve cipher suites in SSL/TLS,\n additions to handle elliptic curve infrastructure has been added to public_key\n and crypto.\n\n This also has resulted in a rewrite of the crypto API to gain consistency and\n remove unnecessary overhead. All OTP applications using crypto has been\n updated to use the new API.\n\n Impact: Elliptic curve cryptography (ECC) offers equivalent security with\n smaller key sizes than other public key algorithms. Smaller key sizes result\n in savings for power, memory, bandwidth, and computational cost that make ECC\n especially attractive for constrained environments.\n\n Own Id: OTP-11009","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 5.2.1 - SSL Release Notes","ref":"notes.html#ssl-5-2-1"},{"type":"extras","doc":"- Transport callback handling is changed so that gen_tcp is treated as a special\n case where inet will be called directly for functions such as setopts, as\n gen_tcp does not have its own setopts. This will enable users to use the\n transport callback for other customizations such as websockets.\n\n Own Id: OTP-10847\n\n- Follow up to OTP-10451 solved in ssl-5.2 R16A. Make sure format_error return\n good strings. Replace confusing legacy atoms with more descriptive atoms.\n\n Own Id: OTP-10864","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 5.1.2.1 - SSL Release Notes","ref":"notes.html#ssl-5-1-2-1"},{"type":"extras","doc":"- Make log_alert configurable as option in ssl, SSLLogLevel added as option to\n inets conf file\n\n Own Id: OTP-11259","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 5.2 - SSL Release Notes","ref":"notes.html#ssl-5-2"},{"type":"extras","doc":"- SSL: TLS 1.2, advertise sha224 support, thanks to Andreas Schultz.\n\n Own Id: OTP-10586\n\n- If an ssl server is restarted with new options and a client tries to reuse a\n session the server must make sure that it complies to the new options before\n agreeing to reuse it.\n\n Own Id: OTP-10595\n\n- Now handles cleaning of CA-certificate database correctly so that there will\n be no memory leek, bug was introduced in ssl- 5.1 when changing implementation\n to increase parallel execution.\n\n Impact: Improved memory usage, especially if you have many different\n certificates and upgrade tcp-connections to TLS-connections.\n\n Own Id: OTP-10710","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Support Next Protocol Negotiation in TLS, thanks to Ben Murphy for the\n contribution.\n\n Impact: Could give performance benefit if used as it saves a round trip.\n\n Own Id: OTP-10361 Aux Id: kunagi-214 \\[125]\n\n- TLS 1.2 will now be the default TLS version if sufficient crypto support is\n available otherwise TLS 1.1 will be default.\n\n Impact: A default TLS connection will have higher security and hence it may be\n perceived as slower then before.\n\n Own Id: OTP-10425 Aux Id: kunagi-275 \\[186]\n\n- It is now possible to call controlling_process on a listen socket, same as in\n gen_tcp.\n\n Own Id: OTP-10447\n\n- Remove filter mechanisms that made error messages backwards compatible with\n old ssl but hid information about what actually happened.\n\n This does not break the documented API however other reason terms may be\n returned, so code that matches on the reason part of \\{error, Reason\\} may\n fail.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-10451 Aux Id: kunagi-270 \\[181]\n\n- Added missing dependencies to Makefile\n\n Own Id: OTP-10594\n\n- Removed deprecated function ssl:pid/0, it has been pointless since R14 but has\n been keep for backwards compatibility.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-10613 Aux Id: kunagi-331 \\[242]\n\n- Refactor to simplify addition of key exchange methods, thanks to Andreas\n Schultz.\n\n Own Id: OTP-10709","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 5.1.2 - SSL Release Notes","ref":"notes.html#ssl-5-1-2"},{"type":"extras","doc":"- ssl:ssl_accept/2 timeout is no longer ignored\n\n Own Id: OTP-10600","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 5.1.1 - SSL Release Notes","ref":"notes.html#ssl-5-1-1"},{"type":"extras","doc":"- ssl:recv/3 could \"loose\" data when the timeout occurs. If the timeout in\n ssl:connect or ssl:ssl_accept expired the ssl connection process was not\n terminated as it should, this due to gen_fsm:send_all_state_event timeout is a\n client side time out. These timouts are now handled by the gen_fsm-procss\n instead.\n\n Own Id: OTP-10569","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Better termination handling that avoids hanging.\n\n Own Id: OTP-10574","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 5.1 - SSL Release Notes","ref":"notes.html#ssl-5-1"},{"type":"extras","doc":"- Sometimes the client process could receive an extra \\{error, closed\\} message\n after ssl:recv had returned \\{error, closed\\}.\n\n Own Id: OTP-10118\n\n- ssl v3 alert number 41 (no_certificate_RESERVED) is now recognized\n\n Own Id: OTP-10196","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Experimental support for TLS 1.1 is now available, will be officially\n supported from OTP-R16. Thanks to Andreas Schultz for implementing the first\n version.\n\n Own Id: OTP-8871\n\n- Experimental support for TLS 1.2 is now available, will be officially\n supported from OTP-R16. Thanks to Andreas Schultz for implementing the first\n version.\n\n Own Id: OTP-8872\n\n- Removed some bottlenecks increasing the applications parallelism especially\n for the client side.\n\n Own Id: OTP-10113\n\n- Workaround for handling certificates that wrongly encode X509countryname in\n utf-8 when the actual value is a valid ASCCI value of length 2. Such\n certificates are accepted by many browsers such as Chrome and Fierfox so for\n interoperability reasons we will too.\n\n Own Id: OTP-10222","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 5.0.1 - SSL Release Notes","ref":"notes.html#ssl-5-0-1"},{"type":"extras","doc":"- Robustness and improvement to distribution over SSL\n\n Fix a bug where ssl_tls_dist_proxy would crash at caller timeout. Fix a bug\n where a timeout from the SSL layer would block the distribution indefinitely.\n Run the proxy exclusively on the loopback interface. (Thanks to Paul Guyot)\n\n Own Id: OTP-9915\n\n- Fix setup loop of SSL TLS dist proxy\n\n Fix potential leak of processes waiting indefinitely for data from closed\n sockets during socket setup phase. (Thanks to Paul Guyot)\n\n Own Id: OTP-9916\n\n- Correct spelling of registered (Thanks to Richard Carlsson)\n\n Own Id: OTP-9925\n\n- Added TLS PRF function to the SSL API for generation of additional key\n material from a TLS session. (Thanks to Andreas Schultz)\n\n Own Id: OTP-10024","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 5.0 - SSL Release Notes","ref":"notes.html#ssl-5-0"},{"type":"extras","doc":"- Invalidation handling of sessions could cause the time_stamp field in the\n session record to be set to undefined crashing the session clean up process.\n This did not affect the connections but would result in that the session table\n would grow.\n\n Own Id: OTP-9696 Aux Id: seq11947\n\n- Changed code to use ets:foldl and throw instead of ets:next traversal,\n avoiding the need to explicitly call ets:safe_fixtable. It was possible to get\n a badarg-crash under special circumstances.\n\n Own Id: OTP-9703 Aux Id: seq11947\n\n- Send ssl_closed notification to active ssl user when a tcp error occurs.\n\n Own Id: OTP-9734 Aux Id: seq11946\n\n- If a passive receive was ongoing during a renegotiation the process evaluating\n ssl:recv could be left hanging for ever.\n\n Own Id: OTP-9744","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Support for the old ssl implementation is dropped and the code is removed.\n\n Own Id: OTP-7048\n\n- The erlang distribution can now be run over the new ssl implementation. All\n options can currently not be set but it is enough to replace to old ssl\n implementation.\n\n Own Id: OTP-7053\n\n- public_key, ssl and crypto now supports PKCS-8\n\n Own Id: OTP-9312\n\n- Implements a CBC timing attack counter measure. Thanks to Andreas Schultz for\n providing the patch.\n\n Own Id: OTP-9683\n\n- Mitigates an SSL/TLS Computational DoS attack by disallowing the client to\n renegotiate many times in a row in a short time interval, thanks to Tuncer\n Ayaz for alerting us about this.\n\n Own Id: OTP-9739\n\n- Implements the 1/n-1 splitting countermeasure to the Rizzo Duong BEAST attack,\n affects SSL 3.0 and TLS 1.0. Thanks to Tuncer Ayaz for alerting us about this.\n\n Own Id: OTP-9750","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 4.1.6 - SSL Release Notes","ref":"notes.html#ssl-4-1-6"},{"type":"extras","doc":"- replace \"a ssl\" with \"an ssl\" reindent pkix_path_validation/3 Trivial\n documentation fixes (Thanks to Christian von Roques )\n\n Own Id: OTP-9464","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Adds function clause to avoid denial of service attack. Thanks to Vinod for\n reporting this vulnerability.\n\n Own Id: OTP-9364\n\n- Error handling code now takes care of inet:getopts/2 and inets:setopts/2\n crashes. Thanks to Richard Jones for reporting this.\n\n Own Id: OTP-9382\n\n- Support explicit use of packet option httph and httph_bin\n\n Own Id: OTP-9461\n\n- Decoding of hello extensions could fail to come to the correct conclusion due\n to an error in a binary match pattern. Thanks to Ben Murphy.\n\n Own Id: OTP-9589","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 4.1.5 - SSL Release Notes","ref":"notes.html#ssl-4-1-5"},{"type":"extras","doc":"- Calling gen_tcp:connect with option \\{ip, \\{127,0,0,1\\}\\} results in an exit\n with reason badarg. Neither SSL nor INETS This was not caught, resulting in\n crashes with incomprehensible reasons.\n\n Own Id: OTP-9289 Aux Id: seq11845","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 4.1.3 - SSL Release Notes","ref":"notes.html#ssl-4-1-3"},{"type":"extras","doc":"- Fixed error in cache-handling fix from ssl-4.1.2\n\n Own Id: OTP-9018 Aux Id: seq11739\n\n- Verification of a critical extended_key_usage-extension corrected\n\n Own Id: OTP-9029 Aux Id: seq11541","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 4.1.2 - SSL Release Notes","ref":"notes.html#ssl-4-1-2"},{"type":"extras","doc":"- The ssl application caches certificate files, it will now invalidate cache\n entries if the diskfile is changed.\n\n Own Id: OTP-8965 Aux Id: seq11739\n\n- Now runs the terminate function before returning from the call made by\n ssl:close/1, as before the caller of ssl:close/1 could get problems with the\n reuseaddr option.\n\n Own Id: OTP-8992","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"SSL 4.1.1 - SSL Release Notes","ref":"notes.html#ssl-4-1-1"},{"type":"extras","doc":"- Correct handling of client certificate verify message When checking the client\n certificate verify message the server used the wrong algorithm identifier to\n determine the signing algorithm, causing a function clause error in the\n public_key application when the key-exchange algorithm and the public key\n algorithm of the client certificate happen to differ.\n\n Own Id: OTP-8897","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- For testing purposes ssl now also support some anonymous cipher suites when\n explicitly configured to do so.\n\n Own Id: OTP-8870\n\n- Sends an error alert instead of crashing if a crypto function for the selected\n cipher suite fails.\n\n Own Id: OTP-8930 Aux Id: seq11720","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 4.1 - SSL Release Notes","ref":"notes.html#ssl-4-1"},{"type":"extras","doc":"- Updated ssl to ignore CA certs that violate the asn1-spec for a certificate,\n and updated public key asn1 spec to handle inherited DSS-params.\n\n Own Id: OTP-7884\n\n- Changed ssl implementation to retain backwards compatibility for old option\n \\{verify, 0\\} that shall be equivalent to \\{verify, verify_none\\}, also\n separate the cases unknown ca and selfsigned peer cert, and restored return\n value of deprecated function public_key:pem_to_der/1.\n\n Own Id: OTP-8858\n\n- Changed the verify fun so that it differentiate between the peer certificate\n and CA certificates by using valid_peer or valid as the second argument to the\n verify fun. It may not always be trivial or even possible to know when the\n peer certificate is reached otherwise.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8873","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 4.0.1 - SSL Release Notes","ref":"notes.html#ssl-4-0-1"},{"type":"extras","doc":"- The server now verifies the client certificate verify message correctly,\n instead of causing a case-clause.\n\n Own Id: OTP-8721\n\n- The client hello message now always include ALL available cipher suites (or\n those specified by the ciphers option). Previous implementation would filter\n them based on the client certificate key usage extension (such filtering only\n makes sense for the server certificate).\n\n Own Id: OTP-8772\n\n- Fixed handling of the option \\{mode, list\\} that was broken for some packet\n types for instance line.\n\n Own Id: OTP-8785\n\n- Empty packets were not delivered to the client.\n\n Own Id: OTP-8790\n\n- Building in a source tree without prebuilt platform independent build results\n failed on the SSL examples when:\n\n - cross building. This has been solved by not building the SSL examples during\n a cross build.\n - building on Windows.\n\n Own Id: OTP-8791\n\n- Fixed a handshake error which occurred on some ssl implementations.\n\n Own Id: OTP-8793","title":"Fixed Bugs and Malfunctions - SSL Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Revise the public_key API - Cleaned up and documented the public_key API to\n make it useful for general use, also changed ssl to use the new API.\n\n Own Id: OTP-8722\n\n- Added support for inputing certificates and keys directly in DER format these\n options will override the pem-file options if specified.\n\n Own Id: OTP-8723\n\n- To gain interoperability ssl will not check for padding errors when using TLS\n 1.0. It is first in TLS 1.1 that checking the padding is an requirement.\n\n Own Id: OTP-8740\n\n- Changed the semantics of the verify_fun option in the ssl-application so that\n it takes care of both application handling of path validation errors and\n verification of application specific extensions. This means that it is now\n possible for the server application in verify_peer mode to handle path\n validation errors. This change moved some functionality earlier in ssl to the\n public_key application.\n\n Own Id: OTP-8770\n\n- Added the functionality so that the verification fun will be called when a\n certificate is considered valid by the path validation to allow access to each\n certificate in the path to the user application. Also try to verify\n subject-AltName, if unable to verify it let the application verify it.\n\n Own Id: OTP-8825","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"SSL 4.0 - SSL Release Notes","ref":"notes.html#ssl-4-0"},{"type":"extras","doc":"- New ssl now support client/server-certificates signed by dsa keys.\n\n Own Id: OTP-8587\n\n- Ssl has now switched default implementation and removed deprecated certificate\n handling. All certificate handling is done by the public_key application.\n\n Own Id: OTP-8695","title":"Improvements and New Features - SSL Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"\n\n# TLS/DTLS Protocol Overview","title":"TLS/DTLS Protocol Overview","ref":"ssl_protocol.html"},{"type":"extras","doc":"Transport Layer Security (TLS) and its predecessor, the Secure Sockets Layer\n(SSL), are cryptographic protocols designed to provide communications security\nover a computer network. The protocols use X.509 certificates and hence public\nkey (asymmetric) cryptography to authenticate the counterpart with whom they\ncommunicate, and to exchange a symmetric key for payload encryption. The\nprotocol provides data/message confidentiality (encryption), integrity (through\nmessage authentication code checks) and host verification (through certificate\npath validation). DTLS (Datagram Transport Layer Security) that is based on TLS\nbut datagram oriented instead of stream oriented.\n\n# Erlang Support\n\nThe Erlang SSL application implements the TLS/DTLS protocol for the currently\nsupported versions, see the `m:ssl` manual page.\n\nBy default TLS is run over the TCP/IP protocol even though you can plug in any\nother reliable transport protocol with the same Application Programming\nInterface (API) as the `gen_tcp` module in Kernel. DTLS is by default run over\nUDP/IP, which means that application data has no delivery guarantees. Other\ntransports, such as SCTP, may be supported in future releases.\n\nIf a client and a server wants to use an upgrade mechanism, such as defined by\nRFC 2817, to upgrade a regular TCP/IP connection to a TLS connection, this is\nsupported by the Erlang SSL application API. This can be useful for, for\nexample, supporting HTTP and HTTPS on the same port and implementing virtual\nhosting. Note this is a TLS feature only.","title":"Purpose - TLS/DTLS Protocol Overview","ref":"ssl_protocol.html#purpose"},{"type":"extras","doc":"To achieve authentication and privacy, the client and server perform a TLS/DTLS\nhandshake procedure before transmitting or receiving any data. During the\nhandshake, they agree on a protocol version and cryptographic algorithms,\ngenerate shared secrets using public key cryptographies, and optionally\nauthenticate each other with digital certificates.","title":"Security Overview - TLS/DTLS Protocol Overview","ref":"ssl_protocol.html#security-overview"},{"type":"extras","doc":"A _symmetric key_ algorithm has one key only. The key is used for both\nencryption and decryption. These algorithms are fast, compared to public key\nalgorithms (using two keys, one public and one private) and are therefore\ntypically used for encrypting bulk data.\n\nThe keys for the symmetric encryption are generated uniquely for each connection\nand are based on a secret negotiated in the TLS/DTLS handshake.\n\nThe TLS/DTLS handshake protocol and data transfer is run on top of the TLS/DTLS\nRecord Protocol, which uses a keyed-hash Message Authenticity Code (MAC), or a\nHash-based MAC (HMAC), to protect the message data integrity. From the TLS RFC:\n\"A Message Authentication Code is a one-way hash computed from a message and\nsome secret data. It is difficult to forge without knowing the secret data. Its\npurpose is to detect if the message has been altered.\"","title":"Data Privacy and Integrity - TLS/DTLS Protocol Overview","ref":"ssl_protocol.html#data-privacy-and-integrity"},{"type":"extras","doc":"A certificate is similar to a driver's license, or a passport. The holder of the\ncertificate is called the _subject_. The certificate is signed with the private\nkey of the issuer of the certificate. A chain of trust is built by having the\nissuer in its turn being certified by another certificate, and so on, until you\nreach the so called root certificate, which is self-signed, that is, issued by\nitself.\n\nCertificates are issued by Certification Authorities (CAs) only. A handful of\ntop CAs in the world issue root certificates. You can examine several of these\ncertificates by clicking through the menus of your web browser.","title":"Digital Certificates - TLS/DTLS Protocol Overview","ref":"ssl_protocol.html#digital-certificates"},{"type":"extras","doc":"Authentication of the peer is done by public key path validation as defined in\nRFC 3280. This means basically the following:\n\n- Each certificate in the certificate chain is issued by the previous one.\n- The certificates attributes are valid.\n- The root certificate is a trusted certificate that is present in the trusted\n certificate database kept by the peer.\n\nThe server always sends a certificate chain as part of the TLS handshake, but\nthe client only sends one if requested by the server. If the client does not\nhave an appropriate certificate, it can send an \"empty\" certificate to the\nserver.\n\nThe client can choose to accept some path evaluation errors, for example, a web\nbrowser can ask the user whether to accept an unknown CA root certificate. The\nserver, if it requests a certificate, does however not accept any path\nvalidation errors. It is configurable if the server is to accept or reject an\n\"empty\" certificate as response to a certificate request.","title":"Peer Authentication - TLS/DTLS Protocol Overview","ref":"ssl_protocol.html#peer-authentication"},{"type":"extras","doc":"From the TLS RFC: \"A TLS session is an association between a client and a\nserver. Sessions are created by the handshake protocol. Sessions define a set of\ncryptographic security parameters, which can be shared among multiple\nconnections. Sessions are used to avoid the expensive negotiation of new\nsecurity parameters for each connection.\"\n\nSession data is by default kept by the SSL application in a memory storage,\nhence session data is lost at application restart or takeover. Users can define\ntheir own callback module to handle session data storage if persistent data\nstorage is required. Session data is also invalidated when session database\nexceeds its limit or 24 hours after being saved (RFC max lifetime\nrecommendation). The amount of time the session data is to be saved can be\nconfigured.\n\nBy default the TLS/DTLS clients try to reuse an available session and by default\nthe TLS/DTLS servers agree to reuse sessions when clients ask for it. See also\n[Session Reuse Prior to TLS-1.3](using_ssl.md#session-reuse-prior-to-tls-1-3)","title":"TLS Sessions - Prior to TLS-1.3 - TLS/DTLS Protocol Overview","ref":"ssl_protocol.html#tls-sessions-prior-to-tls-1-3"},{"type":"extras","doc":"In TLS 1.3 the session reuse is replaced by a new session tickets mechanism\nbased on the prior to shared key concept. This mechanism also obsoletes the session\ntickets from RFC5077, not implemented by this application. See also\n[Session Tickets and Session Resumption in TLS-1.3](using_ssl.md#session-tickets-and-session-resumption-in-tls-1-3)","title":"TLS-1.3 session tickets - TLS/DTLS Protocol Overview","ref":"ssl_protocol.html#tls-1-3-session-tickets"},{"type":"extras","doc":"\n# Examples\n\nTo see relevant version information for ssl, call `ssl:versions/0` .\n\nTo see all supported cipher suites, call\n[`ssl:cipher_suites(all, 'tlsv1.3')`](`ssl:cipher_suites/2`). The available\ncipher suites for a connection depend on the TLS version and prior to TLS-1.3 also on\nthe certificate. To see the default cipher suite list change `all` to `default`.\nNote that TLS 1.3 and previous versions do not have any cipher suites in common,\nfor listing cipher suites for a specific version use\n[`ssl:cipher_suites(exclusive, 'tlsv1.3')`](`ssl:cipher_suites/2`). Specific\ncipher suites that you want your connection to use can also be specified.\nDefault is to use the strongest available.\n\n\n> #### Warning {: .warning }\n>Enabling cipher suites using RSA as a key exchange algorithm is\n>strongly discouraged (only available prior to TLS-1.3). For some\n>configurations software preventions may exist, and can make them usable if they work,\n>but relying on them to work is risky and there are many more reliable\n>cipher suites that can be used instead.\n\nThe following sections shows small examples of how to set up client/server\nconnections using the Erlang shell. The returned value of the `sslsocket` is\nabbreviated with `[...]` as it can be fairly large and is opaque to the user\nexcept for the purpose of pattern matching.\n\n> #### Note {: .info }\n>\n> Note that client certificate verification is optional for the server and needs\n> additional conguration on both sides to work. The Certificate and keys, in the\n> examples, are provided using the `t:ssl:cert_key_conf/0` supplied in the `certs_keys`\n> introduced in OTP 25.","title":"Examples","ref":"using_ssl.html"},{"type":"extras","doc":"```erlang\n 1 > ssl:start(), ssl:connect(\"google.com\", 443, [{verify, verify_peer},\n {cacerts, public_key:cacerts_get()}]).\n {ok,{sslsocket, [...]}}\n```","title":"Basic Client - Examples","ref":"using_ssl.html#basic-client"},{"type":"extras","doc":"_Step 1:_ Start the server side:\n\n```erlang\n1 server> ssl:start().\nok\n```\n\n_Step 2:_ with alternative certificates, in this example the EDDSA certificate\nwill be preferred if TLS-1.3 is negotiated and the RSA certificate will always\nbe used for TLS-1.2 as it does not support the EDDSA algorithm:\n\n```erlang\n2 server> {ok, ListenSocket} =\nssl:listen(9999, [{certs_keys, [#{certfile => \"eddsacert.pem\",\n keyfile => \"eddsakey.pem\"},\n #{certfile => \"rsacert.pem\",\n keyfile => \"rsakey.pem\",\n password => \"foobar\"}\n ]},{reuseaddr, true}]).\n{ok,{sslsocket, [...]}}\n```\n\n_Step 3:_ Do a transport accept on the TLS listen socket:\n\n```erlang\n3 server> {ok, TLSTransportSocket} = ssl:transport_accept(ListenSocket).\n{ok,{sslsocket, [...]}}\n```\n\n> #### Note {: .info }\n>\n> `ssl:transport_accept/1` and `ssl:handshake/2` are separate functions so that the\n> handshake part can be called in a new Erlang process dedicated to handling the\n> connection\n\n_Step 4:_ Start the client side:\n\n```erlang\n1 client> ssl:start().\nok\n```\n\nBe sure to configure trusted certificates to use for server certificate\nverification.\n\n```erlang\n2 client> {ok, Socket} = ssl:connect(\"localhost\", 9999,\n [{verify, verify_peer},\n {cacertfile, \"cacerts.pem\"}, {active, once}], infinity).\n{ok,{sslsocket, [...]}}\n```\n\n_Step 5:_ Do the TLS handshake:\n\n```erlang\n4 server> {ok, Socket} = ssl:handshake(TLSTransportSocket).\n{ok,{sslsocket, [...]}}\n```\n\n> #### Note {: .info }\n>\n> A real server should use `ssl:handshake/2`, which accepts a timeout, to avoid DoS\n> attacks. In the example the timeout defaults to `infinity`.\n\n_Step 6:_ Send a message over TLS:\n\n```erlang\n5 server> ssl:send(Socket, \"foo\").\nok\n```\n\n_Step 7:_ Flush the shell message queue to see that the message sent on the\nserver side is recived by the client side:\n\n```erlang\n3 client> flush().\nShell got {ssl,{sslsocket,[...]},\"foo\"}\nok\n```","title":"Basic Connection - Examples","ref":"using_ssl.html#basic-connection"},{"type":"extras","doc":"Upgrading a a TCP/IP connection to a TLS connections is mostly used when there\nis a desire have unencrypted communication first and then later secure the\ncommunication channel by using TLS. Note that the client and server need to\nagree to do the upgrade in the protocol doing the communication. This is concept\nis often referenced as `STARTLS` and used in many protocols such as `SMTP`,\n`FTPS` and `HTTPS` via a proxy.\n\n> #### Warning {: .warning }\n>\n> Maximum security recommendations are however moving away from such solutions.\n\nTo upgrade to a TLS connection:\n\n_Step 1:_ Start the server side:\n\n```erlang\n1 server> ssl:start().\n ok\n```\n\n_Step 2:_ Create a normal TCP listen socket and ensure `active` is set to\n`false` and not set to any active mode otherwise TLS handshake messages can be\ndelivered to the wrong process.\n\n```erlang\n2 server> {ok, ListenSocket} = gen_tcp:listen(9999, [{reuseaddr, true},\n {active, false}]).\n {ok, #Port<0.475>}\n```\n\n_Step 3:_ Accept client connection:\n\n```erlang\n3 server> {ok, Socket} = gen_tcp:accept(ListenSocket).\n {ok, #Port<0.476>}\n```\n\n_Step 4:_ Start the client side:\n\n```erlang\n1 client> ssl:start().\n ok\n```\n\n```erlang\n2 client> {ok, Socket} = gen_tcp:connect(\"localhost\", 9999, [], infinity).\n```\n\n_Step 5:_ Do the TLS handshake:\n\n```erlang\n4 server> {ok, TLSSocket} = ssl:handshake(Socket, [{verify, verify_peer},\n {fail_if_no_peer_cert, true},\n {cacertfile, \"cacerts.pem\"},\n {certs_keys, [#{certfile => \"cert.pem\", keyfile => \"key.pem\"}]}]).\n {ok,{sslsocket,[...]}}\n```\n\n_Step 6:_ Upgrade to a TLS connection. The client and server must agree upon the\nupgrade. The server must be prepared to be a TLS server before the client can do\na successful connect.\n\n```erlang\n3 client>{ok, TLSSocket} = ssl:connect(Socket, [{verify, verify_peer},\n {cacertfile, \"cacerts.pem\"},\n {certs_keys, [#{certfile => \"cert.pem\", keyfile => \"key.pem\"}]}], infinity).\n{ok,{sslsocket,[...]}}\n```\n\n_Step 7:_ Send a message over TLS:\n\n```erlang\n4 client> ssl:send(TLSSocket, \"foo\").\n ok\n```\n\n_Step 8:_ Set `active once` on the TLS socket:\n\n```erlang\n5 server> ssl:setopts(TLSSocket, [{active, once}]).\n ok\n```\n\n_Step 9:_ Flush the shell message queue to see that the message sent on the\nclient side is recived by the server side:\n\n```erlang\n5 server> flush().\n Shell got {ssl,{sslsocket,[...]},\"foo\"}\n ok\n```","title":"Upgrade Example - TLS only - Examples","ref":"using_ssl.html#upgrade-example-tls-only"},{"type":"extras","doc":"Fetch default cipher suite list for a TLS/DTLS version. Change default to all to\nget all possible cipher suites.\n\n```erlang\n1> Default = ssl:cipher_suites(default, 'tlsv1.2').\n [#{cipher => aes_256_gcm,key_exchange => ecdhe_ecdsa,\n mac => aead,prf => sha384}, ....]\n```\n\nIn OTP 20 it is desirable to remove all cipher suites that uses rsa key exchange\n(removed from default in 21)\n\n```erlang\n2> NoRSA =\n ssl:filter_cipher_suites(Default,\n [{key_exchange, fun(rsa) -> false;\n (_) -> true\n end}]).\n [...]\n```\n\nPick just a few suites\n\n```erlang\n 3> Suites =\n ssl:filter_cipher_suites(Default,\n [{key_exchange, fun(ecdh_ecdsa) -> true;\n (_) -> false\n end},\n {cipher, fun(aes_128_cbc) -> true;\n (_) ->false\n end}]).\n\n[#{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,\n mac => sha256,prf => sha256},\n #{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,mac => sha,\n prf => default_prf}]\n```\n\nMake some particular suites the most preferred, or least preferred by changing\nprepend to append.\n\n```erlang\n 4>ssl:prepend_cipher_suites(Suites, Default).\n [#{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,\n mac => sha256,prf => sha256},\n #{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,mac => sha,\n prf => default_prf},\n #{cipher => aes_256_cbc,key_exchange => ecdhe_ecdsa,\n mac => sha384,prf => sha384}, ...]\n```","title":"Customizing cipher suites - Examples","ref":"using_ssl.html#customizing-cipher-suites"},{"type":"extras","doc":"Starting from TLS-1.2 signature algorithms (called signature schemes in TLS-1.3)\nis something that can be negotiated and hence also configured. These\nalgorithms/schemes will be used for digital signatures in protocol messages and\nin certificates.\n\n> #### Note {: .info }\n>\n> TLS-1.3 schemes have atom names whereas TLS-1.2 configuration is two element\n> tuples composed by one hash algorithm and one signature algorithm. When both\n> versions are supported the configuration can be a mix of these as both\n> versions might be negotiated. All `rsa_pss` based schemes are back ported to\n> TLS-1.2 and can be used also in a TLS-1.2 configuration. In TLS-1.2 the\n> signature algorithms chosen by the server will also be affected by the chiper\n> suite that is chosen, which is not the case in TLS-1.3.\n\nUsing the function `ssl:signature_algs/2` will let you inspect different aspects\nof possible configurations for your system. For example if TLS-1.3 and TLS-1.2\nis supported the default signature_algorithm list in OTP-26 and cryptolib from\nOpenSSL 3.0.2 would look like:\n\n```erlang\n 1> ssl:signature_algs(default, 'tlsv1.3').\n %% TLS-1.3 schemes\n [eddsa_ed25519,eddsa_ed448,ecdsa_secp521r1_sha512,\n ecdsa_secp384r1_sha384,ecdsa_secp256r1_sha256,\n rsa_pss_pss_sha512,rsa_pss_pss_sha384,rsa_pss_pss_sha256,\n rsa_pss_rsae_sha512,rsa_pss_rsae_sha384,rsa_pss_rsae_sha256,\n %% Legacy schemes only valid for certificate signatures in TLS-1.3\n %% (would have a tuple name in TLS-1.2 only configuration)\n rsa_pkcs1_sha512,rsa_pkcs1_sha384,rsa_pkcs1_sha256\n %% TLS 1.2 algorithms\n {sha512,ecdsa},\n {sha384,ecdsa},\n {sha256,ecdsa}]\n```\n\nIf you want to add support for non default supported algorithms you should\nappend them to the default list as the configuration is in prefered order,\nsomething like this:\n\n```erlang\n MySignatureAlgs = ssl:signature_algs(default, 'tlsv1.3') ++ [{sha, rsa}, {sha, dsa}],\n ssl:connect(Host,Port,[{signature_algs, MySignatureAlgs,...]}),\n ...\n```\n\nSee also `ssl:signature_algs/2` and [sign_algo()](`t:ssl:signature_algs/0`)","title":"Customizing signature algorithms(TLS-1.2)/schemes(TLS-1.3) - Examples","ref":"using_ssl.html#customizing-signature-algorithms-tls-1-2-schemes-tls-1-3"},{"type":"extras","doc":"Erlang ssl application is able to use private keys provided by OpenSSL engines\nusing the following mechanism:\n\n```erlang\n1> ssl:start().\nok\n```\n\nLoad a crypto engine, should be done once per engine used. For example\ndynamically load the engine called `MyEngine`:\n\n```erlang\n2> {ok, EngineRef} =\ncrypto:engine_load(<<\"dynamic\">>,\n[{<<\"SO_PATH\">>, \"/tmp/user/engines/MyEngine\"},<<\"LOAD\">>],\n[]).\n{ok,#Ref<0.2399045421.3028942852.173962>}\n```\n\nCreate a map with the engine information and the algorithm used by the engine:\n\n```erlang\n3> PrivKey =\n #{algorithm => rsa,\n engine => EngineRef,\n key_id => \"id of the private key in Engine\"}.\n```\n\nUse the map in the ssl key option:\n\n```erlang\n4> {ok, SSLSocket} =\n ssl:connect(\"localhost\", 9999,\n [{cacertfile, \"cacerts.pem\"},\n {certs_keys, [#{certfile => \"cert.pem\", key => PrivKey}]}\n ], infinity).\n\n```\n\nSee also [crypto documentation](`e:crypto:engine_load.md#engine_load`)","title":"Using an Engine Stored Key - Examples","ref":"using_ssl.html#using-an-engine-stored-key"},{"type":"extras","doc":"The NSS keylog debug feature can be used by authorized users to for instance\nenable wireshark to decrypt TLS packets.\n\n_Server (with NSS key logging)_\n\n```erlang\n server() ->\n application:load(ssl),\n {ok, _} = application:ensure_all_started(ssl),\n Port = 11029,\n LOpts = [{certs_keys, [#{certfile => \"cert.pem\", keyfile => \"key.pem\"}]},\n {reuseaddr, true},\n {versions, ['tlsv1.2','tlsv1.3']},\n {keep_secrets, true} %% Enable NSS key log (debug option)\n ],\n {ok, LSock} = ssl:listen(Port, LOpts),\n {ok, ASock} = ssl:transport_accept(LSock),\n {ok, CSock} = ssl:handshake(ASock).\n```\n\n_Exporting the secrets_\n\n```erlang\n {ok, [{keylog, KeylogItems}]} = ssl:connection_information(CSock, [keylog]).\n file:write_file(\"key.log\", [[KeylogItem,$\\n] || KeylogItem <- KeylogItems]).\n```","title":"NSS keylog - Examples","ref":"using_ssl.html#nss-keylog"},{"type":"extras","doc":"Clients can request to reuse a session established by a previous full handshake\nbetween that client and server by sending the id of the session in the initial\nhandshake message. The server may or may not agree to reuse it. If agreed the\nserver will send back the id and if not it will send a new id. The ssl\napplication has several options for handling session reuse.\n\nOn the client side the ssl application will save session data to try to automate\nsession reuse on behalf of the client processes on the Erlang node. Note that\nonly verified sessions will be saved for security reasons, that is session\nresumption relies on the certificate validation to have been run in the original\nhandshake. To minimize memory consumption only unique sessions will be saved\nunless the special `save` value is specified for the following option\n`{reuse_sessions, boolean() | save}` in which case a full handshake will be\nperformed and that specific session will have been saved before the handshake\nreturns. The session id and even an opaque binary containing the session data\ncan be retrieved using `ssl:connection_information/1` function. A saved session\n(guaranteed by the save option) can be explicitly reused using\n`{reuse_session, SessionId}`. Also it is possible for the client to reuse a\nsession that is not saved by the ssl application using\n`{reuse_session, {SessionId, SessionData}}`.\n\n> #### Note {: .info }\n>\n> When using explicit session reuse, it is up to the client to make sure that\n> the session being reused is for the correct server and has been verified.\n\nHere follows a client side example, divide into several steps for readability.\n\nStep 1 - Automated Session Reuse\n\n```erlang\n1> ssl:start().\nok\n\n2>{ok, C1} = ssl:connect(\"localhost\", 9999, [{verify, verify_peer},\n {versions, ['tlsv1.2']},\n {cacertfile, \"cacerts.pem\"}]).\n{ok,{sslsocket,{gen_tcp,#Port<0.7>,tls_connection,undefined}, ...}}\n\n3> ssl:connection_information(C1, [session_id]).\n{ok,[{session_id,<<95,32,43,22,35,63,249,22,26,36,106,\n 152,49,52,124,56,130,192,137,161,\n 146,145,164,232,...>>}]}\n\n%% Reuse session if possible, note that if C2 is really fast the session\n%% data might not be available for reuse.\n4>{ok, C2} = ssl:connect(\"localhost\", 9999, [{verify, verify_peer},\n {versions, ['tlsv1.2']},\n {cacertfile, \"cacerts.pem\"},\n {reuse_sessions, true}]).\n{ok,{sslsocket,{gen_tcp,#Port<0.8>,tls_connection,undefined}, ...]}}\n\n%% C2 got same session ID as client one, session was automatically reused.\n5> ssl:connection_information(C2, [session_id]).\n{ok,[{session_id,<<95,32,43,22,35,63,249,22,26,36,106,\n 152,49,52,124,56,130,192,137,161,\n 146,145,164,232,...>>}]}\n```\n\nStep 2- Using `save` Option\n\n```erlang\n%% We want save this particular session for\n%% reuse although it has the same basis as C1\n6> {ok, C3} = ssl:connect(\"localhost\", 9999, [{verify, verify_peer},\n {versions, ['tlsv1.2']},\n {cacertfile, \"cacerts.pem\"},\n {reuse_sessions, save}]).\n\n{ok,{sslsocket,{gen_tcp,#Port<0.9>,tls_connection,undefined}, ...]}}\n\n%% A full handshake is performed and we get a new session ID\n7> {ok, [{session_id, ID}]} = ssl:connection_information(C3, [session_id]).\n{ok,[{session_id,<<91,84,27,151,183,39,84,90,143,141,\n 121,190,66,192,10,1,27,192,33,95,78,\n 8,34,180,...>>}]}\n\n%% Use automatic session reuse\n8> {ok, C4} = ssl:connect(\"localhost\", 9999, [{verify, verify_peer},\n {versions, ['tlsv1.2']},\n {cacertfile, \"cacerts.pem\"},\n {reuse_sessions, true}]).\n\n{ok,{sslsocket,{gen_tcp,#Port<0.10>,tls_connection,\n undefined}, ...]}}\n\n%% The \"saved\" one happened to be selected, but this is not a guarantee\n9> ssl:connection_information(C4, [session_id]).\n{ok,[{session_id,<<91,84,27,151,183,39,84,90,143,141,\n 121,190,66,192,10,1,27,192,33,95,78,\n 8,34,180,...>>}]}\n\n%% Make sure to reuse the \"saved\" session\n10> {ok, C5} = ssl:connect(\"localhost\", 9999, [{verify, verify_peer},\n {versions, ['tlsv1.2']},\n {cacertfile, \"cacerts.pem\"},\n {reuse_session, ID}]).\n{ok,{sslsocket,{gen_tcp,#Port<0.11>,tls_connection,\n undefined}, ...]}}\n\n11> ssl:connection_information(C5, [session_id]).\n{ok,[{session_id,<<91,84,27,151,183,39,84,90,143,141,\n 121,190,66,192,10,1,27,192,33,95,78,\n 8,34,180,...>>}]}\n```\n\nStep 3 - Explicit Session Reuse\n\n```erlang\n%% Perform a full handshake and the session will not be saved for reuse\n12> {ok, C9} =\nssl:connect(\"localhost\", 9999, [{verify, verify_peer},\n {versions, ['tlsv1.2']},\n {cacertfile, \"cacerts.pem\"},\n {reuse_sessions, false},\n {server_name_indication, disable}]).\n{ok,{sslsocket,{gen_tcp,#Port<0.14>,tls_connection, ...}}\n\n%% Fetch session ID and data for C9 connection\n12> {ok, [{session_id, ID1}, {session_data, SessData}]} =\n ssl:connection_information(C9, [session_id, session_data]).\n{ok,[{session_id,<<9,233,4,54,170,88,170,180,17,96,202,\n 85,85,99,119,47,9,68,195,50,120,52,\n 130,239,...>>},\n {session_data,<<131,104,13,100,0,7,115,101,115,115,105,\n 111,110,109,0,0,0,32,9,233,4,54,170,...>>}]}\n\n%% Explicitly reuse the session from C9\n13> {ok, C10} = ssl:connect(\"localhost\", 9999, [{verify, verify_peer},\n {versions, ['tlsv1.2']},\n {cacertfile, \"cacerts.pem\"},\n {reuse_session, {ID1, SessData}}]).\n{ok,{sslsocket,{gen_tcp,#Port<0.15>,tls_connection,\n undefined}, ...}}\n\n14> ssl:connection_information(C10, [session_id]).\n{ok,[{session_id,<<9,233,4,54,170,88,170,180,17,96,202,\n 85,85,99,119,47,9,68,195,50,120,52,\n 130,239,...>>}]}\n```\n\nStep 4 - Not Possible to Reuse Explicit Session by ID Only\n\n```erlang\n%% Try to reuse the session from C9 using only the id\n15> {ok, E} = ssl:connect(\"localhost\", 9999, [{verify, verify_peer},\n {versions, ['tlsv1.2']},\n {cacertfile, \"cacerts.pem\"},\n {reuse_session, ID1}]).\n{ok,{sslsocket,{gen_tcp,#Port<0.18>,tls_connection,\n undefined}, ...}}\n\n%% This will fail (as it is not saved for reuse)\n%% and a full handshake will be performed, we get a new id.\n16> ssl:connection_information(E, [session_id]).\n{ok,[{session_id,<<87,46,43,126,175,68,160,153,37,29,\n 196,240,65,160,254,88,65,224,18,63,\n 18,17,174,39,...>>}]}\n```\n\nOn the server side the the `{reuse_sessions, boolean()}` option determines if\nthe server will save session data and allow session reuse or not. This can be\nfurther customized by the option `{reuse_session, fun()}` that may introduce a\nlocal policy for session reuse.","title":"Session Reuse Prior to TLS 1.3 - Examples","ref":"using_ssl.html#session-reuse-prior-to-tls-1-3"},{"type":"extras","doc":"TLS 1.3 introduces a new secure way of resuming sessions by using session\ntickets. A session ticket is an opaque data structure that is sent in the\npre_shared_key extension of a ClientHello, when a client attempts to resume a\nsession with keying material from a previous successful handshake.\n\nSession tickets can be stateful or stateless. A stateful session ticket is a\ndatabase reference (session ticket store) and used with stateful servers, while\na stateless ticket is a self-encrypted and self-authenticated data structure\nwith cryptographic keying material and state data, enabling session resumption\nwith stateless servers.\n\nThe choice between stateful or stateless depends on the server requirements as\nthe session tickets are opaque for the clients. Generally, stateful tickets are\nsmaller and the server can guarantee that tickets are only used once. Stateless\ntickets contain additional data, require less storage on the server side, but\nthey offer different guarantees against anti-replay. See also\n[Anti-Replay Protection in TLS 1.3](using_ssl.md#anti-replay-protection-in-tls-1-3)\n\nSession tickets are sent by servers on newly established TLS connections. The\nnumber of tickets sent and their lifetime are configurable by application\nvariables. See also [SSL's configuration](ssl_app.md#configuration).\n\nSession tickets are protected by application traffic keys, and in stateless\ntickets, the opaque data structure itself is self-encrypted.\n\nAn example with automatic and manual session resumption:\n\n```erlang\n {ok, _} = application:ensure_all_started(ssl).\n LOpts = [{certs_keys, [#{certfile => \"cert.pem\",\n keyfile => \"key.pem\"}]},\n {versions, ['tlsv1.2','tlsv1.3']},\n {session_tickets, stateless}].\n {ok, LSock} = ssl:listen(8001, LOpts).\n {ok, ASock} = ssl:transport_accept(LSock).\n```\n\n_Step 2 (client):_ Start the client and connect to server:\n\n```erlang\n {ok, _} = application:ensure_all_started(ssl).\n COpts = [{cacertfile, \"cert.pem\"},\n {versions, ['tlsv1.2','tlsv1.3']},\n {log_level, debug},\n {session_tickets, auto}].\n ssl:connect(\"localhost\", 8001, COpts).\n```\n\n_Step 3 (server):_ Start the TLS handshake:\n\n```erlang\n {ok, CSocket} = ssl:handshake(ASock).\n```\n\nA connection is established using a full handshake. Below is a summary of the\nexchanged messages:\n\n```erlang\n >>> TLS 1.3 Handshake, ClientHello ...\n << >> Handshake, Finished ...\n << >> TLS 1.3 Handshake, ClientHello ...\n << >> Handshake, Finished ...\n << TicketData end.\n```\n\n_Step 11 (server):_ Accept a new connection on the server:\n\n```erlang\n {ok, ASock4} = ssl:transport_accept(LSock).\n```\n\n_Step 12 (client):_ Initiate a new connection to the server with the session\nticket received in Step 10:\n\n```erlang\n {ok, _} = application:ensure_all_started(ssl).\n COpts2 = [{cacertfile, \"cert.pem\"},\n {versions, ['tlsv1.2','tlsv1.3']},\n {log_level, debug},\n {session_tickets, manual},\n {use_ticket, [Ticket]}].\n ssl:connect(\"localhost\", 8001, COpts).\n```\n\n_Step 13 (server):_ Start the handshake:\n\n```erlang\n {ok, CSock4} = ssl:handshake(ASock4).\n```","title":"Session Tickets and Session Resumption in TLS 1.3 - Examples","ref":"using_ssl.html#session-tickets-and-session-resumption-in-tls-1-3"},{"type":"extras","doc":"TLS 1.3 allows clients to send data on the first flight if the endpoints have a\nshared crypographic secret (pre-shared key). This means that clients can send\nearly data if they have a valid session ticket received in a previous successful\nhandshake. For more information about session resumption see\n[Session Tickets and Session Resumption in TLS 1.3](using_ssl.md#session-tickets-and-session-resumption-in-tls-1-3).\n\nThe security properties of Early Data are weaker than other kinds of TLS data.\nThis data is not forward secret, and it is vulnerable to replay attacks. For\navailable mitigation strategies see\n[Anti-Replay Protection in TLS 1.3](using_ssl.md#anti-replay-protection-in-tls-1-3).\n\nIn normal operation, clients will not know which, if any, of the available\nmitigation strategies servers actually implement, and hence must only send early\ndata which they deem safe to be replayed. For example, idempotent HTTP\noperations, such as HEAD and GET, can usually be regarded as safe but even they\ncan be exploited by a large number of replays causing resource limit exhaustion\nand other similar problems.\n\nAn example of sending early data with automatic and manual session ticket\nhandling:\n\n_Server_\n\n```erlang\nearly_data_server() ->\n application:load(ssl),\n {ok, _} = application:ensure_all_started(ssl),\n Port = 11029,\n LOpts = [{certs_keys, [#{certfile => \"cert.pem\", keyfile => \"key.pem\"}]},\n {reuseaddr, true},\n {versions, ['tlsv1.2','tlsv1.3']},\n {session_tickets, stateless},\n {early_data, enabled},\n ],\n {ok, LSock} = ssl:listen(Port, LOpts),\n %% Accept first connection\n {ok, ASock0} = ssl:transport_accept(LSock),\n {ok, CSock0} = ssl:handshake(ASock0),\n %% Accept second connection\n {ok, ASock1} = ssl:transport_accept(LSock),\n {ok, CSock1} = ssl:handshake(ASock1),\n Sock.\n```\n\n_Client (automatic ticket handling):_\n\n```erlang\nearly_data_auto() ->\n %% First handshake 1-RTT - get session tickets\n application:load(ssl),\n {ok, _} = application:ensure_all_started(ssl),\n Port = 11029,\n Data = <<\"HEAD / HTTP/1.1\\r\\nHost: \\r\\nConnection: close\\r\\n\">>,\n COpts0 = [{cacertfile, \"cacerts.pem\"},\n {versions, ['tlsv1.2', 'tlsv1.3']},\n {session_tickets, auto}],\n {ok, Sock0} = ssl:connect(\"localhost\", Port, COpts0),\n\n %% Wait for session tickets\n timer:sleep(500),\n %% Close socket if server cannot handle multiple\n %% connections e.g. openssl s_server\n ssl:close(Sock0),\n\n %% Second handshake 0-RTT\n COpts1 = [{cacertfile, \"cacerts.pem\"},\n {versions, ['tlsv1.2', 'tlsv1.3']},\n {session_tickets, auto},\n {early_data, Data}],\n {ok, Sock} = ssl:connect(\"localhost\", Port, COpts1),\n Sock.\n\n```\n\n_Client (manual ticket handling):_\n\n```erlang\nearly_data_manual() ->\n %% First handshake 1-RTT - get session tickets\n application:load(ssl),\n {ok, _} = application:ensure_all_started(ssl),\n Port = 11029,\n Data = <<\"HEAD / HTTP/1.1\\r\\nHost: \\r\\nConnection: close\\r\\n\">>,\n COpts0 = [{cacertfile, \"cacerts.pem\"},\n {versions, ['tlsv1.2', 'tlsv1.3']},\n {session_tickets, manual}],\n {ok, Sock0} = ssl:connect(\"localhost\", Port, COpts0),\n\n %% Wait for session tickets\n Ticket =\n receive\n {ssl, session_ticket, Ticket0} ->\n Ticket0\n end,\n\n %% Close socket if server cannot handle multiple connections\n %% e.g. openssl s_server\n ssl:close(Sock0),\n\n %% Second handshake 0-RTT\n COpts1 = [{cacertfile, \"cacerts.pem\"},\n {versions, ['tlsv1.2', 'tlsv1.3']},\n {session_tickets, manual},\n {use_ticket, [Ticket]},\n {early_data, Data}],\n {ok, Sock} = ssl:connect(\"localhost\", Port, COpts1),\n Sock.\n```","title":"Early Data in TLS-1.3 - Examples","ref":"using_ssl.html#early-data-in-tls-1-3"},{"type":"extras","doc":"The TLS 1.3 protocol does not provide inherent protection for replay of 0-RTT\ndata but describes mechanisms that SHOULD be implemented by compliant server\nimplementations. The implementation of TLS 1.3 in the SSL application employs\nall standard methods to prevent potential threats.\n\n_Single-use tickets_\n\nThis mechanism is available with stateful session tickets. Session tickets can\nonly be used once, subsequent use of the same ticket results in a full\nhandshake. Stateful servers enforce this rule by maintaining a database of\noutstanding valid tickets.\n\n_Client Hello Recording_\n\nThis mechanism is available with stateless session tickets. The server records a\nunique value derived from the ClientHello (PSK binder) in a given time window.\nThe ticket's age is verified by using both the \"obsfuscated_ticket_age\" and an\nadditional timestamp encrypted in the ticket data. As the used datastore allows\nfalse positives, apparent replays will be answered by doing a full 1-RTT\nhandshake.\n\n_Freshness Checks_\n\nThis mechanism is available with the stateless session tickets. As the ticket\ndata has an embedded timestamp, the server can determine if a ClientHello was\nsent reasonably recently and accept the 0-RTT handshake, otherwise if falls back\nto a full 1-RTT handshake. This mechanism is tightly coupled with the previous\none, it prevents storing an unlimited number of ClientHellos.\n\nThe current implementation uses a pair of Bloom filters to implement the last\ntwo mechanisms. Bloom filters are fast, memory-efficient, probabilistic data\nstructures that can tell if an element may be in a set or if it is definitely\nnot in the set.\n\nIf the option `anti_replay` is defined in the server, a\npair of Bloom filters (_current_ and _old_) are used to record incoming\nClientHello messages (it is the unique binder value that is actually stored).\nThe _current_ Bloom filter is used for `WindowSize` seconds to store new\nelements. At the end of the time window the Bloom filters are rotated (the\n_current_ Bloom filter becomes the _old_ and an empty Bloom filter is set as\n_current_.\n\nThe Anti-Replay protection feature in stateless servers executes in the\nfollowing steps when a new ClientHello is received:\n\n- Reported ticket age (obfuscated ticket age) shall be less than ticket\n lifetime.\n- Actual ticket age shall be less than the ticket lifetime (stateless session\n tickets contain the servers timestamp when the ticket was issued).\n- ClientHello created with the ticket shall be sent relatively recently\n (freshness checks).\n- If all above checks passed both _current_ and _old_ Bloom filters are checked\n to detect if binder was already seen. Being a probabilistic data structure,\n false positives can occur and they trigger a full handshake.\n- If the binder is not seen, the binder is validated. If the binder is valid,\n the server proceeds with the 0-RTT handshake.","title":"Anti-Replay Protection in TLS 1.3 - Examples","ref":"using_ssl.html#anti-replay-protection-in-tls-1-3"},{"type":"extras","doc":"Using DTLS has basically the same API as TLS. You need to add the option\n\\{protocol, dtls\\} to the connect and listen functions. For example\n\n```erlang\n client>{ok, Socket} = ssl:connect(\"localhost\", 9999, [{protocol, dtls},\n {verify, verify_peer},\n {cacertfile, \"cacerts.pem\"}],\n infinity).\n{ok,{sslsocket, [...]}}\n\n```","title":"Using DTLS - Examples","ref":"using_ssl.html#using-dtls"},{"type":"extras","doc":"\n# Erlang Distribution over TLS\n\nThis section describes how the Erlang distribution can use TLS to get extra\nverification and security.\n\nThe Erlang distribution can in theory use almost any connection-based protocol\nas bearer. However, a module that implements the protocol-specific parts of the\nconnection setup is needed. The default distribution module is `inet_tcp_dist`\nin the Kernel application. When starting an Erlang node distributed,\n`net_kernel` uses this module to set up listen ports and connections.\n\nIn the SSL application, an extra distribution module, `inet_tls_dist`, can be\nused as an alternative. All distribution connections will use TLS and all\nparticipating Erlang nodes in a distributed system must use this distribution\nmodule.\n\nThe security level depends on the parameters provided to the TLS connection\nsetup. Erlang node cookies are however always used, as they can be used to\ndifferentiate between two different Erlang networks.\n\nTo set up Erlang distribution over TLS:\n\n- _Step 1:_ Build boot scripts including the SSL application.\n- _Step 2:_ Specify the distribution module for `net_kernel`.\n- _Step 3:_ Specify the security options and other SSL options.\n- _Step 4:_ Set up the environment to always use TLS.\n\nThe following sections describe these steps.","title":"Erlang Distribution over TLS","ref":"ssl_distribution.html"},{"type":"extras","doc":"Boot scripts are built using the `systools` utility in the SASL application. For\nmore information on `systools`, see the SASL documentation. This is only an\nexample of what can be done.\n\nThe simplest boot script possible includes only the Kernel and STDLIB\napplications. Such a script is located in the `bin` directory of the Erlang\ndistribution. The source for the script is found under the Erlang installation\ntop directory under `releases/ /start_clean.rel`.\n\nDo the following:\n\n- Copy that script to another location (and preferably another name).\n- Add the applications Crypto, Public Key, and SSL with their current version\n numbers after the STDLIB application.\n\nThe following shows an example `.rel` file with TLS added:\n\n```erlang\n {release, {\"OTP APN 181 01\",\"R15A\"}, {erts, \"5.9\"},\n [{kernel,\"2.15\"},\n {stdlib,\"1.18\"},\n {crypto, \"2.0.3\"},\n {public_key, \"0.12\"},\n {asn1, \"4.0\"},\n {ssl, \"5.0\"}\n ]}.\n```\n\nThe version numbers differ in your system. Whenever one of the applications\nincluded in the script is upgraded, change the script.\n\nDo the following:\n\n- Build the boot script.\n\n Assuming the `.rel file` is stored in a file `start_ssl.rel` in the current\n directory, a boot script can be built as follows:\n\n```text\n 1> systools:make_script(\"start_ssl\",[]).\n```\n\nThere is now a `start_ssl.boot` file in the current directory.\n\nDo the following:\n\n- Test the boot script. To do this, start Erlang with the `-boot` command-line\n parameter specifying this boot script (with its full path, but without the\n `.boot` suffix). In UNIX it can look as follows:\n\n```text\n$ erl -boot /home/me/ssl/start_ssl\nErlang (BEAM) emulator version 5.0\n\nEshell V5.0 (abort with ^G)\n1> whereis(ssl_manager).\n<0.41.0>\n```\n\nThe `whereis` function-call verifies that the SSL application is started.\n\nAs an alternative to building a bootscript, you can explicitly add the path to\nthe SSL `ebin` directory on the command line. This is done with command-line\noption `-pa`. This works as the SSL application does not need to be started for\nthe distribution to come up, as a clone of the SSL application is hooked into\nthe Kernel application. So, as long as the SSL application code can be reached,\nthe distribution starts. The `-pa` method is only recommended for testing\npurposes.\n\n> #### Note {: .info }\n>\n> The clone of the SSL application must enable the use of the SSL code in such\n> an early bootstage as needed to set up the distribution. However, this makes\n> it impossible to soft upgrade the SSL application.","title":"Building Boot Scripts Including the SSL Application - Erlang Distribution over TLS","ref":"ssl_distribution.html#building-boot-scripts-including-the-ssl-application"},{"type":"extras","doc":"The distribution module for TLS is named `inet_tls_dist` and is specified on the\ncommand line with option `-proto_dist`. The argument to `-proto_dist` is to be\nthe module name without suffix `_dist`. So, this distribution module is\nspecified with `-proto_dist inet_tls` on the command line.\n\nExtending the command line gives the following:\n\n```text\n$ erl -boot /home/me/ssl/start_ssl -proto_dist inet_tls\n```\n\nFor the distribution to be started, give the emulator a name as well:\n\n```text\n$ erl -boot /home/me/ssl/start_ssl -proto_dist inet_tls -sname ssl_test\nErlang (BEAM) emulator version 5.0 [source]\n\nEshell V5.0 (abort with ^G)\n(ssl_test@myhost)1>\n```\n\nHowever, a node started in this way refuses to talk to other nodes, as no TLS\nparameters are supplied (see the next section).","title":"Specifying Distribution Module for net_kernel - Erlang Distribution over TLS","ref":"ssl_distribution.html#specifying-distribution-module-for-net_kernel"},{"type":"extras","doc":"The TLS distribution options can be written into a file that is consulted when\nthe node is started. This file name is then specified with the command line\nargument `-ssl_dist_optfile`.\n\nAny available TLS option can be specified in an options file.\n\n> #### Note {: .info }\nOptions that take a `fun()` has to use the syntax `fun Mod:Func/Arity` since a\nfunction body cannot be compiled when consulting a file. Also the encoding\nof the file can be specified as defined by module `m:epp`.\n\n> #### Warning {: .warning }\nDo not tamper with the socket options `list`, `binary`, `active`, `packet`,\n`nodelay` and `deliver` since they are used by the distribution protocol handler\nitself. Other raw socket options such as `packet_size` may interfere severely,\nso beware\\!\n\nFor TLS to work, at least a public key and a certificate must be specified for\nthe server side and the client needs to specify CAs that it trusts (client certification\nis optional and requires more configuration).\n\nIn the following example (to keep it simple), the PEM file `\"/home/me/ssl/erlserver.pem\"`\ncontains both the server certificate and its private key .\n\nCreate a file named for example `\"/home/me/ssl/ssl_test@myhost.conf\"`:\n\n```erlang\n[{server,\n [{certfile, \"/home/me/ssl/erlserver.pem\"}]},\n {client,\n [{cacertfile, \"/home/me/ssl/client_trusted.pem\"}]}].\n```\n\nAnd then start the node like this (line breaks in the command are for\nreadability, and shall not be there when typed):\n\n```text\n$ erl -boot /home/me/ssl/start_ssl -proto_dist inet_tls\n -ssl_dist_optfile \"/home/me/ssl/ssl_test@myhost.conf\"\n -sname ssl_test\n```\n\nThe options in the `{server, Opts}` tuple are used when calling\n`ssl:handshake/3`, and the options in the `{client, Opts}` tuple are used when\ncalling `ssl:connect/4`.\n\nFor the client, the option `{server_name_indication, atom_to_list(TargetNode)}`\nis added when connecting. This makes it possible to use the client option\n`{verify, verify_peer}`, and the client will verify that the certificate matches\nthe node name you are connecting to. This only works if the the server\ncertificate is issued to the name\n[`atom_to_list(TargetNode)`](`atom_to_list/1`).\n\nFor the server it is also possible to use the option `{verify, verify_peer}` and\nthe server will only accept client connections with certificates that are\ntrusted by a root certificate that the server knows. A client that presents an\nuntrusted certificate will be rejected. This option is preferably combined with\n`{fail_if_no_peer_cert, true}` or a client will still be accepted if it does not\npresent any certificate.\n\nA node started in this way is fully functional, using TLS as the distribution\nprotocol.","title":"Specifying TLS Options - Erlang Distribution over TLS","ref":"ssl_distribution.html#specifying-tls-options"},{"type":"extras","doc":"It is possible to use TLS distribution over IPv6 instead of IPv4. To do this,\npass the option `-proto_dist inet6_tls` instead of `-proto_dist inet_tls` when\nstarting Erlang, either on the command line or in the `ERL_FLAGS` environment\nvariable.\n\nAn example command line with this option would look like this:\n\n```text\n$ erl -boot /home/me/ssl/start_ssl -proto_dist inet6_tls\n -ssl_dist_optfile \"/home/me/ssl/ssl_test@myhost.conf\"\n -sname ssl_test\n```\n\nA node started in this way will only be able to communicate with other nodes\nusing TLS distribution over IPv6.","title":"Using TLS distribution over IPv6 - Erlang Distribution over TLS","ref":"ssl_distribution.html#using-tls-distribution-over-ipv6"},{"type":"extras","doc":"> #### Note {: .info }\n> The following section describes TLS Option handling prior to OTP 20.2\n> and can only handle a small subset of the actual available options.\n> It is here only for the sake of backwards compatibility .\n\nAs in the previous section the PEM file `\"/home/me/ssl/erlserver.pem\"` contains\nboth the server certificate and its private key.\n\nOn the `erl` command line you can specify options that the TLS distribution adds\nwhen creating a socket.\n\nThe simplest TLS options in the following list can be specified by adding the\nprefix `server_` or `client_` to the option name:\n\n- `certfile`\n- `keyfile`\n- `password`\n- `cacertfile`\n- `verify`\n- `verify_fun` (write as `{Module, Function, InitialUserState}`)\n- `crl_check`\n- `crl_cache` (write as Erlang term)\n- `reuse_sessions`\n- `secure_renegotiate`\n- `depth`\n- `hibernate_after`\n- `ciphers` (use old string format)\n\nNote that `verify_fun` needs to be written in a different form than the\ncorresponding TLS option, since funs are not accepted on the command line.\n\nThe server can also take the options `dhfile` and `fail_if_no_peer_cert` (also\nprefixed).\n\n`client_`\\-prefixed options are used when the distribution initiates a\nconnection to another node. `server_`\\-prefixed options are used when accepting\na connection from a remote node.\n\nRaw socket options, such as `packet` and `size` must not be specified on the\ncommand line.\n\nThe command-line argument for specifying the TLS options is named\n`-ssl_dist_opt` and is to be followed by pairs of SSL options and their values.\nArgument `-ssl_dist_opt` can be repeated any number of times.\n\nAn example command line doing the same as the example in the previous section\ncan now look as follows (line breaks in the command are for readability, and\nshall not be there when typed):\n\n```text\n$ erl -boot /home/me/ssl/start_ssl -proto_dist inet_tls\n -ssl_dist_opt server_certfile \"/home/me/ssl/erlserver.pem\"\n -ssl_dist_opt server_secure_renegotiate true client_secure_renegotiate true\n -sname ssl_test\nErlang (BEAM) emulator version 5.0 [source]\n\nEshell V5.0 (abort with ^G)\n(ssl_test@myhost)1>\n```","title":"Specifying TLS Options (Legacy) - Erlang Distribution over TLS","ref":"ssl_distribution.html#specifying-tls-options-legacy"},{"type":"extras","doc":"A convenient way to specify arguments to Erlang is to use environment variable\n`ERL_FLAGS`. All the flags needed to use the TLS distribution can be specified\nin that variable and are then interpreted as command-line arguments for all\nsubsequent invocations of Erlang.\n\nIn a Unix (Bourne) shell, it can look as follows (line breaks are for\nreadability, they are not to be there when typed):\n\n```erlang\n$ ERL_FLAGS=\"-boot /home/me/ssl/start_ssl -proto_dist inet_tls\n -ssl_dist_opt server_certfile /home/me/ssl/erlserver.pem\n -ssl_dist_opt server_secure_renegotiate true client_secure_renegotiate true\"\n$ export ERL_FLAGS\n$ erl -sname ssl_test\nErlang (BEAM) emulator version 5.0 [source]\n\nEshell V5.0 (abort with ^G)\n(ssl_test@myhost)1> init:get_arguments().\n[{root,[\"/usr/local/erlang\"]},\n {progname,[\"erl \"]},\n {sname,[\"ssl_test\"]},\n {boot,[\"/home/me/ssl/start_ssl\"]},\n {proto_dist,[\"inet_tls\"]},\n {ssl_dist_opt,[\"server_certfile\",\"/home/me/ssl/erlserver.pem\"]},\n {ssl_dist_opt,[\"server_secure_renegotiate\",\"true\",\n \"client_secure_renegotiate\",\"true\"]\n {home,[\"/home/me\"]}]\n```\n\nThe `init:get_arguments()` call verifies that the correct arguments are supplied\nto the emulator.","title":"Setting up Environment to Always Use TLS - Erlang Distribution over TLS","ref":"ssl_distribution.html#setting-up-environment-to-always-use-tls"},{"type":"extras","doc":"\n# Standards Compliance","title":"Standards Compliance","ref":"standards_compliance.html"},{"type":"extras","doc":"This section describes the current state of standards compliance of the ssl\napplication.","title":"Purpose - Standards Compliance","ref":"standards_compliance.html#purpose"},{"type":"extras","doc":"- For security reasons RSA key exchange cipher suites are no longer supported by\n default, but can be configured. (OTP 21)\n- For security reasons DES cipher suites are no longer supported by default, but\n can be configured. (OTP 20)\n- For security reasons 3DES cipher suites are no longer supported by default,\n but can be configured. (OTP 21)\n- Renegotiation Indication Extension\n [RFC 5746](http://www.ietf.org/rfc/rfc5746.txt) is supported\n- Ephemeral Diffie-Hellman cipher suites are supported, but not Diffie Hellman\n Certificates cipher suites.\n- Elliptic Curve cipher suites are supported if the Crypto application supports\n it and named curves are used.\n- Export cipher suites are not supported as the U.S. lifted its export\n restrictions in early 2000.\n- IDEA cipher suites are not supported as they have become deprecated by the TLS\n 1.2 specification so it is not motivated to implement them.\n- Compression is not supported.\n- It is possible to use Pre-Shared Key (PSK) and Secure Remote Password (SRP)\n cipher suites, but they are not enabled by default and need addition configuration.","title":"Common (prior to TLS 1.3) - Standards Compliance","ref":"standards_compliance.html#common-prior-to-tls-1-3"},{"type":"extras","doc":"- CRL validation is supported.\n- Policy certificate extensions are supported. (OTP 27)\n- 'Server Name Indication' extension\n ([RFC 6066](http://www.ietf.org/rfc/rfc6066.txt)) is supported.\n- Application Layer Protocol Negotiation (ALPN) and its successor Next Protocol\n Negotiation (NPN) are supported.","title":"Common - Standards Compliance","ref":"standards_compliance.html#common"},{"type":"extras","doc":"For security reasons SSL-2.0 is not supported. Interoperability with SSL-2.0\nenabled clients dropped. (OTP 21)","title":"SSL 2.0 - Standards Compliance","ref":"standards_compliance.html#ssl-2-0"},{"type":"extras","doc":"For security reasons SSL-3.0 is no longer supported at all. (OTP 23)\n\nFor security reasons SSL-3.0 is no longer supported by default, but can be\nconfigured. (OTP 19)","title":"SSL 3.0 - Standards Compliance","ref":"standards_compliance.html#ssl-3-0"},{"type":"extras","doc":"For security reasons TLS-1.0 is no longer supported by default, but can be\nconfigured. (OTP 22)","title":"TLS 1.0 - Standards Compliance","ref":"standards_compliance.html#tls-1-0"},{"type":"extras","doc":"For security reasons TLS-1.1 is no longer supported by default, but can be\nconfigured. (OTP 22)","title":"TLS 1.1 - Standards Compliance","ref":"standards_compliance.html#tls-1-1"},{"type":"extras","doc":"Supported","title":"TLS 1.2 - Standards Compliance","ref":"standards_compliance.html#tls-1-2"},{"type":"extras","doc":"For security reasons DTLS-1.0 (based on TLS 1.1) is no longer supported by\ndefault, but can be configured. (OTP 22)","title":"DTLS 1.0 - Standards Compliance","ref":"standards_compliance.html#dtls-1-0"},{"type":"extras","doc":"Supported (based on TLS 1.2)","title":"DTLS 1.2 - Standards Compliance","ref":"standards_compliance.html#dtls-1-2"},{"type":"extras","doc":"Not yet supported","title":"DTLS 1.3 - Standards Compliance","ref":"standards_compliance.html#dtls-1-3"},{"type":"extras","doc":"OTP-22 introduces support for TLS 1.3. The current implementation supports a\nselective set of cryptographic algorithms:\n\n- Key Exchange: ECDHE groups supported by default\n- Groups: all standard groups supported for the Diffie-Hellman key exchange\n- Groups: Support brainpool groups from RFC 8734\n- Ciphers: all mandatory cipher suites are supported\n- Signature Algorithms: All algorithms form RFC 8446\n- Certificates: RSA, ECDSA and EDDSA keys\n\nOther notable features:\n\n- PSK and session resumption is supported (stateful and stateless tickets)\n- Anti-replay protection using Bloom-filters with stateless tickets\n- Early data and 0-RTT is supported\n- Key and Initialization Vector Update is supported\n\nFor more detailed information see the\n[Standards Compliance](standards_compliance.md#soc_table) below.\n\nThe following table describes the current state of standards compliance for TLS\n1.3.\n\n(_C_ = Compliant, _NC_ = Non-Compliant, _PC_ = Partially-Compliant, _NA_ = Not\nApplicable)\n\n[](){: #soc_table }\n\n| _Section_ | _Feature_ | _State_ | _Since_ |\n| --------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------- |\n| [1\\.3. Updates Affecting TLS 1.2](https://tools.ietf.org/html/rfc8446#section-1.2) | | _C_ | _24\\.1_ |\n| | Version downgrade protection mechanism | _C_ | _22_ |\n| | RSASSA-PSS signature schemes | _C_ | _24\\.1_ |\n| | supported_versions (ClientHello) extension | _C_ | _22_ |\n| | signature_algorithms_cert extension | _C_ | _24\\.1_ |\n| [2\\. Protocol Overview](https://tools.ietf.org/html/rfc8446#section/2) | | _PC_ | _22_ |\n| | (EC)DHE | _C_ | _22_ |\n| | PSK-only | _NC_ | |\n| | PSK with (EC)DHE | _C_ | _22\\.2_ |\n| [2\\.1. Incorrect DHE share](https://tools.ietf.org/html/rfc8446#section-2.1) | HelloRetryRequest | _C_ | _22_ |\n| [2\\.2. Resumption and Pre-Shared Key (PSK)](https://tools.ietf.org/html/rfc8446#section-2.2) | | _C_ | _22\\.2_ |\n| [2\\.3. 0-RTT Data](https://tools.ietf.org/html/rfc8446#section-2.3) | | _PC_ | _23\\.3_ |\n| [4\\.1.1. Cryptographic Negotiation](https://tools.ietf.org/html/rfc8446#section-4.1.1) | | _C_ | _22\\.2_ |\n| | supported_groups extension | _C_ | _22_ |\n| | signature_algorithms extension | _C_ | _22_ |\n| | pre_shared_key extension | _C_ | _22\\.2_ |\n| [4\\.1.2. Client Hello](https://tools.ietf.org/html/rfc8446#section-4.1.2) | _Client_ | _PC_ | _22\\.1_ |\n| | server_name (RFC6066) | _C_ | _23\\.2_ |\n| | max_fragment_length (RFC6066) | _C_ | _23\\.0_ |\n| | status_request (RFC6066) | _C_ | _27\\.0_ |\n| | supported_groups (RFC7919) | _C_ | _22\\.1_ |\n| | signature_algorithms (RFC8446) | _C_ | _22\\.1_ |\n| | use_srtp (RFC5764) | _C_ | 26\\.0 |\n| | heartbeat (RFC6520) | _NC_ | |\n| | application_layer_protocol_negotiation (RFC7301) | _C_ | _22\\.1_ |\n| | signed_certificate_timestamp (RFC6962) | _NC_ | |\n| | client_certificate_type (RFC7250) | _NC_ | |\n| | server_certificate_type (RFC7250) | _NC_ | |\n| | padding (RFC7685) | _NC_ | |\n| | key_share (RFC8446) | _C_ | _22\\.1_ |\n| | pre_shared_key (RFC8446) | _C_ | _22\\.2_ |\n| | psk_key_exchange_modes (RFC8446) | _C_ | _22\\.2_ |\n| | early_data (RFC8446) | _C_ | _23\\.3_ |\n| | cookie (RFC8446) | _C_ | _23\\.1_ |\n| | supported_versions (RFC8446) | _C_ | _22\\.1_ |\n| | certificate_authorities (RFC8446) | _C_ | 24\\.3 |\n| | oid_filters (RFC8446) | _NC_ | |\n| | post_handshake_auth (RFC8446) | _NC_ | |\n| | signature_algorithms_cert (RFC8446) | _C_ | _22\\.1_ |\n| | _Server_ | _PC_ | _22_ |\n| | server_name (RFC6066) | _C_ | _23\\.2_ |\n| | max_fragment_length (RFC6066) | _C_ | _23\\.0_ |\n| | status_request (RFC6066) | _NC_ | |\n| | supported_groups (RFC7919) | _C_ | _22_ |\n| | signature_algorithms (RFC8446) | _C_ | _22_ |\n| | use_srtp (RFC5764) | _C_ | 26\\.0 |\n| | heartbeat (RFC6520) | _NC_ | |\n| | application_layer_protocol_negotiation (RFC7301) | _C_ | _22\\.1_ |\n| | signed_certificate_timestamp (RFC6962) | _NC_ | |\n| | client_certificate_type (RFC7250) | _NC_ | |\n| | server_certificate_type (RFC7250) | _NC_ | |\n| | padding (RFC7685) | _NC_ | |\n| | key_share (RFC8446) | _C_ | _22_ |\n| | pre_shared_key (RFC8446) | _C_ | _22\\.2_ |\n| | psk_key_exchange_modes (RFC8446) | _C_ | _22\\.2_ |\n| | early_data (RFC8446) | _C_ | _23\\.3_ |\n| | cookie (RFC8446) | _C_ | _23\\.1_ |\n| | supported_versions (RFC8446) | _C_ | _22_ |\n| | oid_filters (RFC8446) | _NC_ | |\n| | post_handshake_auth (RFC8446) | _NC_ | |\n| | signature_algorithms_cert (RFC8446) | _C_ | _22_ |\n| [4\\.1.3. Server Hello](https://tools.ietf.org/html/rfc8446#section-4.1.3) | _Client_ | _C_ | _22\\.2_ |\n| | Version downgrade protection | _C_ | _22\\.1_ |\n| | key_share (RFC8446) | _C_ | _22\\.1_ |\n| | pre_shared_key (RFC8446) | _C_ | _22\\.2_ |\n| | supported_versions (RFC8446) | _C_ | _22\\.1_ |\n| | use_srtp (RFC5764) | _C_ | 26\\.0 |\n| | _Server_ | _C_ | _22\\.2_ |\n| | Version downgrade protection | _C_ | _22_ |\n| | key_share (RFC8446) | _C_ | _22_ |\n| | pre_shared_key (RFC8446) | _C_ | _22\\.2_ |\n| | supported_versions (RFC8446) | _C_ | _22_ |\n| | use_srtp (RFC5764) | _C_ | 26\\.0 |\n| [4\\.1.4. Hello Retry Request](https://tools.ietf.org/html/rfc8446#section-4.1.4) | _Server_ | _C_ | _22_ |\n| | key_share (RFC8446) | _C_ | _22_ |\n| | cookie (RFC8446) | _C_ | _23\\.1_ |\n| | supported_versions (RFC8446) | _C_ | _22_ |\n| [4\\.2.1. Supported Versions](https://tools.ietf.org/html/rfc8446#section-4.2.1) | _Client_ | _C_ | _22\\.1_ |\n| | _Server_ | _C_ | _22_ |\n| [4\\.2.2. Cookie](https://tools.ietf.org/html/rfc8446#section-4.2.2) | _Client_ | _C_ | _23\\.1_ |\n| | _Server_ | _C_ | _23\\.1_ |\n| [4\\.2.3. Signature Algorithms](https://tools.ietf.org/html/rfc8446#section-4.2.3) | _Client_ | _C_ | _24_ |\n| | rsa_pkcs1_sha256 | _C_ | _22\\.1_ |\n| | rsa_pkcs1_sha384 | _C_ | _22\\.1_ |\n| | rsa_pkcs1_sha512 | _C_ | _22\\.1_ |\n| | ecdsa_secp256r1_sha256 | _C_ | _22\\.1_ |\n| | ecdsa_secp384r1_sha384 | _C_ | _22\\.1_ |\n| | ecdsa_secp521r1_sha512 | _C_ | _22\\.1_ |\n| | rsa_pss_rsae_sha256 | _C_ | _22\\.1_ |\n| | rsa_pss_rsae_sha384 | _C_ | _22\\.1_ |\n| | rsa_pss_rsae_sha512 | _C_ | _22\\.1_ |\n| | ed25519 | _C_ | _24_ |\n| | ed448 | _C_ | _24_ |\n| | rsa_pss_pss_sha256 | _C_ | _23_ |\n| | rsa_pss_pss_sha384 | _C_ | _23_ |\n| | rsa_pss_pss_sha512 | _C_ | _23_ |\n| | rsa_pkcs1_sha1 | _C_ | _22\\.1_ |\n| | ecdsa_sha1 | _C_ | _22\\.1_ |\n| | _Server_ | _C_ | _24_ |\n| | rsa_pkcs1_sha256 | _C_ | _22_ |\n| | rsa_pkcs1_sha384 | _C_ | _22_ |\n| | rsa_pkcs1_sha512 | _C_ | _22_ |\n| | ecdsa_secp256r1_sha256 | _C_ | _22\\.1_ |\n| | ecdsa_secp384r1_sha384 | _C_ | _22\\.1_ |\n| | ecdsa_secp521r1_sha512 | _C_ | _22\\.1_ |\n| | rsa_pss_rsae_sha256 | _C_ | _22_ |\n| | rsa_pss_rsae_sha384 | _C_ | _22_ |\n| | rsa_pss_rsae_sha512 | _C_ | _22_ |\n| | ed25519 | _C_ | _24_ |\n| | ed448 | _C_ | _24_ |\n| | rsa_pss_pss_sha256 | _C_ | _23_ |\n| | rsa_pss_pss_sha384 | _C_ | _23_ |\n| | rsa_pss_pss_sha512 | _C_ | _23_ |\n| | rsa_pkcs1_sha1 | _C_ | _22_ |\n| | ecdsa_sha1 | _C_ | _22_ |\n| [4\\.2.4. Certificate Authorities](https://tools.ietf.org/html/rfc8446#section-4.2.4) | _Client_ | _C_ | 24\\.3 |\n| | _Server_ | _C_ | _24\\.3_ |\n| [4\\.2.5. OID Filters](https://tools.ietf.org/html/rfc8446#section-4.2.5) | _Client_ | _NC_ | |\n| | _Server_ | _NC_ | |\n| [4\\.2.6. Post-Handshake Client Authentication](https://tools.ietf.org/html/rfc8446#section-4.2.6) | _Client_ | _NC_ | |\n| | _Server_ | _NC_ | |\n| [4\\.2.7. Supported Groups](https://tools.ietf.org/html/rfc8446#section-4.2.7) | _Client_ | _C_ | _22\\.1_ |\n| | secp256r1 | _C_ | _22\\.1_ |\n| | secp384r1 | _C_ | _22\\.1_ |\n| | secp521r1 | _C_ | _22\\.1_ |\n| | x25519 | _C_ | _22\\.1_ |\n| | x448 | _C_ | _22\\.1_ |\n| | ffdhe2048 | _C_ | _22\\.1_ |\n| | ffdhe3072 | _C_ | _22\\.1_ |\n| | ffdhe4096 | _C_ | _22\\.1_ |\n| | ffdhe6144 | _C_ | _22\\.1_ |\n| | ffdhe8192 | _C_ | _22\\.1_ |\n| | _Server_ | _C_ | _22_ |\n| | secp256r1 | _C_ | _22_ |\n| | secp384r1 | _C_ | _22_ |\n| | secp521r1 | _C_ | _22_ |\n| | x25519 | _C_ | _22_ |\n| | x448 | _C_ | _22_ |\n| | ffdhe2048 | _C_ | _22_ |\n| | ffdhe3072 | _C_ | _22_ |\n| | ffdhe4096 | _C_ | _22_ |\n| | ffdhe6144 | _C_ | _22_ |\n| | ffdhe8192 | _C_ | _22_ |\n| [4\\.2.8. Key Share](https://tools.ietf.org/html/rfc8446#section-4.2.8) | _Client_ | _C_ | _22\\.1_ |\n| | _Server_ | _C_ | _22_ |\n| [4\\.2.9. Pre-Shared Key Exchange Modes](https://tools.ietf.org/html/rfc8446#section-4.2.9) | _Client_ | _C_ | _22\\.2_ |\n| | _Server_ | _C_ | _22\\.2_ |\n| [4\\.2.10. Early Data Indication](https://tools.ietf.org/html/rfc8446#section-4.2.10) | _Client_ | _C_ | _23\\.3_ |\n| | _Server_ | _C_ | _23\\.3_ |\n| [4\\.2.11. Pre-Shared Key Extension](https://tools.ietf.org/html/rfc8446#section-4.2.11) | _Client_ | _C_ | _22\\.2_ |\n| | _Server_ | _C_ | _22\\.2_ |\n| [4\\.2.11.1. Ticket Age](https://tools.ietf.org/html/rfc8446#section-4.2.11.1) | _Client_ | _C_ | _22\\.2_ |\n| | _Server_ | _C_ | _22\\.2_ |\n| [4\\.2.11.2. PSK Binder](https://tools.ietf.org/html/rfc8446#section-4.2.11.2) | _Client_ | _C_ | _22\\.2_ |\n| | _Server_ | _C_ | _22\\.2_ |\n| [4\\.2.11.3. Processing Order](https://tools.ietf.org/html/rfc8446#section-4.2.11.3) | _Client_ | _NC_ | |\n| | _Server_ | _NC_ | |\n| [4\\.3.1. Encrypted Extensions](https://tools.ietf.org/html/rfc8446#section-4.3.1) | _Client_ | _PC_ | _22\\.1_ |\n| | server_name (RFC6066) | _C_ | _23\\.2_ |\n| | max_fragment_length (RFC6066) | _C_ | _23\\.0_ |\n| | supported_groups (RFC7919) | _NC_ | |\n| | use_srtp (RFC5764) | _NC_ | |\n| | heartbeat (RFC6520) | _NC_ | |\n| | application_layer_protocol_negotiation (RFC7301) | _C_ | 23\\.0 |\n| | client_certificate_type (RFC7250) | _NC_ | |\n| | server_certificate_type (RFC7250) | _NC_ | |\n| | early_data (RFC8446) | _C_ | _23\\.3_ |\n| | _Server_ | _PC_ | _22_ |\n| | server_name (RFC6066) | _C_ | _23\\.2_ |\n| | max_fragment_length (RFC6066) | _C_ | _23\\.0_ |\n| | supported_groups (RFC7919) | _NC_ | |\n| | use_srtp (RFC5764) | _NC_ | |\n| | heartbeat (RFC6520) | _NC_ | |\n| | application_layer_protocol_negotiation (RFC7301) | _C_ | 23\\.0 |\n| | client_certificate_type (RFC7250) | _NC_ | |\n| | server_certificate_type (RFC7250) | _NC_ | |\n| | early_data (RFC8446) | _C_ | _23\\.3_ |\n| [4\\.3.2. Certificate Request](https://tools.ietf.org/html/rfc8446#section-4.3.2) | _Client_ | _PC_ | _22\\.1_ |\n| | status_request (RFC6066) | _NC_ | |\n| | signature_algorithms (RFC8446) | _C_ | _22\\.1_ |\n| | signed_certificate_timestamp (RFC6962) | _NC_ | |\n| | certificate_authorities (RFC8446) | _C_ | 24\\.3 |\n| | oid_filters (RFC8446) | _NC_ | |\n| | signature_algorithms_cert (RFC8446) | _C_ | _22\\.1_ |\n| | _Server_ | _PC_ | _22_ |\n| | status_request (RFC6066) | _NC_ | |\n| | signature_algorithms (RFC8446) | _C_ | _22_ |\n| | signed_certificate_timestamp (RFC6962) | _NC_ | |\n| | certificate_authorities (RFC8446) | _C_ | 24\\.3 |\n| | oid_filters (RFC8446) | _NC_ | |\n| | signature_algorithms_cert (RFC8446) | _C_ | _22_ |\n| [4\\.4.1. The Transcript Hash](https://tools.ietf.org/html/rfc8446#section-4.4.1) | | _C_ | _22_ |\n| [4\\.4.2. Certificate](https://tools.ietf.org/html/rfc8446#section-4.4.2) | _Client_ | _PC_ | _22\\.1_ |\n| | Arbitrary certificate chain orderings | _C_ | _22\\.2_ |\n| | Extraneous certificates in chain | _C_ | _23\\.2_ |\n| | status_request (RFC6066) | _C_ | 27\\.0 |\n| | signed_certificate_timestamp (RFC6962) | _NC_ | |\n| | _Server_ | _PC_ | _22_ |\n| | status_request (RFC6066) | _NC_ | |\n| | signed_certificate_timestamp (RFC6962) | _NC_ | |\n| [4\\.4.2.1. OCSP Status and SCT Extensions](https://tools.ietf.org/html/rfc8446#section-4.4.2.1) | _Client_ | _PC_ | _27\\.0_ |\n| | _Server_ | _NC_ | |\n| [4\\.4.2.2. Server Certificate Selection](https://tools.ietf.org/html/rfc8446#section-4.4.2.2) | | _C_ | _24\\.3_ |\n| | The certificate type MUST be X.509v3, unless explicitly negotiated otherwise | _C_ | _22_ |\n| | The server's end-entity certificate's public key (and associated restrictions) MUST be compatible with the selected authentication algorithm from the client's \"signature_algorithms\" extension (currently RSA, ECDSA, or EdDSA). | _C_ | _22_ |\n| | The certificate MUST allow the key to be used for signing with a signature scheme indicated in the client's \"signature_algorithms\"/\"signature_algorithms_cert\" extensions | _C_ | _22_ |\n| | The \"server_name\" and \"certificate_authorities\" extensions are used to guide certificate selection. As servers MAY require the presence of the \"server_name\" extension, clients SHOULD send this extension, when applicable. | _C_ | _24\\.3_ |\n| [4\\.4.2.3. Client Certificate Selection](https://tools.ietf.org/html/rfc8446#section-4.4.2.3) | | _PC_ | _22\\.1_ |\n| | The certificate type MUST be X.509v3, unless explicitly negotiated otherwise | _C_ | _22\\.1_ |\n| | If the \"certificate_authorities\" extension in the CertificateRequest message was present, at least one of the certificates in the certificate chain SHOULD be issued by one of the listed CAs. | _C_ | _24\\.3_ |\n| | The certificates MUST be signed using an acceptable signature algorithm | _C_ | _22\\.1_ |\n| | If the CertificateRequest message contained a non-empty \"oid_filters\" extension, the end-entity certificate MUST match the extension OIDs that are recognized by the client | _NC_ | |\n| [4\\.4.2.4. Receiving a Certificate Message](https://tools.ietf.org/html/rfc8446#section-4.4.2.4) | _Client_ | _C_ | _22\\.1_ |\n| | _Server_ | _C_ | _22_ |\n| [4\\.4.3. Certificate Verify](https://tools.ietf.org/html/rfc8446#section-4.4.3) | _Client_ | _C_ | _22\\.1_ |\n| | _Server_ | _C_ | _22_ |\n| [4\\.4.4. Finished](https://tools.ietf.org/html/rfc8446#section-4.4.4) | _Client_ | _C_ | _22\\.1_ |\n| | _Server_ | _C_ | _22_ |\n| [4\\.5. End of Early Data](https://tools.ietf.org/html/rfc8446#section-4.5) | _Client_ | _C_ | _23\\.3_ |\n| | _Server_ | _C_ | _23\\.3_ |\n| [4\\.6.1. New Session Ticket Message](https://tools.ietf.org/html/rfc8446#section-4.6.1) | _Client_ | _C_ | _23\\.3_ |\n| | early_data (RFC8446) | _C_ | _23\\.3_ |\n| | _Server_ | _C_ | _23\\.3_ |\n| | early_data (RFC8446) | _C_ | _23\\.3_ |\n| [4\\.6.2. Post-Handshake Authentication](https://tools.ietf.org/html/rfc8446#section-4.6.2) | _Client_ | _NC_ | |\n| | _Server_ | _NC_ | |\n| [4\\.6.3. Key and Initialization Vector Update](https://tools.ietf.org/html/rfc8446#section-4.6.3) | _Client_ | _C_ | _22\\.3_ |\n| | _Server_ | _C_ | _22\\.3_ |\n| [5\\.1. Record Layer](https://tools.ietf.org/html/rfc8446#section-5.1) | | _C_ | _22_ |\n| | MUST NOT be interleaved with other record types | _C_ | _22_ |\n| | MUST NOT span key changes | _C_ | _22_ |\n| | MUST NOT send zero-length fragments | _C_ | _22_ |\n| | Alert messages MUST NOT be fragmented | _C_ | _22_ |\n| [5\\.2. Record Payload Protection](https://tools.ietf.org/html/rfc8446#section-5.2) | | _C_ | _22_ |\n| [5\\.3. Per-Record Nonce](https://tools.ietf.org/html/rfc8446#section-5.3) | | _C_ | _22_ |\n| [5\\.4. Record Padding](https://tools.ietf.org/html/rfc8446#section-5.4) | | _PC_ | _22_ |\n| | MAY choose to pad | _NC_ | |\n| | MUST NOT send Handshake and Alert records that have a zero-length TLSInnerPlaintext.content | _NC_ | |\n| | The padding sent is automatically verified | _C_ | _22_ |\n| [5\\.5. Limits on Key Usage](https://tools.ietf.org/html/rfc8446#section-5.5) | | _C_ | _22\\.3_ |\n| [6\\.1. Closure Alerts](https://tools.ietf.org/html/rfc8446#section-6.1) | | _22_ | |\n| | close_notify | _C_ | _22_ | |\n| | user_cancelled | _C_ | _22_ | |\n| [6\\.2. Error Alerts](https://tools.ietf.org/html/rfc8446#section-6.2) | | _PC_ | _22_ |\n| [7\\.1. Key Schedule](https://tools.ietf.org/html/rfc8446#section-7.1) | | _C_ | _22_ |\n| [7\\.2. Updating Traffic Secrets](https://tools.ietf.org/html/rfc8446#section-7.2) | | _C_ | _22_ |\n| [7\\.3. Traffic Key Calculation](https://tools.ietf.org/html/rfc8446#section-7.3) | | _C_ | _22_ |\n| [7\\.5. Exporters](https://tools.ietf.org/html/rfc8446#section-7.5) | | _PC_ | _26\\.3_ |\n| [8\\. 0-RTT and Anti-Replay](https://tools.ietf.org/html/rfc8446#section/8) | | _C_ | _22\\.2_ |\n| [8\\.1. Single-Use Tickets](https://tools.ietf.org/html/rfc8446#section-8.1) | | _C_ | _22\\.2_ |\n| [8\\.2. Client Hello Recording](https://tools.ietf.org/html/rfc8446#section-8.2) | | _C_ | _22\\.2_ |\n| [8\\.3. Freshness Checks](https://tools.ietf.org/html/rfc8446#section-8.3) | | _C_ | _22\\.2_ |\n| [9\\.1. Mandatory-to-Implement Cipher Suites](https://tools.ietf.org/html/rfc8446#section-9.1) | | _C_ | _22\\.1_ |\n| | MUST implement the TLS_AES_128_GCM_SHA256 | _C_ | _22_ |\n| | SHOULD implement the TLS_AES_256_GCM_SHA384 | _C_ | _22_ |\n| | SHOULD implement the TLS_CHACHA20_POLY1305_SHA256 | _C_ | _22_ |\n| | _Digital signatures_ | _C_ | _22\\.1_ |\n| | MUST support rsa_pkcs1_sha256 (for certificates) | _C_ | _22_ |\n| | MUST support rsa_pss_rsae_sha256 (for CertificateVerify and certificates) | _C_ | _22_ |\n| | MUST support ecdsa_secp256r1_sha256 | _C_ | _22\\.1_ |\n| | _Key Exchange_ | _C_ | _22_ |\n| | MUST support key exchange with secp256r1 | _C_ | _22_ |\n| | SHOULD support key exchange with X25519 | _C_ | _22_ |\n| [9\\.2. Mandatory-to-Implement Extensions](https://tools.ietf.org/html/rfc8446#section-9.2) | | _C_ | _23\\.2_ |\n| | Supported Versions | _C_ | _22_ |\n| | Cookie | _C_ | _23\\.1_ |\n| | Signature Algorithms | _C_ | _22_ |\n| | Signature Algorithms Certificate | _C_ | _22_ |\n| | Negotiated Groups | _C_ | _22_ |\n| | Key Share | _C_ | _22_ |\n| | Server Name Indication | _C_ | _23\\.2_ |\n| | _MUST send and use these extensions_ | _C_ | _22\\.2_ |\n| | \"supported_versions\" is REQUIRED for ClientHello, ServerHello and HelloRetryRequest | _C_ | _22\\.1_ |\n| | \"signature_algorithms\" is REQUIRED for certificate authentication | _C_ | _22_ |\n| | \"supported_groups\" is REQUIRED for ClientHello messages using (EC)DHE key exchange | _C_ | _22_ |\n| | \"key_share\" is REQUIRED for (EC)DHE key exchange | _C_ | _22_ |\n| | \"pre_shared_key\" is REQUIRED for PSK key agreement | _C_ | _22\\.2_ |\n| | \"psk_key_exchange_modes\" is REQUIRED for PSK key agreement | _C_ | _22\\.2_ |\n| | _TLS 1.3 ClientHello_ | _C_ | _22\\.1_ |\n| | If not containing a \"pre_shared_key\" extension, it MUST contain both a \"signature_algorithms\" extension and a \"supported_groups\" extension. | _C_ | _22\\.1_ |\n| | If containing a \"supported_groups\" extension, it MUST also contain a \"key_share\" extension, and vice versa. An empty KeyShare.client_shares vector is permitted. | _C_ | _22\\.1_ |\n| | _TLS 1.3 ServerHello_ | _C_ | _23\\.2_ |\n| | MUST support the use of the \"server_name\" extension | _C_ | _23\\.2_ |\n| [9\\.3. Protocol Invariants](https://tools.ietf.org/html/rfc8446#section-9.3) | | _C_ | _22\\.1_ |\n| | _MUST correctly handle extensible fields_ | _C_ | _22\\.1_ |\n| | A client sending a ClientHello MUST support all parameters advertised in it. Otherwise, the server may fail to interoperate by selecting one of those parameters. | _C_ | _22\\.1_ |\n| | A server receiving a ClientHello MUST correctly ignore all unrecognized cipher suites, extensions, and other parameters. Otherwise, it may fail to interoperate with newer clients. In TLS 1.3, a client receiving a CertificateRequest or NewSessionTicket MUST also ignore all unrecognized extensions. | _C_ | _22\\.1_ |\n| | A middlebox which terminates a TLS connection MUST behave as a compliant TLS server | _NA_ | |\n| | A middlebox which forwards ClientHello parameters it does not understand MUST NOT process any messages beyond that ClientHello. It MUST forward all subsequent traffic unmodified. Otherwise, it may fail to interoperate with newer clients and servers. | _NA_ | |\n| [B.4. Cipher Suites](https://tools.ietf.org/html/rfc8446#section-B.4) | | _C_ | _23_ |\n| | TLS_AES_128_GCM_SHA256 | _C_ | _22_ |\n| | TLS_AES_256_GCM_SHA384 | _C_ | _22_ |\n| | TLS_CHACHA20_POLY1305_SHA256 | _C_ | _22_ |\n| | TLS_AES_128_CCM_SHA256 | _C_ | _22_ |\n| | TLS_AES_128_CCM_8_SHA256 | _C_ | _23_ |\n| [C.1. Random Number Generation and Seeding](https://tools.ietf.org/html/rfc8446#section-C.1) | | _C_ | _22_ |\n| [C.2. Certificates and Authentication](https://tools.ietf.org/html/rfc8446#section-C.2) | | _C_ | _22_ |\n| [C.3. Implementation Pitfalls](https://tools.ietf.org/html/rfc8446#section-C.3) | | _PC_ | _22_ |\n| [C.4. Client Tracking Prevention](https://tools.ietf.org/html/rfc8446#section-C.4) | | _C_ | _22\\.2_ |\n| [C.5. Unauthenticated Operation](https://tools.ietf.org/html/rfc8446#section-C.5) | | _C_ | _22_ |\n| [D.1. Negotiating with an Older Server](https://tools.ietf.org/html/rfc8446#section-D.1) | | _C_ | _22\\.2_ |\n| [D.2. Negotiating with an Older Client](https://tools.ietf.org/html/rfc8446#section-D.2) | | _C_ | _22_ |\n| [D.3. 0-RTT Backward Compatibility](https://tools.ietf.org/html/rfc8446#section-D.3) | | _NC_ | |\n| [D.4. Middlebox Compatibility Mode](https://tools.ietf.org/html/rfc8446#section-D.4) | | _C_ | _23_ |\n| [D.5. Security Restrictions Related to Backward Compatibility](https://tools.ietf.org/html/rfc8446#section-D.5) | | _C_ | _22_ |\n\n_Table: Standards Compliance_","title":"TLS 1.3 - Standards Compliance","ref":"standards_compliance.html#tls-1-3"}],"content_type":"text/plain","producer":{"name":"ex_doc","version":[48,46,51,52,46,49]}} \ No newline at end of file diff --git a/prs/9045/lib/ssl-11.2.4/doc/html/search.html b/prs/9045/lib/ssl-11.2.4/doc/html/search.html index 8205dcebc8fb..5508840004be 100644 --- a/prs/9045/lib/ssl-11.2.4/doc/html/search.html +++ b/prs/9045/lib/ssl-11.2.4/doc/html/search.html @@ -128,7 +128,7 @@

    - +

    diff --git a/prs/9045/lib/ssl-11.2.4/doc/html/ssl.epub b/prs/9045/lib/ssl-11.2.4/doc/html/ssl.epub index e049bf31b7c8..777d72de21f8 100644 Binary files a/prs/9045/lib/ssl-11.2.4/doc/html/ssl.epub and b/prs/9045/lib/ssl-11.2.4/doc/html/ssl.epub differ diff --git a/prs/9045/lib/ssl-11.2.4/doc/html/ssl.html b/prs/9045/lib/ssl-11.2.4/doc/html/ssl.html index 0390108e1078..7d9750597aca 100644 --- a/prs/9045/lib/ssl-11.2.4/doc/html/ssl.html +++ b/prs/9045/lib/ssl-11.2.4/doc/html/ssl.html @@ -137,9 +137,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.

    @@ -2541,26 +2541,26 @@

    signature_algs()

    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
    @@ -2650,8 +2650,8 @@ 

    anchor_fun()

    -

    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.

    @@ -3103,7 +3103,7 @@

    client_option_cert()

    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 @@ -3247,7 +3247,7 @@

    client_option_tls13()

    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, {SNI, TicketData}}

      where SNI is the ServerNameIndication and TicketData is the extended ticket +information to user process in a 3-tuple:

      {ssl, session_ticket, {SNI, TicketData}}

      where SNI is the ServerNameIndication and TicketData is the extended ticket data that can be used in subsequent session resumptions.

      If it is set to auto, the client automatically handles received tickets and tries to use them when making new TLS connections (session resumption with pre-shared keys).

      Ticket lifetime, the number of tickets sent by the server, and the @@ -3257,7 +3257,7 @@

      client_option_tls13()

      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 @@ -3674,20 +3674,20 @@

      common_option_cert()

      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()}.
      +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()}.
      +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 @@ -3704,25 +3704,25 @@

      common_option_cert()

      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 CA is normally a so-called ROOT CA, which is a self-signed certificate. Trust can be claimed for an intermediate CA (the trusted anchor does not have to be @@ -3863,11 +3863,11 @@

      common_option_pre_tls13()

      enforced. If SecureRenegotiate is false secure renegotiation will still be used if possible, but it falls back to insecure renegotiation if the peer does not support if RFC -5746.

    • {user_lookup_fun, {LookupFun, UserState}} - PSK/SRP cipher suite option

      The lookup fun is to be defined as follows:

      fun(psk, PSKIdentity :: binary(), UserState :: term()) ->
      -  {ok, SharedSecret :: binary()} | error;
      -fun(srp, Username :: binary(), UserState :: term()) ->
      -  {ok, {SRPParams :: srp_param_type(), Salt :: binary(),
      -        DerivedKey :: binary()}} | error.

      For Pre-Shared Key (PSK) cipher suites, the lookup fun is called by the client +5746.

    • {user_lookup_fun, {LookupFun, UserState}} - PSK/SRP cipher suite option

      The lookup fun is to be defined as follows:

      fun(psk, PSKIdentity :: binary(), UserState :: term()) ->
      +  {ok, SharedSecret :: binary()} | error;
      +fun(srp, Username :: binary(), UserState :: term()) ->
      +  {ok, {SRPParams :: srp_param_type(), Salt :: binary(),
      +        DerivedKey :: binary()}} | error.

      For Pre-Shared Key (PSK) cipher suites, the lookup fun is called by the client and server to determine the shared secret. When called by the client, PSKIdentity is the hint presented by the server or undefined. When called by the server, PSKIdentity is the identity presented by the client.

      For Secure Remote Password (SRP), the fun is only used by the server to obtain @@ -4180,8 +4180,8 @@

      connect(TCPSocketOrHost, TLSOptionsOrPort, -

      Opens a TLS/DTLS connection.

      connect(TCPSocket, TLSOptions, Timeout).

      Upgrades a gen_tcp (or equivalent) connected socket to a TLS socket by -performing the client-side TLS handshake.

      connect(Host, Port, TLSOptions).

      Opens a TLS/DTLS connection to Host, Port. This call is equivalent to:

      connect(Host, Port, TLSOptions, infinity).
      +

      Opens a TLS/DTLS connection.

      connect(TCPSocket, TLSOptions, Timeout).

      Upgrades a gen_tcp (or equivalent) connected socket to a TLS socket by +performing the client-side TLS handshake.

      connect(Host, Port, TLSOptions).

      Opens a TLS/DTLS connection to Host, Port. This call is equivalent to:

      connect(Host, Port, TLSOptions, infinity).
      @@ -4317,7 +4317,7 @@

      handshake(HsSocket, OptionsOrTimeout)

      -

      Performs the TLS/DTLS server-side handshake.

      If the second argument is a timeout value:

      handshake(HsSocket, Timeout).

      this call is equivalent to:

      handshake(HsSocket, [], Timeout).

      Otherwise, if the second argument is a list of options:

      handshake(HsSocket, Options).

      this call is equivalent to:

      handshake(HsSocket, Options, infinity).
      +

      Performs the TLS/DTLS server-side handshake.

      If the second argument is a timeout value:

      handshake(HsSocket, Timeout).

      this call is equivalent to:

      handshake(HsSocket, [], Timeout).

      Otherwise, if the second argument is a list of options:

      handshake(HsSocket, Options).

      this call is equivalent to:

      handshake(HsSocket, Options, infinity).
      @@ -5716,35 +5716,35 @@

      signature_algs(Description, Version)

      Lists all available signature algorithms corresponding to Description.

      The exclusive option will exclusively list algorithms or algorithm schemes for that protocol version, whereas the default and all options lists the combined list to support the range of protocols from (D)TLS-1.2, the first -version to support configuration of the signature algorithms, to Version.

      Example:

      1> ssl:signature_algs(default, 'tlsv1.3').
      -[eddsa_ed25519,eddsa_ed448,ecdsa_secp521r1_sha512,
      +version to support configuration of the signature algorithms, to Version.

      Example:

      1> ssl:signature_algs(default, 'tlsv1.3').
      +[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,
       rsa_pkcs1_sha512,rsa_pkcs1_sha384,rsa_pkcs1_sha256,
      -{sha512,ecdsa},
      -{sha384,ecdsa},
      -{sha256,ecdsa}]
      +{sha512,ecdsa},
      +{sha384,ecdsa},
      +{sha256,ecdsa}]
       
      -2> ssl:signature_algs(all, 'tlsv1.3').
      -[eddsa_ed25519,eddsa_ed448,ecdsa_secp521r1_sha512,
      +2> ssl:signature_algs(all, 'tlsv1.3').
      +[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,
       rsa_pkcs1_sha512,rsa_pkcs1_sha384,rsa_pkcs1_sha256,
      -{sha512,ecdsa},
      -{sha384,ecdsa},
      -{sha256,ecdsa},
      -{sha224,ecdsa},
      -{sha224,rsa},
      -{sha,rsa},
      -{sha,dsa}]
      -
      -3> ssl:signature_algs(exclusive, 'tlsv1.3').
      -[eddsa_ed25519,eddsa_ed448,ecdsa_secp521r1_sha512,
      +{sha512,ecdsa},
      +{sha384,ecdsa},
      +{sha256,ecdsa},
      +{sha224,ecdsa},
      +{sha224,rsa},
      +{sha,rsa},
      +{sha,dsa}]
      +
      +3> ssl:signature_algs(exclusive, 'tlsv1.3').
      +[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]

      Note

      Some TLS-1-3 scheme names overlap with TLS-1.2 algorithm-tuple-pair-names and +rsa_pss_rsae_sha512,rsa_pss_rsae_sha384,rsa_pss_rsae_sha256]

      Note

      Some TLS-1-3 scheme names overlap with TLS-1.2 algorithm-tuple-pair-names and then TLS-1.3 names will be used, for example rsa_pkcs1_sha256 instead of {sha256, rsa}. These are legacy algorithms in TLS-1.3 that apply only to certificate signatures in this version of the protocol.

      diff --git a/prs/9045/lib/ssl-11.2.4/doc/html/ssl_distribution.html b/prs/9045/lib/ssl-11.2.4/doc/html/ssl_distribution.html index 6761c46b4d48..f1fae5fa1f25 100644 --- a/prs/9045/lib/ssl-11.2.4/doc/html/ssl_distribution.html +++ b/prs/9045/lib/ssl-11.2.4/doc/html/ssl_distribution.html @@ -153,14 +153,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 @@ -207,10 +207,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 @@ -280,19 +280,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] - -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 +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 to the emulator.

    diff --git a/prs/9045/lib/ssl-11.2.4/doc/html/using_ssl.html b/prs/9045/lib/ssl-11.2.4/doc/html/using_ssl.html index 81966fb8265e..fcdfed07052b 100644 --- a/prs/9045/lib/ssl-11.2.4/doc/html/using_ssl.html +++ b/prs/9045/lib/ssl-11.2.4/doc/html/using_ssl.html @@ -155,38 +155,38 @@

    Basic Client

    -
     1 > ssl:start(), ssl:connect("google.com", 443, [{verify, verify_peer},
    -                                                 {cacerts, public_key:cacerts_get()}]).
    -   {ok,{sslsocket, [...]}}

    +
     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().
    +

    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

    @@ -198,27 +198,27 @@

    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

    @@ -226,34 +226,34 @@

    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}, ...]

    + 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}, ...]

    @@ -271,9 +271,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,
    @@ -281,12 +281,12 @@ 

    %% (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()

    @@ -294,20 +294,20 @@

    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,
    -                [{cacertfile, "cacerts.pem"},
    -                 {certs_keys, [#{certfile => "cert.pem", key => PrivKey}]}
    -                ], infinity).
    +   key_id => "id of the private key in Engine"}.

    Use the map in the ssl key option:

    4> {ok, SSLSocket} =
    + ssl:connect("localhost", 9999,
    +                [{cacertfile, "cacerts.pem"},
    +                 {certs_keys, [#{certfile => "cert.pem", key => PrivKey}]}
    +                ], infinity).
     

    See also crypto documentation

    @@ -315,19 +315,19 @@

    NSS keylog

    The NSS keylog debug feature can be used by authorized users to for instance -enable wireshark to decrypt TLS packets.

    Server (with NSS key logging)

        server() ->
    -        application:load(ssl),
    -        {ok, _} = application:ensure_all_started(ssl),
    +enable wireshark to decrypt TLS packets.

    Server (with NSS key logging)

        server() ->
    +        application:load(ssl),
    +        {ok, _} = application:ensure_all_started(ssl),
             Port = 11029,
    -        LOpts = [{certs_keys, [#{certfile => "cert.pem", keyfile => "key.pem"}]},
    -        {reuseaddr, true},
    -        {versions, ['tlsv1.2','tlsv1.3']},
    -        {keep_secrets, true} %% Enable NSS key log (debug option)
    -        ],
    -        {ok, LSock} = ssl:listen(Port, LOpts),
    -        {ok, ASock} = ssl:transport_accept(LSock),
    -        {ok, CSock} = ssl:handshake(ASock).

    Exporting the secrets

          {ok, [{keylog, KeylogItems}]} = ssl:connection_information(CSock, [keylog]).
    -      file:write_file("key.log", [[KeylogItem,$\n] || KeylogItem <- KeylogItems]).

    + LOpts = [{certs_keys, [#{certfile => "cert.pem", keyfile => "key.pem"}]}, + {reuseaddr, true}, + {versions, ['tlsv1.2','tlsv1.3']}, + {keep_secrets, true} %% Enable NSS key log (debug option) + ], + {ok, LSock} = ssl:listen(Port, LOpts), + {ok, ASock} = ssl:transport_accept(LSock), + {ok, CSock} = ssl:handshake(ASock).

    Exporting the secrets

          {ok, [{keylog, KeylogItems}]} = ssl:connection_information(CSock, [keylog]).
    +      file:write_file("key.log", [[KeylogItem,$\n] || KeylogItem <- KeylogItems]).

    @@ -351,115 +351,115 @@

    {reuse_session, SessionId}. Also it is possible for the client to reuse a session that is not saved by the ssl application using {reuse_session, {SessionId, SessionData}}.

    Note

    When using explicit session reuse, it is up to the client to make sure that -the session being reused is for the correct server and has been verified.

    Here follows a client side example, divide into several steps for readability.

    Step 1 - Automated Session Reuse

    1> ssl:start().
    +the session being reused is for the correct server and has been verified.

    Here follows a client side example, divide into several steps for readability.

    Step 1 - Automated Session Reuse

    1> ssl:start().
     ok
     
    -2>{ok, C1} = ssl:connect("localhost", 9999, [{verify, verify_peer},
    -                                           {versions, ['tlsv1.2']},
    -                                           {cacertfile, "cacerts.pem"}]).
    -{ok,{sslsocket,{gen_tcp,#Port<0.7>,tls_connection,undefined}, ...}}
    +2>{ok, C1} = ssl:connect("localhost", 9999, [{verify, verify_peer},
    +                                           {versions, ['tlsv1.2']},
    +                                           {cacertfile, "cacerts.pem"}]).
    +{ok,{sslsocket,{gen_tcp,#Port<0.7>,tls_connection,undefined}, ...}}
     
    -3> ssl:connection_information(C1, [session_id]).
    -{ok,[{session_id,<<95,32,43,22,35,63,249,22,26,36,106,
    +3> ssl:connection_information(C1, [session_id]).
    +{ok,[{session_id,<<95,32,43,22,35,63,249,22,26,36,106,
                        152,49,52,124,56,130,192,137,161,
    -                   146,145,164,232,...>>}]}
    +                   146,145,164,232,...>>}]}
     
     %% Reuse session if possible, note that if C2 is really fast the session
     %% data might not be available for reuse.
    -4>{ok, C2} = ssl:connect("localhost", 9999, [{verify, verify_peer},
    -                                           {versions, ['tlsv1.2']},
    -                                           {cacertfile, "cacerts.pem"},
    -                                           {reuse_sessions, true}]).
    -{ok,{sslsocket,{gen_tcp,#Port<0.8>,tls_connection,undefined}, ...]}}
    +4>{ok, C2} = ssl:connect("localhost", 9999, [{verify, verify_peer},
    +                                           {versions, ['tlsv1.2']},
    +                                           {cacertfile, "cacerts.pem"},
    +                                           {reuse_sessions, true}]).
    +{ok,{sslsocket,{gen_tcp,#Port<0.8>,tls_connection,undefined}, ...]}}
     
     %% C2 got same session ID as client one, session was automatically reused.
    -5> ssl:connection_information(C2, [session_id]).
    -{ok,[{session_id,<<95,32,43,22,35,63,249,22,26,36,106,
    +5> ssl:connection_information(C2, [session_id]).
    +{ok,[{session_id,<<95,32,43,22,35,63,249,22,26,36,106,
                        152,49,52,124,56,130,192,137,161,
    -                   146,145,164,232,...>>}]}

    Step 2- Using save Option

    %% We want save this particular session for
    +                   146,145,164,232,...>>}]}

    Step 2- Using save Option

    %% We want save this particular session for
     %% reuse although it has the same basis as C1
    -6> {ok, C3} = ssl:connect("localhost", 9999, [{verify, verify_peer},
    -                                           {versions, ['tlsv1.2']},
    -                                           {cacertfile, "cacerts.pem"},
    -                                           {reuse_sessions, save}]).
    +6> {ok, C3} = ssl:connect("localhost", 9999, [{verify, verify_peer},
    +                                           {versions, ['tlsv1.2']},
    +                                           {cacertfile, "cacerts.pem"},
    +                                           {reuse_sessions, save}]).
     
    -{ok,{sslsocket,{gen_tcp,#Port<0.9>,tls_connection,undefined}, ...]}}
    +{ok,{sslsocket,{gen_tcp,#Port<0.9>,tls_connection,undefined}, ...]}}
     
     %% A full handshake is performed and we get a new session ID
    -7> {ok, [{session_id, ID}]} = ssl:connection_information(C3, [session_id]).
    -{ok,[{session_id,<<91,84,27,151,183,39,84,90,143,141,
    +7> {ok, [{session_id, ID}]} = ssl:connection_information(C3, [session_id]).
    +{ok,[{session_id,<<91,84,27,151,183,39,84,90,143,141,
                        121,190,66,192,10,1,27,192,33,95,78,
    -                   8,34,180,...>>}]}
    +                   8,34,180,...>>}]}
     
     %% Use automatic session reuse
    -8> {ok, C4} = ssl:connect("localhost", 9999, [{verify, verify_peer},
    -                                           {versions, ['tlsv1.2']},
    -                                           {cacertfile, "cacerts.pem"},
    -                                           {reuse_sessions, true}]).
    +8> {ok, C4} = ssl:connect("localhost", 9999, [{verify, verify_peer},
    +                                           {versions, ['tlsv1.2']},
    +                                           {cacertfile, "cacerts.pem"},
    +                                           {reuse_sessions, true}]).
     
    -{ok,{sslsocket,{gen_tcp,#Port<0.10>,tls_connection,
    -                        undefined}, ...]}}
    +{ok,{sslsocket,{gen_tcp,#Port<0.10>,tls_connection,
    +                        undefined}, ...]}}
     
     %% The "saved" one happened to be selected, but this is not a guarantee
    -9> ssl:connection_information(C4, [session_id]).
    -{ok,[{session_id,<<91,84,27,151,183,39,84,90,143,141,
    +9> ssl:connection_information(C4, [session_id]).
    +{ok,[{session_id,<<91,84,27,151,183,39,84,90,143,141,
                        121,190,66,192,10,1,27,192,33,95,78,
    -                   8,34,180,...>>}]}
    +                   8,34,180,...>>}]}
     
     %% Make sure to reuse the "saved" session
    -10> {ok, C5} = ssl:connect("localhost", 9999, [{verify, verify_peer},
    -                                           {versions, ['tlsv1.2']},
    -                                           {cacertfile, "cacerts.pem"},
    -                                           {reuse_session, ID}]).
    -{ok,{sslsocket,{gen_tcp,#Port<0.11>,tls_connection,
    -                        undefined}, ...]}}
    -
    -11> ssl:connection_information(C5, [session_id]).
    -{ok,[{session_id,<<91,84,27,151,183,39,84,90,143,141,
    +10> {ok, C5} = ssl:connect("localhost", 9999, [{verify, verify_peer},
    +                                           {versions, ['tlsv1.2']},
    +                                           {cacertfile, "cacerts.pem"},
    +                                           {reuse_session, ID}]).
    +{ok,{sslsocket,{gen_tcp,#Port<0.11>,tls_connection,
    +                        undefined}, ...]}}
    +
    +11> ssl:connection_information(C5, [session_id]).
    +{ok,[{session_id,<<91,84,27,151,183,39,84,90,143,141,
                        121,190,66,192,10,1,27,192,33,95,78,
    -                   8,34,180,...>>}]}

    Step 3 - Explicit Session Reuse

    %% Perform a full handshake and the session will not be saved for reuse
    -12> {ok, C9} =
    -ssl:connect("localhost", 9999, [{verify, verify_peer},
    -                                    {versions, ['tlsv1.2']},
    -                                    {cacertfile, "cacerts.pem"},
    -                                    {reuse_sessions, false},
    -                                    {server_name_indication, disable}]).
    -{ok,{sslsocket,{gen_tcp,#Port<0.14>,tls_connection, ...}}
    +                   8,34,180,...>>}]}

    Step 3 - Explicit Session Reuse

    %% Perform a full handshake and the session will not be saved for reuse
    +12> {ok, C9} =
    +ssl:connect("localhost", 9999, [{verify, verify_peer},
    +                                    {versions, ['tlsv1.2']},
    +                                    {cacertfile, "cacerts.pem"},
    +                                    {reuse_sessions, false},
    +                                    {server_name_indication, disable}]).
    +{ok,{sslsocket,{gen_tcp,#Port<0.14>,tls_connection, ...}}
     
     %% Fetch session ID and data for C9 connection
    -12> {ok, [{session_id, ID1}, {session_data, SessData}]} =
    -        ssl:connection_information(C9, [session_id, session_data]).
    -{ok,[{session_id,<<9,233,4,54,170,88,170,180,17,96,202,
    +12> {ok, [{session_id, ID1}, {session_data, SessData}]} =
    +        ssl:connection_information(C9, [session_id, session_data]).
    +{ok,[{session_id,<<9,233,4,54,170,88,170,180,17,96,202,
                        85,85,99,119,47,9,68,195,50,120,52,
    -                   130,239,...>>},
    -     {session_data,<<131,104,13,100,0,7,115,101,115,115,105,
    -                     111,110,109,0,0,0,32,9,233,4,54,170,...>>}]}
    +                   130,239,...>>},
    +     {session_data,<<131,104,13,100,0,7,115,101,115,115,105,
    +                     111,110,109,0,0,0,32,9,233,4,54,170,...>>}]}
     
     %% Explicitly reuse the session from C9
    -13> {ok, C10} = ssl:connect("localhost", 9999, [{verify, verify_peer},
    -                                    {versions, ['tlsv1.2']},
    -                                    {cacertfile, "cacerts.pem"},
    -                                    {reuse_session, {ID1, SessData}}]).
    -{ok,{sslsocket,{gen_tcp,#Port<0.15>,tls_connection,
    -                        undefined}, ...}}
    -
    -14> ssl:connection_information(C10, [session_id]).
    -{ok,[{session_id,<<9,233,4,54,170,88,170,180,17,96,202,
    +13> {ok, C10} = ssl:connect("localhost", 9999, [{verify, verify_peer},
    +                                    {versions, ['tlsv1.2']},
    +                                    {cacertfile, "cacerts.pem"},
    +                                    {reuse_session, {ID1, SessData}}]).
    +{ok,{sslsocket,{gen_tcp,#Port<0.15>,tls_connection,
    +                        undefined}, ...}}
    +
    +14> ssl:connection_information(C10, [session_id]).
    +{ok,[{session_id,<<9,233,4,54,170,88,170,180,17,96,202,
                        85,85,99,119,47,9,68,195,50,120,52,
    -                   130,239,...>>}]}

    Step 4 - Not Possible to Reuse Explicit Session by ID Only

    %% Try to reuse the session from C9 using only the id
    -15> {ok, E} =  ssl:connect("localhost", 9999, [{verify, verify_peer},
    -                                    {versions, ['tlsv1.2']},
    -                                    {cacertfile, "cacerts.pem"},
    -                                    {reuse_session, ID1}]).
    -{ok,{sslsocket,{gen_tcp,#Port<0.18>,tls_connection,
    -                        undefined}, ...}}
    +                   130,239,...>>}]}

    Step 4 - Not Possible to Reuse Explicit Session by ID Only

    %% Try to reuse the session from C9 using only the id
    +15> {ok, E} =  ssl:connect("localhost", 9999, [{verify, verify_peer},
    +                                    {versions, ['tlsv1.2']},
    +                                    {cacertfile, "cacerts.pem"},
    +                                    {reuse_session, ID1}]).
    +{ok,{sslsocket,{gen_tcp,#Port<0.18>,tls_connection,
    +                        undefined}, ...}}
     
     %% This will fail (as it is not saved for reuse)
     %% and a full handshake will be performed, we get a new id.
    -16>  ssl:connection_information(E, [session_id]).
    -{ok,[{session_id,<<87,46,43,126,175,68,160,153,37,29,
    +16>  ssl:connection_information(E, [session_id]).
    +{ok,[{session_id,<<87,46,43,126,175,68,160,153,37,29,
                        196,240,65,160,254,88,65,224,18,63,
    -                   18,17,174,39,...>>}]}

    On the server side the the {reuse_sessions, boolean()} option determines if + 18,17,174,39,...>>}]}

    On the server side the the {reuse_sessions, boolean()} option determines if the server will save session data and allow session reuse or not. This can be further customized by the option {reuse_session, fun()} that may introduce a local policy for session reuse.

    @@ -483,18 +483,18 @@

    Anti-Replay Protection in TLS 1.3

    Session tickets are sent by servers on newly established TLS connections. The number of tickets sent and their lifetime are configurable by application variables. See also SSL's configuration.

    Session tickets are protected by application traffic keys, and in stateless -tickets, the opaque data structure itself is self-encrypted.

    An example with automatic and manual session resumption:

          {ok, _} = application:ensure_all_started(ssl).
    -      LOpts = [{certs_keys, [#{certfile => "cert.pem",
    -                               keyfile => "key.pem"}]},
    -               {versions, ['tlsv1.2','tlsv1.3']},
    -               {session_tickets, stateless}].
    -      {ok, LSock} = ssl:listen(8001, LOpts).
    -      {ok, ASock} = ssl:transport_accept(LSock).

    Step 2 (client): Start the client and connect to server:

          {ok, _} = application:ensure_all_started(ssl).
    -      COpts = [{cacertfile, "cert.pem"},
    -               {versions, ['tlsv1.2','tlsv1.3']},
    -               {log_level, debug},
    -               {session_tickets, auto}].
    -      ssl:connect("localhost", 8001, COpts).

    Step 3 (server): Start the TLS handshake:

          {ok, CSocket} = ssl:handshake(ASock).

    A connection is established using a full handshake. Below is a summary of the +tickets, the opaque data structure itself is self-encrypted.

    An example with automatic and manual session resumption:

          {ok, _} = application:ensure_all_started(ssl).
    +      LOpts = [{certs_keys, [#{certfile => "cert.pem",
    +                               keyfile => "key.pem"}]},
    +               {versions, ['tlsv1.2','tlsv1.3']},
    +               {session_tickets, stateless}].
    +      {ok, LSock} = ssl:listen(8001, LOpts).
    +      {ok, ASock} = ssl:transport_accept(LSock).

    Step 2 (client): Start the client and connect to server:

          {ok, _} = application:ensure_all_started(ssl).
    +      COpts = [{cacertfile, "cert.pem"},
    +               {versions, ['tlsv1.2','tlsv1.3']},
    +               {log_level, debug},
    +               {session_tickets, auto}].
    +      ssl:connect("localhost", 8001, COpts).

    Step 3 (server): Start the TLS handshake:

          {ok, CSocket} = ssl:handshake(ASock).

    A connection is established using a full handshake. Below is a summary of the exchanged messages:

          >>> TLS 1.3 Handshake, ClientHello ...
           <<< TLS 1.3 Handshake, ServerHello ...
           <<< Handshake, EncryptedExtensions ...
    @@ -503,27 +503,27 @@ 

    <<< Handshake, Finished ... >>> Handshake, Finished ... <<< Post-Handshake, NewSessionTicket ...

    At this point the client has stored the received session tickets and ready to -use them when establishing new connections to the same server.

    Step 4 (server): Accept a new connection on the server:

          {ok, ASock2} = ssl:transport_accept(LSock).

    Step 5 (client): Make a new connection:

          ssl:connect("localhost", 8001, COpts).

    Step 6 (server): Start the handshake:

          {ok, CSock2} =ssl:handshake(ASock2).

    The second connection is a session resumption using keying material from the +use them when establishing new connections to the same server.

    Step 4 (server): Accept a new connection on the server:

          {ok, ASock2} = ssl:transport_accept(LSock).

    Step 5 (client): Make a new connection:

          ssl:connect("localhost", 8001, COpts).

    Step 6 (server): Start the handshake:

          {ok, CSock2} =ssl:handshake(ASock2).

    The second connection is a session resumption using keying material from the previous handshake:

          >>> TLS 1.3 Handshake, ClientHello ...
           <<< TLS 1.3 Handshake, ServerHello ...
           <<< Handshake, EncryptedExtensions ...
           <<< Handshake, Finished ...
           >>> Handshake, Finished ...
           <<< Post-Handshake, NewSessionTicket ...

    Manual handling of session tickets is also supported. In manual mode, it is the -responsibility of the client to handle received session tickets.

    Step 7 (server): Accept a new connection on the server:

          {ok, ASock3} = ssl:transport_accept(LSock).

    Step 8 (client): Make a new connection to server:

          {ok, _} = application:ensure_all_started(ssl).
    -      COpts2 = [{cacertfile, "cacerts.pem"},
    -                {versions, ['tlsv1.2','tlsv1.3']},
    -                {log_level, debug},
    -                {session_tickets, manual}].
    -      ssl:connect("localhost", 8001, COpts).

    Step 9 (server): Start the handshake:

          {ok, CSock3} = ssl:handshake(ASock3).

    After the handshake is performed, the user process receivess messages with the -tickets sent by the server.

    Step 10 (client): Receive a new session ticket:

          Ticket = receive {ssl, session_ticket, {_, TicketData}} -> TicketData end.

    Step 11 (server): Accept a new connection on the server:

          {ok, ASock4} = ssl:transport_accept(LSock).

    Step 12 (client): Initiate a new connection to the server with the session -ticket received in Step 10:

          {ok, _} = application:ensure_all_started(ssl).
    -      COpts2 = [{cacertfile, "cert.pem"},
    -                {versions, ['tlsv1.2','tlsv1.3']},
    -                {log_level, debug},
    -                {session_tickets, manual},
    -                {use_ticket, [Ticket]}].
    -      ssl:connect("localhost", 8001, COpts).

    Step 13 (server): Start the handshake:

          {ok, CSock4} = ssl:handshake(ASock4).

    +responsibility of the client to handle received session tickets.

    Step 7 (server): Accept a new connection on the server:

          {ok, ASock3} = ssl:transport_accept(LSock).

    Step 8 (client): Make a new connection to server:

          {ok, _} = application:ensure_all_started(ssl).
    +      COpts2 = [{cacertfile, "cacerts.pem"},
    +                {versions, ['tlsv1.2','tlsv1.3']},
    +                {log_level, debug},
    +                {session_tickets, manual}].
    +      ssl:connect("localhost", 8001, COpts).

    Step 9 (server): Start the handshake:

          {ok, CSock3} = ssl:handshake(ASock3).

    After the handshake is performed, the user process receivess messages with the +tickets sent by the server.

    Step 10 (client): Receive a new session ticket:

          Ticket = receive {ssl, session_ticket, {_, TicketData}} -> TicketData end.

    Step 11 (server): Accept a new connection on the server:

          {ok, ASock4} = ssl:transport_accept(LSock).

    Step 12 (client): Initiate a new connection to the server with the session +ticket received in Step 10:

          {ok, _} = application:ensure_all_started(ssl).
    +      COpts2 = [{cacertfile, "cert.pem"},
    +                {versions, ['tlsv1.2','tlsv1.3']},
    +                {log_level, debug},
    +                {session_tickets, manual},
    +                {use_ticket, [Ticket]}].
    +      ssl:connect("localhost", 8001, COpts).

    Step 13 (server): Start the handshake:

          {ok, CSock4} = ssl:handshake(ASock4).

    @@ -542,76 +542,76 @@

    operations, such as HEAD and GET, can usually be regarded as safe but even they can be exploited by a large number of replays causing resource limit exhaustion and other similar problems.

    An example of sending early data with automatic and manual session ticket -handling:

    Server

    early_data_server() ->
    -    application:load(ssl),
    -    {ok, _} = application:ensure_all_started(ssl),
    +handling:

    Server

    early_data_server() ->
    +    application:load(ssl),
    +    {ok, _} = application:ensure_all_started(ssl),
         Port = 11029,
    -    LOpts = [{certs_keys, [#{certfile => "cert.pem", keyfile => "key.pem"}]},
    -             {reuseaddr, true},
    -             {versions, ['tlsv1.2','tlsv1.3']},
    -             {session_tickets, stateless},
    -             {early_data, enabled},
    -            ],
    -    {ok, LSock} = ssl:listen(Port, LOpts),
    +    LOpts = [{certs_keys, [#{certfile => "cert.pem", keyfile => "key.pem"}]},
    +             {reuseaddr, true},
    +             {versions, ['tlsv1.2','tlsv1.3']},
    +             {session_tickets, stateless},
    +             {early_data, enabled},
    +            ],
    +    {ok, LSock} = ssl:listen(Port, LOpts),
         %% Accept first connection
    -    {ok, ASock0} = ssl:transport_accept(LSock),
    -    {ok, CSock0} = ssl:handshake(ASock0),
    +    {ok, ASock0} = ssl:transport_accept(LSock),
    +    {ok, CSock0} = ssl:handshake(ASock0),
         %% Accept second connection
    -    {ok, ASock1} = ssl:transport_accept(LSock),
    -    {ok, CSock1} = ssl:handshake(ASock1),
    -    Sock.

    Client (automatic ticket handling):

    early_data_auto() ->
    +    {ok, ASock1} = ssl:transport_accept(LSock),
    +    {ok, CSock1} = ssl:handshake(ASock1),
    +    Sock.

    Client (automatic ticket handling):

    early_data_auto() ->
         %% First handshake 1-RTT - get session tickets
    -    application:load(ssl),
    -    {ok, _} = application:ensure_all_started(ssl),
    +    application:load(ssl),
    +    {ok, _} = application:ensure_all_started(ssl),
         Port = 11029,
         Data = <<"HEAD / HTTP/1.1\r\nHost: \r\nConnection: close\r\n">>,
    -    COpts0 = [{cacertfile, "cacerts.pem"},
    -              {versions, ['tlsv1.2', 'tlsv1.3']},
    -              {session_tickets, auto}],
    -    {ok, Sock0} = ssl:connect("localhost", Port, COpts0),
    +    COpts0 = [{cacertfile, "cacerts.pem"},
    +              {versions, ['tlsv1.2', 'tlsv1.3']},
    +              {session_tickets, auto}],
    +    {ok, Sock0} = ssl:connect("localhost", Port, COpts0),
     
         %% Wait for session tickets
    -    timer:sleep(500),
    +    timer:sleep(500),
         %% Close socket if server cannot handle multiple
         %% connections e.g. openssl s_server
    -    ssl:close(Sock0),
    +    ssl:close(Sock0),
     
         %% Second handshake 0-RTT
    -    COpts1 = [{cacertfile,  "cacerts.pem"},
    -              {versions, ['tlsv1.2', 'tlsv1.3']},
    -              {session_tickets, auto},
    -              {early_data, Data}],
    -    {ok, Sock} = ssl:connect("localhost", Port, COpts1),
    +    COpts1 = [{cacertfile,  "cacerts.pem"},
    +              {versions, ['tlsv1.2', 'tlsv1.3']},
    +              {session_tickets, auto},
    +              {early_data, Data}],
    +    {ok, Sock} = ssl:connect("localhost", Port, COpts1),
         Sock.
    -

    Client (manual ticket handling):

    early_data_manual() ->
    +

    Client (manual ticket handling):

    early_data_manual() ->
         %% First handshake 1-RTT - get session tickets
    -    application:load(ssl),
    -    {ok, _} = application:ensure_all_started(ssl),
    +    application:load(ssl),
    +    {ok, _} = application:ensure_all_started(ssl),
         Port = 11029,
         Data = <<"HEAD / HTTP/1.1\r\nHost: \r\nConnection: close\r\n">>,
    -    COpts0 = [{cacertfile, "cacerts.pem"},
    -              {versions, ['tlsv1.2', 'tlsv1.3']},
    -              {session_tickets, manual}],
    -    {ok, Sock0} = ssl:connect("localhost", Port, COpts0),
    +    COpts0 = [{cacertfile, "cacerts.pem"},
    +              {versions, ['tlsv1.2', 'tlsv1.3']},
    +              {session_tickets, manual}],
    +    {ok, Sock0} = ssl:connect("localhost", Port, COpts0),
     
         %% Wait for session tickets
         Ticket =
             receive
    -            {ssl, session_ticket, Ticket0} ->
    +            {ssl, session_ticket, Ticket0} ->
                     Ticket0
             end,
     
         %% Close socket if server cannot handle multiple connections
         %% e.g. openssl s_server
    -    ssl:close(Sock0),
    +    ssl:close(Sock0),
     
         %% Second handshake 0-RTT
    -    COpts1 = [{cacertfile, "cacerts.pem"},
    -              {versions, ['tlsv1.2', 'tlsv1.3']},
    -              {session_tickets, manual},
    -              {use_ticket, [Ticket]},
    -              {early_data, Data}],
    -    {ok, Sock} = ssl:connect("localhost", Port, COpts1),
    +    COpts1 = [{cacertfile, "cacerts.pem"},
    +              {versions, ['tlsv1.2', 'tlsv1.3']},
    +              {session_tickets, manual},
    +              {use_ticket, [Ticket]},
    +              {early_data, Data}],
    +    {ok, Sock} = ssl:connect("localhost", Port, COpts1),
         Sock.

    @@ -656,11 +656,11 @@

    Using DTLS

    Using DTLS has basically the same API as TLS. You need to add the option -{protocol, dtls} to the connect and listen functions. For example

     client>{ok, Socket} = ssl:connect("localhost", 9999, [{protocol, dtls},
    -                                               {verify, verify_peer},
    -                                               {cacertfile, "cacerts.pem"}],
    -                           infinity).
    -{ok,{sslsocket, [...]}}
    +{protocol, dtls} to the connect and listen functions. For example

     client>{ok, Socket} = ssl:connect("localhost", 9999, [{protocol, dtls},
    +                                               {verify, verify_peer},
    +                                               {cacertfile, "cacerts.pem"}],
    +                           infinity).
    +{ok,{sslsocket, [...]}}
     
    diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/.build b/prs/9045/lib/stdlib-6.1.2/doc/html/.build index c10a50f60727..1a7355243b0f 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/.build +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/.build @@ -34,7 +34,7 @@ dist/lato-latin-ext-300-normal-VPGGJKJL.woff2 dist/lato-latin-ext-400-normal-N27NCBWW.woff2 dist/lato-latin-ext-700-normal-Q2L5DVMW.woff2 dist/remixicon-NKANDIL5.woff2 -dist/search_data-6D22CF61.js +dist/search_data-D370A15C.js dist/sidebar_items-3EFE45AC.js edlin.html edlin_expand.html diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/argparse.html b/prs/9045/lib/stdlib-6.1.2/doc/html/argparse.html index a0d81d0cff90..e7c64845fc22 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/argparse.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/argparse.html @@ -153,20 +153,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}).
    -
    -cli() ->
    -    #{
    -        arguments => [
    -            #{name => left, type => integer},
    -            #{name => right, type => integer}
    -        ],
    +main(Args) ->
    +    argparse:run(Args, cli(), #{progname => mul}).
    +
    +cli() ->
    +    #{
    +        arguments => [
    +            #{name => left, type => integer},
    +            #{name => right, type => integer}
    +        ],
             handler =>
    -            fun (#{left := Left, right := Right}) ->
    -                io:format("~b~n", [Left * Right])
    +            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 @@ -180,25 +180,25 @@

    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 @@ -216,14 +216,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 @@ -654,111 +654,111 @@

    argument()

    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, if it does not start with an option prefix. Otherwise, adds a specified Erlang term to the arguments map.

  • all - Fold all remaining command line arguments into a list, ignoring any option prefixes or switches. Useful for proxying arguments into another -command line utility.

    1> Cmd = #{arguments => [
    -    #{name => verbose, short => $v, type => boolean},
    -    #{name => raw, long => "-", nargs => all}
    -]},
    -argparse:parse(["-v", "--", "-kernel", "arg", "opt"], Cmd).
    +command line utility.

    1> Cmd = #{arguments => [
    +    #{name => verbose, short => $v, type => boolean},
    +    #{name => raw, long => "-", nargs => all}
    +]},
    +argparse:parse(["-v", "--", "-kernel", "arg", "opt"], Cmd).
     
    -{ok,#{raw => ["-kernel","arg","opt"],verbose => true}, ...
  • action - Defines an action to take when the argument is found in the +{ok,#{raw => ["-kernel","arg","opt"],verbose => true}, ...

  • action - Defines an action to take when the argument is found in the command line. The default action is store.

    • store - Store the value in the arguments map. Overwrites the value -previously written.

      1> Cmd = #{arguments => [#{name => str, short => $s}]},
      -argparse:parse(["-s", "one", "-s", "two"], Cmd).
      +previously written.

      1> Cmd = #{arguments => [#{name => str, short => $s}]},
      +argparse:parse(["-s", "one", "-s", "two"], Cmd).
       
      -{ok, #{str => "two"}, ...
    • {store, term()} - Stores the specified term instead of reading the -value from the command line.

      1> Cmd = #{arguments => [#{name => str, short => $s, action => {store, "two"}}]},
      -argparse:parse(["-s"], Cmd).
      +{ok, #{str => "two"}, ...
    • {store, term()} - Stores the specified term instead of reading the +value from the command line.

      1> Cmd = #{arguments => [#{name => str, short => $s, action => {store, "two"}}]},
      +argparse:parse(["-s"], Cmd).
       
      -{ok, #{str => "two"}, ...
    • append - Appends the repeating occurrences of the argument instead of -overwriting.

      1> Cmd = #{arguments => [#{name => node, short => $n, action => append}]},
      -argparse:parse(["-n", "one", "-n", "two", "-n", "three"], Cmd).
      +{ok, #{str => "two"}, ...
    • append - Appends the repeating occurrences of the argument instead of +overwriting.

      1> Cmd = #{arguments => [#{name => node, short => $n, action => append}]},
      +argparse:parse(["-n", "one", "-n", "two", "-n", "three"], Cmd).
       
      -{ok, #{node => ["one", "two", "three"]}, ...
      +{ok, #{node => ["one", "two", "three"]}, ...
       
       %% Always produces a list - even if there is one occurrence
      -2> argparse:parse(["-n", "one"], Cmd).
      +2> argparse:parse(["-n", "one"], Cmd).
       
      -{ok, #{node => ["one"]}, ...
    • {append, term()} - Same as append, but instead of consuming the +{ok, #{node => ["one"]}, ...

  • {append, term()} - Same as append, but instead of consuming the argument from the command line, appends a provided term/0.

  • count - Puts a counter as a value in the arguments map. Useful for -implementing verbosity option:

    1> Cmd = #{arguments => [#{name => verbose, short => $v, action => count}]},
    -argparse:parse(["-v"], Cmd).
    +implementing verbosity option:

    1> Cmd = #{arguments => [#{name => verbose, short => $v, action => count}]},
    +argparse:parse(["-v"], Cmd).
     
    -{ok, #{verbose => 1}, ...
    +{ok, #{verbose => 1}, ...
     
    -2> argparse:parse(["-vvvv"], Cmd).
    +2> argparse:parse(["-vvvv"], Cmd).
     
    -{ok, #{verbose => 4}, ...
  • extend - Works as append, but flattens the resulting list. Valid -only for nargs set to list, nonempty_list, all or pos_integer/0.

    1> Cmd = #{arguments => [#{name => duet, short => $d, nargs => 2, action => extend}]},
    -argparse:parse(["-d", "a", "b", "-d", "c", "d"], Cmd).
    +{ok, #{verbose => 4}, ...
  • extend - Works as append, but flattens the resulting list. Valid +only for nargs set to list, nonempty_list, all or pos_integer/0.

    1> Cmd = #{arguments => [#{name => duet, short => $d, nargs => 2, action => extend}]},
    +argparse:parse(["-d", "a", "b", "-d", "c", "d"], Cmd).
     
    -{ok, #{duet => ["a", "b", "c", "d"]}, ...
    +{ok, #{duet => ["a", "b", "c", "d"]}, ...
     
     %% 'append' would result in {ok, #{duet => [["a", "b"],["c", "d"]]},
  • help - Specifies help/usage text for the argument. argparse provides automatic generation based on the argument name, type and default value, but @@ -975,16 +975,16 @@

    handler()

    exported from Module, accepting argument map.

  • {fun(() -> term()), Default :: term()} - Function accepting as many arguments as there are in the arguments list for this command. Arguments missing from the parsed map are replaced with the Default. Convenient way to -expose existing functions.

    1> Cmd = #{arguments => [
    -        #{name => x, type => float},
    -        #{name => y, type => float, short => $p}],
    -    handler => {fun math:pow/2, 1}},
    -argparse:run(["2", "-p", "3"], Cmd, #{}).
    +expose existing functions.

    1> Cmd = #{arguments => [
    +        #{name => x, type => float},
    +        #{name => y, type => float, short => $p}],
    +    handler => {fun math:pow/2, 1}},
    +argparse:run(["2", "-p", "3"], Cmd, #{}).
     
     8.0
     
     %% default term 1 is passed to math:pow/2
    -2> argparse:run(["2"], Cmd, #{}).
    +2> argparse:run(["2"], Cmd, #{}).
     
     2.0
  • {Module :: module(), Function :: atom(), Default :: term()} - Function named Function, exported from Module, accepting as many arguments as diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/array.html b/prs/9045/lib/stdlib-6.1.2/doc/html/array.html index cf2312b7f23a..d28775a125bf 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/array.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/array.html @@ -142,14 +142,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)).
    @@ -1190,7 +1190,7 @@

    new(Options)

    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.

    @@ -1223,7 +1223,7 @@

    new(Size, Options)

    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.

    diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/assert_hrl.html b/prs/9045/lib/stdlib-6.1.2/doc/html/assert_hrl.html index 37048753e287..e0b9b4d35ff0 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/assert_hrl.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/assert_hrl.html @@ -138,7 +138,7 @@

    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 @@ -166,7 +166,7 @@

    • 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 diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/base64.html b/prs/9045/lib/stdlib-6.1.2/doc/html/base64.html index 57c087b68a87..10526f503d1a 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/base64.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/base64.html @@ -677,15 +677,15 @@

      decode(Base64, Options)

      Decodes a base64 string encoded using the standard alphabet according to RFC 4648 Section 4 to plain ASCII.

      The function will strips 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==").
      +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==").
      +2> base64:decode("AQ ID BA==").
       <<1,2,3,4>>
      -3> base64:decode("AQIDBA=").
      +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 }).
      +4> base64:decode("AQIDBA=", #{ padding => false }).
       <<1,2,3,4>>

    @@ -940,9 +940,9 @@

    mime_decode(Base64, Options)

    Decodes a base64 "mime" string encoded using the standard alphabet according to RFC 4648 Section 4 to plain ASCII.

    The function will strips 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==").
    +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=").
    +2> base64:mime_decode("AQIDB=A=").
     <<1,2,3,4>>
    diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/beam_lib.html b/prs/9045/lib/stdlib-6.1.2/doc/html/beam_lib.html index 91dddcdef223..732224992452 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/beam_lib.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/beam_lib.html @@ -157,8 +157,8 @@

    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))]).

    +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))]).

    @@ -188,13 +188,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.

    @@ -1601,11 +1601,11 @@

    crypto_key_fun(CryptoKeyFun)

    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 @@ -1972,14 +1972,14 @@

    version(Beam)

    -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]}}
    diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/binary.html b/prs/9045/lib/stdlib-6.1.2/doc/html/binary.html index af870145c542..289da8a68ebb 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/binary.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/binary.html @@ -659,7 +659,7 @@

    bin_to_list(Subject)

    -

    Converts Subject to a list of byte/0s, each representing the value of one byte.

    Example:

    1> binary:bin_to_list(<<"erlang">>).
    +

    Converts Subject to a list of byte/0s, each representing the value of one byte.

    Example:

    1> binary:bin_to_list(<<"erlang">>).
     "erlang"
     %% or [101,114,108,97,110,103] in list notation.
    @@ -725,7 +725,7 @@

    bin_to_list(Subject, Pos, Len)

    Converts Subject to a list of byte/0s, each representing the value of one byte. PosLen or alternatively Pos and Len denote which part of the Subject binary to convert. By default, the entire Subject binary is -converted.

    Example:

    1> binary:bin_to_list(<<"erlang">>, {1,3}).
    +converted.

    Example:

    1> binary:bin_to_list(<<"erlang">>, {1,3}).
     "rla"
     %% or [114,108,97] in list notation.

    If PosLen or alternatively Pos and Len in any way reference outside the binary, a badarg exception is raised.

    @@ -867,7 +867,7 @@

    decode_hex(Bin)

    -

    Decodes a hex encoded binary into a binary.

    Example

    1> binary:decode_hex(<<"66">>).
    +

    Decodes a hex encoded binary into a binary.

    Example

    1> binary:decode_hex(<<"66">>).
     <<"f">>
    @@ -933,11 +933,11 @@

    decode_unsigned(Subject, Endianness)

    Converts the binary digit representation, in big endian or little endian, of a -positive integer in Subject to an Erlang integer/0.

    Example:

    1> binary:decode_unsigned(<<169,138,199>>).
    +positive integer in Subject to an Erlang integer/0.

    Example:

    1> binary:decode_unsigned(<<169,138,199>>).
     11111111
    -2> binary:decode_unsigned(<<169,138,199>>, big).
    +2> binary:decode_unsigned(<<169,138,199>>, big).
     11111111
    -3> binary:decode_unsigned(<<169,138,199>>, little).
    +3> binary:decode_unsigned(<<169,138,199>>, little).
     13077161
    @@ -1000,13 +1000,13 @@

    encode_hex(Bin, Case)

    Encodes a binary into a hex encoded binary using the specified case for the -hexadecimal digits "a" to "f".

    The default case is uppercase.

    Example:

    1> binary:encode_hex(<<"f">>).
    +hexadecimal digits "a" to "f".

    The default case is uppercase.

    Example:

    1> binary:encode_hex(<<"f">>).
     <<"66">>
    -2> binary:encode_hex(<<"/">>).
    +2> binary:encode_hex(<<"/">>).
     <<"2F">>
    -3> binary:encode_hex(<<"/">>, lowercase).
    +3> binary:encode_hex(<<"/">>, lowercase).
     <<"2f">>
    -4> binary:encode_hex(<<"/">>, uppercase).
    +4> binary:encode_hex(<<"/">>, uppercase).
     <<"2F">>
    @@ -1069,11 +1069,11 @@

    encode_unsigned(Unsigned, Endianness)

    Converts a positive integer to the smallest possible representation in a binary -digit representation, either big endian or little endian.

    Example:

    1> binary:encode_unsigned(11111111).
    +digit representation, either big endian or little endian.

    Example:

    1> binary:encode_unsigned(11111111).
     <<169,138,199>>
    -2> binary:encode_unsigned(11111111, big).
    +2> binary:encode_unsigned(11111111, big).
     <<169,138,199>>
    -2> binary:encode_unsigned(11111111, little).
    +2> binary:encode_unsigned(11111111, little).
     <<199,138,169>>
    @@ -1135,7 +1135,7 @@

    join/2

    -

    Joins a list of binaries together by a specified Separator.

    Equivalent to iolist_to_binary(lists:join(Separator, Binaries)), but faster.

    Example:

    1> binary:join([<<"a">>, <<"b">>, <<"c">>], <<", ">>).
    +

    Joins a list of binaries together by a specified Separator.

    Equivalent to iolist_to_binary(lists:join(Separator, Binaries)), but faster.

    Example:

    1> binary:join([<<"a">>, <<"b">>, <<"c">>], <<", ">>).
     <<"a, b, c">>
    @@ -1228,9 +1228,9 @@

    longest_common_prefix(Binaries)

    Returns the length of the longest common prefix of the binaries in list -Binaries.

    Example:

    1> binary:longest_common_prefix([<<"erlang">>, <<"ergonomy">>]).
    +Binaries.

    Example:

    1> binary:longest_common_prefix([<<"erlang">>, <<"ergonomy">>]).
     2
    -2> binary:longest_common_prefix([<<"erlang">>, <<"perl">>]).
    +2> binary:longest_common_prefix([<<"erlang">>, <<"perl">>]).
     0

    If Binaries is not a flat non-empty list of binaries, a badarg exception is raised.

    @@ -1263,9 +1263,9 @@

    longest_common_suffix(Binaries)

    Returns the length of the longest common suffix of the binaries in list -Binaries.

    Example:

    1> binary:longest_common_suffix([<<"erlang">>, <<"fang">>]).
    +Binaries.

    Example:

    1> binary:longest_common_suffix([<<"erlang">>, <<"fang">>]).
     3
    -2> binary:longest_common_suffix([<<"erlang">>, <<"perl">>]).
    +2> binary:longest_common_suffix([<<"erlang">>, <<"perl">>]).
     0

    If Binaries is not a flat non-empty list of binaries, a badarg exception is raised.

    @@ -1341,8 +1341,8 @@

    match(Subject, Pattern, Options)

    Searches for the first occurrence of Pattern in Subject and returns the position and length.

    The function returns {Pos, Length} for the binary in Pattern, starting at -the lowest position in Subject.

    Example:

    1> binary:match(<<"abcde">>, [<<"bcde">>, <<"cd">>],[]).
    -{1,4}

    Even though <<"cd">> ends before <<"bcde">>, <<"bcde">> begins first and +the lowest position in Subject.

    Example:

    1> binary:match(<<"abcde">>, [<<"bcde">>, <<"cd">>],[]).
    +{1,4}

    Even though <<"cd">> ends before <<"bcde">>, <<"bcde">> begins first and is therefore the first match. If two overlapping matches begin at the same position, the longest is returned.

    Summary of the options:

    • {scope, {Start, Length}} - Only the specified part is searched. Return values still have offsets from the beginning of Subject. A negative Length @@ -1422,9 +1422,9 @@

      matches(Subject, Pattern, Options)

      As match/2, but Subject is searched until exhausted and a list of all non-overlapping parts matching Pattern is returned (in order).

      The first and longest match is preferred to a shorter, which is illustrated by -the following example:

      1> binary:matches(<<"abcde">>,
      -                  [<<"bcde">>,<<"bc">>,<<"de">>],[]).
      -[{1,4}]

      The result shows that <<"bcde">> is selected instead of the shorter match +the following example:

      1> binary:matches(<<"abcde">>,
      +                  [<<"bcde">>,<<"bc">>,<<"de">>],[]).
      +[{1,4}]

      The result shows that <<"bcde">> is selected instead of the shorter match <<"bc">> (which would have given raise to one more match, <<"de">>). This corresponds to the behavior of POSIX regular expressions (and programs like awk), but is not consistent with alternative matches in re (and Perl), where @@ -1493,7 +1493,7 @@

      part(Subject, Pos, Len)

      Extracts the part of binary Subject described by PosLen.

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

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

      Note

      part/2 and part/3 are also available in the erlang module under the names binary_part/2 and binary_part/3. Those BIFs are allowed in guard tests.

      If PosLen in any way references outside the binary, a badarg exception is @@ -1531,33 +1531,33 @@

      referenced_byte_size(Binary)

      it can be useful to get the size of the referenced binary. This function can be used in a program to trigger the use of copy/1. By copying a binary, one can dereference the original, possibly large, binary that a -smaller binary is a reference to.

      Example:

      store(Binary, GBSet) ->
      +smaller binary is a reference to.

      Example:

      store(Binary, GBSet) ->
         NewBin =
      -      case binary:referenced_byte_size(Binary) of
      -          Large when Large > 2 * byte_size(Binary) ->
      -             binary:copy(Binary);
      +      case binary:referenced_byte_size(Binary) of
      +          Large when Large > 2 * byte_size(Binary) ->
      +             binary:copy(Binary);
                 _ ->
                    Binary
             end,
      -  gb_sets:insert(NewBin,GBSet).

      In this example, we chose to copy the binary content before inserting it in + gb_sets:insert(NewBin,GBSet).

      In this example, we chose to copy the binary content before inserting it in gb_sets:set() if it references a binary more than twice the data size we want to keep. Of course, different rules apply when copying to different programs.

      Binary sharing occurs whenever binaries are taken apart. This is the fundamental reason why binaries are fast, decomposition can always be done with O(1) complexity. In rare circumstances this data sharing is however undesirable, why this function together with copy/1 can be useful when optimizing -for memory use.

      Example of binary sharing:

      1> A = binary:copy(<<1>>, 100).
      +for memory use.

      Example of binary sharing:

      1> A = binary:copy(<<1>>, 100).
       <<1,1,1,1,1 ...
      -2> byte_size(A).
      +2> byte_size(A).
       100
      -3> binary:referenced_byte_size(A).
      +3> binary:referenced_byte_size(A).
       100
       4> <<B:10/binary, C:90/binary>> = A.
       <<1,1,1,1,1 ...
      -5> {byte_size(B), binary:referenced_byte_size(B)}.
      -{10,10}
      -6> {byte_size(C), binary:referenced_byte_size(C)}.
      -{90,100}

      In the above example, the small binary B was copied while the larger binary +5> {byte_size(B), binary:referenced_byte_size(B)}. +{10,10} +6> {byte_size(C), binary:referenced_byte_size(C)}. +{90,100}

      In the above example, the small binary B was copied while the larger binary C references binary A.

      Note

      Binary data is shared among processes. If another process still references the larger binary, copying the part this process uses only consumes more memory and does not free up the larger binary for garbage collection. Use this kind @@ -1646,28 +1646,28 @@

      replace(Subject, Pattern, Replacement, Opti at the specified position (or positions) before inserting Replacement into Subject. If Replacement is given as a fun instead, this option is ignored.

      If any position specified in InsPos > size of the replacement binary, a badarg exception is raised.

      Options global and {scope, part()} work as for split/3. The return type is -always a binary/0.

      For a description of Pattern, see compile_pattern/1.

      Examples:

      1> binary:replace(<<"abcde">>, [<<"b">>, <<"d">>], <<"X">>, []).
      +always a binary/0.

      For a description of Pattern, see compile_pattern/1.

      Examples:

      1> binary:replace(<<"abcde">>, [<<"b">>, <<"d">>], <<"X">>, []).
       <<"aXcde">>
       
      -2> binary:replace(<<"abcde">>, [<<"b">>, <<"d">>], <<"X">>, [global]).
      +2> binary:replace(<<"abcde">>, [<<"b">>, <<"d">>], <<"X">>, [global]).
       <<"aXcXe">>
       
      -3> binary:replace(<<"abcde">>, <<"b">>, <<"[]">>, [{insert_replaced, 1}]).
      +3> binary:replace(<<"abcde">>, <<"b">>, <<"[]">>, [{insert_replaced, 1}]).
       <<"a[b]cde">>
       
      -4> binary:replace(<<"abcde">>, [<<"b">>, <<"d">>], <<"[]">>, [global, {insert_replaced, 1}]).
      +4> binary:replace(<<"abcde">>, [<<"b">>, <<"d">>], <<"[]">>, [global, {insert_replaced, 1}]).
       <<"a[b]c[d]e">>
       
      -5> binary:replace(<<"abcde">>, [<<"b">>, <<"d">>], <<"[]">>, [global, {insert_replaced, [1, 1]}]).
      +5> binary:replace(<<"abcde">>, [<<"b">>, <<"d">>], <<"[]">>, [global, {insert_replaced, [1, 1]}]).
       <<"a[bb]c[dd]e">>
       
      -6> binary:replace(<<"abcde">>, [<<"b">>, <<"d">>], <<"[-]">>, [global, {insert_replaced, [1, 2]}]).
      +6> binary:replace(<<"abcde">>, [<<"b">>, <<"d">>], <<"[-]">>, [global, {insert_replaced, [1, 2]}]).
       <<"a[b-b]c[d-d]e">>
       
      -7> binary:replace(<<"abcde">>, [<<"b">>, <<"d">>], fun(M) -> <<$[, M/binary, $]>> end, []).
      +7> binary:replace(<<"abcde">>, [<<"b">>, <<"d">>], fun(M) -> <<$[, M/binary, $]>> end, []).
       <<"a[b]cde">>
       
      -8> binary:replace(<<"abcde">>, [<<"b">>, <<"d">>], fun(M) -> <<$[, M/binary, $]>> end, [global]).
      +8> binary:replace(<<"abcde">>, [<<"b">>, <<"d">>], fun(M) -> <<$[, M/binary, $]>> end, [global]).
       <<"a[b]c[d]e">>
      @@ -1741,20 +1741,20 @@

      split(Subject, Pattern, Options)

      Splits Subject into a list of binaries based on Pattern.

      If option global is not specified, only the first occurrence of Pattern in -Subject gives rise to a split.

      The parts of Pattern found in Subject are not included in the result.

      Example:

      1> binary:split(<<1,255,4,0,0,0,2,3>>, [<<0,0,0>>,<<2>>],[]).
      -[<<1,255,4>>, <<2,3>>]
      -2> binary:split(<<0,1,0,0,4,255,255,9>>, [<<0,0>>, <<255,255>>],[global]).
      -[<<0,1>>,<<4>>,<<9>>]

      Summary of options:

      • {scope, part()} - Works as in match/3 and matches/3. Notice that +Subject gives rise to a split.

        The parts of Pattern found in Subject are not included in the result.

        Example:

        1> binary:split(<<1,255,4,0,0,0,2,3>>, [<<0,0,0>>,<<2>>],[]).
        +[<<1,255,4>>, <<2,3>>]
        +2> binary:split(<<0,1,0,0,4,255,255,9>>, [<<0,0>>, <<255,255>>],[global]).
        +[<<0,1>>,<<4>>,<<9>>]

        Summary of options:

        • {scope, part()} - Works as in match/3 and matches/3. Notice that this only defines the scope of the search for matching strings, it does not cut the binary before splitting. The bytes before and after the scope are kept in the result. See the example below.

        • trim - Removes trailing empty parts of the result (as does trim in re:split/3.

        • trim_all - Removes all empty parts of the result.

        • global - Repeats the split until Subject is exhausted. Conceptually option global makes split work on the positions returned by matches/3, while it normally works on the position returned by match/3.

        Example of the difference between a scope and taking the binary apart before -splitting:

        1> binary:split(<<"banana">>, [<<"a">>],[{scope,{2,3}}]).
        -[<<"ban">>,<<"na">>]
        -2> binary:split(binary:part(<<"banana">>,{2,3}), [<<"a">>],[]).
        -[<<"n">>,<<"n">>]

        The return type is always a list of binaries that are all referencing Subject. +splitting:

        1> binary:split(<<"banana">>, [<<"a">>],[{scope,{2,3}}]).
        +[<<"ban">>,<<"na">>]
        +2> binary:split(binary:part(<<"banana">>,{2,3}), [<<"a">>],[]).
        +[<<"n">>,<<"n">>]

        The return type is always a list of binaries that are all referencing Subject. This means that the data in Subject is not copied to new binaries, and that Subject cannot be garbage collected until the results of the split are no longer referenced.

        For a description of Pattern, see compile_pattern/1.

        diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/c.html b/prs/9045/lib/stdlib-6.1.2/doc/html/c.html index 97d07fa8a915..79c49022c6d8 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/c.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/c.html @@ -1764,7 +1764,7 @@

        nc(File, Options)

        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])
        diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/calendar.html b/prs/9045/lib/stdlib-6.1.2/doc/html/calendar.html index 773654f51e3c..217fc30318b1 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/calendar.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/calendar.html @@ -1851,13 +1851,13 @@

        rfc3339_to_system_time(DateTimeString, Opti

        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
      @@ -2029,19 +2029,19 @@

      system_time_to_rfc3339(Time, Options)

      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}]).
    +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">>
    diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/custom_shell.html b/prs/9045/lib/stdlib-6.1.2/doc/html/custom_shell.html index 3d7a75413e50..26f11ecd0bee 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/custom_shell.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/custom_shell.html @@ -158,20 +158,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).
    -
    -loop() ->
    -    receive _M -> loop() end.

    If we run the above we will get this:

    $ ./pshell.es
    +-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
     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
    @@ -188,32 +188,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]).
    -
    -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) ->
    +    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) ->
         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]
     
    @@ -233,28 +233,28 @@ 

    <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;

    @@ -264,31 +264,31 @@

    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"]).
    -
    -expand_fun(_Curr, []) ->
    -    {no, "", []};
    -expand_fun(Curr, [Cmd | T]) ->
    -    case lists:prefix(Curr, Cmd) of
    +-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
             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 diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/dets.html b/prs/9045/lib/stdlib-6.1.2/doc/html/dets.html index d764a04971f4..86ddb28baf4d 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/dets.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/dets.html @@ -1920,14 +1920,14 @@

    lookup(Name, Key)

    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 @@ -2784,11 +2784,11 @@

    table(Name, Options)

    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.

    @@ -2862,7 +2862,7 @@

    traverse(Name, Fun)

    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.

    diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/dict.html b/prs/9045/lib/stdlib-6.1.2/doc/html/dict.html index ed7d139f3063..705fd801132f 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/dict.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/dict.html @@ -144,13 +144,13 @@

    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.

    @@ -911,10 +911,10 @@

    merge(Fun, Dict1, Dict2)

    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).
    @@ -1127,8 +1127,8 @@

    update(Key, Fun, Initial, Dict1)

    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).
    @@ -1159,8 +1159,8 @@

    update_counter(Key, Increment, Dict1)

    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).
    diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/dist/search_data-6D22CF61.js b/prs/9045/lib/stdlib-6.1.2/doc/html/dist/search_data-D370A15C.js similarity index 65% rename from prs/9045/lib/stdlib-6.1.2/doc/html/dist/search_data-6D22CF61.js rename to prs/9045/lib/stdlib-6.1.2/doc/html/dist/search_data-D370A15C.js index 20a7e3a74c0a..1e70c1d7aaca 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/dist/search_data-6D22CF61.js +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/dist/search_data-D370A15C.js @@ -1 +1 @@ -searchData={"items":[{"type":"module","doc":"Unix 'tar' utility for reading and writing tar archives.\n\nThis module archives and extract files to and from a tar file. This module\nsupports reading most common tar formats, namely v7, STAR, USTAR, and PAX, as\nwell as some of GNU tar's extensions to the USTAR format (sparse files most\nnotably). It produces tar archives in USTAR format, unless the files being\narchived require PAX format due to restrictions in USTAR (such as unicode\nmetadata, filename length, and more). As such, `erl_tar` supports tar archives\nproduced by most all modern tar utilities, and produces tarballs which should be\nsimilarly portable.\n\nBy convention, the name of a tar file is to end in \"`.tar`\". To abide to the\nconvention, add \"`.tar`\" to the name.\n\nTar files can be created in one operation using function `create/2` or\n`create/3`.\n\nAlternatively, for more control, use functions `open/2`, [`add/3,4`](`add/3`),\nand `close/1`.\n\nTo extract all files from a tar file, use function `extract/1`. To extract only\nsome files or to be able to specify some more options, use function `extract/2`.\n\nTo return a list of the files in a tar file, use function `table/1` or\n`table/2`. To print a list of files to the Erlang shell, use function `t/1` or\n`tt/1`.\n\nTo convert an error term returned from one of the functions above to a readable\nmessage, use function `format_error/1`.","title":"erl_tar","ref":"erl_tar.html"},{"type":"module","doc":"If `file:native_name_encoding/0` returns `utf8`, path names are encoded in UTF-8\nwhen creating tar files, and path names are assumed to be encoded in UTF-8 when\nextracting tar files.\n\nIf `file:native_name_encoding/0` returns `latin1`, no translation of path names\nis done.\n\nUnicode metadata stored in PAX headers is preserved","title":"Unicode Support - erl_tar","ref":"erl_tar.html#module-unicode-support"},{"type":"module","doc":"The `m:ftp` module normally accesses the tar file on disk using the `m:file`\nmodule. When other needs arise, you can define your own low-level Erlang\nfunctions to perform the writing and reading on the storage media; use function\n`init/3`.\n\nAn example of this is the SFTP support in `ssh_sftp:open_tar/3`. This function\nopens a tar file on a remote machine using an SFTP channel.","title":"Other Storage Media - erl_tar","ref":"erl_tar.html#module-other-storage-media"},{"type":"module","doc":"- If you must remain compatible with the USTAR tar format, you must ensure file\n paths being stored are less than 255 bytes in total, with a maximum filename\n component length of 100 bytes. USTAR uses a header field (prefix) in addition\n to the name field, and splits file paths longer than 100 bytes into two parts.\n This split is done on a directory boundary, and is done in such a way to make\n the best use of the space available in those two fields, but in practice this\n will often mean that you have less than 255 bytes for a path. `erl_tar` will\n automatically upgrade the format to PAX to handle longer filenames, so this is\n only an issue if you need to extract the archive with an older implementation\n of `erl_tar` or `tar` which does not support PAX. In this case, the PAX\n headers will be extracted as regular files, and you will need to apply them\n manually.\n- Like the above, if you must remain USTAR compatible, you must also ensure that\n paths for symbolic/hard links are no more than 100 bytes, otherwise PAX\n headers will be used.","title":"Limitations - erl_tar","ref":"erl_tar.html#module-limitations"},{"type":"function","doc":"Equivalent to `add/4`.\n\nIf `Name` is `t:name_in_archive/0`, then [`add(TarDescriptor, Name, Name, Options)`](`add/4`) is called.\n\nIf `Name` is a two tuple then [`add(TarDescriptor, NameInArchive, Name, Options)`](`add/4`) is called.","title":"erl_tar.add/3","ref":"erl_tar.html#add/3"},{"type":"function","doc":"Adds a file to a tar file that has been opened for writing by\n[`open/1`](`open/2`).\n\n`NameInArchive` is the name under which the file becomes stored in the tar file.\nThe file gets this name when it is extracted from the tar file.\n\nOptions:\n\n- **`dereference`** - By default, symbolic links are stored as symbolic links in\n the tar file. To override the default and store the file that the symbolic\n link points to into the tar file, use option `dereference`.\n\n- **`verbose`** - Prints an informational message about the added file.\n\n- **`{chunks,ChunkSize}`** - Reads data in parts from the file. This is intended\n for memory-limited machines that, for example, builds a tar file on a remote\n machine over SFTP, see `ssh_sftp:open_tar/3`.\n\n- **`{atime,non_neg_integer()}`** - Sets the last time, as\n [POSIX time](`e:erts:time_correction.md#posix-time`), when the file was read.\n See also `file:read_file_info/1`.\n\n- **`{mtime,non_neg_integer()}`** - Sets the last time, as\n [POSIX time](`e:erts:time_correction.md#posix-time`), when the file was\n written. See also `file:read_file_info/1`.\n\n- **`{ctime,non_neg_integer()}`** - Sets the time, as\n [POSIX time](`e:erts:time_correction.md#posix-time`), when the file was\n created. See also `file:read_file_info/1`.\n\n- **`{uid,non_neg_integer()}`** - Sets the file owner. `file:read_file_info/1`.\n\n- **`{gid,non_neg_integer()}`** - Sets the group that the file owner belongs to.\n `file:read_file_info/1`.","title":"erl_tar.add/4","ref":"erl_tar.html#add/4"},{"type":"function","doc":"Closes a tar file opened by `open/2`.","title":"erl_tar.close/1","ref":"erl_tar.html#close/1"},{"type":"function","doc":"Creates a tar file and archives the files whose names are specified in\n`FileList` into it. The files can either be read from disk or be specified as\nbinaries.","title":"erl_tar.create/2","ref":"erl_tar.html#create/2"},{"type":"function","doc":"Creates a tar file and archives the files whose names are specified in\n`FileList` into it. The files can either be read from disk or be specified as\nbinaries.\n\nThe options in `OptionList` modify the defaults as follows:\n\n- **`compressed`** - The entire tar file is compressed, as if it has been run\n through the `gzip` program. To abide to the convention that a compressed tar\n file is to end in \"`.tar.gz`\" or \"`.tgz`\", add the appropriate extension.\n\n- **`cooked`** - By default, function [`open/2`](`open/2`) opens the tar file in\n `raw` mode, which is faster but does not allow a remote (Erlang) file server\n to be used. Adding `cooked` to the mode list overrides the default and opens\n the tar file without option `raw`.\n\n- **`dereference`** - By default, symbolic links are stored as symbolic links in\n the tar file. To override the default and store the file that the symbolic\n link points to into the tar file, use option `dereference`.\n\n- **`verbose`** - Prints an informational message about each added file.","title":"erl_tar.create/3","ref":"erl_tar.html#create/3"},{"type":"function","doc":"Extracts all files from a tar archive.\n\nIf argument `Name` is specified as `{binary,Binary}`, the contents of the binary\nis assumed to be a tar archive.\n\nIf argument `Name` is specified as `{file,Fd}`, `Fd` is assumed to be a file\ndescriptor returned from function `file:open/2`.\n\nOtherwise, `Name` is to be a filename.\n\n> #### Note {: .info }\n>\n> Leading slashes in tar member names will be removed before writing the file.\n> That is, absolute paths will be turned into relative paths. There will be an\n> info message written to the error logger when paths are changed in this way.\n\n> #### Warning {: .warning }\n>\n> The `compressed` and `cooked` flags are invalid when passing a file descriptor\n> with `{file,Fd}`. The file is assumed to have been opened with the appropriate\n> flags.","title":"erl_tar.extract/1","ref":"erl_tar.html#extract/1"},{"type":"function","doc":"Extracts files from a tar archive.\n\nIf argument `Name` is specified as `{binary,Binary}`, the contents of the binary\nis assumed to be a tar archive.\n\nIf argument `Name` is specified as `{file,Fd}`, `Fd` is assumed to be a file\ndescriptor returned from function `file:open/2`.\n\nOtherwise, `Name` is to be a filename.\n\nThe following options modify the defaults for the extraction as follows:\n\n- **`{cwd,Cwd}`** - Files with relative filenames are by default extracted to\n the current working directory. With this option, files are instead extracted\n into directory `Cwd`.\n\n- **`{files,FileList}`** - By default, all files are extracted from the tar\n file. With this option, only those files are extracted whose names are\n included in `FileList`.\n\n- **`compressed`** - With this option, the file is uncompressed while\n extracting. If the tar file is not compressed, this option is ignored.\n\n- **`cooked`** - By default, function [`open/2`](`open/2`) function opens the\n tar file in `raw` mode, which is faster but does not allow a remote (Erlang)\n file server to be used. Adding `cooked` to the mode list overrides the default\n and opens the tar file without option `raw`.\n\n- **`memory`** - Instead of extracting to a directory, this option gives the\n result as a list of tuples `{Filename, Binary}`, where `Binary` is a binary\n containing the extracted data of the file named `Filename` in the tar file.\n\n- **`keep_old_files`** - By default, all existing files with the same name as\n files in the tar file are overwritten. With this option, existing files are\n not overwriten.\n\n- **`verbose`** - Prints an informational message for each extracted file.\n\n> #### Warning {: .warning }\n>\n> The `compressed` and `cooked` flags are invalid when passing a file descriptor\n> with `{file,Fd}`. The file is assumed to have been opened with the appropriate\n> flags.","title":"erl_tar.extract/2","ref":"erl_tar.html#extract/2"},{"type":"function","doc":"Converts an error reason term to a human-readable error message string.","title":"erl_tar.format_error/1","ref":"erl_tar.html#format_error/1"},{"type":"function","doc":"The `Fun` is the definition of what to do when the different storage operations\nfunctions are to be called from the higher tar handling functions (such as\n[`add/3`](`add/3`), [`add/4`](`add/4`), and [`close/1`](`close/1`)).\n\nThe `Fun` is called when the tar function wants to do a low-level operation,\nlike writing a block to a file. The `Fun` is called as\n`Fun(Op, {UserData,Parameters...})`, where `Op` is the operation name,\n`UserData` is the term passed as the first argument to `init/1` and\n`Parameters...` are the data added by the tar function to be passed down to the\nstorage handling function.\n\nParameter `UserData` is typically the result of opening a low-level structure\nlike a file descriptor or an SFTP channel id. The different `Fun` clauses\noperate on that very term.\n\nThe following are the fun clauses parameter lists:\n\n- **`(write, {UserData,DataToWrite})`** - Writes term `DataToWrite` using\n `UserData`.\n\n- **`(close, UserData)`** - Closes the access.\n\n- **`(read2, {UserData,Size})`** - Reads using `UserData` but only `Size` bytes.\n Notice that there is only an arity-2 read function, not an arity-1 function.\n\n- **`(position,{UserData,Position})`** - Sets the position of `UserData` as\n defined for files in `file:position/2`\n\n_Example:_\n\nThe following is a complete `Fun` parameter for reading and writing on files\nusing the `m:file` module:\n\n```erlang\nExampleFun =\n fun(write, {Fd,Data}) -> file:write(Fd, Data);\n (position, {Fd,Pos}) -> file:position(Fd, Pos);\n (read2, {Fd,Size}) -> file:read(Fd, Size);\n (close, Fd) -> file:close(Fd)\n end\n```\n\nHere `Fd` was specified to function [`init/3`](`init/3`) as:\n\n```erlang\n{ok,Fd} = file:open(Name, ...).\n{ok,TarDesc} = erl_tar:init(Fd, [write], ExampleFun),\n```\n\n`TarDesc` is then used:\n\n```erlang\nerl_tar:add(TarDesc, SomeValueIwantToAdd, FileNameInTarFile),\n...,\nerl_tar:close(TarDesc)\n```\n\nWhen the `erl_tar` core wants to, for example, write a piece of `Data`, it would\ncall `ExampleFun(write, {UserData,Data})`.\n\n> #### Note {: .info }\n>\n> This example with the `file` module operations is not necessary to use\n> directly, as that is what function `open/2` in principle does.\n\n> #### Warning {: .warning }\n>\n> The `TarDescriptor` term is not a file descriptor. You are advised not to rely\n> on the specific contents of this term, as it can change in future Erlang/OTP\n> releases when more features are added to this module.","title":"erl_tar.init/3","ref":"erl_tar.html#init/3"},{"type":"function","doc":"Creates a tar file for writing (any existing file with the same name is\ntruncated).\n\nBy convention, the name of a tar file is to end in \"`.tar`\". To abide to the\nconvention, add \"`.tar`\" to the name.\n\nExcept for the `write` atom, the following atoms can be added to `OpenModeList`:\n\n- **`compressed`** - The entire tar file is compressed, as if it has been run\n through the `gzip` program. To abide to the convention that a compressed tar\n file is to end in \"`.tar.gz`\" or \"`.tgz`\", add the appropriate extension.\n\n- **`cooked`** - By default, the tar file is opened in `raw` mode, which is\n faster but does not allow a remote (Erlang) file server to be used. Adding\n `cooked` to the mode list overrides the default and opens the tar file without\n option `raw`.\n\nTo add one file at the time into an opened tar file, use function\n[`add/3,4`](`add/3`). When you are finished adding files, use function `close/1`\nto close the tar file.\n\n> #### Warning {: .warning }\n>\n> The `compressed` and `cooked` flags are invalid when passing a file descriptor\n> with `{file,Fd}`. The file must already be opened with the appropriate flags.\n\n> #### Warning {: .warning }\n>\n> The `TarDescriptor` term is not a file descriptor. You are advised not to rely\n> on the specific contents of this term, as it can change in future Erlang/OTP\n> releases when more features are added to this module.","title":"erl_tar.open/2","ref":"erl_tar.html#open/2"},{"type":"function","doc":"Prints the names of all files in the tar file `Name` to the Erlang shell\n(similar to \"`tar t`\").","title":"erl_tar.t/1","ref":"erl_tar.html#t/1"},{"type":"function","doc":"","title":"erl_tar.table/1","ref":"erl_tar.html#table/1"},{"type":"function","doc":"Retrieves the names of all files in the tar file `Name`.","title":"erl_tar.table/2","ref":"erl_tar.html#table/2"},{"type":"function","doc":"Prints names and information about all files in the tar file `Name` to the\nErlang shell (similar to \"`tar tv`\").","title":"erl_tar.tt/1","ref":"erl_tar.html#tt/1"},{"type":"type","doc":"","title":"erl_tar.add_opt/0","ref":"erl_tar.html#t:add_opt/0"},{"type":"type","doc":"","title":"erl_tar.create_opt/0","ref":"erl_tar.html#t:create_opt/0"},{"type":"type","doc":"","title":"erl_tar.extract_opt/0","ref":"erl_tar.html#t:extract_opt/0"},{"type":"type","doc":"","title":"erl_tar.file_op/0","ref":"erl_tar.html#t:file_op/0"},{"type":"type","doc":"","title":"erl_tar.filelist/0","ref":"erl_tar.html#t:filelist/0"},{"type":"type","doc":"","title":"erl_tar.gid/0","ref":"erl_tar.html#t:gid/0"},{"type":"type","doc":"","title":"erl_tar.mode/0","ref":"erl_tar.html#t:mode/0"},{"type":"type","doc":"","title":"erl_tar.name_in_archive/0","ref":"erl_tar.html#t:name_in_archive/0"},{"type":"type","doc":"","title":"erl_tar.open_type/0","ref":"erl_tar.html#t:open_type/0"},{"type":"opaque","doc":"","title":"erl_tar.tar_descriptor/0","ref":"erl_tar.html#t:tar_descriptor/0"},{"type":"type","doc":"","title":"erl_tar.tar_entry/0","ref":"erl_tar.html#t:tar_entry/0"},{"type":"type","doc":"","title":"erl_tar.tar_time/0","ref":"erl_tar.html#t:tar_time/0"},{"type":"type","doc":"","title":"erl_tar.typeflag/0","ref":"erl_tar.html#t:typeflag/0"},{"type":"type","doc":"","title":"erl_tar.uid/0","ref":"erl_tar.html#t:uid/0"},{"type":"type","doc":"","title":"erl_tar.user_data/0","ref":"erl_tar.html#t:user_data/0"},{"type":"module","doc":"Pseudo random number generation\n\nThis module provides pseudo random number generation and implements\na number of base generator algorithms. Most are provided through\na [plug-in framework](#plug-in-framework) that adds\nfeatures to the base generators.\n\nAt the end of this module documentation there are some\n[niche algorithms](#niche-algorithms) that don't use\nthis module's normal [plug-in framework](#plug-in-framework).\nThey may be useful for special purposes like short generation time\nwhen quality is not essential, for seeding other generators, and such.\n\n[](){: #plug-in-framework } Plug-in framework\n---------------------------------------------\n\nThe [plug-in framework](#plug-in-framework-api) implements\na common [API](#plug-in-framework-api) to, and enhancements\nof the base generators:\n\n* Operating on a generator state in the\n [process dictionary](#generator-state).\n* [Automatic](#generator-state) [seeding](`seed/1`).\n* Manual [seeding support](`seed/2`) to avoid common pitfalls.\n* Generating [integers](`t:integer/0`) in any range, with\n [uniform distribution](`uniform/1`), without noticable bias.\n* Generating [integers](`t:integer/0`) in any range, larger than\n the base generator's, with [uniform distribution](`uniform/1`).\n* Generating [floating-point numbers](`t:float/0`) with\n [uniform distribution](`uniform/0`).\n* Generating [floating-point numbers](`t:float/0`) with\n [normal distribution](`normal/0`).\n* Generating any number of [bytes](`bytes/1`).\n\nThe base generator algorithms implements the\n[Xoroshiro and Xorshift algorithms](http://xorshift.di.unimi.it)\nby Sebastiano Vigna. During an iteration they generate a large integer\n(at least 58-bit) and operate on a state of several large integers.\n\nTo create numbers with normal distribution the\n[Ziggurat Method by Marsaglia and Tsang](http://www.jstatsoft.org/v05/i08)\nis used on the output from a base generator.\n\nFor most algorithms, jump functions are provided for generating\nnon-overlapping sequences. A jump function perform a calculation\nequivalent to a large number of repeated state iterations,\nbut execute in a time roughly equivalent to one regular iteration\nper generator bit.\n\n[](){: #algorithms } The following algorithms are provided:\n\n- **`exsss`**, the [_default algorithm_](#default-algorithm)\n *(Since OTP 22.0)* \n Xorshift116\\*\\*, 58 bits precision and period of 2^116-1\n\n Jump function: equivalent to 2^64 calls\n\n This is the Xorshift116 generator combined with the StarStar scrambler from\n the 2018 paper by David Blackman and Sebastiano Vigna:\n [Scrambled Linear Pseudorandom Number Generators](http://vigna.di.unimi.it/ftp/papers/ScrambledLinear.pdf)\n\n The generator doesn't use 58-bit rotates so it is faster than the\n Xoroshiro116 generator, and when combined with the StarStar scrambler\n it doesn't have any weak low bits like `exrop` (Xoroshiro116+).\n\n Alas, this combination is about 10% slower than `exrop`, but despite that\n it is the [_default algorithm_](#default-algorithm) thanks to\n its statistical qualities.\n\n- **`exro928ss`** *(Since OTP 22.0)* \n Xoroshiro928\\*\\*, 58 bits precision and a period of 2^928-1\n\n Jump function: equivalent to 2^512 calls\n\n This is a 58 bit version of Xoroshiro1024\\*\\*, from the 2018 paper by\n David Blackman and Sebastiano Vigna:\n [Scrambled Linear Pseudorandom Number Generators](http://vigna.di.unimi.it/ftp/papers/ScrambledLinear.pdf)\n that on a 64 bit Erlang system executes only about 40% slower than the\n [*default `exsss` algorithm*](#default-algorithm)\n but with much longer period and better statistical properties,\n but on the flip side a larger state.\n\n Many thanks to Sebastiano Vigna for his help with the 58 bit adaption.\n\n- **`exrop`** *(Since OTP 20.0)* \n Xoroshiro116+, 58 bits precision and period of 2^116-1\n\n Jump function: equivalent to 2^64 calls\n\n- **`exs1024s`** *(Since OTP 20.0)* \n Xorshift1024\\*, 64 bits precision and a period of 2^1024-1\n\n Jump function: equivalent to 2^512 calls\n\n- **`exsp`** *(Since OTP 20.0)* \n Xorshift116+, 58 bits precision and period of 2^116-1\n\n Jump function: equivalent to 2^64 calls\n\n This is a corrected version of a previous\n [_default algorithm_](#default-algorithm) (`exsplus`, _deprecated_),\n that was superseded by Xoroshiro116+ (`exrop`). Since this algorithm\n doesn't use rotate it executes a little (say < 15%) faster than `exrop`\n (that has to do a 58 bit rotate, for which there is no native instruction).\n See the [algorithms' homepage](http://xorshift.di.unimi.it).\n\n[](){: #default-algorithm }\n#### Default Algorithm\n\nThe current _default algorithm_ is\n[`exsss` (Xorshift116\\*\\*)](#algorithms). If a specific algorithm is\nrequired, ensure to always use `seed/1` to initialize the state.\n\nWhich algorithm that is the default may change between Erlang/OTP releases,\nand is selected to be one with high speed, small state and \"good enough\"\nstatistical properties.\n\n#### Old Algorithms\n\nUndocumented (old) algorithms are deprecated but still implemented so old code\nrelying on them will produce the same pseudo random sequences as before.\n\n> #### Note {: .info }\n>\n> There were a number of problems in the implementation of\n> the now undocumented algorithms, which is why they are deprecated.\n> The new algorithms are a bit slower but do not have these problems:\n>\n> Uniform integer ranges had a skew in the probability distribution\n> that was not noticable for small ranges but for large ranges\n> less than the generator's precision the probability to produce\n> a low number could be twice the probability for a high.\n>\n> Uniform integer ranges larger than or equal to the generator's precision\n> used a floating point fallback that only calculated with 52 bits\n> which is smaller than the requested range and therefore all numbers\n> in the requested range weren't even possible to produce.\n>\n> Uniform floats had a non-uniform density so small values for example\n> less than 0.5 had got smaller intervals decreasing as the generated value\n> approached 0.0 although still uniformly distributed for sufficiently large\n> subranges. The new algorithms produces uniformly distributed floats\n> on the form `N * 2.0^(-53)` hence they are equally spaced.\n\n[](){: #generator-state }\n#### Generator State\n\nEvery time a random number is generated, a state is used to calculate it,\nproducing a new state. The state can either be implicit\nor be an explicit argument and return value.\n\nThe functions with implicit state operates on a state stored\nin the process dictionary under the key `rand_seed`. If that key\ndoesn't exist when the function is called, `seed/1` is called automatically\nwith the [_default algorithm_](#default-algorithm) and creates\na reasonably unpredictable seed.\n\nThe functions with explicit state don't use the process dictionary.\n\n#### _Examples_\n\nSimple use; create and seed the\n[_default algorithm_](#default-algorithm) with a non-fixed seed,\nif not already done, and generate two uniformly distibuted\nfloating point numbers.\n\n```erlang\nR0 = rand:uniform(),\nR1 = rand:uniform(),\n```\n\nUse a specified algorithm:\n\n```erlang\n_ = rand:seed(exro928ss),\nR2 = rand:uniform(),\n```\n\nUse a specified algorithm with a fixed seed:\n\n```erlang\n_ = rand:seed(exro928ss, {123, 123534, 345345}),\nR3 = rand:uniform(),\n```\n\nUse the functional API with a non-fixed seed:\n\n```erlang\nS0 = rand:seed_s(exsss),\n{R4, S1} = rand:uniform_s(S0),\n```\n\nGenerate a textbook basic form Box-Muller standard normal distribution number:\n\n```erlang\nR5 = rand:uniform_real(),\nR6 = rand:uniform(),\nSND0 = math:sqrt(-2 * math:log(R5)) * math:cos(math:pi() * R6)\n```\n\nGenerate a standard normal distribution number:\n\n```erlang\n{SND1, S2} = rand:normal_s(S1),\n```\n\nGenerate a normal distribution number with with mean -3 and variance 0.5:\n\n```erlang\n{ND0, S3} = rand:normal_s(-3, 0.5, S2),\n```\n\n#### Quality of the Generated Numbers\n\n> #### Note {: .info }\n>\n> The builtin random number generator algorithms are not cryptographically\n> strong. If a cryptographically strong random number generator is needed,\n> use something like `crypto:rand_seed/0`.\n\nFor all these generators except `exro928ss` and `exsss` the lowest bit(s)\nhave got a slightly less random behaviour than all other bits.\n1 bit for `exrop` (and `exsp`), and 3 bits for `exs1024s`. See for example\nthis explanation in the\n[Xoroshiro128+](http://xoroshiro.di.unimi.it/xoroshiro128plus.c)\ngenerator source code:\n\n> Beside passing BigCrush, this generator passes the PractRand test suite\n> up to (and included) 16TB, with the exception of binary rank tests,\n> which fail due to the lowest bit being an LFSR; all other bits pass all\n> tests. We suggest to use a sign test to extract a random Boolean value.\n\nIf this is a problem; to generate a boolean with these algorithms,\nuse something like this:\n\n```erlang\n(rand:uniform(256) > 128) % -> boolean()\n```\n\n```erlang\n((rand:uniform(256) - 1) bsr 7) % -> 0 | 1\n```\n\nFor a general range, with `N = 1` for `exrop`, and `N = 3` for `exs1024s`:\n\n```erlang\n(((rand:uniform(Range bsl N) - 1) bsr N) + 1)\n```\n\nThe floating point generating functions in this module waste the lowest bits\nwhen converting from an integer so they avoid this snag.\n\n\n[](){: #niche-algorithms } Niche algorithms\n-------------------------------------------\n\nThe [niche algorithms API](#niche-algorithms-api) contains\nspecial purpose algorithms that don't use the\n[plug-in framework](#plug-in-framework), mainly for performance reasons.\n\nSince these algorithms lack the plug-in framework support, generating numbers\nin a range other than the base generator's range may become a problem.\n\nThere are at least four ways to do this, assuming the `Range` is less than\nthe generator's range:\n\n[](){: #modulo-method }\n- **Modulo** \n To generate a number `V` in the range `0..Range-1`:\n\n > Generate a number `X`. \n > Use `V = X rem Range` as your value.\n\n This method uses `rem`, that is, the remainder of an integer division,\n which is a slow operation.\n\n Low bits from the generator propagate straight through to\n the generated value, so if the generator has got weaknesses\n in the low bits this method propagates them too.\n\n If `Range` is not a divisor of the generator range, the generated numbers\n have a bias. Example:\n\n Say the generator generates a byte, that is, the generator range\n is `0..255`, and the desired range is `0..99` (`Range = 100`).\n Then there are 3 generator outputs that produce the value `0`,\n these are; `0`, `100` and `200`.\n But there are only 2 generator outputs that produce the value `99`,\n which are; `99` and `199`. So the probability for a value `V` in `0..55`\n is 3/2 times the probability for the other values `56..99`.\n\n If `Range` is much smaller than the generator range, then this bias\n gets hard to detect. The rule of thumb is that if `Range` is smaller\n than the square root of the generator range, the bias is small enough.\n Example:\n\n A byte generator when `Range = 20`. There are 12 (`256 div 20`)\n possibilities to generate the highest numbers and one more to generate\n a number `V < 16` (`256 rem 20`). So the probability is 13/12\n for a low number versus a high. To detect that difference with\n some confidence you would need to generate a lot more numbers\n than the generator range, `256` in this small example.\n\n[](){: #truncated-multiplication-method }\n- **Truncated multiplication** \n To generate a number `V` in the range `0..Range-1`, when you have\n a generator with a power of 2 range (`0..2^Bits-1`):\n\n > Generate a number `X`. \n > Use `V = X * Range bsr Bits` as your value.\n\n If the multiplication `X * Range` creates a bignum\n this method becomes very slow.\n\n High bits from the generator propagate through to the generated value,\n so if the generator has got weaknesses in the high bits this method\n propagates them too.\n\n If `Range` is not a divisor of the generator range, the generated numbers\n have a bias, pretty much as for the [Modulo](#modulo-method) method above.\n\n[](){: #shift-or-mask-method }\n- **Shift or mask** \n To generate a number in a power of 2 range (`0..2^RBits-1`),\n when you have a generator with a power of 2 range (`0..2^Bits`):\n\n > Generate a number `X`. \n > Use `V = X band ((1 bsl RBits)-1)` or `V = X bsr (Bits-RBits)`\n > as your value.\n\n Masking with `band` preserves the low bits, and right shifting\n with `bsr` preserves the high, so if the generator has got weaknesses\n in high or low bits; choose the right operator.\n\n If the generator has got a range that is not a power of 2\n and this method is used anyway, it introduces bias in the same way\n as for the [Modulo](#modulo-method) method above.\n\n[](){: #rejection-method }\n- **Rejection** \n\n > Generate a number `X`. \n > If `X` is in the range, use it as your value,\n > otherwise reject it and repeat.\n\n In theory it is not certain that this method will ever complete,\n but in practice you ensure that the probability of rejection is low.\n Then the probability for yet another iteration decreases exponentially\n so the expected mean number of iterations will often be between 1 and 2.\n Also, since the base generator is a full length generator,\n a value that will break the loop must eventually be generated.\n\n These methods can be combined, such as using\n the [Modulo](#modulo-method) method and only if the generator value\n would create bias use [Rejection](#rejection-method).\n Or using [Shift or mask](#shift-or-mask-method) to reduce the size\n of a generator value so that\n [Truncated multiplication](#truncated-multiplication-method)\n will not create a bignum.\n\n The recommended way to generate a floating point number\n (IEEE 745 Double, that has got a 53-bit mantissa) in the range\n `0..1`, that is `0.0 =< V < 1.0` is to generate a 53-bit number `X`\n and then use `V = X * (1.0/((1 bsl 53)))` as your value.\n This will create a value on the form N*2^-53 with equal probability\n for every possible N for the range.","title":"rand","ref":"rand.html"},{"type":"function","doc":"Generate random bytes as a `t:binary()`,\nusing the state in the process dictionary.\n\nLike `bytes_s/2` but operates on the state stored in\nthe process dictionary. Returns the generated [`Bytes`](`t:binary/0`).","title":"rand.bytes/1","ref":"rand.html#bytes/1"},{"type":"function","doc":"Generate random bytes as a `t:binary()`.\n\nFor a specified integer `N >= 0`, generates a `t:binary/0`\nwith that number of random bytes.\n\nThe selected algorithm is used to generate as many random numbers\nas required to compose the `t:binary/0`. Returns the generated\n[`Bytes`](`t:binary/0`) and a [`NewState`](`t:state/0`).","title":"rand.bytes_s/2","ref":"rand.html#bytes_s/2"},{"type":"function","doc":"Export the seed value.\n\nReturns the random number state in an external format.\nTo be used with `seed/1`.","title":"rand.export_seed/0","ref":"rand.html#export_seed/0"},{"type":"function","doc":"Export the seed value.\n\nReturns the random number generator state in an external format.\nTo be used with `seed/1`.","title":"rand.export_seed_s/1","ref":"rand.html#export_seed_s/1"},{"type":"function","doc":"Jump the generator state forward.\n\nPerforms a [`State`](`t:state/0`) jump calculation\nthat is equvalent to a 2^64 state iterations.\n\nReturns the [`NewState`](`t:state/0`).\n\nThis feature can be used to create many non-overlapping\nrandom number sequences from one start state.\n\nSee the description of jump functions at the top of this module description.\n\nSee `exsp_next/1` about why this internal implementation function\nhas been exposed.","title":"rand.exsp_jump/1","ref":"rand.html#exsp_jump/1"},{"type":"function","doc":"Generate an Xorshift116+ random integer and new algorithm state.\n\nFrom the specified [`AlgState`](`t:exsplus_state/0`),\ngenerates a random 58-bit integer [`X`](`t:uint58/0`)\nand a new algorithm state [`NewAlgState`](`t:exsplus_state/0`),\naccording to the Xorshift116+ algorithm.\n\nThis is an API function exposing the internal implementation of the\n[`exsp`](#algorithms) algorithm that enables using it without the\noverhead of the plug-in framework, which might be useful for time critial\napplications. On a typical 64 bit Erlang VM this approach executes\nin just above 30% (1/3) of the time for the default algorithm through\nthis module's normal plug-in framework.\n\nTo seed this generator use [`{_, AlgState} = rand:seed_s(exsp)`](`seed_s/1`)\nor [`{_, AlgState} = rand:seed_s(exsp, Seed)`](`seed_s/1`)\nwith a specific [`Seed`](`t:seed/0`).\n\n> #### Note {: .info }\n>\n> This function offers no help in generating a number on a selected range,\n> nor in generating floating point numbers. It is easy to accidentally\n> mess up the statistical properties of this generator or to loose\n> the performance advantage when doing either.\n> See the recepies at the start of this\n> [Niche algorithms API](#niche-algorithms-api) description.\n>\n> Note also the caveat about weak low bits that this generator suffers from.\n>\n> The generator is exported in this form primarily for performance reasons.","title":"rand.exsp_next/1","ref":"rand.html#exsp_next/1"},{"type":"function","doc":"Jump the generator state forward.\n\nLike `jump/1` but operates on the state stored in\nthe process dictionary. Returns the [`NewState`](`t:state/0`).","title":"rand.jump/0","ref":"rand.html#jump/0"},{"type":"function","doc":"Jump the generator state forward.\n\nPerforms an algorithm specific [`State`](`t:state/0`) jump calculation\nthat is equvalent to a large number of state iterations.\nSee this module's [algorithms list](#algorithms).\n\nReturns the [`NewState`](`t:state/0`).\n\nThis feature can be used to create many non-overlapping\nrandom number sequences from one start state.\n\nThis function raises a `not_implemented` error exception if there is\nno jump function implemented for the [`State`](`t:state/0`)'s algorithm.","title":"rand.jump/1","ref":"rand.html#jump/1"},{"type":"function","doc":"Generate a new MWC59 state.\n\nFrom the specified generator state [`CX0`](`t:mwc59_state/0`) generate\na new state [`CX1`](`t:mwc59_state/0`), according to a Multiply With Carry\ngenerator, which is an efficient implementation of\na Multiplicative Congruential Generator with a power of 2 multiplier\nand a prime modulus.\n\nThis generator uses the multiplier `2^32` and the modulus\n`16#7fa6502 * 2^32 - 1`, which have been selected, in collaboration with\nSebastiano Vigna, to avoid bignum operations and still get\ngood statistical quality. It has been named \"MWC59\" and can be written as:\n\n```erlang\nC = CX0 bsr 32\nX = CX0 band ((1 bsl 32)-1))\nCX1 = 16#7fa6502 * X + C\n```\n\nBecause the generator uses a multiplier that is a power of 2 it gets\nstatistical flaws for collision tests and birthday spacings tests\nin 2 and 3 dimensions, and these caveats apply even when looking\nonly at the MWC \"digit\", that is the low 32 bits (the multiplier)\nof the generator state. The higher bits of the state are worse.\n\nThe quality of the output value improves much by using a scrambler,\ninstead of just taking the low bits.\nFunction [`mwc59_value32`](`mwc59_value32/1`) is a fast scrambler\nthat returns a decent 32-bit number. The slightly slower\n[`mwc59_value`](`mwc59_value/1`) scrambler returns 59 bits of\nvery good quality, and [`mwc59_float`](`mwc59_float/1`) returns\na `t:float/0` of very good quality.\n\nThe low bits of the base generator are surprisingly good, so the lowest\n16 bits actually pass fairly strict PRNG tests, despite the generator's\nweaknesses that lie in the high bits of the 32-bit MWC \"digit\".\nIt is recommended to use `rem` on the the generator state, or bit mask\nextracting the lowest bits to produce numbers in a range 16 bits or less.\nSee the recepies at the start of this\n[Niche algorithms API](#niche-algorithms-api) description.\n\nOn a typical 64 bit Erlang VM this generator executes in below 8% (1/13)\nof the time for the default algorithm in the\n[plug-in framework API](#plug-in-framework-api) of this module.\nWith the [`mwc59_value32`](`mwc59_value32/1`) scrambler the total time\nbecomes 16% (1/6), and with [`mwc59_value`](`mwc59_value/1`)\nit becomes 20% (1/5) of the time for the default algorithm.\nWith [`mwc59_float`](`mwc59_float/1`) the total time\nis 60% of the time for the default algorithm generating a `t:float/0`.\n\n> #### Note {: .info }\n>\n> This generator is a niche generator for high speed applications.\n> It has a much shorter period than the default generator, which in itself\n> is a quality concern, although when used with the value scramblers\n> it passes strict PRNG tests. The generator is much faster than\n> `exsp_next/1` but with a bit lower quality and much shorter period.","title":"rand.mwc59/1","ref":"rand.html#mwc59/1"},{"type":"function","doc":"Calculate a scrambled `t:float/0` from a [MWC59 state](`t:mwc59_state/0`).\n\nReturns a value `V ::` `t:float/0` from a generator state `CX`,\nin the range `0.0 =< V < 1.0` like for example `uniform_s/1`.\n\nThe generator state is scrambled as with\n[`mwc59_value/1`](`mwc59_value/1`) before converted to a `t:float/0`.","title":"rand.mwc59_float/1","ref":"rand.html#mwc59_float/1"},{"type":"function","doc":"Create a [MWC59 generator state](`t:mwc59_state/0`).\n\nLike `mwc59_seed/1` but it hashes the default seed value\nof [`seed_s(atom())`](`seed_s/1`).","title":"rand.mwc59_seed/0","ref":"rand.html#mwc59_seed/0"},{"type":"function","doc":"Create a [MWC59 generator state](`t:mwc59_state/0`).\n\nReturns a generator state [`CX`](`t:mwc59_state/0`).\nThe 58-bit seed value `S` is hashed to create the generator state,\nto avoid that similar seeds create similar sequences.","title":"rand.mwc59_seed/1","ref":"rand.html#mwc59_seed/1"},{"type":"function","doc":"Calculate a 32-bit scrambled value from a [MWC59 state](`t:mwc59_state/0`).\n\nReturns a 32-bit value [`V`](`t:integer/0`) from a generator state `CX`.\nThe generator state is scrambled using an 8-bit xorshift which masks\nthe statistical imperfecions of the base generator [`mwc59`](`mwc59/1`)\nenough to produce numbers of decent quality. Still some problems\nin 2- and 3-dimensional birthday spacing and collision tests show through.\n\nWhen using this scrambler it is in general better to use the high bits of the\nvalue than the low. The lowest 8 bits are of good quality and are passed\nright through from the base generator. They are combined with the next 8\nin the xorshift making the low 16 good quality, but in the range\n16..31 bits there are weaker bits that should not become high bits\nof the generated values.\n\nTherefore it is in general safer to shift out low bits. See the recepies\nat the start of this [Niche algorithms API](#niche-algorithms-api)\ndescription.\n\nFor a non power of 2 range less than about 16 bits (to not get\ntoo much bias and to avoid bignums) truncated multiplication can be used,\nthat is: `(Range*V) bsr 32`, which is much faster than using `rem`.","title":"rand.mwc59_value32/1","ref":"rand.html#mwc59_value32/1"},{"type":"function","doc":"Calculate a 59-bit scrambled value from a [MWC59 state](`t:mwc59_state/0`).\n\nReturns a 59-bit value [`V`](`t:integer/0`) from a generator state `CX`.\nThe generator state is scrambled using an 4-bit followed by a 27-bit xorshift,\nwhich masks the statistical imperfecions of the [MWC59](`mwc59/1`)\nbase generator enough that all 59 bits are of very good quality.\n\nBe careful to not accidentaly create a bignum when handling the value `V`.\n\nIt is in general general better to use the high bits from this scrambler than\nthe low. See the recepies at the start of this\n[Niche algorithms API](#niche-algorithms-api) description.\n\nFor a non power of 2 range less than about 29 bits (to not get\ntoo much bias and to avoid bignums) truncated multiplication can be used,\nwhich is much faster than using `rem`. Example for range 1'000'000'000;\nthe range is 30 bits, we use 29 bits from the generator,\nadding up to 59 bits, which is not a bignum (on a 64-bit VM ):\n`(1000000000 * (V bsr (59-29))) bsr 29`.","title":"rand.mwc59_value/1","ref":"rand.html#mwc59_value/1"},{"type":"function","doc":"Generate a random number with standard normal distribution.\n\nLike `normal_s/1` but operates on the state stored in\nthe process dictionary. Returns the generated number `X`.","title":"rand.normal/0","ref":"rand.html#normal/0"},{"type":"function","doc":"Generate a random number with specified normal distribution 𝒩 *(μ, σ²)*.\n\nLike `normal_s/3` but operates on the state stored in\nthe process dictionary. Returns the generated number `X`.","title":"rand.normal/2","ref":"rand.html#normal/2"},{"type":"function","doc":"Generate a random number with standard normal distribution.\n\nFrom the specified `State`, generates a random number `X ::` `t:float/0`,\nwith standard normal distribution, that is with mean value `0.0`\nand variance `1.0`.\n\nReturns the generated number [`X`](`t:float/0`)\nand the [`NewState`](`t:state/0`).","title":"rand.normal_s/1","ref":"rand.html#normal_s/1"},{"type":"function","doc":"Generate a random number with specified normal distribution 𝒩 *(μ, σ²)*.\n\nFrom the specified `State`, generates a random number `X ::` `t:float/0`,\nwith normal distribution 𝒩 *(μ, σ²)*, that is 𝒩 (Mean, Variance)\nwhere `Variance >= 0.0`.\n\nReturns [`X`](`t:float/0`) and the [`NewState`](`t:state/0`).","title":"rand.normal_s/3","ref":"rand.html#normal_s/3"},{"type":"function","doc":"Seed the random number generator and select algorithm.\n\nThe same as [`seed_s(Alg_or_State)`](`seed_s/1`),\nbut also stores the generated state in the process dictionary.\n\nThe argument `default` is an alias for the\n[_default algorithm_](#default-algorithm)\nthat has been implemented *(Since OTP 24.0)*.","title":"rand.seed/1","ref":"rand.html#seed/1"},{"type":"function","doc":"Seed the random number generator and select algorithm.\n\nThe same as [`seed_s(Alg, Seed)`](`seed_s/2`),\nbut also stores the generated state in the process dictionary.\n\n`Alg = default` is an alias for the\n[_default algorithm_](#default-algorithm)\nthat has been implemented *(Since OTP 24.0)*.","title":"rand.seed/2","ref":"rand.html#seed/2"},{"type":"function","doc":"Seed the random number generator and select algorithm.\n\nWith the argument `Alg`, select that algorithm and seed random number\ngeneration with reasonably unpredictable time dependent data.\n\n`Alg = default` is an alias for the\n[_default algorithm_](#default-algorithm)\n*(Since OTP 24.0)*.\n\nWith the argument `State`, re-creates the state and returns it.\nSee also `export_seed/0`.","title":"rand.seed_s/1","ref":"rand.html#seed_s/1"},{"type":"function","doc":"Seed the random number generator and select algorithm.\n\nCreates and returns a generator state for the specified algorithm\nfrom the specified `t:seed/0` integers.\n\n`Alg = default` is an alias for the [_default algorithm_](#default-algorithm)\nthat has been implemented *since OTP 24.0*.","title":"rand.seed_s/2","ref":"rand.html#seed_s/2"},{"type":"function","doc":"Generate a SplitMix64 random 64-bit integer and new algorithm state.\n\nFrom the specified `AlgState` generates a random 64-bit integer\n[`X`](`t:uint64/0`) and a new generator state\n[`NewAlgState`](`t:splitmix64_state/0`),\naccording to the SplitMix64 algorithm.\n\nThis generator is used internally in the `rand` module for seeding other\ngenerators since it is of a quite different breed which reduces\nthe probability for creating an accidentally bad seed.","title":"rand.splitmix64_next/1","ref":"rand.html#splitmix64_next/1"},{"type":"function","doc":"Generate a uniformly distributed random number `0.0 =< X < 1.0`,\nusing the state in the process dictionary.\n\nLike `uniform_s/1` but operates on the state stored in\nthe process dictionary. Returns the generated number `X`.","title":"rand.uniform/0","ref":"rand.html#uniform/0"},{"type":"function","doc":"Generate a uniformly distributed random integer `1 =< X =< N`,\nusing the state in the process dictionary.\n\nLike `uniform_s/2` but operates on the state stored in\nthe process dictionary. Returns the generated number `X`.","title":"rand.uniform/1","ref":"rand.html#uniform/1"},{"type":"function","doc":"Generate a uniformly distributed random number `0.0 < X < 1.0`,\nusing the state in the process dictionary.\n\nLike `uniform_real_s/1` but operates on the state stored in\nthe process dictionary. Returns the generated number `X`.\n\nSee `uniform_real_s/1`.","title":"rand.uniform_real/0","ref":"rand.html#uniform_real/0"},{"type":"function","doc":"Generate a uniformly distributed random number `0.0 < X < 1.0`.\n\nFrom the specified state, generates a random float, uniformly distributed\nin the value range `DBL_MIN = #### Note {: .info }\n>\n> The generated numbers from this function has got better granularity\n> for small numbers than the regular `uniform_s/1` because all bits\n> in the mantissa are random. This property, in combination with the fact\n> that exactly zero is never returned is useful for algorithms doing\n> for example `1.0 / X` or `math:log(X)`.\n\nThe concept implicates that the probability to get exactly zero is extremely\nlow; so low that this function in fact never returns `0.0`.\nThe smallest number that it might return is `DBL_MIN`,\nwhich is `2.0^(-1022)`.\n\nThe value range stated at the top of this function description is\ntechnically correct, but `0.0 =< X < 1.0` is a better description\nof the generated numbers' statistical distribution, and that\nthis function never returns exactly `0.0` is impossible to observe.\n\nFor all sub ranges `N*2.0^(-53) =< X < (N+1)*2.0^(-53)` where\n`0 =< integer(N) < 2.0^53`, the probability to generate a number\nin the range is the same. Compare with the numbers\ngenerated by `uniform_s/1`.\n\nHaving to generate extra random bits for occasional small numbers\ncosts a little performance. This function is about 20% slower\nthan the regular `uniform_s/1`","title":"rand.uniform_real_s/1","ref":"rand.html#uniform_real_s/1"},{"type":"function","doc":"Generate a uniformly distributed random number `0.0 =< X < 1.0`.\n\nFrom the specified `State`, generates a random number `X ::` `t:float/0`,\nuniformly distributed in the value range `0.0 = #### Warning {: .warning }\n>\n> This function may return exactly `0.0` which can be fatal for certain\n> applications. If that is undesired you can use `(1.0 - rand:uniform())`\n> to get the interval `0.0 < X =< 1.0`, or instead use `uniform_real/0`.\n>\n> If neither endpoint is desired you can achieve the range\n> `0.0 < X < 1.0` using test and re-try like this:\n>\n> ```erlang\n> my_uniform() ->\n> case rand:uniform() of\n> X when 0.0 X;\n> _ -> my_uniform()\n> end.\n> ```","title":"rand.uniform_s/1","ref":"rand.html#uniform_s/1"},{"type":"function","doc":"Generate a uniformly distributed random integer `1 =< X =< N`.\n\nFrom the specified `State`, generates a random number `X ::` `t:integer/0`,\nuniformly distributed in the specified range `1 =< X =< N`.\nReturns the number `X` and the updated `NewState`.","title":"rand.uniform_s/2","ref":"rand.html#uniform_s/2"},{"type":"type","doc":"","title":"rand.alg/0","ref":"rand.html#t:alg/0"},{"type":"type","doc":"","title":"rand.alg_handler/0","ref":"rand.html#t:alg_handler/0"},{"type":"type","doc":"","title":"rand.alg_state/0","ref":"rand.html#t:alg_state/0"},{"type":"type","doc":"","title":"rand.builtin_alg/0","ref":"rand.html#t:builtin_alg/0"},{"type":"type","doc":"Algorithm specific internal state","title":"rand.dummy_state/0","ref":"rand.html#t:dummy_state/0"},{"type":"type","doc":"Algorithm-dependent state that can be printed or saved to file.","title":"rand.export_state/0","ref":"rand.html#t:export_state/0"},{"type":"opaque","doc":"Algorithm specific internal state","title":"rand.exro928_state/0","ref":"rand.html#t:exro928_state/0"},{"type":"opaque","doc":"Algorithm specific internal state","title":"rand.exrop_state/0","ref":"rand.html#t:exrop_state/0"},{"type":"opaque","doc":"Algorithm specific internal state","title":"rand.exs64_state/0","ref":"rand.html#t:exs64_state/0"},{"type":"opaque","doc":"Algorithm specific internal state","title":"rand.exs1024_state/0","ref":"rand.html#t:exs1024_state/0"},{"type":"opaque","doc":"Algorithm specific internal state","title":"rand.exsplus_state/0","ref":"rand.html#t:exsplus_state/0"},{"type":"type","doc":"`1 .. (16#1ffb072 bsl 29) - 2`","title":"rand.mwc59_state/0","ref":"rand.html#t:mwc59_state/0"},{"type":"type","doc":"Generator seed value.\n\nA list of integers sets the generator's internal state directly, after\nalgorithm-dependent checks of the value and masking to the proper word size.\nThe number of integers must be equal to the number of state words\nin the generator.\n\nA single integer is used as the initial state for a SplitMix64 generator.\nThe sequential output values of that is then used for setting\nthe generator's internal state after masking to the proper word size\nand if needed avoiding zero values.\n\nA traditional 3-tuple of integers seed is passed through algorithm-dependent\nhashing functions to create the generator's initial state.","title":"rand.seed/0","ref":"rand.html#t:seed/0"},{"type":"type","doc":"Algorithm specific state","title":"rand.splitmix64_state/0","ref":"rand.html#t:splitmix64_state/0"},{"type":"type","doc":"Algorithm-dependent state.","title":"rand.state/0","ref":"rand.html#t:state/0"},{"type":"type","doc":"`0 .. (2^58 - 1)`","title":"rand.uint58/0","ref":"rand.html#t:uint58/0"},{"type":"type","doc":"`0 .. (2^64 - 1)`","title":"rand.uint64/0","ref":"rand.html#t:uint64/0"},{"type":"module","doc":"Pseudo-random number generation.\n\nThis module provides a random number generator. The method is attributed to B.A.\nWichmann and I.D. Hill in 'An efficient and portable pseudo-random number\ngenerator', Journal of Applied Statistics. AS183. 1982. Also Byte March 1987.\n\nThe algorithm is a modification of the version attributed to Richard A. O'Keefe\nin the standard Prolog library.\n\nEvery time a random number is requested, a state is used to calculate it, and a\nnew state is produced. The state can either be implicit (kept in the process\ndictionary) or be an explicit argument and return value. In this implementation,\nthe state (the type `t:ran/0`) consists of a tuple of three integers.\n\n> #### Note {: .info }\n>\n> This random number generator is not cryptographically strong. If a strong\n> cryptographic random number generator is needed, use one of functions in the\n> `m:crypto` module, for example, [`crypto:strong_rand_bytes/1`](`m:crypto`).\n\n> #### Note {: .info }\n>\n> The improved `m:rand` module is to be used instead of this module.","title":"random","ref":"random.html"},{"type":"module","doc":"Some of the functions use the process dictionary variable `random_seed` to\nremember the current seed.\n\nIf a process calls `uniform/0` or `uniform/1` without setting a seed first,\n`seed/0` is called automatically.\n\nThe implementation changed in Erlang/OTP R15. Upgrading to R15 breaks\napplications that expect a specific output for a specified seed. The output is\nstill deterministic number series, but different compared to releases older than\nR15. Seed `{0,0,0}` does, for example, no longer produce a flawed series of only\nzeros.","title":"Note - random","ref":"random.html#module-note"},{"type":"function","doc":"Returns the default state.","title":"random.seed0/0","ref":"random.html#seed0/0"},{"type":"function","doc":"Seeds random number generation with default (fixed) values in the process\ndictionary and returns the old state.","title":"random.seed/0","ref":"random.html#seed/0"},{"type":"function","doc":"[`seed({A1, A2, A3})`](`seed/1`) is equivalent to\n[`seed(A1, A2, A3)`](`seed/3`).","title":"random.seed/1","ref":"random.html#seed/1"},{"type":"function","doc":"Seeds random number generation with integer values in the process dictionary and\nreturns the old state.\n\nThe following is an easy way of obtaining a unique value to seed with:\n\n```erlang\nrandom:seed(erlang:phash2([node()]),\n erlang:monotonic_time(),\n erlang:unique_integer())\n```\n\nFor details, see `erlang:phash2/1`, `erlang:node/0`, `erlang:monotonic_time/0`,\nand `erlang:unique_integer/0`.","title":"random.seed/3","ref":"random.html#seed/3"},{"type":"function","doc":"Returns a random float uniformly distributed between `0.0` and `1.0`, updating\nthe state in the process dictionary.","title":"random.uniform/0","ref":"random.html#uniform/0"},{"type":"function","doc":"Returns, for a specified integer `N >= 1`, a random integer uniformly\ndistributed between `1` and `N`, updating the state in the process dictionary.","title":"random.uniform/1","ref":"random.html#uniform/1"},{"type":"function","doc":"Returns, for a specified state, a random float uniformly distributed between\n`0.0` and `1.0`, and a new state.","title":"random.uniform_s/1","ref":"random.html#uniform_s/1"},{"type":"function","doc":"Returns, for a specified integer `N >= 1` and a state, a random integer\nuniformly distributed between `1` and `N`, and a new state.","title":"random.uniform_s/2","ref":"random.html#uniform_s/2"},{"type":"type","doc":"The state.","title":"random.ran/0","ref":"random.html#t:ran/0"},{"type":"module","doc":"Utility for reading and creating 'zip' archives.\n\nThis module archives and extracts files to and from a zip archive. The zip\nformat is specified by the \"ZIP Appnote.txt\" file, available on the PKWARE web\nsite [www.pkware.com](http://www.pkware.com).\n\nThe zip module supports zip archive versions up to 6.1. However,\npassword-protection is not supported.\n\nBy convention, the name of a zip file is to end with `.zip`. To abide to the\nconvention, add `.zip` to the filename.\n\n- To create zip archives, use function `zip/2` or `zip/3`. They are\n also available as [`create/2,3`](`create/3`), to resemble the `m:erl_tar` module.\n- To extract files from a zip archive, use function `unzip/1` or `unzip/2`. They\n are also available as [`extract/1,2`](`extract/1`), to resemble the `m:erl_tar` module.\n- To fold a function over all files in a zip archive, use function `foldl/3`.\n- To return a list of the files in a zip archive, use function `list_dir/1` or\n `list_dir/2`. They are also available as [`table/1,2`](`table/1`), to resemble the\n `m:erl_tar` module.\n- To print a list of files to the Erlang shell, use function `t/1` or `tt/1`.\n- Sometimes it is desirable to open a zip archive, and to unzip files from it\n file by file, without having to reopen the archive. This can be done by\n functions [`zip_open/1,2`](`zip_open/1`), [`zip_get/1,2`](`zip_get/1`),\n `zip_list_dir/1`, and `zip_close/1`.\n- The ZIP extensions 0x5355 \"extended timestamps\" and 0x7875 \"UID+GID handling\"\n are supported. Both extensions are by default enabled when creating an archive,\n but only \"extended timestamps\" are enabled when extracting. Use the `t:extra/0`\n option to change how these extensions are used.","title":"zip","ref":"zip.html"},{"type":"module","doc":"- Password-protected and encrypted archives are not supported.\n- Only the DEFLATE (zlib-compression) and the STORE (uncompressed data) zip\n methods are supported.\n- Comments for individual files are not supported when creating zip archives.\n The zip archive comment for the whole zip archive is supported.\n- Changing a zip archive is not supported. To add or remove a file from an\n archive, the whole archive must be recreated.","title":"Limitations - zip","ref":"zip.html#module-limitations"},{"type":"function","doc":"","title":"zip.create/2","ref":"zip.html#create/2"},{"type":"function","doc":"","title":"zip.create/3","ref":"zip.html#create/3"},{"type":"function","doc":"","title":"zip.extract/1","ref":"zip.html#extract/1"},{"type":"function","doc":"","title":"zip.extract/2","ref":"zip.html#extract/2"},{"type":"function","doc":"Calls `Fun(FileInArchive, GetInfo, GetBin, AccIn)` on successive files in the\n`Archive`, starting with `AccIn == Acc0`.\n\n`FileInArchive` is the name that the file has in the archive.\n\n`GetInfo` is a fun that returns information about the file.\n\n`GetBin` returns the file contents.\n\nBoth `GetInfo` and `GetBin` must be called within the `Fun`. Their behavior is\nundefined if they are called outside the context of `Fun`.\n\nThe `Fun` must return a new accumulator, which is passed to the next call.\n[`foldl/3`](`foldl/3`) returns the final accumulator value. `Acc0` is returned\nif the archive is empty. It is not necessary to iterate over all files in the\narchive. The iteration can be ended prematurely in a controlled manner by\nthrowing an exception.\n\n_Example:_\n\n```erlang\n> Name = \"dummy.zip\".\n\"dummy.zip\"\n> {ok, {Name, Bin}} = zip:create(Name, [{\"foo\", <<\"FOO\">>}, {\"bar\", <<\"BAR\">>}], [memory]).\n{ok,{\"dummy.zip\",\n <<80,75,3,4,20,0,0,0,0,0,74,152,97,60,171,39,212,26,3,0,\n 0,0,3,0,0,...>>}}\n> {ok, FileSpec} = zip:foldl(fun(N, I, B, Acc) -> [{N, B(), I()} | Acc] end, [], {Name, Bin}).\n{ok,[{\"bar\",<<\"BAR\">>,\n {file_info,3,regular,read_write,\n {{2010,3,1},{19,2,10}},\n {{2010,3,1},{19,2,10}},\n {{2010,3,1},{19,2,10}},\n 54,1,0,0,0,0,0}},\n {\"foo\",<<\"FOO\">>,\n {file_info,3,regular,read_write,\n {{2010,3,1},{19,2,10}},\n {{2010,3,1},{19,2,10}},\n {{2010,3,1},{19,2,10}},\n 54,1,0,0,0,0,0}}]}\n> {ok, {Name, Bin}} = zip:create(Name, lists:reverse(FileSpec), [memory]).\n{ok,{\"dummy.zip\",\n <<80,75,3,4,20,0,0,0,0,0,74,152,97,60,171,39,212,26,3,0,\n 0,0,3,0,0,...>>}}\n> catch zip:foldl(fun(\"foo\", _, B, _) -> throw(B()); (_,_,_,Acc) -> Acc end, [], {Name, Bin}).\n<<\"FOO\">>\n```","title":"zip.foldl/3","ref":"zip.html#foldl/3"},{"type":"function","doc":"","title":"zip.list_dir/1","ref":"zip.html#list_dir/1"},{"type":"function","doc":"Retrieves all filenames in the zip archive `Archive`.\n\nThe result value is the tuple `{ok, List}`, where `List` contains the zip\narchive comment as the first element.\n\nOne option is available:\n\n- **`cooked`** - By default, this function opens the zip file in `raw` mode,\n which is faster but does not allow a remote (Erlang) file server to be used.\n Adding `cooked` to the mode list overrides the default and opens the zip file\n without option `raw`.\n\n- **`skip_directories`** - By default empty directories within zip archives are\n listed. With option `skip_directories` set, empty directories are no longer\n listed.\n\n- **`{extra, Extras}`** - The zip \"extra\" features to respect. The supported\n \"extra\" features are \"extended timestamps\" and \"UID and GID\" handling.\n By default only \"extended timestamps\" is enabled when listing files.\n See `t:extra/0` for more details.","title":"zip.list_dir/2","ref":"zip.html#list_dir/2"},{"type":"function","doc":"Prints all filenames in the zip archive `Archive` to the Erlang shell. (Similar\nto `tar t`.)","title":"zip.t/1","ref":"zip.html#t/1"},{"type":"function","doc":"","title":"zip.table/1","ref":"zip.html#table/1"},{"type":"function","doc":"","title":"zip.table/2","ref":"zip.html#table/2"},{"type":"function","doc":"Prints filenames and information about all files in the zip archive `Archive` to\nthe Erlang shell. (Similar to `tar tv`.)","title":"zip.tt/1","ref":"zip.html#tt/1"},{"type":"function","doc":"","title":"zip.unzip/1","ref":"zip.html#unzip/1"},{"type":"function","doc":"Extracts all files from a zip archive.\n\nIf argument `Archive` is specified as a `t:binary/0`, the contents of the binary is\nassumed to be a zip archive, otherwise a filename.\n\nOptions:\n\n- **`{file_list, FileList}`** - By default, all files are extracted from the zip\n archive. With option `{file_list, FileList}`, function [`unzip/2`](`unzip/2`)\n only extracts the files whose names are included in `FileList`. The full\n paths, including the names of all subdirectories within the zip archive, must\n be specified.\n\n- **`cooked`** - By default, this function opens the zip file in `raw` mode,\n which is faster but does not allow a remote (Erlang) file server to be used.\n Adding `cooked` to the mode list overrides the default and opens the zip file\n without option `raw`. The same applies for the files extracted.\n\n- **`keep_old_files`** - By default, all files with the same name as files in\n the zip archive are overwritten. With option `keep_old_files` set, function\n [`unzip/2`](`unzip/2`) does not overwrite existing files. Notice that even\n with option `memory` specified, which means that no files are overwritten,\n existing files are excluded from the result.\n\n- **`skip_directories`** - By default empty directories within zip archives are\n extracted. With option `skip_directories` set, empty directories are no longer\n created.\n\n- **`{extra, Extras}`** - The zip \"extra\" features to respect. The supported\n \"extra\" features are \"extended timestamps\" and \"UID and GID\" handling.\n By default only \"extended timestamps\" is enabled when unzipping.\n See `t:extra/0` for more details.\n\n- **`verbose`** - Prints an informational message for each extracted file.\n\n- **`memory`** - Instead of extracting to the current directory, the result is\n given as a list of tuples `{Filename, Binary}`, where `Binary` is a binary\n containing the extracted data of file `Filename` in the zip archive.\n\n- **`{cwd, CWD}`** - Uses the specified directory as current directory. It is\n prepended to filenames when extracting them from the zip archive. (Acting like\n `file:set_cwd/1` in Kernel, but without changing the global `cwd` property.)","title":"zip.unzip/2","ref":"zip.html#unzip/2"},{"type":"function","doc":"","title":"zip.zip/2","ref":"zip.html#zip/2"},{"type":"function","doc":"Creates a zip archive containing the files specified in `FileList`.\n\n`FileList` is a list of files, with paths relative to the current directory,\nwhich are stored with this path in the archive. File system operations are\nperformed to read the file metadata and, when compression is enabled, to stream\nthe file contents without loading whole files into memory. Files can also be\nspecified as binaries to create an archive directly from data. In such cases, no\nmetadata or file system reads are performed.\n\nFiles are compressed using the DEFLATE compression, as described in the\n\"Appnote.txt\" file. However, files are stored without compression if they are\nalready compressed. [`zip/2`](`zip/2`) and [`zip/3`](`zip/3`) check the file\nextension to determine if the file is to be stored without compression. Files\nwith the following extensions are not compressed: `.Z`, `.zip`, `.zoo`, `.arc`,\n`.lzh`, `.arj`.\n\nIt is possible to override the default behavior and control what types of files\nthat are to be compressed by using options `{compress, What}` and\n`{uncompress, What}`. It is also possible to use many `compress` and\n`uncompress` options.\n\nTo trigger file compression, its extension must match with the `compress`\ncondition and must not match the `uncompress` condition. For example, if\n`compress` is set to `[\"gif\", \"jpg\"]` and `uncompress` is set to `[\"jpg\"]`, only\nfiles with extension `\"gif\"` are compressed.\n\n[](){: #zip_options }\n\nOptions:\n\n- **`cooked`** - By default, this function opens the zip file in mode `raw`,\n which is faster but does not allow a remote (Erlang) file server to be used.\n Adding `cooked` to the mode list overrides the default and opens the zip file\n without the `raw` option. The same applies for the files added.\n\n- **`verbose`** - Prints an informational message about each added file.\n\n- **`memory`** - The output is not to a file, but instead as a tuple\n `{FileName, binary()}`. The binary is a full zip archive with header and can\n be extracted with, for example, `unzip/2`.\n\n- **`{comment, Comment}`** - Adds a comment to the zip archive.\n\n- **`{cwd, CWD}`** - Uses the specified directory as current work directory\n (`cwd`). This is prepended to filenames when adding them, although not in the\n zip archive (acting like `file:set_cwd/1` in Kernel, but without changing the\n global `cwd` property.).\n\n- **`{extra, Extras}`** - The zip \"extra\" features to respect. The supported\n \"extra\" features are \"extended timestamps\" and \"UID and GID\" handling.\n By default both these \"extra\" features are enabled.\n See `t:extra/0` for more details.\n\n- **`{compress, What}`** - Controls what types of files to be compressed.\n Defaults to `all`. The following values of `What` are allowed:\n\n - **`all`** - All files are compressed (as long as they pass the `uncompress`\n condition).\n\n - **`[Extension]`** - Only files with exactly these extensions are compressed.\n\n - **`{add,[Extension]}`** - Adds these extensions to the list of compress\n extensions.\n\n - **`{del,[Extension]}`** - Deletes these extensions from the list of compress\n extensions.\n\n- **`{uncompress, What}`** - Controls what types of files to be uncompressed.\n Defaults to `[\".Z\", \".zip\", \".zoo\", \".arc\", \".lzh\", \".arj\"]`. The following\n values of `What` are allowed:\n\n - **`all`** - No files are compressed.\n\n - **`[Extension]`** - Files with these extensions are uncompressed.\n\n - **`{add,[Extension]}`** - Adds these extensions to the list of uncompress\n extensions.\n\n - **`{del,[Extension]}`** - Deletes these extensions from the list of\n uncompress extensions.","title":"zip.zip/3","ref":"zip.html#zip/3"},{"type":"function","doc":"Closes a zip archive, previously opened with [`zip_open/1,2`](`zip_open/1`). All\nresources are closed, and the handle is not to be used after closing.","title":"zip.zip_close/1","ref":"zip.html#zip_close/1"},{"type":"function","doc":"","title":"zip.zip_get/1","ref":"zip.html#zip_get/1"},{"type":"function","doc":"Extracts one or all files from an open archive.\n\nThe files are unzipped to memory or to file, depending on the options specified\nto function [`zip_open/1,2`](`zip_open/1`) when opening the archive.","title":"zip.zip_get/2","ref":"zip.html#zip_get/2"},{"type":"function","doc":"Extracts one crc32 checksum from an open archive.","title":"zip.zip_get_crc32/2","ref":"zip.html#zip_get_crc32/2"},{"type":"function","doc":"Returns the file list of an open zip archive. The first returned element is the\nzip archive comment.","title":"zip.zip_list_dir/1","ref":"zip.html#zip_list_dir/1"},{"type":"function","doc":"","title":"zip.zip_open/1","ref":"zip.html#zip_open/1"},{"type":"function","doc":"Opens a zip archive, and reads and saves its directory. This means that later\nreading files from the archive is faster than unzipping files one at a time with\n[`unzip/1,2`](`unzip/1`).\n\nThe options are equivalent to those in `unzip/2`.\n\nThe archive must be closed with `zip_close/1`.\n\nThe `ZipHandle` is closed if the process that originally opened the archive\ndies.","title":"zip.zip_open/2","ref":"zip.html#zip_open/2"},{"type":"type","doc":"These options are described in [`create/3`](`m:zip#zip_options`).","title":"zip.create_option/0","ref":"zip.html#t:create_option/0"},{"type":"type","doc":"A filename extension, for example \".txt\".","title":"zip.extension/0","ref":"zip.html#t:extension/0"},{"type":"type","doc":"","title":"zip.extension_spec/0","ref":"zip.html#t:extension_spec/0"},{"type":"type","doc":"The possible extra extension that can be used.\n\n- **`extended_timestamp`** - enables the 0x5455 \"extended timestamps\" zip extension\n that embeds POSIX timestamps for access and modification times for each file in the\n archive. This makes the timestamps to be in UTC instead of local time and also increases\n the time resolution from 2 seconds to 1 second.\n- **`uid_gid`** - enables 0x7875 \"UNIX 3rd generation\" zip extension that embeds the\n UID and GID for each file into the archive.","title":"zip.extra/0","ref":"zip.html#t:extra/0"},{"type":"type","doc":"The name of a zip file.","title":"zip.filename/0","ref":"zip.html#t:filename/0"},{"type":"opaque","doc":"As returned by `zip_open/2`.","title":"zip.handle/0","ref":"zip.html#t:handle/0"},{"type":"type","doc":"The record `zip_comment` only contains the archive comment for a zip archive.","title":"zip.zip_comment/0","ref":"zip.html#t:zip_comment/0"},{"type":"type","doc":"The record `zip_file` contains the following fields:\n\n- **`name`** - The filename\n\n- **`info`** - File information as in `file:read_file_info/1` in Kernel.\n `mtime`, `atime` and `ctime` are expected to be\n in [`local time`](`erlang:localtime/0`) if represented using `t:calendar:datetime/0`,\n or in [OS system time](`e:erts:time_correction.md#os-system-time`) if represented by an integer.\n\n- **`comment`** - The comment for the file in the zip archive\n\n- **`offset`** - The file offset in the zip archive (used internally)\n\n- **`comp_size`** - The size of the compressed file (the size of the\n uncompressed file is found in `info`)","title":"zip.zip_file/0","ref":"zip.html#t:zip_file/0"},{"type":"module","doc":"This module provides an interface to files created by the BEAM Compiler (\"BEAM\nfiles\").\n\nThe format used, a variant of \"EA IFF 1985\" Standard for Interchange Format Files,\ndivides data into chunks.\n\nChunk data can be returned as binaries or as compound terms. Compound terms are\nreturned when chunks are referenced by names (atoms) rather than identifiers\n(strings). The recognized names and the corresponding identifiers are as\nfollows:\n\n- `atoms (\"Atom\")`\n- `attributes (\"Attr\")`\n- `compile_info (\"CInf\")`\n- `debug_info (\"Dbgi\")`\n- `exports (\"ExpT\")`\n- `imports (\"ImpT\")`\n- `indexed_imports (\"ImpT\")`\n- `labeled_exports (\"ExpT\")`\n- `labeled_locals (\"LocT\")`\n- `literals (\"LitT\")`\n- `locals (\"LocT\")`\n- `documentation (\"Docs\")`\n\n[](){: #debug_info }","title":"beam_lib","ref":"beam_lib.html"},{"type":"module","doc":"Option `debug_info` can be specified to the Compiler (see\n[`compile`](`m:compile#debug_info`)) to have debug information, such as\n[Erlang Abstract Format](`e:erts:absform.md`), stored in the `debug_info` chunk.\nTools such as Debugger and Xref require the debug information to be included.\n\n> #### Warning {: .warning }\n>\n> Source code can be reconstructed from the debug information. To prevent this,\n> use encrypted debug information (see below).\n\nThe debug information can also be removed from BEAM files using `strip/1`,\n`strip_files/1`, and/or `strip_release/1`.","title":"Debug Information/Abstract Code - beam_lib","ref":"beam_lib.html#module-debug-information-abstract-code"},{"type":"module","doc":"The following example shows how to reconstruct Erlang source code from the debug\ninformation in a BEAM file `Beam`:\n\n```erlang\n{ok,{_,[{abstract_code,{_,AC}}]}} = beam_lib:chunks(Beam,[abstract_code]).\nio:fwrite(\"~s~n\", [erl_prettypr:format(erl_syntax:form_list(AC))]).\n```","title":"Reconstruct Source Code - beam_lib","ref":"beam_lib.html#module-reconstruct-source-code"},{"type":"module","doc":"The debug information can be encrypted to keep the source code secret, but still\nbe able to use tools such as Debugger or Xref.\n\nTo use encrypted debug information, a key must be provided to the compiler and\n`beam_lib`. The key is specified as a string. It is recommended that the string\ncontains at least 32 characters and that both upper and lower case letters as\nwell as digits and special characters are used.\n\nThe default type (and currently the only type) of crypto algorithm is\n`des3_cbc`, three rounds of DES. The key string is scrambled using\n`erlang:md5/1` to generate the keys used for `des3_cbc`.\n\n> #### Note {: .info }\n>\n> As far as we know by the time of writing, it is infeasible to break `des3_cbc`\n> encryption without any knowledge of the key. Therefore, as long as the key is\n> kept safe and is unguessable, the encrypted debug information _should_ be safe\n> from intruders.\n\nThe key can be provided in the following two ways:\n\n1. Use Compiler option `{debug_info_key,Key}`, see\n [`compile`](`m:compile#debug_info_key`) and function `crypto_key_fun/1` to\n register a fun that returns the key whenever `beam_lib` must decrypt the\n debug information.\n\nIf no such fun is registered, `beam_lib` instead searches for an `.erlang.crypt`\nfile, see the next section.\n\n1. Store the key in a text file named `.erlang.crypt`.\n\nIn this case, Compiler option `encrypt_debug_info` can be used, see\n[`compile`](`m:compile#encrypt_debug_info`).\n\n## .erlang.crypt\n\n`beam_lib` searches for `.erlang.crypt` in the current directory, then the\n[user's home directory](`m:init#home`) and then\n[`filename:basedir(user_config, \"erlang\")`](`m:filename#user_config`). If the\nfile is found and contains a key, `beam_lib` implicitly creates a crypto key fun\nand registers it.\n\nFile `.erlang.crypt` is to contain a single list of tuples:\n\n```erlang\n{debug_info, Mode, Module, Key}\n```\n\n`Mode` is the type of crypto algorithm; currently, the only allowed value is\n`des3_cbc`. `Module` is either an atom, in which case `Key` is only used for the\nmodule `Module`, or `[]`, in which case `Key` is used for all modules. `Key` is\nthe non-empty key string.\n\n`Key` in the first tuple where both `Mode` and `Module` match is used.\n\nThe following is an example of an `.erlang.crypt` file that returns the same key\nfor all modules:\n\n```erlang\n[{debug_info, des3_cbc, [], \"%>7}|pc/DM6Cga*68$Mw]L#&_Gejr]G^\"}].\n```\n\nThe following is a slightly more complicated example of an `.erlang.crypt`\nproviding one key for module `t` and another key for all other modules:\n\n```erlang\n[{debug_info, des3_cbc, t, \"My KEY\"},\n {debug_info, des3_cbc, [], \"%>7}|pc/DM6Cga*68$Mw]L#&_Gejr]G^\"}].\n```\n\n> #### Note {: .info }\n>\n> Do not use any of the keys in these examples. Use your own keys.","title":"Encrypted Debug Information - beam_lib","ref":"beam_lib.html#module-encrypted-debug-information"},{"type":"function","doc":"Reads chunk data for all chunks.","title":"beam_lib.all_chunks/1","ref":"beam_lib.html#all_chunks/1"},{"type":"function","doc":"Builds a BEAM module (as a binary) from a list of chunks.","title":"beam_lib.build_module/1","ref":"beam_lib.html#build_module/1"},{"type":"function","doc":"Reads chunk data for selected chunks references. The order of the returned list\nof chunk data is determined by the order of the list of chunks references.","title":"beam_lib.chunks/2","ref":"beam_lib.html#chunks/2"},{"type":"function","doc":"Reads chunk data for selected chunks references. The order of the returned list\nof chunk data is determined by the order of the list of chunks references.\n\nBy default, if any requested chunk is missing in `Beam`, an `error` tuple is\nreturned. However, if option `allow_missing_chunks` is specified, a result is\nreturned even if chunks are missing. In the result list, any missing chunks are\nrepresented as `{ChunkRef,missing_chunk}`. Notice however that if chunk `\"Atom\"`\nis missing, that is considered a fatal error and the return value is an `error`\ntuple.","title":"beam_lib.chunks/3","ref":"beam_lib.html#chunks/3"},{"type":"function","doc":"Unregisters the crypto key fun and terminates the process holding it, started by\n`crypto_key_fun/1`.\n\nReturns either `{ok, undefined}` if no crypto key fun is registered, or\n`{ok, Term}`, where `Term` is the return value from `CryptoKeyFun(clear)`, see\n[`crypto_key_fun/1`](`crypto_key_fun/1`).","title":"beam_lib.clear_crypto_key_fun/0","ref":"beam_lib.html#clear_crypto_key_fun/0"},{"type":"function","doc":"Compares the contents of two BEAM files.\n\nIf the module names are the same, and all chunks except for chunk `\"CInf\"`\n(the chunk containing the compilation information that is returned by\n`Module:module_info(compile)`) have the same contents in both files, `ok` is\nreturned. Otherwise an error message is returned.","title":"beam_lib.cmp/2","ref":"beam_lib.html#cmp/2"},{"type":"function","doc":"Compares the BEAM files in two directories.\n\nOnly files with extension `\".beam\"` are compared. BEAM files that exist only in\ndirectory `Dir1` (`Dir2`) are returned in `Only1` (`Only2`). BEAM files that\nexist in both directories but are considered different by [`cmp/2`](`cmp/2`) are\n returned as pairs \\{`Filename1`, `Filename2`\\}, where `Filename1` (`Filename2`)\nexists in directory `Dir1` (`Dir2`).","title":"beam_lib.cmp_dirs/2","ref":"beam_lib.html#cmp_dirs/2"},{"type":"function","doc":"Registers an unary fun that is called if `beam_lib` must read an `debug_info`\nchunk that has been encrypted. The fun is held in a process that is started by\nthe function.\n\nIf a fun is already registered when attempting to register a fun,\n`{error, exists}` is returned.\n\nThe fun must handle the following arguments:\n\n```erlang\nCryptoKeyFun(init) -> ok | {ok, NewCryptoKeyFun} | {error, Term}\n```\n\nCalled when the fun is registered, in the process that holds the fun. Here the\ncrypto key fun can do any necessary initializations. If `{ok, NewCryptoKeyFun}`\nis returned, `NewCryptoKeyFun` is registered instead of `CryptoKeyFun`. If\n`{error, Term}` is returned, the registration is aborted and\n[`crypto_key_fun/1`](`crypto_key_fun/1`) also returns `{error, Term}`.\n\n```erlang\nCryptoKeyFun({debug_info, Mode, Module, Filename}) -> Key\n```\n\nCalled when the key is needed for module `Module` in the file named `Filename`.\n`Mode` is the type of crypto algorithm; currently, the only possible value is\n`des3_cbc`. The call is to fail (raise an exception) if no key is available.\n\n```text\nCryptoKeyFun(clear) -> term()\n```\n\nCalled before the fun is unregistered. Here any cleaning up can be done. The\nreturn value is not important, but is passed back to the caller of\n`clear_crypto_key_fun/0` as part of its return value.","title":"beam_lib.crypto_key_fun/1","ref":"beam_lib.html#crypto_key_fun/1"},{"type":"function","doc":"Compares the BEAM files in two directories as `cmp_dirs/2`, but the names of\nfiles that exist in only one directory or are different are presented on\nstandard output.","title":"beam_lib.diff_dirs/2","ref":"beam_lib.html#diff_dirs/2"},{"type":"function","doc":"For a specified error returned by any function in this module, this function\nreturns a descriptive string of the error in English. For file errors, function\n[`file:format_error(Posix)`](`file:format_error/1`) is to be called.","title":"beam_lib.format_error/1","ref":"beam_lib.html#format_error/1"},{"type":"function","doc":"Returns a list containing some information about a BEAM file as tuples\n`{Item, Info}`:\n\n- **`{file, Filename} | {binary, Binary}`** - The name (string) of the BEAM\n file, or the binary from which the information was extracted.\n\n- **`{module, Module}`** - The name (atom) of the module.\n\n- **`{chunks, [{ChunkId, Pos, Size}]}`** - For each chunk, the identifier\n (string) and the position and size of the chunk data, in bytes.","title":"beam_lib.info/1","ref":"beam_lib.html#info/1"},{"type":"function","doc":"Calculates an MD5 redundancy check for the code of the module (compilation date\nand other attributes are not included).","title":"beam_lib.md5/1","ref":"beam_lib.html#md5/1"},{"type":"function","doc":"Removes all chunks from a BEAM file except those used by the loader.\n\nIn particular, the debug information (chunk `debug_info` and `abstract_code`) is\nremoved.","title":"beam_lib.strip/1","ref":"beam_lib.html#strip/1"},{"type":"function","doc":"Removes all chunks from a BEAM file except those used by the loader or mentioned\nin `AdditionalChunks`.\n\nIn particular, the debug information (chunk `debug_info` and `abstract_code`) is removed.","title":"beam_lib.strip/2","ref":"beam_lib.html#strip/2"},{"type":"function","doc":"Removes all chunks except those used by the loader from `Files`.\n\nIn particular, the debug information (chunk `debug_info` and `abstract_code`) is\nremoved. The returned list contains one element for each specified filename, in\nthe same order as in `Files`.","title":"beam_lib.strip_files/1","ref":"beam_lib.html#strip_files/1"},{"type":"function","doc":"Removes all chunks except those used by the loader or mentioned in\n`AdditionalChunks` from `Files`.\n\nIn particular, the debug information (chunk `debug_info` and `abstract_code`) is\nremoved. The returned list contains one element for each specified filename,\nin the same order as in `Files`.","title":"beam_lib.strip_files/2","ref":"beam_lib.html#strip_files/2"},{"type":"function","doc":"Removes all chunks except those used by the loader from the BEAM files of a\nrelease.\n\n`Dir` is to be the installation root directory. For example, the current OTP\nrelease can be stripped with the call `beam_lib:strip_release(code:root_dir())`.","title":"beam_lib.strip_release/1","ref":"beam_lib.html#strip_release/1"},{"type":"function","doc":"Removes all chunks except those used by the loader or mentioned in\n`AdditionalChunks`.\n\n`Dir` is to be the installation root directory. For example, the current OTP\nrelease can be stripped with the call `beam_lib:strip_release(code:root_dir(),[documentation])`.","title":"beam_lib.strip_release/2","ref":"beam_lib.html#strip_release/2"},{"type":"function","doc":"Returns the module version or versions. A version is defined by module attribute\n`-vsn(Vsn)`.\n\nIf this attribute is not specified, the version defaults to the\nchecksum of the module. Notice that if version `Vsn` is not a list, it is made\ninto one, that is `{ok,{Module,[Vsn]}}` is returned. If there are many `-vsn`\nmodule attributes, the result is the concatenated list of versions.\n\n_Examples:_\n\n```erlang\n1> beam_lib:version(a). % -vsn(1).\n{ok,{a,[1]}}\n2> beam_lib:version(b). % -vsn([1]).\n{ok,{b,[1]}}\n3> beam_lib:version(c). % -vsn([1]). -vsn(2).\n{ok,{c,[1,2]}}\n4> beam_lib:version(d). % no -vsn attribute\n{ok,{d,[275613208176997377698094100858909383631]}}\n```","title":"beam_lib.version/1","ref":"beam_lib.html#version/1"},{"type":"type","doc":"It is not checked that the forms conform to the abstract format indicated by\n`AbstVersion`. `no_abstract_code` means that chunk `\"Abst\"` is present, but\nempty.\n\nFor modules compiled with OTP 20 onwards, the `abst_code` chunk is automatically\ncomputed from the `debug_info` chunk.","title":"beam_lib.abst_code/0","ref":"beam_lib.html#t:abst_code/0"},{"type":"type","doc":"","title":"beam_lib.attrib_entry/0","ref":"beam_lib.html#t:attrib_entry/0"},{"type":"type","doc":"Each of the functions described below accept either the filename (as a string)\nor a binary containing the BEAM module.","title":"beam_lib.beam/0","ref":"beam_lib.html#t:beam/0"},{"type":"type","doc":"","title":"beam_lib.chnk_rsn/0","ref":"beam_lib.html#t:chnk_rsn/0"},{"type":"type","doc":"The list of attributes is sorted on `Attribute` (in `t:attrib_entry/0`) and each\nattribute name occurs once in the list. The attribute values occur in the same\norder as in the file. The lists of functions are also sorted.","title":"beam_lib.chunkdata/0","ref":"beam_lib.html#t:chunkdata/0"},{"type":"type","doc":"`\"Attr\" | \"CInf\" | \"Dbgi\" | \"ExpT\" | \"ImpT\" | \"LocT\" | \"AtU8\" | \"Docs\"`","title":"beam_lib.chunkid/0","ref":"beam_lib.html#t:chunkid/0"},{"type":"type","doc":"","title":"beam_lib.chunkname/0","ref":"beam_lib.html#t:chunkname/0"},{"type":"type","doc":"","title":"beam_lib.chunkref/0","ref":"beam_lib.html#t:chunkref/0"},{"type":"type","doc":"","title":"beam_lib.cmp_rsn/0","ref":"beam_lib.html#t:cmp_rsn/0"},{"type":"type","doc":"","title":"beam_lib.compinfo_entry/0","ref":"beam_lib.html#t:compinfo_entry/0"},{"type":"type","doc":"","title":"beam_lib.crypto_fun/0","ref":"beam_lib.html#t:crypto_fun/0"},{"type":"type","doc":"","title":"beam_lib.crypto_fun_arg/0","ref":"beam_lib.html#t:crypto_fun_arg/0"},{"type":"type","doc":"","title":"beam_lib.dataB/0","ref":"beam_lib.html#t:dataB/0"},{"type":"type","doc":"The format stored in the `debug_info` chunk.\n\nTo retrieve particular code representation from the backend,\n`Backend:debug_info(Format, Module, Data, Opts)` must be invoked. `Format` is an\natom, such as `erlang_v1` for the Erlang Abstract Format or `core_v1` for Core\nErlang. `Module` is the module represented by the beam file and `Data` is the\nvalue stored in the debug info chunk. `Opts` is any list of values supported by\nthe `Backend`. `Backend:debug_info/4` must return `{ok, Code}` or\n`{error, Term}`.\n\nDevelopers must always invoke the `debug_info/4` function and never rely on the\n`Data` stored in the `debug_info` chunk, as it is opaque and may change at any\nmoment. `no_debug_info` means that chunk `\"Dbgi\"` is present, but empty.","title":"beam_lib.debug_info/0","ref":"beam_lib.html#t:debug_info/0"},{"type":"type","doc":"[EEP-48 documentation format](`e:kernel:eep48_chapter.md#the-docs-format`)","title":"beam_lib.docs/0","ref":"beam_lib.html#t:docs/0"},{"type":"type","doc":"","title":"beam_lib.forms/0","ref":"beam_lib.html#t:forms/0"},{"type":"type","doc":"","title":"beam_lib.index/0","ref":"beam_lib.html#t:index/0"},{"type":"type","doc":"","title":"beam_lib.info_rsn/0","ref":"beam_lib.html#t:info_rsn/0"},{"type":"type","doc":"","title":"beam_lib.label/0","ref":"beam_lib.html#t:label/0"},{"type":"type","doc":"","title":"beam_lib.labeled_entry/0","ref":"beam_lib.html#t:labeled_entry/0"},{"type":"type","doc":"","title":"beam_lib.literals/0","ref":"beam_lib.html#t:literals/0"},{"type":"type","doc":"","title":"beam_lib.mode/0","ref":"beam_lib.html#t:mode/0"},{"type":"module","doc":"An Erlang code preprocessor.\n\nThe Erlang code preprocessor includes functions that are used by the `m:compile`\nmodule to preprocess macros and include files before the parsing takes place.\n\nThe Erlang source file _encoding_{: #encoding } is selected by a comment in one\nof the first two lines of the source file. The first string matching the regular\nexpression `coding\\s*[:=]\\s*([-a-zA-Z0-9])+` selects the encoding. If the\nmatching string is not a valid encoding, it is ignored. The valid encodings are\n`Latin-1` and `UTF-8`, where the case of the characters can be chosen freely.\n\n_Examples:_\n\n```erlang\n%% coding: utf-8\n```\n\n```erlang\n%% For this file we have chosen encoding = Latin-1\n```\n\n```erlang\n%% -*- coding: latin-1 -*-\n```","title":"epp","ref":"epp.html"},{"type":"module","doc":"`ErrorInfo` is the standard `ErrorInfo` structure that is returned from all I/O\nmodules. The format is as follows:\n\n```erlang\n{ErrorLine, Module, ErrorDescriptor}\n```\n\nA string describing the error is obtained with the following call:\n\n```erlang\nModule:format_error(ErrorDescriptor)\n```","title":"Error Information - epp","ref":"epp.html#module-error-information"},{"type":"module","doc":"`m:erl_parse`","title":"See Also - epp","ref":"epp.html#module-see-also"},{"type":"function","doc":"Closes the preprocessing of a file.","title":"epp.close/1","ref":"epp.html#close/1"},{"type":"function","doc":"Returns the default encoding of Erlang source files.","title":"epp.default_encoding/0","ref":"epp.html#default_encoding/0"},{"type":"function","doc":"Returns a string representation of an encoding. The string is recognized by\n[`read_encoding/1,2`](`read_encoding/1`),\n[`read_encoding_from_binary/1,2`](`read_encoding_from_binary/1`), and\n[`set_encoding/1,2`](`set_encoding/1`) as a valid encoding.","title":"epp.encoding_to_string/1","ref":"epp.html#encoding_to_string/1"},{"type":"function","doc":"Takes an `ErrorDescriptor` and returns a string that describes the error or\nwarning. This function is usually called implicitly when processing an\n`ErrorInfo` structure (see section [Error Information](`m:epp#module-error-information`)).","title":"epp.format_error/1","ref":"epp.html#format_error/1"},{"type":"function","doc":"Opens a file for preprocessing.\n\nIf you want to change the file name of the implicit -file() attributes inserted\nduring preprocessing, you can do with `{source_name, SourceName}`. If unset it\nwill default to the name of the opened file.\n\nSetting `{deterministic, Enabled}` will additionally reduce the file name of the\nimplicit -file() attributes inserted during preprocessing to only the basename\nof the path.\n\nIf `extra` is specified in `Options`, the return value is `{ok, Epp, Extra}`\ninstead of `{ok, Epp}`.\n\nThe option `location` is forwarded to the Erlang token scanner, see\n[`erl_scan:tokens/3,4`](`erl_scan:tokens/3`).\n\nThe `{compiler_internal,term()}` option is forwarded to the Erlang token\nscanner, see [`{compiler_internal,term()}`](`m:erl_scan#compiler_interal`).","title":"epp.open/1","ref":"epp.html#open/1"},{"type":"function","doc":"Equivalent to `epp:open([{name, FileName}, {includes, IncludePath}])`.","title":"epp.open/2","ref":"epp.html#open/2"},{"type":"function","doc":"Equivalent to\n`epp:open([{name, FileName}, {includes, IncludePath}, {macros, PredefMacros}])`.","title":"epp.open/3","ref":"epp.html#open/3"},{"type":"function","doc":"Returns the next Erlang form from the opened Erlang source file. Tuple\n`{eof, Location}` is returned at the end of the file. The first form corresponds\nto an implicit attribute `-file(File,1).`, where `File` is the file name.","title":"epp.parse_erl_form/1","ref":"epp.html#parse_erl_form/1"},{"type":"function","doc":"Preprocesses and parses an Erlang source file. Notice that tuple\n`{eof, Location}` returned at the end of the file is included as a \"form\".\n\nIf you want to change the file name of the implicit -file() attributes inserted\nduring preprocessing, you can do with `{source_name, SourceName}`. If unset it\nwill default to the name of the opened file.\n\nIf `extra` is specified in `Options`, the return value is `{ok, [Form], Extra}`\ninstead of `{ok, [Form]}`.\n\nThe option `location` is forwarded to the Erlang token scanner, see\n[`erl_scan:tokens/3,4`](`erl_scan:tokens/3`).\n\nThe `{compiler_internal,term()}` option is forwarded to the Erlang token\nscanner, see [`{compiler_internal,term()}`](`m:erl_scan#compiler_interal`).","title":"epp.parse_file/2","ref":"epp.html#parse_file/2"},{"type":"function","doc":"Equivalent to\n`epp:parse_file(FileName, [{includes, IncludePath}, {macros, PredefMacros}])`.","title":"epp.parse_file/3","ref":"epp.html#parse_file/3"},{"type":"function","doc":"","title":"epp.read_encoding/1","ref":"epp.html#read_encoding/1"},{"type":"function","doc":"Read the [encoding](`m:epp#encoding`) from a file. Returns the read encoding, or\n`none` if no valid encoding is found.\n\nOption `in_comment_only` is `true` by default, which is correct for Erlang\nsource files. If set to `false`, the encoding string does not necessarily have\nto occur in a comment.","title":"epp.read_encoding/2","ref":"epp.html#read_encoding/2"},{"type":"function","doc":"","title":"epp.read_encoding_from_binary/1","ref":"epp.html#read_encoding_from_binary/1"},{"type":"function","doc":"Read the [encoding](`m:epp#encoding`) from a binary. Returns the read encoding,\nor `none` if no valid encoding is found.\n\nOption `in_comment_only` is `true` by default, which is correct for Erlang\nsource files. If set to `false`, the encoding string does not necessarily have\nto occur in a comment.","title":"epp.read_encoding_from_binary/2","ref":"epp.html#read_encoding_from_binary/2"},{"type":"function","doc":"Returns the raw tokens of the next Erlang form from the opened Erlang source\nfile. A tuple `{eof, Line}` is returned at the end of the file. The first form\ncorresponds to an implicit attribute `-file(File,1).`, where `File` is the file\nname.","title":"epp.scan_erl_form/1","ref":"epp.html#scan_erl_form/1"},{"type":"function","doc":"Preprocesses an Erlang source file returning a list of the lists of raw tokens\nof each form. Notice that the tuple `{eof, Line}` returned at the end of the\nfile is included as a \"form\", and any failures to scan a form are included in\nthe list as tuples `{error, ErrorInfo}`.","title":"epp.scan_file/2","ref":"epp.html#scan_file/2"},{"type":"function","doc":"Reads the [encoding](`m:epp#encoding`) from an I/O device and sets the encoding\nof the device accordingly. The position of the I/O device referenced by `File`\nis not affected. If no valid encoding can be read from the I/O device, the\nencoding of the I/O device is set to the default encoding.\n\nReturns the read encoding, or `none` if no valid encoding is found.","title":"epp.set_encoding/1","ref":"epp.html#set_encoding/1"},{"type":"function","doc":"Reads the [encoding](`m:epp#encoding`) from an I/O device and sets the encoding\nof the device accordingly. The position of the I/O device referenced by `File`\nis not affected. If no valid encoding can be read from the I/O device, the\nencoding of the I/O device is set to the [encoding](`m:epp#encoding`) specified\nby `Default`.\n\nReturns the read encoding, or `none` if no valid encoding is found.","title":"epp.set_encoding/2","ref":"epp.html#set_encoding/2"},{"type":"type","doc":"Handle to the `epp` server.","title":"epp.epp_handle/0","ref":"epp.html#t:epp_handle/0"},{"type":"type","doc":"","title":"epp.macros/0","ref":"epp.html#t:macros/0"},{"type":"type","doc":"","title":"epp.source_encoding/0","ref":"epp.html#t:source_encoding/0"},{"type":"type","doc":"","title":"epp.warning_info/0","ref":"epp.html#t:warning_info/0"},{"type":"module","doc":"Abstract datatype for the annotations of the Erlang Compiler.\n\nThis module provides an abstract type that is used by the Erlang Compiler and\nits helper modules for holding data such as column, line number, and text. The\ndata type is a collection of _annotations_{: #annotations } as described in the\nfollowing.\n\nThe Erlang Token Scanner returns tokens with a subset of the following\nannotations, depending on the options:\n\n- **`column`** - The column where the token begins.\n\n- **`location`** - The line and column where the token begins, or just the line\n if the column is unknown.\n\n- **`text`** - The token's text.\n\nFrom this, the following annotation is derived:\n\n- **`line`** - The line where the token begins.\n\nThis module also supports the following annotations, which are used by various\nmodules:\n\n- **`file`** - A filename.\n\n- **`generated`** - A Boolean indicating if the abstract code is\n compiler-generated. The Erlang Compiler does not emit warnings for such code.\n\n- **`record`** - A Boolean indicating if the origin of the abstract code is a\n record. Used by [Dialyzer](`m:dialyzer`) to assign types to tuple elements.\n\nThe functions [`column()`](`erl_scan:column/1`),\n[`end_location()`](`erl_scan:end_location/1`), [`line()`](`erl_scan:line/1`),\n[`location()`](`erl_scan:location/1`), and [`text()`](`erl_scan:text/1`) in the\n`erl_scan` module can be used for inspecting annotations in tokens.\n\nThe functions [`anno_from_term()`](`erl_parse:anno_from_term/1`),\n[`anno_to_term()`](`erl_parse:anno_to_term/1`),\n[`fold_anno()`](`erl_parse:fold_anno/3`),\n[`map_anno()`](`erl_parse:map_anno/2`),\n[`mapfold_anno()`](`erl_parse:mapfold_anno/3`), and\n[`new_anno()`](`erl_parse:new_anno/1`), in the `erl_parse` module can be used\nfor manipulating annotations in abstract code.","title":"erl_anno","ref":"erl_anno.html"},{"type":"module","doc":"`m:erl_parse`, `m:erl_scan`","title":"See Also - erl_anno","ref":"erl_anno.html#module-see-also"},{"type":"function","doc":"Returns the column of the annotations Anno.","title":"erl_anno.column/1","ref":"erl_anno.html#column/1"},{"type":"function","doc":"Returns the end location of the annotations Anno.\n\nIf the end location annotation is present, its value is returned. Otherwise,\nif the text annotation is present, the end location is inferred from the\nlocation and the text. Finally, if there is no text, `undefined` is returned.","title":"erl_anno.end_location/1","ref":"erl_anno.html#end_location/1"},{"type":"function","doc":"Returns the filename of the annotations Anno. If there is no filename,\n`undefined` is returned.","title":"erl_anno.file/1","ref":"erl_anno.html#file/1"},{"type":"function","doc":"Returns annotations with representation Term.\n\nSee also [to_term()](`to_term/1`).","title":"erl_anno.from_term/1","ref":"erl_anno.html#from_term/1"},{"type":"function","doc":"Returns `true` if annotations Anno is marked as generated. The default is to\nreturn `false`.","title":"erl_anno.generated/1","ref":"erl_anno.html#generated/1"},{"type":"function","doc":"Returns `true` if Term is a collection of annotations, otherwise `false`.","title":"erl_anno.is_anno/1","ref":"erl_anno.html#is_anno/1"},{"type":"function","doc":"Returns the line of the annotations Anno.","title":"erl_anno.line/1","ref":"erl_anno.html#line/1"},{"type":"function","doc":"Returns the location of the annotations Anno.","title":"erl_anno.location/1","ref":"erl_anno.html#location/1"},{"type":"function","doc":"Creates a new collection of annotations given a location.","title":"erl_anno.new/1","ref":"erl_anno.html#new/1"},{"type":"function","doc":"Modifies the end location of the annotations Anno.","title":"erl_anno.set_end_location/2","ref":"erl_anno.html#set_end_location/2"},{"type":"function","doc":"Modifies the filename of the annotations Anno.","title":"erl_anno.set_file/2","ref":"erl_anno.html#set_file/2"},{"type":"function","doc":"Modifies the generated marker of the annotations Anno.","title":"erl_anno.set_generated/2","ref":"erl_anno.html#set_generated/2"},{"type":"function","doc":"Modifies the line of the annotations Anno.","title":"erl_anno.set_line/2","ref":"erl_anno.html#set_line/2"},{"type":"function","doc":"Modifies the location of the annotations Anno.","title":"erl_anno.set_location/2","ref":"erl_anno.html#set_location/2"},{"type":"function","doc":"Modifies the record marker of the annotations Anno.","title":"erl_anno.set_record/2","ref":"erl_anno.html#set_record/2"},{"type":"function","doc":"Modifies the text of the annotations Anno.","title":"erl_anno.set_text/2","ref":"erl_anno.html#set_text/2"},{"type":"function","doc":"Returns the text of the annotations Anno. If there is no text, `undefined` is\nreturned.","title":"erl_anno.text/1","ref":"erl_anno.html#text/1"},{"type":"function","doc":"Returns the term representing the annotations Anno.\n\nSee also [from_term()](`from_term/1`).","title":"erl_anno.to_term/1","ref":"erl_anno.html#to_term/1"},{"type":"opaque","doc":"A collection of annotations.","title":"erl_anno.anno/0","ref":"erl_anno.html#t:anno/0"},{"type":"type","doc":"The term representing a collection of annotations. It is either a `t:location/0`\nor a list of key-value pairs.","title":"erl_anno.anno_term/0","ref":"erl_anno.html#t:anno_term/0"},{"type":"type","doc":"","title":"erl_anno.column/0","ref":"erl_anno.html#t:column/0"},{"type":"type","doc":"","title":"erl_anno.filename/0","ref":"erl_anno.html#t:filename/0"},{"type":"type","doc":"","title":"erl_anno.generated/0","ref":"erl_anno.html#t:generated/0"},{"type":"type","doc":"","title":"erl_anno.line/0","ref":"erl_anno.html#t:line/0"},{"type":"type","doc":"","title":"erl_anno.location/0","ref":"erl_anno.html#t:location/0"},{"type":"type","doc":"","title":"erl_anno.record/0","ref":"erl_anno.html#t:record/0"},{"type":"type","doc":"","title":"erl_anno.text/0","ref":"erl_anno.html#t:text/0"},{"type":"module","doc":"The Erlang meta interpreter.\n\nThis module provides an interpreter for Erlang expressions. The expressions are\nin the abstract syntax as returned by `m:erl_parse`, the Erlang parser, or\n`m:io`.","title":"erl_eval","ref":"erl_eval.html"},{"type":"module","doc":"During evaluation of a function, no calls can be made to local functions. An\nundefined function error would be generated. However, the optional argument\n`LocalFunctionHandler` can be used to define a function that is called when\nthere is a call to a local function. The argument can have the following\nformats:\n\n- **`{value,Func}`** - This defines a local function handler that is called\n with:\n\n ```erlang\n Func(Name, Arguments)\n ```\n\n `Name` is the name of the local function (an atom) and `Arguments` is a list\n of the _evaluated_ arguments. The function handler returns the value of the\n local function. In this case, the current bindings cannot be accessed. To\n signal an error, the function handler calls [`exit/1`](`exit/1`) with a\n suitable exit value.\n\n- **`{eval,Func}`** - This defines a local function handler that is called with:\n\n ```erlang\n Func(Name, Arguments, Bindings)\n ```\n\n `Name` is the name of the local function (an atom), `Arguments` is a list of\n the _unevaluated_ arguments, and `Bindings` are the current variable bindings.\n The function handler returns:\n\n ```erlang\n {value,Value,NewBindings}\n ```\n\n `Value` is the value of the local function and `NewBindings` are the updated\n variable bindings. In this case, the function handler must itself evaluate all\n the function arguments and manage the bindings. To signal an error, the\n function handler calls [`exit/1`](`exit/1`) with a suitable exit value.\n\n- **`none`** - There is no local function handler.","title":"Local Function Handler - erl_eval","ref":"erl_eval.html#module-local-function-handler"},{"type":"module","doc":"The optional argument `NonLocalFunctionHandler` can be used to define a function\nthat is called in the following cases:\n\n- A functional object (fun) is called.\n- A built-in function is called.\n- A function is called using the `M:F` syntax, where `M` and `F` are atoms or\n expressions.\n- An operator `Op/A` is called (this is handled as a call to function\n `erlang:Op/A`).\n\nExceptions are calls to `erlang:apply/2,3`; neither of the function handlers are\ncalled for such calls. The argument can have the following formats:\n\n- **`{value,Func}`** - This defines a non-local function handler. The function\n may be called with two arguments:\n\n ```erlang\n Func(FuncSpec, Arguments)\n ```\n\n or three arguments:\n\n ```erlang\n Func(Anno, FuncSpec, Arguments)\n ```\n\n `Anno` is the [`erl_anno:anno()`](`t:erl_anno:anno/0`) of the node, `FuncSpec`\n is the name of the function on the form `{Module,Function}` or a fun, and\n `Arguments` is a list of the _evaluated_ arguments. The function handler\n returns the value of the function. To signal an error, the function handler\n calls [`exit/1`](`exit/1`) with a suitable exit value.\n\n- **`none`** - There is no non-local function handler.\n\n> #### Note {: .info }\n>\n> For calls such as `erlang:apply(Fun, Args)` or\n> `erlang:apply(Module, Function, Args)`, the call of the non-local function\n> handler corresponding to the call to `erlang:apply/2,3` itself\n> (`Func({erlang, apply}, [Fun, Args])` or\n> `Func({erlang, apply}, [Module, Function, Args])`) never takes place.\n>\n> The non-local function handler _is_ however called with the evaluated\n> arguments of the call to `erlang:apply/2,3`: `Func(Fun, Args)` or\n> `Func({Module, Function}, Args)` (assuming that `{Module, Function}` is not\n> `{erlang, apply}`).\n>\n> Calls to functions defined by evaluating fun expressions `\"fun ... end\"` are\n> also hidden from non-local function handlers.\n\nThe non-local function handler argument is probably not used as frequently as\nthe local function handler argument. A possible use is to call\n[`exit/1`](`exit/1`) on calls to functions that for some reason are not allowed\nto be called.","title":"Non-Local Function Handler - erl_eval","ref":"erl_eval.html#module-non-local-function-handler"},{"type":"function","doc":"Adds binding `Name=Value` to `BindingStruct`. Returns an updated binding\nstructure.","title":"erl_eval.add_binding/3","ref":"erl_eval.html#add_binding/3"},{"type":"function","doc":"Returns the binding of `Name` in `BindingStruct`.","title":"erl_eval.binding/2","ref":"erl_eval.html#binding/2"},{"type":"function","doc":"Returns the list of bindings contained in the binding structure.","title":"erl_eval.bindings/1","ref":"erl_eval.html#bindings/1"},{"type":"function","doc":"Removes the binding of `Name` in `BindingStruct`. Returns an updated binding\nstructure.","title":"erl_eval.del_binding/2","ref":"erl_eval.html#del_binding/2"},{"type":"function","doc":"","title":"erl_eval.expr/2","ref":"erl_eval.html#expr/2"},{"type":"function","doc":"","title":"erl_eval.expr/3","ref":"erl_eval.html#expr/3"},{"type":"function","doc":"","title":"erl_eval.expr/4","ref":"erl_eval.html#expr/4"},{"type":"function","doc":"Evaluates `Expression` with the set of bindings `Bindings`. `Expression` is an\nexpression in abstract syntax.\n\nFor an explanation of when and how to use arguments `LocalFunctionHandler` and\n`NonLocalFunctionHandler`, see sections\n[Local Function Handler](`m:erl_eval#module-local-function-handler`) and\n[Non-Local Function Handler](`m:erl_eval#module-non-local-function-handler`) in this\nmodule.\n\nReturns `{value, Value, NewBindings}` by default. If `ReturnFormat` is `value`,\nonly `Value` is returned.","title":"erl_eval.expr/5","ref":"erl_eval.html#expr/5"},{"type":"function","doc":"","title":"erl_eval.expr_list/2","ref":"erl_eval.html#expr_list/2"},{"type":"function","doc":"","title":"erl_eval.expr_list/3","ref":"erl_eval.html#expr_list/3"},{"type":"function","doc":"Evaluates a list of expressions in parallel, using the same initial bindings for\neach expression. Attempts are made to merge the bindings returned from each\nevaluation.\n\nThis function is useful in `LocalFunctionHandler`, see section\n[Local Function Handler](`m:erl_eval#module-local-function-handler`) in this module.\n\nReturns `{ValueList, NewBindings}`.","title":"erl_eval.expr_list/4","ref":"erl_eval.html#expr_list/4"},{"type":"function","doc":"","title":"erl_eval.exprs/2","ref":"erl_eval.html#exprs/2"},{"type":"function","doc":"","title":"erl_eval.exprs/3","ref":"erl_eval.html#exprs/3"},{"type":"function","doc":"Evaluates `Expressions` with the set of bindings `Bindings`, where `Expressions`\nis a sequence of expressions (in abstract syntax) of a type that can be returned\nby `io:parse_erl_exprs/2`.\n\nFor an explanation of when and how to use arguments\n`LocalFunctionHandler` and `NonLocalFunctionHandler`, see sections\n[Local Function Handler](`m:erl_eval#module-local-function-handler`) and\n[Non-Local Function Handler](`m:erl_eval#module-non-local-function-handler`) in this\nmodule.\n\nReturns `{value, Value, NewBindings}`","title":"erl_eval.exprs/4","ref":"erl_eval.html#exprs/4"},{"type":"function","doc":"Returns an empty binding structure.","title":"erl_eval.new_bindings/0","ref":"erl_eval.html#new_bindings/0"},{"type":"function","doc":"","title":"erl_eval.new_bindings/1","ref":"erl_eval.html#new_bindings/1"},{"type":"type","doc":"A binding structure. It is either a `map` or an `orddict`. `erl_eval` will\nalways return the same type as the one given.","title":"erl_eval.binding_struct/0","ref":"erl_eval.html#t:binding_struct/0"},{"type":"type","doc":"","title":"erl_eval.bindings/0","ref":"erl_eval.html#t:bindings/0"},{"type":"type","doc":"","title":"erl_eval.expression/0","ref":"erl_eval.html#t:expression/0"},{"type":"type","doc":"","title":"erl_eval.expression_list/0","ref":"erl_eval.html#t:expression_list/0"},{"type":"type","doc":"As returned by `erl_parse:parse_exprs/1` or `io:parse_erl_exprs/2`.","title":"erl_eval.expressions/0","ref":"erl_eval.html#t:expressions/0"},{"type":"type","doc":"","title":"erl_eval.func_spec/0","ref":"erl_eval.html#t:func_spec/0"},{"type":"type","doc":"","title":"erl_eval.lfun_eval_handler/0","ref":"erl_eval.html#t:lfun_eval_handler/0"},{"type":"type","doc":"","title":"erl_eval.lfun_value_handler/0","ref":"erl_eval.html#t:lfun_value_handler/0"},{"type":"type","doc":"Further described in section\n[Local Function Handler](`m:erl_eval#module-local-function-handler`) in this module","title":"erl_eval.local_function_handler/0","ref":"erl_eval.html#t:local_function_handler/0"},{"type":"type","doc":"","title":"erl_eval.name/0","ref":"erl_eval.html#t:name/0"},{"type":"type","doc":"","title":"erl_eval.nlfun_handler/0","ref":"erl_eval.html#t:nlfun_handler/0"},{"type":"type","doc":"Further described in section\n[Non-Local Function Handler](`m:erl_eval#module-non-local-function-handler`) in this\nmodule.","title":"erl_eval.non_local_function_handler/0","ref":"erl_eval.html#t:non_local_function_handler/0"},{"type":"type","doc":"","title":"erl_eval.value/0","ref":"erl_eval.html#t:value/0"},{"type":"module","doc":"This module expands records in a module.","title":"erl_expand_records","ref":"erl_expand_records.html"},{"type":"module","doc":"Section [The Abstract Format](`e:erts:absform.md`) in ERTS User's Guide.","title":"See Also - erl_expand_records","ref":"erl_expand_records.html#module-see-also"},{"type":"function","doc":"Expands all records in a module to use explicit tuple operations and adds\nexplicit module names to calls to BIFs and imported functions. The returned\nmodule has no references to records, attributes, or code.","title":"erl_expand_records.module/2","ref":"erl_expand_records.html#module/2"},{"type":"module","doc":"This module contains functions for supporting features that can be\nenabled/disabled in Erlang.\n\nIt should be considered as mostly for internal use, although there are some\nfunctions that might be useful when writing tools.","title":"erl_features","ref":"erl_features.html"},{"type":"function","doc":"Return a list of all known features. This list will include features that have\nbeen removed (status `rejected`) and features that are no longer configurable\n(status `permanent`).","title":"erl_features.all/0","ref":"erl_features.html#all/0"},{"type":"function","doc":"Return a list of all configurable features, that is, features with status\n`experimental` or `approved`. These are the features that can be enabled or\ndisabled.","title":"erl_features.configurable/0","ref":"erl_features.html#configurable/0"},{"type":"function","doc":"Return a list of the features that are currently enabled. Note that the set of\nenabled is set during startup and can then not be changed.","title":"erl_features.enabled/0","ref":"erl_features.html#enabled/0"},{"type":"function","doc":"Return a map containing information about the given feature.","title":"erl_features.info/1","ref":"erl_features.html#info/1"},{"type":"function","doc":"Return the list of features enabled when compiling the module. The module need\nnot be loaded, but is found if it exists in the loadpath. If not all features\nused by the module are enabled in the runtime, loading the module is not\nallowed.","title":"erl_features.used/1","ref":"erl_features.html#used/1"},{"type":"type","doc":"","title":"erl_features.feature/0","ref":"erl_features.html#t:feature/0"},{"type":"type","doc":"","title":"erl_features.release/0","ref":"erl_features.html#t:release/0"},{"type":"type","doc":"","title":"erl_features.status/0","ref":"erl_features.html#t:status/0"},{"type":"type","doc":"","title":"erl_features.type/0","ref":"erl_features.html#t:type/0"},{"type":"module","doc":"This module performs an identity parse transformation of Erlang code.\n\nIt is included as an example for users who wants to write their own\nparse transformers. If option `{parse_transform,Module}` is passed\nto the compiler, a user-written function `parse_transform/2`\nis called by the compiler before the code is checked for errors.\n\nBefore the function `parse_transform/2` is called, the Erlang\nCompiler checks if the parse transformation can handle abstract code\nwith column numbers: If the function `parse_transform_info/0`\nis implemented and returns a map where the key `error_location` is\nassociated with the value `line`, the compiler removes\ncolumn numbers from the abstract code before calling the parse\ntransform. Otherwise, the compiler passes the abstract code on\nwithout modification.","title":"erl_id_trans","ref":"erl_id_trans.html"},{"type":"module","doc":"Parse transformations are used if a programmer wants to use\nErlang syntax, but with different semantics. The original Erlang\ncode is then transformed into other Erlang code.\n\n> #### Note {: .info }\n>\n> Programmers are strongly advised not to engage in parse\n> transformations. No support is offered for problems encountered.\n>","title":"Parse Transformations - erl_id_trans","ref":"erl_id_trans.html#module-parse-transformations"},{"type":"module","doc":"`m:erl_parse` and `m:compile`.","title":"See Also - erl_id_trans","ref":"erl_id_trans.html#module-see-also"},{"type":"function","doc":"Performs an identity transformation on Erlang forms, as an example.","title":"erl_id_trans.parse_transform/2","ref":"erl_id_trans.html#parse_transform/2"},{"type":"function","doc":"Returns information about the parse transform itself.","title":"erl_id_trans.parse_transform_info/0","ref":"erl_id_trans.html#parse_transform_info/0"},{"type":"module","doc":"Internal Erlang definitions.\n\nThis module defines Erlang BIFs, guard tests, and operators. This module is only\nof interest to programmers who manipulate Erlang code.","title":"erl_internal","ref":"erl_internal.html"},{"type":"function","doc":"Adds to `Forms` the code for the standard pre-defined functions (such as\n`module_info/0`) that are to be included in every module.","title":"erl_internal.add_predefined_functions/1","ref":"erl_internal.html#add_predefined_functions/1"},{"type":"function","doc":"Returns `true` if `OpName/Arity` is an arithmetic operator, otherwise `false`.","title":"erl_internal.arith_op/2","ref":"erl_internal.html#arith_op/2"},{"type":"function","doc":"Returns `true` if `Name/Arity` is an Erlang BIF that is automatically recognized\nby the compiler, otherwise `false`.","title":"erl_internal.bif/2","ref":"erl_internal.html#bif/2"},{"type":"function","doc":"Returns `true` if `OpName/Arity` is a Boolean operator, otherwise `false`.","title":"erl_internal.bool_op/2","ref":"erl_internal.html#bool_op/2"},{"type":"function","doc":"Returns `true` if `OpName/Arity` is a comparison operator, otherwise `false`.","title":"erl_internal.comp_op/2","ref":"erl_internal.html#comp_op/2"},{"type":"function","doc":"Returns `true` if `Name/Arity` is an Erlang BIF that is allowed in guards,\notherwise `false`.","title":"erl_internal.guard_bif/2","ref":"erl_internal.html#guard_bif/2"},{"type":"function","doc":"Returns `true` if `OpName/Arity` is a list operator, otherwise `false`.","title":"erl_internal.list_op/2","ref":"erl_internal.html#list_op/2"},{"type":"function","doc":"Returns the `Type` of operator that `OpName/Arity` belongs to, or generates a\n`function_clause` error if it is not an operator.","title":"erl_internal.op_type/2","ref":"erl_internal.html#op_type/2"},{"type":"function","doc":"Returns `true` if `OpName/Arity` is a send operator, otherwise `false`.","title":"erl_internal.send_op/2","ref":"erl_internal.html#send_op/2"},{"type":"function","doc":"Returns `true` if `Name/Arity` is a valid Erlang type test, otherwise `false`.","title":"erl_internal.type_test/2","ref":"erl_internal.html#type_test/2"},{"type":"module","doc":"The Erlang code linter.\n\nThis module is used to check Erlang code for illegal syntax and other bugs. It\nalso warns against coding practices that are not recommended.\n\nThe errors detected include:\n\n- Redefined and undefined functions\n- Unbound and unsafe variables\n- Illegal record use\n\nThe warnings detected include:\n\n- Unused functions and imports\n- Unused variables\n- Variables imported into matches\n- Variables exported from `if`/`case`/`receive`\n- Variables shadowed in funs and list comprehensions\n\nSome of the warnings are optional, and can be turned on by specifying the\nappropriate option, described below.\n\nThe functions in this module are invoked automatically by the Erlang compiler.\nThere is no reason to invoke these functions separately unless you have written\nyour own Erlang compiler.","title":"erl_lint","ref":"erl_lint.html"},{"type":"module","doc":"`ErrorInfo` is the standard `ErrorInfo` structure that is returned from all I/O\nmodules. The format is as follows:\n\n```erlang\n{ErrorLine, Module, ErrorDescriptor}\n```\n\nA string describing the error is obtained with the following call:\n\n```erlang\nModule:format_error(ErrorDescriptor)\n```","title":"Error Information - erl_lint","ref":"erl_lint.html#module-error-information"},{"type":"module","doc":"`m:epp`, `m:erl_parse`","title":"See Also - erl_lint","ref":"erl_lint.html#module-see-also"},{"type":"function","doc":"Takes an `ErrorDescriptor` and returns a string that describes the error or\nwarning. This function is usually called implicitly when processing an\n`ErrorInfo` structure (see section [Error Information](`m:erl_lint#module-error-information`)).","title":"erl_lint.format_error/1","ref":"erl_lint.html#format_error/1"},{"type":"function","doc":"Tests if `Expr` is a legal guard test. `Expr` is an Erlang term representing the\nabstract form for the expression.\n[`erl_parse:parse_exprs(Tokens)`](`erl_parse:parse_exprs/1`) can be used to\ngenerate a list of `Expr`.","title":"erl_lint.is_guard_test/1","ref":"erl_lint.html#is_guard_test/1"},{"type":"function","doc":"","title":"erl_lint.module/1","ref":"erl_lint.html#module/1"},{"type":"function","doc":"","title":"erl_lint.module/2","ref":"erl_lint.html#module/2"},{"type":"function","doc":"Checks all the forms in a module for errors. It returns:\n\n- **`{ok,Warnings}`** - There are no errors in the module.\n\n- **`{error,Errors,Warnings}`** - There are errors in the module.\n\nAs this module is of interest only to the maintainers of the compiler, and to\navoid the same description in two places, the elements of `Options` that control\nthe warnings are only described in the [`compile`](`m:compile#erl_lint_options`)\nmodule.\n\n`AbsForms` of a module, which comes from a file that is read through `epp`, the\nErlang preprocessor, can come from many files. This means that any references to\nerrors must include the filename, see the `m:epp` module or parser (see the\n`m:erl_parse` module). The returned errors and warnings have the following\nformat:\n\n```text\n[{SourceFile,[ErrorInfo]}]\n```\n\nThe errors and warnings are listed in the order in which they are encountered in\nthe forms. The errors from one file can therefore be split into different\nentries in the list of errors.","title":"erl_lint.module/3","ref":"erl_lint.html#module/3"},{"type":"type","doc":"","title":"erl_lint.error_description/0","ref":"erl_lint.html#t:error_description/0"},{"type":"type","doc":"","title":"erl_lint.error_info/0","ref":"erl_lint.html#t:error_info/0"},{"type":"type","doc":"","title":"erl_lint.fa/0","ref":"erl_lint.html#t:fa/0"},{"type":"type","doc":"","title":"erl_lint.fun_used_vars/0","ref":"erl_lint.html#t:fun_used_vars/0"},{"type":"module","doc":"This module is the basic Erlang parser that converts tokens into the abstract\nform of either forms (that is, top-level constructs), expressions, or terms.\n\nThe Abstract Format is described in the ERTS User's Guide. Notice that a token\nlist must end with the dot token to be acceptable to the parse functions\n(see the `m:erl_scan`) module.","title":"erl_parse","ref":"erl_parse.html"},{"type":"module","doc":"ErrorInfo is the standard ErrorInfo structure that is returned from all I/O modules.\nThe format is as follows:\n\n```\n{ErrorLine, Module, ErrorDescriptor}\n```\n\nA string describing the error is obtained with the following call:\n\n```\nModule:format_error(ErrorDescriptor)\n```","title":"Error Information - erl_parse","ref":"erl_parse.html#module-error-information"},{"type":"module","doc":"`m:erl_anno`, `m:erl_scan`, `m:io`, section [The Abstract Format](`e:erts:absform`)\nin the ERTS User's Guide.","title":"See Also - erl_parse","ref":"erl_parse.html#module-see-also"},{"type":"function","doc":"Converts the Erlang data structure `Data` into an abstract form of type\n`AbsTerm`. This function is the inverse of `normalise/1`.\n\n`erl_parse:abstract(T)` is equivalent to `erl_parse:abstract(T, 0)`.","title":"erl_parse.abstract/1","ref":"erl_parse.html#abstract/1"},{"type":"function","doc":"Converts the Erlang data structure `Data` into an abstract form of type\n`AbsTerm`.\n\nEach node of `AbsTerm` is assigned an annotation, see `m:erl_anno`. The\nannotation contains the location given by option `location` or by option `line`.\nOption `location` overrides option `line`. If neither option `location` nor\noption `line` is given, `0` is used as location.\n\nOption `Encoding` is used for selecting which integer lists to be considered as\nstrings. The default is to use the encoding returned by function\n`epp:default_encoding/0`. Value `none` means that no integer lists are\nconsidered as strings. `encoding_func()` is called with one integer of a list at\na time; if it returns `true` for every integer, the list is considered a string.","title":"erl_parse.abstract/2","ref":"erl_parse.html#abstract/2"},{"type":"function","doc":"Assumes that `Term` is a term with the same structure as a `erl_parse` tree, but\nwith terms, say `T`, where a `erl_parse` tree has collections of annotations.\n\nReturns a `erl_parse` tree where each term `T` is replaced by the value returned\nby [`erl_anno:from_term(T)`](`erl_anno:from_term/1`). The term `Term` is\ntraversed in a depth-first, left-to-right fashion.","title":"erl_parse.anno_from_term/1","ref":"erl_parse.html#anno_from_term/1"},{"type":"function","doc":"Returns a term where each collection of annotations `Anno` of the nodes of the\n`erl_parse` tree `Abstr` is replaced by the term returned by\n[`erl_anno:to_term(Anno)`](`erl_anno:to_term/1`). The `erl_parse` tree is\ntraversed in a depth-first, left-to-right fashion.","title":"erl_parse.anno_to_term/1","ref":"erl_parse.html#anno_to_term/1"},{"type":"function","doc":"Updates an accumulator by applying `Fun` on each collection of annotations of\nthe `erl_parse` tree `Abstr`.\n\nThe first call to `Fun` has `AccIn` as argument, the returned accumulator\n`AccOut` is passed to the next call, and so on. The\nfinal value of the accumulator is returned. The `erl_parse` tree is traversed in\na depth-first, left-to-right fashion.","title":"erl_parse.fold_anno/3","ref":"erl_parse.html#fold_anno/3"},{"type":"function","doc":"Uses an ErrorDescriptor and returns a string that describes the error.\n\nThis function is usually called implicitly when an ErrorInfo structure is\nprocessed (see section [Error Information](#module-error-information)).","title":"erl_parse.format_error/1","ref":"erl_parse.html#format_error/1"},{"type":"function","doc":"Modifies the `erl_parse` tree `Abstr` by applying `Fun` on each collection of\nannotations of the nodes of the `erl_parse` tree. The `erl_parse` tree is\ntraversed in a depth-first, left-to-right fashion.","title":"erl_parse.map_anno/2","ref":"erl_parse.html#map_anno/2"},{"type":"function","doc":"Modifies the `erl_parse` tree `Abstr` by applying `Fun` on each collection of\nannotations of the nodes of the `erl_parse` tree, while at the same time\nupdating an accumulator.\n\nThe first call to `Fun` has `AccIn` as second argument,\nthe returned accumulator `AccOut` is passed to the next call, and so on. The\nmodified `erl_parse` tree and the final value of the accumulator are returned.\nThe `erl_parse` tree is traversed in a depth-first, left-to-right fashion.","title":"erl_parse.mapfold_anno/3","ref":"erl_parse.html#mapfold_anno/3"},{"type":"function","doc":"Assumes that `Term` is a term with the same structure as a `erl_parse` tree, but\nwith [locations](`t:erl_anno:location/0`) where a `erl_parse` tree has\ncollections of annotations.\n\nReturns a `erl_parse` tree where each location `L`\nis replaced by the value returned by [`erl_anno:new(L)`](`erl_anno:new/1`). The\nterm `Term` is traversed in a depth-first, left-to-right fashion.","title":"erl_parse.new_anno/1","ref":"erl_parse.html#new_anno/1"},{"type":"function","doc":"Converts the abstract form `AbsTerm` of a term into a conventional Erlang data\nstructure (that is, the term itself). This function is the inverse of\n`abstract/1`.","title":"erl_parse.normalise/1","ref":"erl_parse.html#normalise/1"},{"type":"function","doc":"Parses `Tokens` as if it was a list of expressions.\n\nReturns one of the following:\n\n- **`{ok, ExprList}`** - The parsing was successful. `ExprList` is a list of the\n abstract forms of the parsed expressions.\n\n- **`{error, ErrorInfo}`** - An error occurred.","title":"erl_parse.parse_exprs/1","ref":"erl_parse.html#parse_exprs/1"},{"type":"function","doc":"Parses `Tokens` as if it was a form.\n\nReturns one of the following:\n\n- **`{ok, AbsForm}`** - The parsing was successful. `AbsForm` is the abstract\n form of the parsed form.\n\n- **`{error, ErrorInfo}`** - An error occurred.","title":"erl_parse.parse_form/1","ref":"erl_parse.html#parse_form/1"},{"type":"function","doc":"Parses `Tokens` as if it was a term.\n\nReturns one of the following:\n\n- **`{ok, Term}`** - The parsing was successful. `Term` is the Erlang term\n corresponding to the token list.\n\n- **`{error, ErrorInfo}`** - An error occurred.","title":"erl_parse.parse_term/1","ref":"erl_parse.html#parse_term/1"},{"type":"function","doc":"","title":"erl_parse.tokens/1","ref":"erl_parse.html#tokens/1"},{"type":"function","doc":"Generates a list of tokens representing the abstract form `AbsTerm` of an\nexpression. Optionally, `MoreTokens` is appended.","title":"erl_parse.tokens/2","ref":"erl_parse.html#tokens/2"},{"type":"type","doc":"Abstract form of an Erlang clause.","title":"erl_parse.abstract_clause/0","ref":"erl_parse.html#t:abstract_clause/0"},{"type":"type","doc":"Abstract form of an Erlang expression.","title":"erl_parse.abstract_expr/0","ref":"erl_parse.html#t:abstract_expr/0"},{"type":"type","doc":"Abstract form of an Erlang form.","title":"erl_parse.abstract_form/0","ref":"erl_parse.html#t:abstract_form/0"},{"type":"type","doc":"Abstract form of an Erlang type.","title":"erl_parse.abstract_type/0","ref":"erl_parse.html#t:abstract_type/0"},{"type":"type","doc":"","title":"erl_parse.af_anno/0","ref":"erl_parse.html#t:af_anno/0"},{"type":"type","doc":"","title":"erl_parse.af_annotated_type/0","ref":"erl_parse.html#t:af_annotated_type/0"},{"type":"type","doc":"","title":"erl_parse.af_args/0","ref":"erl_parse.html#t:af_args/0"},{"type":"type","doc":"","title":"erl_parse.af_assoc/1","ref":"erl_parse.html#t:af_assoc/1"},{"type":"type","doc":"","title":"erl_parse.af_assoc_exact/1","ref":"erl_parse.html#t:af_assoc_exact/1"},{"type":"type","doc":"","title":"erl_parse.af_assoc_type/0","ref":"erl_parse.html#t:af_assoc_type/0"},{"type":"type","doc":"","title":"erl_parse.af_atom/0","ref":"erl_parse.html#t:af_atom/0"},{"type":"type","doc":"","title":"erl_parse.af_behavior/0","ref":"erl_parse.html#t:af_behavior/0"},{"type":"type","doc":"","title":"erl_parse.af_behaviour/0","ref":"erl_parse.html#t:af_behaviour/0"},{"type":"type","doc":"","title":"erl_parse.af_bin/1","ref":"erl_parse.html#t:af_bin/1"},{"type":"type","doc":"","title":"erl_parse.af_binary_comprehension/0","ref":"erl_parse.html#t:af_binary_comprehension/0"},{"type":"type","doc":"","title":"erl_parse.af_binary_op/1","ref":"erl_parse.html#t:af_binary_op/1"},{"type":"type","doc":"Abstract representation of an element of a bitstring.","title":"erl_parse.af_binelement/1","ref":"erl_parse.html#t:af_binelement/1"},{"type":"type","doc":"","title":"erl_parse.af_binelement_size/0","ref":"erl_parse.html#t:af_binelement_size/0"},{"type":"type","doc":"","title":"erl_parse.af_bitstring_type/0","ref":"erl_parse.html#t:af_bitstring_type/0"},{"type":"type","doc":"","title":"erl_parse.af_block/0","ref":"erl_parse.html#t:af_block/0"},{"type":"type","doc":"","title":"erl_parse.af_body/0","ref":"erl_parse.html#t:af_body/0"},{"type":"type","doc":"","title":"erl_parse.af_case/0","ref":"erl_parse.html#t:af_case/0"},{"type":"type","doc":"","title":"erl_parse.af_catch/0","ref":"erl_parse.html#t:af_catch/0"},{"type":"type","doc":"","title":"erl_parse.af_character/0","ref":"erl_parse.html#t:af_character/0"},{"type":"type","doc":"","title":"erl_parse.af_clause/0","ref":"erl_parse.html#t:af_clause/0"},{"type":"type","doc":"","title":"erl_parse.af_clause_seq/0","ref":"erl_parse.html#t:af_clause_seq/0"},{"type":"type","doc":"","title":"erl_parse.af_compile/0","ref":"erl_parse.html#t:af_compile/0"},{"type":"type","doc":"","title":"erl_parse.af_cons/1","ref":"erl_parse.html#t:af_cons/1"},{"type":"type","doc":"","title":"erl_parse.af_constrained_function_type/0","ref":"erl_parse.html#t:af_constrained_function_type/0"},{"type":"type","doc":"","title":"erl_parse.af_constraint/0","ref":"erl_parse.html#t:af_constraint/0"},{"type":"type","doc":"","title":"erl_parse.af_empty_list_type/0","ref":"erl_parse.html#t:af_empty_list_type/0"},{"type":"type","doc":"","title":"erl_parse.af_export/0","ref":"erl_parse.html#t:af_export/0"},{"type":"type","doc":"","title":"erl_parse.af_export_type/0","ref":"erl_parse.html#t:af_export_type/0"},{"type":"type","doc":"","title":"erl_parse.af_fa_list/0","ref":"erl_parse.html#t:af_fa_list/0"},{"type":"type","doc":"","title":"erl_parse.af_field/0","ref":"erl_parse.html#t:af_field/0"},{"type":"type","doc":"Abstract representation of a record field.","title":"erl_parse.af_field_decl/0","ref":"erl_parse.html#t:af_field_decl/0"},{"type":"type","doc":"","title":"erl_parse.af_field_name/0","ref":"erl_parse.html#t:af_field_name/0"},{"type":"type","doc":"","title":"erl_parse.af_file/0","ref":"erl_parse.html#t:af_file/0"},{"type":"type","doc":"","title":"erl_parse.af_filter/0","ref":"erl_parse.html#t:af_filter/0"},{"type":"type","doc":"","title":"erl_parse.af_float/0","ref":"erl_parse.html#t:af_float/0"},{"type":"type","doc":"","title":"erl_parse.af_fun/0","ref":"erl_parse.html#t:af_fun/0"},{"type":"type","doc":"","title":"erl_parse.af_fun_type/0","ref":"erl_parse.html#t:af_fun_type/0"},{"type":"type","doc":"","title":"erl_parse.af_function_constraint/0","ref":"erl_parse.html#t:af_function_constraint/0"},{"type":"type","doc":"","title":"erl_parse.af_function_decl/0","ref":"erl_parse.html#t:af_function_decl/0"},{"type":"type","doc":"","title":"erl_parse.af_function_spec/0","ref":"erl_parse.html#t:af_function_spec/0"},{"type":"type","doc":"","title":"erl_parse.af_function_type/0","ref":"erl_parse.html#t:af_function_type/0"},{"type":"type","doc":"","title":"erl_parse.af_function_type_list/0","ref":"erl_parse.html#t:af_function_type_list/0"},{"type":"type","doc":"Abstract representation of a list, bitstring or map generator.","title":"erl_parse.af_generator/0","ref":"erl_parse.html#t:af_generator/0"},{"type":"type","doc":"","title":"erl_parse.af_guard/0","ref":"erl_parse.html#t:af_guard/0"},{"type":"type","doc":"","title":"erl_parse.af_guard_call/0","ref":"erl_parse.html#t:af_guard_call/0"},{"type":"type","doc":"","title":"erl_parse.af_guard_seq/0","ref":"erl_parse.html#t:af_guard_seq/0"},{"type":"type","doc":"","title":"erl_parse.af_guard_test/0","ref":"erl_parse.html#t:af_guard_test/0"},{"type":"type","doc":"","title":"erl_parse.af_if/0","ref":"erl_parse.html#t:af_if/0"},{"type":"type","doc":"","title":"erl_parse.af_import/0","ref":"erl_parse.html#t:af_import/0"},{"type":"type","doc":"","title":"erl_parse.af_integer/0","ref":"erl_parse.html#t:af_integer/0"},{"type":"type","doc":"","title":"erl_parse.af_integer_range_type/0","ref":"erl_parse.html#t:af_integer_range_type/0"},{"type":"type","doc":"","title":"erl_parse.af_list_comprehension/0","ref":"erl_parse.html#t:af_list_comprehension/0"},{"type":"type","doc":"","title":"erl_parse.af_lit_atom/1","ref":"erl_parse.html#t:af_lit_atom/1"},{"type":"type","doc":"","title":"erl_parse.af_literal/0","ref":"erl_parse.html#t:af_literal/0"},{"type":"type","doc":"","title":"erl_parse.af_local_call/0","ref":"erl_parse.html#t:af_local_call/0"},{"type":"type","doc":"","title":"erl_parse.af_local_fun/0","ref":"erl_parse.html#t:af_local_fun/0"},{"type":"type","doc":"","title":"erl_parse.af_local_function/0","ref":"erl_parse.html#t:af_local_function/0"},{"type":"type","doc":"","title":"erl_parse.af_map_comprehension/0","ref":"erl_parse.html#t:af_map_comprehension/0"},{"type":"type","doc":"","title":"erl_parse.af_map_creation/1","ref":"erl_parse.html#t:af_map_creation/1"},{"type":"type","doc":"","title":"erl_parse.af_map_pattern/0","ref":"erl_parse.html#t:af_map_pattern/0"},{"type":"type","doc":"","title":"erl_parse.af_map_type/0","ref":"erl_parse.html#t:af_map_type/0"},{"type":"type","doc":"","title":"erl_parse.af_map_update/1","ref":"erl_parse.html#t:af_map_update/1"},{"type":"type","doc":"","title":"erl_parse.af_match/1","ref":"erl_parse.html#t:af_match/1"},{"type":"type","doc":"","title":"erl_parse.af_maybe/0","ref":"erl_parse.html#t:af_maybe/0"},{"type":"type","doc":"","title":"erl_parse.af_maybe_else/0","ref":"erl_parse.html#t:af_maybe_else/0"},{"type":"type","doc":"","title":"erl_parse.af_maybe_match/0","ref":"erl_parse.html#t:af_maybe_match/0"},{"type":"type","doc":"","title":"erl_parse.af_module/0","ref":"erl_parse.html#t:af_module/0"},{"type":"type","doc":"","title":"erl_parse.af_named_fun/0","ref":"erl_parse.html#t:af_named_fun/0"},{"type":"type","doc":"","title":"erl_parse.af_nil/0","ref":"erl_parse.html#t:af_nil/0"},{"type":"type","doc":"","title":"erl_parse.af_pattern/0","ref":"erl_parse.html#t:af_pattern/0"},{"type":"type","doc":"","title":"erl_parse.af_predefined_type/0","ref":"erl_parse.html#t:af_predefined_type/0"},{"type":"type","doc":"","title":"erl_parse.af_qualifier/0","ref":"erl_parse.html#t:af_qualifier/0"},{"type":"type","doc":"","title":"erl_parse.af_qualifier_seq/0","ref":"erl_parse.html#t:af_qualifier_seq/0"},{"type":"type","doc":"","title":"erl_parse.af_receive/0","ref":"erl_parse.html#t:af_receive/0"},{"type":"type","doc":"","title":"erl_parse.af_record_creation/1","ref":"erl_parse.html#t:af_record_creation/1"},{"type":"type","doc":"","title":"erl_parse.af_record_decl/0","ref":"erl_parse.html#t:af_record_decl/0"},{"type":"type","doc":"","title":"erl_parse.af_record_field/1","ref":"erl_parse.html#t:af_record_field/1"},{"type":"type","doc":"","title":"erl_parse.af_record_field_access/1","ref":"erl_parse.html#t:af_record_field_access/1"},{"type":"type","doc":"","title":"erl_parse.af_record_field_type/0","ref":"erl_parse.html#t:af_record_field_type/0"},{"type":"type","doc":"","title":"erl_parse.af_record_index/0","ref":"erl_parse.html#t:af_record_index/0"},{"type":"type","doc":"","title":"erl_parse.af_record_type/0","ref":"erl_parse.html#t:af_record_type/0"},{"type":"type","doc":"","title":"erl_parse.af_record_update/1","ref":"erl_parse.html#t:af_record_update/1"},{"type":"type","doc":"","title":"erl_parse.af_remote_call/0","ref":"erl_parse.html#t:af_remote_call/0"},{"type":"type","doc":"","title":"erl_parse.af_remote_fun/0","ref":"erl_parse.html#t:af_remote_fun/0"},{"type":"type","doc":"Abstract representation of a remote function call.","title":"erl_parse.af_remote_function/0","ref":"erl_parse.html#t:af_remote_function/0"},{"type":"type","doc":"","title":"erl_parse.af_remote_guard_call/0","ref":"erl_parse.html#t:af_remote_guard_call/0"},{"type":"type","doc":"","title":"erl_parse.af_remote_type/0","ref":"erl_parse.html#t:af_remote_type/0"},{"type":"type","doc":"","title":"erl_parse.af_singleton_integer_type/0","ref":"erl_parse.html#t:af_singleton_integer_type/0"},{"type":"type","doc":"","title":"erl_parse.af_string/0","ref":"erl_parse.html#t:af_string/0"},{"type":"type","doc":"","title":"erl_parse.af_ta_list/0","ref":"erl_parse.html#t:af_ta_list/0"},{"type":"type","doc":"","title":"erl_parse.af_template/0","ref":"erl_parse.html#t:af_template/0"},{"type":"type","doc":"","title":"erl_parse.af_try/0","ref":"erl_parse.html#t:af_try/0"},{"type":"type","doc":"","title":"erl_parse.af_tuple/1","ref":"erl_parse.html#t:af_tuple/1"},{"type":"type","doc":"","title":"erl_parse.af_tuple_type/0","ref":"erl_parse.html#t:af_tuple_type/0"},{"type":"type","doc":"","title":"erl_parse.af_type_decl/0","ref":"erl_parse.html#t:af_type_decl/0"},{"type":"type","doc":"","title":"erl_parse.af_type_union/0","ref":"erl_parse.html#t:af_type_union/0"},{"type":"type","doc":"","title":"erl_parse.af_type_variable/0","ref":"erl_parse.html#t:af_type_variable/0"},{"type":"type","doc":"","title":"erl_parse.af_typed_field/0","ref":"erl_parse.html#t:af_typed_field/0"},{"type":"type","doc":"","title":"erl_parse.af_unary_op/1","ref":"erl_parse.html#t:af_unary_op/1"},{"type":"type","doc":"","title":"erl_parse.af_user_defined_type/0","ref":"erl_parse.html#t:af_user_defined_type/0"},{"type":"type","doc":"","title":"erl_parse.af_variable/0","ref":"erl_parse.html#t:af_variable/0"},{"type":"type","doc":"","title":"erl_parse.af_wild_attribute/0","ref":"erl_parse.html#t:af_wild_attribute/0"},{"type":"type","doc":"","title":"erl_parse.af_zip_generator/0","ref":"erl_parse.html#t:af_zip_generator/0"},{"type":"type","doc":"","title":"erl_parse.anno/0","ref":"erl_parse.html#t:anno/0"},{"type":"type","doc":"","title":"erl_parse.behaviour/0","ref":"erl_parse.html#t:behaviour/0"},{"type":"type","doc":"","title":"erl_parse.binary_op/0","ref":"erl_parse.html#t:binary_op/0"},{"type":"type","doc":"","title":"erl_parse.encoding_func/0","ref":"erl_parse.html#t:encoding_func/0"},{"type":"type","doc":"","title":"erl_parse.endianness/0","ref":"erl_parse.html#t:endianness/0"},{"type":"type","doc":"","title":"erl_parse.erl_parse_tree/0","ref":"erl_parse.html#t:erl_parse_tree/0"},{"type":"type","doc":"","title":"erl_parse.error_description/0","ref":"erl_parse.html#t:error_description/0"},{"type":"type","doc":"","title":"erl_parse.error_info/0","ref":"erl_parse.html#t:error_info/0"},{"type":"type","doc":"Tuples `{error, error_info()}` and `{warning, error_info()}`, denoting\nsyntactically incorrect forms and warnings, and `{eof, line()}`, denoting an\nend-of-stream encountered before a complete form had been parsed.","title":"erl_parse.form_info/0","ref":"erl_parse.html#t:form_info/0"},{"type":"type","doc":"","title":"erl_parse.fun_name/0","ref":"erl_parse.html#t:fun_name/0"},{"type":"type","doc":"","title":"erl_parse.function_name/0","ref":"erl_parse.html#t:function_name/0"},{"type":"type","doc":"","title":"erl_parse.record_name/0","ref":"erl_parse.html#t:record_name/0"},{"type":"type","doc":"","title":"erl_parse.signedness/0","ref":"erl_parse.html#t:signedness/0"},{"type":"type","doc":"","title":"erl_parse.spec_attr/0","ref":"erl_parse.html#t:spec_attr/0"},{"type":"type","doc":"","title":"erl_parse.token/0","ref":"erl_parse.html#t:token/0"},{"type":"type","doc":"","title":"erl_parse.type/0","ref":"erl_parse.html#t:type/0"},{"type":"type","doc":"","title":"erl_parse.type_attr/0","ref":"erl_parse.html#t:type_attr/0"},{"type":"type","doc":"","title":"erl_parse.type_name/0","ref":"erl_parse.html#t:type_name/0"},{"type":"type","doc":"","title":"erl_parse.type_specifier/0","ref":"erl_parse.html#t:type_specifier/0"},{"type":"type","doc":"","title":"erl_parse.type_specifier_list/0","ref":"erl_parse.html#t:type_specifier_list/0"},{"type":"type","doc":"","title":"erl_parse.unary_op/0","ref":"erl_parse.html#t:unary_op/0"},{"type":"type","doc":"","title":"erl_parse.unit/0","ref":"erl_parse.html#t:unit/0"},{"type":"module","doc":"The Erlang pretty printer.\n\nThe functions in this module are used to generate aesthetically attractive\nrepresentations of abstract forms, which are suitable for printing. All\nfunctions return (possibly deep) lists of characters and generate an error if\nthe form is wrong.\n\nAll functions can have an optional argument, which specifies a hook that is\ncalled if an attempt is made to print an unknown form.\n\nNote that if the functions in this module are used to convert abstract code back\nto Erlang source code, the enclosing function should first be processed by\n`legalize_vars/1` in order to ensure that the output is semantically equivalent\nto the abstract code.","title":"erl_pp","ref":"erl_pp.html"},{"type":"module","doc":"It is not possible to have hook functions for unknown forms at other places than\nexpressions.","title":"Known Limitations - erl_pp","ref":"erl_pp.html#module-known-limitations"},{"type":"module","doc":"`m:erl_eval`, `m:erl_parse`, `m:io`","title":"See Also - erl_pp","ref":"erl_pp.html#module-see-also"},{"type":"function","doc":"","title":"erl_pp.attribute/1","ref":"erl_pp.html#attribute/1"},{"type":"function","doc":"Same as [`form/1,2`](`form/1`), but only for attribute `Attribute`.","title":"erl_pp.attribute/2","ref":"erl_pp.html#attribute/2"},{"type":"function","doc":"","title":"erl_pp.expr/1","ref":"erl_pp.html#expr/1"},{"type":"function","doc":"","title":"erl_pp.expr/2","ref":"erl_pp.html#expr/2"},{"type":"function","doc":"","title":"erl_pp.expr/3","ref":"erl_pp.html#expr/3"},{"type":"function","doc":"Prints one expression.\n\nIt is useful for implementing hooks (see section\n[Known Limitations](`m:erl_pp#module-known-limitations`)).","title":"erl_pp.expr/4","ref":"erl_pp.html#expr/4"},{"type":"function","doc":"","title":"erl_pp.exprs/1","ref":"erl_pp.html#exprs/1"},{"type":"function","doc":"","title":"erl_pp.exprs/2","ref":"erl_pp.html#exprs/2"},{"type":"function","doc":"Same as [`form/1,2`](`form/1`), but only for the sequence of expressions in\n`Expressions`.","title":"erl_pp.exprs/3","ref":"erl_pp.html#exprs/3"},{"type":"function","doc":"","title":"erl_pp.form/1","ref":"erl_pp.html#form/1"},{"type":"function","doc":"Pretty prints a `Form`, which is an abstract form of a type that is returned by\n`erl_parse:parse_form/1`.","title":"erl_pp.form/2","ref":"erl_pp.html#form/2"},{"type":"function","doc":"","title":"erl_pp.function/1","ref":"erl_pp.html#function/1"},{"type":"function","doc":"Same as [`form/1,2`](`form/1`), but only for function `Function`.","title":"erl_pp.function/2","ref":"erl_pp.html#function/2"},{"type":"function","doc":"","title":"erl_pp.guard/1","ref":"erl_pp.html#guard/1"},{"type":"function","doc":"Same as [`form/1,2`](`form/1`), but only for the guard test `Guard`.","title":"erl_pp.guard/2","ref":"erl_pp.html#guard/2"},{"type":"function","doc":"The Erlang compiler will, when expanding records to tuples, introduce new\nvariables in the abstract representation. As the expansion is done on the\nabstract representation, the compiler can safely name the new variables with\nnames that are not syntactically valid in Erlang source code (the name starts\nwith a lowercase letter), thus ensuring the uniqueness of the new names.\n\nThe above strategy leads to problems if a user wants to convert the abstract\nrepresentation, using the functions of this module back to Erlang source code.\nTypically, pattern variables are output as atoms thus changing the sematics of\nthe program. To solve this problem [`legalize_vars/1`](`legalize_vars/1`), when\nrun on the abstract representation of a function, will return an equivalent\nfunction where all variables will have syntactically valid names.","title":"erl_pp.legalize_vars/1","ref":"erl_pp.html#legalize_vars/1"},{"type":"type","doc":"Optional argument `HookFunction`{: #hook_function }, shown in the functions\ndescribed in this module, defines a function that is called when an unknown form\noccurs where there is to be a valid expression. If `HookFunction` is equal to\n`none`, there is no hook function.\n\nThe called hook function is to return a (possibly deep) list of characters.\nFunction `expr/4` is useful in a hook.\n\nIf `CurrentIndentation` is negative, there are no line breaks and only a space\nis used as a separator.","title":"erl_pp.hook_function/0","ref":"erl_pp.html#t:hook_function/0"},{"type":"type","doc":"The option `quote_singleton_atom_types` is used to add quotes to all singleton\natom types.\n\nThe option `linewidth` controls the maximum line width for formatted lines\n(defaults to 72 characters).\n\nThe option `indent` controls the indention for formatted lines (defaults to 4\nspaces).","title":"erl_pp.option/0","ref":"erl_pp.html#t:option/0"},{"type":"type","doc":"","title":"erl_pp.options/0","ref":"erl_pp.html#t:options/0"},{"type":"module","doc":"The Erlang token scanner.\n\nThis module contains functions for tokenizing (scanning) characters into Erlang\ntokens.","title":"erl_scan","ref":"erl_scan.html"},{"type":"module","doc":"`ErrorInfo` is the standard `ErrorInfo` structure that is returned from all I/O\nmodules. The format is as follows:\n\n```erlang\n{ErrorLocation, Module, ErrorDescriptor}\n```\n\nA string describing the error is obtained with the following call:\n\n```erlang\nModule:format_error(ErrorDescriptor)\n```","title":"Error Information - erl_scan","ref":"erl_scan.html#module-error-information"},{"type":"module","doc":"The continuation of the first call to the re-entrant input functions must be\n`[]`. For a complete description of how the re-entrant input scheme works, see\nArmstrong, Virding and Williams: 'Concurrent Programming in Erlang', Chapter 13.","title":"Notes - erl_scan","ref":"erl_scan.html#module-notes"},{"type":"module","doc":"`m:erl_anno`, `m:erl_parse`, `m:io`","title":"See Also - erl_scan","ref":"erl_scan.html#module-see-also"},{"type":"function","doc":"Returns the category of `Token`.","title":"erl_scan.category/1","ref":"erl_scan.html#category/1"},{"type":"function","doc":"Returns the column of `Token`'s collection of annotations.","title":"erl_scan.column/1","ref":"erl_scan.html#column/1"},{"type":"function","doc":"Returns the end location of the text of `Token`'s collection of annotations. If\nthere is no text, `undefined` is returned.","title":"erl_scan.end_location/1","ref":"erl_scan.html#end_location/1"},{"type":"function","doc":"Uses an `ErrorDescriptor` and returns a string that describes the error or\nwarning. This function is usually called implicitly when an `ErrorInfo`\nstructure is processed (see section\n[Error Information](`m:erl_scan#module-error-information`)).","title":"erl_scan.format_error/1","ref":"erl_scan.html#format_error/1"},{"type":"function","doc":"Returns the line of `Token`'s collection of annotations.","title":"erl_scan.line/1","ref":"erl_scan.html#line/1"},{"type":"function","doc":"Returns the location of `Token`'s collection of annotations.","title":"erl_scan.location/1","ref":"erl_scan.html#location/1"},{"type":"function","doc":"Returns `true` if `Atom` is an Erlang reserved word, otherwise `false`.","title":"erl_scan.reserved_word/1","ref":"erl_scan.html#reserved_word/1"},{"type":"function","doc":"","title":"erl_scan.string/1","ref":"erl_scan.html#string/1"},{"type":"function","doc":"","title":"erl_scan.string/2","ref":"erl_scan.html#string/2"},{"type":"function","doc":"Takes the list of characters `String` and tries to scan (tokenize) them.\n\nReturns one of the following:\n\n- **`{ok, Tokens, EndLocation}`** - `Tokens` are the Erlang tokens from\n `String`. `EndLocation` is the first location after the last token.\n\n- **`{error, ErrorInfo, ErrorLocation}`** - An error occurred. `ErrorLocation`\n is the first location after the erroneous token.\n\n`StartLocation` indicates the initial location when scanning starts. If\n`StartLocation` is a line, `Anno`, `EndLocation`, and `ErrorLocation` are lines.\nIf `StartLocation` is a pair of a line and a column, `Anno` takes the form of an\nopaque compound data type, and `EndLocation` and `ErrorLocation` are pairs of a\nline and a column. The _token annotations_ contain information about the column\nand the line where the token begins, as well as the text of the token (if option\n`text` is specified), all of which can be accessed by calling `column/1`,\n`line/1`, `location/1`, and `text/1`.\n\nA _token_ is a tuple containing information about syntactic category, the token\nannotations, and the terminal symbol. For punctuation characters (such as `;`\nand `|`) and reserved words, the category and the symbol coincide, and the token\nis represented by a two-tuple. Three-tuples have one of the following forms:\n\n- `{atom, Anno, atom()}`\n- `{char, Anno, char()}`\n- `{comment, Anno, string()}`\n- `{float, Anno, float()}`\n- `{integer, Anno, integer()}`\n- `{var, Anno, atom()}`\n- `{white_space, Anno, string()}`\n\nValid options:\n\n- **`{reserved_word_fun, reserved_word_fun()}`** - A callback function that is\n called when the scanner has found an unquoted atom. If the function returns\n `true`, the unquoted atom itself becomes the category of the token. If the\n function returns `false`, `atom` becomes the category of the unquoted atom.\n\n- **`return_comments`** - Return comment tokens.\n\n- **`return_white_spaces`** - Return white space tokens. By convention, a\n newline character, if present, is always the first character of the text\n (there cannot be more than one newline in a white space token).\n\n- **`return`** - Short for `[return_comments, return_white_spaces]`.\n\n- **`text`{: #text }** - Include the token text in the token annotation. The\n text is the part of the input corresponding to the token. See also\n [`text_fun`](`m:erl_scan#text_fun`).\n\n- **`{text_fun, text_fun()}`{: #text_fun }** - A callback function used to\n determine whether the full text for the token shall be included in the token\n annotation. Arguments of the function are the category of the token and the\n full token string. This is only used when [`text`](`m:erl_scan#text`) is not\n present. If neither are present the text will not be saved in the token\n annotation.\n\n- **`{compiler_internal, term()}`{: #compiler_interal }** - Pass\n compiler-internal options to the scanner. The set of internal options\n understood by the scanner should be considered experimental and can thus be\n changed at any time without prior warning.\n\n The following options are currently understood:\n\n - **`ssa_checks`** - Tokenizes source code annotations used for encoding tests\n on the BEAM SSA code produced by the compiler.","title":"erl_scan.string/3","ref":"erl_scan.html#string/3"},{"type":"function","doc":"Returns the symbol of `Token`.","title":"erl_scan.symbol/1","ref":"erl_scan.html#symbol/1"},{"type":"function","doc":"Returns the text of `Token`'s collection of annotations. If there is no text,\n`undefined` is returned.","title":"erl_scan.text/1","ref":"erl_scan.html#text/1"},{"type":"function","doc":"","title":"erl_scan.tokens/3","ref":"erl_scan.html#tokens/3"},{"type":"function","doc":"This is the re-entrant scanner, which scans characters until either a _dot_ ('.'\nfollowed by a white space) or `eof` is reached.\n\nIt returns:\n\n- **`{done, Result, LeftOverChars}`** - Indicates that there is sufficient input\n data to get a result. `Result` is:\n\n - **`{ok, Tokens, EndLocation}`** - The scanning was successful. `Tokens` is\n the list of tokens including _dot_.\n\n - **`{eof, EndLocation}`** - End of file was encountered before any more\n tokens.\n\n - **`{error, ErrorInfo, EndLocation}`** - An error occurred. `LeftOverChars`\n is the remaining characters of the input data, starting from `EndLocation`.\n\n- **`{more, Continuation1}`** - More data is required for building a term.\n `Continuation1` must be passed in a new call to `tokens/3,4` when more data is\n available.\n\nThe `CharSpec` `eof` signals end of file. `LeftOverChars` then takes the value\n`eof` as well.\n\nFor a description of the options, see `string/3`.","title":"erl_scan.tokens/4","ref":"erl_scan.html#tokens/4"},{"type":"type","doc":"","title":"erl_scan.category/0","ref":"erl_scan.html#t:category/0"},{"type":"type","doc":"","title":"erl_scan.char_spec/0","ref":"erl_scan.html#t:char_spec/0"},{"type":"type","doc":"","title":"erl_scan.error_description/0","ref":"erl_scan.html#t:error_description/0"},{"type":"type","doc":"","title":"erl_scan.error_info/0","ref":"erl_scan.html#t:error_info/0"},{"type":"type","doc":"","title":"erl_scan.option/0","ref":"erl_scan.html#t:option/0"},{"type":"type","doc":"","title":"erl_scan.options/0","ref":"erl_scan.html#t:options/0"},{"type":"type","doc":"","title":"erl_scan.resword_fun/0","ref":"erl_scan.html#t:resword_fun/0"},{"type":"opaque","doc":"","title":"erl_scan.return_cont/0","ref":"erl_scan.html#t:return_cont/0"},{"type":"type","doc":"","title":"erl_scan.symbol/0","ref":"erl_scan.html#t:symbol/0"},{"type":"type","doc":"","title":"erl_scan.text_fun/0","ref":"erl_scan.html#t:text_fun/0"},{"type":"type","doc":"","title":"erl_scan.token/0","ref":"erl_scan.html#t:token/0"},{"type":"type","doc":"","title":"erl_scan.tokens/0","ref":"erl_scan.html#t:tokens/0"},{"type":"type","doc":"","title":"erl_scan.tokens_result/0","ref":"erl_scan.html#t:tokens_result/0"},{"type":"module","doc":"A parse transformation that translates fun syntax into match specifications.\n\nThis module provides the parse transformation that makes calls to `m:ets` and\n`dbg:fun2ms/1` translate into literal match specifications. It also provides the\nback end for the same functions when called from the Erlang shell.\n\nThe translation from funs to match specifications is accessed through the two\n\"pseudo functions\" `ets:fun2ms/1` and `dbg:fun2ms/1`.\n\nAs everyone trying to use [`ets:select/2`](`ets:select/1`) or `m:dbg` seems to\nend up reading this manual page, this description is an introduction to the\nconcept of match specifications.\n\nRead the whole manual page if it is the first time you are using the\ntransformations.\n\nMatch specifications are used more or less as filters. They resemble usual\nErlang matching in a list comprehension or in a fun used with `lists:foldl/3`,\nand so on. However, the syntax of pure match specifications is awkward, as they\nare made up purely by Erlang terms, and the language has no syntax to make the\nmatch specifications more readable.\n\nAs the execution and structure of the match specifications are like that of a\nfun, it is more straightforward to write it using the familiar fun syntax and to\nhave that translated into a match specification automatically. A real fun is\nclearly more powerful than the match specifications allow, but bearing the match\nspecifications in mind, and what they can do, it is still more convenient to\nwrite it all as a fun. This module contains the code that translates the fun\nsyntax into match specification terms.","title":"ms_transform","ref":"ms_transform.html"},{"type":"module","doc":"Using `ets:select/2` and a match specification, one can filter out rows of a\ntable and construct a list of tuples containing relevant parts of the data in\nthese rows. One can use `ets:foldl/3` instead, but the `ets:select/2` call is\nfar more efficient. Without the translation provided by `ms_transform`, one must\nstruggle with writing match specifications terms to accommodate this.\n\nConsider a simple table of employees:\n\n```erlang\n-record(emp, {empno, %Employee number as a string, the key\n surname, %Surname of the employee\n givenname, %Given name of employee\n dept, %Department, one of {dev,sales,prod,adm}\n empyear}). %Year the employee was employed\n```\n\nWe create the table using:\n\n```text\nets:new(emp_tab, [{keypos,#emp.empno},named_table,ordered_set]).\n```\n\nWe fill the table with randomly chosen data:\n\n```erlang\n[{emp,\"011103\",\"Black\",\"Alfred\",sales,2000},\n {emp,\"041231\",\"Doe\",\"John\",prod,2001},\n {emp,\"052341\",\"Smith\",\"John\",dev,1997},\n {emp,\"076324\",\"Smith\",\"Ella\",sales,1995},\n {emp,\"122334\",\"Weston\",\"Anna\",prod,2002},\n {emp,\"535216\",\"Chalker\",\"Samuel\",adm,1998},\n {emp,\"789789\",\"Harrysson\",\"Joe\",adm,1996},\n {emp,\"963721\",\"Scott\",\"Juliana\",dev,2003},\n {emp,\"989891\",\"Brown\",\"Gabriel\",prod,1999}]\n```\n\nAssuming that we want the employee numbers of everyone in the sales department,\nthere are several ways.\n\n`ets:match/2` can be used:\n\n```erlang\n1> ets:match(emp_tab, {'_', '$1', '_', '_', sales, '_'}).\n[[\"011103\"],[\"076324\"]]\n```\n\n`ets:match/2` uses a simpler type of match specification, but it is still\nunreadable, and one has little control over the returned result. It is always a\nlist of lists.\n\n`ets:foldl/3` or `ets:foldr/3` can be used to avoid the nested lists:\n\n```erlang\nets:foldr(fun(#emp{empno = E, dept = sales},Acc) -> [E | Acc];\n (_,Acc) -> Acc\n end,\n [],\n emp_tab).\n```\n\nThe result is `[\"011103\",\"076324\"]`. The fun is straightforward, so the only\nproblem is that all the data from the table must be transferred from the table\nto the calling process for filtering. That is inefficient compared to the\n`ets:match/2` call where the filtering can be done \"inside\" the emulator and\nonly the result is transferred to the process.\n\nConsider a \"pure\" `ets:select/2` call that does what `ets:foldr` does:\n\n```erlang\nets:select(emp_tab, [{#emp{empno = '$1', dept = sales, _='_'},[],['$1']}]).\n```\n\nAlthough the record syntax is used, it is still hard to read and even harder to\nwrite. The first element of the tuple,\n`#emp{empno = '$1', dept = sales, _='_'}`, tells what to match. Elements not\nmatching this are not returned, as in the `ets:match/2` example. The second\nelement, the empty list, is a list of guard expressions, which we do not need.\nThe third element is the list of expressions constructing the return value (in\nETS this is almost always a list containing one single term). In our case `'$1'`\nis bound to the employee number in the head (first element of the tuple), and\nhence the employee number is returned. The result is `[\"011103\",\"076324\"]`, as\nin the `ets:foldr/3` example, but the result is retrieved much more efficiently\nin terms of execution speed and memory consumption.\n\nUsing `ets:fun2ms/1`, we can combine the ease of use of the `ets:foldr/3` and\nthe efficiency of the pure `ets:select/2` example:\n\n```erlang\n-include_lib(\"stdlib/include/ms_transform.hrl\").\n\nets:select(emp_tab, ets:fun2ms(\n fun(#emp{empno = E, dept = sales}) ->\n E\n end)).\n```\n\nThis example requires no special knowledge of match specifications to\nunderstand. The head of the fun matches what you want to filter out and the body\nreturns what you want returned. As long as the fun can be kept within the limits\nof the match specifications, there is no need to transfer all table data to the\nprocess for filtering as in the `ets:foldr/3` example. It is easier to read than\nthe `ets:foldr/3` example, as the select call in itself discards anything that\ndoes not match, while the fun of the `ets:foldr/3` call needs to handle both the\nelements matching and the ones not matching.\n\nIn the `ets:fun2ms/1` example above, it is needed to include `ms_transform.hrl`\nin the source code, as this is what triggers the parse transformation of the\n`ets:fun2ms/1` call to a valid match specification. This also implies that the\ntransformation is done at compile time (except when called from the shell) and\ntherefore takes no resources in runtime. That is, although you use the more\nintuitive fun syntax, it gets as efficient in runtime as writing match\nspecifications by hand.","title":"Example 1 - ms_transform","ref":"ms_transform.html#module-example-1"},{"type":"module","doc":"Assume that we want to get all the employee numbers of employees hired before\nyear 2000. Using `ets:match/2` is not an alternative here, as relational\noperators cannot be expressed there. Once again, `ets:foldr/3` can do it\n(slowly, but correct):\n\n```erlang\nets:foldr(fun(#emp{empno = E, empyear = Y},Acc) when Y < 2000 -> [E | Acc];\n (_,Acc) -> Acc\n end,\n [],\n emp_tab).\n```\n\nThe result is `[\"052341\",\"076324\",\"535216\",\"789789\",\"989891\"]`, as expected. The\nequivalent expression using a handwritten match specification would look like\nthis:\n\n```erlang\nets:select(emp_tab, [{#emp{empno = '$1', empyear = '$2', _='_'},\n [{'<', '$2', 2000}],\n ['$1']}]).\n```\n\nThis gives the same result. `[{'<', '$2', 2000}]` is in the guard part and\ntherefore discards anything that does not have an `empyear` (bound to `'$2'` in\nthe head) less than 2000, as the guard in the `foldr/3` example.\n\nWe write it using `ets:fun2ms/1`:\n\n```erlang\n-include_lib(\"stdlib/include/ms_transform.hrl\").\n\nets:select(emp_tab, ets:fun2ms(\n fun(#emp{empno = E, empyear = Y}) when Y < 2000 ->\n E\n end)).\n```","title":"Example 2 - ms_transform","ref":"ms_transform.html#module-example-2"},{"type":"module","doc":"Assume that we want the whole object matching instead of only one element. One\nalternative is to assign a variable to every part of the record and build it up\nonce again in the body of the fun, but the following is easier:\n\n```erlang\nets:select(emp_tab, ets:fun2ms(\n fun(Obj = #emp{empno = E, empyear = Y})\n when Y < 2000 ->\n Obj\n end)).\n```\n\nAs in ordinary Erlang matching, you can bind a variable to the whole matched\nobject using a \"match inside the match\", that is, a `=`. Unfortunately in funs\ntranslated to match specifications, it is allowed only at the \"top-level\", that\nis, matching the _whole_ object arriving to be matched into a separate variable.\nIf you are used to writing match specifications by hand, we mention that\nvariable A is simply translated into '$\\_'. Alternatively, pseudo function\n`object/0` also returns the whole matched object, see section\n[Warnings and Restrictions](`m:ms_transform#warnings_and_restrictions`).","title":"Example 3 - ms_transform","ref":"ms_transform.html#module-example-3"},{"type":"module","doc":"This example concerns the body of the fun. Assume that all employee numbers\nbeginning with zero (`0`) must be changed to begin with one (`1`) instead, and\nthat we want to create the list `[{ , }]`:\n\n```erlang\nets:select(emp_tab, ets:fun2ms(\n fun(#emp{empno = [$0 | Rest] }) ->\n {[$0|Rest],[$1|Rest]}\n end)).\n```\n\nThis query hits the feature of partially bound keys in table type `ordered_set`,\nso that not the whole table needs to be searched, only the part containing keys\nbeginning with `0` is looked into.","title":"Example 4 - ms_transform","ref":"ms_transform.html#module-example-4"},{"type":"module","doc":"The fun can have many clauses. Assume that we want to do the following:\n\n- If an employee started before 1997, return the tuple\n `{inventory, }`.\n- If an employee started 1997 or later, but before 2001, return\n `{rookie, }`.\n- For all other employees, return `{newbie, }`, except for\n those named `Smith` as they would be affronted by anything other than the tag\n `guru` and that is also what is returned for their numbers:\n `{guru, }`.\n\nThis is accomplished as follows:\n\n```erlang\nets:select(emp_tab, ets:fun2ms(\n fun(#emp{empno = E, surname = \"Smith\" }) ->\n {guru,E};\n (#emp{empno = E, empyear = Y}) when Y < 1997 ->\n {inventory, E};\n (#emp{empno = E, empyear = Y}) when Y > 2001 ->\n {newbie, E};\n (#emp{empno = E, empyear = Y}) -> % 1997 -- 2001\n {rookie, E}\n end)).\n```\n\nThe result is as follows:\n\n```erlang\n[{rookie,\"011103\"},\n {rookie,\"041231\"},\n {guru,\"052341\"},\n {guru,\"076324\"},\n {newbie,\"122334\"},\n {rookie,\"535216\"},\n {inventory,\"789789\"},\n {newbie,\"963721\"},\n {rookie,\"989891\"}]\n```","title":"Example 5 - ms_transform","ref":"ms_transform.html#module-example-5"},{"type":"module","doc":"What more can you do? A simple answer is: see the documentation of\n[match specifications](`e:erts:match_spec.md`) in ERTS User's Guide. However,\nthe following is a brief overview of the most useful \"built-in functions\" that\nyou can use when the fun is to be translated into a match specification by\n`ets:fun2ms/1`. It is not possible to call other functions than those allowed in\nmatch specifications. No \"usual\" Erlang code can be executed by the fun that is\ntranslated by `ets:fun2ms/1`. The fun is limited exactly to the power of the\nmatch specifications, which is unfortunate, but the price one must pay for the\nexecution speed of `ets:select/2` compared to `ets:foldl/foldr`.\n\nThe head of the fun is a head matching (or mismatching) _one_ parameter, one\nobject of the table we select from. The object is always a single variable (can\nbe `_`) or a tuple, as ETS, Dets, and Mnesia tables include that. The match\nspecification returned by `ets:fun2ms/1` can be used with `dets:select/2` and\n`mnesia:select/2`, and with `ets:select/2`. The use of `=` in the head is\nallowed (and encouraged) at the top-level.\n\nThe guard section can contain any guard expression of Erlang. The following is a\nlist of BIFs and expressions:\n\n- Type tests: `is_atom`, `is_float`, `is_integer`, `is_list`, `is_number`,\n `is_pid`, `is_port`, `is_reference`, `is_tuple`, `is_binary`, `is_function`,\n `is_record`\n- Boolean operators: `not`, `and`, `or`, `andalso`, `orelse`\n- Relational operators: `>`, `>=`, `<`, `=<`, `=:=`, `==`, `=/=`, `/=`\n- Arithmetic: `+`, `-`, `*`, `div`, `rem`\n- Bitwise operators: `band`, `bor`, `bxor`, `bnot`, `bsl`, `bsr`\n- The guard BIFs: `abs`, `element`, `hd`, `length`, `node`, `round`, `size`,\n `byte_size`, `tl`, `trunc`, `binary_part`, `self`\n\nContrary to the fact with \"handwritten\" match specifications, the `is_record`\nguard works as in ordinary Erlang code.\n\nSemicolons (`;`) in guards are allowed, the result is (as expected) one \"match\nspecification clause\" for each semicolon-separated part of the guard. The\nsemantics is identical to the Erlang semantics.\n\nThe body of the fun is used to construct the resulting value. When selecting\nfrom tables, one usually construct a suiting term here, using ordinary Erlang\nterm construction, like tuple parentheses, list brackets, and variables matched\nout in the head, possibly with the occasional constant. Whatever expressions are\nallowed in guards are also allowed here, but no special functions exist except\n`object` and `bindings` (see further down), which returns the whole matched\nobject and all known variable bindings, respectively.\n\nThe `dbg` variants of match specifications have an imperative approach to the\nmatch specification body, the ETS dialect has not. The fun body for\n`ets:fun2ms/1` returns the result without side effects. As matching (`=`) in the\nbody of the match specifications is not allowed (for performance reasons) the\nonly thing left, more or less, is term construction.","title":"Useful BIFs - ms_transform","ref":"ms_transform.html#module-useful-bifs"},{"type":"module","doc":"This section describes the slightly different match specifications translated by\n`dbg:fun2ms/1`.\n\nThe same reasons for using the parse transformation apply to `dbg`, maybe even\nmore, as filtering using Erlang code is not a good idea when tracing (except\nafterwards, if you trace to file). The concept is similar to that of\n`ets:fun2ms/1` except that you usually use it directly from the shell (which can\nalso be done with `ets:fun2ms/1`).\n\nThe following is an example module to trace on:\n\n```erlang\n-module(toy).\n\n-export([start/1, store/2, retrieve/1]).\n\nstart(Args) ->\n toy_table = ets:new(toy_table, Args).\n\nstore(Key, Value) ->\n ets:insert(toy_table, {Key,Value}).\n\nretrieve(Key) ->\n [{Key, Value}] = ets:lookup(toy_table, Key),\n Value.\n```\n\nDuring model testing, the first test results in `{badmatch,16}` in\n`{toy,start,1}`, why?\n\nWe suspect the `ets:new/2` call, as we match hard on the return value, but want\nonly the particular `new/2` call with `toy_table` as first parameter. So we\nstart a default tracer on the node:\n\n```text\n1> dbg:tracer().\n{ok,<0.88.0>}\n```\n\nWe turn on call tracing for all processes, we want to make a pretty restrictive\ntrace pattern, so there is no need to call trace only a few processes (usually\nit is not):\n\n```text\n2> dbg:p(all,call).\n{ok,[{matched,nonode@nohost,25}]}\n```\n\nWe specify the filter, we want to view calls that resemble\n`ets:new(toy_table, )`:\n\n```erlang\n3> dbg:tp(ets,new,dbg:fun2ms(fun([toy_table,_]) -> true end)).\n{ok,[{matched,nonode@nohost,1},{saved,1}]}\n```\n\nAs can be seen, the fun used with `dbg:fun2ms/1` takes a single list as\nparameter instead of a single tuple. The list matches a list of the parameters\nto the traced function. A single variable can also be used. The body of the fun\nexpresses, in a more imperative way, actions to be taken if the fun head (and\nthe guards) matches. `true` is returned here, only because the body of a fun\ncannot be empty. The return value is discarded.\n\nThe following trace output is received during test:\n\n```erlang\n(<0.86.0>) call ets:new(toy_table, [ordered_set])\n```\n\nAssume that we have not found the problem yet, and want to see what `ets:new/2`\nreturns. We use a slightly different trace pattern:\n\n```erlang\n4> dbg:tp(ets,new,dbg:fun2ms(fun([toy_table,_]) -> return_trace() end)).\n```\n\nThe following trace output is received during test:\n\n```erlang\n(<0.86.0>) call ets:new(toy_table,[ordered_set])\n(<0.86.0>) returned from ets:new/2 -> 24\n```\n\nThe call to `return_trace` results in a trace message when the function returns.\nIt applies only to the specific function call triggering the match specification\n(and matching the head/guards of the match specification). This is by far the\nmost common call in the body of a `dbg` match specification.\n\nThe test now fails with `{badmatch,24}` because the atom `toy_table` does not\nmatch the number returned for an unnamed table. So, the problem is found, the\ntable is to be named, and the arguments supplied by the test program do not\ninclude `named_table`. We rewrite the start function:\n\n```erlang\nstart(Args) ->\n toy_table = ets:new(toy_table, [named_table|Args]).\n```\n\nWith the same tracing turned on, the following trace output is received:\n\n```erlang\n(<0.86.0>) call ets:new(toy_table,[named_table,ordered_set])\n(<0.86.0>) returned from ets:new/2 -> toy_table\n```\n\nAssume that the module now passes all testing and goes into the system. After a\nwhile, it is found that table `toy_table` grows while the system is running and\nthat there are many elements with atoms as keys. We expected only integer keys\nand so does the rest of the system, but clearly not the entire system. We turn\non call tracing and try to see calls to the module with an atom as the key:\n\n```erlang\n1> dbg:tracer().\n{ok,<0.88.0>}\n2> dbg:p(all,call).\n{ok,[{matched,nonode@nohost,25}]}\n3> dbg:tpl(toy,store,dbg:fun2ms(fun([A,_]) when is_atom(A) -> true end)).\n{ok,[{matched,nonode@nohost,1},{saved,1}]}\n```\n\nWe use `dbg:tpl/3` to ensure to catch local calls (assume that the module has\ngrown since the smaller version and we are unsure if this inserting of atoms is\nnot done locally). When in doubt, always use local call tracing.\n\nAssume that nothing happens when tracing in this way. The function is never\ncalled with these parameters. We conclude that someone else (some other module)\nis doing it and realize that we must trace on `ets:insert/2` and want to see the\ncalling function. The calling function can be retrieved using the match\nspecification function `caller`. To get it into the trace message, the match\nspecification function `message` must be used. The filter call looks like this\n(looking for calls to `ets:insert/2`):\n\n```erlang\n4> dbg:tpl(ets,insert,dbg:fun2ms(fun([toy_table,{A,_}]) when is_atom(A) ->\n message(caller())\n end)).\n{ok,[{matched,nonode@nohost,1},{saved,2}]}\n```\n\nThe caller is now displayed in the \"additional message\" part of the trace\noutput, and the following is displayed after a while:\n\n```erlang\n(<0.86.0>) call ets:insert(toy_table,{garbage,can}) ({evil_mod,evil_fun,2})\n```\n\nYou have realized that function `evil_fun` of the `evil_mod` module, with arity\n`2`, is causing all this trouble.\n\nThis example illustrates the most used calls in match specifications for `dbg`.\nThe other, more esoteric, calls are listed and explained in\n[Match specifications in Erlang](`e:erts:match_spec.md`) in ERTS User's Guide,\nas they are beyond the scope of this description.","title":"Example with dbg - ms_transform","ref":"ms_transform.html#module-example-with-dbg"},{"type":"module","doc":"[](){: #warnings_and_restrictions }\n\nThe following warnings and restrictions apply to the funs used in with\n`ets:fun2ms/1` and `dbg:fun2ms/1`.\n\n> #### Warning {: .warning }\n>\n> To use the pseudo functions triggering the translation, ensure to include the\n> header file `ms_transform.hrl` in the source code. Failure to do so possibly\n> results in runtime errors rather than compile time, as the expression can be\n> valid as a plain Erlang program without translation.\n\n> #### Warning {: .warning }\n>\n> The fun must be literally constructed inside the parameter list to the pseudo\n> functions. The fun cannot be bound to a variable first and then passed to\n> `ets:fun2ms/1` or `dbg:fun2ms/1`. For example, `ets:fun2ms(fun(A) -> A end)`\n> works, but not `F = fun(A) -> A end, ets:fun2ms(F)`. The latter results in a\n> compile-time error if the header is included, otherwise a runtime error.\n\nMany restrictions apply to the fun that is translated into a match\nspecification. To put it simple: you cannot use anything in the fun that you\ncannot use in a match specification. This means that, among others, the\nfollowing restrictions apply to the fun itself:\n\n- Functions written in Erlang cannot be called, neither can local functions,\n global functions, or real funs.\n- Everything that is written as a function call is translated into a match\n specification call to a built-in function, so that the call\n [`is_list(X)`](`is_list/1`) is translated to `{'is_list', '$1'}` (`'$1'` is\n only an example, the numbering can vary). If one tries to call a function that\n is not a match specification built-in, it causes an error.\n- Variables occurring in the head of the fun are replaced by match specification\n variables in the order of occurrence, so that fragment `fun({A,B,C})` is\n replaced by `{'$1', '$2', '$3'}`, and so on. Every occurrence of such a\n variable in the match specification is replaced by a match specification\n variable in the same way, so that the fun\n `fun({A,B}) when is_atom(A) -> B end` is translated into\n `[{{'$1','$2'},[{is_atom,'$1'}],['$2']}]`.\n- Variables that are not included in the head are imported from the environment\n and made into match specification `const` expressions. Example from the shell:\n\n ```erlang\n 1> X = 25.\n 25\n 2> ets:fun2ms(fun({A,B}) when A > X -> B end).\n [{{'$1','$2'},[{'>','$1',{const,25}}],['$2']}]\n ```\n\n- Matching with `=` cannot be used in the body. It can only be used on the\n top-level in the head of the fun. Example from the shell again:\n\n ```erlang\n 1> ets:fun2ms(fun({A,[B|C]} = D) when A > B -> D end).\n [{{'$1',['$2'|'$3']},[{'>','$1','$2'}],['$_']}]\n 2> ets:fun2ms(fun({A,[B|C]=D}) when A > B -> D end).\n Error: fun with head matching ('=' in head) cannot be translated into\n match_spec\n {error,transform_error}\n 3> ets:fun2ms(fun({A,[B|C]}) when A > B -> D = [B|C], D end).\n Error: fun with body matching ('=' in body) is illegal as match_spec\n {error,transform_error}\n ```\n\n All variables are bound in the head of a match specification, so the\n translator cannot allow multiple bindings. The special case when matching is\n done on the top-level makes the variable bind to `'$_'` in the resulting match\n specification. It is to allow a more natural access to the whole matched\n object. Pseudo function `object()` can be used instead, see below.\n\n The following expressions are translated equally:\n\n ```erlang\n ets:fun2ms(fun({a,_} = A) -> A end).\n ets:fun2ms(fun({a,_}) -> object() end).\n ```\n\n- The special match specification variables `'$_'` and `'$*'` can be accessed\n through the pseudo functions `object()` (for `'$_'`) and `bindings()` (for\n `'$*'`). As an example, one can translate the following `ets:match_object/2`\n call to a `ets:select/2` call:\n\n ```erlang\n ets:match_object(Table, {'$1',test,'$2'}).\n ```\n\n This is the same as:\n\n ```erlang\n ets:select(Table, ets:fun2ms(fun({A,test,B}) -> object() end)).\n ```\n\n In this simple case, the former expression is probably preferable in terms of\n readability.\n\n The `ets:select/2` call conceptually looks like this in the resulting code:\n\n ```erlang\n ets:select(Table, [{{'$1',test,'$2'},[],['$_']}]).\n ```\n\n Matching on the top-level of the fun head can be a more natural way to access\n `'$_'`, see above.\n\n- Term constructions/literals are translated as much as is needed to get them\n into valid match specification. This way tuples are made into match\n specification tuple constructions (a one element tuple containing the tuple)\n and constant expressions are used when importing variables from the\n environment. Records are also translated into plain tuple constructions, calls\n to element, and so on. The guard test [`is_record/2`](`is_record/2`) is\n translated into match specification code using the three parameter version\n that is built into match specification, so that\n [`is_record(A,t)`](`is_record/2`) is translated into `{is_record,'$1',t,5}` if\n the record size of record type `t` is 5.\n- Language constructions such as `case`, `if`, and `catch` that are not present\n in match specifications are not allowed.\n- If header file `ms_transform.hrl` is not included, the fun is not translated,\n which can result in a _runtime error_ (depending on whether the fun is valid\n in a pure Erlang context).\n\n Ensure that the header is included when using `ets` and `dbg:fun2ms/1` in\n compiled code.\n\n- If pseudo function triggering the translation is `ets:fun2ms/1`, the head of\n the fun must contain a single variable or a single tuple. If the pseudo\n function is `dbg:fun2ms/1`, the head of the fun must contain a single variable\n or a single list.\n\nThe translation from funs to match specifications is done at compile time, so\nruntime performance is not affected by using these pseudo functions.\n\nFor more information about match specifications, see the\n[Match specifications in Erlang](`e:erts:match_spec.md`) in ERTS User's Guide.","title":"Warnings and Restrictions - ms_transform","ref":"ms_transform.html#module-warnings-and-restrictions"},{"type":"function","doc":"Takes an error code returned by one of the other functions in the module and\ncreates a textual description of the error.","title":"ms_transform.format_error/1","ref":"ms_transform.html#format_error/1"},{"type":"function","doc":"Implements the transformation at compile time. This function is called by the\ncompiler to do the source code transformation if and when header file\n`ms_transform.hrl` is included in the source code.\n\nFor information about how to use this parse transformation, see `m:ets` and\n`dbg:fun2ms/1`.\n\nFor a description of match specifications, see section\n[Match Specification in Erlang](`e:erts:match_spec.md`) in ERTS User's Guide.","title":"ms_transform.parse_transform/2","ref":"ms_transform.html#parse_transform/2"},{"type":"function","doc":"Implements the transformation when the `fun2ms/1` functions are called from the\nshell. In this case, the abstract form is for one single fun (parsed by the\nErlang shell). All imported variables are to be in the key-value list passed as\n`BoundEnvironment`. The result is a term, normalized, that is, not in abstract\nformat.","title":"ms_transform.transform_from_shell/3","ref":"ms_transform.html#transform_from_shell/3"},{"type":"module","doc":"Functional, extendible arrays.\n\nArrays can have fixed size, or can grow automatically as needed. A default value\nis used for entries that have not been explicitly set.\n\nArrays uses _zero_-based indexing. This is a deliberate design choice and\ndiffers from other Erlang data structures, for example, tuples.\n\nUnless specified by the user when the array is created, the default value is the\natom `undefined`. There is no difference between an unset entry and an entry\nthat has been explicitly set to the same value as the default one (compare\n`reset/2`). If you need to differentiate between unset and set entries, ensure\nthat the default value cannot be confused with the values of set entries.\n\nThe array never shrinks automatically. If an index `I` has been used to set an\nentry successfully, all indices in the range `[0,I]` stay accessible unless the\narray size is explicitly changed by calling `resize/2`.\n\n_Examples:_\n\nCreate a fixed-size array with entries 0-9 set to `undefined`:\n\n```\nA0 = array:new(10).\n10 = array:size(A0).\n```\n\nCreate an extendible array and set entry 17 to `true`, causing the array to grow\nautomatically:\n\n```\nA1 = array:set(17, true, array:new()).\n18 = array:size(A1).\n```\n\nRead back a stored value:\n\n```\ntrue = array:get(17, A1).\n```\n\nAccessing an unset entry returns default value:\n\n```\nundefined = array:get(3, A1)\n```\n\nAccessing an entry beyond the last set entry also returns the default value, if\nthe array does not have fixed size:\n\n```\nundefined = array:get(18, A1).\n```\n\n\"Sparse\" functions ignore default-valued entries:\n\n```\nA2 = array:set(4, false, A1).\n[{4, false}, {17, true}] = array:sparse_to_orddict(A2).\n```\n\nAn extendible array can be made fixed-size later:\n\n```\nA3 = array:fix(A2).\n```\n\nA fixed-size array does not grow automatically and does not allow accesses\nbeyond the last set entry:\n\n```\n{'EXIT',{badarg,_}} = (catch array:set(18, true, A3)).\n{'EXIT',{badarg,_}} = (catch array:get(18, A3)).\n```","title":"array","ref":"array.html"},{"type":"function","doc":"Gets the value used for uninitialized entries.\n\nSee also `new/2`.","title":"array.default/1","ref":"array.html#default/1"},{"type":"function","doc":"Fixes the array size. This prevents it from growing automatically upon\ninsertion.\n\nSee also `set/3` and `relax/1`.","title":"array.fix/1","ref":"array.html#fix/1"},{"type":"function","doc":"Folds the array elements using the specified function and initial accumulator\nvalue. The elements are visited in order from the lowest index to the highest.\n\nIf `Function` is not a function, the call fails with reason `badarg`.\n\nSee also `foldr/3`, `map/2`, `sparse_foldl/3`.","title":"array.foldl/3","ref":"array.html#foldl/3"},{"type":"function","doc":"Folds the array elements right-to-left using the specified function and initial\naccumulator value. The elements are visited in order from the highest index to\nthe lowest.\n\nIf `Function` is not a function, the call fails with reason `badarg`.\n\nSee also `foldl/3`, `map/2`.","title":"array.foldr/3","ref":"array.html#foldr/3"},{"type":"function","doc":"Equivalent to [`from_list(List, undefined)`](`from_list/2`).","title":"array.from_list/1","ref":"array.html#from_list/1"},{"type":"function","doc":"Converts a list to an extendible array. `Default` is used as the value for\nuninitialized entries of the array.\n\nIf `List` is not a proper list, the call fails with reason `badarg`.\n\nSee also `new/2`, `to_list/1`.","title":"array.from_list/2","ref":"array.html#from_list/2"},{"type":"function","doc":"Equivalent to [`from_orddict(Orddict, undefined)`](`from_orddict/2`).","title":"array.from_orddict/1","ref":"array.html#from_orddict/1"},{"type":"function","doc":"Converts an ordered list of pairs `{Index, Value}` to a corresponding extendible\narray. `Default` is used as the value for uninitialized entries of the array.\n\nIf `Orddict` is not a proper, ordered list of pairs whose first elements are\nnon-negative integers, the call fails with reason `badarg`.\n\nSee also `new/2`, `to_orddict/1`.","title":"array.from_orddict/2","ref":"array.html#from_orddict/2"},{"type":"function","doc":"Gets the value of entry `I`.\n\nIf `I` is not a non-negative integer, or if the array has fixed size and `I` is\nlarger than the maximum index, the call fails with reason `badarg`.\n\nIf the array does not have fixed size, the default value for any index `I`\ngreater than `size(Array)-1` is returned.\n\nSee also `set/3`.","title":"array.get/2","ref":"array.html#get/2"},{"type":"function","doc":"Returns `true` if `X` is an array, otherwise `false`.\n\nNotice that the check is only shallow, as there is no guarantee that `X` is a\nwell-formed array representation even if this function returns `true`.","title":"array.is_array/1","ref":"array.html#is_array/1"},{"type":"function","doc":"Checks if the array has fixed size. Returns `true` if the array is fixed,\notherwise `false`.\n\nSee also `fix/1`.","title":"array.is_fix/1","ref":"array.html#is_fix/1"},{"type":"function","doc":"Maps the specified function onto each array element. The elements are visited in\norder from the lowest index to the highest.\n\nIf `Function` is not a function, the call fails with reason `badarg`.\n\nSee also `foldl/3`, `foldr/3`, `sparse_map/2`.","title":"array.map/2","ref":"array.html#map/2"},{"type":"function","doc":"Creates a new, extendible array with initial size zero.\n\nSee also `new/1`, `new/2`.","title":"array.new/0","ref":"array.html#new/0"},{"type":"function","doc":"Creates a new array according to the specified options. By default, the array is\nextendible and has initial size zero. Array indices start at `0`.\n\n`Options` is a single term or a list of terms, selected from the following:\n\n- **`N::integer() >= 0` or `{size, N::integer() >= 0}`** - Specifies the initial\n array size; this also implies `{fixed, true}`. If `N` is not a non-negative\n integer, the call fails with reason `badarg`.\n\n- **`fixed` or `{fixed, true}`** - Creates a fixed-size array. See also `fix/1`.\n\n- **`{fixed, false}`** - Creates an extendible (non-fixed-size) array.\n\n- **`{default, Value}`** - Sets the default value for the array to `Value`.\n\nOptions are processed in the order they occur in the list, that is, later\noptions have higher precedence.\n\nThe default value is used as the value of uninitialized entries, and cannot be\nchanged once the array has been created.\n\n_Examples:_\n\n```\narray:new(100)\n```\n\ncreates a fixed-size array of size 100.\n\n```\narray:new({default,0})\n```\n\ncreates an empty, extendible array whose default value is `0`.\n\n```\narray:new([{size,10},{fixed,false},{default,-1}])\n```\n\ncreates an extendible array with initial size 10 whose default value is `-1`.\n\nSee also `fix/1`, `from_list/2`, `get/2`, `new/0`, `new/2`, `set/3`.","title":"array.new/1","ref":"array.html#new/1"},{"type":"function","doc":"Creates a new array according to the specified size and options.\n\nIf `Size` is not a non-negative integer, the call fails with reason `badarg`.\nBy default, the array has fixed size. Notice that any size specifications in\n`Options` override parameter `Size`.\n\nIf `Options` is a list, this is equivalent to\n[`new([{size, Size} | Options])`](`new/1`), otherwise it is equivalent to\n[`new([{size, Size} | [Options]])`](`new/1`). However, using this function\ndirectly is more efficient.\n\n_Example:_\n\n```\narray:new(100, {default,0})\n```\n\ncreates a fixed-size array of size 100, whose default value is `0`.\n\nSee also `new/1`.","title":"array.new/2","ref":"array.html#new/2"},{"type":"function","doc":"Makes the array resizable. (Reverses the effects of `fix/1`.)\n\nSee also `fix/1`.","title":"array.relax/1","ref":"array.html#relax/1"},{"type":"function","doc":"Resets entry `I` to the default value for the array. If the value of entry `I`\nis the default value, the array is returned unchanged.\n\nReset never changes the array size. Shrinking can be done explicitly by calling\n`resize/2`.\n\nIf `I` is not a non-negative integer, or if the array has fixed size and `I` is\nlarger than the maximum index, the call fails with reason `badarg`; compare\n`set/3`\n\nSee also `new/2`, `set/3`.","title":"array.reset/2","ref":"array.html#reset/2"},{"type":"function","doc":"Changes the array size to that reported by `sparse_size/1`. If the specified\narray has fixed size, also the resulting array has fixed size.\n\nSee also `resize/2`, `sparse_size/1`.","title":"array.resize/1","ref":"array.html#resize/1"},{"type":"function","doc":"Change the array size.\n\nIf `Size` is not a non-negative integer, the call fails with reason `badarg`. If\nthe specified array has fixed size, also the resulting array has fixed size.","title":"array.resize/2","ref":"array.html#resize/2"},{"type":"function","doc":"Sets entry `I` of the array to `Value`.\n\nIf `I` is not a non-negative integer, or if the array has fixed size and `I` is\nlarger than the maximum index, the call fails with reason `badarg`.\n\nIf the array does not have fixed size, and `I` is greater than `size(Array)-1`,\nthe array grows to size `I+1`.\n\nSee also `get/2`, `reset/2`.","title":"array.set/3","ref":"array.html#set/3"},{"type":"function","doc":"Gets the number of entries in the array. Entries are numbered from `0` to\n`size(Array)-1`. Hence, this is also the index of the first entry that is\nguaranteed to not have been previously set.\n\nSee also `set/3`, `sparse_size/1`.","title":"array.size/1","ref":"array.html#size/1"},{"type":"function","doc":"Folds the array elements using the specified function and initial accumulator\nvalue, skipping default-valued entries. The elements are visited in order from\nthe lowest index to the highest.\n\nIf `Function` is not a function, the call fails with reason `badarg`.\n\nSee also `foldl/3`, `sparse_foldr/3`.","title":"array.sparse_foldl/3","ref":"array.html#sparse_foldl/3"},{"type":"function","doc":"Folds the array elements right-to-left using the specified function and initial\naccumulator value, skipping default-valued entries. The elements are visited in\norder from the highest index to the lowest.\n\nIf `Function` is not a function, the call fails with reason `badarg`.\n\nSee also `foldr/3`, `sparse_foldl/3`.","title":"array.sparse_foldr/3","ref":"array.html#sparse_foldr/3"},{"type":"function","doc":"Maps the specified function onto each array element, skipping default-valued\nentries. The elements are visited in order from the lowest index to the highest.\n\nIf `Function` is not a function, the call fails with reason `badarg`.\n\nSee also `map/2`.","title":"array.sparse_map/2","ref":"array.html#sparse_map/2"},{"type":"function","doc":"Gets the number of entries in the array up until the last non-default-valued\nentry. That is, returns `I+1` if `I` is the last non-default-valued entry in the\narray, or zero if no such entry exists.\n\nSee also `resize/1`, `size/1`.","title":"array.sparse_size/1","ref":"array.html#sparse_size/1"},{"type":"function","doc":"Converts the array to a list, skipping default-valued entries.\n\nSee also `to_list/1`.","title":"array.sparse_to_list/1","ref":"array.html#sparse_to_list/1"},{"type":"function","doc":"Converts the array to an ordered list of pairs `{Index, Value}`, skipping\ndefault-valued entries.\n\nSee also `to_orddict/1`.","title":"array.sparse_to_orddict/1","ref":"array.html#sparse_to_orddict/1"},{"type":"function","doc":"Converts the array to a list.\n\nSee also `from_list/2`, `sparse_to_list/1`.","title":"array.to_list/1","ref":"array.html#to_list/1"},{"type":"function","doc":"Converts the array to an ordered list of pairs `{Index, Value}`.\n\nSee also `from_orddict/2`, `sparse_to_orddict/1`.","title":"array.to_orddict/1","ref":"array.html#to_orddict/1"},{"type":"type","doc":"","title":"array.array/0","ref":"array.html#t:array/0"},{"type":"opaque","doc":"A functional, extendible array. The representation is not documented and is\nsubject to change without notice. Notice that arrays cannot be directly compared\nfor equality.","title":"array.array/1","ref":"array.html#t:array/1"},{"type":"type","doc":"","title":"array.array_indx/0","ref":"array.html#t:array_indx/0"},{"type":"type","doc":"","title":"array.array_opt/0","ref":"array.html#t:array_opt/0"},{"type":"type","doc":"","title":"array.array_opts/0","ref":"array.html#t:array_opts/0"},{"type":"type","doc":"","title":"array.indx_pair/1","ref":"array.html#t:indx_pair/1"},{"type":"type","doc":"","title":"array.indx_pairs/1","ref":"array.html#t:indx_pairs/1"},{"type":"module","doc":"A disk-based term storage.\n\nThis module provides a term storage on file. The stored terms, in this module\ncalled _objects_, are tuples such that one element is defined to be the key. A\nDets _table_ is a collection of objects with the key at the same position stored\non a file.\n\nThis module is used by the Mnesia application, and is provided \"as is\" for users\nwho are interested in efficient storage of Erlang terms on disk only. Many\napplications only need to store some terms in a file. Mnesia adds transactions,\nqueries, and distribution. The size of Dets files cannot exceed 2 GB. If larger\ntables are needed, table fragmentation in Mnesia can be used.\n\nThree types of Dets tables exist:\n\n- `set`. A table of this type has at most one object with a given key. If an\n object with a key already present in the table is inserted, the existing\n object is overwritten by the new object.\n- `bag`. A table of this type has zero or more different objects with a given\n key.\n- `duplicate_bag`. A table of this type has zero or more possibly matching\n objects with a given key.\n\nDets tables must be opened before they can be updated or read, and when finished\nthey must be properly closed. If a table is not properly closed, Dets\nautomatically repairs the table. This can take a substantial time if the table\nis large. A Dets table is closed when the process which opened the table\nterminates. If many Erlang processes (users) open the same Dets table, they\nshare the table. The table is properly closed when all users have either\nterminated or closed the table. Dets tables are not properly closed if the\nErlang runtime system terminates abnormally.\n\n> #### Note {: .info }\n>\n> A `^C` command abnormally terminates an Erlang runtime system in a Unix\n> environment with a break-handler.\n\nAs all operations performed by Dets are disk operations, it is important to\nrealize that a single look-up operation involves a series of disk seek and read\noperations. The Dets functions are therefore much slower than the corresponding\n`m:ets` functions, although Dets exports a similar interface.\n\nDets organizes data as a linear hash list and the hash list grows gracefully as\nmore data is inserted into the table. Space management on the file is performed\nby what is called a buddy system. The current implementation keeps the entire\nbuddy system in RAM, which implies that if the table gets heavily fragmented,\nquite some memory can be used up. The only way to defragment a table is to close\nit and then open it again with option `repair` set to `force`.\n\nNotice that type `ordered_set` in Ets is not yet provided by Dets, neither is\nthe limited support for concurrent updates that makes a sequence of `first` and\n`next` calls safe to use on fixed ETS tables. Both these features may be\nprovided by Dets in a future release of Erlang/OTP. Until then, the Mnesia\napplication (or some user-implemented method for locking) must be used to\nimplement safe concurrency. Currently, no Erlang/OTP library has support for\nordered disk-based term storage.\n\nAll Dets functions return `{error, Reason}` if an error occurs (`first/1` and\n`next/2` are exceptions, they exit the process with the error tuple). If badly\nformed arguments are specified, all functions exit the process with a `badarg`\nmessage.","title":"dets","ref":"dets.html"},{"type":"module","doc":"`m:ets`, `m:mnesia`, `m:qlc`","title":"See Also - dets","ref":"dets.html#module-see-also"},{"type":"function","doc":"Returns a list of the names of all open tables on this node.","title":"dets.all/0","ref":"dets.html#all/0"},{"type":"function","doc":"Returns a list of objects stored in a table. The exact representation of the\nreturned objects is not public.\n\nThe lists of data can be used for initializing a table by specifying value\n`bchunk` to option `format` of function `init_table/3`. The Mnesia application\nuses this function for copying open tables.\n\nUnless the table is protected using [`safe_fixtable/2`](`safe_fixtable/2`),\ncalls to [`bchunk/2`](`bchunk/2`) do possibly not work as expected if concurrent\nupdates are made to the table.\n\nThe first time [`bchunk/2`](`bchunk/2`) is called, an initial continuation, the\natom `start`, must be provided.\n\n[`bchunk/2`](`bchunk/2`) returns a tuple `{Continuation2, Data}`, where `Data`\nis a list of objects. `Continuation2` is another continuation that is to be\npassed on to a subsequent call to [`bchunk/2`](`bchunk/2`). With a series of\ncalls to [`bchunk/2`](`bchunk/2`), all table objects can be extracted.\n\n[`bchunk/2`](`bchunk/2`) returns `'$end_of_table'` when all objects are\nreturned, or `{error, Reason}` if an error occurs.","title":"dets.bchunk/2","ref":"dets.html#bchunk/2"},{"type":"function","doc":"Closes a table. Only processes that have opened a table are allowed to close it.\n\nAll open tables must be closed before the system is stopped. If an attempt is\nmade to open a table that is not properly closed, Dets automatically tries to\nrepair it.","title":"dets.close/1","ref":"dets.html#close/1"},{"type":"function","doc":"Deletes all objects with key `Key` from table `Name`.","title":"dets.delete/2","ref":"dets.html#delete/2"},{"type":"function","doc":"Deletes all objects from a table in almost constant time. However, if the table\nif fixed, [`delete_all_objects(T)`](`delete_all_objects/1`) is equivalent to\n[`match_delete(T, '_')`](`match_delete/2`).","title":"dets.delete_all_objects/1","ref":"dets.html#delete_all_objects/1"},{"type":"function","doc":"Deletes all instances of a specified object from a table. If a table is of type\n`bag` or `duplicate_bag`, this function can be used to delete only some of the\nobjects with a specified key.","title":"dets.delete_object/2","ref":"dets.html#delete_object/2"},{"type":"function","doc":"Returns the first key stored in table `Name` according to the internal order of\nthe table, or `'$end_of_table'` if the table is empty.\n\nUnless the table is protected using [`safe_fixtable/2`](`safe_fixtable/2`),\nsubsequent calls to `next/2` do possibly not work as expected if concurrent\nupdates are made to the table.\n\nIf an error occurs, the process is exited with an error tuple `{error, Reason}`.\nThe error tuple is not returned, as it cannot be distinguished from a key.\n\nThere are two reasons why [`first/1`](`first/1`) and [`next/2`](`next/2`) are\nnot to be used: they are not efficient, and they prevent the use of key\n`'$end_of_table'`, as this atom is used to indicate the end of the table. If\npossible, use functions [`match`](`match/1`),\n[`match_object`](`match_object/1`), and [`select`](`select/1`) for traversing\ntables.","title":"dets.first/1","ref":"dets.html#first/1"},{"type":"function","doc":"","title":"dets.foldl/3","ref":"dets.html#foldl/3"},{"type":"function","doc":"Calls `Function` on successive elements of table `Name` together with an extra\nargument `AccIn`. The table elements are traversed in unspecified order.\n`Function` must return a new accumulator that is passed to the next call. `Acc0`\nis returned if the table is empty.","title":"dets.foldr/3","ref":"dets.html#foldr/3"},{"type":"function","doc":"Deletes all objects of table `Name` and then inserts all the objects of the ETS\ntable `EtsTab`. The objects are inserted in unspecified order. As\n`ets:safe_fixtable/2` is called, the ETS table must be public or owned by the\ncalling process.","title":"dets.from_ets/2","ref":"dets.html#from_ets/2"},{"type":"function","doc":"Returns information about table `Name` as a list of tuples:\n\n- `{file_size, integer() >= 0}}` \\- The file size, in bytes.\n- `{filename,` `t:file:name/0` `}` \\- The name of the file where objects are\n stored.\n- `{keypos,` `t:keypos/0` `}` \\- The key position.\n- `{size, integer() >= 0}` \\- The number of objects stored in the table.\n- `{type,` `t:type/0` `}` \\- The table type.","title":"dets.info/1","ref":"dets.html#info/1"},{"type":"function","doc":"Returns the information associated with `Item` for table `Name`. In addition to\nthe `{Item, Value}` pairs defined for `info/1`, the following items are allowed:\n\n- `{access,` `t:access/0` `}` \\- The access mode.\n- `{auto_save,` `t:auto_save/0` `}` \\- The autosave interval.\n- `{bchunk_format, binary()}` \\- An opaque binary describing the format of the\n objects returned by [`bchunk/2`](`bchunk/2`). The binary can be used as\n argument to\n [`is_compatible_bchunk_format/2`](`is_compatible_bchunk_format/2`).\n- `{hash, Hash}` \\- Describes which BIF is used to calculate the hash values of\n the objects stored in the Dets table. Possible values of `Hash`:\n\n - `phash` \\- Implies that the `erlang:phash/2` BIF is used.\n - `phash2` \\- Implies that the `erlang:phash2/1` BIF is used.\n\n- `{memory, integer() >= 0}` \\- The file size, in bytes. The same value is\n associated with item `file_size`.\n- `{no_keys, integer >= 0()}` \\- The number of different keys stored in the\n table.\n- `{no_objects, integer >= 0()}` \\- The number of objects stored in the table.\n- `{no_slots, {Min, Used, Max}}` \\- The number of slots of the table. `Min` is\n the minimum number of slots, `Used` is the number of currently used slots, and\n `Max` is the maximum number of slots.\n- `{owner, pid()}` \\- The pid of the process that handles requests to the Dets\n table.\n- `{ram_file, boolean()}` \\- Whether the table is kept in RAM.\n- `{safe_fixed_monotonic_time, SafeFixed}` \\- If the table is fixed, `SafeFixed`\n is a tuple `{FixedAtTime, [{Pid,RefCount}]}`. `FixedAtTime` is the time when\n the table was first fixed, and `Pid` is the pid of the process that fixes the\n table `RefCount` times. There can be any number of processes in the list. If\n the table is not fixed, `SafeFixed` is the atom `false`.\n\n `FixedAtTime` corresponds to the result returned by `erlang:monotonic_time/0`\n at the time of fixation. The use of `safe_fixed_monotonic_time` is\n [time warp safe](`e:erts:time_correction.md#time-warp-safe-code`).\n\n- `{safe_fixed, SafeFixed}` \\- The same as\n `{safe_fixed_monotonic_time, SafeFixed}` except the format and value of\n `FixedAtTime`.\n\n `FixedAtTime` corresponds to the result returned by `erlang:timestamp/0` at\n the time of fixation. Notice that when the system uses single or multi\n [time warp modes](`e:erts:time_correction.md#time-warp-modes`), this can\n produce strange results. This is because the use of `safe_fixed` is not\n [time warp safe](`e:erts:time_correction.md#time-warp-safe-code`). Time warp\n safe code must use `safe_fixed_monotonic_time` instead.","title":"dets.info/2","ref":"dets.html#info/2"},{"type":"function","doc":"","title":"dets.init_table/2","ref":"dets.html#init_table/2"},{"type":"function","doc":"Replaces the existing objects of table `Name` with objects created by calling\nthe input function `InitFun`.\n\nThe reason for using this function rather than calling [`insert/2`](`insert/2`)\nis that of efficiency. Notice that the input functions are called by the process\nthat handles requests to the Dets table, not by the calling process.\n\nWhen called with argument `read`, function `InitFun` is assumed to return\n`end_of_input` when there is no more input, or `{Objects, Fun}`, where `Objects`\nis a list of objects and `Fun` is a new input function. Any other value `Value`\nis returned as an error `{error, {init_fun, Value}}`. Each input function is\ncalled exactly once, and if an error occurs, the last function is called with\nargument `close`, the reply of which is ignored.\n\nIf the table type is `set` and more than one object exists with a given key, one\nof the objects is chosen. This is not necessarily the last object with the given\nkey in the sequence of objects returned by the input functions. Avoid duplicate\nkeys, otherwise the file becomes unnecessarily fragmented. This holds also for\nduplicated objects stored in tables of type `bag`.\n\nIt is important that the table has a sufficient number of slots for the objects.\nIf not, the hash list starts to grow when [`init_table/2`](`init_table/2`)\nreturns, which significantly slows down access to the table for a period of\ntime. The minimum number of slots is set by the [`open_file/2`](`open_file/2`)\noption `min_no_slots` and returned by the [`info/2`](`info/2`) item `no_slots`.\nSee also option `min_no_slots` below.\n\nArgument `Options` is a list of `{Key, Val}` tuples, where the following values\nare allowed:\n\n- `{min_no_slots, no_slots()}` \\- Specifies the estimated number of different\n keys to be stored in the table. The [`open_file/2`](`open_file/2`) option with\n the same name is ignored, unless the table is created, in which case\n performance can be enhanced by supplying an estimate when initializing the\n table.\n- `{format, Format}` \\- Specifies the format of the objects returned by function\n `InitFun`. If `Format` is `term` (the default), `InitFun` is assumed to return\n a list of tuples. If `Format` is `bchunk`, `InitFun` is assumed to return\n `Data` as returned by `bchunk/2`. This option overrides option `min_no_slots`.","title":"dets.init_table/3","ref":"dets.html#init_table/3"},{"type":"function","doc":"Inserts one or more objects into the table `Name`. If there already exists an\nobject with a key matching the key of some of the given objects and the table\ntype is `set`, the old object will be replaced.","title":"dets.insert/2","ref":"dets.html#insert/2"},{"type":"function","doc":"Inserts one or more objects into table `Name`. If there already exists some\nobject with a key matching the key of any of the specified objects, the table is\nnot updated and `false` is returned. Otherwise the objects are inserted and\n`true` returned.","title":"dets.insert_new/2","ref":"dets.html#insert_new/2"},{"type":"function","doc":"Returns `true` if it would be possible to initialize table `Name`, using\n`init_table/3` with option `{format, bchunk}`, with objects read with `bchunk/2`\nfrom some table `T`, such that calling [`info(T, bchunk_format)`](`info/2`)\nreturns `BchunkFormat`.","title":"dets.is_compatible_bchunk_format/2","ref":"dets.html#is_compatible_bchunk_format/2"},{"type":"function","doc":"Returns `true` if file `Filename` is a Dets table, otherwise `false`.","title":"dets.is_dets_file/1","ref":"dets.html#is_dets_file/1"},{"type":"function","doc":"Returns a list of all objects with key `Key` stored in table `Name`, for\nexample:\n\n```erlang\n2> dets:open_file(abc, [{type, bag}]).\n{ok,abc}\n3> dets:insert(abc, {1,2,3}).\nok\n4> dets:insert(abc, {1,3,4}).\nok\n5> dets:lookup(abc, 1).\n[{1,2,3},{1,3,4}]\n```\n\nIf the table type is `set`, the function returns either the empty list or a list\nwith one object, as there cannot be more than one object with a given key. If\nthe table type is `bag` or `duplicate_bag`, the function returns a list of\narbitrary length.\n\nNotice that the order of objects returned is unspecified. In particular, the\norder in which objects were inserted is not reflected.","title":"dets.lookup/2","ref":"dets.html#lookup/2"},{"type":"function","doc":"Matches some objects stored in a table and returns a non-empty list of the\nbindings matching a specified pattern in some unspecified order. The table, the\npattern, and the number of objects that are matched are all defined by\n`Continuation`, which has been returned by a previous call to\n[`match/1`](`match/1`) or [`match/3`](`match/3`).\n\nWhen all table objects are matched, `'$end_of_table'` is returned.","title":"dets.match/1","ref":"dets.html#match/1"},{"type":"function","doc":"Returns for each object of table `Name` that matches `Pattern` a list of\nbindings in some unspecified order. For a description of patterns, see\n`ets:match/2`. If the keypos'th element of `Pattern` is unbound, all table\nobjects are matched. If the keypos'th element is bound, only the objects with\nthe correct key are matched.","title":"dets.match/2","ref":"dets.html#match/2"},{"type":"function","doc":"Matches some or all objects of table `Name` and returns a non-empty list of the\nbindings that match `Pattern` in some unspecified order. For a description of\npatterns, see `ets:match/2`.\n\nA tuple of the bindings and a continuation is returned, unless the table is\nempty, in which case `'$end_of_table'` is returned. The continuation is to be\nused when matching further objects by calling `match/1`.\n\nIf the keypos'th element of `Pattern` is bound, all table objects are matched.\nIf the keypos'th element is unbound, all table objects are matched, `N` objects\nat a time, until at least one object matches or the end of the table is reached.\nThe default, indicated by giving `N` the value `default`, is to let the number\nof objects vary depending on the sizes of the objects. All objects with the same\nkey are always matched at the same time, which implies that more than N objects\ncan sometimes be matched.\n\nThe table is always to be protected using `safe_fixtable/2` before calling\n[`match/3`](`match/3`), otherwise errors can occur when calling\n[`match/1`](`match/1`).","title":"dets.match/3","ref":"dets.html#match/3"},{"type":"function","doc":"Deletes all objects that match `Pattern` from table `Name`. For a description of\npatterns, see `ets:match/2`.\n\nIf the keypos'th element of `Pattern` is bound, only the objects with the\ncorrect key are matched.","title":"dets.match_delete/2","ref":"dets.html#match_delete/2"},{"type":"function","doc":"Returns a non-empty list of some objects stored in a table that match a given\npattern in some unspecified order. The table, the pattern, and the number of\nobjects that are matched are all defined by `Continuation`, which has been\nreturned by a previous call to [`match_object/1`](`match_object/1`) or\n[`match_object/3`](`match_object/3`).\n\nWhen all table objects are matched, `'$end_of_table'` is returned.","title":"dets.match_object/1","ref":"dets.html#match_object/1"},{"type":"function","doc":"Returns a list of all objects of table `Name` that match `Pattern` in some\nunspecified order. For a description of patterns, see `ets:match/2`.\n\nIf the keypos'th element of `Pattern` is unbound, all table objects are matched.\nIf the keypos'th element of `Pattern` is bound, only the objects with the\ncorrect key are matched.\n\nUsing the `match_object` functions for traversing all table objects is more\nefficient than calling [`first/1`](`first/1`) and [`next/2`](`next/2`) or\n[`slot/2`](`slot/2`).","title":"dets.match_object/2","ref":"dets.html#match_object/2"},{"type":"function","doc":"Matches some or all objects stored in table `Name` and returns a non-empty list\nof the objects that match `Pattern` in some unspecified order. For a description\nof patterns, see `ets:match/2`.\n\nA list of objects and a continuation is returned, unless the table is empty, in\nwhich case `'$end_of_table'` is returned. The continuation is to be used when\nmatching further objects by calling `match_object/1`.\n\nIf the keypos'th element of `Pattern` is bound, all table objects are matched.\nIf the keypos'th element is unbound, all table objects are matched, `N` objects\nat a time, until at least one object matches or the end of the table is reached.\nThe default, indicated by giving `N` the value `default`, is to let the number\nof objects vary depending on the sizes of the objects. All matching objects with\nthe same key are always returned in the same reply, which implies that more than\nN objects can sometimes be returned.\n\nThe table is always to be protected using `safe_fixtable/2` before calling\n[`match_object/3`](`match_object/3`), otherwise errors can occur when calling\n[`match_object/1`](`match_object/1`).","title":"dets.match_object/3","ref":"dets.html#match_object/3"},{"type":"function","doc":"Works like `lookup/2`, but does not return the objects. Returns `true` if one or\nmore table elements has key `Key`, otherwise `false`.","title":"dets.member/2","ref":"dets.html#member/2"},{"type":"function","doc":"Returns either the key following `Key1` in table `Name` according to the\ninternal order of the table, or `'$end_of_table'` if there is no next key.\n\nIf an error occurs, the process is exited with an error tuple `{error, Reason}`.\n\nTo find the first key in the table, use `first/1`.","title":"dets.next/2","ref":"dets.html#next/2"},{"type":"function","doc":"Opens an existing table. If the table is not properly closed, it is repaired.\nThe returned reference is to be used as the table name. This function is most\nuseful for debugging purposes.","title":"dets.open_file/1","ref":"dets.html#open_file/1"},{"type":"function","doc":"Opens a table. An empty Dets table is created if no file exists.\n\nThe atom `Name` is the table name. The table name must be provided in all\nsubsequent operations on the table. The name can be used by other processes as\nwell, and many processes can share one table.\n\nIf two processes open the same table by giving the same name and arguments, the\ntable has two users. If one user closes the table, it remains open until the\nsecond user closes it.\n\nArgument `Args` is a list of `{Key, Val}` tuples, where the following values are\nallowed:\n\n- `{access,` `t:access/0` `}` \\- Existing tables can be opened in read-only mode.\n A table that is opened in read-only mode is not subjected to the automatic\n file reparation algorithm if it is later opened after a crash. Defaults to\n `read_write`.\n- `{auto_save,` `t:auto_save/0` `}` \\- The autosave interval. If the interval is\n an integer `Time`, the table is flushed to disk whenever it is not accessed\n for `Time` milliseconds. A table that has been flushed requires no reparation\n when reopened after an uncontrolled emulator halt. If the interval is the atom\n `infinity`, autosave is disabled. Defaults to 180000 (3 minutes).\n- `{estimated_no_objects,` `t:no_slots/0` `}` \\- Equivalent to option\n `min_no_slots`.\n- `{file,` `t:file:name/0` `}` \\- The name of the file to be opened. Defaults to\n the table name.\n- `{max_no_slots,` `t:no_slots/0` `}` \\- The maximum number of slots to be used.\n Defaults to 32 M, which is the maximal value. Notice that a higher value can\n increase the table fragmentation, and a smaller value can decrease the\n fragmentation, at the expense of execution time.\n- `{min_no_slots,` `t:no_slots/0` `}` \\- Application performance can be enhanced\n with this flag by specifying, when the table is created, the estimated number\n of different keys to be stored in the table. Defaults to 256, which is the\n minimum value.\n- `{keypos,` `t:keypos/0` `}` \\- The position of the element of each object to be\n used as key. Defaults to 1. The ability to explicitly state the key position\n is most convenient when we want to store Erlang records in which the first\n position of the record is the name of the record type.\n- `{ram_file, boolean()}` \\- Whether the table is to be kept in RAM. Keeping the\n table in RAM can sound like an anomaly, but can enhance the performance of\n applications that open a table, insert a set of objects, and then close the\n table. When the table is closed, its contents are written to the disk file.\n Defaults to `false`.\n- `{repair, Value}` \\- `Value` can be either a `t:boolean/0` or the atom\n `force`. The flag specifies if the Dets server is to invoke the automatic file\n reparation algorithm. Defaults to `true`. If `false` is specified, no attempt\n is made to repair the file, and `{error, {needs_repair, FileName}}` is\n returned if the table must be repaired.\n\n Value `force` means that a reparation is made even if the table is properly\n closed. This is a seldom needed option.\n\n Option `repair` is ignored if the table is already open.\n\n- `{type,` `t:type/0` `}` \\- The table type. Defaults to `set`.","title":"dets.open_file/2","ref":"dets.html#open_file/2"},{"type":"function","doc":"Returns the table name given the pid of a process that handles requests to a\ntable, or `undefined` if there is no such table.\n\nThis function is meant to be used for debugging only.","title":"dets.pid2name/1","ref":"dets.html#pid2name/1"},{"type":"function","doc":"This function can be used to restore an opaque continuation returned by\n`select/3` or `select/1` if the continuation has passed through external term\nformat (been sent between nodes or stored on disk).\n\nThe reason for this function is that continuation terms contain compiled match\nspecifications and therefore are invalidated if converted to external term\nformat. Given that the original match specification is kept intact, the\ncontinuation can be restored, meaning it can once again be used in subsequent\n[`select/1`](`select/1`) calls even though it has been stored on disk or on\nanother node.\n\nFor more information and examples, see the `m:ets` module.\n\n> #### Note {: .info }\n>\n> This function is rarely needed in application code. It is used by application\n> Mnesia to provide distributed [`select/3`](`select/3`) and\n> [`select/1`](`select/1`) sequences. A normal application would either use\n> Mnesia or keep the continuation from being converted to external format.\n>\n> The reason for not having an external representation of compiled match\n> specifications is performance. It can be subject to change in future releases,\n> while this interface remains for backward compatibility.","title":"dets.repair_continuation/2","ref":"dets.html#repair_continuation/2"},{"type":"function","doc":"If `Fix` is `true`, table `Name` is fixed (once more) by the calling process,\notherwise the table is released. The table is also released when a fixing\nprocess terminates.\n\nIf many processes fix a table, the table remains fixed until all processes have\nreleased it or terminated. A reference counter is kept on a per process basis,\nand N consecutive fixes require N releases to release the table.\n\nIt is not guaranteed that calls to [`first/1`](`first/1`), [`next/2`](`next/2`),\nor select and match functions work as expected even if the table is fixed; the\nlimited support for concurrency provided by the `m:ets` module is not yet\nprovided by Dets. Fixing a table currently only disables resizing of the hash\nlist of the table.\n\nIf objects have been added while the table was fixed, the hash list starts to\ngrow when the table is released, which significantly slows down access to the\ntable for a period of time.","title":"dets.safe_fixtable/2","ref":"dets.html#safe_fixtable/2"},{"type":"function","doc":"Applies a match specification to some objects stored in a table and returns a\nnon-empty list of the results. The table, the match specification, and the\nnumber of objects that are matched are all defined by `Continuation`, which is\nreturned by a previous call to `select/1` or `select/3`.\n\nWhen all objects of the table have been matched, `'$end_of_table'` is returned.","title":"dets.select/1","ref":"dets.html#select/1"},{"type":"function","doc":"Returns the results of applying match specification `MatchSpec` to all or some\nobjects stored in table `Name`. The order of the objects is not specified. For a\ndescription of match specifications, see the\n[ERTS User's Guide](`e:erts:match_spec.md`).\n\nIf the keypos'th element of `MatchSpec` is unbound, the match specification is\napplied to all objects of the table. If the keypos'th element is bound, the\nmatch specification is applied to the objects with the correct key(s) only.\n\nUsing the `select` functions for traversing all objects of a table is more\nefficient than calling [`first/1`](`first/1`) and [`next/2`](`next/2`) or\n[`slot/2`](`slot/2`).","title":"dets.select/2","ref":"dets.html#select/2"},{"type":"function","doc":"Returns the results of applying match specification `MatchSpec` to some or all\nobjects stored in table `Name`. The order of the objects is not specified. For a\ndescription of match specifications, see the\n[ERTS User's Guide](`e:erts:match_spec.md`).\n\nA tuple of the results of applying the match specification and a continuation is\nreturned, unless the table is empty, in which case `'$end_of_table'` is\nreturned. The continuation is to be used when matching more objects by calling\n`select/1`.\n\nIf the keypos'th element of `MatchSpec` is bound, the match specification is\napplied to all objects of the table with the correct key(s). If the keypos'th\nelement of `MatchSpec` is unbound, the match specification is applied to all\nobjects of the table, `N` objects at a time, until at least one object matches\nor the end of the table is reached. The default, indicated by giving `N` the\nvalue `default`, is to let the number of objects vary depending on the sizes of\nthe objects. All objects with the same key are always handled at the same time,\nwhich implies that the match specification can be applied to more than N\nobjects.\n\nThe table is always to be protected using `safe_fixtable/2` before calling\n[`select/3`](`select/3`), otherwise errors can occur when calling\n[`select/1`](`select/1`).","title":"dets.select/3","ref":"dets.html#select/3"},{"type":"function","doc":"Deletes each object from table `Name` such that applying match specification\n`MatchSpec` to the object returns value `true`. For a description of match\nspecifications, see the [ERTS User's Guide](`e:erts:match_spec.md`). Returns the\nnumber of deleted objects.\n\nIf the keypos'th element of `MatchSpec` is bound, the match specification is\napplied to the objects with the correct key(s) only.","title":"dets.select_delete/2","ref":"dets.html#select_delete/2"},{"type":"function","doc":"The objects of a table are distributed among slots, starting with slot `0` and\nending with slot `n`. Returns the list of objects associated with slot `I`. If\n`I` > `n`, `'$end_of_table'` is returned.","title":"dets.slot/2","ref":"dets.html#slot/2"},{"type":"function","doc":"Ensures that all updates made to table `Name` are written to disk. This also\napplies to tables that have been opened with flag `ram_file` set to `true`. In\nthis case, the contents of the RAM file are flushed to disk.\n\nNotice that the space management data structures kept in RAM, the buddy system,\nis also written to the disk. This can take some time if the table is fragmented.","title":"dets.sync/1","ref":"dets.html#sync/1"},{"type":"function","doc":"","title":"dets.table/1","ref":"dets.html#table/1"},{"type":"function","doc":"Returns a Query List Comprehension (QLC) query handle. The `m:qlc` module\nprovides a query language aimed mainly for Mnesia, but ETS tables, Dets tables,\nand lists are also recognized by `qlc` as sources of data. Calling\n[`dets:table/1,2`](`table/1`) is the means to make Dets table `Name` usable to\n`qlc`.\n\nWhen there are only simple restrictions on the key position, `qlc` uses\n[`dets:lookup/2`](`lookup/2`) to look up the keys. When that is not possible,\nthe whole table is traversed. Option `traverse` determines how this is done:\n\n- `first_next` \\- The table is traversed one key at a time by calling\n `dets:first/1` and `dets:next/2`.\n- `select` \\- The table is traversed by calling [`dets:select/3`](`select/3`)\n and [`dets:select/1`](`select/1`). Option `n_objects` determines the number of\n objects returned (the third argument of [`select/3`](`select/3`)). The match\n specification (the second argument of [`select/3`](`select/3`)) is assembled\n by `qlc`:\n\n - Simple filters are translated into equivalent match specifications.\n - More complicated filters must be applied to all objects returned by\n [`select/3`](`select/3`) given a match specification that matches all\n objects.\n\n- `{select,` `t:match_spec/0` `}` \\- As for `select`, the table is traversed by\n calling `dets:select/3` and `dets:select/1`. The difference is that the match\n specification is specified explicitly. This is how to state match\n specifications that cannot easily be expressed within the syntax provided by\n `qlc`.\n\nThe following example uses an explicit match specification to traverse the\ntable:\n\n```erlang\n1> dets:open_file(t, []),\nok = dets:insert(t, [{1,a},{2,b},{3,c},{4,d}]),\nMS = ets:fun2ms(fun({X,Y}) when (X > 1) or (X < 5) -> {Y} end),\nQH1 = dets:table(t, [{traverse, {select, MS}}]).\n```\n\nAn example with implicit match specification:\n\n```erlang\n2> QH2 = qlc:q([{Y} || {X,Y} <- dets:table(t), (X > 1) or (X < 5)]).\n```\n\nThe latter example is equivalent to the former, which can be verified using\nfunction `qlc:info/1`:\n\n```erlang\n3> qlc:info(QH1) =:= qlc:info(QH2).\ntrue\n```\n\n`qlc:info/1` returns information about a query handle. In this case identical\ninformation is returned for the two query handles.","title":"dets.table/2","ref":"dets.html#table/2"},{"type":"function","doc":"Inserts the objects of the Dets table `Name` into the ETS table `EtsTab`. The\norder in which the objects are inserted is not specified. The existing objects\nof the ETS table are kept unless overwritten.","title":"dets.to_ets/2","ref":"dets.html#to_ets/2"},{"type":"function","doc":"Applies `Fun` to each object stored in table `Name` in some unspecified order.\nDifferent actions are taken depending on the return value of `Fun`. The\nfollowing `Fun` return values are allowed:\n\n- **`continue`** - Continue to perform the traversal. For example, the following\n function can be used to print the contents of a table:\n\n ```erlang\n fun(X) -> io:format(\"~p~n\", [X]), continue end.\n ```\n\n- **`{continue, Val}`** - Continue the traversal and accumulate `Val`. The\n following function is supplied to collect all objects of a table in a list:\n\n ```text\n fun(X) -> {continue, X} end.\n ```\n\n- **`{done, Value}`** - Terminate the traversal and return `[Value | Acc]`.\n\nAny other value `OtherValue` returned by `Fun` terminates the traversal and is\nreturned immediately.","title":"dets.traverse/2","ref":"dets.html#traverse/2"},{"type":"function","doc":"Updates the object with key `Key` stored in table `Name` of type `set` by adding\n`Incr` to the element at the `Pos`:th position. The new counter value is\nreturned. If no position is specified, the element directly following the key is\nupdated.\n\nThis functions provides a way of updating a counter, without having to look up\nan object, update the object by incrementing an element, and insert the\nresulting object into the table again.","title":"dets.update_counter/3","ref":"dets.html#update_counter/3"},{"type":"type","doc":"","title":"dets.access/0","ref":"dets.html#t:access/0"},{"type":"type","doc":"","title":"dets.auto_save/0","ref":"dets.html#t:auto_save/0"},{"type":"opaque","doc":"Opaque continuation used by `match/1` and `match/3`.","title":"dets.bindings_cont/0","ref":"dets.html#t:bindings_cont/0"},{"type":"opaque","doc":"Opaque continuation used by `bchunk/2`.","title":"dets.cont/0","ref":"dets.html#t:cont/0"},{"type":"type","doc":"","title":"dets.keypos/0","ref":"dets.html#t:keypos/0"},{"type":"type","doc":"Match specifications, see section\n[Match Specification in Erlang](`e:erts:match_spec.md`) in ERTS User's Guide and\nthe `m:ms_transform` module.","title":"dets.match_spec/0","ref":"dets.html#t:match_spec/0"},{"type":"type","doc":"","title":"dets.no_slots/0","ref":"dets.html#t:no_slots/0"},{"type":"type","doc":"","title":"dets.object/0","ref":"dets.html#t:object/0"},{"type":"opaque","doc":"Opaque continuation used by `match_object/1` and `match_object/3`.","title":"dets.object_cont/0","ref":"dets.html#t:object_cont/0"},{"type":"type","doc":"For a description of patterns, see `ets:match/2`.","title":"dets.pattern/0","ref":"dets.html#t:pattern/0"},{"type":"opaque","doc":"Opaque continuation used by `select/1` and `select/3`.","title":"dets.select_cont/0","ref":"dets.html#t:select_cont/0"},{"type":"type","doc":"","title":"dets.tab_name/0","ref":"dets.html#t:tab_name/0"},{"type":"type","doc":"","title":"dets.type/0","ref":"dets.html#t:type/0"},{"type":"module","doc":"A Key-value dictionary.\n\nThe representation of a dictionary is not defined.\n\nThis module provides the same interface as the `m:orddict` module. One\ndifference is that while this module considers two keys as different if they do\nnot match (`=:=`), `orddict` considers two keys as different if and only if they\ndo not compare equal (`==`).","title":"dict","ref":"dict.html"},{"type":"module","doc":"[](){: #notes }\n\nFunctions `append` and `append_list` are included so that keyed values can be\nstored in a list _accumulator_, for example:\n\n```erlang\n> D0 = dict:new(),\n D1 = dict:store(files, [], D0),\n D2 = dict:append(files, f1, D1),\n D3 = dict:append(files, f2, D2),\n D4 = dict:append(files, f3, D3),\n dict:fetch(files, D4).\n[f1,f2,f3]\n```\n\nThis saves the trouble of first fetching a keyed value, appending a new value to\nthe list of stored values, and storing the result.\n\nFunction `fetch` is to be used if the key is known to be in the dictionary,\notherwise function `find`.","title":"Notes - dict","ref":"dict.html#module-notes"},{"type":"module","doc":"`m:gb_trees`, `m:orddict`","title":"See Also - dict","ref":"dict.html#module-see-also"},{"type":"function","doc":"Appends a new `Value` to the current list of values associated with `Key`.\n\nSee also section [Notes](`m:dict#module-notes`).","title":"dict.append/3","ref":"dict.html#append/3"},{"type":"function","doc":"Appends a list of values `ValList` to the current list of values associated with\n`Key`. An exception is generated if the initial value associated with `Key` is\nnot a list of values.\n\nSee also section [Notes](`m:dict#module-notes`).","title":"dict.append_list/3","ref":"dict.html#append_list/3"},{"type":"function","doc":"Erases all items with a given key from a dictionary.","title":"dict.erase/2","ref":"dict.html#erase/2"},{"type":"function","doc":"Returns the value associated with `Key` in dictionary `Dict`. This function\nassumes that `Key` is present in dictionary `Dict`, and an exception is\ngenerated if `Key` is not in the dictionary.\n\nSee also section [Notes](`m:dict#module-notes`).","title":"dict.fetch/2","ref":"dict.html#fetch/2"},{"type":"function","doc":"Returns a list of all keys in dictionary `Dict`.","title":"dict.fetch_keys/1","ref":"dict.html#fetch_keys/1"},{"type":"function","doc":"`Dict2` is a dictionary of all keys and values in `Dict1` for which\n`Pred(Key, Value)` is `true`.","title":"dict.filter/2","ref":"dict.html#filter/2"},{"type":"function","doc":"Searches for a key in dictionary `Dict`. Returns `{ok, Value}`, where `Value` is\nthe value associated with `Key`, or `error` if the key is not present in the\ndictionary.\n\nSee also section [Notes](`m:dict#module-notes`).","title":"dict.find/2","ref":"dict.html#find/2"},{"type":"function","doc":"Calls `Fun` on successive keys and values of dictionary `Dict` together with an\nextra argument `Acc` (short for accumulator). `Fun` must return a new\naccumulator that is passed to the next call. `Acc0` is returned if the\ndictionary is empty. The evaluation order is undefined.","title":"dict.fold/3","ref":"dict.html#fold/3"},{"type":"function","doc":"Converts the `Key`-`Value` list `List` to dictionary `Dict`.","title":"dict.from_list/1","ref":"dict.html#from_list/1"},{"type":"function","doc":"Returns `true` if dictionary `Dict` has no elements, otherwise `false`.","title":"dict.is_empty/1","ref":"dict.html#is_empty/1"},{"type":"function","doc":"Tests if `Key` is contained in dictionary `Dict`.","title":"dict.is_key/2","ref":"dict.html#is_key/2"},{"type":"function","doc":"Calls `Fun` on successive keys and values of dictionary `Dict1` to return a new\nvalue for each key. The evaluation order is undefined.","title":"dict.map/2","ref":"dict.html#map/2"},{"type":"function","doc":"Merges two dictionaries, `Dict1` and `Dict2`, to create a new dictionary. All\nthe `Key`-`Value` pairs from both dictionaries are included in the new\ndictionary. If a key occurs in both dictionaries, `Fun` is called with the key\nand both values to return a new value. `merge` can be defined as follows, but is\nfaster:\n\n```erlang\nmerge(Fun, D1, D2) ->\n fold(fun (K, V1, D) ->\n update(K, fun (V2) -> Fun(K, V1, V2) end, V1, D)\n end, D2, D1).\n```","title":"dict.merge/3","ref":"dict.html#merge/3"},{"type":"function","doc":"Creates a new dictionary.","title":"dict.new/0","ref":"dict.html#new/0"},{"type":"function","doc":"Returns the number of elements in dictionary `Dict`.","title":"dict.size/1","ref":"dict.html#size/1"},{"type":"function","doc":"Stores a `Key`-`Value` pair in dictionary `Dict2`. If `Key` already exists in\n`Dict1`, the associated value is replaced by `Value`.","title":"dict.store/3","ref":"dict.html#store/3"},{"type":"function","doc":"This function returns value from dictionary and a new dictionary without this\nvalue. Returns `error` if the key is not present in the dictionary.","title":"dict.take/2","ref":"dict.html#take/2"},{"type":"function","doc":"Converts dictionary `Dict` to a list representation.","title":"dict.to_list/1","ref":"dict.html#to_list/1"},{"type":"function","doc":"Updates a value in a dictionary by calling `Fun` on the value to get a new\nvalue. An exception is generated if `Key` is not present in the dictionary.","title":"dict.update/3","ref":"dict.html#update/3"},{"type":"function","doc":"Updates a value in a dictionary by calling `Fun` on the value to get a new\nvalue. If `Key` is not present in the dictionary, `Initial` is stored as the\nfirst value. For example, [`append/3`](`append/3`) can be defined as:\n\n```erlang\nappend(Key, Val, D) ->\n update(Key, fun (Old) -> Old ++ [Val] end, [Val], D).\n```","title":"dict.update/4","ref":"dict.html#update/4"},{"type":"function","doc":"Adds `Increment` to the value associated with `Key` and stores this value. If\n`Key` is not present in the dictionary, `Increment` is stored as the first\nvalue.\n\nThis can be defined as follows, but is faster:\n\n```erlang\nupdate_counter(Key, Incr, D) ->\n update(Key, fun (Old) -> Old + Incr end, Incr, D).\n```","title":"dict.update_counter/3","ref":"dict.html#update_counter/3"},{"type":"type","doc":"","title":"dict.dict/0","ref":"dict.html#t:dict/0"},{"type":"opaque","doc":"Dictionary as returned by `new/0`.","title":"dict.dict/2","ref":"dict.html#t:dict/2"},{"type":"module","doc":"This module provides a version of labeled directed graphs (\"digraphs\").\n\nThe digraphs managed by this module are stored in [ETS tables](`m:ets`). That\nimplies the following:\n\n- Only the process that created the digraph is allowed to update it.\n- Digraphs will not be garbage collected. The ETS tables used for a digraph will\n only be deleted when `delete/1` is called or the process that created the\n digraph terminates.\n- A digraph is a mutable data structure.\n\nWhat makes the graphs provided here non-proper directed graphs is that multiple\nedges between vertices are allowed. However, the customary definition of\ndirected graphs is used here.\n\n- A _directed graph_{: #digraph } (or just \"digraph\") is a pair (V, E) of a\n finite set V of _vertices_{: #vertex } and a finite set E of _directed\n edges_{: #edge } (or just \"edges\"). The set of edges E is a subset of V × V\n (the Cartesian product of V with itself).\n\n In this module, V is allowed to be empty. The so obtained unique digraph is\n called the _empty digraph_{: #empty_digraph }. Both vertices and edges are\n represented by unique Erlang terms.\n\n- Digraphs can be annotated with more information. Such information can be\n attached to the vertices and to the edges of the digraph. An annotated digraph\n is called a _labeled digraph_, and the information attached to a vertex or an\n edge is called a _label_{: #label }. Labels are Erlang terms.\n- An edge e = (v, w) is said to _emanate_{: #emanate } from vertex v and to be\n _incident_{: #incident } on vertex w.\n- The _out-degree_{: #out_degree } of a vertex is the number of edges emanating\n from that vertex.\n- The _in-degree_{: #in_degree } of a vertex is the number of edges incident on\n that vertex.\n- If an edge is emanating from v and incident on w, then w is said to be an\n _out-neighbor_{: #out_neighbour } of v, and v is said to be an _in-neighbor_{:\n #in_neighbour } of w.\n- A _path_{: #path } P from v\\[1] to v\\[k] in a digraph (V, E) is a non-empty\n sequence v\\[1], v\\[2], ..., v\\[k] of vertices in V such that there is an edge\n (v\\[i],v\\[i+1]) in E for 1 <= i < k.\n- The _length_{: #length } of path P is k-1.\n- Path P is _simple_{: #simple_path } if all vertices are distinct, except that\n the first and the last vertices can be the same.\n- Path P is a _cycle_{: #cycle } if the length of P is not zero and v\\[1] =\n v\\[k].\n- A _loop_{: #loop } is a cycle of length one.\n- A _simple cycle_{: #simple_cycle } is a path that is both a cycle and simple.\n- An _acyclic digraph_{: #acyclic_digraph } is a digraph without cycles.","title":"digraph","ref":"digraph.html"},{"type":"module","doc":"`m:digraph_utils`, `m:ets`","title":"See Also - digraph","ref":"digraph.html#module-see-also"},{"type":"function","doc":"","title":"digraph.add_edge/3","ref":"digraph.html#add_edge/3"},{"type":"function","doc":"Equivalent to [`add_edge(G, E, V1, V2, Label)`](`add_edge/5`), where `E` is a created edge.\n\nThe created edge is represented by term `['$e' | N]`, where `N` is an integer >= 0.\n\nSee `t:add_edge_err_rsn/0` for details on possible errors.","title":"digraph.add_edge/4","ref":"digraph.html#add_edge/4"},{"type":"function","doc":"Creates (or modifies) an edge with the identifier\n`E` of digraph `G`, using `Label` as the (new) [label](`m:digraph#label`) of the\nedge. The edge is [emanating](`m:digraph#emanate`) from `V1` and\n[incident](`m:digraph#incident`) on `V2`. Returns `E`.\n\nSee `t:add_edge_err_rsn/0` for details on possible errors.","title":"digraph.add_edge/5","ref":"digraph.html#add_edge/5"},{"type":"function","doc":"Creates a vertex using the empty list as label, and returns the created vertex.\n\nThe created vertex is represented by term `['$v' | N]`, where `N` is an integer >= 0.","title":"digraph.add_vertex/1","ref":"digraph.html#add_vertex/1"},{"type":"function","doc":"","title":"digraph.add_vertex/2","ref":"digraph.html#add_vertex/2"},{"type":"function","doc":"Creates (or modifies) vertex `V` of digraph `G`, using `Label` as the (new)\n[label](`m:digraph#label`) of the vertex. Returns the new vertex `V`.","title":"digraph.add_vertex/3","ref":"digraph.html#add_vertex/3"},{"type":"function","doc":"Deletes edge `E` from digraph `G`.","title":"digraph.del_edge/2","ref":"digraph.html#del_edge/2"},{"type":"function","doc":"Deletes the edges in list `Edges` from digraph `G`.","title":"digraph.del_edges/2","ref":"digraph.html#del_edges/2"},{"type":"function","doc":"Deletes edges from digraph `G` until there are no [paths](`m:digraph#path`) from\nvertex `V1` to vertex `V2`.\n\nA sketch of the procedure employed:\n\n- Find an arbitrary [simple path](`m:digraph#simple_path`)\n v\\[1], v\\[2], ..., v\\[k] from `V1` to `V2` in `G`.\n- Remove all edges of `G` [emanating](`m:digraph#emanate`) from v\\[i] and\n [incident](`m:digraph#incident`) to v\\[i+1] for 1 <= i < k (including multiple\n edges).\n- Repeat until there is no path between `V1` and `V2`.","title":"digraph.del_path/3","ref":"digraph.html#del_path/3"},{"type":"function","doc":"Deletes vertex `V` from digraph `G`. Any edges [emanating](`m:digraph#emanate`)\nfrom `V` or [incident](`m:digraph#incident`) on `V` are also deleted.","title":"digraph.del_vertex/2","ref":"digraph.html#del_vertex/2"},{"type":"function","doc":"Deletes the vertices in list `Vertices` from digraph `G`.","title":"digraph.del_vertices/2","ref":"digraph.html#del_vertices/2"},{"type":"function","doc":"Deletes digraph `G`. This call is important as digraphs are implemented with\nETS. There is no garbage collection of ETS tables. However, the digraph is\ndeleted if the process that created the digraph terminates.","title":"digraph.delete/1","ref":"digraph.html#delete/1"},{"type":"function","doc":"Returns `{E, V1, V2, Label}`, where `Label` is the [label](`m:digraph#label`) of\nedge `E` [emanating](`m:digraph#emanate`) from `V1` and\n[incident](`m:digraph#incident`) on `V2` of digraph `G`. If no edge `E` of\ndigraph `G` exists, `false` is returned.","title":"digraph.edge/2","ref":"digraph.html#edge/2"},{"type":"function","doc":"Returns a list of all edges of digraph `G`, in some unspecified order.","title":"digraph.edges/1","ref":"digraph.html#edges/1"},{"type":"function","doc":"Returns a list of all edges [emanating](`m:digraph#emanate`) from or\n[incident](`m:digraph#incident`) on `V` of digraph `G`, in some unspecified\norder.","title":"digraph.edges/2","ref":"digraph.html#edges/2"},{"type":"function","doc":"If a [simple cycle](`m:digraph#simple_cycle`) of length two or more exists\nthrough vertex `V`, the cycle is returned as a list `[V, ..., V]` of vertices.\nIf a [loop](`m:digraph#loop`) through `V` exists, the loop is returned as a list\n`[V]`. If no cycles through `V` exist, `false` is returned.\n\n`get_path/3` is used for finding a simple cycle through `V`.","title":"digraph.get_cycle/2","ref":"digraph.html#get_cycle/2"},{"type":"function","doc":"Tries to find a [simple path](`m:digraph#simple_path`) from vertex `V1` to\nvertex `V2` of digraph `G`. Returns the path as a list `[V1, ..., V2]` of\nvertices, or `false` if no simple path from `V1` to `V2` of length one or more\nexists.\n\nDigraph `G` is traversed in a depth-first manner, and the first found path is\nreturned.","title":"digraph.get_path/3","ref":"digraph.html#get_path/3"},{"type":"function","doc":"Tries to find an as short as possible [simple cycle](`m:digraph#simple_cycle`)\nthrough vertex `V` of digraph `G`. Returns the cycle as a list `[V, ..., V]` of\nvertices, or `false` if no simple cycle through `V` exists. Notice that a\n[loop](`m:digraph#loop`) through `V` is returned as list `[V, V]`.\n\n`get_short_path/3` is used for finding a simple cycle through `V`.","title":"digraph.get_short_cycle/2","ref":"digraph.html#get_short_cycle/2"},{"type":"function","doc":"Tries to find an as short as possible [simple path](`m:digraph#simple_path`)\nfrom vertex `V1` to vertex `V2` of digraph `G`. Returns the path as a list\n`[V1, ..., V2]` of vertices, or `false` if no simple path from `V1` to `V2` of\nlength one or more exists.\n\nDigraph `G` is traversed in a breadth-first manner, and the first found path is\nreturned.","title":"digraph.get_short_path/3","ref":"digraph.html#get_short_path/3"},{"type":"function","doc":"Returns the [in-degree](`m:digraph#in_degree`) of vertex `V` of digraph `G`.","title":"digraph.in_degree/2","ref":"digraph.html#in_degree/2"},{"type":"function","doc":"Returns a list of all edges [incident](`m:digraph#incident`) on `V` of digraph\n`G`, in some unspecified order.","title":"digraph.in_edges/2","ref":"digraph.html#in_edges/2"},{"type":"function","doc":"Returns a list of all [in-neighbors](`m:digraph#in_neighbour`) of `V` of digraph\n`G`, in some unspecified order.","title":"digraph.in_neighbours/2","ref":"digraph.html#in_neighbours/2"},{"type":"function","doc":"Returns a list of `{Tag, Value}` pairs describing digraph `G`. The following\npairs are returned:\n\n- `{cyclicity, Cyclicity}`, where `Cyclicity` is `cyclic` or `acyclic`,\n according to the options given to `new`.\n- `{memory, NoWords}`, where `NoWords` is the number of words allocated to the\n ETS tables.\n- `{protection, Protection}`, where `Protection` is `protected` or `private`,\n according to the options given to `new`.","title":"digraph.info/1","ref":"digraph.html#info/1"},{"type":"function","doc":"","title":"digraph.new/0","ref":"digraph.html#new/0"},{"type":"function","doc":"Returns an [empty digraph](`m:digraph#empty_digraph`) with properties according\nto the options in `Type`:\n\n- **`cyclic`** - Allows [cycles](`m:digraph#cycle`) in the digraph (default).\n\n- **`acyclic`** - The digraph is to be kept\n [acyclic](`m:digraph#acyclic_digraph`).\n\n- **`protected`** - Other processes can read the digraph (default).\n\n- **`private`** - The digraph can be read and modified by the creating process\n only.\n\nIf an unrecognized type option `T` is specified or `Type` is not a proper list,\na `badarg` exception is raised.","title":"digraph.new/1","ref":"digraph.html#new/1"},{"type":"function","doc":"Returns the number of edges of digraph `G`.","title":"digraph.no_edges/1","ref":"digraph.html#no_edges/1"},{"type":"function","doc":"Returns the number of vertices of digraph `G`.","title":"digraph.no_vertices/1","ref":"digraph.html#no_vertices/1"},{"type":"function","doc":"Returns the [out-degree](`m:digraph#out_degree`) of vertex `V` of digraph `G`.","title":"digraph.out_degree/2","ref":"digraph.html#out_degree/2"},{"type":"function","doc":"Returns a list of all edges [emanating](`m:digraph#emanate`) from `V` of digraph\n`G`, in some unspecified order.","title":"digraph.out_edges/2","ref":"digraph.html#out_edges/2"},{"type":"function","doc":"Returns a list of all [out-neighbors](`m:digraph#out_neighbour`) of `V` of\ndigraph `G`, in some unspecified order.","title":"digraph.out_neighbours/2","ref":"digraph.html#out_neighbours/2"},{"type":"function","doc":"Returns `{V, Label}`, where `Label` is the [label](`m:digraph#label`) of the\nvertex `V` of digraph `G`, or `false` if no vertex `V` of digraph `G` exists.","title":"digraph.vertex/2","ref":"digraph.html#vertex/2"},{"type":"function","doc":"Returns a list of all vertices of digraph `G`, in some unspecified order.","title":"digraph.vertices/1","ref":"digraph.html#vertices/1"},{"type":"type","doc":"The error reason for when an edge could not be added to a graph.\n\nIf the edge would create a cycle in an\n[acyclic digraph](`m:digraph#acyclic_digraph`), `{error, {bad_edge, Path}}` is\nreturned. If `G` already has an edge with value `E` connecting a different pair\nof vertices, `{error, {bad_edge, [V1, V2]}}` is returned. If either of `V1` or\n`V2` is not a vertex of digraph `G`, `{error, {bad_vertex, `V`}}` is returned,\nV = `V1` or V = `V2`.","title":"digraph.add_edge_err_rsn/0","ref":"digraph.html#t:add_edge_err_rsn/0"},{"type":"type","doc":"","title":"digraph.d_cyclicity/0","ref":"digraph.html#t:d_cyclicity/0"},{"type":"type","doc":"","title":"digraph.d_protection/0","ref":"digraph.html#t:d_protection/0"},{"type":"type","doc":"","title":"digraph.d_type/0","ref":"digraph.html#t:d_type/0"},{"type":"type","doc":"Serves as the identifier or \"name\" of an edge. This is distinct from an edge\n\"label\" which attaches ancillary information to the edge rather than identifying\nthe edge itself.","title":"digraph.edge/0","ref":"digraph.html#t:edge/0"},{"type":"opaque","doc":"A digraph as returned by [`new/0,1`](`new/0`).","title":"digraph.graph/0","ref":"digraph.html#t:graph/0"},{"type":"type","doc":"","title":"digraph.label/0","ref":"digraph.html#t:label/0"},{"type":"type","doc":"","title":"digraph.vertex/0","ref":"digraph.html#t:vertex/0"},{"type":"module","doc":"This module provides algorithms based on depth-first traversal of directed\ngraphs.\n\nFor basic functions on directed graphs, see the `m:digraph` module.\n\n- A _directed graph_{: #digraph } (or just \"digraph\") is a pair (V, E) of a\n finite set V of _vertices_{: #vertex } and a finite set E of _directed\n edges_{: #edge } (or just \"edges\"). The set of edges E is a subset of V × V\n (the Cartesian product of V with itself).\n- Digraphs can be annotated with more information. Such information can be\n attached to the vertices and to the edges of the digraph. An annotated digraph\n is called a _labeled digraph_, and the information attached to a vertex or an\n edge is called a _label_{: #label }.\n- An edge e = (v, w) is said to _emanate_{: #emanate } from vertex v and to be\n _incident_{: #incident } on vertex w.\n- If an edge is emanating from v and incident on w, then w is said to be an\n _out-neighbor_{: #out_neighbour } of v, and v is said to be an _in-neighbor_{:\n #in_neighbour } of w.\n- A _path_{: #path } P from v\\[1] to v\\[k] in a digraph (V, E) is a non-empty\n sequence v\\[1], v\\[2], ..., v\\[k] of vertices in V such that there is an edge\n (v\\[i],v\\[i+1]) in E for 1 <= i < k.\n- The _length_{: #length } of path P is k-1.\n- Path P is a _cycle_{: #cycle } if the length of P is not zero and v\\[1] =\n v\\[k].\n- A _loop_{: #loop } is a cycle of length one.\n- An _acyclic digraph_{: #acyclic_digraph } is a digraph without cycles.\n- A _depth-first traversal_{: #depth_first_traversal } of a directed digraph can\n be viewed as a process that visits all vertices of the digraph. Initially, all\n vertices are marked as unvisited. The traversal starts with an arbitrarily\n chosen vertex, which is marked as visited, and follows an edge to an unmarked\n vertex, marking that vertex. The search then proceeds from that vertex in the\n same fashion, until there is no edge leading to an unvisited vertex. At that\n point the process backtracks, and the traversal continues as long as there are\n unexamined edges. If unvisited vertices remain when all edges from the first\n vertex have been examined, some so far unvisited vertex is chosen, and the\n process is repeated.\n- A _partial ordering_{: #partial_ordering } of a set S is a transitive,\n antisymmetric, and reflexive relation between the objects of S.\n- The problem of _topological sorting_{: #topsort } is to find a total ordering\n of S that is a superset of the partial ordering. A digraph G = (V, E) is\n equivalent to a relation E on V (we neglect that the version of directed\n graphs provided by the `digraph` module allows multiple edges between\n vertices). If the digraph has no cycles of length two or more, the reflexive\n and transitive closure of E is a partial ordering.\n- A _subgraph_{: #subgraph } G' of G is a digraph whose vertices and edges form\n subsets of the vertices and edges of G.\n- G' is _maximal_ with respect to a property P if all other subgraphs that\n include the vertices of G' do not have property P.\n- A _strongly connected component_{: #strong_components } is a maximal subgraph\n such that there is a path between each pair of vertices.\n- A _connected component_{: #components } is a maximal subgraph such that there\n is a path between each pair of vertices, considering all edges undirected.\n- An _arborescence_{: #arborescence } is an acyclic digraph with a vertex V, the\n _root_{: #root }, such that there is a unique path from V to every other\n vertex of G.\n- A _tree_{: #tree } is an acyclic non-empty digraph such that there is a unique\n path between every pair of vertices, considering all edges undirected.","title":"digraph_utils","ref":"digraph_utils.html"},{"type":"module","doc":"`m:digraph`","title":"See Also - digraph_utils","ref":"digraph_utils.html#module-see-also"},{"type":"function","doc":"Returns `{yes, Root}` if `Root` is the [root](`m:digraph_utils#root`) of the\narborescence `Digraph`, otherwise `no`.","title":"digraph_utils.arborescence_root/1","ref":"digraph_utils.html#arborescence_root/1"},{"type":"function","doc":"Returns a list of [connected components](`m:digraph_utils#components`). Each\ncomponent is represented by its vertices. The order of the vertices and the\norder of the components are arbitrary. Each vertex of digraph `Digraph` occurs\nin exactly one component.","title":"digraph_utils.components/1","ref":"digraph_utils.html#components/1"},{"type":"function","doc":"Creates a digraph where the vertices are the\n[strongly connected components](`m:digraph_utils#strong_components`) of\n`Digraph` as returned by `strong_components/1`. If X and Y are two different\nstrongly connected components, and vertices x and y exist in X and Y,\nrespectively, such that there is an edge [emanating](`m:digraph_utils#emanate`)\nfrom x and [incident](`m:digraph_utils#incident`) on y, then an edge emanating\nfrom X and incident on Y is created.\n\nThe created digraph has the same type as `Digraph`. All vertices and edges have\nthe default [label](`m:digraph_utils#label`) `[]`.\n\nEach [cycle](`m:digraph_utils#cycle`) is included in some strongly connected\ncomponent, which implies that a\n[topological ordering](`m:digraph_utils#topsort`) of the created digraph always\nexists.","title":"digraph_utils.condensation/1","ref":"digraph_utils.html#condensation/1"},{"type":"function","doc":"Returns a list of\n[strongly connected components](`m:digraph_utils#strong_components`). Each\nstrongly component is represented by its vertices. The order of the vertices and\nthe order of the components are arbitrary. Only vertices that are included in\nsome [cycle](`m:digraph_utils#cycle`) in `Digraph` are returned, otherwise the\nreturned list is equal to that returned by `strong_components/1`.","title":"digraph_utils.cyclic_strong_components/1","ref":"digraph_utils.html#cyclic_strong_components/1"},{"type":"function","doc":"Returns `true` if and only if digraph `Digraph` is\n[acyclic](`m:digraph_utils#acyclic_digraph`).","title":"digraph_utils.is_acyclic/1","ref":"digraph_utils.html#is_acyclic/1"},{"type":"function","doc":"Returns `true` if and only if digraph `Digraph` is an\n[arborescence](`m:digraph_utils#arborescence`).","title":"digraph_utils.is_arborescence/1","ref":"digraph_utils.html#is_arborescence/1"},{"type":"function","doc":"Returns `true` if and only if digraph `Digraph` is a\n[tree](`m:digraph_utils#tree`).","title":"digraph_utils.is_tree/1","ref":"digraph_utils.html#is_tree/1"},{"type":"function","doc":"Returns a list of all vertices of `Digraph` that are included in some\n[loop](`m:digraph_utils#loop`).","title":"digraph_utils.loop_vertices/1","ref":"digraph_utils.html#loop_vertices/1"},{"type":"function","doc":"Returns all vertices of digraph `Digraph`. The order is given by a\n[depth-first traversal](`m:digraph_utils#depth_first_traversal`) of the digraph,\ncollecting visited vertices in postorder. More precisely, the vertices visited\nwhile searching from an arbitrarily chosen vertex are collected in postorder,\nand all those collected vertices are placed before the subsequently visited\nvertices.","title":"digraph_utils.postorder/1","ref":"digraph_utils.html#postorder/1"},{"type":"function","doc":"Returns all vertices of digraph `Digraph`. The order is given by a\n[depth-first traversal](`m:digraph_utils#depth_first_traversal`) of the digraph,\ncollecting visited vertices in preorder.","title":"digraph_utils.preorder/1","ref":"digraph_utils.html#preorder/1"},{"type":"function","doc":"Returns an unsorted list of digraph vertices such that for each vertex in the\nlist, there is a [path](`m:digraph_utils#path`) in `Digraph` from some vertex of\n`Vertices` to the vertex. In particular, as paths can have length zero, the\nvertices of `Vertices` are included in the returned list.","title":"digraph_utils.reachable/2","ref":"digraph_utils.html#reachable/2"},{"type":"function","doc":"Returns an unsorted list of digraph vertices such that for each vertex in the\nlist, there is a [path](`m:digraph_utils#path`) in `Digraph` of length one or\nmore from some vertex of `Vertices` to the vertex. As a consequence, only those\nvertices of `Vertices` that are included in some\n[cycle](`m:digraph_utils#cycle`) are returned.","title":"digraph_utils.reachable_neighbours/2","ref":"digraph_utils.html#reachable_neighbours/2"},{"type":"function","doc":"Returns an unsorted list of digraph vertices such that for each vertex in the\nlist, there is a [path](`m:digraph_utils#path`) from the vertex to some vertex\nof `Vertices`. In particular, as paths can have length zero, the vertices of\n`Vertices` are included in the returned list.","title":"digraph_utils.reaching/2","ref":"digraph_utils.html#reaching/2"},{"type":"function","doc":"Returns an unsorted list of digraph vertices such that for each vertex in the\nlist, there is a [path](`m:digraph_utils#path`) of length one or more from the\nvertex to some vertex of `Vertices`. Therefore only those vertices of `Vertices`\nthat are included in some [cycle](`m:digraph_utils#cycle`) are returned.","title":"digraph_utils.reaching_neighbours/2","ref":"digraph_utils.html#reaching_neighbours/2"},{"type":"function","doc":"Returns a list of\n[strongly connected components](`m:digraph_utils#strong_components`). Each\nstrongly component is represented by its vertices. The order of the vertices and\nthe order of the components are arbitrary. Each vertex of digraph `Digraph`\noccurs in exactly one strong component.","title":"digraph_utils.strong_components/1","ref":"digraph_utils.html#strong_components/1"},{"type":"function","doc":"","title":"digraph_utils.subgraph/2","ref":"digraph_utils.html#subgraph/2"},{"type":"function","doc":"Creates a maximal [subgraph](`m:digraph_utils#subgraph`) of `Digraph` having as\nvertices those vertices of `Digraph` that are mentioned in `Vertices`.\n\nIf the value of option `type` is `inherit`, which is the default, the type of\n`Digraph` is used for the subgraph as well. Otherwise the option value of `type`\nis used as argument to `digraph:new/1`.\n\nIf the value of option `keep_labels` is `true`, which is the default, the\n[labels](`m:digraph_utils#label`) of vertices and edges of `Digraph` are used\nfor the subgraph as well. If the value is `false`, default label `[]` is used\nfor the vertices and edges of the subgroup.\n\n[`subgraph(Digraph, Vertices)`](`subgraph/2`) is equivalent to\n[`subgraph(Digraph, Vertices, [])`](`subgraph/3`).\n\nIf any of the arguments are invalid, a `badarg` exception is raised.","title":"digraph_utils.subgraph/3","ref":"digraph_utils.html#subgraph/3"},{"type":"function","doc":"Returns a [topological ordering](`m:digraph_utils#topsort`) of the vertices of\ndigraph `Digraph` if such an ordering exists, otherwise `false`. For each vertex\nin the returned list, no [out-neighbors](`m:digraph_utils#out_neighbour`) occur\nearlier in the list.","title":"digraph_utils.topsort/1","ref":"digraph_utils.html#topsort/1"},{"type":"module","doc":"Built-in term storage.\n\nThis module is an interface to the Erlang built-in term storage BIFs. These\nprovide the ability to store very large quantities of data in an Erlang runtime\nsystem, and to have constant access time to the data. (In the case of\n`ordered_set`, see below, access time is proportional to the logarithm of the\nnumber of stored objects.)\n\nData is organized as a set of dynamic tables, which can store tuples. Each table\nis created by a process. When the process terminates, the table is automatically\ndestroyed. Every table has access rights set at creation.\n\nTables are divided into four different types, `set`, `ordered_set`, `bag`, and\n`duplicate_bag`. A `set` or `ordered_set` table can only have one object\nassociated with each key. A `bag` or `duplicate_bag` table can have many objects\nassociated with each key.\n\nInsert and lookup times in tables of type `set` are constant, regardless of the\ntable size. For table types `bag` and `duplicate_bag` time is proportional to\nthe number of objects with the same key. Even seemingly unrelated keys may\ninflict linear search to be skipped past while looking for the key of interest\n(due to hash collision).\n\n> #### Warning {: .warning }\n>\n> For tables of type `bag` and `duplicate_bag`, avoid inserting an extensive\n> amount of objects with the same key. It will hurt insert and lookup\n> performance as well as real time characteristics of the runtime environment\n> (hash bucket linear search do not yield).\n\nThe `ordered_set` table type uses a binary search tree. Insert and lookup times\nare proportional to the logarithm of the number of objects in the table.\n\n[](){: #max_ets_tables }\n\n> #### Note {: .info }\n>\n> The number of tables stored at one Erlang node _used_ to be limited. This is\n> no longer the case (except by memory usage). The previous default limit was\n> about 1400 tables and could be increased by setting the environment variable\n> `ERL_MAX_ETS_TABLES` or the command line option\n> [`+e`](`e:erts:erl_cmd.md#%2Be`) before starting the Erlang runtime system.\n> This hard limit has been removed, but it is currently useful to set the\n> `ERL_MAX_ETS_TABLES` anyway. It should be set to an approximate of the maximum\n> amount of tables used since an internal table for named tables is sized using\n> this value. If large amounts of named tables are used and `ERL_MAX_ETS_TABLES`\n> hasn't been increased, the performance of named table lookup will degrade.\n\nNotice that there is no automatic garbage collection for tables. Even if there\nare no references to a table from any process, it is not automatically destroyed\nunless the owner process terminates. To destroy a table explicitly, use function\n`delete/1`. The default owner is the process that created the table. To transfer\ntable ownership at process termination, use option [`heir`](`m:ets#heir`) or\ncall `give_away/3`.\n\nSome implementation details:\n\n- In the current implementation, every object insert and look-up operation\n results in a copy of the object.\n- `'$end_of_table'` is not to be used as a key, as this atom is used to mark the\n end of the table when using functions `first/1` and `next/2`.\n\nNotice the subtle difference between _matching_ and _comparing equal_, which is\ndemonstrated by table types `set` and `ordered_set`:\n\n- Two Erlang terms `match` if they are of the same type and have the same value,\n so that `1` matches `1`, but not `1.0` (as `1.0` is a `t:float/0` and not an\n `t:integer/0`).\n- Two Erlang terms _compare equal_ if they either are of the same type and\n value, or if both are numeric types and extend to the same value, so that `1`\n compares equal to both `1` and `1.0`.\n- The `ordered_set` works on the _Erlang term order_ and no defined order exists\n between an `t:integer/0` and a `t:float/0` that extends to the same value.\n Hence the key `1` and the key `1.0` are regarded as equal in an `ordered_set`\n table.\n\n[](){: #ets_failures }","title":"ets","ref":"ets.html"},{"type":"module","doc":"Functions in this module fail by raising an error exception with error reason:\n\n- **`badarg`** - If any argument has the wrong format.\n\n- **`badarg`** - If the table identifier is invalid.\n\n- **`badarg`** - If the operation is denied because of table access rights\n ([protected](`m:ets#protected`) or [private](`m:ets#private`)).\n\n- **`system_limit`** - Modification of a value causes it to not be representable\n internally in the VM. For example, incrementation of a counter past the\n largest integer representable.\n\n- **`system_limit`** - If a match specification passed as argument has excessive\n nesting which causes scheduler stack exhaustion for the scheduler that the\n calling process is executing on.\n [Scheduler stack size](`e:erts:erl_cmd.md#sched_thread_stack_size`) can be\n configured when starting the runtime system.\n\n[](){: #concurrency }","title":"Failures - ets","ref":"ets.html#module-failures"},{"type":"module","doc":"This module provides some limited support for concurrent access. All updates to\nsingle objects are guaranteed to be both _atomic_ and _isolated_. This means\nthat an updating operation to a single object either succeeds or fails\ncompletely without any effect (atomicity) and that no intermediate results of\nthe update can be seen by other processes (isolation). Some functions that\nupdate many objects state that they even guarantee atomicity and isolation for\nthe entire operation. In database terms the isolation level can be seen as\n\"serializable\", as if all isolated operations are carried out serially, one\nafter the other in a strict order.\n\n[](){: #traversal }","title":"Concurrency - ets","ref":"ets.html#module-concurrency"},{"type":"module","doc":"There are different ways to traverse through the objects of a table.\n\n- _Single-step_ traversal one key at at time, using `first/1`, `next/2`,\n `last/1` and `prev/2`.\n- _Single-step_ traversal one key at at time, but using `first_lookup/1`,\n `next_lookup/2`, `last_lookup/1` and `prev_lookup/2`. This is more efficient\n when you also need to lookup the objects for the keys.\n- Search with simple _match patterns_, using [`match/1/2/3`](`match/1`),\n `match_delete/2` and [`match_object/1/2/3`](`match_object/1`).\n- Search with more powerful _match specifications_, using\n [`select/1/2/3`](`select/1`), `select_count/2`, `select_delete/2`,\n `select_replace/2` and [`select_reverse/1/2/3`](`select_reverse/1`).\n- _Table conversions_, using [`tab2file/2/3`](`tab2file/2`) and `tab2list/1`.\n\nNo table traversal will guarantee a consistent snapshot of the entire table if\nthe table is also updated by concurrent processes during the traversal. The\nresult of each concurrently updated object may be seen (or not) depending on if\nit has happened when the traversal visits that part of the table. The only way\nto guarantee a full consistent table snapshot (if you really need that) is to\ndisallow concurrent updates during the entire traversal.\n\nMoreover, traversals not done in a _safe_ way, on tables where keys are inserted\nor deleted during the traversal, may yield the following undesired effects:\n\n- Any key may be missed.\n- Any key may be found more than once.\n- The traversal may fail with `badarg` exception if keys are deleted.\n\nA table traversal is _safe_ if either\n\n- the table is of type `ordered_set`.\n- the entire table traversal is done within one ETS function call.\n- function `safe_fixtable/2` is used to keep the table fixated during the entire\n traversal.\n\n> #### Note {: .info }\n>\n> Even though the access of a single object is always guaranteed to be\n> [atomic and isolated](`m:ets#module-concurrency`), each traversal through a table to\n> find the next key is not done with such guarantees. This is often not a\n> problem, but may cause rare subtle \"unexpected\" effects if a concurrent\n> process inserts objects during a traversal. For example, consider one process\n> doing\n>\n> ```erlang\n> ets:new(t, [ordered_set, named_table]),\n> ets:insert(t, {1}),\n> ets:insert(t, {2}),\n> ets:insert(t, {3}),\n> ```\n>\n> A concurrent call to `ets:first(t)`, done by another process, may then in rare\n> cases return `2` even though `2` has never existed in the table ordered as the\n> first key. In the same way, a concurrent call to `ets:next(t, 1)` may return\n> `3` even though `3` never existed in the table ordered directly after `1`.\n>\n> Effects like this are improbable but possible. The probability will further be\n> reduced (if not vanish) if table option\n> [`write_concurrency`](`m:ets#new_2_write_concurrency`) is not enabled. This\n> can also only be a potential concern for `ordered_set` where the traversal\n> order is defined.\n\nTraversals using `match` and `select` functions may not need to scan the entire\ntable depending on how the key is specified. A match pattern with a _fully bound\nkey_ (without any match variables) will optimize the operation to a single key\nlookup without any table traversal at all. For `ordered_set` a _partially bound\nkey_ will limit the traversal to only scan a subset of the table based on term\norder. A partially bound key is either a list or a tuple with a prefix that is\nfully bound. Example:\n\n```erlang\n1> T = ets:new(t,[ordered_set]), ets:insert(T, {\"555-1234\", \"John Smith\"}).\ntrue\n2> %% Efficient search of all with area code 555\n2> ets:match(T,{[$5,$5,$5,$- |'$1'],'$2'}).\n[[\"1234\",\"John Smith\"]]\n```\n\n[](){: #match_spec }","title":"Table traversal - ets","ref":"ets.html#module-table-traversal"},{"type":"module","doc":"Some of the functions use a _match specification_, `match_spec`. For a brief\nexplanation, see `select/2`. For a detailed description, see section\n[Match Specifications in Erlang](`e:erts:match_spec.md`) in ERTS User's Guide.\n\nA match specifications with excessive nesting will cause a\n[`system_limit`](`m:ets#ets_failures`) error exception to be raised.","title":"Match Specifications - ets","ref":"ets.html#module-match-specifications"},{"type":"function","doc":"Returns a list of all tables at the node. Named tables are specified by their\nnames, unnamed tables are specified by their table identifiers.\n\nThere is no guarantee of consistency in the returned list. Tables created or\ndeleted by other processes \"during\" the `ets:all()` call either are or are not\nincluded in the list. Only tables created/deleted _before_ `ets:all()` is called\nare guaranteed to be included/excluded.","title":"ets.all/0","ref":"ets.html#all/0"},{"type":"function","doc":"Deletes the entire table `Table`.","title":"ets.delete/1","ref":"ets.html#delete/1"},{"type":"function","doc":"Deletes all objects with key `Key` from table `Table`. This function succeeds\neven if no objects with key `Key` exist.","title":"ets.delete/2","ref":"ets.html#delete/2"},{"type":"function","doc":"Delete all objects in the ETS table `Table`. The operation is guaranteed to be\n[atomic and isolated](`m:ets#module-concurrency`).","title":"ets.delete_all_objects/1","ref":"ets.html#delete_all_objects/1"},{"type":"function","doc":"Delete the exact object `Object` from the ETS table, leaving objects with the\nsame key but other differences (useful for type `bag`). In a `duplicate_bag`\ntable, all instances of the object are deleted.","title":"ets.delete_object/2","ref":"ets.html#delete_object/2"},{"type":"function","doc":"Reads a file produced by `tab2file/2` or `tab2file/3` and creates the\ncorresponding table `Table`.\n\nEquivalent to [`file2tab(Filename, [])`](`file2tab/2`).","title":"ets.file2tab/1","ref":"ets.html#file2tab/1"},{"type":"function","doc":"Reads a file produced by `tab2file/2` or `tab2file/3` and creates the\ncorresponding table `Table`.\n\nThe only supported option is `{verify,boolean()}`. If verification is turned on\n(by specifying `{verify,true}`), the function uses whatever information is\npresent in the file to assert that the information is not damaged. How this is\ndone depends on which `extended_info` was written using `tab2file/3`.\n\nIf no `extended_info` is present in the file and `{verify,true}` is specified,\nthe number of objects written is compared to the size of the original table when\nthe dump was started. This can make verification fail if the table was `public`\nand objects were added or removed while the table was dumped to file. To avoid\nthis problem, either do not verify files dumped while updated simultaneously or\nuse option `{extended_info, [object_count]}` to `tab2file/3`, which extends the\ninformation in the file with the number of objects written.\n\nIf verification is turned on and the file was written with option\n`{extended_info, [md5sum]}`, reading the file is slower and consumes radically\nmore CPU time than otherwise.\n\n`{verify,false}` is the default.","title":"ets.file2tab/2","ref":"ets.html#file2tab/2"},{"type":"function","doc":"Returns the first key `Key` in table `Table`. For an `ordered_set` table, the\nfirst key in Erlang term order is returned. For other table types, the first key\naccording to the internal order of the table is returned. If the table is empty,\n`'$end_of_table'` is returned.\n\nTo find subsequent keys in the table, use `next/2`.","title":"ets.first/1","ref":"ets.html#first/1"},{"type":"function","doc":"Similar to `first/1` except that it returns the object(s) along with the key\nstored in the table. This is equivalent to doing `first/1` followed by a\n`lookup/2`. If the table is empty, `'$end_of_table'` is returned.\n\nTo find subsequent objects in the table, use `next_lookup/2`.","title":"ets.first_lookup/1","ref":"ets.html#first_lookup/1"},{"type":"function","doc":"`Acc0` is returned if the table is empty. This function is similar to\n`lists:foldl/3`. The table elements are traversed in an unspecified order,\nexcept for `ordered_set` tables, where they are traversed first to last.\n\nIf `Function` inserts objects into the table, or another process inserts objects\ninto the table, those objects _can_ (depending on key ordering) be included in\nthe traversal.","title":"ets.foldl/3","ref":"ets.html#foldl/3"},{"type":"function","doc":"`Acc0` is returned if the table is empty. This function is similar to\n`lists:foldr/3`. The table elements are traversed in an unspecified order,\nexcept for `ordered_set` tables, where they are traversed last to first.\n\nIf `Function` inserts objects into the table, or another process inserts objects\ninto the table, those objects _can_ (depending on key ordering) be included in\nthe traversal.","title":"ets.foldr/3","ref":"ets.html#foldr/3"},{"type":"function","doc":"Fills an already created ETS table with the objects in the already opened Dets\ntable `DetsTab`. Existing objects in the ETS table are kept unless overwritten.\n\nIf any of the tables does not exist or the Dets table is not open, a `badarg`\nexception is raised.","title":"ets.from_dets/2","ref":"ets.html#from_dets/2"},{"type":"function","doc":"Pseudo function that by a `parse_transform` translates `LiteralFun` typed as\nparameter in the function call to a [match specification](`m:ets#match_spec`).\nWith \"literal\" is meant that the fun must textually be written as the parameter\nof the function, it cannot be held in a variable that in turn is passed to the\nfunction.\n\nThe parse transform is provided in the `ms_transform` module and the source\n_must_ include file `ms_transform.hrl` in STDLIB for this pseudo function to\nwork. Failing to include the hrl file in the source results in a runtime error,\nnot a compile time error. The include file is easiest included by adding line\n`-include_lib(\"stdlib/include/ms_transform.hrl\").` to the source file.\n\nThe fun is very restricted, it can take only a single parameter (the object to\nmatch): a sole variable or a tuple. It must use the `is_` guard tests. Language\nconstructs that have no representation in a match specification (`if`, `case`,\n`receive`, and so on) are not allowed.\n\nThe return value is the resulting match specification.\n\n_Example:_\n\n```erlang\n1> ets:fun2ms(fun({M,N}) when N > 3 -> M end).\n[{{'$1','$2'},[{'>','$2',3}],['$1']}]\n```\n\nVariables from the environment can be imported, so that the following works:\n\n```erlang\n2> X=3.\n3\n3> ets:fun2ms(fun({M,N}) when N > X -> M end).\n[{{'$1','$2'},[{'>','$2',{const,3}}],['$1']}]\n```\n\nThe imported variables are replaced by match specification `const` expressions,\nwhich is consistent with the static scoping for Erlang funs. However, local or\nglobal function calls cannot be in the guard or body of the fun. Calls to\nbuilt-in match specification functions is of course allowed:\n\n```erlang\n4> ets:fun2ms(fun({M,N}) when N > X, my_fun(M) -> M end).\nError: fun containing local Erlang function calls\n('my_fun' called in guard) cannot be translated into match_spec\n{error,transform_error}\n5> ets:fun2ms(fun({M,N}) when N > X, is_atom(M) -> M end).\n[{{'$1','$2'},[{'>','$2',{const,3}},{is_atom,'$1'}],['$1']}]\n```\n\nAs shown by the example, the function can be called from the shell also. The fun\nmust be literally in the call when used from the shell as well.\n\n> #### Warning {: .warning }\n>\n> If the `parse_transform` is not applied to a module that calls this pseudo\n> function, the call fails in runtime (with a `badarg`). The `ets` module\n> exports a function with this name, but it is never to be called except when\n> using the function in the shell. If the `parse_transform` is properly applied\n> by including header file `ms_transform.hrl`, compiled code never calls the\n> function, but the function call is replaced by a literal match specification.\n\nFor more information, see [`ms_transform`](`m:ms_transform`).","title":"ets.fun2ms/1","ref":"ets.html#fun2ms/1"},{"type":"function","doc":"Make process `Pid` the new owner of table `Table`. If successful, message\n`{'ETS-TRANSFER',Table,FromPid,GiftData}` is sent to the new owner.\n\nThe process `Pid` must be alive, local, and not already the owner of the table.\nThe calling process must be the table owner.\n\nNotice that this function does not affect option [`heir`](`m:ets#heir`) of the\ntable. A table owner can, for example, set `heir` to itself, give the table\naway, and then get it back if the receiver terminates.","title":"ets.give_away/3","ref":"ets.html#give_away/3"},{"type":"function","doc":"Displays information about all ETS tables on a terminal.","title":"ets.i/0","ref":"ets.html#i/0"},{"type":"function","doc":"Browses table `Table` on a terminal.","title":"ets.i/1","ref":"ets.html#i/1"},{"type":"function","doc":"Returns information about table `Table` as a list of tuples. If `Table` has the\ncorrect type for a table identifier, but does not refer to an existing ETS\ntable, `undefined` is returned. If `Table` is not of the correct type, a\n`badarg` exception is raised.\n\n- **`{compressed, boolean()}`** - Indicates if the table is compressed.\n\n- **`{decentralized_counters, boolean()}`** - Indicates whether the table uses\n `decentralized_counters`.\n\n- **`{heir, pid() | none}`** - The pid of the heir of the table, or `none` if no\n heir is set.\n\n- **`{id,`[ `tid()`](`t:tid/0`)`}`** - The table identifier.\n\n- **`{keypos, integer() >= 1}`** - The key position.\n\n- **`{memory, integer() >= 0}`** - The number of words allocated to the table.\n\n- **`{name, atom()}`** - The table name.\n\n- **`{named_table, boolean()}`** - Indicates if the table is named.\n\n- **`{node, node()}`** - The node where the table is stored. This field is no\n longer meaningful, as tables cannot be accessed from other nodes.\n\n- **`{owner, pid()}`** - The pid of the owner of the table.\n\n- **`{protection,` [`access()`](`t:table_access/0`)`}`** - The table access\n rights.\n\n- **`{size, integer() >= 0}`** - The number of objects inserted in the table.\n\n- **`{type,` [`type()`](`t:table_type/0`)`}`** - The table type.\n\n- **`{read_concurrency, boolean()}`** - Indicates whether the table uses\n `read_concurrency` or not.\n\n- **`{write_concurrency, WriteConcurrencyAlternative}`** - Indicates which\n `write_concurrency` option the table uses.\n\n> #### Note {: .info }\n>\n> The execution time of this function is affected by the\n> [`decentralized_counters`](`m:ets#new_2_decentralized_counters`) table option.\n> The execution time is much longer when the `decentralized_counters` option is\n> set to `true` than when the `decentralized_counters` option is set to `false`.","title":"ets.info/1","ref":"ets.html#info/1"},{"type":"function","doc":"Returns the information associated with `Item` for table `Table`, or returns\n`undefined` if `Table` does not refer an existing ETS table. If `Table` is not\nof the correct type, or if `Item` is not one of the allowed values, a `badarg`\nexception is raised.\n\nIn addition to the `{Item,Value}` pairs defined for `info/1`, the following\nitems are allowed:\n\n- `Item=binary, Value=BinInfo`\n\n `BinInfo` is a list containing miscellaneous information about binaries kept\n by the table. This `Item` can be changed or removed without prior notice. In\n the current implementation `BinInfo` is a list of tuples\n `{BinaryId,BinarySize,BinaryRefcCount}`.\n\n- `Item=fixed, Value=boolean()`\n\n Indicates if the table is fixed by any process.\n\n- [](){: #info_2_safe_fixed_monotonic_time }\n\n `Item=safe_fixed|safe_fixed_monotonic_time, Value={FixationTime,Info}|false`\n\n If the table is fixed using `safe_fixtable/2`, the call returns a tuple where\n `FixationTime` is the last time when the table changed from unfixed to fixed.\n\n The format and value of `FixationTime` depends on `Item`:\n\n - **`safe_fixed`** - `FixationTime` corresponds to the result returned by\n `erlang:timestamp/0` at the time of fixation. Notice that when the system\n uses single or multi\n [time warp modes](`e:erts:time_correction.md#time-warp-modes`) this can\n produce strange results, as the use of `safe_fixed` is not\n [time warp safe](`e:erts:time_correction.md#time-warp-safe-code`). Time warp\n safe code must use `safe_fixed_monotonic_time` instead.\n\n - **`safe_fixed_monotonic_time`** - `FixationTime` corresponds to the result\n returned by `erlang:monotonic_time/0` at the time of fixation. The use of\n `safe_fixed_monotonic_time` is\n [time warp safe](`e:erts:time_correction.md#time-warp-safe-code`).\n\n `Info` is a possibly empty lists of tuples `{Pid,RefCount}`, one tuple for\n every process the table is fixed by now. `RefCount` is the value of the\n reference counter and it keeps track of how many times the table has been\n fixed by the process.\n\n Table fixations are not limited to `safe_fixtable/2`. Temporary fixations may\n also be done by for example [traversing functions](`m:ets#traversal`) like\n `select` and `match`. Such table fixations are automatically released before\n the corresponding functions returns, but they may be seen by a concurrent call\n to `ets:info(T,safe_fixed|safe_fixed_monotonic_time)`.\n\n If the table is not fixed at all, the call returns `false`.\n\n- `Item=stats, Value=tuple()`\n\n Returns internal statistics about tables on an internal format used by OTP\n test suites. Not for production use.\n\n> #### Note {: .info }\n>\n> The execution time of this function is affected by the\n> [`decentralized_counters`](`m:ets#new_2_decentralized_counters`) table option\n> when the second argument of the function is `size` or `memory`. The execution\n> time is much longer when the `decentralized_counters` option is set to `true`\n> than when the `decentralized_counters` option is set to `false`.","title":"ets.info/2","ref":"ets.html#info/2"},{"type":"function","doc":"Replaces the existing objects of table `Table` with objects created by calling\nthe input function `InitFun`, see below. This function is provided for\ncompatibility with the `dets` module, it is not more efficient than filling a\ntable by using `insert/2`.\n\nWhen called with argument `read`, the function `InitFun` is assumed to return\n`end_of_input` when there is no more input, or `{Objects, Fun}`, where `Objects`\nis a list of objects and `Fun` is a new input function. Any other value `Value`\nis returned as an error `{error, {init_fun, Value}}`. Each input function is\ncalled exactly once, and if an error occur, the last function is called with\nargument `close`, the reply of which is ignored.\n\nIf the table type is `set` and more than one object exists with a given key, one\nof the objects is chosen. This is not necessarily the last object with the given\nkey in the sequence of objects returned by the input functions. This holds also\nfor duplicated objects stored in tables of type `bag`.","title":"ets.init_table/2","ref":"ets.html#init_table/2"},{"type":"function","doc":"Inserts the object or all of the objects in list `ObjectOrObjects` into table\n`Table`.\n\n- If the table type is `set` and the key of the inserted objects _matches_ the\n key of any object in the table, the old object is replaced.\n- If the table type is `ordered_set` and the key of the inserted object\n _compares equal_ to the key of any object in the table, the old object is\n replaced.\n- If the table type is `bag` and the object _matches_ any whole object in the\n table, the object is not inserted.\n- If the list contains more than one object with _matching_ keys and the table\n type is `set`, one is inserted, which one is not defined. The same holds for\n table type `ordered_set` if the keys _compare equal_.\n\nThe entire operation is guaranteed to be\n[atomic and isolated](`m:ets#module-concurrency`), even when a list of objects is\ninserted.\n\n[](){: #insert_list_order }\n\nFor `bag` and `duplicate_bag`, objects in the list with identical keys will be\ninserted in list order (from head to tail). That is, a subsequent call to\n[`lookup(T,Key)`](`lookup/2`) will return them in that inserted order.\n\n> #### Note {: .info }\n>\n> For `bag` the insertion order of indentical keys described above was\n> accidentally reverted in OTP 23.0 and later fixed in OTP 25.3. That is, from\n> OTP 23.0 up until OTP 25.3 the objects in a list are inserted in reverse order\n> (from tail to head).\n>\n> For `duplicate_bag` the same faulty reverse insertion exist from OTP 23.0\n> until OTP 25.3. However, it is unpredictable and may or may not happen. A\n> longer list will increase the probabiliy of the insertion being done in\n> reverse.","title":"ets.insert/2","ref":"ets.html#insert/2"},{"type":"function","doc":"Same as `insert/2` except that instead of overwriting objects with the same key\n(for `set` or `ordered_set`) or adding more objects with keys already existing\nin the table (for `bag` and `duplicate_bag`), `false` is returned.\n\nIf `ObjectOrObjects` is a list, the function checks _every_ key before inserting\nanything. Nothing is inserted unless _all_ keys present in the list are absent\nfrom the table. Like [`insert/2`](`insert/2`), the entire operation is\nguaranteed to be [atomic and isolated](`m:ets#module-concurrency`).","title":"ets.insert_new/2","ref":"ets.html#insert_new/2"},{"type":"function","doc":"Checks if a term represent a valid compiled\n[match specification](`m:ets#match_spec`). A compiled match specification is\nonly valid on the Erlang node where it was compiled by calling\n`match_spec_compile/1`.\n\n> #### Note {: .info }\n>\n> Before STDLIB 3.4 (OTP 20.0) compiled match specifications did not have an\n> external representation. If passed through\n> [`binary_to_term(term_to_binary(CMS))`](`binary_to_term/1`) or sent to another\n> node and back, the result was always an empty binary `<<>>`.\n>\n> After STDLIB 3.4 (OTP 20.0) compiled match specifications have an external\n> representation as a node specific reference to the original compiled match\n> specification. If passed through\n> [`binary_to_term(term_to_binary(CMS))`](`binary_to_term/1`) or sent to another\n> node and back, the result _may or may not_ be a valid compiled match\n> specification depending on if the original compiled match specification was\n> still alive.","title":"ets.is_compiled_ms/1","ref":"ets.html#is_compiled_ms/1"},{"type":"function","doc":"Returns the last key `Key` according to Erlang term order in table `Table` of\ntype `ordered_set`. For other table types, the function is synonymous to\n`first/1`. If the table is empty, `'$end_of_table'` is returned.\n\nTo find preceding keys in the table, use `prev/2`.","title":"ets.last/1","ref":"ets.html#last/1"},{"type":"function","doc":"Similar to `last/1` except that it returns the object(s) along with the key\nstored in the table. This is equivalent to doing `last/1` followed by a\n`lookup/2`. If the table is empty, `'$end_of_table'` is returned.\n\nTo find preceding objects in the table, use `prev_lookup/2`.","title":"ets.last_lookup/1","ref":"ets.html#last_lookup/1"},{"type":"function","doc":"Returns a list of all objects with key `Key` in table `Table`.\n\n- For tables of type `set`, `bag`, or `duplicate_bag`, an object is returned\n only if the specified key _matches_ the key of the object in the table.\n- For tables of type `ordered_set`, an object is returned if the specified key\n _compares equal_ to the key of an object in the table.\n\nThe difference is the same as between `=:=` and `==`.\n\nAs an example, one can insert an object with `t:integer/0` `1` as a key in an\n`ordered_set` and get the object returned as a result of doing a\n[`lookup/2`](`lookup/2`) with `t:float/0` `1.0` as the key to search for.\n\nFor tables of type `set` or `ordered_set`, the function returns either the empty\nlist or a list with one element, as there cannot be more than one object with\nthe same key. For tables of type `bag` or `duplicate_bag`, the function returns\na list of arbitrary length.\n\nNotice that the sequential order of object insertions is preserved; the first\nobject inserted with the specified key is the first in the resulting list, and\nso on. See also the note about\n[list insertion order](`m:ets#insert_list_order`).","title":"ets.lookup/2","ref":"ets.html#lookup/2"},{"type":"function","doc":"For a table `Table` of type `set` or `ordered_set`, the function returns the\n`Pos`:th element of the object with key `Key`.\n\nFor tables of type `bag` or `duplicate_bag`, the functions returns a list with\nthe `Pos`:th element of every object with key `Key`.\n\nIf no object with key `Key` exists, the function exits with reason `badarg`.\n\nIf `Pos` is larger than the size of the tuple, the function exits with reason\n`badarg`.\n\nThe difference between `set`, `bag`, and `duplicate_bag` on one hand, and\n`ordered_set` on the other, regarding the fact that `ordered_set` view keys as\nequal when they _compare equal_ whereas the other table types regard them equal\nonly when they _match_, holds for [`lookup_element/3`](`lookup_element/3`).","title":"ets.lookup_element/3","ref":"ets.html#lookup_element/3"},{"type":"function","doc":"For a table `Table` of type `set` or `ordered_set`, the function returns the\n`Pos`:th element of the object with key `Key`.\n\nFor tables of type `bag` or `duplicate_bag`, the functions returns a list with\nthe `Pos`:th element of every object with key `Key`.\n\nIf no object with key `Key` exists, the function returns `Default`.\n\nIf `Pos` is larger than the size of any tuple with a matching key, the function\nexits with reason `badarg`.\n\nThe difference between `set`, `bag`, and `duplicate_bag` on one hand, and\n`ordered_set` on the other, regarding the fact that `ordered_set` view keys as\nequal when they _compare equal_ whereas the other table types regard them equal\nonly when they _match_, holds for [`lookup_element/4`](`lookup_element/4`).","title":"ets.lookup_element/4","ref":"ets.html#lookup_element/4"},{"type":"function","doc":"Continues a match started with `match/3`. The next chunk of the size specified\nin the initial [`match/3`](`match/3`) call is returned together with a new\n`Continuation`, which can be used in subsequent calls to this function.\n\nWhen there are no more objects in the table, `'$end_of_table'` is returned.","title":"ets.match/1","ref":"ets.html#match/1"},{"type":"function","doc":"Matches the objects in table `Table` against pattern `Pattern`.\n\nA pattern is a term that can contain:\n\n- Bound parts (Erlang terms)\n- `'_'` that matches any Erlang term\n- Pattern variables `'$N'`, where `N`=0,1,...\n\nThe function returns a list with one element for each matching object, where\neach element is an ordered list of pattern variable bindings, for example:\n\n```erlang\n6> ets:match(T, '$1'). % Matches every object in table\n[[{rufsen,dog,7}],[{brunte,horse,5}],[{ludde,dog,5}]]\n7> ets:match(T, {'_',dog,'$1'}).\n[[7],[5]]\n8> ets:match(T, {'_',cow,'$1'}).\n[]\n```\n\nIf the key is specified in the pattern, the match is very efficient. If the key\nis not specified, that is, if it is a variable or an underscore, the entire\ntable must be searched. The search time can be substantial if the table is very\nlarge.\n\nFor tables of type `ordered_set`, the result is in the same order as in a\n`first`/`next` traversal.","title":"ets.match/2","ref":"ets.html#match/2"},{"type":"function","doc":"Works like `match/2`, but returns only a limited (`Limit`) number of matching\nobjects. Term `Continuation` can then be used in subsequent calls to `match/1`\nto get the next chunk of matching objects. This is a space-efficient way to work\non objects in a table, which is faster than traversing the table object by\nobject using `first/1` and `next/2`.\n\nIf the table is empty, `'$end_of_table'` is returned.\n\nUse `safe_fixtable/2` to guarantee [safe traversal](`m:ets#traversal`) for\nsubsequent calls to `match/1`.","title":"ets.match/3","ref":"ets.html#match/3"},{"type":"function","doc":"Deletes all objects that match pattern `Pattern` from table `Table`. For a\ndescription of patterns, see `match/2`.","title":"ets.match_delete/2","ref":"ets.html#match_delete/2"},{"type":"function","doc":"Continues a match started with `match_object/3`. The next chunk of the size\nspecified in the initial [`match_object/3`](`match_object/3`) call is returned\ntogether with a new `Continuation`, which can be used in subsequent calls to\nthis function.\n\nWhen there are no more objects in the table, `'$end_of_table'` is returned.","title":"ets.match_object/1","ref":"ets.html#match_object/1"},{"type":"function","doc":"Matches the objects in table `Table` against pattern `Pattern`. For a\ndescription of patterns, see `match/2`. The function returns a list of all\nobjects that match the pattern.\n\nIf the key is specified in the pattern, the match is very efficient. If the key\nis not specified, that is, if it is a variable or an underscore, the entire\ntable must be searched. The search time can be substantial if the table is very\nlarge.\n\nFor tables of type `ordered_set`, the result is in the same order as in a\n`first`/`next` traversal.","title":"ets.match_object/2","ref":"ets.html#match_object/2"},{"type":"function","doc":"Works like `match_object/2`, but only returns a limited (`Limit`) number of\nmatching objects. Term `Continuation` can then be used in subsequent calls to\n`match_object/1` to get the next chunk of matching objects. This is a\nspace-efficient way to work on objects in a table, which is faster than\ntraversing the table object by object using `first/1` and `next/2`.\n\nIf the table is empty, `'$end_of_table'` is returned.\n\nUse `safe_fixtable/2` to guarantee [safe traversal](`m:ets#traversal`) for\nsubsequent calls to `match_object/1`.","title":"ets.match_object/3","ref":"ets.html#match_object/3"},{"type":"function","doc":"Transforms a [match specification](`m:ets#match_spec`) into an internal\nrepresentation that can be used in subsequent calls to `match_spec_run/2`. The\ninternal representation is opaque. To check the validity of a compiled match\nspecification, use `is_compiled_ms/1`.\n\nIf term `MatchSpec` does not represent a valid match specification, a `badarg`\nexception is raised.\n\n> #### Note {: .info }\n>\n> This function has limited use in normal code. It is used by the `m:dets`\n> module to perform the `dets:select/1` operations.","title":"ets.match_spec_compile/1","ref":"ets.html#match_spec_compile/1"},{"type":"function","doc":"Executes the matching specified in a compiled\n[match specification](`m:ets#match_spec`) on a list of terms. Term\n`CompiledMatchSpec` is to be the result of a call to `match_spec_compile/1` and\nis hence the internal representation of the match specification one wants to\nuse.\n\nThe matching is executed on each element in `List` and the function returns a\nlist containing all results. If an element in `List` does not match, nothing is\nreturned for that element. The length of the result list is therefore equal or\nless than the length of parameter `List`.\n\n_Example:_\n\nThe following two calls give the same result (but certainly not the same\nexecution time):\n\n```erlang\nTable = ets:new...\nMatchSpec = ...\n% The following call...\nets:match_spec_run(ets:tab2list(Table),\n ets:match_spec_compile(MatchSpec)),\n% ...gives the same result as the more common (and more efficient)\nets:select(Table, MatchSpec),\n```\n\n> #### Note {: .info }\n>\n> This function has limited use in normal code. It is used by the `m:dets`\n> module to perform the `dets:select/1` operations and by Mnesia during\n> transactions.","title":"ets.match_spec_run/2","ref":"ets.html#match_spec_run/2"},{"type":"function","doc":"Works like `lookup/2`, but does not return the objects. Returns `true` if one or\nmore elements in the table has key `Key`, otherwise `false`.","title":"ets.member/2","ref":"ets.html#member/2"},{"type":"function","doc":"Creates a new table and returns a table identifier that can be used in\nsubsequent operations. The table identifier can be sent to other processes so\nthat a table can be shared between different processes within a node.\n\nParameter `Options` is a list of options that specifies table type, access\nrights, key position, and whether the table is named. Default values are used\nfor omitted options. This means that not specifying any options (`[]`) is the\nsame as specifying\n`[set, protected, {keypos,1}, {heir,none}, {write_concurrency,false}, {read_concurrency,false}, {decentralized_counters,false}]`.\n\n- **`set`** - The table is a `set` table: one key, one object, no order among\n objects. This is the default table type.\n\n- **`ordered_set`** - The table is a `ordered_set` table: one key, one object,\n ordered in Erlang term order, which is the order implied by the \n operators. Tables of this type have a somewhat different behavior in some\n situations than tables of other types. Most notably, the `ordered_set` tables\n regard keys as equal when they _compare equal_, not only when they match. This\n means that to an `ordered_set` table, `t:integer/0` `1` and `t:float/0` `1.0`\n are regarded as equal. This also means that the key used to lookup an element\n does not necessarily _match_ the key in the returned elements, if\n `t:float/0`'s and `t:integer/0`'s are mixed in keys of a table.\n\n- **`bag`** - The table is a `bag` table, which can have many objects, but only\n one instance of each object, per key.\n\n- **`duplicate_bag`** - The table is a `duplicate_bag` table, which can have\n many objects, including multiple copies of the same object, per key.\n\n- **`public`** - Any process can read or write to the table.\n\n [](){: #protected }\n\n- **`protected`** - The owner process can read and write to the table. Other\n processes can only read the table. This is the default setting for the access\n rights.\n\n [](){: #private }\n\n- **`private`** - Only the owner process can read or write to the table.\n\n- **`named_table`** - If this option is present, the table is registered under\n its `Name` which can then be used instead of the table identifier in\n subsequent operations.\n\n The function will also return the `Name` instead of the table identifier. To\n get the table identifier of a named table, use `whereis/1`.\n\n- **`{keypos,Pos}`** - Specifies which element in the stored tuples to use as\n key. By default, it is the first element, that is, `Pos=1`. However, this is\n not always appropriate. In particular, we do not want the first element to be\n the key if we want to store Erlang records in a table.\n\n Notice that any tuple stored in the table must have at least `Pos` number of\n elements.\n\n [](){: #heir }\n\n- **`{heir,Pid,HeirData} | {heir,none}`** - Set a process as heir. The heir\n inherits the table if the owner terminates. Message\n `{'ETS-TRANSFER',tid(),FromPid,HeirData}` is sent to the heir when that\n occurs. The heir must be a local process. Default heir is `none`, which\n destroys the table when the owner terminates.\n\n [](){: #new_2_write_concurrency }\n\n- **`{write_concurrency,WriteConcurrencyAlternative}`** - Performance tuning.\n Defaults to `false`, in which case an operation that mutates (writes to) the\n table obtains exclusive access, blocking any concurrent access of the same\n table until finished. If set to `true`, the table is optimized for concurrent\n write access. Different objects of the same table can be mutated (and read) by\n concurrent processes. This is achieved to some degree at the expense of memory\n consumption and the performance of sequential access and concurrent reading.\n\n The `auto` alternative for the `write_concurrency` option is similar to the\n `true` option but automatically adjusts the synchronization granularity during\n runtime depending on how the table is used. This is the recommended\n `write_concurrency` option when using Erlang/OTP 25 and above as it performs\n well in most scenarios.\n\n The `write_concurrency` option can be combined with the options\n [`read_concurrency`](`m:ets#new_2_read_concurrency`) and\n [`decentralized_counters`](`m:ets#new_2_decentralized_counters`). You\n typically want to combine `write_concurrency` with `read_concurrency` when\n large concurrent read bursts and large concurrent write bursts are common; for\n more information, see option\n [`read_concurrency`](`m:ets#new_2_read_concurrency`). It is almost always a\n good idea to combine the `write_concurrency` option with the\n [`decentralized_counters`](`m:ets#new_2_decentralized_counters`) option.\n\n Notice that this option does not change any guarantees about\n [atomicity and isolation](`m:ets#module-concurrency`). Functions that makes such\n promises over many objects (like `insert/2`) gain less (or nothing) from this\n option.\n\n The memory consumption inflicted by both `write_concurrency` and\n `read_concurrency` is a constant overhead per table for `set`, `bag` and\n `duplicate_bag` when the `true` alternative for the `write_concurrency` option\n is not used. For all tables with the `auto` alternative and `ordered_set`\n tables with `true` alternative the memory overhead depends on the amount of\n actual detected concurrency during runtime. The memory overhead can be\n especially large when both `write_concurrency` and `read_concurrency` are\n combined.\n\n > #### Note {: .info }\n >\n > Prior to stdlib-3.7 (OTP-22.0) `write_concurrency` had no effect on\n > `ordered_set`.\n\n > #### Note {: .info }\n >\n > The `auto` alternative for the `write_concurrency` option is only available\n > in OTP-25.0 and above.\n\n [](){: #new_2_read_concurrency }\n\n- **`{read_concurrency,boolean()}`**(Since OTP R14B) \n Performance tuning. Defaults to `false`. When set to `true`, the table is\n optimized for concurrent read operations. When this option is enabled read\n operations become much cheaper; especially on systems with multiple physical\n processors. However, switching between read and write operations becomes more\n expensive.\n\n You typically want to enable this option when concurrent read operations are\n much more frequent than write operations, or when concurrent reads and writes\n comes in large read and write bursts (that is, many reads not interrupted by\n writes, and many writes not interrupted by reads).\n\n You typically do _not_ want to enable this option when the common access\n pattern is a few read operations interleaved with a few write operations\n repeatedly. In this case, you would get a performance degradation by enabling\n this option.\n\n Option `read_concurrency` can be combined with option\n [`write_concurrency`](`m:ets#new_2_write_concurrency`). You typically want to\n combine these when large concurrent read bursts and large concurrent write\n bursts are common.\n\n [](){: #new_2_decentralized_counters }\n\n- **`{decentralized_counters,boolean()}`**(Since OTP 23.0) \n Performance tuning. Defaults to `true` for all tables with the\n `write_concurrency` option set to `auto`. For tables of type `ordered_set` the\n option also defaults to true when the `write_concurrency` option is set to\n `true`. The option defaults to `false` for all other configurations. This\n option has no effect if the `write_concurrency` option is set to `false`.\n\n When this option is set to `true`, the table is optimized for frequent\n concurrent calls to operations that modify the tables size and/or its memory\n consumption (e.g., `insert/2` and `delete/2`). The drawback is that calls to\n `info/1` and `info/2` with `size` or `memory` as the second argument can get\n much slower when the `decentralized_counters` option is turned on.\n\n When this option is enabled the counters for the table size and memory\n consumption are distributed over several cache lines and the scheduling\n threads are mapped to one of those cache lines. The `erl` option\n [`+dcg`](`e:erts:erl_cmd.md#%2Bdcg`) can be used to control the number of\n cache lines that the counters are distributed over.\n\n [](){: #new_2_compressed }\n\n- **`compressed`**(Since OTP R14B01) \n If this option is present, the table data is stored in a more compact format\n to consume less memory. However, it will make table operations slower.\n Especially operations that need to inspect entire objects, such as `match` and\n `select`, get much slower. The key element is not compressed.","title":"ets.new/2","ref":"ets.html#new/2"},{"type":"function","doc":"Returns the next key `Key2`, following key `Key1` in table `Table`. For table\ntype `ordered_set`, the next key in Erlang term order is returned. For other\ntable types, the next key according to the internal order of the table is\nreturned. If no next key exists, `'$end_of_table'` is returned.\n\nTo find the first key in the table, use `first/1`.\n\nUnless a table of type `set`, `bag`, or `duplicate_bag` is fixated using\n`safe_fixtable/2`, a call to [`next/2`](`next/2`) will fail if `Key1` no longer\nexists in the table. For table type `ordered_set`, the function always returns\nthe next key after `Key1` in term order, regardless whether `Key1` ever existed\nin the table.","title":"ets.next/2","ref":"ets.html#next/2"},{"type":"function","doc":"Similar to `next/2` except that it returns the object(s) along with the key\nstored in the table. This is equivalent to doing `next/2` followed by a\n`lookup/2`. If no next key exists, `'$end_of_table'` is returned.\n\nIt can be interleaved with `next/2` during traversal.","title":"ets.next_lookup/2","ref":"ets.html#next_lookup/2"},{"type":"function","doc":"Returns the previous key `Key2`, preceding key `Key1` according to Erlang term\norder in table `Table` of type `ordered_set`. For other table types, the\nfunction is synonymous to `next/2`. If no previous key exists, `'$end_of_table'`\nis returned.\n\nTo find the last key in an `ordered_set` table, use `last/1`.","title":"ets.prev/2","ref":"ets.html#prev/2"},{"type":"function","doc":"Similar to `prev/2` except that it returns the object(s) along with the key\nstored in the table. This is equivalent to doing `prev/2` followed by a\n`lookup/2`. If no previous key exists, `'$end_of_table'` is returned.\n\nIt can be interleaved with `prev/2` during traversal.","title":"ets.prev_lookup/2","ref":"ets.html#prev_lookup/2"},{"type":"function","doc":"Renames the named table `Table` to the new name `Name`. Afterwards, the old name\ncannot be used to access the table. Renaming an unnamed table has no effect.","title":"ets.rename/2","ref":"ets.html#rename/2"},{"type":"function","doc":"Restores an opaque continuation returned by `select/3` or `select/1` if the\ncontinuation has passed through external term format (been sent between nodes or\nstored on disk).\n\nThe reason for this function is that continuation terms contain compiled match\nspecifications and may therefore be invalidated if converted to external term\nformat. Given that the original match specification is kept intact, the\ncontinuation can be restored, meaning it can once again be used in subsequent\n[`select/1`](`select/1`) calls even though it has been stored on disk or on\nanother node.\n\n_Examples:_\n\nThe following sequence of calls may fail:\n\n```erlang\nT=ets:new(x,[]),\n...\nMS = ets:fun2ms(fun({N,_}=A) when (N rem 10) =:= 0 -> A end),\n{_,C} = ets:select(T, MS, 10),\nMaybeBroken = binary_to_term(term_to_binary(C)),\nets:select(MaybeBroken).\n```\n\nThe following sequence works, as the call to\n[`repair_continuation/2`](`repair_continuation/2`) reestablishes the\n`MaybeBroken` continuation.\n\n```erlang\nT=ets:new(x,[]),\n...\nMS = ets:fun2ms(fun({N,_}=A) when (N rem 10) =:= 0 -> A end),\n{_,C} = ets:select(T,MS,10),\nMaybeBroken = binary_to_term(term_to_binary(C)),\nets:select(ets:repair_continuation(MaybeBroken,MS)).\n```\n\n> #### Note {: .info }\n>\n> This function is rarely needed in application code. It is used by Mnesia to\n> provide distributed [`select/3`](`select/3`) and [`select/1`](`select/1`)\n> sequences. A normal application would either use Mnesia or keep the\n> continuation from being converted to external format.\n>\n> The actual behavior of compiled match specifications when recreated from\n> external format has changed and may change in future releases, but this\n> interface remains for backward compatibility. See `is_compiled_ms/1`.","title":"ets.repair_continuation/2","ref":"ets.html#repair_continuation/2"},{"type":"function","doc":"Fixes a table of type `set`, `bag`, or `duplicate_bag` for\n[safe traversal](`m:ets#traversal`) using `first/1` & `next/2`, `match/3` &\n`match/1`, `match_object/3` & `match_object/1`, or `select/3` & `select/1`.\n\nA process fixes a table by calling\n[`safe_fixtable(Table, true)`](`safe_fixtable/2`). The table remains fixed until\nthe process releases it by calling\n[`safe_fixtable(Table, false)`](`safe_fixtable/2`), or until the process\nterminates.\n\nIf many processes fix a table, the table remains fixed until all processes have\nreleased it (or terminated). A reference counter is kept on a per process basis,\nand N consecutive fixes requires N releases to release the table.\n\nWhen a table is fixed, a sequence of `first/1` and `next/2` calls are guaranteed\nto succeed even if keys are removed during the traversal. The keys for objects\ninserted or deleted during a traversal may or may not be returned by\n[`next/2`](`next/2`) depending on the ordering of keys within the table and if\nthe key exists at the time [`next/2`](`next/2`) is called.\n\n_Example:_\n\n```erlang\nclean_all_with_value(Table,X) ->\n safe_fixtable(Table,true),\n clean_all_with_value(Table,X,ets:first(Table)),\n safe_fixtable(Table,false).\n\nclean_all_with_value(Table,X,'$end_of_table') ->\n true;\nclean_all_with_value(Table,X,Key) ->\n case ets:lookup(Table,Key) of\n [{Key,X}] ->\n ets:delete(Table,Key);\n _ ->\n true\n end,\n clean_all_with_value(Table,X,ets:next(Table,Key)).\n```\n\nNotice that deleted objects are not freed from a fixed table until it has been\nreleased. If a process fixes a table but never releases it, the memory used by\nthe deleted objects is never freed. The performance of operations on the table\nalso degrades significantly.\n\nTo retrieve information about which processes have fixed which tables, use\n[`info(Table, safe_fixed_monotonic_time)`](`m:ets#info_2_safe_fixed_monotonic_time`).\nA system with many processes fixing tables can need a monitor that sends alarms\nwhen tables have been fixed for too long.\n\nNotice that [`safe_fixtable/2`](`safe_fixtable/2`) is not necessary for table\ntype `ordered_set` and for traversals done by a single ETS function call, like\n`select/2`.","title":"ets.safe_fixtable/2","ref":"ets.html#safe_fixtable/2"},{"type":"function","doc":"Continues a match started with `select/3`. The next chunk of the size specified\nin the initial [`select/3`](`select/3`) call is returned together with a new\n`Continuation`, which can be used in subsequent calls to this function.\n\nWhen there are no more objects in the table, `'$end_of_table'` is returned.","title":"ets.select/1","ref":"ets.html#select/1"},{"type":"function","doc":"Matches the objects in table `Table` using a\n[match specification](`m:ets#match_spec`). This is a more general call than\n`match/2` and `match_object/2` calls. In its simplest form, the match\nspecification is as follows:\n\n```text\nMatchSpec = [MatchFunction]\nMatchFunction = {MatchHead, [Guard], [Result]}\nMatchHead = \"Pattern as in ets:match\"\nGuard = {\"Guardtest name\", ...}\nResult = \"Term construct\"\n```\n\nThis means that the match specification is always a list of one or more tuples\n(of arity 3). The first element of the tuple is to be a pattern as described in\n`match/2`. The second element of the tuple is to be a list of 0 or more guard\ntests (described below). The third element of the tuple is to be a list\ncontaining a description of the value to return. In almost all normal cases, the\nlist contains exactly one term that fully describes the value to return for each\nobject.\n\nThe return value is constructed using the \"match variables\" bound in `MatchHead`\nor using the special match variables `'$_'` (the whole matching object) and\n`'$$'` (all match variables in a list), so that the following\n[`match/2`](`match/2`) expression:\n\n```text\nets:match(Table,{'$1','$2','$3'})\n```\n\nis exactly equivalent to:\n\n```text\nets:select(Table,[{{'$1','$2','$3'},[],['$$']}])\n```\n\nAnd that the following [`match_object/2`](`match_object/2`) call:\n\n```text\nets:match_object(Table,{'$1','$2','$1'})\n```\n\nis exactly equivalent to\n\n```text\nets:select(Table,[{{'$1','$2','$1'},[],['$_']}])\n```\n\nComposite terms can be constructed in the `Result` part either by simply writing\na list, so that the following code:\n\n```text\nets:select(Table,[{{'$1','$2','$3'},[],['$$']}])\n```\n\ngives the same output as:\n\n```text\nets:select(Table,[{{'$1','$2','$3'},[],[['$1','$2','$3']]}])\n```\n\nThat is, all the bound variables in the match head as a list. If tuples are to\nbe constructed, one has to write a tuple of arity 1 where the single element in\nthe tuple is the tuple one wants to construct (as an ordinary tuple can be\nmistaken for a `Guard`).\n\nTherefore the following call:\n\n```text\nets:select(Table,[{{'$1','$2','$1'},[],['$_']}])\n```\n\ngives the same output as:\n\n```erlang\nets:select(Table,[{{'$1','$2','$1'},[],[{{'$1','$2','$3'}}]}])\n```\n\nThis syntax is equivalent to the syntax used in the trace patterns (see the\n`m:dbg`) module in Runtime_Tools.\n\nThe `Guard`s are constructed as tuples, where the first element is the test name\nand the remaining elements are the test parameters. To check for a specific type\n(say a list) of the element bound to the match variable `'$1'`, one would write\nthe test as `{is_list, '$1'}`. If the test fails, the object in the table does\nnot match and the next `MatchFunction` (if any) is tried. Most guard tests\npresent in Erlang can be used, but only the new versions prefixed `is_` are\nallowed (`is_float`, `is_atom`, and so on).\n\nThe `Guard` section can also contain logic and arithmetic operations, which are\nwritten with the same syntax as the guard tests (prefix notation), so that the\nfollowing guard test written in Erlang:\n\n```text\nis_integer(X), is_integer(Y), X + Y < 4711\n```\n\nis expressed as follows (`X` replaced with `'$1'` and `Y` with `'$2'`):\n\n```text\n[{is_integer, '$1'}, {is_integer, '$2'}, {'<', {'+', '$1', '$2'}, 4711}]\n```\n\nFor tables of type `ordered_set`, objects are visited in the same order as in a\n`first`/`next` traversal. This means that the match specification is executed\nagainst objects with keys in the `first`/`next` order and the corresponding\nresult list is in the order of that execution.","title":"ets.select/2","ref":"ets.html#select/2"},{"type":"function","doc":"Works like `select/2`, but only returns a limited (`Limit`) number of matching\nobjects. Term `Continuation` can then be used in subsequent calls to `select/1`\nto get the next chunk of matching objects. This is a space-efficient way to work\non objects in a table, which is still faster than traversing the table object by\nobject using `first/1` and `next/2`.\n\nIf the table is empty, `'$end_of_table'` is returned.\n\nUse `safe_fixtable/2` to guarantee [safe traversal](`m:ets#traversal`) for\nsubsequent calls to `select/1`.","title":"ets.select/3","ref":"ets.html#select/3"},{"type":"function","doc":"Matches the objects in table `Table` using a\n[match specification](`m:ets#match_spec`). If and only if the match specification\nreturns `true` for an object, that object is considered a match and is counted.\nFor any other result from the match specification the object is not considered a\nmatch and is therefore not counted.\n\nThe function returns the number of objects matched.","title":"ets.select_count/2","ref":"ets.html#select_count/2"},{"type":"function","doc":"Matches the objects in table `Table` using a\n[match specification](`m:ets#match_spec`). If and only if the match\nspecification returns `true` for an object, that object is removed from the\ntable. For any other result from the match specification the object is\nretained. This is a more general function than `match_delete/2`.\n\nThe function returns the number of objects deleted from the table.\n\n> #### Note {: .info }\n>\n> The match specification has to return the atom `true` if the object is to be\n> deleted. No other return value gets the object deleted. So one cannot use the\n> same match specification for looking up elements as for deleting them.","title":"ets.select_delete/2","ref":"ets.html#select_delete/2"},{"type":"function","doc":"Matches the objects in the table `Table` using a\n[match specification](`m:ets#match_spec`). For each matched object, the existing\nobject is replaced with the match specification result.\n\nThe match-and-replace operation for each individual object is guaranteed to be\n[atomic and isolated](`m:ets#module-concurrency`). The `select_replace` table traversal\nas a whole, like all other select functions, does not give such guarantees.\n\nThe match specification must be guaranteed to _retain the key_ of any matched\nobject. If not, `select_replace` will fail with `badarg` without updating any\nobjects.\n\nFor the moment, due to performance and semantic constraints, tables of type\n`bag` are not yet supported.\n\nThe function returns the total number of replaced objects.\n\n_Example_\n\nFor all 2-tuples with a list in second position, add atom `'marker'` first in\nthe list:\n\n```erlang\n1> T = ets:new(x,[]), ets:insert(T, {key, [1, 2, 3]}).\ntrue\n2> MS = ets:fun2ms(fun({K, L}) when is_list(L) -> {K, [marker | L]} end).\n[{{'$1','$2'},[{is_list,'$2'}],[{{'$1',[marker|'$2']}}]}]\n3> ets:select_replace(T, MS).\n1\n4> ets:tab2list(T).\n[{key,[marker,1,2,3]}]\n```\n\nA generic single object compare-and-swap operation:\n\n```erlang\n[Old] = ets:lookup(T, Key),\nNew = update_object(Old),\nSuccess = (1 =:= ets:select_replace(T, [{Old, [], [{const, New}]}])),\n```","title":"ets.select_replace/2","ref":"ets.html#select_replace/2"},{"type":"function","doc":"Continues a match started with `select_reverse/3`. For tables of type\n`ordered_set`, the traversal of the table continues to objects with keys earlier\nin the Erlang term order. The returned list also contains objects with keys in\nreverse order. For all other table types, the behavior is exactly that of\n`select/1`.\n\n_Example:_\n\n```erlang\n1> T = ets:new(x,[ordered_set]).\n2> [ ets:insert(T,{N}) || N <- lists:seq(1,10) ].\n...\n3> {R0,C0} = ets:select_reverse(T,[{'_',[],['$_']}],4).\n...\n4> R0.\n[{10},{9},{8},{7}]\n5> {R1,C1} = ets:select_reverse(C0).\n...\n6> R1.\n[{6},{5},{4},{3}]\n7> {R2,C2} = ets:select_reverse(C1).\n...\n8> R2.\n[{2},{1}]\n9> '$end_of_table' = ets:select_reverse(C2).\n...\n```","title":"ets.select_reverse/1","ref":"ets.html#select_reverse/1"},{"type":"function","doc":"Works like `select/2`, but returns the list in reverse order for table type\n`ordered_set`. For all other table types, the return value is identical to that\nof [`select/2`](`select/2`).","title":"ets.select_reverse/2","ref":"ets.html#select_reverse/2"},{"type":"function","doc":"Works like `select/3`, but for table type `ordered_set` traversing is done\nstarting at the last object in Erlang term order and moves to the first. For all\nother table types, the return value is identical to that of\n[`select/3`](`select/3`).\n\nNotice that this is _not_ equivalent to reversing the result list of a\n[`select/3`](`select/3`) call, as the result list is not only reversed, but also\ncontains the last `Limit` matching objects in the table, not the first.","title":"ets.select_reverse/3","ref":"ets.html#select_reverse/3"},{"type":"function","doc":"Sets table options. The only allowed option to be set after the table has been\ncreated is [`heir`](`m:ets#heir`). The calling process must be the table owner.","title":"ets.setopts/2","ref":"ets.html#setopts/2"},{"type":"function","doc":"This function is mostly for debugging purposes, normally `first`/`next` or\n`last`/`prev` are to be used instead.\n\nReturns all objects in slot `I` of table `Table`. A table can be traversed by\nrepeatedly calling the function, starting with the first slot `I=0` and ending\nwhen `'$end_of_table'` is returned. If argument `I` is out of range, the\nfunction fails with reason `badarg`.\n\nUnless a table of type `set`, `bag`, or `duplicate_bag` is protected using\n`safe_fixtable/2`, a traversal can fail if concurrent updates are made to the\ntable. For table type `ordered_set`, the function returns a list containing\nobject `I` in Erlang term order.","title":"ets.slot/2","ref":"ets.html#slot/2"},{"type":"function","doc":"Dumps table `Table` to file `Filename`.\n\nEquivalent to [`tab2file(Table, Filename,[])`](`tab2file/3`)","title":"ets.tab2file/2","ref":"ets.html#tab2file/2"},{"type":"function","doc":"Dumps table `Table` to file `Filename`.\n\nWhen dumping the table, some information about the table is dumped to a header\nat the beginning of the dump. This information contains data about the table\ntype, name, protection, size, version, and if it is a named table. It also\ncontains notes about what extended information is added to the file, which can\nbe a count of the objects in the file or a MD5 sum of the header and records in\nthe file.\n\nThe size field in the header might not correspond to the number of records in\nthe file if the table is public and records are added or removed from the table\nduring dumping. Public tables updated during dump, and that one wants to verify\nwhen reading, needs at least one field of extended information for the read\nverification process to be reliable later.\n\nOption `extended_info` specifies what extra information is written to the table\ndump:\n\n- **`object_count`** - The number of objects written to the file is noted in the\n file footer, so file truncation can be verified even if the file was updated\n during dump.\n\n- **`md5sum`** - The header and objects in the file are checksummed using the\n built-in MD5 functions. The MD5 sum of all objects is written in the file\n footer, so that verification while reading detects the slightest bitflip in\n the file data. Using this costs a fair amount of CPU time.\n\nWhenever option `extended_info` is used, it results in a file not readable by\nversions of ETS before that in STDLIB 1.15.1\n\nIf option `sync` is set to `true`, it ensures that the content of the file is\nwritten to the disk before `tab2file` returns. Defaults to `{sync, false}`.","title":"ets.tab2file/3","ref":"ets.html#tab2file/3"},{"type":"function","doc":"Returns a list of all objects in table `Table`.","title":"ets.tab2list/1","ref":"ets.html#tab2list/1"},{"type":"function","doc":"Returns information about the table dumped to file by `tab2file/2` or\n`tab2file/3`.\n\nThe following items are returned:\n\n- **`name`** - The name of the dumped table. If the table was a named table, a\n table with the same name cannot exist when the table is loaded from file with\n `file2tab/2`. If the table is not saved as a named table, this field has no\n significance when loading the table from file.\n\n- **`type`** - The ETS type of the dumped table (that is, `set`, `bag`,\n `duplicate_bag`, or `ordered_set`). This type is used when loading the table\n again.\n\n- **`protection`** - The protection of the dumped table (that is, `private`,\n `protected`, or `public`). A table loaded from the file gets the same\n protection.\n\n- **`named_table`** - `true` if the table was a named table when dumped to file,\n otherwise `false`. Notice that when a named table is loaded from a file, there\n cannot exist a table in the system with the same name.\n\n- **`keypos`** - The `keypos` of the table dumped to file, which is used when\n loading the table again.\n\n- **`size`** - The number of objects in the table when the table dump to file\n started. For a `public` table, this number does not need to correspond to the\n number of objects saved to the file, as objects can have been added or deleted\n by another process during table dump.\n\n- **`extended_info`** - The extended information written in the file footer to\n allow stronger verification during table loading from file, as specified to\n `tab2file/3`. Notice that this function only tells _which_ information is\n present, not the values in the file footer. The value is a list containing one\n or more of the atoms `object_count` and `md5sum`.\n\n- **`version`** - A tuple `{Major,Minor}` containing the major and minor version\n of the file format for ETS table dumps. This version field was added beginning\n with STDLIB 1.5.1. Files dumped with older versions return `{0,0}` in this\n field.\n\nAn error is returned if the file is inaccessible, badly damaged, or not produced\nwith `tab2file/2` or `tab2file/3`.","title":"ets.tabfile_info/1","ref":"ets.html#tabfile_info/1"},{"type":"function","doc":"","title":"ets.table/1","ref":"ets.html#table/1"},{"type":"function","doc":"Returns a Query List Comprehension (QLC) query handle. The `m:qlc` module\nprovides a query language aimed mainly at Mnesia, but ETS tables, Dets tables,\nand lists are also recognized by QLC as sources of data. Calling `table/1,2` is\nthe means to make the ETS table `Table` usable to QLC.\n\nWhen there are only simple restrictions on the key position, QLC uses `lookup/2`\nto look up the keys. When that is not possible, the whole table is traversed.\nOption `traverse` determines how this is done:\n\n- **`first_next`** - The table is traversed one key at a time by calling\n `first/1` and `next/2`.\n\n- **`last_prev`** - The table is traversed one key at a time by calling `last/1`\n and `prev/2`.\n\n- **`select`** - The table is traversed by calling `select/3` and `select/1`.\n Option `n_objects` determines the number of objects returned (the third\n argument of [`select/3`](`select/3`)); the default is to return `100` objects\n at a time. The [match specification](`m:ets#match_spec`) (the second argument\n of [`select/3`](`select/3`)) is assembled by QLC: simple filters are\n translated into equivalent match specifications while more complicated filters\n must be applied to all objects returned by [`select/3`](`select/3`) given a\n match specification that matches all objects.\n\n- **`{select, MatchSpec}`** - As for `select`, the table is traversed by calling\n `select/3` and `select/1`. The difference is that the match specification is\n explicitly specified. This is how to state match specifications that cannot\n easily be expressed within the syntax provided by QLC.\n\n_Examples:_\n\nAn explicit match specification is here used to traverse the table:\n\n```erlang\n9> true = ets:insert(Table = ets:new(t, []), [{1,a},{2,b},{3,c},{4,d}]),\nMS = ets:fun2ms(fun({X,Y}) when (X > 1) or (X < 5) -> {Y} end),\nQH1 = ets:table(Table, [{traverse, {select, MS}}]).\n```\n\nAn example with an implicit match specification:\n\n```erlang\n10> QH2 = qlc:q([{Y} || {X,Y} <- ets:table(Table), (X > 1) or (X < 5)]).\n```\n\nThe latter example is equivalent to the former, which can be verified using\nfunction `qlc:info/1`:\n\n```erlang\n11> qlc:info(QH1) =:= qlc:info(QH2).\ntrue\n```\n\n`qlc:info/1` returns information about a query handle, and in this case\nidentical information is returned for the two query handles.","title":"ets.table/2","ref":"ets.html#table/2"},{"type":"function","doc":"Returns and removes a list of all objects with key `Key` in table `Table`.\n\nThe specified `Key` is used to identify the object by either _comparing equal_\nthe key of an object in an `ordered_set` table, or _matching_ in other types of\ntables (for details on the difference, see `lookup/2` and `new/2`).","title":"ets.take/2","ref":"ets.html#take/2"},{"type":"function","doc":"This function is a utility to test a [match specification](`m:ets#match_spec`)\nused in calls to `select/2`. The function both tests `MatchSpec` for \"syntactic\"\ncorrectness and runs the match specification against object `Tuple`.\n\nIf the match specification is syntactically correct, the function either returns\n`{ok,Result}`, where `Result` is what would have been the result in a real\n[`select/2`](`select/2`) call, or `false` if the match specification does not\nmatch object `Tuple`.\n\nIf the match specification contains errors, tuple `{error, Errors}` is returned,\nwhere `Errors` is a list of natural language descriptions of what was wrong with\nthe match specification.\n\nThis is a useful debugging and test tool, especially when writing complicated\n[`select/2`](`select/2`) calls.\n\nSee also: `erlang:match_spec_test/3`.","title":"ets.test_ms/2","ref":"ets.html#test_ms/2"},{"type":"function","doc":"Fills an already created/opened Dets table with the objects in the already\nopened ETS table named `Table`. The Dets table is emptied before the objects are\ninserted.","title":"ets.to_dets/2","ref":"ets.html#to_dets/2"},{"type":"function","doc":"","title":"ets.update_counter/3","ref":"ets.html#update_counter/3"},{"type":"function","doc":"This function provides an efficient way to update one or more counters, without\nthe trouble of having to look up an object, update the object by incrementing an\nelement, and insert the resulting object into the table again. The operation is\nguaranteed to be [atomic and isolated](`m:ets#module-concurrency`).\n\nThis function destructively updates the object with key `Key` in table `Table`\nby adding `Incr` to the element at position `Pos`. The new counter value is\nreturned. If no position is specified, the element directly following key\n(` +1`) is updated.\n\nIf a `Threshold` is specified, the counter is reset to value `SetValue` if the\nfollowing conditions occur:\n\n- `Incr` is not negative (`>= 0`) and the result would be greater than (`>`)\n `Threshold`.\n- `Incr` is negative (`< 0`) and the result would be less than (`<`)\n `Threshold`.\n\nA list of `UpdateOp` can be supplied to do many update operations within the\nobject. The operations are carried out in the order specified in the list. If\nthe same counter position occurs more than once in the list, the corresponding\ncounter is thus updated many times, each time based on the previous result. The\nreturn value is a list of the new counter values from each update operation in\nthe same order as in the operation list. If an empty list is specified, nothing\nis updated and an empty list is returned. If the function fails, no updates are\ndone.\n\nThe specified `Key` is used to identify the object by either _matching_ the key\nof an object in a `set` table, or _compare equal_ to the key of an object in an\n`ordered_set` table (for details on the difference, see `lookup/2` and `new/2`).\n\nIf a default object `Default` is specified, it is used as the object to be\nupdated if the key is missing from the table. The value in place of the key is\nignored and replaced by the proper key value. The return value is as if the\ndefault object had not been used, that is, a single updated element or a list of\nthem.\n\nThe function fails with reason `badarg` in the following situations:\n\n- The table type is not `set` or `ordered_set`.\n- No object with the correct key exists and no default object was supplied.\n- The object has the wrong arity.\n- The default object arity is smaller than ` `.\n- Any field from the default object that is updated is not an integer.\n- The element to update is not an integer.\n- The element to update is also the key.\n- Any of `Pos`, `Incr`, `Threshold`, or `SetValue` is not an integer.","title":"ets.update_counter/4","ref":"ets.html#update_counter/4"},{"type":"function","doc":"","title":"ets.update_element/3","ref":"ets.html#update_element/3"},{"type":"function","doc":"This function provides an efficient way to update one or more elements within an\nobject, without the trouble of having to look up, update, and write back the\nentire object.\n\nThis function destructively updates the object with key `Key` in table `Table`.\nThe element at position `Pos` is given the value `Value`.\n\nA list of `{Pos,Value}` can be supplied to update many elements within the same\nobject. If the same position occurs more than once in the list, the last value\nin the list is written. If the list is empty or the function fails, no updates\nare done. The function is also atomic in the sense that other processes can\nnever see any intermediate results.\n\nReturns `true` if an object with key `Key` is found, otherwise `false`.\n\nThe specified `Key` is used to identify the object by either _matching_ the key\nof an object in a `set` table, or _compare equal_ to the key of an object in an\n`ordered_set` table (for details on the difference, see `lookup/2` and `new/2`).\n\nIf a default object `Default` is specified, it is used as the object to be\nupdated if the key is missing from the table. The value in place of the key is\nignored and replaced by the proper key value.\n\nThe function fails with reason `badarg` in the following situations:\n\n- The table type is not `set` or `ordered_set`.\n- `Pos` < 1.\n- `Pos` > object arity.\n- The default object arity is smaller than ` `.\n- The element to update is also the key.","title":"ets.update_element/4","ref":"ets.html#update_element/4"},{"type":"function","doc":"This function returns the `t:tid/0` of the named table identified by\n`TableName`, or `undefined` if no such table exists. The `t:tid/0` can be used\nin place of the table name in all operations, which is slightly faster since the\nname does not have to be resolved on each call.\n\nIf the table is deleted, the `t:tid/0` will be invalid even if another named\ntable is created with the same name.","title":"ets.whereis/1","ref":"ets.html#whereis/1"},{"type":"type","doc":"","title":"ets.comp_match_spec/0","ref":"ets.html#t:comp_match_spec/0"},{"type":"opaque","doc":"A compiled match specification.","title":"ets.compiled_match_spec/0","ref":"ets.html#t:compiled_match_spec/0"},{"type":"type","doc":"Opaque continuation used by [`select/1,3`](`select/1`),\n[`select_reverse/1,3`](`select_reverse/1`), [`match/1,3`](`match/1`), and\n[`match_object/1,3`](`match_object/1`).","title":"ets.continuation/0","ref":"ets.html#t:continuation/0"},{"type":"type","doc":"","title":"ets.match_pattern/0","ref":"ets.html#t:match_pattern/0"},{"type":"type","doc":"A match specification, see [Match Specifications](`m:ets#match_spec`).","title":"ets.match_spec/0","ref":"ets.html#t:match_spec/0"},{"type":"type","doc":"","title":"ets.tab/0","ref":"ets.html#t:tab/0"},{"type":"type","doc":"","title":"ets.table/0","ref":"ets.html#t:table/0"},{"type":"type","doc":"","title":"ets.table_access/0","ref":"ets.html#t:table_access/0"},{"type":"type","doc":"","title":"ets.table_type/0","ref":"ets.html#t:table_type/0"},{"type":"opaque","doc":"A table identifier, as returned by `new/2`.","title":"ets.tid/0","ref":"ets.html#t:tid/0"},{"type":"module","doc":"Sets represented by general balanced trees.\n\nThis module provides ordered sets using Prof. Arne Andersson's General Balanced\nTrees. Ordered sets can be much more efficient than using ordered lists, for\nlarger sets, but depends on the application.\n\nThe data representing a set as used by this module is to be regarded as opaque\nby other modules. In abstract terms, the representation is a composite type of\nexisting Erlang terms. See note on\n[data types](`e:system:data_types.md#no_user_types`). Any code assuming\nknowledge of the format is running on thin ice.\n\nThis module considers two elements as different if and only if they do not\ncompare equal (`==`).","title":"gb_sets","ref":"gb_sets.html"},{"type":"module","doc":"The complexity on set operations is bounded by either _O(|S|)_ or _O(|T| _\nlog(|S|))\\*, where S is the largest given set, depending on which is fastest for\nany particular function call. For operating on sets of almost equal size, this\nimplementation is about 3 times slower than using ordered-list sets directly.\nFor sets of very different sizes, however, this solution can be arbitrarily much\nfaster; in practical cases, often 10-100 times. This implementation is\nparticularly suited for accumulating elements a few at a time, building up a\nlarge set (> 100-200 elements), and repeatedly testing for membership in the\ncurrent set.\n\nAs with normal tree structures, lookup (membership testing), insertion, and\ndeletion have logarithmic complexity.","title":"Complexity Note - gb_sets","ref":"gb_sets.html#module-complexity-note"},{"type":"module","doc":"See the [Compatibility Section in the `sets` module](`m:sets#module-compatibility`)\nfor information about the compatibility of the different implementations of sets\nin the Standard Library.","title":"Compatibility - gb_sets","ref":"gb_sets.html#module-compatibility"},{"type":"module","doc":"`m:gb_trees`, `m:ordsets`, `m:sets`","title":"See Also - gb_sets","ref":"gb_sets.html#module-see-also"},{"type":"function","doc":"","title":"gb_sets.add/2","ref":"gb_sets.html#add/2"},{"type":"function","doc":"Returns a new set formed from `Set1` with `Element` inserted. If `Element` is\nalready an element in `Set1`, nothing is changed.","title":"gb_sets.add_element/2","ref":"gb_sets.html#add_element/2"},{"type":"function","doc":"Rebalances the tree representation of `Set1`.\n\nNotice that this is rarely necessary, but can be motivated when a large number of\nelements have been deleted from the tree without further insertions. Rebalancing\n can then be forced to minimise lookup times, as deletion does not rebalance the\ntree.","title":"gb_sets.balance/1","ref":"gb_sets.html#balance/1"},{"type":"function","doc":"","title":"gb_sets.del_element/2","ref":"gb_sets.html#del_element/2"},{"type":"function","doc":"Returns a new set formed from `Set1` with `Element` removed. Assumes that\n`Element` is present in `Set1`.","title":"gb_sets.delete/2","ref":"gb_sets.html#delete/2"},{"type":"function","doc":"Returns a new set formed from `Set1` with `Element` removed. If `Element` is not\nan element in `Set1`, nothing is changed.","title":"gb_sets.delete_any/2","ref":"gb_sets.html#delete_any/2"},{"type":"function","doc":"","title":"gb_sets.difference/2","ref":"gb_sets.html#difference/2"},{"type":"function","doc":"Returns a new empty set.","title":"gb_sets.empty/0","ref":"gb_sets.html#empty/0"},{"type":"function","doc":"Filters elements in `Set1` using predicate function `Pred`.","title":"gb_sets.filter/2","ref":"gb_sets.html#filter/2"},{"type":"function","doc":"Filters and maps elements in `Set1` using function `Fun`.","title":"gb_sets.filtermap/2","ref":"gb_sets.html#filtermap/2"},{"type":"function","doc":"Folds `Function` over every element in `Set` returning the final value of the\naccumulator.","title":"gb_sets.fold/3","ref":"gb_sets.html#fold/3"},{"type":"function","doc":"Returns a set of the elements in `List`, where `List` can be unordered and\ncontain duplicates.","title":"gb_sets.from_list/1","ref":"gb_sets.html#from_list/1"},{"type":"function","doc":"Turns an ordered-set list `List` into a set. The list must not contain\nduplicates.","title":"gb_sets.from_ordset/1","ref":"gb_sets.html#from_ordset/1"},{"type":"function","doc":"Returns a new set formed from `Set1` with `Element` inserted. Assumes that\n`Element` is not present in `Set1`.","title":"gb_sets.insert/2","ref":"gb_sets.html#insert/2"},{"type":"function","doc":"Returns the intersection of the non-empty list of sets.","title":"gb_sets.intersection/1","ref":"gb_sets.html#intersection/1"},{"type":"function","doc":"Returns the intersection of `Set1` and `Set2`.","title":"gb_sets.intersection/2","ref":"gb_sets.html#intersection/2"},{"type":"function","doc":"Returns `true` if `Set1` and `Set2` are disjoint (have no elements in common),\notherwise `false`.","title":"gb_sets.is_disjoint/2","ref":"gb_sets.html#is_disjoint/2"},{"type":"function","doc":"","title":"gb_sets.is_element/2","ref":"gb_sets.html#is_element/2"},{"type":"function","doc":"Returns `true` if `Set` is an empty set, otherwise `false`.","title":"gb_sets.is_empty/1","ref":"gb_sets.html#is_empty/1"},{"type":"function","doc":"Returns `true` if `Set1` and `Set2` are equal, that is when every element of one\nset is also a member of the respective other set, otherwise `false`.","title":"gb_sets.is_equal/2","ref":"gb_sets.html#is_equal/2"},{"type":"function","doc":"Returns `true` if `Element` is an member of `Set`, otherwise `false`.","title":"gb_sets.is_member/2","ref":"gb_sets.html#is_member/2"},{"type":"function","doc":"Returns `true` if `Term` appears to be a set, otherwise `false`. This function\nwill return `true` for any term that coincides with the representation of a\n`gb_set`, while not really being a `gb_set`, thus it might return false positive\nresults. See also note on [data types](`e:system:data_types.md#no_user_types`).","title":"gb_sets.is_set/1","ref":"gb_sets.html#is_set/1"},{"type":"function","doc":"Returns `true` when every element of `Set1` is also a member of `Set2`,\notherwise `false`.","title":"gb_sets.is_subset/2","ref":"gb_sets.html#is_subset/2"},{"type":"function","doc":"Returns an iterator that can be used for traversing the entries of `Set`; see\n`next/1`.\n\nEquivalent to [`iterator(Set, ordered)`](`iterator/2`).","title":"gb_sets.iterator/1","ref":"gb_sets.html#iterator/1"},{"type":"function","doc":"Returns an iterator that can be used for traversing the entries of `Set` in\neither `ordered` or `reversed` direction; see `next/1`.\n\nThe implementation of this is very efficient; traversing the whole set using\n[`next/1`](`next/1`) is only slightly slower than getting the list of all\n elements using `to_list/1` and traversing that. The main advantage of the\niterator approach is that it does not require the complete list of all elements\nto be built in memory at one time.","title":"gb_sets.iterator/2","ref":"gb_sets.html#iterator/2"},{"type":"function","doc":"Returns an iterator that can be used for traversing the entries of `Set`; see\n`next/1`. The difference as compared to the iterator returned by `iterator/1` is\nthat the iterator starts with the first element greater than or equal to\n`Element`.\n\nEquivalent to [`iterator_from(Element, Set, ordered)`](`iterator_from/3`).","title":"gb_sets.iterator_from/2","ref":"gb_sets.html#iterator_from/2"},{"type":"function","doc":"Returns an iterator that can be used for traversing the entries of `Set`; see\n`next/1`. The difference as compared to the iterator returned by `iterator/2` is\nthat the iterator starts with the first element next to or equal to `Element`.","title":"gb_sets.iterator_from/3","ref":"gb_sets.html#iterator_from/3"},{"type":"function","doc":"Returns `{found, Element2}`, where `Element2` is the least element strictly\ngreater than `Element1`.\n\nReturns `none` if no such element exists.","title":"gb_sets.larger/2","ref":"gb_sets.html#larger/2"},{"type":"function","doc":"Returns the largest element in `Set`. Assumes that `Set` is not empty.","title":"gb_sets.largest/1","ref":"gb_sets.html#largest/1"},{"type":"function","doc":"Maps elements in `Set1` using mapping function `Fun`.","title":"gb_sets.map/2","ref":"gb_sets.html#map/2"},{"type":"function","doc":"Returns a new empty set.","title":"gb_sets.new/0","ref":"gb_sets.html#new/0"},{"type":"function","doc":"Returns `{Element, Iter2}`, where `Element` is the smallest element referred to\nby iterator `Iter1`, and `Iter2` is the new iterator to be used for traversing\nthe remaining elements, or the atom `none` if no elements remain.","title":"gb_sets.next/1","ref":"gb_sets.html#next/1"},{"type":"function","doc":"Returns a set containing only element `Element`.","title":"gb_sets.singleton/1","ref":"gb_sets.html#singleton/1"},{"type":"function","doc":"Returns the number of elements in `Set`.","title":"gb_sets.size/1","ref":"gb_sets.html#size/1"},{"type":"function","doc":"Returns `{found, Element2}`, where `Element2` is the greatest element strictly\nless than `Element1`.\n\nReturns `none` if no such element exists.","title":"gb_sets.smaller/2","ref":"gb_sets.html#smaller/2"},{"type":"function","doc":"Returns the smallest element in `Set`. Assumes that `Set` is not empty.","title":"gb_sets.smallest/1","ref":"gb_sets.html#smallest/1"},{"type":"function","doc":"Returns only the elements of `Set1` that are not also elements of `Set2`.","title":"gb_sets.subtract/2","ref":"gb_sets.html#subtract/2"},{"type":"function","doc":"Returns `{Element, Set2}`, where `Element` is the largest element in `Set1`, and\n`Set2` is this set with `Element` deleted. Assumes that `Set1` is not empty.","title":"gb_sets.take_largest/1","ref":"gb_sets.html#take_largest/1"},{"type":"function","doc":"Returns `{Element, Set2}`, where `Element` is the smallest element in `Set1`,\nand `Set2` is this set with `Element` deleted. Assumes that `Set1` is not empty.","title":"gb_sets.take_smallest/1","ref":"gb_sets.html#take_smallest/1"},{"type":"function","doc":"Returns the elements of `Set` as a list.","title":"gb_sets.to_list/1","ref":"gb_sets.html#to_list/1"},{"type":"function","doc":"Returns the merged (union) set of the list of sets.","title":"gb_sets.union/1","ref":"gb_sets.html#union/1"},{"type":"function","doc":"Returns the merged (union) set of `Set1` and `Set2`.","title":"gb_sets.union/2","ref":"gb_sets.html#union/2"},{"type":"type","doc":"","title":"gb_sets.iter/0","ref":"gb_sets.html#t:iter/0"},{"type":"opaque","doc":"A general balanced set iterator.","title":"gb_sets.iter/1","ref":"gb_sets.html#t:iter/1"},{"type":"type","doc":"","title":"gb_sets.set/0","ref":"gb_sets.html#t:set/0"},{"type":"opaque","doc":"A general balanced set.","title":"gb_sets.set/1","ref":"gb_sets.html#t:set/1"},{"type":"module","doc":"General balanced trees.\n\nThis module provides Prof. Arne Andersson's General Balanced Trees. These have\nno storage overhead compared to unbalanced binary trees, and their performance\nis better than AVL trees.\n\nThis module considers two keys as different if and only if they do not compare\nequal (`==`).","title":"gb_trees","ref":"gb_trees.html"},{"type":"module","doc":"Trees and iterators are built using opaque data structures that should not be\npattern-matched from outside this module.\n\nThere is no attempt to balance trees after deletions. As deletions do not\nincrease the height of a tree, this should be OK.\n\nThe original balance condition `h(T) <= ceil(c * log(|T|))` has been changed to\nthe similar (but not quite equivalent) condition `2 ^ h(T) <= |T| ^ c`. This\nshould also be OK.","title":"Data Structure - gb_trees","ref":"gb_trees.html#module-data-structure"},{"type":"module","doc":"`m:dict`, `m:gb_sets`","title":"See Also - gb_trees","ref":"gb_trees.html#module-see-also"},{"type":"function","doc":"Rebalances `Tree1`.\n\nNotice that this is rarely necessary, but can be motivated\nwhen many nodes have been deleted from the tree without further insertions.\nRebalancing can then be forced to minimize lookup times, as deletion does not\nrebalance the tree.","title":"gb_trees.balance/1","ref":"gb_trees.html#balance/1"},{"type":"function","doc":"Removes the node with key `Key` from `Tree1` and returns the new tree. Assumes\nthat the key is present in the tree, crashes otherwise.","title":"gb_trees.delete/2","ref":"gb_trees.html#delete/2"},{"type":"function","doc":"Removes the node with key `Key` from `Tree1` if the key is present in the tree,\notherwise does nothing. Returns the new tree.","title":"gb_trees.delete_any/2","ref":"gb_trees.html#delete_any/2"},{"type":"function","doc":"Returns a new empty tree.","title":"gb_trees.empty/0","ref":"gb_trees.html#empty/0"},{"type":"function","doc":"Inserts `Key` with value `Value` into `Tree1` if the key is not present in the\ntree, otherwise updates `Key` to value `Value` in `Tree1`. Returns the new tree.","title":"gb_trees.enter/3","ref":"gb_trees.html#enter/3"},{"type":"function","doc":"Turns an ordered list `List` of key-value tuples into a tree. The list must not\ncontain duplicate keys.","title":"gb_trees.from_orddict/1","ref":"gb_trees.html#from_orddict/1"},{"type":"function","doc":"Retrieves the value stored with `Key` in `Tree`. Assumes that the key is present\nin the tree, crashes otherwise.","title":"gb_trees.get/2","ref":"gb_trees.html#get/2"},{"type":"function","doc":"Inserts `Key` with value `Value` into `Tree1` and returns the new tree. Assumes\nthat the key is not present in the tree, crashes otherwise.","title":"gb_trees.insert/3","ref":"gb_trees.html#insert/3"},{"type":"function","doc":"Returns `true` if `Key` is present in `Tree`, otherwise `false`.","title":"gb_trees.is_defined/2","ref":"gb_trees.html#is_defined/2"},{"type":"function","doc":"Returns `true` if `Tree` is an empty tree, othwewise `false`.","title":"gb_trees.is_empty/1","ref":"gb_trees.html#is_empty/1"},{"type":"function","doc":"Returns an iterator that can be used for traversing the entries of `Tree`; see\n`next/1`.\n\nEquivalent to [`iterator(Tree, ordered)`](`iterator/2`).","title":"gb_trees.iterator/1","ref":"gb_trees.html#iterator/1"},{"type":"function","doc":"Returns an iterator that can be used for traversing the entries of `Tree` in\neither `ordered` or `reversed` direction; see `next/1`.\n\nThe implementation of this is very efficient; traversing the whole tree using\n[`next/1`](`next/1`) is only slightly slower than getting the list of all\nelements using `to_list/1` and traversing that. The main advantage of the\niterator approach is that it does not require the complete list of all elements\nto be built in memory at one time.","title":"gb_trees.iterator/2","ref":"gb_trees.html#iterator/2"},{"type":"function","doc":"Returns an iterator that can be used for traversing the entries of `Tree`; see\n`next/1`. The difference as compared to the iterator returned by `iterator/1` is\nthat the iterator starts with the first key greater than or equal to `Key`.\n\nEquivalent to [`iterator_from(Key, Tree, ordered)`](`iterator_from/3`).","title":"gb_trees.iterator_from/2","ref":"gb_trees.html#iterator_from/2"},{"type":"function","doc":"Returns an iterator that can be used for traversing the entries of `Tree` in\neither `ordered` or `reversed` direction; see `next/1`. The difference as\ncompared to the iterator returned by `iterator/2` is that the iterator starts\nwith the first key next to or equal to `Key`.","title":"gb_trees.iterator_from/3","ref":"gb_trees.html#iterator_from/3"},{"type":"function","doc":"Returns the keys in `Tree` as an ordered list.","title":"gb_trees.keys/1","ref":"gb_trees.html#keys/1"},{"type":"function","doc":"Returns `{Key2, Value}`, where `Key2` is the least key strictly greater than\n`Key1`, `Value` is the value associated with this key.\n\nReturns `none` if no such pair exists.","title":"gb_trees.larger/2","ref":"gb_trees.html#larger/2"},{"type":"function","doc":"Returns `{Key, Value}`, where `Key` is the largest key in `Tree`, and `Value` is\nthe value associated with this key. Assumes that the tree is not empty.","title":"gb_trees.largest/1","ref":"gb_trees.html#largest/1"},{"type":"function","doc":"Looks up `Key` in `Tree`. Returns `{value, Value}`, or `none` if `Key` is not\npresent.","title":"gb_trees.lookup/2","ref":"gb_trees.html#lookup/2"},{"type":"function","doc":"Maps function F(K, V1) -> V2 to all key-value pairs of tree `Tree1`. Returns a\nnew tree `Tree2` with the same set of keys as `Tree1` and the new set of values\n`V2`.","title":"gb_trees.map/2","ref":"gb_trees.html#map/2"},{"type":"function","doc":"Returns `{Key, Value, Iter2}`, where `Key` is the next key referred to by\niterator `Iter1`, and `Iter2` is the new iterator to be used for traversing the\nremaining nodes, or the atom `none` if no nodes remain.","title":"gb_trees.next/1","ref":"gb_trees.html#next/1"},{"type":"function","doc":"Returns the number of nodes in `Tree`.","title":"gb_trees.size/1","ref":"gb_trees.html#size/1"},{"type":"function","doc":"Returns `{Key2, Value}`, where `Key2` is the greatest key strictly less than\n`Key1`, `Value` is the value associated with this key.\n\nReturns `none` if no such pair exists.","title":"gb_trees.smaller/2","ref":"gb_trees.html#smaller/2"},{"type":"function","doc":"Returns `{Key, Value}`, where `Key` is the smallest key in `Tree`, and `Value`\nis the value associated with this key. Assumes that the tree is not empty.","title":"gb_trees.smallest/1","ref":"gb_trees.html#smallest/1"},{"type":"function","doc":"Returns a value `Value` from node with key `Key` and new `Tree2` without the\nnode with this value. Assumes that the node with key is present in the tree,\ncrashes otherwise.","title":"gb_trees.take/2","ref":"gb_trees.html#take/2"},{"type":"function","doc":"Returns a value `Value` from node with key `Key` and new `Tree2` without the\nnode with this value. Returns `error` if the node with the key is not present in\nthe tree.","title":"gb_trees.take_any/2","ref":"gb_trees.html#take_any/2"},{"type":"function","doc":"Returns `{Key, Value, Tree2}`, where `Key` is the largest key in `Tree1`,\n`Value` is the value associated with this key, and `Tree2` is this tree with the\ncorresponding node deleted. Assumes that the tree is not empty.","title":"gb_trees.take_largest/1","ref":"gb_trees.html#take_largest/1"},{"type":"function","doc":"Returns `{Key, Value, Tree2}`, where `Key` is the smallest key in `Tree1`,\n`Value` is the value associated with this key, and `Tree2` is this tree with the\ncorresponding node deleted. Assumes that the tree is not empty.","title":"gb_trees.take_smallest/1","ref":"gb_trees.html#take_smallest/1"},{"type":"function","doc":"Converts a tree into an ordered list of key-value tuples.","title":"gb_trees.to_list/1","ref":"gb_trees.html#to_list/1"},{"type":"function","doc":"Updates `Key` to value `Value` in `Tree1` and returns the new tree. Assumes that\nthe key is present in the tree.","title":"gb_trees.update/3","ref":"gb_trees.html#update/3"},{"type":"function","doc":"Returns the values in `Tree` as an ordered list, sorted by their corresponding\nkeys. Duplicates are not removed.","title":"gb_trees.values/1","ref":"gb_trees.html#values/1"},{"type":"type","doc":"","title":"gb_trees.iter/0","ref":"gb_trees.html#t:iter/0"},{"type":"opaque","doc":"A general balanced tree iterator.","title":"gb_trees.iter/2","ref":"gb_trees.html#t:iter/2"},{"type":"type","doc":"","title":"gb_trees.tree/0","ref":"gb_trees.html#t:tree/0"},{"type":"opaque","doc":"A general balanced tree.","title":"gb_trees.tree/2","ref":"gb_trees.html#t:tree/2"},{"type":"module","doc":"A library for encoding and decoding JSON.\n\nThis module implements [EEP68](https://github.com/erlang/eep/blob/master/eeps/eep-0068.md).\n\nBoth encoder and decoder fully conform to\n[RFC 8259](https://tools.ietf.org/html/rfc8259) and\n[ECMA 404](https://ecma-international.org/publications-and-standards/standards/ecma-404/)\nstandards. The decoder is tested using [JSONTestSuite](https://github.com/nst/JSONTestSuite).","title":"json","ref":"json.html"},{"type":"function","doc":"Parses a JSON value from `Binary`.\n\nSupports basic data mapping:\n\n| **JSON** | **Erlang** |\n|----------|------------------------|\n| Number | `integer() \\| float()` |\n| Boolean | `true \\| false` |\n| Null | `null` |\n| String | `binary()` |\n| Object | `#{binary() => _}` |","title":"json.decode/1","ref":"json.html#decode/1"},{"type":"function","doc":"* `error(unexpected_end)` if `Binary` contains incomplete JSON value\n* `error({invalid_byte, Byte})` if `Binary` contains unexpected byte or invalid UTF-8 byte\n* `error({unexpected_sequence, Bytes})` if `Binary` contains invalid UTF-8 escape","title":"Errors - json.decode/1","ref":"json.html#decode/1-errors"},{"type":"function","doc":"```erlang\n> json:decode(<<\"{\\\"foo\\\": 1}\">>).\n#{<<\"foo\">> => 1}\n```","title":"Example - json.decode/1","ref":"json.html#decode/1-example"},{"type":"function","doc":"Parses a JSON value from `Binary`.\n\nSimilar to `decode/1` except the decoding process\ncan be customized with the callbacks specified in\n`Decoders`. The callbacks will use the `Acc` value\nas the initial accumulator.\n\nAny leftover, unparsed data in `Binary` will be returned.","title":"json.decode/3","ref":"json.html#decode/3"},{"type":"function","doc":"All callbacks are optional. If not provided, they will fall back to\nimplementations used by the `decode/1` function:\n\n* for `array_start`: `fun(_) -> [] end`\n* for `array_push`: `fun(Elem, Acc) -> [Elem | Acc] end`\n* for `array_finish`: `fun(Acc, OldAcc) -> {lists:reverse(Acc), OldAcc} end`\n* for `object_start`: `fun(_) -> [] end`\n* for `object_push`: `fun(Key, Value, Acc) -> [{Key, Value} | Acc] end`\n* for `object_finish`: `fun(Acc, OldAcc) -> {maps:from_list(Acc), OldAcc} end`\n* for `float`: `fun erlang:binary_to_float/1`\n* for `integer`: `fun erlang:binary_to_integer/1`\n* for `string`: `fun (Value) -> Value end`\n* for `null`: the atom `null`","title":"Default callbacks - json.decode/3","ref":"json.html#decode/3-default-callbacks"},{"type":"function","doc":"* `error({invalid_byte, Byte})` if `Binary` contains unexpected byte or invalid UTF-8 byte\n* `error({unexpected_sequence, Bytes})` if `Binary` contains invalid UTF-8 escape\n* `error(unexpected_end)` if `Binary` contains incomplete JSON value","title":"Errors - json.decode/3","ref":"json.html#decode/3-errors"},{"type":"function","doc":"Decoding object keys as atoms:\n\n```erlang\n> Push = fun(Key, Value, Acc) -> [{binary_to_existing_atom(Key), Value} | Acc] end.\n> json:decode(<<\"{\\\"foo\\\": 1}\">>, ok, #{object_push => Push}).\n{#{foo => 1},ok,<<>>}\n```","title":"Example - json.decode/3","ref":"json.html#decode/3-example"},{"type":"function","doc":"Continue parsing a stream of bytes of a JSON value.\n\nSimilar to `decode_start/3`, if the function returns `{continue, State}` and\nthere is no more data, use `end_of_input` instead of a binary.\n\n```erlang\n> {continue, State} = json:decode_start(<<\"{\\\"foo\\\":\">>, ok, #{}).\n> json:decode_continue(<<\"1}\">>, State).\n{#{foo => 1},ok,<<>>}\n```\n```erlang\n> {continue, State} = json:decode_start(<<\"123\">>, ok, #{}).\n> json:decode_continue(end_of_input, State).\n{123,ok,<<>>}\n```","title":"json.decode_continue/2","ref":"json.html#decode_continue/2"},{"type":"function","doc":"Begin parsing a stream of bytes of a JSON value.\n\nSimilar to `decode/3` but returns when a complete JSON value can be parsed or\nreturns `{continue, State}` for incomplete data,\nthe `State` can be fed to the `decode_continue/2` function when more data is available.","title":"json.decode_start/3","ref":"json.html#decode_start/3"},{"type":"function","doc":"Generates JSON corresponding to `Term`.\n\nSupports basic data mapping:\n\n| **Erlang** | **JSON** |\n|------------------------|----------|\n| `integer() \\| float()` | Number |\n| `true \\| false ` | Boolean |\n| `null` | Null |\n| `binary()` | String |\n| `atom()` | String |\n| `list()` | Array |\n| `#{binary() => _}` | Object |\n| `#{atom() => _}` | Object |\n| `#{integer() => _}` | Object |\n\nThis is equivalent to `encode(Term, fun json:encode_value/2)`.","title":"json.encode/1","ref":"json.html#encode/1"},{"type":"function","doc":"```erlang\n> iolist_to_binary(json:encode(#{foo => <<\"bar\">>})).\n<<\"{\\\"foo\\\":\\\"bar\\\"}\">>\n```","title":"Examples - json.encode/1","ref":"json.html#encode/1-examples"},{"type":"function","doc":"Generates JSON corresponding to `Term`.\n\nCan be customised with the `Encoder` callback.\nThe callback will be recursively called for all the data\nto be encoded and is expected to return the corresponding\nencoded JSON as iodata.\n\nVarious `encode_*` functions in this module can be used\nto help in constructing such callbacks.","title":"json.encode/2","ref":"json.html#encode/2"},{"type":"function","doc":"An encoder that uses a heuristic to differentiate object-like\nlists of key-value pairs from plain lists:\n\n```erlang\n> encoder([{_, _} | _] = Value, Encode) -> json:encode_key_value_list(Value, Encode);\n> encoder(Other, Encode) -> json:encode_value(Other, Encode).\n> custom_encode(Value) -> json:encode(Value, fun(Value, Encode) -> encoder(Value, Encode) end).\n> iolist_to_binary(custom_encode([{a, []}, {b, 1}])).\n<<\"{\\\"a\\\":[],\\\"b\\\":1}\">>\n```","title":"Examples - json.encode/2","ref":"json.html#encode/2-examples"},{"type":"function","doc":"Default encoder for atoms used by `json:encode/1`.\n\nEncodes the atom `null` as JSON `null`,\natoms `true` and `false` as JSON booleans,\nand everything else as JSON strings calling the `Encode`\ncallback with the corresponding binary.","title":"json.encode_atom/2","ref":"json.html#encode_atom/2"},{"type":"function","doc":"Default encoder for binaries as JSON strings used by `json:encode/1`.","title":"json.encode_binary/1","ref":"json.html#encode_binary/1"},{"type":"function","doc":"* `error(unexpected_end)` if the binary contains incomplete UTF-8 sequences.\n* `error({invalid_byte, Byte})` if the binary contains invalid UTF-8 sequences.","title":"Errors - json.encode_binary/1","ref":"json.html#encode_binary/1-errors"},{"type":"function","doc":"Encoder for binaries as JSON strings producing pure-ASCII JSON.\n\nFor any non-ASCII unicode character, a corresponding `\\\\uXXXX` sequence is used.","title":"json.encode_binary_escape_all/1","ref":"json.html#encode_binary_escape_all/1"},{"type":"function","doc":"* `error(unexpected_end)` if the binary contains incomplete UTF-8 sequences.\n* `error({invalid_byte, Byte})` if the binary contains invalid UTF-8 sequences.","title":"Errors - json.encode_binary_escape_all/1","ref":"json.html#encode_binary_escape_all/1-errors"},{"type":"function","doc":"Default encoder for floats as JSON numbers used by `json:encode/1`.","title":"json.encode_float/1","ref":"json.html#encode_float/1"},{"type":"function","doc":"Default encoder for integers as JSON numbers used by `json:encode/1`.","title":"json.encode_integer/1","ref":"json.html#encode_integer/1"},{"type":"function","doc":"Encoder for lists of key-value pairs as JSON objects.\n\nAccepts lists with atom, binary, integer, or float keys.","title":"json.encode_key_value_list/2","ref":"json.html#encode_key_value_list/2"},{"type":"function","doc":"Encoder for lists of key-value pairs as JSON objects.\n\nAccepts lists with atom, binary, integer, or float keys.\nVerifies that no duplicate keys will be produced in the\nresulting JSON object.","title":"json.encode_key_value_list_checked/2","ref":"json.html#encode_key_value_list_checked/2"},{"type":"function","doc":"Raises `error({duplicate_key, Key})` if there are duplicates.","title":"Errors - json.encode_key_value_list_checked/2","ref":"json.html#encode_key_value_list_checked/2-errors"},{"type":"function","doc":"Default encoder for lists as JSON arrays used by `json:encode/1`.","title":"json.encode_list/2","ref":"json.html#encode_list/2"},{"type":"function","doc":"Default encoder for maps as JSON objects used by `json:encode/1`.\n\nAccepts maps with atom, binary, integer, or float keys.","title":"json.encode_map/2","ref":"json.html#encode_map/2"},{"type":"function","doc":"Encoder for maps as JSON objects.\n\nAccepts maps with atom, binary, integer, or float keys.\nVerifies that no duplicate keys will be produced in the\nresulting JSON object.","title":"json.encode_map_checked/2","ref":"json.html#encode_map_checked/2"},{"type":"function","doc":"Raises `error({duplicate_key, Key})` if there are duplicates.","title":"Errors - json.encode_map_checked/2","ref":"json.html#encode_map_checked/2-errors"},{"type":"function","doc":"Default encoder used by `json:encode/1`.\n\nRecursively calls `Encode` on all the values in `Value`.","title":"json.encode_value/2","ref":"json.html#encode_value/2"},{"type":"function","doc":"Generates formatted JSON corresponding to `Term`.\n\nSimiliar to `encode/1` but with added whitespaces for formatting.\n\n```erlang\n> io:put_chars(json:format(#{foo => <<\"bar\">>, baz => 52})).\n{\n \"baz\": 52,\n \"foo\": \"bar\"\n}\nok\n```","title":"json.format/1","ref":"json.html#format/1"},{"type":"function","doc":"Generates formatted JSON corresponding to `Term`.\n\nEquivalent to `format(Term, fun json:format_value/3, Options)` or `format(Term, Encoder, #{})`","title":"json.format/2","ref":"json.html#format/2"},{"type":"function","doc":"Generates formatted JSON corresponding to `Term`.\n\nSimilar to `encode/2`, can be customised with the `Encoder` callback and `Options`.\n\n`Options` can include 'indent' to specify number of spaces per level and 'max' which loosely limits\nthe width of lists.\n\nThe `Encoder` will get a 'State' argument which contains the 'Options' maps merged with other data\nwhen recursing through 'Term'.\n\n`format_value/3` or various `encode_*` functions in this module can be used\nto help in constructing such callbacks.\n\n```erlang\n> formatter({posix_time, SysTimeSecs}, Encode, State) ->\n TimeStr = calendar:system_time_to_rfc3339(SysTimeSecs, [{offset, \"Z\"}]),\n json:format_value(unicode:characters_to_binary(TimeStr), Encode, State);\n> formatter(Other, Encode, State) -> json:format_value(Other, Encode, State).\n>\n> Fun = fun(Value, Encode, State) -> formatter(Value, Encode, State) end.\n> Options = #{indent => 4}.\n> Term = #{id => 1, time => {posix_time, erlang:system_time(seconds)}}.\n>\n> io:put_chars(json:format(Term, Fun, Options)).\n{\n \"id\": 1,\n \"time\": \"2024-05-23T16:07:48Z\"\n}\nok\n```","title":"json.format/3","ref":"json.html#format/3"},{"type":"function","doc":"Format function for lists of key-value pairs as JSON objects.\n\nAccepts lists with atom, binary, integer, or float keys.","title":"json.format_key_value_list/3","ref":"json.html#format_key_value_list/3"},{"type":"function","doc":"Format function for lists of key-value pairs as JSON objects.\n\nAccepts lists with atom, binary, integer, or float keys.\nVerifies that no duplicate keys will be produced in the\nresulting JSON object.","title":"json.format_key_value_list_checked/3","ref":"json.html#format_key_value_list_checked/3"},{"type":"function","doc":"Raises `error({duplicate_key, Key})` if there are duplicates.","title":"Errors - json.format_key_value_list_checked/3","ref":"json.html#format_key_value_list_checked/3-errors"},{"type":"function","doc":"Default format function used by `json:format/1`.\n\nRecursively calls `Encode` on all the values in `Value`,\nand indents objects and lists.","title":"json.format_value/3","ref":"json.html#format_value/3"},{"type":"type","doc":"","title":"json.array_finish_fun/0","ref":"json.html#t:array_finish_fun/0"},{"type":"type","doc":"","title":"json.array_push_fun/0","ref":"json.html#t:array_push_fun/0"},{"type":"type","doc":"","title":"json.array_start_fun/0","ref":"json.html#t:array_start_fun/0"},{"type":"opaque","doc":"","title":"json.continuation_state/0","ref":"json.html#t:continuation_state/0"},{"type":"type","doc":"","title":"json.decode_value/0","ref":"json.html#t:decode_value/0"},{"type":"type","doc":"","title":"json.decoders/0","ref":"json.html#t:decoders/0"},{"type":"type","doc":"","title":"json.encode_map/1","ref":"json.html#t:encode_map/1"},{"type":"type","doc":"Simple JSON value encodeable with `json:encode/1`.","title":"json.encode_value/0","ref":"json.html#t:encode_value/0"},{"type":"type","doc":"","title":"json.encoder/0","ref":"json.html#t:encoder/0"},{"type":"type","doc":"","title":"json.formatter/0","ref":"json.html#t:formatter/0"},{"type":"type","doc":"","title":"json.from_binary_fun/0","ref":"json.html#t:from_binary_fun/0"},{"type":"type","doc":"","title":"json.object_finish_fun/0","ref":"json.html#t:object_finish_fun/0"},{"type":"type","doc":"","title":"json.object_push_fun/0","ref":"json.html#t:object_push_fun/0"},{"type":"type","doc":"","title":"json.object_start_fun/0","ref":"json.html#t:object_start_fun/0"},{"type":"module","doc":"Key-value dictionary as ordered list.\n\nThis module provides a `Key`-`Value` dictionary. An `orddict` is a\nrepresentation of a dictionary, where a list of pairs is used to store the keys\nand values. The list is ordered after the keys in the\n[Erlang term order](`e:system:expressions.md#term-comparisons`).\n\nThis module provides the same interface as the `m:dict` module but with a\ndefined representation. One difference is that while `dict` considers two keys\nas different if they do not match (`=:=`), this module considers two keys as\ndifferent if and only if they do not compare equal (`==`).","title":"orddict","ref":"orddict.html"},{"type":"module","doc":"[](){: #notes }\n\nFunctions [`append/3`](`append/3`) and [`append_list/3`](`append_list/3`) are\nincluded so that keyed values can be stored in a list _accumulator_, for\nexample:\n\n```erlang\n> D0 = orddict:new(),\n D1 = orddict:store(files, [], D0),\n D2 = orddict:append(files, f1, D1),\n D3 = orddict:append(files, f2, D2),\n D4 = orddict:append(files, f3, D3),\n orddict:fetch(files, D4).\n[f1,f2,f3]\n```\n\nThis saves the trouble of first fetching a keyed value, appending a new value to\nthe list of stored values, and storing the result.\n\nFunction [`fetch/2`](`fetch/2`) is to be used if the key is known to be in the\ndictionary, otherwise function [`find/2`](`find/2`).","title":"Notes - orddict","ref":"orddict.html#module-notes"},{"type":"module","doc":"`m:dict`, `m:gb_trees`","title":"See Also - orddict","ref":"orddict.html#module-see-also"},{"type":"function","doc":"Appends a new `Value` to the current list of values associated with `Key`. An\nexception is generated if the initial value associated with `Key` is not a list\nof values.\n\nSee also section [Notes](`m:orddict#module-notes`).\n\n_Example 1:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{x, []}]).\n[{x,[]}]\n2> OrdDict2 = orddict:append(x, 1, OrdDict1).\n[{x,[1]}]\n3> OrdDict3 = orddict:append(x, 2, OrdDict2).\n[{x,[1,2]}]\n4> orddict:append(y, 3, OrdDict3).\n[{x,[1,2]},{y,[3]}]\n```\n\n_Example 2:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{a, no_list}]).\n[{a,no_list}]\n2> orddict:append(a, 1, OrdDict1).\n** exception error: bad argument\n in operator ++/2\n called as no_list ++ [1]\n```","title":"orddict.append/3","ref":"orddict.html#append/3"},{"type":"function","doc":"Appends a list of values `ValList` to the current list of values associated with\n`Key`. An exception is generated if the initial value associated with `Key` is\nnot a list of values.\n\nSee also section [Notes](`m:orddict#module-notes`).\n\n_Example:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{x, []}]).\n[{x,[]}]\n2> OrdDict2 = orddict:append_list(x, [1,2], OrdDict1).\n[{x,[1,2]}]\n3> OrdDict3 = orddict:append_list(y, [3,4], OrdDict2).\n[{x,[1,2]},{y,[3,4]}]\n```","title":"orddict.append_list/3","ref":"orddict.html#append_list/3"},{"type":"function","doc":"Erases all items with a specified key from a dictionary.\n\n_Example:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).\n[{a,1},{b,2}]\n2> orddict:erase(a, OrdDict1).\n[{b,2}]\n```","title":"orddict.erase/2","ref":"orddict.html#erase/2"},{"type":"function","doc":"Returns the value associated with `Key` in dictionary `Orddict`. This function\nassumes that the `Key` is present in the dictionary. An exception is generated\nif `Key` is not in the dictionary.\n\nSee also section [Notes](`m:orddict#module-notes`).\n\n_Example:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).\n[{a,1},{b,2}]\n2> orddict:fetch(a, OrdDict1).\n1\n3> orddict:fetch(missing, OrdDict1).\n** exception error: no function clause matching orddict:fetch(missing,[])\n```","title":"orddict.fetch/2","ref":"orddict.html#fetch/2"},{"type":"function","doc":"Returns a list of all keys in a dictionary.\n\n_Example:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).\n[{a,1},{b,2}]\n2> orddict:fetch_keys(OrdDict1).\n[a,b]\n```","title":"orddict.fetch_keys/1","ref":"orddict.html#fetch_keys/1"},{"type":"function","doc":"`Orddict2` is a dictionary of all keys and values in `Orddict1` for which\n`Pred(Key, Value)` is `true`.\n\n_Example:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).\n[{a,1},{b,2}]\n2> orddict:filter(fun (K, V) -> V > 1 end, OrdDict1).\n[{b,2}]\n```","title":"orddict.filter/2","ref":"orddict.html#filter/2"},{"type":"function","doc":"Searches for a key in a dictionary. Returns `{ok, Value}`, where `Value` is the\nvalue associated with `Key`, or `error` if the key is not present in the\ndictionary.\n\nSee also section [Notes](`m:orddict#module-notes`).\n\n_Example:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).\n[{a,1},{b,2}]\n2> orddict:find(a, OrdDict1).\n{ok,1}\n3> orddict:find(c, OrdDict1).\nerror\n```","title":"orddict.find/2","ref":"orddict.html#find/2"},{"type":"function","doc":"Calls `Fun` on successive keys and values of `Orddict` together with an extra\nargument `Acc` (short for accumulator). `Fun` must return a new accumulator that\nis passed to the next call. `Acc0` is returned if the list is empty.\n\n_Example:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).\n[{a,1},{b,2}]\n2> orddict:fold(fun (K, V, Acc) -> [{K, V+100} | Acc] end, [], OrdDict1).\n[{b,102},{a,101}]\n```","title":"orddict.fold/3","ref":"orddict.html#fold/3"},{"type":"function","doc":"Converts the `Key`-`Value` list `List` to a dictionary.","title":"orddict.from_list/1","ref":"orddict.html#from_list/1"},{"type":"function","doc":"Returns `true` if `Orddict` has no elements, otherwise `false`.","title":"orddict.is_empty/1","ref":"orddict.html#is_empty/1"},{"type":"function","doc":"Tests if `Key` is contained in dictionary `Orddict`.","title":"orddict.is_key/2","ref":"orddict.html#is_key/2"},{"type":"function","doc":"Calls `Fun` on successive keys and values of `Orddict1` to return a new value\nfor each key.\n\n_Example:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).\n[{a,1},{b,2}]\n2> orddict:map(fun (_K, V) -> V + 100 end, OrdDict1).\n[{a,101},{b,102}]\n```","title":"orddict.map/2","ref":"orddict.html#map/2"},{"type":"function","doc":"Merges two dictionaries, `Orddict1` and `Orddict2`, to create a new dictionary.\nAll the `Key`-`Value` pairs from both dictionaries are included in the new\ndictionary.\n\nIf a key occurs in both dictionaries, `Fun` is called with the key\nand both values to return a new value.\n\n[`merge/3`](`merge/3`) can be defined as follows, but is faster:\n\n```erlang\nmerge(Fun, D1, D2) ->\n fold(fun (K, V1, D) ->\n update(K, fun (V2) -> Fun(K, V1, V2) end, V1, D)\n end, D2, D1).\n```\n\n_Example:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).\n[{a,1},{b,2}]\n2> OrdDict2 = orddict:from_list([{b, 7}, {c, 8}]).\n[{b,7},{c,8}]\n3> orddict:merge(fun (K, V1, V2) -> V1 * V2 end, OrdDict1, OrdDict2).\n[{a,1},{b,14},{c,8}]\n```","title":"orddict.merge/3","ref":"orddict.html#merge/3"},{"type":"function","doc":"Creates a new dictionary.","title":"orddict.new/0","ref":"orddict.html#new/0"},{"type":"function","doc":"Returns the number of elements in an `Orddict`.","title":"orddict.size/1","ref":"orddict.html#size/1"},{"type":"function","doc":"Stores a `Key`-`Value` pair in a dictionary. If the `Key` already exists in\n`Orddict1`, the associated value is replaced by `Value`.\n\n_Example:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).\n[{a,1},{b,2}]\n2> orddict:store(a, 99, OrdDict1).\n[{a,99},{b,2}]\n3> orddict:store(c, 100, OrdDict1).\n[{a,1},{b,2},{c,100}]\n```","title":"orddict.store/3","ref":"orddict.html#store/3"},{"type":"function","doc":"This function returns value from dictionary and new dictionary without this\nvalue. Returns `error` if the key is not present in the dictionary.\n\n_Example:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).\n[{a,1},{b,2}]\n2> orddict:take(a, OrdDict1).\n{1,[{b,2}]}\n3> orddict:take(missing, OrdDict1).\nerror\n```","title":"orddict.take/2","ref":"orddict.html#take/2"},{"type":"function","doc":"Converts a dictionary to a list representation.","title":"orddict.to_list/1","ref":"orddict.html#to_list/1"},{"type":"function","doc":"Updates a value in a dictionary by calling `Fun` on the value to get a new\nvalue. An exception is generated if `Key` is not present in the dictionary.\n\n_Example:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).\n[{a,1},{b,2}]\n2> orddict:update(a, fun (V) -> V + 100 end, OrdDict1).\n[{a,101},{b,2}]\n```","title":"orddict.update/3","ref":"orddict.html#update/3"},{"type":"function","doc":"Updates a value in a dictionary by calling `Fun` on the value to get a new\nvalue. If `Key` is not present in the dictionary, `Initial` is stored as the\nfirst value.\n\nFor example, [`append/3`](`append/3`) can be defined as follows:\n\n```erlang\nappend(Key, Val, D) ->\n update(Key, fun (Old) -> Old ++ [Val] end, [Val], D).\n```\n\n_Example 1:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).\n[{a,1},{b,2}]\n2> orddict:update(c, fun (V) -> V + 100 end, 99, OrdDict1).\n[{a,1},{b,2},{c,99}]\n```\n\n_Example 2:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).\n[{a,1},{b,2}]\n2> orddict:update(a, fun (V) -> V + 100 end, 99, OrdDict1).\n[{a,101},{b,2}]\n```","title":"orddict.update/4","ref":"orddict.html#update/4"},{"type":"function","doc":"Adds `Increment` to the value associated with `Key` and store this value. If\n`Key` is not present in the dictionary, `Increment` is stored as the first\nvalue.\n\nThis can be defined as follows, but is faster:\n\n```erlang\nupdate_counter(Key, Incr, D) ->\n update(Key, fun (Old) -> Old + Incr end, Incr, D).\n```","title":"orddict.update_counter/3","ref":"orddict.html#update_counter/3"},{"type":"type","doc":"","title":"orddict.orddict/0","ref":"orddict.html#t:orddict/0"},{"type":"type","doc":"Dictionary as returned by `new/0`.","title":"orddict.orddict/2","ref":"orddict.html#t:orddict/2"},{"type":"module","doc":"Functions for manipulating sets as ordered lists.\n\nSets are collections of elements with no duplicate elements. An `ordset` is a\nrepresentation of a set, where an ordered list is used to store the elements of\nthe set. An ordered list is more efficient than an unordered list. Elements are\nordered according to the _Erlang term order_.\n\nThis module provides the same interface as the `m:sets` module but with a\ndefined representation. One difference is that while `sets` considers two\nelements as different if they do not match (`=:=`), this module considers two\nelements as different if and only if they do not compare equal (`==`).\n\nSee the [Compatibility Section in the `sets` module](`m:sets#module-compatibility`)\nfor more information about the compatibility of the different implementations of\nsets in the Standard Library.","title":"ordsets","ref":"ordsets.html"},{"type":"module","doc":"`m:gb_sets`, `m:sets`","title":"See Also - ordsets","ref":"ordsets.html#module-see-also"},{"type":"function","doc":"Returns a new ordered set formed from `Ordset1` with `Element` inserted.","title":"ordsets.add_element/2","ref":"ordsets.html#add_element/2"},{"type":"function","doc":"Returns `Ordset1`, but with `Element` removed.","title":"ordsets.del_element/2","ref":"ordsets.html#del_element/2"},{"type":"function","doc":"Filters elements in `Ordset1` with boolean function `Pred`.","title":"ordsets.filter/2","ref":"ordsets.html#filter/2"},{"type":"function","doc":"Filters and maps elements in `Ordset1` with function `Fun`.","title":"ordsets.filtermap/2","ref":"ordsets.html#filtermap/2"},{"type":"function","doc":"Folds `Function` over every element in `Ordset` and returns the final value of\nthe accumulator.","title":"ordsets.fold/3","ref":"ordsets.html#fold/3"},{"type":"function","doc":"Returns an ordered set of the elements in `List`.","title":"ordsets.from_list/1","ref":"ordsets.html#from_list/1"},{"type":"function","doc":"Returns the intersection of the non-empty list of sets.","title":"ordsets.intersection/1","ref":"ordsets.html#intersection/1"},{"type":"function","doc":"Returns the intersection of `Ordset1` and `Ordset2`.","title":"ordsets.intersection/2","ref":"ordsets.html#intersection/2"},{"type":"function","doc":"Returns `true` if `Ordset1` and `Ordset2` are disjoint (have no elements in\ncommon), otherwise `false`.","title":"ordsets.is_disjoint/2","ref":"ordsets.html#is_disjoint/2"},{"type":"function","doc":"Returns `true` if `Element` is an element of `Ordset`, otherwise `false`.","title":"ordsets.is_element/2","ref":"ordsets.html#is_element/2"},{"type":"function","doc":"Returns `true` if `Ordset` is an empty set, otherwise `false`.","title":"ordsets.is_empty/1","ref":"ordsets.html#is_empty/1"},{"type":"function","doc":"Returns `true` if `Ordset1` and `Ordset2` are equal, that is when every element\nof one set is also a member of the respective other set, otherwise `false`.","title":"ordsets.is_equal/2","ref":"ordsets.html#is_equal/2"},{"type":"function","doc":"Returns `true` if `Ordset` is an ordered set of elements, otherwise `false`.\nThis function will return `true` for any ordered list, even when not constructed\nby the functions in this module.","title":"ordsets.is_set/1","ref":"ordsets.html#is_set/1"},{"type":"function","doc":"Returns `true` when every element of `Ordset1` is also a member of `Ordset2`,\notherwise `false`.","title":"ordsets.is_subset/2","ref":"ordsets.html#is_subset/2"},{"type":"function","doc":"Maps elements in `Ordset1` with mapping function `Fun`.","title":"ordsets.map/2","ref":"ordsets.html#map/2"},{"type":"function","doc":"Returns a new empty ordered set.","title":"ordsets.new/0","ref":"ordsets.html#new/0"},{"type":"function","doc":"Returns the number of elements in `Ordset`.","title":"ordsets.size/1","ref":"ordsets.html#size/1"},{"type":"function","doc":"Returns only the elements of `Ordset1` that are not also elements of `Ordset2`.","title":"ordsets.subtract/2","ref":"ordsets.html#subtract/2"},{"type":"function","doc":"Returns the elements of `Ordset` as a list.","title":"ordsets.to_list/1","ref":"ordsets.html#to_list/1"},{"type":"function","doc":"Returns the merged (union) set of the list of sets.","title":"ordsets.union/1","ref":"ordsets.html#union/1"},{"type":"function","doc":"Returns the merged (union) set of `Ordset1` and `Ordset2`.","title":"ordsets.union/2","ref":"ordsets.html#union/2"},{"type":"type","doc":"As returned by `new/0`.","title":"ordsets.ordset/1","ref":"ordsets.html#t:ordset/1"},{"type":"module","doc":"Support functions for property lists.\n\nProperty lists are ordinary lists containing entries in the form of either\ntuples, whose first elements are keys used for lookup and insertion, or atoms,\nwhich work as shorthand for tuples `{Atom, true}`. (Other terms are allowed in\nthe lists, but are ignored by this module.) If there is more than one entry in a\nlist for a certain key, the first occurrence normally overrides any later\n(irrespective of the arity of the tuples).\n\nProperty lists are useful for representing inherited properties, such as options\npassed to a function where a user can specify options overriding the default\nsettings, object properties, annotations, and so on.\n\nTwo keys are considered equal if they match (`=:=`). That is, numbers are\ncompared literally rather than by value, so that, for example, `1` and `1.0` are\ndifferent keys.","title":"proplists","ref":"proplists.html"},{"type":"function","doc":"Similar to `get_all_values/2`, but each value is wrapped in a list unless it is\nalready itself a list. The resulting list of lists is concatenated. This is\noften useful for \"incremental\" options.\n\n_Example:_\n\n```erlang\nappend_values(a, [{a, [1,2]}, {b, 0}, {a, 3}, {c, -1}, {a, [4]}])\n```\n\nreturns:\n\n```erlang\n[1,2,3,4]\n```","title":"proplists.append_values/2","ref":"proplists.html#append_values/2"},{"type":"function","doc":"Minimizes the representation of all entries in the list. This is equivalent to\n`[property(P) || P <- ListIn]`.\n\nSee also `property/1`, `unfold/1`.","title":"proplists.compact/1","ref":"proplists.html#compact/1"},{"type":"function","doc":"Deletes all entries associated with `Key` from `List`.","title":"proplists.delete/2","ref":"proplists.html#delete/2"},{"type":"function","doc":"Expands particular properties to corresponding sets of properties (or other\nterms).\n\nFor each pair `{Property, Expansion}` in `Expansions`: if `E` is the\nfirst entry in `ListIn` with the same key as `Property`, and `E` and `Property`\nhave equivalent normal forms, then `E` is replaced with the terms in\n`Expansion`, and any following entries with the same key are deleted from\n`ListIn`.\n\nFor example, the following expressions all return `[fie, bar, baz, fum]`:\n\n```erlang\nexpand([{foo, [bar, baz]}], [fie, foo, fum])\nexpand([{{foo, true}, [bar, baz]}], [fie, foo, fum])\nexpand([{{foo, false}, [bar, baz]}], [fie, {foo, false}, fum])\n```\n\nHowever, no expansion is done in the following call because `{foo, false}`\nshadows `foo`:\n\n```erlang\nexpand([{{foo, true}, [bar, baz]}], [{foo, false}, fie, foo, fum])\n```\n\nNotice that if the original property term is to be preserved in the result when\nexpanded, it must be included in the expansion list. The inserted terms are not\nexpanded recursively. If `Expansions` contains more than one property with the\nsame key, only the first occurrence is used.\n\nSee also `normalize/2`.","title":"proplists.expand/2","ref":"proplists.html#expand/2"},{"type":"function","doc":"Converts the map `Map` to a property list.","title":"proplists.from_map/1","ref":"proplists.html#from_map/1"},{"type":"function","doc":"Similar to `get_value/2`, but returns the list of values for _all_ entries\n`{Key, Value}` in `List`. If no such entry exists, the result is the empty list.","title":"proplists.get_all_values/2","ref":"proplists.html#get_all_values/2"},{"type":"function","doc":"Returns the value of a boolean key/value option. If\n[`lookup(Key, List)`](`lookup/2`) would yield `{Key, true}`, this function\nreturns `true`, otherwise `false`.\n\nSee also `get_value/2`, `lookup/2`.","title":"proplists.get_bool/2","ref":"proplists.html#get_bool/2"},{"type":"function","doc":"Returns an unordered list of the keys used in `List`, not containing duplicates.","title":"proplists.get_keys/1","ref":"proplists.html#get_keys/1"},{"type":"function","doc":"","title":"proplists.get_value/2","ref":"proplists.html#get_value/2"},{"type":"function","doc":"Returns the value of a simple key/value property in `List`. If\n[`lookup(Key, List)`](`lookup/2`) would yield `{Key, Value}`, this function\nreturns the corresponding `Value`, otherwise `Default`.\n\nSee also `get_all_values/2`, `get_bool/2`, `get_value/2`, `lookup/2`.","title":"proplists.get_value/3","ref":"proplists.html#get_value/3"},{"type":"function","doc":"Returns `true` if `List` contains at least one entry associated with `Key`,\notherwise `false`.","title":"proplists.is_defined/2","ref":"proplists.html#is_defined/2"},{"type":"function","doc":"Returns the first entry associated with `Key` in `List`, if one exists,\notherwise returns `none`. For an atom `A` in the list, the tuple `{A, true}` is\nthe entry associated with `A`.\n\nSee also `get_bool/2`, `get_value/2`, `lookup_all/2`.","title":"proplists.lookup/2","ref":"proplists.html#lookup/2"},{"type":"function","doc":"Returns the list of all entries associated with `Key` in `List`. If no such\nentry exists, the result is the empty list.\n\nSee also `lookup/2`.","title":"proplists.lookup_all/2","ref":"proplists.html#lookup_all/2"},{"type":"function","doc":"Passes `ListIn` through a sequence of substitution/expansion stages. For an\n`aliases` operation, function `substitute_aliases/2` is applied using the\nspecified list of aliases:\n\n- For a `negations` operation,\n [`substitute_negations/2`](`substitute_negations/2`) is applied using the\n specified negation list.\n- For an `expand` operation, function `expand/2` is applied using the specified\n list of expansions.\n\nThe final result is automatically compacted (compare `compact/1`).\n\nTypically you want to substitute negations first, then aliases, then perform one\nor more expansions (sometimes you want to pre-expand particular entries before\ndoing the main expansion). You might want to substitute negations and/or aliases\nrepeatedly, to allow such forms in the right-hand side of aliases and expansion\nlists.\n\nSee also `substitute_negations/2`.","title":"proplists.normalize/2","ref":"proplists.html#normalize/2"},{"type":"function","doc":"Creates a normal form (minimal) representation of a property. If `PropertyIn` is\n`{Key, true}`, where `Key` is an atom, `Key` is returned, otherwise the whole\nterm `PropertyIn` is returned.\n\nSee also `property/2`.","title":"proplists.property/1","ref":"proplists.html#property/1"},{"type":"function","doc":"Creates a normal form (minimal) representation of a simple key/value property.\nReturns `Key` if `Value` is `true` and `Key` is an atom, otherwise a tuple\n`{Key, Value}` is returned.\n\nSee also `property/1`.","title":"proplists.property/2","ref":"proplists.html#property/2"},{"type":"function","doc":"Partitions `List` into a list of sublists and a remainder.\n\n`Lists` contains one sublist for each key in `Keys`, in the corresponding order.\nThe relative order of the elements in each sublist is preserved from the original `List`.\n`Rest` contains the elements in `List` that are not associated with any of the\nspecified keys, also with their original relative order preserved.\n\n_Example:_\n\n```erlang\nsplit([{c, 2}, {e, 1}, a, {c, 3, 4}, d, {b, 5}, b], [a, b, c])\n```\n\nreturns:\n\n```erlang\n{[[a], [{b, 5}, b],[{c, 2}, {c, 3, 4}]], [{e, 1}, d]}\n```","title":"proplists.split/2","ref":"proplists.html#split/2"},{"type":"function","doc":"Substitutes keys of properties. For each entry in `ListIn`, if it is associated\nwith some key `K1` such that `{K1, K2}` occurs in `Aliases`, the key of the\nentry is changed to `K2`. If the same `K1` occurs more than once in `Aliases`,\nonly the first occurrence is used.\n\nFor example,\n[`substitute_aliases([{color, colour}], L)`](`substitute_aliases/2`) replaces\nall tuples `{color, ...}` in `L` with `{colour, ...}`, and all atoms `color`\nwith `colour`.\n\nSee also `normalize/2`, `substitute_negations/2`.","title":"proplists.substitute_aliases/2","ref":"proplists.html#substitute_aliases/2"},{"type":"function","doc":"Substitutes keys of boolean-valued properties and simultaneously negates their\nvalues.\n\nFor each entry in `ListIn`, if it is associated with some key `K1` such\nthat `{K1, K2}` occurs in `Negations`: if the entry was `{K1, true}`, it is\nreplaced with `{K2, false}`, otherwise with `K2`, thus changing the name of the\noption and simultaneously negating the value specified by\n[`get_bool(Key, ListIn)`](`get_bool/2`). If the same `K1` occurs more than once\nin `Negations`, only the first occurrence is used.\n\nFor example,\n[`substitute_negations([{no_foo, foo}], L)`](`substitute_negations/2`) replaces\nany atom `no_foo` or tuple `{no_foo, true}` in `L` with `{foo, false}`, and any\nother tuple `{no_foo, ...}` with `foo`.\n\nSee also `get_bool/2`, `normalize/2`, `substitute_aliases/2`.","title":"proplists.substitute_negations/2","ref":"proplists.html#substitute_negations/2"},{"type":"function","doc":"Converts the property list `List` to a map.\n\nShorthand atom values in `List` will be expanded to an association of the form\n`Atom => true`. Tuples of the form `{Key, Value}` in `List` will be converted to\nan association of the form `Key => Value`. Anything else will be silently\nignored.\n\nIf the same key appears in `List` multiple times, the value of the one appearing\nnearest to the head of `List` will be in the result map, that is the value that\nwould be returned by a call to [`get_value(Key, List)`](`get_value/2`).\n\n_Example:_\n\n```erlang\nto_map([a, {b, 1}, {c, 2}, {c, 3}])\n```\n\nreturns:\n\n```erlang\n#{a => true, b => 1, c => 2}\n```","title":"proplists.to_map/1","ref":"proplists.html#to_map/1"},{"type":"function","doc":"Converts the property list `List` to a map after applying the normalizations\ngiven in `Stages`.\n\nSee also `normalize/2`, `to_map/1`.","title":"proplists.to_map/2","ref":"proplists.html#to_map/2"},{"type":"function","doc":"Unfolds all occurrences of atoms in `ListIn` to tuples `{Atom, true}`.\n\nSee also `compact/1`.","title":"proplists.unfold/1","ref":"proplists.html#unfold/1"},{"type":"type","doc":"A property item within a list","title":"proplists.property/0","ref":"proplists.html#t:property/0"},{"type":"type","doc":"A list of `t:property/0`, also knows as a proplist.","title":"proplists.proplist/0","ref":"proplists.html#t:proplist/0"},{"type":"module","doc":"This module provides a query interface to [Mnesia](`m:mnesia`), [ETS](`m:ets`),\n[Dets](`m:dets`), and other data structures that provide an iterator style\ntraversal of objects.","title":"qlc","ref":"qlc.html"},{"type":"module","doc":"This module provides a query interface to _QLC tables_. Typical QLC tables are\nMnesia, ETS, and Dets tables. Support is also provided for user-defined tables,\nsee section [Implementing a QLC Table](`m:qlc#implementing_a_qlc_table`). [](){:\n#query_list_comprehension } A _query_ is expressed using _Query List\nComprehensions_ (QLCs). The answers to a query are determined by data in QLC\ntables that fulfill the constraints expressed by the QLCs of the query. QLCs are\nsimilar to ordinary list comprehensions as described in\n[Erlang Reference Manual](`e:system:expressions.md#lcs`) and\n[Programming Examples](`e:system:list_comprehensions.md`), except that variables\nintroduced in patterns cannot be used in list expressions. In the absence of\noptimizations and options such as `cache` and `unique` (see section\n[Common Options](`m:qlc#common_options`), every QLC free of QLC tables evaluates\nto the same list of answers as the identical ordinary list comprehension.\n\nWhile ordinary list comprehensions evaluate to lists, calling [`q/1,2`](`q/1`)\nreturns a _query handle_{: #query_handle }. To obtain all the answers to a\nquery, [`eval/1,2`](`eval/1`) is to be called with the query handle as first\nargument. Query handles are essentially functional objects (funs) created in the\nmodule calling `q/1,2`. As the funs refer to the module code, be careful not to\nkeep query handles too long if the module code is to be replaced. Code\nreplacement is described in section\n[Compilation and Code Loading](`e:system:code_loading.md`) in the Erlang\nReference Manual. The list of answers can also be traversed in chunks by use of\na _query cursor_{: #query_cursor }. Query cursors are created by calling\n[`cursor/1,2`](`cursor/1`) with a query handle as first argument. Query cursors\nare essentially Erlang processes. One answer at a time is sent from the query\ncursor process to the process that created the cursor.","title":"Overview - qlc","ref":"qlc.html#module-overview"},{"type":"module","doc":"Syntactically QLCs have the same parts as ordinary list comprehensions:\n\n```text\n[Expression || Qualifier1, Qualifier2, ...]\n```\n\n`Expression` (the _template_) is any Erlang expression. Qualifiers are either\n_filters_ or _generators_. Filters are Erlang expressions returning\n`t:boolean/0`. Generators have the form `Pattern <- ListExpression`, where\n`ListExpression` is an expression evaluating to a query handle or a list. Query\nhandles are returned from [`append/1,2`](`append/1`),\n[`keysort/2,3`](`keysort/2`), [`q/1,2`](`q/1`), [`sort/1,2`](`sort/1`),\n[`string_to_handle/1,2,3`](`string_to_handle/1`), and `table/2`.","title":"Syntax - qlc","ref":"qlc.html#module-syntax"},{"type":"module","doc":"A query handle is evaluated in the following order:\n\n- Inspection of options and the collection of information about tables. As a\n result, qualifiers are modified during the optimization phase.\n- All list expressions are evaluated. If a cursor has been created, evaluation\n takes place in the cursor process. For list expressions that are QLCs, the\n list expressions of the generators of the QLCs are evaluated as well. Be\n careful if list expressions have side effects, as list expressions are\n evaluated in unspecified order.\n- The answers are found by evaluating the qualifiers from left to right,\n backtracking when some filter returns `false`, or collecting the template when\n all filters return `true`.\n\nFilters that do not return `t:boolean/0` but fail are handled differently\ndepending on their syntax: if the filter is a guard, it returns `false`,\notherwise the query evaluation fails. This behavior makes it possible for the\n`qlc` module to do some optimizations without affecting the meaning of a query.\nFor example, when testing some position of a table and one or more constants for\nequality, only the objects with equal values are candidates for further\nevaluation. The other objects are guaranteed to make the filter return `false`,\nbut never fail. The (small) set of candidate objects can often be found by\nlooking up some key values of the table or by traversing the table using a match\nspecification. It is necessary to place the guard filters immediately after the\ntable generator, otherwise the candidate objects are not restricted to a small\nset. The reason is that objects that could make the query evaluation fail must\nnot be excluded by looking up a key or running a match specification.","title":"Evaluation - qlc","ref":"qlc.html#module-evaluation"},{"type":"module","doc":"The `qlc` module supports fast join of two query handles. Fast join is possible\nif some position `P1` of one query handler and some position `P2` of another\nquery handler are tested for equality. Two fast join methods are provided:\n\n- _Lookup join_ traverses all objects of one query handle and finds objects of\n the other handle (a QLC table) such that the values at `P1` and `P2` match or\n compare equal. The `qlc` module does not create any indexes but looks up\n values using the key position and the indexed positions of the QLC table.\n- _Merge join_ sorts the objects of each query handle if necessary and filters\n out objects where the values at `P1` and `P2` do not compare equal. If many\n objects with the same value of `P2` exist, a temporary file is used for the\n equivalence classes.\n\nThe `qlc` module warns at compile time if a QLC combines query handles in such a\nway that more than one join is possible. That is, no query planner is provided\nthat can select a good order between possible join operations. It is up to the\nuser to order the joins by introducing query handles.\n\nThe join is to be expressed as a guard filter. The filter must be placed\nimmediately after the two joined generators, possibly after guard filters that\nuse variables from no other generators but the two joined generators. The `qlc`\nmodule inspects the operands of `=:=/2`, `==/2`, [`is_record/2`](`is_record/2`),\n[`element/2`](`element/2`), and logical operators (`and/2`, `or/2`, `andalso/2`,\n`orelse/2`, `xor/2`) when determining which joins to consider.\n\n[](){: #common_options }","title":"Join - qlc","ref":"qlc.html#module-join"},{"type":"module","doc":"The following options are accepted by `cursor/2`, `eval/2`, `fold/4`, and\n`info/2`:\n\n- `{cache_all, Cache}`, where `Cache` is equal to `ets` or `list` adds a\n `{cache, Cache}` option to every list expression of the query except tables\n and lists. Defaults to `{cache_all, no}`. Option `cache_all` is equivalent to\n `{cache_all, ets}`.\n- `{max_list_size, MaxListSize}`{: #max_list_size }, where `MaxListSize` is the\n size in bytes of terms on the external format. If the accumulated size of\n collected objects exceeds `MaxListSize`, the objects are written onto a\n temporary file. This option is used by option `{cache, list}` and by the merge\n join method. Defaults to 512\\*1024 bytes.\n- `{tmpdir_usage, TmpFileUsage}` determines the action taken when `qlc` is about\n to create temporary files on the directory set by option `tmpdir`. If the\n value is `not_allowed`, an error tuple is returned, otherwise temporary files\n are created as needed. Default is `allowed`, which means that no further\n action is taken. The values `info_msg`, `warning_msg`, and `error_msg` mean\n that the function with the corresponding name in module `m:error_logger` is\n called for printing some information (currently the stacktrace).\n- `{tmpdir, TempDirectory}` sets the directory used by merge join for temporary\n files and by option `{cache, list}`. The option also overrides option `tmpdir`\n of `keysort/3` and `sort/2`. Defaults to `\"\"`, which means that the directory\n returned by `file:get_cwd()` is used.\n- `{unique_all, true}` adds a `{unique, true}` option to every list expression\n of the query. Defaults to `{unique_all, false}`. Option `unique_all` is\n equivalent to `{unique_all, true}`.\n\n[](){: #getting_started }","title":"Common Options - qlc","ref":"qlc.html#module-common-options"},{"type":"module","doc":"As mentioned earlier, queries are expressed in the list comprehension syntax as\ndescribed in section [Expressions](`e:system:expressions.md`) in Erlang\nReference Manual. In the following, some familiarity with list comprehensions is\nassumed. The examples in section\n[List Comprehensions](`e:system:list_comprehensions.md`) in Programming Examples\ncan get you started. Notice that list comprehensions do not add any\ncomputational power to the language; anything that can be done with list\ncomprehensions can also be done without them. But they add syntax for expressing\nsimple search problems, which is compact and clear once you get used to it.\n\nMany list comprehension expressions can be evaluated by the `qlc` module.\nExceptions are expressions, such that variables introduced in patterns (or\nfilters) are used in some generator later in the list comprehension. As an\nexample, consider an implementation of `lists:append(L)`:\n`[X ||Y <- L, X <- Y]`. `Y` is introduced in the first generator and used in the\nsecond. The ordinary list comprehension is normally to be preferred when there\nis a choice as to which to use. One difference is that [`eval/1,2`](`eval/1`)\ncollects answers in a list that is finally reversed, while list comprehensions\ncollect answers on the stack that is finally unwound.\n\nWhat the `qlc` module primarily adds to list comprehensions is that data can be\nread from QLC tables in small chunks. A QLC table is created by calling\n[`qlc:table/2`](`table/2`). Usually `qlc:table/2` is not called directly from\nthe query but through an interface function of some data structure. Erlang/OTP\nincludes a few examples of such functions:\n[`mnesia:table/1,2`](`mnesia:table/1`), [`ets:table/1,2`](`ets:table/1`), and\n[`dets:table/1,2`](`dets:table/1`). For a given data structure, many functions\ncan create QLC tables, but common for these functions is that they return a\nquery handle created by [`qlc:table/2`](`table/2`). Using the QLC tables\nprovided by Erlang/OTP is usually probably sufficient, but for the more advanced\nuser section [Implementing a QLC Table](`m:qlc#implementing_a_qlc_table`)\ndescribes the implementation of a function calling `qlc:table/2`.\n\nBesides `qlc:table/2`, other functions return query handles. They are used more\nseldom than tables, but are sometimes useful. [`qlc:append/1,2`](`append/1`)\ntraverses objects from many tables or lists after each other. If, for example,\nyou want to traverse all answers to a query `QH` and then finish off by a term\n`{finished}`, you can do that by calling `qlc:append(QH, [{finished}])`.\n[`append/2`](`append/2`) first returns all objects of `QH`, then `{finished}`.\nIf a tuple `{finished}` exists among the answers to `QH`, it is returned twice\nfrom [`append/2`](`append/2`).\n\nAs another example, consider concatenating the answers to two queries `QH1` and\n`QH2` while removing all duplicates. This is accomplished by using option\n`unique`:\n\n```erlang\nqlc:q([X || X <- qlc:append(QH1, QH2)], {unique, true})\n```\n\nThe cost is substantial: every returned answer is stored in an ETS table. Before\nreturning an answer, it is looked up in the ETS table to check if it has already\nbeen returned. Without the `unique` option, all answers to `QH1` would be\nreturned followed by all answers to `QH2`. The `unique` option keeps the order\nbetween the remaining answers.\n\nIf the order of the answers is not important, there is an alternative to the\n`unique` option, namely to sort the answers uniquely:\n\n```erlang\nqlc:sort(qlc:q([X || X <- qlc:append(QH1, QH2)], {unique, true})).\n```\n\nThis query also removes duplicates but the answers are sorted. If there are many\nanswers, temporary files are used. Notice that to get the first unique answer,\nall answers must be found and sorted. Both alternatives find duplicates by\ncomparing answers, that is, if `A1` and `A2` are answers found in that order,\nthen `A2` is a removed if `A1 == A2`.\n\nTo return only a few answers, cursors can be used. The following code returns no\nmore than five answers using an ETS table for storing the unique answers:\n\n```erlang\nC = qlc:cursor(qlc:q([X || X <- qlc:append(QH1, QH2)],{unique,true})),\nR = qlc:next_answers(C, 5),\nok = qlc:delete_cursor(C),\nR.\n```\n\nQLCs are convenient for stating constraints on data from two or more tables. The\nfollowing example does a natural join on two query handles on position 2:\n\n```erlang\nqlc:q([{X1,X2,X3,Y1} ||\n {X1,X2,X3} <- QH1,\n {Y1,Y2} <- QH2,\n X2 =:= Y2])\n```\n\nThe `qlc` module evaluates this differently depending on the query handles `QH1`\nand `QH2`. If, for example, `X2` is matched against the key of a QLC table, the\nlookup join method traverses the objects of `QH2` while looking up key values in\nthe table. However, if not `X2` or `Y2` is matched against the key or an indexed\nposition of a QLC table, the merge join method ensures that `QH1` and `QH2` are\nboth sorted on position 2 and next do the join by traversing the objects one by\none.\n\nOption `join` can be used to force the `qlc` module to use a certain join\nmethod. For the rest of this section it is assumed that the excessively slow\njoin method called \"nested loop\" has been chosen:\n\n```erlang\nqlc:q([{X1,X2,X3,Y1} ||\n {X1,X2,X3} <- QH1,\n {Y1,Y2} <- QH2,\n X2 =:= Y2],\n {join, nested_loop})\n```\n\nIn this case the filter is applied to every possible pair of answers to `QH1`\nand `QH2`, one at a time. If there are M answers to `QH1` and N answers to\n`QH2`, the filter is run M\\*N times.\n\nIf `QH2` is a call to the function for `m:gb_trees`, as defined in section\n[Implementing a QLC Table](`m:qlc#implementing_a_qlc_table`), then\n[`gb_table:table/1` ](`m:qlc#gb_table`), the iterator for the gb-tree is\ninitiated for each answer to `QH1`. The objects of the gb-tree are then returned\none by one. This is probably the most efficient way of traversing the table in\nthat case, as it takes minimal computational power to get the following object.\nBut if `QH2` is not a table but a more complicated QLC, it can be more efficient\nto use some RAM memory for collecting the answers in a cache, particularly if\nthere are only a few answers. It must then be assumed that evaluating `QH2` has\nno side effects so that the meaning of the query does not change if `QH2` is\nevaluated only once. One way of caching the answers is to evaluate `QH2` first\nof all and substitute the list of answers for `QH2` in the query. Another way is\nto use option `cache`. It is expressed like this:\n\n```erlang\nQH2' = qlc:q([X || X <- QH2], {cache, ets})\n```\n\nor only\n\n```text\nQH2' = qlc:q([X || X <- QH2], cache)\n```\n\nThe effect of option `cache` is that when generator `QH2'` is run the first\ntime, every answer is stored in an ETS table. When the next answer of `QH1` is\ntried, answers to `QH2'` are copied from the ETS table, which is very fast. As\nfor option `unique` the cost is a possibly substantial amount of RAM memory.\n\nOption `{cache, list}` offers the possibility to store the answers in a list on\nthe process heap. This has the potential of being faster than ETS tables, as\nthere is no need to copy answers from the table. However, it can often result in\nslower evaluation because of more garbage collections of the process heap and\nincreased RAM memory consumption because of larger heaps. Another drawback with\ncache lists is that if the list size exceeds a limit, a temporary file is used.\nReading the answers from a file is much slower than copying them from an ETS\ntable. But if the available RAM memory is scarce, setting the\n[limit](`m:qlc#max_list_size`) to some low value is an alternative.\n\nOption `cache_all` can be set to `ets` or `list` when evaluating a query. It\nadds a `cache` or `{cache, list}` option to every list expression except QLC\ntables and lists on all levels of the query. This can be used for testing if\ncaching would improve efficiency at all. If the answer is yes, further testing\nis needed to pinpoint the generators that are to be cached.\n\n[](){: #implementing_a_qlc_table }","title":"Getting Started - qlc","ref":"qlc.html#module-getting-started"},{"type":"module","doc":"As an example of how to use function `table/2`, the implementation of a QLC\ntable for the `m:gb_trees` module is given:\n\n[](){: #gb_table }\n\n```erlang\n-module(gb_table).\n\n-export([table/1]).\n\ntable(T) ->\n TF = fun() -> qlc_next(gb_trees:next(gb_trees:iterator(T))) end,\n InfoFun = fun(num_of_objects) -> gb_trees:size(T);\n (keypos) -> 1;\n (is_sorted_key) -> true;\n (is_unique_objects) -> true;\n (_) -> undefined\n end,\n LookupFun =\n fun(1, Ks) ->\n lists:flatmap(fun(K) ->\n case gb_trees:lookup(K, T) of\n {value, V} -> [{K,V}];\n none -> []\n end\n end, Ks)\n end,\n FormatFun =\n fun({all, NElements, ElementFun}) ->\n ValsS = io_lib:format(\"gb_trees:from_orddict(~w)\",\n [gb_nodes(T, NElements, ElementFun)]),\n io_lib:format(\"gb_table:table(~s)\", [ValsS]);\n ({lookup, 1, KeyValues, _NElements, ElementFun}) ->\n ValsS = io_lib:format(\"gb_trees:from_orddict(~w)\",\n [gb_nodes(T, infinity, ElementFun)]),\n io_lib:format(\"lists:flatmap(fun(K) -> \"\n \"case gb_trees:lookup(K, ~s) of \"\n \"{value, V} -> [{K,V}];none -> [] end \"\n \"end, ~w)\",\n [ValsS, [ElementFun(KV) || KV <- KeyValues]])\n end,\n qlc:table(TF, [{info_fun, InfoFun}, {format_fun, FormatFun},\n {lookup_fun, LookupFun},{key_equality,'=='}]).\n\nqlc_next({X, V, S}) ->\n [{X,V} | fun() -> qlc_next(gb_trees:next(S)) end];\nqlc_next(none) ->\n [].\n\ngb_nodes(T, infinity, ElementFun) ->\n gb_nodes(T, -1, ElementFun);\ngb_nodes(T, NElements, ElementFun) ->\n gb_iter(gb_trees:iterator(T), NElements, ElementFun).\n\ngb_iter(_I, 0, _EFun) ->\n '...';\ngb_iter(I0, N, EFun) ->\n case gb_trees:next(I0) of\n {X, V, I} ->\n [EFun({X,V}) | gb_iter(I, N-1, EFun)];\n none ->\n []\n end.\n```\n\n`TF` is the traversal function. The `qlc` module requires that there is a way of\ntraversing all objects of the data structure. `gb_trees` has an iterator\nfunction suitable for that purpose. Notice that for each object returned, a new\nfun is created. As long as the list is not terminated by `[]`, it is assumed\nthat the tail of the list is a nullary function and that calling the function\nreturns further objects (and functions).\n\nThe lookup function is optional. It is assumed that the lookup function always\nfinds values much faster than it would take to traverse the table. The first\nargument is the position of the key. As `qlc_next/1` returns the objects as\n`{Key, Value}` pairs, the position is 1. Notice that the lookup function is to\nreturn `{Key, Value}` pairs, as the traversal function does.\n\nThe format function is also optional. It is called by [`info/1,2`](`info/1`) to\ngive feedback at runtime of how the query is to be evaluated. Try to give as\ngood feedback as possible without showing too much details. In the example, at\nmost seven objects of the table are shown. The format function handles two\ncases: `all` means that all objects of the table are traversed;\n`{lookup, 1, KeyValues}` means that the lookup function is used for looking up\nkey values.\n\nWhether the whole table is traversed or only some keys looked up depends on how\nthe query is expressed. If the query has the form\n\n```text\nqlc:q([T || P <- LE, F])\n```\n\nand `P` is a tuple, the `qlc` module analyzes `P` and `F` in compile time to\nfind positions of tuple `P` that are tested for equality to constants. If such a\nposition at runtime turns out to be the key position, the lookup function can be\nused, otherwise all objects of the table must be traversed. The info function\n`InfoFun` returns the key position. There can be indexed positions as well, also\nreturned by the info function. An index is an extra table that makes lookup on\nsome position fast. Mnesia maintains indexes upon request, and introduces so\ncalled secondary keys. The `qlc` module prefers to look up objects using the key\nbefore secondary keys regardless of the number of constants to look up.","title":"Implementing a QLC Table - qlc","ref":"qlc.html#module-implementing-a-qlc-table"},{"type":"module","doc":"Erlang/OTP has two operators for testing term equality: `==/2` and `=:=/2`. The\ndifference is all about the integers that can be represented by floats. For\nexample, `2 == 2.0` evaluates to `true` while `2 =:= 2.0` evaluates to `false`.\nNormally this is a minor issue, but the `qlc` module cannot ignore the\ndifference, which affects the user's choice of operators in QLCs.\n\nIf the `qlc` module at compile time can determine that some constant is free of\nintegers, it does not matter which one of `==/2` or `=:=/2` is used:\n\n```erlang\n1> E1 = ets:new(t, [set]), % uses =:=/2 for key equality\nQ1 = qlc:q([K ||\n{K} <- ets:table(E1),\nK == 2.71 orelse K == a]),\nio:format(\"~s~n\", [qlc:info(Q1)]).\nets:match_spec_run(\n lists:flatmap(fun(V) ->\n\t\t\t ets:lookup(#Ref<0.3098908599.2283929601.256025>,\n\t\t\t\t V)\n\t\t end,\n\t\t [a, 2.71]),\n ets:match_spec_compile([{{'$1'}, [], ['$1']}]))\n```\n\nIn the example, operator `==/2` has been handled exactly as `=:=/2` would have\nbeen handled. However, if it cannot be determined at compile time that some\nconstant is free of integers, and the table uses `=:=/2` when comparing keys for\nequality (see option [key_equality](`m:qlc#key_equality`)), then the `qlc`\nmodule does not try to look up the constant. The reason is that there is in the\ngeneral case no upper limit on the number of key values that can compare equal\nto such a constant; every combination of integers and floats must be looked up:\n\n```erlang\n2> E2 = ets:new(t, [set]),\ntrue = ets:insert(E2, [{{2,2},a},{{2,2.0},b},{{2.0,2},c}]),\nF2 = fun(I) ->\nqlc:q([V || {K,V} <- ets:table(E2), K == I])\nend,\nQ2 = F2({2,2}),\nio:format(\"~s~n\", [qlc:info(Q2)]).\nets:table(#Ref<0.3098908599.2283929601.256125>,\n [{traverse,\n {select,\n [{{'$1', '$2'}, [{'==', '$1', {const, {2, 2}}}], ['$2']}]}}])\n3> lists:sort(qlc:e(Q2)).\n[a,b,c]\n```\n\nLooking up only `{2,2}` would not return `b` and `c`.\n\nIf the table uses `==/2` when comparing keys for equality, the `qlc` module\nlooks up the constant regardless of which operator is used in the QLC. However,\n`==/2` is to be preferred:\n\n```erlang\n4> E3 = ets:new(t, [ordered_set]), % uses ==/2 for key equality\ntrue = ets:insert(E3, [{{2,2.0},b}]),\nF3 = fun(I) ->\nqlc:q([V || {K,V} <- ets:table(E3), K == I])\nend,\nQ3 = F3({2,2}),\nio:format(\"~s~n\", [qlc:info(Q3)]).\nets:match_spec_run(ets:lookup(#Ref<0.3098908599.2283929601.256211>,\n {2, 2}),\n ets:match_spec_compile([{{'$1', '$2'}, [], ['$2']}]))\n5> qlc:e(Q3).\n[b]\n```\n\nLookup join is handled analogously to lookup of constants in a table: if the\njoin operator is `==/2`, and the table where constants are to be looked up uses\n`=:=/2` when testing keys for equality, then the `qlc` module does not consider\nlookup join for that table.","title":"Key Equality - qlc","ref":"qlc.html#module-key-equality"},{"type":"module","doc":"`m:dets`, `m:erl_eval`, `m:erlang`, `m:error_logger`, `m:ets`, `m:file`,\n`m:file_sorter`, `m:mnesia`, `m:shell`,\n[Erlang Reference Manual](`e:system:index.html`),\n[Programming Examples](`e:system:index.html`)","title":"See Also - qlc","ref":"qlc.html#module-see-also"},{"type":"function","doc":"Returns a query handle. When evaluating query handle `QH`, all answers to the\nfirst query handle in `QHL` are returned, followed by all answers to the\nremaining query handles in `QHL`.","title":"qlc.append/1","ref":"qlc.html#append/1"},{"type":"function","doc":"Returns a query handle. When evaluating query handle `QH3`, all answers to `QH1`\nare returned, followed by all answers to `QH2`.\n\n[`append(QH1, QH2)`](`append/2`) is equivalent to\n[`append([QH1, QH2])`](`append/1`).","title":"qlc.append/2","ref":"qlc.html#append/2"},{"type":"function","doc":"","title":"qlc.cursor/1","ref":"qlc.html#cursor/1"},{"type":"function","doc":"Creates a query cursor and makes the calling process the owner of the cursor.\n\nThe cursor is to be used as argument to [`next_answers/1,2`](`next_answers/1`)\nand (eventually) `delete_cursor/1`. Calls `erlang:spawn_opt/2` to spawn and link\nto a process that evaluates the query handle. The value of option\n`spawn_options` is used as last argument when calling\n[`spawn_opt/2`](`spawn_opt/2`). Defaults to `[link]`.\n\n_Example:_\n\n```erlang\n1> QH = qlc:q([{X,Y} || X <- [a,b], Y <- [1,2]]),\nQC = qlc:cursor(QH),\nqlc:next_answers(QC, 1).\n[{a,1}]\n2> qlc:next_answers(QC, 1).\n[{a,2}]\n3> qlc:next_answers(QC, all_remaining).\n[{b,1},{b,2}]\n4> qlc:delete_cursor(QC).\nok\n```","title":"qlc.cursor/2","ref":"qlc.html#cursor/2"},{"type":"function","doc":"Deletes a query cursor. Only the owner of the cursor can delete the cursor.","title":"qlc.delete_cursor/1","ref":"qlc.html#delete_cursor/1"},{"type":"function","doc":"","title":"qlc.e/1","ref":"qlc.html#e/1"},{"type":"function","doc":"","title":"qlc.e/2","ref":"qlc.html#e/2"},{"type":"function","doc":"","title":"qlc.eval/1","ref":"qlc.html#eval/1"},{"type":"function","doc":"Evaluates a query handle in the calling process and collects all answers in a\nlist.\n\n_Example:_\n\n```erlang\n1> QH = qlc:q([{X,Y} || X <- [a,b], Y <- [1,2]]),\nqlc:eval(QH).\n[{a,1},{a,2},{b,1},{b,2}]\n```","title":"qlc.eval/2","ref":"qlc.html#eval/2"},{"type":"function","doc":"","title":"qlc.fold/3","ref":"qlc.html#fold/3"},{"type":"function","doc":"Calls `Function` on successive answers to the query handle together with an\nextra argument `AccIn`.\n\nThe query handle and the function are evaluated in the\ncalling process. `Function` must return a new accumulator, which is passed to\nthe next call. `Acc0` is returned if there are no answers to the query handle.\n\n_Example:_\n\n```erlang\n1> QH = [1,2,3,4,5,6],\nqlc:fold(fun(X, Sum) -> X + Sum end, 0, QH).\n21\n```","title":"qlc.fold/4","ref":"qlc.html#fold/4"},{"type":"function","doc":"Returns a descriptive string in English of an error tuple returned by some of\nthe functions of the `qlc` module or the parse transform. This function is\nmainly used by the compiler invoking the parse transform.","title":"qlc.format_error/1","ref":"qlc.html#format_error/1"},{"type":"function","doc":"","title":"qlc.info/1","ref":"qlc.html#info/1"},{"type":"function","doc":"Returns information about a query handle. The information describes the\nsimplifications and optimizations that are the results of preparing the query\nfor evaluation. This function is probably mainly useful during debugging.\n\nThe information has the form of an Erlang expression where QLCs most likely\noccur. Depending on the format functions of mentioned QLC tables, it is not\ncertain that the information is absolutely accurate.\n\nOptions:\n\n- The default is to return a sequence of QLCs in a block, but if option\n `{flat, false}` is specified, one single QLC is returned.\n- The default is to return a string, but if option `{format, abstract_code}` is\n specified, abstract code is returned instead. In the abstract code, port\n identifiers, references, and pids are represented by strings.\n- The default is to return all elements in lists, but if option\n `{n_elements, NElements}` is specified, only a limited number of elements are\n returned.\n- The default is to show all parts of objects and match specifications, but if\n option `{depth, Depth}` is specified, parts of terms below a certain depth are\n replaced by `'...'`.\n\n_Examples:_\n\nIn the following example two simple QLCs are inserted only to hold option\n`{unique, true}`:\n\n```erlang\n1> QH = qlc:q([{X,Y} || X <- [x,y], Y <- [a,b]]),\nio:format(\"~s~n\", [qlc:info(QH, unique_all)]).\nbegin\n V1 =\n qlc:q([\n SQV ||\n SQV <- [x, y]\n ],\n [{unique, true}]),\n V2 =\n qlc:q([\n SQV ||\n SQV <- [a, b]\n ],\n [{unique, true}]),\n qlc:q([\n {X,Y} ||\n X <- V1,\n Y <- V2\n ],\n [{unique, true}])\nend\n```\n\nIn the following example QLC `V2` has been inserted to show the joined\ngenerators and the join method chosen. A convention is used for lookup join: the\nfirst generator (`G2`) is the one traversed, the second (`G1`) is the table\nwhere constants are looked up.\n\n```erlang\n1> E1 = ets:new(e1, []),\nE2 = ets:new(e2, []),\ntrue = ets:insert(E1, [{1,a},{2,b}]),\ntrue = ets:insert(E2, [{a,1},{b,2}]),\nQ = qlc:q([{X,Z,W} ||\n{X, Z} <- ets:table(E1),\n{W, Y} <- ets:table(E2),\nX =:= Y]),\nio:format(\"~s~n\", [qlc:info(Q)]).\nbegin\n V1 =\n qlc:q([\n P0 ||\n P0 = {W, Y} <-\n ets:table(#Ref<0.3098908599.2283929601.256549>)\n ]),\n V2 =\n qlc:q([\n [G1 | G2] ||\n G2 <- V1,\n G1 <-\n ets:table(#Ref<0.3098908599.2283929601.256548>),\n element(2, G1) =:= element(1, G2)\n ],\n [{join, lookup}]),\n qlc:q([\n {X, Z, W} ||\n [{X, Z} | {W, Y}] <- V2\n ])\nend\n```","title":"qlc.info/2","ref":"qlc.html#info/2"},{"type":"function","doc":"","title":"qlc.keysort/2","ref":"qlc.html#keysort/2"},{"type":"function","doc":"Returns a query handle. When evaluating query handle `QH2`, the answers to query\nhandle `QH1` are sorted by `file_sorter:keysort/4` according to the options.\n\nThe sorter uses temporary files only if `QH1` does not evaluate to a list and\nthe size of the binary representation of the answers exceeds `Size` bytes, where\n`Size` is the value of option `size`.","title":"qlc.keysort/3","ref":"qlc.html#keysort/3"},{"type":"function","doc":"","title":"qlc.next_answers/1","ref":"qlc.html#next_answers/1"},{"type":"function","doc":"Returns some or all of the remaining answers to a query cursor. Only the owner\nof `QueryCursor` can retrieve answers.\n\nArgument `NumberOfAnswers` determines the maximum number of answers\nreturned. If less than the requested number of answers is\nreturned, subsequent calls to `next_answers` return `[]`.","title":"qlc.next_answers/2","ref":"qlc.html#next_answers/2"},{"type":"function","doc":"","title":"qlc.q/1","ref":"qlc.html#q/1"},{"type":"function","doc":"Returns a query handle for a QLC. The QLC must be the first argument to this\nfunction, otherwise it is evaluated as an ordinary list comprehension. It is\nalso necessary to add the following line to the source code:\n\n```erlang\n-include_lib(\"stdlib/include/qlc.hrl\").\n```\n\nThis causes a parse transform to substitute a fun for the QLC. The (compiled)\nfun is called when the query handle is evaluated.\n\nWhen calling `qlc:q/1,2` from the Erlang shell, the parse transform is\nautomatically called. When this occurs, the fun substituted for the QLC is not\ncompiled but is evaluated by `m:erl_eval`. This is also true when expressions\nare evaluated by `file:eval/1,2` or in the debugger.\n\nTo be explicit, this does not work:\n\n```erlang\n...\nA = [X || {X} <- [{1},{2}]],\nQH = qlc:q(A),\n...\n```\n\nVariable `A` is bound to the evaluated value of the list comprehension\n(`[1,2]`). The compiler complains with an error message (\"argument is not a\nquery list comprehension\"); the shell process stops with a `badarg` reason.\n\nOptions:\n\n- Option `{cache, ets}` can be used to cache the answers to a QLC. The answers\n are stored in one ETS table for each cached QLC. When a cached QLC is\n evaluated again, answers are fetched from the table without any further\n computations. Therefore, when all answers to a cached QLC have been found, the\n ETS tables used for caching answers to the qualifiers of the QLC can be\n emptied. Option `cache` is equivalent to `{cache, ets}`.\n- Option `{cache, list}` can be used to cache the answers to a QLC like\n `{cache, ets}`. The difference is that the answers are kept in a list (on the\n process heap). If the answers would occupy more than a certain amount of RAM\n memory, a temporary file is used for storing the answers. Option\n `max_list_size` sets the limit in bytes and the temporary file is put on the\n directory set by option `tmpdir`.\n\n Option `cache` has no effect if it is known that the QLC is to be evaluated at\n most once. This is always true for the top-most QLC and also for the list\n expression of the first generator in a list of qualifiers. Notice that in the\n presence of side effects in filters or callback functions, the answers to QLCs\n can be affected by option `cache`.\n\n- Option `{unique, true}` can be used to remove duplicate answers to a QLC. The\n unique answers are stored in one ETS table for each QLC. The table is emptied\n every time it is known that there are no more answers to the QLC. Option\n `unique` is equivalent to `{unique, true}`. If option `unique` is combined\n with option `{cache, ets}`, two ETS tables are used, but the full answers are\n stored in one table only. If option `unique` is combined with option\n `{cache, list}`, the answers are sorted twice using `keysort/3`; once to\n remove duplicates and once to restore the order.\n\nOptions `cache` and `unique` apply not only to the QLC itself but also to the\nresults of looking up constants, running match specifications, and joining\nhandles.\n\n_Example:_\n\nIn the following example the cached results of the merge join are traversed for\neach value of `A`. Notice that without option `cache` the join would have been\ncarried out three times, once for each value of `A`.\n\n```erlang\n1> Q = qlc:q([{A,X,Z,W} ||\nA <- [a,b,c],\n{X,Z} <- [{a,1},{b,4},{c,6}],\n{W,Y} <- [{2,a},{3,b},{4,c}],\nX =:= Y],\n{cache, list}),\nio:format(\"~s~n\", [qlc:info(Q)]).\nbegin\n V1 =\n qlc:q([\n P0 ||\n P0 = {X, Z} <-\n qlc:keysort(1, [{a, 1}, {b, 4}, {c, 6}], [])\n ]),\n V2 =\n qlc:q([\n P0 ||\n P0 = {W, Y} <-\n qlc:keysort(2, [{2, a}, {3, b}, {4, c}], [])\n ]),\n V3 =\n qlc:q([\n [G1 | G2] ||\n G1 <- V1,\n G2 <- V2,\n element(1, G1) == element(2, G2)\n ],\n [{join, merge}, {cache, list}]),\n qlc:q([\n {A, X, Z, W} ||\n A <- [a, b, c],\n [{X, Z} | {W, Y}] <- V3,\n X =:= Y\n ])\nend\n```\n\n[`sort/1,2`](`sort/1`) and [`keysort/2,3`](`keysort/2`) can also be used for\ncaching answers and for removing duplicates. When sorting answers are cached in\na list, possibly stored on a temporary file, and no ETS tables are used.\n\nSometimes (see `table/2`) traversal of tables can be done by looking up key\nvalues, which is assumed to be fast. Under certain (rare) circumstances there\ncan be too many key values to look up. [](){: #max_lookup } Option\n`{max_lookup, MaxLookup}` can then be used to limit the number of lookups: if\nmore than `MaxLookup` lookups would be required, no lookups are done but the\ntable is traversed instead. Defaults to `infinity`, which means that there is no\nlimit on the number of keys to look up.\n\n_Example:_\n\nIn the following example, using the `gb_table` module from section\n[Implementing a QLC Table](`m:qlc#implementing_a_qlc_table`), there are six keys\nto look up: `{1,a}`, `{1,b}`, `{1,c}`, `{2,a}`, `{2,b}`, and `{2,c}`. The reason\nis that the two elements of key `{X, Y}` are compared separately.\n\n```erlang\n1> T = gb_trees:empty(),\nQH = qlc:q([X || {{X,Y},_} <- gb_table:table(T),\n((X == 1) or (X == 2)) andalso\n((Y == a) or (Y == b) or (Y == c))]),\nio:format(\"~s~n\", [qlc:info(QH)]).\nets:match_spec_run(\n lists:flatmap(fun(K) ->\n case\n gb_trees:lookup(K,\n gb_trees:from_orddict([]))\n of\n {value, V} ->\n [{K, V}];\n none ->\n []\n end\n end,\n [{1, a},\n {1, b},\n {1, c},\n {2, a},\n {2, b},\n {2, c}]),\n ets:match_spec_compile([{{{'$1', '$2'}, '_'},\n [],\n ['$1']}]))\n```\n\nOptions:\n\n- Option `{lookup, true}` can be used to ensure that the `qlc` module looks up\n constants in some QLC table. If there are more than one QLC table among the\n list expressions of the generators, constants must be looked up in at least\n one of the tables. The evaluation of the query fails if there are no constants\n to look up. This option is useful when it would be unacceptable to traverse\n all objects in some table. Setting option `lookup` to `false` ensures that no\n constants are looked up (`{max_lookup, 0}` has the same effect). Defaults to\n `any`, which means that constants are looked up whenever possible.\n- Option `{join, Join}` can be used to ensure that a certain join method is\n used:\n\n - `{join, lookup}` invokes the lookup join method.\n - `{join, merge}` invokes the merge join method.\n - `{join, nested_loop}` invokes the method of matching every pair of objects\n from two handles. This method is mostly very slow.\n\n The evaluation of the query fails if the `qlc` module cannot carry out the\n chosen join method. Defaults to `any`, which means that some fast join method\n is used if possible.","title":"qlc.q/2","ref":"qlc.html#q/2"},{"type":"function","doc":"","title":"qlc.sort/1","ref":"qlc.html#sort/1"},{"type":"function","doc":"Returns a query handle. When evaluating query handle `QH2`, the answers to query\nhandle `QH1` are sorted by `file_sorter:sort/3` according to the options.\n\nThe sorter uses temporary files only if `QH1` does not evaluate to a list and\nthe size of the binary representation of the answers exceeds `Size` bytes, where\n`Size` is the value of option `size`.","title":"qlc.sort/2","ref":"qlc.html#sort/2"},{"type":"function","doc":"","title":"qlc.string_to_handle/1","ref":"qlc.html#string_to_handle/1"},{"type":"function","doc":"","title":"qlc.string_to_handle/2","ref":"qlc.html#string_to_handle/2"},{"type":"function","doc":"A string version of [`q/1,2`](`q/1`). When the query handle is evaluated, the\nfun created by the parse transform is interpreted by `m:erl_eval`. The query\nstring is to be one single QLC terminated by a period.\n\n_Example:_\n\n```erlang\n1> L = [1,2,3],\nBs = erl_eval:add_binding('L', L, erl_eval:new_bindings()),\nQH = qlc:string_to_handle(\"[X+1 || X <- L].\", [], Bs),\nqlc:eval(QH).\n[2,3,4]\n```\n\nThis function is probably mainly useful when called from outside of Erlang, for\nexample from a driver written in C.\n\n> #### Note {: .info }\n>\n> Query handles created this way may have worse performance than when created\n> directly via [`q/1,2`](`q/1`).","title":"qlc.string_to_handle/3","ref":"qlc.html#string_to_handle/3"},{"type":"function","doc":"Returns a query handle for a QLC table. In Erlang/OTP there is support for ETS,\nDets, and Mnesia tables, but many other data structures can be turned into QLC\ntables. This is accomplished by letting function(s) in the module implementing\nthe data structure create a query handle by calling `qlc:table/2`.\n\nThe different ways to traverse the table and properties of the table are handled\nby callback functions provided as options to `qlc:table/2`.\n\n- Callback function `TraverseFun` is used for traversing the table. It is to\n return a list of objects terminated by either `[]` or a nullary fun to be used\n for traversing the not yet traversed objects of the table. Any other return\n value is immediately returned as value of the query evaluation. Unary\n `TraverseFun`s are to accept a match specification as argument. The match\n specification is created by the parse transform by analyzing the pattern of\n the generator calling `qlc:table/2` and filters using variables introduced in\n the pattern. If the parse transform cannot find a match specification\n equivalent to the pattern and filters, `TraverseFun` is called with a match\n specification returning every object.\n\n - Modules that can use match specifications for optimized traversal of tables\n are to call `qlc:table/2` with an unary `TraverseFun`. An example is\n `ets:table/2`.\n - Other modules can provide a nullary `TraverseFun`. An example is\n [`gb_table:table/1`](`m:qlc#gb_table`) in section\n [Implementing a QLC Table](`m:qlc#implementing_a_qlc_table`).\n\n- Unary callback function `PreFun` is called once before the table is read for\n the first time. If the call fails, the query evaluation fails.\n\n Argument `PreArgs` is a list of tagged values. There are two tags,\n `parent_value` and `stop_fun`, used by Mnesia for managing transactions.\n\n - The value of `parent_value` is the value returned by `ParentFun`, or\n `undefined` if there is no `ParentFun`. `ParentFun` is called once just\n before the call of `PreFun` in the context of the process calling\n [`eval/1,2`](`eval/1`), [`fold/3,4`](`fold/3`), or\n [`cursor/1,2`](`cursor/1`).\n - The value of `stop_fun` is a nullary fun that deletes the cursor if called\n from the parent, or `undefined` if there is no cursor.\n\n- Nullary callback function `PostFun` is called once after the table was last\n read. The return value, which is caught, is ignored. If `PreFun` has been\n called for a table, `PostFun` is guaranteed to be called for that table, even\n if the evaluation of the query fails for some reason.\n\n The pre (post) functions for different tables are evaluated in unspecified\n order.\n\n Other table access than reading, such as calling `InfoFun`, is assumed to be\n OK at any time.\n\n- [](){: #lookup_fun } Binary callback function `LookupFun` is used for looking\n up objects in the table. The first argument `Position` is the key position or\n an indexed position and the second argument `Keys` is a sorted list of unique\n values. The return value is to be a list of all objects (tuples), such that\n the element at `Position` is a member of `Keys`. Any other return value is\n immediately returned as value of the query evaluation. `LookupFun` is called\n instead of traversing the table if the parse transform at compile time can\n determine that the filters match and compare the element at `Position` in such\n a way that only `Keys` need to be looked up to find all potential answers.\n\n The key position is obtained by calling `InfoFun(keypos)` and the indexed\n positions by calling `InfoFun(indices)`. If the key position can be used for\n lookup, it is always chosen, otherwise the indexed position requiring the\n least number of lookups is chosen. If there is a tie between two indexed\n positions, the one occurring first in the list returned by `InfoFun` is\n chosen. Positions requiring more than [max_lookup](`m:qlc#max_lookup`) lookups\n are ignored.\n\n- Unary callback function `InfoFun` is to return information about the table.\n `undefined` is to be returned if the value of some tag is unknown:\n\n - **`indices`** - Returns a list of indexed positions, a list of positive\n integers.\n\n - **`is_unique_objects`** - Returns `true` if the objects returned by\n `TraverseFun` are unique.\n\n - **`keypos`** - Returns the position of the table key, a positive integer.\n\n - **`is_sorted_key`** - Returns `true` if the objects returned by\n `TraverseFun` are sorted on the key.\n\n - **`num_of_objects`** - Returns the number of objects in the table, a\n non-negative integer.\n\n- Unary callback function `FormatFun` is used by [`info/1,2`](`info/1`) for\n displaying the call that created the query handle of the table. Defaults to\n `undefined`, which means that `info/1,2` displays a call to `'$MOD':'$FUN'/0`.\n It is up to `FormatFun` to present the selected objects of the table in a\n suitable way. However, if a character list is chosen for presentation, it must\n be an Erlang expression that can be scanned and parsed (a trailing dot is\n added by `info/1,2` though).\n\n `FormatFun` is called with an argument that describes the selected objects\n based on optimizations done as a result of analyzing the filters of the QLC\n where the call to `qlc:table/2` occurs. The argument can have the following\n values:\n\n - **`{lookup, Position, Keys, NElements, DepthFun}`.** - `LookupFun` is used\n for looking up objects in the table.\n\n - **`{match_spec, MatchExpression}`** - No way of finding all possible answers\n by looking up keys was found, but the filters could be transformed into a\n match specification. All answers are found by calling\n `TraverseFun(MatchExpression)`.\n\n - **`{all, NElements, DepthFun}`** - No optimization was found. A match\n specification matching all objects is used if `TraverseFun` is unary.\n\n `NElements` is the value of the `info/1,2` option `n_elements`.\n\n `DepthFun` is a function that can be used for limiting the size of terms;\n calling `DepthFun(Term)` substitutes `'...'` for parts of `Term` below the\n depth specified by the `info/1,2` option `depth`.\n\n If calling `FormatFun` with an argument including `NElements` and `DepthFun`\n fails, `FormatFun` is called once again with an argument excluding\n `NElements` and `DepthFun` (`{lookup, Position, Keys}` or `all`).\n\n- [](){: #key_equality } The value of option `key_equality` is to be `'=:='` if\n the table considers two keys equal if they match, and to be `'=='` if two keys\n are equal if they compare equal. Defaults to `'=:='`.\n\nFor the various options recognized by `table/1,2` in respective module, see\n[`ets`](`ets:table/1`), [`dets`](`dets:table/1`), and\n[`mnesia`](`mnesia:table/1`).","title":"qlc.table/2","ref":"qlc.html#table/2"},{"type":"type","doc":"Parse trees for Erlang expression, see section\n[The Abstract Format](`e:erts:absform.md`) in the ERTS User's Guide.","title":"qlc.abstract_expr/0","ref":"qlc.html#t:abstract_expr/0"},{"type":"type","doc":"","title":"qlc.answer/0","ref":"qlc.html#t:answer/0"},{"type":"type","doc":"","title":"qlc.answers/0","ref":"qlc.html#t:answers/0"},{"type":"type","doc":"","title":"qlc.cache/0","ref":"qlc.html#t:cache/0"},{"type":"type","doc":"","title":"qlc.key_pos/0","ref":"qlc.html#t:key_pos/0"},{"type":"type","doc":"Match specification, see section\n[Match Specifications in Erlang](`e:erts:match_spec.md`) in the ERTS User's\nGuide and `m:ms_transform`.","title":"qlc.match_expression/0","ref":"qlc.html#t:match_expression/0"},{"type":"type","doc":"","title":"qlc.max_list_size/0","ref":"qlc.html#t:max_list_size/0"},{"type":"type","doc":"An integer > 1.","title":"qlc.no_files/0","ref":"qlc.html#t:no_files/0"},{"type":"type","doc":"","title":"qlc.order/0","ref":"qlc.html#t:order/0"},{"type":"type","doc":"","title":"qlc.order_fun/0","ref":"qlc.html#t:order_fun/0"},{"type":"opaque","doc":"A [query cursor](`m:qlc#query_cursor`).","title":"qlc.query_cursor/0","ref":"qlc.html#t:query_cursor/0"},{"type":"opaque","doc":"A [query handle](`m:qlc#query_handle`).","title":"qlc.query_handle/0","ref":"qlc.html#t:query_handle/0"},{"type":"type","doc":"","title":"qlc.query_handle_or_list/0","ref":"qlc.html#t:query_handle_or_list/0"},{"type":"type","doc":"A literal [query list comprehension](`m:qlc#query_list_comprehension`).","title":"qlc.query_list_comprehension/0","ref":"qlc.html#t:query_list_comprehension/0"},{"type":"type","doc":"See `m:file_sorter` for a description of the options.","title":"qlc.sort_option/0","ref":"qlc.html#t:sort_option/0"},{"type":"type","doc":"","title":"qlc.sort_options/0","ref":"qlc.html#t:sort_options/0"},{"type":"type","doc":"","title":"qlc.spawn_options/0","ref":"qlc.html#t:spawn_options/0"},{"type":"type","doc":"","title":"qlc.tmp_directory/0","ref":"qlc.html#t:tmp_directory/0"},{"type":"type","doc":"","title":"qlc.tmp_file_usage/0","ref":"qlc.html#t:tmp_file_usage/0"},{"type":"module","doc":"Abstract data type for FIFO queues.\n\nThis module provides (double-ended) FIFO queues in an efficient manner.\n\nAll functions fail with reason `badarg` if arguments are of wrong type, for\nexample, queue arguments are not queues, indexes are not integers, and list\narguments are not lists. Improper lists cause internal crashes. An index out of\nrange for a queue also causes a failure with reason `badarg`.\n\nSome functions, where noted, fail with reason `empty` for an empty queue.\n\nThe data representing a queue as used by this module is to be regarded as opaque\nby other modules. In abstract terms, the representation is a composite type of\nexisting Erlang terms. See note on\n[data types](`e:system:data_types.md#no_user_types`). Any code assuming\nknowledge of the format is running on thin ice.\n\nAll operations have an amortized O(1) running time, except `all/2`, `any/2`,\n`delete/2`, `delete_r/2`, `delete_with/2`, `delete_with_r/2`, `filter/2`,\n`filtermap/2`, `fold/3`, `join/2`, `len/1`, `member/2`, `split/2` that have\nO(n). To minimize the size of a queue minimizing the amount of garbage built by\nqueue operations, the queues do not contain explicit length information, and\nthat is why [`len/1`](`len/1`) is O(n). If better performance for this\nparticular operation is essential, it is easy for the caller to keep track of\nthe length.\n\nQueues are double-ended. The mental picture of a queue is a line of people\n(items) waiting for their turn. The queue front is the end with the item that\nhas waited the longest. The queue rear is the end an item enters when it starts\nto wait. If instead using the mental picture of a list, the front is called head\nand the rear is called tail.\n\nEntering at the front and exiting at the rear are reverse operations on the\nqueue.\n\nThis module has three sets of interface functions: the _\"Original API\"_, the\n_\"Extended API\"_, and the _\"Okasaki API\"_.\n\nThe \"Original API\" and the \"Extended API\" both use the mental picture of a\nwaiting line of items. Both have reverse operations suffixed \"\\_r\".\n\nThe \"Original API\" item removal functions return compound terms with both the\nremoved item and the resulting queue. The \"Extended API\" contains alternative\nfunctions that build less garbage and functions for just inspecting the queue\nends. Also the \"Okasaki API\" functions build less garbage.\n\nThe \"Okasaki API\" is inspired by \"Purely Functional Data Structures\" by Chris\nOkasaki. It regards queues as lists. This API is by many regarded as strange and\navoidable. For example, many reverse operations have lexically reversed names,\nsome with more readable but perhaps less understandable aliases.","title":"queue","ref":"queue.html"},{"type":"function","doc":"Returns `true` if `Pred(Item)` returns `true` for all items `Item` in `Q`,\notherwise `false`.\n\n_Example:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5]).\n2> queue:all(fun (E) -> E > 3 end, Queue).\nfalse\n3> queue:all(fun (E) -> E > 0 end, Queue).\ntrue\n```","title":"queue.all/2","ref":"queue.html#all/2"},{"type":"function","doc":"Returns `true` if `Pred(Item)` returns `true` for at least one item `Item` in\n`Q`, otherwise `false`.\n\n_Example:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5]).\n2> queue:any(fun (E) -> E > 10 end, Queue).\nfalse\n3> queue:any(fun (E) -> E > 3 end, Queue).\ntrue\n```","title":"queue.any/2","ref":"queue.html#any/2"},{"type":"function","doc":"Inserts `Item` at the head of queue `Q1`. Returns the new queue `Q2`.\n\n_Example:_\n\n```erlang\n1> Queue = queue:cons(0, queue:from_list([1,2,3])).\n{[3,2],[0,1]}\n2> queue:to_list(Queue).\n[0,1,2,3]\n```","title":"queue.cons/2","ref":"queue.html#cons/2"},{"type":"function","doc":"Returns the tail item of queue `Q`.\n\nFails with reason `empty` if `Q` is empty.\n\n_Example 1:_\n\n```erlang\n1> queue:daeh(queue:from_list([1,2,3])).\n3\n```","title":"queue.daeh/1","ref":"queue.html#daeh/1"},{"type":"function","doc":"Returns a copy of `Q1` where the first item matching `Item` is deleted, if there\nis such an item.\n\n_Example:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5]).\n2> Queue1 = queue:delete(3, Queue).\n3> queue:member(3, Queue1).\nfalse\n```","title":"queue.delete/2","ref":"queue.html#delete/2"},{"type":"function","doc":"Returns a copy of `Q1` where the last item matching `Item` is deleted, if there\nis such an item.\n\n_Example:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,3,5]).\n2> Queue1 = queue:delete_r(3, Queue).\n3> queue:to_list(Queue1).\n[1,2,3,4,5]\n```","title":"queue.delete_r/2","ref":"queue.html#delete_r/2"},{"type":"function","doc":"Returns a copy of `Q1` where the first item for which `Pred` returns `true` is\ndeleted, if there is such an item.\n\n_Example:_\n\n```erlang\n1> Queue = queue:from_list([100,1,2,3,4,5]).\n2> Queue1 = queue:delete_with(fun (E) -> E > 0, Queue).\n3> queue:to_list(Queue1).\n[1,2,3,4,5]\n```","title":"queue.delete_with/2","ref":"queue.html#delete_with/2"},{"type":"function","doc":"Returns a copy of `Q1` where the last item for which `Pred` returns `true` is\ndeleted, if there is such an item.\n\n_Example:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5,100]).\n2> Queue1 = queue:delete_with(fun (E) -> E > 10, Queue).\n3> queue:to_list(Queue1).\n[1,2,3,4,5]\n```","title":"queue.delete_with_r/2","ref":"queue.html#delete_with_r/2"},{"type":"function","doc":"Returns a queue `Q2` that is the result of removing the front item from `Q1`.\n\nFails with reason `empty` if `Q1` is empty.\n\n_Example:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5]).\n{[5,4,3],[1,2]}\n2> Queue = queue:drop(Queue).\n{[5,4,3],[2]}\n3> queue:to_list(Queue1).\n[2,3,4,5]\n```","title":"queue.drop/1","ref":"queue.html#drop/1"},{"type":"function","doc":"Returns a queue `Q2` that is the result of removing the rear item from `Q1`.\n\nFails with reason `empty` if `Q1` is empty.\n\n_Example:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5]).\n{[5,4,3],[1,2]}\n2> Queue = queue:drop_r(Queue).\n{[4,3],[1,2]}\n3> queue:to_list(Queue1).\n[1,2,3,4]\n```","title":"queue.drop_r/1","ref":"queue.html#drop_r/1"},{"type":"function","doc":"Returns a queue `Q2` that is the result of calling `Fun(Item)` on all items in\n`Q1`.\n\nIf `Fun(Item)` returns `true`, `Item` is copied to the result queue. If it\nreturns `false`, `Item` is not copied. If it returns a list, the list elements\nare inserted instead of `Item` in the result queue.\n\n_Example 1:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5]).\n{[5,4,3],[1,2]}\n2> Queue1 = queue:filter(fun (E) -> E > 2 end, Queue).\n{[5],[3,4]}\n3> queue:to_list(Queue1).\n[3,4,5]\n```\n\nSo, `Fun(Item)` returning `[Item]` is thereby semantically equivalent to\nreturning `true`, just as returning `[]` is semantically equivalent to returning\n`false`. But returning a list builds more garbage than returning an atom.\n\n_Example 2:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5]).\n{[5,4,3],[1,2]}\n2> Queue1 = queue:filter(fun (E) -> [E, E+1] end, Queue).\n{[6,5,5,4,4,3],[1,2,2,3]}\n3> queue:to_list(Queue1).\n[1,2,2,3,3,4,4,5,5,6]\n```","title":"queue.filter/2","ref":"queue.html#filter/2"},{"type":"function","doc":"Returns a queue `Q2` that is the result of calling `Fun(Item)` on all items in\n`Q1`.\n\nIf `Fun(Item)` returns `true`, `Item` is copied to the result queue. If it\nreturns `false`, `Item` is not copied. If it returns `{true, NewItem}`, the\nqueue element at this position is replaced with `NewItem` in the result queue.\n\n_Example 1:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5]).\n{[5,4,3],[1,2]}\n2> Queue1 = queue:filtermap(fun (E) -> E > 2 end, Queue).\n{[5],[3,4]}\n3> queue:to_list(Queue1).\n[3,4,5]\n4> Queue1 = queue:filtermap(fun (E) -> {true, E+100} end, Queue).\n{\"ihg\",\"ef\"}\n5> queue:to_list(Queue1).\n\"efghi\n```","title":"queue.filtermap/2","ref":"queue.html#filtermap/2"},{"type":"function","doc":"Calls `Fun(Item, AccIn)` on successive items `Item` of `Queue`, starting with\n`AccIn == Acc0`. The queue is traversed in queue order, that is, from front to\nrear. `Fun/2` must return a new accumulator, which is passed to the next call.\nThe function returns the final value of the accumulator. `Acc0` is returned if\nthe queue is empty.\n\n_Example:_\n\n```erlang\n1> queue:fold(fun(X, Sum) -> X + Sum end, 0, queue:from_list([1,2,3,4,5])).\n15\n2> queue:fold(fun(X, Prod) -> X * Prod end, 1, queue:from_list([1,2,3,4,5])).\n120\n```","title":"queue.fold/3","ref":"queue.html#fold/3"},{"type":"function","doc":"Returns a queue containing the items in `L` in the same order; the head item of\nthe list becomes the front item of the queue.","title":"queue.from_list/1","ref":"queue.html#from_list/1"},{"type":"function","doc":"Returns `Item` at the front of queue `Q`.\n\nFails with reason `empty` if `Q` is empty.\n\n_Example 1:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5]).\n{[5,4,3],[1,2]}\n2> 1 == queue:get(Queue).\ntrue\n```","title":"queue.get/1","ref":"queue.html#get/1"},{"type":"function","doc":"Returns `Item` at the rear of queue `Q`.\n\nFails with reason `empty` if `Q` is empty.\n\n_Example 1:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5]).\n{[5,4,3],[1,2]}\n2> 5 == queue:get_r(Queue).\ntrue\n```","title":"queue.get_r/1","ref":"queue.html#get_r/1"},{"type":"function","doc":"Returns `Item` from the head of queue `Q`.\n\nFails with reason `empty` if `Q` is empty.\n\n_Example 1:_\n\n```erlang\n1> queue:head(queue:from_list([1,2,3])).\n1\n```","title":"queue.head/1","ref":"queue.html#head/1"},{"type":"function","doc":"Inserts `Item` at the rear of queue `Q1`. Returns the resulting queue `Q2`.\n\n_Example:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5]).\n{[5,4,3],[1,2]}\n2> Queue1 = queue:in(100, Queue).\n{[100,5,4,3],[1,2]}\n3> queue:to_list(Queue1).\n[1,2,3,4,5,100]\n```","title":"queue.in/2","ref":"queue.html#in/2"},{"type":"function","doc":"Inserts `Item` at the front of queue `Q1`. Returns the resulting queue `Q2`.\n\n_Example:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5]).\n{[5,4,3],[1,2]}\n2> Queue1 = queue:in_r(100, Queue).\n{[5,4,3],[100,1,2]}\n3> queue:to_list(Queue1).\n[100,1,2,3,4,5]\n```","title":"queue.in_r/2","ref":"queue.html#in_r/2"},{"type":"function","doc":"Returns a queue `Q2` that is the result of removing the tail item from `Q1`.\n\nFails with reason `empty` if `Q1` is empty.\n\n_Example:_\n\n```erlang\n1> Queue = queue:init(queue:from_list([1,2,3])).\n{[2],[1]}\n2> queue:to_list(Queue).\n[1,2]\n```","title":"queue.init/1","ref":"queue.html#init/1"},{"type":"function","doc":"Tests if `Q` is empty and returns `true` if so, otherwise `false`.","title":"queue.is_empty/1","ref":"queue.html#is_empty/1"},{"type":"function","doc":"Tests if `Term` is a queue and returns `true` if so, otherwise `false`. Note\nthat the test will return `true` for a term coinciding with the representation\nof a queue, even when not constructed by thus module. See also note on\n[data types](`e:system:data_types.md#no_user_types`).","title":"queue.is_queue/1","ref":"queue.html#is_queue/1"},{"type":"function","doc":"Returns a queue `Q3` that is the result of joining `Q1` and `Q2` with `Q1` in\nfront of `Q2`.\n\n_Example:_\n\n```erlang\n1> Queue1 = queue:from_list([1,3]).\n{[3],[1]}\n2> Queue2 = queue:from_list([2,4]).\n{[4],[2]}\n3> queue:to_list(queue:join(Queue1, Queue2)).\n[1,3,2,4]\n```","title":"queue.join/2","ref":"queue.html#join/2"},{"type":"function","doc":"Returns a queue `Q2` that is the result of removing the tail item from `Q1`.\n\nFails with reason `empty` if `Q1` is empty.\n\nThe name [`lait/1`](`lait/1`) is a misspelling - do not use it anymore.","title":"queue.lait/1","ref":"queue.html#lait/1"},{"type":"function","doc":"Returns the tail item of queue `Q`.\n\nFails with reason `empty` if `Q` is empty.\n\n_Example:_\n\n```erlang\n1> queue:last(queue:from_list([1,2,3])).\n3\n```","title":"queue.last/1","ref":"queue.html#last/1"},{"type":"function","doc":"Calculates and returns the length of queue `Q`.","title":"queue.len/1","ref":"queue.html#len/1"},{"type":"function","doc":"Returns a queue `Q2` that is the result of removing the tail item from `Q1`.\n\nFails with reason `empty` if `Q1` is empty.\n\n_Example:_\n\n```erlang\n1> Queue = queue:liat(queue:from_list([1,2,3])).\n{[2],[1]}\n2> queue:to_list(Queue).\n[1,2]\n```","title":"queue.liat/1","ref":"queue.html#liat/1"},{"type":"function","doc":"Returns `true` if `Item` matches some element in `Q`, otherwise `false`.","title":"queue.member/2","ref":"queue.html#member/2"},{"type":"function","doc":"Returns an empty queue.","title":"queue.new/0","ref":"queue.html#new/0"},{"type":"function","doc":"Removes the item at the front of queue `Q1`. Returns tuple\n`{{value, Item}, Q2}`, where `Item` is the item removed and `Q2` is the\nresulting queue. If `Q1` is empty, tuple `{empty, Q1}` is returned.\n\n_Example:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5]).\n{[5,4,3],[1,2]}\n2> {{value, 1=Item}, Queue1} = queue:out(Queue).\n{{value,1},{[5,4,3],[2]}}\n3> queue:to_list(Queue1).\n[2,3,4,5]\n```","title":"queue.out/1","ref":"queue.html#out/1"},{"type":"function","doc":"Removes the item at the rear of queue `Q1`. Returns tuple `{{value, Item}, Q2}`,\nwhere `Item` is the item removed and `Q2` is the new queue. If `Q1` is empty,\ntuple `{empty, Q1}` is returned.\n\n_Example:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5]).\n{[5,4,3],[1,2]}\n2> {{value, 5=Item}, Queue1} = queue:out_r(Queue).\n{{value,5},{[4,3],[1,2]}}\n3> queue:to_list(Queue1).\n[1,2,3,4]\n```","title":"queue.out_r/1","ref":"queue.html#out_r/1"},{"type":"function","doc":"Returns tuple `{value, Item}`, where `Item` is the front item of `Q`, or `empty`\nif `Q` is empty.\n\n_Example 1:_\n\n```erlang\n1> queue:peek(queue:new()).\nempty\n2> Queue = queue:from_list([1,2,3,4,5]).\n{[5,4,3],[1,2]}\n3> queue:peek(Queue).\n{value, 1}\n```","title":"queue.peek/1","ref":"queue.html#peek/1"},{"type":"function","doc":"Returns tuple `{value, Item}`, where `Item` is the rear item of `Q`, or `empty`\nif `Q` is empty.\n\n_Example 1:_\n\n```erlang\n1> queue:peek_r(queue:new()).\nempty\n2> Queue = queue:from_list([1,2,3,4,5]).\n{[5,4,3],[1,2]}\n3> queue:peek_r(Queue).\n{value, 5}\n```","title":"queue.peek_r/1","ref":"queue.html#peek_r/1"},{"type":"function","doc":"Returns a queue `Q2` containing the items of `Q1` in the reverse order.","title":"queue.reverse/1","ref":"queue.html#reverse/1"},{"type":"function","doc":"Inserts `Item` as the tail item of queue `Q1`. Returns the new queue `Q2`.\n\n_Example:_\n\n```erlang\n1> Queue = queue:snoc(queue:from_list([1,2,3]), 4).\n{[4,3,2],[1]}\n2> queue:to_list(Queue).\n[1,2,3,4]\n```","title":"queue.snoc/2","ref":"queue.html#snoc/2"},{"type":"function","doc":"Splits `Q1` in two. The `N` front items are put in `Q2` and the rest in `Q3`.","title":"queue.split/2","ref":"queue.html#split/2"},{"type":"function","doc":"Returns a queue `Q2` that is the result of removing the head item from `Q1`.\n\nFails with reason `empty` if `Q1` is empty.","title":"queue.tail/1","ref":"queue.html#tail/1"},{"type":"function","doc":"Returns a list of the items in the queue in the same order; the front item of\nthe queue becomes the head of the list.\n\n_Example:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5]).\n{[5,4,3],[1,2]}\n2> List == queue:to_list(Queue).\ntrue\n```","title":"queue.to_list/1","ref":"queue.html#to_list/1"},{"type":"type","doc":"","title":"queue.queue/0","ref":"queue.html#t:queue/0"},{"type":"opaque","doc":"As returned by `new/0`.","title":"queue.queue/1","ref":"queue.html#t:queue/1"},{"type":"module","doc":"Sets are collections of elements with no duplicate elements.\n\nThe data representing a set as used by this module is to be regarded as opaque\nby other modules. In abstract terms, the representation is a composite type of\nexisting Erlang terms. See note on\n[data types](`e:system:data_types.md#no_user_types`). Any code assuming\nknowledge of the format is running on thin ice.\n\nThis module provides the same interface as the `m:ordsets` module but with an\nundefined representation. One difference is that while this module considers two\nelements as different if they do not match (`=:=`), `ordsets` considers two\nelements as different if and only if they do not compare equal (`==`).\n\nErlang/OTP 24.0 introduced a new more performant representation for sets which\nhas become the default in Erlang/OTP 28. Developers can use the old representation\nby passing the `{version, 1}` flag to `new/1` and `from_list/2`. Functions that\nwork on two sets, such as `union/2`, will work with sets of different\nversions. In such cases, there is no guarantee about the version of the returned set.\nExplicit conversion from the old version to the new one can be done with\n`sets:from_list(sets:to_list(Old), [{version,2}])`.","title":"sets","ref":"sets.html"},{"type":"module","doc":"The following functions in this module also exist and provide the same\nfunctionality in the `m:gb_sets` and `m:ordsets` modules. That is, by only\nchanging the module name for each call, you can try out different set\nrepresentations.\n\n- `add_element/2`\n- `del_element/2`\n- `filter/2`\n- `filtermap/2`\n- `fold/3`\n- `from_list/1`\n- `intersection/1`\n- `intersection/2`\n- `is_element/2`\n- `is_empty/1`\n- `is_equal/2`\n- `is_set/1`\n- `is_subset/2`\n- `map/2`\n- `new/0`\n- `size/1`\n- `subtract/2`\n- `to_list/1`\n- `union/1`\n- `union/2`\n\n> #### Note {: .info }\n>\n> While the three set implementations offer the same _functionality_ with\n> respect to the aforementioned functions, their overall _behavior_ may differ.\n> As mentioned, this module considers elements as different if and only if they\n> do not match (`=:=`), while both `m:ordsets` and `m:gb_sets` consider elements\n> as different if and only if they do not compare equal (`==`).\n>\n> _Example:_\n>\n> ```erlang\n> 1> sets:is_element(1.0, sets:from_list([1])).\n> false\n> 2> ordsets:is_element(1.0, ordsets:from_list([1])).\n> true\n> 2> gb_sets:is_element(1.0, gb_sets:from_list([1])).\n> true\n> ```","title":"Compatibility - sets","ref":"sets.html#module-compatibility"},{"type":"module","doc":"`m:gb_sets`, `m:ordsets`","title":"See Also - sets","ref":"sets.html#module-see-also"},{"type":"function","doc":"Returns a new set formed from `Set1` with `Element` inserted.","title":"sets.add_element/2","ref":"sets.html#add_element/2"},{"type":"function","doc":"Returns `Set1`, but with `Element` removed.","title":"sets.del_element/2","ref":"sets.html#del_element/2"},{"type":"function","doc":"Filters elements in `Set1` with boolean function `Pred`.","title":"sets.filter/2","ref":"sets.html#filter/2"},{"type":"function","doc":"Filters and maps elements in `Set1` with function `Fun`.","title":"sets.filtermap/2","ref":"sets.html#filtermap/2"},{"type":"function","doc":"Folds `Function` over every element in `Set` and returns the final value of the\naccumulator. The evaluation order is undefined.","title":"sets.fold/3","ref":"sets.html#fold/3"},{"type":"function","doc":"Returns a set of the elements in `List`.","title":"sets.from_list/1","ref":"sets.html#from_list/1"},{"type":"function","doc":"Returns a set of the elements in `List` at the given version.","title":"sets.from_list/2","ref":"sets.html#from_list/2"},{"type":"function","doc":"Returns the intersection of the non-empty list of sets.","title":"sets.intersection/1","ref":"sets.html#intersection/1"},{"type":"function","doc":"Returns the intersection of `Set1` and `Set2`.","title":"sets.intersection/2","ref":"sets.html#intersection/2"},{"type":"function","doc":"Returns `true` if `Set1` and `Set2` are disjoint (have no elements in common),\notherwise `false`.","title":"sets.is_disjoint/2","ref":"sets.html#is_disjoint/2"},{"type":"function","doc":"Returns `true` if `Element` is an element of `Set`, otherwise `false`.","title":"sets.is_element/2","ref":"sets.html#is_element/2"},{"type":"function","doc":"Returns `true` if `Set` is an empty set, otherwise `false`.","title":"sets.is_empty/1","ref":"sets.html#is_empty/1"},{"type":"function","doc":"Returns `true` if `Set1` and `Set2` are equal, that is when every element of one\nset is also a member of the respective other set, otherwise `false`.","title":"sets.is_equal/2","ref":"sets.html#is_equal/2"},{"type":"function","doc":"Returns `true` if `Set` appears to be a set of elements, otherwise `false`.\n\nNote that the test is shallow and will return `true` for any term that coincides with\nthe possible representations of a set. See also note on [data types](`e:system:data_types.md#no_user_types`).","title":"sets.is_set/1","ref":"sets.html#is_set/1"},{"type":"function","doc":"Returns `true` when every element of `Set1` is also a member of `Set2`,\notherwise `false`.","title":"sets.is_subset/2","ref":"sets.html#is_subset/2"},{"type":"function","doc":"Maps elements in `Set1` with mapping function `Fun`.","title":"sets.map/2","ref":"sets.html#map/2"},{"type":"function","doc":"Returns a new empty set.","title":"sets.new/0","ref":"sets.html#new/0"},{"type":"function","doc":"Returns a new empty set at the given version.","title":"sets.new/1","ref":"sets.html#new/1"},{"type":"function","doc":"Returns the number of elements in `Set`.","title":"sets.size/1","ref":"sets.html#size/1"},{"type":"function","doc":"Returns only the elements of `Set1` that are not also elements of `Set2`.","title":"sets.subtract/2","ref":"sets.html#subtract/2"},{"type":"function","doc":"Returns the elements of `Set` as a list. The order of the returned elements is\nundefined.","title":"sets.to_list/1","ref":"sets.html#to_list/1"},{"type":"function","doc":"Returns the merged (union) set of the list of sets.","title":"sets.union/1","ref":"sets.html#union/1"},{"type":"function","doc":"Returns the merged (union) set of `Set1` and `Set2`.","title":"sets.union/2","ref":"sets.html#union/2"},{"type":"type","doc":"","title":"sets.set/0","ref":"sets.html#t:set/0"},{"type":"opaque","doc":"As returned by `new/0`.","title":"sets.set/1","ref":"sets.html#t:set/1"},{"type":"module","doc":"Functions for manipulating sets of sets.\n\nThis module provides operations on finite sets and relations represented as\nsets. Intuitively, a set is a collection of elements; every element belongs to\nthe set, and the set contains every element.\n\nThe data representing `sofs` as used by this module is to be regarded as opaque\nby other modules. In abstract terms, the representation is a composite type of\nexisting Erlang terms. See note on\n[data types](`e:system:data_types.md#no_user_types`). Any code assuming\nknowledge of the format is running on thin ice.\n\nGiven a set A and a sentence S(x), where x is a free variable, a new set B whose\nelements are exactly those elements of A for which S(x) holds can be formed,\nthis is denoted B = \\{x in A : S(x)\\}. Sentences are expressed using the logical\noperators \"for some\" (or \"there exists\"), \"for all\", \"and\", \"or\", \"not\". If the\nexistence of a set containing all the specified elements is known (as is always\nthe case in this module), this is denoted B = \\{x : S(x)\\}.\n\n- The _unordered set_ containing the elements a, b, and c is denoted\n \\{a, b, c\\}. This notation is not to be confused with tuples.\n\n The _ordered pair_ of a and b, with first _coordinate_ a and second coordinate\n b, is denoted (a, b). An ordered pair is an _ordered set_ of two elements. In\n this module, ordered sets can contain one, two, or more elements, and\n parentheses are used to enclose the elements.\n\n Unordered sets and ordered sets are orthogonal, again in this module; there is\n no unordered set equal to any ordered set.\n\n- The _empty set_ contains no elements.\n\n Set A is _equal_{: #equal } to set B if they contain the same elements, which\n is denoted A = B. Two ordered sets are equal if they contain the same number\n of elements and have equal elements at each coordinate.\n\n Set B is a _subset_{: #subset } of set A if A contains all elements that B\n contains.\n\n The _union_{: #union } of two sets A and B is the smallest set that contains\n all elements of A and all elements of B.\n\n The _intersection_{: #intersection } of two sets A and B is the set that\n contains all elements of A that belong to B.\n\n Two sets are _disjoint_{: #disjoint } if their intersection is the empty set.\n\n The _difference_{: #difference } of two sets A and B is the set that contains\n all elements of A that do not belong to B.\n\n The _symmetric difference_{: #symmetric_difference } of two sets is the set\n that contains those element that belong to either of the two sets, but not\n both.\n\n The _union_{: #union_n } of a collection of sets is the smallest set that\n contains all the elements that belong to at least one set of the collection.\n\n The _intersection_{: #intersection_n } of a non-empty collection of sets is\n the set that contains all elements that belong to every set of the collection.\n\n- The _Cartesian product_{: #Cartesian_product } of two sets X and Y, denoted\n X × Y, is the set \\{a : a = (x, y) for some x in X and for some y in Y\\}.\n\n A _relation_{: #relation } is a subset of X × Y. Let R be a relation. The fact\n that (x, y) belongs to R is written as x R y. As relations are sets, the\n definitions of the last item (subset, union, and so on) apply to relations as\n well.\n\n The _domain_{: #domain } of R is the set \\{x : x R y for some y in Y\\}.\n\n The _range_{: #range } of R is the set \\{y : x R y for some x in X\\}.\n\n The _converse_{: #converse } of R is the set \\{a : a = (y, x) for some\n (x, y) in R\\}.\n\n If A is a subset of X, the _image_{: #image } of A under R is the set \\{y :\n x R y for some x in A\\}. If B is a subset of Y, the _inverse image_{:\n #inverse_image } of B is the set \\{x : x R y for some y in B\\}.\n\n If R is a relation from X to Y, and S is a relation from Y to Z, the _relative\n product_{: #relative_product } of R and S is the relation T from X to Z\n defined so that x T z if and only if there exists an element y in Y such that\n x R y and y S z.\n\n The _restriction_{: #restriction } of R to A is the set S defined so that\n x S y if and only if there exists an element x in A such that x R y.\n\n If S is a restriction of R to A, then R is an _extension_{: #extension } of S\n to X.\n\n If X = Y, then R is called a relation _in_ X.\n\n The _field_{: #field } of a relation R in X is the union of the domain of R\n and the range of R.\n\n If R is a relation in X, and if S is defined so that x S y if x R y and not\n x = y, then S is the _strict_{: #strict_relation } relation corresponding to\n R. Conversely, if S is a relation in X, and if R is defined so that x R y if\n x S y or x = y, then R is the _weak_{: #weak_relation } relation corresponding\n to S.\n\n A relation R in X is _reflexive_ if x R x for every element x of X, it is\n _symmetric_ if x R y implies that y R x, and it is _transitive_ if x R y and\n y R z imply that x R z.\n\n- A _function_{: #function } F is a relation, a subset of X × Y, such that the\n domain of F is equal to X and such that for every x in X there is a unique\n element y in Y with (x, y) in F. The latter condition can be formulated as\n follows: if x F y and x F z, then y = z. In this module, it is not required\n that the domain of F is equal to X for a relation to be considered a function.\n\n Instead of writing (x, y) in F or x F y, we write F(x) = y when F is a\n function, and say that F maps x onto y, or that the value of F at x is y.\n\n As functions are relations, the definitions of the last item (domain, range,\n and so on) apply to functions as well.\n\n If the converse of a function F is a function F', then F' is called the\n _inverse_{: #inverse } of F.\n\n The relative product of two functions F1 and F2 is called the _composite_{:\n #composite } of F1 and F2 if the range of F1 is a subset of the domain of F2.\n\n- Sometimes, when the range of a function is more important than the function\n itself, the function is called a _family_.\n\n The domain of a family is called the _index set_, and the range is called the\n _indexed set_.\n\n If x is a family from I to X, then x\\[i] denotes the value of the function at\n index i. The notation \"a family in X\" is used for such a family.\n\n When the indexed set is a set of subsets of a set X, we call x a _family of\n subsets_{: #family } of X.\n\n If x is a family of subsets of X, the union of the range of x is called the\n _union of the family_ x.\n\n If x is non-empty (the index set is non-empty), the _intersection of the\n family_ x is the intersection of the range of x.\n\n In this module, the only families that are considered are families of subsets\n of some set X; in the following, the word \"family\" is used for such families\n of subsets.\n\n- A _partition_{: #partition } of a set X is a collection S of non-empty subsets\n of X whose union is X and whose elements are pairwise disjoint.\n\n A relation in a set is an _equivalence relation_ if it is reflexive,\n symmetric, and transitive.\n\n If R is an equivalence relation in X, and x is an element of X, the\n _equivalence class_{: #equivalence_class } of x with respect to R is the set\n of all those elements y of X for which x R y holds. The equivalence classes\n constitute a partitioning of X. Conversely, if C is a partition of X, the\n relation that holds for any two elements of X if they belong to the same\n equivalence class, is an equivalence relation induced by the partition C.\n\n If R is an equivalence relation in X, the _canonical map_{: #canonical_map }\n is the function that maps every element of X onto its equivalence class.\n\n- [](){: #binary_relation } Relations as defined above (as sets of ordered\n pairs) are from now on referred to as _binary relations_.\n\n We call a set of ordered sets (x\\[1], ..., x\\[n]) an _(n-ary) relation_{:\n #n_ary_relation }, and say that the relation is a subset of the [](){:\n #Cartesian_product_tuple } Cartesian product X\\[1] × ... × X\\[n], where x\\[i]\n is an element of X\\[i], 1 <= i <= n.\n\n The _projection_{: #projection } of an n-ary relation R onto coordinate i is\n the set \\{x\\[i] : (x\\[1], ..., x\\[i], ..., x\\[n]) in R for some\n x\\[j] in X\\[j], 1 <= j <= n and not i = j\\}. The projections of a binary\n relation R onto the first and second coordinates are the domain and the range\n of R, respectively.\n\n The relative product of binary relations can be generalized to n-ary relations\n as follows. Let TR be an ordered set (R\\[1], ..., R\\[n]) of binary relations\n from X to Y\\[i] and S a binary relation from (Y\\[1] × ... × Y\\[n]) to Z. The\n _relative product_{: #tuple_relative_product } of TR and S is the binary\n relation T from X to Z defined so that x T z if and only if there exists an\n element y\\[i] in Y\\[i] for each 1 <= i <= n such that x R\\[i] y\\[i] and\n (y\\[1], ..., y\\[n]) S z. Now let TR be a an ordered set (R\\[1], ..., R\\[n]) of\n binary relations from X\\[i] to Y\\[i] and S a subset of X\\[1] × ... × X\\[n].\n The _multiple relative product_{: #multiple_relative_product } of TR and S is\n defined to be the set \\{z : z = ((x\\[1], ..., x\\[n]), (y\\[1],...,y\\[n])) for\n some (x\\[1], ..., x\\[n]) in S and for some (x\\[i], y\\[i]) in R\\[i],\n 1 <= i <= n\\}.\n\n The _natural join_{: #natural_join } of an n-ary relation R and an m-ary\n relation S on coordinate i and j is defined to be the set \\{z : z =\n (x\\[1], ..., x\\[n],  y\\[1], ..., y\\[j-1], y\\[j+1], ..., y\\[m]) for some\n (x\\[1], ..., x\\[n]) in R and for some (y\\[1], ..., y\\[m]) in S such that\n x\\[i] = y\\[j]\\}.\n\n- [](){: #sets_definition } The sets recognized by this module are represented\n by elements of the relation Sets, which is defined as the smallest set such\n that:\n\n - For every atom T, except '\\_', and for every term X, (T, X) belongs to Sets\n (_atomic sets_).\n - (\\['\\_'], []) belongs to Sets (the _untyped empty set_).\n - For every tuple T = \\{T\\[1], ..., T\\[n]\\} and for every tuple X =\n \\{X\\[1], ..., X\\[n]\\}, if (T\\[i], X\\[i]) belongs to Sets for every\n 1 <= i <= n, then (T, X) belongs to Sets (_ordered sets_).\n - For every term T, if X is the empty list or a non-empty sorted list\n \\[X[1], ..., X\\[n]] without duplicates such that (T, X\\[i]) belongs to Sets\n for every 1 <= i <= n, then (\\[T], X) belongs to Sets (_typed unordered\n sets_).\n\n An _external set_{: #external_set } is an element of the range of Sets.\n\n A _type_{: #type } is an element of the domain of Sets.\n\n If S is an element (T, X) of Sets, then T is a _valid type_{: #valid_type } of\n X, T is the type of S, and X is the external set of S. `from_term/2` creates a\n set from a type and an Erlang term turned into an external set.\n\n The sets represented by Sets are the elements of the range of function Set\n from Sets to Erlang terms and sets of Erlang terms:\n\n - Set(T,Term) = Term, where T is an atom\n - Set(\\{T\\[1], ..., T\\[n]\\}, \\{X\\[1], ...,  X\\[n]\\}) =\n (Set(T\\[1], X\\[1]), ...,  Set(T\\[n], X\\[n]))\n - Set(\\[T], \\[X[1], ..., X\\[n]]) = \\{Set(T, X\\[1]), ..., Set(T, X\\[n])\\}\n - Set(\\[T], []) = \\{\\}\n\n When there is no risk of confusion, elements of Sets are identified with the\n sets they represent. For example, if U is the result of calling `union/2` with\n S1 and S2 as arguments, then U is said to be the union of S1 and S2. A more\n precise formulation is that Set(U) is the union of Set(S1) and Set(S2).\n\nThe types are used to implement the various conditions that sets must fulfill.\nAs an example, consider the relative product of two sets R and S, and recall\nthat the relative product of R and S is defined if R is a binary relation to Y\nand S is a binary relation from Y. The function that implements the relative\nproduct, `relative_product/2`, checks that the arguments represent binary\nrelations by matching \\[\\{A,B\\}] against the type of the first argument (Arg1\nsay), and \\[\\{C,D\\}] against the type of the second argument (Arg2 say). The\nfact that \\[\\{A,B\\}] matches the type of Arg1 is to be interpreted as Arg1\nrepresenting a binary relation from X to Y, where X is defined as all sets\nSet(x) for some element x in Sets the type of which is A, and similarly for Y.\nIn the same way Arg2 is interpreted as representing a binary relation from W to\nZ. Finally it is checked that B matches C, which is sufficient to ensure that W\nis equal to Y. The untyped empty set is handled separately: its type, \\['\\_'],\nmatches the type of any unordered set.\n\nA few functions of this module (`drestriction/3`, `family_projection/2`,\n`partition/2`, `partition_family/2`, `projection/2`, `restriction/3`,\n`substitution/2`) accept an Erlang function as a means to modify each element of\na given unordered set. [](){: #set_fun } Such a function, called SetFun in the\nfollowing, can be specified as a functional object (fun), a tuple\n`{external, Fun}`, or an integer:\n\n- If SetFun is specified as a fun, the fun is applied to each element of the\n given set and the return value is assumed to be a set.\n- If SetFun is specified as a tuple `{external, Fun}`, Fun is applied to the\n external set of each element of the given set and the return value is assumed\n to be an external set. Selecting the elements of an unordered set as external\n sets and assembling a new unordered set from a list of external sets is in the\n present implementation more efficient than modifying each element as a set.\n However, this optimization can only be used when the elements of the unordered\n set are atomic or ordered sets. It must also be the case that the type of the\n elements matches some clause of Fun (the type of the created set is the result\n of applying Fun to the type of the given set), and that Fun does nothing but\n selecting, duplicating, or rearranging parts of the elements.\n- Specifying a SetFun as an integer I is equivalent to specifying\n `{external, fun(X) -> element(I, X) end}`, but is to be preferred, as it makes\n it possible to handle this case even more efficiently.\n\nExamples of SetFuns:\n\n```erlang\nfun sofs:union/1\nfun(S) -> sofs:partition(1, S) end\n{external, fun(A) -> A end}\n{external, fun({A,_,C}) -> {C,A} end}\n{external, fun({_,{_,C}}) -> C end}\n{external, fun({_,{_,{_,E}=C}}) -> {E,{E,C}} end}\n2\n```\n\nThe order in which a SetFun is applied to the elements of an unordered set is\nnot specified, and can change in future versions of this module.\n\nThe execution time of the functions of this module is dominated by the time it\ntakes to sort lists. When no sorting is needed, the execution time is in the\nworst case proportional to the sum of the sizes of the input arguments and the\nreturned value. A few functions execute in constant time: `from_external/2`,\n`is_empty_set/1`, `is_set/1`, `is_sofs_set/1`, `to_external/1` `type/1`.\n\nThe functions of this module exit the process with a `badarg`, `bad_function`,\nor `type_mismatch` message when given badly formed arguments or sets the types\nof which are not compatible.\n\nWhen comparing external sets, operator `==/2` is used.","title":"sofs","ref":"sofs.html"},{"type":"module","doc":"`m:dict`, `m:digraph`, `m:orddict`, `m:ordsets`, `m:sets`","title":"See Also - sofs","ref":"sofs.html#module-see-also"},{"type":"function","doc":"","title":"sofs.a_function/1","ref":"sofs.html#a_function/1"},{"type":"function","doc":"Creates a [function](`m:sofs#function`).\n\n[`a_function(F, T)`](`a_function/2`) is equivalent to\n[`from_term(F, T)`](`from_term/2`) if the result is a function.","title":"sofs.a_function/2","ref":"sofs.html#a_function/2"},{"type":"function","doc":"Returns the binary relation containing the elements (E, Set) such that Set\nbelongs to `SetOfSets` and E belongs to Set.\n\nIf `SetOfSets` is a [partition](`m:sofs#partition`) of a set X and R is the\nequivalence relation in X induced by `SetOfSets`, then the returned relation is the\n[canonical map](`m:sofs#canonical_map`) from X onto the equivalence classes with\nrespect to R.\n\n```erlang\n1> Ss = sofs:from_term([[a,b],[b,c]]),\nCR = sofs:canonical_relation(Ss),\nsofs:to_external(CR).\n[{a,[a,b]},{b,[a,b]},{b,[b,c]},{c,[b,c]}]\n```","title":"sofs.canonical_relation/1","ref":"sofs.html#canonical_relation/1"},{"type":"function","doc":"Returns the [composite](`m:sofs#composite`) of the functions `Function1` and\n`Function2`.\n\n```erlang\n1> F1 = sofs:a_function([{a,1},{b,2},{c,2}]),\nF2 = sofs:a_function([{1,x},{2,y},{3,z}]),\nF = sofs:composite(F1, F2),\nsofs:to_external(F).\n[{a,x},{b,y},{c,y}]\n```","title":"sofs.composite/2","ref":"sofs.html#composite/2"},{"type":"function","doc":"Creates the [function](`m:sofs#function`) that maps each element of set `Set`\nonto `AnySet`.\n\n```erlang\n1> S = sofs:set([a,b]),\nE = sofs:from_term(1),\nR = sofs:constant_function(S, E),\nsofs:to_external(R).\n[{a,1},{b,1}]\n```","title":"sofs.constant_function/2","ref":"sofs.html#constant_function/2"},{"type":"function","doc":"Returns the [converse](`m:sofs#converse`) of the binary relation `BinRel1`.\n\n```erlang\n1> R1 = sofs:relation([{1,a},{2,b},{3,a}]),\nR2 = sofs:converse(R1),\nsofs:to_external(R2).\n[{a,1},{a,3},{b,2}]\n```","title":"sofs.converse/1","ref":"sofs.html#converse/1"},{"type":"function","doc":"Returns the [difference](`m:sofs#difference`) of the sets `Set1` and `Set2`.","title":"sofs.difference/2","ref":"sofs.html#difference/2"},{"type":"function","doc":"","title":"sofs.digraph_to_family/1","ref":"sofs.html#digraph_to_family/1"},{"type":"function","doc":"Creates a [family](`m:sofs#family`) from the directed graph `Graph`. Each vertex\na of `Graph` is represented by a pair (a, \\{b\\[1], ..., b\\[n]\\}), where the\nb\\[i]:s are the out-neighbors of a. It is assumed that `Type` is\na [valid type](`m:sofs#valid_type`) of the external set of the family.\n\nIf G is a directed graph, it holds that the vertices and edges of G are the same\nas the vertices and edges of\n[`family_to_digraph(digraph_to_family(G))`](`family_to_digraph/1`).","title":"sofs.digraph_to_family/2","ref":"sofs.html#digraph_to_family/2"},{"type":"function","doc":"Returns the [domain](`m:sofs#domain`) of the binary relation `BinRel`.\n\n```erlang\n1> R = sofs:relation([{1,a},{1,b},{2,b},{2,c}]),\nS = sofs:domain(R),\nsofs:to_external(S).\n[1,2]\n```","title":"sofs.domain/1","ref":"sofs.html#domain/1"},{"type":"function","doc":"Returns the difference between the binary relation `BinRel1` and the\n[restriction](`m:sofs#restriction`) of `BinRel1` to `Set`.\n\n```erlang\n1> R1 = sofs:relation([{1,a},{2,b},{3,c}]),\nS = sofs:set([2,4,6]),\nR2 = sofs:drestriction(R1, S),\nsofs:to_external(R2).\n[{1,a},{3,c}]\n```\n\n[`drestriction(R, S)`](`drestriction/2`) is equivalent to\n[`difference(R, restriction(R, S))`](`difference/2`).","title":"sofs.drestriction/2","ref":"sofs.html#drestriction/2"},{"type":"function","doc":"Returns a subset of `Set1` containing those elements that do not give an element\nin `Set2` as the result of applying `SetFun`.\n\n```erlang\n1> SetFun = {external, fun({_A,B,C}) -> {B,C} end},\nR1 = sofs:relation([{a,aa,1},{b,bb,2},{c,cc,3}]),\nR2 = sofs:relation([{bb,2},{cc,3},{dd,4}]),\nR3 = sofs:drestriction(SetFun, R1, R2),\nsofs:to_external(R3).\n[{a,aa,1}]\n```\n\n[`drestriction(F, S1, S2)`](`drestriction/3`) is equivalent to\n[`difference(S1, restriction(F, S1, S2))`](`difference/2`).","title":"sofs.drestriction/3","ref":"sofs.html#drestriction/3"},{"type":"function","doc":"Returns the [untyped empty set](`m:sofs#sets_definition`). `empty_set/0` is\nequivalent to [`from_term([], ['_'])`](`from_term/2`).","title":"sofs.empty_set/0","ref":"sofs.html#empty_set/0"},{"type":"function","doc":"Returns the [extension](`m:sofs#extension`) of `BinRel1` such that for each\nelement E in `Set` that does not belong to the [domain](`m:sofs#domain`) of\n`BinRel1`, `BinRel2` contains the pair (E, `AnySet`).\n\n```erlang\n1> S = sofs:set([b,c]),\nA = sofs:empty_set(),\nR = sofs:family([{a,[1,2]},{b,[3]}]),\nX = sofs:extension(R, S, A),\nsofs:to_external(X).\n[{a,[1,2]},{b,[3]},{c,[]}]\n```","title":"sofs.extension/3","ref":"sofs.html#extension/3"},{"type":"function","doc":"","title":"sofs.family/1","ref":"sofs.html#family/1"},{"type":"function","doc":"Creates a [family of subsets](`m:sofs#family`). [`family(F, T)`](`family/2`) is\nequivalent to [`from_term(F, T)`](`from_term/2`) if the result is a family.","title":"sofs.family/2","ref":"sofs.html#family/2"},{"type":"function","doc":"If `Family1` and `Family2` are [families](`m:sofs#family`), then `Family3` is\nthe family such that the index set is equal to the index set of `Family1`, and\n`Family3`\\[i] is the difference between `Family1`\\[i] and `Family2`\\[i] if\n`Family2` maps i, otherwise `Family1[i]`.\n\n```erlang\n1> F1 = sofs:family([{a,[1,2]},{b,[3,4]}]),\nF2 = sofs:family([{b,[4,5]},{c,[6,7]}]),\nF3 = sofs:family_difference(F1, F2),\nsofs:to_external(F3).\n[{a,[1,2]},{b,[3]}]\n```","title":"sofs.family_difference/2","ref":"sofs.html#family_difference/2"},{"type":"function","doc":"If `Family1` is a [family](`m:sofs#family`) and `Family1`\\[i] is a binary\nrelation for every i in the index set of `Family1`, then `Family2` is the family\nwith the same index set as `Family1` such that `Family2`\\[i] is the\n[domain](`m:sofs#domain`) of `Family1[i]`.\n\n```erlang\n1> FR = sofs:from_term([{a,[{1,a},{2,b},{3,c}]},{b,[]},{c,[{4,d},{5,e}]}]),\nF = sofs:family_domain(FR),\nsofs:to_external(F).\n[{a,[1,2,3]},{b,[]},{c,[4,5]}]\n```","title":"sofs.family_domain/1","ref":"sofs.html#family_domain/1"},{"type":"function","doc":"If `Family1` is a [family](`m:sofs#family`) and `Family1`\\[i] is a binary\nrelation for every i in the index set of `Family1`, then `Family2` is the family\nwith the same index set as `Family1` such that `Family2`\\[i] is the\n[field](`m:sofs#field`) of `Family1`\\[i].\n\n```erlang\n1> FR = sofs:from_term([{a,[{1,a},{2,b},{3,c}]},{b,[]},{c,[{4,d},{5,e}]}]),\nF = sofs:family_field(FR),\nsofs:to_external(F).\n[{a,[1,2,3,a,b,c]},{b,[]},{c,[4,5,d,e]}]\n```\n\n[`family_field(Family1)`](`family_field/1`) is equivalent to\n[`family_union(family_domain(Family1), family_range(Family1))`](`family_union/2`).","title":"sofs.family_field/1","ref":"sofs.html#family_field/1"},{"type":"function","doc":"If `Family1` is a [family](`m:sofs#family`) and `Family1`\\[i] is a set of sets\nfor every i in the index set of `Family1`, then `Family2` is the family with the\nsame index set as `Family1` such that `Family2`\\[i] is the\n[intersection](`m:sofs#intersection_n`) of `Family1`\\[i].\n\nIf `Family1`\\[i] is an empty set for some i, the process exits with a `badarg`\nmessage.\n\n```erlang\n1> F1 = sofs:from_term([{a,[[1,2,3],[2,3,4]]},{b,[[x,y,z],[x,y]]}]),\nF2 = sofs:family_intersection(F1),\nsofs:to_external(F2).\n[{a,[2,3]},{b,[x,y]}]\n```","title":"sofs.family_intersection/1","ref":"sofs.html#family_intersection/1"},{"type":"function","doc":"If `Family1` and `Family2` are [families](`m:sofs#family`), then `Family3` is\nthe family such that the index set is the intersection of `Family1`:s and\n`Family2`:s index sets, and `Family3`\\[i] is the intersection of `Family1`\\[i]\nand `Family2`\\[i].\n\n```erlang\n1> F1 = sofs:family([{a,[1,2]},{b,[3,4]},{c,[5,6]}]),\nF2 = sofs:family([{b,[4,5]},{c,[7,8]},{d,[9,10]}]),\nF3 = sofs:family_intersection(F1, F2),\nsofs:to_external(F3).\n[{b,[4]},{c,[]}]\n```","title":"sofs.family_intersection/2","ref":"sofs.html#family_intersection/2"},{"type":"function","doc":"If `Family1` is a [family](`m:sofs#family`), then `Family2` is the family with\nthe same index set as `Family1` such that `Family2`\\[i] is the result of calling\n`SetFun` with `Family1`\\[i] as argument.\n\n```erlang\n1> F1 = sofs:from_term([{a,[[1,2],[2,3]]},{b,[[]]}]),\nF2 = sofs:family_projection(fun sofs:union/1, F1),\nsofs:to_external(F2).\n[{a,[1,2,3]},{b,[]}]\n```","title":"sofs.family_projection/2","ref":"sofs.html#family_projection/2"},{"type":"function","doc":"If `Family1` is a [family](`m:sofs#family`) and `Family1`\\[i] is a binary\nrelation for every i in the index set of `Family1`, then `Family2` is the family\nwith the same index set as `Family1` such that `Family2`\\[i] is the\n[range](`m:sofs#range`) of `Family1`\\[i].\n\n```erlang\n1> FR = sofs:from_term([{a,[{1,a},{2,b},{3,c}]},{b,[]},{c,[{4,d},{5,e}]}]),\nF = sofs:family_range(FR),\nsofs:to_external(F).\n[{a,[a,b,c]},{b,[]},{c,[d,e]}]\n```","title":"sofs.family_range/1","ref":"sofs.html#family_range/1"},{"type":"function","doc":"If `Family1` is a [family](`m:sofs#family`), then `Family2` is the\n[restriction](`m:sofs#restriction`) of `Family1` to those elements i of the\nindex set for which `Fun` applied to `Family1`\\[i] returns `true`. If `Fun` is a\ntuple `{external, Fun2}`, then `Fun2` is applied to the\n[external set](`m:sofs#external_set`) of `Family1`\\[i], otherwise `Fun` is\napplied to `Family1`\\[i].\n\n```erlang\n1> F1 = sofs:family([{a,[1,2,3]},{b,[1,2]},{c,[1]}]),\nSpecFun = fun(S) -> sofs:no_elements(S) =:= 2 end,\nF2 = sofs:family_specification(SpecFun, F1),\nsofs:to_external(F2).\n[{b,[1,2]}]\n```","title":"sofs.family_specification/2","ref":"sofs.html#family_specification/2"},{"type":"function","doc":"","title":"sofs.family_to_digraph/1","ref":"sofs.html#family_to_digraph/1"},{"type":"function","doc":"Creates a directed graph from [family](`m:sofs#family`) `Family`. For each pair\n(a, \\{b\\[1], ..., b\\[n]\\}) of `Family`, vertex a and the edges (a, b\\[i]) for\n1 <= i <= n are added to a newly created directed graph.\n\n`GraphType` is passed on to `digraph:new/1`.\n\nIt F is a family, it holds that F is a subset of\n[`digraph_to_family(family_to_digraph(F), type(F))`](`digraph_to_family/2`).\nEquality holds if [`union_of_family(F)`](`union_of_family/1`) is a subset of\n[`domain(F)`](`domain/1`).\n\nCreating a cycle in an acyclic graph exits the process with a `cyclic` message.","title":"sofs.family_to_digraph/2","ref":"sofs.html#family_to_digraph/2"},{"type":"function","doc":"If `Family` is a [family](`m:sofs#family`), then `BinRel` is the binary relation\ncontaining all pairs (i, x) such that i belongs to the index set of `Family` and\nx belongs to `Family`\\[i].\n\n```erlang\n1> F = sofs:family([{a,[]}, {b,[1]}, {c,[2,3]}]),\nR = sofs:family_to_relation(F),\nsofs:to_external(R).\n[{b,1},{c,2},{c,3}]\n```","title":"sofs.family_to_relation/1","ref":"sofs.html#family_to_relation/1"},{"type":"function","doc":"If `Family1` is a [family](`m:sofs#family`) and `Family1`\\[i] is a set of sets\nfor each i in the index set of `Family1`, then `Family2` is the family with the\nsame index set as `Family1` such that `Family2`\\[i] is the\n[union](`m:sofs#union_n`) of `Family1`\\[i].\n\n```erlang\n1> F1 = sofs:from_term([{a,[[1,2],[2,3]]},{b,[[]]}]),\nF2 = sofs:family_union(F1),\nsofs:to_external(F2).\n[{a,[1,2,3]},{b,[]}]\n```\n\n[`family_union(F)`](`family_union/1`) is equivalent to\n[`family_projection(fun sofs:union/1, F)`](`family_projection/2`).","title":"sofs.family_union/1","ref":"sofs.html#family_union/1"},{"type":"function","doc":"If `Family1` and `Family2` are [families](`m:sofs#family`), then `Family3` is\nthe family such that the index set is the union of `Family1`:s and `Family2`:s\nindex sets, and `Family3`\\[i] is the union of `Family1`\\[i] and `Family2`\\[i] if\nboth map i, otherwise `Family1`\\[i] or `Family2`\\[i].\n\n```erlang\n1> F1 = sofs:family([{a,[1,2]},{b,[3,4]},{c,[5,6]}]),\nF2 = sofs:family([{b,[4,5]},{c,[7,8]},{d,[9,10]}]),\nF3 = sofs:family_union(F1, F2),\nsofs:to_external(F3).\n[{a,[1,2]},{b,[3,4,5]},{c,[5,6,7,8]},{d,[9,10]}]\n```","title":"sofs.family_union/2","ref":"sofs.html#family_union/2"},{"type":"function","doc":"Returns the [field](`m:sofs#field`) of the binary relation `BinRel`.\n\n```erlang\n1> R = sofs:relation([{1,a},{1,b},{2,b},{2,c}]),\nS = sofs:field(R),\nsofs:to_external(S).\n[1,2,a,b,c]\n```\n\n[`field(R)`](`field/1`) is equivalent to\n[`union(domain(R), range(R))`](`union/2`).","title":"sofs.field/1","ref":"sofs.html#field/1"},{"type":"function","doc":"Creates a set from the [external set](`m:sofs#external_set`) `ExternalSet` and\nthe [type](`m:sofs#type`) `Type`. It is assumed that `Type` is a\n[valid type](`m:sofs#valid_type`) of `ExternalSet`.","title":"sofs.from_external/2","ref":"sofs.html#from_external/2"},{"type":"function","doc":"Returns the [unordered set](`m:sofs#sets_definition`) containing the sets of\nlist `ListOfSets`.\n\n```erlang\n1> S1 = sofs:relation([{a,1},{b,2}]),\nS2 = sofs:relation([{x,3},{y,4}]),\nS = sofs:from_sets([S1,S2]),\nsofs:to_external(S).\n[[{a,1},{b,2}],[{x,3},{y,4}]]\n```\n\nReturns the [ordered set](`m:sofs#sets_definition`) containing the sets of the\nnon-empty tuple `TupleOfSets`.","title":"sofs.from_sets/1","ref":"sofs.html#from_sets/1"},{"type":"function","doc":"","title":"sofs.from_term/1","ref":"sofs.html#from_term/1"},{"type":"function","doc":"Creates an element of [Sets](`m:sofs#sets_definition`) by\ntraversing term `Term`, sorting lists, removing duplicates, and deriving or\nverifying a [valid type](`m:sofs#valid_type`) for the so obtained external set.\n\nAn explicitly specified [type](`m:sofs#type`) `Type` can be used to limit the\ndepth of the traversal; an atomic type stops the traversal, as shown by the\nfollowing example where `\"foo\"` and `{\"foo\"}` are left unmodified:\n\n```erlang\n1> S = sofs:from_term([{{\"foo\"},[1,1]},{\"foo\",[2,2]}],\n [{atom,[atom]}]),\n sofs:to_external(S).\n[{{\"foo\"},[1]},{\"foo\",[2]}]\n```\n\n`from_term` can be used for creating atomic or ordered sets. The only purpose of\nsuch a set is that of later building unordered sets, as all functions in this\nmodule that _do_ anything operate on unordered sets. Creating unordered sets\nfrom a collection of ordered sets can be the way to go if the ordered sets are\nbig and one does not want to waste heap by rebuilding the elements of the\nunordered set. The following example shows that a set can be built \"layer by\nlayer\":\n\n```erlang\n1> A = sofs:from_term(a),\nS = sofs:set([1,2,3]),\nP1 = sofs:from_sets({A,S}),\nP2 = sofs:from_term({b,[6,5,4]}),\nSs = sofs:from_sets([P1,P2]),\nsofs:to_external(Ss).\n[{a,[1,2,3]},{b,[4,5,6]}]\n```\n\nOther functions that create sets are `from_external/2` and `from_sets/1`.\nSpecial cases of [`from_term/2`](`from_term/2`) are\n[`a_function/1,2`](`a_function/1`), `empty_set/0`, [`family/1,2`](`family/1`),\n[`relation/1,2`](`relation/1`), and [`set/1,2`](`set/1`).","title":"sofs.from_term/2","ref":"sofs.html#from_term/2"},{"type":"function","doc":"Returns the [image](`m:sofs#image`) of set `Set1` under the binary relation\n`BinRel`.\n\n```erlang\n1> R = sofs:relation([{1,a},{2,b},{2,c},{3,d}]),\nS1 = sofs:set([1,2]),\nS2 = sofs:image(R, S1),\nsofs:to_external(S2).\n[a,b,c]\n```","title":"sofs.image/2","ref":"sofs.html#image/2"},{"type":"function","doc":"Returns the [intersection](`m:sofs#intersection_n`) of the set of sets\n`SetOfSets`.\n\nIntersecting an empty set of sets exits the process with a `badarg` message.","title":"sofs.intersection/1","ref":"sofs.html#intersection/1"},{"type":"function","doc":"Returns the [intersection](`m:sofs#intersection`) of `Set1` and `Set2`.","title":"sofs.intersection/2","ref":"sofs.html#intersection/2"},{"type":"function","doc":"Returns the intersection of [family](`m:sofs#family`) `Family`.\n\nIntersecting an empty family exits the process with a `badarg` message.\n\n```erlang\n1> F = sofs:family([{a,[0,2,4]},{b,[0,1,2]},{c,[2,3]}]),\nS = sofs:intersection_of_family(F),\nsofs:to_external(S).\n[2]\n```","title":"sofs.intersection_of_family/1","ref":"sofs.html#intersection_of_family/1"},{"type":"function","doc":"Returns the [inverse](`m:sofs#inverse`) of function `Function1`.\n\n```erlang\n1> R1 = sofs:relation([{1,a},{2,b},{3,c}]),\nR2 = sofs:inverse(R1),\nsofs:to_external(R2).\n[{a,1},{b,2},{c,3}]\n```","title":"sofs.inverse/1","ref":"sofs.html#inverse/1"},{"type":"function","doc":"Returns the [inverse image](`m:sofs#inverse_image`) of `Set1` under the binary\nrelation `BinRel`.\n\n```erlang\n1> R = sofs:relation([{1,a},{2,b},{2,c},{3,d}]),\nS1 = sofs:set([c,d,e]),\nS2 = sofs:inverse_image(R, S1),\nsofs:to_external(S2).\n[2,3]\n```","title":"sofs.inverse_image/2","ref":"sofs.html#inverse_image/2"},{"type":"function","doc":"Returns `true` if the binary relation `BinRel` is a\n[function](`m:sofs#function`) or the untyped empty set, otherwise `false`.","title":"sofs.is_a_function/1","ref":"sofs.html#is_a_function/1"},{"type":"function","doc":"Returns `true` if `Set1` and `Set2` are [disjoint](`m:sofs#disjoint`), otherwise\n`false`.","title":"sofs.is_disjoint/2","ref":"sofs.html#is_disjoint/2"},{"type":"function","doc":"Returns `true` if `AnySet` is an empty unordered set, otherwise `false`.","title":"sofs.is_empty_set/1","ref":"sofs.html#is_empty_set/1"},{"type":"function","doc":"Returns `true` if `AnySet1` and `AnySet2` are [equal](`m:sofs#equal`), otherwise\n`false`. The following example shows that `==/2` is used when comparing sets for\nequality:\n\n```erlang\n1> S1 = sofs:set([1.0]),\nS2 = sofs:set([1]),\nsofs:is_equal(S1, S2).\ntrue\n```","title":"sofs.is_equal/2","ref":"sofs.html#is_equal/2"},{"type":"function","doc":"Returns `true` if `AnySet` appears to be an\n[unordered set](`m:sofs#sets_definition`), and `false` if `AnySet` is an ordered\nset or an atomic set or any other term.\n\nNote that the test is shallow and this function will return `true` for any term\nthat coincides with the representation of an unordered set. See also note on\n[data types](`e:system:data_types.md#no_user_types`).","title":"sofs.is_set/1","ref":"sofs.html#is_set/1"},{"type":"function","doc":"Returns `true` if `Term` appears to be an\n[unordered set](`m:sofs#sets_definition`), an ordered set, or an atomic set,\notherwise `false`.\n\nNote that this function will return `true` for any term that\ncoincides with the representation of a `sofs` set. See also note on\n[data types](`e:system:data_types.md#no_user_types`).","title":"sofs.is_sofs_set/1","ref":"sofs.html#is_sofs_set/1"},{"type":"function","doc":"Returns `true` if `Set1` is a [subset](`m:sofs#subset`) of `Set2`, otherwise\n`false`.","title":"sofs.is_subset/2","ref":"sofs.html#is_subset/2"},{"type":"function","doc":"Returns `true` if term `Term` is a [type](`m:sofs#type`).","title":"sofs.is_type/1","ref":"sofs.html#is_type/1"},{"type":"function","doc":"Returns the [natural join](`m:sofs#natural_join`) of the relations `Relation1`\nand `Relation2` on coordinates `I` and `J`.\n\n```erlang\n1> R1 = sofs:relation([{a,x,1},{b,y,2}]),\nR2 = sofs:relation([{1,f,g},{1,h,i},{2,3,4}]),\nJ = sofs:join(R1, 3, R2, 1),\nsofs:to_external(J).\n[{a,x,1,f,g},{a,x,1,h,i},{b,y,2,3,4}]\n```","title":"sofs.join/4","ref":"sofs.html#join/4"},{"type":"function","doc":"If `TupleOfBinRels` is a non-empty tuple \\{R\\[1], ..., R\\[n]\\} of binary\nrelations and `BinRel1` is a binary relation, then `BinRel2` is the\n[multiple relative product](`m:sofs#multiple_relative_product`) of the ordered\nset (R\\[i], ..., R\\[n]) and `BinRel1`.\n\n```erlang\n1> Ri = sofs:relation([{a,1},{b,2},{c,3}]),\nR = sofs:relation([{a,b},{b,c},{c,a}]),\nMP = sofs:multiple_relative_product({Ri, Ri}, R),\nsofs:to_external(sofs:range(MP)).\n[{1,2},{2,3},{3,1}]\n```","title":"sofs.multiple_relative_product/2","ref":"sofs.html#multiple_relative_product/2"},{"type":"function","doc":"Returns the number of elements of the ordered or unordered set `ASet`.","title":"sofs.no_elements/1","ref":"sofs.html#no_elements/1"},{"type":"function","doc":"Returns the [partition](`m:sofs#partition`) of the union of the set of sets\n`SetOfSets` such that two elements are considered equal if they belong to the\nsame elements of `SetOfSets`.\n\n```erlang\n1> Sets1 = sofs:from_term([[a,b,c],[d,e,f],[g,h,i]]),\nSets2 = sofs:from_term([[b,c,d],[e,f,g],[h,i,j]]),\nP = sofs:partition(sofs:union(Sets1, Sets2)),\nsofs:to_external(P).\n[[a],[b,c],[d],[e,f],[g],[h,i],[j]]\n```","title":"sofs.partition/1","ref":"sofs.html#partition/1"},{"type":"function","doc":"Returns the [partition](`m:sofs#partition`) of `Set` such that two elements are\nconsidered equal if the results of applying `SetFun` are equal.\n\n```erlang\n1> Ss = sofs:from_term([[a],[b],[c,d],[e,f]]),\nSetFun = fun(S) -> sofs:from_term(sofs:no_elements(S)) end,\nP = sofs:partition(SetFun, Ss),\nsofs:to_external(P).\n[[[a],[b]],[[c,d],[e,f]]]\n```","title":"sofs.partition/2","ref":"sofs.html#partition/2"},{"type":"function","doc":"Returns a pair of sets that, regarded as constituting a set, forms a\n[partition](`m:sofs#partition`) of `Set1`. If the result of applying `SetFun` to\nan element of `Set1` gives an element in `Set2`, the element belongs to `Set3`,\notherwise the element belongs to `Set4`.\n\n```erlang\n1> R1 = sofs:relation([{1,a},{2,b},{3,c}]),\nS = sofs:set([2,4,6]),\n{R2,R3} = sofs:partition(1, R1, S),\n{sofs:to_external(R2),sofs:to_external(R3)}.\n{[{2,b}],[{1,a},{3,c}]}\n```\n\n[`partition(F, S1, S2)`](`partition/3`) is equivalent to\n`{restriction(F, S1, S2), drestriction(F, S1, S2)}`.","title":"sofs.partition/3","ref":"sofs.html#partition/3"},{"type":"function","doc":"Returns [family](`m:sofs#family`) `Family` where the indexed set is a\n[partition](`m:sofs#partition`) of `Set` such that two elements are considered\nequal if the results of applying `SetFun` are the same value i. This i is the\nindex that `Family` maps onto the\n[equivalence class](`m:sofs#equivalence_class`).\n\n```erlang\n1> S = sofs:relation([{a,a,a,a},{a,a,b,b},{a,b,b,b}]),\nSetFun = {external, fun({A,_,C,_}) -> {A,C} end},\nF = sofs:partition_family(SetFun, S),\nsofs:to_external(F).\n[{{a,a},[{a,a,a,a}]},{{a,b},[{a,a,b,b},{a,b,b,b}]}]\n```","title":"sofs.partition_family/2","ref":"sofs.html#partition_family/2"},{"type":"function","doc":"Returns the [Cartesian product](`m:sofs#Cartesian_product_tuple`) of the\nnon-empty tuple of sets `TupleOfSets`. If (x\\[1], ..., x\\[n]) is an element of\nthe n-ary relation `Relation`, then x\\[i] is drawn from element i of\n`TupleOfSets`.\n\n```erlang\n1> S1 = sofs:set([a,b]),\nS2 = sofs:set([1,2]),\nS3 = sofs:set([x,y]),\nP3 = sofs:product({S1,S2,S3}),\nsofs:to_external(P3).\n[{a,1,x},{a,1,y},{a,2,x},{a,2,y},{b,1,x},{b,1,y},{b,2,x},{b,2,y}]\n```","title":"sofs.product/1","ref":"sofs.html#product/1"},{"type":"function","doc":"Returns the [Cartesian product](`m:sofs#Cartesian_product`) of `Set1` and\n`Set2`.\n\n```erlang\n1> S1 = sofs:set([1,2]),\nS2 = sofs:set([a,b]),\nR = sofs:product(S1, S2),\nsofs:to_external(R).\n[{1,a},{1,b},{2,a},{2,b}]\n```\n\n[`product(S1, S2)`](`product/2`) is equivalent to\n[`product({S1, S2})`](`product/1`).","title":"sofs.product/2","ref":"sofs.html#product/2"},{"type":"function","doc":"Returns the set created by substituting each element of `Set1` by the result of\napplying `SetFun` to the element.\n\nIf `SetFun` is a number i >= 1 and `Set1` is a relation, then the returned set\nis the [projection](`m:sofs#projection`) of `Set1` onto coordinate i.\n\n```erlang\n1> S1 = sofs:from_term([{1,a},{2,b},{3,a}]),\nS2 = sofs:projection(2, S1),\nsofs:to_external(S2).\n[a,b]\n```","title":"sofs.projection/2","ref":"sofs.html#projection/2"},{"type":"function","doc":"Returns the [range](`m:sofs#range`) of the binary relation `BinRel`.\n\n```erlang\n1> R = sofs:relation([{1,a},{1,b},{2,b},{2,c}]),\nS = sofs:range(R),\nsofs:to_external(S).\n[a,b,c]\n```","title":"sofs.range/1","ref":"sofs.html#range/1"},{"type":"function","doc":"Equivalent to [`relation(Tuples, Type)`](`relation/2`) where `Type` is the size\nof the first tuple of `Tuples` is used if there is such a tuple.\n\nIf tuples is `[]`, then `Type` is `2`.","title":"sofs.relation/1","ref":"sofs.html#relation/1"},{"type":"function","doc":"Creates a [relation](`m:sofs#relation`). [`relation(R, T)`](`relation/2`) is\nequivalent to [`from_term(R, T)`](`from_term/2`), if T is a\n[type](`m:sofs#type`) and the result is a relation.\n\nIf `Type` is an integer N, then `[{atom, ..., atom}])`, where the tuple size is N,\nis used as type of the relation.","title":"sofs.relation/2","ref":"sofs.html#relation/2"},{"type":"function","doc":"Returns [family](`m:sofs#family`) `Family` such that the index set is equal to\nthe [domain](`m:sofs#domain`) of the binary relation `BinRel`, and `Family`\\[i]\nis the [image](`m:sofs#image`) of the set of i under `BinRel`.\n\n```erlang\n1> R = sofs:relation([{b,1},{c,2},{c,3}]),\nF = sofs:relation_to_family(R),\nsofs:to_external(F).\n[{b,[1]},{c,[2,3]}]\n```","title":"sofs.relation_to_family/1","ref":"sofs.html#relation_to_family/1"},{"type":"function","doc":"Returns the [relative product](`m:sofs#relative_product`) of the\n[converse](`m:sofs#converse`) of the binary relation `BinRel1` and the binary\nrelation `BinRel2`.\n\n```erlang\n1> R1 = sofs:relation([{1,a},{1,aa},{2,b}]),\nR2 = sofs:relation([{1,u},{2,v},{3,c}]),\nR3 = sofs:relative_product1(R1, R2),\nsofs:to_external(R3).\n[{a,u},{aa,u},{b,v}]\n```\n\n[`relative_product1(R1, R2)`](`relative_product1/2`) is equivalent to\n[`relative_product(converse(R1), R2)`](`relative_product/2`).","title":"sofs.relative_product1/2","ref":"sofs.html#relative_product1/2"},{"type":"function","doc":"","title":"sofs.relative_product/1","ref":"sofs.html#relative_product/1"},{"type":"function","doc":"If `ListOfBinRels` is a non-empty list \\[R[1], ..., R\\[n]] of binary relations\nand `BinRel1` is a binary relation, then `BinRel2` is the\n[relative product](`m:sofs#tuple_relative_product`) of the ordered set\n(R\\[i], ..., R\\[n]) and `BinRel1`.\n\nIf `BinRel1` is omitted, the relation of equality between the elements of the\n[Cartesian product](`m:sofs#Cartesian_product_tuple`) of the ranges of R\\[i],\nrange R\\[1] × ... × range R\\[n], is used instead (intuitively, nothing is\n\"lost\").\n\n```erlang\n1> TR = sofs:relation([{1,a},{1,aa},{2,b}]),\nR1 = sofs:relation([{1,u},{2,v},{3,c}]),\nR2 = sofs:relative_product([TR, R1]),\nsofs:to_external(R2).\n[{1,{a,u}},{1,{aa,u}},{2,{b,v}}]\n```\n\nNotice that [`relative_product([R1], R2)`](`relative_product/2`) is different\nfrom [`relative_product(R1, R2)`](`relative_product/2`); the list of one element\nis not identified with the element itself.\n\nReturns the [relative product](`m:sofs#relative_product`) of the binary\nrelations `BinRel1` and `BinRel2`.","title":"sofs.relative_product/2","ref":"sofs.html#relative_product/2"},{"type":"function","doc":"Returns the [restriction](`m:sofs#restriction`) of the binary relation `BinRel1`\nto `Set`.\n\n```erlang\n1> R1 = sofs:relation([{1,a},{2,b},{3,c}]),\nS = sofs:set([1,2,4]),\nR2 = sofs:restriction(R1, S),\nsofs:to_external(R2).\n[{1,a},{2,b}]\n```","title":"sofs.restriction/2","ref":"sofs.html#restriction/2"},{"type":"function","doc":"Returns a subset of `Set1` containing those elements that gives an element in\n`Set2` as the result of applying `SetFun`.\n\n```erlang\n1> S1 = sofs:relation([{1,a},{2,b},{3,c}]),\nS2 = sofs:set([b,c,d]),\nS3 = sofs:restriction(2, S1, S2),\nsofs:to_external(S3).\n[{2,b},{3,c}]\n```","title":"sofs.restriction/3","ref":"sofs.html#restriction/3"},{"type":"function","doc":"","title":"sofs.set/1","ref":"sofs.html#set/1"},{"type":"function","doc":"Creates an [unordered set](`m:sofs#sets_definition`). [`set(L, T)`](`set/2`) is\nequivalent to [`from_term(L, T)`](`from_term/2`), if the result is an unordered\nset.","title":"sofs.set/2","ref":"sofs.html#set/2"},{"type":"function","doc":"Returns the set containing every element of `Set1` for which `Fun` returns\n`true`. If `Fun` is a tuple `{external, Fun2}`, `Fun2` is applied to the\n[external set](`m:sofs#external_set`) of each element, otherwise `Fun` is\napplied to each element.\n\n```erlang\n1> R1 = sofs:relation([{a,1},{b,2}]),\nR2 = sofs:relation([{x,1},{x,2},{y,3}]),\nS1 = sofs:from_sets([R1,R2]),\nS2 = sofs:specification(fun sofs:is_a_function/1, S1),\nsofs:to_external(S2).\n[[{a,1},{b,2}]]\n```","title":"sofs.specification/2","ref":"sofs.html#specification/2"},{"type":"function","doc":"Returns the [strict relation](`m:sofs#strict_relation`) corresponding to the\nbinary relation `BinRel1`.\n\n```erlang\n1> R1 = sofs:relation([{1,1},{1,2},{2,1},{2,2}]),\nR2 = sofs:strict_relation(R1),\nsofs:to_external(R2).\n[{1,2},{2,1}]\n```","title":"sofs.strict_relation/1","ref":"sofs.html#strict_relation/1"},{"type":"function","doc":"Returns a function, the domain of which is `Set1`. The value of an element of\nthe domain is the result of applying `SetFun` to the element.\n\n```erlang\n1> L = [{a,1},{b,2}].\n[{a,1},{b,2}]\n2> sofs:to_external(sofs:projection(1,sofs:relation(L))).\n[a,b]\n3> sofs:to_external(sofs:substitution(1,sofs:relation(L))).\n[{{a,1},a},{{b,2},b}]\n4> SetFun = {external, fun({A,_}=E) -> {E,A} end},\nsofs:to_external(sofs:projection(SetFun,sofs:relation(L))).\n[{{a,1},a},{{b,2},b}]\n```\n\nThe relation of equality between the elements of \\{a,b,c\\}:\n\n```erlang\n1> I = sofs:substitution(fun(A) -> A end, sofs:set([a,b,c])),\nsofs:to_external(I).\n[{a,a},{b,b},{c,c}]\n```\n\nLet `SetOfSets` be a set of sets and `BinRel` a binary relation. The function\nthat maps each element `Set` of `SetOfSets` onto the [image](`m:sofs#image`) of\n`Set` under `BinRel` is returned by the following function:\n\n```erlang\nimages(SetOfSets, BinRel) ->\n Fun = fun(Set) -> sofs:image(BinRel, Set) end,\n sofs:substitution(Fun, SetOfSets).\n```\n\nExternal unordered sets are represented as sorted lists. So, creating the image\nof a set under a relation R can traverse all elements of R (to that comes the\nsorting of results, the image). In `image/2`, `BinRel` is traversed once for\neach element of `SetOfSets`, which can take too long. The following efficient\nfunction can be used instead under the assumption that the image of each element\nof `SetOfSets` under `BinRel` is non-empty:\n\n```erlang\nimages2(SetOfSets, BinRel) ->\n CR = sofs:canonical_relation(SetOfSets),\n R = sofs:relative_product1(CR, BinRel),\n sofs:relation_to_family(R).\n```","title":"sofs.substitution/2","ref":"sofs.html#substitution/2"},{"type":"function","doc":"Returns the [symmetric difference](`m:sofs#symmetric_difference`) (or the\nBoolean sum) of `Set1` and `Set2`.\n\n```erlang\n1> S1 = sofs:set([1,2,3]),\nS2 = sofs:set([2,3,4]),\nP = sofs:symdiff(S1, S2),\nsofs:to_external(P).\n[1,4]\n```","title":"sofs.symdiff/2","ref":"sofs.html#symdiff/2"},{"type":"function","doc":"Returns a triple of sets:\n\n- `Set3` contains the elements of `Set1` that do not belong to `Set2`.\n- `Set4` contains the elements of `Set1` that belong to `Set2`.\n- `Set5` contains the elements of `Set2` that do not belong to `Set1`.","title":"sofs.symmetric_partition/2","ref":"sofs.html#symmetric_partition/2"},{"type":"function","doc":"Returns the [external set](`m:sofs#external_set`) of an atomic, ordered, or\nunordered set.","title":"sofs.to_external/1","ref":"sofs.html#to_external/1"},{"type":"function","doc":"Returns the elements of the ordered set `ASet` as a tuple of sets, and the\nelements of the unordered set `ASet` as a sorted list of sets without\nduplicates.","title":"sofs.to_sets/1","ref":"sofs.html#to_sets/1"},{"type":"function","doc":"Returns the [type](`m:sofs#type`) of an atomic, ordered, or unordered set.","title":"sofs.type/1","ref":"sofs.html#type/1"},{"type":"function","doc":"Returns the [union](`m:sofs#union_n`) of the set of sets `SetOfSets`.","title":"sofs.union/1","ref":"sofs.html#union/1"},{"type":"function","doc":"Returns the [union](`m:sofs#union`) of `Set1` and `Set2`.","title":"sofs.union/2","ref":"sofs.html#union/2"},{"type":"function","doc":"Returns the union of [family](`m:sofs#family`) `Family`.\n\n```erlang\n1> F = sofs:family([{a,[0,2,4]},{b,[0,1,2]},{c,[2,3]}]),\nS = sofs:union_of_family(F),\nsofs:to_external(S).\n[0,1,2,3,4]\n```","title":"sofs.union_of_family/1","ref":"sofs.html#union_of_family/1"},{"type":"function","doc":"Returns a subset S of the [weak relation](`m:sofs#weak_relation`) W\ncorresponding to the binary relation `BinRel1`. Let F be the\n[field](`m:sofs#field`) of `BinRel1`. The subset S is defined so that x S y if x\nW y for some x in F and for some y in F.\n\n```erlang\n1> R1 = sofs:relation([{1,1},{1,2},{3,1}]),\nR2 = sofs:weak_relation(R1),\nsofs:to_external(R2).\n[{1,1},{1,2},{2,2},{3,1},{3,3}]\n```","title":"sofs.weak_relation/1","ref":"sofs.html#weak_relation/1"},{"type":"type","doc":"A [function](`m:sofs#function`).","title":"sofs.a_function/0","ref":"sofs.html#t:a_function/0"},{"type":"opaque","doc":"An [unordered set](`m:sofs#sets_definition`).","title":"sofs.a_set/0","ref":"sofs.html#t:a_set/0"},{"type":"type","doc":"Any kind of set (also included are the atomic sets).","title":"sofs.anyset/0","ref":"sofs.html#t:anyset/0"},{"type":"type","doc":"A [binary relation](`m:sofs#binary_relation`).","title":"sofs.binary_relation/0","ref":"sofs.html#t:binary_relation/0"},{"type":"type","doc":"An [external set](`m:sofs#external_set`).","title":"sofs.external_set/0","ref":"sofs.html#t:external_set/0"},{"type":"type","doc":"A [family](`m:sofs#family`) (of subsets).","title":"sofs.family/0","ref":"sofs.html#t:family/0"},{"type":"opaque","doc":"An [ordered set](`m:sofs#sets_definition`).","title":"sofs.ordset/0","ref":"sofs.html#t:ordset/0"},{"type":"type","doc":"An [n-ary relation](`m:sofs#n_ary_relation`).","title":"sofs.relation/0","ref":"sofs.html#t:relation/0"},{"type":"type","doc":"A [SetFun](`m:sofs#set_fun`).","title":"sofs.set_fun/0","ref":"sofs.html#t:set_fun/0"},{"type":"type","doc":"An [unordered set](`m:sofs#sets_definition`) of unordered sets.","title":"sofs.set_of_sets/0","ref":"sofs.html#t:set_of_sets/0"},{"type":"type","doc":"","title":"sofs.spec_fun/0","ref":"sofs.html#t:spec_fun/0"},{"type":"type","doc":"A tuple where the elements are of type `T`.","title":"sofs.tuple_of/1","ref":"sofs.html#t:tuple_of/1"},{"type":"type","doc":"A [type](`m:sofs#type`).","title":"sofs.type/0","ref":"sofs.html#t:type/0"},{"type":"module","doc":"Library for handling binary data.\n\nThis module contains functions for manipulating byte-oriented binaries. Although\nthe majority of functions could be provided using bit-syntax, the functions in\nthis library are highly optimized and are expected to either execute faster or\nconsume less memory, or both, than a counterpart written in pure Erlang.\n\nThe module is provided according to Erlang Enhancement Proposal (EEP) 31.\n\n> #### Note {: .info }\n>\n> The library handles byte-oriented data. For bitstrings that are not binaries\n> (does not contain whole octets of bits) a `badarg` exception is thrown from\n> any of the functions in this module.","title":"binary","ref":"binary.html"},{"type":"function","doc":"Returns the byte at position `Pos` (zero-based) in binary `Subject` as an\ninteger.\n\nIf `Pos` >= [`byte_size(Subject)`](`byte_size/1`), a `badarg` exception\nis raised.","title":"binary.at/2","ref":"binary.html#at/2"},{"type":"function","doc":"Converts `Subject` to a list of `t:byte/0`s, each representing the value of one byte.\n\n_Example:_\n\n```erlang\n1> binary:bin_to_list(<<\"erlang\">>).\n\"erlang\"\n%% or [101,114,108,97,110,103] in list notation.\n```","title":"binary.bin_to_list/1","ref":"binary.html#bin_to_list/1"},{"type":"function","doc":"","title":"binary.bin_to_list/2","ref":"binary.html#bin_to_list/2"},{"type":"function","doc":"Converts `Subject` to a list of `t:byte/0`s, each representing the value of one\nbyte. `PosLen` or alternatively `Pos` and `Len` denote which part of the\n`Subject` binary to convert. By default, the entire `Subject` binary is\nconverted.\n\n_Example:_\n\n```erlang\n1> binary:bin_to_list(<<\"erlang\">>, {1,3}).\n\"rla\"\n%% or [114,108,97] in list notation.\n```\n\nIf `PosLen` or alternatively `Pos` and `Len` in any way reference outside the\nbinary, a `badarg` exception is raised.","title":"binary.bin_to_list/3","ref":"binary.html#bin_to_list/3"},{"type":"function","doc":"Builds an internal structure representing a compilation of a search pattern,\nlater to be used in functions `match/3`, `matches/3`, `split/3`, or `replace/4`.\n\nThe `t:cp/0` returned is guaranteed to be a `t:tuple/0` to allow programs to\ndistinguish it from non-precompiled search patterns.\n\nWhen a list of binaries is specified, it denotes a set of alternative binaries\nto search for. For example, if `[<<\"functional\">>,<<\"programming\">>]` is\nspecified as `Pattern`, this means either `<<\"functional\">>` or\n`<<\"programming\">>`\". The pattern is a set of alternatives; when only a single\nbinary is specified, the set has only one element. The order of alternatives in\na pattern is not significant.\n\nThe list of binaries used for search alternatives must be flat, proper and\nnon-empty.\n\nIf `Pattern` is not a binary or a flat proper non-empty list of binaries with\nlength > 0, a `badarg` exception is raised.","title":"binary.compile_pattern/1","ref":"binary.html#compile_pattern/1"},{"type":"function","doc":"","title":"binary.copy/1","ref":"binary.html#copy/1"},{"type":"function","doc":"Creates a binary with the content of `Subject` duplicated `N` times.\n\nThis function always creates a new binary, even if `N = 1`. By using `copy/1` on\na binary referencing a larger binary, one can free up the larger binary for\ngarbage collection.\n\n> #### Note {: .info }\n>\n> By deliberately copying a single binary to avoid referencing a larger binary,\n> one can, instead of freeing up the larger binary for later garbage collection,\n> create much more binary data than needed. Sharing binary data is usually good.\n> Only in special cases, when small parts reference large binaries and the large\n> binaries are no longer used in any process, deliberate copying can be a good\n> idea.","title":"binary.copy/2","ref":"binary.html#copy/2"},{"type":"function","doc":"Decodes a hex encoded binary into a binary.\n\n_Example_\n\n```erlang\n1> binary:decode_hex(<<\"66\">>).\n<<\"f\">>\n```","title":"binary.decode_hex/1","ref":"binary.html#decode_hex/1"},{"type":"function","doc":"","title":"binary.decode_unsigned/1","ref":"binary.html#decode_unsigned/1"},{"type":"function","doc":"Converts the binary digit representation, in big endian or little endian, of a\npositive integer in `Subject` to an Erlang `t:integer/0`.\n\n_Example:_\n\n```erlang\n1> binary:decode_unsigned(<<169,138,199>>).\n11111111\n2> binary:decode_unsigned(<<169,138,199>>, big).\n11111111\n3> binary:decode_unsigned(<<169,138,199>>, little).\n13077161\n```","title":"binary.decode_unsigned/2","ref":"binary.html#decode_unsigned/2"},{"type":"function","doc":"","title":"binary.encode_hex/1","ref":"binary.html#encode_hex/1"},{"type":"function","doc":"Encodes a binary into a hex encoded binary using the specified case for the\nhexadecimal digits \"a\" to \"f\".\n\nThe default case is `uppercase`.\n\n_Example:_\n\n```erlang\n1> binary:encode_hex(<<\"f\">>).\n<<\"66\">>\n2> binary:encode_hex(<<\"/\">>).\n<<\"2F\">>\n3> binary:encode_hex(<<\"/\">>, lowercase).\n<<\"2f\">>\n4> binary:encode_hex(<<\"/\">>, uppercase).\n<<\"2F\">>\n```","title":"binary.encode_hex/2","ref":"binary.html#encode_hex/2"},{"type":"function","doc":"","title":"binary.encode_unsigned/1","ref":"binary.html#encode_unsigned/1"},{"type":"function","doc":"Converts a positive integer to the smallest possible representation in a binary\ndigit representation, either big endian or little endian.\n\n_Example:_\n\n```erlang\n1> binary:encode_unsigned(11111111).\n<<169,138,199>>\n2> binary:encode_unsigned(11111111, big).\n<<169,138,199>>\n2> binary:encode_unsigned(11111111, little).\n<<199,138,169>>\n```","title":"binary.encode_unsigned/2","ref":"binary.html#encode_unsigned/2"},{"type":"function","doc":"Returns the first byte of binary `Subject` as an integer. If the size of\n`Subject` is zero, a `badarg` exception is raised.","title":"binary.first/1","ref":"binary.html#first/1"},{"type":"function","doc":"Joins a list of binaries together by a specified `Separator`.\n\nEquivalent to `iolist_to_binary(lists:join(Separator, Binaries))`, but faster.\n\n_Example:_\n\n```erlang\n1> binary:join([<<\"a\">>, <<\"b\">>, <<\"c\">>], <<\", \">>).\n<<\"a, b, c\">>\n```","title":"binary.join/2","ref":"binary.html#join/2"},{"type":"function","doc":"Returns the last byte of binary `Subject` as an integer. If the size of\n`Subject` is zero, a `badarg` exception is raised.","title":"binary.last/1","ref":"binary.html#last/1"},{"type":"function","doc":"Works exactly as `erlang:list_to_binary/1`, added for completeness.","title":"binary.list_to_bin/1","ref":"binary.html#list_to_bin/1"},{"type":"function","doc":"Returns the length of the longest common prefix of the binaries in list\n`Binaries`.\n\n_Example:_\n\n```erlang\n1> binary:longest_common_prefix([<<\"erlang\">>, <<\"ergonomy\">>]).\n2\n2> binary:longest_common_prefix([<<\"erlang\">>, <<\"perl\">>]).\n0\n```\n\nIf `Binaries` is not a flat non-empty list of binaries, a `badarg` exception is\nraised.","title":"binary.longest_common_prefix/1","ref":"binary.html#longest_common_prefix/1"},{"type":"function","doc":"Returns the length of the longest common suffix of the binaries in list\n`Binaries`.\n\n_Example:_\n\n```erlang\n1> binary:longest_common_suffix([<<\"erlang\">>, <<\"fang\">>]).\n3\n2> binary:longest_common_suffix([<<\"erlang\">>, <<\"perl\">>]).\n0\n```\n\nIf `Binaries` is not a flat non-empty list of binaries, a `badarg` exception is\nraised.","title":"binary.longest_common_suffix/1","ref":"binary.html#longest_common_suffix/1"},{"type":"function","doc":"","title":"binary.match/2","ref":"binary.html#match/2"},{"type":"function","doc":"Searches for the first occurrence of `Pattern` in `Subject` and returns the\nposition and length.\n\nThe function returns `{Pos, Length}` for the binary in `Pattern`, starting at\nthe lowest position in `Subject`.\n\n_Example:_\n\n```erlang\n1> binary:match(<<\"abcde\">>, [<<\"bcde\">>, <<\"cd\">>],[]).\n{1,4}\n```\n\nEven though `<<\"cd\">>` ends before `<<\"bcde\">>`, `<<\"bcde\">>` begins first and\nis therefore the first match. If two overlapping matches begin at the same\nposition, the longest is returned.\n\nSummary of the options:\n\n- **\\{scope, \\{Start, Length\\}\\}** - Only the specified part is searched. Return\n values still have offsets from the beginning of `Subject`. A negative `Length`\n is allowed as described in section Data Types in this manual.\n\nIf none of the strings in `Pattern` is found, the atom `nomatch` is returned.\n\nFor a description of `Pattern`, see function `compile_pattern/1`.\n\nIf `{scope, {Start,Length}}` is specified in the options such that `Start` >\nsize of `Subject`, `Start` \\+ `Length` < 0 or `Start` \\+ `Length` > size of\n`Subject`, a `badarg` exception is raised.","title":"binary.match/3","ref":"binary.html#match/3"},{"type":"function","doc":"","title":"binary.matches/2","ref":"binary.html#matches/2"},{"type":"function","doc":"As `match/2`, but `Subject` is searched until exhausted and a list of all\nnon-overlapping parts matching `Pattern` is returned (in order).\n\nThe first and longest match is preferred to a shorter, which is illustrated by\nthe following example:\n\n```erlang\n1> binary:matches(<<\"abcde\">>,\n [<<\"bcde\">>,<<\"bc\">>,<<\"de\">>],[]).\n[{1,4}]\n```\n\nThe result shows that <<\"bcde\">> is selected instead of the shorter match\n<<\"bc\">> (which would have given raise to one more match, <<\"de\">>). This\ncorresponds to the behavior of POSIX regular expressions (and programs like\nawk), but is not consistent with alternative matches in `re` (and Perl), where\ninstead lexical ordering in the search pattern selects which string matches.\n\nIf none of the strings in a pattern is found, an empty list is returned.\n\nFor a description of `Pattern`, see `compile_pattern/1`. For a description of\navailable options, see `match/3`.\n\nIf `{scope, {Start,Length}}` is specified in the options such that `Start` >\nsize of `Subject`, `Start + Length` < 0 or `Start + Length` is > size of\n`Subject`, a `badarg` exception is raised.","title":"binary.matches/3","ref":"binary.html#matches/3"},{"type":"function","doc":"","title":"binary.part/2","ref":"binary.html#part/2"},{"type":"function","doc":"Extracts the part of binary `Subject` described by `PosLen`.\n\nA negative length can be used to extract bytes at the end of a binary:\n\n```erlang\n1> Bin = <<1,2,3,4,5,6,7,8,9,10>>.\n2> binary:part(Bin, {byte_size(Bin), -5}).\n<<6,7,8,9,10>>\n```\n\n> #### Note {: .info }\n>\n> `part/2` and `part/3` are also available in the `m:erlang` module under the\n> names [`binary_part/2`](`binary_part/2`) and\n> [`binary_part/3`](`binary_part/3`). Those BIFs are allowed in guard tests.\n\nIf `PosLen` in any way references outside the binary, a `badarg` exception is\nraised.","title":"binary.part/3","ref":"binary.html#part/3"},{"type":"function","doc":"Get the size of the underlying binary referenced by `Binary`.\n\nIf a binary references a larger binary (often described as being a subbinary),\nit can be useful to get the size of the referenced binary. This function can be\nused in a program to trigger the use of `copy/1`. By copying\n a binary, one can dereference the original, possibly large, binary that a\nsmaller binary is a reference to.\n\n_Example:_\n\n```erlang\nstore(Binary, GBSet) ->\n NewBin =\n case binary:referenced_byte_size(Binary) of\n Large when Large > 2 * byte_size(Binary) ->\n binary:copy(Binary);\n _ ->\n Binary\n end,\n gb_sets:insert(NewBin,GBSet).\n```\n\nIn this example, we chose to copy the binary content before inserting it in\n[`gb_sets:set()`](`t:gb_sets:set/0`) if it references a binary more than twice\nthe data size we want to keep. Of course, different rules apply when copying to\ndifferent programs.\n\nBinary sharing occurs whenever binaries are taken apart. This is the fundamental\nreason why binaries are fast, decomposition can always be done with O(1)\ncomplexity. In rare circumstances this data sharing is however undesirable, why\nthis function together with [`copy/1`](`copy/1`) can be useful when optimizing\nfor memory use.\n\nExample of binary sharing:\n\n```erlang\n1> A = binary:copy(<<1>>, 100).\n<<1,1,1,1,1 ...\n2> byte_size(A).\n100\n3> binary:referenced_byte_size(A).\n100\n4> < > = A.\n<<1,1,1,1,1 ...\n5> {byte_size(B), binary:referenced_byte_size(B)}.\n{10,10}\n6> {byte_size(C), binary:referenced_byte_size(C)}.\n{90,100}\n```\n\nIn the above example, the small binary `B` was copied while the larger binary\n`C` references binary `A`.\n\n> #### Note {: .info }\n>\n> Binary data is shared among processes. If another process still references the\n> larger binary, copying the part this process uses only consumes more memory\n> and does not free up the larger binary for garbage collection. Use this kind\n> of intrusive functions with extreme care and only if a real problem is\n> detected.","title":"binary.referenced_byte_size/1","ref":"binary.html#referenced_byte_size/1"},{"type":"function","doc":"","title":"binary.replace/3","ref":"binary.html#replace/3"},{"type":"function","doc":"Constructs a new binary by replacing the parts in `Subject` matching `Pattern`\nwith `Replacement` if given as a literal `t:binary/0` or with the result of\napplying `Replacement` to a matching subpart if given as a `fun`.\n\nIf `Replacement` is given as a `t:binary/0` and the matching subpart of\n`Subject` giving raise to the replacement is to be inserted in the result,\noption `{insert_replaced, InsPos}` inserts the matching part into `Replacement`\nat the specified position (or positions) before inserting `Replacement` into\n`Subject`. If `Replacement` is given as a `fun` instead, this option is ignored.\n\nIf any position specified in `InsPos` > size of the replacement binary, a\n`badarg` exception is raised.\n\nOptions `global` and `{scope, part()}` work as for `split/3`. The return type is\nalways a `t:binary/0`.\n\nFor a description of `Pattern`, see `compile_pattern/1`.\n\n_Examples:_\n\n```erlang\n1> binary:replace(<<\"abcde\">>, [<<\"b\">>, <<\"d\">>], <<\"X\">>, []).\n<<\"aXcde\">>\n\n2> binary:replace(<<\"abcde\">>, [<<\"b\">>, <<\"d\">>], <<\"X\">>, [global]).\n<<\"aXcXe\">>\n\n3> binary:replace(<<\"abcde\">>, <<\"b\">>, <<\"[]\">>, [{insert_replaced, 1}]).\n<<\"a[b]cde\">>\n\n4> binary:replace(<<\"abcde\">>, [<<\"b\">>, <<\"d\">>], <<\"[]\">>, [global, {insert_replaced, 1}]).\n<<\"a[b]c[d]e\">>\n\n5> binary:replace(<<\"abcde\">>, [<<\"b\">>, <<\"d\">>], <<\"[]\">>, [global, {insert_replaced, [1, 1]}]).\n<<\"a[bb]c[dd]e\">>\n\n6> binary:replace(<<\"abcde\">>, [<<\"b\">>, <<\"d\">>], <<\"[-]\">>, [global, {insert_replaced, [1, 2]}]).\n<<\"a[b-b]c[d-d]e\">>\n\n7> binary:replace(<<\"abcde\">>, [<<\"b\">>, <<\"d\">>], fun(M) -> <<$[, M/binary, $]>> end, []).\n<<\"a[b]cde\">>\n\n8> binary:replace(<<\"abcde\">>, [<<\"b\">>, <<\"d\">>], fun(M) -> <<$[, M/binary, $]>> end, [global]).\n<<\"a[b]c[d]e\">>\n```","title":"binary.replace/4","ref":"binary.html#replace/4"},{"type":"function","doc":"","title":"binary.split/2","ref":"binary.html#split/2"},{"type":"function","doc":"Splits `Subject` into a list of binaries based on `Pattern`.\n\nIf option `global` is not specified, only the first occurrence of `Pattern` in\n`Subject` gives rise to a split.\n\nThe parts of `Pattern` found in `Subject` are not included in the result.\n\n_Example:_\n\n```erlang\n1> binary:split(<<1,255,4,0,0,0,2,3>>, [<<0,0,0>>,<<2>>],[]).\n[<<1,255,4>>, <<2,3>>]\n2> binary:split(<<0,1,0,0,4,255,255,9>>, [<<0,0>>, <<255,255>>],[global]).\n[<<0,1>>,<<4>>,<<9>>]\n```\n\nSummary of options:\n\n- **\\{scope, part()\\}** - Works as in `match/3` and `matches/3`. Notice that\n this only defines the scope of the search for matching strings, it does not\n cut the binary before splitting. The bytes before and after the scope are kept\n in the result. See the example below.\n\n- **trim** - Removes trailing empty parts of the result (as does `trim` in\n `re:split/3`.\n\n- **trim_all** - Removes all empty parts of the result.\n\n- **global** - Repeats the split until `Subject` is exhausted. Conceptually\n option `global` makes split work on the positions returned by `matches/3`,\n while it normally works on the position returned by `match/3`.\n\nExample of the difference between a scope and taking the binary apart before\nsplitting:\n\n```erlang\n1> binary:split(<<\"banana\">>, [<<\"a\">>],[{scope,{2,3}}]).\n[<<\"ban\">>,<<\"na\">>]\n2> binary:split(binary:part(<<\"banana\">>,{2,3}), [<<\"a\">>],[]).\n[<<\"n\">>,<<\"n\">>]\n```\n\nThe return type is always a list of binaries that are all referencing `Subject`.\nThis means that the data in `Subject` is not copied to new binaries, and that\n`Subject` cannot be garbage collected until the results of the split are no\nlonger referenced.\n\nFor a description of `Pattern`, see `compile_pattern/1`.","title":"binary.split/3","ref":"binary.html#split/3"},{"type":"opaque","doc":"Opaque data type representing a compiled search pattern.\n\nGuaranteed to be a `t:tuple/0` to allow programs to distinguish it from\nnon-precompiled search patterns.","title":"binary.cp/0","ref":"binary.html#t:cp/0"},{"type":"type","doc":"A representation of a part (or range) in a binary. `Start` is a zero-based\noffset into a `t:binary/0` and `Length` is the length of that part.\n\nAs input to functions in this module, a reverse part specification is allowed, constructed\nwith a negative `Length`, so that the part of the binary begins at `Start` \\+\n`Length` and is -`Length` long. This is useful for referencing the last `N`\nbytes of a binary as `{size(Binary), -N}`. The functions in this module always\nreturn `t:part/0`s with positive `Length`.","title":"binary.part/0","ref":"binary.html#t:part/0"},{"type":"module","doc":"List processing functions.\n\nThis module contains functions for list processing.\n\nUnless otherwise stated, all functions assume that position numbering starts\nat 1. That is, the first element of a list is at position 1.\n\nTwo terms `T1` and `T2` compare equal if `T1 == T2` evaluates to `true`. They\nmatch if `T1 =:= T2` evaluates to `true`.\n\nWhenever an _ordering function_{: #ordering_function } `F` is expected as\nargument, it is assumed that the following properties hold of `F` for all x, y,\nand z:\n\n- If x `F` y and y `F` x, then x = y (`F` is antisymmetric).\n- If x `F` y and y `F` z, then x `F` z (`F` is transitive).\n- x `F` y or y `F` x (`F` is total).\n\nAn example of a typical ordering function is less than or equal to: `= lists:append([[1, 2, 3], [a, b], [4, 5, 6]]).\n[1,2,3,a,b,4,5,6]\n```","title":"lists.append/1","ref":"lists.html#append/1"},{"type":"function","doc":"Returns a new list `List3`, which is made from the elements of `List1` followed\nby the elements of `List2`.\n\n_Example:_\n\n```erlang\n> lists:append(\"abc\", \"def\").\n\"abcdef\"\n```\n\n`lists:append(A, B)` is equivalent to `A ++ B`.","title":"lists.append/2","ref":"lists.html#append/2"},{"type":"function","doc":"Concatenates the text representation of the elements of `Things`. The elements\nof `Things` can be atoms, integers, floats, or strings.\n\n_Example:_\n\n```erlang\n> lists:concat([doc, '/', file, '.', 3]).\n\"doc/file.3\"\n```","title":"lists.concat/1","ref":"lists.html#concat/1"},{"type":"function","doc":"Returns a copy of `List1` where the first element matching `Elem` is deleted, if\nthere is such an element.","title":"lists.delete/2","ref":"lists.html#delete/2"},{"type":"function","doc":"Drops the last element of a `List`. The list is to be non-empty, otherwise the\nfunction crashes with a `function_clause`.","title":"lists.droplast/1","ref":"lists.html#droplast/1"},{"type":"function","doc":"Drops elements `Elem` from `List1` while `Pred(Elem)` returns `true` and returns\nthe remaining list. The `Pred` function must return a boolean.","title":"lists.dropwhile/2","ref":"lists.html#dropwhile/2"},{"type":"function","doc":"Returns a list containing `N` copies of term `Elem`.\n\n_Example:_\n\n```erlang\n> lists:duplicate(5, xx).\n[xx,xx,xx,xx,xx]\n```","title":"lists.duplicate/2","ref":"lists.html#duplicate/2"},{"type":"function","doc":"","title":"lists.enumerate/1","ref":"lists.html#enumerate/1"},{"type":"function","doc":"","title":"lists.enumerate/2","ref":"lists.html#enumerate/2"},{"type":"function","doc":"Returns `List1` with each element `H` replaced by a tuple of form `{I, H}` where\n`I` is the position of `H` in `List1`. The enumeration starts with `Index` and\nincreases by `Step` in each step.\n\nThat is, [`enumerate/3`](`enumerate/3`) behaves as if it had been defined as\nfollows:\n\n```erlang\nenumerate(I, S, List) ->\n {List1, _ } = lists:mapfoldl(fun(T, Acc) -> {{Acc, T}, Acc+S} end, I, List),\n List1.\n```\n\nThe default values for `Index` and `Step` are both `1`.\n\n_Examples:_\n\n```erlang\n> lists:enumerate([a,b,c]).\n[{1,a},{2,b},{3,c}]\n```\n\n```erlang\n> lists:enumerate(10, [a,b,c]).\n[{10,a},{11,b},{12,c}]\n```\n\n```erlang\n> lists:enumerate(0, -2, [a,b,c]).\n[{0,a},{-2,b},{-4,c}]\n```","title":"lists.enumerate/3","ref":"lists.html#enumerate/3"},{"type":"function","doc":"`List2` is a list of all elements `Elem` in `List1` for which `Pred(Elem)`\nreturns `true`. The `Pred` function must return a boolean.","title":"lists.filter/2","ref":"lists.html#filter/2"},{"type":"function","doc":"Calls `Fun(Elem)` on successive elements `Elem` of `List1` in order to update or\nremove elements from `List1`.\n\n`Fun/1` must return either a Boolean or a tuple `{true, Value}`. The function\nreturns the list of elements for which `Fun` returns a new value, where a value\nof `true` is synonymous with `{true, Elem}`.\n\nThat is, `filtermap` behaves as if it had been defined as follows:\n\n```erlang\nfiltermap(Fun, List1) ->\n lists:foldr(fun(Elem, Acc) ->\n case Fun(Elem) of\n false -> Acc;\n true -> [Elem|Acc];\n {true,Value} -> [Value|Acc]\n end\n end, [], List1).\n```\n\n_Example:_\n\n```erlang\n> lists:filtermap(fun(X) -> case X rem 2 of 0 -> {true, X div 2}; _ -> false end end, [1,2,3,4,5]).\n[1,2]\n```","title":"lists.filtermap/2","ref":"lists.html#filtermap/2"},{"type":"function","doc":"Equivalent to [`length(flatten(DeepList))`](`length/1`), but more efficient.","title":"lists.flatlength/1","ref":"lists.html#flatlength/1"},{"type":"function","doc":"Takes a function from `A`s to lists of `B`s, and a list of `A`s (`List1`) and\nproduces a list of `B`s by applying the function to every element in `List1` and\nappending the resulting lists.\n\nThat is, `flatmap` behaves as if it had been defined as follows:\n\n```erlang\nflatmap(Fun, List1) ->\n append(map(Fun, List1)).\n```\n\n_Example:_\n\n```erlang\n> lists:flatmap(fun(X)->[X,X] end, [a,b,c]).\n[a,a,b,b,c,c]\n```","title":"lists.flatmap/2","ref":"lists.html#flatmap/2"},{"type":"function","doc":"Returns a flattened version of `DeepList`.","title":"lists.flatten/1","ref":"lists.html#flatten/1"},{"type":"function","doc":"Returns a flattened version of `DeepList` with tail `Tail` appended.","title":"lists.flatten/2","ref":"lists.html#flatten/2"},{"type":"function","doc":"Calls `Fun(Elem, AccIn)` on successive elements `A` of `List`, starting with\n`AccIn == Acc0`. `Fun/2` must return a new accumulator, which is passed to the\nnext call. The function returns the final value of the accumulator. `Acc0` is\nreturned if the list is empty.\n\n_Example:_\n\n```erlang\n> lists:foldl(fun(X, Sum) -> X + Sum end, 0, [1,2,3,4,5]).\n15\n> lists:foldl(fun(X, Prod) -> X * Prod end, 1, [1,2,3,4,5]).\n120\n```","title":"lists.foldl/3","ref":"lists.html#foldl/3"},{"type":"function","doc":"Like `foldl/3`, but the list is traversed from right to left.\n\n_Example:_\n\n```erlang\n> P = fun(A, AccIn) -> io:format(\"~p \", [A]), AccIn end.\n#Fun \n> lists:foldl(P, void, [1,2,3]).\n1 2 3 void\n> lists:foldr(P, void, [1,2,3]).\n3 2 1 void\n```\n\n[`foldl/3`](`foldl/3`) is tail recursive and is usually preferred to\n[`foldr/3`](`foldr/3`).","title":"lists.foldr/3","ref":"lists.html#foldr/3"},{"type":"function","doc":"Calls `Fun(Elem)` for each element `Elem` in `List`. This function is used for\nits side effects and the evaluation order is defined to be the same as the order\nof the elements in the list.","title":"lists.foreach/2","ref":"lists.html#foreach/2"},{"type":"function","doc":"Inserts `Sep` between each element in `List1`. Has no effect on the empty list\nand on a singleton list. For example:\n\n```erlang\n> lists:join(x, [a,b,c]).\n[a,x,b,x,c]\n> lists:join(x, [a]).\n[a]\n> lists:join(x, []).\n[]\n```","title":"lists.join/2","ref":"lists.html#join/2"},{"type":"function","doc":"Returns a copy of `TupleList1` where the first occurrence of a tuple whose `N`th\nelement compares equal to `Key` is deleted, if there is such a tuple.","title":"lists.keydelete/3","ref":"lists.html#keydelete/3"},{"type":"function","doc":"Searches the list of tuples `TupleList` for a tuple whose `N`th element compares\nequal to `Key`. Returns `Tuple` if such a tuple is found, otherwise `false`.","title":"lists.keyfind/3","ref":"lists.html#keyfind/3"},{"type":"function","doc":"Returns a list of tuples where, for each tuple in `TupleList1`, the `N`th\nelement `Term1` of the tuple has been replaced with the result of calling\n`Fun(Term1)`.\n\n_Examples:_\n\n```erlang\n> Fun = fun(Atom) -> atom_to_list(Atom) end.\n#Fun \n2> lists:keymap(Fun, 2, [{name,jane,22},{name,lizzie,20},{name,lydia,15}]).\n[{name,\"jane\",22},{name,\"lizzie\",20},{name,\"lydia\",15}]\n```","title":"lists.keymap/3","ref":"lists.html#keymap/3"},{"type":"function","doc":"Returns `true` if there is a tuple in `TupleList` whose `N`th element compares\nequal to `Key`, otherwise `false`.","title":"lists.keymember/3","ref":"lists.html#keymember/3"},{"type":"function","doc":"Returns the sorted list formed by merging `TupleList1` and `TupleList2`.\n\nThe merge is performed on the `N`th element of each tuple. Both `TupleList1` and\n`TupleList2` must be key-sorted before evaluating this function. When two tuples\ncompare equal, the tuple from `TupleList1` is picked before the tuple from\n`TupleList2`.","title":"lists.keymerge/3","ref":"lists.html#keymerge/3"},{"type":"function","doc":"Returns a copy of `TupleList1` where the first occurrence of a `T` tuple whose\n`N`th element compares equal to `Key` is replaced with `NewTuple`, if there is\nsuch a tuple `T`.","title":"lists.keyreplace/4","ref":"lists.html#keyreplace/4"},{"type":"function","doc":"Searches the list of tuples `TupleList` for a tuple whose `N`th element compares\nequal to `Key`. Returns `{value, Tuple}` if such a tuple is found, otherwise\n`false`.\n\n> #### Note {: .info }\n>\n> This function is retained for backward compatibility. Function `keyfind/3` is\n> usually more convenient.","title":"lists.keysearch/3","ref":"lists.html#keysearch/3"},{"type":"function","doc":"Returns a list containing the sorted elements of list `TupleList1`. Sorting is\nperformed on the `N`th element of the tuples. The sort is stable.","title":"lists.keysort/2","ref":"lists.html#keysort/2"},{"type":"function","doc":"Returns a copy of `TupleList1` where the first occurrence of a tuple `T` whose\n`N`th element compares equal to `Key` is replaced with `NewTuple`, if there is\nsuch a tuple `T`. If there is no such tuple `T`, a copy of `TupleList1` where\n[`NewTuple`] has been appended to the end is returned.","title":"lists.keystore/4","ref":"lists.html#keystore/4"},{"type":"function","doc":"Searches the list of tuples `TupleList1` for a tuple whose `N`th element\ncompares equal to `Key`. Returns `{value, Tuple, TupleList2}` if such a tuple is\nfound, otherwise `false`. `TupleList2` is a copy of `TupleList1` where the first\noccurrence of `Tuple` has been removed.","title":"lists.keytake/3","ref":"lists.html#keytake/3"},{"type":"function","doc":"Returns the last element in `List`.","title":"lists.last/1","ref":"lists.html#last/1"},{"type":"function","doc":"Takes a function from `A`s to `B`s, and a list of `A`s and produces a list of\n`B`s by applying the function to every element in the list. This function is\nused to obtain the return values. The evaluation order depends on the\nimplementation.","title":"lists.map/2","ref":"lists.html#map/2"},{"type":"function","doc":"Combines the operations of `map/2` and `foldl/3` into one pass.\n\n_Example:_\n\nSumming the elements in a list and double them at the same time:\n\n```erlang\n> lists:mapfoldl(fun(X, Sum) -> {2*X, X+Sum} end,\n0, [1,2,3,4,5]).\n{[2,4,6,8,10],15}\n```","title":"lists.mapfoldl/3","ref":"lists.html#mapfoldl/3"},{"type":"function","doc":"Combines the operations of `map/2` and `foldr/3` into one pass.","title":"lists.mapfoldr/3","ref":"lists.html#mapfoldr/3"},{"type":"function","doc":"Returns the first element of `List` that compares greater than or equal to all\nother elements of `List`.","title":"lists.max/1","ref":"lists.html#max/1"},{"type":"function","doc":"Returns `true` if `Elem` matches some element of `List`, otherwise `false`.","title":"lists.member/2","ref":"lists.html#member/2"},{"type":"function","doc":"Returns the sorted list formed by merging `List1`, `List2`, and `List3`. All of\n`List1`, `List2`, and `List3` must be sorted before evaluating this function.\n\nWhen two elements compare equal, the element from `List1`, if there is such an\nelement, is picked before the other element, otherwise the element from `List2`\nis picked before the element from `List3`.","title":"lists.merge3/3","ref":"lists.html#merge3/3"},{"type":"function","doc":"Returns the sorted list formed by merging all the sublists of `ListOfLists`. All\nsublists must be sorted before evaluating this function.\n\nWhen two elements compare equal, the element from the sublist with the lowest\nposition in `ListOfLists` is picked before the other element.","title":"lists.merge/1","ref":"lists.html#merge/1"},{"type":"function","doc":"Returns the sorted list formed by merging `List1` and `List2`. Both `List1` and\n`List2` must be sorted before evaluating this function.\n\nWhen two elements compare equal, the element from `List1` is picked before the\nelement from `List2`.","title":"lists.merge/2","ref":"lists.html#merge/2"},{"type":"function","doc":"Returns the sorted list formed by merging `List1` and `List2`. Both `List1` and\n`List2` must be sorted according to the\n[ordering function](`m:lists#ordering_function`) `Fun` before evaluating this\nfunction.\n\n`Fun(A, B)` is to return `true` if `A` compares less than or equal to\n`B` in the ordering, otherwise `false`. When two elements compare equal, the\nelement from `List1` is picked before the element from `List2`.","title":"lists.merge/3","ref":"lists.html#merge/3"},{"type":"function","doc":"Returns the first element of `List` that compares less than or equal to all\nother elements of `List`.","title":"lists.min/1","ref":"lists.html#min/1"},{"type":"function","doc":"Returns the `N`th element of `List`.\n\n_Example:_\n\n```erlang\n> lists:nth(3, [a, b, c, d, e]).\nc\n```","title":"lists.nth/2","ref":"lists.html#nth/2"},{"type":"function","doc":"Returns the `N`th tail of `List`, that is, the sublist of `List` starting at\n`N+1` and continuing up to the end of the list.\n\n_Example_\n\n```erlang\n> lists:nthtail(3, [a, b, c, d, e]).\n[d,e]\n> tl(tl(tl([a, b, c, d, e]))).\n[d,e]\n> lists:nthtail(0, [a, b, c, d, e]).\n[a,b,c,d,e]\n> lists:nthtail(5, [a, b, c, d, e]).\n[]\n```","title":"lists.nthtail/2","ref":"lists.html#nthtail/2"},{"type":"function","doc":"Partitions `List` into two lists, where the first list contains all elements for\nwhich `Pred(Elem)` returns `true`, and the second list contains all elements for\nwhich `Pred(Elem)` returns `false`.\n\n_Examples:_\n\n```erlang\n> lists:partition(fun(A) -> A rem 2 == 1 end, [1,2,3,4,5,6,7]).\n{[1,3,5,7],[2,4,6]}\n> lists:partition(fun(A) -> is_atom(A) end, [a,b,1,c,d,2,3,4,e]).\n{[a,b,c,d,e],[1,2,3,4]}\n```\n\nFor a different way to partition a list, see `splitwith/2`.","title":"lists.partition/2","ref":"lists.html#partition/2"},{"type":"function","doc":"Returns `true` if `List1` is a prefix of `List2`, otherwise `false`.","title":"lists.prefix/2","ref":"lists.html#prefix/2"},{"type":"function","doc":"Returns a list with the elements in `List1` in reverse order.","title":"lists.reverse/1","ref":"lists.html#reverse/1"},{"type":"function","doc":"Returns a list with the elements in `List1` in reverse order, with tail `Tail`\nappended.\n\n_Example:_\n\n```erlang\n> lists:reverse([1, 2, 3, 4], [a, b, c]).\n[4,3,2,1,a,b,c]\n```","title":"lists.reverse/2","ref":"lists.html#reverse/2"},{"type":"function","doc":"If there is a `Value` in `List` such that `Pred(Value)` returns `true`, returns\n`{value, Value}` for the first such `Value`, otherwise returns `false`. The\n`Pred` function must return a boolean.","title":"lists.search/2","ref":"lists.html#search/2"},{"type":"function","doc":"","title":"lists.seq/2","ref":"lists.html#seq/2"},{"type":"function","doc":"Returns a sequence of integers that starts with `From` and contains the\nsuccessive results of adding `Incr` to the previous element, until `To` is\nreached or passed (in the latter case, `To` is not an element of the sequence).\n`Incr` defaults to 1.\n\nFailures:\n\n- If `To 0`.\n- If `To > From - Incr` and `Incr < 0`.\n- If `Incr =:= 0` and `From =/= To`.\n\nThe following equalities hold for all sequences:\n\n```erlang\nlength(lists:seq(From, To)) =:= To - From + 1\nlength(lists:seq(From, To, Incr)) =:= (To - From + Incr) div Incr\n```\n\n_Examples:_\n\n```erlang\n> lists:seq(1, 10).\n[1,2,3,4,5,6,7,8,9,10]\n> lists:seq(1, 20, 3).\n[1,4,7,10,13,16,19]\n> lists:seq(1, 0, 1).\n[]\n> lists:seq(10, 6, 4).\n[]\n> lists:seq(1, 1, 0).\n[1]\n```","title":"lists.seq/3","ref":"lists.html#seq/3"},{"type":"function","doc":"Returns a list containing the sorted elements of `List1`.","title":"lists.sort/1","ref":"lists.html#sort/1"},{"type":"function","doc":"Returns a list containing the sorted elements of `List1`, according to the\n[ordering function](`m:lists#ordering_function`) `Fun`. `Fun(A, B)` is to return\n`true` if `A` compares less than or equal to `B` in the ordering, otherwise\n`false`.","title":"lists.sort/2","ref":"lists.html#sort/2"},{"type":"function","doc":"Splits `List1` into `List2` and `List3`. `List2` contains the first `N` elements\nand `List3` the remaining elements (the `N`th tail).","title":"lists.split/2","ref":"lists.html#split/2"},{"type":"function","doc":"Partitions `List` into two lists according to `Pred`.\n[`splitwith/2`](`splitwith/2`) behaves as if it is defined as follows:\n\n```erlang\nsplitwith(Pred, List) ->\n {takewhile(Pred, List), dropwhile(Pred, List)}.\n```\n\n_Examples:_\n\n```erlang\n> lists:splitwith(fun(A) -> A rem 2 == 1 end, [1,2,3,4,5,6,7]).\n{[1],[2,3,4,5,6,7]}\n> lists:splitwith(fun(A) -> is_atom(A) end, [a,b,1,c,d,2,3,4,e]).\n{[a,b],[1,c,d,2,3,4,e]}\n```\n\nThe `Pred` function must return a boolean. For a different way to partition a\nlist, see `partition/2`.","title":"lists.splitwith/2","ref":"lists.html#splitwith/2"},{"type":"function","doc":"Returns the sublist of `List1` starting at position 1 and with (maximum) `Len`\nelements. It is not an error for `Len` to exceed the length of the list, in that\ncase the whole list is returned.","title":"lists.sublist/2","ref":"lists.html#sublist/2"},{"type":"function","doc":"Returns the sublist of `List1` starting at `Start` and with (maximum) `Len`\nelements. It is not an error for `Start+Len` to exceed the length of the list.\n\n_Examples:_\n\n```erlang\n> lists:sublist([1,2,3,4], 2, 2).\n[2,3]\n> lists:sublist([1,2,3,4], 2, 5).\n[2,3,4]\n> lists:sublist([1,2,3,4], 5, 2).\n[]\n```","title":"lists.sublist/3","ref":"lists.html#sublist/3"},{"type":"function","doc":"Returns a new list `List3` that is a copy of `List1`, subjected to the following\nprocedure: for each element in `List2`, its first occurrence in `List1` is\ndeleted.\n\n_Example:_\n\n```erlang\n> lists:subtract(\"123212\", \"212\").\n\"312\".\n```\n\n`lists:subtract(A, B)` is equivalent to `A -- B`.","title":"lists.subtract/2","ref":"lists.html#subtract/2"},{"type":"function","doc":"Returns `true` if `List1` is a suffix of `List2`, otherwise `false`.","title":"lists.suffix/2","ref":"lists.html#suffix/2"},{"type":"function","doc":"Returns the sum of the elements in `List`.","title":"lists.sum/1","ref":"lists.html#sum/1"},{"type":"function","doc":"Takes elements `Elem` from `List1` while `Pred(Elem)` returns `true`, that is,\nthe function returns the longest prefix of the list for which all elements\nsatisfy the predicate. The `Pred` function must return a boolean.","title":"lists.takewhile/2","ref":"lists.html#takewhile/2"},{"type":"function","doc":"Returns the sorted list formed by merging `TupleList1` and `TupleList2`. The\nmerge is performed on the `N`th element of each tuple. Both `TupleList1` and\n`TupleList2` must be key-sorted without duplicates before evaluating this\nfunction.\n\nWhen two tuples compare equal, the tuple from `TupleList1` is picked\nand the one from `TupleList2` is deleted.","title":"lists.ukeymerge/3","ref":"lists.html#ukeymerge/3"},{"type":"function","doc":"Returns a list containing the sorted elements of list `TupleList1` where all\nexcept the first tuple of the tuples comparing equal have been deleted. Sorting\nis performed on the `N`th element of the tuples.","title":"lists.ukeysort/2","ref":"lists.html#ukeysort/2"},{"type":"function","doc":"Returns the sorted list formed by merging `List1`, `List2`, and `List3`. All of\n`List1`, `List2`, and `List3` must be sorted and contain no duplicates before\nevaluating this function.\n\nWhen two elements compare equal, the element from\n`List1` is picked if there is such an element, otherwise the element from\n`List2` is picked, and the other is deleted.","title":"lists.umerge3/3","ref":"lists.html#umerge3/3"},{"type":"function","doc":"Returns the sorted list formed by merging all the sublists of `ListOfLists`. All\nsublists must be sorted and contain no duplicates before evaluating this\nfunction.\n\nWhen two elements compare equal, the element from the sublist with the\nlowest position in `ListOfLists` is picked and the other is deleted.","title":"lists.umerge/1","ref":"lists.html#umerge/1"},{"type":"function","doc":"Returns the sorted list formed by merging `List1` and `List2`. Both `List1` and\n`List2` must be sorted and contain no duplicates before evaluating this\nfunction.\n\nWhen two elements compare equal, the element from `List1` is picked\nand the one from `List2` is deleted.","title":"lists.umerge/2","ref":"lists.html#umerge/2"},{"type":"function","doc":"Returns the sorted list formed by merging `List1` and `List2`. Both `List1` and\n`List2` must be sorted according to the\n[ordering function](`m:lists#ordering_function`) `Fun` and contain no duplicates\nbefore evaluating this function.\n\n`Fun(A, B)` is to return `true` if `A` compares\nless than or equal to `B` in the ordering, otherwise `false`. When two elements\ncompare equal, the element from `List1` is picked and the one from `List2` is\ndeleted.","title":"lists.umerge/3","ref":"lists.html#umerge/3"},{"type":"function","doc":"Returns a list containing the elements of `List1` with duplicated elements\nremoved (preserving the order of the elements). The first occurrence of each\nelement is kept.\n\n_Examples:_\n\n```erlang\n> lists:uniq([3,3,1,2,1,2,3]).\n[3,1,2]\n> lists:uniq([a, a, 1, b, 2, a, 3]).\n[a, 1, b, 2, 3]\n```","title":"lists.uniq/1","ref":"lists.html#uniq/1"},{"type":"function","doc":"Returns a list containing the elements of `List1` without the elements for which\n`Fun` returned duplicate values (preserving the order of the elements). The\nfirst occurrence of each element is kept.\n\n_Examples:_\n\n```erlang\n> lists:uniq(fun({X, _}) -> X end, [{b, 2}, {a, 1}, {c, 3}, {a, 2}]).\n[{b, 2}, {a, 1}, {c, 3}]\n```","title":"lists.uniq/2","ref":"lists.html#uniq/2"},{"type":"function","doc":"\"Unzips\" a list of three-tuples into three lists, where the first list contains\nthe first element of each tuple, the second list contains the second element of\neach tuple, and the third list contains the third element of each tuple.","title":"lists.unzip3/1","ref":"lists.html#unzip3/1"},{"type":"function","doc":"\"Unzips\" a list of two-tuples into two lists, where the first list contains the\nfirst element of each tuple, and the second list contains the second element of\neach tuple.","title":"lists.unzip/1","ref":"lists.html#unzip/1"},{"type":"function","doc":"Returns a list containing the sorted elements of `List1` where all except the\nfirst element of the elements comparing equal have been deleted.","title":"lists.usort/1","ref":"lists.html#usort/1"},{"type":"function","doc":"Returns a list containing the sorted elements of `List1` where all except the\nfirst element of the elements comparing equal according to the\n[ordering function](`m:lists#ordering_function`) `Fun` have been deleted.\n`Fun(A, B)` is to return `true` if `A` compares less than or equal to `B` in the\nordering, otherwise `false`.","title":"lists.usort/2","ref":"lists.html#usort/2"},{"type":"function","doc":"","title":"lists.zip3/3","ref":"lists.html#zip3/3"},{"type":"function","doc":"\"Zips\" three lists into one list of three-tuples, where the first element of\neach tuple is taken from the first list, the second element is taken from the\ncorresponding element in the second list, and the third element is taken from\nthe corresponding element in the third list.\n\nFor a description of the `How` parameter, see `zip/3`.","title":"lists.zip3/4","ref":"lists.html#zip3/4"},{"type":"function","doc":"","title":"lists.zip/2","ref":"lists.html#zip/2"},{"type":"function","doc":"\"Zips\" two lists into one list of two-tuples, where the first element of each\ntuple is taken from the first list and the second element is taken from the\ncorresponding element in the second list.\n\nThe `How` parameter specifies the behavior if the given lists are of different\nlengths.\n\n- **`fail`** - The call will fail if the given lists are not of equal length.\n This is the default.\n\n- **`trim`** - Surplus elements from the longer list will be ignored.\n\n _Examples:_\n\n ```erlang\n > lists:zip([a, b], [1, 2, 3], trim).\n [{a,1},{b,2}]\n > lists:zip([a, b, c], [1, 2], trim).\n [{a,1},{b,2}]\n ```\n\n- **`{pad, Defaults}`** - The shorter list will be padded to the length of the\n longer list, using the respective elements from the given `Defaults` tuple.\n\n _Examples:_\n\n ```erlang\n > lists:zip([a, b], [1, 2, 3], {pad, {x, 0}}).\n [{a,1},{b,2},{x,3}]\n > lists:zip([a, b, c], [1, 2], {pad, {x, 0}}).\n [{a,1},{b,2},{c,0}]\n ```","title":"lists.zip/3","ref":"lists.html#zip/3"},{"type":"function","doc":"","title":"lists.zipwith3/4","ref":"lists.html#zipwith3/4"},{"type":"function","doc":"Combines the elements of three lists into one list. For each triple `X, Y, Z` of\nlist elements from the three lists, the element in the result list is\n`Combine(X, Y, Z)`.\n\nFor a description of the `How` parameter, see `zip/3`.\n\n[`zipwith3(fun(X, Y, Z) -> {X,Y,Z} end, List1, List2, List3)`](`zipwith3/4`) is\nequivalent to [`zip3(List1, List2, List3)`](`zip3/3`).\n\n_Examples:_\n\n```erlang\n> lists:zipwith3(fun(X, Y, Z) -> X+Y+Z end, [1,2,3], [4,5,6], [7,8,9]).\n[12,15,18]\n> lists:zipwith3(fun(X, Y, Z) -> [X,Y,Z] end, [a,b,c], [x,y,z], [1,2,3]).\n[[a,x,1],[b,y,2],[c,z,3]]\n```","title":"lists.zipwith3/5","ref":"lists.html#zipwith3/5"},{"type":"function","doc":"","title":"lists.zipwith/3","ref":"lists.html#zipwith/3"},{"type":"function","doc":"Combines the elements of two lists into one list. For each pair `X, Y` of list\nelements from the two lists, the element in the result list is `Combine(X, Y)`.\n\nFor a description of the `How` parameter, see `zip/3`.\n\n[`zipwith(fun(X, Y) -> {X,Y} end, List1, List2)`](`zipwith/3`) is equivalent to\n[`zip(List1, List2)`](`zip/2`).\n\n_Example:_\n\n```erlang\n> lists:zipwith(fun(X, Y) -> X+Y end, [1,2,3], [4,5,6]).\n[5,7,9]\n```","title":"lists.zipwith/4","ref":"lists.html#zipwith/4"},{"type":"module","doc":"Maps processing functions.\n\nThis module contains functions for maps processing. The Efficiency Guide\ncontains a chapter that describes\n[how to use maps efficiently](`e:system:maps.md`).","title":"maps","ref":"maps.html"},{"type":"function","doc":"Returns a map `Map` for which predicate `Pred` holds true in `MapOrIter`.\n\nThe call fails with a `{badmap,Map}` exception if `MapOrIter` is not a map or\nvalid iterator, or with `badarg` if `Pred` is not a function of arity 2.\n\n_Example:_\n\n```erlang\n> M = #{a => 2, b => 3, c=> 4, \"a\" => 1, \"b\" => 2, \"c\" => 4},\n Pred = fun(K,V) -> is_atom(K) andalso (V rem 2) =:= 0 end,\n maps:filter(Pred,M).\n#{a => 2,c => 4}\n```","title":"maps.filter/2","ref":"maps.html#filter/2"},{"type":"function","doc":"Returns a map `Map` that is the result of calling `Fun(Key, Value1)` for every\n`Key` to value `Value1` association in `MapOrIter` in any order.\n\nIf `Fun(Key, Value1)` returns `true`, the association is copied to the result\nmap. If it returns `false`, the association is not copied. If it returns\n`{true, NewValue}`, the value for `Key` is replaced with `NewValue` in the\nresult map.\n\nThe call fails with a `{badmap,Map}` exception if `MapOrIter` is not a map or\nvalid iterator, or with `badarg` if `Fun` is not a function of arity 2.\n\n_Example:_\n\n```erlang\n> Fun = fun(K,V) when is_atom(K) -> {true, V*2}; (_,V) -> (V rem 2) =:= 0 end,\n Map = #{k1 => 1, \"k2\" => 2, \"k3\" => 3},\n maps:filtermap(Fun,Map).\n#{k1 => 2,\"k2\" => 2}\n```","title":"maps.filtermap/2","ref":"maps.html#filtermap/2"},{"type":"function","doc":"Returns a tuple `{ok, Value}`, where `Value` is the value associated with `Key`,\nor `error` if no value is associated with `Key` in `Map`.\n\nThe call fails with a `{badmap,Map}` exception if `Map` is not a map.\n\n_Example:_\n\n```erlang\n> Map = #{\"hi\" => 42},\n Key = \"hi\",\n maps:find(Key,Map).\n{ok,42}\n```","title":"maps.find/2","ref":"maps.html#find/2"},{"type":"function","doc":"Calls `F(Key, Value, AccIn)` for every `Key` to value `Value` association in\n`MapOrIter` in any order. Function `fun F/3` must return a new accumulator,\nwhich is passed to the next successive call. This function returns the final\nvalue of the accumulator. The initial accumulator value `Init` is returned if\nthe map is empty.\n\nThe call fails with a `{badmap,Map}` exception if `MapOrIter` is not a map or\nvalid iterator, or with `badarg` if `Fun` is not a function of arity 3.\n\n_Example:_\n\n```erlang\n> Fun = fun(K,V,AccIn) when is_list(K) -> AccIn + V end,\n Map = #{\"k1\" => 1, \"k2\" => 2, \"k3\" => 3},\n maps:fold(Fun,0,Map).\n6\n```","title":"maps.fold/3","ref":"maps.html#fold/3"},{"type":"function","doc":"Calls `fun F(Key, Value)` for every `Key` to value `Value` association in\n`MapOrIter` in any order.\n\nThe call fails with a `{badmap,Map}` exception if `MapOrIter` is not a map or\nvalid iterator, or with `badarg` if `Fun` is not a function of arity 2.","title":"maps.foreach/2","ref":"maps.html#foreach/2"},{"type":"function","doc":"Takes a list of keys and a value and builds a map where all keys point to the\nsame value. The key can be in any order, and keys and value can be of any term.\n\n_Example:_\n\n```erlang\n> Keys = [\"a\", \"b\", \"c\"], maps:from_keys(Keys, ok).\n#{\"a\" => ok,\"b\" => ok,\"c\" => ok}\n```","title":"maps.from_keys/2","ref":"maps.html#from_keys/2"},{"type":"function","doc":"Takes a list of key-value tuples elements and builds a map. The associations can\nbe in any order, and both keys and values in the association can be of any term.\n\n\nIf the same key appears more than once, the latter (right-most) value is used\nand the previous values are ignored.\n\n_Example:_\n\n```erlang\n> List = [{\"a\",ignored},{1337,\"value two\"},{42,value_three},{\"a\",1}],\n maps:from_list(List).\n#{42 => value_three,1337 => \"value two\",\"a\" => 1}\n```","title":"maps.from_list/1","ref":"maps.html#from_list/1"},{"type":"function","doc":"Returns value `Value` associated with `Key` if `Map` contains `Key`.\n\nThe call fails with a `{badmap,Map}` exception if `Map` is not a map, or with a\n`{badkey,Key}` exception if no value is associated with `Key`.\n\n_Example:_\n\n```erlang\n> Key = 1337,\n Map = #{42 => value_two,1337 => \"value one\",\"a\" => 1},\n maps:get(Key,Map).\n\"value one\"\n```","title":"maps.get/2","ref":"maps.html#get/2"},{"type":"function","doc":"Returns value `Value` associated with `Key` if `Map` contains `Key`. If no value\nis associated with `Key`, `Default` is returned.\n\nThe call fails with a `{badmap,Map}` exception if `Map` is not a map.\n\n_Example:_\n\n```erlang\n> Map = #{ key1 => val1, key2 => val2 }.\n#{key1 => val1,key2 => val2}\n> maps:get(key1, Map, \"Default value\").\nval1\n> maps:get(key3, Map, \"Default value\").\n\"Default value\"\n```","title":"maps.get/3","ref":"maps.html#get/3"},{"type":"function","doc":"Partitions the given `List` into a map of groups.\n\nThe result is a map where each key is given by `KeyFun` and each value is a list\nof elements from the given `List` for which `KeyFun` returned the same key.\n\nThe order of elements within each group list is preserved from the original\nlist.\n\n_Examples:_\n\n```erlang\n> EvenOdd = fun(X) -> case X rem 2 of 0 -> even; 1 -> odd end end,\nmaps:groups_from_list(EvenOdd, [1, 2, 3]).\n#{even => [2], odd => [1, 3]}\n> maps:groups_from_list(fun erlang:length/1, [\"ant\", \"buffalo\", \"cat\", \"dingo\"]).\n#{3 => [\"ant\", \"cat\"], 5 => [\"dingo\"], 7 => [\"buffalo\"]}\n```","title":"maps.groups_from_list/2","ref":"maps.html#groups_from_list/2"},{"type":"function","doc":"Partitions the given `List` into a map of groups.\n\nThe result is a map where each key is given by `KeyFun` and each value is a list\nof elements from the given `List`, mapped via `ValueFun`, for which `KeyFun`\nreturned the same key.\n\nThe order of elements within each group list is preserved from the original\nlist.\n\n_Examples:_\n\n```erlang\n> EvenOdd = fun(X) -> case X rem 2 of 0 -> even; 1 -> odd end end,\n> Square = fun(X) -> X * X end,\n> maps:groups_from_list(EvenOdd, Square, [1, 2, 3]).\n#{even => [4], odd => [1, 9]}\n> maps:groups_from_list(\n fun erlang:length/1,\n fun lists:reverse/1,\n [\"ant\", \"buffalo\", \"cat\", \"dingo\"]).\n#{3 => [\"tna\", \"tac\"],5 => [\"ognid\"],7 => [\"olaffub\"]}\n```","title":"maps.groups_from_list/3","ref":"maps.html#groups_from_list/3"},{"type":"function","doc":"Intersects two maps into a single map `Map3`. If a key exists in both maps, the\nvalue in `Map1` is superseded by the value in `Map2`.\n\nThe call fails with a `{badmap,Map}` exception if `Map1` or `Map2` is not a map.\n\n_Example:_\n\n```erlang\n> Map1 = #{a => \"value_one\", b => \"value_two\"},\n Map2 = #{a => 1, c => 2},\n maps:intersect(Map1,Map2).\n#{a => 1}\n```","title":"maps.intersect/2","ref":"maps.html#intersect/2"},{"type":"function","doc":"Intersects two maps into a single map `Map3`. If a key exists in both maps, the\nvalue in `Map1` is combined with the value in `Map2` by the `Combiner` fun.\n\nWhen `Combiner` is applied the key that exists in both maps is the first parameter,\nthe value from `Map1` is the second parameter, and the value from `Map2` is the\nthird parameter.\n\nThe call fails with a `{badmap,Map}` exception if `Map1` or `Map2` is not a map.\nThe call fails with a `badarg` exception if `Combiner` is not a fun that takes\nthree arguments.\n\n_Example:_\n\n```erlang\n> Map1 = #{a => \"value_one\", b => \"value_two\"},\n Map2 = #{a => 1, c => 2},\n maps:intersect_with(fun(_Key, Value1, Value2) -> {Value1, Value2} end, Map1, Map2).\n#{a => {\"value_one\",1}}\n```","title":"maps.intersect_with/3","ref":"maps.html#intersect_with/3"},{"type":"function","doc":"Returns `true` if map `Map` contains `Key` and returns `false` if it does not\ncontain the `Key`.\n\nThe call fails with a `{badmap,Map}` exception if `Map` is not a map.\n\n_Example:_\n\n```erlang\n> Map = #{\"42\" => value}.\n#{\"42\" => value}\n> maps:is_key(\"42\",Map).\ntrue\n> maps:is_key(value,Map).\nfalse\n```","title":"maps.is_key/2","ref":"maps.html#is_key/2"},{"type":"function","doc":"Returns a map iterator `Iterator` that can be used by [`maps:next/1`](`next/1`)\nto traverse the key-value associations in a map. When iterating over a map, the\nmemory usage is guaranteed to be bounded no matter the size of the map.\n\nThe call fails with a `{badmap,Map}` exception if `Map` is not a map.\n\n_Example:_\n\n```erlang\n> M = #{ a => 1, b => 2 }.\n#{a => 1,b => 2}\n> I = maps:iterator(M), ok.\nok\n> {K1, V1, I2} = maps:next(I), {K1, V1}.\n{a,1}\n> {K2, V2, I3} = maps:next(I2),{K2, V2}.\n{b,2}\n> maps:next(I3).\nnone\n```","title":"maps.iterator/1","ref":"maps.html#iterator/1"},{"type":"function","doc":"Returns a map iterator `Iterator` that can be used by [`maps:next/1`](`next/1`)\nto traverse the key-value associations in a map sorted by key using the given\n`Order`.\n\nThe call fails with a `{badmap,Map}` exception if `Map` is not a map or if\n`Order` is invalid.\n\n_Example (when _`Order`_ is _`ordered`_):_\n\n```erlang\n> M = #{ a => 1, b => 2 }.\n#{a => 1,b => 2}\n> OrdI = maps:iterator(M, ordered), ok.\nok\n> {K1, V1, OrdI2} = maps:next(OrdI), {K1, V1}.\n{a,1}\n> {K2, V2, OrdI3} = maps:next(OrdI2),{K2, V2}.\n{b,2}\n> maps:next(OrdI3).\nnone\n```\n\n_Example (when _`Order`_ is _`reversed`_):_\n\n```erlang\n> M = #{ a => 1, b => 2 }.\n#{a => 1,b => 2}\n> RevI = maps:iterator(M, reversed), ok.\nok\n> {K2, V2, RevI2} = maps:next(RevI), {K2, V2}.\n{b,2}\n> {K1, V1, RevI3} = maps:next(RevI2),{K1, V1}.\n{a,1}\n> maps:next(RevI3).\nnone\n```\n\n_Example (when _`Order`_ is an arithmetic sorting function):_\n\n```erlang\n> M = #{ -1 => a, -1.0 => b, 0 => c, 0.0 => d }.\n#{-1 => a,0 => c,-1.0 => b,0.0 => d}\n> ArithOrdI = maps:iterator(M, fun(A, B) -> A = maps:to_list(ArithOrdI).\n[{-1,a},{-1.0,b},{0,c},{0.0,d}]\n> ArithRevI = maps:iterator(M, fun(A, B) -> B maps:to_list(ArithRevI).\n[{0.0,d},{0,c},{-1.0,b},{-1,a}]\n```","title":"maps.iterator/2","ref":"maps.html#iterator/2"},{"type":"function","doc":"Returns a complete list of keys, in any order, which resides within `Map`.\n\nThe call fails with a `{badmap,Map}` exception if `Map` is not a map.\n\n_Example:_\n\n```erlang\n> Map = #{42 => value_three,1337 => \"value two\",\"a\" => 1},\n maps:keys(Map).\n[42,1337,\"a\"]\n```","title":"maps.keys/1","ref":"maps.html#keys/1"},{"type":"function","doc":"Produces a new map `Map` by calling function `fun F(Key, Value1)` for every\n`Key` to value `Value1` association in `MapOrIter` in any order. Function\n`fun Fun/2` must return value `Value2` to be associated with key `Key` for the\nnew map `Map`.\n\nThe call fails with a `{badmap,Map}` exception if `MapOrIter` is not a map or\nvalid iterator, or with `badarg` if `Fun` is not a function of arity 2.\n\n_Example:_\n\n```erlang\n> Fun = fun(K,V1) when is_list(K) -> V1*2 end,\n Map = #{\"k1\" => 1, \"k2\" => 2, \"k3\" => 3},\n maps:map(Fun,Map).\n#{\"k1\" => 2,\"k2\" => 4,\"k3\" => 6}\n```","title":"maps.map/2","ref":"maps.html#map/2"},{"type":"function","doc":"Merges two maps into a single map `Map3`. If two keys exist in both maps, the\nvalue in `Map1` is superseded by the value in `Map2`.\n\nThe call fails with a `{badmap,Map}` exception if `Map1` or `Map2` is not a map.\n\n_Example:_\n\n```erlang\n> Map1 = #{a => \"value_one\", b => \"value_two\"},\n Map2 = #{a => 1, c => 2},\n maps:merge(Map1,Map2).\n#{a => 1,b => \"value_two\",c => 2}\n```","title":"maps.merge/2","ref":"maps.html#merge/2"},{"type":"function","doc":"Merges two maps into a single map `Map3`. If a key exists in both maps, the\nvalue in `Map1` is combined with the value in `Map2` by the `Combiner` fun.\n\nWhen `Combiner` is applied the key that exists in both maps is the first parameter,\nthe value from `Map1` is the second parameter, and the value from `Map2` is the\nthird parameter.\n\nThe call fails with a `{badmap,Map}` exception if `Map1` or `Map2` is not a map.\nThe call fails with a `badarg` exception if `Combiner` is not a fun that takes\nthree arguments.\n\n_Example:_\n\n```erlang\n> Map1 = #{a => \"value_one\", b => \"value_two\"},\n Map2 = #{a => 1, c => 2},\n maps:merge_with(fun(_Key, Value1, Value2) -> {Value1, Value2} end, Map1, Map2).\n#{a => {\"value_one\",1},b => \"value_two\",c => 2}\n```","title":"maps.merge_with/3","ref":"maps.html#merge_with/3"},{"type":"function","doc":"Returns a new empty map.\n\n_Example:_\n\n```text\n> maps:new().\n#{}\n```","title":"maps.new/0","ref":"maps.html#new/0"},{"type":"function","doc":"Returns the next key-value association in `Iterator` and a new iterator for the\nremaining associations in the iterator.\n\nIf there are no more associations in the iterator, `none` is returned.\n\n_Example:_\n\n```erlang\n> Map = #{a => 1, b => 2, c => 3}.\n#{a => 1,b => 2,c => 3}\n> I = maps:iterator(Map), ok.\nok\n> {K1, V1, I1} = maps:next(I), {K1, V1}.\n{a,1}\n> {K2, V2, I2} = maps:next(I1), {K2, V2}.\n{b,2}\n> {K3, V3, I3} = maps:next(I2), {K3, V3}.\n{c,3}\n> maps:next(I3).\nnone\n```","title":"maps.next/1","ref":"maps.html#next/1"},{"type":"function","doc":"Associates `Key` with value `Value` and inserts the association into map `Map2`.\nIf key `Key` already exists in map `Map1`, the old associated value is replaced\nby value `Value`. The function returns a new map `Map2` containing the new\nassociation and the old associations in `Map1`.\n\nThe call fails with a `{badmap,Map}` exception if `Map1` is not a map.\n\n_Example:_\n\n```erlang\n> Map = #{\"a\" => 1}.\n#{\"a\" => 1}\n> maps:put(\"a\", 42, Map).\n#{\"a\" => 42}\n> maps:put(\"b\", 1337, Map).\n#{\"a\" => 1,\"b\" => 1337}\n```","title":"maps.put/3","ref":"maps.html#put/3"},{"type":"function","doc":"Removes the `Key`, if it exists, and its associated value from `Map1` and\nreturns a new map `Map2` without key `Key`.\n\nThe call fails with a `{badmap,Map}` exception if `Map1` is not a map.\n\n_Example:_\n\n```erlang\n> Map = #{\"a\" => 1}.\n#{\"a\" => 1}\n> maps:remove(\"a\",Map).\n#{}\n> maps:remove(\"b\",Map).\n#{\"a\" => 1}\n```","title":"maps.remove/2","ref":"maps.html#remove/2"},{"type":"function","doc":"Returns the number of key-value associations in `Map`. This operation occurs in\nconstant time.\n\n_Example:_\n\n```erlang\n> Map = #{42 => value_two,1337 => \"value one\",\"a\" => 1},\n maps:size(Map).\n3\n```","title":"maps.size/1","ref":"maps.html#size/1"},{"type":"function","doc":"The function removes the `Key`, if it exists, and its associated value from\n`Map1` and returns a tuple with the removed `Value` and the new map `Map2`\nwithout key `Key`. If the key does not exist `error` is returned.\n\nThe call will fail with a `{badmap,Map}` exception if `Map1` is not a map.\n\nExample:\n\n```erlang\n> Map = #{\"a\" => \"hello\", \"b\" => \"world\"}.\n#{\"a\" => \"hello\", \"b\" => \"world\"}\n> maps:take(\"a\",Map).\n{\"hello\",#{\"b\" => \"world\"}}\n> maps:take(\"does not exist\",Map).\nerror\n```","title":"maps.take/2","ref":"maps.html#take/2"},{"type":"function","doc":"Returns a list of pairs representing the key-value associations of\n`MapOrIterator`, where the pairs `[{K1,V1}, ..., {Kn,Vn}]` are returned in\narbitrary order.\n\nThe call fails with a `{badmap,Map}` exception if `MapOrIterator` is not a map\nor an iterator obtained by a call to `iterator/1` or `iterator/2`.\n\n_Example:_\n\n```erlang\n> Map = #{42 => value_three,1337 => \"value two\",\"a\" => 1},\n maps:to_list(Map).\n[{42,value_three},{1337,\"value two\"},{\"a\",1}]\n```\n\n_Example (using _`iterator/2`_):_\n\n```erlang\n> Map = #{ z => 1, y => 2, x => 3 }.\n#{x => 3,y => 2,z => 1}\n> maps:to_list(maps:iterator(Map, ordered)).\n[{x,3},{y,2},{z,1}]\n```","title":"maps.to_list/1","ref":"maps.html#to_list/1"},{"type":"function","doc":"If `Key` exists in `Map1`, the old associated value is replaced by value\n`Value`. The function returns a new map `Map2` containing the new associated\nvalue.\n\nThe call fails with a `{badmap,Map}` exception if `Map1` is not a map, or with a\n`{badkey,Key}` exception if no value is associated with `Key`.\n\n_Example:_\n\n```erlang\n> Map = #{\"a\" => 1}.\n#{\"a\" => 1}\n> maps:update(\"a\", 42, Map).\n#{\"a\" => 42}\n```","title":"maps.update/3","ref":"maps.html#update/3"},{"type":"function","doc":"Update a value in a `Map1` associated with `Key` by calling `Fun` on the old\nvalue to get a new value. An exception `{badkey,Key}` is generated if `Key` is\nnot present in the map.\n\nExample:\n\n```erlang\n> Map = #{\"counter\" => 1},\n Fun = fun(V) -> V + 1 end,\n maps:update_with(\"counter\",Fun,Map).\n#{\"counter\" => 2}\n```","title":"maps.update_with/3","ref":"maps.html#update_with/3"},{"type":"function","doc":"Update a value in a `Map1` associated with `Key` by calling `Fun` on the old\nvalue to get a new value. If `Key` is not present in `Map1` then `Init` will be\nassociated with `Key`.\n\nExample:\n\n```erlang\n> Map = #{\"counter\" => 1},\n Fun = fun(V) -> V + 1 end,\n maps:update_with(\"new counter\",Fun,42,Map).\n#{\"counter\" => 1,\"new counter\" => 42}\n```","title":"maps.update_with/4","ref":"maps.html#update_with/4"},{"type":"function","doc":"Returns a complete list of values, in arbitrary order, contained in map `Map`.\n\nThe call fails with a `{badmap,Map}` exception if `Map` is not a map.\n\n_Example:_\n\n```erlang\n> Map = #{42 => value_three,1337 => \"value two\",\"a\" => 1},\n maps:values(Map).\n[value_three,\"value two\",1]\n```","title":"maps.values/1","ref":"maps.html#values/1"},{"type":"function","doc":"Returns a new map `Map2` with the keys `K1` through `Kn` and their associated\nvalues from map `Map1`. Any key in `Ks` that does not exist in `Map1` is\nignored.\n\n_Example:_\n\n```erlang\n> Map = #{42 => value_three,1337 => \"value two\",\"a\" => 1},\n Ks = [\"a\",42,\"other key\"],\n maps:with(Ks,Map).\n#{42 => value_three,\"a\" => 1}\n```","title":"maps.with/2","ref":"maps.html#with/2"},{"type":"function","doc":"Returns a new map `Map2` without keys `K1` through `Kn` and their associated\nvalues from map `Map1`. Any key in `Ks` that does not exist in `Map1` is ignored\n\n_Example:_\n\n```erlang\n> Map = #{42 => value_three,1337 => \"value two\",\"a\" => 1},\n Ks = [\"a\",42,\"other key\"],\n maps:without(Ks,Map).\n#{1337 => \"value two\"}\n```","title":"maps.without/2","ref":"maps.html#without/2"},{"type":"type","doc":"","title":"maps.iterator/0","ref":"maps.html#t:iterator/0"},{"type":"opaque","doc":"An iterator representing the associations in a map with keys of type `Key` and\nvalues of type `Value`.\n\nCreated using [`maps:iterator/1`](`iterator/1`) or\n[`maps:iterator/2`](`iterator/2`).\n\nConsumed by:\n\n- [`maps:next/1`](`next/1`)\n- [`maps:filter/2`](`filter/2`)\n- [`maps:filtermap/2`](`filtermap/2`)\n- [`maps:fold/3`](`fold/3`)\n- [`maps:foreach/2`](`foreach/2`)\n- [`maps:map/2`](`map/2`)\n- [`maps:to_list/1`](`to_list/1`)","title":"maps.iterator/2","ref":"maps.html#t:iterator/2"},{"type":"type","doc":"","title":"maps.iterator_order/0","ref":"maps.html#t:iterator_order/0"},{"type":"type","doc":"Key-based iterator order option that can be one of `undefined` (default for\n[`maps:iterator/1`](`iterator/1`)), `ordered` (sorted in map-key order),\n`reversed`, or a custom sorting function.\n\nUsed by [`maps:iterator/2`](`iterator/2`).\n\nThe [Expressions section](`e:system:expressions.md#term-comparisons`) contains\ndescriptions of how terms are ordered.","title":"maps.iterator_order/1","ref":"maps.html#t:iterator_order/1"},{"type":"module","doc":"Mathematical functions.\n\nThis module provides an interface to a number of mathematical functions.\nFor details about what each function does, see the the C library documentation\non your system. On Unix systems the easiest way it to run `man sin`. On\nWindows you should check the [Math and floating-point support](https://learn.microsoft.com/en-us/cpp/c-runtime-library/floating-point-support)\ndocumentation.","title":"math","ref":"math.html"},{"type":"module","doc":"As these are the C library, the same limitations apply.","title":"Limitations - math","ref":"math.html#module-limitations"},{"type":"function","doc":"Inverse cosine of `X`, return value is in radians.","title":"math.acos/1","ref":"math.html#acos/1"},{"type":"function","doc":"Inverse hyperbolic cosine of `X`.","title":"math.acosh/1","ref":"math.html#acosh/1"},{"type":"function","doc":"Inverse sine of `X`, return value is in radians.","title":"math.asin/1","ref":"math.html#asin/1"},{"type":"function","doc":"Inverse hyperbolic sine of `X`.","title":"math.asinh/1","ref":"math.html#asinh/1"},{"type":"function","doc":"Inverse 2-argument tangent of `X`, return value is in radians.","title":"math.atan2/2","ref":"math.html#atan2/2"},{"type":"function","doc":"Inverse tangent of `X`, return value is in radians.","title":"math.atan/1","ref":"math.html#atan/1"},{"type":"function","doc":"Inverse hyperbolic tangent of `X`.","title":"math.atanh/1","ref":"math.html#atanh/1"},{"type":"function","doc":"The ceiling of `X`.","title":"math.ceil/1","ref":"math.html#ceil/1"},{"type":"function","doc":"The cosine of `X` in radians.","title":"math.cos/1","ref":"math.html#cos/1"},{"type":"function","doc":"The hyperbolic cosine of `X`.","title":"math.cosh/1","ref":"math.html#cosh/1"},{"type":"function","doc":"Returns the error function (or Gauss error function) of `X`.\n\nWhere:\n\n```text\nerf(X) = 2/sqrt(pi)*integral from 0 to X of exp(-t*t) dt.\n```","title":"math.erf/1","ref":"math.html#erf/1"},{"type":"function","doc":"[`erfc(X)`](`erfc/1`) returns `1.0` - [`erf(X)`](`erf/1`), computed by methods\nthat avoid cancellation for large `X`.","title":"math.erfc/1","ref":"math.html#erfc/1"},{"type":"function","doc":"Raise e by `X`, that is `eˣ`.\n\nWhere e is the base of the natural logarithm.","title":"math.exp/1","ref":"math.html#exp/1"},{"type":"function","doc":"The floor of `X`.","title":"math.floor/1","ref":"math.html#floor/1"},{"type":"function","doc":"Returns `X` modulus `Y`.","title":"math.fmod/2","ref":"math.html#fmod/2"},{"type":"function","doc":"The base-2 logarithm of `X`.","title":"math.log2/1","ref":"math.html#log2/1"},{"type":"function","doc":"The base-10 logarithm of `X`.","title":"math.log10/1","ref":"math.html#log10/1"},{"type":"function","doc":"The natural (base-e) logarithm of `X`.","title":"math.log/1","ref":"math.html#log/1"},{"type":"function","doc":"Ratio of the circumference of a circle to its diameter.\n\nFloating point approximation of mathematical constant pi.","title":"math.pi/0","ref":"math.html#pi/0"},{"type":"function","doc":"Raise `X` by `N`, that is `xⁿ`.","title":"math.pow/2","ref":"math.html#pow/2"},{"type":"function","doc":"Sine of `X` in radians.","title":"math.sin/1","ref":"math.html#sin/1"},{"type":"function","doc":"Hyperbolic sine of `X`.","title":"math.sinh/1","ref":"math.html#sinh/1"},{"type":"function","doc":"Square root of `X`.","title":"math.sqrt/1","ref":"math.html#sqrt/1"},{"type":"function","doc":"Tangent of `X` in radians.","title":"math.tan/1","ref":"math.html#tan/1"},{"type":"function","doc":"Hyperbolic tangent of `X`.","title":"math.tanh/1","ref":"math.html#tanh/1"},{"type":"function","doc":"Ratio of the circumference of a circle to its radius.\n\nThis constant is equivalent to a full turn when described in radians.\n\nThe same as `2 * pi()`.","title":"math.tau/0","ref":"math.html#tau/0"},{"type":"module","doc":"Local and universal time, day of the week, date and time conversions.\n\nThis module provides computation of local and universal time, day of the week,\nand many time conversion functions.\n\nTime is local when it is adjusted in accordance with the current time zone and\ndaylight saving. Time is universal when it reflects the time at longitude zero,\nwithout any adjustment for daylight saving. Universal Coordinated Time (UTC)\ntime is also called Greenwich Mean Time (GMT).\n\nThe time functions `local_time/0` and `universal_time/0` in this module both\nreturn date and time. This is because separate functions for date and time can\nresult in a date/time combination that is displaced by 24 hours. This occurs if\none of the functions is called before midnight, and the other after midnight.\nThis problem also applies to the Erlang BIFs `date/0` and `time/0`, and their\nuse is strongly discouraged if a reliable date/time stamp is required.\n\nAll dates conform to the Gregorian calendar. This calendar was introduced by\nPope Gregory XIII in 1582 and was used in all Catholic countries from this year.\nProtestant parts of Germany and the Netherlands adopted it in 1698, England\nfollowed in 1752, and Russia in 1918 (the October revolution of 1917 took place\nin November according to the Gregorian calendar).\n\nThe Gregorian calendar in this module is extended back to year 0. For a given\ndate, the _gregorian days_ is the number of days up to and including the date\nspecified. Similarly, the _gregorian seconds_ for a specified date and time is\nthe number of seconds up to and including the specified date and time.\n\nFor computing differences between epochs in time, use the functions counting\ngregorian days or seconds. If epochs are specified as local time, they must be\nconverted to universal time to get the correct value of the elapsed time between\nepochs. Use of function [`time_difference/2`](`time_difference/2`) is\ndiscouraged.\n\nDifferent definitions exist for the week of the year. This module contains a\nweek of the year implementation conforming to the ISO 8601 standard. As the week\nnumber for a specified date can fall on the previous, the current, or on the\nnext year, it is important to specify both the year and the week number.\nFunctions `iso_week_number/0` and [`iso_week_number/1`](`iso_week_number/1`)\nreturn a tuple of the year and the week number.","title":"calendar","ref":"calendar.html"},{"type":"module","doc":"The notion that every fourth year is a leap year is not completely true. By the\nGregorian rule, a year Y is a leap year if one of the following rules is valid:\n\n- Y is divisible by 4, but not by 100.\n- Y is divisible by 400.\n\nHence, 1996 is a leap year, 1900 is not, but 2000 is.","title":"Leap Years - calendar","ref":"calendar.html#module-leap-years"},{"type":"module","doc":"Local time is obtained from the Erlang BIF `localtime/0`. Universal time is\ncomputed from the BIF `universaltime/0`.\n\nThe following apply:\n\n- There are 86400 seconds in a day.\n- There are 365 days in an ordinary year.\n- There are 366 days in a leap year.\n- There are 1461 days in a 4 year period.\n- There are 36524 days in a 100 year period.\n- There are 146097 days in a 400 year period.\n- There are 719528 days between Jan 1, 0 and Jan 1, 1970.","title":"Date and Time Source - calendar","ref":"calendar.html#module-date-and-time-source"},{"type":"function","doc":"Computes the number of gregorian days starting with year 0 and ending at the\nspecified date.","title":"calendar.date_to_gregorian_days/1","ref":"calendar.html#date_to_gregorian_days/1"},{"type":"function","doc":"","title":"calendar.date_to_gregorian_days/3","ref":"calendar.html#date_to_gregorian_days/3"},{"type":"function","doc":"Computes the number of gregorian seconds starting with year 0 and ending at the\nspecified date and time.","title":"calendar.datetime_to_gregorian_seconds/1","ref":"calendar.html#datetime_to_gregorian_seconds/1"},{"type":"function","doc":"Computes the day of the week from the specified `Year`, `Month`, and `Day`.\nReturns the day of the week as `1`: Monday, `2`: Tuesday, and so on.","title":"calendar.day_of_the_week/1","ref":"calendar.html#day_of_the_week/1"},{"type":"function","doc":"","title":"calendar.day_of_the_week/3","ref":"calendar.html#day_of_the_week/3"},{"type":"function","doc":"Computes the date from the specified number of gregorian days.","title":"calendar.gregorian_days_to_date/1","ref":"calendar.html#gregorian_days_to_date/1"},{"type":"function","doc":"Computes the date and time from the specified number of gregorian seconds.","title":"calendar.gregorian_seconds_to_datetime/1","ref":"calendar.html#gregorian_seconds_to_datetime/1"},{"type":"function","doc":"Checks if the specified year is a leap year.","title":"calendar.is_leap_year/1","ref":"calendar.html#is_leap_year/1"},{"type":"function","doc":"Returns tuple `{Year, WeekNum}` representing the ISO week number for the actual\ndate. To determine the actual date, use function `local_time/0`.","title":"calendar.iso_week_number/0","ref":"calendar.html#iso_week_number/0"},{"type":"function","doc":"Returns tuple `{Year, WeekNum}` representing the ISO week number for the\nspecified date.","title":"calendar.iso_week_number/1","ref":"calendar.html#iso_week_number/1"},{"type":"function","doc":"Computes the number of days in a month.","title":"calendar.last_day_of_the_month/2","ref":"calendar.html#last_day_of_the_month/2"},{"type":"function","doc":"Returns the local time reported by the underlying operating system.","title":"calendar.local_time/0","ref":"calendar.html#local_time/0"},{"type":"function","doc":"Converts from local time to Universal Coordinated Time (UTC). `DateTime1` must\nrefer to a local date after Jan 1, 1970.\n\n> #### Warning {: .warning }\n>\n> This function is deprecated. Use `local_time_to_universal_time_dst/1` instead,\n> as it gives a more correct and complete result. Especially for the period that\n> does not exist, as it is skipped during the switch _to_ daylight saving time,\n> this function still returns a result.","title":"calendar.local_time_to_universal_time/1","ref":"calendar.html#local_time_to_universal_time/1"},{"type":"function","doc":"Converts from local time to Universal Coordinated Time (UTC). `DateTime1` must\nrefer to a local date after Jan 1, 1970.\n\nThe return value is a list of 0, 1, or 2 possible UTC times:\n\n- **`[]`** - For a local `{Date1, Time1}` during the period that is skipped when\n switching _to_ daylight saving time, there is no corresponding UTC, as the\n local time is illegal (it has never occured).\n\n- **`[DstDateTimeUTC, DateTimeUTC]`** - For a local `{Date1, Time1}` during the\n period that is repeated when switching _from_ daylight saving time, two\n corresponding UTCs exist; one for the first instance of the period when\n daylight saving time is still active, and one for the second instance.\n\n- **`[DateTimeUTC]`** - For all other local times only one corresponding UTC\n exists.","title":"calendar.local_time_to_universal_time_dst/1","ref":"calendar.html#local_time_to_universal_time_dst/1"},{"type":"function","doc":"Returns Universal Coordinated Time (UTC) converted from the return value from\n`erlang:timestamp/0`.","title":"calendar.now_to_datetime/1","ref":"calendar.html#now_to_datetime/1"},{"type":"function","doc":"Returns local date and time converted from the return value from\n`erlang:timestamp/0`.","title":"calendar.now_to_local_time/1","ref":"calendar.html#now_to_local_time/1"},{"type":"function","doc":"Returns Universal Coordinated Time (UTC) converted from the return value from\n`erlang:timestamp/0`.","title":"calendar.now_to_universal_time/1","ref":"calendar.html#now_to_universal_time/1"},{"type":"function","doc":"","title":"calendar.rfc3339_to_system_time/1","ref":"calendar.html#rfc3339_to_system_time/1"},{"type":"function","doc":"Converts an RFC 3339 timestamp into system time. The data format of RFC 3339\ntimestamps is described by [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt).\nStarting from OTP 25.1, the minutes part of the time zone is optional.\n\nValid option:\n\n- **`{unit, Unit}`** - The time unit of the return value. The default is\n `second`.\n\n```erlang\n1> calendar:rfc3339_to_system_time(\"2018-02-01T16:17:58+01:00\").\n1517498278\n2> calendar:rfc3339_to_system_time(\"2018-02-01 15:18:02.088Z\",\n [{unit, nanosecond}]).\n1517498282088000000\n3> calendar:rfc3339_to_system_time(<<\"2018-02-01 15:18:02.088Z\">>,\n [{unit, nanosecond}]).\n1517498282088000000\n```","title":"calendar.rfc3339_to_system_time/2","ref":"calendar.html#rfc3339_to_system_time/2"},{"type":"function","doc":"Converts a specified number of seconds into days, hours, minutes, and seconds.\n`Time` is always non-negative, but `Days` is negative if argument `Seconds` is.","title":"calendar.seconds_to_daystime/1","ref":"calendar.html#seconds_to_daystime/1"},{"type":"function","doc":"Computes the time from the specified number of seconds. `Seconds` must be less\nthan the number of seconds per day (86400).","title":"calendar.seconds_to_time/1","ref":"calendar.html#seconds_to_time/1"},{"type":"function","doc":"Converts a specified system time into local date and time.","title":"calendar.system_time_to_local_time/2","ref":"calendar.html#system_time_to_local_time/2"},{"type":"function","doc":"","title":"calendar.system_time_to_rfc3339/1","ref":"calendar.html#system_time_to_rfc3339/1"},{"type":"function","doc":"Converts a system time into an RFC 3339 timestamp.\n\nThe data format of RFC 3339 timestamps is described by [RFC 3339].\nThe data format of offsets is also described by [RFC 3339].\n\nValid options:\n\n- **`{offset, Offset}`** - The offset, either a string or an integer, to be\n included in the formatted string. An empty string, which is the default, is\n interpreted as local time. A non-empty string is included as is. The time unit\n of the integer is the same as the one of `Time`.\n\n- **`{time_designator, Character}`** - The character used as time designator,\n that is, the date and time separator. The default is `$T`.\n\n- **`{unit, Unit}`** - The time unit of `Time`. The default is `second`. If some\n other unit is given (`millisecond`, `microsecond`, `nanosecond`, or `native`),\n the formatted string includes a fraction of a second. The number of fractional\n second digits is three, six, or nine depending on what time unit is chosen.\n For `native` three fractional digits are included. Notice that trailing zeros\n are not removed from the fraction.\n\n- **`{return, Return}`** - The desired encoding type for the output,\n whether a string or a binary is desired. Defaults to string.\n\n```erlang\n1> calendar:system_time_to_rfc3339(erlang:system_time(second)).\n\"2018-04-23T14:56:28+02:00\"\n2> calendar:system_time_to_rfc3339(erlang:system_time(second),\n [{offset, \"-02:00\"}]).\n\"2018-04-23T10:56:52-02:00\"\n3> calendar:system_time_to_rfc3339(erlang:system_time(second),\n [{offset, -7200}]).\n\"2018-04-23T10:57:05-02:00\"\n4> calendar:system_time_to_rfc3339(erlang:system_time(millisecond),\n [{unit, millisecond}, {time_designator, $\\s}, {offset, \"Z\"}]).\n\"2018-04-23 12:57:20.482Z\"\n5> calendar:system_time_to_rfc3339(erlang:system_time(millisecond),\n [{unit, millisecond}, {time_designator, $\\s}, {offset, \"Z\"}, {return, binary}]).\n<<\"2018-04-23 12:57:20.482Z\">>\n```\n[RFC 3339]: https://www.ietf.org/rfc/rfc3339.txt","title":"calendar.system_time_to_rfc3339/2","ref":"calendar.html#system_time_to_rfc3339/2"},{"type":"function","doc":"Converts a specified system time into universal date and time.","title":"calendar.system_time_to_universal_time/2","ref":"calendar.html#system_time_to_universal_time/2"},{"type":"function","doc":"Returns the difference between two `{Date, Time}` tuples. `T2` is to refer to an\nepoch later than `T1`.\n\n> #### Warning {: .warning }\n>\n> This function is obsolete. Use the conversion functions for gregorian days and\n> seconds instead.","title":"calendar.time_difference/2","ref":"calendar.html#time_difference/2"},{"type":"function","doc":"Returns the number of seconds since midnight up to the specified time.","title":"calendar.time_to_seconds/1","ref":"calendar.html#time_to_seconds/1"},{"type":"function","doc":"Returns the Universal Coordinated Time (UTC) reported by the underlying\noperating system. Returns local time if universal time is unavailable.","title":"calendar.universal_time/0","ref":"calendar.html#universal_time/0"},{"type":"function","doc":"Converts from Universal Coordinated Time (UTC) to local time. `DateTime` must\nrefer to a date after Jan 1, 1970.","title":"calendar.universal_time_to_local_time/1","ref":"calendar.html#universal_time_to_local_time/1"},{"type":"function","doc":"This function checks if a date is a valid.","title":"calendar.valid_date/1","ref":"calendar.html#valid_date/1"},{"type":"function","doc":"","title":"calendar.valid_date/3","ref":"calendar.html#valid_date/3"},{"type":"type","doc":"A date using the Gregorian calendar.\n\nAll APIs expect this to be a valid date. If the source of the date\nis unknown, then verify that is it valid by calling `valid_date/1`\nbefore using it.","title":"calendar.date/0","ref":"calendar.html#t:date/0"},{"type":"type","doc":"","title":"calendar.datetime1970/0","ref":"calendar.html#t:datetime1970/0"},{"type":"type","doc":"","title":"calendar.datetime/0","ref":"calendar.html#t:datetime/0"},{"type":"type","doc":"","title":"calendar.day/0","ref":"calendar.html#t:day/0"},{"type":"type","doc":"","title":"calendar.daynum/0","ref":"calendar.html#t:daynum/0"},{"type":"type","doc":"","title":"calendar.hour/0","ref":"calendar.html#t:hour/0"},{"type":"type","doc":"The last day of the month.","title":"calendar.ldom/0","ref":"calendar.html#t:ldom/0"},{"type":"type","doc":"","title":"calendar.minute/0","ref":"calendar.html#t:minute/0"},{"type":"type","doc":"","title":"calendar.month/0","ref":"calendar.html#t:month/0"},{"type":"type","doc":"","title":"calendar.offset/0","ref":"calendar.html#t:offset/0"},{"type":"type","doc":"","title":"calendar.rfc3339_string/0","ref":"calendar.html#t:rfc3339_string/0"},{"type":"type","doc":"The time unit used by the rfc3339 conversion functions.\n\n> #### Note {: .info }\n>\n> The `native` time unit was added to `t:rfc3339_time_unit/0` in OTP 25.0.","title":"calendar.rfc3339_time_unit/0","ref":"calendar.html#t:rfc3339_time_unit/0"},{"type":"type","doc":"","title":"calendar.second/0","ref":"calendar.html#t:second/0"},{"type":"type","doc":"","title":"calendar.secs_per_day/0","ref":"calendar.html#t:secs_per_day/0"},{"type":"type","doc":"","title":"calendar.time/0","ref":"calendar.html#t:time/0"},{"type":"type","doc":"","title":"calendar.weeknum/0","ref":"calendar.html#t:weeknum/0"},{"type":"type","doc":"","title":"calendar.year1970/0","ref":"calendar.html#t:year1970/0"},{"type":"type","doc":"The year using the Gregorian calendar.\n\nYear cannot be abbreviated. For example, 93 denotes year 93, not 1993. The valid\nrange depends on the underlying operating system.","title":"calendar.year/0","ref":"calendar.html#t:year/0"},{"type":"type","doc":"","title":"calendar.yearweeknum/0","ref":"calendar.html#t:yearweeknum/0"},{"type":"module","doc":"Timer functions.\n\nThis module provides useful functions related to time. Unless otherwise stated,\ntime is always measured in _milliseconds_. All timer functions return\nimmediately, regardless of work done by another process.\n\nSuccessful evaluations of the timer functions give return values containing a\ntimer reference, denoted `TRef`. By using `cancel/1`, the returned reference can\nbe used to cancel any requested action. A `TRef` is an Erlang term, which\ncontents must not be changed.\n\nThe time-outs are not exact, but are _at least_ as long as requested.\n\nCreating timers using `erlang:send_after/3` and `erlang:start_timer/3` is more\nefficient than using the timers provided by this module. However, the timer\nmodule has been improved in OTP 25, making it more efficient and less\nsusceptible to being overloaded. See\n[the Timer Module section in the Efficiency Guide](`e:system:commoncaveats.md#timer-module`).\n\nFor more information on timers in Erlang in general, see the\n[*Timers*](`e:erts:time_correction.md#timers`) section of the\n[*Time and Time Correction in Erlang*](`e:erts:time_correction.md`)\nERTS User's guide.","title":"timer","ref":"timer.html"},{"type":"module","doc":"_Example 1_\n\nThe following example shows how to print \"Hello World\\!\" in 5 seconds:\n\n```erlang\n1> timer:apply_after(5000, io, format, [\"~nHello World!~n\", []]).\n{ok,TRef}\nHello World!\n```\n\n_Example 2_\n\nThe following example shows a process performing a certain action, and if this\naction is not completed within a certain limit, the process is killed:\n\n```erlang\nPid = spawn(mod, fun, [foo, bar]),\n%% If pid is not finished in 10 seconds, kill him\n{ok, R} = timer:kill_after(timer:seconds(10), Pid),\n...\n%% We change our mind...\ntimer:cancel(R),\n...\n```","title":"Examples - timer","ref":"timer.html#module-examples"},{"type":"module","doc":"A timer can always be removed by calling `cancel/1`.\n\nAn interval timer, that is, a timer created by evaluating any of the functions\n`apply_interval/2`, `apply_interval/3`, `apply_interval/4`,\n`apply_repeatedly/2`, `apply_repeatedly/3`, `apply_repeatedly/4`,\n`send_interval/2`, and `send_interval/3` is linked to the process to which the\ntimer performs its task.\n\nA one-shot timer, that is, a timer created by evaluating any of the functions\n`apply_after/2`, `apply_after/3`, `apply_after/4`, `send_after/2`,\n`send_after/3`, `exit_after/2`, `exit_after/3`, `kill_after/1`, and\n`kill_after/2` is not linked to any process. Hence, such a timer is removed only\nwhen it reaches its time-out, or if it is explicitly removed by a call to\n`cancel/1`.\n\nThe functions given to `apply_after/2`, `apply_after/3`, `apply_interval/2`,\n`apply_interval/3`, `apply_repeatedly/2`, and `apply_repeatedly/3`, or denoted\nby `Module`, `Function` and `Arguments` given to `apply_after/4`,\n`apply_interval/4`, and `apply_repeatedly/4` are executed in a freshly-spawned\nprocess, and therefore calls to `self/0` in those functions will return the Pid\nof this process, which is different from the process that called\n`timer:apply_*`.\n\n_Example_\n\nIn the following example, the intention is to set a timer to execute a function\nafter 1 second, which performs a fictional task, and then wants to inform the\nprocess which set the timer about its completion, by sending it a `done`\nmessage.\n\nUsing `self/0` _inside_ the timed function, the code below does not work as\nintended. The task gets done, but the `done` message gets sent to the wrong\nprocess and is lost.\n\n```erlang\n1> timer:apply_after(1000, fun() -> do_something(), self() ! done end).\n{ok,TRef}\n2> receive done -> done after 5000 -> timeout end.\n%% ... 5s pass...\ntimeout\n```\n\nThe code below calls `self/0` in the process which sets the timer and assigns it\nto a variable, which is then used in the function to send the `done` message to,\nand so works as intended.\n\n```erlang\n1> Target = self()\n<0.82.0>\n2> timer:apply_after(1000, fun() -> do_something(), Target ! done end).\n{ok,TRef}\n3> receive done -> done after 5000 -> timeout end.\n%% ... 1s passes...\ndone\n```\n\nAnother option is to pass the message target as a parameter to the function.\n\n```erlang\n1> timer:apply_after(1000, fun(Target) -> do_something(), Target ! done end, [self()]).\n{ok,TRef}\n2> receive done -> done after 5000 -> timeout end.\n%% ... 1s passes...\ndone\n```","title":"Notes - timer","ref":"timer.html#module-notes"},{"type":"function","doc":"Evaluates [`spawn(erlang, apply, [Function, []])`](`spawn/3`) after `Time`\nmilliseconds.","title":"timer.apply_after/2","ref":"timer.html#apply_after/2"},{"type":"function","doc":"Evaluates [`spawn(erlang, apply, [Function, Arguments])`](`spawn/3`) after\n`Time` milliseconds.","title":"timer.apply_after/3","ref":"timer.html#apply_after/3"},{"type":"function","doc":"Evaluates [`spawn(Module, Function, Arguments)`](`spawn/3`) after `Time`\nmilliseconds.","title":"timer.apply_after/4","ref":"timer.html#apply_after/4"},{"type":"function","doc":"Evaluates [`spawn(erlang, apply, [Function, []])`](`spawn/3`) repeatedly at\nintervals of `Time`, irrespective of whether a previously spawned process has\nfinished or not.","title":"timer.apply_interval/2","ref":"timer.html#apply_interval/2"},{"type":"function","doc":"Evaluates [`spawn(erlang, apply, [Function, Arguments])`](`spawn/3`) repeatedly\nat intervals of `Time`, irrespective of whether a previously spawned process has\nfinished or not.","title":"timer.apply_interval/3","ref":"timer.html#apply_interval/3"},{"type":"function","doc":"Evaluates [`spawn(Module, Function, Arguments)`](`spawn/3`) repeatedly at\nintervals of `Time`, irrespective of whether a previously spawned process has\nfinished or not.\n\n> #### Warning {: .warning }\n>\n> If the execution time of the spawned process is, on average, greater than the\n> given `Time`, multiple such processes will run at the same time. With long\n> execution times, short intervals, and many interval timers running, this may\n> even lead to exceeding the number of allowed processes. As an extreme example,\n> consider\n> `[timer:apply_interval(1, timer, sleep, [1000]) || _ <- lists:seq(1, 1000)]`,\n> that is, 1,000 interval timers executing a process that takes 1s to complete,\n> started in intervals of 1ms, which would result in 1,000,000 processes running\n> at the same time, far more than a node started with default settings allows\n> (see the\n> [System Limits section in the Effiency Guide](`e:system:system_limits.md`)).","title":"timer.apply_interval/4","ref":"timer.html#apply_interval/4"},{"type":"function","doc":"Evaluates [`spawn(erlang, apply, [Function, []])`](`spawn/3`) repeatedly at\nintervals of `Time`, waiting for the spawned process to finish before starting\nthe next.","title":"timer.apply_repeatedly/2","ref":"timer.html#apply_repeatedly/2"},{"type":"function","doc":"Evaluates [`spawn(erlang, apply, [Function, Arguments])`](`spawn/3`) repeatedly\nat intervals of `Time`, waiting for the spawned process to finish before\nstarting the next.","title":"timer.apply_repeatedly/3","ref":"timer.html#apply_repeatedly/3"},{"type":"function","doc":"Evaluates [`spawn(Module, Function, Arguments)`](`spawn/3`) repeatedly at\nintervals of `Time`, waiting for the spawned process to finish before starting\nthe next.\n\nIf the execution time of the spawned process is greater than the given `Time`,\nthe next process is spawned immediately after the one currently running has\nfinished. Assuming that execution times of the spawned processes performing the\napplies on average are smaller than `Time`, the amount of applies made over a\nlarge amount of time will be the same even if some individual execution times\nare larger than `Time`. The system will try to catch up as soon as possible. For\nexample, if one apply takes `2.5*Time`, the following two applies will be made\nimmediately one after the other in sequence.","title":"timer.apply_repeatedly/4","ref":"timer.html#apply_repeatedly/4"},{"type":"function","doc":"Cancels a previously requested time-out. `TRef` is a unique timer reference\nreturned by the related timer function.\n\nReturns `{ok, cancel}`, or `{error, Reason}` when `TRef` is not a timer\nreference.","title":"timer.cancel/1","ref":"timer.html#cancel/1"},{"type":"function","doc":"","title":"timer.exit_after/2","ref":"timer.html#exit_after/2"},{"type":"function","doc":"Sends an exit signal with reason `Reason1` to `Target`, which can be a local\nprocess identifier or an atom of a registered name.","title":"timer.exit_after/3","ref":"timer.html#exit_after/3"},{"type":"function","doc":"Returns the number of milliseconds in `Hours + Minutes + Seconds`.","title":"timer.hms/3","ref":"timer.html#hms/3"},{"type":"function","doc":"Returns the number of milliseconds in `Hours`.","title":"timer.hours/1","ref":"timer.html#hours/1"},{"type":"function","doc":"","title":"timer.kill_after/1","ref":"timer.html#kill_after/1"},{"type":"function","doc":"","title":"timer.kill_after/2","ref":"timer.html#kill_after/2"},{"type":"function","doc":"Returns the number of milliseconds in `Minutes`.","title":"timer.minutes/1","ref":"timer.html#minutes/1"},{"type":"function","doc":"Calculates the time difference `Tdiff = T2 - T1` in _microseconds_, where `T1`\nand `T2` are time-stamp tuples on the same format as returned from\n`erlang:timestamp/0` or `os:timestamp/0`.","title":"timer.now_diff/2","ref":"timer.html#now_diff/2"},{"type":"function","doc":"Returns the number of milliseconds in `Seconds`.","title":"timer.seconds/1","ref":"timer.html#seconds/1"},{"type":"function","doc":"","title":"timer.send_after/2","ref":"timer.html#send_after/2"},{"type":"function","doc":"Evaluates `Destination ! Message` after `Time` milliseconds.\n\n`Destination` can be a remote or local process identifier, an atom of a\nregistered name or a tuple `{RegName, Node}` for a registered name at another node.\n\nSee also [the Timer Module section in the Efficiency Guide](`e:system:commoncaveats.md#timer-module`).","title":"timer.send_after/3","ref":"timer.html#send_after/3"},{"type":"function","doc":"","title":"timer.send_interval/2","ref":"timer.html#send_interval/2"},{"type":"function","doc":"Evaluates `Destination ! Message` repeatedly after `Time` milliseconds.\n\n`Destination` can be a remote or local process identifier, an atom of a registered\nname or a tuple `{RegName, Node}` for a registered name at another node.","title":"timer.send_interval/3","ref":"timer.html#send_interval/3"},{"type":"function","doc":"Suspends the process calling this function for `Time` milliseconds and then\nreturns `ok`, or suspends the process forever if `Time` is the atom `infinity`.\nNaturally, this function does _not_ return immediately.\n\n> #### Note {: .info }\n>\n> Before OTP 25, `timer:sleep/1` did not accept integer timeout values greater\n> than `16#ffffffff`, that is, `2^32-1`. Since OTP 25, arbitrarily high integer\n> values are accepted.","title":"timer.sleep/1","ref":"timer.html#sleep/1"},{"type":"function","doc":"Starts the timer server.\n\nNormally, the server does not need to be started explicitly. It is started dynamically\nif it is needed. This is useful during development, but in a target system the server\nis to be started explicitly. Use configuration parameters for [Kernel](`e:kernel:index.html`)\nfor this.","title":"timer.start/0","ref":"timer.html#start/0"},{"type":"function","doc":"","title":"timer.tc/1","ref":"timer.html#tc/1"},{"type":"function","doc":"Measures the execution time of `Fun`.\n\nEquivalent to [`tc(Fun, Arguments, microsecond)`](`tc/3`) if called as `tc(Fun, Arguments)`.\n\nMeasures the execution time of `Fun` in `TimeUnit` if called as `tc(Fun, TimeUnit)`. Added in OTP 26.0.","title":"timer.tc/2","ref":"timer.html#tc/2"},{"type":"function","doc":"Measures the execution time of `Fun` or `apply(Module, Function, Arguments)`.\n\nEquivalent to [`tc(Module, Function, Arguments, microsecond)`](`tc/4`) if called as `tc(Module, Function, Arguments)`.\n\nEquivalent to [`tc(erlang, apply, [Fun, Arguments], TimeUnit)`](`tc/4`) if called as `tc(Fun, Arguments, TimeUnit)`. Added in OTP 26.0","title":"timer.tc/3","ref":"timer.html#tc/3"},{"type":"function","doc":"Evaluates [`apply(Module, Function, Arguments)`](`apply/3`) and measures the elapsed\nreal time as reported by `erlang:monotonic_time/0`.\n\nReturns `{Time, Value}`, where `Time` is the elapsed real time in the\nspecified `TimeUnit`, and `Value` is what is returned from the apply.","title":"timer.tc/4","ref":"timer.html#tc/4"},{"type":"type","doc":"Time in milliseconds.","title":"timer.time/0","ref":"timer.html#t:time/0"},{"type":"opaque","doc":"A timer reference.","title":"timer.tref/0","ref":"timer.html#t:tref/0"},{"type":"module","doc":"Command line arguments parser.\n\nThis module implements command line parser. Parser operates with _commands_ and\n_arguments_ represented as a tree. Commands are branches, and arguments are\nleaves of the tree. Parser always starts with the root command, named after\n`progname` (the name of the program which started Erlang).\n\nA [`command specification`](`t:command/0`) may contain handler definition for\neach command, and a number argument specifications. When parser is successful,\n`argparse` calls the matching handler, passing arguments extracted from the\ncommand line. Arguments can be positional (occupying specific position in the\ncommand line), and optional, residing anywhere but prefixed with a specified\ncharacter.\n\n`argparse` automatically generates help and usage messages. It will also issue\nerrors when users give the program invalid arguments.","title":"argparse","ref":"argparse.html"},{"type":"module","doc":"`argparse` is designed to work with [`escript`](`e:erts:escript_cmd.md`). The\nexample below is a fully functioning Erlang program accepting two command line\narguments and printing their product.\n\n```erlang\n#!/usr/bin/env escript\n\nmain(Args) ->\n argparse:run(Args, cli(), #{progname => mul}).\n\ncli() ->\n #{\n arguments => [\n #{name => left, type => integer},\n #{name => right, type => integer}\n ],\n handler =>\n fun (#{left := Left, right := Right}) ->\n io:format(\"~b~n\", [Left * Right])\n end\n }.\n```\n\nRunning this script with no arguments results in an error, accompanied by the\nusage information.\n\nThe `cli` function defines a single command with embedded handler accepting a\nmap. Keys of the map are argument names as defined by the `argument` field of\nthe command, `left` and `right` in the example. Values are taken from the\ncommand line, and converted into integers, as requested by the type\nspecification. Both arguments in the example above are required (and therefore\ndefined as positional).","title":"Quick start - argparse","ref":"argparse.html#module-quick-start"},{"type":"module","doc":"A command may contain nested commands, forming a hierarchy. Arguments defined at\nthe upper level command are automatically added to all nested commands. Nested\ncommands example (assuming `progname` is `nested`):\n\n```erlang\ncli() ->\n #{\n %% top level argument applicable to all commands\n arguments => [#{name => top}],\n commands => #{\n \"first\" => #{\n %% argument applicable to \"first\" command and\n %% all commands nested into \"first\"\n arguments => [#{name => mid}],\n commands => #{\n \"second\" => #{\n %% argument only applicable for \"second\" command\n arguments => [#{name => bottom}],\n handler => fun (A) -> io:format(\"~p~n\", [A]) end\n }\n }\n }\n }\n }.\n```\n\nIn the example above, a 3-level hierarchy is defined. First is the script itself\n(`nested`), accepting the only argument `top`. Since it has no associated\nhandler, `run/3` will not accept user input omitting nested command selection.\nFor this example, user has to supply 5 arguments in the command line, two being\ncommand names, and another 3 - required positional arguments:\n\n```text\n./nested.erl one first second two three\n#{top => \"one\",mid => \"two\",bottom => \"three\"}\n```\n\nCommands have preference over positional argument values. In the example above,\ncommands and positional arguments are interleaving, and `argparse` matches\ncommand name first.","title":"Command hierarchy - argparse","ref":"argparse.html#module-command-hierarchy"},{"type":"module","doc":"`argparse` supports positional and optional arguments. Optional arguments, or\noptions for short, must be prefixed with a special character (`-` is the default\non all operating systems). Both options and positional arguments have 1 or more\nassociated values. See [`argument specification`](`t:argument/0`) to find more\ndetails about supported combinations.\n\nIn the user input, short options may be concatenated with their values. Long\noptions support values separated by `=`. Consider this definition:\n\n```erlang\ncli() ->\n #{\n arguments => [\n #{name => long, long => \"-long\"},\n #{name => short, short => $s}\n ],\n handler => fun (Args) -> io:format(\"~p~n\", [Args]) end\n }.\n```\n\nRunning `./args --long=VALUE` prints `#{long => \"VALUE\"}`, running\n`./args -sVALUE` prints `#{short => \"VALUE\"}`\n\n`argparse` supports boolean flags concatenation: it is possible to shorten\n`-r -f -v` to `-rfv`.\n\nShortened option names are not supported: it is not possible to use `--my-argum`\ninstead of `--my-argument-name` even when such option can be unambiguously\nfound.","title":"Arguments - argparse","ref":"argparse.html#module-arguments"},{"type":"function","doc":"Generates human-readable text for [`parser error`](`t:parser_error/0`). Does not\ninclude help/usage information, and does not provide localisation.","title":"argparse.format_error/1","ref":"argparse.html#format_error/1"},{"type":"function","doc":"","title":"argparse.help/1","ref":"argparse.html#help/1"},{"type":"function","doc":"Generates help/usage information text for the command supplied, or any nested\ncommand when `command` option is specified. Arguments are displayed in the same\norder as specified in `Command`. Does not provide localisation. Expects\n`progname` to be set, otherwise defaults to return value of\n`init:get_argument(progname)`.","title":"argparse.help/2","ref":"argparse.html#help/2"},{"type":"function","doc":"","title":"argparse.parse/2","ref":"argparse.html#parse/2"},{"type":"function","doc":"Parses command line arguments according to the command specification. Raises an\nexception if the command specification is not valid. Use\n[`erl_error:format_exception/3,4` ](`erl_error:format_exception/3`)to see a\nfriendlier message. Invalid command line input does not raise an exception, but\nmakes `parse/2,3` to return a tuple\n[`{error, parser_error()}`](`t:parser_error/0`).\n\nThis function does not call command handler.","title":"argparse.parse/3","ref":"argparse.html#parse/3"},{"type":"function","doc":"Parses command line arguments and calls the matching command handler. Prints\nhuman-readable error, help/usage information for the discovered command, and\nhalts the emulator with code 1 if there is any error in the command\nspecification or user-provided command line input.\n\n> #### Warning {: .warning }\n>\n> This function is designed to work as an entry point to a standalone\n> [`escript`](`e:erts:escript_cmd.md`). Therefore, it halts the emulator for any\n> error detected. Do not use this function through remote procedure call, or it\n> may result in an unexpected shutdown of a remote node.","title":"argparse.run/3","ref":"argparse.html#run/3"},{"type":"type","doc":"Arguments map is the map of argument names to the values extracted from the\ncommand line. It is passed to the matching command handler. If an argument is\nomitted, but has the default value is specified, it is added to the map. When no\ndefault value specified, and argument is not present in the command line,\ncorresponding key is not present in the resulting map.","title":"argparse.arg_map/0","ref":"argparse.html#t:arg_map/0"},{"type":"type","doc":"Defines type conversion applied to the string retrieved from the user input. If\nthe conversion is successful, resulting value is validated using optional\n`Choices`, or minimums and maximums (for integer and floating point values\nonly). Strings and binary values may be validated using regular expressions.\nIt's possible to define custom type conversion function, accepting a string and\nreturning Erlang term. If this function raises error with `badarg` reason,\nargument is treated as invalid.","title":"argparse.arg_type/0","ref":"argparse.html#t:arg_type/0"},{"type":"type","doc":"List of command line arguments to be parsed.","title":"argparse.args/0","ref":"argparse.html#t:args/0"},{"type":"type","doc":"Argument specification. Defines a single named argument that is returned in the\n[`argument map`](`t:arg_map/0`). The only required field is `name`, all other\nfields have defaults.\n\nIf either of the `short` or `long` fields is specified, the argument is treated\nas optional. Optional arguments do not have specific order and may appear\nanywhere in the command line. Positional arguments are ordered the same way as\nthey appear in the arguments list of the command specification.\n\nBy default, all positional arguments must be present in the command line. The\nparser will return an error otherwise. Options, however, may be omitted, in\nwhich case resulting argument map will either contain the default value, or not\nhave the key at all.\n\n- **`name`** - Sets the argument name in the parsed argument map. If `help` is\n not defined, name is also used to generate the default usage message.\n\n- **`short`** - Defines a short (single character) form of an optional argument.\n\n ```erlang\n %% Define a command accepting argument named myarg, with short form $a:\n 1> Cmd = #{arguments => [#{name => myarg, short => $a}]}.\n %% Parse command line \"-a str\":\n 2> {ok, ArgMap, _, _} = argparse:parse([\"-a\", \"str\"], Cmd), ArgMap.\n\n #{myarg => \"str\"}\n\n %% Option value can be concatenated with the switch: \"-astr\"\n 3> {ok, ArgMap, _, _} = argparse:parse([\"-astr\"], Cmd), ArgMap.\n\n #{myarg => \"str\"}\n ```\n\n By default all options expect a single value following the option switch. The\n only exception is an option of a boolean type.\n\n- **`long`** - Defines a long form of an optional argument.\n\n ```erlang\n 1> Cmd = #{arguments => [#{name => myarg, long => \"name\"}]}.\n %% Parse command line \"-name Erlang\":\n 2> {ok, ArgMap, _, _} = argparse:parse([\"-name\", \"Erlang\"], Cmd), ArgMap.\n\n #{myarg => \"Erlang\"}\n %% Or use \"=\" to separate the switch and the value:\n 3> {ok, ArgMap, _, _} = argparse:parse([\"-name=Erlang\"], Cmd), ArgMap.\n\n #{myarg => \"Erlang\"}\n ```\n\n If neither `short` not `long` is defined, the argument is treated as\n positional.\n\n- **`required`** - Forces the parser to expect the argument to be present in the\n command line. By default, all positional argument are required, and all\n options are not.\n\n- **`default`** - Specifies the default value to put in the parsed argument map\n if the value is not supplied in the command line.\n\n ```erlang\n 1> argparse:parse([], #{arguments => [#{name => myarg, short => $m}]}).\n\n {ok,#{}, ...\n 2> argparse:parse([], #{arguments => [#{name => myarg, short => $m, default => \"def\"}]}).\n\n {ok,#{myarg => \"def\"}, ...\n ```\n\n- **`type`** - Defines type conversion and validation routine. The default is\n `string`, assuming no conversion.\n\n- **`nargs`** - Defines the number of following arguments to consume from the\n command line. By default, the parser consumes the next argument and converts\n it into an Erlang term according to the specified type.\n\n - **`t:pos_integer/0`** - Consume exactly this number of positional arguments,\n fail if there is not enough. Value in the argument map contains a list of\n exactly this length. Example, defining a positional argument expecting 3\n integer values:\n\n ```erlang\n 1> Cmd = #{arguments => [#{name => ints, type => integer, nargs => 3}]},\n argparse:parse([\"1\", \"2\", \"3\"], Cmd).\n\n {ok, #{ints => [1, 2, 3]}, ...\n ```\n\n Another example defining an option accepted as `-env` and expecting two\n string arguments:\n\n ```erlang\n 1> Cmd = #{arguments => [#{name => env, long => \"env\", nargs => 2}]},\n argparse:parse([\"-env\", \"key\", \"value\"], Cmd).\n\n {ok, #{env => [\"key\", \"value\"]}, ...\n ```\n\n - **`list`** - Consume all following arguments until hitting the next option\n (starting with an option prefix). May result in an empty list added to the\n arguments map.\n\n ```erlang\n 1> Cmd = #{arguments => [\n #{name => nodes, long => \"nodes\", nargs => list},\n #{name => verbose, short => $v, type => boolean}\n ]},\n argparse:parse([\"-nodes\", \"one\", \"two\", \"-v\"], Cmd).\n\n {ok, #{nodes => [\"one\", \"two\"], verbose => true}, ...\n ```\n\n - **`nonempty_list`** - Same as `list`, but expects at least one argument.\n Returns an error if the following command line argument is an option switch\n (starting with the prefix).\n\n - **`'maybe'`** - Consumes the next argument from the command line, if it does\n not start with an option prefix. Otherwise, adds a default value to the\n arguments map.\n\n ```erlang\n 1> Cmd = #{arguments => [\n #{name => level, short => $l, nargs => 'maybe', default => \"error\"},\n #{name => verbose, short => $v, type => boolean}\n ]},\n argparse:parse([\"-l\", \"info\", \"-v\"], Cmd).\n\n {ok,#{level => \"info\",verbose => true}, ...\n\n %% When \"info\" is omitted, argument maps receives the default \"error\"\n 2> argparse:parse([\"-l\", \"-v\"], Cmd).\n\n {ok,#{level => \"error\",verbose => true}, ...\n ```\n\n - **`{'maybe', term()}`** - Consumes the next argument from the command line,\n if it does not start with an option prefix. Otherwise, adds a specified\n Erlang term to the arguments map.\n\n - **`all`** - Fold all remaining command line arguments into a list, ignoring\n any option prefixes or switches. Useful for proxying arguments into another\n command line utility.\n\n ```erlang\n 1> Cmd = #{arguments => [\n #{name => verbose, short => $v, type => boolean},\n #{name => raw, long => \"-\", nargs => all}\n ]},\n argparse:parse([\"-v\", \"--\", \"-kernel\", \"arg\", \"opt\"], Cmd).\n\n {ok,#{raw => [\"-kernel\",\"arg\",\"opt\"],verbose => true}, ...\n ```\n\n- **`action`** - Defines an action to take when the argument is found in the\n command line. The default action is `store`.\n\n - **`store`** - Store the value in the arguments map. Overwrites the value\n previously written.\n\n ```erlang\n 1> Cmd = #{arguments => [#{name => str, short => $s}]},\n argparse:parse([\"-s\", \"one\", \"-s\", \"two\"], Cmd).\n\n {ok, #{str => \"two\"}, ...\n ```\n\n - **`{store, term()}`** - Stores the specified term instead of reading the\n value from the command line.\n\n ```erlang\n 1> Cmd = #{arguments => [#{name => str, short => $s, action => {store, \"two\"}}]},\n argparse:parse([\"-s\"], Cmd).\n\n {ok, #{str => \"two\"}, ...\n ```\n\n - **`append`** - Appends the repeating occurrences of the argument instead of\n overwriting.\n\n ```erlang\n 1> Cmd = #{arguments => [#{name => node, short => $n, action => append}]},\n argparse:parse([\"-n\", \"one\", \"-n\", \"two\", \"-n\", \"three\"], Cmd).\n\n {ok, #{node => [\"one\", \"two\", \"three\"]}, ...\n\n %% Always produces a list - even if there is one occurrence\n 2> argparse:parse([\"-n\", \"one\"], Cmd).\n\n {ok, #{node => [\"one\"]}, ...\n ```\n\n - **`{append, term()}`** - Same as `append`, but instead of consuming the\n argument from the command line, appends a provided `t:term/0`.\n\n - **`count`** - Puts a counter as a value in the arguments map. Useful for\n implementing verbosity option:\n\n ```erlang\n 1> Cmd = #{arguments => [#{name => verbose, short => $v, action => count}]},\n argparse:parse([\"-v\"], Cmd).\n\n {ok, #{verbose => 1}, ...\n\n 2> argparse:parse([\"-vvvv\"], Cmd).\n\n {ok, #{verbose => 4}, ...\n ```\n\n - **`extend`** - Works as `append`, but flattens the resulting list. Valid\n only for `nargs` set to `list`, `nonempty_list`, `all` or `t:pos_integer/0`.\n\n ```erlang\n 1> Cmd = #{arguments => [#{name => duet, short => $d, nargs => 2, action => extend}]},\n argparse:parse([\"-d\", \"a\", \"b\", \"-d\", \"c\", \"d\"], Cmd).\n\n {ok, #{duet => [\"a\", \"b\", \"c\", \"d\"]}, ...\n\n %% 'append' would result in {ok, #{duet => [[\"a\", \"b\"],[\"c\", \"d\"]]},\n ```\n\n- **`help`** - Specifies help/usage text for the argument. `argparse` provides\n automatic generation based on the argument name, type and default value, but\n for better usability it is recommended to have a proper description. Setting\n this field to `hidden` suppresses usage output for this argument.","title":"argparse.argument/0","ref":"argparse.html#t:argument/0"},{"type":"type","doc":"User-defined help template to print in the command usage. First element of a\ntuple must be a string. It is printed as a part of the usage header. Second\nelement of the tuple can be either a list containing strings, `type` and\n`default` atoms, or a user-defined function that must return a string. A plain\nstring should be wrapped as a list such as `[\"string is nested\"]`.","title":"argparse.argument_help/0","ref":"argparse.html#t:argument_help/0"},{"type":"type","doc":"Argument name is used to populate argument map.","title":"argparse.argument_name/0","ref":"argparse.html#t:argument_name/0"},{"type":"type","doc":"Path to the nested command. First element is always the `progname`, subsequent\nelements are nested command names.","title":"argparse.cmd_path/0","ref":"argparse.html#t:cmd_path/0"},{"type":"type","doc":"Command specification. May contain nested commands, forming a hierarchy.\n\n- **`commands`** - Maps of nested commands. Keys must be strings, matching\n command line input. Basic utilities do not need to specify any nested\n commands.\n\n- **`arguments`** - List of arguments accepted by this command, and all nested\n commands in the hierarchy.\n\n- **`help`** - Specifies help/usage text for this command. Pass `hidden` to\n remove this command from the usage output.\n\n- **`handler`** - Specifies a callback function to call by `run/3` when the\n parser is successful.","title":"argparse.command/0","ref":"argparse.html#t:command/0"},{"type":"type","doc":"User-defined help template. Use this option to mix custom and predefined usage\ntext. Help template may contain unicode strings, and following atoms:\n\n- **usage** - Formatted command line usage text, e.g. `rm [-rf] `.\n\n- **commands** - Expanded list of sub-commands.\n\n- **arguments** - Detailed description of positional arguments.\n\n- **options** - Detailed description of optional arguments.","title":"argparse.command_help/0","ref":"argparse.html#t:command_help/0"},{"type":"type","doc":"Command handler specification. Called by [`run/3` ](`run/3`)upon successful\nparser return.\n\n- **`fun((arg_map()) -> term())`** - Function accepting\n [`argument map`](`t:arg_map/0`). See the basic example in the\n [Quick Start](`m:argparse#module-quick-start`) section.\n\n- **`{Module :: module(), Function :: atom()}`** - Function named `Function`,\n exported from `Module`, accepting [`argument map`](`t:arg_map/0`).\n\n- **`{fun(() -> term()), Default :: term()}`** - Function accepting as many\n arguments as there are in the `arguments` list for this command. Arguments\n missing from the parsed map are replaced with the `Default`. Convenient way to\n expose existing functions.\n\n ```erlang\n 1> Cmd = #{arguments => [\n #{name => x, type => float},\n #{name => y, type => float, short => $p}],\n handler => {fun math:pow/2, 1}},\n argparse:run([\"2\", \"-p\", \"3\"], Cmd, #{}).\n\n 8.0\n\n %% default term 1 is passed to math:pow/2\n 2> argparse:run([\"2\"], Cmd, #{}).\n\n 2.0\n ```\n\n- **`{Module :: module(), Function :: atom(), Default :: term()}`** - Function\n named `Function`, exported from `Module`, accepting as many arguments as\n defined for this command. Arguments missing from the parsed map are replaced\n with the `Default`. Effectively, just a different syntax to the same\n functionality as demonstrated in the code above.","title":"argparse.handler/0","ref":"argparse.html#t:handler/0"},{"type":"type","doc":"Returned from [`parse/2,3`](`parse/3`). Contains arguments extracted from the\ncommand line, path to the nested command (if any), and a (potentially nested)\ncommand specification that was considered when the parser finished successfully.\nIt is expected that the command contains a handler definition, that will be\ncalled passing the argument map.","title":"argparse.parse_result/0","ref":"argparse.html#t:parse_result/0"},{"type":"type","doc":"Returned from [`parse/2,3`](`parse/3`) when the user input cannot be parsed\naccording to the command specification.\n\nFirst element is the path to the command that was considered when the parser\ndetected an error. Second element, `Expected`, is the argument specification\nthat caused an error. It could be `undefined`, meaning that `Actual` argument\nhad no corresponding specification in the arguments list for the current\ncommand.\n\nWhen `Actual` is set to `undefined`, it means that a required argument is\nmissing from the command line. If both `Expected` and `Actual` have values, it\nmeans validation error.\n\nUse `format_error/1` to generate a human-readable error description, unless\nthere is a need to provide localised error messages.","title":"argparse.parser_error/0","ref":"argparse.html#t:parser_error/0"},{"type":"type","doc":"Options changing parser behaviour.\n\n- **`prefixes`** - Changes the option prefix (the default is `-`).\n\n- **`default`** - Specifies the default value for all optional arguments. When\n this field is set, resulting argument map will contain all argument names.\n Useful for easy pattern matching on the argument map in the handler function.\n\n- **`progname`** - Specifies the program (root command) name. Returned as the\n first element of the command path, and printed in help/usage text. It is\n recommended to have this value set, otherwise the default one is determined\n with `init:get_argument(progname)` and is often set to `erl` instead of the\n actual script name.\n\n- **`command`** - Specifies the path to the nested command for `help/2`. Useful\n to limit output for complex utilities with multiple commands, and used by the\n default error handling logic.\n\n- **`columns`** - Specifies the help/usage text width (characters) for `help/2`.\n Default value is 80.","title":"argparse.parser_options/0","ref":"argparse.html#t:parser_options/0"},{"type":"module","doc":"This module provides functions to create and inspect escripts.\n\nSee the [escript](`e:erts:escript_cmd.md`) program documentation\nfor more details on how to use escripts.","title":"escript","ref":"escript.html"},{"type":"function","doc":"Creates an escript from a list of sections.\n\nThe sections can be specified in any order. An escript begins with an optional\n`Header` followed by a mandatory `Body`. If the header is present, it does always\n begin with a `shebang`, possibly followed by a `comment` and `emu_args`. The\n`shebang` defaults to `\"/usr/bin/env escript\"`. The `comment` defaults to\n`\"This is an -*- erlang -*- file\"`. The created escript can either be returned\nas a binary or written to file.\n\nAs an example of how the function can be used, we create an interpreted escript\nthat uses `emu_args` to set some emulator flag. In this case, it happens to set\nnumber of schedulers with `+S3`. We also extract the different sections from the\nnewly created script:\n\n```erlang\n> Source = \"%% Demo\\nmain(_Args) ->\\n io:format(\\\"~p\\\",[erlang:system_info(schedulers)]).\\n\".\n\"%% Demo\\nmain(_Args) ->\\n io:format(erlang:system_info(schedulers)).\\n\"\n> io:format(\"~s\\n\", [Source]).\n%% Demo\nmain(_Args) ->\n io:format(erlang:system_info(schedulers)).\n\nok\n> {ok, Bin} = escript:create(binary, [shebang, comment, {emu_args, \"+S3\"},\n {source, list_to_binary(Source)}]).\n{ok,<<\"#!/usr/bin/env escript\\n%% This is an -*- erlang -*- file\\n%%!+S3\"...>>}\n> file:write_file(\"demo.escript\", Bin).\nok\n> os:cmd(\"escript demo.escript\").\n\"3\"\n> escript:extract(\"demo.escript\", []).\n{ok,[{shebang,default}, {comment,default}, {emu_args,\"+S3\"},\n {source,<<\"%% Demo\\nmain(_Args) ->\\n io:format(erlang:system_info(schedu\"...>>}]}\n```\n\nAn escript without header can be created as follows:\n\n```erlang\n> file:write_file(\"demo.erl\",\n [\"%% demo.erl\\n-module(demo).\\n-export([main/1]).\\n\\n\", Source]).\nok\n> {ok, _, BeamCode} = compile:file(\"demo.erl\", [binary, debug_info]).\n{ok,demo,\n <<70,79,82,49,0,0,2,208,66,69,65,77,65,116,111,109,0,0,0,\n 79,0,0,0,9,4,100,...>>}\n> escript:create(\"demo.beam\", [{beam, BeamCode}]).\nok\n> escript:extract(\"demo.beam\", []).\n{ok,[{shebang,undefined}, {comment,undefined}, {emu_args,undefined},\n {beam,<<70,79,82,49,0,0,3,68,66,69,65,77,65,116,\n 111,109,0,0,0,83,0,0,0,9,...>>}]}\n> os:cmd(\"escript demo.beam\").\n\"true\"\n```\n\nHere we create an archive script containing both Erlang code and Beam code, then\nwe iterate over all files in the archive and collect their contents and some\ninformation about them:\n\n```erlang\n> {ok, SourceCode} = file:read_file(\"demo.erl\").\n{ok,<<\"%% demo.erl\\n-module(demo).\\n-export([main/1]).\\n\\n%% Demo\\nmain(_Arg\"...>>}\n> escript:create(\"demo.escript\",\n [shebang,\n {archive, [{\"demo.erl\", SourceCode},\n {\"demo.beam\", BeamCode}], []}]).\nok\n> {ok, [{shebang,default}, {comment,undefined}, {emu_args,undefined},\n {archive, ArchiveBin}]} = escript:extract(\"demo.escript\", []).\n{ok,[{shebang,default}, {comment,undefined}, {emu_args,undefined},\n {{archive,<<80,75,3,4,20,0,0,0,8,0,118,7,98,60,105,\n 152,61,93,107,0,0,0,118,0,...>>}]}\n> file:write_file(\"demo.zip\", ArchiveBin).\nok\n> zip:foldl(fun(N, I, B, A) -> [{N, I(), B()} | A] end, [], \"demo.zip\").\n{ok,[{\"demo.beam\",\n {file_info,748,regular,read_write,\n {{2010,3,2},{0,59,22}},\n {{2010,3,2},{0,59,22}},\n {{2010,3,2},{0,59,22}},\n 54,1,0,0,0,0,0},\n <<70,79,82,49,0,0,2,228,66,69,65,77,65,116,111,109,0,0,0,\n 83,0,0,...>>},\n {\"demo.erl\",\n {file_info,118,regular,read_write,\n {{2010,3,2},{0,59,22}},\n {{2010,3,2},{0,59,22}},\n {{2010,3,2},{0,59,22}},\n 54,1,0,0,0,0,0},\n <<\"%% demo.erl\\n-module(demo).\\n-export([main/1]).\\n\\n%% Demo\\nmain(_Arg\"...>>}]}\n```","title":"escript.create/2","ref":"escript.html#create/2"},{"type":"function","doc":"Parses an escript and extracts its sections. This is the reverse of `create/2`.\n\nAll sections are returned even if they do not exist in the escript. If a\nparticular section happens to have the same value as the default value, the\nextracted value is set to the atom `default`. If a section is missing, the\nextracted value is set to the atom `undefined`.\n\nOption `compile_source` only affects the result if the escript contains `source`\ncode. In this case the Erlang code is automatically compiled and\n`{source, BeamCode}` is returned instead of `{source, SourceCode}`.\n\nExample:\n\n```erlang\n> escript:create(\"demo.escript\",\n [shebang, {archive, [{\"demo.erl\", SourceCode},\n {\"demo.beam\", BeamCode}], []}]).\nok\n> {ok, [{shebang,default}, {comment,undefined}, {emu_args,undefined},\n {archive, ArchiveBin}]} =\n escript:extract(\"demo.escript\", []).\n{ok,[{{archive,<<80,75,3,4,20,0,0,0,8,0,118,7,98,60,105,\n 152,61,93,107,0,0,0,118,0,...>>}\n {emu_args,undefined}]}\n```","title":"escript.extract/2","ref":"escript.html#extract/2"},{"type":"function","doc":"Returns the name of the escript that is executed.\n\nIf the function is invoked outside the context of an escript,\nthe behavior is undefined.","title":"escript.script_name/0","ref":"escript.html#script_name/0"},{"type":"type","doc":"","title":"escript.comment/0","ref":"escript.html#t:comment/0"},{"type":"type","doc":"Any arguments that should be passed to [erl](`e:erts:erl_cmd.md`) when starting.","title":"escript.emu_args/0","ref":"escript.html#t:emu_args/0"},{"type":"type","doc":"","title":"escript.extract_option/0","ref":"escript.html#t:extract_option/0"},{"type":"type","doc":"","title":"escript.section/0","ref":"escript.html#t:section/0"},{"type":"type","doc":"","title":"escript.section_name/0","ref":"escript.html#t:section_name/0"},{"type":"type","doc":"The initial `#!` line.\n\nFor example:\n\n```text\n#!/usr/bin/env escript\n```","title":"escript.shebang/0","ref":"escript.html#t:shebang/0"},{"type":"type","doc":"","title":"escript.zip_file/0","ref":"escript.html#t:zip_file/0"},{"type":"module","doc":"Start and control linked Erlang nodes.\n\nThis module provides functions for starting linked Erlang nodes. The node\nspawning new nodes is called _origin_, and newly started nodes are _peer_ nodes,\nor peers. A peer node automatically terminates when it loses the _control\nconnection_ to the origin. This connection could be an Erlang distribution\nconnection, or an alternative - TCP or standard I/O. The alternative connection\nprovides a way to execute remote procedure calls even when Erlang Distribution\nis not available, allowing to test the distribution itself.\n\nPeer node terminal input/output is relayed through the origin. If a standard I/O\nalternative connection is requested, console output also goes via the origin,\nallowing debugging of node startup and boot script execution (see\n[`-init_debug`](`e:erts:erl_cmd.md#init_debug`)). File I/O is not redirected,\ncontrary to `m:slave` behaviour.\n\nThe peer node can start on the same or a different host (via `ssh`) or in a\nseparate container (for example Docker). When the peer starts on the same host\nas the origin, it inherits the current directory and environment variables from\nthe origin.\n\n> #### Note {: .info }\n>\n> This module is designed to facilitate multi-node testing with Common Test. Use\n> the `?CT_PEER()` macro to start a linked peer node according to Common Test\n> conventions: crash dumps written to specific location, node name prefixed with\n> module name, calling function, and origin OS process ID). Use `random_name/1`\n> to create sufficiently unique node names if you need more control.\n>\n> A peer node started without alternative connection behaves similarly to\n> `m:slave`. When an alternative connection is requested, the behaviour is\n> similar to `test_server:start_node(Name, peer, Args).`","title":"peer","ref":"peer.html"},{"type":"module","doc":"The following example implements a test suite starting extra Erlang nodes. It\nemploys a number of techniques to speed up testing and reliably shut down peer\nnodes:\n\n- peers start linked to test runner process. If the test case fails, the peer\n node is stopped automatically, leaving no rogue nodes running in the\n background\n- arguments used to start the peer are saved in the control process state for\n manual analysis. If the test case fails, the CRASH REPORT contains these\n arguments\n- multiple test cases can run concurrently speeding up overall testing process,\n peer node names are unique even when there are multiple instances of the same\n test suite running in parallel\n\n```erlang\n-module(my_SUITE).\n-behaviour(ct_suite).\n-export([all/0, groups/0]).\n-export([basic/1, args/1, named/1, restart_node/1, multi_node/1]).\n\n-include_lib(\"common_test/include/ct.hrl\").\n\ngroups() ->\n [{quick, [parallel],\n [basic, args, named, restart_node, multi_node]}].\n\nall() ->\n [{group, quick}].\n\nbasic(Config) when is_list(Config) ->\n {ok, Peer, _Node} = ?CT_PEER(),\n peer:stop(Peer).\n\nargs(Config) when is_list(Config) ->\n %% specify additional arguments to the new node\n {ok, Peer, _Node} = ?CT_PEER([\"-emu_flavor\", \"smp\"]),\n peer:stop(Peer).\n\nnamed(Config) when is_list(Config) ->\n %% pass test case name down to function starting nodes\n Peer = start_node_impl(named_test),\n peer:stop(Peer).\n\nstart_node_impl(ActualTestCase) ->\n {ok, Peer, Node} = ?CT_PEER(#{name => ?CT_PEER_NAME(ActualTestCase)}),\n %% extra setup needed for multiple test cases\n ok = rpc:call(Node, application, set_env, [kernel, key, value]),\n Peer.\n\nrestart_node(Config) when is_list(Config) ->\n Name = ?CT_PEER_NAME(),\n {ok, Peer, Node} = ?CT_PEER(#{name => Name}),\n peer:stop(Peer),\n %% restart the node with the same name as before\n {ok, Peer2, Node} = ?CT_PEER(#{name => Name, args => [\"+fnl\"]}),\n peer:stop(Peer2).\n```\n\nThe next example demonstrates how to start multiple nodes concurrently:\n\n```erlang\nmulti_node(Config) when is_list(Config) ->\n Peers = [?CT_PEER(#{wait_boot => {self(), tag}})\n || _ <- lists:seq(1, 4)],\n %% wait for all nodes to complete boot process, get their names:\n _Nodes = [receive {tag, {started, Node, Peer}} -> Node end\n || {ok, Peer} <- Peers],\n [peer:stop(Peer) || {ok, Peer} <- Peers].\n```\n\nStart a peer on a different host. Requires `ssh` key-based authentication set\nup, allowing \"another_host\" connection without password prompt.\n\n```erlang\nSsh = os:find_executable(\"ssh\"),\npeer:start_link(#{exec => {Ssh, [\"another_host\", \"erl\"]},\n connection => standard_io}),\n```\n\nThe following Common Test case demonstrates Docker integration, starting two\ncontainers with hostnames \"one\" and \"two\". In this example Erlang nodes running\ninside containers form an Erlang cluster.\n\n```erlang\ndocker(Config) when is_list(Config) ->\n Docker = os:find_executable(\"docker\"),\n PrivDir = proplists:get_value(priv_dir, Config),\n build_release(PrivDir),\n build_image(PrivDir),\n\n %% start two Docker containers\n {ok, Peer, Node} = peer:start_link(#{name => lambda,\n connection => standard_io,\n exec => {Docker, [\"run\", \"-h\", \"one\", \"-i\", \"lambda\"]}}),\n {ok, Peer2, Node2} = peer:start_link(#{name => lambda,\n connection => standard_io,\n exec => {Docker, [\"run\", \"-h\", \"two\", \"-i\", \"lambda\"]}}),\n\n %% find IP address of the second node using alternative connection RPC\n {ok, Ips} = peer:call(Peer2, inet, getifaddrs, []),\n {\"eth0\", Eth0} = lists:keyfind(\"eth0\", 1, Ips),\n {addr, Ip} = lists:keyfind(addr, 1, Eth0),\n\n %% make first node to discover second one\n ok = peer:call(Peer, inet_db, set_lookup, [[file]]),\n ok = peer:call(Peer, inet_db, add_host, [Ip, [\"two\"]]),\n\n %% join a cluster\n true = peer:call(Peer, net_kernel, connect_node, [Node2]),\n %% verify that second peer node has only the first node visible\n [Node] = peer:call(Peer2, erlang, nodes, []),\n\n %% stop peers, causing containers to also stop\n peer:stop(Peer2),\n peer:stop(Peer).\n\nbuild_release(Dir) ->\n %% load sasl.app file, otherwise application:get_key will fail\n application:load(sasl),\n %% create *.rel - release file\n RelFile = filename:join(Dir, \"lambda.rel\"),\n Release = {release, {\"lambda\", \"1.0.0\"},\n {erts, erlang:system_info(version)},\n [{App, begin {ok, Vsn} = application:get_key(App, vsn), Vsn end}\n || App <- [kernel, stdlib, sasl]]},\n ok = file:write_file(RelFile, list_to_binary(lists:flatten(\n io_lib:format(\"~tp.\", [Release])))),\n RelFileNoExt = filename:join(Dir, \"lambda\"),\n\n %% create boot script\n {ok, systools_make, []} = systools:make_script(RelFileNoExt,\n [silent, {outdir, Dir}]),\n %% package release into *.tar.gz\n ok = systools:make_tar(RelFileNoExt, [{erts, code:root_dir()}]).\n\nbuild_image(Dir) ->\n %% Create Dockerfile example, working only for Ubuntu 20.04\n %% Expose port 4445, and make Erlang distribution to listen\n %% on this port, and connect to it without EPMD\n %% Set cookie on both nodes to be the same.\n BuildScript = filename:join(Dir, \"Dockerfile\"),\n Dockerfile =\n \"FROM ubuntu:20.04 as runner\\n\"\n \"EXPOSE 4445\\n\"\n \"WORKDIR /opt/lambda\\n\"\n \"COPY lambda.tar.gz /tmp\\n\"\n \"RUN tar -zxvf /tmp/lambda.tar.gz -C /opt/lambda\\n\"\n \"ENTRYPOINT [\\\"/opt/lambda/erts-\" ++ erlang:system_info(version) ++\n \"/bin/dyn_erl\\\", \\\"-boot\\\", \\\"/opt/lambda/releases/1.0.0/start\\\",\"\n \" \\\"-kernel\\\", \\\"inet_dist_listen_min\\\", \\\"4445\\\",\"\n \" \\\"-erl_epmd_port\\\", \\\"4445\\\",\"\n \" \\\"-setcookie\\\", \\\"secret\\\"]\\n\",\n ok = file:write_file(BuildScript, Dockerfile),\n os:cmd(\"docker build -t lambda \" ++ Dir).\n```","title":"Example - peer","ref":"peer.html#module-example"},{"type":"function","doc":"","title":"peer.call/4","ref":"peer.html#call/4"},{"type":"function","doc":"Uses the alternative connection to evaluate\n[`apply(Module, Function, Args)`](`apply/3`) on the peer node and returns the\ncorresponding value `Result`.\n\n`Timeout` is an integer representing the timeout in milliseconds or the atom\n`infinity` which prevents the operation from ever timing out.\n\nWhen an alternative connection is not requested, this function will raise `exit`\nsignal with the `noconnection` reason. Use `m:erpc` module to communicate over\nErlang distribution.","title":"peer.call/5","ref":"peer.html#call/5"},{"type":"function","doc":"Uses the alternative connection to evaluate\n[`apply(Module, Function, Args)`](`apply/3`) on the peer node. No response is\ndelivered to the calling process.\n\n`peer:cast/4` fails silently when the alternative connection is not configured.\nUse `m:erpc` module to communicate over Erlang distribution.","title":"peer.cast/4","ref":"peer.html#cast/4"},{"type":"function","doc":"Returns the peer node state.\n\nThe initial state is `booting`; the node stays in that state until then boot\nscript is complete, and then the node progresses to `running`. If the node stops\n(gracefully or not), the state changes to `down`.","title":"peer.get_state/1","ref":"peer.html#get_state/1"},{"type":"function","doc":"","title":"peer.random_name/0","ref":"peer.html#random_name/0"},{"type":"function","doc":"Creates a sufficiently unique node name for the current host, combining a\nprefix, a unique number, and the current OS process ID.\n\n> #### Note {: .info }\n>\n> Use the `?CT_PEER([\"erl_arg1\"])` macro provided by Common Test\n> `-include_lib(\"common_test/include/ct.hrl\")` for convenience. It starts a new\n> peer using Erlang distribution as the control channel, supplies thes calling\n> module's code path to the peer, and uses the calling function name for the\n> name prefix.","title":"peer.random_name/1","ref":"peer.html#random_name/1"},{"type":"function","doc":"Uses the alternative connection to send Message to a process on the the peer node.\n\nSilently fails if no alternative connection is configured. The process can\nbe referenced by process ID or registered name.","title":"peer.send/3","ref":"peer.html#send/3"},{"type":"function","doc":"Starts a peer node with the specified `t:start_options/0`. Returns the\ncontrolling process and the full peer node name, unless `wait_boot` is not\nrequested and the host name is not known in advance.","title":"peer.start/1","ref":"peer.html#start/1"},{"type":"function","doc":"The same as [`start_link(#{name => random_name()})`](`start_link/1`).","title":"peer.start_link/0","ref":"peer.html#start_link/0"},{"type":"function","doc":"Starts a peer node in the same way as `start/1`, except that the peer node is\nlinked to the currently executing process. If that process terminates, the peer\nnode also terminates.\n\nAccepts `t:start_options/0`. Returns the controlling process and the full peer\nnode name, unless `wait_boot` is not requested and host name is not known in\nadvance.\n\nWhen the `standard_io` alternative connection is requested, and `wait_boot` is\nnot set to `false`, a failed peer boot sequence causes the caller to exit with\nthe `{boot_failed, {exit_status, ExitCode}}` reason.","title":"peer.start_link/1","ref":"peer.html#start_link/1"},{"type":"function","doc":"Stops a peer node. How the node is stopped depends on the\n[`shutdown`](`t:start_options/0`) option passed when starting the peer node.\nCurrently the following `shutdown` options are supported:\n\n- **`halt`** - This is the default shutdown behavior. It behaves as `shutdown`\n option `{halt, DefaultTimeout}` where `DefaultTimeout` currently equals\n `5000`.\n\n- **`{halt, Timeout :: disconnect_timeout()}`** - Triggers a call to\n [`erlang:halt()`](`erlang:halt/0`) on the peer node and then waits for the\n Erlang distribution connection to the peer node to be taken down. If this\n connection has not been taken down after `Timeout` milliseconds, it will\n forcefully be taken down by `peer:stop/1`. See the\n [warning](`m:peer#dist_connection_close`) below for more info about this.\n\n- **`Timeout :: disconnect_timeout()`** - Triggers a call to\n [`init:stop()`](`init:stop/0`) on the peer node and then waits for the Erlang\n distribution connection to the peer node to be taken down. If this connection\n has not been taken down after `Timeout` milliseconds, it will forcefully be\n taken down by `peer:stop/1`. See the [warning](`m:peer#dist_connection_close`)\n below for more info about this.\n\n- **`close`** - Close the _control connection_ to the peer node and return. This\n is the fastest way for the caller of `peer:stop/1` to stop a peer node.\n\n Note that if the Erlang distribution connection is not used as control\n connection it might not have been taken down when `peer:stop/1` returns. Also\n note that the [warning](`m:peer#dist_connection_close`) below applies when the\n Erlang distribution connection is used as control connection.\n\n[](){: #dist_connection_close }\n\n> #### Warning {: .warning }\n>\n> In the cases where the Erlang distribution connection is taken down by\n> `peer:stop/1`, other code independent of the peer code might react to the\n> connection loss before the peer node is stopped which might cause undesirable\n> effects. For example, [`global`](`m:global#prevent_overlapping_partitions`)\n> might trigger even more Erlang distribution connections to other nodes to be\n> taken down. The potential undesirable effects are, however, not limited to\n> this. It is hard to say what the effects will be since these effects can be\n> caused by any code with links or monitors to something on the origin node, or\n> code monitoring the connection to the origin node.","title":"peer.stop/1","ref":"peer.html#stop/1"},{"type":"type","doc":"Alternative connection between the origin and the peer. When the connection\ncloses, the peer node terminates automatically.\n\nIf the `peer_down` startup flag is set to `crash`, the controlling process on\nthe origin node exits with corresponding reason, effectively providing a two-way link.\n\nWhen `connection` is set to a port number, the origin starts listening on the\nrequested TCP port, and the peer node connects to the port. When it is set to an\n`{IP, Port}` tuple, the origin listens only on the specified IP. The port number\ncan be set to 0 for automatic selection.\n\nUsing the `standard_io` alternative connection starts the peer attached to the\norigin (other connections use `-detached` flag to erl). In this mode peer and\norigin communicate via stdin/stdout.","title":"peer.connection/0","ref":"peer.html#t:connection/0"},{"type":"type","doc":"Disconnect timeout. See [`stop()`](`stop/1`).","title":"peer.disconnect_timeout/0","ref":"peer.html#t:disconnect_timeout/0"},{"type":"type","doc":"Overrides executable to start peer nodes with.\n\nBy default it is the path to \"erl\", taken from `init:get_argument(progname)`.\nIf `progname` is not known, `peer` makes best guess given the current ERTS version.\n\nWhen a tuple is passed, the first element is the path to executable, and the\nsecond element is prepended to the final command line. This can be used to start\npeers on a remote host or in a Docker container. See the examples above.\n\nThis option is useful for testing backwards compatibility with previous\nreleases, installed at specific paths, or when the Erlang installation location\nis missing from the `PATH`.","title":"peer.exec/0","ref":"peer.html#t:exec/0"},{"type":"type","doc":"Peer node state.","title":"peer.peer_state/0","ref":"peer.html#t:peer_state/0"},{"type":"type","doc":"Identifies the controlling process of a peer node.","title":"peer.server_ref/0","ref":"peer.html#t:server_ref/0"},{"type":"type","doc":"Options that can be used when starting a `peer` node through `start/1` and\n[`start_link/0,1`](`start_link/0`).\n\n- **`name`** - Node name (the part before \"@\"). When `name` is not specified,\n but `host` is, `peer` follows compatibility behaviour and uses the origin node\n name.\n\n- **`longnames`** - Use long names to start a node. Default is taken from the\n origin using `net_kernel:longnames()`. If the origin is not distributed, short\n names is the default.\n\n- **`host`** - Enforces a specific host name. Can be used to override the\n default behaviour and start \"node@localhost\" instead of \"node@realhostname\".\n\n- **`peer_down`** - Defines the peer control process behaviour when the control\n connection is closed from the peer node side (for example when the peer\n crashes or dumps core). When set to `stop` (default), a lost control\n connection causes the control process to exit normally. Setting `peer_down` to\n `continue` keeps the control process running, and `crash` will cause the\n controlling process to exit abnormally.\n\n- **`connection`** - Alternative connection specification. See the\n [`connection` datatype](`t:connection/0`).\n\n- **`exec`** - Alternative mechanism to start peer nodes with, for example, ssh\n instead of the default bash.\n\n- **`detached`** - Defines whether to pass the `-detached` flag to the started\n peer. This option cannot be set to `false` using the `standard_io` alternative\n connection type. Default is `true`.\n\n- **`args`** - Extra command line arguments to append to the \"erl\" command.\n Arguments are passed as is, no escaping or quoting is needed or accepted.\n\n- **`post_process_args`** - Allows the user to change the arguments passed to\n `exec` before the peer is started. This can for example be useful when the\n `exec` program wants the arguments to \"erl\" as a single argument. Example:\n\n ```erlang\n peer:start(#{ name => peer:random_name(),\n exec => {os:find_executable(\"bash\"),[\"-c\",\"erl\"]},\n post_process_args =>\n fun([\"-c\"|Args]) -> [\"-c\", lists:flatten(lists:join($\\s, Args))] end\n }).\n ```\n\n- **`env`** - List of environment variables with their values. This list is\n applied to a locally started executable. If you need to change the environment\n of the remote peer, adjust `args` to contain `-env ENV_KEY ENV_VALUE`.\n\n- **`wait_boot`** - Specifies the start/start_link timeout. See\n [`wait_boot` datatype](`t:wait_boot/0`).\n\n- **`shutdown`** - Specifies the peer node stopping behaviour. See\n [`stop()`](`stop/1`).","title":"peer.start_options/0","ref":"peer.html#t:start_options/0"},{"type":"type","doc":"Specifies start/start_link timeout in milliseconds. Can be set to `false`,\nallowing the peer to start asynchronously. If `{Pid, Tag}` is specified instead\nof a timeout, the peer will send `Tag` to the requested process.\n\nThe default is `15_000` ms.","title":"peer.wait_boot/0","ref":"peer.html#t:wait_boot/0"},{"type":"module","doc":"This module provides functions for starting Erlang slave nodes.\n\nAll slave nodes that are started by a master terminate automatically when the\nmaster terminates. All terminal output produced at the slave is sent back to\nthe master node. File I/O is done through the master.\n\nSlave nodes on other hosts than the current one are started with the `ssh`\nprogram. The user must be allowed to `ssh` to the remote hosts without being\nprompted for a password. This can be arranged in a number of ways (for details,\nsee the `ssh` documentation). A slave node started on the same host as the\nmaster inherits certain environment values from the master, such as the current\ndirectory and the environment variables. For what can be assumed about the\nenvironment when a slave is started on another host, see the documentation for\nthe `ssh` program.\n\nAn alternative to the `ssh` program can be specified on the command line to\n[`erl(1)`](`e:erts:erl_cmd.md`) as follows:\n\n```text\n-rsh Program\n```\n\nNote that the command specified with the `-rsh` flag is treated as a file name\nwhich may contain spaces. It is thus not possible to include any command line\noptions. The remote node will be launched as\n`\"$RSH\" \"$REMOTE_HOSTNAME\" erl -detached -noinput ...`, so the `erl` command\nmust be found in the path on the remote host.\n\nThe slave node is to use the same file system at the master. At least,\nErlang/OTP is to be installed in the same place on both computers and the same\nversion of Erlang is to be used.\n\nA node running on Windows can only start slave nodes on the host on which it is\nrunning.\n\nThe master node must be alive.","title":"slave","ref":"slave.html"},{"type":"function","doc":"Calls [`pseudo(Master, ServerList)`](`pseudo/2`). If you want to start a node\nfrom the command line and set up a number of pseudo servers, an Erlang runtime\nsystem can be started as follows:\n\n```text\n% erl -name abc -s slave pseudo klacke@super x --\n```","title":"slave.pseudo/1","ref":"slave.html#pseudo/1"},{"type":"function","doc":"Starts a number of pseudo servers. A pseudo server is a server with a registered\nname that does nothing but pass on all message to the real server that executes\nat a master node. A pseudo server is an intermediary that only has the same\nregistered name as the real server.\n\nFor example, if you have started a slave node `N` and want to execute `pxw`\ngraphics code on this node, you can start server `pxw_server` as a pseudo server\nat the slave node. This is illustrated as follows:\n\n```erlang\nrpc:call(N, slave, pseudo, [node(), [pxw_server]]).\n```","title":"slave.pseudo/2","ref":"slave.html#pseudo/2"},{"type":"function","doc":"Runs a pseudo server. This function never returns any value and the process that\nexecutes the function receives messages. All messages received are simply passed\non to `Pid`.","title":"slave.relay/1","ref":"slave.html#relay/1"},{"type":"function","doc":"Equivalent to [`start(Host, Name)`](`start/2`) where `Name` is the same\nas the node that executes this call.","title":"slave.start/1","ref":"slave.html#start/1"},{"type":"function","doc":"","title":"slave.start/2","ref":"slave.html#start/2"},{"type":"function","doc":"Starts a slave node on host `Host`. Host names need not necessarily be specified\nas fully qualified names; short names can also be used. This is the same\ncondition that applies to names of distributed Erlang nodes.\n\nThe name of the started node becomes `Name@Host`.\n\nThe slave node resets its `t:io:user/0` process so that all terminal I/O that is\nproduced at the slave is automatically relayed to the master. Also, the file\nserver is relayed to the master.\n\nArgument `Args` is used to set `erl` command-line arguments. It is\npassed to the new node and can be used for a variety of purposes; see\n[`erl(1)`](`e:erts:erl_cmd.md`).\n\nAs an example, suppose that you want to start a slave node at host `H` with node\nname `Name@H` and want the slave node to have the following properties:\n\n- Directory `Dir` is to be added to the code path.\n- The Mnesia directory is to be set to `M`.\n- The Unix `DISPLAY` environment variable is to be set to the display of the\n master node.\n\nThe following code is executed to achieve this:\n\n```erlang\nE = \" -env DISPLAY \" ++ net_adm:localhost() ++ \":0 \",\nArg = \"-mnesia_dir \" ++ M ++ \" -pa \" ++ Dir ++ E,\nslave:start(H, Name, Arg).\n```\n\nThe function returns `{ok, Node}`, where `Node` is the name of the new node,\notherwise `{error, Reason}`, where `Reason` can be one of:\n\n- **`timeout`** - The master node failed to get in contact with the slave node.\n This can occur in a number of circumstances:\n\n - Erlang/OTP is not installed on the remote host.\n - The file system on the other host has a different structure to the the\n master.\n - The Erlang nodes have different cookies.\n\n- **`no_rsh`** - No remote shell program was found on the computer. Note that\n `ssh` is used by default, but this can be overridden with the `-rsh` flag.\n\n- **`{already_running, Node}`** - A node with name `Name@Host` already exists.","title":"slave.start/3","ref":"slave.html#start/3"},{"type":"function","doc":"","title":"slave.start_link/1","ref":"slave.html#start_link/1"},{"type":"function","doc":"","title":"slave.start_link/2","ref":"slave.html#start_link/2"},{"type":"function","doc":"Starts a slave node in the same way as `start/1,2,3`, except that the slave node\nis linked to the currently executing process. If that process terminates, the\nslave node also terminates.\n\nFor a description of arguments and return values, see\n[`start/1,2,3`](`start/1`).","title":"slave.start_link/3","ref":"slave.html#start_link/3"},{"type":"function","doc":"Stops (kills) a node.","title":"slave.stop/1","ref":"slave.html#stop/1"},{"type":"module","doc":"Provides access to the registry on Windows.\n\nThis module provides read and write access to the registry on Windows. It is\nessentially a port driver wrapped around the Win32 API calls for accessing the\nregistry.\n\nThe registry is a hierarchical database, used to store various system and\nsoftware information in Windows. It contains installation data, and is updated\nby installers and system programs. The Erlang installer updates the registry by\nadding data that Erlang needs.\n\nThe registry contains keys and values. Keys are like the directories in a file\nsystem, they form a hierarchy. Values are like files, they have a name and a\nvalue, and also a type.\n\nPaths to keys are left to right, with subkeys to the right and backslash between\nkeys. (Remember that backslashes must be doubled in Erlang strings.) Case is\npreserved but not significant.\n\nFor example, `\"\\\\hkey_local_machine\\\\software\\\\Ericsson\\\\Erlang\\\\5.0\"` is the\nkey for the installation data for the latest Erlang release.\n\nThere are six entry points in the Windows registry, top-level keys. They can be\nabbreviated in this module as follows:\n\n```text\nAbbreviation Registry key\n============ ============\nhkcr HKEY_CLASSES_ROOT\ncurrent_user HKEY_CURRENT_USER\nhkcu HKEY_CURRENT_USER\nlocal_machine HKEY_LOCAL_MACHINE\nhklm HKEY_LOCAL_MACHINE\nusers HKEY_USERS\nhku HKEY_USERS\ncurrent_config HKEY_CURRENT_CONFIG\nhkcc HKEY_CURRENT_CONFIG\ndyn_data HKEY_DYN_DATA\nhkdd HKEY_DYN_DATA\n```\n\nThe key above can be written as `\"\\\\hklm\\\\software\\\\ericsson\\\\erlang\\\\5.0\"`.\n\nThis module uses a current key. It works much like the current directory. From\nthe current key, values can be fetched, subkeys can be listed, and so on.\n\nUnder a key, any number of named values can be stored. They have names, types,\nand data.\n\n`win32reg` supports storing of the following types:\n\n- `REG_DWORD`, which is an integer\n- `REG_SZ`, which is a string\n- `REG_BINARY`, which is a binary\n\nOther types can be read, and are returned as binaries.\n\nThere is also a \"default\" value, which has the empty string as name. It is read\nand written with the atom `default` instead of the name.\n\nSome registry values are stored as strings with references to environment\nvariables, for example, `%SystemRoot%Windows`. `SystemRoot` is an environment\nvariable, and is to be replaced with its value. Function `expand/1` is provided\nso that environment variables surrounded by `%` can be expanded to their values.\n\nFor more information on the Windows registry, see consult the Win32 Programmer's\nReference.","title":"win32reg","ref":"win32reg.html"},{"type":"module","doc":"`erl_posix_msg`, The Windows 95 Registry (book from O'Reilly), Win32\nProgrammer's Reference (from Microsoft)","title":"See Also - win32reg","ref":"win32reg.html#module-see-also"},{"type":"function","doc":"Changes the current key to another key. Works like `cd`. The key can be\nspecified as a relative path or as an absolute path, starting with `\\.`","title":"win32reg.change_key/2","ref":"win32reg.html#change_key/2"},{"type":"function","doc":"Creates a key, or just changes to it, if it is already there. Works like a\ncombination of `mkdir` and `cd`. Calls the Win32 API function\n`RegCreateKeyEx()`.\n\nThe registry must have been opened in write mode.","title":"win32reg.change_key_create/2","ref":"win32reg.html#change_key_create/2"},{"type":"function","doc":"Closes the registry. After that, the `RegHandle` cannot be used.","title":"win32reg.close/1","ref":"win32reg.html#close/1"},{"type":"function","doc":"Returns the path to the current key. This is the equivalent of `pwd`.\n\nNotice that the current key is stored in the driver, and can be invalid (for\nexample, if the key has been removed).","title":"win32reg.current_key/1","ref":"win32reg.html#current_key/1"},{"type":"function","doc":"Deletes the current key, if it is valid. Calls the Win32 API function\n`RegDeleteKey()`. Notice that this call does not change the current key (unlike\n`change_key_create/2`). This means that after the call, the current key is\ninvalid.","title":"win32reg.delete_key/1","ref":"win32reg.html#delete_key/1"},{"type":"function","doc":"Deletes a named value on the current key. The atom `default` is used for the\ndefault value.\n\nThe registry must have been opened in write mode.","title":"win32reg.delete_value/2","ref":"win32reg.html#delete_value/2"},{"type":"function","doc":"Expands a string containing environment variables between percent characters.\nAnything between two `%` is taken for an environment variable, and is replaced\nby the value. Two consecutive `%` are replaced by one `%`.\n\nA variable name that is not in the environment results in an error.","title":"win32reg.expand/1","ref":"win32reg.html#expand/1"},{"type":"function","doc":"Converts a POSIX error code to a string (by calling `file:format_error/1`).","title":"win32reg.format_error/1","ref":"win32reg.html#format_error/1"},{"type":"function","doc":"Opens the registry for reading or writing. The current key is the root\n(`HKEY_CLASSES_ROOT`). Flag `read` in the mode list can be omitted.\n\nUse `change_key/2` with an absolute path after [`open`](`open/1`).","title":"win32reg.open/1","ref":"win32reg.html#open/1"},{"type":"function","doc":"Sets the named (or default) value to `value`. Calls the Win32 API function\n`RegSetValueEx()`. The value can be of three types, and the corresponding\nregistry type is used. The supported types are the following:\n\n- `REG_DWORD` for integers\n- `REG_SZ` for strings\n- `REG_BINARY` for binaries\n\nOther types cannot be added or changed.\n\nThe registry must have been opened in write mode.","title":"win32reg.set_value/3","ref":"win32reg.html#set_value/3"},{"type":"function","doc":"Returns a list of subkeys to the current key. Calls the Win32 API function\n`EnumRegKeysEx()`.\n\nAvoid calling this on the root keys, as it can be slow.","title":"win32reg.sub_keys/1","ref":"win32reg.html#sub_keys/1"},{"type":"function","doc":"Retrieves the named value (or default) on the current key. Registry values of\ntype `REG_SZ` are returned as strings. Type `REG_DWORD` values are returned as\nintegers. All other types are returned as binaries.","title":"win32reg.value/2","ref":"win32reg.html#value/2"},{"type":"function","doc":"Retrieves a list of all values on the current key. The values have types\ncorresponding to the registry types, see `value/2`. Calls the Win32 API function\n`EnumRegValuesEx()`.","title":"win32reg.values/1","ref":"win32reg.html#values/1"},{"type":"type","doc":"","title":"win32reg.name/0","ref":"win32reg.html#t:name/0"},{"type":"opaque","doc":"As returned by `open/1`.","title":"win32reg.reg_handle/0","ref":"win32reg.html#t:reg_handle/0"},{"type":"type","doc":"","title":"win32reg.value/0","ref":"win32reg.html#t:value/0"},{"type":"behaviour","doc":"Generic event handling behavior.\n\nThis behavior module provides event handling functionality.\nIt consists of a generic event manager process with any number of\nevent handlers that are added and deleted dynamically.\n\nAn event manager implemented using this module has a standard set of\ninterface functions and includes functionality for tracing\nand error reporting. It also fits into an OTP supervision tree.\nFor more information, see [OTP Design Principles](`e:system:events.md`).\n\nEach event handler is implemented as a callback module\nexporting a predefined set of functions. The relationship between\nthe behavior functions and the callback functions is as follows:\n\n```text\ngen_event module Callback module\n---------------- ---------------\ngen_event:start\ngen_event:start_monitor\ngen_event:start_link -----> -\n\ngen_event:add_handler\ngen_event:add_sup_handler -----> Module:init/1\n\ngen_event:notify\ngen_event:sync_notify -----> Module:handle_event/2\n\ngen_event:send_request\ngen_event:call -----> Module:handle_call/2\n\n- -----> Module:handle_info/2\n\ngen_event:delete_handler -----> Module:terminate/2\n\ngen_event:swap_handler\ngen_event:swap_sup_handler -----> Module1:terminate/2\n Module2:init/1\n\ngen_event:which_handlers -----> -\n\ngen_event:stop -----> Module:terminate/2\n\n- -----> Module:code_change/3\n```\n\nAs each event handler is one callback module, an event manager\nhas many callback modules that are added and deleted dynamically.\n`gen_event` is therefore more tolerant of callback module errors\nthan the other behaviors. If a callback function for an installed\nevent handler fails with `Reason`, or returns a bad value `Term`,\nthe event manager does not fail. It deletes the event handler\nby calling callback function [`Module:terminate/2`](`c:terminate/2`),\ngiving as argument `{error, {'EXIT', Reason}}` or `{error, Term}`,\nrespectively. No other event handler is affected.\n\nA `gen_event` process handles system messages as described in `m:sys`.\nThe `sys` module can be used for debugging an event manager.\n\nNotice that an event manager _does_ trap exit signals automatically.\n\nThe `gen_event` process can go into hibernation\n(see `erlang:hibernate/3`) if a callback function in a handler module\nspecifies `hibernate` in its return value. This can be useful\nif the server is expected to be idle for a long time.\nHowever, use this feature with care, as hibernation implies\nat least two garbage collections (when hibernating\nand shortly after waking up) and is not something you want to do\nbetween each event handled by a busy event manager.\n\nNotice that when multiple event handlers are invoked,\nit is sufficient that one single event handler returns a `hibernate`\nrequest for the whole event manager to go into hibernation.\n\nUnless otherwise stated, all functions in this module fail\nif the specified event manager does not exist\nor if bad arguments are specified.\n\n> #### Note {: .info }\n>\n> For some important information about distributed signals, see the\n> [_Blocking Signaling Over Distribution_\n> ](`e:system:ref_man_processes.md#blocking-signaling-over-distribution`)\n> section in the _Processes_ chapter of the _Erlang Reference Manual_.\n> Blocking signaling can, for example, cause call timeouts in `gen_event`\n> to be significantly delayed.","title":"gen_event","ref":"gen_event.html"},{"type":"behaviour","doc":"`m:supervisor`, `m:sys`","title":"See Also - gen_event","ref":"gen_event.html#module-see-also"},{"type":"function","doc":"Add a new event handler to an event manager.\n\nThe new event handler is added to event manager `EventMgrRef`.\nThe event manager calls [`Module:init/1`](`c:init/1`)\nto initiate the event handler and its internal state.\n\n`Handler` is the name of the callback module `Module`\nor a tuple `{Module, Id}`, where `Id` is any term.\nThe `{Module, Id}` representation makes it possible to\nidentify a specific event handler, when many event handlers\nuse the same callback module.\n\n`Args` is any term that is passed as the argument to\n[`Module:init/1`](`c:init/1`).\n\nIf [`Module:init/1`](`c:init/1`) returns a correct value\nindicating successful completion, the event manager\nadds the event handler and this function returns `ok`.\nIf [`Module:init/1`](`c:init/1`) fails with `Reason` or returns\n`{error,Reason}`, the event handler is ignored and this function\nreturns `{'EXIT',Reason}` or `{error,Reason}`, respectively.","title":"gen_event.add_handler/3","ref":"gen_event.html#add_handler/3"},{"type":"function","doc":"Add a new event handler to an event manager, supervised.\n\nThe new event handler is added as for `add_handler/3`,\nbut the event manager also supervises the connection\nby linking the event handler and the calling process.\n\n- If the calling process later terminates with `Reason`,\n the event manager deletes any supervised event handlers by calling\n [`Module:terminate/2`](`c:terminate/2`), then calls\n [`Module:handle_info/2`](`c:handle_info/2`) for each remaining handler.\n\n- If the event handler is deleted later, the event manager\n sends a message `{gen_event_EXIT,Handler,Reason}`\n to the calling process. `Reason` is one of the following:\n\n + `normal`, if the event handler has been removed because of\n a call to [`delete_handler/3`](`delete_handler/3`),\n or `remove_handler` has been returned by a callback function\n (see below).\n + `shutdown`, if the event handler has been removed\n because the event manager is terminating.\n + `{swapped, NewHandler, Pid}`, if the process `Pid` has replaced\n the event handler with another event handler `NewHandler`,\n through a call to `swap_handler/3` or `swap_sup_handler/3`.\n + Other `t:term/0`, if the event handler is removed\n because of an error. Which term depends on the error.\n\nFor a description of the arguments and return values, see `add_handler/3`.","title":"gen_event.add_sup_handler/3","ref":"gen_event.html#add_sup_handler/3"},{"type":"function","doc":"","title":"gen_event.call/3","ref":"gen_event.html#call/3"},{"type":"function","doc":"Make a synchronous call to an event handler.\n\nThe call is sent to `Handler`, installed in event manager `EventMgrRef`,\nby sending a request and waiting until a reply arrives,\nor a time-out occurs. The event manager calls\n[`Module:handle_call/2`](`c:handle_call/2`) to handle the request.\n\n`Request` is any term that is passed as one of the arguments to\n[`Module:handle_call/2`](`c:handle_call/2`).\n\n`Timeout` is an integer greater than zero that specifies\nhow many milliseconds to wait for a reply, or the atom `infinity`\nto wait indefinitely. Defaults to 5000. If no reply is received\nwithin the specified time, the function call fails.\n\nThe return value `Reply` is defined in the return value of\n[`Module:handle_call/2`](`c:handle_call/2`). If the specified\nevent handler is not installed, the function returns\n`{error, bad_module}`. If the callback function fails with `Reason`,\nor returns an unexpected value `Term`, this function returns\n`{error, {'EXIT', Reason}}` or `{error, Term}`, respectively.\n\nWhen this call fails it [exits](`erlang:exit/1`) the calling process.\nThe exit term is on the form `{Reason, Location}` where\n`Location = {gen_event, call, ArgList}`. See `gen_server:call/3`\nthat has a description of relevant values for the `Reason`\nin the exit term.","title":"gen_event.call/4","ref":"gen_event.html#call/4"},{"type":"function","doc":"Check if a received message is a request response.\n\nCheck if `Msg` is a response corresponding to\nthe request identifier `ReqId`. The request must have been made\nby `send_request/3`, and by the same process calling this function.\n\nIf `Msg` is a response corresponding to `ReqId` the response is returned\nin `Reply`. Otherwise this function returns `no_reply`\nand no cleanup is done. Thus this function must be invoked repeatedly\nuntil a response is returned.\n\nIf the specified event handler is not installed, the function returns\n`{error, bad_module}`. If the callback function fails with `Reason`\nor returns an unexpected value `Term`, this function returns\n`{error, {'EXIT', Reason}}` or `{error, Term}`, respectively.\nIf the event manager has died before this function is called,\nthat is; `Msg` reports the server's death, this function returns\n`{error,{Reason, EventMgrRef}}` where `Reason` is the exit reason.","title":"gen_event.check_response/2","ref":"gen_event.html#check_response/2"},{"type":"function","doc":"Check if a received message is a request response in a collection.\n\nCheck if `Msg` is a response corresponding to a request identifier\nstored in `ReqIdCollection`. All request identifiers of `ReqIdCollection`\nmust correspond to requests that have been made using `send_request/3`\nor `send_request/5`, and all requests must have been made\nby the process calling this function.\n\nThe `Label` in the response is the `Label` associated with\nthe request identifier that the response corresponds to.\nThe `Label` of a request identifier is associated\nwhen [storing the request id](`reqids_add/3`) in a collection,\nor when sending the request using `send_request/5`.\n\nCompared to `check_response/2`, the returned result or exception\nassociated with a specific request identifier will be wrapped\nin a 3-tuple `{Response, Label, NewReqIdCollection}`.\n`Response` is the value that would have been produced\nby `check_response/2`, `Label` is the value associated with\nthe specific [request identifier](`t:request_id/0`)\nand `NewReqIdCollection` is a possibly modified\nrequest identifier collection.\n\nIf `ReqIdCollection` is empty, `no_request` will be returned.\n\nIf `Msg` does not correspond to any of the request identifiers\nin `ReqIdCollection`, `no_reply` is returned.\n\nIf `Delete` is `true`, the association with `Label` has been deleted\nfrom `ReqIdCollection` in the resulting `NewReqIdCollection`.\nIf `Delete` is `false`, `NewReqIdCollection` will equal `ReqIdCollection`.\nNote that deleting an association is not for free and that\na collection containing already handled requests\ncan still be used by subsequent calls to `check_response/3`),\n`receive_response/3`, and `wait_response/3`.\n\nHowever, without deleting handled associations, the above calls\nwill not be able to detect when there are no more outstanding requests\nto handle, so you will have to keep track of this some other way\nthan relying on a `no_request` return. Note that if you pass\na collection only containing associations of already handled\nor abandoned requests to `check_response/3`,\nit will always return `no_reply`.","title":"gen_event.check_response/3","ref":"gen_event.html#check_response/3"},{"type":"callback","doc":"Update the event handler state after code change.\n\nThis function is called for an installed event handler\nthat is to update its internal state during a release upgrade/downgrade,\nthat is, when the instruction `{update, Module, Change,...}`,\nis specified in the [`appup`](`e:sasl:appup.md`) file.\n\nFor more information, see [OTP Design Principles](`e:system:index.html`).\n\nFor an upgrade, `OldVsn` is `Vsn`, and for a downgrade,\n`OldVsn` is `{down, Vsn}`. `Vsn` is defined by the `vsn` attribute(s)\nof the old version of the callback module `Module`. If no such attribute\nis defined, the version is the checksum of the Beam file.\n\n`State` is the internal state of the event handler.\n\n`Extra` is passed \"as is\" from the `{advanced, Extra}` part\nof the update instruction.\n\nThe function is to return the updated internal state.\n\n> #### Note {: .info }\n>\n> If a release upgrade/downgrade with `Change={advanced, Extra}`\n> specified in the [`.appup`](`e:sasl:appup.md`) file is made\n> when `c:code_change/3` is not implemented the event handler will crash\n> with an `undef` error reason.","title":"gen_event.code_change/3","ref":"gen_event.html#c:code_change/3"},{"type":"function","doc":"Deletes an event handler from an event manager.\n\nThis function deletes event handler `Handler` from event manager\n`EventMgrRef`. The event manager calls\n[`Module:terminate/2`](`c:terminate/2`) to terminate the event handler.\n\n`Args` is any term that is passed as one of the arguments to\n[`Module:terminate/2`](`c:terminate/2`).\n\nThe return value is the return value of\n[`Module:terminate/2`](`c:terminate/2`). If the specified\nevent handler is not installed, the function returns\n`{error, module_not_found}`. If the callback function fails\nwith `Reason`, the function returns `{'EXIT', Reason}`.","title":"gen_event.delete_handler/3","ref":"gen_event.html#delete_handler/3"},{"type":"callback","doc":"Format/limit the status value.\n\nThis function is called by a `gen_event` process in in order to\nformat/limit the server state for debugging and logging purposes.\n\nIt is called in the following situations:\n\n- One of [`sys:get_status/1,2`](`sys:get_status/1`) is invoked\n to get the `gen_event` status.\n\n- The event handler terminates abnormally and `gen_event` logs an error.\n\nThis callback is used to limit the status of the event handler returned by\n[`sys:get_status/1,2`](`sys:get_status/1`) or sent to `m:logger`.\n\nThe callback gets a map `Status` describing the current status\nand shall return a map `NewStatus` with the same keys,\nbut it may transform some values.\n\nTwo possible use cases for this callback is to remove\nsensitive information from the state to prevent it from being printed\nin log files, or to compact large irrelevant status items\nthat would only clutter the logs.\n\n_Example_:\n\n```erlang\nformat_status(Status) ->\n maps:map(\n fun(state,State) ->\n maps:remove(private_key, State);\n (message,{password, _Pass}) ->\n {password, removed};\n (_,Value) ->\n Value\n end, Status).\n```\n\n> #### Note {: .info }\n>\n> This callback is optional, so event handler modules need not export it.\n> If a handler does not export this function, the `gen_event` module\n> uses the handler state directly for the purposes described below.\n>\n> If this callback is exported but fails, to hide possibly sensitive data,\n> the default function will instead return the fact that\n> [`format_status/1`](`c:format_status/1`) has crashed.","title":"gen_event.format_status/1","ref":"gen_event.html#c:format_status/1"},{"type":"callback","doc":"Format/limit the status value.\n\nThis function is called by a `gen_event` process in in order to\nformat/limit the server state for debugging and logging purposes.\n\nIt is called in the following situations:\n\n- One of [`sys:get_status/1,2`](`sys:get_status/1`) is invoked\n to get the `gen_event` status. `Opt` is set to the atom `normal`\n for this case.\n\n- The event handler terminates abnormally and `gen_event` logs an error.\n `Opt` is set to the atom `terminate` for this case.\n\nThis function is useful for changing the form and appearance of the event\nhandler state for these cases. An event handler callback module\nwishing to change the `sys:get_status/1,2` return value as well as\nhow its state appears in termination error logs, exports an instance of\n[`format_status/2`](`c:format_status/2`) that returns a term\ndescribing the current state of the event handler.\n\n`PDict` is the current value of the process dictionary of `gen_event`.\n\n`State` is the internal state of the event handler.\n\nThe function is to return `Status`, a term that change the details of\nthe current state of the event handler. Any term is allowed for `Status`.\nThe `gen_event` module uses `Status` as follows:\n\n- When `sys:get_status/1,2` is called, `gen_event` ensures that\n its return value contains `Status` in place of the state term\n of the event handler.\n\n- When an event handler terminates abnormally, `gen_event` logs `Status`\n in place of the state term of the event handler.\n\nOne use for this function is to return compact alternative\nstate representations to avoid that large state terms\nare printed in log files.\n\n> #### Note {: .info }\n>\n> This callback is optional, so event handler modules need not export it.\n> If a handler does not export this function, the `gen_event` module\n> uses the handler state directly for the purposes described below.","title":"gen_event.format_status/2","ref":"gen_event.html#c:format_status/2"},{"type":"callback","doc":"Handle a call.\n\nWhenever an event manager receives a request sent using\n[`call/3,4`](`call/3`), this function is called\nfor the specified event handler to handle the request.\n\n`Request` is the `Request` argument of `call/3,4`.\n\n`State` is the internal state of the event handler.\n\nThe return values are the same as for\n[`Module:handle_event/2`](`c:handle_event/2`) except that\nthey also contain a term `Reply`, which is the reply to the client\nas the return value of `call/3,4`.","title":"gen_event.handle_call/2","ref":"gen_event.html#c:handle_call/2"},{"type":"callback","doc":"Handle an event.\n\nWhenever an event manager receives an event sent using `notify/2` or\n`sync_notify/2`, this function is called for each installed event handler\nto handle the event.\n\n`Event` is the `Event` argument of `notify/2` / `sync_notify/2`.\n\n`State` is the internal state of the event handler.\n\n- If `{ok, NewState}` or `{ok, NewState, hibernate}` is returned,\n the event handler remains in the event manager with the possibly\n updated internal state `NewState`.\n\n- If `{ok, NewState, hibernate}` is returned, the event manager\n also goes into hibernation (by calling `proc_lib:hibernate/3`),\n waiting for the next event to occur. It is sufficient\n that one of the event handlers return `{ok, NewState, hibernate}`\n for the whole event manager process to hibernate.\n\n- If `{swap_handler, Args1, NewState, Handler2, Args2}` is returned,\n the event handler is replaced by `Handler2` by first calling\n [`Module:terminate(Args1, NewState)`](`c:terminate/2`) and then\n [`Module2:init({Args2, Term})`](`c:init/1`), where `Term`\n is the return value of [`Module:terminate/2`](`c:terminate/2`).\n For more information, see `swap_handler/3`.\n\n- If `remove_handler` is returned, the event handler is deleted by calling\n [`Module:terminate(remove_handler, State)`](`c:terminate/2`).","title":"gen_event.handle_event/2","ref":"gen_event.html#c:handle_event/2"},{"type":"callback","doc":"Handle an info message (regular process message).\n\nThis function is called for each installed event handler when\nan event manager receives any other message than an event\nor a synchronous request (or a system message).\n\n`Info` is the received message.\n\nIn particular, this callback will be made when a process terminated\nafter calling `add_sup_handler/3`. Any event handler attached to\nan event manager which in turn has a supervised handler\nshould expect callbacks of the shape\n[`Module:handle_info({'EXIT', Pid, Reason}, State)`](`c:handle_info/2`).\n\nFor a description of `State` and possible return values,\nsee [`Module:handle_event/2`](`c:handle_event/2`).\n\n> #### Note {: .info }\n>\n> This callback is optional, so callback modules need not export it.\n> The `gen_event` module provides a default implementation\n> of this function that logs about the unexpected `Info` message,\n> drops it and returns `{ok, State}`.","title":"gen_event.handle_info/2","ref":"gen_event.html#c:handle_info/2"},{"type":"callback","doc":"Initialize the event handler.\n\nWhenever a new event handler is added to an event manager,\nthis function is called to initialize the event handler.\n\nIf the event handler is added because of a call to `add_handler/3` or\n`add_sup_handler/3`, `InitArgs` is the `Args` argument of these functions.\n\nIf the event handler replaces another event handler because of\na call to `swap_handler/3` or `swap_sup_handler/3`, or because of\na `swap` return tuple from one of the other callback functions,\n`InitArgs` is a tuple `{Args, Term}`, where `Args` is the argument\nprovided in the function call/return tuple and `Term` is the result\nof terminating the old event handler, see `swap_handler/3`.\n\nIf successful, the function returns `{ok, State}` or\n`{ok, State, hibernate}`, where `State` is the initial internal state\nof the event handler.\n\nIf `{ok, State, hibernate}` is returned, the event manager\ngoes into hibernation (by calling `proc_lib:hibernate/3`),\nwaiting for the next event to occur.","title":"gen_event.init/1","ref":"gen_event.html#c:init/1"},{"type":"function","doc":"Send an asynchronous event notification to an event manager.\n\nThe event is sent to `EventMgrRef`, that calls\n[`Module:handle_event/2`](`c:handle_event/2`) for each installed\nevent handler to handle the event.\n\n`Event` is any term that is passed as one of the arguments to\n[`Module:handle_event/2`](`c:handle_event/2`).\n\n`notify/1` does not fail even if the specified event manager\ndoes not exist, unless it is specified as `Name`.","title":"gen_event.notify/2","ref":"gen_event.html#notify/2"},{"type":"function","doc":"Receive a request response.\n\nReceive a response corresponding to the request identifier `ReqId`.\nThe request must have been made by `send_request/3`,\nand it must have been made from the same process calling this function.\n\n`Timeout` specifies how long to wait for a response.\nIf no response is received within the specified time,\nthis function returns `timeout`. Assuming that the\nserver executes on a node supporting aliases (introduced in OTP 24)\nthe request will also be abandoned. That is,\nno response will be received after a timeout.\nOtherwise, a stray response might be received at a later time.\n\nThe return value `Reply` is defined in the return value of\n[`Module:handle_call/2`](`c:handle_call/2`).\n\nIf the specified event handler is not installed, this function returns\n`{error, bad_module}`. If the callback function fails\nwith `Reason` or returns an unexpected value `Term`,\nthis function returns `{error, {'EXIT', Reason}}` or`{error,Term}`,\nrespectively. If the event manager dies before or during the\nrequest this function returns `{error, {Reason, EventMgrRef}}`.\n\nThe difference between `wait_response/2` and `receive_response/2`\nis that `receive_response/2` abandons the request at time-out\nso that a potential future response is ignored,\nwhile [`wait_response/2`](`wait_response/2`) does not.","title":"gen_event.receive_response/2","ref":"gen_event.html#receive_response/2"},{"type":"function","doc":"Receive a request response in a collection.\n\nReceive a response in `ReqIdCollection`. All request identifiers\nof `ReqIdCollection` must correspond to requests that have been\nmade using `send_request/3` or `send_request/5`, and all requests\nmust have been made by the process calling this function.\n\nThe `Label` in the response is the `Label` associated with\nthe request identifier that the response corresponds to.\nThe `Label` of a request identifier is associated\nwhen [adding the request id](`reqids_add/3`) to a collection,\nor when sending the request using `send_request/5`.\n\nCompared to `receive_response/2`, the returned result or exception\nassociated with a specific request identifier will be wrapped\nin a 3-tuple `{Response, Label, NewReqIdCollection}`.\n`Response` is the value that would have been produced\nby `receive_response/2`, `Label` is the value associated with\nthe specific [request identifier](`t:request_id/0`)\nand `NewReqIdCollection` is a possibly modified\nrequest identifier collection.\n\nIf `ReqIdCollection` is empty, `no_request` will be returned.\n\n`Timeout` specifies how long to wait for a response. If no response\nis received within the specified time, the function returns `timeout`.\nAssuming that the server executes on a node supporting aliases\n(introduced in OTP 24) all requests identified by `ReqIdCollection`\nwill also be abandoned. That is, no responses will be received\nafter a time-out. Otherwise, stray responses might be received\nat a later time.\n\nThe difference between `receive_response/3` and `wait_response/3`\nis that `receive_response/3` abandons the requests at time-out\nso that potential future responses are ignored,\nwhile `wait_response/3` does not.\n\nIf `Delete` is `true`, the association with `Label`\nis deleted from `ReqIdCollection` in the resulting\n`NewReqIdCollection`. If `Delete` is `false`, `NewReqIdCollection`\nwill equal `ReqIdCollection`. Note that deleting an association\nis not for free and that a collection containing already handled\nrequests can still be used by subsequent calls to\n`receive_response/3`, `check_response/3`, and `wait_response/3`.\n\nHowever, without deleting handled associations,\nthe above calls will not be able to detect when there are\nno more outstanding requests to handle, so you will have to keep track\nof this some other way than relying on a `no_request` return.\nNote that if you pass a collection only containing\nassociations of already handled or abandoned requests to\n`receive_response/3`, it will always block until `Timeout` expires\nand then return `timeout`.","title":"gen_event.receive_response/3","ref":"gen_event.html#receive_response/3"},{"type":"function","doc":"Store a request identifier in a colletion.\n\nStores `ReqId` and associates a `Label` with the request identifier\nby adding this information to `ReqIdCollection` and returning\nthe resulting request identifier collection.","title":"gen_event.reqids_add/3","ref":"gen_event.html#reqids_add/3"},{"type":"function","doc":"Create an empty request identifier collection.\n\nReturns a new empty request identifier collection.\nA request identifier collection can be utilized to handle\nmultiple outstanding requests.\n\nRequest identifiers of requests made by `send_request/3`\ncan be saved in a request identifier collection using `reqids_add/3`.\nSuch a collection of request identifiers can later be used\nin order to get one response corresponding to a request\nin the collection by passing the collection as argument to\n`receive_response/3`, `wait_response/3`, or, `check_response/3`.\n\n`reqids_size/1` can be used to determine the number of\nrequest identifiers in a collection.","title":"gen_event.reqids_new/0","ref":"gen_event.html#reqids_new/0"},{"type":"function","doc":"Returns the number of request identifiers in `ReqIdCollection`.","title":"gen_event.reqids_size/1","ref":"gen_event.html#reqids_size/1"},{"type":"function","doc":"Convert a request identifier collection to a list.\n\nReturns a list of `{ReqId, Label}` tuples which corresponds to\nall request identifiers with their associated labels\nin [`ReqIdCollection`](`t:request_id_collection/0`).","title":"gen_event.reqids_to_list/1","ref":"gen_event.html#reqids_to_list/1"},{"type":"function","doc":"Send an asynchronous `call` request to an event handler.\n\nThis function sends the call request `Request` to the event handler\n`Handler` installed in the event manager identified by `EventMgrRef`,\nand returns a request identifier `ReqId`. The return value `ReqId`\nshall later be used with `receive_response/2`, `wait_response/2`,\nor `check_response/2` to fetch the actual result of the request.\n\nBesides passing the request identifier directly to these functions,\nit can also be stored in a request identifier collection\nusing `reqids_add/3`. Such a collection of request identifiers\ncan later be used in order to get one response corresponding to\na request in the collection by passing the collection as argument to\n`receive_response/3`, `wait_response/3`, or `check_response/3`.\nIf you are about to store the request identifier in a collection,\nyou may want to consider using `send_request/5` instead.\n\nThe calls\n`gen_event:receive_response(gen_event:send_request(EventMgrRef,\nHandler, Request), Timeout)`\ncan be seen as equivalent to\n[`gen_event:call(EventMgrRef, Handler, Request, Timeout)`](`call/3`),\nignoring the error handling.\n\nThe event manager calls [`Module:handle_call/2`](`c:handle_call/2`)\nto handle the request.\n\n`Request` may be any term and is passed as one of the arguments to\n[`Module:handle_call/2`](`c:handle_call/2`).","title":"gen_event.send_request/3","ref":"gen_event.html#send_request/3"},{"type":"function","doc":"Send an asynchronous `call` request to an event handler,\nstoring it in a request identifier collection.\n\nThis function sends the call request `Request` to the event handler\n`Handler` installed in the event manager identified by `EventMgrRef`.\nThe `Label` will be associated with the request identifier\nof the operation and added to the returned\nrequest identifier collection `NewReqIdCollection`.\n\nThe collection can later be used in order to get one response\ncorresponding to a request in the collection by passing the collection\nas argument to `receive_response/3`, `wait_response/3`,\nor `check_response/3`.\n\nThe same as calling\n[`gen_event:reqids_add`](`reqids_add/3`)`(`[`gen_event:send_request`](`send_request/3`)`(EventMgrRef, Handler, Request), Label, ReqIdCollection)`,\nbut slightly more efficient.","title":"gen_event.send_request/5","ref":"gen_event.html#send_request/5"},{"type":"function","doc":"","title":"gen_event.start/0","ref":"gen_event.html#start/0"},{"type":"function","doc":"Create a stand-alone event manager process, possibly nameless.\n\nEquivalent to [`start(EventMgrName, Options)`](`start/2`).\n\nWith argument `EventMgrName`, `Options` is `[]`.\n\nWith argument `Options` a nameless event manager is created.\n\nFor a description of the arguments and return values, see `start_link/2`.","title":"gen_event.start/1","ref":"gen_event.html#start/1"},{"type":"function","doc":"Create a stand-alone event manager process.\n\nThe created event manager process is not part of a supervision tree\nand thus has no supervisor.\n\nFor a description of the arguments and return values, see `start_link/2`.","title":"gen_event.start/2","ref":"gen_event.html#start/2"},{"type":"function","doc":"","title":"gen_event.start_link/0","ref":"gen_event.html#start_link/0"},{"type":"function","doc":"Create an event manager process as part of a supervision tree,\npossibly nameless.\n\nEquivalent to [`start_link(EventMgrName, Options)`](`start_link/2`).\n\nWith argument `EventMgrName`, `Options` is `[]`.\n\nWith argument `Options` a nameless event manager is created.\n\nFor a description of the arguments and return values, see `start_link/2`.","title":"gen_event.start_link/1","ref":"gen_event.html#start_link/1"},{"type":"function","doc":"Create an event manager process as part of a supervision tree.\n\nThe function is to be called, directly or indirectly, by the supervisor.\nFor example, it ensures that the event manager is linked\nto the caller (supervisor).\n\n- If option `{hibernate_after, HibernateAfterTimeout}` is present, the\n `gen_event` process awaits any message for `HibernateAfterTimeout`\n milliseconds and if no message is received, the process\n goes into hibernation automatically (by calling `proc_lib:hibernate/3`).\n\nIf the event manager is successfully created,\nthe function returns `{ok, Pid}` where `Pid` is the `t:pid/0`\nof the event manager.\n\nIf a process with the specified `EventMgrName` exists already,\nthe function returns `{error,{already_started,OtherPid}}`,\nwhere `OtherPid` is the pid of that process, and the event manager process\nexits with reason `normal`.\n\nIf the event manager fails to start within the specified start timeout\n`{timeout, Time}`, which is very unlikely since the start\ndoes not interact with other processes, the function returns\n`{error, timeout}` and the failed event manager is killed with\n[`exit(_, kill)`](`erlang:exit/2`).\n\nIf `start_link/1,2` returns `{error, _}`, the started event manager process\nhas terminated. If an `'EXIT'` message was delivered\nto the calling process (due to the process link), that message\nhas been consumed.\n\n> #### Warning {: .warning }\n>\n> Before OTP 26.0, if the started event manager failed to register\n> its name, this founction could return\n> `{error, {already_started, OtherPid}}` _before_\n> the started event manager process had terminated,\n> so starting again might fail because the registered name\n> was not yet unregistered, and an `'EXIT'` message could arrive later\n> to the process calling this function.\n>\n> But if the start timed out, this function killed\n> the started event manager process and returned `{error, timeout}`,\n> and then the process link `{'EXIT', Pid, killed}` message _was_ consumed.\n>\n> The start was made synchronous in OTP 26.0 and a guarantee\n> was implemented that no process link `'EXIT'` message\n> from a failed start will linger in the caller's inbox.","title":"gen_event.start_link/2","ref":"gen_event.html#start_link/2"},{"type":"function","doc":"","title":"gen_event.start_monitor/0","ref":"gen_event.html#start_monitor/0"},{"type":"function","doc":"Creates a stand-alone event manager process,\nmonitored, possibly nameless.\n\nEquivalent to [`start_monitor(EventMgrName, Options)`](`start_monitor/2`).\n\nWith argument `EventMgrName`, `Options` is `[]`.\n\nWith argument `Options` a nameless event manager is created.\n\nFor a description of the arguments and return values,\nsee `start_monitor/2` and `start_link/1`.","title":"gen_event.start_monitor/1","ref":"gen_event.html#start_monitor/1"},{"type":"function","doc":"Creates a stand-alone event manager process, monitored.\n\nThe created event manager process is not part of a supervision tree\nand thus has no supervisor. A monitor is atomically set up\nto the newly created process.\n\nFor a description of the arguments and return values, see\n[`start_link/2`](`start_link/2`). Note that the return value\nfor a successful start differs from `start_link/2`.\n`start_monitor/0,1,2` will return `{ok, {Pid, Mon}}`\nwhere `Pid` is the process identifier of the process,\nand `Mon` is a reference to the monitor set up to monitor the process.\nIf the start is not successful, the caller will be blocked\nuntil the `DOWN` message has been received and removed\nfrom the message queue.","title":"gen_event.start_monitor/2","ref":"gen_event.html#start_monitor/2"},{"type":"function","doc":"","title":"gen_event.stop/1","ref":"gen_event.html#stop/1"},{"type":"function","doc":"Stop an event manager.\n\nOrders event manager `EventMgrRef` to exit with the specifies `Reason`,\nand waits for it to terminate. Before terminating, `gen_event` calls\n[`Module:terminate(stop,...)`](`c:terminate/2`)\nfor each installed event handler.\n\nThe function returns `ok` if the event manager terminates\nwith the expected reason. Any other reason than `normal`,\n`shutdown`, or `{shutdown, Term}` causes an error report\nto be issued using `m:logger`.\n\n`Timeout` is an integer greater than zero that specifies\nhow many milliseconds to wait for the event manager to terminate,\nor the atom `infinity` to wait indefinitely. If the event manager\nhas not terminated within the specified time, the call exits\nthe calling process with reason `timeout`.\n\nIf the process does not exist,\nthe call exits the calling process with reason `noproc`,\nand with reason `{nodedown, Node}` if the connection fails\nto the remote `Node` where the server runs.","title":"gen_event.stop/3","ref":"gen_event.html#stop/3"},{"type":"function","doc":"Replace an event handler.\n\nThis function replaces an event handler in event manager `EventMgrRef`.\n\nFor a description of `OldHandler` and `NewHandler`, see `add_handler/3`.\n\nFirst the old event handler `OldHandler` is deleted. The event manager\ncalls `OldModule:terminate(Args1, ...)`, where `OldModule`\nis the callback module of `OldHandler`, and collects the return value.\n\nThen the new event handler `NewHandler` is added and initiated\nby calling [`NewModule:init({Args2,Term})`](`c:init/1`), where `NewModule`\nis the callback module of `NewHandler`, and `Term` is the return value\nof [`OldModule:terminate/2`](`c:terminate/2`). This makes it possible\nto transfer information from `OldHandler` to `NewHandler`.\n\nThe new handler is added even if the the specified old event handler\nis not installed, in which case `Term = error`, or if\n[`OldModule:terminate/2`](`c:terminate/2`) fails with `Reason`,\nin which case `Term = {'EXIT', Reason}`. The old handler\nis deleted even if [`NewModule:init/1`](`c:init/1`) fails.\n\nIf there was a supervised connection\nbetween `OldHandler` and a process `Pid`,\nthere is a supervised connection between `NewHandler` and `Pid` instead.\n\nIf [`NewModule:init/1`](`c:init/1`) returns a correct value,\nthis function returns `ok`. If [`NewModule:init/1`](`c:init/1`) fails\nwith `Reason` or returns an unexpected value `Term`,\nthis function returns `{error, {'EXIT', Reason}}` or\n`{error, Term}`, respectively.","title":"gen_event.swap_handler/3","ref":"gen_event.html#swap_handler/3"},{"type":"function","doc":"Replace an event handler, and supervise it.\n\nReplaces an event handler in event manager `EventMgrRef`\nin the same way as [`swap_handler/3`](`swap_handler/3`),\nbut also supervises the connection between `NewHandler`\nand the calling process.\n\nFor a description of the arguments and return values, see `swap_handler/3`.","title":"gen_event.swap_sup_handler/3","ref":"gen_event.html#swap_sup_handler/3"},{"type":"function","doc":"Send a synchronous event notification to an event manager.\n\nThe event is sent to `EventMgrRef` that callsr calls\n[`Module:handle_event/2`](`c:handle_event/2`) for each installed\nevent handler to handle the event. This function will return `ok`\nafter the event has been handled by all event handlers.\n\n`Event` is any term that is passed as one of the arguments to\n[`Module:handle_event/2`](`c:handle_event/2`).","title":"gen_event.sync_notify/2","ref":"gen_event.html#sync_notify/2"},{"type":"callback","doc":"Handle event handler termination.\n\nWhenever an event handler is deleted from an event manager,\nthis function is called. It is to be the opposite\nof [`Module:init/1`](`c:init/1`) and do any necessary cleaning up.\n\nIf the event handler is deleted because of a call to `delete_handler/3`,\n`swap_handler/3`, or `swap_sup_handler/3`, `Arg` is\nthe `Args` argument of this function call.\n\n`Arg = {stop, Reason}` if the event handler has a supervised connection\nto a process that has terminated with reason `Reason`.\n\n`Arg = stop` if the event handler is deleted because\nthe event manager is terminating.\n\nThe event manager terminates if it is part of a supervision tree\nand it is ordered by its supervisor to terminate. Even if\nit is _not_ part of a supervision tree, it terminates if it receives\nan `'EXIT'` message from its parent.\n\n`Arg = remove_handler` if the event handler is deleted\nbecause another callback function has returned `remove_handler`\nor `{remove_handler, Reply}`.\n\n`Arg = {error, Term}` if the event handler is deleted because\na callback function returned an unexpected value `Term`,\nor `Arg = {error, {'EXIT', Reason}}` if a callback function failed.\n\n`State` is the internal state of the event handler.\n\nThe function can return any term. If the event handler\nis deleted because of a call to `gen_event:delete_handler/3`,\nthe return value of that function becomes the return value\nof this function. If the event handler is to be replaced with\nanother event handler because of a swap, the return value\nis passed to the `init` function of the new event handler.\nOtherwise the return value is ignored.\n\n> #### Note {: .info }\n>\n> This callback is optional, so callback modules need not export it.\n> The `gen_event` module provides a default implementation\n> without cleanup.","title":"gen_event.terminate/2","ref":"gen_event.html#c:terminate/2"},{"type":"function","doc":"Wait for a request resonse.\n\nWait for the response to the request identifier `ReqId`. The request\nmust have been made by `send_request/3`, from the same process\nthat called `send_request/3`.\n\n`WaitTime` specifies how long to wait for a response.\nIf no response is received within the specified time,\nthe function returns `timeout` and no cleanup is done,\nThus the function can be invoked repeatedly until a reply is returned.\n\nThe return value `Reply` is defined in the return value of\n[`Module:handle_call/2`](`c:handle_call/2`).\n\nIf the specified event handler is not installed, the function returns\n`{error, bad_module}`. If the callback function fails with `Reason`,\nor returns an unexpected value `Term`, this function returns\n`{error,{'EXIT',Reason}}` or `{error,Term}`, respectively.\nIf the event manager dies before or during the request\nthis function returns `{error, {Reason, EventMgrRef}}`.\n\nThe difference between `receive_response/2` and\n`wait_response/2` is that `receive_response/2` abandons the request\nat timeout so that a potential future response is ignored,\nwhile [`wait_response/2`](`wait_response/2`) does not.","title":"gen_event.wait_response/2","ref":"gen_event.html#wait_response/2"},{"type":"function","doc":"Wait for any request response in a collection.\n\nWait for a response in a `ReqIdCollection`. All request identifiers\nof `ReqIdCollection` must correspond to requests that have been made\nusing `send_request/3` or `send_request/5`, and all requests\nmust have been made by the process calling this function.\n\nThe `Label` in the response is the `Label` associated with\nthe request identifier that the response corresponds to.\nThe `Label` of a request identifier is associated\nwhen [adding the request id](`reqids_add/3`) to a collection,\nor when sending the request using `send_request/5`.\n\nCompared to `wait_response/2`, the returned result or exception\nassociated with a specific request identifier will be wrapped\nin a 3-tuple `{Response, Label, NewReqIdCollection}`.\n`Response` is the value that would have been produced\nby `wait_response/2`, `Label` is the value associated with\nthe specific [request identifier](`t:request_id/0`)\nand `NewReqIdCollection` is a possibly modified\nrequest identifier collection.\n\nIf `ReqIdCollection` is empty, `no_request` will be returned.\n\nIf no response is received before the `WaitTime` has expired,\n`timeout` is returned. It is valid to continue waiting\nfor a response as many times as needed up until a response\nhas been received and completed by `check_response()`,\n`receive_response()`, or `wait_response()`.\n\nThe difference between `receive_response/3` and `wait_response/3`\nis that `receive_response/3` abandons requests at time-out\nso that potential future responses are ignored, while\n[`wait_response/3`](`wait_response/3`) does not.\n\nIf `Delete` is `true`, the association with `Label`\nhas been deleted from `ReqIdCollection` in the resulting\n`NewReqIdCollection`. If `Delete` is`false`, `NewReqIdCollection`\nwill equal `ReqIdCollection`. Note that deleting an association\nis not for free and that a collection containing already handled\nrequests can still be used by subsequent calls to\n`wait_response/3`, `check_response/3`, and `receive_response/3`.\n\nHowever, without deleting handled associations, the above\ncalls will not be able to detect when there are\nno more outstanding requests to handle, so you will have to keep track\nof this some other way than relying on a `no_request` return.\nNote that if you pass a collection only containing\nassociations of already handled or abandoned requests\nto this function, it will always block until `WaitTime` expires\nand then return `timeout`.","title":"gen_event.wait_response/3","ref":"gen_event.html#wait_response/3"},{"type":"function","doc":"Return all event handlers in an event manager.\n\nThis function returns a list of all event handlers\ninstalled in event manager `EventMgrRef`.\n\nFor a description of `Handler`, see `add_handler/3`.","title":"gen_event.which_handlers/1","ref":"gen_event.html#which_handlers/1"},{"type":"type","doc":"","title":"gen_event.add_handler_ret/0","ref":"gen_event.html#t:add_handler_ret/0"},{"type":"type","doc":"","title":"gen_event.debug_flag/0","ref":"gen_event.html#t:debug_flag/0"},{"type":"type","doc":"","title":"gen_event.del_handler_ret/0","ref":"gen_event.html#t:del_handler_ret/0"},{"type":"type","doc":"Event manager name specification: `local`, `global`, or `via` registered.\n\n- *`{local, Name}`* - the event manager is registered locally as\n `Name` using [`register/2`](`register/2`).\n- *`{global, GlobalName}`* - The event manager is registered\n globally as `GlobalName` using `global:register_name/2`.\n If no name is provided, the event manager is not registered.\n- *`{via, Module, ViaName}`*, the event manager registers with the\n registry represented by `Module`. The `Module` callback is to export\n the functions `register_name/2`, `unregister_name/1`, `whereis_name/1`,\n and `send/2`, which are to behave as the corresponding functions\n in `m:global`. Thus, `{via, global, GlobalName}` is a valid reference.","title":"gen_event.emgr_name/0","ref":"gen_event.html#t:emgr_name/0"},{"type":"type","doc":"A reference used to locate an event manager.\n\nThe reference can be any of the following:\n\n- The pid of the event manager\n- `Name`, if the event manager is locally registered\n- `{Name, Node}`, if the event manager is locally registered\n at another node\n- `{global, GlobalName}`, if the event manager is globally registered\n- `{via, Module, ViaName}`, if the event manager is registered through\n an alternative process registry","title":"gen_event.emgr_ref/0","ref":"gen_event.html#t:emgr_ref/0"},{"type":"type","doc":"A map that describes the `gen_event` process status.\n\nThe keys are:\n- **`state`** - The internal state of the event handler.\n- **`message`** - The message that caused the event handler to terminate.\n- **`reason`** - The reason that caused the event handler to terminate.\n- **`log`** - The [sys log](`sys:log/2`) of the server.\n\nNew associations may be added into the status map without prior notice.","title":"gen_event.format_status/0","ref":"gen_event.html#t:format_status/0"},{"type":"type","doc":"","title":"gen_event.handler/0","ref":"gen_event.html#t:handler/0"},{"type":"type","doc":"","title":"gen_event.handler_args/0","ref":"gen_event.html#t:handler_args/0"},{"type":"type","doc":"Options that can be used to configure an event handler\nwhen it is started.","title":"gen_event.options/0","ref":"gen_event.html#t:options/0"},{"type":"opaque","doc":"An opaque request identifier. See `send_request/3` for details.","title":"gen_event.request_id/0","ref":"gen_event.html#t:request_id/0"},{"type":"opaque","doc":"An opaque collection of request identifiers (`t:request_id/0`).\n\nEach request identifier can be associated with a label\nchosen by the user. For more information see `reqids_new/0`.","title":"gen_event.request_id_collection/0","ref":"gen_event.html#t:request_id_collection/0"},{"type":"type","doc":"Response time-out for an asynchronous call.\n\nUsed to set a time limit on how long to wait for a response using either\n`receive_response/2`, `receive_response/3`, `wait_response/2`, or\n`wait_response/3`. The time unit used is `millisecond`.\nCurrently valid values:\n\n- **`0..4294967295`** - Timeout relative to current time in milliseconds.\n\n- **`infinity`** - Infinite timeout. That is, the operation\n will never time out.\n\n- **`{abs, Timeout}`** - An absolute\n [Erlang monotonic time](`erlang:monotonic_time/1`) timeout\n in milliseconds. That is, the operation will time out when\n [`erlang:monotonic_time(millisecond)`](`erlang:monotonic_time/1`)\n returns a value larger than or equal to `Timeout`.\n `Timeout` is not allowed to identify a time further into the future\n than `4294967295` milliseconds. Identifying the timeout using\n an absolute timeout value is especially handy when you have a\n deadline for responses corresponding to a complete collection\n of requests (`t:request_id_collection/0`) , since you do not have to\n recalculate the relative time until the deadline over and over again.","title":"gen_event.response_timeout/0","ref":"gen_event.html#t:response_timeout/0"},{"type":"type","doc":"","title":"gen_event.start_mon_ret/0","ref":"gen_event.html#t:start_mon_ret/0"},{"type":"type","doc":"","title":"gen_event.start_ret/0","ref":"gen_event.html#t:start_ret/0"},{"type":"behaviour","doc":"Deprecated and replaced by `m:gen_statem` in OTP 20.\n\nMigration to gen_statem\n-----------------------\n\nHere follows a simple example of turning a gen_fsm into a `m:gen_statem`.\nThe example comes from the previous User's Guide for `gen_fsm`\n\n```erlang\n-module(code_lock).\n-define(NAME, code_lock).\n%-define(BEFORE_REWRITE, true).\n\n-ifdef(BEFORE_REWRITE).\n-behaviour(gen_fsm).\n-else.\n-behaviour(gen_statem).\n-endif.\n\n-export([start_link/1, button/1, stop/0]).\n\n-ifdef(BEFORE_REWRITE).\n-export([init/1, locked/2, open/2, handle_sync_event/4, handle_event/3,\n handle_info/3, terminate/3, code_change/4]).\n-else.\n-export([init/1, callback_mode/0, locked/3, open/3,\n terminate/3, code_change/4]).\n%% Add callback__mode/0\n%% Change arity of the state functions\n%% Remove handle_info/3\n-endif.\n\n-ifdef(BEFORE_REWRITE).\nstart_link(Code) ->\n gen_fsm:start_link({local, ?NAME}, ?MODULE, Code, []).\n-else.\nstart_link(Code) ->\n gen_statem:start_link({local,?NAME}, ?MODULE, Code, []).\n-endif.\n\n-ifdef(BEFORE_REWRITE).\nbutton(Digit) ->\n gen_fsm:send_event(?NAME, {button, Digit}).\n-else.\nbutton(Digit) ->\n gen_statem:cast(?NAME, {button,Digit}).\n %% send_event is asynchronous and becomes a cast\n-endif.\n\n-ifdef(BEFORE_REWRITE).\nstop() ->\n gen_fsm:sync_send_all_state_event(?NAME, stop).\n-else.\nstop() ->\n gen_statem:call(?NAME, stop).\n %% sync_send is synchronous and becomes call\n %% all_state is handled by callback code in gen_statem\n-endif.\n\ninit(Code) ->\n do_lock(),\n Data = #{code => Code, remaining => Code},\n {ok, locked, Data}.\n\n-ifdef(BEFORE_REWRITE).\n-else.\ncallback_mode() ->\n state_functions.\n%% state_functions mode is the mode most similar to\n%% gen_fsm. There is also handle_event mode which is\n%% a fairly different concept.\n-endif.\n\n-ifdef(BEFORE_REWRITE).\nlocked({button, Digit}, Data0) ->\n case analyze_lock(Digit, Data0) of\n {open = StateName, Data} ->\n {next_state, StateName, Data, 10000};\n {StateName, Data} ->\n {next_state, StateName, Data}\n end.\n-else.\nlocked(cast, {button,Digit}, Data0) ->\n case analyze_lock(Digit, Data0) of\n {open = StateName, Data} ->\n {next_state, StateName, Data, 10000};\n {StateName, Data} ->\n {next_state, StateName, Data}\n end;\nlocked({call, From}, Msg, Data) ->\n handle_call(From, Msg, Data);\nlocked({info, Msg}, StateName, Data) ->\n handle_info(Msg, StateName, Data).\n%% Arity differs\n%% All state events are dispatched to handle_call and handle_info help\n%% functions. If you want to handle a call or cast event specifically\n%% for this state you would add a special clause for it above.\n-endif.\n\n-ifdef(BEFORE_REWRITE).\nopen(timeout, State) ->\n do_lock(),\n {next_state, locked, State};\nopen({button,_}, Data) ->\n {next_state, locked, Data}.\n-else.\nopen(timeout, _, Data) ->\n do_lock(),\n {next_state, locked, Data};\nopen(cast, {button,_}, Data) ->\n {next_state, locked, Data};\nopen({call, From}, Msg, Data) ->\n handle_call(From, Msg, Data);\nopen(info, Msg, Data) ->\n handle_info(Msg, open, Data).\n%% Arity differs\n%% All state events are dispatched to handle_call and handle_info help\n%% functions. If you want to handle a call or cast event specifically\n%% for this state you would add a special clause for it above.\n-endif.\n\n-ifdef(BEFORE_REWRITE).\nhandle_sync_event(stop, _From, _StateName, Data) ->\n {stop, normal, ok, Data}.\n\nhandle_event(Event, StateName, Data) ->\n {stop, {shutdown, {unexpected, Event, StateName}}, Data}.\n\nhandle_info(Info, StateName, Data) ->\n {stop, {shutdown, {unexpected, Info, StateName}}, StateName, Data}.\n-else.\n-endif.\n\nterminate(_Reason, State, _Data) ->\n State =/= locked andalso do_lock(),\n ok.\ncode_change(_Vsn, State, Data, _Extra) ->\n {ok, State, Data}.\n\n%% Internal functions\n-ifdef(BEFORE_REWRITE).\n-else.\nhandle_call(From, stop, Data) ->\n {stop_and_reply, normal, {reply, From, ok}, Data}.\n\nhandle_info(Info, StateName, Data) ->\n {stop, {shutdown, {unexpected, Info, StateName}}, StateName, Data}.\n%% These are internal functions for handling all state events\n%% and not behaviour callbacks as in gen_fsm\n-endif.\n\nanalyze_lock(Digit, #{code := Code, remaining := Remaining} = Data) ->\n case Remaining of\n [Digit] ->\n do_unlock(),\n {open, Data#{remaining := Code}};\n [Digit|Rest] -> % Incomplete\n {locked, Data#{remaining := Rest}};\n _Wrong ->\n {locked, Data#{remaining := Code}}\n end.\n\ndo_lock() ->\n io:format(\"Lock~n\", []).\ndo_unlock() ->\n io:format(\"Unlock~n\", []).\n```\n\nOTP 19 Documentation\n--------------------","title":"gen_fsm","ref":"gen_fsm.html"},{"type":"behaviour","doc":"`gen_fsm`","title":"Module - gen_fsm","ref":"gen_fsm.html#module-module"},{"type":"behaviour","doc":"Generic finite state machine behavior.","title":"Module Summary - gen_fsm","ref":"gen_fsm.html#module-module-summary"},{"type":"behaviour","doc":"This behavior module provides a finite state machine.\nA generic finite state machine process (`gen_fsm`) implemented\nusing this module has a standard set of interface functions\nand includes functionality for tracing and error reporting.\nIt also fits into an OTP supervision tree. For more information,\nsee [OTP Design Principles](`e:system:design_principles`).\n\nA `gen_fsm` process assumes all specific parts to be located\nin a callback module exporting a predefined set of functions.\nThe relationship between the behavior functions\nand the callback functions is as follows:\n\n``` text\ngen_fsm module Callback module\n-------------- ---------------\ngen_fsm:start\ngen_fsm:start_link -----> Module:init/1\n\ngen_fsm:stop -----> Module:terminate/3\n\ngen_fsm:send_event -----> Module:StateName/2\n\ngen_fsm:send_all_state_event -----> Module:handle_event/3\n\ngen_fsm:sync_send_event -----> Module:StateName/3\n\ngen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4\n\n- -----> Module:handle_info/3\n\n- -----> Module:terminate/3\n\n- -----> Module:code_change/4\n```\n\nIf a callback function fails or returns a bad value,\nthe `gen_fsm` process terminates.\n\nA `gen_fsm` process handles system messages as described\nin [sys(3)](`m:sys`). The sys module can be used for\ndebugging a `gen_fsm` process.\n\nNotice that a `gen_fsm` process does not trap exit signals automatically,\nthis must be explicitly initiated in the callback module.\n\nUnless otherwise stated, all functions in this module fail\nif the specified `gen_fsm` process does not exist\nor if bad arguments are specified.\n\nThe gen_fsm process can go into hibernation (see `erlang:hibernate/3`)\nif a callback function specifies `hibernate` instead of a time-out value.\nThis can be useful if the server is expected to be idle for a long time.\nHowever, use this feature with care, as hibernation implies at least\ntwo garbage collections (when hibernating and shortly after waking up)\nand is not something you want to do between each call\nto a busy state machine.","title":"Description - gen_fsm","ref":"gen_fsm.html#module-description"},{"type":"behaviour","doc":"See the [Callback Functions](#callbacks-deprecated) section\nfor the functions to be exported from a `gen_fsm` callback module.\n\n[]() {: #state-name }\n**State name** denotes a state of the state machine.\n\n[]() {: #state-data }\n**State data** denotes the internal state of the Erlang process\nthat implements the state machine.","title":"Callback Functions - gen_fsm","ref":"gen_fsm.html#module-callback-functions"},{"type":"function","doc":"Cancel an internal timer in a generic FSM.\n\nCancels an internal timer referred by `Ref` in the `gen_fsm` process\nthat calls this function.\n\n`Ref` is a reference returned from `send_event_after/2`\nor `start_timer/2`.\n\nIf the timer has already timed out, but the event not yet been delivered,\nit is cancelled as if it had not timed out, so there is no false\ntimer event after returning from this function.\n\nReturns the remaining time in milliseconds until the timer\nwould have expired if `Ref` referred to an active timer,\notherwise `false`.","title":"gen_fsm.cancel_timer/1","ref":"gen_fsm.html#cancel_timer/1"},{"type":"callback","doc":"Update the internal [*state data*](#state-data) during upgrade/downgrade.\n\nThis function is called by a `gen_fsm` process when it is to update\nits internal [*state data*](#state-data)\nduring a release upgrade/downgrade, that is,\nwhen instruction `{update, Module, Change, ...}`,\nwhere `Change = {advanced, Extra}`, is given in the appup file;\nsee section Release Handling Instructions in OTP Design Principles.\n[OTP Design Principles](`e:system:release_handling.md#instr`).\n\nFor an upgrade, `OldVsn` is `Vsn`, and for a downgrade,\n`OldVsn` is `{down, Vsn}`. `Vsn` is defined by the vsn attribute(s)\nof the old version of the callback module `Module`. If no such\n attribute is defined, the version is the checksum of the Beam file.\n\n`StateName` is the current [*state name*](#state-name)\n and `StateData` the internal [*state data*](#state-data)\n of the `gen_fsm` process.\n\n`Extra` is passed \"as is\" from the `{advanced, Extra}` part\n of the update instruction.\n\nThe function is to return the new current [*state name*](#state-name)\nand updated internal data.","title":"gen_fsm.code_change/4","ref":"gen_fsm.html#c:code_change/4"},{"type":"function","doc":"Enter the `gen_fsm` receive loop.\n\nEquivalent to `enter_loop/6` with `Timeout = infinity`\nbut the started server is not registered as for `start_link/3`.","title":"gen_fsm.enter_loop/4","ref":"gen_fsm.html#enter_loop/4"},{"type":"function","doc":"Enter the `gen_fsm` receive loop.\n\nWith argument `FsmName` equivalent to `enter_loop/6`\nwith `Timeout = infinity`.\n\nWith argument `Timeout` equivalent to `enter_loop/6`\nbut the started server is not registered as for `start_link/3`.","title":"gen_fsm.enter_loop/5","ref":"gen_fsm.html#enter_loop/5"},{"type":"function","doc":"Enter the `gen_fsm` receive loop.\n\nMakes an existing process into a `gen_fsm` process. Does not return,\ninstead the calling process enters the `gen_fsm` receive loop\nand becomes a `gen_fsm` process. The process must have been started\nusing one of the start functions in `m:proc_lib`. The user is responsible\nfor any initialization of the process, including registering a name for it.\n\nThis function is useful when a more complex initialization procedure\nis needed than the `gen_fsm` behavior provides.\n\n`Module`, `Options`, and `FsmName` have the same meanings\nas when calling [`start[_link]/3,4`](`start_link/4`).\nHowever, the process must have been registered according to\n`FsmName` before this function is called.\n\n`StateName`, `StateData`, and `Timeout` have the same meanings\nas in the return value of [`Module:init/1`](`c:init/1`).\nThe callback module `Module` does not need to export\nan `c:init/1` function.\n\nThe function fails if the calling process was not started\nby a `m:proc_lib` start function, or if it is not registered\naccording to `FsmName`.","title":"gen_fsm.enter_loop/6","ref":"gen_fsm.html#enter_loop/6"},{"type":"callback","doc":"Optional function for providing a term describing\nthe current `gen_fsm` process status.\n\nThe second argument is `[PDict, StateData]`, that is, a list\nwith the 2 elements, in that order.\n\n> #### Note {: .info }\n>\n> This callback is optional, so callback modules need not export it.\n> The `gen_fsm` module provides a default implementation\n> of this function that returns the callback module\n> [*state data*](#state-data).\n\nThis function is called by a `gen_fsm` process\nin the following situations:\n\n- One of [`sys:get_status/1,2`](`sys:get_status/1`) is invoked to get\n the `gen_fsm` status. `Opt` is set to the atom `normal` for this case.\n- The `gen_fsm` process terminates abnormally and logs an error.\n `Opt` is set to the atom terminate for this case.\n\nThis function is useful for changing the form and appearance\nof the `gen_fsm` status for these cases. A callback module\nwishing to change the [`sys:get_status/1,2`](`sys:get_status/1`)\nreturn value as well as how its status appears in termination error logs,\nexports an instance of `c:format_status/2` that returns a term\ndescribing the current status of the `gen_fsm` process.\n\n`PDict` is the current value of the process dictionary\nof the `gen_fsm` process.\n\n`StateData` is the internal [*state data*](#state-data)\nof the `gen_fsm` process.\n\nThe function is to return `Status`, a term that change the details\nof the current state and status of the `gen_fsm` process.\nThere are no restrictions on the form `Status` can take,\nbut for the [`sys:get_status/1,2`](`sys:get_status/1`) case\n(when `Opt` is `normal`), the recommended form for the `Status` value\nis `[{data, [{\"StateData\", Term}]}]`, where `Term` provides\nrelevant details of the `gen_fsm` [*state data*](#state-data).\nFollowing this recommendation is not required, but it makes\nthe callback module status consistent with the rest of\nthe [`sys:get_status/1,2`](`sys:get_status/1`) return value.\n\nOne use for this function is to return compact alternative\n[*state data*](#state-data) representations to avoid\nthat large state terms are printed in log files.","title":"gen_fsm.format_status/2","ref":"gen_fsm.html#c:format_status/2"},{"type":"callback","doc":"Handle an asynchronous event.\n\nWhenever a `gen_fsm` process receives an event sent using\n`send_all_state_event/2`, this function is called to handle the event.\n\n`StateName` is the current [*state name*](#state-name)\nof the `gen_fsm` process.\n\nFor a description of the other arguments and possible return values,\nsee [`Module:StateName/2`](`c:'StateName'/2`).","title":"gen_fsm.handle_event/3","ref":"gen_fsm.html#c:handle_event/3"},{"type":"callback","doc":"Handle an incoming message\n\nThis function is called by a `gen_fsm` process when it receives\nany other message than a synchronous or asynchronous event\n(or a system message).\n\n`Info` is the received message.\n\nFor a description of the other arguments and possible return values,\nsee [`Module:StateName/2`](`c:'StateName'/2`).","title":"gen_fsm.handle_info/3","ref":"gen_fsm.html#c:handle_info/3"},{"type":"callback","doc":"Handle a synchronous event.\n\nWhenever a `gen_fsm` process receives an event sent using\n[`sync_send_all_state_event/2,3`](`sync_send_all_state_event/3`),\nthis function is called to handle the event.\n\n`StateName` is the current [*state name*](#state-name)\nof the `gen_fsm` process.\n\nFor a description of the other arguments and possible return values,\nsee [`Module:StateName/3`](`c:'StateName'/3`).","title":"gen_fsm.handle_sync_event/4","ref":"gen_fsm.html#c:handle_sync_event/4"},{"type":"callback","doc":"Initialize process and internal [*state name*](#state-name)\nand [*state data*](#state-data).\n\nWhenever a `gen_fsm` process is started using\n[`start/3,4`](`start/4`) or [`start_link/3,4`](`start_link/4`),\nthis function is called by the new process to initialize.\n\n`Args` is the `Args` argument provided to the start function.\n\nIf initialization is successful, the function is to return\n{ok, StateName, StateData}, {ok, StateName, StateData, Timeout},\nor {ok, StateName, StateData, hibernate}, where `StateName`\nis the initial [*state name*](#state-name) and `StateData`\nthe initial [*state data*](#state-data) of the `gen_fsm` process.\n\nIf an `t:integer/0` time-out value is provided, a time-out occurs\nunless an event or a message is received within `Timeout` milliseconds.\nA time-out is represented by the atom `timeout` and is to be handled\nby the [`Module:StateName/2`](`c:'StateName'/2`) callback functions.\nThe atom `infinity` can be used to wait indefinitely, this is\nthe default value.\n\nIf `hibernate` is specified instead of a time-out value,\nthe process goes into hibernation when waiting for the next message\nto arrive (by calling `proc_lib:hibernate/3`).\n\nIf the initialization fails, the function returns `{stop, Reason}`,\nwhere `Reason` is any term, or `ignore`.","title":"gen_fsm.init/1","ref":"gen_fsm.html#c:init/1"},{"type":"function","doc":"Send a reply to a caller.\n\nThis function can be used by a `gen_fsm` process to explicitly send\na reply to a client process that called\n[`sync_send_event/2,3`](`sync_send_event/3`) or\n[`sync_send_all_state_event/2,3`](`sync_send_all_state_event/3`)\nwhen the reply cannot be defined in the return value of\n[`Module:StateName/3`](`c:'StateName'/3`) or\n[`Module:handle_sync_event/4`](`c:handle_sync_event/4`).\n\n`Caller` must be the `From` argument provided to the callback function.\n`Reply` is any term given back to the client as the return value of\n[`sync_send_event/2,3`](`sync_send_event/3`) or\n[`sync_send_all_state_event/2,3`](`sync_send_all_state_event/3`).\n\nReturn value `Result` is not further defined, and is always to be ignored.","title":"gen_fsm.reply/2","ref":"gen_fsm.html#reply/2"},{"type":"callback","doc":"Handle an asynchronous event.\n\nThere is to be one instance of this function\nfor each possible [*state name*](#state-name).\nWhenever a `gen_fsm` process receives an event sent using `send_event/2`,\nthe instance of this function with the same name as the current\n[*state name*](#state-name) `StateName` is called to handle the event.\nIt is also called if a time-out occurs.\n\n`Event` is either the atom `timeout`, if a time-out has occurred,\nor the `Event` argument provided to `send_event/2`.\n\n`StateData` is the [*state data*](#state-data) of the `gen_fsm` process.\n\nIf the function returns `{next_state, NextStateName, NewStateData},\n{next_state, NextStateName, NewStateData, Timeout},\nor {next_state, NextStateName, NewStateData, hibernate},\nthe `gen_fsm` process continues executing with\nthe current [*state name*](#state-name) set to `NextStateName`\nand with the possibly updated [*state data*](#state-data)\n`NewStateData`. For a description of `Timeout` and `hibernate`,\nsee [`Module:init/1`](`c:init/1`).\n\nIf the function returns `{stop ,Reason, NewStateData},\nthe `gen_fsm` process calls\n[`Module:terminate(Reason, StateName, NewStateData)`](`c:terminate/3`)\nand terminates.","title":"gen_fsm.StateName/2","ref":"gen_fsm.html#c:StateName/2"},{"type":"callback","doc":"Handle a synchronous event.\n\nThere is to be one instance of this function\nfor each possible [*state name*](#state-name).\nWhenever a `gen_fsm` process receives an event sent using\n[`sync_send_event/2,3`](`sync_send_event/3`),\nthe instance of this function with the same name\nas the current [*state name*](#state-name) `StateName` is called\nto handle the event.\n\n`Event` is the `Event` argument provided to\n[`sync_send_event/2,3`](`sync_send_event/3`).\n\n`From` is a tuple `{Pid, Tag}` where `Pid` is the `t:pid/0`\nof the process that called [`sync_send_event/2,3`](`sync_send_event/3`),\n`Tag` is a unique tag.\n\n`StateData` is the [*state data*](#state-data) of the `gen_fsm` process.\n\n- If `{reply, Reply, NextStateName, NewStateData}`,\n `{reply, Reply, NextStateName, NewStateData, Timeout}`,\n or `{reply, Reply, NextStateName, NewStateData, hibernate}` is returned,\n `Reply` is given back to `From` as the return value of\n [`sync_send_event/2,3`](`sync_send_event/3`).\n The `gen_fsm` process then continues executing\n with the current [*state name*](#state-name) set to `NextStateName`\n and with the possibly updated [*state data*](#state-data) `NewStateData`.\n For a description of `Timeout` and `hibernate`,\n see [`Module:init/1`](`c:init/1`).\n\n- If `{next_state, NextStateName, NewStateData}`,\n `{next_state, NextStateName, NewStateData, Timeout}`,\n or `{next_state, NextStateName, NewStateData, hibernate}` is returned,\n the `gen_fsm` process continues executing in `NextStateName`\n with `NewStateData`. Any reply to `From`\n must be specified explicitly using `reply/2`.\n\n- If the function returns `{stop, Reason, Reply, NewStateData}`,\n `Reply` is given back to `From`. If the function returns\n {stop, Reason, NewStateData}, any reply to `From` must be specified\n explicitly using `reply/2`. The `gen_fsm` process then calls\n [`Module:terminate(Reason, StateName, NewStateData)`](`c:terminate/3`)\n and terminates.","title":"gen_fsm.StateName/3","ref":"gen_fsm.html#c:StateName/3"},{"type":"function","doc":"Send an event asynchronously to a generic FSM.\n\nSends an event asynchronously to the `FsmRef` of the `gen_fsm` process\nand returns `ok` immediately. The `gen_fsm` process calls\n[`Module:handle_event/3`](`c:handle_event/3`) to handle the event.\n\nFor a description of the arguments, see `send_event/2`.\n\nThe difference between `send_event/2` and `send_all_state_event/2`\nis which callback function is used to handle the event.\nThis function is useful when sending events that are handled\nthe same way in every state, as only one `handle_event` clause\nis needed to handle the event instead of one clause\nin each state name function.","title":"gen_fsm.send_all_state_event/2","ref":"gen_fsm.html#send_all_state_event/2"},{"type":"function","doc":"Send an event asynchronously to a generic FSM.\n\nSends `Event` to the `FsmRef` of the `gen_fsm` process\nand returns `ok` immediately. The `gen_fsm` process calls\n[`Module:StateName/2`](`c:'StateName'/2`) to handle the event,\nwhere `StateName` is the name of the current state\nof the `gen_fsm` process.\n\n[](){: #fsm-ref }\n`FsmRef` can be any of the following:\n\n- The `t:pid/0`\n- `Name`, if the `gen_fsm` process is locally registered\n- `{Name, Node}`, if the `gen_fsm` process is locally registered\n at another node\n- `{global, GlobalName}`, if the `gen_fsm` process is globally registered\n- `{via, Module, ViaName}`, if the `gen_fsm` process is registered\n through an alternative process registry\n\n`Event` is any term that is passed as one of the arguments\nto `Module:StateName/2`.","title":"gen_fsm.send_event/2","ref":"gen_fsm.html#send_event/2"},{"type":"function","doc":"Send a delayed event internally in a generic FSM.\n\nSends a delayed event internally in the `gen_fsm` process\nthat calls this function after `Time` milliseconds.\nReturns immediately a reference that can be used to cancel\nthe delayed send using `cancel_timer/1`.\n\nThe `gen_fsm` process calls [`Module:StateName/2`](`c:'StateName'/2`)\nto handle the event, where `'StateName'` is the name of\nthe current state of the `gen_fsm` process at the time\nthe delayed event is delivered.\n\n`Event` is any term that is passed as one of the arguments\nto [`Module:StateName/2`](`c:'StateName'/2`).","title":"gen_fsm.send_event_after/2","ref":"gen_fsm.html#send_event_after/2"},{"type":"function","doc":"Create a standalone `gen_fsm` process, not registered.\n\nEquivalent to [`start(Name, Mod, Args, Options)`](`start/4`)\nwithout registering a `Name`.\n\nFor a description of arguments and return values,\nsee [`start_link/3,4`](`start_link/3`).","title":"gen_fsm.start/3","ref":"gen_fsm.html#start/3"},{"type":"function","doc":"Create a standalone `gen_fsm` process.\n\nThe created process is not part of a supervision tree\nand thus has no supervisor.\n\nFor a description of arguments and return values,\nsee [`start_link/3,4`](`start_link/4`).","title":"gen_fsm.start/4","ref":"gen_fsm.html#start/4"},{"type":"function","doc":"Create a `gen_fsm` process in a supervision tree, not registered.\n\nEquivalent to [`start_link(Name, Mod, Args, Options)`](`start_link/4`)\nwithout registering a `Name`.","title":"gen_fsm.start_link/3","ref":"gen_fsm.html#start_link/3"},{"type":"function","doc":"Create a `gen_fsm` process in a supervision tree.\n\nThe process is created as part of a supervision tree. The function\nis to be called, directly or indirectly, by the supervisor.\nFor example, it ensures that the `gen_fsm` process\nis linked to the supervisor.\n\nThe `gen_fsm` process calls [`Module:init/1`](`c:init/1`) to initialize.\nTo ensure a synchronized startup procedure,\n[`start_link/3,4`](`start_link/4`) does not return\nuntil `Module:init/1` has returned.\n\n[]() {: #fsm-name }\n\n- If **`FsmName = {local, Name}`**, the `gen_fsm` process\n is registered locally as `Name` using `register/2`.\n\n- If **`FsmName = {global, GlobalName}`**, the `gen_fsm` process\n is registered globally as `GlobalName` using `global:register_name/2`.\n\n- If **`FsmName = {via, Module, ViaName}`**,\n the `gen_fsm` process registers with the registry\n represented by `Module`. The `Module` callback is to export\n the functions `register_name/2`, `unregister_name/1`,\n `whereis_name/1`, and `send/2`, which are to behave like\n the corresponding functions in `m:global`.\n Thus, `{via, global, GlobalName}` is a valid reference.\n\n`Module` is the name of the callback module.\n\n`Args` is any term that is passed as the argument to `Module:init/1`.\n\n[]() {: #start-options }\n\nIf option **`{timeout, Time}`** is present, the `gen_fsm` process\nis allowed to spend `Time` milliseconds initializing or it terminates\nand the start function returns `{error, timeout}`.\n\nIf option **`{debug, Dbgs}`** is present, the corresponding `sys` function\nis called for each item in `Dbgs`; see [`sys(3)`](`m:sys`).\n\nIf option **`{spawn_opt, SOpts}`** is present, `SOpts` is passed\nas option list to the `spawn_opt` BIF that is used\nto spawn the `gen_fsm` process; see `spawn_opt/2`.\n\n> #### Note {: .info }\n> Using spawn option `monitor` is not allowed, it causes\n> the function to fail with reason `badarg`.\n\nIf the `gen_fsm` process is successfully created and initialized,\nthe function returns `{ok, Pid}`, where `Pid` is the pid\nof the `gen_fsm` process. If a process with the specified `FsmName`\nexists already, the function returns `{error, {already_started, Pid}}`,\nwhere `Pid` is the pid of that process.\n\nIf `Module:init/1` fails with `Reason`, the function returns\n`{error, Reason}`. If `Module:init/1` returns `{stop, Reason}`\nor `ignore`, the process is terminated and the function returns\n`{error, Reason}` or `ignore`, respectively.","title":"gen_fsm.start_link/4","ref":"gen_fsm.html#start_link/4"},{"type":"function","doc":"Send a time-out event internally in a generic FSM.\n\nSends a time-out event internally in the `gen_fsm process`\nthat calls this function after `Time` milliseconds.\nReturns immediately a reference that can be used to cancel the timer\nusing `cancel_timer/1`.\n\nThe `gen_fsm` process calls [`Module:StateName/2`](`c:'StateName'/2`)\nto handle the event, where `'StateName'` is the name\nof the current state of the `gen_fsm` process at the time\nthe time-out message is delivered.\n\n`Msg` is any term that is passed in the time-out message,\n`{timeout, Ref, Msg}`, as one of the arguments\nto [`Module:StateName/2`](`c:'StateName'/2`).","title":"gen_fsm.start_timer/2","ref":"gen_fsm.html#start_timer/2"},{"type":"function","doc":"","title":"gen_fsm.stop/1","ref":"gen_fsm.html#stop/1"},{"type":"function","doc":"Synchronously stop a generic FSM.\n\nOrders a generic finite state machine to exit with the specified `Reason`\nand waits for it to terminate. The `gen_fsm` process calls\n[`Module:terminate/3`](`c:terminate/3`) before exiting.\n\nThe function returns `ok` if the generic finite state machine terminates\nwith the expected reason. Any other reason than `normal`, `shutdown`,\nor `{shutdown, Term}` causes an error report to be issued using\n`error_logger:format/2`.\n\n`Timeout` is an integer greater than zero that specifies\nhow many milliseconds to wait for the generic FSM to terminate,\nor the atom `infinity` to wait indefinitely.\nIf the generic finite state machine has not terminated\nwithin the specified time, a `timeout` exception is raised.\n\nIf the process does not exist, a `noproc` exception is raised.","title":"gen_fsm.stop/3","ref":"gen_fsm.html#stop/3"},{"type":"function","doc":"","title":"gen_fsm.sync_send_all_state_event/2","ref":"gen_fsm.html#sync_send_all_state_event/2"},{"type":"function","doc":"Send an event synchronously to a generic FSM.\n\nSends an event to the `FsmRef` of the `gen_fsm` process and waits\nuntil a reply arrives or a time-out occurs. The `gen_fsm` process calls\n[`Module:handle_sync_event/4`](`c:handle_sync_event/4`)\nto handle the event.\n\nFor a description of `FsmRef` and `Event`, see `send_event/2`.\nFor a description of `Timeout` and `Reply`, see `sync_send_event/3`.\n\nFor a discussion about the difference between `sync_send_event`\nand `sync_send_all_state_event`, see `send_all_state_event/2`.","title":"gen_fsm.sync_send_all_state_event/3","ref":"gen_fsm.html#sync_send_all_state_event/3"},{"type":"function","doc":"","title":"gen_fsm.sync_send_event/2","ref":"gen_fsm.html#sync_send_event/2"},{"type":"function","doc":"Send an event synchronously to a generic FSM.\n\nSends an event to the `FsmRef` of the `gen_fsm` process\nand waits until a reply arrives or a time-out occurs.\nThe `gen_fsm` process calls [`Module:StateName/3`](`c:'StateName'/3`)\nto handle the event, where `'StateName'` is the name\nof the current state of the `gen_fsm` process.\n\nFor a description of `FsmRef` and `Event`, see `send_event/2`.\n\n`Timeout` is an integer greater than zero that specifies\nhow many milliseconds to wait for a reply, or the atom `infinity`\nto wait indefinitely. If no reply is received within the specified time,\nthe function call fails.\n\nReturn value `Reply` is defined in the return value of\n[`Module:StateName/3`](`c:'StateName'/3`)\n\n> #### Note {: .info }\n> The ancient behavior of sometimes consuming the server exit message\n> if the server died during the call while linked to the client\n> was removed in Erlang 5.6/OTP R12B.","title":"gen_fsm.sync_send_event/3","ref":"gen_fsm.html#sync_send_event/3"},{"type":"callback","doc":"Clean up before termination.\n\nThis function is called by a `gen_fsm` process\nwhen it is about to terminate. It is to be the opposite of\n[`Module:init/1`](`c:init/1`) and do any necessary cleaning up.\nWhen it returns, the `gen_fsm` process terminates with `Reason`.\nThe return value is ignored.\n\n`Reason` is a term denoting the stop reason, `StateName` is\nthe current [*state name*](#state-name),\nand `StateData` is the [*state data*](#state-data)\nof the `gen_fsm` process.\n\n`Reason` depends on why the `gen_fsm` process is terminating.\nIf it is because another callback function has returned a stop tuple\n`{stop, ...}`, `Reason` has the value specified in that tuple.\nIf it is because of a failure, `Reason` is the error reason.\n\nIf the `gen_fsm` process is part of a supervision tree\nand is ordered by its supervisor to terminate, this function\nis called with `Reason = shutdown` if the following conditions apply:\n\n- The gen_fsm process has been set to trap exit signals.\n\n- The shutdown strategy as defined in the child specification\n of the supervisor is an integer time-out value, not brutal_kill.\n\nEven if the gen_fsm process is **not** part of a supervision tree,\nthis function is called if it receives an `'EXIT'` message\nfrom its parent. `Reason` is the same as in the `'EXIT'` message.\n\nOtherwise, the gen_fsm process terminates immediately.\n\nNotice that for any other reason than `normal`, `shutdown`,\nor `{shutdown, Term}` the `gen_fsm` process is assumed to terminate\nbecause of an error and an error report is issued\nusing `error_logger:format/2`.","title":"gen_fsm.terminate/3","ref":"gen_fsm.html#c:terminate/3"},{"type":"type","doc":"[Start options](#start-options) for the\n[`enter_loop/4,5,6`](`enter_loop/6`), [`start/3,4`](`start/3`),\nand [`start_link/3,4`](`start_link/3`) functions.\n\nSee `start_link/4`.","title":"gen_fsm.enter_loop_opt/0","ref":"gen_fsm.html#t:enter_loop_opt/0"},{"type":"type","doc":"Reply destination. See `reply/2`","title":"gen_fsm.from/0","ref":"gen_fsm.html#t:from/0"},{"type":"type","doc":"[FSM name](#fsm-name) specification:\n`local`, `global`, or `via` registered.\n\nTo be used when starting a `gen_fsm`. See `start_link/4`.","title":"gen_fsm.fsm_name/0","ref":"gen_fsm.html#t:fsm_name/0"},{"type":"type","doc":"[FSM reference](#fsm-ref) `t:pid/0` or registered `t:fsm_name/0`.\n\nTo be used in for example `send_event/2` to specify the server.","title":"gen_fsm.fsm_ref/0","ref":"gen_fsm.html#t:fsm_ref/0"},{"type":"type","doc":"[Start options](#start-options) for the [`start/3,4`](`start/3`),\nand [`start_link/3,4`](`start_link/3`) functions.\n\nSee `start_link/4`.","title":"gen_fsm.start_opt/0","ref":"gen_fsm.html#t:start_opt/0"},{"type":"behaviour","doc":"Generic server behavior.\n\nThis behavior module provides the server in a client-server relation.\nA generic server process (`gen_server`) implemented using this module\nhas a standard set of interface functions and includes functionality\nfor tracing and error reporting. It also fits into\nan OTP supervision tree. For more information, see section\n[gen_server Behaviour](`e:system:gen_server_concepts.md`)\nin OTP Design Principles.\n\nA `gen_server` process assumes all specific parts to be located\nin a callback module exporting a predefined set of functions.\nThe relationship between the behavior functions\nand the callback functions is as follows:\n\n```text\ngen_server module Callback module\n----------------- ---------------\ngen_server:start\ngen_server:start_monitor\ngen_server:start_link -----> Module:init/1\n\ngen_server:stop -----> Module:terminate/2\n\ngen_server:call\ngen_server:send_request\ngen_server:multi_call -----> Module:handle_call/3\n\ngen_server:cast\ngen_server:abcast -----> Module:handle_cast/2\n\n- -----> Module:handle_info/2\n\n- -----> Module:handle_continue/2\n\n- -----> Module:terminate/2\n\n- -----> Module:code_change/3\n```\n\nIf a callback function fails or returns a bad value,\nthe `gen_server` process terminates. However, an exception of class\n[`throw`](`erlang:throw/1`) is not regarded as an error\nbut as a valid return, from all callback functions.\n\nA `gen_server` process handles system messages as described in `m:sys`.\nThe `m:sys` module can be used for debugging a `gen_server` process.\n\nNotice that a `gen_server` process does not trap exit signals\nautomatically, this must be explicitly initiated in the callback module.\n\nUnless otherwise stated, all functions in this module fail\nif the specified `gen_server` process does not exist\nor if bad arguments are specified.\n\nThe `gen_server` process can go into hibernation (see `erlang:hibernate/3`)\nif a callback function specifies `'hibernate'` instead of a time-out value.\nThis can be useful if the server is expected to be idle for a long time.\nHowever, use this feature with care, as hibernation implies at least\ntwo garbage collections (when hibernating and shortly after waking up)\nand is not something you want to do between each call to a busy server.\n\nIf the `gen_server` process needs to perform an action after\ninitialization or to break the execution of a callback into multiple steps,\nit can return `{continue, Continue}` in place of\nthe time-out or hibernation value, which will invoke\nthe [`Module:handle_continue/2`](`c:handle_continue/2`) callback,\nbefore receiving any external message / request.\n\nIf the `gen_server` process terminates, e.g. as a result of a function\nin the callback module returning `{stop,Reason,NewState}`,\nan exit signal with this `Reason` is sent to linked processes and ports.\nSee [Processes](`e:system:ref_man_processes.md#errors`)\nin the Reference Manual for details regarding error handling\nusing exit signals.\n\n> #### Note {: .info }\n>\n> For some important information about distributed signals, see the\n> [_Blocking Signaling Over Distribution_][1]\n> section in the _Processes_ chapter of the _Erlang Reference Manual_.\n> Blocking signaling can, for example, cause call time-outs\n> in `gen_server` to be significantly delayed.\n\n[1]: `e:system:ref_man_processes.md#blocking-signaling-over-distribution`","title":"gen_server","ref":"gen_server.html"},{"type":"behaviour","doc":"`m:gen_event`, `m:gen_statem`, `m:proc_lib`, `m:supervisor`, `m:sys`","title":"See Also - gen_server","ref":"gen_server.html#module-see-also"},{"type":"function","doc":"Cast a request to multiple nodes.\n\nEquivalent to [`abcast(Nodes, Name, Request)`](`abcast/3`)\nwhere `Nodes` is all nodes connected to the calling node,\nincluding the calling node itself.","title":"gen_server.abcast/2","ref":"gen_server.html#abcast/2"},{"type":"function","doc":"Cast a request to multiple nodes.\n\nSends an asynchronous request to the `gen_server` processes\nlocally registered as `Name` at the specified nodes.\nThe function returns immediately and ignores nodes that do not exist,\nor where the `gen_server` `Name` does not exist. The `gen_server`\nprocesses call [`Module:handle_cast/2`](`c:handle_cast/2`)\nto handle the request.\n\nFor a description of the arguments,\nsee [`multi_call/2,3,4`](`multi_call/2`).","title":"gen_server.abcast/3","ref":"gen_server.html#abcast/3"},{"type":"function","doc":"","title":"gen_server.call/2","ref":"gen_server.html#call/2"},{"type":"function","doc":"Call a server: send request and wait for response.\n\nMakes a synchronous call to the `ServerRef` of the `gen_server` process\nby sending a request and waiting until a reply arrives\nor a time-out occurs. The `gen_server` process calls\n[`Module:handle_call/3`](`c:handle_call/3`) to handle the request.\n\nSee also `ServerRef`'s type `t:server_ref/0`.\n\n`Request` is any term that is passed as the first argument to\n[`Module:handle_call/3`](`c:handle_call/3`).\n\n`Timeout` is an integer that specifies how many milliseconds to wait\nfor a reply, or the atom `infinity` to wait indefinitely. If no reply\nis received within the specified time, this function exits the calling\nprocess with an exit term containing `Reason = timeout` as described below.\n\n> #### Note {: .info }\n>\n> Before OTP 24, if the caller uses (`try`...)`catch`\n> to avoid process exit, and the server happens to just be late\n> with the reply, it may arrive to the process message queue\n> any time later. The calling process must therefore after\n> catching a time-out exit be prepared to receive garbage message(s)\n> on the form `{reference(), _}` and deal with them appropriately\n> (discard them) so they do not clog the process message queue,\n> or gets mistaken for other messages.\n>\n> Starting with OTP 24, `gen_server:call` uses process aliases,\n> so late replies will not be received.\n\nThe return value `Reply` is passed from the return value of\n[`Module:handle_call/3`](`c:handle_call/3`).\n\nThis call may exit the calling process with an exit term on the form\n`{Reason, Location}` where `Location = {gen_server, call, ArgList}`\nand `Reason` can be (at least) one of:\n\n- **`timeout`** - The call was aborted after waiting `Timeout` milliseconds\n for a reply, as described above.\n\n- **`noproc`** - The `ServerRef` refers to a server by name (it is not a\n `t:pid/0`) and looking up the server process failed, or the `t:pid/0`\n was already terminated.\n\n- **`{nodedown,Node}`** - The `ServerRef` refers to a server\n on the remote node `Node` and the connection to that node failed.\n\n- **`calling_self`** - A call to `self/0` would hang indefinitely.\n\n- **`shutdown`** - The server was stopped during the call\n by its supervisor. See also `stop/3`.\n\n- **`normal`\\\n `{shutdown,Term}`** - The server stopped during the call\n by returning `{stop,Reason,_}` from one of its callbacks\n without replying to this call. See also `stop/3`.\n\n- **`_OtherTerm`** - The server process exited during the call,\n with reason `Reason`. Either by returning `{stop,Reason,_}`\n from one of its callbacks (without replying to this call),\n by raising an exception, or due to getting an exit signal\n it did not trap.","title":"gen_server.call/3","ref":"gen_server.html#call/3"},{"type":"function","doc":"Cast a request to a server.\n\nSends an asynchronous request to the `gen_server`\n[`ServerRef`](`t:server_ref/0`) and returns `ok` immediately,\nignoring if the destination node or `gen_server`\nprocess does not exist.\n\nThe `gen_server` process calls\n[`Module:handle_cast(Request, _)`](`c:handle_cast/2`)\nto handle the request.","title":"gen_server.cast/2","ref":"gen_server.html#cast/2"},{"type":"function","doc":"Check if a received message is a request response.\n\nChecks if `Msg` is a response corresponding to\nthe request identifier `ReqId`. The request must have been made\nby `send_request/2`, and by the same process calling this function.\n\nIf `Msg` is a reply to the handle `ReqId` the result of the request\nis returned in `Reply`. Otherwise this function returns `no_reply`\nand no cleanup is done, and thus the function shall be invoked repeatedly\nuntil the response is returned.\n\nThe return value `Reply` is passed from the return value of\n[`Module:handle_call/3`](`c:handle_call/3`).\n\nIf the `gen_statem` server process has died when this function\nis called, that is; `Msg` reports the server's death,\nthis function returns an `error` return with the exit `Reason`.","title":"gen_server.check_response/2","ref":"gen_server.html#check_response/2"},{"type":"function","doc":"Check if a received message is a request response in a collection.\n\nCheck if `Msg` is a response corresponding to a request identifier\nstored in `ReqIdCollection`. All request identifiers of `ReqIdCollection`\nmust correspond to requests that have been made using `send_request/2`\nor `send_request/4`, by the process calling this function.\n\nThe `Label` in the response equals the `Label` associated\nwith the request identifier that the response corresponds to.\nThe `Label` of a request identifier is associated\nwhen [storing the request id](`reqids_add/3`) in a collection,\nor when sending the request using `send_request/4`.\n\nCompared to `check_response/2`, the returned result or exception\nassociated with a specific request identifier will be wrapped\nin a 3-tuple `{Response, Label, NewReqIdCollection}`.\n`Response` is the value that would have been produced\nby `check_response/2`, `Label` is the value associated with\nthe specific [request identifier](`t:request_id/0`)\nand `NewReqIdCollection` is a possibly modified\nrequest identifier collection.\n\nIf `ReqIdCollection` is empty, `no_request` will be returned.\n\nIf `Msg` does not correspond to any of the request identifiers\nin `ReqIdCollection`, `no_reply` is returned.\n\nIf `Delete` is `true`, the association with `Label`\nhas been deleted from `ReqIdCollection` in the resulting\n`NewReqIdCollection`. If `Delete` is `false`, `NewReqIdCollection`\nwill equal `ReqIdCollection`. Note that deleting an association\nis not for free and that a collection containing already handled\nrequests can still be used by subsequent calls to\n`check_response/3`, `receive_response/3`, and `wait_response/3`.\n\nHowever, without deleting handled associations,\nthe above calls will not be able to detect when there are\nno more outstanding requests to handle, so you will have to keep track\nof this some other way than relying on a `no_request` return.\nNote that if you pass a collection only containing\nassociations of already handled or abandoned requests to\nthis function, it will always return `no_reply`.","title":"gen_server.check_response/3","ref":"gen_server.html#check_response/3"},{"type":"callback","doc":"Update the server state after code change.\n\nThis function is called by a `gen_server` process when it is to update\nits internal state during a release upgrade/downgrade, that is,\nwhen the instruction `{update, Module, Change, ...}`, is specified\nin the [`appup`](`e:sasl:appup.md`) file.\n\nFor more information, see section\n[Release Handling Instructions](`e:system:release_handling.md#instr`)\nin OTP Design Principles.\n\nFor an upgrade, `OldVsn` is `Vsn`, and for a downgrade, `OldVsn` is\n`{down,Vsn}`. `Vsn` is defined by the `vsn` attribute(s)\nof the old version of the callback module `Module`. If no such attribute\nis defined, the version is the checksum of the Beam file.\n\n`State` is the internal state of the `gen_server` process.\n\n`Extra` is passed \"as is\" from the `{advanced,Extra}` part\nof the update instruction.\n\nIf successful, the function must return the updated internal state.\n\nIf the function returns `{error,Reason}`,\nthe ongoing upgrade fails and rolls back to the old release.\n\n> #### Note {: .info }\n>\n> If a release upgrade/downgrade with `Change = {advanced, Extra}`\n> specified in the [`.appup`](`e:sasl:appup.md`) file is made when\n> [`Module:code_change/3`](`c:code_change/3`) is not implemented,\n> the callback call will crash with an `undef` error reason.","title":"gen_server.code_change/3","ref":"gen_server.html#c:code_change/3"},{"type":"function","doc":"","title":"gen_server.enter_loop/3","ref":"gen_server.html#enter_loop/3"},{"type":"function","doc":"Make the calling process become a `gen_server` process.\n\nWith argument `ServerName` equivalent to\n[`enter_loop(Module, Options,\n State, ServerName, infinity)`](`enter_loop/5`).\n\nWith argument `How` equivalent to\n[`enter_loop(Module, Options, State, self(), How)`](`enter_loop/5`).","title":"gen_server.enter_loop/4","ref":"gen_server.html#enter_loop/4"},{"type":"function","doc":"Make the calling process become a `gen_server` process.\n\nDoes not return, instead the calling process enters the `gen_server`\nprocess receive loop and becomes a `gen_server` process.\nThe process _must_ have been started using one of the start functions\nin `m:proc_lib`. The user is responsible for any initialization\nof the process, including registering a name for it.\n\nThis function is useful when a more complex initialization procedure\nis needed than the `gen_server` [`Module:init/1`](`c:init/1`);\ncallback provides.\n\n`Module`, `Options`, and `ServerName` have the same meanings\nas when calling [`start[_link|_monitor]/3,4`](`start_link/3`)\nor `ServerName` can be `self/0` for an anonymous server,\nwhich is the same as calling an `enter_loop/3,4` function\nwithout a `ServerName` argument. However, if `ServerName`\nis specified (and not as `self/0`), the process must have been registered\naccordingly _before_ this function is called.\n\n`State`, `Timeout`, `Hibernate` and `Cont` have the same meanings\nas in the return value of [`Module:init/1`](`c:init/1`),\nwhich is _not_ called when `enter_loop/3,4,5` is used. Note that\nto adhere to the [gen_server Behaviour](`e:system:gen_server_concepts.md`)\nsuch a callback function needs to be defined, and it might as well\nbe the one used when starting the `gen_server` process\nthrough `proc_lib`, and then be the one that calls `enter_loop/3,4,5`.\nBut if such a [`Module:init/1`](`c:init/1`) function,\nin for example error cases, cannot call `enter_loop/3,4,5`,\nit should return a value that follows the type specification\nfor [`Module:init/1`](`c:init/1`) such as `ignore`,\nalthough that value will be lost when returning to the spawning function.\n\nThis function fails if the calling process was not started\nby a `proc_lib` start function, or if it is not registered\naccording to `ServerName`.","title":"gen_server.enter_loop/5","ref":"gen_server.html#enter_loop/5"},{"type":"callback","doc":"Format/limit the status value.\n\nThis function is called by a `gen_server` process in in order to\nformat/limit the server state for debugging and logging purposes.\n\nIt is called in the following situations:\n\n- [`sys:get_status/1,2`](`sys:get_status/1`) is invoked\n to get the `gen_server` status.\n- The `gen_server` process terminates abnormally and logs an error.\n\nThis callback is used to limit the status of the process returned by\n[`sys:get_status/1,2`](`sys:get_status/1`) or sent to `m:logger`.\n\nThe callback gets a map `Status` describing the current status\nand shall return a map `NewStatus` with the same keys,\nbut it may transform some values.\n\nTwo possible use cases for this callback is to remove\nsensitive information from the state to prevent it from being printed\nin log files, or to compact large irrelevant status items\nthat would only clutter the logs.\n\nExample:\n\n```erlang\nformat_status(Status) ->\n maps:map(\n fun(state,State) ->\n maps:remove(private_key, State);\n (message,{password, _Pass}) ->\n {password, removed};\n (_,Value) ->\n Value\n end, Status).\n```\n\n> #### Note {: .info }\n>\n> This callback is optional, so callback modules need not export it. The\n> `gen_server` module provides a default implementation\n> of this function that returns the callback module state.\n>\n> If this callback is exported but fails,\n> to hide possibly sensitive data,\n> the default function will instead return the fact that\n> [`Module:format_status/1`](`c:format_status/1`) has crashed.","title":"gen_server.format_status/1","ref":"gen_server.html#c:format_status/1"},{"type":"callback","doc":"Format/limit the status value.\n\nThis function is called by a `gen_server` process\nin in order to format/limit the server state\nfor debugging and logging purposes.\n\nIt is called in the following situations:\n\n- One of [`sys:get_status/1,2`](`sys:get_status/1`) is invoked to get the\n `gen_server` status. `Opt` is set to the atom `normal`.\n- The `gen_server` process terminates abnormally and logs an error.\n `Opt` is set to the atom `terminate`.\n\nThis function is useful for changing the form and appearance\nof the `gen_server` status for these cases. A callback module\nwishing to change the `sys:get_status/1,2` return value,\nas well as how its status appears in termination error logs,\nexports an instance of [`Module:format_status/2`](`c:format_status/2`)\nthat returns a term describing the current status\nof the `gen_server` process.\n\n`PDict` is the current value of the process dictionary\nof the `gen_server` process..\n\n`State` is the internal state of the `gen_server` process.\n\nThe function is to return `Status`, a term that changes the details\nof the current state and status of the `gen_server` process.\nThere are no restrictions on the form `Status` can take,\nbut for the `sys:get_status/1,2` case (when `Opt` is `normal`),\nthe recommended form for the `Status` value is\n`[{data, [{\"State\", Term}]}]`, where `Term` provides relevant details\nof the `gen_server` state. Following this recommendation is not required,\nbut it makes the callback module status consistent with the rest of\nthe `sys:get_status/1,2` return value.\n\nOne use for this function is to return compact alternative\nstate representations to avoid that large state terms are printed\nin log files.\n\n> #### Note {: .info }\n>\n> This callback is optional, so callback modules need not export it.\n> The `gen_server` module provides a default implementation\n> of this function that returns the callback module state.","title":"gen_server.format_status/2","ref":"gen_server.html#c:format_status/2"},{"type":"callback","doc":"Handle a call.\n\nWhenever a `gen_server` process receives a request sent using\n[`call/2,3`](`call/3`), [`multi_call/2,3,4`](`multi_call/4`),\nor [`send_request/2,4`](`send_request/4`), this function is called\nto handle the request.\n\n`State` is the internal state of the `gen_server` process,\nand `NewState` a possibly updated one.\n\n`Request` is passed from the same argument provided\nto `call` or `multi_call`.\n\nThe return value `Result` is interpreted as follows:\n\n- **`{reply,Reply,NewState}`\\\n `{reply,Reply,NewState,_}`** - The `Reply` value is sent back\n to the client request and there becomes its return value.\n\n The `gen_server` process continues executing with the possibly updated\n internal state `NewState`.\n\n- **`{noreply,NewState}`\\\n `{noreply,NewState,_}`** - The `gen_server` process\n continues executing with the possibly updated internal state `NewState`.\n\n A reply to the client request has to be created by calling\n [`reply(From, Reply)`](`reply/2`), either in this\n or in a later callback.\n\n- **`{reply,_,_,Timeout}`\\\n `{noreply,_,Timeout}`** - If an integer `Timeout` is provided,\n a time-out occurs unless a request or a message is received\n within that many milliseconds. A time-out is represented\n by the atom `timeout` to be handled by the\n [`Module:handle_info/2`](`c:handle_info/2`) callback function.\n `Timeout =:= infinity` can be used to wait indefinitely,\n which is the same as returning a value without a `Timeout` member.\n\n- **`{reply,_,_,hibernate}`\\\n `{noreply,_,hibernate}`** - The process goes into hibernation,\n by calling `proc_lib:hibernate/3`, waiting for\n the next message to arrive\n\n- **`{reply,_,_,{continue,Continue}}`\\\n `{noreply,_,{continue,Continue}}`** - The process will execute the\n [`Module:handle_continue/2`](`c:handle_continue/2`) callback function,\n with `Continue` as the first argument.\n\n- **`{stop,Reason,NewState}`\\\n `{stop,Reason,Reply,NewState}`** - The `gen_server` process will call\n [`Module:terminate(Reason,NewState)`](`c:terminate/2`),\n and then terminate.\n\n `{stop,_,Reply,_}` will create a reply to the client request just as\n `{reply,Reply,...}` while `{stop,_,_}` will not, so just as for\n `{noreply,NewState,...}` a reply has to be created by calling\n [`reply(From, Reply)`](`reply/2`) before returning `{stop,_,_}`.","title":"gen_server.handle_call/3","ref":"gen_server.html#c:handle_call/3"},{"type":"callback","doc":"Handle a cast message.\n\nWhenever a `gen_server` process receives a request sent using `cast/2`\nor [`abcast/2,3`](`abcast/2`), this function is called\nto handle the request.\n\nFor a description of the arguments and possible return values,\nsee [`Module:handle_call/3`](`c:handle_call/3`).","title":"gen_server.handle_cast/2","ref":"gen_server.html#c:handle_cast/2"},{"type":"callback","doc":"Handle a callback continuation.\n\nThis function is called by a `gen_server` process whenever\na previous callback returns one of the tuples containing\n`{continue, Continue}`. The call is invoked immediately after\nthe previous callback, which makes it useful for performing work\nafter initialization or, for splitting the work in a callback\ninto multiple steps, updating the process state along the way.\n\nFor a description of the other arguments and possible return values,\nsee [`Module:handle_call/3`](`c:handle_call/3`).\n\n> #### Note {: .info }\n>\n> This callback is optional, so callback modules need to export it\n> only if theyreturn one of the tuples containing `{continue,Continue}`\n> from another callback. If such a `{continue,_}` tuple is used\n> and the callback is not implemented, the process will exit\n> with `undef` error.","title":"gen_server.handle_continue/2","ref":"gen_server.html#c:handle_continue/2"},{"type":"callback","doc":"Handle an info message (regular process message).\n\nThis function is called by a `gen_server` process when a time-out occurs\nor when it receives any other message than a synchronous\nor asynchronous request (or a system message).\n\n`Info` is either the atom `timeout`, if a time-out has occurred,\nor the received message.\n\nFor a description of the other arguments and possible return values,\nsee [`Module:handle_call/3`](`c:handle_call/3`).\n\n> #### Note {: .info }\n>\n> This callback is optional, so callback modules need not export it.\n> The `gen_server` module provides a default implementation\n> of this function that logs about the unexpected `Info` message,\n> drops it and returns `{noreply, State}`.","title":"gen_server.handle_info/2","ref":"gen_server.html#c:handle_info/2"},{"type":"callback","doc":"Initialize the server.\n\nWhenever a `gen_server` process is started using [`start/3,4`](`start/3`),\n[`start_monitor/3,4`](`start_monitor/3`),\nor [`start_link/3,4`](`start_link/3`), this function is called\nby the new process to initialize the server.\n\n`Args` is the `Args` argument provided to the start function.\n\nThe return value `Result` is interpreted as follows:\n\n- **`{ok,State}`\\\n `{ok,State,_}`** - Initialization was succesful\n and `State` is the internal state of the `gen_server` process.\n\n- **`{ok,_,Timeout}`\\\n `{ok,_,hibernate}`\\\n `{ok,_,{continue,Continue}}`** - See the corresponding return values from\n [`Module:handle_call/3`](`c:handle_call/3`) for a description\n of this tuple member.\n\n- **`{stop,Reason}`** - Initialization failed. The `gen_server`\n process exits with reason `Reason`.\n\n- **`{error,Reason}` _since OTP 26.0_\\\n `ignore`** - Initialization failed. The `gen_server` process exits\n with reason `normal`.\n\nSee function [`start_link/3,4`](`start_link/3`)'s return value\n`t:start_ret/0` in these different cases.","title":"gen_server.init/1","ref":"gen_server.html#c:init/1"},{"type":"function","doc":"Call servers on multiple nodes in parallel.\n\nEquivalent to [`multi_call(Nodes, Name, Request)`](`multi_call/3`)\nwhere `Nodes` is all nodes connected to the calling node,\nincluding the calling node itself.","title":"gen_server.multi_call/2","ref":"gen_server.html#multi_call/2"},{"type":"function","doc":"","title":"gen_server.multi_call/3","ref":"gen_server.html#multi_call/3"},{"type":"function","doc":"Call servers on multiple nodes in parallel.\n\nMakes a synchronous call to all `gen_server` processes\nlocally registered as `Name` at the specified nodes,\nby first sending the request to the nodes, and then waiting\nfor the replies. The `gen_server` processes on the nodes call\n[`Module:handle_call/3`](`c:handle_call/3`) to handle the request.\n\nThe function returns a tuple `{Replies, BadNodes}`,\nwhere `Replies` is a list of `{Node, Reply}` tuples,\nand `BadNodes` is a list of nodes that either did not exist,\nwhere `Name` was not a registered `gen_server`,\nor where it did not reply.\n\n`Nodes` is a list of node names to which the request is to be sent.\n\n`Name` is the locally registered name for each `gen_server` process.\n\n`Request` is any term that is passed as the first argument to\n[`Module:handle_call/3`](`c:handle_call/3`).\n\n`Timeout` is an integer that specifies how many milliseconds\nto wait for all replies, or the atom `infinity` to wait indefinitely.\nIf no reply is received from a node within the specified time,\nthe node is added to `BadNodes`.\n\nWhen a reply `Reply` is received from the `gen_server` process\nat a node `Node`, `{Node,Reply}` is added to `Replies`.\n`Reply` is passed from the return value of\n[`Module:handle_call/3`](`c:handle_call/3`).\n\n> #### Warning {: .warning }\n>\n> If one of the nodes cannot process monitors, for example,\n> C or Java nodes, and the `gen_server` process is not started\n> when the requests are sent, but starts within 2 seconds,\n> this function waits the whole `Timeout`, which may be infinity.\n>\n> This problem does not exist if all nodes are Erlang nodes.\n\nTo prevent late answers (after the time-out)\nfrom polluting the message queue of the caller,\na middleman process is used to do the calls.\nLate answers are then discarded when they arrive to\nthe terminated middleman process.","title":"gen_server.multi_call/4","ref":"gen_server.html#multi_call/4"},{"type":"function","doc":"Receive a request response.\n\nReceive a response corresponding to the request identifier `ReqId`.\nThe request must have been made by `send_request/2`,\nand it must have been made by the same process calling this function.\n\n`Timeout` specifies how long to wait for a response.\nIf no response is received within the specified time,\nthis function returns `timeout`. Assuming that the\nserver executes on a node supporting aliases (introduced in OTP 24)\nthe request will also be abandoned. That is,\nno response will be received after a time-out.\nOtherwise, a stray response might be received at a later time.\n\nThe return value `Reply` is passed from the return value of\n[`Module:handle_call/3`](`c:handle_call/3`).\n\nThe function returns an error if the `gen_server` died\nbefore a reply was sent.\n\nThe difference between `receive_response/2` and `wait_response/2`\nis that `receive_response/2` abandons the request at time-out\nso that a potential future response is ignored,\nwhile `wait_response/2` does not.","title":"gen_server.receive_response/2","ref":"gen_server.html#receive_response/2"},{"type":"function","doc":"Receive a request response in a collection.\n\nReceive a response in `ReqIdCollection`. All request identifiers\nof `ReqIdCollection` must correspond to requests that have been made\nusing `send_request/2` or `send_request/4`, and all requests\nmust have been made by the process calling this function.\n\nThe `Label` in the response is the `Label` associated with\nthe request identifier that the response corresponds to.\nThe `Label` of a request identifier is associated\nwhen [adding the request id](`reqids_add/3`) to a collection,\nor when sending the request using `send_request/4`.\n\nCompared to `receive_response/2`, the returned result or exception\nassociated with a specific request identifier will be wrapped\nin a 3-tuple `{Response, Label, NewReqIdCollection}`.\n`Response` is the value that would have been produced\nby `receive_response/2`, `Label` is the value associated with\nthe specific [request identifier](`t:request_id/0`)\nand `NewReqIdCollection` is a possibly modified\nrequest identifier collection.\n\nIf `ReqIdCollection` is empty, `no_request` will be returned.\n\n`Timeout` specifies how long to wait for a response. If no response\nis received within the specified time, the function returns `timeout`.\nAssuming that the server executes on a node supporting aliases\n(introduced in OTP 24) all requests identified by `ReqIdCollection`\nwill also be abandoned. That is, no responses will be received\nafter a time-out. Otherwise, stray responses might be received\nat a later time.\n\nThe difference between `receive_response/3` and `wait_response/3`\nis that `receive_response/3` abandons the requests at time-out\nso that potential future responses are ignored,\nwhile [`wait_response/3`](`wait_response/3`) does not.\n\nIf `Delete` is `true`, the association with `Label`\nis deleted from `ReqIdCollection` in the resulting\n`NewReqIdCollection`. If `Delete` is `false`, `NewReqIdCollection`\nwill equal `ReqIdCollection`. Note that deleting an association\nis not for free and that a collection containing already handled\nrequests can still be used by subsequent calls to\n`receive_response/3`, `check_response/3`, and `wait_response/3`.\n\nHowever, without deleting handled associations,\nthe above calls will not be able to detect when there are\nno more outstanding requests to handle, so you will have to keep track\nof this some other way than relying on a `no_request` return.\nNote that if you pass a collection only containing\nassociations of already handled or abandoned requests to\nthis function, it will always block until `Timeout` expires\nand then return `timeout`.","title":"gen_server.receive_response/3","ref":"gen_server.html#receive_response/3"},{"type":"function","doc":"Send a reply to a client.\n\nThis function can be used by a `gen_server` process to explicitly send\na reply to a client that called [`call/2,3`](`call/2`) or\n[`multi_call/2,3,4`](`multi_call/2`), when the reply cannot be passed\nin the return value of [`Module:handle_call/3`](`c:handle_call/3`).\n\n`Client` must be the `From` argument provided to the `c:handle_call/3`\ncallback function. `Reply` is any term passed back to the client\nas the return value of `call/2,3` or `multi_call/2,3,4`.","title":"gen_server.reply/2","ref":"gen_server.html#reply/2"},{"type":"function","doc":"Store a request identifier in a colletion.\n\nStores `ReqId` and associates a `Label` with the request identifier\nby adding this information to `ReqIdCollection` and returning\nthe resulting request identifier collection.","title":"gen_server.reqids_add/3","ref":"gen_server.html#reqids_add/3"},{"type":"function","doc":"Create an empty request identifier collection.\n\nReturns a new empty request identifier collection.\nA request identifier collection can be utilized to handle\nmultiple outstanding requests.\n\nRequest identifiers of requests made by `send_request/2`\ncan be stored in a collection using `reqids_add/3`.\nSuch a collection of request identifiers can later be used\nin order to get one response corresponding to a request\nin the collection by passing the collection as argument to\n`receive_response/3`, `wait_response/3`, or, `check_response/3`.\n\n`reqids_size/1` can be used to determine the number of\nrequest identifiers in a collection.","title":"gen_server.reqids_new/0","ref":"gen_server.html#reqids_new/0"},{"type":"function","doc":"Returns the number of request identifiers in `ReqIdCollection`.","title":"gen_server.reqids_size/1","ref":"gen_server.html#reqids_size/1"},{"type":"function","doc":"Convert a request identifier collection to a list.\n\nReturns a list of `{ReqId, Label}` tuples which corresponds to\nall request identifiers with their associated labels\nin [`ReqIdCollection`](`t:request_id_collection/0`).","title":"gen_server.reqids_to_list/1","ref":"gen_server.html#reqids_to_list/1"},{"type":"function","doc":"Send an asynchronous `call` request.\n\nSends `Request` to the `gen_server` process identified by `ServerRef`\nand returns a request identifier `ReqId`.\n\nThe return value `ReqId` shall later be used with `receive_response/2`,\n`wait_response/2`, or `check_response/2` to fetch the actual result\nof the request. Besides passing the request identifier directly\nto these functions, it can also be stored in\na request identifier collection using `reqids_add/3`.\nSuch a collection of request identifiers can later be used\nin order to get one response corresponding to a\nrequest in the collection by passing the collection\nas argument to `receive_response/3`, `wait_response/3`,\nor `check_response/3`. If you are about to store the request identifier\nin a collection, you may want to consider using `send_request/4` instead.\n\nThe call\n`gen_server:receive_response(gen_server:send_request(ServerRef, Request), Timeout)`\ncan be seen as equivalent to\n[`gen_server:call(ServerRef, Request, Timeout)`](`call/3`),\nignoring the error handling.\n\nThe `gen_server` process calls [`Module:handle_call/3`](`c:handle_call/3`) to\nhandle the request.\n\nSee the type `t:server_ref/0` for the possible values for `ServerRef`.\n\n`Request` is any term that is passed as the first argument to\n[`Module:handle_call/3`](`c:handle_call/3`).","title":"gen_server.send_request/2","ref":"gen_server.html#send_request/2"},{"type":"function","doc":"Send an asynchronous `call` request and add it\nto a request identifier collection.\n\nSends `Request` to the `gen_server` process identified by `ServerRef`.\nThe `Label` will be associated with the request identifier\nof the operation and added to the returned request identifier collection\n`NewReqIdCollection`. The collection can later be used in order to\nget one response corresponding to a request in the collection\nby passing the collection as argument to `receive_response/3`,\n`wait_response/3`, or `check_response/3`.\n\nThe same as calling\n[`reqids_add`](`reqids_add/3`)`(`[`send_request`](`send_request/2`)`(ServerRef, Request), Label, ReqIdCollection)`,\nbut slightly more efficient.","title":"gen_server.send_request/4","ref":"gen_server.html#send_request/4"},{"type":"function","doc":"Start a server, neither linked nor registered.\n\nEquivalent to `start/4` except that the `gen_server` process is not\nregistered with any [name service](`t:server_name/0`).","title":"gen_server.start/3","ref":"gen_server.html#start/3"},{"type":"function","doc":"Start a server, neither linked nor registered.\n\nCreates a standalone `gen_server` process, that is,\na `gen_server` process that is not part of a supervision tree,\nand thus has no supervisor.\n\nOther than that see `start_link/4`.","title":"gen_server.start/4","ref":"gen_server.html#start/4"},{"type":"function","doc":"Start a server, linked but not registered.\n\nEquivalent to `start_link/4` except that the `gen_server` process is\nnot registered with any [name service](`t:server_name/0`).","title":"gen_server.start_link/3","ref":"gen_server.html#start_link/3"},{"type":"function","doc":"Start a server, linked but not registered.\n\nCreates a `gen_server` process as part of a supervision tree.\nThis function is to be called, directly or indirectly, by the supervisor.\nFor example, it ensures that the `gen_server` process is spawned\nas linked to the caller (supervisor).\n\nThe `gen_server` process calls [`Module:init/1`](`c:init/1`)\nto initialize. To ensure a synchronized startup procedure,\n`start_link/3,4` does not return until [`Module:init/1`](`c:init/1`)\nhas returned or failed.\n\n[`ServerName`](`t:server_name/0`) specifies with what name\nand now to register the server name. See type `t:server_name/0`\nfor different name registrations.\n\n`Module` is the name of the callback module.\n\n`Args` is any term that is passed as the argument to\n[`Module:init/1`](`c:init/1`).\n\nSee type `t:start_opt/0` for `Options` for starting\nthe `gen_server` process.\n\nSee type `t:start_ret/0` for a description this function's return values.\n\nIf `start_link/3,4` returns `ignore` or `{error, _}`,\nthe started `gen_server` process has terminated. If an `'EXIT'` message\nwas delivered to the calling process (due to the process link),\nthat message has been consumed.\n\n> #### Warning {: .warning }\n>\n> Before OTP 26.0, if the started `gen_server` process returned e.g.\n> `{stop, Reason}` from [`Module:init/1`](`c:init/1`), this function\n> could return `{error, Reason}` _before_ the started `m:gen_server` process\n> had terminated so starting again might fail because VM resources\n> such as the registered name was not yet unregistered. An `'EXIT'` message\n> could arrive later to the process calling this function.\n>\n> But if the started `gen_server` process instead failed during\n> [`Module:init/1`](`c:init/1`), a process link `{'EXIT', Pid, Reason}`\n> message caused this function to return `{error, Reason}`,\n> so the `'EXIT'` message had been consumed and the started\n> `m:gen_server` process had terminated.\n>\n> Since it was impossible to tell the difference between these two cases\n> from `start_link/3,4`'s return value, this inconsistency was cleaned up\n> in OTP 26.0.\n\nThe difference between returning `{stop, _}` and `{error, _}` from\n[`Module:init/1`](`c:init/1`), is that `{error, _}` results in a graceful\n(\"silent\") termination since the `gen_server` process exits\nwith reason `normal`.","title":"gen_server.start_link/4","ref":"gen_server.html#start_link/4"},{"type":"function","doc":"Start a server, monitored but neither linked nor registered.\n\nEquivalent to `start_monitor/4` except that the `gen_server` process\nis not registered with any [name service](`t:server_name/0`).","title":"gen_server.start_monitor/3","ref":"gen_server.html#start_monitor/3"},{"type":"function","doc":"Start a server, monitored and registered, but not linked.\n\nCreates a standalone `gen_server` process, that is,\na `gen_server` process that is not part of a supervision tree\n(and thus has no supervisor) and atomically sets up a monitor\nto the newly created server.\n\nOther than that see [`start_link/3,4`](`start_link/3`).\nNote that the return value for a successful start differs in that\nit returns a monitor `reference`. See type `t:start_mon_ret/0`.\n\nIf the start is not successful, the caller will be blocked\nuntil the monitor's `'DOWN'` message has been received\nand removed from the message queue.","title":"gen_server.start_monitor/4","ref":"gen_server.html#start_monitor/4"},{"type":"function","doc":"","title":"gen_server.stop/1","ref":"gen_server.html#stop/1"},{"type":"function","doc":"Stop a server.\n\nOrders the generic server specified by `ServerRef` to exit\nwith the specified `Reason` and waits for it to terminate.\nThe `gen_server` process calls [`Module:terminate/2`](`c:terminate/2`)\nbefore exiting.\n\nThe function returns `ok` if the server terminates\nwith the expected reason. Any other reason than `normal`, `shutdown`,\nor `{shutdown,Term}` causes an error report to be issued using `m:logger`.\nAn exit signal with the same reason is sent to linked processes and ports.\n\n`Timeout` is an integer that specifies how many milliseconds to wait\nfor the server to terminate, or the atom `infinity` to wait indefinitely.\nIf the server has not terminated within the specified time,\nthe call exits the calling process with reason `timeout`.\n\nIf the process does not exist, the call exits the calling process\nwith reason `noproc`, or with reason `{nodedown,Node}`\nif the connection fails to the remote `Node` where the server runs.","title":"gen_server.stop/3","ref":"gen_server.html#stop/3"},{"type":"callback","doc":"Handle server termination.\n\nThis function is called by a `gen_server` process\nwhen it is about to terminate.\n\nIt is to be the opposite of [`Module:init/1`](`c:init/1`)\nand do any necessary cleaning up. When it returns,\nthe `gen_server` process terminates with `Reason`.\nThe return value is ignored.\n\n`Reason` is a term denoting the stop reason and `State`\nis the internal state of the `gen_server` process.\n\n`Reason` depends on why the `gen_server` process is terminating.\nIf it is because another callback function has returned a stop tuple\n`{stop,..}`, `Reason` has the value specified in that tuple.\nIf it is because of a failure, `Reason` is the error reason.\n\nIf the `gen_server` process is part of a supervision tree\nand is ordered by its supervisor to terminate, this function is called\nwith `Reason=shutdown` if the following conditions apply:\n\n- The `gen_server` process has been set to trap exit signals.\n- The shutdown strategy as defined in the child specification\n of the supervisor is an integer time-out value, not `brutal_kill`.\n\nEven if the `gen_server` process is _not_ part of a supervision tree,\nthis function is called if it receives an `'EXIT'` message from its parent.\n`Reason` is the same as in the `'EXIT'` message.\n\nIf the `gen_server` process does not trap exits,\nthe `gen_server` process terminates immediately.\n\nNotice that for any other reason than `normal`, `shutdown`, or\n`{shutdown,Term}`, see `stop/3`, the `gen_server` process is assumed\nto terminate because of an error, and an error report is issued\nusing `m:logger`.\n\nWhen the gen_server process exits, an exit signal with the same reason\nis sent to linked processes and ports.\n\n> #### Note {: .info }\n>\n> This callback is optional, so callback modules need not export it.\n> The `gen_server` module provides a default implementation\n> with no cleanup.","title":"gen_server.terminate/2","ref":"gen_server.html#c:terminate/2"},{"type":"function","doc":"Wait for a request response.\n\nWait for the response to the request identifier `ReqId`. The request\nmust have been made by `send_request/2`, and it must have been made\nby the same process calling this function.\n\n`WaitTime` specifies how long to wait for a reply.\nIf no reply is received within the specified time,\nthe function returns `timeout` and no cleanup is done.\nThus the function can be invoked repeatedly until a reply is returned.\n\nThe return value `Reply` is passed from the return value of\n[`Module:handle_call/3`](`c:handle_call/3`).\n\nThe function returns an error if the `gen_server`\ndied before a reply was sent.\n\nThe difference between `receive_response/2` and\n`wait_response/2` is that `receive_response/2` abandons\nthe request at time-out so that a potential future response is ignored,\nwhile [`wait_response/2`](`wait_response/2`) does not.","title":"gen_server.wait_response/2","ref":"gen_server.html#wait_response/2"},{"type":"function","doc":"Wait for any request response in a collection.\n\nWait for a response in a `ReqIdCollection`. All request identifiers\nof `ReqIdCollection` must correspond to requests that have been made\nusing `send_request/2` or `send_request/4`, and all requests\nmust have been made by the process calling this function.\n\nThe `Label` in the response is the `Label` associated with\nthe request identifier that the response corresponds to.\nThe `Label` of a request identifier is associated\nwhen [adding the request id](`reqids_add/3`) to a collection,\nor when sending the request using `send_request/4`.\n\nCompared to `wait_response/2`, the returned result or exception\nassociated with a specific request identifier will be wrapped\nin a 3-tuple `{Response, Label, NewReqIdCollection}`.\n`Response` is the value that would have been produced\nby `wait_response/2`, `Label` is the value associated with\nthe specific [request identifier](`t:request_id/0`)\nand `NewReqIdCollection` is a possibly modified\nrequest identifier collection.\n\nIf `ReqIdCollection` is empty, `no_request` will be returned.\n\nIf no response is received before `WaitTime` has expired,\n`timeout` is returned. It is valid to continue waiting\nfor a response as many times as needed up until a response\nhas been received and completed by `check_response()`,\n`receive_response()`, or `wait_response()`.\n\nThe difference between `receive_response/3` and `wait_response/3`\nis that `receive_response/3` abandons requests at time-out\nso that potential future responses are ignored, while\n`wait_response/3` does not.\n\nIf `Delete` is `true`, the association with `Label`\nhas been deleted from `ReqIdCollection` in the resulting\n`NewReqIdCollection`. If `Delete` is `false`, `NewReqIdCollection`\nwill equal `ReqIdCollection`. Note that deleting an association\nis not for free and that a collection containing already handled\nrequests can still be used by subsequent calls to\n`wait_response/3`, `check_response/3`, and `receive_response/3`.\n\nHowever, without deleting handled associations, the above\ncalls will not be able to detect when there are\nno more outstanding requests to handle, so you will have to keep track\nof this some other way than relying on a `no_request` return.\nNote that if you pass a collection only containing\nassociations of already handled or abandoned requests\nto this function, it will always block until `WaitTime` expires\nand then return `timeout`.","title":"gen_server.wait_response/3","ref":"gen_server.html#wait_response/3"},{"type":"type","doc":"Server start options for the [`start`](`start_link/4`) or\n[`enter_loop`](`enter_loop/5`) functions.\n\nOptions that can be used when starting a `gen_server` server through\n[`enter_loop/3-5`](`enter_loop/5`) or the start functions such as\n[`start_link/3,4`](`start_link/4`).\n\n- **`{hibernate_after, HibernateAfterTimeout}`** - Specifies that the\n `gen_server` process awaits any message for `HibernateAfterTimeout`\n milliseconds and if no message is received, the process goes into\n hibernation automatically (by calling `proc_lib:hibernate/3`).\n\n- **`{debug, Dbgs}`** - For every entry in `Dbgs`,\n the corresponding function in `m:sys` is called.","title":"gen_server.enter_loop_opt/0","ref":"gen_server.html#t:enter_loop_opt/0"},{"type":"type","doc":"A map that describes the `gen_server` status.\n\nThe keys are:\n- **`state`** - The internal state of the `gen_server` process.\n- **`message`** - The message that caused the server to terminate.\n- **`reason`** - The reason that caused the server to terminate.\n- **`log`** - The [sys log](`sys:log/2`) of the server.\n\nNew associations may be added to the status map without prior notice.","title":"gen_server.format_status/0","ref":"gen_server.html#t:format_status/0"},{"type":"type","doc":"A call's reply destination.\n\nDestination, given to the `gen_server` as the first argument\nto the callback function [`Module:handle_call/3`](`c:handle_call/3`),\nto be used by the when replying through `reply/2` (instead of\nthrough the callback function's return value), to the process `Client`\nthat has called the `gen_server` using [`call/2,3`](`call/2`).\n`Tag` is a term that is unique for this call/request instance.","title":"gen_server.from/0","ref":"gen_server.html#t:from/0"},{"type":"opaque","doc":"A handle that associates a reply to the corresponding request.","title":"gen_server.reply_tag/0","ref":"gen_server.html#t:reply_tag/0"},{"type":"opaque","doc":"An opaque request identifier. See `send_request/2` for details.","title":"gen_server.request_id/0","ref":"gen_server.html#t:request_id/0"},{"type":"opaque","doc":"An opaque collection of request identifiers (`t:request_id/0`).\n\nEach request identifier can be associated with a label\nchosen by the user. For more information see `reqids_new/0`.","title":"gen_server.request_id_collection/0","ref":"gen_server.html#t:request_id_collection/0"},{"type":"type","doc":"Response time-out for an asynchronous call.\n\nUsed to set a time limit on how long to wait for a response using either\n`receive_response/2`, `receive_response/3`, `wait_response/2`, or\n`wait_response/3`. The time unit used is `millisecond`.\n\nCurrently valid values:\n\n- **`0..4294967295`** - Time-out relative to current time in milliseconds.\n\n- **`infinity`** - Infinite time-out. That is,\n the operation will never time out.\n\n- **`{abs, Timeout}`** - An absolute\n [Erlang monotonic time](`erlang:monotonic_time/1`)\n time-out in milliseconds. That is, the operation will time out when\n [`erlang:monotonic_time(millisecond)`](`erlang:monotonic_time/1`)\n returns a value larger than or equal to `Timeout`.\n `Timeout` is not allowed to identify a time further into the future\n than `4294967295` milliseconds. Specifying the time-out\n using an absolute value is especially handy when you have\n a deadline for responses corresponding to a complete collection\n of requests (`t:request_id_collection/0`), since you do not have to\n recalculate the relative time until the deadline over and over again.","title":"gen_server.response_timeout/0","ref":"gen_server.html#t:response_timeout/0"},{"type":"type","doc":"Server name specification: `local`, `global`, or `via` registered.\n\nTo be used when starting a `gen_server`. See functions\n[`start/3,4`](`start/3`),\n[`start_link/3,4`](`start_link/3`),\n[`start_monitor/3,4`](`start_monitor/3`),\n[`enter_loop/3,4,5`](`enter_loop/3`), and the type `t:server_ref/0`.\n\n- **`{local, LocalName}`** - Register the `gen_server` locally\n as `LocalName` using [`register/2`](`erlang:register/2`).\n\n- **`{global, GlobalName}`** - Register the `gen_server` process id\n globally as `GlobalName` using `global:register_name/2`.\n\n- **`{via, RegMod, ViaName}`** - Register the `gen_server` process\n with the registry represented by `RegMod`. The `RegMod` callback\n is to export the functions `register_name/2`, `unregister_name/1`,\n `whereis_name/1`, and `send/2`, which are to behave like\n the corresponding functions in `m:global`.\n Thus, `{via, global, GlobalName}` is a valid reference\n equivalent to `{global, GlobalName}`.","title":"gen_server.server_name/0","ref":"gen_server.html#t:server_name/0"},{"type":"type","doc":"Server specification: `t:pid/0` or registered `t:server_name/0`.\n\nTo be used when addressing a `gen_server`. See [`call/2,3`](`call/2`),\n`cast/2`, `send_request/2`, `check_response/2`, `wait_response/2`,\n[`stop/2,3`](`stop/1`) and the type `t:server_name/0`.\n\nIt can be:\n\n- **`t:pid/0`** - The `gen_server`'s process identifier.\n\n- **`LocalName`** - The `gen_server` is locally registered\n as `LocalName` with [`register/2`](`erlang:register/2`).\n\n- **`{Name,Node}`** - The `gen_server` is locally registered\n on another node.\n\n- **`{global, GlobalName}`** - The `gen_server` is globally registered\n in `m:global`.\n\n- **`{via, RegMod, ViaName}`** - The `gen_server` is registered\n in an alternative process registry. See the same term\n described for `t:server_name/0`.","title":"gen_server.server_ref/0","ref":"gen_server.html#t:server_ref/0"},{"type":"type","doc":"Return value from the [`start_monitor/3,4`](`start_monitor/3`) functions.\n\nThe same as type `t:start_ret/0` except that for a succesful start\nit returns both the process identifier `Pid`\nand a [`monitor/2,3`](`erlang:monitor/2`) [`MonRef`](`t:reference/0`).","title":"gen_server.start_mon_ret/0","ref":"gen_server.html#t:start_mon_ret/0"},{"type":"type","doc":"Server start options for the [`start` functions](`start_link/3`).\n\nOptions that can be used when starting a `gen_server` server through,\nfor example, [`start_link/3,4`](`start_link/4`).\n\n- **`{timeout, Timeout}`** - How many milliseconds\n the `gen_server` process is allowed to spend initializing\n or it is terminated and the start function returns `{error, timeout}`.\n\n- **`{spawn_opt, SpawnOptions}`** - The `SpawnOptions` option list\n is passed to the function used to spawn the `gen_server`;\n see `t:proc_lib:start_spawn_option/0`).\n\n > #### Note {: .info }\n >\n > Using spawn option `monitor` is not allowed -\n > it causes a `badarg` failure.\n\n- **`t:enter_loop_opt/0`** - See the type `t:enter_loop_opt/0`\n below for more start options that are also allowed\n by [`enter_loop/3,4,5`](`enter_loop/3`).","title":"gen_server.start_opt/0","ref":"gen_server.html#t:start_opt/0"},{"type":"type","doc":"Return value from the [`start/3,4`](`start/3`) and\n[`start_link/3,4`](`start_link/3`) functions.\n\n- **`{ok, Pid}`** - The `gen_server` process was succesfully created and\n initialized, with the process identifier `Pid`.\n\n- **`{error, {already_started, OtherPid}}`** - A process with the specified\n `ServerName` exists already with the process identifier `OtherPid`.\n This function failed to start a `gen_server`. It exited with reason\n `normal` before calling [`Module:init/1`](`c:init/1`).\n\n- **`{error, timeout}`** - The `gen_server` process failed to initialize\n since [`Module:init/1`](`c:init/1`) did not return within the\n [start time-out](`t:start_opt/0`). The `gen_server` process was killed\n with [`exit(_, kill)`](`erlang:exit/2`).\n\n- **`ignore`** - The `gen_server` process failed to initialize since\n [`Module:init/1`](`c:init/1`) returned `ignore`.\n\n- **`{error,Reason}`** - The `gen_server` process failed to initialize since\n [`Module:init/1`](`c:init/1`) returned `{stop,Reason}`, `{error,Reason}`,\n or it failed with reason `Reason`.\n\nSee [`Module:init/1`](`c:init/1`) about the exit reason\nfor the `gen_server` process when it fails to initialize.","title":"gen_server.start_ret/0","ref":"gen_server.html#t:start_ret/0"},{"type":"behaviour","doc":"Generic state machine behavior.\n\n`gen_statem` provides a generic state machine behaviour\nthat since Erlang/OTP 20.0 replaces its predecessor `m:gen_fsm`,\nand should be used for new code. The `gen_fsm` behaviour\nremains in OTP \"as is\" to not break old code using it.\n\nA generic state machine server process (`gen_statem`) implemented\nusing this module has a standard set of interface functions\nand includes functionality for tracing and error reporting.\nIt also fits into an OTP supervision tree. For more information,\nsee [OTP Design Principles](`e:system:statem.md`).\n\n> #### Note {: .info }\n>\n> If you are new to `gen_statem` and want an overview\n> of concepts and operation the section\n> [`gen_statem` Behaviour](`e:system:statem.md`) located in\n> the User's Guide [OTP Design Principles](`e:system:index.html`)\n> is recommended to read. This reference manual focuses on\n> being correct and complete, which might make it hard to see\n> the forest for all the trees.\n\n#### Features\n\n`gen_statem` has got the same features that `m:gen_fsm` had\nand adds some really useful:\n\n- [Co-located state code](#state_functions)\n- [Arbitrary term state](#handle_event_function)\n- [Event postponing](#event-postponing)\n- [Self-generated events](#event-insertion)\n- [State time-out](`t:state_timeout/0`)\n- [Multiple generic named time-outs](`t:generic_timeout/0`)\n- [Absolute time-out time](`t:timeout_option/0`)\n- [Automatic state enter calls](#state-enter-calls)\n- [Reply from other state than the request](#reply-to-a-call),\n traceable with `m:sys`\n- [Multiple replies](#reply-to-a-call), traceable with `m:sys`\n- [Changing the callback module](#change_callback_module)\n\nTwo [_callback modes_](`t:callback_mode/0`) are supported:\n\n- `state_functions` - for finite-state machines (`m:gen_fsm` like),\n which requires the state to be an atom and uses that state\n as the name of the current callback function, arity 3.\n- `handle_event_function` - that allows the state to be any term\n and that uses `c:handle_event/4` as callback function for all states.\n\nThe callback modes for `gen_statem` differs from the one for\n`gen_fsm`, but it is still fairly easy to\nrewrite from `gen_fsm` to `gen_statem`. See the\n[rewrite guide](`m:gen_fsm#module-migration-to-gen_statem`)\nat the start of the `m:gen_fsm` documentation.\n\n#### Callback module\n\nA `gen_statem` assumes all specific parts to be located\nin a callback module exporting a predefined set of functions.\nThe relationship between the behavior functions\nand the callback functions is as follows:\n\n```\ngen_statem module Callback module\n----------------- ---------------\ngen_statem:start\ngen_statem:start_monitor\ngen_statem:start_link -----> Module:init/1\n\nServer start or code change\n -----> Module:callback_mode/0\n selects callback mode\n\ngen_statem:stop\nSupervisor exit\nCallback failure -----> Module:terminate/3\n\ngen_statem:call\ngen_statem:cast\ngen_statem:send_request\nerlang:send\nerlang:'!' -----> Module:StateName/3\n or -----> Module:handle_event/4\n depending on callback mode\n\nRelease upgrade/downgrade\n(code change)\n -----> Module:code_change/4\n```\n\n#### State callback {: #state-callback }\n\nThe _state callback_ for a specific [state](`t:state/0`) in a `gen_statem`\nis the callback function that is called for all events in this state.\nIt is selected depending on which [_callback mode_](`t:callback_mode/0`)\nthat the callback module defines with the callback function\n[`Module:callback_mode/0`](`c:callback_mode/0`).\n\n[](){: #state_functions }\nWhen the [_callback mode_](`t:callback_mode/0`) is `state_functions`,\nthe state must be an atom and is used as the _state callback_ name;\nsee [`Module:StateName/3`](`c:'StateName'/3`). This co-locates all code\nfor a specific state in one function as the `gen_statem` engine branches\ndepending on state name. Note the fact that the callback function\n[`Module:terminate/3`](`c:terminate/3`) makes the state name `terminate`\nunusable in this mode.\n\n[](){: #handle_event_function }\nWhen the [_callback mode_](`t:callback_mode/0`) is `handle_event_function`,\nthe state can be any term and the _state callback_ name is\n[`Module:handle_event/4`](`c:handle_event/4`). This makes it easy\nto branch depending on state or event as you desire. Be careful about\nwhich events you handle in which states so that you do not accidentally\npostpone an event forever creating an infinite busy loop.\n\n#### Event types\n\nEvents are of different [types](`t:event_type/0`),\ntherefore the callback functions can know the origin of an event\nwhen handling it. [External events](`t:external_event_type/0`) are\n`call`, `cast`, and `info`. Internal events are\n[`timeout`](`t:timeout_event_type/0`) and `internal`.\n\n#### Event handling\n\nWhen `gen_statem` receives a process message it is transformed\ninto an event and the [_state callback_](#state-callback)\nis called with the event as two arguments: type and content. When the\n[_state callback_](#state-callback) has processed the event\nit returns to `gen_statem` which does a _state transition_. If this\n_state transition_ is to a different state, that is: `NextState =/= State`,\nit is a _state change_.\n\n#### Transition actions\n\nThe [_state callback_](#state-callback) may return\n[_transition actions_](`t:action/0`) for `gen_statem` to execute\nduring the _state transition_, for example to set a time-out\nor reply to a call.\n\n#### Reply to a call {: #reply-to-a-call }\n\nSee [`gen_statem:call/2,3`](#call-reply) about how to reply\nto a call. A reply can be sent from any _state callback_,\nnot just the one that got the request event.\n\n#### Event postponing {: #event-postponing }\n\nOne of the possible _transition actions_ is to postpone the current event.\nThen it will not be handled in the current state. The `gen_statem` engine\nkeeps a queue of events divided into postponed events and\nevents still to process (not presented yet). After a _state change_\nthe queue restarts with the postponed events.\n\nThe `gen_statem` event queue model is sufficient to emulate\nthe normal process message queue with selective receive.\nPostponing an event corresponds to not matching it\nin a receive statement, and changing states corresponds to\nentering a new receive statement.\n\n#### Event insertion {: #event-insertion }\n\nThe [_state callback_](#state-callback) can insert\nevents using the [_transition action_](`t:action/0`) `next_event`,\nand such an event is inserted in the event queue as the next to call the\n[_state callback_](#state-callback) with. That is,\nas if it is the oldest incoming event. A dedicated `t:event_type/0`\n`internal` can be used for such events making it possible to\nsafely distinguish them from external events.\n\nInserting an event replaces the trick of calling your own state handling\nfunctions that you often would have to resort to in, for example,\n`m:gen_fsm` to force processing an inserted event before others.\n\n> #### Note {: .info }\n>\n> If you postpone an event and (against good practice) directly call\n> a different _state callback_, the postponed event is not retried,\n> since there was no _state change_.\n>\n> Instead of directly calling a _state callback_, do a _state change_.\n> This makes the `gen_statem` engine retry postponed events.\n>\n> Inserting an event in a _state change_ also triggers\n> the new _state callback_ to be called with that event\n> before receiving any external events.\n\n#### State enter calls {: #state-enter-calls }\n\nThe `gen_statem` engine can automatically make a special call to the\n[_state callback_](#state-callback) whenever a new state is\nentered; see `t:state_enter/0`. This is for writing code common\nto all state entries. Another way to do it is to explicitly insert\nan event at the _state transition_, and/or to use a dedicated\n_state transition_ function, but that is something you will have to\nremember at every _state transition_ to the state(s) that need it.\n\nFor the details of a _state transition_, see type `t:transition_option/0`.\n\n#### Hibernation\n\nThe `gen_statem` process can go into hibernation;\nsee `proc_lib:hibernate/3`. It is done when\na [_state callback_](#state-callback) or\n[`Module:init/1`](`c:init/1`) specifies `hibernate`\nin the returned [`Actions`](`t:enter_action/0`) list. This feature\ncan be useful to reclaim process heap memory while the server\nis expected to be idle for a long time. However, use it with care,\nas hibernation can be too costly to use after every event;\nsee `erlang:hibernate/3`.\n\nThere is also a server start option\n[`{hibernate_after, Timeout}`](`t:enter_loop_opt/0`)\nfor [`start/3,4`](`start/3`), [`start_link/3,4`](`start_link/3`),\n[`start_monitor/3,4`](`start_monitor/3`),\nor [`enter_loop/4,5,6`](`enter_loop/6`), that may be used\nto automatically hibernate the server.\n\n#### Callback failure\n\nIf a callback function fails or returns a bad value,\nthe `gen_statem` terminates. However, an exception of class\n[`throw`](`erlang:throw/1`) is not regarded as an error\nbut as a valid return, from all callback functions.\n\n#### System messages and the `m:sys` module\n\nA `gen_statem` handles system messages as described in `m:sys`.\nThe `m:sys` module can be used for debugging a `gen_statem`.\nReplies sent through [_transition actions_](`t:action/0`)\ngets logged, but not replies sent through [`reply/1,2`](`reply/2`).\n\n#### Trapping exit\n\nA `gen_statem` process, like all `gen_`\\* behaviours,\ndoes not trap exit signals automatically;\nthis must be explicitly initiated in the callback module\n(by calling [`process_flag(trap_exit, true)`](`erlang:process_flag/2`)\npreferably from `c:init/1`.\n\n#### Server termination\n\nIf the `gen_statem` process terminates, e.g. as a result\nof a callback function returning `{stop, Reason}`, an exit signal\nwith this `Reason` is sent to linked processes and ports.\nSee [Processes](`e:system:ref_man_processes.md#errors`)\nin the Reference Manual for details regarding error handling\nusing exit signals.\n\n> #### Note {: .info }\n>\n> For some important information about distributed signals, see the\n> [_Blocking Signaling Over Distribution_\n> ](`e:system:ref_man_processes.md#blocking-signaling-over-distribution`)\n> section in the _Processes_ chapter of the _Erlang Reference Manual_.\n> Blocking signaling can, for example, cause call time-outs in `gen_statem`\n> to be significantly delayed.\n\n#### Bad argument\n\nUnless otherwise stated, all functions in this module fail if the specified\n`gen_statem` does not exist or if bad arguments are specified.","title":"gen_statem","ref":"gen_statem.html"},{"type":"behaviour","doc":"The following example shows a simple pushbutton model\nfor a toggling pushbutton implemented with\n[_callback mode_](`t:callback_mode/0`) `state_functions`.\nYou can push the button and it replies if it went on or off,\nand you can ask for a count of how many times it has been pushed\nto switch on.","title":"Example - gen_statem","ref":"gen_statem.html#module-example"},{"type":"behaviour","doc":"```mermaid\n---\ntitle: Pushbutton State Diagram\n---\nstateDiagram-v2\n [*] --> off\n off --> on : push\\n* Increment count\\n* Reply 'on'\n on --> off : push\\n* Reply 'off'\n```\n\nNot shown in the state diagram:\n* The API function `push()` generates an event `push` of type `call`.\n* The API function `get_count()` generates an event `get_count`\n of type `call` that is handled in all states by replying with\n the current count value.\n* Unknown events are ignored and discarded.\n* There is boilerplate code for start, stop, terminate, code change,\n init, to set the callback mode to `state_functions`, etc...","title":"Pushbutton State Diagram - gen_statem","ref":"gen_statem.html#module-pushbutton-state-diagram"},{"type":"behaviour","doc":"The following is the complete callback module file `pushbutton.erl`:\n\n```erlang\n-module(pushbutton).\n-behaviour(gen_statem).\n\n-export([start/0,push/0,get_count/0,stop/0]).\n-export([terminate/3,code_change/4,init/1,callback_mode/0]).\n-export([on/3,off/3]).\n\nname() -> pushbutton_statem. % The registered server name\n\n%% API. This example uses a registered name name()\n%% and does not link to the caller.\nstart() ->\n gen_statem:start({local,name()}, ?MODULE, [], []).\npush() ->\n gen_statem:call(name(), push).\nget_count() ->\n gen_statem:call(name(), get_count).\nstop() ->\n gen_statem:stop(name()).\n\n%% Mandatory callback functions\nterminate(_Reason, _State, _Data) ->\n void.\ncode_change(_Vsn, State, Data, _Extra) ->\n {ok,State,Data}.\ninit([]) ->\n %% Set the initial state + data. Data is used only as a counter.\n State = off, Data = 0,\n {ok,State,Data}.\ncallback_mode() -> state_functions.\n\n%%% state callback(s)\n\noff({call,From}, push, Data) ->\n %% Go to 'on', increment count and reply\n %% that the resulting status is 'on'\n {next_state,on,Data+1,[{reply,From,on}]};\noff(EventType, EventContent, Data) ->\n handle_event(EventType, EventContent, Data).\n\non({call,From}, push, Data) ->\n %% Go to 'off' and reply that the resulting status is 'off'\n {next_state,off,Data,[{reply,From,off}]};\non(EventType, EventContent, Data) ->\n handle_event(EventType, EventContent, Data).\n\n%% Handle events common to all states\nhandle_event({call,From}, get_count, Data) ->\n %% Reply with the current count\n {keep_state,Data,[{reply,From,Data}]};\nhandle_event(_, _, Data) ->\n %% Ignore all other events\n {keep_state,Data}.\n```\n\nThe following is a shell session when running it:\n\n```erlang\n1> pushbutton:start().\n{ok,<0.36.0>}\n2> pushbutton:get_count().\n0\n3> pushbutton:push().\non\n4> pushbutton:get_count().\n1\n5> pushbutton:push().\noff\n6> pushbutton:get_count().\n1\n7> pushbutton:stop().\nok\n8> pushbutton:push().\n** exception exit: {noproc,{gen_statem,call,[pushbutton_statem,push,infinity]}}\n in function gen:do_for_proc/2 (gen.erl, line 261)\n in call from gen_statem:call/3 (gen_statem.erl, line 386)\n```\n\nTo compare styles, here follows the same example using\n[_callback mode_](`t:callback_mode/0`) `handle_event_function`,\nor rather, the code to replace after function [`init/1`](`c:init/1`)\nof the `pushbutton.erl` example file above:\n\n```erlang\ncallback_mode() -> handle_event_function.\n\n%%% state callback(s)\n\nhandle_event({call,From}, push, off, Data) ->\n %% Go to 'on', increment count and reply\n %% that the resulting status is 'on'\n {next_state,on,Data+1,[{reply,From,on}]};\nhandle_event({call,From}, push, on, Data) ->\n %% Go to 'off' and reply that the resulting status is 'off'\n {next_state,off,Data,[{reply,From,off}]};\n%%\n%% Event handling common to all states\nhandle_event({call,From}, get_count, State, Data) ->\n %% Reply with the current count\n {next_state,State,Data,[{reply,From,Data}]};\nhandle_event(_, _, State, Data) ->\n %% Ignore all other events\n {next_state,State,Data}.\n```\n\n> #### Note {: .info }\n>","title":"Pushbutton Code - gen_statem","ref":"gen_statem.html#module-pushbutton-code"},{"type":"behaviour","doc":"> - This behavior appeared in Erlang/OTP 19.0 as experimental.\n> - In OTP 19.1 a backwards incompatible change of the return tuple from\n> [`Module:init/1`](`c:init/1`) was made,\n> the mandatory callback function\n> [`Module:callback_mode/0`](`c:callback_mode/0`) was introduced,\n> and `enter_loop/4` was added.\n> - In OTP 19.2 [_state enter calls_](`t:state_enter/0`) were added.\n> - In OTP 19.3 [state time-outs](`t:state_timeout/0`) were added.\n> - In OTP 20.0 [generic time-outs](`t:generic_timeout/0`) were added\n> and `gen_statem` was stated to be no longer experimental and\n> preferred over `gen_fsm`.\n> - In OTP 22.1 time-out content [`update`](`t:timeout_update_action/0`)\n> and explicit time-out [`cancel`](`t:timeout_cancel_action/0`)\n> were added.\n> - In OTP 22.3 the possibility to change the callback module with actions\n> [`change_callback_module`](#change_callback_module),\n> [`push_callback_module`](#push_callback_module) and\n> [`pop_callback_module`](#pop_callback_module), was added.\n> - In OTP 23.0 [`start_monitor/3,4`](`start_monitor/3`) were added,\n> as well as functions for asynchronous calls: `send_request/2`,\n> [`wait_response/1,2`](`wait_response/2`), and `check_response/2`.\n> - In OTP 24.0 [`receive_response/1,2`](`receive_response/2`) were added.\n> - In OTP 25.0 [`Module:format_status/1`](`c:format_status/1`)\n> was added to replace [`Module:format_status/2`](`c:format_status/2`),\n> as well as functions for collections of asynchronous calls:\n> `send_request/4`, `wait_response/3`, `receive_response/3`,\n> `check_response/3`, `reqids_new/0`, `reqids_size/1`,\n> `reqids_add/3`, `reqids_to_list/1`.\n> - In OTP 26.0 the possibility to return `{error, Reason}` from\n> [`Module:init/1`](`c:init/1`) was added.\n> - In OTP 27.0 [`Module:format_status/2`](`c:format_status/2`)\n> was deprecated.","title":"API changes - gen_statem","ref":"gen_statem.html#module-api-changes"},{"type":"behaviour","doc":"`m:gen_event`, `m:gen_fsm`, `m:gen_server`, `m:proc_lib`, `m:supervisor`,\n`m:sys`.","title":"See Also - gen_statem","ref":"gen_statem.html#module-see-also"},{"type":"function","doc":"","title":"gen_statem.call/2","ref":"gen_statem.html#call/2"},{"type":"function","doc":"Call a server: send request and wait for response.\n\nMakes a synchronous call to the `gen_statem`\n[`ServerRef`](`t:server_ref/0`) by sending a request\nand waiting until the response arrives.\n\n[](){: #call-reply }\nThe `gen_statem` calls the\n[_state callback_](#state-callback)\nwith `t:event_type/0` `{call, From}` and event content `Request`.\n\nThe server's reply is sent from a [_state callback_](#state-callback),\nby returning a [_transition action_](`t:action/0`) `{reply, From, Reply}`,\ncalling [`reply(Replies)`](`reply/1`) with such a reply action\nin the `Replies` list, or calling [`reply(From, Reply)`](`reply/2`).\n\n`Timeout` is an integer > 0, which specifies how many milliseconds\nto wait for a reply, or the atom `infinity` to wait indefinitely,\nwhich is the default. If no reply is received within the specified time,\nthe function call fails.\n\nPrevious issue with late replies that could occur\nwhen having network issues or using `dirty_timeout`\nis now prevented by use of\n[_process aliases_](`e:system:ref_man_processes.md#process-aliases`).\n`{clean_timeout, T}` and `{dirty_timeout, T}` therefore\nno longer serves any purpose and will work the same as `Timeout`\nwhile all of them also being equally efficient.\n\nThe call can also fail, for example, if the `gen_statem`\ndies before or during this function call.\n\nWhen this call fails it [exits](`erlang:exit/1`)\nthe calling process. The exit term is on the form\n`{Reason, Location}` where `Location = {gen_statem, call, ArgList}`.\nSee [`gen_server:call/3`](`gen_server:call/3`) that has a description\nof relevant values for the `Reason` in the exit term.","title":"gen_statem.call/3","ref":"gen_statem.html#call/3"},{"type":"callback","doc":"Select the _callback mode_ and possibly\n[_state enter calls_](`t:state_enter/0`).\n\nThis function is called by a `gen_statem` when it needs to find out the\n[_callback mode_](`t:callback_mode/0`) of the callback module.\n\nThe value is cached by `gen_statem` for efficiency reasons,\nso this function is only called once after server start,\nafter code change, and after changing the callback module,\nbut before the first [_state callback_](#state-callback)\nin the current callback module's code is called. More occasions may be\nadded in future versions of `gen_statem`.\n\nServer start happens either when [`Module:init/1`](`c:init/1`)\nreturns or when [`enter_loop/4,5,6`](`enter_loop/6`) is called.\nCode change happens when [`Module:code_change/4`](`c:code_change/4`)\nreturns. A change of the callback module happens when\na [_state callback_](#state-callback) returns\nany of the actions [`change_callback_module`](#push_callback_module),\n[`push_callback_module`](#push_callback_module) or\n[`pop_callback_module`](#pop_callback_module).\n\nThe `CallbackMode` is either just `t:callback_mode/0`\nor a list containing `t:callback_mode/0` and possibly\nthe atom [`state_enter`](`t:state_enter/0`).\n\n> #### Note {: .info }\n>\n> If this function's body does not return an inline constant value\n> the callback module is doing something strange.","title":"gen_statem.callback_mode/0","ref":"gen_statem.html#c:callback_mode/0"},{"type":"function","doc":"Cast an event to a server.\n\nSends an asynchronous `cast` event to the `gen_statem`\n[`ServerRef`](`t:server_ref/0`) and returns `ok` immediately,\nignoring if the destination node or `gen_statem` does not exist.\n\nThe `gen_statem` calls the\n[_state callback_](#state-callback)\nwith `t:event_type/0` `cast` and event content `Msg`.","title":"gen_statem.cast/2","ref":"gen_statem.html#cast/2"},{"type":"function","doc":"Check if a received message is a request response.\n\nChecks if `Msg` is a response corresponding to\nthe request identifier `ReqId`. The request must have been made\nby `send_request/2` and by the same process calling this function.\n\nIf `Msg` is a reply to the handle `ReqId` the result of the request\nis returned in `Reply`. Otherwise this function returns `no_reply`\nand no cleanup is done, and thus the function shall be invoked repeatedly\nuntil the response is returned.\n\nSee [`call/3`](#call-reply) about how the request is handled\nand the `Reply` is sent by the `gen_statem` server.\n\nIf the `gen_statem` server process has died when this function\nis called, that is; `Msg` reports the server's death,\nthis function returns an `error` return with the exit `Reason`.","title":"gen_statem.check_response/2","ref":"gen_statem.html#check_response/2"},{"type":"function","doc":"Check if a received message is a request response in a collection.\n\nCheck if `Msg` is a response corresponding to a request identifier\nstored in `ReqIdCollection`. All request identifiers of `ReqIdCollection`\nmust correspond to requests that have been made using `send_request/2`\nor `send_request/4`, by the process calling this function.\n\nThe `Label` in the response equals the `Label` associated\nwith the request identifier that the response corresponds to.\nThe `Label` of a request identifier is associated\nwhen [storing the request id](`reqids_add/3`) in a collection,\nor when sending the request using `send_request/4`.\n\nCompared to `check_response/2`, the returned result or exception\nassociated with a specific request identifier will be wrapped\nin a 3-tuple `{Response, Label, NewReqIdCollection}`.\n`Response` is the value that would have been produced\nby `check_response/2`, `Label` is the value associated with\nthe specific [request identifier](`t:request_id/0`)\nand `NewReqIdCollection` is a possibly modified\nrequest identifier collection.\n\nIf `ReqIdCollection` is empty, `no_request` is returned.\n\nIf `Msg` does not correspond to any of the request identifiers\nin `ReqIdCollection`, `no_reply` is returned.\n\nIf `Delete` equals `true`, the association with `Label`\nhas been deleted from `ReqIdCollection` in the resulting\n`NewReqIdCollection`. If `Delete` is `false`, `NewReqIdCollection`\nwill equal `ReqIdCollection`. Note that deleting an association\nis not for free and that a collection containing already handled\nrequests can still be used by subsequent calls to\n`wait_response/3`, `check_response/3`, and `receive_response/3`.\n\nHowever, without deleting handled associations,\nthe above calls will not be able to detect when there are\nno more outstanding requests to handle, so you will have to keep track\nof this some other way than relying on a `no_request` return.\nNote that if you pass a collection only containing\nassociations of already handled or abandoned requests to\nthis function, it will always return `no_reply`.","title":"gen_statem.check_response/3","ref":"gen_statem.html#check_response/3"},{"type":"callback","doc":"Update the [state](`t:state/0`) and [data](`t:data/0`)\nafter code change.\n\nThis function is called by a `gen_statem` when it is to update\nits internal state during a release upgrade/downgrade, that is,\nwhen the instruction `{update, Module, Change, ...}`,\nwhere `Change = {advanced, Extra}`, is specified in\nthe [`appup`](`e:sasl:appup.md`) file. For more information, see\n[OTP Design Principles](`e:system:release_handling.md#instr`).\n\nFor an upgrade, `OldVsn` is `Vsn`, and for a downgrade, `OldVsn` is\n`{down, Vsn}`. `Vsn` is defined by the `vsn` attribute(s)\nof the old version of the callback module `Module`.\nIf no such attribute is defined, the version is the checksum\nof the Beam file.\n\n`OldState` and `OldData` is the internal state of the `gen_statem`.\n\n`Extra` is passed \"as is\" from the `{advanced, Extra}` part\nof the update instruction.\n\nIf successful, the function must return the updated internal state\nin an `{ok, NewState, NewData}` tuple.\n\nIf the function returns a failure `Reason`, the ongoing upgrade fails\nand rolls back to the old release. Note that `Reason` cannot be\nan `{ok, _, _}` tuple since that will be regarded\nas a `{ok, NewState, NewData}` tuple, and that a tuple matching `{ok, _}`\nis an also invalid failure `Reason`. It is recommended to use\nan atom as `Reason` since it will be wrapped in an `{error, Reason}` tuple.\n\nAlso note when upgrading a `gen_statem`, this function and hence the\n`Change = {advanced, Extra}` parameter\nin the [`appup`](`e:sasl:appup.md`) file is not only needed\nto update the internal state or to act on the `Extra`\nargument. It is also needed if an upgrade or downgrade should change\n[_callback mode_](`t:callback_mode/0`), or else the _callback mode_\nafter the code change will not be honoured, most probably causing\na server crash.\n\nIf the server changes callback module using any of the actions\n[`change_callback_module`](#change_callback_module),\n[`push_callback_module`](#push_callback_module), or\n[`pop_callback_module`](#pop_callback_module), be aware that it is always\nthe current callback module that will get this callback call.\nThat the current callback module handles the current\nstate and data update should be no surprise, but it\nmust be able to handle even parts of the state and data\nthat it is not familiar with, somehow.\n\nIn the supervisor\n[child specification](`e:system:sup_princ.md#child-specification`)\nthere is a list of modules which is recommended to contain\nonly the callback module. For a `gen_statem`\nwith multiple callback modules there is no real need to list\nall of them, it may not even be possible since the list could change\nafter code upgrade. If this list would contain only\nthe start callback module, as recommended, what is important\nis to upgrade _that_ module whenever\na _synchronized code replacement_ is done.\nThen the release handler concludes that\nan upgrade that upgrades _that_ module needs to suspend,\ncode change, and resume any server whose child specification declares\nthat it is using _that_ module.\nAnd again; the _current_ callback module will get the\n[`Module:code_change/4`](`c:code_change/4`) call.\n\n> #### Note {: .info }\n>\n> If a release upgrade/downgrade with `Change = {advanced, Extra}`\n> specified in the `.appup` file is made\n> when [`Module:code_change/4`](`c:code_change/4`) is not implemented\n> the process will crash with exit reason `undef`.","title":"gen_statem.code_change/4","ref":"gen_statem.html#c:code_change/4"},{"type":"function","doc":"","title":"gen_statem.enter_loop/4","ref":"gen_statem.html#enter_loop/4"},{"type":"function","doc":"Make the calling process become a `gen_statem` server.\n\nWith argument `Actions`, equivalent to\n[`enter_loop(Module, Opts, State, Data, self(), Actions)`](`enter_loop/6`).\n\nOtherwise equivalent to\n[`enter_loop(Module, Opts, State, Data, Server, [])`](`enter_loop/6`).","title":"gen_statem.enter_loop/5","ref":"gen_statem.html#enter_loop/5"},{"type":"function","doc":"Make the calling process become a `gen_statem` server.\n\nDoes not return, instead the calling process enters the `gen_statem`\nreceive loop and becomes a `gen_statem` server. The process\n_must_ have been started using one of the start functions\nin `m:proc_lib`. The user is responsible for any initialization\nof the process, including registering a name for it.\n\nThis function is useful when a more complex initialization procedure\nis needed than the `gen_statem` [`Module:init/1`](`c:init/1`)\ncallback offers.\n\n`Module` and `Opts` have the same meanings as when calling\n[`start[link | monitor]/3,4`](`start_link/3`).\n\nIf `Server` is `self/0` an anonymous server is created just as when using\n[`start[link |_monitor]/3`](`start_link/3`). If `Server`\nis a `t:server_name/0` a named server is created just as when using\n[`start[link |_monitor]/4`](`start_link/4`). However,\nthe `t:server_name/0` name must have been registered accordingly\n_before_ this function is called.\n\n`State`, `Data`, and `Actions` have the same meanings\nas in the return value of [`Module:init/1`](`c:init/1`).\nAlso, the callback module does not need to export\na [`Module:init/1`](`c:init/1`) function.\n\nThe function fails if the calling process was not started\nby a `m:proc_lib` start function, or if it is not registered\naccording to `t:server_name/0`.","title":"gen_statem.enter_loop/6","ref":"gen_statem.html#enter_loop/6"},{"type":"callback","doc":"Format/limit the status value.\n\nThis function is called by a `gen_statem` process\nin order to format/limit the server status\nfor debugging and logging purposes.\n\nIt is called in the following situations:\n\n- [`sys:get_status/1,2`](`sys:get_status/1`) is invoked\n to get the `gen_statem` status.\n- The `gen_statem` process terminates abnormally and logs an error.\n\nThis function is useful for changing the form and appearance\nof the `gen_statem` status for these cases. A callback module\nwishing to change the [`sys:get_status/1,2`](`sys:get_status/1`)\nreturn value and how its status appears in termination error logs,\nexports an instance of [`Module:format_status/1`](`c:format_status/1`),\nwhich will get a map `Status` that describes the current state\nof the `gen_statem`, and shall return a map `NewStatus`\ncontaining the same keys as the input map,\nbut it may transform some values.\n\nOne use case for this function is to return compact alternative state\nrepresentations to avoid having large state terms printed in log files.\nAnother is to hide sensitive data from being written to the error log.\n\nExample:\n\n```erlang\nformat_status(Status) ->\n maps:map(\n fun(state,State) ->\n maps:remove(private_key, State);\n (message,{password, _Pass}) ->\n {password, removed};\n (_,Value) ->\n Value\n end, Status).\n```\n\n> #### Note {: .info }\n>\n> This callback is optional, so a callback module does not need\n> to export it. The `gen_statem` module provides\n> a default implementation of this function that returns `{State, Data}`.\n>\n> If this callback is exported but fails, to hide possibly sensitive data,\n> the default function will instead return `{State, Info}`,\n> where `Info` says nothing but the fact that\n> [`Module:format_status/2`](`c:format_status/2`) has crashed.","title":"gen_statem.format_status/1","ref":"gen_statem.html#c:format_status/1"},{"type":"callback","doc":"Format/limit the status value.\n\nThis function is called by a `gen_statem` process\nin in order to format/limit the server state\nfor debugging and logging purposes.\n\nIt is called in the following situations:\n\n- One of [`sys:get_status/1,2`](`sys:get_status/1`) is invoked to get the\n `gen_statem` status. `Opt` is set to the atom `normal` for this case.\n\n- The `gen_statem` terminates abnormally and logs an error.\n `Opt` is set to the atom `terminate` for this case.\n\nThis function is useful for changing the form and appearance of\nthe `gen_statem` status for these cases. A callback module wishing to\nchange the [`sys:get_status/1,2`](`sys:get_status/1`) return value\nand how its status appears in termination error logs, should export\nan instance of [`Module:format_status/2`](`c:format_status/2`),\nthat returns a term describing the current status of the `gen_statem`.\n\n`PDict` is the current value of the process dictionary of the `gen_statem`.\n\n[`State`](`t:state/0`) is the internal state of the `gen_statem`.\n\n[`Data`](`t:data/0`) is the internal server data of the `gen_statem`.\n\nThe function is to return `Status`, a term that contains\nthe appropriate details of the current state and status\nof the `gen_statem`. There are no restrictions on the form `Status`\ncan take, but for the [`sys:get_status/1,2`](`sys:get_status/1`) case\n(when `Opt` is `normal`), the recommended form for the `Status` value\nis `[{data, [{\"State\", Term}]}]`, where `Term` provides relevant details\nof the `gen_statem` state. Following this recommendation is not required,\nbut it makes the callback module status consistent\nwith the rest of the [`sys:get_status/1,2`](`sys:get_status/1`)\nreturn value.\n\nOne use for this function is to return compact alternative\nstate representations to avoid having large state terms printed\nin log files. Another use is to hide sensitive data\nfrom being written to the error log.\n\n> #### Note {: .info }\n>\n> This callback is optional, so a callback module does not need\n> to export it. The `gen_statem` module provides a default\n> implementation of this function that returns `{State, Data}`.\n>\n> If this callback is exported but fails, to hide possibly sensitive data,\n> the default function will instead return `{State, Info}`,\n> where `Info` says nothing but the fact that\n> [`Module:format_status/2`](`c:format_status/2`) has crashed.","title":"gen_statem.format_status/2","ref":"gen_statem.html#c:format_status/2"},{"type":"callback","doc":"[_State callback_](#state-callback) in\n[_callback mode_](`t:callback_mode/0`) `handle_event_function`.\n\nWhenever a `gen_statem` receives an event from [`call/2,3`](`call/3`),\n`cast/2`, or as a normal process message, this function is called.\n\nIf `EventType` is [`{call, From}`](`t:event_type/0`),\nthe caller waits for a reply. The reply can be sent from this\nor from any other [_state callback_](#state-callback)\nby returning with `{reply, From, Reply}` in [`Actions`](`t:action/0`),\nin [`Replies`](`t:reply_action/0`), or by calling\n[`reply(From, Reply)`](`reply/2`).\n\nIf this function returns with a next state\nthat does not match equal (`=/=`) to the current state,\nall postponed events are retried in the next state.\n\nFor options that can be set and actions that can be done\nby `gen_statem` after returning from this function, see `t:action/0`.\n\nWhen the `gen_statem` runs with [_state enter calls_](`t:state_enter/0`),\nthis function is also called with arguments `(enter, OldState, ...)`\nduring every _state change_. In this case there are some restrictions\non the [actions](`t:action/0`) that may be returned:\n\n- `t:postpone/0` is not allowed since a _state enter call_\n is not an event so there is no event to postpone.\n- [`{next_event, _, _}`](`t:action/0`) is not allowed since\n using _state enter calls_ should not affect how events\n are consumed and produced.\n- It is not allowed to change states from this call.\n Should you return `{next_state, NextState, ...}`\n with `NextState =/= State` the `gen_statem` crashes.\n\n Note that it is actually allowed to use `{repeat_state, NewData, ...}`\n although it makes little sense since you immediately\n will be called again with a new _state enter call_ making this\n just a weird way of looping, and there are better ways to loop in Erlang.\n\n If you do not update `NewData` and have some loop termination condition,\n or if you use `{repeat_state_and_data, _}` or `repeat_state_and_data`\n you have an infinite loop\\!\n\n You are advised to use `{keep_state, ...}`, `{keep_state_and_data, _}`\n or `keep_state_and_data` since changing states\n from a _state enter call_ is not possible anyway.\n\nNote the fact that you can use [`throw`](`erlang:throw/1`)\nto return the result, which can be useful. For example to bail out with\n[`throw(keep_state_and_data)`](`throw/1`) from deep within complex code\nthat cannot return `{next_state, State, Data}` because `State` or `Data`\nis no longer in scope.","title":"gen_statem.handle_event/4","ref":"gen_statem.html#c:handle_event/4"},{"type":"callback","doc":"Initialize the state machine.\n\nWhenever a `gen_statem` is started using\n[`start_link/3,4`](`start_link/3`),\n[`start_monitor/3,4`](`start_monitor/3`), or\n[`start/3,4`](`start/3`), this function is called by the new process\nto initialize the implementation state and server data.\n\n`Args` is the `Args` argument provided to that start function.\n\n> #### Note {: .info }\n>\n> Note that if the `gen_statem` is started through `m:proc_lib`\n> and [`enter_loop/4,5,6`](`enter_loop/6`), this callback\n> will never be called. Since this callback is not optional\n> it can in that case be implemented as:\n>\n> ```erlang\n> -spec init(_) -> no_return().\n> init(Args) -> erlang:error(not_implemented, [Args]).\n> ```","title":"gen_statem.init/1","ref":"gen_statem.html#c:init/1"},{"type":"function","doc":"","title":"gen_statem.receive_response/1","ref":"gen_statem.html#receive_response/1"},{"type":"function","doc":"Receive a request response.\n\nReceive a response corresponding to the request identifier `ReqId`.\nThe request must have been made by `send_request/2`\nto the `gen_statem` process. This function must be called\nfrom the same process from which `send_request/2` was made.\n\n`Timeout` specifies how long to wait for a response.\nIf no response is received within the specified time,\nthis function returns `timeout`. Assuming that the server executes\non a node supporting aliases (introduced in OTP 24)\nthe request will also be abandoned. That is,\nno response will be received after a time-out.\nOtherwise, a stray response might be received at a later time.\n\nSee [`call/3`](#call-reply) about how the request is handled\nand the `Reply` is sent by the `gen_statem` server.\n\nIf the `gen_statem` server process is dead or dies while\nthis function waits for the reply, it returns an `error` return\nwith the exit `Reason`.\n\nThe difference between `wait_response/2` and `receive_response/2`\nis that `receive_response/2` abandons the request at time-out\nso that a potential future response is ignored,\nwhile `wait_response/2` does not.","title":"gen_statem.receive_response/2","ref":"gen_statem.html#receive_response/2"},{"type":"function","doc":"Receive a request response in a collection.\n\nReceive a response in `ReqIdCollection`. All request identifiers\nof `ReqIdCollection` must correspond to requests that have been made\nusing `send_request/2` or `send_request/4`, and all requests\nmust have been made by the process calling this function.\n\nThe `Label` in the response is the `Label` associated with\nthe request identifier that the response corresponds to.\nThe `Label` of a request identifier is associated\nwhen [adding the request id](`reqids_add/3`) to a collection,\nor when sending the request using `send_request/4`.\n\nCompared to `receive_response/2`, the returned result or exception\nassociated with a specific request identifier will be wrapped\nin a 3-tuple `{Response, Label, NewReqIdCollection}`.\n`Response` is the value that would have been produced\nby `receive_response/2`, `Label` is the value associated with\nthe specific [request identifier](`t:request_id/0`)\nand `NewReqIdCollection` is a possibly modified\nrequest identifier collection.\n\nIf `ReqIdCollection` is empty, `no_request` will be returned.\n\n`Timeout` specifies how long to wait for a response. If no response\nis received within the specified time, the function returns `timeout`.\nAssuming that the server executes on a node supporting aliases\n(introduced in OTP 24) all requests identified by `ReqIdCollection`\nwill also be abandoned. That is, no responses will be received\nafter a time-out. Otherwise, stray responses might be received\nat a later time.\n\nThe difference between `receive_response/3` and `wait_response/3`\nis that `receive_response/3` abandons requests at time-out\nso that potential future responses are ignored,\nwhile `wait_response/3` does not.\n\nIf `Delete` is `true`, the association with `Label`\nis deleted from `ReqIdCollection` in the resulting\n`NewReqIdCollection`. If `Delete` is `false`, `NewReqIdCollection`\nwill equal`ReqIdCollection`. Note that deleting an association\nis not for free and that a collection containing already handled\nrequests can still be used by subsequent calls to\n`wait_response/3`, `check_response/3`, and `receive_response/3`.\n\nHowever, without deleting handled associations,\nthe above calls will not be able to detect when there are\nno more outstanding requests to handle, so you will have to keep track\nof this some other way than relying on a `no_request` return.\nNote that if you pass a collection only containing\nassociations of already handled or abandoned requests to\nthis function, it will always block until `Timeout` expires\nand then return `timeout`.","title":"gen_statem.receive_response/3","ref":"gen_statem.html#receive_response/3"},{"type":"function","doc":"Send one or multiple `call` replies.\n\nThis funcion can be used by a `gen_statem` callback to explicitly send\none or multiple replies to processes waiting for `call` requests' replies,\nwhen it is impractical or impossible to return `t:reply_action/0`s\nfrom a [_state callback_](#state-callback).\n\n> #### Note {: .info }\n>\n> A reply sent with this function is not visible in `m:sys` debug output.","title":"gen_statem.reply/1","ref":"gen_statem.html#reply/1"},{"type":"function","doc":"Send a `call` `Reply` to `From`.\n\nThis funcion can be used by a `gen_statem` callback to explicitly send\na reply to a process waiting for a `call` requests' reply,\nwhen it is impractical or impossible to return a `t:reply_action/0`\nfrom a [_state callback_](#state-callback).\n\n> #### Note {: .info }\n>\n> A reply sent with this function is not visible in `m:sys` debug output.","title":"gen_statem.reply/2","ref":"gen_statem.html#reply/2"},{"type":"function","doc":"Store a request identifier in a colletion.\n\nStores `ReqId` and associates a `Label` with the request identifier\nby adding this information to `ReqIdCollection` and returning\nthe resulting request identifier collection.","title":"gen_statem.reqids_add/3","ref":"gen_statem.html#reqids_add/3"},{"type":"function","doc":"Create an empty request identifier collection.\n\nReturns a new empty request identifier collection.\nA request identifier collection can be used to handle\nmultiple outstanding requests.\n\nRequest identifiers of requests made by `send_request/2`\ncan be stored in a collection using `reqids_add/3`.\nSuch a collection of request identifiers can later be used\nin order to get one response corresponding to a request\nin the collection by passing the collection as argument to\n`receive_response/3`, `wait_response/3`, or, `check_response/3`.\n\n`reqids_size/1` can be used to determine the number of\nrequest identifiers in a collection.","title":"gen_statem.reqids_new/0","ref":"gen_statem.html#reqids_new/0"},{"type":"function","doc":"Return the number of request identifiers in `ReqIdCollection`.","title":"gen_statem.reqids_size/1","ref":"gen_statem.html#reqids_size/1"},{"type":"function","doc":"Convert a request identifier collection to a list.\n\nReturns a list of `{ReqId, Label}` tuples which corresponds to\nall request identifiers with their associated labels\nin [`ReqIdCollection`](`t:request_id_collection/0`).","title":"gen_statem.reqids_to_list/1","ref":"gen_statem.html#reqids_to_list/1"},{"type":"callback","doc":"[_State callback_](#state-callback) in\n[_callback mode_](`t:callback_mode/0`) `state_functions`.\n\nState callback that handles all events in state `StateName`, where\n[`StateName :: state_name()`](`t:state_name/0`)\nhas to be an `t:atom/0`.\n\n`StateName` cannot be `terminate` since that would collide\nwith the callback function [`Module:terminate/3`](`c:terminate/3`).\n\nBesides that when doing a [_state change_](#state-callback)\nthe next state always has to be an `t:atom/0`,\nthis function is equivalent to\n[`Module:handle_event(​EventType, EventContent,\n?FUNCTION_NAME, Data)`](`c:handle_event/4`),\nwhich is the [_state callback_](#state-callback) in\n[_callback mode_](`t:callback_mode/0`) `handle_event_function`.","title":"gen_statem.StateName/3","ref":"gen_statem.html#c:StateName/3"},{"type":"function","doc":"Send an asynchronous `call` request.\n\nSends `Request` to the `gen_statem` process identified by `ServerRef`\nand returns a request identifier `ReqId`.\n\nThe return value `ReqId` shall later be used with `receive_response/2`,\n`wait_response/2`, or `check_response/2` to fetch the actual result\nof the request. Besides passing the request identifier directly\nto these functions, it can also be stored in\na request identifier collection using `reqids_add/3`.\nSuch a collection of request identifiers can later be used\nin order to get one response corresponding to a\nrequest in the collection by passing the collection\nas argument to `receive_response/3`, `wait_response/3`,\nor `check_response/3`. If you are about to store the request identifier\nin a collection, you may want to consider using `send_request/4` instead.\n\nThe call\n`gen_statem:wait_response(gen_statem:send_request(ServerRef,\nRequest), Timeout)` can be seen as equivalent to\n[`gen_statem:call(Server, Request, Timeout)`](`call/3`),\nignoring the error handling.\n\nSee [`call/3`](#call-reply) about how the request is handled\nand the `Reply` is sent by the `gen_statem` server.\n\nThe server's `Reply` is returned by one of the\n[`receive_response/1,2`](`receive_response/2`),\n[`wait_response/1,2`](`wait_response/2`),\nor `check_response/2` functions.","title":"gen_statem.send_request/2","ref":"gen_statem.html#send_request/2"},{"type":"function","doc":"Send an asynchronous `call` request and add it\nto a request identifier collection.\n\nSends `Request` to the `gen_statem` process identified by `ServerRef`.\nThe `Label` will be associated with the request identifier\nof the operation and added to the returned request identifier collection\n`NewReqIdCollection`. The collection can later be used in order to\nget one response corresponding to a request in the collection\nby passing the collection as argument to `receive_response/3`,\n`wait_response/3`, or `check_response/3`.\n\nThe same as calling\n[`reqids_add(​`](`reqids_add/3`)[`send_request(ServerRef, Request),\n`](`send_request/2`)[`Label, ReqIdCollection)`](`reqids_add/3`),\nbut slightly more efficient.","title":"gen_statem.send_request/4","ref":"gen_statem.html#send_request/4"},{"type":"function","doc":"Start a server, neither linked nor registered.\n\nEquivalent to `start/4` except that the `gen_statem` process\nis not registered with any [name service](`t:server_name/0`).","title":"gen_statem.start/3","ref":"gen_statem.html#start/3"},{"type":"function","doc":"Start a server, registered but not linked.\n\nCreates a standalone `gen_statem` process according to\nOTP design principles (using `m:proc_lib` primitives).\nAs it does not get linked to the calling process,\nthis start function cannot be used by a supervisor to start a child.\n\nFor a description of arguments and return values,\nsee [`start_link/4`](`start_link/4`).","title":"gen_statem.start/4","ref":"gen_statem.html#start/4"},{"type":"function","doc":"Start a server, linked but not registered.\n\nEquivalent to `start_link/4` except that the `gen_statem` process\nis not registered with any [name service](`t:server_name/0`).","title":"gen_statem.start_link/3","ref":"gen_statem.html#start_link/3"},{"type":"function","doc":"Start a server, linked and registered.\n\nCreates a `gen_statem` process according to OTP design principles\n(using `m:proc_lib` primitives) that is spawned linked to\nthe calling process. This is essential when the `gen_statem`\nmust be part of a supervision tree so it gets linked to its supervisor.\n\nThe spawned `gen_statem` process calls [`Module:init/1`](`c:init/1`)\nto initialize the server. To ensure a synchronized startup procedure,\n`start_link/3,4` does not return until [`Module:init/1`](`c:init/1`)\nhas returned or failed.\n\n`ServerName` specifies the `t:server_name/0` to register\nfor the `gen_statem` process. If the `gen_statem` process is started with\n[`start_link/3`](`start_link/3`), no `ServerName` is provided and the\n`gen_statem` process is not registered.\n\n`Module` is the name of the callback module.\n\n`Args` is an arbitrary term that is passed as the argument to\n[`Module:init/1`](`c:init/1`).\n\n#### Start options in `Opts` {: #start-options }\n\n- **[`{timeout, Time}`](`t:start_opt/0`)** - The `gen_statem` process\n is allowed to spend `Time` milliseconds before returning\n from [`Module:init/1`](`c:init/1`), or it is terminated\n and this start function returns [`{error, timeout}`](`t:start_ret/0`).\n\n- **[`{spawn_opt, SpawnOpts}`](`t:start_opt/0`)** -\n `SpawnOpts` is passed as option list to `erlang:spawn_opt/2`,\n which is used to spawn the `gen_statem` process.\n See `t:proc_lib:start_spawn_option/0`.\n\n > #### Note {: .info }\n >\n > Using spawn option `monitor` is not allowed,\n > it causes a `badarg` failure.\n\n- **[`{hibernate_after, HibernateAfterTimeout}`](`t:enter_loop_opt/0`)** -\n When the `gen_statem` process waits for a message, if no message\n is received within `HibernateAfterTimeout` milliseconds,\n the process goes into hibernation automatically\n (by calling `proc_lib:hibernate/3`). This option is also\n allowed for the [`enter_loop`](`enter_loop/6`) functions.\n\n Note that there is also a `t:transition_option/0`\n to explicitly hibernate the server from a\n [_state callback_](#state-callback).\n\n- **[`{debug, Dbgs}`](`t:enter_loop_opt/0`)** - Activates\n debugging through `m:sys`. For every entry in `Dbgs`,\n the corresponding function in `m:sys` is called. This option is also\n allowed for the [`enter_loop`](`enter_loop/6`) functions.\n\n#### Return values {: #start-return-values }\n\n- **[`{ok, Pid}`](`t:start_ret/0`)** -\n The `gen_statem` server process was successfully created and\n initialized. `Pid` is the `t:pid/0` of the process.\n\n- **[`ignore`](`t:start_ret/0`)** -\n [`Module:init/1`](`c:init/1`) returned [`ignore`](`t:init_result/1`).\n The `gen_statem` process has exited with reason `normal`.\n\n- **[`{error, {already_started, OtherPid}}`](`t:start_ret/0`)** -\n A process with the specified [`ServerName`](`t:server_name/0`)\n already exists. `OtherPid` is the `t:pid/0` of that process.\n The `gen_statem` process exited with reason `normal`\n before calling [`Module:init/1`](`c:init/1`).\n\n- **[`{error, timeout}`](`t:start_ret/0`)** -\n [`Module:init/1`](`c:init/1`) did not return within\n the [start time-out](`t:start_opt/0`). The `gen_statem` process\n has been killed with [`exit(_, kill)`](`erlang:exit/2`).\n\n- **[`{error, Reason}`](`t:start_ret/0`)**\n + Either [`Module:init/1`](`c:init/1`) returned\n [`{stop, Reason}`](`t:init_result/1`) or failed with reason `Reason`,\n The `gen_statem` process exited with reason `Reason`.\n + Or [`Module:init/1`](`c:init/1`) returned\n [`{error, Reason}`](`t:init_result/1`).\n The `gen_statem` process did a graceful exit with reason `normal`.\n\nIf the return value is `ignore` or `{error, _}`, the started\n`gen_statem` process has terminated. If an `'EXIT'` message\nwas delivered to the calling process (due to the process link),\nthat message has been consumed.\n\n> #### Warning {: .warning }\n>\n> Before OTP 26.0, if the started `gen_statem` process returned e.g.\n> `{stop, Reason}` from [`Module:init/1`](`c:init/1`),\n> this function could return `{error, Reason}`\n> _before_ the started `gen_statem` process had terminated,\n> so starting again might fail because VM resources\n> such as the registered name was not yet unregistered,\n> and an `'EXIT'` message could arrive later to the\n> process calling this function.\n>\n> But if the started `gen_statem` process instead failed during\n> [`Module:init/1`](`c:init/1`), a process link `{'EXIT', Pid, Reason}`\n> message caused this function to return `{error, Reason}`,\n> so the `'EXIT'` message had been consumed and\n> the started `gen_statem` process had terminated.\n>\n> Since it was impossible to tell the difference between these two cases\n> from `start_link/3,4`'s return value, this inconsistency\n> was cleaned up in OTP 26.0.","title":"gen_statem.start_link/4","ref":"gen_statem.html#start_link/4"},{"type":"function","doc":"Start a server, monitored but neither linked nor registered.\n\nEquivalent to `start_monitor/4` except that the `gen_statem`\nprocess is not registered with any [name service](`t:server_name/0`).","title":"gen_statem.start_monitor/3","ref":"gen_statem.html#start_monitor/3"},{"type":"function","doc":"Start a server, monitored and registered, but not linked.\n\nCreates a standalone `gen_statem` process according to\nOTP design principles (using `m:proc_lib` primitives),\nand atomically sets up a monitor to the newly created process.\n\nAs the started process does not get linked to the calling process,\nthis start function cannot be used by a supervisor to start a child.\n\nFor a description of arguments and return values, see\n[`start_link/4`](`start_link/4`), but note that for a succesful start\nthe return value differs since this function returns `{ok, {Pid, Mon}}`,\nwhere `Pid` is the process identifier of the process,\nand `Mon` is the monitor reference for the process.\nIf the start is not successful, the caller will be blocked\nuntil the `DOWN` message has been received\nand removed from the caller's message queue.","title":"gen_statem.start_monitor/4","ref":"gen_statem.html#start_monitor/4"},{"type":"function","doc":"","title":"gen_statem.stop/1","ref":"gen_statem.html#stop/1"},{"type":"function","doc":"Stop a server.\n\nOrders the `gen_statem` [`ServerRef`](`t:server_ref/0`) to exit with the\nspecified `Reason` and waits for it to terminate. The `gen_statem` calls\n[`Module:terminate/3`](`c:terminate/3`) before exiting.\n\nThis function returns `ok` if the server terminates\nwith the expected reason. Any other reason than `normal`, `shutdown`,\nor `{shutdown, Term}` causes an error report to be issued\nthrough `m:logger`. An exit signal with the same reason is\nsent to linked processes and ports. The default `Reason` is `normal`.\n\n`Timeout` is an integer > 0, which specifies how many milliseconds\nto wait for the server to terminate, or the atom `infinity`\nto wait indefinitely. Defaults to `infinity`.\nIf the server does not terminate within the specified time,\nthe call exits the calling process with reason `timeout`.\n\nIf the process does not exist, the call exits the calling process\nwith reason `noproc`, or with reason `{nodedown, Node}`\nif the connection fails to the remote `Node` where the server runs.","title":"gen_statem.stop/3","ref":"gen_statem.html#stop/3"},{"type":"callback","doc":"Handle state machine termination.\n\nThis function is called by a `gen_statem` when it is about to terminate.\nIt is to be the opposite of [`Module:init/1`](`c:init/1`)\nand do any necessary cleaning up. When it returns, the `gen_statem`\nterminates with `Reason`. The return value is ignored.\n\n`Reason` is a term denoting the stop reason and [`State`](`t:state/0`)\nis the internal state of the `gen_statem`.\n\n`Reason` depends on why the `gen_statem` is terminating. If it is because\nanother callback function has returned, a stop tuple `{stop, Reason}` in\n[`Actions`](`t:action/0`), `Reason` has the value specified in that tuple.\nIf it is because of a failure, `Reason` is the error reason.\n\nIf the `gen_statem` is part of a supervision tree and is ordered by its\nsupervisor to terminate, this function is called with `Reason = shutdown`\nif both the following conditions apply:\n\n- The `gen_statem` process has been set to trap exit signals.\n- The shutdown strategy as defined in the supervisor's\n child specification is an integer time-out value, not `brutal_kill`.\n\nEven if the `gen_statem` is _not_ part of a supervision tree,\nthis function is called if it receives an `'EXIT'` message\nfrom its parent. `Reason` is the same as in the `'EXIT'` message.\n\nIf the `gen_statem` process is not set up to trap\nexit signals it is immediately terminated, just like any process,\nand this function is not called.\n\nNotice that for any other reason than `normal`, `shutdown`, or\n`{shutdown, Term}`, the `gen_statem` is assumed to terminate\nbecause of an error and an error report is issued using `m:logger`.\n\nWhen the `gen_statem` process exits, an exit signal\nwith the same reason is sent to linked processes and ports,\njust as for any process.","title":"gen_statem.terminate/3","ref":"gen_statem.html#c:terminate/3"},{"type":"function","doc":"","title":"gen_statem.wait_response/1","ref":"gen_statem.html#wait_response/1"},{"type":"function","doc":"Wait for a request response.\n\nWaits for the response to the request identifier `ReqId`. The request\nmust have been made by `send_request/2` to the `gen_statem` process.\nThis function must be called from the same process from which\n`send_request/2` was called.\n\n`WaitTime` specifies how long to wait for a reply.\nIf no reply is received within the specified time,\nthe function returns `timeout` and no cleanup is done,\nThus the function can be invoked repeatedly until a reply is returned.\n\nSee [`call/3`](#call-reply) about how the request is handled\nand the `Reply` is sent by the `gen_statem` server.\n\nIf the `gen_statem` server process is dead or dies while\nthis function waits for the reply, it returns an `error` return\nwith the exit `Reason`.\n\nThe difference between `receive_response/2` and\n`wait_response/2` is that `receive_response/2` abandons\nthe request at time-out so that a potential future response is ignored,\nwhile `wait_response/2` does not.","title":"gen_statem.wait_response/2","ref":"gen_statem.html#wait_response/2"},{"type":"function","doc":"Wait for any request response in a collection.\n\nWaits for a response in `ReqIdCollection`. All request identifiers\nof `ReqIdCollection` must correspond to requests that have been made\nusing `send_request/2` or `send_request/4`, and all requests\nmust have been made by the process calling this function.\n\nThe `Label` in the response is the `Label` associated with\nthe request identifier that the response corresponds to.\nThe `Label` of a request identifier is associated\nwhen [adding the request id](`reqids_add/3`) to a collection,\nor when sending the request using `send_request/4`.\n\nCompared to `wait_response/2`, the returned result or exception\nassociated with a specific request identifier will be wrapped\nin a 3-tuple `{Response, Label, NewReqIdCollection}`.\n`Response` is the value that would have been produced\nby `wait_response/2`, `Label` is the value associated with\nthe specific [request identifier](`t:request_id/0`)\nand `NewReqIdCollection` is a possibly modified\nrequest identifier collection.\n\nIf `ReqIdCollection` is empty, `no_request` is returned.\n\nIf no response is received before `WaitTime` has expired,\n`timeout` is returned. It is valid to continue waiting\nfor a response as many times as needed up until a response\nhas been received and completed by `check_response()`,\n`receive_response()`, or `wait_response()`.\n\nThe difference between `receive_response/3` and `wait_response/3`\nis that `receive_response/3` abandons requests at time-out\nso that potential future responses are ignored,\nwhile `wait_response/3` does not.\n\nIf `Delete` is `true`, the association with `Label`\nhas been deleted from `ReqIdCollection` in the resulting\n`NewReqIdCollection`. If `Delete` is `false`, `NewReqIdCollection`\nwill equal`ReqIdCollection`. Note that deleting an association\nis not for free and that a collection containing already handled\nrequests can still be used by subsequent calls to\n`wait_response/3`, `check_response/3`, and `receive_response/3`.\n\nHowever, without deleting handled associations,\nthe above calls will not be able to detect when there are\nno more outstanding requests to handle, so you will have to keep track\nof this some other way than relying on a `no_request` return.\nNote that if you pass a collection only containing\nassociations of already handled or abandoned requests\nto this function, it will always block until `WaitTime` expires\nand then return `timeout`.","title":"gen_statem.wait_response/3","ref":"gen_statem.html#wait_response/3"},{"type":"type","doc":"Actions for a _state transition_, or when starting the server.\n\nThese _transition actions_ can be invoked by returning them from the\n[_state callback_](#state-callback) when it is called\nwith an [event](`t:event_type/0`), from [`Module:init/1`](`c:init/1`)\nor by passing them to [`enter_loop/4,5,6`](`enter_loop/6`).\nThey are **not allowed** from _state enter calls_.\n\nActions are executed in the containing list order.\n\nActions that set [transition options](`t:transition_option/0`)\noverride any previous of the same type, so the last\nin the containing list wins. For example, the last `t:postpone/0`\noverrides any previous `t:postpone/0` in the list.\n\n- **`{postpone, Value}`** - Sets the\n [`transition_option()` ](`t:transition_option/0`)`t:postpone/0`\n for this _state transition_. This action is ignored when returned from\n [`Module:init/1`](`c:init/1`) or passed to\n [`enter_loop/4,5,6`](`enter_loop/6`), as there is no event to postpone\n in those cases.\n\n `postpone` is equivalent to `{postpone, true}`.\n\n- **`{next_event, EventType, EventContent}`** - This action\n does not set any [`transition_option()`](`t:transition_option/0`)\n but instead stores the specified `EventType` and `EventContent`\n for insertion after all actions have been executed.\n\n The stored events are inserted in the queue as the next to process\n before any already queued events. The order of these stored events\n is preserved, so the first `next_event` in the containing list\n becomes the first to process.\n\n An event of type [`internal`](`t:event_type/0`) should be used\n when you want to reliably distinguish an event inserted this way\n from any external event.\n\n- **`{change_callback_module, NewModule}`** {: #change_callback_module } -\n Changes the callback module to `NewModule` which will be used\n when calling all subsequent [state callbacks](#state-callback).\\\n **Since OTP 22.3.**\n\n The `gen_statem` engine will find out the\n [_callback mode_](`t:callback_mode/0`) of `NewModule` by calling\n [`NewModule:callback_mode/0`](`c:callback_mode/0`) before the next\n [state callback](#state-callback).\n\n Changing the callback module does not affect the _state transition_\n in any way, it only changes which module that handles the events.\n Be aware that all relevant callback functions in `NewModule` such as\n the [state callback](#state-callback),\n [`NewModule:code_change/4`](`c:code_change/4`),\n [`NewModule:format_status/1`](`c:format_status/1`) and\n [`NewModule:terminate/3`](`c:terminate/3`) must be able to handle\n the state and data from the old module.\n\n- **`{push_callback_module, NewModule}`** {: #push_callback_module } -\n Pushes the current callback module to the top of an internal stack\n of callback modules, and changes the callback module to `NewModule`.\n Otherwise like `{change_callback_module, NewModule}` above.\\\n **Since OTP 22.3.**\n\n- **`pop_callback_module`** {: #pop_callback_module } -\n Pops the top module from the internal stack of callback modules\n and changes the callback module to be the popped module.\n If the stack is empty the server fails.\n Otherwise like `{change_callback_module, NewModule}` above.\\\n **Since OTP 22.3.**","title":"gen_statem.action/0","ref":"gen_statem.html#t:action/0"},{"type":"type","doc":"One function per state or one common event handler.\n\nThe _callback mode_ is selected with the return value from\n[`Module:callback_mode/0`](`c:callback_mode/0`):\n\n- **`state_functions`** - The state must be of type `t:state_name/0`\n and one callback function per state, that is,\n [`Module:StateName/3`](`c:'StateName'/3`), is used.\n\n- **`handle_event_function`** - The state can be any term and the callback\n function [`Module:handle_event/4`](`c:handle_event/4`)\n is used for all states.\n\nThe function [`Module:callback_mode/0`](`c:callback_mode/0`) is called\nwhen starting the `gen_statem`, after code change and after changing\nthe callback module with any of the actions\n[`change_callback_module`](#change_callback_module),\n[`push_callback_module`](#push_callback_module),\nor [`pop_callback_module`](#pop_callback_module).\nThe result is cached for subsequent calls to\n[_state callbacks_](#state-callback).","title":"gen_statem.callback_mode/0","ref":"gen_statem.html#t:callback_mode/0"},{"type":"type","doc":"Return value from [`Module:callback_mode/0`](`c:callback_mode/0`).\n\nThis is the return type from\n[`Module:callback_mode/0`](`c:callback_mode/0`)\nwhich selects [_callback mode_](`t:callback_mode/0`)\nand whether to do [_state enter calls_](`t:state_enter/0`),\nor not.","title":"gen_statem.callback_mode_result/0","ref":"gen_statem.html#t:callback_mode_result/0"},{"type":"type","doc":"Generic state data for the server.\n\nA term in which the state machine implementation is to store\nany server data it needs. The difference between this and the `t:state/0`\nitself is that a change in this data does not cause postponed events\nto be retried. Hence, if a change in this data would change\nthe set of events that are handled, then that data item\nshould be part of the `t:state/0` instead.","title":"gen_statem.data/0","ref":"gen_statem.html#t:data/0"},{"type":"type","doc":"Actions for any callback: hibernate, time-outs or replies.\n\nThese _transition actions_ are allowed when a `t:action/0` is allowed,\nand also from a _state enter call_, and can be invoked\nby returning them from the [_state callback_](#state-callback), from\n[`Module:init/1`](`c:init/1`) or by passing them to\n[`enter_loop/4,5,6`](`enter_loop/6`).\n\nActions are executed in the containing list order.\n\nActions that set [transition options](`t:transition_option/0`)\noverride any previous of the same type,\nso the last in the containing list wins. For example,\nthe last `t:event_timeout/0` overrides any previous\n`t:event_timeout/0` in the list.\n\n- **`{hibernate, Value}`** - Sets the `t:transition_option/0`\n `t:hibernate/0` for this _state transition_.\n\n `hibernate` is equivalent to `{hibernate, true}`.","title":"gen_statem.enter_action/0","ref":"gen_statem.html#t:enter_action/0"},{"type":"type","doc":"Server [start options](#start-options) for the\n[`enter_loop/4,5,6`](`enter_loop/6`),\n[`start/3,4`](`start/3`), [`start_link/3,4`](`start_link/3`),\nand [`start_monitor/3,4`](`start_monitor/3`), functions.\n\nSee [`start_link/4`](#start-options).","title":"gen_statem.enter_loop_opt/0","ref":"gen_statem.html#t:enter_loop_opt/0"},{"type":"type","doc":"Event payload from the event's origin, delivered to\nthe [_state callback_](#state-callback).\n\nSee [`event_type`](`t:event_type/0`) that describes the origins of\nthe different event types, which is also where the event's content\ncomes from.","title":"gen_statem.event_content/0","ref":"gen_statem.html#t:event_content/0"},{"type":"type","doc":"","title":"gen_statem.event_handler_result/1","ref":"gen_statem.html#t:event_handler_result/1"},{"type":"type","doc":"Return value from a [_state callback_](#state-callback)\nafter handling an event.\n\n`StateType` is `t:state_name/0`\nif [_callback mode_](`t:callback_mode/0`) is `state_functions`,\nor `t:state/0`\nif [_callback mode_](`t:callback_mode/0`) is `handle_event_function`.\n\n- **`{next_state, NextState, NewData [, Actions]}`** -\n The `gen_statem` does a _state transition_ to `NextState`\n (which may be the same as the current state), sets `NewData`\n as the current server `t:data/0`, and executes all `Actions`.\n If `NextState =/= CurrentState` the _state transition_\n is a _state change_.","title":"gen_statem.event_handler_result/2","ref":"gen_statem.html#t:event_handler_result/2"},{"type":"type","doc":"How long to wait for an event.\n\nStarts a timer set by `t:timeout_action/0`\n`Time`, or `{timeout, Time, EventContent [, Options]}`.\n\nWhen the timer expires an event of `t:event_type/0` `timeout`\nwill be generated. See `erlang:start_timer/4` for how `Time`\nand [`Options`](`t:timeout_option/0`) are interpreted. Future\n`erlang:start_timer/4` `Options` will not necessarily be supported.\n\nAny event that arrives cancels this time-out. Note that a retried\nor inserted event counts as arrived. So does a state time-out zero event,\nif it was generated before this time-out is requested.\n\nIf `Time` is `infinity`, no timer is started,\nas it never would expire anyway.\n\nIf `Time` is relative and `0` no timer is actually started,\ninstead the the time-out event is enqueued to ensure\nthat it gets processed before any not yet received external event,\nbut after already queued events.\n\nNote that it is not possible nor needed to cancel this time-out,\nas it is cancelled automatically by any other event, meaning that\nwhenever a callback is invoked that may want to cancel this time-out,\nthe timer is already cancelled or expired.\n\nThe timer `EventContent` can be updated with the\n[`{timeout, update, NewEventContent}`](`t:timeout_update_action/0`)\naction without affecting the time of expiry.","title":"gen_statem.event_timeout/0","ref":"gen_statem.html#t:event_timeout/0"},{"type":"type","doc":"All event types: [external](`t:external_event_type/0`),\n[time-out](`t:timeout_event_type/0`), or `internal`.\n\n`internal` events can only be generated by the state machine itself\nthrough the _transition action_ [`next_event`](`t:action/0`).","title":"gen_statem.event_type/0","ref":"gen_statem.html#t:event_type/0"},{"type":"type","doc":"Event from a [call](`call/3`), [cast](`cast/2`),\nor regular process message; \"info\".\n\nType `{call, From}` originates from the API functions\n[`call/2,3`](`call/3`) or `send_request/2`. The event contains\n[`From`](`t:from/0`), which is whom to reply to\nby a `t:reply_action/0` or [`reply/2,3`](`reply/2`) call.\n\nType `cast` originates from the API function `cast/2`.\n\nType `info` originates from regular process messages\nsent to the `gen_statem` process.","title":"gen_statem.external_event_type/0","ref":"gen_statem.html#t:external_event_type/0"},{"type":"type","doc":"A map that describes the server's status.\n\nThe keys are:\n- **`state`** - The current state.\n- **`data`** - The state data.\n- **`reason`** - The reason that caused the process to terminate.\n- **`queue`** - The event queue.\n- **`postponed`** - The queue of [postponed](`t:postpone/0`) events.\n- **`timeouts`** - The active [time-outs](`t:timeout_action/0`).\n- **`log`** - The [sys log](`sys:log/2`) of the server.\n\nNew associations may be added to the status map without prior notice.","title":"gen_statem.format_status/0","ref":"gen_statem.html#t:format_status/0"},{"type":"type","doc":"A [`call`](`t:external_event_type/0`) event's reply destination.\n\nDestination to use when replying through, for example,\nthe action [`{reply, From, Reply}`](`t:reply_action/0`)\nto a process that has called the `gen_statem` server\nusing [`call/2,3`](`call/3`).","title":"gen_statem.from/0","ref":"gen_statem.html#t:from/0"},{"type":"type","doc":"How long to wait for a named time-out event.\n\nStarts a timer set by `t:timeout_action/0`\n`{{timeout, Name}, Time, EventContent [, Options]}`.\n\nWhen the timer expires an event of `t:event_type/0` `{timeout, Name}`\nwill be generated. See `erlang:start_timer/4` for how `Time`\nand [`Options`](`t:timeout_option/0`) are interpreted. Future\n`erlang:start_timer/4` `Options` will not necessarily be supported.\n\nIf `Time` is `infinity`, no timer is started,\nas it never would expire anyway.\n\nIf `Time` is relative and `0` no timer is actually started,\ninstead the time-out event is enqueued to ensure\nthat it gets processed before any not yet received external event.\n\nSetting a timer with the same `Name` while it is running\nwill restart it with the new time-out value. Therefore it is possible\nto cancel a specific time-out by setting it to `infinity`.\nIt can also be cancelled more explicitly with the\n[`{{timeout, Name}, cancel}`](`t:timeout_cancel_action/0`) action.\n\nThe timer `EventContent` can be updated with the\n[`{{timeout, Name}, update, NewEventContent}`](`t:timeout_update_action/0`)\naction without affecting the time of expiry.","title":"gen_statem.generic_timeout/0","ref":"gen_statem.html#t:generic_timeout/0"},{"type":"type","doc":"Hibernate the server process.\n\nIf `true`, hibernates the `gen_statem` by calling `proc_lib:hibernate/3`\nbefore going into `receive` to wait for a new external event.\n\nThere is also a server start option\n[`{hibernate_after, Timeout}`](`t:enter_loop_opt/0`)\nfor automatic hibernation.\n\n> #### Note {: .info }\n>\n> If there are enqueued events to process when hibernation is requested,\n> this is optimized by not hibernating but instead calling\n> [`erlang:garbage_collect/0`](`erlang:garbage_collect/0`) to simulate,\n> in a more effective way, that the `gen_statem` entered hibernation\n> and immediately got awakened by an enqueued event.","title":"gen_statem.hibernate/0","ref":"gen_statem.html#t:hibernate/0"},{"type":"type","doc":"","title":"gen_statem.init_result/1","ref":"gen_statem.html#t:init_result/1"},{"type":"type","doc":"The return value from [`Module:init/1`](`c:init/1`).\n\nFor a succesful initialization, `State` is the initial `t:state/0`,\nand `Data` the initial server `t:data/0` of the `gen_statem`.\n\nThe [`Actions`](`t:action/0`) are executed when entering the first\n[state](`t:state/0`) just as for a\n[_state callback_](#state-callback), except that the action\n`postpone` is forced to `false` since there is no event to postpone.\n\nFor an unsuccesful initialization, `{stop, Reason}`, `{error, Reason}`,\nor `ignore` should be used; see [`start_link/3,4`](`start_link/3`).\n\n`{error, Reason}` has been allowed **since OTP 26.0**.\n\nThe `{ok, ...}` tuples have existed **since OTP 19.1**,\nbefore that they were not `ok` tagged. This was before\n`gen_statem` replaced `gen_fsm` in OTP 20.0.","title":"gen_statem.init_result/2","ref":"gen_statem.html#t:init_result/2"},{"type":"type","doc":"Postpone an event to handle it later.\n\nIf `true`, postpones the current event.\nAfter a _state change_ (`NextState =/= State`), it is retried.","title":"gen_statem.postpone/0","ref":"gen_statem.html#t:postpone/0"},{"type":"type","doc":"Reply to a [`call/2,3`](`call/3`).\n\nThis _transition action_ can be invoked by returning it from the\n[_state callback_](#state-callback), from\n[`Module:init/1`](`c:init/1`) or by passing it to\n[`enter_loop/4,5,6`](`enter_loop/6`).\n\nIt does not set any [`transition_option()`](`t:transition_option/0`)\nbut instead replies to a caller waiting for a reply in `call/3`.\n`From` must be the term from argument [`{call, From}`](`t:event_type/0`)\nin a call to a [_state callback_](#state-callback).\n\nNote that using this action from [`Module:init/1`](`c:init/1`) or\n[`enter_loop/4,5,6`](`enter_loop/6`) would be weird\non the border of witchcraft since there has been no earlier call to a\n[_state callback_](#state-callback) in this server.","title":"gen_statem.reply_action/0","ref":"gen_statem.html#t:reply_action/0"},{"type":"opaque","doc":"A handle that associates a reply to the corresponding request.","title":"gen_statem.reply_tag/0","ref":"gen_statem.html#t:reply_tag/0"},{"type":"opaque","doc":"An opaque request identifier. See `send_request/2` for details.","title":"gen_statem.request_id/0","ref":"gen_statem.html#t:request_id/0"},{"type":"opaque","doc":"An opaque collection of request identifiers (`t:request_id/0`).\n\nEach request identifier can be associated with\na label chosen by the user. For more information see `reqids_new/0`.","title":"gen_statem.request_id_collection/0","ref":"gen_statem.html#t:request_id_collection/0"},{"type":"type","doc":"Response time-out for an asynchronous call.\n\nUsed to set a time limit on how long to wait for a response using either\n`receive_response/2`, `receive_response/3`, `wait_response/2`, or\n`wait_response/3`. The time unit used is `millisecond`.\n\n Currently valid values:\n\n- **`0..4294967295`** - Time-out relative to current time in milliseconds.\n\n- **`infinity`** - Infinite time-out. That is,\n the operation will never time out.\n\n- **`{abs, Timeout}`** - An absolute\n [Erlang monotonic time](`erlang:monotonic_time/1`)\n time-out in milliseconds. That is, the operation will time out when\n [`erlang:monotonic_time(millisecond)`](`erlang:monotonic_time/1`)\n returns a value larger than or equal to `Timeout`.\n `Timeout` is not allowed to identify a time further into the future\n than `4294967295` milliseconds. Specifying the time-out\n using an absolute value is especially handy when you have\n a deadline for responses corresponding to a complete collection\n of requests (`t:request_id_collection/0`), since you do not have to\n recalculate the relative time until the deadline over and over again.","title":"gen_statem.response_timeout/0","ref":"gen_statem.html#t:response_timeout/0"},{"type":"type","doc":"Server name specification: `local`, `global`, or `via` registered.\n\nName specification to use when starting a `gen_statem` server.\nSee `start_link/3` and `t:server_ref/0` below.","title":"gen_statem.server_name/0","ref":"gen_statem.html#t:server_name/0"},{"type":"type","doc":"Server specification: `t:pid/0` or registered `t:server_name/0`.\n\nTo be used in [`call/2,3`](`call/3`) to specify the server.\n\nIt can be:\n\n- **`pid() | LocalName`** - The `gen_statem` is locally registered.\n\n- **`{Name, Node}`** - The `gen_statem` is locally registered\n on another node.\n\n- **`{global, GlobalName}`** - The `gen_statem` is globally registered\n in `m:global`.\n\n- **`{via, RegMod, ViaName}`** - The `gen_statem` is registered\n in an alternative process registry. The registry callback module\n `RegMod` is to export functions `register_name/2`, `unregister_name/1`,\n `whereis_name/1`, and `send/2`, which are to behave like\n the corresponding functions in `m:global`.\n Thus, `{via, global, GlobalName}` is the same as `{global, GlobalName}`.","title":"gen_statem.server_ref/0","ref":"gen_statem.html#t:server_ref/0"},{"type":"type","doc":"Return value from the [`start_monitor/3,4`](`start_monitor/3`) functions.\n\nAs for [`start_link/4`](#start-return-values) but a succesful return\nwraps the process ID and the [monitor reference](`erlang:monitor/2`) in a\n`{ok, {`[`pid()`](`t:pid/0`)`, `[`reference()`](`t:reference/0`)`}}`\ntuple.","title":"gen_statem.start_mon_ret/0","ref":"gen_statem.html#t:start_mon_ret/0"},{"type":"type","doc":"Server [start options](#start-options) for the\n[`start/3,4`](`start/3`), [`start_link/3,4`](`start_link/3`),\nand [`start_monitor/3,4`](`start_monitor/3`) functions.\n\nSee [`start_link/4`](#start-options).","title":"gen_statem.start_opt/0","ref":"gen_statem.html#t:start_opt/0"},{"type":"type","doc":"[Return value](#start-return-values) from the [`start/3,4`](`start/3`)\nand [`start_link/3,4`](`start_link/3`) functions.\n\nSee [`start_link/4`](#start-return-values).","title":"gen_statem.start_ret/0","ref":"gen_statem.html#t:start_ret/0"},{"type":"type","doc":"State name or state term.\n\nIf the [_callback mode_](`t:callback_mode/0`) is `handle_event_function`,\nthe state can be any term. After a _state change_ (`NextState =/= State`),\nall postponed events are retried.\n\nComparing two states for strict equality is assumed to be a fast operation,\nsince for every _state transition_ the `gen_statem` engine has to deduce\nif it is a _state change_.\n\n> #### Note {: .info }\n> The smaller the state term, in general, the faster the comparison.\n>\n> Note that if the \"same\" state term is returned for a state transition\n> (or a return action without a `NextState` field is used),\n> the comparison for equality is always fast because that can be seen\n> from the term handle.\n>\n> But if a newly constructed state term is returned,\n> both the old and the new state terms will have to be traversed\n> until an inequality is found, or until both terms\n> have been fully traversed.\n>\n> So it is possible to use large state terms that are fast to compare,\n> but very easy to accidentally mess up. Using small state terms is\n> the safe choice.","title":"gen_statem.state/0","ref":"gen_statem.html#t:state/0"},{"type":"type","doc":"Return value from any [_state callback_](#state-callback).\n\n`ActionType` is `t:enter_action/0` if the state callback\nwas called with a [_state enter call_](`t:state_enter/0`),\nand `t:action/0` if the state callback was called with an event.\n\n- **`{keep_state, NewData [, Actions]}`** - The same as\n `{next_state, CurrentState, NewData [, Actions]}`.\n\n- **`keep_state_and_data | {keep_state_and_data, Actions}`** -\n The same as `{keep_state, CurrentData [, Actions]}`.\n\n- **`{repeat_state, NewData [, Actions]}`** - If the `gen_statem`\n runs with [_state enter calls_](`t:state_enter/0`),\n the _state enter call_ is repeated, see type `t:transition_option/0`.\n Other than that `{repeat_state, NewData [, Actions]}` is the same as\n `{keep_state, NewData [, Actions]}`.\n\n- **`repeat_state_and_data | {repeat_state_and_data, Actions}`** -\n The same as `{repeat_state, CurrentData [, Actions]}`.\n\n- **`{stop, Reason [, NewData]}`** - Terminates the `gen_statem`\n by calling [`Module:terminate/3`](`c:terminate/3`)\n with `Reason` and `NewData`, if specified. An exit signal\n with this reason is sent to linked processes and ports.\n\n- **`stop`** - The same as `{stop, normal}`.\n\n- **`{stop_and_reply, Reason, Replies [, NewData]}`** -\n Sends all `Replies`, then terminates the `gen_statem`\n like with `{stop, Reason [, NewData]}`.\n\nAll these terms are tuples or atoms and will be so\nin all future versions of `gen_statem`.","title":"gen_statem.state_callback_result/2","ref":"gen_statem.html#t:state_callback_result/2"},{"type":"type","doc":"[_Callback mode_](`t:callback_mode/0`) modifier\nfor _state enter calls_: the atom `state_enter`.\n\nBoth _callback modes_ can use _state enter calls_,\nand this is selected by adding this `state_enter` flag\nto the [_callback mode_](`t:callback_mode/0`) return value from\n[`Module:callback_mode/0`](`c:callback_mode/0`).\n\nIf [`Module:callback_mode/0`](`c:callback_mode/0`) returns\na list containing `state_enter`, the `gen_statem` engine will,\nat every _state change_, that is; `NextState =/= CurrentState`,\ncall the [_state callback_](#state-callback) with arguments\n`(enter, OldState, Data)` or `(enter, OldState, State, Data)`,\ndepending on the [_callback mode_](`t:callback_mode/0`).\n\nThis may look like an event but is really a call performed\nafter the previous [_state callback_](#state-callback) returned,\nand before any event is delivered to the new\n[_state callback_](#state-callback).\nSee [`Module:StateName/3`](`c:'StateName'/3`) and\n[`Module:handle_event/4`](`c:handle_event/4`). A _state enter call_\nmay be repeated without doing a _state change_ by returning\na [`repeat_state`](`t:state_callback_result/2`) or\n[`repeat_state_and_data`](`t:state_callback_result/2`) action\nfrom the _state callback_.\n\nIf [`Module:callback_mode/0`](`c:callback_mode/0`) does not return\na list containing `state_enter`, no _state enter calls_ are done.\n\nIf [`Module:code_change/4`](`c:code_change/4`) should transform the state,\nit is regarded as a state rename and not a _state change_,\nwhich will not cause a _state enter call_.\n\nNote that a _state enter call_ **will** be done right before entering\nthe initial state, which may be seen as a state change from no state\nto the initial state. In this case `OldState =:= State`,\nwhich cannot happen for a subsequent state change,\nbut will happen when repeating the _state enter call_.","title":"gen_statem.state_enter/0","ref":"gen_statem.html#t:state_enter/0"},{"type":"type","doc":"","title":"gen_statem.state_enter_result/1","ref":"gen_statem.html#t:state_enter_result/1"},{"type":"type","doc":"Return value from a [_state callback_](#state-callback)\nafter a _state enter call_.\n\n`State` is the current state and it cannot be changed\nsince the state callback was called with a\n[_state enter call_](`t:state_enter/0`).\n\n- **`{next_state, State, NewData [, Actions]}`** -\n The `gen_statem` does a state transition to `State`, which has to be\n equal to the current state, sets `NewData`, and executes all `Actions`.","title":"gen_statem.state_enter_result/2","ref":"gen_statem.html#t:state_enter_result/2"},{"type":"type","doc":"State name in [_callback mode_](`t:callback_mode/0`) `state_functions`.\n\nIf the [_callback mode_](`t:callback_mode/0`) is `state_functions`,\nthe state must be an atom. After a _state change_ (`NextState =/= State`),\nall postponed events are retried. Note that the state `terminate`\nis not possible to use since it would collide with the optional\ncallback function [`Module:terminate/3`](`c:terminate/3`).","title":"gen_statem.state_name/0","ref":"gen_statem.html#t:state_name/0"},{"type":"type","doc":"How long to wait in the current state.\n\nStarts a timer set by `t:timeout_action/0`, or\n`{state_timeout, Time, EventContent [, Options]}`.\n\nWhen the timer expires an event of `t:event_type/0` `state_timeout`\nwill be generated. See `erlang:start_timer/4` for how `Time`\nand [`Options`](`t:timeout_option/0`) are interpreted. Future\n`erlang:start_timer/4` `Options` will not necessarily be supported.\n\nA _state change_ cancels this timer, if it is running.\nThat is, if the `t:timeout_action/0` that starts this timer\nis part of a list of `t:action/0`s for a _state change_,\n`NextState =/= CurrentState`, the timer runs in the **`NextState`**.\n\nIf the state machine stays in that new state, now the current state,\nthe timer will run until it expires, which creates the time-out event.\nIf the state machine changes states from the now current state,\nthe timer is cancelled. During the _state change_ from\nthe now current state, a new _state time-out_ may be started\nfor the next **`NextState`**.\n\nIf the `t:timeout_action/0` that starts this timer\nis part of a list of `t:action/0`s for a _state transition_\nthat is not a _state change_, the timer runs in the current state.\n\nIf `Time` is `infinity`, no timer is started,\nas it never would expire anyway.\n\nIf `Time` is relative and `0` no timer is actually started,\ninstead the the time-out event is enqueued to ensure\nthat it gets processed before any not yet received external event.\n\nSetting this timer while it is running will restart it\nwith the new time-out value. Therefore it is possible\nto cancel this time-out by setting it to `infinity`.\nIt can also be cancelled more explicitly with\n[`{state_timeout, cancel}`](`t:timeout_cancel_action/0`).\n\nThe timer `EventContent` can be updated with the\n[`{state_timeout, update, NewEventContent}`](`t:timeout_update_action/0`)\naction without affecting the time of expiry.","title":"gen_statem.state_timeout/0","ref":"gen_statem.html#t:state_timeout/0"},{"type":"type","doc":"Event time-out, generic time-outs or state time-out.\n\nThese _transition actions_ can be invoked by returning them from the\n[_state callback_](#state-callback), from\n[`Module:init/1`](`c:init/1`) or by passing them to\n[`enter_loop/4,5,6`](`enter_loop/6`).\n\nThese time-out actions sets time-out\n[transition options](`t:transition_option/0`).\n\n- **`Time`** - Short for `{timeout, Time, Time}`, that is,\n the time-out message is the time-out time. This form exists to allow the\n [_state callback_](#state-callback) return value\n `{next_state, NextState, NewData, Time}` like in `gen_fsm`.\n\n- **`{timeout, Time, EventContent [, Options]}`** -\n Sets the `t:transition_option/0` `t:event_timeout/0` to `Time`\n with `EventContent`, and time-out options\n [`Options`](`t:timeout_option/0`).\n\n- **`{{timeout,Name}, Time, EventContent [, Options]}`** -\n Sets the `t:transition_option/0` `t:generic_timeout/0` to `Time`\n for time-out `Name` with `EventContent`, and time-out options\n [`Options`](`t:timeout_option/0`).\\\n **Since OTP 20.0**.\n\n- **`{state_timeout, Time, EventContent [, Options]}`** -\n Sets the `t:transition_option/0` `t:state_timeout/0` to `Time`\n with `EventContent`, and time-out options\n [`Options`](`t:timeout_option/0`).\\\n **Since OTP 19.3**.","title":"gen_statem.timeout_action/0","ref":"gen_statem.html#t:timeout_action/0"},{"type":"type","doc":"Clearer way to cancel a time-out than the original\nsetting it to 'infinity'.\n\nIt has always been possible to cancel a time-out using\n`t:timeout_action/0` with `Time = infinity`, since setting a new\ntime-out time overrides a running timer, and since setting the time\nto `infinity` is optimized to not setting a timer (that never\nwill expire). Using this action shows the intention more clearly.","title":"gen_statem.timeout_cancel_action/0","ref":"gen_statem.html#t:timeout_cancel_action/0"},{"type":"type","doc":"[Event time-out](`t:event_timeout/0`),\n[generic time-out](`t:generic_timeout/0`),\nor [state time-out](`t:state_timeout/0`).\n\nThe time-out event types that the state machine can generate\nfor itself with the corresponding `t:timeout_action/0`s:\n\n| Time-out type | Action | Event type |\n|-------------------|--------------------------------|-------------------|\n| Event time-out | `{timeout, Time, ...}` | `timeout` |\n| Generic time-out | `{{timeout, Name}, Time, ...}` | `{timeout, Name}` |\n| State time-out | `{state_timeout, Time, ...}` | `state_timeout` |\n\nIn short; the action to set a time-out with\n[`EventType`](`t:timeout_event_type/0`) is `{EventType, Time, ...}`.","title":"gen_statem.timeout_event_type/0","ref":"gen_statem.html#t:timeout_event_type/0"},{"type":"type","doc":"Time-out timer start option, to select absolute time of expiry.\n\nIf `Abs` is `true` an absolute timer is started,\nand if it is `false` a relative, which is the default.\nSee [`erlang:start_timer/4`](`erlang:start_timer/4`) for details.","title":"gen_statem.timeout_option/0","ref":"gen_statem.html#t:timeout_option/0"},{"type":"type","doc":"Update the `EventContent` without affecting the time of expiry.\n\nSets a new `EventContent` for a running time-out timer.\nSee [timeout_action()](`t:timeout_action/0`) for how to start a time-out.\n\nIf no time-out of this type is active, instead inserts\nthe time-out event just like when starting a time-out\nwith relative `Time = 0`. This is a time-out autostart with\nimmediate expiry, so there will be noise for example\nif a generic time-out name was misspelled.","title":"gen_statem.timeout_update_action/0","ref":"gen_statem.html#t:timeout_update_action/0"},{"type":"type","doc":"_State transition_ options set by [actions](`t:action/0`).\n\nThese determine what happens during the _state transition_.\nThe _state transition_ takes place when the\n[_state callback_](#state-callback) has processed an event\nand returns. Here are the sequence of steps for a _state transition_:\n\n1. All returned [actions](`t:action/0`) are processed\n in order of appearance. In this step all replies generated\n by any `t:reply_action/0` are sent. Other actions set\n `t:transition_option/0`s that come into play in subsequent steps.\n\n2. If [_state enter calls_](`t:state_enter/0`) are used,\n it is either the initial state or one of the callback results\n [`repeat_state`](`t:state_callback_result/2`) or\n [`repeat_state_and_data`](`t:state_callback_result/2`) is used the\n `gen_statem` engine calls the current _state callback_ with arguments\n [`(enter, State, Data)`](`t:state_enter/0`) or\n [`(enter, State, State, Data)`](`t:state_enter/0`) (depending on\n [_callback mode_](`t:callback_mode/0`)) and when it returns\n starts again from the top of this sequence.\n\n If [_state enter calls_](`t:state_enter/0`) are used,\n and the state changes, the `gen_statem` engine calls\n the new _state callback_ with arguments\n [`(enter, OldState, Data)`](`t:state_enter/0`) or\n [`(enter, OldState, State, Data)`](`t:state_enter/0`) (depending on\n [_callback mode_](`t:callback_mode/0`)) and when it returns\n starts again from the top of this sequence.\n\n3. If `t:postpone/0` is `true`, the current event is postponed.\n\n4. If this is a _state change_, the queue of incoming events is reset\n to start with the oldest postponed.\n\n5. All events stored with `t:action/0` `next_event` are inserted\n to be processed before previously queued events.\n\n6. Time-out timers `t:event_timeout/0`, `t:generic_timeout/0` and\n `t:state_timeout/0` are handled. Time-outs with zero time\n are guaranteed to be delivered to the state machine\n before any external not yet received event so if there is\n such a time-out requested, the corresponding time-out zero event\n is enqueued as the newest received event; that is after\n already queued events such as inserted and postponed events.\n\n Any event cancels an `t:event_timeout/0` so a zero time event time-out\n is only generated if the event queue is empty.\n\n A _state change_ cancels a `t:state_timeout/0` and any new transition\n option of this type belongs to the new state, that is;\n a `t:state_timeout/0` applies to the state the state machine enters.\n\n7. If there are enqueued events the\n [_state callback_](#state-callback) for the possibly\n new state is called with the oldest enqueued event, and we start again\n from the top of this sequence.\n\n8. Otherwise the `gen_statem` goes into `receive` or hibernation\n (if `t:hibernate/0` is `true`) to wait for the next message.\n In hibernation the next non-system event awakens the `gen_statem`,\n or rather the next incoming message awakens the `gen_statem`,\n but if it is a system event it goes right back into hibernation.\n When a new message arrives the\n [_state callback_](#state-callback) is called with\n the corresponding event, and we start again\n from the top of this sequence.\n\n> #### Note {: .info }\n> The behaviour of a zero time-out (a time-out with time `0`)\n> differs subtly from Erlang's `receive ... after 0 ... end`.\n>\n> The latter receives one message if there is one,\n> while using the `t:timeout_action/0` `{timeout, 0}` does not\n> receive any external event.\n>\n> `m:gen_server`'s time-out works like Erlang's\n> `receive ... after 0 ... end`, in contrast to `gen_statem`.","title":"gen_statem.transition_option/0","ref":"gen_statem.html#t:transition_option/0"},{"type":"module","doc":"An event handler that logs events to disk.\n\nThis module is a `gen_event` handler module that can be installed in any\n`gen_event` process. It logs onto disk all events that are sent to an event\nmanager. Each event is written as a binary, which makes the logging very fast.\nHowever, a tool such as the Report Browser (`m:rb`) must be used to read the\nfiles. The events are written to multiple files. When all files have been used,\nthe first one is reused and overwritten. The directory location, the number of\nfiles, and the size of each file are configurable. The directory will include\none file called `index`, and report files `1, 2, ...`.","title":"log_mf_h","ref":"log_mf_h.html"},{"type":"module","doc":"`m:gen_event`, `m:rb`","title":"See Also - log_mf_h","ref":"log_mf_h.html#module-see-also"},{"type":"function","doc":"","title":"log_mf_h.init/3","ref":"log_mf_h.html#init/3"},{"type":"function","doc":"Initiates the event handler. Returns `Args`, which is to be used in a call to\n[`gen_event:add_handler(EventMgr, log_mf_h, Args)`](`gen_event:add_handler/3`).\n\n`Dir` specifies which directory to use for the log files. `MaxBytes` specifies\nthe size of each individual file. `MaxFiles` specifies how many files are used.\n`Pred` is a predicate function used to filter the events. If no predicate\nfunction is specified, all events are logged.","title":"log_mf_h.init/4","ref":"log_mf_h.html#init/4"},{"type":"opaque","doc":"Term to be sent to `gen_event:add_handler/3`.","title":"log_mf_h.args/0","ref":"log_mf_h.html#t:args/0"},{"type":"type","doc":"","title":"log_mf_h.b/0","ref":"log_mf_h.html#t:b/0"},{"type":"type","doc":"","title":"log_mf_h.f/0","ref":"log_mf_h.html#t:f/0"},{"type":"type","doc":"","title":"log_mf_h.pred/0","ref":"log_mf_h.html#t:pred/0"},{"type":"module","doc":"Load distribution facility.\n\nThis module can be used to run a set of Erlang nodes as a pool of computational\nprocessors. It is organized as a master and a set of slave nodes and includes\nthe following features:\n\n- The slave nodes send regular reports to the master about their current load.\n- Queries can be sent to the master to determine which node will have the least\n load.\n\nThe BIF [`statistics(run_queue)`](`statistics/1`) is used for estimating future\nloads. It returns the length of the queue of ready to run processes in the\nErlang runtime system.\n\nThe slave nodes are started with the `m:slave` module. This effects terminal\nI/O, file I/O, and code loading.\n\nIf the master node fails, the entire pool exits.\n\n[](){: #files }","title":"pool","ref":"pool.html"},{"type":"module","doc":"`.hosts.erlang` is used to pick hosts where nodes can be started. For\ninformation about format and location of this file, see `net_adm:host_file/0`.\n\n`$HOME/.erlang.slave.out.HOST` is used for all extra I/O that can come from the\nslave nodes on standard I/O. If the startup procedure does not work, this file\ncan indicate the reason.","title":"Files - pool","ref":"pool.html#module-files"},{"type":"function","doc":"Ensures that a pool master is running and includes `Node` in the pool master's\npool of nodes.","title":"pool.attach/1","ref":"pool.html#attach/1"},{"type":"function","doc":"Returns the node with the expected lowest future load.","title":"pool.get_node/0","ref":"pool.html#get_node/0"},{"type":"function","doc":"Returns a list of the current member nodes of the pool.","title":"pool.get_nodes/0","ref":"pool.html#get_nodes/0"},{"type":"function","doc":"Spawns a process on the pool node that is expected to have the lowest future\nload.","title":"pool.pspawn/3","ref":"pool.html#pspawn/3"},{"type":"function","doc":"Spawns and links to a process on the pool node that is expected to have the\nlowest future load.","title":"pool.pspawn_link/3","ref":"pool.html#pspawn_link/3"},{"type":"function","doc":"","title":"pool.start/1","ref":"pool.html#start/1"},{"type":"function","doc":"Starts a new pool.\n\nThe file `.hosts.erlang` is read to find host names where the\npool nodes can be started; see section [Files](`m:pool#module-files`). The startup\nprocedure fails if the file is not found.\n\nThe slave nodes are started with [`slave:start/2,3`](`slave:start/2`), passing\nalong `Name` and, if provided, `Args`. `Name` is used as the first part of the\nnode names, `Args` is used to specify command-line arguments.\n\nAccess rights must be set so that all nodes in the pool have the authority to\naccess each other.\n\nThe function is synchronous and all the nodes, and all the system servers, are\nrunning when it returns a value.","title":"pool.start/2","ref":"pool.html#start/2"},{"type":"function","doc":"Stops the pool and kills all the slave nodes.","title":"pool.stop/0","ref":"pool.html#stop/0"},{"type":"module","doc":"Functions for asynchronous and synchronous start of processes adhering to the\nOTP design principles.\n\nThis module is used to start processes adhering to the\n[OTP Design Principles](`e:system:design_principles.md`). Specifically, the\nfunctions in this module are used by the OTP standard behaviors (for example,\n`m:gen_server` and `m:gen_statem`) when starting new processes. The functions can\nalso be used to start _special processes_, user-defined processes that comply to\nthe OTP design principles. For an example, see section\n[sys and proc_lib](`e:system:spec_proc.md`) in OTP Design Principles.\n\nSome useful information is initialized when a process starts. The registered\nnames, or the process identifiers, of the parent process, and the parent\nancestors, are stored together with information about the function initially\ncalled in the process.\n\nWhile in \"plain Erlang\", a process is said to terminate normally only for exit\nreason `normal`, a process started using `m:proc_lib` is also said to terminate\nnormally if it exits with reason `shutdown` or `{shutdown,Term}`. `shutdown` is\nthe reason used when an application (supervision tree) is stopped.\n\nWhen a process that is started using `m:proc_lib` terminates abnormally (that is,\nwith another exit reason than `normal`, `shutdown`, or `{shutdown,Term}`), a\n_crash report_ is generated, which is written to terminal by the default logger\nhandler setup by Kernel. For more information about how crash reports were\nlogged prior to Erlang/OTP 21.0, see\n[SASL Error Logging](`e:sasl:error_logging.md`) in the SASL User's Guide.\n\nUnlike in \"plain Erlang\", `m:proc_lib` processes will not generate _error\nreports_, which are written to the terminal by the emulator. All exceptions are\nconverted to _exits_ which are ignored by the default `logger` handler.\n\nThe crash report contains the previously stored information, such as ancestors\nand initial function, the termination reason, and information about other\nprocesses that terminate as a result of this process terminating.","title":"proc_lib","ref":"proc_lib.html"},{"type":"module","doc":"`m:logger`","title":"See Also - proc_lib","ref":"proc_lib.html#module-see-also"},{"type":"function","doc":"Equivalent to [`format(CrashReport, latin1)`](`format/2`).","title":"proc_lib.format/1","ref":"proc_lib.html#format/1"},{"type":"function","doc":"> #### Note {: .info }\n>\n> This function is deprecated in the sense that the `error_logger` is no longer\n> the preferred interface for logging in Erlang/OTP. A new\n> [logging API](`e:kernel:logger_chapter.md`) was added in Erlang/OTP 21.0, but\n> legacy `error_logger` handlers can still be used. New Logger handlers do not\n> need to use this function, since the formatting callback (`report_cb`) is\n> included as metadata in the log event.\n\nThis function can be used by a user-defined legacy `error_logger` event handler\nto format a crash report. The crash report is sent using `m:logger`, and the\nevent to be handled is of the format\n`{error_report, GL, {Pid, crash_report, CrashReport}}`, where `GL` is the group\nleader pid of process `Pid` that sent the crash report.","title":"proc_lib.format/2","ref":"proc_lib.html#format/2"},{"type":"function","doc":"> #### Note {: .info }\n>\n> This function is deprecated in the sense that the `error_logger` is no longer\n> the preferred interface for logging in Erlang/OTP. A new\n> [logging API](`e:kernel:logger_chapter.md`) was added in Erlang/OTP 21.0, but\n> legacy `error_logger` handlers can still be used. New Logger handlers do not\n> need to used this function, since the formatting callback (`report_cb`) is\n> included as metadata in the log event.\n\nThis function can be used by a user-defined legacy `error_logger` event handler\nto format a crash report. When Depth is specified as a positive integer, it is\nused in the format string to limit the output as follows:\n`io_lib:format(\"~P\", [Term,Depth])`.","title":"proc_lib.format/3","ref":"proc_lib.html#format/3"},{"type":"function","doc":"Returns either `undefined` or the label for the process Pid set with\n[`proc_lib:set_label/1`](`set_label/1`).","title":"proc_lib.get_label/1","ref":"proc_lib.html#get_label/1"},{"type":"function","doc":"This function does the same as (and does call) the\n[`hibernate/3`](`erlang:hibernate/3`) BIF, but ensures that exception handling\nand logging continues to work as expected when the process wakes up.\n\nAlways use this function instead of the BIF for processes started using\n`proc_lib` functions.","title":"proc_lib.hibernate/3","ref":"proc_lib.html#hibernate/3"},{"type":"function","doc":"Equivalent to [`init_ack(Parent, Ret)`](`init_ack/2`) where `Parent` is\nthe process that called `start/5`.","title":"proc_lib.init_ack/1","ref":"proc_lib.html#init_ack/1"},{"type":"function","doc":"This function must only be used by a process that has been started by a\n[`start[_link|_monitor]/3,4,5`](`start/5`) function. It tells `Parent` that the\nprocess has initialized itself and started.\n\nFunction [`init_ack/1`](`init_ack/1`) uses the parent value previously stored by\nthe start function used.\n\nIf neither this function nor [`init_fail/2,3`](`init_fail/3`) is called by the\nstarted process, the start function returns an error tuple when the started\nprocess exits, or when the start function time-out (if used) has passed, see\n[`start/3,4,5`](`start/5`).\n\n> #### Warning {: .warning }\n>\n> Do not use this function to return an error indicating that the process start\n> failed. When doing so the start function can return before the failing process\n> has exited, which may block VM resources required for a new start attempt to\n> succeed. Use [`init_fail/2,3`](`init_fail/3`) for that purpose.\n\nThe following example illustrates how this function and `proc_lib:start_link/3`\nare used:\n\n```erlang\n-module(my_proc).\n-export([start_link/0]).\n-export([init/1]).\n\nstart_link() ->\n proc_lib:start_link(my_proc, init, [self()]).\n\ninit(Parent) ->\n case do_initialization() of\n ok ->\n proc_lib:init_ack(Parent, {ok, self()});\n {error, Reason} ->\n exit(Reason)\n end,\n loop().\n\n...\n```","title":"proc_lib.init_ack/2","ref":"proc_lib.html#init_ack/2"},{"type":"function","doc":"Equivalent to [`init_fail(Parent, Return, Exception)`](`init_fail/3`) where\n`Parent` is the process that called `start/5`.","title":"proc_lib.init_fail/2","ref":"proc_lib.html#init_fail/2"},{"type":"function","doc":"This function must only be used by a process that has been started by a\n[`start[_link|_monitor]/3,4,5`](`start/3`) function. It tells `Parent` that the\nprocess has failed to initialize, and immediately raises an exception according\nto `Exception`. The start function then returns `Ret`.\n\nSee `erlang:raise/3` for a description of `Class`, `Reason` and `Stacktrace`.\n\n> #### Warning {: .warning }\n>\n> Do not consider catching the exception from this function. That would defeat\n> its purpose. A process started by a [`start[_link|_monitor]/3,4,5`](`start/3`)\n> function should end in a value (that will be ignored) or an exception that\n> will be handled by this module. See [Description](`m:proc_lib`).\n\nIf neither this function nor [`init_ack/1,2`](`init_ack/1`) is called by the\nstarted process, the start function returns an error tuple when the started\nprocess exits, or when the start function time-out (if used) has passed, see\n[`start/3,4,5`](`start/3`).\n\nThe following example illustrates how this function and `proc_lib:start_link/3`\ncan be used:\n\n```erlang\n-module(my_proc).\n-export([start_link/0]).\n-export([init/1]).\n\nstart_link() ->\n proc_lib:start_link(my_proc, init, [self()]).\n\ninit(Parent) ->\n case do_initialization() of\n ok ->\n proc_lib:init_ack(Parent, {ok, self()});\n {error, Reason} = Error ->\n proc_lib:init_fail(Parent, Error, {exit, normal})\n end,\n loop().\n\n...\n```","title":"proc_lib.init_fail/3","ref":"proc_lib.html#init_fail/3"},{"type":"function","doc":"Extracts the initial call of a process that was started using one of the spawn\nor start functions in this module. `Process` can either be a pid, an integer\ntuple (from which a pid can be created), or the process information of a process\n`Pid` fetched through an `erlang:process_info(Pid)` function call.\n\n> #### Note {: .info }\n>\n> The list `Args` no longer contains the arguments, but the same number of atoms\n> as the number of arguments; the first atom is `'Argument__1'`, the second\n> `'Argument__2'`, and so on. The reason is that the argument list could waste a\n> significant amount of memory, and if the argument list contained funs, it\n> could be impossible to upgrade the code for the module.\n>\n> If the process was spawned using a fun, [`initial_call/1`](`initial_call/1`)\n> no longer returns the fun, but the module, function for the local function\n> implementing the fun, and the arity, for example,\n> `{some_module,-work/3-fun-0-,0}` (meaning that the fun was created in function\n> `some_module:work/3`). The reason is that keeping the fun would prevent code\n> upgrade for the module, and that a significant amount of memory could be\n> wasted.","title":"proc_lib.initial_call/1","ref":"proc_lib.html#initial_call/1"},{"type":"function","doc":"Set a label for the current process. The primary purpose is to aid in debugging\nunregistered processes. The process label can be used in tools and crash reports\nto identify processes but it doesn't have to be unique or an atom, as a\nregistered name needs to be. The process label can be any term, for example\n`{worker_process, 1..N}`.\n\nUse [`proc_lib:get_label/1`](`get_label/1`) to lookup the process description.","title":"proc_lib.set_label/1","ref":"proc_lib.html#set_label/1"},{"type":"function","doc":"","title":"proc_lib.spawn/1","ref":"proc_lib.html#spawn/1"},{"type":"function","doc":"","title":"proc_lib.spawn/2","ref":"proc_lib.html#spawn/2"},{"type":"function","doc":"","title":"proc_lib.spawn/3","ref":"proc_lib.html#spawn/3"},{"type":"function","doc":"Spawns a new process and initializes it as described in the beginning of this\nmanual page. The process is spawned using the [`spawn`](`erlang:spawn/1`) BIFs.","title":"proc_lib.spawn/4","ref":"proc_lib.html#spawn/4"},{"type":"function","doc":"","title":"proc_lib.spawn_link/1","ref":"proc_lib.html#spawn_link/1"},{"type":"function","doc":"","title":"proc_lib.spawn_link/2","ref":"proc_lib.html#spawn_link/2"},{"type":"function","doc":"","title":"proc_lib.spawn_link/3","ref":"proc_lib.html#spawn_link/3"},{"type":"function","doc":"Spawns a new process and initializes it as described in the beginning of this\nmanual page. The process is spawned using the\n[`spawn_link`](`erlang:spawn_link/1`) BIFs.","title":"proc_lib.spawn_link/4","ref":"proc_lib.html#spawn_link/4"},{"type":"function","doc":"","title":"proc_lib.spawn_opt/2","ref":"proc_lib.html#spawn_opt/2"},{"type":"function","doc":"","title":"proc_lib.spawn_opt/3","ref":"proc_lib.html#spawn_opt/3"},{"type":"function","doc":"","title":"proc_lib.spawn_opt/4","ref":"proc_lib.html#spawn_opt/4"},{"type":"function","doc":"Spawns a new process and initializes it as described in the beginning of this\nmanual page. The process is spawned using the\n[`erlang:spawn_opt`](`erlang:spawn_opt/2`) BIFs.","title":"proc_lib.spawn_opt/5","ref":"proc_lib.html#spawn_opt/5"},{"type":"function","doc":"","title":"proc_lib.start/3","ref":"proc_lib.html#start/3"},{"type":"function","doc":"","title":"proc_lib.start/4","ref":"proc_lib.html#start/4"},{"type":"function","doc":"Starts a new process synchronously. Spawns the process and waits for it to\nstart.\n\nTo indicate a succesful start, the started process _must_ call\n[`init_ack(Parent, Ret)`](`init_ack/2`) where `Parent` is the process that\nevaluates this function, or [`init_ack(Ret)`](`init_ack/1`). `Ret` is then\nreturned by this function.\n\nIf the process fails to start, it _must_ fail; preferably by calling\n[`init_fail(Parent, Ret, Exception)` ](`init_fail/3`) where `Parent` is the\nprocess that evaluates this function, or\n[`init_fail(Ret, Exception)`](`init_fail/2`). `Ret` is then returned by this\nfunction, and the started process fails with `Exception`.\n\nIf the process instead fails before calling `init_ack/1,2` or `init_fail/2,3`,\nthis function returns `{error, Reason}` where `Reason` depends a bit on the\nexception just like for a process link `{'EXIT',Pid,Reason}` message.\n\nIf `Time` is specified as an integer, this function waits for `Time`\nmilliseconds for the new process to call `init_ack/1,2` or `init_fail/2,3`,\notherwise the process gets killed and `Ret = {error, timeout}` is returned.\n\nArgument `SpawnOpts`, if specified, is passed as the last argument to the\n[`spawn_opt/4`](`erlang:spawn_opt/4`) BIF.\n\n> #### Note {: .info }\n>\n> Using spawn option `monitor` is not allowed. It causes the function to fail\n> with reason `badarg`.\n>\n> Using spawn option `link` will set a link to the spawned process, just like\n> [start_link/3,4,5](`start_link/3`).","title":"proc_lib.start/5","ref":"proc_lib.html#start/5"},{"type":"function","doc":"","title":"proc_lib.start_link/3","ref":"proc_lib.html#start_link/3"},{"type":"function","doc":"","title":"proc_lib.start_link/4","ref":"proc_lib.html#start_link/4"},{"type":"function","doc":"Starts a new process synchronously. Spawns the process and waits for it to\nstart. A link is atomically set on the newly spawned process.\n\n> #### Note {: .info }\n>\n> If the started process gets killed or crashes with a reason that is not\n> `normal`, the process link will kill the calling process so this function does\n> not return, unless the calling process traps exits. For example, if this\n> function times out it will kill the spawned process, and then the link might\n> kill the calling process.\n\nBesides setting a link on the spawned process this function behaves like\n[start/5](`start/5`).\n\nWhen the calling process traps exits; if this function returns due to the\nspawned process exiting (any error return), this function receives (consumes)\nthe `'EXIT'` message, also when this function times out and kills the spawned\nprocess.\n\n> #### Note {: .info }\n>\n> Using spawn option `monitor` is not allowed. It causes the function to fail\n> with reason `badarg`.","title":"proc_lib.start_link/5","ref":"proc_lib.html#start_link/5"},{"type":"function","doc":"","title":"proc_lib.start_monitor/3","ref":"proc_lib.html#start_monitor/3"},{"type":"function","doc":"","title":"proc_lib.start_monitor/4","ref":"proc_lib.html#start_monitor/4"},{"type":"function","doc":"Starts a new process synchronously. Spawns the process and waits for it to\nstart. A monitor is atomically set on the newly spawned process.\n\nBesides setting a monitor on the spawned process this function behaves like\n[start/5](`start/5`).\n\nThe return value is `{Ret, Mon}` where `Ret` corresponds to the `Ret` argument\nin the call to `init_ack/1,2` or `init_fail/2,3`, and `Mon` is the monitor\nreference of the monitor that has been set up.\n\nIf this function returns due to the spawned process exiting, that is returns any\nerror value, a `'DOWN'` message will be delivered to the calling process, also\nwhen this function times out and kills the spawned process.\n\n> #### Note {: .info }\n>\n> Using spawn option `monitor` is not allowed. It causes the function to fail\n> with reason `badarg`.\n>\n> Using spawn option `link` will set a link to the spawned process, just like\n> [start_link/3,4,5](`start_link/3`).","title":"proc_lib.start_monitor/5","ref":"proc_lib.html#start_monitor/5"},{"type":"function","doc":"Equivalent to [`stop(Process, normal, infinity)`](`stop/3`).","title":"proc_lib.stop/1","ref":"proc_lib.html#stop/1"},{"type":"function","doc":"Orders the process to exit with the specified `Reason` and waits for it to\nterminate.\n\nReturns `ok` if the process exits with the specified `Reason` within `Timeout`\nmilliseconds.\n\nIf the call times out, a `timeout` exception is raised.\n\nIf the process does not exist, a `noproc` exception is raised.\n\nThe implementation of this function is based on the `terminate` system message,\nand requires that the process handles system messages correctly. For information\nabout system messages, see `m:sys` and section\n[sys and proc_lib](`e:system:spec_proc.md`) in OTP Design Principles.","title":"proc_lib.stop/3","ref":"proc_lib.html#stop/3"},{"type":"function","doc":"This function is used by functions `\\c:i/0` and `\\c:regs/0` to present process\ninformation.\n\nThis function extracts the initial call of a process that was started using one\nof the spawn or start functions in this module, and translates it to more useful\ninformation. `Process` can either be a pid, an integer tuple (from which a pid\ncan be created), or the process information of a process `Pid` fetched through\nan `erlang:process_info(Pid)` function call.\n\nIf the initial call is to one of the system-defined behaviors such as\n`gen_server` or `gen_event`, it is translated to more useful information. If a\n`gen_server` is spawned, the returned `Module` is the name of the callback\nmodule and `Function` is `init` (the function that initiates the new server).\n\nA `supervisor` and a `supervisor_bridge` are also `gen_server` processes. To\nreturn information that this process is a supervisor and the name of the\ncallback module, `Module` is `supervisor` and `Function` is the name of the\nsupervisor callback module. `Arity` is `1`, as the `init/1` function is called\ninitially in the callback module.\n\nBy default, `{proc_lib,init_p,5}` is returned if no information about the\ninitial call can be found. It is assumed that the caller knows that the process\nhas been spawned with the `proc_lib` module.","title":"proc_lib.translate_initial_call/1","ref":"proc_lib.html#translate_initial_call/1"},{"type":"type","doc":"","title":"proc_lib.dict_or_pid/0","ref":"proc_lib.html#t:dict_or_pid/0"},{"type":"type","doc":"An exception passed to `init_fail/3`. See `erlang:raise/3` for a description\nof `Class`, `Reason` and `Stacktrace`.","title":"proc_lib.exception/0","ref":"proc_lib.html#t:exception/0"},{"type":"type","doc":"Equivalent to `t:erlang:spawn_opt_option/0`.","title":"proc_lib.spawn_option/0","ref":"proc_lib.html#t:spawn_option/0"},{"type":"type","doc":"A restricted set of [spawn options](`t:spawn_option/0`). Most notably `monitor`\nis _not_ part of these options.","title":"proc_lib.start_spawn_option/0","ref":"proc_lib.html#t:start_spawn_option/0"},{"type":"behaviour","doc":"Generic supervisor behavior.\n\nThis behavior module provides a supervisor, a process that supervises other\nprocesses called child processes. A child process can either be another\nsupervisor or a worker process. Worker processes are normally implemented using\none of the `m:gen_event`, `m:gen_server`, or `m:gen_statem` behaviors. A\nsupervisor implemented using this module has a standard set of interface\nfunctions and includes functionality for tracing and error reporting.\nSupervisors are used to build a hierarchical process structure called a\nsupervision tree, a nice way to structure a fault-tolerant application. For more\ninformation, see [Supervisor Behaviour](`e:system:sup_princ.md`) in OTP Design\nPrinciples.\n\nA supervisor expects the definition of which child processes to supervise to be\nspecified in a callback module exporting a predefined set of functions.\n\nUnless otherwise stated, all functions in this module fail if the specified\nsupervisor does not exist or if bad arguments are specified.\n\n[](){: #supervision_princ }","title":"supervisor","ref":"supervisor.html"},{"type":"behaviour","doc":"The supervisor is responsible for starting, stopping, and monitoring its child\nprocesses. The basic idea of a supervisor is that it must keep its child\nprocesses alive by restarting them when necessary.\n\nThe children of a supervisor are defined as a list of _child specifications_.\nWhen the supervisor is started, the child processes are started in order from\nleft to right according to this list. When the supervisor is going to terminate,\nit first terminates its child processes in reversed start order, from right to\nleft.\n\n[](){: #sup_flags }","title":"Supervision Principles - supervisor","ref":"supervisor.html#module-supervision-principles"},{"type":"behaviour","doc":"The supervisor properties are defined by the supervisor flags. The type\ndefinition for the supervisor flags is as follows:\n\n```erlang\nsup_flags() = #{strategy => strategy(), % optional\n intensity => non_neg_integer(), % optional\n period => pos_integer(), % optional\n auto_shutdown => auto_shutdown()} % optional\n```\n\n#### Restart Strategies\n\nA supervisor can have one of the following _restart strategies_ specified with\nthe `strategy` key in the above map:\n\n- `one_for_one` \\- If one child process terminates and is to be restarted, only\n that child process is affected. This is the default restart strategy.\n- `one_for_all` \\- If one child process terminates and is to be restarted, all\n other child processes are terminated and then all child processes are\n restarted.\n- `rest_for_one` \\- If one child process terminates and is to be restarted, the\n 'rest' of the child processes (that is, the child processes after the\n terminated child process in the start order) are terminated. Then the\n terminated child process and all child processes after it are restarted.\n- `simple_one_for_one` \\- A simplified `one_for_one` supervisor, where all child\n processes are dynamically added instances of the same process type, that is,\n running the same code.\n\n Functions `delete_child/2` and `restart_child/2` are invalid for\n `simple_one_for_one` supervisors and return `{error,simple_one_for_one}` if\n the specified supervisor uses this restart strategy.\n\n Function `terminate_child/2` can be used for children under\n `simple_one_for_one` supervisors by specifying the child's `t:pid/0` as the\n second argument. If instead the child specification identifier is used,\n [`terminate_child/2`](`terminate_child/2`) return\n `{error,simple_one_for_one}`.\n\n As a `simple_one_for_one` supervisor can have many children, it shuts them all\n down asynchronously. This means that the children do their cleanup in\n parallel, and therefore the order in which they are stopped is not defined.\n\n#### Restart intensity and period\n\nTo prevent a supervisor from getting into an infinite loop of child process\nterminations and restarts, a _maximum restart intensity_ is defined using two\ninteger values specified with keys `intensity` and `period` in the above map.\nAssuming the values `MaxR` for `intensity` and `MaxT` for `period`, then, if\nmore than `MaxR` restarts occur within `MaxT` seconds, the supervisor terminates\nall child processes and then itself. The termination reason for the supervisor\nitself in that case will be `shutdown`. `intensity` defaults to `1` and `period`\ndefaults to `5`.\n\n[](){: #auto_shutdown }\n\n#### Automatic Shutdown\n\nA supervisor can be configured to automatically shut itself down with exit\nreason `shutdown` when [significant children](`m:supervisor#significant_child`)\nterminate with the `auto_shutdown` key in the above map:\n\n- `never` \\- Automic shutdown is disabled. This is the default setting.\n\n With `auto_shutdown` set to `never`, child specs with the `significant` flag\n set to `true` are considered invalid and will be rejected.\n\n- `any_significant` \\- The supervisor will shut itself down when _any_\n significant child terminates, that is, when a `transient` significant child\n terminates normally or when a `temporary` significant child terminates\n normally or abnormally.\n- `all_significant` \\- The supervisor will shut itself down when _all_\n significant children have terminated, that is, when the _last active_\n significant child terminates. The same rules as for `any_significant` apply.\n\nFor more information, see the section\n[Automatic Shutdown](`e:system:sup_princ.md#automatic-shutdown`) in Supervisor\nBehavior in OTP Design Principles.\n\n> #### Warning {: .warning }\n>\n> The automatic shutdown feature appeared in OTP 24.0, but applications using\n> this feature will also compile and run with older OTP versions.\n>\n> However, such applications, when compiled with an OTP version that predates\n> the appearance of the automatic shutdown feature, will leak processes because\n> the automatic shutdowns they rely on will not happen.\n>\n> It is up to implementors to take proper precautions if they expect that their\n> applications may be compiled with older OTP versions.\n\n[](){: #child_spec }","title":"Supervisor flags - supervisor","ref":"supervisor.html#module-supervisor-flags"},{"type":"behaviour","doc":"The type definition of a child specification is as follows:\n\n```erlang\nchild_spec() = #{id => child_id(), % mandatory\n start => mfargs(), % mandatory\n restart => restart(), % optional\n significant => significant(), % optional\n shutdown => shutdown(), % optional\n type => worker(), % optional\n modules => modules()} % optional\n```\n\nThe old tuple format is kept for backwards compatibility, see `t:child_spec/0`,\nbut the map is preferred.\n\n- `id` is used to identify the child specification internally by the supervisor.\n\n The `id` key is mandatory.\n\n Notice that this identifier on occations has been called \"name\". As far as\n possible, the terms \"identifier\" or \"id\" are now used but to keep backward\n compatibility, some occurences of \"name\" can still be found, for example in\n error messages.\n\n- `start` defines the function call used to start the child process. It must be\n a module-function-arguments tuple `{M,F,A}` used as\n [`apply(M,F,A)`](`apply/3`).\n\n The start function _must create and link to_ the child process, and must\n return `{ok,Child}` or `{ok,Child,Info}`, where `Child` is the pid of the\n child process and `Info` any term that is ignored by the supervisor.\n\n The start function can also return `ignore` if the child process for some\n reason cannot be started, in which case the child specification is kept by the\n supervisor (unless it is a temporary child) but the non-existing child process\n is ignored.\n\n If something goes wrong, the function can also return an error tuple\n `{error,Error}`.\n\n Notice that the `start_link` functions of the different behavior modules\n fulfill the above requirements.\n\n The `start` key is mandatory.\n\n- [](){: #restart } `restart` defines when a terminated child process must be\n restarted. A `permanent` child process is always restarted. A `temporary`\n child process is never restarted (even when the supervisor's restart strategy\n is `rest_for_one` or `one_for_all` and a sibling's death causes the temporary\n process to be terminated). A `transient` child process is restarted only if it\n terminates abnormally, that is, with another exit reason than `normal`,\n `shutdown`, or `{shutdown,Term}`.\n\n The `restart` key is optional. If it is not specified, it defaults to\n `permanent`.\n\n- [](){: #significant_child } `significant` defines if a child is considered\n significant for [automatic self-shutdown](`m:supervisor#auto_shutdown`) of the\n supervisor.\n\n Setting this option to `true` when the [restart type](`m:supervisor#restart`)\n is `permanent` is invalid. Also, it is considered invalid to start children\n with this option set to `true` in a supervisor when the\n [`auto_shutdown`](`m:supervisor#auto_shutdown`) supervisor flag is set to\n `never`.\n\n The `significant` key is optional. If it is not specified, it defaults to\n `false`.\n\n- `shutdown` defines how a child process must be terminated. `brutal_kill` means\n that the child process is unconditionally terminated using\n [`exit(Child,kill)`](`exit/2`). An integer time-out value means that the\n supervisor tells the child process to terminate by calling\n [`exit(Child,shutdown)`](`exit/2`) and then wait for an exit signal with\n reason `shutdown` back from the child process. If no exit signal is received\n within the specified number of milliseconds, the child process is\n unconditionally terminated using [`exit(Child,kill)`](`exit/2`).\n\n If the child process is another supervisor, the shutdown time must be set to\n `infinity` to give the subtree ample time to shut down.\n\n > #### Warning {: .warning }\n >\n > Setting the shutdown time to anything other than `infinity` for a child of\n > type `supervisor` can cause a race condition where the child in question\n > unlinks its own children, but fails to terminate them before it is killed.\n\n It is also allowed to set it to `infinity`, if the child process is a worker.\n\n > #### Warning {: .warning }\n >\n > Be careful when setting the shutdown time to `infinity` when the child\n > process is a worker. Because, in this situation, the termination of the\n > supervision tree depends on the child process, it must be implemented in a\n > safe way and its cleanup procedure must always return.\n\n Notice that all child processes implemented using the standard OTP behavior\n modules automatically adhere to the shutdown protocol.\n\n The `shutdown` key is optional. If it is not specified, it defaults to `5000`\n if the child is of type `worker` and it defaults to `infinity` if the child is\n of type `supervisor`.\n\n- `type` specifies if the child process is a supervisor or a worker.\n\n The `type` key is optional. If it is not specified, it defaults to `worker`.\n\n- `modules` is used by the release handler during code replacement to determine\n which processes are using a certain module. As a rule of thumb, if the child\n process is a `m:supervisor`, `m:gen_server` or, `m:gen_statem`, this is to be a list\n with one element `[Module]`, where `Module` is the callback module. If the\n child process is an event manager (`m:gen_event`) with a dynamic set of callback\n modules, value `dynamic` must be used. For more information about release\n handling, see [Release Handling](`e:system:release_handling.md`) in OTP Design\n Principles.\n\n The `modules` key is optional. If it is not specified, it defaults to `[M]`,\n where `M` comes from the child's start `{M,F,A}`.\n\n- Internally, the supervisor also keeps track of the pid `Child` of the child\n process, or `undefined` if no pid exists.","title":"Child specification - supervisor","ref":"supervisor.html#module-child-specification"},{"type":"behaviour","doc":"`m:gen_event`, `m:gen_statem`, `m:gen_server`, `m:sys`","title":"See Also - supervisor","ref":"supervisor.html#module-see-also"},{"type":"function","doc":"","title":"supervisor.check_childspecs/1","ref":"supervisor.html#check_childspecs/1"},{"type":"function","doc":"Takes a list of child specification as argument and returns `ok` if all of them\nare syntactically correct, otherwise `{error,Error}`.\n\nIf the `AutoShutdown` argument is not `undefined`, also\nchecks if the child specifications are allowed for the given\n[auto_shutdown](`m:supervisor#auto_shutdown`) option.","title":"supervisor.check_childspecs/2","ref":"supervisor.html#check_childspecs/2"},{"type":"function","doc":"Returns a [property list](`t:proplists:proplist/0`) containing the counts for each of\nthe following elements of the supervisor's child specifications and managed\nprocesses:\n\n- `specs` \\- The total count of children, dead or alive.\n- `active` \\- The count of all actively running child processes managed by this\n supervisor. For a `simple_one_for_one` supervisors, no check is done to ensure\n that each child process is still alive, although the result provided here is\n likely to be very accurate unless the supervisor is heavily overloaded.\n- `supervisors` \\- The count of all children marked as `child_type = supervisor`\n in the specification list, regardless if the child process is still alive.\n- `workers` \\- The count of all children marked as `child_type = worker` in the\n specification list, regardless if the child process is still alive.","title":"supervisor.count_children/1","ref":"supervisor.html#count_children/1"},{"type":"function","doc":"Tells supervisor `SupRef` to delete the child specification identified by `Id`.\nThe corresponding child process must not be running. Use `terminate_child/2` to\nterminate it.\n\nIf successful, the function returns `ok`. If the child specification identified\nby `Id` exists but the corresponding child process is running or is about to be\nrestarted, the function returns `{error,running}` or `{error,restarting}`,\nrespectively. If the child specification identified by `Id` does not exist, the\nfunction returns `{error,not_found}`.","title":"supervisor.delete_child/2","ref":"supervisor.html#delete_child/2"},{"type":"function","doc":"Returns the child specification map for the child identified by `Id` under\nsupervisor `SupRef`. The returned map contains all keys, both mandatory and\noptional.","title":"supervisor.get_childspec/2","ref":"supervisor.html#get_childspec/2"},{"type":"callback","doc":"Whenever a supervisor is started using [`start_link/2,3`](`start_link/2`), this\nfunction is called by the new process to find out about restart strategy,\nmaximum restart intensity, and child specifications.\n\n`Args` is the `Args` argument provided to the start function.\n\n`SupFlags` is the supervisor flags defining the restart strategy and maximum\nrestart intensity for the supervisor. `[ChildSpec]` is a list of valid child\nspecifications defining which child processes the supervisor must start and\nmonitor. See the discussion in section\n[`Supervision Principles`](`m:supervisor#supervision_princ`) earlier.\n\nNotice that when the restart strategy is `simple_one_for_one`, the list of child\nspecifications must be a list with one child specification only. (The child\nspecification identifier is ignored.) No child process is then started during\nthe initialization phase, but all children are assumed to be started dynamically\nusing `start_child/2`.\n\nThe function can also return `ignore`.\n\nNotice that this function can also be called as a part of a code upgrade\nprocedure. Therefore, the function is not to have any side effects. For more\ninformation about code upgrade of supervisors, see section\n[Changing a Supervisor](`e:system:appup_cookbook.md#sup`) in OTP Design\nPrinciples.","title":"supervisor.init/1","ref":"supervisor.html#c:init/1"},{"type":"function","doc":"Tells supervisor `SupRef` to restart a child process corresponding to the child\nspecification identified by `Id`. The child specification must exist, and the\ncorresponding child process must not be running.\n\nNotice that for temporary children, the child specification is automatically\ndeleted when the child terminates; thus, it is not possible to restart such\nchildren.\n\nIf the child specification identified by `Id` does not exist, the function\nreturns `{error,not_found}`. If the child specification exists but the\ncorresponding process is already running, the function returns\n`{error,running}`.\n\nIf the child process start function returns `{ok,Child}` or `{ok,Child,Info}`,\nthe pid is added to the supervisor and the function returns the same value.\n\nIf the child process start function returns `ignore`, the pid remains set to\n`undefined` and the function returns `{ok,undefined}`.\n\nIf the child process start function returns an error tuple or an erroneous\nvalue, or if it fails, the function returns `{error,Error}`, where `Error` is a\nterm containing information about the error.","title":"supervisor.restart_child/2","ref":"supervisor.html#restart_child/2"},{"type":"function","doc":"Dynamically adds a child specification to supervisor `SupRef`, which starts the\ncorresponding child process.\n\nFor `one_for_one`, `one_for_all` and `rest_for_one` supervisors, the second\nargument must be a valid child specification `ChildSpec`. The child process\nis started by using the start function as defined in the child specification.\n\nFor `simple_one_for_one` supervisors, the child specification defined in\n[`Module:init/1`](`c:init/1`) is used, and the second argument must instead\nbe an arbitrary list of terms `ExtraArgs`. The child process is then started\nby appending `ExtraArgs` to the existing start function arguments, that is, by\ncalling [`apply(M, F, A++ExtraArgs)`](`apply/3`), where `{M,F,A}` is the start\nfunction defined in the child specification.\n\n- If there already exists a child specification with the specified identifier,\n `ChildSpec` is discarded, and the function returns `{error,already_present}`\n or `{error,{already_started,Child}}`, depending on if the corresponding child\n process is running or not.\n- If the child process start function returns `{ok,Child}` or `{ok,Child,Info}`,\n the child specification and pid are added to the supervisor and the function\n returns the same value.\n- If the child process start function returns `ignore`, the child specification\n `ChildSpec` is added to the supervisor if it is an `one_for_one`, `one_for_all`\n or `rest_for_one` supervisor, and the pid is set to `undefined`. For\n `simple_one_for_one` supervisors, no child is added to the supervisor. The\n function returns `{ok,undefined}`.\n\nIf the child process start function returns an error tuple or an erroneous\nvalue, or if it fails, the child specification is discarded, and the function\nreturns `{error,Error}`, where `Error` is a term containing information about\nthe error and child specification.","title":"supervisor.start_child/2","ref":"supervisor.html#start_child/2"},{"type":"function","doc":"Creates a nameless supervisor process as part of a supervision tree.\n\nEquivalent to `start_link/3` except that the supervisor process is not\n[`registered`](`erlang:register/2`).","title":"supervisor.start_link/2","ref":"supervisor.html#start_link/2"},{"type":"function","doc":"Creates a supervisor process as part of a supervision tree.\n\nFor example, the function ensures that the supervisor is linked to the calling\nprocess (its supervisor).\n\nThe created supervisor process calls [`Module:init/1`](`c:init/1`) to find out\nabout restart strategy, maximum restart intensity, and child processes. To\nensure a synchronized startup procedure, `start_link/2,3` does not return until\n[`Module:init/1`](`c:init/1`) has returned and all child processes have been\nstarted.\n\n- If `SupName={local,Name}`, the supervisor is registered locally as `Name`\n using [`register/2`](`register/2`).\n- If `SupName={global,Name}`, the supervisor is registered globally as `Name`\n using `global:register_name/2`.\n- If `SupName={via,Module,Name}`, the supervisor is registered as `Name` using\n the registry represented by `Module`. The `Module` callback must export the\n functions `register_name/2`, `unregister_name/1`, and `send/2`, which must\n behave like the corresponding functions in `m:global`. Thus,\n `{via,global,Name}` is a valid reference.\n\n`Module` is the name of the callback module.\n\n`Args` is any term that is passed as the argument to\n[`Module:init/1`](`c:init/1`).\n\n- If the supervisor and its child processes are successfully created (that is,\n if all child process start functions return `{ok,Child}`, `{ok,Child,Info}`,\n or `ignore`), the function returns `{ok,Pid}`, where `Pid` is the pid of the\n supervisor.\n- If there already exists a process with the specified `SupName`, the function\n returns `{error,{already_started,Pid}}`, where `Pid` is the pid of that\n process.\n- If [`Module:init/1`](`c:init/1`) returns `ignore`, this function returns\n `ignore` as well, and the supervisor terminates with reason `normal`.\n- If [`Module:init/1`](`c:init/1`) fails or returns an incorrect value, this\n function returns `{error,Term}`, where `Term` is a term with information about\n the error, and the supervisor terminates with reason `Term`.\n- If any child process start function fails or returns an error tuple or an\n erroneous value, the supervisor first terminates all already started child\n processes with reason `shutdown` and then terminate itself and returns\n `{error, {shutdown, Reason}}`.","title":"supervisor.start_link/3","ref":"supervisor.html#start_link/3"},{"type":"function","doc":"Tells supervisor `SupRef` to terminate the specified child.\n\nIf the supervisor is not `simple_one_for_one`, `Id` must be the child\nspecification identifier. The process, if any, is terminated and, unless it is a\ntemporary child, the child specification is kept by the supervisor. The child\nprocess can later be restarted by the supervisor. The child process can also be\nrestarted explicitly by calling `restart_child/2`. Use `delete_child/2` to\nremove the child specification.\n\nIf the child is temporary, the child specification is deleted as soon as the\nprocess terminates. This means that [`delete_child/2`](`delete_child/2`) has no\nmeaning and [`restart_child/2`](`restart_child/2`) cannot be used for these\nchildren.\n\nIf the supervisor is `simple_one_for_one`, `Id` must be the `t:pid/0` of the\nchild process. If the specified process is alive, but is not a child of the\nspecified supervisor, the function returns `{error,not_found}`. If the child\nspecification identifier is specified instead of a `t:pid/0`, the function\nreturns `{error,simple_one_for_one}`.\n\nIf successful, the function returns `ok`. If there is no child specification\nwith the specified `Id`, the function returns `{error,not_found}`.","title":"supervisor.terminate_child/2","ref":"supervisor.html#terminate_child/2"},{"type":"function","doc":"Returns information about the child specification and child process identified\nby the given `Id`.\n\nSee `which_children/1` for an explanation of the information returned.\n\nIf no child with the given `Id` exists, returns `{error, not_found}`.","title":"supervisor.which_child/2","ref":"supervisor.html#which_child/2"},{"type":"function","doc":"Returns a newly created list with information about all child specifications and\nchild processes belonging to supervisor `SupRef`.\n\nNotice that calling this function when supervising many children under low\nmemory conditions can cause an out of memory exception.\n\nThe following information is given for each child specification/process:\n\n- `Id` \\- As defined in the child specification or `undefined` for a\n `simple_one_for_one` supervisor.\n- `Child` \\- The pid of the corresponding child process, the atom `restarting`\n if the process is about to be restarted, or `undefined` if there is no such\n process.\n- `Type` \\- As defined in the child specification.\n- `Modules` \\- As defined in the child specification.","title":"supervisor.which_children/1","ref":"supervisor.html#which_children/1"},{"type":"type","doc":"","title":"supervisor.auto_shutdown/0","ref":"supervisor.html#t:auto_shutdown/0"},{"type":"type","doc":"","title":"supervisor.child/0","ref":"supervisor.html#t:child/0"},{"type":"type","doc":"Not a `t:pid/0`.","title":"supervisor.child_id/0","ref":"supervisor.html#t:child_id/0"},{"type":"type","doc":"","title":"supervisor.child_rec/0","ref":"supervisor.html#t:child_rec/0"},{"type":"type","doc":"The tuple format is kept for backward compatibility only. A map is preferred;\nsee more details [above](`m:supervisor#child_spec`).","title":"supervisor.child_spec/0","ref":"supervisor.html#t:child_spec/0"},{"type":"type","doc":"","title":"supervisor.children/0","ref":"supervisor.html#t:children/0"},{"type":"type","doc":"Value `undefined` for `A` (the argument list) is only to be used internally in\n`m:supervisor`. If the restart type of the child is `temporary`, the process is\nnever to be restarted and therefore there is no need to store the real argument\nlist. Value `undefined` is then stored instead.","title":"supervisor.mfargs/0","ref":"supervisor.html#t:mfargs/0"},{"type":"type","doc":"","title":"supervisor.modules/0","ref":"supervisor.html#t:modules/0"},{"type":"type","doc":"","title":"supervisor.restart/0","ref":"supervisor.html#t:restart/0"},{"type":"type","doc":"","title":"supervisor.shutdown/0","ref":"supervisor.html#t:shutdown/0"},{"type":"type","doc":"","title":"supervisor.significant/0","ref":"supervisor.html#t:significant/0"},{"type":"type","doc":"","title":"supervisor.startchild_err/0","ref":"supervisor.html#t:startchild_err/0"},{"type":"type","doc":"","title":"supervisor.startchild_ret/0","ref":"supervisor.html#t:startchild_ret/0"},{"type":"type","doc":"","title":"supervisor.startlink_err/0","ref":"supervisor.html#t:startlink_err/0"},{"type":"type","doc":"","title":"supervisor.startlink_ret/0","ref":"supervisor.html#t:startlink_ret/0"},{"type":"type","doc":"","title":"supervisor.strategy/0","ref":"supervisor.html#t:strategy/0"},{"type":"type","doc":"The tuple format is kept for backward compatibility only. A map is preferred;\nsee more details [above](`m:supervisor#sup_flags`).","title":"supervisor.sup_flags/0","ref":"supervisor.html#t:sup_flags/0"},{"type":"type","doc":"Name specification to use when starting a `supervisor`. See function\n[`start_link/2,3`](`start_link/2`) and the type `t:sup_ref/0` below.\n\n- **`{local,LocalName}`** - Register the `supervisor` locally as `LocalName`\n using [`register/2`](`erlang:register/2`).\n\n- **`{global,GlobalName}`** - Register the `supervisor` process id globally as\n `GlobalName` using `global:register_name/2`.\n\n- **`{via,RegMod,ViaName}`** - Register the `supervisor` process with the\n registry represented by `RegMod`. The `RegMod` callback is to export the\n functions `register_name/2`, `unregister_name/1`, `whereis_name/1`, and\n `send/2`, which are to behave like the corresponding functions in `m:global`.\n Thus, `{via,global,GlobalName}` is a valid reference equivalent to\n `{global,GlobalName}`.","title":"supervisor.sup_name/0","ref":"supervisor.html#t:sup_name/0"},{"type":"type","doc":"Supervisor specification to use when addressing a `supervisor`. See\n[`count_children/1`](`count_children/1`), [`delete_child/2`](`delete_child/2`),\n[`get_childspec/2`](`get_childspec/2`), [`restart_child/2`](`restart_child/2`),\n[`start_child/2`](`start_child/2`), [`terminate_child/2`](`terminate_child/2`),\n[`which_children/1`](`which_children/1`) and the type `t:sup_name/0` above.\n\nIt can be:\n\n- **`t:pid/0`** - The `supervisor`'s process identifier.\n\n- **`LocalName`** - The `supervisor` is locally registered as `LocalName` with\n [`register/2`](`erlang:register/2`).\n\n- **`{Name,Node}`** - The `supervisor` is locally registered on another node.\n\n- **`{global,GlobalName}`** - The `supervisor` is globally registered in\n `m:global`.\n\n- **`{via,RegMod,ViaName}`** - The `supervisor` is registered in an alternative\n process registry. The registry callback module `RegMod` is to export functions\n `register_name/2`, `unregister_name/1`, `whereis_name/1`, and `send/2`, which\n are to behave like the corresponding functions in `m:global`. Thus,\n `{via,global,GlobalName}` is the same as `{global,GlobalName}`.","title":"supervisor.sup_ref/0","ref":"supervisor.html#t:sup_ref/0"},{"type":"type","doc":"","title":"supervisor.worker/0","ref":"supervisor.html#t:worker/0"},{"type":"behaviour","doc":"Generic supervisor bridge behavior.\n\nThis behavior module provides a supervisor bridge, a process that connects a\nsubsystem not designed according to the OTP design principles to a supervision\ntree. The supervisor bridge sits between a supervisor and the subsystem. It\nbehaves like a real supervisor to its own supervisor, but has a different\ninterface than a real supervisor to the subsystem. For more information, see\n[Supervisor Behaviour](`e:system:sup_princ.md`) in OTP Design Principles.\n\nA supervisor bridge assumes the functions for starting and stopping the\nsubsystem to be located in a callback module exporting a predefined set of\nfunctions.\n\nThe `m:sys` module can be used for debugging a supervisor bridge.\n\nUnless otherwise stated, all functions in this module fail if the specified\nsupervisor bridge does not exist or if bad arguments are specified.","title":"supervisor_bridge","ref":"supervisor_bridge.html"},{"type":"behaviour","doc":"`m:supervisor`, `m:sys`","title":"See Also - supervisor_bridge","ref":"supervisor_bridge.html#module-see-also"},{"type":"callback","doc":"Whenever a supervisor bridge is started using\n[`start_link/2,3`](`start_link/2`), this function is called by the new process\nto start the subsystem and initialize.\n\n`Args` is the `Args` argument provided to the start function.\n\nThe function is to return `{ok,Pid,State}`, where `Pid` is the pid of the main\nprocess in the subsystem and `State` is any term.\n\nIf later `Pid` terminates with a reason `Reason`, the supervisor bridge\nterminates with reason `Reason` as well. If later the supervisor bridge is\nstopped by its supervisor with reason `Reason`, it calls\n[`Module:terminate(Reason,State)`](`c:terminate/2`) to terminate.\n\nIf the initialization fails, the function is to return `{error,Error}`, where\n`Error` is any term, or `ignore`.","title":"supervisor_bridge.init/1","ref":"supervisor_bridge.html#c:init/1"},{"type":"function","doc":"Creates a nameless supervisor bridge process as part of a supervision tree.\n\nEquivalent to `start_link/3` except that the supervisor process is not\n[`registered`](`erlang:register/2`).","title":"supervisor_bridge.start_link/2","ref":"supervisor_bridge.html#start_link/2"},{"type":"function","doc":"Creates a supervisor bridge process, linked to the calling process, which calls\n[`Module:init/1`](`c:init/1`) to start the subsystem.\n\nTo ensure a synchronized startup procedure, this function does not return until\n[`Module:init/1`](`c:init/1`) has returned.\n\n- If `SupBridgeName={local,Name}`, the supervisor bridge is registered locally\n as `Name` using [`register/2`](`register/2`).\n- If `SupBridgeName={global,GlobalName}`, the supervisor bridge is registered\n globally as `GlobalName` using `global:register_name/2`.\n- If `SupBridgeName={via,Module,ViaName}`, the supervisor bridge is registered\n as `ViaName` using a registry represented by Module. The `Module` callback is\n to export functions `register_name/2`, `unregister_name/1`, and `send/2`,\n which are to behave like the corresponding functions in `m:global`. Thus,\n `{via,global,GlobalName}` is a valid reference.\n\n`Module` is the name of the callback module.\n\n`Args` is an arbitrary term that is passed as the argument to\n[`Module:init/1`](`c:init/1`).\n\n- If the supervisor bridge and the subsystem are successfully started, the\n function returns `{ok,Pid}`, where `Pid` is is the pid of the supervisor\n bridge.\n- If there already exists a process with the specified `SupBridgeName`, the\n function returns `{error,{already_started,Pid}}`, where `Pid` is the pid of\n that process.\n- If [`Module:init/1`](`c:init/1`) returns `ignore`, this function returns\n `ignore` as well and the supervisor bridge terminates with reason `normal`.\n- If [`Module:init/1`](`c:init/1`) fails or returns an error tuple or an\n incorrect value, this function returns `{error,Error}`, where `Error` is a\n term with information about the error, and the supervisor bridge terminates\n with reason `Error`.","title":"supervisor_bridge.start_link/3","ref":"supervisor_bridge.html#start_link/3"},{"type":"callback","doc":"This function is called by the supervisor bridge when it is about to terminate.\nIt is to be the opposite of [`Module:init/1`](`c:init/1`) and stop the subsystem\nand do any necessary cleaning up. The return value is ignored.\n\n`Reason` is `shutdown` if the supervisor bridge is terminated by its supervisor.\nIf the supervisor bridge terminates because a a linked process (apart from the\nmain process of the subsystem) has terminated with reason `Term`, then `Reason`\nbecomes `Term`.\n\n`State` is taken from the return value of [`Module:init/1`](`c:init/1`).","title":"supervisor_bridge.terminate/2","ref":"supervisor_bridge.html#c:terminate/2"},{"type":"behaviour","doc":"A functional interface to system messages.\n\nThis module contains functions for sending system messages used by programs, and\nmessages used for debugging purposes.\n\nFunctions used for implementation of processes are also expected to understand\nsystem messages, such as debug messages and code change. These functions must be\nused to implement the use of system messages for a process; either directly, or\nthrough standard behaviors, such as `m:gen_server`.\n\nThe default time-out is 5000 ms, unless otherwise specified. `timeout` defines\nthe time to wait for the process to respond to a request. If the process does\nnot respond, the function evaluates [`exit({timeout, {M, F, A}})`](`exit/1`).\n\n[](){: #dbg_opt }\n\nThe functions make references to a debug structure. The debug structure is a\nlist of `t:dbg_opt/0`, which is an internal data type used by function\n`handle_system_msg/6`. No debugging is performed if it is an empty list.","title":"sys","ref":"sys.html"},{"type":"behaviour","doc":"Processes that are not implemented as one of the standard behaviors must still\nunderstand system messages. The following three messages must be understood:\n\n- Plain system messages. These are received as `{system, From, Msg}`. The\n content and meaning of this message are not interpreted by the receiving\n process module. When a system message is received, function\n `handle_system_msg/6` is called to handle the request.\n- Shutdown messages. If the process traps exits, it must be able to handle a\n shutdown request from its parent, the supervisor. The message\n `{'EXIT', Parent, Reason}` from the parent is an order to terminate. The\n process must terminate when this message is received, normally with the same\n `Reason` as `Parent`.\n- If the modules used to implement the process change dynamically during\n runtime, the process must understand one more message. An example is the\n `m:gen_event` processes. The message is `{_Label, {From, Ref}, get_modules}`.\n The reply to this message is `From ! {Ref, Modules}`, where `Modules` is a\n list of the currently active modules in the process.\n\n This message is used by the release handler to find which processes that\n execute a certain module. The process can later be suspended and ordered to\n perform a code change for one of its modules.","title":"System Messages - sys","ref":"sys.html#module-system-messages"},{"type":"behaviour","doc":"When debugging a process with the functions of this module, the process\ngenerates _system_events_, which are then treated in the debug function. For\nexample, `trace` formats the system events to the terminal.\n\nFour predefined system events are used when a process receives or sends a\nmessage. The process can also define its own system events. It is always up to\nthe process itself to format these events.","title":"System Events - sys","ref":"sys.html#module-system-events"},{"type":"function","doc":"","title":"sys.change_code/4","ref":"sys.html#change_code/4"},{"type":"function","doc":"Tells the process to change code.\n\nThe process must be suspended to handle this message.\nArgument `Extra` is reserved for each process to use as its own.\nFunction [`Module:system_code_change/4`](`c:system_code_change/4`) is called.\n`OldVsn` is the old version of the `Module`.","title":"sys.change_code/5","ref":"sys.html#change_code/5"},{"type":"function","doc":"Can be used by a process that initiates a debug structure from a list of\noptions. The values of argument `Opt` are the same as for the corresponding\nfunctions.","title":"sys.debug_options/1","ref":"sys.html#debug_options/1"},{"type":"function","doc":"Gets the data associated with a debug option. `Default` is returned if `Item` is\nnot found. Can be used by the process to retrieve debug data for printing before\nit terminates.","title":"sys.get_debug/3","ref":"sys.html#get_debug/3"},{"type":"function","doc":"Returns the logged system events in the debug structure, that is the last\nargument to `handle_debug/4`.","title":"sys.get_log/1","ref":"sys.html#get_log/1"},{"type":"function","doc":"","title":"sys.get_state/1","ref":"sys.html#get_state/1"},{"type":"function","doc":"Gets the state of the process.\n\n> #### Note {: .info }\n>\n> These functions are intended only to help with debugging. They are provided\n> for convenience, allowing developers to avoid having to create their own state\n> extraction functions and also avoid having to interactively extract the state\n> from the return values of `get_status/1` or `get_status/2` while debugging.\n\nThe value of `State` varies for different types of processes, as follows:\n\n- For a `m:gen_server` process, the returned `State` is the state of the\n callback module.\n- For a `m:gen_statem` process, `State` is the tuple\n `{CurrentState,CurrentData}`.\n- For a `m:gen_event` process, `State` is a list of tuples, where each tuple\n corresponds to an event handler registered in the process and contains\n `{Module, Id, HandlerState}`, as follows:\n\n - **`Module`** - The module name of the event handler.\n\n - **`Id`** - The ID of the handler (which is `false` if it was registered\n without an ID).\n\n - **`HandlerState`** - The state of the handler.\n\nIf the callback module exports a function\n[`system_get_state/1`](`c:system_get_state/1`), it is called in the target\nprocess to get its state. Its argument is the same as the `Misc` value returned\nby [`get_status/1,2`](`get_status/1`), and function\n[`Module:system_get_state/1`](`c:system_get_state/1`) is expected to extract the\nstate of the callback module from it. Function\n[`system_get_state/1`](`c:system_get_state/1`) must return `{ok, State}`, where\n`State` is the state of the callback module.\n\nIf the callback module does not export a\n[`system_get_state/1`](`c:system_get_state/1`) function, `get_state/1,2` assumes\nthat the `Misc` value is the state of the callback module and returns it\ndirectly instead.\n\nIf the callback module's [`system_get_state/1`](`c:system_get_state/1`) function\ncrashes or throws an exception, the caller exits with error\n`{callback_failed, {Module, system_get_state}, {Class, Reason}}`, where `Module`\nis the name of the callback module and `Class` and `Reason` indicate details of\nthe exception.\n\nFunction [`system_get_state/1`](`c:system_get_state/1`) is primarily useful for\nuser-defined behaviors and modules that implement OTP\n[special processes](`m:sys#process-implementation-functions`). The `m:gen_server`,\n`m:gen_statem`, and `m:gen_event` OTP behavior modules export this function, so\ncallback modules for those behaviors need not to supply their own.\n\nFor more information about a process, including its state, see `get_status/1`\nand `get_status/2`.","title":"sys.get_state/2","ref":"sys.html#get_state/2"},{"type":"function","doc":"","title":"sys.get_status/1","ref":"sys.html#get_status/1"},{"type":"function","doc":"Gets the status of the process.\n\nThe value of `Misc` varies for different types of processes, for example:\n\n- A `m:gen_server` process returns the state of the callback module.\n- A `m:gen_statem` process returns information, such as its current state name\n and state data.\n- A `m:gen_event` process returns information about each of its registered\n handlers.\n- A bare `m:sys` process returns the value passed as `Misc` to\n `handle_system_message/6`.\n\nCallback modules for `m:gen_server`, `m:gen_statem`, and `m:gen_event` can also change\nthe value of `Misc` by exporting a function `format_status/1`, which contributes\nmodule-specific information. For details, see `c:gen_server:format_status/1`,\n`c:gen_statem:format_status/1`, and `c:gen_event:format_status/1`.","title":"sys.get_status/2","ref":"sys.html#get_status/2"},{"type":"function","doc":"This function is called by a process when it generates a system event.\n`FormFunc` is a formatting function, called as `FormFunc(Device, Event, Extra)`\nto print the events, which is necessary if tracing is activated. `Extra` is any\nextra information that the process needs in the format function, for example,\nthe process name.","title":"sys.handle_debug/4","ref":"sys.html#handle_debug/4"},{"type":"function","doc":"This function is used by a process module to take care of system messages. The\nprocess receives a `{system, From, Msg}` message and passes `Msg` and `From` to\nthis function.\n\nThis function _never_ returns. It calls either of the following functions:\n\n- [`Module:system_continue(Parent, NDebug, Misc)`](`c:system_continue/3`), where\n the process continues the execution.\n- [`Module:system_terminate(Reason, Parent, Debug, Misc)`](`c:system_terminate/4`),\n if the process is to terminate.\n\n`Module` must export the following:\n\n- [`system_continue/3`](`c:system_continue/3`)\n- [`system_terminate/4`](`c:system_terminate/4`)\n- [`system_code_change/4`](`c:system_code_change/4`)\n- [`system_get_state/1`](`c:system_get_state/1`)\n- [`system_replace_state/2`](`c:system_replace_state/2`)\n\nArgument `Misc` can be used to save internal data in a process, for example, its\nstate. It is sent to [`Module:system_continue/3`](`c:system_continue/3`) or\n[`Module:system_terminate/4`](`c:system_terminate/4`).","title":"sys.handle_system_msg/6","ref":"sys.html#handle_system_msg/6"},{"type":"function","doc":"","title":"sys.install/2","ref":"sys.html#install/2"},{"type":"function","doc":"Enables installation of alternative debug functions. An example of such a\nfunction is a trigger, a function that waits for some special event and performs\nsome action when the event is generated. For example, turning on low-level\ntracing.\n\n`Func` is called whenever a system event is generated. This function is to\nreturn `done`, or a new `Func` state. In the first case, the function is\nremoved. It is also removed if the function fails. If one debug function should\nbe installed more times, a unique `FuncId` must be specified for each\ninstallation.","title":"sys.install/3","ref":"sys.html#install/3"},{"type":"function","doc":"","title":"sys.log/2","ref":"sys.html#log/2"},{"type":"function","doc":"Turns the logging of system events on or off. If on, a maximum of `N` events are\nkept in the debug structure (default is 10).\n\nIf `Flag` is `get`, a list of all logged events is returned.\n\nIf `Flag` is `print`, the logged events are printed to\n[`standard_io`](`t:io:standard_io/0`).\n\nThe events are formatted with a function that is defined by the process that\ngenerated the event (with a call to [`handle_debug/4`)](`handle_debug/4`).","title":"sys.log/3","ref":"sys.html#log/3"},{"type":"function","doc":"","title":"sys.log_to_file/2","ref":"sys.html#log_to_file/2"},{"type":"function","doc":"Enables or disables the logging of all system events in text format to the file.\nThe events are formatted with a function that is defined by the process that\ngenerated the event (with a call to `handle_debug/4`). The file is opened with\nencoding UTF-8.","title":"sys.log_to_file/3","ref":"sys.html#log_to_file/3"},{"type":"function","doc":"","title":"sys.no_debug/1","ref":"sys.html#no_debug/1"},{"type":"function","doc":"Turns off all debugging for the process. This includes functions that are\ninstalled explicitly with function [`install/2,3`](`install/2`), for example,\ntriggers.","title":"sys.no_debug/2","ref":"sys.html#no_debug/2"},{"type":"function","doc":"Prints the logged system events in the debug structure, using `FormFunc` as\ndefined when the event was generated by a call to `handle_debug/4`.","title":"sys.print_log/1","ref":"sys.html#print_log/1"},{"type":"function","doc":"","title":"sys.remove/2","ref":"sys.html#remove/2"},{"type":"function","doc":"Removes an installed debug function from the process. `Func` or `FuncId` must be\nthe same as previously installed.","title":"sys.remove/3","ref":"sys.html#remove/3"},{"type":"function","doc":"","title":"sys.replace_state/2","ref":"sys.html#replace_state/2"},{"type":"function","doc":"Replaces the state of the process, and returns the new state.\n\n> #### Note {: .info }\n>\n> These functions are intended only to help with debugging, and are not to be\n> called from normal code. They are provided for convenience, allowing\n> developers to avoid having to create their own custom state replacement\n> functions.\n\nFunction `StateFun` provides a new state for the process. Argument `State` and\nthe `NewState` return value of `StateFun` vary for different types of processes\nas follows:\n\n- For a `m:gen_server` process, `State` is the state of the callback module and\n `NewState` is a new instance of that state.\n- For a `m:gen_statem` process, `State` is the tuple\n `{CurrentState,CurrentData}`, and `NewState` is a similar tuple, which can\n contain a new current state, new state data, or both.\n- For a `m:gen_event` process, `State` is the tuple `{Module, Id, HandlerState}`\n as follows:\n\n - **`Module`** - The module name of the event handler.\n\n - **`Id`** - The ID of the handler (which is `false` if it was registered\n without an ID).\n\n - **`HandlerState`** - The state of the handler.\n\n `NewState` is a similar tuple where `Module` and `Id` are to have the same\n values as in `State`, but the value of `HandlerState` can be different.\n Returning a `NewState`, whose `Module` or `Id` values differ from those of\n `State`, leaves the state of the event handler unchanged. For a `m:gen_event`\n process, `StateFun` is called once for each event handler registered in the\n `m:gen_event` process.\n\nIf a `StateFun` function decides not to effect any change in process state, then\nregardless of process type, it can return its `State` argument.\n\nIf a `StateFun` function crashes or throws an exception, the original state of\nthe process is unchanged for `m:gen_server`, and `m:gen_statem` processes. For\n`m:gen_event` processes, a crashing or failing `StateFun` function means that only\nthe state of the particular event handler it was working on when it failed or\ncrashed is unchanged; it can still succeed in changing the states of other event\nhandlers registered in the same `m:gen_event` process.\n\nIf the callback module exports a `c:system_replace_state/2` function, it is\ncalled in the target process to replace its state using `StateFun`. Its two\narguments are `StateFun` and `Misc`, where `Misc` is the same as the `Misc`\nvalue returned by [`get_status/1,2`](`get_status/1`). A\n[`system_replace_state/2`](`c:system_replace_state/2`) function is expected to\nreturn `{ok, NewState, NewMisc}`, where `NewState` is the new state of the\ncallback module, obtained by calling `StateFun`, and `NewMisc` is a possibly new\nvalue used to replace the original `Misc` (required as `Misc` often contains the\nstate of the callback module within it).\n\nIf the callback module does not export a\n[`system_replace_state/2`](`c:system_replace_state/2`) function,\n[`replace_state/2,3`](`replace_state/2`) assumes that `Misc` is the state of the\ncallback module, passes it to `StateFun` and uses the return value as both the\nnew state and as the new value of `Misc`.\n\nIf the callback module's function\n[`system_replace_state/2`](`c:system_replace_state/2`) crashes or throws an\nexception, the caller exits with error\n`{callback_failed, {Module, system_replace_state}, {Class, Reason}}`, where\n`Module` is the name of the callback module and `Class` and `Reason` indicate\ndetails of the exception. If the callback module does not provide a\n[`system_replace_state/2`](`c:system_replace_state/2`) function and `StateFun`\ncrashes or throws an exception, the caller exits with error\n`{callback_failed, StateFun, {Class, Reason}}`.\n\nFunction [`system_replace_state/2`](`c:system_replace_state/2`) is primarily\nuseful for user-defined behaviors and modules that implement OTP\n[special processes](`m:sys#process-implementation-functions`). The OTP behavior\nmodules `m:gen_server`, `m:gen_statem`, and `m:gen_event` export this function, so\ncallback modules for those behaviors need not to supply their own.","title":"sys.replace_state/3","ref":"sys.html#replace_state/3"},{"type":"function","doc":"","title":"sys.resume/1","ref":"sys.html#resume/1"},{"type":"function","doc":"Resumes a suspended process.","title":"sys.resume/2","ref":"sys.html#resume/2"},{"type":"function","doc":"","title":"sys.statistics/2","ref":"sys.html#statistics/2"},{"type":"function","doc":"Enables or disables the collection of statistics. If `Flag` is `get`, the\nstatistical collection is returned.","title":"sys.statistics/3","ref":"sys.html#statistics/3"},{"type":"function","doc":"","title":"sys.suspend/1","ref":"sys.html#suspend/1"},{"type":"function","doc":"Suspends the process. When the process is suspended, it only responds to other\nsystem messages, but not other messages.","title":"sys.suspend/2","ref":"sys.html#suspend/2"},{"type":"callback","doc":"Called from `handle_system_msg/6` when the process is to perform a code change.\nThe code change is used when the internal data structure has changed. This\nfunction converts argument `Misc` to the new data structure. `OldVsn` is\nattribute _vsn_ of the old version of the `Module`. If no such attribute is\ndefined, the atom `undefined` is sent.","title":"sys.system_code_change/4","ref":"sys.html#c:system_code_change/4"},{"type":"callback","doc":"Called from `handle_system_msg/6` when the process is to continue its execution\n(for example, after it has been suspended). This function never returns.","title":"sys.system_continue/3","ref":"sys.html#c:system_continue/3"},{"type":"callback","doc":"Called from `handle_system_msg/6` when the process is to return a term that\nreflects its current state. `State` is the value returned by `get_state/2`.","title":"sys.system_get_state/1","ref":"sys.html#c:system_get_state/1"},{"type":"callback","doc":"Called from `handle_system_msg/6` when the process is to replace its current\nstate. `NState` is the value returned by `replace_state/3`.","title":"sys.system_replace_state/2","ref":"sys.html#c:system_replace_state/2"},{"type":"callback","doc":"Called from `handle_system_msg/6` when the process is to terminate. For example,\nthis function is called when the process is suspended and its parent orders\nshutdown. It gives the process a chance to do a cleanup. This function never\nreturns.","title":"sys.system_terminate/4","ref":"sys.html#c:system_terminate/4"},{"type":"function","doc":"","title":"sys.terminate/2","ref":"sys.html#terminate/2"},{"type":"function","doc":"Orders the process to terminate with the specified `Reason`. The termination is\ndone asynchronously, so it is not guaranteed that the process is terminated when\nthe function returns.","title":"sys.terminate/3","ref":"sys.html#terminate/3"},{"type":"function","doc":"","title":"sys.trace/2","ref":"sys.html#trace/2"},{"type":"function","doc":"Prints all system events on [`standard_io`](`t:io:standard_io/0`). The events\nare formatted with a function that is defined by the process that generated the\nevent (with a call to `handle_debug/4`).","title":"sys.trace/3","ref":"sys.html#trace/3"},{"type":"type","doc":"","title":"sys.dbg_fun/0","ref":"sys.html#t:dbg_fun/0"},{"type":"opaque","doc":"See the introduction of this manual page.","title":"sys.dbg_opt/0","ref":"sys.html#t:dbg_opt/0"},{"type":"type","doc":"","title":"sys.debug_option/0","ref":"sys.html#t:debug_option/0"},{"type":"type","doc":"","title":"sys.format_fun/0","ref":"sys.html#t:format_fun/0"},{"type":"type","doc":"","title":"sys.name/0","ref":"sys.html#t:name/0"},{"type":"type","doc":"Debug events produced by `m:gen_server`, `m:gen_statem` and `m:gen_event`\n\n- **`{in,Msg}`** - Is produced by `m:gen_server` and `m:gen_event` when the message\n `Msg` arrives.\n\n- **`{in,Msg,State}`** - Is produced by `m:gen_statem` when the message `Msg`\n arrives in state `State`.\n\n For `m:gen_statem` the `Msg` term is an `{EventType,EventContent}` tuple.\n\n- **`{out,Msg,To}`** - Is produced by `m:gen_statem` when the reply `Msg` is sent\n back to `To` by returning a `{reply,To,Msg}` action from the callback module.\n\n `To` is of the same type as the first argument to `gen_statem:reply/2`.\n\n- **`{out,Msg,To,State}`** - Is produced by `m:gen_server` when the reply `Msg` is\n sent back to `To` by returning a `{reply,...}` tuple from the callback module.\n\n `To` is of the same type as the first argument to `gen_server:reply/2`.\n\n `State` is the new server state.\n\n- **`{noreply,State}`** - Is produced by `m:gen_server` when a `{noreply,...}`\n tuple is returned from the callback module.\n\n `State` is the new server state.\n\n- **`{continue,Continuation}`** - Is produced by `m:gen_server` when a\n `{continue,Continuation}` tuple is returned from the callback module.\n\n- **`{postpone,Event,State,NextState}`** - Is produced by `m:gen_statem` when the\n message `Event` is postponed in state `State`. `NextState` is the new state.\n\n `Event` is an `{EventType,EventContent}` tuple.\n\n- **`{consume,Event,State,NextState}`** - Is produced by `m:gen_statem` when the\n message `Event` is consumed in state `State`. `NextState` is the new state.\n\n `Event` is an `{EventType,EventContent}` tuple.\n\n- **`{start_timer,Action,State}`** - Is produced by `m:gen_statem` when the action\n `Action` starts a timer in state `State`.\n\n- **`{insert_timeout,Event,State}`** - Is produced by `m:gen_statem` when a\n timeout zero action inserts event `Event` in state `State`.\n\n `Event` is an `{EventType,EventContent}` tuple.\n\n- **`{enter,Module,State}`** - Is produced by `m:gen_statem` when module `Module`\n enters the first state `State`.\n\n- **`{module,Module,State}`** - Is produced by `m:gen_statem` when setting module\n `Module` in state `State`.\n\n- **`{terminate,Reason,State}`** - Is produced by `m:gen_statem` when it\n terminates with reason `Reason` in state `State`.","title":"sys.system_event/0","ref":"sys.html#t:system_event/0"},{"type":"module","doc":"Command line interface module.\n\nThis module enables users to enter the short form of some commonly used\ncommands.\n\n> #### Note {: .info }\n>\n> These functions are intended for interactive use in the Erlang shell only. The\n> module prefix can be omitted.","title":"c","ref":"c.html"},{"type":"module","doc":"`m:filename`, `m:compile`, `m:erlang`, `m:yecc`, `m:xref`","title":"See Also - c","ref":"c.html#module-see-also"},{"type":"function","doc":"Stack backtrace for a process. Equivalent to\n`erlang:process_display(Pid, backtrace)`.","title":"c.bt/1","ref":"c.html#bt/1"},{"type":"function","doc":"Works like [`c(Module, [])`](`c/2`).","title":"c.c/1","ref":"c.html#c/1"},{"type":"function","doc":"Compiles and then purges and loads the code for a module. `Module` can be either\na module name or a source file path, with or without `.erl` extension.\n\nIf `Module` is a string, it is assumed to be a source file path, and the\ncompiler will attempt to compile the source file with the options `Options`. If\ncompilation fails, the old object file (if any) is deleted.\n\nIf `Module` is an atom, a source file with that exact name or with `.erl`\nextension will be looked for. If found, the source file is compiled with the\noptions `Options`. If compilation fails, the old object file (if any) is\ndeleted.\n\nIf `Module` is an atom and is not the path of a source file, then the code path\nis searched to locate the object file for the module and extract its original\ncompiler options and source path. If the source file is not found in the\noriginal location, `filelib:find_source/1` is used to search for it relative to\nthe directory of the object file.\n\nThe source file is compiled with the the original options appended to the given\n`Options`, the output replacing the old object file if and only if compilation\nsucceeds.\n\nNotice that purging the code means that any processes lingering in old code for\nthe module are killed without warning. For more information, see the `m:code`\nmodule.","title":"c.c/2","ref":"c.html#c/2"},{"type":"function","doc":"Compiles and then purges and loads the code for module `Module`, which must be\nan atom.\n\nThe code path is searched to locate the object file for module `Module` and\nextract its original compiler options and source path. If the source file is not\nfound in the original location, `filelib:find_source/1` is used to search for it\nrelative to the directory of the object file.\n\nThe source file is compiled with the the original options appended to the given\n`Options`, the output replacing the old object file if and only if compilation\nsucceeds. The function `Filter` specifies which elements to remove from the\noriginal compiler options before the new options are added. The `Filter` fun\nshould return `true` for options to keep, and `false` for options to remove.\n\nNotice that purging the code means that any processes lingering in old code for\nthe module are killed without warning. For more information, see the `m:code`\nmodule.","title":"c.c/3","ref":"c.html#c/3"},{"type":"function","doc":"Changes working directory to `Dir`, which can be a relative name, and then\nprints the name of the new working directory.\n\n_Example:_\n\n```text\n2> cd(\"../erlang\").\n/home/ron/erlang\n```","title":"c.cd/1","ref":"c.html#cd/1"},{"type":"function","doc":"Search `PathList` and load `.erlang` resource file if found.","title":"c.erlangrc/1","ref":"c.html#erlangrc/1"},{"type":"function","doc":"Flushes any messages sent to the shell.","title":"c.flush/0","ref":"c.html#flush/0"},{"type":"function","doc":"Print the documentation for `Module`","title":"c.h/1","ref":"c.html#h/1"},{"type":"function","doc":"Print the documentation for all `Module:Function`s (regardless of arity).","title":"c.h/2","ref":"c.html#h/2"},{"type":"function","doc":"Print the documentation for `Module:Function/Arity`.","title":"c.h/3","ref":"c.html#h/3"},{"type":"function","doc":"Print the callback documentation for `Module`","title":"c.hcb/1","ref":"c.html#hcb/1"},{"type":"function","doc":"Print the callback documentation for all `Module:Callback`s (regardless of\narity).","title":"c.hcb/2","ref":"c.html#hcb/2"},{"type":"function","doc":"Print the callback documentation for `Module:Callback/Arity`.","title":"c.hcb/3","ref":"c.html#hcb/3"},{"type":"function","doc":"Displays help information: all valid shell internal commands, and commands in\nthis module.","title":"c.help/0","ref":"c.html#help/0"},{"type":"function","doc":"Print the type documentation for `Module`","title":"c.ht/1","ref":"c.html#ht/1"},{"type":"function","doc":"Print the type documentation for `Type` in `Module` regardless of arity.","title":"c.ht/2","ref":"c.html#ht/2"},{"type":"function","doc":"Print the type documentation for `Type/Arity` in `Module`.","title":"c.ht/3","ref":"c.html#ht/3"},{"type":"function","doc":"","title":"c.i/0","ref":"c.html#i/0"},{"type":"function","doc":"Displays information about a process, Equivalent to\n[`process_info(pid(X, Y, Z))`](`process_info/1`), but location transparent.","title":"c.i/3","ref":"c.html#i/3"},{"type":"function","doc":"Purges and loads, or reloads, a module by calling `code:purge(Module)` followed\nby `code:load_file(Module)`.\n\nNotice that purging the code means that any processes lingering in old code for\nthe module are killed without warning. For more information, see `code/3`.","title":"c.l/1","ref":"c.html#l/1"},{"type":"function","doc":"Compiles a list of files by calling\n`compile:file(File, [report_errors, report_warnings])` for each `File` in\n`Files`.\n\nFor information about `File`, see `t:file:filename/0`.","title":"c.lc/1","ref":"c.html#lc/1"},{"type":"function","doc":"Reloads all currently loaded modules that have changed on disk (see `mm/0`).\nReturns the list of results from calling [`l(M)`](`l/1`) for each such `M`.","title":"c.lm/0","ref":"c.html#lm/0"},{"type":"function","doc":"Lists files in the current directory.","title":"c.ls/0","ref":"c.html#ls/0"},{"type":"function","doc":"Lists files in directory `Dir` or, if `Dir` is a file, only lists it.","title":"c.ls/1","ref":"c.html#ls/1"},{"type":"function","doc":"Displays information about the loaded modules, including the files from which\nthey have been loaded.","title":"c.m/0","ref":"c.html#m/0"},{"type":"function","doc":"Displays information about `Module`.","title":"c.m/1","ref":"c.html#m/1"},{"type":"function","doc":"Memory allocation information. Equivalent to `erlang:memory/0`.","title":"c.memory/0","ref":"c.html#memory/0"},{"type":"function","doc":"Memory allocation information. Equivalent to `erlang:memory/1`.","title":"c.memory/1","ref":"c.html#memory/1"},{"type":"function","doc":"Lists all modified modules. Shorthand for `code:modified_modules/0`.","title":"c.mm/0","ref":"c.html#mm/0"},{"type":"function","doc":"","title":"c.nc/1","ref":"c.html#nc/1"},{"type":"function","doc":"Compiles and then loads the code for a file on all nodes. `Options` defaults to\n`[]`. Compilation is equivalent to:\n\n```erlang\ncompile:file(File, Options ++ [report_errors, report_warnings])\n```","title":"c.nc/2","ref":"c.html#nc/2"},{"type":"function","doc":"`i/0` displays system information, listing information about all processes.\n`ni/0` does the same, but for all nodes in the network.","title":"c.ni/0","ref":"c.html#ni/0"},{"type":"function","doc":"Loads `Module` on all nodes.","title":"c.nl/1","ref":"c.html#nl/1"},{"type":"function","doc":"","title":"c.nregs/0","ref":"c.html#nregs/0"},{"type":"function","doc":"Converts `X`, `Y`, `Z` to pid ` `. This function is only to be used when\ndebugging.","title":"c.pid/3","ref":"c.html#pid/3"},{"type":"function","doc":"Prints the name of the working directory.","title":"c.pwd/0","ref":"c.html#pwd/0"},{"type":"function","doc":"This function is shorthand for `init:stop()`, that is, it causes the node to\nstop in a controlled fashion.","title":"c.q/0","ref":"c.html#q/0"},{"type":"function","doc":"`regs/0` displays information about all registered processes. `nregs/0` does the\nsame, but for all nodes in the network.","title":"c.regs/0","ref":"c.html#regs/0"},{"type":"function","doc":"Prints the node uptime (as specified by `erlang:statistics(wall_clock)`) in\nhuman-readable form.","title":"c.uptime/0","ref":"c.html#uptime/0"},{"type":"function","doc":"Finds undefined functions, unused functions, and calls to deprecated functions\nin a module by calling `xref:m/1`.","title":"c.xm/1","ref":"c.html#xm/1"},{"type":"function","doc":"Generates an LALR-1 parser. Equivalent to:\n\n```text\nyecc:file(File)\n```\n\nFor information about `File = name()`, see `m:filename`. For information about\n`YeccRet`, see [`yecc:file/2`](`yecc:file/1`).","title":"c.y/1","ref":"c.html#y/1"},{"type":"function","doc":"Generates an LALR-1 parser. Equivalent to:\n\n```text\nyecc:file(File, Options)\n```\n\nFor information about `File = name()`, see `m:filename`. For information about\n`Options` and `YeccRet`, see [`yecc:file/2`](`yecc:file/1`).","title":"c.y/2","ref":"c.html#y/2"},{"type":"type","doc":"","title":"c.cmd_line_arg/0","ref":"c.html#t:cmd_line_arg/0"},{"type":"type","doc":"","title":"c.h_return/0","ref":"c.html#t:h_return/0"},{"type":"type","doc":"","title":"c.hcb_return/0","ref":"c.html#t:hcb_return/0"},{"type":"type","doc":"","title":"c.hf_return/0","ref":"c.html#t:hf_return/0"},{"type":"type","doc":"","title":"c.ht_return/0","ref":"c.html#t:ht_return/0"},{"type":"module","doc":"Line and input interpretter for the erlang shell.\n\nThis module reads input, handles any escape sequences that have been configured\nvia edlin_key and outputs action requests. The action requests are handled\neither by modules `group` or the `user_drv`.","title":"edlin","ref":"edlin.html"},{"type":"module","doc":"You can setup a custom key configuration that overrides the default key\nconfiguration. This is done by setting the stdlib application parameter\n[`shell_keymap`](stdlib_app.md#shell_keymap) before Erlang is started. If you\nwant to have the same keymap in all Erlang shells you can do so by putting a\n[config](`e:kernel:config.md`) file in your user's home directory and then set\n[ERL_FLAGS](`e:erts:erl_cmd.md#ERL_FLAGS`) to load it at startup. For example:\n\n```text\n$ cat $HOME/.erlang_keymap.config\n[{stdlib,\n [{shell_keymap,\n #{ normal => #{ \"\\^[A\" => clear } }\n }]\n}].\n$ ERL_FLAGS=\"-config $HOME/.erlang_keymap\" erl\n```\n\nThe current keymap configuration can be fetched through\n[edlin:keymap()](`keymap/0`). If a custom keymap or keymap file is specified,\nthen it will be merged with the default keymap.\n\nThe keymap is a map of maps where the keys in the parent map corresponds to\ndifferent editing modes in the shell. The valid modes currently supported are\n`normal` and `search`.\n\nThe keys in the child maps are the escape sequences that are sent from the\nterminal when a key is pressed and each value is a valid action as seen below.\n\nThe default atom is used to specify that an action should happen when a key is\npressed that does not have any mapping. Typically used to exit a mode.\n\nSee [tty - A Command-Line Interface](`e:erts:tty.md`) for more information about\nthe default keymap.","title":"Key configuration - edlin","ref":"edlin.html#module-key-configuration"},{"type":"module","doc":"The commands below are the built-in action requests for switching input modes on\nthe normal shell or navigating, or manipulating the line feed. The line feed\nsupports multiple lines.\n\n- **`auto_blink`** - Automatically close the closest matching opening\n parenthesis.\n\n- **`backward_char`** - Move backward one character.\n\n- **`backward_delete_char`** - Delete the character behind the cursor.\n\n- **`backward_delete_word`** - Delete the word behind the cursor.\n\n- **`backward_kill_line`** - Delete all characters from the cursor to the\n beginning of the line and save them in the kill buffer.\n\n- **`backward_kill_word`** - Delete the word behind the cursor and save it in\n the kill buffer.\n\n- **`backward_line`** - Move backward one line.\n\n- **`backward_word`** - Move backward one word.\n\n- **`beginning_of_expression`** - Move to the beginning of the expression.\n\n- **`beginning_of_line`** - Move to the beginning of the line.\n\n- **`clear`** - Clear the screen.\n\n- **`clear_line`** - Clear the current expression.\n\n- **`end_of_expression`** - Move to the end of the expression.\n\n- **`end_of_line`** - Move to the end of the line.\n\n- **`forward_char`** - Move forward one character.\n\n- **`forward_delete_char`** - Delete the character under the cursor.\n\n- **`forward_line`** - Move forward one line.\n\n- **`forward_word`** - Move forward one word.\n\n- **`help`** - Display help for the module or function closest on the left of\n the cursor.\n\n- **`help_full`** - Display the whole help text for the module or function closest on the left of\n the cursor.\n\n- **`history_down`** - Move to the next item in the history.\n\n- **`history_up`** - Move to the previous item in the history.\n\n- **`kill_line`** - Delete all characters from the cursor to the end of the line\n and save them in the kill buffer.\n\n- **`kill_word`** - Delete the word under the cursor and save it in the kill\n buffer.\n\n- **`move_expand_down`** - Move down one line in the expand area e.g. help or\n tab completion pager.\n\n- **`move_expand_up`** - Move up one line in the expand area e.g. help or tab\n completion pager.\n\n- **`new_line_finish`** - Add a newline at the end of the line and try to\n evaluate the current expression.\n\n- **`newline`** - Add a newline at the cursor position.\n\n- **`open_editor`** - Open the current line in an editor e.g. EDITOR=\"code -w\"\n opens a buffer in vs code. Note that you need to pass a flag to the editor so\n that it signals the shell when you close the buffer.\n\n- **`redraw_line`** - Redraw the current line.\n\n- **`scroll_expand_down`** - Scroll down five lines in the expand area e.g. help\n or tab completion pager.\n\n- **`scroll_expand_up`** - Scroll up five lines in the expand area e.g. help or\n tab completion pager.\n\n- **`search_cancel`** - Cancel the current search.\n\n- **`search_found`** - Accept the current search result and submit it.\n\n- **`search_quit`** - Accept the current search result, but edit it before\n submitting.\n\n- **`search`** - Enter search mode, search the history.\n\n- **`skip_down`** - Skip to the next line in the history that matches the\n current search expression.\n\n- **`skip_up`** - Skip to the previous line in the history that matches the\n current search expression.\n\n- **`tab_expand_full`** - Output all possible tab completions.\n\n- **`tab_expand_quit`** - Go back to normal mode.\n\n- **`tab_expand`** - Autocomplete the current word, or show 5 lines of possible\n completions.\n\n- **`transpose_char`** - Swap the character behind the cursor with the one in\n front of it.\n\n- **`transpose_word`** - Swap the word behind the cursor with the one in front\n of it.\n\n- **`yank`** - Insert the contents of the kill buffer at the cursor position.","title":"Actions - edlin","ref":"edlin.html#module-actions"},{"type":"function","doc":"Get the current keymap used in the shell. Each key in the parent map represents\na _shell mode_ e.g. `normal` or `search`. Each map associated with the _shell\nmodes_ contains _key sequences_ represented as strings, paired with an _action_,\nwhich is one of the valid actions mentioned above.","title":"edlin.keymap/0","ref":"edlin.html#keymap/0"},{"type":"type","doc":"A map of maps for each shell mode containing key, action pairs.","title":"edlin.keymap/0","ref":"edlin.html#t:keymap/0"},{"type":"module","doc":"Shell expansion and formatting of expansion suggestions.\n\nThis module provides an expand_fun for the erlang shell\n[`expand/1,2`](`expand/1`). It is possible to override this expand_fun\n[`io:setopts/1,2`](`io:setopts/1`).","title":"edlin_expand","ref":"edlin_expand.html"},{"type":"function","doc":"","title":"edlin_expand.expand/1","ref":"edlin_expand.html#expand/1"},{"type":"function","doc":"The standard expansion function is able to expand strings to valid erlang terms.\nThis includes module names:\n\n```text\n1> erla\nmodules\nerlang:\n```\n\nfunction names:\n\n```text\n1> is_ato\nfunctions\nis_atom(\n2> erlang:is_ato\nfunctions\nis_atom(\n```\n\nfunction types:\n\n```text\n1> erlang:is_atom(\ntypespecs\nerlang:is_atom(Term)\nany()\n```\n\nand automatically add , or closing parenthesis when no other valid expansion is\npossible. The expand function also completes: shell bindings, record names,\nrecord fields and map keys.\n\nAs seen below, function headers are grouped together if they've got the same\nexpansion suggestion, in this case all had the same suggestions, that is '\\}'.\nThere is also limited support for filtering out function typespecs that that\ndoes not match the types on the terms on the prompt. Only 4 suggestions are\nshown below but there exists plenty more typespecs for `erlang:system_info`.\n\n```text\n1> erlang:system_info({allocator, my_allocator\ntypespecs\nerlang:system_info(wordsize | {wordsize, ...} | {wordsize, ...})\nerlang:system_info({allocator, ...})\nerlang:system_info({allocator_sizes, ...})\nerlang:system_info({cpu_topology, ...})\n}\n```\n\nThe return type of `expand` function specifies either a list of `Element` tuples\nor a list of `Section` maps. The section concept was introduced to enable more\nformatting options for the expansion results. For example, the shell expansion\nhas support to highlight text and hide suggestions. There are also a\n`{highlight, Text}` that highlights all occurances of `Text` in the title, and a\n`highlight_all` for simplicity which highlights the whole title, as can be seen\nabove for `functions` and `typespecs`.\n\nBy setting the `{hide, result}` or `{hide, title}` options you may hide\nsuggestions. Sometimes the title isn't useful and just produces text noise, in\nthe example above the `t:any/0` result is part of a section with title `Types`.\nHiding results is currently not in use, but the idea is that a section can be\nselected in the expand area and all the other section entries should be\ncollapsed.\n\nIts possible to set a custom separator between the title and the results. This\ncan be done with `{separator, Separator}`. By default its set to be `\\n`, some\nresults display a `type_name() :: `followed by all types that define\n`type_name()`.\n\nThe `{ending, Text}` ElementOption just appends Text to the `Element`.","title":"edlin_expand.expand/2","ref":"edlin_expand.html#expand/2"},{"type":"module","doc":"The Erlang shell.\n\nThe shell is a user interface program for entering expression sequences. The\nexpressions are evaluated and a value is returned. The shell provides an Emacs\nlike set of shortcuts for editing the text of the current line. See\n[tty - A Command-Line Interface](`e:erts:tty.md`) in the ERTS User's Guide for a\nlist of all available shortcuts. You may also change the shortcuts to suit your\npreferences more, see [edlin - line editor in the shell](`m:edlin`).\n\nA history mechanism saves previous commands and their values, which can then be\nincorporated in later commands. How many commands and results to save can be\ndetermined by the user, either interactively, by calling `history/1` and\n`results/1`, or by setting the application configuration parameters\n[`shell_history_length`](stdlib_app.md#shell_history_length) and\n[`shell_saved_results`](stdlib_app.md#shell_saved_results) for the STDLIB\napplication. The shell history can be saved to disk by setting the application\nconfiguration parameter\n[`shell_history`](`e:kernel:kernel_app.md#shell_history`) for the Kernel\napplication.\n\nThe shell uses a helper process for evaluating commands to protect the history\nmechanism from exceptions. By default the evaluator process is killed when an\nexception occurs, but by calling `catch_exception/1` or by setting the\napplication configuration parameter `shell_catch_exception` for the STDLIB\napplication this behavior can be changed. See also the example below.\n\nVariable bindings, and local process dictionary changes that are generated in\nuser expressions are preserved, and the variables can be used in later commands\nto access their values. The bindings can also be forgotten so the variables can\nbe reused.\n\nThe special shell commands all have the syntax of (local) function calls. They\nare evaluated as normal function calls and many commands can be used in one\nexpression sequence.\n\nIf a command (local function call) is not recognized by the shell, an attempt is\nfirst made to find the function in module `user_default`, where customized local\ncommands can be placed. If found, the function is evaluated, otherwise an\nattempt is made to evaluate the function in module `shell_default`. Module\n`user_default` must be explicitly loaded.\n\nThe shell also permits the user to start multiple concurrent jobs. A job can be\nregarded as a set of processes that can communicate with the shell.\n\nThere is some support for reading and printing records in the shell. During\ncompilation record expressions are translated to tuple expressions. In runtime\nit is not known whether a tuple represents a record, and the record definitions\nused by the compiler are unavailable at runtime. So, to read the record syntax\nand print tuples as records when possible, record definitions must be maintained\nby the shell itself.\n\nThe shell commands for reading, defining, forgetting, listing, and printing\nrecords are described below. Notice that each job has its own set of record\ndefinitions. To facilitate matters, record definitions in modules\n`shell_default` and `user_default` (if loaded) are read each time a new job is\nstarted. For example, adding the following line to `user_default` makes the\ndefinition of `file_info` readily available in the shell:\n\n```erlang\n-include_lib(\"kernel/include/file.hrl\").\n```\n\nThe shell runs in two modes:\n\n- `Normal (possibly restricted)` mode, in which commands can be edited and\n expressions evaluated\n- Job Control Mode, `JCL`, in which jobs can be started, killed, detached, and\n connected\n\nOnly the currently connected job can 'talk' to the shell.","title":"shell","ref":"shell.html"},{"type":"module","doc":"The commands below are the built-in shell commands that are always available. In\nmost system the commands listed in the `m:c` module are also available in the\nshell.\n\n- **`b()`** - Prints the current variable bindings.\n\n- **`f()`** - Removes all variable bindings.\n\n- **`f(X)`** - Removes the binding of variable `X`.\n\n > #### Note {: .info }\n >\n > If a huge value is stored in a variable binding, you have to both call\n > `f(X)` and call [`history(0)`](`history/1`) or [`results(0)`](`results/1`)\n > to free up that memory.\n\n- **`h()`** - Prints the history list.\n\n- **[`history(N)`](`history/1`)** - Sets the number of previous commands to keep\n in the history list to `N`. The previous number is returned. Defaults to 20.\n\n- **[`results(N)`](`results/1`)** - Sets the number of results from previous\n commands to keep in the history list to `N`. The previous number is returned.\n Defaults to 20.\n\n- **`e(N)`** - Repeats command `N`, if `N` is positive. If it is negative, the\n `N`th previous command is repeated (that is, `e(-1)` repeats the previous\n command).\n\n- **`v(N)`** - Uses the return value of command `N` in the current command, if\n `N` is positive. If it is negative, the return value of the `N`th previous\n command is used (that is, `v(-1)` uses the value of the previous command).\n\n- **`help()`** - Evaluates `shell_default:help()`.\n\n- **`h(Module, Function)`** - Print the documentation for `Module:Function` in\n the shell if available.\n\n- **`ht(Module, Type)`** - Print the documentation for `Module:Type` in the\n shell if available.\n\n- **`hcb(Module, Callback)`** - Print the documentation for `Module:Callback` in\n the shell if available.\n\n- **`c(Mod)`** - Evaluates `shell_default:c(Mod)`. This compiles and loads the\n module `Mod` and purges old versions of the code, if necessary. `Mod` can be\n either a module name or a a source file path, with or without `.erl`\n extension.\n\n- **[`catch_exception(Bool)`](`catch_exception/1`)** - Sets the exception\n handling of the evaluator process. The previous exception handling is\n returned. The default (`false`) is to kill the evaluator process when an\n exception occurs, which causes the shell to create a new evaluator process.\n When the exception handling is set to `true`, the evaluator process lives on.\n This means, for example, that ports and ETS tables as well as processes linked\n to the evaluator process survive the exception.\n\n- **`rd(RecordName, RecordDefinition)`** - Defines a record in the shell.\n `RecordName` is an atom and `RecordDefinition` lists the field names and the\n default values. Usually record definitions are made known to the shell by use\n of the `rr/1,2,3` commands described below, but sometimes it is handy to\n define records on the fly.\n\n- **`rf()`** - Removes all record definitions, then reads record definitions\n from the modules `shell_default` and `user_default` (if loaded). Returns the\n names of the records defined.\n\n- **`rf(RecordNames)`** - Removes selected record definitions. `RecordNames` is\n a record name or a list of record names. To remove all record definitions, use\n `'_'`.\n\n- **`rl()`** - Prints all record definitions.\n\n- **`rl(RecordNames)`** - Prints selected record definitions. `RecordNames` is a\n record name or a list of record names.\n\n- **`rp(Term)`** - Prints a term using the record definitions known to the\n shell. All of `Term` is printed; the depth is not limited as is the case when\n a return value is printed.\n\n- **`rr(Module)`** - Reads record definitions from a module's BEAM file. If\n there are no record definitions in the BEAM file, the source file is located\n and read instead. Returns the names of the record definitions read. `Module`\n is an atom.\n\n- **`rr(Wildcard)`** - Reads record definitions from files. Existing definitions\n of any of the record names read are replaced. `Wildcard` is a wildcard string\n as defined in `m:filelib`, but not an atom.\n\n- **`rr(WildcardOrModule, RecordNames)`** - Reads record definitions from files\n but discards record names not mentioned in `RecordNames` (a record name or a\n list of record names).\n\n- **`rr(WildcardOrModule, RecordNames, Options)`** - Reads record definitions\n from files. The compiler options `{i, Dir}`, `{d, Macro}`, and\n `{d, Macro, Value}` are recognized and used for setting up the include path\n and macro definitions. To read all record definitions, use `'_'` as value of\n `RecordNames`.\n\n- **`lf()`** - Outputs locally defined function with function specs if they\n exist.\n\n- **`lt()`** - Outputs locally defined types.\n\n- **`lr()`** - Outputs locally defined records.\n\n- **`ff()`** - Forget locally defined functions (including function specs if\n they exist).\n\n- **`ff({FunName,Arity})`** - Forget a locally defined function (including\n function spec if it exist). Where `FunName` is the name of the function as an\n atom and `Arity` is an integer.\n\n- **`tf()`** - Forget locally defined types.\n\n- **`tf(Type)`** - Forget locally defined type where `Type` is the name of the\n type represented as an atom.\n\n- **`fl()`** - Forget locally defined functions, types and records.\n\n- **`save_module(FilePath)`** - Saves all locally defined functions, types and\n records to a module file, where `FilePath` should include both the path to the\n file and the name of the module with `.erl` suffix.\n\n Example: `src/my_module.erl`","title":"Shell Commands - shell","ref":"shell.html#module-shell-commands"},{"type":"module","doc":"The following example is a long dialog with the shell. Commands starting with\n`>` are inputs to the shell. All other lines are output from the shell.\n\n```erlang\nstrider 1> erl\nErlang (BEAM) emulator version 5.3 [hipe] [threads:0]\n\nEshell V5.3 (abort with ^G)\n1> Str = \"abcd\".\n\"abcd\"\n```\n\nCommand 1 sets variable `Str` to string `\"abcd\"`.\n\n```erlang\n2> L = length(Str).\n4\n```\n\nCommand 2 sets `L` to the length of string `Str`.\n\n```erlang\n3> Descriptor = {L, list_to_atom(Str)}.\n{4,abcd}\n```\n\nCommand 3 builds the tuple `Descriptor`, evaluating the BIF\n[`list_to_atom/1` ](`erlang:list_to_atom/1`).\n\n```erlang\n4> L.\n4\n```\n\nCommand 4 prints the value of variable `L`.\n\n```erlang\n5> b().\nDescriptor = {4,abcd}\nL = 4\nStr = \"abcd\"\nok\n```\n\nCommand 5 evaluates the internal shell command `b()`, which is an abbreviation\nof \"bindings\". This prints the current shell variables and their bindings. `ok`\nat the end is the return value of function `b()`.\n\n```erlang\n6> f(L).\nok\n```\n\nCommand 6 evaluates the internal shell command `f(L)` (abbreviation of\n\"forget\"). The value of variable `L` is removed.\n\n```erlang\n7> b().\nDescriptor = {4,abcd}\nStr = \"abcd\"\nok\n```\n\nCommand 7 prints the new bindings.\n\n```erlang\n8> f(L).\nok\n```\n\nCommand 8 has no effect, as `L` has no value.\n\n```erlang\n9> {L, _} = Descriptor.\n{4,abcd}\n```\n\nCommand 9 performs a pattern matching operation on `Descriptor`, binding a new\nvalue to `L`.\n\n```erlang\n10> L.\n4\n```\n\nCommand 10 prints the current value of `L`.\n\n```erlang\n11> {P, Q, R} = Descriptor.\n** exception error: no match of right hand side value {4,abcd}\n```\n\nCommand 11 tries to match `{P, Q, R}` against `Descriptor`, which is `{4, abc}`.\nThe match fails and none of the new variables become bound. The printout\nstarting with \"`** exception error:`\" is not the value of the expression (the\nexpression had no value because its evaluation failed), but a warning printed by\nthe system to inform the user that an error has occurred. The values of the\nother variables (`L`, `Str`, and so on) are unchanged.\n\n```erlang\n12> P.\n* 1:1: variable 'P' is unbound\n13> Descriptor.\n{4,abcd}\n```\n\nCommands 12 and 13 show that `P` is unbound because the previous command failed,\nand that `Descriptor` has not changed.\n\n```erlang\n14>{P, Q} = Descriptor.\n{4,abcd}\n15> P.\n4\n```\n\nCommands 14 and 15 show a correct match where `P` and `Q` are bound.\n\n```erlang\n16> f().\nok\n```\n\nCommand 16 clears all bindings.\n\nThe next few commands assume that `test1:demo(X)` is defined as follows:\n\n```erlang\ndemo(X) ->\n    put(aa, worked),\n    X = 1,\n    X + 10.\n```\n\n```erlang\n17> put(aa, hello).\nundefined\n18> get(aa).\nhello\n```\n\nCommands 17 and 18 set and inspect the value of item `aa` in the process\ndictionary.\n\n```erlang\n19> Y = test1:demo(1).\n11\n```\n\nCommand 19 evaluates `test1:demo(1)`. The evaluation succeeds and the changes\nmade in the process dictionary become visible to the shell. The new value of\ndictionary item `aa` can be seen in command 20.\n\n```erlang\n20> get().\n[{aa,worked}]\n21> put(aa, hello).\nworked\n22> Z = test1:demo(2).\n** exception error: no match of right hand side value 1\n in function test1:demo/1\n```\n\nCommands 21 and 22 change the value of dictionary item `aa` to `hello` and call\n`test1:demo(2)`. Evaluation fails and the changes made to the dictionary in\n`test1:demo(2)`, before the error occurred, are discarded.\n\n```erlang\n23> Z.\n* 1:1: variable 'Z' is unbound\n24> get(aa).\nhello\n```\n\nCommands 23 and 24 show that `Z` was not bound and that dictionary item `aa` has\nretained its original value.\n\n```erlang\n25> erase(), put(aa, hello).\nundefined\n26> spawn(test1, demo, [1]).\n<0.57.0>\n27> get(aa).\nhello\n```\n\nCommands 25, 26, and 27 show the effect of evaluating `test1:demo(1)` in the\nbackground. In this case, the expression is evaluated in a newly spawned\nprocess. Any changes made in the process dictionary are local to the newly\nspawned process and therefore not visible to the shell.\n\n```erlang\n28> io:format(\"hello hello\\n\").\nhello hello\nok\n29> e(28).\nhello hello\nok\n30> v(28).\nok\n```\n\nCommands 28, 29 and 30 use the history facilities of the shell. Command 29\nre-evaluates command 28. Command 30 uses the value (result) of command 28. In\nthe cases of a pure function (a function with no side effects), the result is\nthe same. For a function with side effects, the result can be different.\n\nThe next few commands show some record manipulation. It is assumed that `ex.erl`\ndefines a record as follows:\n\n`-record(rec, {a, b = val()}).`\n\n`val() ->` \n    `3.`\n\n```erlang\n31> c(ex).\n{ok,ex}\n32> rr(ex).\n[rec]\n```\n\nCommands 31 and 32 compile file `ex.erl` and read the record definitions in\n`ex.beam`. If the compiler did not output any record definitions on the BEAM\nfile, `rr(ex)` tries to read record definitions from the source file instead.\n\n```erlang\n33> rl(rec).\n-record(rec,{a,b = val()}).\nok\n```\n\nCommand 33 prints the definition of the record named `rec`.\n\n```erlang\n34> #rec{}.\n** exception error: undefined shell command val/0\n```\n\nCommand 34 tries to create a `rec` record, but fails as function `val/0` is\nundefined.\n\n```erlang\n35> #rec{b = 3}.\n#rec{a = undefined,b = 3}\n```\n\nCommand 35 shows the workaround: explicitly assign values to record fields that\ncannot otherwise be initialized.\n\n```erlang\n36> rp(v(-1)).\n#rec{a = undefined,b = 3}\nok\n```\n\nCommand 36 prints the newly created record using record definitions maintained\nby the shell.\n\n```erlang\n37> rd(rec, {f = orddict:new()}).\nrec\n```\n\nCommand 37 defines a record directly in the shell. The definition replaces the\none read from file `ex.beam`.\n\n```erlang\n38> #rec{}.\n#rec{f = []}\nok\n```\n\nCommand 38 creates a record using the new definition, and prints the result.\n\n```erlang\n39> rd(rec, {c}), A.\n* 1:15: variable 'A' is unbound\n40> #rec{}.\n#rec{c = undefined}\nok\n```\n\nCommand 39 and 40 show that record definitions are updated as side effects. The\nevaluation of the command fails, but the definition of `rec` has been carried\nout.\n\nFor the next command, it is assumed that `test1:loop(N)` is defined as follows:\n\n`loop(N) ->` \n    `io:format(\"Hello Number: ~w~n\", [N]),` \n    `loop(N+1).`\n\n```text\n41> test1:loop(0).\nHello Number: 0\nHello Number: 1\nHello Number: 2\nHello Number: 3\n\nUser switch command\n --> i\n --> c\n.\n.\n.\nHello Number: 3374\nHello Number: 3375\nHello Number: 3376\nHello Number: 3377\nHello Number: 3378\n** exception exit: killed\n```\n\nCommand 41 evaluates `test1:loop(0)`, which puts the system into an infinite\nloop. At this point the user types `^G` (Control G), which suspends output from\nthe current process, which is stuck in a loop, and activates `JCL` mode. In\n`JCL` mode the user can start and stop jobs.\n\nIn this particular case, command `i` (\"interrupt\") terminates the looping\nprogram, and command `c` connects to the shell again. As the process was running\nin the background before we killed it, more printouts occur before message\n\"`** exception exit: killed`\" is shown.\n\n```erlang\n42> E = ets:new(t, []).\n#Ref<0.1662103692.2407923716.214192>\n```\n\nCommand 42 creates an ETS table.\n\n```erlang\n43> ets:insert({d,1,2}).\n** exception error: undefined function ets:insert/1\n```\n\nCommand 43 tries to insert a tuple into the ETS table, but the first argument\n(the table) is missing. The exception kills the evaluator process.\n\n```erlang\n44> ets:insert(E, {d,1,2}).\n** exception error: argument is of wrong type\n in function ets:insert/2\n called as ets:insert(16,{d,1,2})\n```\n\nCommand 44 corrects the mistake, but the ETS table has been destroyed as it was\nowned by the killed evaluator process.\n\n```erlang\n45> f(E).\nok\n46> catch_exception(true).\nfalse\n```\n\nCommand 46 sets the exception handling of the evaluator process to `true`. The\nexception handling can also be set when starting Erlang by\n`erl -stdlib shell_catch_exception true`.\n\n```erlang\n47> E = ets:new(t, []).\n#Ref<0.1662103692.2407923716.214197>\n48> ets:insert({d,1,2}).\n* exception error: undefined function ets:insert/1\n```\n\nCommand 48 makes the same mistake as in command 43, but this time the evaluator\nprocess lives on. The single star at the beginning of the printout signals that\nthe exception has been caught.\n\n```erlang\n49> ets:insert(E, {d,1,2}).\ntrue\n```\n\nCommand 49 successfully inserts the tuple into the ETS table.\n\n```erlang\n50> ets:insert(#Ref<0.1662103692.2407923716.214197>, {e,3,4}).\ntrue\n```\n\nCommand 50 inserts another tuple into the ETS table. This time the first\nargument is the table identifier itself. The shell can parse commands with pids\n(`<0.60.0>`), ports (`#Port<0.536>`), references\n(`#Ref<0.1662103692.2407792644.214210>`), and external functions\n(`#Fun `), but the command fails unless the corresponding pid, port,\nreference, or function can be created in the running system.\n\n```erlang\n51> halt().\nstrider 2>\n```\n\nCommand 51 exits the Erlang runtime system.","title":"Example - shell","ref":"shell.html#module-example"},{"type":"module","doc":"When the shell starts, it starts a single evaluator process. This process,\ntogether with any local processes that it spawns, is referred to as a `job`.\nOnly the current job, which is said to be `connected`, can perform operations\nwith standard I/O. All other jobs, which are said to be `detached`, are\n`blocked` if they attempt to use standard I/O.\n\nAll jobs that do not use standard I/O run in the normal way.\n\nThe shell escape key `^G` (Control G) detaches the current job and activates\n`JCL` mode. The `JCL` mode prompt is `\"-->\"`. If `\"?\"` is entered at the prompt,\nthe following help message is displayed:\n\n```text\n--> ?\nc [nn] - connect to job\ni [nn] - interrupt job\nk [nn] - kill job\nj - list all jobs\ns [shell] - start local shell\nr [node [shell]] - start remote shell\nq - quit erlang\n? | h - this message\n```\n\nThe `JCL` commands have the following meaning:\n\n- **`c [nn]`** - Connects to job number ` ` or the current job. The standard\n shell is resumed. Operations that use standard I/O by the current job are\n interleaved with user inputs to the shell.\n\n- **`i [nn]`** - Stops the current evaluator process for job number `nn` or the\n current job, but does not kill the shell process. So, any variable bindings\n and the process dictionary are preserved and the job can be connected again.\n This command can be used to interrupt an endless loop.\n\n- **`k [nn]`** - Kills job number `nn` or the current job. All spawned processes\n in the job are killed, provided they have not evaluated the `group_leader/1`\n BIF and are located on the local machine. Processes spawned on remote nodes\n are not killed.\n\n- **`j`** - Lists all jobs. A list of all known jobs is printed. The current job\n name is prefixed with '\\*'.\n\n- **`s`** - Starts a new job. This is assigned the new index `[nn]`, which can\n be used in references.\n\n- **`s [shell]`** - Starts a new job. This is assigned the new index `[nn]`,\n which can be used in references. If optional argument `shell` is specified, it\n is assumed to be a module that implements an alternative shell.\n\n- **`r [node]`** - Starts a remote job on `node`. This is used in distributed\n Erlang to allow a shell running on one node to control a number of\n applications running on a network of nodes. If optional argument `shell` is\n specified, it is assumed to be a module that implements an alternative shell.\n\n- **`q`** - Quits Erlang. Notice that this option is disabled if Erlang is\n started with the ignore break, `+Bi`, system flag (which can be useful, for\n example when running a restricted shell, see the next section).\n\n- **`?`** - Displays the help message above.\n\nThe behavior of shell escape can be changed by the STDLIB application variable\n`shell_esc`. The value of the variable can be either `jcl`\n(`erl -stdlib shell_esc jcl`) or `abort` (`erl -stdlib shell_esc abort`). The\nfirst option sets `^G` to activate `JCL` mode (which is also default behavior).\nThe latter sets `^G` to terminate the current shell and start a new one. `JCL`\nmode cannot be invoked when `shell_esc` is set to `abort`.\n\nIf you want an Erlang node to have a remote job active from the start (rather\nthan the default local job), start Erlang with flag\n[`-remsh`](`e:erts:erl_cmd.md#remsh`), for example,\n`erl -remsh other_node@other_host`","title":"JCL Mode - shell","ref":"shell.html#module-jcl-mode"},{"type":"module","doc":"The shell can be started in a restricted mode. In this mode, the shell evaluates\na function call only if allowed. This feature makes it possible to, for example,\nprevent a user from accidentally calling a function from the prompt that could\nharm a running system (useful in combination with system flag `+Bi`).\n\nWhen the restricted shell evaluates an expression and encounters a function call\nor an operator application, it calls a callback function (with information about\nthe function call in question). This callback function returns `true` to let the\nshell go ahead with the evaluation, or `false` to abort it. There are two\npossible callback functions for the user to implement:\n\n- `local_allowed(Func, ArgList, State) -> {boolean(),NewState}`\n\n This is used to determine if the call to the local function `Func` with\n arguments `ArgList` is to be allowed.\n\n- `non_local_allowed(FuncSpec, ArgList, State) -> {boolean(),NewState} | {{redirect,NewFuncSpec,NewArgList},NewState}`\n\n This is used to determine if the call to non-local function `FuncSpec`\n (`{Module,Func}` or a fun) with arguments `ArgList` is to be allowed. The\n return value `{redirect,NewFuncSpec,NewArgList}` can be used to let the shell\n evaluate some other function than the one specified by `FuncSpec` and\n `ArgList`.\n\nThese callback functions are called from local and non-local evaluation function\nhandlers, described in the `m:erl_eval` manual page. (Arguments in `ArgList` are\nevaluated before the callback functions are called.)\n\nFrom OTP 25.0, if there are errors evaluating Erlang constructs, such as\n`badmatch` during pattern matching or `bad_generator` in a comprehension, the\nevaluator will dispatch to `erlang:raise(error, Reason, Stacktrace)`. This call\nwill be checked against the `non_local_allowed/3` callback function. You can\neither forbid it, allow it, or redirect to another call of your choice.\n\nArgument `State` is a tuple `{ShellState,ExprState}`. The return value\n`NewState` has the same form. This can be used to carry a state between calls to\nthe callback functions. Data saved in `ShellState` lives through an entire shell\nsession. Data saved in `ExprState` lives only through the evaluation of the\ncurrent expression.\n\nThere are two ways to start a restricted shell session:\n\n- Use STDLIB application variable `restricted_shell` and specify, as its value,\n the name of the callback module. Example (with callback functions implemented\n in `callback_mod.erl`): `$ erl -stdlib restricted_shell callback_mod`.\n- From a normal shell session, call function `start_restricted/1`. This exits\n the current evaluator and starts a new one in restricted mode.\n\n_Notes:_\n\n- When restricted shell mode is activated or deactivated, new jobs started on\n the node run in restricted or normal mode, respectively.\n- If restricted mode has been enabled on a particular node, remote shells\n connecting to this node also run in restricted mode.\n- The callback functions cannot be used to allow or disallow execution of\n functions called from compiled code (only functions called from expressions\n entered at the shell prompt).\n\nErrors when loading the callback module is handled in different ways depending\non how the restricted shell is activated:\n\n- If the restricted shell is activated by setting the STDLIB variable during\n emulator startup, and the callback module cannot be loaded, a default\n restricted shell allowing only the commands `q()` and `init:stop()` is used as\n fallback.\n- If the restricted shell is activated using `start_restricted/1` and the\n callback module cannot be loaded, an error report is sent to the error logger\n and the call returns `{error,Reason}`.","title":"Restricted Shell - shell","ref":"shell.html#module-restricted-shell"},{"type":"module","doc":"The default shell prompt function displays the name of the node (if the node can\nbe part of a distributed system) and the current command number. The user can\ncustomize the prompt function by calling `prompt_func/1` or by setting\napplication configuration parameter `shell_prompt_func` for the STDLIB\napplication. Similarly the multiline prompt can be configured as well, by\ncalling `multiline_prompt_func/1` or by setting the application parameter\n`shell_multiline_prompt` for the STDLIB application.\n\nA customized prompt function is stated as a tuple `{Mod, Func}`. The function is\ncalled as `Mod:Func(L)`, where `L` is a list of key-value pairs created by the\nshell. Currently there is only one pair: `{history, N}`, where `N` is the\ncurrent command number. The function is to return a list of characters or an\natom. This constraint is because of the Erlang I/O protocol. Unicode characters\nbeyond code point 255 are allowed in the list and the atom. Notice that in\nrestricted mode the call `Mod:Func(L)` must be allowed or the default shell\nprompt function is called.","title":"Prompting - shell","ref":"shell.html#module-prompting"},{"type":"function","doc":"Sets the exception handling of the evaluator process. The previous exception\nhandling is returned. The default (`false`) is to kill the evaluator process\nwhen an exception occurs, which causes the shell to create a new evaluator\nprocess. When the exception handling is set to `true`, the evaluator process\nlives on, which means that, for example, ports and ETS tables as well as\nprocesses linked to the evaluator process survive the exception.","title":"shell.catch_exception/1","ref":"shell.html#catch_exception/1"},{"type":"function","doc":"Configures the multiline prompt as two trailing dots. This is the default\nfunction but it may also be set explicitly as\n`-stdlib shell_multiline_prompt {shell, default_multiline_prompt}`.","title":"shell.default_multiline_prompt/1","ref":"shell.html#default_multiline_prompt/1"},{"type":"function","doc":"A formatting function that can be set with `format_shell_func/1` that will make\nexpressions submitted to the shell prettier.\n\n> #### Note {: .info }\n>\n> This formatting function filter comments away from the expressions.","title":"shell.erl_pp_format_func/1","ref":"shell.html#erl_pp_format_func/1"},{"type":"function","doc":"Can be used to set the formatting of the Erlang shell output.\n\nThis has an effect on commands that have been submitted, and how it is saved in history.\nOr if the formatting hotkey is pressed while editing an expression (Alt+R by default). You\ncan specify a `Mod:Func/1` that expects the whole expression as a string and\nreturns a formatted expressions as a string. See\n[`stdlib app config`](stdlib_app.md#format_shell_func) for how to set it before\nshell started.\n\nIf instead a string is provided, it will be used as a shell command. Your\ncommand must include `${file}` somewhere in the string, for the shell to know\nwhere the file goes in the command.\n\n```erlang\nshell:format_shell_func(\"\\\"emacs -batch \\${file} -l ~/erlang-format/emacs-format-file -f emacs-format-function\\\"\").\n```\n\n```erlang\nshell:format_shell_func({shell, erl_pp_format_func}).\n```","title":"shell.format_shell_func/1","ref":"shell.html#format_shell_func/1"},{"type":"function","doc":"Sets the number of previous commands to keep in the history list to `N`. The\nprevious number is returned. Defaults to 20.","title":"shell.history/1","ref":"shell.html#history/1"},{"type":"function","doc":"Configures the multiline prompt as inverted space. It may be set explicitly as\n`-stdlib shell_multiline_prompt {shell, inverted_space_prompt}` or calling\n`multiline_prompt_func({shell, inverted_space_prompt}).`","title":"shell.inverted_space_prompt/1","ref":"shell.html#inverted_space_prompt/1"},{"type":"function","doc":"Sets the shell multiline prompt function to `PromptFunc`. The previous prompt\nfunction is returned.","title":"shell.multiline_prompt_func/1","ref":"shell.html#multiline_prompt_func/1"},{"type":"function","doc":"Sets the shell prompt function to `PromptFunc`. The previous prompt function is\nreturned.","title":"shell.prompt_func/1","ref":"shell.html#prompt_func/1"},{"type":"function","doc":"Equivalent to `prompt_width/2` with `Encoding` set to the encoding used by\n`t:io:user/0`.","title":"shell.prompt_width/1","ref":"shell.html#prompt_width/1"},{"type":"function","doc":"It receives a prompt and computes its width, considering its Unicode characters\nand ANSI escapes.\n\nUseful for creating custom multiline prompts.\n\nExample:\n\n```erlang\n1> shell:prompt_width(\"olá> \", unicode).\n5\n%% \"olá> \" is printed as \"ol\\341> \" on a latin1 systems\n2> shell:prompt_width(\"olá> \", latin1).\n8\n%% Ansi escapes are ignored\n3> shell:prompt_width(\"\\e[32molá\\e[0m> \", unicode).\n5\n%% Double width characters count as 2\n4> shell:prompt_width(\"😀> \", unicode).\n4\n%% \"😀> \" is printed as \"\\x{1F600}> \" on latin1 systems\n5> shell:prompt_width(\"😀> \", latin1).\n11\n```","title":"shell.prompt_width/2","ref":"shell.html#prompt_width/2"},{"type":"function","doc":"Sets the number of results from previous commands to keep in the history list to\n`N`. The previous number is returned. Defaults to 20.","title":"shell.results/1","ref":"shell.html#results/1"},{"type":"function","doc":"Starts the interactive shell if it has not already been started. It can be used\nto programatically start the shell from an escript or when erl is started with\nthe -noinput or -noshell flags.\n\nCalling this function will start a remote shell if `-remsh` is given on the\ncommand line or a local shell if not.","title":"shell.start_interactive/0","ref":"shell.html#start_interactive/0"},{"type":"function","doc":"Starts the interactive shell if it has not already been started. It can be used\nto programatically start the shell from an [`escript`](`e:erts:escript_cmd.md`)\nor when [`erl`](`e:erts:erl_cmd.md`) is started with the\n[`-noinput`](`e:erts:erl_cmd.md#noinput`) or\n[`-noshell`](`e:erts:erl_cmd.md#noshell`) flags. The following options are\nallowed:\n\n- **noshell | {noshell, Mode}** - Starts the interactive shell\n as if [`-noshell`](`e:erts:erl_cmd.md#noshell`) was given to\n [`erl`](`e:erts:erl_cmd.md`).\n\n It is possible to give a `Mode` indicating if the input should be set\n in `cooked` or `raw` mode. `Mode` only has en effect if `t:io:user/0` is a tty.\n If no `Mode` is given, it defaults is `cooked`.\n\n When in `raw` mode all key presses are passed to `t:io:user/0` as they are\n typed when they are typed and the characters are not echoed to the terminal.\n It is possible to set the `echo` to `true` using `io:setopts/2` to enabling\n echoing again.\n\n When in `cooked` mode the OS will handle the line editing and all data is\n passed to `t:io:user/0` when a newline is entered.\n\n- **[mfa()](`t:erlang:mfa/0`)** - Starts the interactive shell using\n [`mfa()`](`t:erlang:mfa/0`) as the default shell. The `t:mfa/0` should\n return the `t:pid/0` of the created shell process.\n\n- **\\{[node()](`t:erlang:node/0`), [mfa()](`t:erlang:mfa/0`)\\}** - Starts the\n interactive shell using [`mfa()`](`t:erlang:mfa/0`) on\n [`node()`](`t:erlang:node/0`) as the default shell. The `t:mfa/0` should\n return the `t:pid/0` of the created shell process.\n\n- **\\{remote, [`string()`](`t:erlang:string/0`)\\}** - Starts the interactive\n shell using as if [`-remsh`](`e:erts:erl_cmd.md#remsh`) was given to\n [`erl`](`e:erts:erl_cmd.md`).\n\n- **\\{remote, [`string()`](`t:erlang:string/0`),\n [`mfa()`](`t:erlang:mfa/0`)\\}** - Starts the interactive shell using as if\n [`-remsh`](`e:erts:erl_cmd.md#remsh`) was given to\n [`erl`](`e:erts:erl_cmd.md`) but with an alternative shell implementation.\n\nOn error this function will return:\n\n- **already_started** - if an interactive shell is already started.\n\n- **noconnection** - if a remote shell was requested but it could not be\n connected to.\n\n- **badfile | nofile | on_load_failure** - if a remote shell was requested with\n a custom [mfa()](`t:erlang:mfa/0`), but the module could not be loaded. See\n [Error Reasons for Code-Loading Functions](`m:code#error_reasons`) for a\n description of the error reasons.","title":"shell.start_interactive/1","ref":"shell.html#start_interactive/1"},{"type":"function","doc":"Exits a normal shell and starts a restricted shell. `Module` specifies the\ncallback module for the functions `local_allowed/3` and `non_local_allowed/3`.\nThe function is meant to be called from the shell.\n\nIf the callback module cannot be loaded, an error tuple is returned. The\n`Reason` in the error tuple is the one returned by the code loader when trying\nto load the code of the callback module.","title":"shell.start_restricted/1","ref":"shell.html#start_restricted/1"},{"type":"function","doc":"Exits a restricted shell and starts a normal shell. The function is meant to be\ncalled from the shell.","title":"shell.stop_restricted/0","ref":"shell.html#stop_restricted/0"},{"type":"function","doc":"Sets pretty printing of lists to `Strings`. The previous value of the flag is\nreturned.\n\nThe flag can also be set by the STDLIB application variable `shell_strings`.\nDefaults to `true`, which means that lists of integers are printed using the\nstring syntax, when possible. Value `false` means that no lists are printed\nusing the string syntax.","title":"shell.strings/1","ref":"shell.html#strings/1"},{"type":"function","doc":"Returns the current shell process on the node where the calling process'\ngroup_leader is located. If that node has no shell this function will return\nundefined.","title":"shell.whereis/0","ref":"shell.html#whereis/0"},{"type":"module","doc":"Customizing the Erlang environment.\n\nThe functions in this module are called when no module name is specified in a\nshell command.\n\nConsider the following shell dialog:\n\n```erlang\n1> lists:reverse(\"abc\").\n\"cba\"\n2> c(foo).\n{ok, foo}\n```\n\nIn command one, module `m:lists` is called. In command two, no module name is\nspecified. The shell searches module `user_default` followed by module\n`shell_default` for function `c/1`.\n\n`shell_default` is intended for \"system wide\" customizations to the shell.\n`user_default` is intended for \"local\" or individual user customizations.","title":"shell_default","ref":"shell_default.html"},{"type":"module","doc":"To add your own commands to the shell, create a module called `user_default` and\nadd the commands you want. Then add the following line as the _first_ line in\nyour `.erlang` file in your home directory.\n\n```text\ncode:load_abs(\"$PATH/user_default\").\n```\n\n`$PATH` is the directory where your `user_default` module can be found.","title":"Hint - shell_default","ref":"shell_default.html#module-hint"},{"type":"function","doc":"Print the help for all shell commands.","title":"shell_default.help/0","ref":"shell_default.html#help/0"},{"type":"module","doc":"Functions used to render [EEP-48](`e:kernel:eep48_chapter.md`) style documentation for a shell.\n\nThis module can be used to render function and type documentation to be printed\nin a shell. This is the module that is used to render the documentation accessed through\nthe shell through [`c:h/1,2,3`](`\\\\c:h/1`). Example:\n\n```txt\n1> h(maps,new,0).\n\n -spec new() -> Map when Map :: #{}.\n\nSince:\n OTP 17.0\n\n Returns a new empty map.\n\n Example:\n\n > maps:new().\n #{}\n```\n\nThis module formats and renders EEP-48 documentation of the format\n`application/erlang+html`. For more information about this format see\n[Documentation Storage](`e:edoc:doc_storage.md`) in EDoc's User's\nGuide. It can also render any other format of \"text\" type, although those will\nbe rendered as is.","title":"shell_docs","ref":"shell_docs.html"},{"type":"function","doc":"This function can be used to do whitespace normalization of\n`application/erlang+html` documentation.","title":"shell_docs.normalize/1","ref":"shell_docs.html#normalize/1"},{"type":"function","doc":"","title":"shell_docs.render/2","ref":"shell_docs.html#render/2"},{"type":"function","doc":"Render module or function documentation.\n\nRenders the module documentation if called as `render(Module, Docs, Config)`.\n\nEquivalent to [`render(Module, Function, Docs, #{})`](`render/4`) if called\nas `render(Module, Function, Docs)`.","title":"shell_docs.render/3","ref":"shell_docs.html#render/3"},{"type":"function","doc":"Render function documentation.\n\nRenders the function documentation if called as `render(Module, Function, Docs, Config)`.\n\nEquivalent to [`render(Module, Function, Arity, Docs, #{})`](`render/4`) if called\nas `render(Module, Function, Arity, Docs)`.","title":"shell_docs.render/4","ref":"shell_docs.html#render/4"},{"type":"function","doc":"Render the documentation for a function.","title":"shell_docs.render/5","ref":"shell_docs.html#render/5"},{"type":"function","doc":"","title":"shell_docs.render_callback/2","ref":"shell_docs.html#render_callback/2"},{"type":"function","doc":"Render all callbacks in a module or callback documentation.\n\nRenders a list with all callbacks if called as `render_callback(Module, Docs, Config)`.\n\nEquivalent to [`render_callback(Module, Callback, Docs, #{})`](`render_callback/4`) if called\nas `render_callback(Module, Callback, Docs)`.","title":"shell_docs.render_callback/3","ref":"shell_docs.html#render_callback/3"},{"type":"function","doc":"Render callback documentation.\n\nRenders the callback documentation if called as `render_callback(Module, Callback, Docs, Config)`.\n\nEquivalent to [`render_callback(Module, Callback, Arity, Docs, #{})`](`render_callback/4`) if called\nas `render_callback(Module, Callback, Arity, Docs)`.","title":"shell_docs.render_callback/4","ref":"shell_docs.html#render_callback/4"},{"type":"function","doc":"Render the documentation of a callback in a module.","title":"shell_docs.render_callback/5","ref":"shell_docs.html#render_callback/5"},{"type":"function","doc":"","title":"shell_docs.render_type/2","ref":"shell_docs.html#render_type/2"},{"type":"function","doc":"Render all types in a module or type documentation.\n\nRenders a list with all types if called as `render_type(Module, Docs, Config)`.\n\nEquivalent to [`render_type(Module, Type, Docs, #{})`](`render_type/4`) if called\nas `render_type(Module, Type, Docs)`.","title":"shell_docs.render_type/3","ref":"shell_docs.html#render_type/3"},{"type":"function","doc":"Render type documentation.\n\nRenders the type documentation if called as `render_type(Module, Type, Docs, Config)`.\n\nEquivalent to [`render_type(Module, Type, Arity, Docs, #{})`](`render_type/4`) if called\nas `render_type(Module, Type, Arity, Docs)`.","title":"shell_docs.render_type/4","ref":"shell_docs.html#render_type/4"},{"type":"function","doc":"Render the documentation of a type in a module.","title":"shell_docs.render_type/5","ref":"shell_docs.html#render_type/5"},{"type":"function","doc":"This function can be used to find out which tags are supported by\n`application/erlang+html` documentation.","title":"shell_docs.supported_tags/0","ref":"shell_docs.html#supported_tags/0"},{"type":"function","doc":"This function can be used to do a basic validation of the doc content of\n`application/erlang+html` format.","title":"shell_docs.validate/1","ref":"shell_docs.html#validate/1"},{"type":"type","doc":"","title":"shell_docs.chunk_element/0","ref":"shell_docs.html#t:chunk_element/0"},{"type":"type","doc":"","title":"shell_docs.chunk_element_attr/0","ref":"shell_docs.html#t:chunk_element_attr/0"},{"type":"type","doc":"","title":"shell_docs.chunk_element_attrs/0","ref":"shell_docs.html#t:chunk_element_attrs/0"},{"type":"type","doc":"","title":"shell_docs.chunk_element_block_type/0","ref":"shell_docs.html#t:chunk_element_block_type/0"},{"type":"type","doc":"","title":"shell_docs.chunk_element_inline_type/0","ref":"shell_docs.html#t:chunk_element_inline_type/0"},{"type":"type","doc":"The HTML tags allowed in `application/erlang+html`.","title":"shell_docs.chunk_element_type/0","ref":"shell_docs.html#t:chunk_element_type/0"},{"type":"type","doc":"","title":"shell_docs.chunk_elements/0","ref":"shell_docs.html#t:chunk_elements/0"},{"type":"type","doc":"The configuration of how the documentation should be rendered.\n\n- **encoding** - Configure the encoding that should be used by the renderer for\n graphical details such as bullet-points. By default `shell_docs` uses the\n value returned by [`io:getopts()`](`io:getopts/0`).\n\n- **ansi** - Configure whether\n [ansi escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code) should be\n used to render graphical details such as bold and underscore. By default\n `shell_docs` will try to determine if the receiving shell supports ansi escape\n codes. It is possible to override the automated check by setting the kernel\n configuration parameter `shell_docs_ansi` to a `t:boolean/0` value.\n\n- **columns** - Configure how wide the target documentation should be rendered.\n By default `shell_docs` used the value returned by\n [`io:columns()`](`io:columns/0`). It is possible to override this default\n by setting the stdlib configuration parameter `shell_docs_columns`\n to a `t:pos_integer/0` value.","title":"shell_docs.config/0","ref":"shell_docs.html#t:config/0"},{"type":"type","doc":"The record holding EEP-48 documentation for a module. You can use\n`code:get_doc/1` to fetch this information from a module.","title":"shell_docs.docs_v1/0","ref":"shell_docs.html#t:docs_v1/0"},{"type":"module","doc":"Provides base64 encode and decode, see\n[RFC 2045](https://www.ietf.org/rfc/rfc2045.txt).","title":"base64","ref":"base64.html"},{"type":"function","doc":"","title":"base64.decode/1","ref":"base64.html#decode/1"},{"type":"function","doc":"Decodes a base64 string encoded using the standard alphabet according to\n[RFC 4648 Section 4](https://datatracker.ietf.org/doc/html/rfc4648#section-4) to\nplain ASCII.\n\nThe function will strips away any whitespace characters and check for the\nthe correct number of `=` padding characters at the end of the encoded string.\n\nSee `t:decode_options/0` for details on which options can be passed.\n\n_Example_:\n```erlang\n1> base64:decode(\"AQIDBA==\").\n<<1,2,3,4>>\n2> base64:decode(\"AQ ID BA==\").\n<<1,2,3,4>>\n3> base64:decode(\"AQIDBA=\").\n** exception error: missing_padding\n in function base64:decode_list/7 (base64.erl, line 734)\n *** data to decode is missing final = padding characters, if this is intended, use the `padding => false` option\n4> base64:decode(\"AQIDBA=\", #{ padding => false }).\n<<1,2,3,4>>\n```","title":"base64.decode/2","ref":"base64.html#decode/2"},{"type":"function","doc":"Equivalent to [`decode(Base64)`](`decode/1`), but returns a `t:byte_string/0`.","title":"base64.decode_to_string/1","ref":"base64.html#decode_to_string/1"},{"type":"function","doc":"Equivalent to [`decode(Base64, Options)`](`decode/2`), but returns a `t:byte_string/0`.","title":"base64.decode_to_string/2","ref":"base64.html#decode_to_string/2"},{"type":"function","doc":"","title":"base64.encode/1","ref":"base64.html#encode/1"},{"type":"function","doc":"Encodes a plain ASCII string into base64 using the alphabet indicated by the\n`mode` option. The result is 33% larger than the data.\n\nSee `t:encode_options/0` for details on which options can be passed.","title":"base64.encode/2","ref":"base64.html#encode/2"},{"type":"function","doc":"Equivalent to [`encode(Data)`](`encode/1`), but returns a `t:byte_string/0`.","title":"base64.encode_to_string/1","ref":"base64.html#encode_to_string/1"},{"type":"function","doc":"Equivalent to [`encode(Data, Options)`](`encode/2`), but returns a `t:byte_string/0`.","title":"base64.encode_to_string/2","ref":"base64.html#encode_to_string/2"},{"type":"function","doc":"","title":"base64.mime_decode/1","ref":"base64.html#mime_decode/1"},{"type":"function","doc":"Decodes a base64 \"mime\" string encoded using the standard alphabet according to\n[RFC 4648 Section 4](https://datatracker.ietf.org/doc/html/rfc4648#section-4) to\nplain ASCII.\n\nThe function will strips away any illegal characters. It does *not* check for the\nthe correct number of `=` padding characters at the end of the encoded string.\n\nSee `t:decode_options/0` for details on which options can be passed.\n\n_Example_:\n```erlang\n1> base64:mime_decode(\"AQIDBA==\").\n<<1,2,3,4>>\n2> base64:mime_decode(\"AQIDB=A=\").\n<<1,2,3,4>>\n```","title":"base64.mime_decode/2","ref":"base64.html#mime_decode/2"},{"type":"function","doc":"Equivalent to [`mime_decode(Base64)`](`mime_decode/1`),\nbut returns a `t:byte_string/0`.","title":"base64.mime_decode_to_string/1","ref":"base64.html#mime_decode_to_string/1"},{"type":"function","doc":"Equivalent to [`mime_decode(Base64, Options)`](`mime_decode/2`),\nbut returns a `t:byte_string/0`.","title":"base64.mime_decode_to_string/2","ref":"base64.html#mime_decode_to_string/2"},{"type":"type","doc":"Base 64 Encoding alphabet, see\n[RFC 4648](https://datatracker.ietf.org/doc/html/rfc4648).","title":"base64.base64_alphabet/0","ref":"base64.html#t:base64_alphabet/0"},{"type":"type","doc":"Base 64 encoded binary.","title":"base64.base64_binary/0","ref":"base64.html#t:base64_binary/0"},{"type":"type","doc":"Selector for the Base 64 Encoding alphabet used for [encoding](`encode/2`) and\n[decoding](`decode/2`). See\n[RFC 4648](https://datatracker.ietf.org/doc/html/rfc4648) Sections\n[4](https://datatracker.ietf.org/doc/html/rfc4648#section-4) and\n[5](https://datatracker.ietf.org/doc/html/rfc4648#section-5).","title":"base64.base64_mode/0","ref":"base64.html#t:base64_mode/0"},{"type":"type","doc":"Base 64 encoded string.","title":"base64.base64_string/0","ref":"base64.html#t:base64_string/0"},{"type":"type","doc":"Arbitrary sequences of octets.","title":"base64.byte_string/0","ref":"base64.html#t:byte_string/0"},{"type":"type","doc":"Customizes the behaviour of the decode functions.\n\nDefault value if omitted entirely or partially is `#{mode => standard, padding => true}`.\n\nThe `mode` option can be one of the following:\n\n- **`standard`** - Default. Decode the given string using the standard base64\n alphabet according to\n [RFC 4648 Section 4](https://datatracker.ietf.org/doc/html/rfc4648#section-4),\n that is `\"+\"` and `\"/\"` are representing bytes `62` and `63` respectively,\n while `\"-\"` and `\"_\"` are illegal characters.\n\n- **`urlsafe`** - Decode the given string using the alternative \"URL and\n Filename safe\" base64 alphabet according to\n [RFC 4648 Section 5](https://datatracker.ietf.org/doc/html/rfc4648#section-5),\n that is `\"-\"` and `\"_\"` are representing bytes `62` and `63` respectively,\n while `\"+\"` and `\"/\"` are illegal characters.\n\nThe `padding` option can be one of the following:\n\n- **`true`** - Default. Checks the correct number of `=` padding characters at\n the end of the encoded string.\n\n- **`false`** - Accepts an encoded string with missing `=` padding characters at\n the end.","title":"base64.decode_options/0","ref":"base64.html#t:decode_options/0"},{"type":"type","doc":"Customizes the behaviour of the decode functions.\n\nDefault value if omitted entirely or partially is `#{mode => standard, padding => true}`.\n\nThe `mode` option can be one of the following:\n\n- **`standard`** - Default. Encode the given string using the standard base64\n alphabet according to\n [RFC 4648 Section 4](https://datatracker.ietf.org/doc/html/rfc4648#section-4).\n\n- **`urlsafe`** - Encode the given string using the alternative \"URL and\n Filename safe\" base64 alphabet according to\n [RFC 4648 Section 5](https://datatracker.ietf.org/doc/html/rfc4648#section-5).\n\nThe `padding` option can be one of the following:\n\n- **`true`** - Default. Appends correct number of `=` padding characters to the\n encoded string.\n\n- **`false`** - Skips appending `=` padding characters to the encoded string.","title":"base64.encode_options/0","ref":"base64.html#t:encode_options/0"},{"type":"behaviour","doc":"This module provides functions for pretty-printing errors and exceptions. It is\nused by both the `m:shell` and by `m:proc_lib` to print exceptions.\n\nIt is possible for the module raising an error to provide additional information\nby calling [`error/3`](`erlang:error/3`) with extra error information. More\ndetails about this mechanism is described in\n[EEP-54](https://www.erlang.org/erlang-enhancement-proposals/eep-0054.html).","title":"erl_error","ref":"erl_error.html"},{"type":"behaviour","doc":"The following functions are to be exported from an Error Info handler.","title":"Callback Functions - erl_error","ref":"erl_error.html#module-callback-functions"},{"type":"callback","doc":"This callback is called when `format_exception/4` or similar functionality wants\nto provide extra information about an error. The `Module`:`Function` called is\nthe one specificed by the `error_info` map.\n\nThe function should return a map with additional information about what have\ncaused the exception. The possible keys of the map are:\n\n- **`ArgumentPosition = pos_integer()`** - The position of the argument that\n caused the error starting at 1.\n\n- **`general`** - An error that is not associated with any argument caused the\n error.\n\n- **`reason`** - If the `Reason` should be printed differently than the default\n way.\n\nIf the text returned includes new-lines, `format_exception/4` will indent the\ntext correctly.\n\nExample:\n\n```erlang\n-module(my_error_module).\n-export([atom_to_string/1, format_error/2]).\n\natom_to_string(Arg) when is_atom(Arg) ->\n atom_to_list(Arg);\natom_to_string(Arg) ->\n erlang:error(badarg,[Arg],\n [{error_info,#{ module => ?MODULE,\n cause => #{ 1 => \"should be an atom\" }}}]).\n\nformat_error(Reason, [{_M,_F,_As,Info}|_]) ->\n ErrorInfo = proplists:get_value(error_info, Info, #{}),\n ErrorMap = maps:get(cause, ErrorInfo),\n ErrorMap#{ general => \"optional general information\",\n reason => io_lib:format(\"~p: ~p\",[?MODULE, Reason]) }.\n```\n\n```erlang\n1> c(my_error_module).\n{ok,my_error_module}\n2> my_error_module:atom_to_string(1).\n** exception error: my_error_module: badarg\n in function my_error_module:atom_to_string/1\n called as my_error_module:atom_to_string(1)\n *** argument 1: should be an atom\n *** optional general information\n```","title":"erl_error.format_error/2","ref":"erl_error.html#c:format_error/2"},{"type":"function","doc":"","title":"erl_error.format_exception/3","ref":"erl_error.html#format_exception/3"},{"type":"function","doc":"Format the error reason and stack back-trace caught using `try` ... `catch` in\nthe same style as the shell formats them.\n\nExample:\n\n```erlang\ntry\n do_something()\ncatch\n C:R:Stk ->\n Message = erl_error:format_exception(C, R, Stk),\n io:format(LogFile, \"~ts\\n\", [Message])\nend\n```\n\nIf `error_info` is provided with the exception, `format_exception` will use that\ninformation to provide additional information about the exception.\n\nExample:\n\n```erlang\ntry\n erlang:raise(badarg,[],[{error_info,#{}}])\ncatch\n C:R:Stk ->\n Message = erl_error:format_exception(C, R, Stk),\n io:format(LogFile, \"~ts\\n\", [Message])\nend\n```\n\nSee `erlang:error/3` for details on how to raise an exception with `error_info`\nincluded.","title":"erl_error.format_exception/4","ref":"erl_error.html#format_exception/4"},{"type":"type","doc":"Start column number. Default is 1.","title":"erl_error.column/0","ref":"erl_error.html#t:column/0"},{"type":"type","doc":"A fun used to format function arguments for BIF and function calls. By default\nthe following fun will be used:\n\n```erlang\nfun(Term, I) -> io_lib:print(Term, I, 80, 30) end\n```","title":"erl_error.format_fun/0","ref":"erl_error.html#t:format_fun/0"},{"type":"type","doc":"A map with formatting options.","title":"erl_error.format_options/0","ref":"erl_error.html#t:format_options/0"},{"type":"type","doc":"A fun used to trim the end of the stacktrace. It is called with module,\nfunction, and arity from an entry from the stacktrace. The fun is to return\n`true` if the entry should be trimmed, and `false` otherwise. The default value\nis:\n\n```text\nfun(_, _, _) -> false end\n```","title":"erl_error.stack_trim_fun/0","ref":"erl_error.html#t:stack_trim_fun/0"},{"type":"module","doc":"File sorter.\n\nThis module contains functions for sorting terms on files, merging already\nsorted files, and checking files for sortedness. Chunks containing binary terms\nare read from a sequence of files, sorted internally in memory and written on\ntemporary files, which are merged producing one sorted file as output. Merging\nis provided as an optimization; it is faster when the files are already sorted,\nbut it always works to sort instead of merge.\n\nOn a file, a term is represented by a header and a binary. Two options define\nthe format of terms on files:\n\n- **`{header, HeaderLength}`** - `HeaderLength` determines the number of bytes\n preceding each binary and containing the length of the binary in bytes.\n Defaults to 4. The order of the header bytes is defined as follows: if `B` is\n a binary containing a header only, size `Size` of the binary is calculated as\n `< > = B`.\n\n- **`{format, Format}`** - Option `Format` determines the function that is\n applied to binaries to create the terms to be sorted. Defaults to\n `binary_term`, which is equivalent to `fun binary_to_term/1`. Value `binary`\n is equivalent to `fun(X) -> X end`, which means that the binaries are sorted\n as they are. This is the fastest format. If `Format` is `term`, `io:read/2` is\n called to read terms. In that case, only the default value of option `header`\n is allowed.\n\n Option `format` also determines what is written to the sorted output file: if\n `Format` is `term`, then `io:format/3` is called to write each term, otherwise\n the binary prefixed by a header is written. Notice that the binary written is\n the same binary that was read; the results of applying function `Format` are\n thrown away when the terms have been sorted. Reading and writing terms using\n the `io` module is much slower than reading and writing binaries.\n\nOther options are:\n\n- **`{order, Order}`** - The default is to sort terms in ascending order, but\n that can be changed by value `descending` or by specifying an ordering\n function `Fun`. An ordering function is antisymmetric, transitive, and total.\n `Fun(A, B)` is to return `true` if `A` comes before `B` in the ordering,\n otherwise `false`. An example of a typical ordering function is less than or\n equal to, `=\n {ok, _} = disk_log:open([{name,Log}, {mode,read_only}]),\n Input = input(Log, start),\n Output = output([]),\n Reply = file_sorter:sort(Input, Output, {format,term}),\n ok = disk_log:close(Log),\n Reply.\n\ninput(Log, Cont) ->\n fun(close) ->\n ok;\n (read) ->\n case disk_log:chunk(Log, Cont) of\n {error, Reason} ->\n {error, Reason};\n {Cont2, Terms} ->\n {Terms, input(Log, Cont2)};\n {Cont2, Terms, _Badbytes} ->\n {Terms, input(Log, Cont2)};\n eof ->\n end_of_input\n end\n end.\n\noutput(L) ->\n fun(close) ->\n lists:append(lists:reverse(L));\n (Terms) ->\n output([Terms | L])\n end.\n```\n\nFor more examples of functions as input and output, see the end of the\n`file_sorter` module; the `term` format is implemented with functions.\n\nThe possible values of `Reason` returned when an error occurs are:\n\n- `bad_object`, `{bad_object, FileName}` \\- Applying the format function failed\n for some binary, or the key(s) could not be extracted from some term.\n- `{bad_term, FileName}` \\- `io:read/2` failed to read some term.\n- `{file_error, FileName, file:posix()}` \\- For an explanation of\n [`file:posix()`](`t:file:posix/0`), see `m:file`.\n- `{premature_eof, FileName}` \\- End-of-file was encountered inside some binary\n term.","title":"file_sorter","ref":"file_sorter.html"},{"type":"function","doc":"","title":"file_sorter.check/1","ref":"file_sorter.html#check/1"},{"type":"function","doc":"Checks files for sortedness. If a file is not sorted, the first out-of-order\nelement is returned. The first term on a file has position 1.","title":"file_sorter.check/2","ref":"file_sorter.html#check/2"},{"type":"function","doc":"","title":"file_sorter.keycheck/2","ref":"file_sorter.html#keycheck/2"},{"type":"function","doc":"Checks files for sortedness. If a file is not sorted, the first out-of-order\nelement is returned. The first term on a file has position 1.","title":"file_sorter.keycheck/3","ref":"file_sorter.html#keycheck/3"},{"type":"function","doc":"","title":"file_sorter.keymerge/3","ref":"file_sorter.html#keymerge/3"},{"type":"function","doc":"Merges tuples on files. Each input file is assumed to be sorted on key(s).","title":"file_sorter.keymerge/4","ref":"file_sorter.html#keymerge/4"},{"type":"function","doc":"Sorts tuples on files.","title":"file_sorter.keysort/2","ref":"file_sorter.html#keysort/2"},{"type":"function","doc":"","title":"file_sorter.keysort/3","ref":"file_sorter.html#keysort/3"},{"type":"function","doc":"Sorts tuples on files. The sort is performed on the element(s) mentioned in\n`KeyPos`. If two tuples compare equal (`==`) on one element, the next element\naccording to `KeyPos` is compared. The sort is stable.","title":"file_sorter.keysort/4","ref":"file_sorter.html#keysort/4"},{"type":"function","doc":"","title":"file_sorter.merge/2","ref":"file_sorter.html#merge/2"},{"type":"function","doc":"Merges terms on files. Each input file is assumed to be sorted.","title":"file_sorter.merge/3","ref":"file_sorter.html#merge/3"},{"type":"function","doc":"Sorts terms on files.","title":"file_sorter.sort/1","ref":"file_sorter.html#sort/1"},{"type":"function","doc":"","title":"file_sorter.sort/2","ref":"file_sorter.html#sort/2"},{"type":"function","doc":"Sorts terms on files.","title":"file_sorter.sort/3","ref":"file_sorter.html#sort/3"},{"type":"type","doc":"","title":"file_sorter.file_name/0","ref":"file_sorter.html#t:file_name/0"},{"type":"type","doc":"","title":"file_sorter.file_names/0","ref":"file_sorter.html#t:file_names/0"},{"type":"type","doc":"","title":"file_sorter.format/0","ref":"file_sorter.html#t:format/0"},{"type":"type","doc":"","title":"file_sorter.format_fun/0","ref":"file_sorter.html#t:format_fun/0"},{"type":"type","doc":"","title":"file_sorter.header_length/0","ref":"file_sorter.html#t:header_length/0"},{"type":"type","doc":"","title":"file_sorter.i_command/0","ref":"file_sorter.html#t:i_command/0"},{"type":"type","doc":"","title":"file_sorter.i_reply/0","ref":"file_sorter.html#t:i_reply/0"},{"type":"type","doc":"","title":"file_sorter.infun/0","ref":"file_sorter.html#t:infun/0"},{"type":"type","doc":"","title":"file_sorter.input/0","ref":"file_sorter.html#t:input/0"},{"type":"type","doc":"","title":"file_sorter.input_reply/0","ref":"file_sorter.html#t:input_reply/0"},{"type":"type","doc":"","title":"file_sorter.key_pos/0","ref":"file_sorter.html#t:key_pos/0"},{"type":"type","doc":"","title":"file_sorter.no_files/0","ref":"file_sorter.html#t:no_files/0"},{"type":"type","doc":"","title":"file_sorter.o_command/0","ref":"file_sorter.html#t:o_command/0"},{"type":"type","doc":"","title":"file_sorter.o_reply/0","ref":"file_sorter.html#t:o_reply/0"},{"type":"type","doc":"","title":"file_sorter.object/0","ref":"file_sorter.html#t:object/0"},{"type":"type","doc":"","title":"file_sorter.option/0","ref":"file_sorter.html#t:option/0"},{"type":"type","doc":"","title":"file_sorter.options/0","ref":"file_sorter.html#t:options/0"},{"type":"type","doc":"","title":"file_sorter.order/0","ref":"file_sorter.html#t:order/0"},{"type":"type","doc":"","title":"file_sorter.order_fun/0","ref":"file_sorter.html#t:order_fun/0"},{"type":"type","doc":"","title":"file_sorter.outfun/0","ref":"file_sorter.html#t:outfun/0"},{"type":"type","doc":"","title":"file_sorter.output/0","ref":"file_sorter.html#t:output/0"},{"type":"type","doc":"","title":"file_sorter.output_reply/0","ref":"file_sorter.html#t:output_reply/0"},{"type":"type","doc":"","title":"file_sorter.reason/0","ref":"file_sorter.html#t:reason/0"},{"type":"type","doc":"","title":"file_sorter.size/0","ref":"file_sorter.html#t:size/0"},{"type":"type","doc":"","title":"file_sorter.tmp_directory/0","ref":"file_sorter.html#t:tmp_directory/0"},{"type":"type","doc":"","title":"file_sorter.value/0","ref":"file_sorter.html#t:value/0"},{"type":"module","doc":"File utilities, such as wildcard matching of filenames.\n\nThis module contains utilities on a higher level than the `m:file` module.\n\nThis module does not support \"raw\" filenames (that is, files whose names do not\ncomply with the expected encoding). Such files are ignored by the functions in\nthis module.\n\nFor more information about raw filenames, see the `m:file` module.\n\n> #### Note {: .info }\n>\n> Functionality in this module generally assumes valid input and does not\n> necessarily fail on input that does not use a valid encoding, but may instead\n> very likely produce invalid output.\n>\n> File operations used to accept filenames containing null characters (integer\n> value zero). This caused the name to be truncated and in some cases arguments\n> to primitive operations to be mixed up. Filenames containing null characters\n> inside the filename are now _rejected_ and will cause primitive file\n> operations to fail.\n\n> #### Warning {: .warning }\n>\n> Currently null characters at the end of the filename will be accepted by\n> primitive file operations. Such filenames are however still documented as\n> invalid. The implementation will also change in the future and reject such\n> filenames.","title":"filelib","ref":"filelib.html"},{"type":"function","doc":"Ensures that all parent directories for the specified file or directory name\n`Name` exist, trying to create them if necessary.\n\nReturns `ok` if all parent directories already exist or can be created. Returns\n`{error, Reason}` if some parent directory does not exist and cannot be created.","title":"filelib.ensure_dir/1","ref":"filelib.html#ensure_dir/1"},{"type":"function","doc":"Ensures that all parent directories for the specified path `Path` exist, trying\nto create them if necessary.\n\nUnlike `ensure_dir/1`, this function will attempt to create all path segments as\na directory, including the last segment.\n\nReturns `ok` if all parent directories already exist or can be created. Returns\n`{error, Reason}` if some parent directory does not exist and cannot be created.","title":"filelib.ensure_path/1","ref":"filelib.html#ensure_path/1"},{"type":"function","doc":"Returns the size of the specified file.","title":"filelib.file_size/1","ref":"filelib.html#file_size/1"},{"type":"function","doc":"","title":"filelib.find_file/2","ref":"filelib.html#find_file/2"},{"type":"function","doc":"Looks for a file of the given name by applying suffix rules to the given\ndirectory path.\n\nFor example, a rule `{\"ebin\", \"src\"}` means that if the directory path ends with\n `\"ebin\"`, the corresponding path ending in `\"src\"` should be searched.\n\nIf `Rules` is left out or is an empty list, the default system rules are used.\nSee also the Kernel application parameter\n[`source_search_rules`](`e:kernel:kernel_app.md#source_search_rules`).","title":"filelib.find_file/3","ref":"filelib.html#find_file/3"},{"type":"function","doc":"Equivalent to [`find_source(Base, Dir)`](`find_source/2`), where `Dir` is\n`filename:dirname(FilePath)` and `Base` is `filename:basename(FilePath)`.","title":"filelib.find_source/1","ref":"filelib.html#find_source/1"},{"type":"function","doc":"","title":"filelib.find_source/2","ref":"filelib.html#find_source/2"},{"type":"function","doc":"Applies file extension specific rules to find the source file for a given object\nfile relative to the object directory.\n\nFor example, for a file with the extension `.beam`, the default rule is to look\nfor a file with a corresponding extension `.erl` by replacing the suffix `\"ebin\"`\nof the object directory path with `\"src\"` or `\"src/*\"`. The file search is done\nthrough `find_file/3`. The directory of the object file is always tried before\nany other directory specified by the rules.\n\nIf `Rules` is left out or is an empty list, the default system rules are used.\nSee also the Kernel application parameter\n[`source_search_rules`](`e:kernel:kernel_app.md#source_search_rules`).","title":"filelib.find_source/3","ref":"filelib.html#find_source/3"},{"type":"function","doc":"Folds function `Fun` over all (regular) files `F` in directory `Dir` whose\nbasename (for example, just `\"baz.erl\"` in `\"foo/bar/baz.erl\"`) matches the\nregular expression `RegExp` (for a description of the allowed regular\nexpressions, see the `m:re` module).\n\nIf `Recursive` is `true`, all subdirectories to `Dir` are processed.\nThe regular expression matching is only done on the filename without the directory part.\n\nIf Unicode filename translation is in effect and the file system is transparent,\nfilenames that cannot be interpreted as Unicode can be encountered, in which\ncase the `fun()` must be prepared to handle raw filenames (that is, binaries).\nIf the regular expression contains codepoints > 255, it does not match filenames\nthat do not conform to the expected character encoding (that is, are not encoded\nin valid UTF-8).\n\nFor more information about raw filenames, see the `m:file` module.","title":"filelib.fold_files/5","ref":"filelib.html#fold_files/5"},{"type":"function","doc":"Returns `true` if `Name` refers to a directory, otherwise `false`.","title":"filelib.is_dir/1","ref":"filelib.html#is_dir/1"},{"type":"function","doc":"Returns `true` if `Name` refers to a file or a directory, otherwise `false`.","title":"filelib.is_file/1","ref":"filelib.html#is_file/1"},{"type":"function","doc":"Returns `true` if `Name` refers to a (regular) file, otherwise `false`.","title":"filelib.is_regular/1","ref":"filelib.html#is_regular/1"},{"type":"function","doc":"Returns the date and time the specified file or directory was last modified, or\n`0` if the file does not exist.","title":"filelib.last_modified/1","ref":"filelib.html#last_modified/1"},{"type":"function","doc":"Sanitizes the relative path by eliminating \"..\" and \".\" components to protect\nagainst directory traversal attacks.\n\nEither returns the sanitized path name, or the atom `unsafe` if the path is unsafe.\nThe path is considered unsafe in the following circumstances:\n\n- The path is not relative.\n- A \"..\" component would climb up above the root of the relative path.\n- A symbolic link in the path points above the root of the relative path.\n\n_Examples:_\n\n```erlang\n1> {ok, Cwd} = file:get_cwd().\n...\n2> filelib:safe_relative_path(\"dir/sub_dir/..\", Cwd).\n\"dir\"\n3> filelib:safe_relative_path(\"dir/..\", Cwd).\n[]\n4> filelib:safe_relative_path(\"dir/../..\", Cwd).\nunsafe\n5> filelib:safe_relative_path(\"/abs/path\", Cwd).\nunsafe\n```","title":"filelib.safe_relative_path/2","ref":"filelib.html#safe_relative_path/2"},{"type":"function","doc":"Returns a list of all files that match Unix-style wildcard string `Wildcard`.\n\nThe wildcard string looks like an ordinary filename, except that the following\n\"wildcard characters\" are interpreted in a special way:\n\n- **?** - Matches one character.\n\n- **\\*** - Matches any number of characters up to the end of the filename, the\n next dot, or the next slash.\n\n- **\\*\\*** - Two adjacent `*` used as a single pattern match all files and zero\n or more directories and subdirectories.\n\n- **\\[Character1,Character2,...]** - Matches any of the characters listed. Two\n characters separated by a hyphen match a range of characters. Example: `[A-Z]`\n matches any uppercase letter.\n\n- **\\{Item,...\\}** - Alternation. Matches one of the alternatives.\n\nOther characters represent themselves. Only filenames that have exactly the same\ncharacter in the same position match. Matching is case-sensitive, for example,\n\"a\" does not match \"A\".\n\nDirectory separators must always be written as `/`, even on Windows.\n\nA character preceded by `\\` loses its special meaning. Note that `\\` must be\nwritten as `\\\\` in a string literal. For example, \"\\\\\\\\?\\*\" will match any\nfilename starting with `?`.\n\nNotice that multiple \"\\*\" characters are allowed (as in Unix wildcards, but\nopposed to Windows/DOS wildcards).\n\n_Examples:_\n\nThe following examples assume that the current directory is the top of an\nErlang/OTP installation.\n\nTo find all `.beam` files in all applications, use the following line:\n\n```text\nfilelib:wildcard(\"lib/*/ebin/*.beam\").\n```\n\nTo find `.erl` or `.hrl` in all applications `src` directories, use either of\nthe following lines:\n\n```text\nfilelib:wildcard(\"lib/*/src/*.?rl\")\n```\n\n```text\nfilelib:wildcard(\"lib/*/src/*.{erl,hrl}\")\n```\n\nTo find all `.hrl` files in `src` or `include` directories:\n\n```text\nfilelib:wildcard(\"lib/*/{src,include}/*.hrl\").\n```\n\nTo find all `.erl` or `.hrl` files in either `src` or `include` directories:\n\n```text\nfilelib:wildcard(\"lib/*/{src,include}/*.{erl,hrl}\")\n```\n\nTo find all `.erl` or `.hrl` files in any subdirectory:\n\n```text\nfilelib:wildcard(\"lib/**/*.{erl,hrl}\")\n```","title":"filelib.wildcard/1","ref":"filelib.html#wildcard/1"},{"type":"function","doc":"Same as `wildcard/1`, except that `Cwd` is used instead of the working\ndirectory.","title":"filelib.wildcard/2","ref":"filelib.html#wildcard/2"},{"type":"type","doc":"","title":"filelib.dirname/0","ref":"filelib.html#t:dirname/0"},{"type":"type","doc":"","title":"filelib.dirname_all/0","ref":"filelib.html#t:dirname_all/0"},{"type":"type","doc":"","title":"filelib.filename/0","ref":"filelib.html#t:filename/0"},{"type":"type","doc":"","title":"filelib.filename_all/0","ref":"filelib.html#t:filename_all/0"},{"type":"type","doc":"","title":"filelib.find_file_rule/0","ref":"filelib.html#t:find_file_rule/0"},{"type":"type","doc":"","title":"filelib.find_source_rule/0","ref":"filelib.html#t:find_source_rule/0"},{"type":"module","doc":"Filename manipulation functions.\n\nThis module provides functions for analyzing and manipulating filenames. These\nfunctions are designed so that the Erlang code can work on many different\nplatforms with different filename formats. With filename is meant all strings\nthat can be used to denote a file. The filename can be a short relative name\nlike `foo.erl`, a long absolute name including a drive designator, a directory\nname like `D:\\usr/local\\bin\\erl/lib\\tools\\foo.erl`, or any variations in\nbetween.\n\nIn Windows, all functions return filenames with forward slashes only, even if\nthe arguments contain backslashes. To normalize a filename by removing redundant\ndirectory separators, use `join/1`.\n\nThe module supports [raw filenames](unicode_usage.md#notes-about-raw-filenames)\nin the way that if a binary is present, or the filename cannot be interpreted\naccording to the return value of `file:native_name_encoding/0`, a raw filename\nis also returned. For example, [`join/1`](`join/1`) provided with a path\ncomponent that is a binary (and cannot be interpreted under the current native\nfilename encoding) results in a raw filename that is returned (the join\noperation is performed of course). For more information about raw filenames, see\nthe `m:file` module.\n\n> #### Note {: .info }\n>\n> Functionality in this module generally assumes valid input and does not\n> necessarily fail on input that does not use a valid encoding, but may instead\n> very likely produce invalid output.\n>\n> File operations used to accept filenames containing null characters (integer\n> value zero). This caused the name to be truncated and in some cases arguments\n> to primitive operations to be mixed up. Filenames containing null characters\n> inside the filename are now _rejected_ and will cause primitive file\n> operations to fail.\n\n> #### Warning {: .warning }\n>\n> Currently null characters at the end of the filename will be accepted by\n> primitive file operations. Such filenames are however still documented as\n> invalid. The implementation will also change in the future and reject such\n> filenames.","title":"filename","ref":"filename.html"},{"type":"function","doc":"Converts a relative `Filename` and returns an absolute name. No attempt is made\nto create the shortest absolute name, as this can give incorrect results on file\nsystems that allow links.\n\n_Unix examples:_\n\n```erlang\n1> pwd().\n\"/usr/local\"\n2> filename:absname(\"foo\").\n\"/usr/local/foo\"\n3> filename:absname(\"../x\").\n\"/usr/local/../x\"\n4> filename:absname(\"/\").\n\"/\"\n```\n\n_Windows examples:_\n\n```erlang\n1> pwd().\n\"D:/usr/local\"\n2> filename:absname(\"foo\").\n\"D:/usr/local/foo\"\n3> filename:absname(\"../x\").\n\"D:/usr/local/../x\"\n4> filename:absname(\"/\").\n\"D:/\"\n```","title":"filename.absname/1","ref":"filename.html#absname/1"},{"type":"function","doc":"Same as `absname/1`, except that the directory to which the filename is to be\nmade relative is specified in argument `Dir`.","title":"filename.absname/2","ref":"filename.html#absname/2"},{"type":"function","doc":"Joins an absolute directory with a relative filename.\n\nSimilar to `join/2`, but on platforms with tight restrictions on raw filename length\nand no support for symbolic links, leading parent directory components in `Filename` are matched\nagainst trailing directory components in `Dir` so they can be removed from the\nresult - minimizing its length.","title":"filename.absname_join/2","ref":"filename.html#absname_join/2"},{"type":"function","doc":"Equivalent to [basedir(PathType, Application, #\\{\\})](`m:filename#basedir_3_1`)\nor [basedir(PathsType, Application, #\\{\\})](`m:filename#basedir_3_2`).","title":"filename.basedir/2","ref":"filename.html#basedir/2"},{"type":"function","doc":"[](){: #basedir_3_1 } [](){: #basedir_3_2 }\n\nReturns a suitable path, or paths, for a given type. If `os` is not set in\n`Opts` the function will default to the native option, that is `'linux'`,\n`'darwin'` or `'windows'`, as understood by `os:type/0`. Anything not recognized\nas `'darwin'` or `'windows'` is interpreted as `'linux'`.\n\nThe options `'author'` and `'version'` are only used with `'windows'` option\nmode.\n\n- `user_cache`{: #user_cache }\n\n The path location is intended for transient data files on a local machine.\n\n On Linux: Respects the os environment variable `XDG_CACHE_HOME`.\n\n ```erlang\n 1> filename:basedir(user_cache, \"my_application\", #{os=>linux}).\n \"/home/otptest/.cache/my_application\"\n ```\n\n On Darwin:\n\n ```erlang\n 1> filename:basedir(user_cache, \"my_application\", #{os=>darwin}).\n \"/home/otptest/Library/Caches/my_application\"\n ```\n\n On Windows:\n\n ```erlang\n 1> filename:basedir(user_cache, \"My App\").\n \"c:/Users/otptest/AppData/Local/My App/Cache\"\n 2> filename:basedir(user_cache, \"My App\").\n \"c:/Users/otptest/AppData/Local/My App/Cache\"\n 3> filename:basedir(user_cache, \"My App\", #{author=>\"Erlang\"}).\n \"c:/Users/otptest/AppData/Local/Erlang/My App/Cache\"\n 4> filename:basedir(user_cache, \"My App\", #{version=>\"1.2\"}).\n \"c:/Users/otptest/AppData/Local/My App/1.2/Cache\"\n 5> filename:basedir(user_cache, \"My App\", #{author=>\"Erlang\",version=>\"1.2\"}).\n \"c:/Users/otptest/AppData/Local/Erlang/My App/1.2/Cache\"\n ```\n\n- `user_config`{: #user_config }\n\n The path location is intended for persistent configuration files.\n\n On Linux: Respects the os environment variable `XDG_CONFIG_HOME`.\n\n ```erlang\n 2> filename:basedir(user_config, \"my_application\", #{os=>linux}).\n \"/home/otptest/.config/my_application\"\n ```\n\n On Darwin:\n\n ```erlang\n 2> filename:basedir(user_config, \"my_application\", #{os=>darwin}).\n \"/home/otptest/Library/Application Support/my_application\"\n ```\n\n On Windows:\n\n ```erlang\n 1> filename:basedir(user_config, \"My App\").\n \"c:/Users/otptest/AppData/Roaming/My App\"\n 2> filename:basedir(user_config, \"My App\", #{author=>\"Erlang\", version=>\"1.2\"}).\n \"c:/Users/otptest/AppData/Roaming/Erlang/My App/1.2\"\n ```\n\n- `user_data`{: #user_data }\n\n The path location is intended for persistent data files.\n\n On Linux: Respects the os environment variable `XDG_DATA_HOME`.\n\n ```erlang\n 3> filename:basedir(user_data, \"my_application\", #{os=>linux}).\n \"/home/otptest/.local/my_application\"\n ```\n\n On Darwin:\n\n ```erlang\n 3> filename:basedir(user_data, \"my_application\", #{os=>darwin}).\n \"/home/otptest/Library/Application Support/my_application\"\n ```\n\n On Windows:\n\n ```erlang\n 8> filename:basedir(user_data, \"My App\").\n \"c:/Users/otptest/AppData/Local/My App\"\n 9> filename:basedir(user_data, \"My App\",#{author=>\"Erlang\",version=>\"1.2\"}).\n \"c:/Users/otptest/AppData/Local/Erlang/My App/1.2\"\n ```\n\n- `user_log`{: #user_log }\n\n The path location is intended for transient log files on a local machine.\n\n On Linux: Respects the os environment variable `XDG_CACHE_HOME`.\n\n ```erlang\n 4> filename:basedir(user_log, \"my_application\", #{os=>linux}).\n \"/home/otptest/.cache/my_application/log\"\n ```\n\n On Darwin:\n\n ```erlang\n 4> filename:basedir(user_log, \"my_application\", #{os=>darwin}).\n \"/home/otptest/Library/Logs/my_application\"\n ```\n\n On Windows:\n\n ```erlang\n 12> filename:basedir(user_log, \"My App\").\n \"c:/Users/otptest/AppData/Local/My App/Logs\"\n 13> filename:basedir(user_log, \"My App\",#{author=>\"Erlang\",version=>\"1.2\"}).\n \"c:/Users/otptest/AppData/Local/Erlang/My App/1.2/Logs\"\n ```\n\n- `site_config`{: #site_config }\n\n On Linux: Respects the os environment variable `XDG_CONFIG_DIRS`.\n\n ```erlang\n 5> filename:basedir(site_config, \"my_application\", #{os=>linux}).\n [\"/usr/local/share/my_application\",\n \"/usr/share/my_application\"]\n 6> os:getenv(\"XDG_CONFIG_DIRS\").\n \"/etc/xdg/xdg-ubuntu:/usr/share/upstart/xdg:/etc/xdg\"\n 7> filename:basedir(site_config, \"my_application\", #{os=>linux}).\n [\"/etc/xdg/xdg-ubuntu/my_application\",\n \"/usr/share/upstart/xdg/my_application\",\n \"/etc/xdg/my_application\"]\n 8> os:unsetenv(\"XDG_CONFIG_DIRS\").\n true\n 9> filename:basedir(site_config, \"my_application\", #{os=>linux}).\n [\"/etc/xdg/my_application\"]\n ```\n\n On Darwin:\n\n ```erlang\n 5> filename:basedir(site_config, \"my_application\", #{os=>darwin}).\n [\"/Library/Application Support/my_application\"]\n ```\n\n- `site_data`{: #site_data }\n\n On Linux: Respects the os environment variable `XDG_DATA_DIRS`.\n\n ```erlang\n 10> os:getenv(\"XDG_DATA_DIRS\").\n \"/usr/share/ubuntu:/usr/share/gnome:/usr/local/share/:/usr/share/\"\n 11> filename:basedir(site_data, \"my_application\", #{os=>linux}).\n [\"/usr/share/ubuntu/my_application\",\n \"/usr/share/gnome/my_application\",\n \"/usr/local/share/my_application\",\n \"/usr/share/my_application\"]\n 12> os:unsetenv(\"XDG_DATA_DIRS\").\n true\n 13> filename:basedir(site_data, \"my_application\", #{os=>linux}).\n [\"/usr/local/share/my_application\",\n \"/usr/share/my_application\"]\n ```\n\n On Darwin:\n\n ```erlang\n 5> filename:basedir(site_data, \"my_application\", #{os=>darwin}).\n [\"/Library/Application Support/my_application\"]\n ```","title":"filename.basedir/3","ref":"filename.html#basedir/3"},{"type":"function","doc":"Returns the last component of `Filename`, or `Filename` itself if it does not\ncontain any directory separators.\n\n_Examples:_\n\n```erlang\n5> filename:basename(\"foo\").\n\"foo\"\n6> filename:basename(\"/usr/foo\").\n\"foo\"\n7> filename:basename(\"/\").\n[]\n```","title":"filename.basename/1","ref":"filename.html#basename/1"},{"type":"function","doc":"Returns the last component of `Filename` with extension `Ext` stripped.\n\nThis function is to be used to remove a (possible) specific extension.\nTo remove an existing extension when you are unsure which one it is, use\n[`rootname(basename(Filename))`](`rootname/1`).\n\n_Examples:_\n\n```erlang\n8> filename:basename(\"~/src/kalle.erl\", \".erl\").\n\"kalle\"\n9> filename:basename(\"~/src/kalle.beam\", \".erl\").\n\"kalle.beam\"\n10> filename:basename(\"~/src/kalle.old.erl\", \".erl\").\n\"kalle.old\"\n11> filename:rootname(filename:basename(\"~/src/kalle.erl\")).\n\"kalle\"\n12> filename:rootname(filename:basename(\"~/src/kalle.beam\")).\n\"kalle\"\n```","title":"filename.basename/2","ref":"filename.html#basename/2"},{"type":"function","doc":"Returns the directory part of `Filename`.\n\n_Examples:_\n\n```erlang\n13> filename:dirname(\"/usr/src/kalle.erl\").\n\"/usr/src\"\n14> filename:dirname(\"kalle.erl\").\n\".\"\n```\n\n```erlang\n5> filename:dirname(\"\\\\usr\\\\src/kalle.erl\"). % Windows\n\"/usr/src\"\n```","title":"filename.dirname/1","ref":"filename.html#dirname/1"},{"type":"function","doc":"Returns the file extension of `Filename`, including the period. Returns an empty\nstring if no extension exists.\n\n_Examples:_\n\n```erlang\n15> filename:extension(\"foo.erl\").\n\".erl\"\n16> filename:extension(\"beam.src/kalle\").\n[]\n```","title":"filename.extension/1","ref":"filename.html#extension/1"},{"type":"function","doc":"Converts a possibly deep list filename consisting of characters and atoms into\nthe corresponding flat string filename.","title":"filename.flatten/1","ref":"filename.html#flatten/1"},{"type":"function","doc":"Joins a list of filename `Components` with directory separators. If one of the\nelements of `Components` includes an absolute path, such as `\"/xxx\"`, the\npreceding elements, if any, are removed from the result.\n\nThe result is \"normalized\":\n\n- Redundant directory separators are removed.\n- In Windows, all directory separators are forward slashes and the drive letter\n is in lower case.\n\n_Examples:_\n\n```erlang\n17> filename:join([\"/usr\", \"local\", \"bin\"]).\n\"/usr/local/bin\"\n18> filename:join([\"a/b///c/\"]).\n\"a/b/c\"\n```\n\n```erlang\n6> filename:join([\"B:a\\\\b///c/\"]). % Windows\n\"b:a/b/c\"\n```","title":"filename.join/1","ref":"filename.html#join/1"},{"type":"function","doc":"Joins two filename components with directory separators. Equivalent to\n[`join([Name1, Name2])`](`join/1`).","title":"filename.join/2","ref":"filename.html#join/2"},{"type":"function","doc":"Converts `Path` to a form accepted by the command shell and native applications\non the current platform. On Windows, forward slashes are converted to backward\nslashes. On all platforms, the name is normalized as done by `join/1`.\n\n_Examples:_\n\n```erlang\n19> filename:nativename(\"/usr/local/bin/\"). % Unix\n\"/usr/local/bin\"\n```\n\n```erlang\n7> filename:nativename(\"/usr/local/bin/\"). % Windows\n\"\\\\usr\\\\local\\\\bin\"\n```","title":"filename.nativename/1","ref":"filename.html#nativename/1"},{"type":"function","doc":"Returns the path type, which is one of the following:\n\n- **`absolute`** - The path name refers to a specific file on a specific volume.\n\n Unix example: `/usr/local/bin`\n\n Windows example: `D:/usr/local/bin`\n\n- **`relative`** - The path name is relative to the current working directory on\n the current volume.\n\n Example: `foo/bar, ../src`\n\n- **`volumerelative`** - The path name is relative to the current working\n directory on a specified volume, or it is a specific file on the current\n working volume.\n\n Windows example: `D:bar.erl, /bar/foo.erl`","title":"filename.pathtype/1","ref":"filename.html#pathtype/1"},{"type":"function","doc":"Removes the filename extension.\n\n_Examples:_\n\n```erlang\n1> filename:rootname(\"/beam.src/kalle\").\n\"/beam.src/kalle\"\n2> filename:rootname(\"/beam.src/foo.erl\").\n\"/beam.src/foo\"\n```","title":"filename.rootname/1","ref":"filename.html#rootname/1"},{"type":"function","doc":"Removes the filename extension `Ext` from `Filename`.\n\n_Examples:_\n\n```erlang\n1> filename:rootname(\"/beam.src/foo.erl\", \".erl\").\n\"/beam.src/foo\"\n2> filename:rootname(\"/beam.src/foo.beam\", \".erl\").\n\"/beam.src/foo.beam\"\n```","title":"filename.rootname/2","ref":"filename.html#rootname/2"},{"type":"function","doc":"Returns a list whose elements are the path components of `Filename`.\n\n_Examples:_\n\n```erlang\n24> filename:split(\"/usr/local/bin\").\n[\"/\",\"usr\",\"local\",\"bin\"]\n25> filename:split(\"foo/bar\").\n[\"foo\",\"bar\"]\n26> filename:split(\"a:\\\\msdev\\\\include\").\n[\"a:/\",\"msdev\",\"include\"]\n```","title":"filename.split/1","ref":"filename.html#split/1"},{"type":"type","doc":"","title":"filename.basedir_opts/0","ref":"filename.html#t:basedir_opts/0"},{"type":"type","doc":"","title":"filename.basedir_path_type/0","ref":"filename.html#t:basedir_path_type/0"},{"type":"type","doc":"","title":"filename.basedir_paths_type/0","ref":"filename.html#t:basedir_paths_type/0"},{"type":"module","doc":"Standard I/O server interface functions.\n\nThis module provides an interface to standard Erlang I/O servers. The output\nfunctions all return `ok` if they are successful, or exit if they are not.\n\nAll functions in this module have an optional parameter\n[`IoDevice`](`t:device/0`). If included, it must be the pid of a process that\nhandles the I/O protocols. Normally, it is an [`IoDevice`](`t:device/0`) returned by\n`file:open/2`. If no [`IoDevice`](`t:device/0`) is given,\n[`standard_io`](`t:standard_io/0`) is used.\n\nFor a description of the I/O protocols, see section\n[The Erlang I/O Protocol](io_protocol.md) in the User's Guide.\n\n> #### Warning {: .warning }\n>\n> The data supplied to function `put_chars/2` is to be in\n> the `t:unicode:chardata/0` format. This means that programs supplying binaries\n> to this function must convert them to UTF-8 before trying to output the data\n> on an I/O device.\n>\n> If an I/O device is set in binary mode, functions\n> [`get_chars/2,3`](`get_chars/2`) and [`get_line/1,2`](`get_line/1`) can return\n> binaries instead of lists. The binaries are encoded in UTF-8.\n>\n> To work with binaries in ISO Latin-1 encoding, use the `m:file` module\n> instead.\n>\n> For conversion functions between character encodings, see the `m:unicode`\n> module.","title":"io","ref":"io.html"},{"type":"module","doc":"The `ErrorInfo` mentioned in this module is the standard `ErrorInfo` structure\nthat is returned from all I/O modules. It has the following format:\n\n```erlang\n{ErrorLocation, Module, ErrorDescriptor}\n```\n\nA string that describes the error is obtained with the following call:\n\n```erlang\nModule:format_error(ErrorDescriptor)\n```","title":"Error Information - io","ref":"io.html#module-error-information"},{"type":"function","doc":"","title":"io.columns/0","ref":"io.html#columns/0"},{"type":"function","doc":"Retrieves the number of columns of the [`IoDevice`](`t:device/0`) (that is, the width of a\nterminal).\n\nThe function succeeds for terminal devices and returns `{error, enotsup}` for\nall other I/O devices.","title":"io.columns/1","ref":"io.html#columns/1"},{"type":"function","doc":"","title":"io.format/1","ref":"io.html#format/1"},{"type":"function","doc":"","title":"io.format/2","ref":"io.html#format/2"},{"type":"function","doc":"","title":"io.format/3","ref":"io.html#format/3"},{"type":"function","doc":"","title":"io.fread/2","ref":"io.html#fread/2"},{"type":"function","doc":"Reads characters from [`IoDevice`](`t:device/0`), prompting it with `Prompt`. Interprets the\ncharacters in accordance with `Format`.\n\n`Format` can contain the following:\n\n- Whitespace characters (_Space_, _Tab_, and _Newline_) that cause input to be\n read to the next non-whitespace character.\n- Ordinary characters that must match the next input character.\n- Control sequences, which have the general format `~*FMC`, where:\n\n - Character `*` is an optional return suppression character. It provides a\n method to specify a field that is to be omitted.\n - `F` is the `field width` of the input field.\n - `M` is an optional translation modifier (of which `t` is the only supported,\n meaning Unicode translation).\n - `C` determines the type of control sequence.\n\n Unless otherwise specified, leading whitespace is ignored for all control\n sequences. An input field cannot be more than one line wide.\n\n _Available control sequences:_\n\n - **`~`** - A single `~` is expected in the input.\n\n - **`d`** - A decimal integer is expected.\n\n - **`u`** - An unsigned integer in base 2-36 is expected. The field width\n parameter is used to specify base. Leading whitespace characters are not\n skipped.\n\n - **`-`** - An optional sign character is expected. A sign character `-` gives\n return value `-1`. Sign character `+` or none gives `1`. The field width\n parameter is ignored. Leading whitespace characters are not skipped.\n\n - **`#`** - An integer in base 2-36 with Erlang-style base prefix (for\n example, `\"16#ffff\"`) is expected.\n\n - **`f`** - A floating point number is expected. It must follow the Erlang\n floating point number syntax.\n\n - **`s`** - A string of non-whitespace characters is read. If a field width\n has been specified, this number of characters are read and all trailing\n whitespace characters are stripped. An Erlang string (list of characters) is\n returned.\n\n If Unicode translation is in effect (`~ts`), characters > 255 are accepted,\n otherwise not. With the translation modifier, the returned list can as a\n consequence also contain integers > 255:\n\n ```erlang\n 1> io:fread(\"Prompt> \",\"~s\").\n Prompt> \n {error,{fread,string}}\n 2> io:fread(\"Prompt> \",\"~ts\").\n Prompt> \n {ok,[[1091,1085,1080,1094,1086,1076,1077]]}\n ```\n\n - **`a`** - Similar to `s`, but the resulting string is converted into an\n atom.\n\n - **`c`** - The number of characters equal to the field width are read\n (default is 1) and returned as an Erlang string. However, leading and\n trailing whitespace characters are not omitted as they are with `s`. All\n characters are returned.\n\n The Unicode translation modifier works as with `s`:\n\n ```erlang\n 1> io:fread(\"Prompt> \",\"~c\").\n Prompt> \n {error,{fread,string}}\n 2> io:fread(\"Prompt> \",\"~tc\").\n Prompt> \n {ok,[[1091]]}\n ```\n\n - **`l`** - Returns the number of characters that have been scanned up to that\n point, including whitespace characters.\n\n The function returns:\n\n - **`{ok, Terms}`** - The read was successful and `Terms` is the list of\n successfully matched and read items.\n\n - **`eof`** - End of file was encountered.\n\n - **`{error, FreadError}`** - The reading failed and `FreadError` gives a hint\n about the error.\n\n - **`{error, ErrorDescription}`** - The read operation failed and parameter\n `ErrorDescription` gives a hint about the error.\n\n_Examples:_\n\n```erlang\n20> io:fread('enter>', \"~f~f~f\").\nenter>1.9 35.5e3 15.0\n{ok,[1.9,3.55e4,15.0]}\n21> io:fread('enter>', \"~10f~d\").\nenter> 5.67899\n{ok,[5.678,99]}\n22> io:fread('enter>', \":~10s:~10c:\").\nenter>: alan : joe :\n{ok, [\"alan\", \" joe \"]}\n```","title":"io.fread/3","ref":"io.html#fread/3"},{"type":"function","doc":"","title":"io.fwrite/1","ref":"io.html#fwrite/1"},{"type":"function","doc":"","title":"io.fwrite/2","ref":"io.html#fwrite/2"},{"type":"function","doc":"Writes the items in `Data` on the [`IoDevice`](`t:device/0`) in accordance with `Format`.\n\n`Format` contains plain characters that are copied to\nthe output device, and control sequences for formatting, see below. If `Format`\nis an atom or a binary, it is first converted to a list with the aid of\n[`atom_to_list/1`](`atom_to_list/1`) or\n[`binary_to_list/1`](`binary_to_list/1`). Example:\n\n```erlang\n1> io:fwrite(\"Hello world!~n\", []).\nHello world!\nok\n```\n\nThe general format of a control sequence is `~F.P.PadModC`.\n\nThe character `C` determines the type of control sequence to be used. It is the\nonly required field. All of `F`, `P`, `Pad`, and `Mod` are optional. For\nexample, to use a `#` for `Pad` but use the default values for `F` and `P`, you\ncan write `~..#C`.\n\n- `F` is the `field width` of the printed argument. A negative value means that\n the argument is left-justified within the field, otherwise right-justified. If\n no field width is specified, the required print width is used. If the field\n width specified is too small, the whole field is filled with `*` characters.\n- `P` is the `precision` of the printed argument. A default value is used if no\n precision is specified. The interpretation of precision depends on the control\n sequences. Unless otherwise specified, argument `within` is used to determine\n print width.\n- `Pad` is the padding character. This is the character used to pad the printed\n representation of the argument so that it conforms to the specified field\n width and precision. Only one padding character can be specified and, whenever\n applicable, it is used for both the field width and precision. The default\n padding character is `' '` (space).\n- `Mod` is the control sequence modifier. This is one or more characters that\n change the interpretation of `Data`.\n\n The current modifiers are:\n\n - **`t`** - For Unicode translation.\n\n - **`l`** - For stopping `p` and `P` from detecting printable characters.\n\n - **`k`** - For use with `p`, `P`, `w`, and `W` to format maps in map-key\n `ordered` order (see `t:maps:iterator_order/0`).\n\n - **`K`** - Similar to `k`, for formatting maps in map-key order, but takes an\n extra argument that specifies the `t:maps:iterator_order/0`.\n\n For example:\n\n ```erlang\n > M = #{ a => 1, b => 2 }.\n #{a => 1,b => 2}\n > io:format(\"~Kp~n\", [reversed, M]).\n #{b => 2,a => 1}\n ok\n ```\n\nIf `F`, `P`, or `Pad` is a `*` character, the next argument in `Data` is used as\nthe value. For example:\n\n```erlang\n1> io:fwrite(\"~*.*.0f~n\",[9, 5, 3.14159265]).\n003.14159\nok\n```\n\nTo use a literal `*` character as `Pad`, it must be passed as an argument:\n\n```erlang\n2> io:fwrite(\"~*.*.*f~n\",[9, 5, $*, 3.14159265]).\n**3.14159\nok\n```\n\n_Available control sequences:_\n\n- **`~`** - Character `~` is written.\n\n- **`c`** - The argument is a number that is interpreted as an ASCII code. The\n precision is the number of times the character is printed and defaults to the\n field width, which in turn defaults to 1. Example:\n\n ```erlang\n 1> io:fwrite(\"|~10.5c|~-10.5c|~5c|~n\", [$a, $b, $c]).\n | aaaaa|bbbbb |ccccc|\n ok\n ```\n\n If the Unicode translation modifier (`t`) is in effect, the integer argument\n can be any number representing a valid Unicode codepoint, otherwise it is to\n be an integer less than or equal to 255, otherwise it is masked with 16#FF:\n\n ```erlang\n 2> io:fwrite(\"~tc~n\",[1024]).\n \\x{400}\n ok\n 3> io:fwrite(\"~c~n\",[1024]).\n ^@\n ok\n ```\n\n- **`f`** - The argument is a float that is written as `[-]ddd.ddd`, where the\n precision is the number of digits after the decimal point. The default\n precision is 6 and it cannot be < 1.\n\n- **`e`** - The argument is a float that is written as `[-]d.ddde+-ddd`, where\n the precision is the number of digits written. The default precision is 6 and\n it cannot be < 2.\n\n- **`g`** - The argument is a float that is written as `f`, if it is >= 0.1 and\n < 10000.0. Otherwise, it is written in the `e` format. The precision is the\n number of significant digits. It defaults to 6 and is not to be < 2. If the\n absolute value of the float does not allow it to be written in the `f` format\n with the desired number of significant digits, it is also written in the `e`\n format.\n\n- **`s`** - Prints the argument with the string syntax. The argument is, if no\n Unicode translation modifier is present, an `t:iolist/0`, a `t:binary/0`, or\n an `t:atom/0`. If the Unicode translation modifier (`t`) is in effect, the\n argument is [`unicode:chardata()`](`t:unicode:chardata/0`), meaning that\n binaries are in UTF-8. The characters are printed without quotes. The string\n is first truncated by the specified precision and then padded and justified to\n the specified field width. The default precision is the field width.\n\n This format can be used for printing any object and truncating the output so\n it fits a specified field:\n\n ```erlang\n 1> io:fwrite(\"|~10w|~n\", [{hey, hey, hey}]).\n |**********|\n ok\n 2> io:fwrite(\"|~10s|~n\", [io_lib:write({hey, hey, hey})]).\n |{hey,hey,h|\n 3> io:fwrite(\"|~-10.8s|~n\", [io_lib:write({hey, hey, hey})]).\n |{hey,hey |\n ok\n ```\n\n A list with integers > 255 is considered an error if the Unicode translation\n modifier is not specified:\n\n ```erlang\n 4> io:fwrite(\"~ts~n\",[[1024]]).\n \\x{400}\n ok\n 5> io:fwrite(\"~s~n\",[[1024]]).\n ** exception error: bad argument\n in function io:format/3\n called as io:format(<0.53.0>,\"~s~n\",[[1024]])\n ```\n\n- **`w`** - Writes data with the standard syntax. This is used to output Erlang\n terms. Atoms are printed within quotes if they contain embedded non-printable\n characters. Atom characters > 255 are escaped unless the Unicode translation\n modifier (`t`) is used. Floats are printed accurately as the shortest,\n correctly rounded string.\n\n- **`p`**{: #tilde_p } - Writes the data with standard syntax in the same way as `~w`, but\n breaks terms whose printed representation is longer than one line into many\n lines and indents each line sensibly. Left-justification is not supported. It\n also tries to detect flat lists of printable characters and output these as\n strings. For example:\n\n ```erlang\n 1> T = [{attributes,[[{id,age,1.50000},{mode,explicit},\n {typename,\"INTEGER\"}], [{id,cho},{mode,explicit},{typename,'Cho'}]]},\n {typename,'Person'},{tag,{'PRIVATE',3}},{mode,implicit}].\n ...\n 2> io:fwrite(\"~w~n\", [T]).\n [{attributes,[[{id,age,1.5},{mode,explicit},{typename,\n [73,78,84,69,71,69,82]}],[{id,cho},{mode,explicit},{typena\n me,'Cho'}]]},{typename,'Person'},{tag,{'PRIVATE',3}},{mode\n ,implicit}]\n ok\n 3> io:fwrite(\"~62p~n\", [T]).\n [{attributes,[[{id,age,1.5},\n {mode,explicit},\n {typename,\"INTEGER\"}],\n [{id,cho},{mode,explicit},{typename,'Cho'}]]},\n {typename,'Person'},\n {tag,{'PRIVATE',3}},\n {mode,implicit}]\n ok\n ```\n\n The field width specifies the maximum line length. It defaults to 80. The\n precision specifies the initial indentation of the term. It defaults to the\n number of characters printed on this line in the _same_ call to `write/1` or\n [`format/1,2,3`](`format/1`). For example, using `T` above:\n\n ```erlang\n 4> io:fwrite(\"Here T = ~62p~n\", [T]).\n Here T = [{attributes,[[{id,age,1.5},\n {mode,explicit},\n {typename,\"INTEGER\"}],\n [{id,cho},\n {mode,explicit},\n {typename,'Cho'}]]},\n {typename,'Person'},\n {tag,{'PRIVATE',3}},\n {mode,implicit}]\n ok\n ```\n\n As from Erlang/OTP 21.0, a field width of value `0` can be used for specifying\n that a line is infinitely long, which means that no line breaks are inserted.\n For example:\n\n ```erlang\n 5> io:fwrite(\"~0p~n\", [lists:seq(1, 30)]).\n [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30]\n ok\n ```\n\n When the modifier `l` is specified, no detection of printable character lists\n takes place, for example:\n\n ```erlang\n 6> S = [{a,\"a\"}, {b, \"b\"}],\n io:fwrite(\"~15p~n\", [S]).\n [{a,\"a\"},\n {b,\"b\"}]\n ok\n 7> io:fwrite(\"~15lp~n\", [S]).\n [{a,[97]},\n {b,[98]}]\n ok\n ```\n\n The Unicode translation modifier `t` specifies how to treat characters outside\n the Latin-1 range of codepoints, in atoms, strings, and binaries. For example,\n printing an atom containing a character > 255:\n\n ```erlang\n 8> io:fwrite(\"~p~n\",[list_to_atom([1024])]).\n '\\x{400}'\n ok\n 9> io:fwrite(\"~tp~n\",[list_to_atom([1024])]).\n 'Ѐ'\n ok\n ```\n\n By default, Erlang only detects lists of characters in the Latin-1 range as\n strings, but the `+pc unicode` flag can be used to change this (see\n `printable_range/0` for details). For example:\n\n ```erlang\n 10> io:fwrite(\"~p~n\",[[214]]).\n \"Ö\"\n ok\n 11> io:fwrite(\"~p~n\",[[1024]]).\n [1024]\n ok\n 12> io:fwrite(\"~tp~n\",[[1024]]).\n [1024]\n ok\n ```\n\n but if Erlang was started with `+pc unicode`:\n\n ```erlang\n 13> io:fwrite(\"~p~n\",[[1024]]).\n [1024]\n ok\n 14> io:fwrite(\"~tp~n\",[[1024]]).\n \"Ѐ\"\n ok\n ```\n\n Similarly, binaries that look like UTF-8 encoded strings are output with the\n binary string syntax if the `t` modifier is specified:\n\n ```erlang\n 15> io:fwrite(\"~p~n\", [<<208,128>>]).\n <<208,128>>\n ok\n 16> io:fwrite(\"~tp~n\", [<<208,128>>]).\n <<\"Ѐ\"/utf8>>\n ok\n 17> io:fwrite(\"~tp~n\", [<<128,128>>]).\n <<128,128>>\n ok\n ```\n\n- **`W`** - Writes data in the same way as `~w`, but takes an extra argument\n that is the maximum depth to which terms are printed. Anything below this\n depth is replaced with `...`. For example, using `T` above:\n\n ```erlang\n 8> io:fwrite(\"~W~n\", [T,9]).\n [{attributes,[[{id,age,1.5},{mode,explicit},{typename,...}],\n [{id,cho},{mode,...},{...}]]},{typename,'Person'},\n {tag,{'PRIVATE',3}},{mode,implicit}]\n ok\n ```\n\n If the maximum depth is reached, it cannot be read in the resultant output.\n Also, the `,...` form in a tuple denotes that there are more elements in the\n tuple but these are below the print depth.\n\n- **`P`** - Writes data in the same way as `~p`, but takes an extra argument\n that is the maximum depth to which terms are printed. Anything below this\n depth is replaced with `...`, for example:\n\n ```erlang\n 9> io:fwrite(\"~62P~n\", [T,9]).\n [{attributes,[[{id,age,1.5},{mode,explicit},{typename,...}],\n [{id,cho},{mode,...},{...}]]},\n {typename,'Person'},\n {tag,{'PRIVATE',3}},\n {mode,implicit}]\n ok\n ```\n\n- **`B`** - Writes an integer in base 2-36, the default base is 10. A leading\n dash is printed for negative integers.\n\n The precision field selects base, for example:\n\n ```erlang\n 1> io:fwrite(\"~.16B~n\", [31]).\n 1F\n ok\n 2> io:fwrite(\"~.2B~n\", [-19]).\n -10011\n ok\n 3> io:fwrite(\"~.36B~n\", [5*36+35]).\n 5Z\n ok\n ```\n\n- **`X`** - Like `B`, but takes an extra argument that is a prefix to insert\n before the number, but after the leading dash, if any.\n\n The prefix can be a possibly deep list of characters or an atom. Example:\n\n ```erlang\n 1> io:fwrite(\"~X~n\", [31,\"10#\"]).\n 10#31\n ok\n 2> io:fwrite(\"~.16X~n\", [-31,\"0x\"]).\n -0x1F\n ok\n ```\n\n- **`#`** - Like `B`, but prints the number with an Erlang style `#`\\-separated\n base prefix. Example:\n\n ```erlang\n 1> io:fwrite(\"~.10#~n\", [31]).\n 10#31\n ok\n 2> io:fwrite(\"~.16#~n\", [-31]).\n -16#1F\n ok\n ```\n\n- **`b`** - Like `B`, but prints lowercase letters.\n\n- **`x`** - Like `X`, but prints lowercase letters.\n\n- **`+`** - Like `#`, but prints lowercase letters.\n\n- **`n`** - Writes a new line.\n\n- **`i`** - Ignores the next term.\n\nThe function returns:\n\n- **`ok`** - The formatting succeeded.\n\nIf an error occurs, there is no output. Example:\n\n```erlang\n1> io:fwrite(\"~s ~w ~i ~w ~c ~n\",['abc def', 'abc def', {foo, 1},{foo, 1}, 65]).\nabc def 'abc def' {foo,1} A\nok\n2> io:fwrite(\"~s\", [65]).\n** exception error: bad argument\n in function io:format/3\n called as io:format(<0.53.0>,\"~s\",\"A\")\n```\n\nIn this example, an attempt was made to output the single character 65 with the\naid of the string formatting directive `\"~s\"`.","title":"io.fwrite/3","ref":"io.html#fwrite/3"},{"type":"function","doc":"","title":"io.get_chars/2","ref":"io.html#get_chars/2"},{"type":"function","doc":"Reads `Count` characters from [`IoDevice`](`t:device/0`), prompting it with `Prompt`.\n\nThe function returns:\n\n- **`Data`** - The input characters. If the I/O device supports Unicode, the\n data can represent codepoints > 255 (the `latin1` range). If the I/O server is\n set to deliver binaries, they are encoded in UTF-8 (regardless of whether the\n I/O device supports Unicode). If you want the data to be returned as a latin1\n encoded binary you should use `file:read/2` instead.\n\n- **`eof`** - End of file was encountered.\n\n- **`{error, ErrorDescription}`** - Other (rare) error condition, such as\n `{error, estale}` if reading from an NFS file system.","title":"io.get_chars/3","ref":"io.html#get_chars/3"},{"type":"function","doc":"","title":"io.get_line/1","ref":"io.html#get_line/1"},{"type":"function","doc":"Reads a line from [`IoDevice`](`t:device/0`), prompting it with `Prompt`.\n\nThe function returns:\n\n- **`Data`** - The characters in the line terminated by a line feed (or end of\n file). If the I/O device supports Unicode, the data can represent codepoints >\n 255 (the `latin1` range). If the I/O server is set to deliver binaries, they\n are encoded in UTF-8 (regardless of if the I/O device supports Unicode). If\n you want the data to be returned as a latin1 encoded binary you should use\n `file:read_line/1` instead.\n\n- **`eof`** - End of file was encountered.\n\n- **`{error, ErrorDescription}`** - Other (rare) error condition, such as\n `{error, estale}` if reading from an NFS file system.","title":"io.get_line/2","ref":"io.html#get_line/2"},{"type":"function","doc":"","title":"io.getopts/0","ref":"io.html#getopts/0"},{"type":"function","doc":"Requests all available options and their current values for a [`IoDevice`](`t:device/0`).\n\nFor example:\n\n```erlang\n1> {ok,F} = file:open(\"/dev/null\",[read]).\n{ok,<0.42.0>}\n2> io:getopts(F).\n[{binary,false},{encoding,latin1}]\n```\n\nHere the file I/O server returns all available options for a file, which are the\nexpected ones, `encoding` and `binary`. However, the standard shell has some\nmore options:\n\n```erlang\n3> io:getopts().\n[{expand_fun,#Fun },\n {echo,true},\n {binary,false},\n {encoding,unicode},\n {terminal,true},\n {stdout,true},\n {stderr,true},\n {stdin,true}]\n```\n\nThis example is, as can be seen, run in an environment where the terminal\nsupports Unicode input and output.\n\nThe `stdin`, `stdout` and `stderr` options are read only and indicates\nwhether the stream is a terminal or not. When it is a terminal, most systems that\nErlang runs on allows the use of [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code)\nto control what the terminal inputs or outputs.\n\n`terminal` is an alias for `stdout`.\n\nSee `setopts/2` for a description of the other options.","title":"io.getopts/1","ref":"io.html#getopts/1"},{"type":"function","doc":"","title":"io.nl/0","ref":"io.html#nl/0"},{"type":"function","doc":"Writes new line to the standard output (`IoDevice`).","title":"io.nl/1","ref":"io.html#nl/1"},{"type":"function","doc":"","title":"io.parse_erl_exprs/1","ref":"io.html#parse_erl_exprs/1"},{"type":"function","doc":"","title":"io.parse_erl_exprs/2","ref":"io.html#parse_erl_exprs/2"},{"type":"function","doc":"","title":"io.parse_erl_exprs/3","ref":"io.html#parse_erl_exprs/3"},{"type":"function","doc":"Reads data from [`IoDevice`](`t:device/0`), prompting it with `Prompt`.\n\nStarts reading at location `StartLocation`. Argument `Options` is passed\non as argument `Options` of function `erl_scan:tokens/4`. The data is tokenized\nand parsed as if it was a sequence of Erlang expressions until a final dot (`.`)\nis reached.\n\nThe function returns:\n\n- **`{ok, ExprList, EndLocation}`** - The parsing was successful.\n\n- **`{eof, EndLocation}`** - End of file was encountered by the tokenizer.\n\n- **`eof`** - End of file was encountered by the I/O server.\n\n- **`{error, ErrorInfo, ErrorLocation}`** - An error occurred while tokenizing\n or parsing.\n\n- **`{error, ErrorDescription}`** - Other (rare) error condition, such as\n `{error, estale}` if reading from an NFS file system.\n\nExample:\n\n```erlang\n25> io:parse_erl_exprs('enter>').\nenter>abc(), \"hey\".\n{ok, [{call,1,{atom,1,abc},[]},{string,1,\"hey\"}],2}\n26> io:parse_erl_exprs('enter>').\nenter>abc(\"hey\".\n{error,{1,erl_parse,[\"syntax error before: \",[\"'.'\"]]},2}\n```","title":"io.parse_erl_exprs/4","ref":"io.html#parse_erl_exprs/4"},{"type":"function","doc":"","title":"io.parse_erl_form/1","ref":"io.html#parse_erl_form/1"},{"type":"function","doc":"","title":"io.parse_erl_form/2","ref":"io.html#parse_erl_form/2"},{"type":"function","doc":"","title":"io.parse_erl_form/3","ref":"io.html#parse_erl_form/3"},{"type":"function","doc":"Reads data from [`IoDevice`](`t:device/0`), prompting it with `Prompt`.\n\nStarts reading at location `StartLocation`. Argument `Options` is passed\non as argument `Options` of function `erl_scan:tokens/4`. The data is tokenized\nand parsed as if it was an Erlang form (one of the valid Erlang expressions in\nan Erlang source file) until a final dot (`.`) is reached.\n\nThe function returns:\n\n- **`{ok, AbsForm, EndLocation}`** - The parsing was successful.\n\n- **`{eof, EndLocation}`** - End of file was encountered by the tokenizer.\n\n- **`eof`** - End of file was encountered by the I/O server.\n\n- **`{error, ErrorInfo, ErrorLocation}`** - An error occurred while tokenizing\n or parsing.\n\n- **`{error, ErrorDescription}`** - Other (rare) error condition, such as\n `{error, estale}` if reading from an NFS file system.","title":"io.parse_erl_form/4","ref":"io.html#parse_erl_form/4"},{"type":"function","doc":"Returns the user-requested range of printable Unicode characters.\n\nThe user can request a range of characters that are to be considered printable\nin heuristic detection of strings by the shell and by the formatting functions.\nThis is done by supplying `+pc ` when starting Erlang.\n\nThe only valid values for ` ` are `latin1` and `unicode`. `latin1` means\nthat only code points < 256 (except control characters, and so on) are\nconsidered printable. `unicode` means that all printable characters in all\nUnicode character ranges are considered printable by the I/O functions.\n\nBy default, Erlang is started so that only the `latin1` range of characters\nindicate that a list of integers is a string.\n\nThe simplest way to use the setting is to call `io_lib:printable_list/1`, which\nuses the return value of this function to decide if a list is a string of\nprintable characters.\n\n> #### Note {: .info }\n>\n> In a future release, this function may return more values and ranges. To avoid\n> compatibility problems, it is recommended to use function\n> `io_lib:printable_list/1`.","title":"io.printable_range/0","ref":"io.html#printable_range/0"},{"type":"function","doc":"","title":"io.put_chars/1","ref":"io.html#put_chars/1"},{"type":"function","doc":"Writes the characters of `CharData` to the [`IoDevice`](`t:device/0`).\n\nIf you want to write latin1 encoded bytes to the [`IoDevice`](`t:device/0`) you should use\n`file:write/2` instead.","title":"io.put_chars/2","ref":"io.html#put_chars/2"},{"type":"function","doc":"","title":"io.read/1","ref":"io.html#read/1"},{"type":"function","doc":"Reads a term `Term` from the standard input (`IoDevice`), prompting it with\n`Prompt`.\n\nThe function returns:\n\n- **`{ok, Term}`** - The parsing was successful.\n\n- **`eof`** - End of file was encountered.\n\n- **`{error, ErrorInfo}`** - The parsing failed.\n\n- **`{error, ErrorDescription}`** - Other (rare) error condition, such as\n `{error, estale}` if reading from an NFS file system.","title":"io.read/2","ref":"io.html#read/2"},{"type":"function","doc":"","title":"io.read/3","ref":"io.html#read/3"},{"type":"function","doc":"Reads a term `Term` from [`IoDevice`](`t:device/0`), prompting it with `Prompt`.\n\nReading starts at location `StartLocation`. Argument `Options` is passed on as\nargument `Options` of function `erl_scan:tokens/4`.\n\nThe function returns:\n\n- **`{ok, Term, EndLocation}`** - The parsing was successful.\n\n- **`{eof, EndLocation}`** - End of file was encountered.\n\n- **`{error, ErrorInfo, ErrorLocation}`** - The parsing failed.\n\n- **`{error, ErrorDescription}`** - Other (rare) error condition, such as\n `{error, estale}` if reading from an NFS file system.","title":"io.read/4","ref":"io.html#read/4"},{"type":"function","doc":"","title":"io.rows/0","ref":"io.html#rows/0"},{"type":"function","doc":"Retrieves the number of rows of [`IoDevice`](`t:device/0`) (that is, the height of a terminal).\n\nThe function only succeeds for terminal devices, for all other I/O devices the\nfunction returns `{error, enotsup}`.","title":"io.rows/1","ref":"io.html#rows/1"},{"type":"function","doc":"","title":"io.scan_erl_exprs/1","ref":"io.html#scan_erl_exprs/1"},{"type":"function","doc":"","title":"io.scan_erl_exprs/2","ref":"io.html#scan_erl_exprs/2"},{"type":"function","doc":"","title":"io.scan_erl_exprs/3","ref":"io.html#scan_erl_exprs/3"},{"type":"function","doc":"Reads data from [`IoDevice`](`t:device/0`), prompting it with `Prompt`.\n\nReading starts at location `StartLocation`. Argument `Options` is passed on as\nargument `Options` of function `erl_scan:tokens/4`. The data is tokenized\nas if it were a sequence of Erlang expressions until a final dot (`.`) is\nreached. This token is also returned.\n\nThe function returns:\n\n- **`{ok, Tokens, EndLocation}`** - The tokenization succeeded.\n\n- **`{eof, EndLocation}`** - End of file was encountered by the tokenizer.\n\n- **`eof`** - End of file was encountered by the I/O server.\n\n- **`{error, ErrorInfo, ErrorLocation}`** - An error occurred while tokenizing.\n\n- **`{error, ErrorDescription}`** - Other (rare) error condition, such as\n `{error, estale}` if reading from an NFS file system.\n\n_Example:_\n\n```erlang\n23> io:scan_erl_exprs('enter>').\nenter>abc(), \"hey\".\n{ok,[{atom,1,abc},{'(',1},{')',1},{',',1},{string,1,\"hey\"},{dot,1}],2}\n24> io:scan_erl_exprs('enter>').\nenter>1.0er.\n{error,{1,erl_scan,{illegal,float}},2}\n```","title":"io.scan_erl_exprs/4","ref":"io.html#scan_erl_exprs/4"},{"type":"function","doc":"","title":"io.scan_erl_form/1","ref":"io.html#scan_erl_form/1"},{"type":"function","doc":"","title":"io.scan_erl_form/2","ref":"io.html#scan_erl_form/2"},{"type":"function","doc":"","title":"io.scan_erl_form/3","ref":"io.html#scan_erl_form/3"},{"type":"function","doc":"Reads data from [`IoDevice`](`t:device/0`), prompting it with `Prompt`.\n\nStarts reading at location `StartLocation` (`1`). Argument `Options` is passed\non as argument `Options` of function `erl_scan:tokens/4`. The data is tokenized\nas if it was an Erlang form (one of the valid Erlang expressions in an Erlang\nsource file) until a final dot (`.`) is reached. This last token is also\nreturned.\n\nThe return values are the same as for [`scan_erl_exprs/4`](`scan_erl_exprs/4`).","title":"io.scan_erl_form/4","ref":"io.html#scan_erl_form/4"},{"type":"function","doc":"","title":"io.setopts/1","ref":"io.html#setopts/1"},{"type":"function","doc":"Set options for [`IoDevice`](`t:device/0`). Possible options and values vary\ndepending on the I/O device.\n\nFor a list of supported options and their current values on a specific I/O\ndevice, use function `getopts/1`.\n\nThe options and values supported by the OTP I/O devices are as follows:\n\n- **`binary`, `list`, or `{binary, boolean()}`** - If set in binary mode\n (`binary` or `{binary, true}`), the I/O server sends binary data (encoded in\n UTF-8) as answers to the `get_line`, `get_chars`, and, if possible,\n `get_until` requests (for details, see section\n [The Erlang I/O Protocol](io_protocol.md)) in the User's Guide). The immediate\n effect is that [`get_chars/2,3`](`get_chars/2`) and\n [`get_line/1,2`](`get_line/1`) return UTF-8 binaries instead of lists of\n characters for the affected I/O device.\n\n By default, all I/O devices in OTP are set in `list` mode. However, the I/O\n functions can handle any of these modes and so should other, user-written,\n modules behaving as clients to I/O servers.\n\n This option is supported by the `t:standard_io/0`, `t:user/0` and `t:file:io_server/0`\n I/O servers.\n\n- **`{echo, boolean()}`** - Denotes if the terminal is to echo input. Only\n supported for the standard shell I/O server (`group.erl`)\n\n- **`{expand_fun, expand_fun()}`** - Provides a function for tab-completion\n (expansion) like the Erlang shell. This function is called when the user\n presses the _Tab_ key. The expansion is active when calling line-reading\n functions, such as [`get_line/1,2`](`get_line/1`).\n\n The function is called with the current line, up to the cursor, as a reversed\n string. It is to return a three-tuple: `{yes|no, string(), list()}`. The first\n element gives a beep if `no`, otherwise the expansion is silent; the second is\n a string that will be entered at the cursor position; the third is a list of\n possible expansions. If this list is not empty, it is printed below the\n current input line. The list of possible expansions can be formatted in\n different ways to make more advanced expansion suggestions more readable to\n the user, see `edlin_expand:expand/2` for documentation of that.\n\n Trivial example (beep on anything except empty line, which is expanded to\n `\"quit\"`):\n\n ```erlang\n fun(\"\") -> {yes, \"quit\", []};\n (_) -> {no, \"\", [\"quit\"]} end\n ```\n\n This option is only supported by the standard shell (`group.erl`).\n\n- **`{line_history, true | false}`** - Specifies if `get_line` and `get_until`\n I/O requests should be saved in the `m:shell` history buffer.\n\n This option is only supported by the standard shell (`group.erl`).\n\n- **`{encoding, latin1 | unicode}`** - Specifies how characters are input or\n output from or to the I/O device, implying that, for example, a terminal is\n set to handle Unicode input and output or a file is set to handle UTF-8 data\n encoding.\n\n The option _does not_ affect how data is returned from the I/O functions or\n how it is sent in the I/O protocol, it only affects how the I/O device is to\n handle Unicode characters to the \"physical\" device.\n\n The standard shell is set for `unicode` or `latin1` encoding when the system\n is started. The encoding is set with the help of the `LANG` or `LC_CTYPE`\n environment variables on Unix-like system or by other means on other systems.\n So, the user can input Unicode characters and the I/O device is in\n `{encoding, unicode}` mode if the I/O device supports it. The mode can be\n changed, if the assumption of the runtime system is wrong, by setting this\n option.\n\n > #### Note {: .info }\n >\n > Prior to OTP 26.0, when Erlang was started with the `-oldshell` or\n > `-noshell` flags (for example, in an `escript`), the default encoding for\n > [`standard_io`](`t:standard_io/0`) was set to `latin1`, meaning that any\n > characters > codepoint 255 were escaped and that input was expected to be\n > plain 8-bit ISO Latin-1. As of OTP 26.0, [`standard_io`](`t:standard_io/0`)\n > always defaults to `unicode` if its supported, otherwise `latin1`.\n >\n > If you want to send raw bytes on [`standard_io`](`t:standard_io/0`), you now\n > always need to explicitly set the encoding to `latin1`; otherwise, code\n > points 128-255 will be converted to UTF-8. This is best done by setting the\n > kernel configuration parameter\n > [standard_io_encoding](`e:kernel:kernel_app.md#standard_io_encoding`) to\n > `latin1`.\n\n Files can also be set in `{encoding, unicode}`, meaning that data is written\n and read as UTF-8. More encodings are possible for files, see below.\n\n `{encoding, unicode | latin1}` is supported by both the standard shell\n (`group.erl` including `werl` on Windows), the 'oldshell' (`user.erl`), and\n the file I/O servers.\n\n- **`{encoding, utf8 | utf16 | utf32 | {utf16,big} | {utf16,little} | {utf32,big} | {utf32,little}}`** -\n For disk files, the encoding can be set to various UTF variants. This has the\n effect that data is expected to be read as the specified encoding from the\n file, and the data is written in the specified encoding to the disk file.\n\n `{encoding, utf8}` has the same effect as `{encoding, unicode}` on files.\n\n The extended encodings are only supported on disk files (opened by function\n `file:open/2`).","title":"io.setopts/2","ref":"io.html#setopts/2"},{"type":"function","doc":"","title":"io.write/1","ref":"io.html#write/1"},{"type":"function","doc":"Writes term `Term` to [`IoDevice`](`t:device/0`).","title":"io.write/2","ref":"io.html#write/2"},{"type":"type","doc":"An I/O device, either `t:standard_io/0`, `t:standard_error/0`, `t:user/0`, a `t:file:io_server/0`,\na registered name, or any pid handling I/O protocols.","title":"io.device/0","ref":"io.html#t:device/0"},{"type":"type","doc":"","title":"io.encoding/0","ref":"io.html#t:encoding/0"},{"type":"type","doc":"","title":"io.expand_fun/0","ref":"io.html#t:expand_fun/0"},{"type":"type","doc":"","title":"io.format/0","ref":"io.html#t:format/0"},{"type":"type","doc":"","title":"io.getopt/0","ref":"io.html#t:getopt/0"},{"type":"type","doc":"","title":"io.option/0","ref":"io.html#t:option/0"},{"type":"type","doc":"","title":"io.parse_form_ret/0","ref":"io.html#t:parse_form_ret/0"},{"type":"type","doc":"","title":"io.parse_ret/0","ref":"io.html#t:parse_ret/0"},{"type":"type","doc":"","title":"io.prompt/0","ref":"io.html#t:prompt/0"},{"type":"type","doc":"What the I/O server sends when there is no data.","title":"io.server_no_data/0","ref":"io.html#t:server_no_data/0"},{"type":"type","doc":"","title":"io.setopt/0","ref":"io.html#t:setopt/0"},{"type":"type","doc":"The I/O device `standard_error` can be used to direct output to whatever the\ncurrent operating system considers a suitable I/O device for error output. This\ncan be useful when standard output is redirected.\n\nExample on a Unix-like operating system:\n\n```text\n$ erl -noinput -eval 'io:format(standard_error,\"Error: ~s~n\",[\"error 11\"]),'\\\n'init:stop().' > /dev/null\nError: error 11\n```","title":"io.standard_error/0","ref":"io.html#t:standard_error/0"},{"type":"type","doc":"The default standard I/O device assigned to a process. This device is used when\nno `IoDevice` argument is specified in the function calls in this module.\n\nIt is sometimes desirable to use an explicit `IoDevice` argument that\nrefers to the default I/O device. This is the case with functions that can\naccess either a file or the default I/O device. The atom `standard_io` has this\nspecial meaning. The following example illustrates this:\n\n```erlang\n27> io:read('enter>').\nenter>foo.\n{ok,foo}\n28> io:read(standard_io, 'enter>').\nenter>bar.\n{ok,bar}\n```\n\nBy default all I/O sent to `standard_io` will end up in the [`user`](`t:user/0`)\nI/O device of the node that spawned the calling process.\n\n`standard_io` is an alias for [`group_leader/0`](`erlang:group_leader/0`), so in\norder to change where the default input/output requests are sent you can change\nthe group leader of the current process using\n[`group_leader(NewGroupLeader, self())`](`erlang:group_leader/2`).","title":"io.standard_io/0","ref":"io.html#t:standard_io/0"},{"type":"type","doc":"An I/O device that can be used to interact with the node local `stdout` and\n`stdin`. This can be either a terminal, a pipe, a file, or a combination.\n\nUse `getopts/1` to get more information about the I/O device.\n\nSee [The Interactive Shell](unicode_usage.md#the-interactive-shell) and\n[Escripts and non-interactive I/O](unicode_usage.md#escripts-and-non-interactive-i-o)\nin the Using Unicode In Erlang User's Guide for details on how Unicode is\nhandled by `user`.","title":"io.user/0","ref":"io.html#t:user/0"},{"type":"module","doc":"I/O library functions.\n\nThis module contains functions for converting to and from strings (lists of\ncharacters). They are used for implementing the functions in the `m:io` module.\nThere is no guarantee that the character lists returned from some of the\nfunctions are flat, they can be deep lists. Function `lists:flatten/1` can be\nused for flattening deep lists.","title":"io_lib","ref":"io_lib.html"},{"type":"function","doc":"For details, see `scan_format/2`.","title":"io_lib.build_text/1","ref":"io_lib.html#build_text/1"},{"type":"function","doc":"Returns `true` if `Term` is a flat list of characters in the Unicode range,\notherwise `false`.","title":"io_lib.char_list/1","ref":"io_lib.html#char_list/1"},{"type":"function","doc":"Returns `true` if `Term` is a, possibly deep, list of characters in the Unicode\nrange, otherwise `false`.","title":"io_lib.deep_char_list/1","ref":"io_lib.html#deep_char_list/1"},{"type":"function","doc":"Returns `true` if `Term` is a, possibly deep, list of characters in the ISO\nLatin-1 range, otherwise `false`.","title":"io_lib.deep_latin1_char_list/1","ref":"io_lib.html#deep_latin1_char_list/1"},{"type":"function","doc":"","title":"io_lib.format/2","ref":"io_lib.html#format/2"},{"type":"function","doc":"","title":"io_lib.format/3","ref":"io_lib.html#format/3"},{"type":"function","doc":"Tries to read `String` in accordance with the control sequences in `Format`.\n\nFor a detailed description of the available formatting options, see `io:fread/3`.\nIt is assumed that `String` contains whole lines.\n\nThe function returns:\n\n- **`{ok, InputList, LeftOverChars}`** - The string was read. `InputList` is the\n list of successfully matched and read items, and `LeftOverChars` are the input\n characters not used.\n\n- **`{more, RestFormat, Nchars, InputStack}`** - The string was read, but more\n input is needed to complete the original format string. `RestFormat` is the\n remaining format string, `Nchars` is the number of characters scanned, and\n `InputStack` is the reversed list of inputs matched up to that point.\n\n- **`{error, What}`** - The read operation failed and parameter `What` gives a\n hint about the error.\n\n_Example:_\n\n```erlang\n3> io_lib:fread(\"~f~f~f\", \"15.6 17.3e-6 24.5\").\n{ok,[15.6,1.73e-5,24.5],[]}\n```","title":"io_lib.fread/2","ref":"io_lib.html#fread/2"},{"type":"function","doc":"This is the re-entrant formatted reader. The continuation of the first call to\nthe functions must be `[]`.\n\nFor a complete description of how the re-entrant input scheme works,\nsee Armstrong, Virding, Williams: 'Concurrent Programming in\nErlang', Chapter 13.\n\nThe function returns:\n\n- **`{done, Result, LeftOverChars}`** - The input is complete. The result is one\n of the following:\n\n - **`{ok, InputList}`** - The string was read. `InputList` is the list of\n successfully matched and read items, and `LeftOverChars` are the remaining\n characters.\n\n - **`eof`** - End of file was encountered. `LeftOverChars` are the input\n characters not used.\n\n - **`{error, What}`** - An error occurred and parameter `What` gives a hint\n about the error.\n\n- **`{more, Continuation}`** - More data is required to build a term.\n `Continuation` must be passed to [`fread/3`](`fread/3`) when more data becomes\n available.","title":"io_lib.fread/3","ref":"io_lib.html#fread/3"},{"type":"function","doc":"Returns a character list that represents `Data` formatted in accordance with\n`Format`.\n\nFor a detailed description of the available formatting options, see\n[`io:fwrite/1,2,3`](`io:fwrite/1`). If the format string or argument list\ncontains an error, a fault is generated.\n\nIf and only if the Unicode translation modifier is used in the format string\n(that is, `~ts` or `~tc`), the resulting list can contain characters beyond the\nISO Latin-1 character range (that is, numbers > 255). If so, the result is still\nan ordinary Erlang `t:string/0`, and can well be used in any context where\nUnicode data is allowed.","title":"io_lib.fwrite/2","ref":"io_lib.html#fwrite/2"},{"type":"function","doc":"Returns a character list that represents `Data` formatted in accordance with\n`Format` in the same way as `fwrite/2` and `format/2`, but takes an extra\nargument, a list of options.\n\nValid option:\n\n- **`{chars_limit, CharsLimit}`** - A soft limit on the number of characters\n returned. When the number of characters is reached, remaining structures are\n replaced by \"`...`\". `CharsLimit` defaults to -1, which means no limit on the\n number of characters returned.","title":"io_lib.fwrite/3","ref":"io_lib.html#fwrite/3"},{"type":"function","doc":"Returns the indentation if `String` has been printed, starting at `StartIndent`.","title":"io_lib.indentation/2","ref":"io_lib.html#indentation/2"},{"type":"function","doc":"Returns `true` if `Term` is a flat list of characters in the ISO Latin-1 range,\notherwise `false`.","title":"io_lib.latin1_char_list/1","ref":"io_lib.html#latin1_char_list/1"},{"type":"function","doc":"Returns a character list that represents a new line character.","title":"io_lib.nl/0","ref":"io_lib.html#nl/0"},{"type":"function","doc":"","title":"io_lib.print/1","ref":"io_lib.html#print/1"},{"type":"function","doc":"Returns a list of characters that represents `Term`, but breaks representations\nlonger than one line into many lines and indents each line sensibly.\n\nAlso tries to detect and output lists of printable characters as strings.\n\n- `Column` is the starting column; defaults to 1.\n- `LineLength` is the maximum line length; defaults to 80.\n- `Depth` is the maximum print depth; defaults to -1, which means no limitation.","title":"io_lib.print/4","ref":"io_lib.html#print/4"},{"type":"function","doc":"Returns `true` if `Term` is a flat list of printable ISO Latin-1 characters,\notherwise `false`.","title":"io_lib.printable_latin1_list/1","ref":"io_lib.html#printable_latin1_list/1"},{"type":"function","doc":"Returns `true` if `Term` is a flat list of printable characters, otherwise\n`false`.\n\nWhat is a printable character in this case is determined by startup flag `+pc`\nto the Erlang VM; see `io:printable_range/0` and\n[`erl(1)`](`e:erts:erl_cmd.md`).","title":"io_lib.printable_list/1","ref":"io_lib.html#printable_list/1"},{"type":"function","doc":"Returns `true` if `Term` is a flat list of printable Unicode characters,\notherwise `false`.","title":"io_lib.printable_unicode_list/1","ref":"io_lib.html#printable_unicode_list/1"},{"type":"function","doc":"Returns a list corresponding to the specified format string, where control\nsequences have been replaced with corresponding tuples. This list can be passed\nto:\n\n- `build_text/1` to have the same effect as [`format(Format, Args)`](`format/2`)\n- `unscan_format/1` to get the corresponding pair of `Format` and `Args` (with\n every `*` and corresponding argument expanded to numeric values)\n\nA typical use of this function is to replace unbounded-size control sequences\nlike `~w` and `~p` with the depth-limited variants `~W` and `~P` before\nformatting to text in, for example, a logger.","title":"io_lib.scan_format/2","ref":"io_lib.html#scan_format/2"},{"type":"function","doc":"For details, see `scan_format/2`.","title":"io_lib.unscan_format/1","ref":"io_lib.html#unscan_format/1"},{"type":"function","doc":"","title":"io_lib.write/1","ref":"io_lib.html#write/1"},{"type":"function","doc":"Returns a character list that represents `Term`. Option `Depth` controls the\ndepth of the structures written.\n\nWhen the specified depth is reached, everything below this level is replaced by\n\"`...`\".\n\n`Depth` defaults to -1, which means no limitation. Option `CharsLimit` puts a\nsoft limit on the number of characters returned. When the number of characters is\nreached, remaining structures are replaced by \"`...`\". `CharsLimit` defaults to -1,\nwhich means no limit on the number of characters returned.\n\n_Example:_\n\n```erlang\n1> lists:flatten(io_lib:write({1,[2],[3],[4,5],6,7,8,9})).\n\"{1,[2],[3],[4,5],6,7,8,9}\"\n2> lists:flatten(io_lib:write({1,[2],[3],[4,5],6,7,8,9}, 5)).\n\"{1,[2],[3],[...],...}\"\n3> lists:flatten(io_lib:write({[1,2,3],[4,5],6,7,8,9}, [{chars_limit,20}])).\n\"{[1,2|...],[4|...],...}\"\n```","title":"io_lib.write/2","ref":"io_lib.html#write/2"},{"type":"function","doc":"Returns the list of characters needed to print atom `Atom`.","title":"io_lib.write_atom/1","ref":"io_lib.html#write_atom/1"},{"type":"function","doc":"Returns the list of characters needed to print atom `Atom`. Non-Latin-1\ncharacters are escaped.","title":"io_lib.write_atom_as_latin1/1","ref":"io_lib.html#write_atom_as_latin1/1"},{"type":"function","doc":"Returns the list of characters needed to print a character constant in the\nUnicode character set.","title":"io_lib.write_char/1","ref":"io_lib.html#write_char/1"},{"type":"function","doc":"Returns the list of characters needed to print a character constant in the\nUnicode character set. Non-Latin-1 characters are escaped.","title":"io_lib.write_char_as_latin1/1","ref":"io_lib.html#write_char_as_latin1/1"},{"type":"function","doc":"Returns the list of characters needed to print a character constant in the ISO\nLatin-1 character set.","title":"io_lib.write_latin1_char/1","ref":"io_lib.html#write_latin1_char/1"},{"type":"function","doc":"Returns the list of characters needed to print `Latin1String` as a string.","title":"io_lib.write_latin1_string/1","ref":"io_lib.html#write_latin1_string/1"},{"type":"function","doc":"Returns the list of characters needed to print `String` as a string.","title":"io_lib.write_string/1","ref":"io_lib.html#write_string/1"},{"type":"function","doc":"Returns the list of characters needed to print `String` as a string. Non-Latin-1\ncharacters are escaped.","title":"io_lib.write_string_as_latin1/1","ref":"io_lib.html#write_string_as_latin1/1"},{"type":"type","doc":"An possibly deep list containing only `t:char/0`s.","title":"io_lib.chars/0","ref":"io_lib.html#t:chars/0"},{"type":"type","doc":"","title":"io_lib.chars_limit/0","ref":"io_lib.html#t:chars_limit/0"},{"type":"opaque","doc":"A continuation as returned by `fread/3`.","title":"io_lib.continuation/0","ref":"io_lib.html#t:continuation/0"},{"type":"type","doc":"","title":"io_lib.depth/0","ref":"io_lib.html#t:depth/0"},{"type":"type","doc":"A map describing the contents of a format string.\n\n- `control_char` is the type of control sequence: `$P`, `$w`, and so on.\n- `args` is a list of the arguments used by the control sequence, or an empty\n list if the control sequence does not take any arguments.\n- `width` is the field width.\n- `adjust` is the adjustment.\n- `precision` is the precision of the printed argument.\n- `pad_char` is the padding character.\n- `encoding` is set to `true` if translation modifier `t` is present.\n- `strings` is set to `false` if modifier `l` is present.\n- `maps_order` is set to `undefined` by default, `ordered` if modifier `k` is\n present, or `reversed` or `CmpFun` if modifier `K` is present.","title":"io_lib.format_spec/0","ref":"io_lib.html#t:format_spec/0"},{"type":"type","doc":"","title":"io_lib.fread_error/0","ref":"io_lib.html#t:fread_error/0"},{"type":"type","doc":"","title":"io_lib.fread_item/0","ref":"io_lib.html#t:fread_item/0"},{"type":"type","doc":"","title":"io_lib.latin1_string/0","ref":"io_lib.html#t:latin1_string/0"},{"type":"module","doc":"This module contains regular expression matching functions for strings and\nbinaries.\n\nThe [regular expression](`m:re#module-perl-like-regular-expression-syntax`) syntax and\nsemantics resemble that of Perl.\n\nThe matching algorithms of the library are based on the PCRE library, but not\nall of the PCRE library is interfaced and some parts of the library go beyond\nwhat PCRE offers. Currently PCRE version 8.40 (release date 2017-01-11) is used.\nThe sections of the PCRE documentation that are relevant to this module are\nincluded here.\n\n> #### Note {: .info }\n>\n> The Erlang literal syntax for strings uses the `\\\\` (backslash) character as\n> an escape code. You need to escape backslashes in literal strings, both in\n> your code and in the shell, with an extra backslash, that is, `\"\\\\\\\\\"` or\n> `<<\"\\\\\\\\\">>`.\n>\n> Since Erlang/OTP 27 you can use [verbatim sigils](`e:system:data_types.md#sigil`)\n> to write literal strings. The example above would be written as `~S\"\\\"` or `~B\"\\\"`.","title":"re","ref":"re.html"},{"type":"module","doc":"The following sections contain reference material for the regular expressions\nused by this module. The information is based on the PCRE documentation, with\nchanges where this module behaves differently to the PCRE library.","title":"Perl-Like Regular Expression Syntax - re","ref":"re.html#module-perl-like-regular-expression-syntax"},{"type":"module","doc":"The syntax and semantics of the regular expressions supported by PCRE are\ndescribed in detail in the following sections. Perl's regular expressions are\ndescribed in its own documentation, and regular expressions in general are\ncovered in many books, some with copious examples. Jeffrey Friedl's \"Mastering\nRegular Expressions\", published by O'Reilly, covers regular expressions in great\ndetail. This description of the PCRE regular expressions is intended as\nreference material.\n\nThe reference material is divided into the following sections:\n\n- [Special Start-of-Pattern Items](`m:re#sect1`)\n- [Characters and Metacharacters](`m:re#sect2`)\n- [Backslash](`m:re#sect3`)\n- [Circumflex and Dollar](`m:re#sect4`)\n- [Full Stop (Period, Dot) and \\\\N](`m:re#sect5`)\n- [Matching a Single Data Unit](`m:re#sect6`)\n- [Square Brackets and Character Classes](`m:re#sect7`)\n- [Posix Character Classes](`m:re#sect8`)\n- [Vertical Bar](`m:re#sect9`)\n- [Internal Option Setting](`m:re#sect10`)\n- [Subpatterns](`m:re#sect11`)\n- [Duplicate Subpattern Numbers](`m:re#sect12`)\n- [Named Subpatterns](`m:re#sect13`)\n- [Repetition](`m:re#sect14`)\n- [Atomic Grouping and Possessive Quantifiers](`m:re#sect15`)\n- [Back References](`m:re#sect16`)\n- [Assertions](`m:re#sect17`)\n- [Conditional Subpatterns](`m:re#sect18`)\n- [Comments](`m:re#sect19`)\n- [Recursive Patterns](`m:re#sect20`)\n- [Subpatterns as Subroutines](`m:re#sect21`)\n- [Oniguruma Subroutine Syntax](`m:re#sect22`)\n- [Backtracking Control](`m:re#sect23`)\n\n[](){: #sect1 }","title":"PCRE Regular Expression Details - re","ref":"re.html#module-pcre-regular-expression-details"},{"type":"module","doc":"Some options that can be passed to `compile/2` can also be set by special items\nat the start of a pattern. These are not Perl-compatible, but are provided to\nmake these options accessible to pattern writers who are not able to change the\nprogram that processes the pattern. Any number of these items can appear, but\nthey must all be together right at the start of the pattern string, and the\nletters must be in upper case.\n\n_UTF Support_\n\nUnicode support is basically UTF-8 based. To use Unicode characters, you either\ncall `compile/2` or `run/3` with option `unicode`, or the pattern must start\nwith one of these special sequences:\n\n```text\n(*UTF8)\n(*UTF)\n```\n\nBoth options give the same effect, the input string is interpreted as UTF-8.\nNotice that with these instructions, the automatic conversion of lists to UTF-8\nis not performed by the `re` functions. Therefore, using these sequences is not\nrecommended. Add option `unicode` when running `compile/2` instead.\n\nSome applications that allow their users to supply patterns can wish to restrict\nthem to non-UTF data for security reasons. If option `never_utf` is set at\ncompile time, (\\*UTF), and so on, are not allowed, and their appearance causes\nan error.\n\n_Unicode Property Support_\n\nThe following is another special sequence that can appear at the start of a\npattern:\n\n```text\n(*UCP)\n```\n\nThis has the same effect as setting option `ucp`: it causes sequences such as\n`\\d` and `\\w` to use Unicode properties to determine character types, instead of\nrecognizing only characters with codes < 256 through a lookup table.\n\n_Disabling Startup Optimizations_\n\nIf a pattern starts with `(*NO_START_OPT)`, it has the same effect as setting\noption `no_start_optimize` at compile time.\n\n_Newline Conventions_\n\n[](){: #newline_conventions }\n\nPCRE supports five conventions for indicating line breaks in strings: a single\nCR (carriage return) character, a single LF (line feed) character, the\ntwo-character sequence CRLF, any of the three preceding, and any Unicode newline\nsequence.\n\nA newline convention can also be specified by starting a pattern string with one\nof the following five sequences:\n\n- **(\\*CR)** - Carriage return\n\n- **(\\*LF)** - Line feed\n\n- **(\\*CRLF)** - >Carriage return followed by line feed\n\n- **(\\*ANYCRLF)** - Any of the three above\n\n- **(\\*ANY)** - All Unicode newline sequences\n\nThese override the default and the options specified to `compile/2`. For\nexample, the following pattern changes the convention to CR:\n\n```text\n(*CR)a.b\n```\n\nThis pattern matches `a\\nb`, as LF is no longer a newline. If more than one of\nthem is present, the last one is used.\n\nThe newline convention affects where the circumflex and dollar assertions are\ntrue. It also affects the interpretation of the dot metacharacter when `dotall`\nis not set, and the behavior of `\\N`. However, it does not affect what the `\\R`\nescape sequence matches. By default, this is any Unicode newline sequence, for\nPerl compatibility. However, this can be changed; see the description of `\\R` in\nsection [Newline Sequences](`m:re#newline_sequences`). A change of the `\\R`\nsetting can be combined with a change of the newline convention.\n\n_Setting Match and Recursion Limits_\n\nThe caller of `run/3` can set a limit on the number of times the internal\nmatch() function is called and on the maximum depth of recursive calls. These\nfacilities are provided to catch runaway matches that are provoked by patterns\nwith huge matching trees (a typical example is a pattern with nested unlimited\nrepeats) and to avoid running out of system stack by too much recursion. When\none of these limits is reached, `pcre_exec()` gives an error return. The limits\ncan also be set by items at the start of the pattern of the following forms:\n\n```text\n(*LIMIT_MATCH=d)\n(*LIMIT_RECURSION=d)\n```\n\nHere d is any number of decimal digits. However, the value of the setting must\nbe less than the value set by the caller of [`run/3`](`run/3`) for it to have\nany effect. That is, the pattern writer can lower the limit set by the\nprogrammer, but not raise it. If there is more than one setting of one of these\nlimits, the lower value is used.\n\nThe default value for both the limits is 10,000,000 in the Erlang VM. Notice\nthat the recursion limit does not affect the stack depth of the VM, as PCRE for\nErlang is compiled in such a way that the match function never does recursion on\nthe C stack.\n\nNote that `LIMIT_MATCH` and `LIMIT_RECURSION` can only reduce the value of the\nlimits set by the caller, not increase them.\n\n[](){: #sect2 }","title":"Special Start-of-Pattern Items - re","ref":"re.html#module-special-start-of-pattern-items"},{"type":"module","doc":"A regular expression is a pattern that is matched against a subject string from\nleft to right. Most characters stand for themselves in a pattern and match the\ncorresponding characters in the subject. As a trivial example, the following\npattern matches a portion of a subject string that is identical to itself:\n\n```text\nThe quick brown fox\n```\n\nWhen caseless matching is specified (option `caseless`), letters are matched\nindependently of case.\n\nThe power of regular expressions comes from the ability to include alternatives\nand repetitions in the pattern. These are encoded in the pattern by the use of\n_metacharacters_, which do not stand for themselves but instead are interpreted\nin some special way.\n\nTwo sets of metacharacters exist: those that are recognized anywhere in the\npattern except within square brackets, and those that are recognized within\nsquare brackets. Outside square brackets, the metacharacters are as follows:\n\n- **`\\`** - General escape character with many uses\n\n- **`^`** - Assert start of string (or line, in multiline mode)\n\n- **`$`** - Assert end of string (or line, in multiline mode)\n\n- **`.`** - Match any character except newline (by default)\n\n- **`[`** - Start character class definition\n\n- **`|`** - Start of alternative branch\n\n- **`(`** - Start subpattern\n\n- **`)`** - End subpattern\n\n- **`?`** - Extends the meaning of (, also 0 or 1 quantifier, also quantifier\n minimizer\n\n- **`*`** - 0 or more quantifiers\n\n- **`+`** - 1 or more quantifier, also \"possessive quantifier\"\n\n- **`{`** - Start min/max quantifier\n\nPart of a pattern within square brackets is called a \"character class\". The\nfollowing are the only metacharacters in a character class:\n\n- **`\\`** - General escape character\n\n- **`^`** - Negate the class, but only if the first character\n\n- **`-`** - Indicates character range\n\n- **`[`** - Posix character class (only if followed by Posix syntax)\n\n- **`]`** - Terminates the character class\n\nThe following sections describe the use of each metacharacter.\n\n[](){: #sect3 }","title":"Characters and Metacharacters - re","ref":"re.html#module-characters-and-metacharacters"},{"type":"module","doc":"The backslash character has many uses. First, if it is followed by a character\nthat is not a number or a letter, it takes away any special meaning that a\ncharacter can have. This use of backslash as an escape character applies both\ninside and outside character classes.\n\nFor example, if you want to match a \"\\_\" character, you write `\\_` in the pattern.\nThis escaping action applies if the following character would otherwise be\ninterpreted as a metacharacter, so it is always safe to precede a\nnon-alphanumeric with backslash to specify that it stands for itself. In\nparticular, if you want to match a backslash, write `\\\\`.\n\nIn `unicode` mode, only ASCII numbers and letters have any special meaning after\na backslash. All other characters (in particular, those whose code points\nare > 127) are treated as literals.\n\nIf a pattern is compiled with option `extended`, whitespace in the pattern\n(other than in a character class) and characters between a # outside a character\nclass and the next newline are ignored. An escaping backslash can be used to\ninclude a whitespace or # character as part of the pattern.\n\nTo remove the special meaning from a sequence of characters, put them between\n`\\Q` and `\\E`. This is different from Perl in that `$` and `@` are handled as literals\nin `\\Q`...`\\E` sequences in PCRE, while `$` and `@` cause variable interpolation in\nPerl. Notice the following examples:\n\n```text\nPattern PCRE matches Perl matches\n\n\\Qabc$xyz\\E abc$xyz abc followed by the contents of $xyz\n\\Qabc\\$xyz\\E abc\\$xyz abc\\$xyz\n\\Qabc\\E\\$\\Qxyz\\E abc$xyz abc$xyz\n```\n\nThe `\\Q`...`\\E` sequence is recognized both inside and outside character classes.\nAn isolated `\\E` that is not preceded by `\\Q` is ignored. If `\\Q` is not followed\nby `\\E` later in the pattern, the literal interpretation continues to the end of\nthe pattern (that is, `\\E` is assumed at the end). If the isolated `\\Q` is inside\na character class, this causes an error, as the character class is not\nterminated.\n\n_Non-Printing Characters_\n\n[](){: #non_printing_characters }\n\nA second use of backslash provides a way of encoding non-printing characters in\npatterns in a visible manner. There is no restriction on the appearance of\nnon-printing characters, apart from the binary zero that terminates a pattern.\nWhen a pattern is prepared by text editing, it is often easier to use one of the\nfollowing escape sequences than the binary character it represents:\n\n- **`\\a`** - Alarm, that is, the BEL character (hex 07)\n\n- **`\\cx`** - \"Control-x\", where x is any ASCII character\n\n- **`\\e`** - Escape (hex 1B)\n\n- **`\\f`** - Form feed (hex 0C)\n\n- **`\\n`** - Line feed (hex 0A)\n\n- **`\\r`** - Carriage return (hex 0D)\n\n- **`\\t`** - Tab (hex 09)\n\n- **`\\0dd`** - Character with octal code 0dd\n\n- **`\\ddd`** - Character with octal code ddd, or back reference\n\n- **`\\o{ddd..}`** - character with octal code ddd..\n\n- **`\\xhh`** - Character with hex code hh\n\n- **`\\x{hhh..}`** - Character with hex code hhh..\n\n> #### Note {: .info }\n>\n> Note that `\\0dd` is always an octal code, and that `\\8` and `\\9` are the literal\n> characters \"8\" and \"9\".\n\nThe precise effect of `\\cx` on ASCII characters is as follows: if x is a\nlowercase letter, it is converted to upper case. Then bit 6 of the character\n(hex 40) is inverted. Thus `\\cA` to `\\cZ` become hex 01 to hex 1A (A is 41, Z is\n5A), but `\\c{` becomes hex 3B (`{` is 7B), and `\\c`; becomes hex 7B (; is 3B). If\nthe data item (byte or 16-bit value) following `\\c` has a value > 127, a\ncompile-time error occurs. This locks out non-ASCII characters in all modes.\n\nThe `\\c` facility was designed for use with ASCII characters, but with the\nextension to Unicode it is even less useful than it once was.\n\nAfter `\\0` up to two further octal digits are read. If there are fewer than two\ndigits, just those that are present are used. Thus the sequence `\\0\\x\\015`\nspecifies two binary zeros followed by a CR character (code value 13). Make sure\nyou supply two digits after the initial zero if the pattern character that\nfollows is itself an octal digit.\n\nThe escape `\\o` must be followed by a sequence of octal digits, enclosed in\nbraces. An error occurs if this is not the case. This escape is a recent\naddition to Perl; it provides way of specifying character code points as octal\nnumbers greater than 0777, and it also allows octal numbers and back references\nto be unambiguously specified.\n\nFor greater clarity and unambiguity, it is best to avoid following `\\` by a digit\ngreater than zero. Instead, use `\\o{}` or `\\x{}` to specify character numbers,\nand `\\g{}` to specify back references. The following paragraphs describe the\nold, ambiguous syntax.\n\nThe handling of a backslash followed by a digit other than 0 is complicated, and\nPerl has changed in recent releases, causing PCRE also to change. Outside a\ncharacter class, PCRE reads the digit and any following digits as a decimal\nnumber. If the number is < 8, or if there have been at least that many previous\ncapturing left parentheses in the expression, the entire sequence is taken as a\n_back reference_. A description of how this works is provided later, following\nthe discussion of parenthesized subpatterns.\n\nInside a character class, or if the decimal number following `\\` is > 7 and there\nhave not been that many capturing subpatterns, PCRE handles `\\8` and `\\9` as the\nliteral characters \"8\" and \"9\", and otherwise re-reads up to three octal digits\nfollowing the backslash, and using them to generate a data character. Any\nsubsequent digits stand for themselves. For example:\n\n- **`\\040`** - Another way of writing an ASCII space\n\n- **`\\40`** - The same, provided there are < 40 previous capturing subpatterns\n\n- **`\\7`** - Always a back reference\n\n- **`\\11`** - Can be a back reference, or another way of writing a tab\n\n- **`\\011`** - Always a tab\n\n- **`\\0113`** - A tab followed by character \"3\"\n\n- **`\\113`** - Can be a back reference, otherwise the character with octal code\n 113\n\n- **`\\377`** - Can be a back reference, otherwise value 255 (decimal)\n\n- **`\\81`** - Either a back reference, or the two characters \"8\" and \"1\"\n\nNotice that octal values >= 100 that are specified using this syntax must not be\nintroduced by a leading zero, as no more than three octal digits are ever read.\n\nBy default, after `\\x` that is not followed by `{`, from zero to two hexadecimal\ndigits are read (letters can be in upper or lower case). Any number of\nhexadecimal digits may appear between `\\x{` and `}`. If a character other than a\nhexadecimal digit appears between `\\x{` and `}`, or if there is no terminating\n`}`, an error occurs.\n\nCharacters whose value is less than 256 can be defined by either of the two\nsyntaxes for `\\x`. There is no difference in the way they are handled. For\nexample, `\\xdc` is exactly the same as `\\x{dc}`.\n\n_Constraints on character values_\n\nCharacters that are specified using octal or hexadecimal numbers are limited to\ncertain values, as follows:\n\n- **8-bit non-UTF mode** - < 0x100\n\n- **8-bit UTF-8 mode** - < 0x10ffff and a valid codepoint\n\nInvalid Unicode codepoints are the range 0xd800 to 0xdfff (the so-called\n\"surrogate\" codepoints), and 0xffef.\n\n_Escape sequences in character classes_\n\nAll the sequences that define a single character value can be used both inside\nand outside character classes. Also, inside a character class, `\\b` is\ninterpreted as the backspace character (hex 08).\n\n`\\N` is not allowed in a character class. `\\B`, `\\R`, and `\\X` are not special\ninside a character class. Like other unrecognized escape sequences, they are\ntreated as the literal characters \"B\", \"R\", and \"X\". Outside a character class,\nthese sequences have different meanings.\n\n_Unsupported Escape Sequences_\n\nIn Perl, the sequences `\\l`, `\\L`, `\\u`, and `\\U` are recognized by its string\nhandler and used to modify the case of following characters. PCRE does not\nsupport these escape sequences.\n\n_Absolute and Relative Back References_\n\nThe sequence `\\g` followed by an unsigned or a negative number, optionally\nenclosed in braces, is an absolute or relative back reference. A named back\nreference can be coded as `\\g{name}`. Back references are discussed later,\nfollowing the discussion of parenthesized subpatterns.\n\n_Absolute and Relative Subroutine Calls_\n\nFor compatibility with Oniguruma, the non-Perl syntax `\\g` followed by a name or\na number enclosed either in angle brackets or single quotes, is alternative\nsyntax for referencing a subpattern as a \"subroutine\". Details are discussed\nlater. Notice that `\\g{...}` (Perl syntax) and `\\g<...>` (Oniguruma syntax) are\n_not_ synonymous. The former is a back reference and the latter is a subroutine\ncall.\n\n_Generic Character Types_\n\n[](){: #generic_character_types }\n\nAnother use of backslash is for specifying generic character types:\n\n- **`\\d`** - Any decimal digit\n\n- **`\\D`** - Any character that is not a decimal digit\n\n- **`\\h`** - Any horizontal whitespace character\n\n- **`\\H`** - Any character that is not a horizontal whitespace character\n\n- **`\\s`** - Any whitespace character\n\n- **`\\S`** - Any character that is not a whitespace character\n\n- **`\\v`** - Any vertical whitespace character\n\n- **`\\V`** - Any character that is not a vertical whitespace character\n\n- **`\\w`** - Any \"word\" character\n\n- **`\\W`** - Any \"non-word\" character\n\nThere is also the single sequence `\\N`, which matches a non-newline character.\nThis is the same as the \".\" metacharacter when `dotall` is not set. Perl also\nuses `\\N` to match characters by name, but PCRE does not support this.\n\nEach pair of lowercase and uppercase escape sequences partitions the complete\nset of characters into two disjoint sets. Any given character matches one, and\nonly one, of each pair. The sequences can appear both inside and outside\ncharacter classes. They each match one character of the appropriate type. If the\ncurrent matching point is at the end of the subject string, all fail, as there\nis no character to match.\n\nFor compatibility with Perl, `\\s` did not used to match the VT character (code\n11), which made it different from the the POSIX \"space\" class. However, Perl\nadded VT at release 5.18, and PCRE followed suit at release 8.34. The default\n`\\s` characters are now HT (9), LF (10), VT (11), FF (12), CR (13), and space\n(32), which are defined as white space in the \"C\" locale. This list may vary if\nlocale-specific matching is taking place. For example, in some locales the\n\"non-breaking space\" character (`\\xA0`) is recognized as white space, and in\nothers the VT character is not.\n\nA \"word\" character is an underscore or any character that is a letter or a\ndigit. By default, the definition of letters and digits is controlled by the\nPCRE low-valued character tables, in Erlang's case (and without option\n`unicode`), the ISO Latin-1 character set.\n\nBy default, in `unicode` mode, characters with values > 255, that is, all\ncharacters outside the ISO Latin-1 character set, never match `\\d`, `\\s`, or `\\w`,\nand always match `\\D`, `\\S`, and `\\W`. These sequences retain their original\nmeanings from before UTF support was available, mainly for efficiency reasons.\nHowever, if option `ucp` is set, the behavior is changed so that Unicode\nproperties are used to determine character types, as follows:\n\n- **`\\d`** - Any character that `\\p{Nd}` matches (decimal digit)\n\n- **`\\s`** - Any character that `\\p{Z}` or `\\h` or `\\v`\n\n- **`\\w`** - Any character that matches `\\p{L}` or `\\p{N}` matches, plus\n underscore\n\nThe uppercase escapes match the inverse sets of characters. Notice that `\\d`\nmatches only decimal digits, while `\\w` matches any Unicode digit, any Unicode\nletter, and underscore. Notice also that `ucp` affects `\\b` and `\\B`, as they are\ndefined in terms of `\\w` and `\\W`. Matching these sequences is noticeably slower\nwhen `ucp` is set.\n\nThe sequences `\\h`, `\\H`, `\\v`, and `\\V` are features that were added to Perl in\nrelease 5.10. In contrast to the other sequences, which match only ASCII\ncharacters by default, these always match certain high-valued code points,\nregardless if `ucp` is set.\n\nThe following are the horizontal space characters:\n\n- **U+0009** - Horizontal tab (HT)\n\n- **U+0020** - Space\n\n- **U+00A0** - Non-break space\n\n- **U+1680** - Ogham space mark\n\n- **U+180E** - Mongolian vowel separator\n\n- **U+2000** - En quad\n\n- **U+2001** - Em quad\n\n- **U+2002** - En space\n\n- **U+2003** - Em space\n\n- **U+2004** - Three-per-em space\n\n- **U+2005** - Four-per-em space\n\n- **U+2006** - Six-per-em space\n\n- **U+2007** - Figure space\n\n- **U+2008** - Punctuation space\n\n- **U+2009** - Thin space\n\n- **U+200A** - Hair space\n\n- **U+202F** - Narrow no-break space\n\n- **U+205F** - Medium mathematical space\n\n- **U+3000** - Ideographic space\n\nThe following are the vertical space characters:\n\n- **U+000A** - Line feed (LF)\n\n- **U+000B** - Vertical tab (VT)\n\n- **U+000C** - Form feed (FF)\n\n- **U+000D** - Carriage return (CR)\n\n- **U+0085** - Next line (NEL)\n\n- **U+2028** - Line separator\n\n- **U+2029** - Paragraph separator\n\nIn 8-bit, non-UTF-8 mode, only the characters with code points < 256 are\nrelevant.\n\n_Newline Sequences_\n\n[](){: #newline_sequences }\n\nOutside a character class, by default, the escape sequence `\\R` matches any\nUnicode newline sequence. In non-UTF-8 mode, `\\R` is equivalent to the following:\n\n```text\n(?>\\r\\n|\\n|\\x0b|\\f|\\r|\\x85)\n```\n\nThis is an example of an \"atomic group\", details are provided below.\n\nThis particular group matches either the two-character sequence CR followed by\nLF, or one of the single characters LF (line feed, U+000A), VT (vertical tab,\nU+000B), FF (form feed, U+000C), CR (carriage return, U+000D), or NEL (next\nline, U+0085). The two-character sequence is treated as a single unit that\ncannot be split.\n\nIn Unicode mode, two more characters whose code points are > 255 are added: LS\n(line separator, U+2028) and PS (paragraph separator, U+2029). Unicode character\nproperty support is not needed for these characters to be recognized.\n\n`\\R` can be restricted to match only CR, LF, or CRLF (instead of the complete set\nof Unicode line endings) by setting option `bsr_anycrlf` either at compile time\nor when the pattern is matched. (BSR is an acronym for \"backslash R\".) This can\nbe made the default when PCRE is built; if so, the other behavior can be\nrequested through option `bsr_unicode`. These settings can also be specified by\nstarting a pattern string with one of the following sequences:\n\n- **(\\*BSR_ANYCRLF)** - CR, LF, or CRLF only\n\n- **(\\*BSR_UNICODE)** - Any Unicode newline sequence\n\nThese override the default and the options specified to the compiling function,\nbut they can themselves be overridden by options specified to a matching\nfunction. Notice that these special settings, which are not Perl-compatible, are\nrecognized only at the very start of a pattern, and that they must be in upper\ncase. If more than one of them is present, the last one is used. They can be\ncombined with a change of newline convention; for example, a pattern can start\nwith:\n\n```text\n(*ANY)(*BSR_ANYCRLF)\n```\n\nThey can also be combined with the (*UTF8), (*UTF), or (\\*UCP) special\nsequences. Inside a character class, `\\R` is treated as an unrecognized escape\nsequence, and so matches the letter \"R\" by default.\n\n_Unicode Character Properties_\n\nThree more escape sequences that match characters with specific properties are\navailable. When in 8-bit non-UTF-8 mode, these sequences are limited to testing\ncharacters whose code points are < 256, but they do work in this mode. The\nfollowing are the extra escape sequences:\n\n- **`\\p{_xx_}`** - A character with property _xx_\n\n- **`\\P{_xx_}`** - A character without property _xx_\n\n- **`\\X`** - A Unicode extended grapheme cluster\n\nThe property names represented by _xx_ above are limited to the Unicode script\nnames, the general category properties, \"Any\", which matches any character\n(including newline), and some special PCRE properties (described in the next\nsection). Other Perl properties, such as \"InMusicalSymbols\", are currently not\nsupported by PCRE. Notice that `\\P{Any}` does not match any characters and\nalways causes a match failure.\n\nSets of Unicode characters are defined as belonging to certain scripts. A\ncharacter from one of these sets can be matched using a script name, for\nexample:\n\n```text\n\\p{Greek} \\P{Han}\n```\n\nThose that are not part of an identified script are lumped together as \"Common\".\nThe following is the current list of scripts:\n\n- Arabic\n- Armenian\n- Avestan\n- Balinese\n- Bamum\n- Bassa_Vah\n- Batak\n- Bengali\n- Bopomofo\n- Braille\n- Buginese\n- Buhid\n- Canadian_Aboriginal\n- Carian\n- Caucasian_Albanian\n- Chakma\n- Cham\n- Cherokee\n- Common\n- Coptic\n- Cuneiform\n- Cypriot\n- Cyrillic\n- Deseret\n- Devanagari\n- Duployan\n- Egyptian_Hieroglyphs\n- Elbasan\n- Ethiopic\n- Georgian\n- Glagolitic\n- Gothic\n- Grantha\n- Greek\n- Gujarati\n- Gurmukhi\n- Han\n- Hangul\n- Hanunoo\n- Hebrew\n- Hiragana\n- Imperial_Aramaic\n- Inherited\n- Inscriptional_Pahlavi\n- Inscriptional_Parthian\n- Javanese\n- Kaithi\n- Kannada\n- Katakana\n- Kayah_Li\n- Kharoshthi\n- Khmer\n- Khojki\n- Khudawadi\n- Lao\n- Latin\n- Lepcha\n- Limbu\n- Linear_A\n- Linear_B\n- Lisu\n- Lycian\n- Lydian\n- Mahajani\n- Malayalam\n- Mandaic\n- Manichaean\n- Meetei_Mayek\n- Mende_Kikakui\n- Meroitic_Cursive\n- Meroitic_Hieroglyphs\n- Miao\n- Modi\n- Mongolian\n- Mro\n- Myanmar\n- Nabataean\n- New_Tai_Lue\n- Nko\n- Ogham\n- Ol_Chiki\n- Old_Italic\n- Old_North_Arabian\n- Old_Permic\n- Old_Persian\n- Oriya\n- Old_South_Arabian\n- Old_Turkic\n- Osmanya\n- Pahawh_Hmong\n- Palmyrene\n- Pau_Cin_Hau\n- Phags_Pa\n- Phoenician\n- Psalter_Pahlavi\n- Rejang\n- Runic\n- Samaritan\n- Saurashtra\n- Sharada\n- Shavian\n- Siddham\n- Sinhala\n- Sora_Sompeng\n- Sundanese\n- Syloti_Nagri\n- Syriac\n- Tagalog\n- Tagbanwa\n- Tai_Le\n- Tai_Tham\n- Tai_Viet\n- Takri\n- Tamil\n- Telugu\n- Thaana\n- Thai\n- Tibetan\n- Tifinagh\n- Tirhuta\n- Ugaritic\n- Vai\n- Warang_Citi\n- Yi\n\nEach character has exactly one Unicode general category property, specified by a\ntwo-letter acronym. For compatibility with Perl, negation can be specified by\nincluding a circumflex between the opening brace and the property name. For\nexample, `\\p{^Lu}` is the same as `\\P{Lu}`.\n\nIf only one letter is specified with `\\p` or `\\P`, it includes all the general\ncategory properties that start with that letter. In this case, in the absence of\nnegation, the curly brackets in the escape sequence are optional. The following\ntwo examples have the same effect:\n\n```text\n\\p{L}\n\\pL\n```\n\nThe following general category property codes are supported:\n\n- **C** - Other\n\n- **Cc** - Control\n\n- **Cf** - Format\n\n- **Cn** - Unassigned\n\n- **Co** - Private use\n\n- **Cs** - Surrogate\n\n- **L** - Letter\n\n- **Ll** - Lowercase letter\n\n- **Lm** - Modifier letter\n\n- **Lo** - Other letter\n\n- **Lt** - Title case letter\n\n- **Lu** - Uppercase letter\n\n- **M** - Mark\n\n- **Mc** - Spacing mark\n\n- **Me** - Enclosing mark\n\n- **Mn** - Non-spacing mark\n\n- **N** - Number\n\n- **Nd** - Decimal number\n\n- **Nl** - Letter number\n\n- **No** - Other number\n\n- **P** - Punctuation\n\n- **Pc** - Connector punctuation\n\n- **Pd** - Dash punctuation\n\n- **Pe** - Close punctuation\n\n- **Pf** - Final punctuation\n\n- **Pi** - Initial punctuation\n\n- **Po** - Other punctuation\n\n- **Ps** - Open punctuation\n\n- **S** - Symbol\n\n- **Sc** - Currency symbol\n\n- **Sk** - Modifier symbol\n\n- **Sm** - Mathematical symbol\n\n- **So** - Other symbol\n\n- **Z** - Separator\n\n- **Zl** - Line separator\n\n- **Zp** - Paragraph separator\n\n- **Zs** - Space separator\n\nThe special property L& is also supported. It matches a character that has the\nLu, Ll, or Lt property, that is, a letter that is not classified as a modifier\nor \"other\".\n\nThe Cs (Surrogate) property applies only to characters in the range U+D800 to\nU+DFFF. Such characters are invalid in Unicode strings and so cannot be tested\nby PCRE. Perl does not support the Cs property.\n\nThe long synonyms for property names supported by Perl (such as `\\p{Letter}`)\nare not supported by PCRE. It is not permitted to prefix any of these properties\nwith \"Is\".\n\nNo character in the Unicode table has the Cn (unassigned) property. This\nproperty is instead assumed for any code point that is not in the Unicode table.\n\nSpecifying caseless matching does not affect these escape sequences. For\nexample, `\\p{Lu}` always matches only uppercase letters. This is different from\nthe behavior of current versions of Perl.\n\nMatching characters by Unicode property is not fast, as PCRE must do a\nmultistage table lookup to find a character property. That is why the\ntraditional escape sequences such as `\\d` and `\\w` do not use Unicode properties\nin PCRE by default. However, you can make them do so by setting option `ucp` or\nby starting the pattern with `(*UCP)`.\n\n_Extended Grapheme Clusters_\n\nThe `\\X` escape matches any number of Unicode characters that form an \"extended\ngrapheme cluster\", and treats the sequence as an atomic group (see below). Up to\nand including release 8.31, PCRE matched an earlier, simpler definition that was\nequivalent to `(?>\\PM\\pM*)`. That is, it matched a character without the \"mark\"\nproperty, followed by zero or more characters with the \"mark\" property.\nCharacters with the \"mark\" property are typically non-spacing accents that\naffect the preceding character.\n\nThis simple definition was extended in Unicode to include more complicated kinds\nof composite character by giving each character a grapheme breaking property,\nand creating rules that use these properties to define the boundaries of\nextended grapheme clusters. In PCRE releases later than 8.31, `\\X` matches one of\nthese clusters.\n\n`\\X` always matches at least one character. Then it decides whether to add more\ncharacters according to the following rules for ending a cluster:\n\n1. End at the end of the subject string.\n1. Do not end between CR and LF; otherwise end after any control character.\n1. Do not break Hangul (a Korean script) syllable sequences. Hangul characters\n are of five types: L, V, T, LV, and LVT. An L character can be followed by an\n L, V, LV, or LVT character. An LV or V character can be followed by a V or T\n character. An LVT or T character can be followed only by a T character.\n1. Do not end before extending characters or spacing marks. Characters with the\n \"mark\" property always have the \"extend\" grapheme breaking property.\n1. Do not end after prepend characters.\n1. Otherwise, end the cluster.\n\n_PCRE Additional Properties_\n\nIn addition to the standard Unicode properties described earlier, PCRE supports\nfour more that make it possible to convert traditional escape sequences, such as\n`\\w` and `\\s` to use Unicode properties. PCRE uses these non-standard, non-Perl\nproperties internally when the `ucp` option is passed. However, they can also be\nused explicitly. The properties are as follows:\n\n- **Xan** - Any alphanumeric character. Matches characters that have either the\n L (letter) or the N (number) property.\n\n- **Xps** - Any Posix space character. Matches the characters tab, line feed,\n vertical tab, form feed, carriage return, and any other character that has the\n Z (separator) property.\n\n- **Xsp** - Any Perl space character. Matches the same as Xps, except that\n vertical tab is excluded.\n\n- **Xwd** - Any Perl \"word\" character. Matches the same characters as Xan, plus\n underscore.\n\nPerl and POSIX space are now the same. Perl added VT to its space character set\nat release 5.18 and PCRE changed at release 8.34.\n\nXan matches characters that have either the L (letter) or the N (number)\nproperty. Xps matches the characters tab, linefeed, vertical tab, form feed, or\ncarriage return, and any other character that has the Z (separator) property.\nXsp is the same as Xps; it used to exclude vertical tab, for Perl compatibility,\nbut Perl changed, and so PCRE followed at release 8.34. Xwd matches the same\ncharacters as Xan, plus underscore.\n\nThere is another non-standard property, Xuc, which matches any character that\ncan be represented by a Universal Character Name in C++ and other programming\nlanguages. These are the characters `$`, `@`, `` ` `` (grave accent), and all characters\nwith Unicode code points >= U+00A0, except for the surrogates U+D800 to U+DFFF.\nNotice that most base (ASCII) characters are excluded. (Universal Character\nNames are of the form `\\uHHHH` or `\\UHHHHHHHH`, where H is a hexadecimal digit.\nNotice that the Xuc property does not match these sequences but the characters\nthat they represent.)\n\n_Resetting the Match Start_\n\nThe escape sequence `\\K` causes any previously matched characters not to be\nincluded in the final matched sequence. For example, the following pattern\nmatches \"foobar\", but reports that it has matched \"bar\":\n\n```text\nfoo\\Kbar\n```\n\nThis feature is similar to a lookbehind assertion (described below). However, in\nthis case, the part of the subject before the real match does not have to be of\nfixed length, as lookbehind assertions do. The use of `\\K` does not interfere\nwith the setting of captured substrings. For example, when the following pattern\nmatches \"foobar\", the first substring is still set to \"foo\":\n\n```text\n(foo)\\Kbar\n```\n\nPerl documents that the use of `\\K` within assertions is \"not well defined\". In\nPCRE, `\\K` is acted upon when it occurs inside positive assertions, but is\nignored in negative assertions. Note that when a pattern such as `(?=ab\\K)`\nmatches, the reported start of the match can be greater than the end of the\nmatch.\n\n_Simple Assertions_\n\nThe final use of backslash is for certain simple assertions. An assertion\nspecifies a condition that must be met at a particular point in a match, without\nconsuming any characters from the subject string. The use of subpatterns for\nmore complicated assertions is described below. The following are the\nbackslashed assertions:\n\n- **`\\b`** - Matches at a word boundary.\n\n- **`\\B`** - Matches when not at a word boundary.\n\n- **`\\A`** - Matches at the start of the subject.\n\n- **`\\Z`** - Matches at the end of the subject, and before a newline at the end\n of the subject.\n\n- **`\\z`** - Matches only at the end of the subject.\n\n- **`\\G`** - Matches at the first matching position in the subject.\n\nInside a character class, `\\b` has a different meaning; it matches the backspace\ncharacter. If any other of these assertions appears in a character class, by\ndefault it matches the corresponding literal character (for example, `\\B` matches\nthe letter B).\n\nA word boundary is a position in the subject string where the current character\nand the previous character do not both match `\\w` or `\\W` (that is, one matches\n`\\w` and the other matches `\\W`), or the start or end of the string if the first\nor last character matches `\\w`, respectively. In UTF mode, the meanings of `\\w`\nand `\\W` can be changed by setting option `ucp`. When this is done, it also\naffects `\\b` and `\\B`. PCRE and Perl do not have a separate \"start of word\" or\n\"end of word\" metasequence. However, whatever follows `\\b` normally determines\nwhich it is. For example, the fragment `\\ba` matches \"a\" at the start of a word.\n\nThe `\\A`, `\\Z`, and `\\z` assertions differ from the traditional circumflex and\ndollar (described in the next section) in that they only ever match at the very\nstart and end of the subject string, whatever options are set. Thus, they are\nindependent of multiline mode. These three assertions are not affected by\noptions `notbol` or `noteol`, which affect only the behavior of the circumflex\nand dollar metacharacters. However, if argument `startoffset` of `run/3` is\nnon-zero, indicating that matching is to start at a point other than the\nbeginning of the subject, `\\A` can never match. The difference between `\\Z` and\n`\\z` is that `\\Z` matches before a newline at the end of the string and at the\nvery end, while `\\z` matches only at the end.\n\nThe `\\G` assertion is true only when the current matching position is at the\nstart point of the match, as specified by argument `startoffset` of\n[`run/3`](`run/3`). It differs from `\\A` when the value of `startoffset` is\nnon-zero. By calling [`run/3`](`run/3`) multiple times with appropriate\narguments, you can mimic the Perl option `/g`, and it is in this kind of\nimplementation where `\\G` can be useful.\n\nNotice, however, that the PCRE interpretation of `\\G`, as the start of the\ncurrent match, is subtly different from Perl, which defines it as the end of the\nprevious match. In Perl, these can be different when the previously matched\nstring was empty. As PCRE does only one match at a time, it cannot reproduce\nthis behavior.\n\nIf all the alternatives of a pattern begin with `\\G`, the expression is anchored\nto the starting match position, and the \"anchored\" flag is set in the compiled\nregular expression.\n\n[](){: #sect4 }","title":"Backslash - re","ref":"re.html#module-backslash"},{"type":"module","doc":"The circumflex and dollar metacharacters are zero-width assertions. That is,\nthey test for a particular condition to be true without consuming any characters\nfrom the subject string.\n\nOutside a character class, in the default matching mode, the circumflex\ncharacter is an assertion that is true only if the current matching point is at\nthe start of the subject string. If argument `startoffset` of `run/3` is\nnon-zero, circumflex can never match if option `multiline` is unset. Inside a\ncharacter class, circumflex has an entirely different meaning (see below).\n\nCircumflex needs not to be the first character of the pattern if some\nalternatives are involved, but it is to be the first thing in each alternative\nin which it appears if the pattern is ever to match that branch. If all possible\nalternatives start with a circumflex, that is, if the pattern is constrained to\nmatch only at the start of the subject, it is said to be an \"anchored\" pattern.\n(There are also other constructs that can cause a pattern to be anchored.)\n\nThe dollar character is an assertion that is true only if the current matching\npoint is at the end of the subject string, or immediately before a newline at\nthe end of the string (by default). Notice however that it does not match the\nnewline. Dollar needs not to be the last character of the pattern if some\nalternatives are involved, but it is to be the last item in any branch in which\nit appears. Dollar has no special meaning in a character class.\n\nThe meaning of dollar can be changed so that it matches only at the very end of\nthe string, by setting option `dollar_endonly` at compile time. This does not\naffect the `\\Z` assertion.\n\nThe meanings of the circumflex and dollar characters are changed if option\n`multiline` is set. When this is the case, a circumflex matches immediately\nafter internal newlines and at the start of the subject string. It does not\nmatch after a newline that ends the string. A dollar matches before any newlines\nin the string, and at the very end, when `multiline` is set. When newline is\nspecified as the two-character sequence CRLF, isolated CR and LF characters do\nnot indicate newlines.\n\nFor example, the pattern `/^abc$/` matches the subject string \"def\\\\nabc\" (where\n\\\\n represents a newline) in multiline mode, but not otherwise. So, patterns\nthat are anchored in single-line mode because all branches start with ^ are not\nanchored in multiline mode, and a match for circumflex is possible when argument\n_startoffset_ of [`run/3`](`run/3`) is non-zero. Option `dollar_endonly` is\nignored if `multiline` is set.\n\nNotice that the sequences `\\A`, `\\Z`, and `\\z` can be used to match the start and\nend of the subject in both modes. If all branches of a pattern start with `\\A`,\nit is always anchored, regardless if `multiline` is set.\n\n[](){: #sect5 }","title":"Circumflex and Dollar - re","ref":"re.html#module-circumflex-and-dollar"},{"type":"module","doc":"Outside a character class, a dot in the pattern matches any character in the\nsubject string except (by default) a character that signifies the end of a line.\n\nWhen a line ending is defined as a single character, dot never matches that\ncharacter. When the two-character sequence CRLF is used, dot does not match CR\nif it is immediately followed by LF, otherwise it matches all characters\n(including isolated CRs and LFs). When any Unicode line endings are recognized,\ndot does not match CR, LF, or any of the other line-ending characters.\n\nThe behavior of dot regarding newlines can be changed. If option `dotall` is\nset, a dot matches any character, without exception. If the two-character\nsequence CRLF is present in the subject string, it takes two dots to match it.\n\nThe handling of dot is entirely independent of the handling of circumflex and\ndollar, the only relationship is that both involve newlines. Dot has no special\nmeaning in a character class.\n\nThe escape sequence `\\N` behaves like a dot, except that it is not affected by\noption `PCRE_DOTALL`. That is, it matches any character except one that\nsignifies the end of a line. Perl also uses `\\N` to match characters by name but\nPCRE does not support this.\n\n[](){: #sect6 }","title":"Full Stop (Period, Dot) and \\\\N - re","ref":"re.html#module-full-stop-period-dot-and-n"},{"type":"module","doc":"Outside a character class, the escape sequence `\\C` matches any data unit,\nregardless if a UTF mode is set. One data unit is one byte. Unlike a dot, `\\C`\nalways matches line-ending characters. The feature is provided in Perl to match\nindividual bytes in UTF-8 mode, but it is unclear how it can usefully be used.\nAs `\\C` breaks up characters into individual data units, matching one unit with\n`\\C` in a UTF mode means that the remaining string can start with a malformed UTF\ncharacter. This has undefined results, as PCRE assumes that it deals with valid\nUTF strings.\n\nPCRE does not allow `\\C` to appear in lookbehind assertions (described below) in\na UTF mode, as this would make it impossible to calculate the length of the\nlookbehind.\n\nThe `\\C` escape sequence is best avoided. However, one way of using it that\navoids the problem of malformed UTF characters is to use a lookahead to check\nthe length of the next character, as in the following pattern, which can be used\nwith a UTF-8 string (ignore whitespace and line breaks):\n\n```text\n(?| (?=[\\x00-\\x7f])(\\C) |\n (?=[\\x80-\\x{7ff}])(\\C)(\\C) |\n (?=[\\x{800}-\\x{ffff}])(\\C)(\\C)(\\C) |\n (?=[\\x{10000}-\\x{1fffff}])(\\C)(\\C)(\\C)(\\C))\n```\n\nA group that starts with (?| resets the capturing parentheses numbers in each\nalternative (see section [Duplicate Subpattern Numbers](`m:re#sect12`)). The\nassertions at the start of each branch check the next UTF-8 character for values\nwhose encoding uses 1, 2, 3, or 4 bytes, respectively. The individual bytes of\nthe character are then captured by the appropriate number of groups.\n\n[](){: #sect7 }","title":"Matching a Single Data Unit - re","ref":"re.html#module-matching-a-single-data-unit"},{"type":"module","doc":"An opening square bracket introduces a character class, terminated by a closing\nsquare bracket. A closing square bracket on its own is not special by default.\nHowever, if option `PCRE_JAVASCRIPT_COMPAT` is set, a lone closing square\nbracket causes a compile-time error. If a closing square bracket is required as\na member of the class, it is to be the first data character in the class (after\nan initial circumflex, if present) or escaped with a backslash.\n\nA character class matches a single character in the subject. In a UTF mode, the\ncharacter can be more than one data unit long. A matched character must be in\nthe set of characters defined by the class, unless the first character in the\nclass definition is a circumflex, in which case the subject character must not\nbe in the set defined by the class. If a circumflex is required as a member of\nthe class, ensure that it is not the first character, or escape it with a\nbackslash.\n\nFor example, the character class `[aeiou]` matches any lowercase vowel, while\n`[^aeiou]` matches any character that is not a lowercase vowel. Notice that a\ncircumflex is just a convenient notation for specifying the characters that are\nin the class by enumerating those that are not. A class that starts with a\ncircumflex is not an assertion; it still consumes a character from the subject\nstring, and therefore it fails if the current pointer is at the end of the\nstring.\n\nIn UTF-8 mode, characters with values > 255 (0xffff) can be included in a class\nas a literal string of data units, or by using the `\\x{` escaping mechanism.\n\nWhen caseless matching is set, any letters in a class represent both their\nuppercase and lowercase versions. For example, a caseless `[aeiou]` matches \"A\"\nand \"a\", and a caseless `[^aeiou]` does not match \"A\", but a caseful version\nwould. In a UTF mode, PCRE always understands the concept of case for characters\nwhose values are < 256, so caseless matching is always possible. For characters\nwith higher values, the concept of case is supported only if PCRE is compiled\nwith Unicode property support. If you want to use caseless matching in a UTF\nmode for characters >=, ensure that PCRE is compiled with Unicode property\nsupport and with UTF support.\n\nCharacters that can indicate line breaks are never treated in any special way\nwhen matching character classes, whatever line-ending sequence is in use, and\nwhatever setting of options `PCRE_DOTALL` and `PCRE_MULTILINE` is used. A class\nsuch as `[^a]` always matches one of these characters.\n\nThe minus (hyphen) character can be used to specify a range of characters in a\ncharacter class. For example, `[d-m]` matches any letter between d and m,\ninclusive. If a minus character is required in a class, it must be escaped with\na backslash or appear in a position where it cannot be interpreted as indicating\na range, typically as the first or last character in the class, or immediately\nafter a range. For example, `[b-d-z]` matches letters in the range b to d, a\nhyphen character, or z.\n\nThe literal character \"]\" cannot be the end character of a range. A pattern such\nas `[W-]46]` is interpreted as a class of two characters (\"W\" and \"-\") followed\nby a literal string \"46]\", so it would match \"W46]\" or \"-46]\". However, if \"]\"\nis escaped with a backslash, it is interpreted as the end of range, so\n`[W-\\]46]` is interpreted as a class containing a range followed by two other\ncharacters. The octal or hexadecimal representation of \"]\" can also be used to\nend a range.\n\nAn error is generated if a POSIX character class (see below) or an escape\nsequence other than one that defines a single character appears at a point where\na range ending character is expected. For example, `[z-\\xff]` is valid, but\n`[A-\\d]` and `[A-[:digit:]]` are not.\n\nRanges operate in the collating sequence of character values. They can also be\nused for characters specified numerically, for example, `[\\000-\\037]`. Ranges\ncan include any characters that are valid for the current mode.\n\nIf a range that includes letters is used when caseless matching is set, it\nmatches the letters in either case. For example, `[W-c]` is equivalent to\n`` [][\\\\^_`wxyzabc] ``, matched caselessly. In a non-UTF mode, if character\ntables for a French locale are in use, `[\\xc8-\\xcb]` matches accented E\ncharacters in both cases. In UTF modes, PCRE supports the concept of case for\ncharacters with values > 255 only when it is compiled with Unicode property\nsupport.\n\nThe character escape sequences `\\d`, `\\D`, `\\h`, `\\H`, `\\p`, `\\P`, `\\s`, `\\S`, `\\v`, `\\V`,\n`\\w`, and `\\W` can appear in a character class, and add the characters that they\nmatch to the class. For example, `[\\dABCDEF]` matches any hexadecimal digit. In\nUTF modes, option `ucp` affects the meanings of `\\d`, `\\s`, `\\w` and their\nuppercase partners, just as it does when they appear outside a character class,\nas described in section\n[Generic Character Types](`m:re#generic_character_types`) earlier. The escape\nsequence `\\b` has a different meaning inside a character class; it matches the\nbackspace character. The sequences `\\B`, `\\N`, `\\R`, and `\\X` are not special inside\na character class. Like any other unrecognized escape sequences, they are\ntreated as the literal characters \"B\", \"N\", \"R\", and \"X\".\n\nA circumflex can conveniently be used with the uppercase character types to\nspecify a more restricted set of characters than the matching lowercase type.\nFor example, class `[^\\W_]` matches any letter or digit, but not underscore,\nwhile `[\\w]` includes underscore. A positive character class is to be read as\n\"something OR something OR ...\" and a negative class as \"NOT something AND NOT\nsomething AND NOT ...\".\n\nOnly the following metacharacters are recognized in character classes:\n\n- Backslash\n- Hyphen (only where it can be interpreted as specifying a range)\n- Circumflex (only at the start)\n- Opening square bracket (only when it can be interpreted as introducing a Posix\n class name, or for a special compatibility feature; see the next two sections)\n- Terminating closing square bracket\n\nHowever, escaping other non-alphanumeric characters does no harm.\n\n[](){: #sect8 }","title":"Square Brackets and Character Classes - re","ref":"re.html#module-square-brackets-and-character-classes"},{"type":"module","doc":"Perl supports the Posix notation for character classes. This uses names enclosed\nby `[:` and `:]` within the enclosing square brackets. PCRE also supports this\nnotation. For example, the following matches \"0\", \"1\", any alphabetic character,\nor \"%\":\n\n```text\n[01[:alpha:]%]\n```\n\nThe following are the supported class names:\n\n- **alnum** - Letters and digits\n\n- **alpha** - Letters\n\n- **blank** - Space or tab only\n\n- **cntrl** - Control characters\n\n- **digit** - Decimal digits (same as `\\d`)\n\n- **graph** - Printing characters, excluding space\n\n- **lower** - Lowercase letters\n\n- **print** - Printing characters, including space\n\n- **punct** - Printing characters, excluding letters, digits, and space\n\n- **space** - Whitespace (the same as `\\s` from PCRE 8.34)\n\n- **upper** - Uppercase letters\n\n- **word** - \"Word\" characters (same as `\\w`)\n\n- **xdigit** - Hexadecimal digits\n\nThere is another character class, `ascii`, that erroneously matches Latin-1\ncharacters instead of the 0-127 range specified by POSIX. This cannot be fixed\nwithout altering the behaviour of other classes, so we recommend matching the\nrange with `[\\\\0-\\x7f]` instead.\n\nThe default \"space\" characters are HT (9), LF (10), VT (11), FF (12), CR (13),\nand space (32). If locale-specific matching is taking place, the list of space\ncharacters may be different; there may be fewer or more of them. \"Space\" used to\nbe different to `\\s`, which did not include VT, for Perl compatibility. However,\nPerl changed at release 5.18, and PCRE followed at release 8.34. \"Space\" and `\\s`\nnow match the same set of characters.\n\nThe name \"word\" is a Perl extension, and \"blank\" is a GNU extension from Perl\n5.8. Another Perl extension is negation, which is indicated by a ^ character\nafter the colon. For example, the following matches \"1\", \"2\", or any non-digit:\n\n```text\n[12[:^digit:]]\n```\n\nPCRE (and Perl) also recognize the Posix syntax `[.ch.]` and `[=ch=]` where \"ch\"\nis a \"collating element\", but these are not supported, and an error is given if\nthey are encountered.\n\nBy default, characters with values > 255 do not match any of the Posix character\nclasses. However, if option `PCRE_UCP` is passed to `pcre_compile()`, some of\nthe classes are changed so that Unicode character properties are used. This is\nachieved by replacing certain Posix classes by other sequences, as follows:\n\n- **`[:alnum:]`** - Becomes _`\\p{Xan}`_\n\n- **`[:alpha:]`** - Becomes _`\\p{L}`_\n\n- **`[:blank:]`** - Becomes _`\\h`_\n\n- **`[:digit:]`** - Becomes _`\\p{Nd}`_\n\n- **`[:lower:]`** - Becomes _`\\p{Ll}`_\n\n- **`[:space:]`** - Becomes _`\\p{Xps}`_\n\n- **`[:upper:]`** - Becomes _`\\p{Lu}`_\n\n- **`[:word:]`** - Becomes _`\\p{Xwd}`_\n\nNegated versions, such as `[:^alpha:]`, use `\\P` instead of `\\p`. Three other POSIX\nclasses are handled specially in UCP mode:\n\n- **`[:graph:]`** - This matches characters that have glyphs that mark the page\n when printed. In Unicode property terms, it matches all characters with the L,\n M, N, P, S, or Cf properties, except for:\n\n - **U+061C** - Arabic Letter Mark\n\n - **U+180E** - Mongolian Vowel Separator\n\n - **U+2066 - U+2069** - Various \"isolate\"s\n\n- **`[:print:]`** - This matches the same characters as `[:graph:]` plus space\n characters that are not controls, that is, characters with the Zs property.\n\n- **`[:punct:]`** - This matches all characters that have the Unicode P\n (punctuation) property, plus those characters whose code points are less than\n 128 that have the S (Symbol) property.\n\nThe other POSIX classes are unchanged, and match only characters with code\npoints less than 128.\n\n_Compatibility Feature for Word Boundaries_\n\nIn the POSIX.2 compliant library that was included in 4.4BSD Unix, the ugly\nsyntax `[[:<:]]` and `[[:>:]]` is used for matching \"start of word\" and \"end of\nword\". PCRE treats these items as follows:\n\n- **`[[:<:]]`** - is converted to `\\b(?=\\w)`\n\n- **`[[:>:]]`** - is converted to `\\b(?<=\\w)`\n\nOnly these exact character sequences are recognized. A sequence such as\n`[a[:<:]b]` provokes error for an unrecognized POSIX class name. This support is\nnot compatible with Perl. It is provided to help migrations from other\nenvironments, and is best not used in any new patterns. Note that `\\b` matches at\nthe start and the end of a word (see \"Simple assertions\" above), and in a\nPerl-style pattern the preceding or following character normally shows which is\nwanted, without the need for the assertions that are used above in order to give\nexactly the POSIX behaviour.\n\n[](){: #sect9 }","title":"Posix Character Classes - re","ref":"re.html#module-posix-character-classes"},{"type":"module","doc":"Vertical bar characters are used to separate alternative patterns. For example,\nthe following pattern matches either \"gilbert\" or \"sullivan\":\n\n```text\ngilbert|sullivan\n```\n\nAny number of alternatives can appear, and an empty alternative is permitted\n(matching the empty string). The matching process tries each alternative in\nturn, from left to right, and the first that succeeds is used. If the\nalternatives are within a subpattern (defined in section\n[Subpatterns](`m:re#sect11`)), \"succeeds\" means matching the remaining main\npattern and the alternative in the subpattern.\n\n[](){: #sect10 }","title":"Vertical Bar - re","ref":"re.html#module-vertical-bar"},{"type":"module","doc":"The settings of the Perl-compatible options `caseless`, `multiline`, `dotall`,\nand `extended` can be changed from within the pattern by a sequence of Perl\noption letters enclosed between \"(?\" and \")\". The option letters are as follows:\n\n- **i** - For `caseless`\n\n- **m** - For `multiline`\n\n- **s** - For `dotall`\n\n- **x** - For `extended`\n\nFor example, `(?im)` sets caseless, multiline matching. These options can also\nbe unset by preceding the letter with a hyphen. A combined setting and unsetting\nsuch as `(?im-sx)`, which sets `caseless` and `multiline`, while unsetting\n`dotall` and `extended`, is also permitted. If a letter appears both before and\nafter the hyphen, the option is unset.\n\nThe PCRE-specific options `dupnames`, `ungreedy`, and `extra` can be changed in\nthe same way as the Perl-compatible options by using the characters J, U, and X\nrespectively.\n\nWhen one of these option changes occurs at top-level (that is, not inside\nsubpattern parentheses), the change applies to the remainder of the pattern that\nfollows.\n\nAn option change within a subpattern (see section [Subpatterns](`m:re#sect11`))\naffects only that part of the subpattern that follows it. So, the following\nmatches abc and aBc and no other strings (assuming `caseless` is not used):\n\n```text\n(a(?i)b)c\n```\n\nBy this means, options can be made to have different settings in different parts\nof the pattern. Any changes made in one alternative do carry on into subsequent\nbranches within the same subpattern. For example:\n\n```text\n(a(?i)b|c)\n```\n\nmatches \"ab\", \"aB\", \"c\", and \"C\", although when matching \"C\" the first branch is\nabandoned before the option setting. This is because the effects of option\nsettings occur at compile time. There would be some weird behavior otherwise.\n\n> #### Note {: .info }\n>\n> Other PCRE-specific options can be set by the application when the compiling\n> or matching functions are called. Sometimes the pattern can contain special\n> leading sequences, such as (\\*CRLF), to override what the application has set\n> or what has been defaulted. Details are provided in section\n> [Newline Sequences](`m:re#newline_sequences`) earlier.\n>\n> The (*UTF8) and (*UCP) leading sequences can be used to set UTF and Unicode\n> property modes. They are equivalent to setting options `unicode` and `ucp`,\n> respectively. The (*UTF) sequence is a generic version that can be used with\n> any of the libraries. However, the application can set option `never_utf`,\n> which locks out the use of the (*UTF) sequences.\n\n[](){: #sect11 }","title":"Internal Option Setting - re","ref":"re.html#module-internal-option-setting"},{"type":"module","doc":"Subpatterns are delimited by parentheses (round brackets), which can be nested.\nTurning part of a pattern into a subpattern does two things:\n\n- **1.** - It localizes a set of alternatives. For example, the following\n pattern matches \"cataract\", \"caterpillar\", or \"cat\":\n\n ```text\n cat(aract|erpillar|)\n ```\n\n Without the parentheses, it would match \"cataract\", \"erpillar\", or an empty\n string.\n\n- **2.** - It sets up the subpattern as a capturing subpattern. That is, when\n the complete pattern matches, that portion of the subject string that matched\n the subpattern is passed back to the caller through the return value of\n `run/3`.\n\nOpening parentheses are counted from left to right (starting from 1) to obtain\nnumbers for the capturing subpatterns. For example, if the string \"the red king\"\nis matched against the following pattern, the captured substrings are \"red\nking\", \"red\", and \"king\", and are numbered 1, 2, and 3, respectively:\n\n```text\nthe ((red|white) (king|queen))\n```\n\nIt is not always helpful that plain parentheses fulfill two functions. Often a\ngrouping subpattern is required without a capturing requirement. If an opening\nparenthesis is followed by a question mark and a colon, the subpattern does not\ndo any capturing, and is not counted when computing the number of any subsequent\ncapturing subpatterns. For example, if the string \"the white queen\" is matched\nagainst the following pattern, the captured substrings are \"white queen\" and\n\"queen\", and are numbered 1 and 2:\n\n```text\nthe ((?:red|white) (king|queen))\n```\n\nThe maximum number of capturing subpatterns is 65535.\n\nAs a convenient shorthand, if any option settings are required at the start of a\nnon-capturing subpattern, the option letters can appear between \"?\" and \":\".\nThus, the following two patterns match the same set of strings:\n\n```text\n(?i:saturday|sunday)\n(?:(?i)saturday|sunday)\n```\n\nAs alternative branches are tried from left to right, and options are not reset\nuntil the end of the subpattern is reached, an option setting in one branch does\naffect subsequent branches, so the above patterns match both \"SUNDAY\" and\n\"Saturday\".\n\n[](){: #sect12 }","title":"Subpatterns - re","ref":"re.html#module-subpatterns"},{"type":"module","doc":"Perl 5.10 introduced a feature where each alternative in a subpattern uses the\nsame numbers for its capturing parentheses. Such a subpattern starts with `(?|`\nand is itself a non-capturing subpattern. For example, consider the following\npattern:\n\n```text\n(?|(Sat)ur|(Sun))day\n```\n\nAs the two alternatives are inside a `(?|` group, both sets of capturing\nparentheses are numbered one. Thus, when the pattern matches, you can look at\ncaptured substring number one, whichever alternative matched. This construct is\nuseful when you want to capture a part, but not all, of one of many\nalternatives. Inside a `(?|` group, parentheses are numbered as usual, but the\nnumber is reset at the start of each branch. The numbers of any capturing\nparentheses that follow the subpattern start after the highest number used in\nany branch. The following example is from the Perl documentation; the numbers\nunderneath show in which buffer the captured content is stored:\n\n```text\n# before ---------------branch-reset----------- after\n/ ( a ) (?| x ( y ) z | (p (q) r) | (t) u (v) ) ( z ) /x\n# 1 2 2 3 2 3 4\n```\n\nA back reference to a numbered subpattern uses the most recent value that is set\nfor that number by any subpattern. The following pattern matches \"abcabc\" or\n\"defdef\":\n\n```text\n/(?|(abc)|(def))\\1/\n```\n\nIn contrast, a subroutine call to a numbered subpattern always refers to the\nfirst one in the pattern with the given number. The following pattern matches\n\"abcabc\" or \"defabc\":\n\n```text\n/(?|(abc)|(def))(?1)/\n```\n\nIf a condition test for a subpattern having matched refers to a non-unique\nnumber, the test is true if any of the subpatterns of that number have matched.\n\nAn alternative approach using this \"branch reset\" feature is to use duplicate\nnamed subpatterns, as described in the next section.\n\n[](){: #sect13 }","title":"Duplicate Subpattern Numbers - re","ref":"re.html#module-duplicate-subpattern-numbers"},{"type":"module","doc":"Identifying capturing parentheses by number is simple, but it can be hard to\nkeep track of the numbers in complicated regular expressions. Also, if an\nexpression is modified, the numbers can change. To help with this difficulty,\nPCRE supports the naming of subpatterns. This feature was not added to Perl\nuntil release 5.10. Python had the feature earlier, and PCRE introduced it at\nrelease 4.0, using the Python syntax. PCRE now supports both the Perl and the\nPython syntax. Perl allows identically numbered subpatterns to have different\nnames, but PCRE does not.\n\nIn PCRE, a subpattern can be named in one of three ways: `(? ...)` or\n`(?'name'...)` as in Perl, or `(?P ...)` as in Python. References to\ncapturing parentheses from other parts of the pattern, such as back references,\nrecursion, and conditions, can be made by name and by number.\n\nNames consist of up to 32 alphanumeric characters and underscores, but must\nstart with a non-digit. Named capturing parentheses are still allocated numbers\nas well as names, exactly as if the names were not present. The `capture`\nspecification to `run/3` can use named values if they are present in the regular\nexpression.\n\nBy default, a name must be unique within a pattern, but this constraint can be\nrelaxed by setting option `dupnames` at compile time. (Duplicate names are also\nalways permitted for subpatterns with the same number, set up as described in\nthe previous section.) Duplicate names can be useful for patterns where only one\ninstance of the named parentheses can match. Suppose that you want to match the\nname of a weekday, either as a 3-letter abbreviation or as the full name, and in\nboth cases you want to extract the abbreviation. The following pattern (ignoring\nthe line breaks) does the job:\n\n```text\n(? Mon|Fri|Sun)(?:day)?|\n(? Tue)(?:sday)?|\n(? Wed)(?:nesday)?|\n(? Thu)(?:rsday)?|\n(? Sat)(?:urday)?\n```\n\nThere are five capturing substrings, but only one is ever set after a match. (An\nalternative way of solving this problem is to use a \"branch reset\" subpattern,\nas described in the previous section.)\n\nFor capturing named subpatterns which names are not unique, the first matching\noccurrence (counted from left to right in the subject) is returned from `run/3`,\nif the name is specified in the `values` part of the `capture` statement. The\n`all_names` capturing value matches all the names in the same way.\n\n> #### Note {: .info }\n>\n> You cannot use different names to distinguish between two subpatterns with the\n> same number, as PCRE uses only the numbers when matching. For this reason, an\n> error is given at compile time if different names are specified to subpatterns\n> with the same number. However, you can specify the same name to subpatterns\n> with the same number, even when `dupnames` is not set.\n\n[](){: #sect14 }","title":"Named Subpatterns - re","ref":"re.html#module-named-subpatterns"},{"type":"module","doc":"Repetition is specified by quantifiers, which can follow any of the following\nitems:\n\n- A literal data character\n- The dot metacharacter\n- The `\\C` escape sequence\n- The `\\X` escape sequence\n- The `\\R` escape sequence\n- An escape such as `\\d` or `\\pL` that matches a single character\n- A character class\n- A back reference (see the next section)\n- A parenthesized subpattern (including assertions)\n- A subroutine call to a subpattern (recursive or otherwise)\n\nThe general repetition quantifier specifies a minimum and maximum number of\npermitted matches, by giving the two numbers in curly brackets (braces),\nseparated by a comma. The numbers must be < 65536, and the first must be less\nthan or equal to the second. For example, the following matches \"zz\", \"zzz\", or\n\"zzzz\":\n\n```text\nz{2,4}\n```\n\nA closing brace on its own is not a special character. If the second number is\nomitted, but the comma is present, there is no upper limit. If the second number\nand the comma are both omitted, the quantifier specifies an exact number of\nrequired matches. Thus, the following matches at least three successive vowels,\nbut can match many more:\n\n```text\n[aeiou]{3,}\n```\n\nThe following matches exactly eight digits:\n\n```text\n\\d{8}\n```\n\nAn opening curly bracket that appears in a position where a quantifier is not\nallowed, or one that does not match the syntax of a quantifier, is taken as a\nliteral character. For example, \\{,6\\} is not a quantifier, but a literal string\nof four characters.\n\nIn Unicode mode, quantifiers apply to characters rather than to individual data\nunits. Thus, for example, `\\x{100}{2}` matches two characters, each of which\nis represented by a 2-byte sequence in a UTF-8 string. Similarly, `\\X{3}`\nmatches three Unicode extended grapheme clusters, each of which can be many data\nunits long (and they can be of different lengths).\n\nThe quantifier \\{0\\} is permitted, causing the expression to behave as if the\nprevious item and the quantifier were not present. This can be useful for\nsubpatterns that are referenced as subroutines from elsewhere in the pattern\n(but see also section\n[Defining Subpatterns for Use by Reference Only](`m:re#defining_subpatterns`)).\nItems other than subpatterns that have a \\{0\\} quantifier are omitted from the\ncompiled pattern.\n\nFor convenience, the three most common quantifiers have single-character\nabbreviations:\n\n- **\\*** - Equivalent to \\{0,\\}\n\n- **+** - Equivalent to \\{1,\\}\n\n- **?** - Equivalent to \\{0,1\\}\n\nInfinite loops can be constructed by following a subpattern that can match no\ncharacters with a quantifier that has no upper limit, for example:\n\n```text\n(a?)*\n```\n\nEarlier versions of Perl and PCRE used to give an error at compile time for such\npatterns. However, as there are cases where this can be useful, such patterns\nare now accepted. However, if any repetition of the subpattern matches no\ncharacters, the loop is forcibly broken.\n\nBy default, the quantifiers are \"greedy\", that is, they match as much as\npossible (up to the maximum number of permitted times), without causing the\nremaining pattern to fail. The classic example of where this gives problems is\nin trying to match comments in C programs. These appear between /_ and _/.\nWithin the comment, individual \\* and / characters can appear. An attempt to\nmatch C comments by applying the pattern\n\n```text\n/\\*.*\\*/\n```\n\nto the string\n\n```text\n/* first comment */ not comment /* second comment */\n```\n\nfails, as it matches the entire string owing to the greediness of the .\\* item.\n\nHowever, if a quantifier is followed by a question mark, it ceases to be greedy,\nand instead matches the minimum number of times possible, so the following\npattern does the right thing with the C comments:\n\n```text\n/\\*.*?\\*/\n```\n\nThe meaning of the various quantifiers is not otherwise changed, only the\npreferred number of matches. Do not confuse this use of question mark with its\nuse as a quantifier in its own right. As it has two uses, it can sometimes\nappear doubled, as in\n\n```text\n\\d??\\d\n```\n\nwhich matches one digit by preference, but can match two if that is the only way\nthe remaining pattern matches.\n\nIf option `ungreedy` is set (an option that is not available in Perl), the\nquantifiers are not greedy by default, but individual ones can be made greedy by\nfollowing them with a question mark. That is, it inverts the default behavior.\n\nWhen a parenthesized subpattern is quantified with a minimum repeat count that\nis > 1 or with a limited maximum, more memory is required for the compiled\npattern, in proportion to the size of the minimum or maximum.\n\nIf a pattern starts with .\\* or .\\{0,\\} and option `dotall` (equivalent to Perl\noption `/s`) is set, thus allowing the dot to match newlines, the pattern is\nimplicitly anchored, because whatever follows is tried against every character\nposition in the subject string. So, there is no point in retrying the overall\nmatch at any position after the first. PCRE normally treats such a pattern as if\nit was preceded by `\\A`.\n\nIn cases where it is known that the subject string contains no newlines, it is\nworth setting `dotall` to obtain this optimization, or alternatively using ^ to\nindicate anchoring explicitly.\n\nHowever, there are some cases where the optimization cannot be used. When .\\* is\ninside capturing parentheses that are the subject of a back reference elsewhere\nin the pattern, a match at the start can fail where a later one succeeds.\nConsider, for example:\n\n```text\n(.*)abc\\1\n```\n\nIf the subject is \"xyz123abc123\", the match point is the fourth character.\nTherefore, such a pattern is not implicitly anchored.\n\nAnother case where implicit anchoring is not applied is when the leading .\\* is\ninside an atomic group. Once again, a match at the start can fail where a later\none succeeds. Consider the following pattern:\n\n```text\n(?>.*?a)b\n```\n\nIt matches \"ab\" in the subject \"aab\". The use of the backtracking control verbs\n(*PRUNE) and (*SKIP) also disable this optimization.\n\nWhen a capturing subpattern is repeated, the value captured is the substring\nthat matched the final iteration. For example, after\n\n```text\n(tweedle[dume]{3}\\s*)+\n```\n\nhas matched \"tweedledum tweedledee\", the value of the captured substring is\n\"tweedledee\". However, if there are nested capturing subpatterns, the\ncorresponding captured values can have been set in previous iterations. For\nexample, after\n\n```text\n/(a|(b))+/\n```\n\nmatches \"aba\", the value of the second captured substring is \"b\".\n\n[](){: #sect15 }","title":"Repetition - re","ref":"re.html#module-repetition"},{"type":"module","doc":"With both maximizing (\"greedy\") and minimizing (\"ungreedy\" or \"lazy\")\nrepetition, failure of what follows normally causes the repeated item to be\nre-evaluated to see if a different number of repeats allows the remaining\npattern to match. Sometimes it is useful to prevent this, either to change the\nnature of the match, or to cause it to fail earlier than it otherwise might,\nwhen the author of the pattern knows that there is no point in carrying on.\n\nConsider, for example, the pattern `\\d+foo` when applied to the following subject\nline:\n\n```text\n123456bar\n```\n\nAfter matching all six digits and then failing to match \"foo\", the normal action\nof the matcher is to try again with only five digits matching item `\\d+`, and\nthen with four, and so on, before ultimately failing. \"Atomic grouping\" (a term\ntaken from Jeffrey Friedl's book) provides the means for specifying that once a\nsubpattern has matched, it is not to be re-evaluated in this way.\n\nIf atomic grouping is used for the previous example, the matcher gives up\nimmediately on failing to match \"foo\" the first time. The notation is a kind of\nspecial parenthesis, starting with `(?>` as in the following example:\n\n```text\n(?>\\d+)foo\n```\n\nThis kind of parenthesis \"locks up\" the part of the pattern it contains once it\nhas matched, and a failure further into the pattern is prevented from\nbacktracking into it. Backtracking past it to previous items, however, works as\nnormal.\n\nAn alternative description is that a subpattern of this type matches the string\nof characters that an identical standalone pattern would match, if anchored at\nthe current point in the subject string.\n\nAtomic grouping subpatterns are not capturing subpatterns. Simple cases such as\nthe above example can be thought of as a maximizing repeat that must swallow\neverything it can. So, while both `\\d+` and `\\d+?` are prepared to adjust the\nnumber of digits they match to make the remaining pattern match, `(?>\\d+)` can\nonly match an entire sequence of digits.\n\nAtomic groups in general can contain any complicated subpatterns, and can be\nnested. However, when the subpattern for an atomic group is just a single\nrepeated item, as in the example above, a simpler notation, called a \"possessive\nquantifier\" can be used. This consists of an extra + character following a\nquantifier. Using this notation, the previous example can be rewritten as\n\n```text\n\\d++foo\n```\n\nNotice that a possessive quantifier can be used with an entire group, for\nexample:\n\n```text\n(abc|xyz){2,3}+\n```\n\nPossessive quantifiers are always greedy; the setting of option `ungreedy` is\nignored. They are a convenient notation for the simpler forms of an atomic\ngroup. However, there is no difference in the meaning of a possessive quantifier\nand the equivalent atomic group, but there can be a performance difference;\npossessive quantifiers are probably slightly faster.\n\nThe possessive quantifier syntax is an extension to the Perl 5.8 syntax. Jeffrey\nFriedl originated the idea (and the name) in the first edition of his book. Mike\nMcCloskey liked it, so implemented it when he built the Sun Java package, and\nPCRE copied it from there. It ultimately found its way into Perl at release\n5.10.\n\nPCRE has an optimization that automatically \"possessifies\" certain simple\npattern constructs. For example, the sequence A+B is treated as A++B, as there\nis no point in backtracking into a sequence of A:s when B must follow.\n\nWhen a pattern contains an unlimited repeat inside a subpattern that can itself\nbe repeated an unlimited number of times, the use of an atomic group is the only\nway to avoid some failing matches taking a long time. The pattern\n\n```text\n(\\D+|<\\d+>)*[!?]\n```\n\nmatches an unlimited number of substrings that either consist of non-digits, or\ndigits enclosed in `<>`, followed by `!` or `?`. When it matches, it runs quickly.\nHowever, if it is applied to\n\n```text\naaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n```\n\nit takes a long time before reporting failure. This is because the string can be\ndivided between the internal `\\D+` repeat and the external \\* repeat in many\nways, and all must be tried. (The example uses `[!?]` rather than a single\ncharacter at the end, as both PCRE and Perl have an optimization that allows for\nfast failure when a single character is used. They remember the last single\ncharacter that is required for a match, and fail early if it is not present in\nthe string.) If the pattern is changed so that it uses an atomic group, like the\nfollowing, sequences of non-digits cannot be broken, and failure happens\nquickly:\n\n```text\n((?>\\D+)|<\\d+>)*[!?]\n```\n\n[](){: #sect16 }","title":"Atomic Grouping and Possessive Quantifiers - re","ref":"re.html#module-atomic-grouping-and-possessive-quantifiers"},{"type":"module","doc":"Outside a character class, a backslash followed by a digit > 0 (and possibly\nfurther digits) is a back reference to a capturing subpattern earlier (that is,\nto its left) in the pattern, provided there have been that many previous\ncapturing left parentheses.\n\nHowever, if the decimal number following the backslash is < 10, it is always\ntaken as a back reference, and causes an error only if there are not that many\ncapturing left parentheses in the entire pattern. That is, the parentheses that\nare referenced do need not be to the left of the reference for numbers < 10. A\n\"forward back reference\" of this type can make sense when a repetition is\ninvolved and the subpattern to the right has participated in an earlier\niteration.\n\nIt is not possible to have a numerical \"forward back reference\" to a subpattern\nwhose number is 10 or more using this syntax, as a sequence such as `\\50` is\ninterpreted as a character defined in octal. For more details of the handling of\ndigits following a backslash, see section\n[Non-Printing Characters](`m:re#non_printing_characters`) earlier. There is no\nsuch problem when named parentheses are used. A back reference to any subpattern\nis possible using named parentheses (see below).\n\nAnother way to avoid the ambiguity inherent in the use of digits following a\nbackslash is to use the `\\g` escape sequence. This escape must be followed by an\nunsigned number or a negative number, optionally enclosed in braces. The\nfollowing examples are identical:\n\n```text\n(ring), \\1\n(ring), \\g1\n(ring), \\g{1}\n```\n\nAn unsigned number specifies an absolute reference without the ambiguity that is\npresent in the older syntax. It is also useful when literal digits follow the\nreference. A negative number is a relative reference. Consider the following\nexample:\n\n```text\n(abc(def)ghi)\\g{-1}\n```\n\nThe sequence `\\g{-1}` is a reference to the most recently started capturing\nsubpattern before `\\g`, that is, it is equivalent to `\\2` in this example.\nSimilarly, `\\g{-2}` would be equivalent to `\\1`. The use of relative references\ncan be helpful in long patterns, and also in patterns that are created by\njoining fragments containing references within themselves.\n\nA back reference matches whatever matched the capturing subpattern in the\ncurrent subject string, rather than anything matching the subpattern itself\n(section [Subpattern as Subroutines](`m:re#sect21`) describes a way of doing\nthat). So, the following pattern matches \"sense and sensibility\" and \"response\nand responsibility\", but not \"sense and responsibility\":\n\n```text\n(sens|respons)e and \\1ibility\n```\n\nIf caseful matching is in force at the time of the back reference, the case of\nletters is relevant. For example, the following matches \"rah rah\" and \"RAH RAH\",\nbut not \"RAH rah\", although the original capturing subpattern is matched\ncaselessly:\n\n```text\n((?i)rah)\\s+\\1\n```\n\nThere are many different ways of writing back references to named subpatterns.\nThe .NET syntax `\\k{name}` and the Perl syntax `\\k ` or `\\k'name'` are\nsupported, as is the Python syntax `(?P=name)`. The unified back reference\nsyntax in Perl 5.10, in which `\\g` can be used for both numeric and named\nreferences, is also supported. The previous example can be rewritten in the\nfollowing ways:\n\n```text\n(? (?i)rah)\\s+\\k \n(?'p1'(?i)rah)\\s+\\k{p1}\n(?P (?i)rah)\\s+(?P=p1)\n(? (?i)rah)\\s+\\g{p1}\n```\n\nA subpattern that is referenced by name can appear in the pattern before or\nafter the reference.\n\nThere can be more than one back reference to the same subpattern. If a\nsubpattern has not been used in a particular match, any back references to it\nalways fails. For example, the following pattern always fails if it starts to\nmatch \"a\" rather than \"bc\":\n\n```text\n(a|(bc))\\2\n```\n\nAs there can be many capturing parentheses in a pattern, all digits following\nthe backslash are taken as part of a potential back reference number. If the\npattern continues with a digit character, some delimiter must be used to\nterminate the back reference. If option `extended` is set, this can be\nwhitespace. Otherwise an empty comment (see section [Comments](`m:re#sect19`))\ncan be used.\n\n_Recursive Back References_\n\nA back reference that occurs inside the parentheses to which it refers fails\nwhen the subpattern is first used, so, for example, (`a\\1`) never matches.\nHowever, such references can be useful inside repeated subpatterns. For example,\nthe following pattern matches any number of \"a\"s and also \"aba\", \"ababbaa\", and\nso on:\n\n```text\n(a|b\\1)+\n```\n\nAt each iteration of the subpattern, the back reference matches the character\nstring corresponding to the previous iteration. In order for this to work, the\npattern must be such that the first iteration does not need to match the back\nreference. This can be done using alternation, as in the example above, or by a\nquantifier with a minimum of zero.\n\nBack references of this type cause the group that they reference to be treated\nas an atomic group. Once the whole group has been matched, a subsequent matching\nfailure cannot cause backtracking into the middle of the group.\n\n[](){: #sect17 }","title":"Back References - re","ref":"re.html#module-back-references"},{"type":"module","doc":"An assertion is a test on the characters following or preceding the current\nmatching point that does not consume any characters. The simple assertions coded\nas `\\b`, `\\B`, `\\A`, `\\G`, `\\Z`, `\\z`, `^`, and `$` are described in the previous\nsections.\n\nMore complicated assertions are coded as subpatterns. There are two kinds: those\nthat look ahead of the current position in the subject string, and those that\nlook behind it. An assertion subpattern is matched in the normal way, except\nthat it does not cause the current matching position to be changed.\n\nAssertion subpatterns are not capturing subpatterns. If such an assertion\ncontains capturing subpatterns within it, these are counted for the purposes of\nnumbering the capturing subpatterns in the whole pattern. However, substring\ncapturing is done only for positive assertions. (Perl sometimes, but not always,\nperforms capturing in negative assertions.)\n\n> #### Warning {: .warning }\n>\n> If a positive assertion containing one or more capturing subpatterns succeeds,\n> but failure to match later in the pattern causes backtracking over this\n> assertion, the captures within the assertion are reset only if no higher\n> numbered captures are already set. This is, unfortunately, a fundamental\n> limitation of the current implementation, and as PCRE1 is now in\n> maintenance-only status, it is unlikely ever to change.\n\nFor compatibility with Perl, assertion subpatterns can be repeated. However, it\nmakes no sense to assert the same thing many times, the side effect of capturing\nparentheses can occasionally be useful. In practice, there are only three cases:\n\n- If the quantifier is \\{0\\}, the assertion is never obeyed during matching.\n However, it can contain internal capturing parenthesized groups that are\n called from elsewhere through the subroutine mechanism.\n- If quantifier is \\{0,n\\}, where n > 0, it is treated as if it was \\{0,1\\}. At\n runtime, the remaining pattern match is tried with and without the assertion,\n the order depends on the greediness of the quantifier.\n- If the minimum repetition is > 0, the quantifier is ignored. The assertion is\n obeyed only once when encountered during matching.\n\n_Lookahead Assertions_\n\nLookahead assertions start with (?= for positive assertions and (?\\! for\nnegative assertions. For example, the following matches a word followed by a\nsemicolon, but does not include the semicolon in the match:\n\n```text\n\\w+(?=;)\n```\n\nThe following matches any occurrence of \"foo\" that is not followed by \"bar\":\n\n```text\nfoo(?!bar)\n```\n\nNotice that the apparently similar pattern\n\n```text\n(?!foo)bar\n```\n\ndoes not find an occurrence of \"bar\" that is preceded by something other than\n\"foo\". It finds any occurrence of \"bar\" whatsoever, as the assertion (?\\!foo) is\nalways true when the next three characters are \"bar\". A lookbehind assertion is\nneeded to achieve the other effect.\n\nIf you want to force a matching failure at some point in a pattern, the most\nconvenient way to do it is with (?\\!), as an empty string always matches. So, an\nassertion that requires there is not to be an empty string must always fail. The\nbacktracking control verb (*FAIL) or (*F) is a synonym for (?\\!).\n\n_Lookbehind Assertions_\n\nLookbehind assertions start with (?<= for positive assertions and (?<\\! for\nnegative assertions. For example, the following finds an occurrence of \"bar\"\nthat is not preceded by \"foo\":\n\n```text\n(?[^()]+) | (?p{$re}) )* \\)}x;\n```\n\nItem (?p\\{...\\}) interpolates Perl code at runtime, and in this case refers\nrecursively to the pattern in which it appears.\n\nObviously, PCRE cannot support the interpolation of Perl code. Instead, it\nsupports special syntax for recursion of the entire pattern, and for individual\nsubpattern recursion. After its introduction in PCRE and Python, this kind of\nrecursion was later introduced into Perl at release 5.10.\n\nA special item that consists of (? followed by a number > 0 and a closing\nparenthesis is a recursive subroutine call of the subpattern of the given\nnumber, if it occurs inside that subpattern. (If not, it is a non-recursive\nsubroutine call, which is described in the next section.) The special item (?R)\nor (?0) is a recursive call of the entire regular expression.\n\nThis PCRE pattern solves the nested parentheses problem (assume that option\n`extended` is set so that whitespace is ignored):\n\n```text\n\\( ( [^()]++ | (?R) )* \\)\n```\n\nFirst it matches an opening parenthesis. Then it matches any number of\nsubstrings, which can either be a sequence of non-parentheses or a recursive\nmatch of the pattern itself (that is, a correctly parenthesized substring).\nFinally there is a closing parenthesis. Notice the use of a possessive\nquantifier to avoid backtracking into sequences of non-parentheses.\n\nIf this was part of a larger pattern, you would not want to recurse the entire\npattern, so instead you can use:\n\n```text\n( \\( ( [^()]++ | (?1) )* \\) )\n```\n\nThe pattern is here within parentheses so that the recursion refers to them\ninstead of the whole pattern.\n\nIn a larger pattern, keeping track of parenthesis numbers can be tricky. This is\nmade easier by the use of relative references. Instead of (?1) in the pattern\nabove, you can write (?-2) to refer to the second most recently opened\nparentheses preceding the recursion. That is, a negative number counts capturing\nparentheses leftwards from the point at which it is encountered.\n\nIt is also possible to refer to later opened parentheses, by writing references\nsuch as (?+2). However, these cannot be recursive, as the reference is not\ninside the parentheses that are referenced. They are always non-recursive\nsubroutine calls, as described in the next section.\n\nAn alternative approach is to use named parentheses instead. The Perl syntax for\nthis is (?&name). The earlier PCRE syntax (?P>name) is also supported. We can\nrewrite the above example as follows:\n\n```text\n(? \\( ( [^()]++ | (?&pn) )* \\) )\n```\n\nIf there is more than one subpattern with the same name, the earliest one is\nused.\n\nThis particular example pattern that we have studied contains nested unlimited\nrepeats, and so the use of a possessive quantifier for matching strings of\nnon-parentheses is important when applying the pattern to strings that do not\nmatch. For example, when this pattern is applied to\n\n```text\n(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa()\n```\n\nit gives \"no match\" quickly. However, if a possessive quantifier is not used,\nthe match runs for a long time, as there are so many different ways the + and \\*\nrepeats can carve up the subject, and all must be tested before failure can be\nreported.\n\nAt the end of a match, the values of capturing parentheses are those from the\noutermost level. If the pattern above is matched against\n\n```text\n(ab(cd)ef)\n```\n\nthe value for the inner capturing parentheses (numbered 2) is \"ef\", which is the\nlast value taken on at the top-level. If a capturing subpattern is not matched\nat the top level, its final captured value is unset, even if it was\n(temporarily) set at a deeper level during the matching process.\n\nDo not confuse item (?R) with condition (R), which tests for recursion. Consider\nthe following pattern, which matches text in angle brackets, allowing for\narbitrary nesting. Only digits are allowed in nested brackets (that is, when\nrecursing), while any characters are permitted at the outer level.\n\n```text\n< (?: (?(R) \\d++ | [^<>]*+) | (?R)) * >\n```\n\nHere (?(R) is the start of a conditional subpattern, with two different\nalternatives for the recursive and non-recursive cases. Item (?R) is the actual\nrecursive call.\n\n_Differences in Recursion Processing between PCRE and Perl_\n\nRecursion processing in PCRE differs from Perl in two important ways. In PCRE\n(like Python, but unlike Perl), a recursive subpattern call is always treated as\nan atomic group. That is, once it has matched some of the subject string, it is\nnever re-entered, even if it contains untried alternatives and there is a\nsubsequent matching failure. This can be illustrated by the following pattern,\nwhich means to match a palindromic string containing an odd number of characters\n(for example, \"a\", \"aba\", \"abcba\", \"abcdcba\"):\n\n```text\n^(.|(.)(?1)\\2)$\n```\n\nThe idea is that it either matches a single character, or two identical\ncharacters surrounding a subpalindrome. In Perl, this pattern works; in PCRE it\ndoes not work if the pattern is longer than three characters. Consider the\nsubject string \"abcba\".\n\nAt the top level, the first character is matched, but as it is not at the end of\nthe string, the first alternative fails, the second alternative is taken, and\nthe recursion kicks in. The recursive call to subpattern 1 successfully matches\nthe next character (\"b\"). (Notice that the beginning and end of line tests are\nnot part of the recursion.)\n\nBack at the top level, the next character (\"c\") is compared with what subpattern\n2 matched, which was \"a\". This fails. As the recursion is treated as an atomic\ngroup, there are now no backtracking points, and so the entire match fails.\n(Perl can now re-enter the recursion and try the second alternative.) However,\nif the pattern is written with the alternatives in the other order, things are\ndifferent:\n\n```text\n^((.)(?1)\\2|.)$\n```\n\nThis time, the recursing alternative is tried first, and continues to recurse\nuntil it runs out of characters, at which point the recursion fails. But this\ntime we have another alternative to try at the higher level. That is the\nsignificant difference: in the previous case the remaining alternative is at a\ndeeper recursion level, which PCRE cannot use.\n\nTo change the pattern so that it matches all palindromic strings, not only those\nwith an odd number of characters, it is tempting to change the pattern to this:\n\n```text\n^((.)(?1)\\2|.?)$\n```\n\nAgain, this works in Perl, but not in PCRE, and for the same reason. When a\ndeeper recursion has matched a single character, it cannot be entered again to\nmatch an empty string. The solution is to separate the two cases, and write out\nthe odd and even cases as alternatives at the higher level:\n\n```text\n^(?:((.)(?1)\\2|)|((.)(?3)\\4|.))\n```\n\nIf you want to match typical palindromic phrases, the pattern must ignore all\nnon-word characters, which can be done as follows:\n\n```text\n^\\W*+(?:((.)\\W*+(?1)\\W*+\\2|)|((.)\\W*+(?3)\\W*+\\4|\\W*+.\\W*+))\\W*+$\n```\n\nIf run with option `caseless`, this pattern matches phrases such as \"A man, a\nplan, a canal: Panama\\!\" and it works well in both PCRE and Perl. Notice the use\nof the possessive quantifier \\*+ to avoid backtracking into sequences of\nnon-word characters. Without this, PCRE takes much longer (10 times or more) to\nmatch typical phrases, and Perl takes so long that you think it has gone into a\nloop.\n\n> #### Note {: .info }\n>\n> The palindrome-matching patterns above work only if the subject string does\n> not start with a palindrome that is shorter than the entire string. For\n> example, although \"abcba\" is correctly matched, if the subject is \"ababa\",\n> PCRE finds palindrome \"aba\" at the start, and then fails at top level, as the\n> end of the string does not follow. Once again, it cannot jump back into the\n> recursion to try other alternatives, so the entire match fails.\n\nThe second way in which PCRE and Perl differ in their recursion processing is in\nthe handling of captured values. In Perl, when a subpattern is called\nrecursively or as a subpattern (see the next section), it has no access to any\nvalues that were captured outside the recursion. In PCRE these values can be\nreferenced. Consider the following pattern:\n\n```text\n^(.)(\\1|a(?2))\n```\n\nIn PCRE, it matches \"bab\". The first capturing parentheses match \"b\", then in\nthe second group, when the back reference `\\1` fails to match \"b\", the second\nalternative matches \"a\", and then recurses. In the recursion, `\\1` does now match\n\"b\" and so the whole match succeeds. In Perl, the pattern fails to match because\ninside the recursive call `\\1` cannot access the externally set value.\n\n[](){: #sect21 }","title":"Recursive Patterns - re","ref":"re.html#module-recursive-patterns"},{"type":"module","doc":"If the syntax for a recursive subpattern call (either by number or by name) is\nused outside the parentheses to which it refers, it operates like a subroutine\nin a programming language. The called subpattern can be defined before or after\nthe reference. A numbered reference can be absolute or relative, as in the\nfollowing examples:\n\n```text\n(...(absolute)...)...(?2)...\n(...(relative)...)...(?-1)...\n(...(?+1)...(relative)...\n```\n\nAn earlier example pointed out that the following pattern matches \"sense and\nsensibility\" and \"response and responsibility\", but not \"sense and\nresponsibility\":\n\n```text\n(sens|respons)e and \\1ibility\n```\n\nIf instead the following pattern is used, it matches \"sense and responsibility\"\nand the other two strings:\n\n```text\n(sens|respons)e and (?1)ibility\n```\n\nAnother example is provided in the discussion of DEFINE earlier.\n\nAll subroutine calls, recursive or not, are always treated as atomic groups.\nThat is, once a subroutine has matched some of the subject string, it is never\nre-entered, even if it contains untried alternatives and there is a subsequent\nmatching failure. Any capturing parentheses that are set during the subroutine\ncall revert to their previous values afterwards.\n\nProcessing options such as case-independence are fixed when a subpattern is\ndefined, so if it is used as a subroutine, such options cannot be changed for\ndifferent calls. For example, the following pattern matches \"abcabc\" but not\n\"abcABC\", as the change of processing option does not affect the called\nsubpattern:\n\n```text\n(abc)(?i:(?-1))\n```\n\n[](){: #sect22 }","title":"Subpatterns as Subroutines - re","ref":"re.html#module-subpatterns-as-subroutines"},{"type":"module","doc":"For compatibility with Oniguruma, the non-Perl syntax `\\g` followed by a name or\na number enclosed either in angle brackets or single quotes, is alternative\nsyntax for referencing a subpattern as a subroutine, possibly recursively. Here\nfollows two of the examples used above, rewritten using this syntax:\n\n```text\n(? \\( ( (?>[^()]+) | \\g )* \\) )\n(sens|respons)e and \\g'1'ibility\n```\n\nPCRE supports an extension to Oniguruma: if a number is preceded by a plus or\nminus sign, it is taken as a relative reference, for example:\n\n```text\n(abc)(?i:\\g<-1>)\n```\n\nNotice that `\\g{...}` (Perl syntax) and `\\g<...>` (Oniguruma syntax) are _not_\nsynonymous. The former is a back reference; the latter is a subroutine call.\n\n[](){: #sect23 }","title":"Oniguruma Subroutine Syntax - re","ref":"re.html#module-oniguruma-subroutine-syntax"},{"type":"module","doc":"Perl 5.10 introduced some \"Special Backtracking Control Verbs\", which are still\ndescribed in the Perl documentation as \"experimental and subject to change or\nremoval in a future version of Perl\". It goes on to say: \"Their usage in\nproduction code should be noted to avoid problems during upgrades.\" The same\nremarks apply to the PCRE features described in this section.\n\nThe new verbs make use of what was previously invalid syntax: an opening\nparenthesis followed by an asterisk. They are generally of the form (*VERB) or\n(*VERB:NAME). Some can take either form, possibly behaving differently depending\non whether a name is present. A name is any sequence of characters that does not\ninclude a closing parenthesis. The maximum name length is 255 in the 8-bit\nlibrary and 65535 in the 16-bit and 32-bit libraries. If the name is empty, that\nis, if the closing parenthesis immediately follows the colon, the effect is as\nif the colon was not there. Any number of these verbs can occur in a pattern.\n\nThe behavior of these verbs in repeated groups, assertions, and in subpatterns\ncalled as subroutines (whether or not recursively) is described below.\n\n_Optimizations That Affect Backtracking Verbs_\n\nPCRE contains some optimizations that are used to speed up matching by running\nsome checks at the start of each match attempt. For example, it can know the\nminimum length of matching subject, or that a particular character must be\npresent. When one of these optimizations bypasses the running of a match, any\nincluded backtracking verbs are not processed. processed. You can suppress the\nstart-of-match optimizations by setting option `no_start_optimize` when calling\n`compile/2` or `run/3`, or by starting the pattern with (\\*NO_START_OPT).\n\nExperiments with Perl suggest that it too has similar optimizations, sometimes\nleading to anomalous results.\n\n_Verbs That Act Immediately_\n\nThe following verbs act as soon as they are encountered. They must not be\nfollowed by a name.\n\n```text\n(*ACCEPT)\n```\n\nThis verb causes the match to end successfully, skipping the remainder of the\npattern. However, when it is inside a subpattern that is called as a subroutine,\nonly that subpattern is ended successfully. Matching then continues at the outer\nlevel. If (\\*ACCEPT) is triggered in a positive assertion, the assertion\nsucceeds; in a negative assertion, the assertion fails.\n\nIf (\\*ACCEPT) is inside capturing parentheses, the data so far is captured. For\nexample, the following matches \"AB\", \"AAD\", or \"ACD\". When it matches \"AB\", \"B\"\nis captured by the outer parentheses.\n\n```text\nA((?:A|B(*ACCEPT)|C)D)\n```\n\nThe following verb causes a matching failure, forcing backtracking to occur. It\nis equivalent to (?\\!) but easier to read.\n\n```text\n(*FAIL) or (*F)\n```\n\nThe Perl documentation states that it is probably useful only when combined with\n(?\\{\\}) or (??\\{\\}). Those are Perl features that are not present in PCRE.\n\nA match with the string \"aaaa\" always fails, but the callout is taken before\neach backtrack occurs (in this example, 10 times).\n\n_Recording Which Path Was Taken_\n\nThe main purpose of this verb is to track how a match was arrived at, although\nit also has a secondary use in with advancing the match starting point (see\n(\\*SKIP) below).\n\n> #### Note {: .info }\n>\n> In Erlang, there is no interface to retrieve a mark with [`run/2,3`](`run/2`),\n> so only the secondary purpose is relevant to the Erlang programmer.\n>\n> The rest of this section is therefore deliberately not adapted for reading by\n> the Erlang programmer, but the examples can help in understanding NAMES as\n> they can be used by (\\*SKIP).\n\n```text\n(*MARK:NAME) or (*:NAME)\n```\n\nA name is always required with this verb. There can be as many instances of\n(\\*MARK) as you like in a pattern, and their names do not have to be unique.\n\nWhen a match succeeds, the name of the last encountered (*MARK:NAME),\n(*PRUNE:NAME), or (*THEN:NAME) on the matching path is passed back to the caller\nas described in section \"Extra data for `pcre_exec()`\" in the `pcreapi`\ndocumentation. In the following example of `pcretest` output, the /K modifier\nrequests the retrieval and outputting of (*MARK) data:\n\n```text\nre> /X(*MARK:A)Y|X(*MARK:B)Z/K\ndata> XY\n 0: XY\nMK: A\nXZ\n 0: XZ\nMK: B\n```\n\nThe (\\*MARK) name is tagged with \"MK:\" in this output, and in this example it\nindicates which of the two alternatives matched. This is a more efficient way of\nobtaining this information than putting each alternative in its own capturing\nparentheses.\n\nIf a verb with a name is encountered in a positive assertion that is true, the\nname is recorded and passed back if it is the last encountered. This does not\noccur for negative assertions or failing positive assertions.\n\nAfter a partial match or a failed match, the last encountered name in the entire\nmatch process is returned, for example:\n\n```text\nre> /X(*MARK:A)Y|X(*MARK:B)Z/K\ndata> XP\nNo match, mark = B\n```\n\nNotice that in this unanchored example, the mark is retained from the match\nattempt that started at letter \"X\" in the subject. Subsequent match attempts\nstarting at \"P\" and then with an empty string do not get as far as the (\\*MARK)\nitem, nevertheless do not reset it.\n\n_Verbs That Act after Backtracking_\n\nThe following verbs do nothing when they are encountered. Matching continues\nwith what follows, but if there is no subsequent match, causing a backtrack to\nthe verb, a failure is forced. That is, backtracking cannot pass to the left of\nthe verb. However, when one of these verbs appears inside an atomic group or an\nassertion that is true, its effect is confined to that group, as once the group\nhas been matched, there is never any backtracking into it. In this situation,\nbacktracking can \"jump back\" to the left of the entire atomic group or\nassertion. (Remember also, as stated above, that this localization also applies\nin subroutine calls.)\n\nThese verbs differ in exactly what kind of failure occurs when backtracking\nreaches them. The behavior described below is what occurs when the verb is not\nin a subroutine or an assertion. Subsequent sections cover these special cases.\n\nThe following verb, which must not be followed by a name, causes the whole match\nto fail outright if there is a later matching failure that causes backtracking\nto reach it. Even if the pattern is unanchored, no further attempts to find a\nmatch by advancing the starting point take place.\n\n```text\n(*COMMIT)\n```\n\nIf (\\*COMMIT) is the only backtracking verb that is encountered, once it has\nbeen passed, [`run/2,3`](`run/2`) is committed to find a match at the current\nstarting point, or not at all, for example:\n\n```text\na+(*COMMIT)b\n```\n\nThis matches \"xxaab\" but not \"aacaab\". It can be thought of as a kind of dynamic\nanchor, or \"I've started, so I must finish\". The name of the most recently\npassed (*MARK) in the path is passed back when (*COMMIT) forces a match failure.\n\nIf more than one backtracking verb exists in a pattern, a different one that\nfollows (*COMMIT) can be triggered first, so merely passing (*COMMIT) during a\nmatch does not always guarantee that a match must be at this starting point.\n\nNotice that (\\*COMMIT) at the start of a pattern is not the same as an anchor,\nunless the PCRE start-of-match optimizations are turned off, as shown in the\nfollowing example:\n\n```erlang\n1> re:run(\"xyzabc\",\"(*COMMIT)abc\",[{capture,all,list}]).\n{match,[\"abc\"]}\n2> re:run(\"xyzabc\",\"(*COMMIT)abc\",[{capture,all,list},no_start_optimize]).\nnomatch\n```\n\nFor this pattern, PCRE knows that any match must start with \"a\", so the\noptimization skips along the subject to \"a\" before applying the pattern to the\nfirst set of data. The match attempt then succeeds. In the second call the\n`no_start_optimize` disables the optimization that skips along to the first\ncharacter. The pattern is now applied starting at \"x\", and so the (\\*COMMIT)\ncauses the match to fail without trying any other starting points.\n\nThe following verb causes the match to fail at the current starting position in\nthe subject if there is a later matching failure that causes backtracking to\nreach it:\n\n```text\n(*PRUNE) or (*PRUNE:NAME)\n```\n\nIf the pattern is unanchored, the normal \"bumpalong\" advance to the next\nstarting character then occurs. Backtracking can occur as usual to the left of\n(*PRUNE), before it is reached, or when matching to the right of (*PRUNE), but\nif there is no match to the right, backtracking cannot cross (*PRUNE). In simple\ncases, the use of (*PRUNE) is just an alternative to an atomic group or\npossessive quantifier, but there are some uses of (*PRUNE) that cannot be\nexpressed in any other way. In an anchored pattern, (*PRUNE) has the same effect\nas (\\*COMMIT).\n\nThe behavior of (*PRUNE:NAME) is the not the same as (*MARK:NAME)(*PRUNE). It is\nlike (*MARK:NAME) in that the name is remembered for passing back to the caller.\nHowever, (*SKIP:NAME) searches only for names set with (*MARK).\n\n> #### Note {: .info }\n>\n> The fact that (\\*PRUNE:NAME) remembers the name is useless to the Erlang\n> programmer, as names cannot be retrieved.\n\nThe following verb, when specified without a name, is like (*PRUNE), except that\nif the pattern is unanchored, the \"bumpalong\" advance is not to the next\ncharacter, but to the position in the subject where (*SKIP) was encountered.\n\n```text\n(*SKIP)\n```\n\n(\\*SKIP) signifies that whatever text was matched leading up to it cannot be\npart of a successful match. Consider:\n\n```text\na+(*SKIP)b\n```\n\nIf the subject is \"aaaac...\", after the first match attempt fails (starting at\nthe first character in the string), the starting point skips on to start the\nnext attempt at \"c\". Notice that a possessive quantifier does not have the same\neffect as this example; although it would suppress backtracking during the first\nmatch attempt, the second attempt would start at the second character instead of\nskipping on to \"c\".\n\nWhen (\\*SKIP) has an associated name, its behavior is modified:\n\n```text\n(*SKIP:NAME)\n```\n\nWhen this is triggered, the previous path through the pattern is searched for\nthe most recent (*MARK) that has the same name. If one is found, the \"bumpalong\"\nadvance is to the subject position that corresponds to that (*MARK) instead of\nto where (*SKIP) was encountered. If no (*MARK) with a matching name is found,\n(\\*SKIP) is ignored.\n\nNotice that (*SKIP:NAME) searches only for names set by (*MARK:NAME). It ignores\nnames that are set by (*PRUNE:NAME) or (*THEN:NAME).\n\nThe following verb causes a skip to the next innermost alternative when\nbacktracking reaches it. That is, it cancels any further backtracking within the\ncurrent alternative.\n\n```text\n(*THEN) or (*THEN:NAME)\n```\n\nThe verb name comes from the observation that it can be used for a pattern-based\nif-then-else block:\n\n```text\n( COND1 (*THEN) FOO | COND2 (*THEN) BAR | COND3 (*THEN) BAZ ) ...\n```\n\nIf the COND1 pattern matches, FOO is tried (and possibly further items after the\nend of the group if FOO succeeds). On failure, the matcher skips to the second\nalternative and tries COND2, without backtracking into COND1. If that succeeds\nand BAR fails, COND3 is tried. If BAZ then fails, there are no more\nalternatives, so there is a backtrack to whatever came before the entire group.\nIf (*THEN) is not inside an alternation, it acts like (*PRUNE).\n\nThe behavior of (*THEN:NAME) is the not the same as (*MARK:NAME)(*THEN). It is\nlike (*MARK:NAME) in that the name is remembered for passing back to the caller.\nHowever, (*SKIP:NAME) searches only for names set with (*MARK).\n\n> #### Note {: .info }\n>\n> The fact that (\\*THEN:NAME) remembers the name is useless to the Erlang\n> programmer, as names cannot be retrieved.\n\nA subpattern that does not contain a | character is just a part of the enclosing\nalternative; it is not a nested alternation with only one alternative. The\neffect of (\\*THEN) extends beyond such a subpattern to the enclosing\nalternative. Consider the following pattern, where A, B, and so on, are complex\npattern fragments that do not contain any | characters at this level:\n\n```text\nA (B(*THEN)C) | D\n```\n\nIf A and B are matched, but there is a failure in C, matching does not backtrack\ninto A; instead it moves to the next alternative, that is, D. However, if the\nsubpattern containing (\\*THEN) is given an alternative, it behaves differently:\n\n```text\nA (B(*THEN)C | (*FAIL)) | D\n```\n\nThe effect of (*THEN) is now confined to the inner subpattern. After a failure\nin C, matching moves to (*FAIL), which causes the whole subpattern to fail, as\nthere are no more alternatives to try. In this case, matching does now backtrack\ninto A.\n\nNotice that a conditional subpattern is not considered as having two\nalternatives, as only one is ever used. That is, the | character in a\nconditional subpattern has a different meaning. Ignoring whitespace, consider:\n\n```text\n^.*? (?(?=a) a | b(*THEN)c )\n```\n\nIf the subject is \"ba\", this pattern does not match. As ._? is ungreedy, it\ninitially matches zero characters. The condition (?=a) then fails, the character\n\"b\" is matched, but \"c\" is not. At this point, matching does not backtrack to\n._? as can perhaps be expected from the presence of the | character. The\nconditional subpattern is part of the single alternative that comprises the\nwhole pattern, and so the match fails. (If there was a backtrack into .\\*?,\nallowing it to match \"b\", the match would succeed.)\n\nThe verbs described above provide four different \"strengths\" of control when\nsubsequent matching fails:\n\n- (\\*THEN) is the weakest, carrying on the match at the next alternative.\n- (\\*PRUNE) comes next, fails the match at the current starting position, but\n allows an advance to the next character (for an unanchored pattern).\n- (\\*SKIP) is similar, except that the advance can be more than one character.\n- (\\*COMMIT) is the strongest, causing the entire match to fail.\n\n_More than One Backtracking Verb_\n\nIf more than one backtracking verb is present in a pattern, the one that is\nbacktracked onto first acts. For example, consider the following pattern, where\nA, B, and so on, are complex pattern fragments:\n\n```text\n(A(*COMMIT)B(*THEN)C|ABD)\n```\n\nIf A matches but B fails, the backtrack to (*COMMIT) causes the entire match to\nfail. However, if A and B match, but C fails, the backtrack to (*THEN) causes\nthe next alternative (ABD) to be tried. This behavior is consistent, but is not\nalways the same as in Perl. It means that if two or more backtracking verbs\nappear in succession, the last of them has no effect. Consider the following\nexample:\n\n```text\n...(*COMMIT)(*PRUNE)...\n```\n\nIf there is a matching failure to the right, backtracking onto (*PRUNE) causes\nit to be triggered, and its action is taken. There can never be a backtrack onto\n(*COMMIT).\n\n_Backtracking Verbs in Repeated Groups_\n\nPCRE differs from Perl in its handling of backtracking verbs in repeated groups.\nFor example, consider:\n\n```text\n/(a(*COMMIT)b)+ac/\n```\n\nIf the subject is \"abac\", Perl matches, but PCRE fails because the (\\*COMMIT) in\nthe second repeat of the group acts.\n\n_Backtracking Verbs in Assertions_\n\n(\\*FAIL) in an assertion has its normal effect: it forces an immediate\nbacktrack.\n\n(*ACCEPT) in a positive assertion causes the assertion to succeed without any\nfurther processing. In a negative assertion, (*ACCEPT) causes the assertion to\nfail without any further processing.\n\nThe other backtracking verbs are not treated specially if they appear in a\npositive assertion. In particular, (\\*THEN) skips to the next alternative in the\ninnermost enclosing group that has alternations, regardless if this is within\nthe assertion.\n\nNegative assertions are, however, different, to ensure that changing a positive\nassertion into a negative assertion changes its result. Backtracking into\n(*COMMIT), (*SKIP), or (*PRUNE) causes a negative assertion to be true, without\nconsidering any further alternative branches in the assertion. Backtracking into\n(*THEN) causes it to skip to the next enclosing alternative within the assertion\n(the normal behavior), but if the assertion does not have such an alternative,\n(*THEN) behaves like (*PRUNE).\n\n_Backtracking Verbs in Subroutines_\n\nThese behaviors occur regardless if the subpattern is called recursively. The\ntreatment of subroutines in Perl is different in some cases.\n\n- (\\*FAIL) in a subpattern called as a subroutine has its normal effect: it\n forces an immediate backtrack.\n- (\\*ACCEPT) in a subpattern called as a subroutine causes the subroutine match\n to succeed without any further processing. Matching then continues after the\n subroutine call.\n- (*COMMIT), (*SKIP), and (\\*PRUNE) in a subpattern called as a subroutine cause\n the subroutine match to fail.\n- (*THEN) skips to the next alternative in the innermost enclosing group within\n the subpattern that has alternatives. If there is no such group within the\n subpattern, (*THEN) causes the subroutine match to fail.","title":"Backtracking Control - re","ref":"re.html#module-backtracking-control"},{"type":"function","doc":"The same as [`compile(Regexp,[])`](`compile/2`)","title":"re.compile/1","ref":"re.html#compile/1"},{"type":"function","doc":"Compiles a regular expression, with the syntax described below, into an internal\nformat to be used later as a parameter to `run/2` and `run/3`.\n\nCompiling the regular expression before matching is useful if the same\nexpression is to be used in matching against multiple subjects during the\nlifetime of the program. Compiling once and executing many times is far more\nefficient than compiling each time one wants to match.\n\nWhen option `unicode` is specified, the regular expression is to be specified as\na valid Unicode `charlist()`, otherwise as any valid `t:iodata/0`.\n\n[](){: #compile_options }\n\nOptions:\n\n- **`unicode`** - The regular expression is specified as a Unicode `charlist()`\n and the resulting regular expression code is to be run against a valid Unicode\n `charlist()` subject. Also consider option `ucp` when using Unicode\n characters.\n\n- **`anchored`** - The pattern is forced to be \"anchored\", that is, it is\n constrained to match only at the first matching point in the string that is\n searched (the \"subject string\"). This effect can also be achieved by\n appropriate constructs in the pattern itself.\n\n- **`caseless`** - Letters in the pattern match both uppercase and lowercase\n letters. It is equivalent to Perl option `/i` and can be changed within a\n pattern by a `(?i)` option setting. Uppercase and lowercase letters are\n defined as in the ISO 8859-1 character set.\n\n- **`dollar_endonly`** - A dollar metacharacter in the pattern matches only at\n the end of the subject string. Without this option, a dollar also matches\n immediately before a newline at the end of the string (but not before any\n other newlines). This option is ignored if option `multiline` is specified.\n There is no equivalent option in Perl, and it cannot be set within a pattern.\n\n- **`dotall`** - A dot in the pattern matches all characters, including those\n indicating newline. Without it, a dot does not match when the current position\n is at a newline. This option is equivalent to Perl option `/s` and it can be\n changed within a pattern by a `(?s)` option setting. A negative class, such as\n `[^a]`, always matches newline characters, independent of the setting of this\n option.\n\n- **`extended`** - If this option is set, most white space characters in the\n pattern are totally ignored except when escaped or inside a character class.\n However, white space is not allowed within sequences such as `(?>` that\n introduce various parenthesized subpatterns, nor within a numerical quantifier\n such as `{1,3}`. However, ignorable white space is permitted between an item\n and a following quantifier and between a quantifier and a following + that\n indicates possessiveness.\n\n White space did not used to include the VT character (code 11), because Perl\n did not treat this character as white space. However, Perl changed at release\n 5.18, so PCRE followed at release 8.34, and VT is now treated as white space.\n\n This also causes characters between an unescaped # outside a character class\n and the next newline, inclusive, to be ignored. This is equivalent to Perl's\n `/x` option, and it can be changed within a pattern by a `(?x)` option\n setting.\n\n With this option, comments inside complicated patterns can be included.\n However, notice that this applies only to data characters. Whitespace\n characters can never appear within special character sequences in a pattern,\n for example within sequence `(?(` that introduces a conditional subpattern.\n\n- **`firstline`** - An unanchored pattern is required to match before or at the\n first newline in the subject string, although the matched text can continue\n over the newline.\n\n- **`multiline`** - By default, PCRE treats the subject string as consisting of\n a single line of characters (even if it contains newlines). The \"start of\n line\" metacharacter (`^`) matches only at the start of the string, while the\n \"end of line\" metacharacter (`$`) matches only at the end of the string, or\n before a terminating newline (unless option `dollar_endonly` is specified).\n This is the same as in Perl.\n\n When this option is specified, the \"start of line\" and \"end of line\"\n constructs match immediately following or immediately before internal newlines\n in the subject string, respectively, as well as at the very start and end.\n This is equivalent to Perl option `/m` and can be changed within a pattern by\n a `(?m)` option setting. If there are no newlines in a subject string, or no\n occurrences of `^` or `$` in a pattern, setting `multiline` has no effect.\n\n- **`no_auto_capture`** - Disables the use of numbered capturing parentheses in\n the pattern. Any opening parenthesis that is not followed by `?` behaves as if\n it is followed by `?:`. Named parentheses can still be used for capturing (and\n they acquire numbers in the usual way). There is no equivalent option in Perl.\n\n- **`dupnames`** - Names used to identify capturing subpatterns need not be\n unique. This can be helpful for certain types of pattern when it is known that\n only one instance of the named subpattern can ever be matched. More details of\n named subpatterns are provided below.\n\n- **`ungreedy`** - Inverts the \"greediness\" of the quantifiers so that they are\n not greedy by default, but become greedy if followed by \"?\". It is not\n compatible with Perl. It can also be set by a `(?U)` option setting within the\n pattern.\n\n- **`{newline, NLSpec}`** - Overrides the default definition of a newline in the\n subject string, which is LF (ASCII 10) in Erlang.\n\n - **`cr`** - Newline is indicated by a single character `cr` (ASCII 13).\n\n - **`lf`** - Newline is indicated by a single character LF (ASCII 10), the\n default.\n\n - **`crlf`** - Newline is indicated by the two-character CRLF (ASCII 13\n followed by ASCII 10) sequence.\n\n - **`anycrlf`** - Any of the three preceding sequences is to be recognized.\n\n - **`any`** - Any of the newline sequences above, and the Unicode sequences VT\n (vertical tab, U+000B), FF (formfeed, U+000C), NEL (next line, U+0085), LS\n (line separator, U+2028), and PS (paragraph separator, U+2029).\n\n- **`bsr_anycrlf`** - Specifies specifically that \\\\R is to match only the CR,\n LF, or CRLF sequences, not the Unicode-specific newline characters.\n\n- **`bsr_unicode`** - Specifies specifically that \\\\R is to match all the\n Unicode newline characters (including CRLF, and so on, the default).\n\n- **`no_start_optimize`** - Disables optimization that can malfunction if\n \"Special start-of-pattern items\" are present in the regular expression. A\n typical example would be when matching \"DEFABC\" against \"(*COMMIT)ABC\", where\n the start optimization of PCRE would skip the subject up to \"A\" and never\n realize that the (*COMMIT) instruction is to have made the matching fail. This\n option is only relevant if you use \"start-of-pattern items\", as discussed in\n section [PCRE Regular Expression Details](`m:re#module-pcre-regular-expression-details`).\n\n- **`ucp`** - Specifies that Unicode character properties are to be used when\n resolving \\\\B, \\\\b, \\\\D, \\\\d, \\\\S, \\\\s, \\\\W and \\\\w. Without this flag, only\n ISO Latin-1 properties are used. Using Unicode properties hurts performance,\n but is semantically correct when working with Unicode characters beyond the\n ISO Latin-1 range.\n\n- **`never_utf`** - Specifies that the (*UTF) and/or (*UTF8) \"start-of-pattern\n items\" are forbidden. This flag cannot be combined with option `unicode`.\n Useful if ISO Latin-1 patterns from an external source are to be compiled.","title":"re.compile/2","ref":"re.html#compile/2"},{"type":"function","doc":"Takes a compiled regular expression and an item, and returns the relevant data\nfrom the regular expression.\n\nThe only supported item is `namelist`, which returns the tuple `{namelist, [binary()]}`,\ncontaining the names of all (unique) named subpatterns in the regular expression.\n\nFor example:\n\n```erlang\n1> {ok,MP} = re:compile(\"(? A)|(? B)|(? C)\").\n{ok,{re_pattern,3,0,0,\n <<69,82,67,80,119,0,0,0,0,0,0,0,1,0,0,0,255,255,255,255,\n 255,255,...>>}}\n2> re:inspect(MP,namelist).\n{namelist,[<<\"A\">>,<<\"B\">>,<<\"C\">>]}\n3> {ok,MPD} = re:compile(\"(? A)|(? B)|(? C)\",[dupnames]).\n{ok,{re_pattern,3,0,0,\n <<69,82,67,80,119,0,0,0,0,0,8,0,1,0,0,0,255,255,255,255,\n 255,255,...>>}}\n4> re:inspect(MPD,namelist).\n{namelist,[<<\"B\">>,<<\"C\">>]}\n```\n\nNotice in the second example that the duplicate name only occurs once in the\nreturned list, and that the list is in alphabetical order regardless of where\nthe names are positioned in the regular expression. The order of the names is\nthe same as the order of captured subexpressions if `{capture, all_names}` is\nspecified as an option to `run/3`. You can therefore create a name-to-value\nmapping from the result of [`run/3`](`run/3`) like this:\n\n```erlang\n1> {ok,MP} = re:compile(\"(? A)|(? B)|(? C)\").\n{ok,{re_pattern,3,0,0,\n <<69,82,67,80,119,0,0,0,0,0,0,0,1,0,0,0,255,255,255,255,\n 255,255,...>>}}\n2> {namelist, N} = re:inspect(MP,namelist).\n{namelist,[<<\"A\">>,<<\"B\">>,<<\"C\">>]}\n3> {match,L} = re:run(\"AA\",MP,[{capture,all_names,binary}]).\n{match,[<<\"A\">>,<<>>,<<>>]}\n4> NameMap = lists:zip(N,L).\n[{<<\"A\">>,<<\"A\">>},{<<\"B\">>,<<>>},{<<\"C\">>,<<>>}]\n```","title":"re.inspect/2","ref":"re.html#inspect/2"},{"type":"function","doc":"","title":"re.replace/3","ref":"re.html#replace/3"},{"type":"function","doc":"Replaces the matched part of the `Subject` string with `Replacement`.\n\nThe permissible options are the same as for `run/3`, except that\noption` capture` is not allowed. Instead a `{return, ReturnType}` is present.\nThe default return type is `iodata`, constructed in a way to minimize copying.\nThe `iodata` result can be used directly in many I/O operations. If a flat\n`t:list/0` is desired, specify `{return, list}`. If a binary is desired, specify\n`{return, binary}`.\n\nAs in function [`run/3`](`run/3`), an `t:mp/0` compiled with option `unicode`\nrequires `Subject` to be a Unicode `charlist()`. If compilation is done\nimplicitly and the `unicode` compilation option is specified to this function,\nboth the regular expression and `Subject` are to specified as valid Unicode\n`charlist()`s.\n\nIf the replacement is given as a string, it can contain the special character\n`&`, which inserts the whole matching expression in the result, and the special\nsequence `\\`N (where N is an integer > 0), `\\g`N, or `\\g{`N`}`, resulting in the\nsubexpression number N, is inserted in the result. If no subexpression with that\nnumber is generated by the regular expression, nothing is inserted.\n\nTo insert an & or a \\\\ in the result, precede it with a \\\\. Notice that Erlang\nalready gives a special meaning to \\\\ in literal strings, so a single \\\\ must be\nwritten as `\"\\\\\"` and therefore a double \\\\ as `\"\\\\\\\\\"`.\n\n_Example:_\n\n```erlang\n1> re:replace(\"abcd\",\"c\",\"[&]\",[{return,list}]).\n\"ab[c]d\"\n```\n\nwhile\n\n```erlang\n2> re:replace(\"abcd\",\"c\",\"[\\\\&]\",[{return,list}]).\n\"ab[&]d\"\n```\n\nIf the replacement is given as a fun, it will be called with the whole matching\nexpression as the first argument and a list of subexpression matches in the\norder in which they appear in the regular expression. The returned value will be\ninserted in the result.\n\n_Example:_\n\n```erlang\n3> re:replace(\"abcd\", \".(.)\",\n fun(Whole, [< >]) ->\n <<$#, Whole/binary, $-, (C - $a + $A), $#>>\n end,\n [{return, list}]).\n\"#ab-B#cd\"\n```\n\n> #### Note {: .info }\n>\n> Non-matching optional subexpressions will not be included in the list of\n> subexpression matches if they are the last subexpressions in the regular\n> expression.\n>\n> _Example:_\n>\n> The regular expression `\"(a)(b)?(c)?\"` (\"a\", optionally followed by \"b\",\n> optionally followed by \"c\") will create the following subexpression lists:\n>\n> - `[<<\"a\">>, <<\"b\">>, <<\"c\">>]` when applied to the string `\"abc\"`\n> - `[<<\"a\">>, <<>>, <<\"c\">>]` when applied to the string `\"acx\"`\n> - `[<<\"a\">>, <<\"b\">>]` when applied to the string `\"abx\"`\n> - `[<<\"a\">>]` when applied to the string `\"axx\"`\n\nAs with [`run/3`](`run/3`), compilation errors raise the `badarg` exception.\n`compile/2` can be used to get more information about the error.","title":"re.replace/4","ref":"re.html#replace/4"},{"type":"function","doc":"","title":"re.run/2","ref":"re.html#run/2"},{"type":"function","doc":"Executes a regular expression matching, and returns `match/{match, Captured}` or\n`nomatch`.\n\nThe regular expression can be specified either as `t:iodata/0` in\nwhich case it is automatically compiled (as by [`compile/2`](`compile/2`)) and\nexecuted, or as a precompiled `t:mp/0` in which case it is executed against the\nsubject directly.\n\nWhen compilation is involved, exception `badarg` is thrown if a compilation\nerror occurs. Call [`compile/2`](`compile/2`) to get information about the\nlocation of the error in the regular expression.\n\nIf the regular expression is previously compiled, the option list can only\ncontain the following options:\n\n- `anchored`\n- `{capture, ValueSpec}/{capture, ValueSpec, Type}`\n- `global`\n- `{match_limit, integer() >= 0}`\n- `{match_limit_recursion, integer() >= 0}`\n- `{newline, NLSpec}`\n- `notbol`\n- `notempty`\n- `notempty_atstart`\n- `noteol`\n- `{offset, integer() >= 0}`\n- `report_errors`\n\nOtherwise all options valid for function [`compile/2`](`compile/2`) are also\nallowed. Options allowed both for compilation and execution of a match, namely\n`anchored` and `{newline, NLSpec}`, affect both the compilation and execution if\npresent together with a non-precompiled regular expression.\n\nIf the regular expression was previously compiled with option `unicode`,\n`Subject` is to be provided as a valid Unicode `charlist()`, otherwise any\n`t:iodata/0` will do. If compilation is involved and option `unicode` is\nspecified, both `Subject` and the regular expression are to be specified as\nvalid Unicode `charlists()`.\n\n`{capture, ValueSpec}/{capture, ValueSpec, Type}` defines what to return from\nthe function upon successful matching. The `capture` tuple can contain both a\nvalue specification, telling which of the captured substrings are to be\nreturned, and a type specification, telling how captured substrings are to be\nreturned (as index tuples, lists, or binaries). The options are described in\ndetail below.\n\nIf the capture options describe that no substring capturing is to be done\n(`{capture, none}`), the function returns the single atom `match` upon\nsuccessful matching, otherwise the tuple `{match, ValueList}`. Disabling\ncapturing can be done either by specifying `none` or an empty list as\n`ValueSpec`.\n\nOption `report_errors` adds the possibility that an error tuple is returned. The\ntuple either indicates a matching error (`match_limit` or\n`match_limit_recursion`), or a compilation error, where the error tuple has the\nformat `{error, {compile, CompileErr}}`. Notice that if option `report_errors`\nis not specified, the function never returns error tuples, but reports\ncompilation errors as a `badarg` exception and failed matches because of\nexceeded match limits simply as `nomatch`.\n\nThe following options are relevant for execution:\n\n- **`anchored`** - Limits [`run/3`](`run/3`) to matching at the first matching\n position. If a pattern was compiled with `anchored`, or turned out to be\n anchored by virtue of its contents, it cannot be made unanchored at matching\n time, hence there is no `unanchored` option.\n\n- **`global`** - Implements global (repetitive) search (flag `g` in Perl). Each\n match is returned as a separate `t:list/0` containing the specific match and\n any matching subexpressions (or as specified by option `capture`. The\n `Captured` part of the return value is hence a `t:list/0` of `t:list/0`s when\n this option is specified.\n\n The interaction of option `global` with a regular expression that matches an\n empty string surprises some users. When option `global` is specified,\n [`run/3`](`run/3`) handles empty matches in the same way as Perl: a\n zero-length match at any point is also retried with options\n `[anchored, notempty_atstart]`. If that search gives a result of length > 0,\n the result is included. Example:\n\n ```erlang\n re:run(\"cat\",\"(|at)\",[global]).\n ```\n\n The following matchings are performed:\n\n - **At offset `0`** - The regular expression `(|at)` first match at the\n initial position of string `cat`, giving the result set `[{0,0},{0,0}]` (the\n second `{0,0}` is because of the subexpression marked by the parentheses).\n As the length of the match is 0, we do not advance to the next position yet.\n\n - **At offset `0` with `[anchored, notempty_atstart]`** - The search is\n retried with options `[anchored, notempty_atstart]` at the same position,\n which does not give any interesting result of longer length, so the search\n position is advanced to the next character (`a`).\n\n - **At offset `1`** - The search results in `[{1,0},{1,0}]`, so this search is\n also repeated with the extra options.\n\n - **At offset `1` with `[anchored, notempty_atstart]`** - Alternative `ab` is\n found and the result is \\[\\{1,2\\},\\{1,2\\}]. The result is added to the list\n of results and the position in the search string is advanced two steps.\n\n - **At offset `3`** - The search once again matches the empty string, giving\n `[{3,0},{3,0}]`.\n\n - **At offset `1` with `[anchored, notempty_atstart]`** - This gives no result\n of length > 0 and we are at the last position, so the global search is\n complete.\n\n The result of the call is:\n\n ```erlang\n {match,[[{0,0},{0,0}],[{1,0},{1,0}],[{1,2},{1,2}],[{3,0},{3,0}]]}\n ```\n\n- **`notempty`** - An empty string is not considered to be a valid match if this\n option is specified. If alternatives in the pattern exist, they are tried. If\n all the alternatives match the empty string, the entire match fails.\n\n _Example:_\n\n If the following pattern is applied to a string not beginning with \"a\" or \"b\",\n it would normally match the empty string at the start of the subject:\n\n ```text\n a?b?\n ```\n\n With option `notempty`, this match is invalid, so [`run/3`](`run/3`) searches\n further into the string for occurrences of \"a\" or \"b\".\n\n- **`notempty_atstart`** - Like `notempty`, except that an empty string match\n that is not at the start of the subject is permitted. If the pattern is\n anchored, such a match can occur only if the pattern contains \\\\K.\n\n Perl has no direct equivalent of `notempty` or `notempty_atstart`, but it does\n make a special case of a pattern match of the empty string within its split()\n function, and when using modifier `/g`. The Perl behavior can be emulated\n after matching a null string by first trying the match again at the same\n offset with `notempty_atstart` and `anchored`, and then, if that fails, by\n advancing the starting offset (see below) and trying an ordinary match again.\n\n- **`notbol`** - Specifies that the first character of the subject string is not\n the beginning of a line, so the circumflex metacharacter is not to match\n before it. Setting this without `multiline` (at compile time) causes\n circumflex never to match. This option only affects the behavior of the\n circumflex metacharacter. It does not affect \\\\A.\n\n- **`noteol`** - Specifies that the end of the subject string is not the end of\n a line, so the dollar metacharacter is not to match it nor (except in\n multiline mode) a newline immediately before it. Setting this without\n `multiline` (at compile time) causes dollar never to match. This option\n affects only the behavior of the dollar metacharacter. It does not affect \\\\Z\n or \\\\z.\n\n- **`report_errors`** - Gives better control of the error handling in\n [`run/3`](`run/3`). When specified, compilation errors (if the regular\n expression is not already compiled) and runtime errors are explicitly returned\n as an error tuple.\n\n The following are the possible runtime errors:\n\n - **`match_limit`** - The PCRE library sets a limit on how many times the\n internal match function can be called. Defaults to 10,000,000 in the library\n compiled for Erlang. If `{error, match_limit}` is returned, the execution of\n the regular expression has reached this limit. This is normally to be\n regarded as a `nomatch`, which is the default return value when this occurs,\n but by specifying `report_errors`, you are informed when the match fails\n because of too many internal calls.\n\n - **`match_limit_recursion`** - This error is very similar to `match_limit`,\n but occurs when the internal match function of PCRE is \"recursively\" called\n more times than the `match_limit_recursion` limit, which defaults to\n 10,000,000 as well. Notice that as long as the `match_limit` and\n `match_limit_default` values are kept at the default values, the\n `match_limit_recursion` error cannot occur, as the `match_limit` error\n occurs before that (each recursive call is also a call, but not conversely).\n Both limits can however be changed, either by setting limits directly in the\n regular expression string (see section\n [PCRE Regular Eexpression Details](`m:re#module-pcre-regular-expression-details`)) or by\n specifying options to [`run/3`](`run/3`).\n\n It is important to understand that what is referred to as \"recursion\" when\n limiting matches is not recursion on the C stack of the Erlang machine or on\n the Erlang process stack. The PCRE version compiled into the Erlang VM uses\n machine \"heap\" memory to store values that must be kept over recursion in\n regular expression matches.\n\n- **`{match_limit, integer() >= 0}`** - Limits the execution time of a match in\n an implementation-specific way. It is described as follows by the PCRE\n documentation:\n\n > The match_limit field provides a means of preventing PCRE from using\n > up a vast amount of resources when running patterns that are not going\n > to match, but which have a very large number of possibilities in their\n > search trees. The classic example is a pattern that uses nested\n > unlimited repeats.\n >\n > Internally, pcre_exec() uses a function called match(), which it calls\n > repeatedly (sometimes recursively). The limit set by match_limit is\n > imposed on the number of times this function is called during a match,\n > which has the effect of limiting the amount of backtracking that can\n > take place. For patterns that are not anchored, the count restarts\n > from zero for each position in the subject string.\n\n This means that runaway regular expression matches can fail faster if the\n limit is lowered using this option. The default value 10,000,000 is compiled\n into the Erlang VM.\n\n > #### Note {: .info }\n >\n > This option does in no way affect the execution of the Erlang VM in terms of\n > \"long running BIFs\". [`run/3`](`run/3`) always gives control back to the\n > scheduler of Erlang processes at intervals that ensures the real-time\n > properties of the Erlang system.\n\n- **`{match_limit_recursion, integer() >= 0}`** - Limits the execution time and\n memory consumption of a match in an implementation-specific way, very similar\n to `match_limit`. It is described as follows by the PCRE documentation:\n\n > The match_limit_recursion field is similar to match_limit, but instead\n > of limiting the total number of times that match() is called, it\n > limits the depth of recursion. The recursion depth is a smaller number\n > than the total number of calls, because not all calls to match() are\n > recursive. This limit is of use only if it is set smaller than\n > match_limit.\n >\n > Limiting the recursion depth limits the amount of machine stack that\n > can be used, or, when PCRE has been compiled to use memory on the heap\n > instead of the stack, the amount of heap memory that can be used.\n\n The Erlang VM uses a PCRE library where heap memory is used when regular\n expression match recursion occurs. This therefore limits the use of machine\n heap, not C stack.\n\n Specifying a lower value can result in matches with deep recursion failing,\n when they should have matched:\n\n ```erlang\n 1> re:run(\"aaaaaaaaaaaaaz\",\"(a+)*z\").\n {match,[{0,14},{0,13}]}\n 2> re:run(\"aaaaaaaaaaaaaz\",\"(a+)*z\",[{match_limit_recursion,5}]).\n nomatch\n 3> re:run(\"aaaaaaaaaaaaaz\",\"(a+)*z\",[{match_limit_recursion,5},report_errors]).\n {error,match_limit_recursion}\n ```\n\n This option and option `match_limit` are only to be used in rare cases.\n Understanding of the PCRE library internals is recommended before tampering\n with these limits.\n\n- **`{offset, integer() >= 0}`** - Start matching at the offset (position)\n specified in the subject string. The offset is zero-based, so that the default\n is `{offset,0}` (all of the subject string).\n\n- **`{newline, NLSpec}`** - Overrides the default definition of a newline in the\n subject string, which is LF (ASCII 10) in Erlang.\n\n - **`cr`** - Newline is indicated by a single character CR (ASCII 13).\n\n - **`lf`** - Newline is indicated by a single character LF (ASCII 10), the\n default.\n\n - **`crlf`** - Newline is indicated by the two-character CRLF (ASCII 13\n followed by ASCII 10) sequence.\n\n - **`anycrlf`** - Any of the three preceding sequences is be recognized.\n\n - **`any`** - Any of the newline sequences above, and the Unicode sequences VT\n (vertical tab, U+000B), FF (formfeed, U+000C), NEL (next line, U+0085), LS\n (line separator, U+2028), and PS (paragraph separator, U+2029).\n\n- **`bsr_anycrlf`** - Specifies specifically that \\\\R is to match only the CR\n LF, or CRLF sequences, not the Unicode-specific newline characters. (Overrides\n the compilation option.)\n\n- **`bsr_unicode`** - Specifies specifically that \\\\R is to match all the\n Unicode newline characters (including CRLF, and so on, the default).\n (Overrides the compilation option.)\n\n- **`{capture, ValueSpec}`/`{capture, ValueSpec, Type}`** - Specifies which\n captured substrings are returned and in what format. By default,\n [`run/3`](`run/3`) captures all of the matching part of the substring and all\n capturing subpatterns (all of the pattern is automatically captured). The\n default return type is (zero-based) indexes of the captured parts of the\n string, specified as `{Offset,Length}` pairs (the `index` `Type` of\n capturing).\n\n As an example of the default behavior, the following call returns, as first\n and only captured string, the matching part of the subject (\"abcd\" in the\n middle) as an index pair `{3,4}`, where character positions are zero-based,\n just as in offsets:\n\n ```erlang\n re:run(\"ABCabcdABC\",\"abcd\",[]).\n ```\n\n The return value of this call is:\n\n ```erlang\n {match,[{3,4}]}\n ```\n\n Another (and quite common) case is where the regular expression matches all of\n the subject:\n\n ```erlang\n re:run(\"ABCabcdABC\",\".*abcd.*\",[]).\n ```\n\n Here the return value correspondingly points out all of the string, beginning\n at index 0, and it is 10 characters long:\n\n ```erlang\n {match,[{0,10}]}\n ```\n\n If the regular expression contains capturing subpatterns, like in:\n\n ```erlang\n re:run(\"ABCabcdABC\",\".*(abcd).*\",[]).\n ```\n\n all of the matched subject is captured, as well as the captured substrings:\n\n ```erlang\n {match,[{0,10},{3,4}]}\n ```\n\n The complete matching pattern always gives the first return value in the list\n and the remaining subpatterns are added in the order they occurred in the\n regular expression.\n\n The capture tuple is built up as follows:\n\n - **`ValueSpec`** - Specifies which captured (sub)patterns are to be returned.\n `ValueSpec` can either be an atom describing a predefined set of return\n values, or a list containing the indexes or the names of specific\n subpatterns to return.\n\n The following are the predefined sets of subpatterns:\n\n - **`all`** - All captured subpatterns including the complete matching\n string. This is the default.\n\n - **`all_names`** - All _named_ subpatterns in the regular expression, as if\n a `t:list/0` of all the names _in alphabetical order_ was specified. The\n list of all names can also be retrieved with `inspect/2`.\n\n - **`first`** - Only the first captured subpattern, which is always the\n complete matching part of the subject. All explicitly captured subpatterns\n are discarded.\n\n - **`all_but_first`** - All but the first matching subpattern, that is, all\n explicitly captured subpatterns, but not the complete matching part of the\n subject string. This is useful if the regular expression as a whole\n matches a large part of the subject, but the part you are interested in is\n in an explicitly captured subpattern. If the return type is `list` or\n `binary`, not returning subpatterns you are not interested in is a good\n way to optimize.\n\n - **`none`** - Returns no matching subpatterns, gives the single atom\n `match` as the return value of the function when matching successfully\n instead of the `{match, list()}` return. Specifying an empty list gives\n the same behavior.\n\n The value list is a list of indexes for the subpatterns to return, where\n index 0 is for all of the pattern, and 1 is for the first explicit capturing\n subpattern in the regular expression, and so on. When using named captured\n subpatterns (see below) in the regular expression, one can use `t:atom/0`s\n or `t:string/0`s to specify the subpatterns to be returned. For example,\n consider the regular expression:\n\n ```text\n \".*(abcd).*\"\n ```\n\n matched against string \"ABCabcdABC\", capturing only the \"abcd\" part (the\n first explicit subpattern):\n\n ```erlang\n re:run(\"ABCabcdABC\",\".*(abcd).*\",[{capture,[1]}]).\n ```\n\n The call gives the following result, as the first explicitly captured\n subpattern is \"(abcd)\", matching \"abcd\" in the subject, at (zero-based)\n position 3, of length 4:\n\n ```erlang\n {match,[{3,4}]}\n ```\n\n Consider the same regular expression, but with the subpattern explicitly\n named 'FOO':\n\n ```text\n \".*(? abcd).*\"\n ```\n\n With this expression, we could still give the index of the subpattern with\n the following call:\n\n ```erlang\n re:run(\"ABCabcdABC\",\".*(? abcd).*\",[{capture,[1]}]).\n ```\n\n giving the same result as before. But, as the subpattern is named, we can\n also specify its name in the value list:\n\n ```erlang\n re:run(\"ABCabcdABC\",\".*(? abcd).*\",[{capture,['FOO']}]).\n ```\n\n This would give the same result as the earlier examples, namely:\n\n ```erlang\n {match,[{3,4}]}\n ```\n\n The values list can specify indexes or names not present in the regular\n expression, in which case the return values vary depending on the type. If\n the type is `index`, the tuple `{-1,0}` is returned for values with no\n corresponding subpattern in the regular expression, but for the other types\n (`binary` and `list`), the values are the empty binary or list,\n respectively.\n\n - **`Type`** - Optionally specifies how captured substrings are to be\n returned. If omitted, the default of `index` is used.\n\n `Type` can be one of the following:\n\n - **`index`** - Returns captured substrings as pairs of byte indexes into\n the subject string and length of the matching string in the subject (as if\n the subject string was flattened with `erlang:iolist_to_binary/1` or\n `unicode:characters_to_binary/2` before matching). Notice that option\n `unicode` results in _byte-oriented_ indexes in a (possibly virtual)\n _UTF-8 encoded_ binary. A byte index tuple `{0,2}` can therefore represent\n one or two characters when `unicode` is in effect. This can seem\n counter-intuitive, but has been deemed the most effective and useful way\n to do it. To return lists instead can result in simpler code if that is\n desired. This return type is the default.\n\n - **`list`** - Returns matching substrings as lists of characters (Erlang\n `t:string/0`s). It option `unicode` is used in combination with the \\\\C\n sequence in the regular expression, a captured subpattern can contain\n bytes that are not valid UTF-8 (\\\\C matches bytes regardless of character\n encoding). In that case the `list` capturing can result in the same types\n of tuples that `unicode:characters_to_list/2` can return, namely\n three-tuples with tag `incomplete` or `error`, the successfully converted\n characters and the invalid UTF-8 tail of the conversion as a binary. The\n best strategy is to avoid using the \\\\C sequence when capturing lists.\n\n - **`binary`** - Returns matching substrings as binaries. If option\n `unicode` is used, these binaries are in UTF-8. If the \\\\C sequence is\n used together with `unicode`, the binaries can be invalid UTF-8.\n\n In general, subpatterns that were not assigned a value in the match are\n returned as the tuple `{-1,0}` when `type` is `index`. Unassigned subpatterns\n are returned as the empty binary or list, respectively, for other return\n types. Consider the following regular expression:\n\n ```text\n \".*((? abdd)|a(..d)).*\"\n ```\n\n There are three explicitly capturing subpatterns, where the opening\n parenthesis position determines the order in the result, hence\n `((? abdd)|a(..d))` is subpattern index 1, `(? abdd)` is subpattern\n index 2, and `(..d)` is subpattern index 3. When matched against the following\n string:\n\n ```text\n \"ABCabcdABC\"\n ```\n\n the subpattern at index 2 does not match, as \"abdd\" is not present in the\n string, but the complete pattern matches (because of the alternative\n `a(..d)`). The subpattern at index 2 is therefore unassigned and the default\n return value is:\n\n ```erlang\n {match,[{0,10},{3,4},{-1,0},{4,3}]}\n ```\n\n Setting the capture `Type` to `binary` gives:\n\n ```erlang\n {match,[<<\"ABCabcdABC\">>,<<\"abcd\">>,<<>>,<<\"bcd\">>]}\n ```\n\n Here the empty binary (`<<>>`) represents the unassigned subpattern. In the\n `binary` case, some information about the matching is therefore lost, as\n `<<>>` can also be an empty string captured.\n\n If differentiation between empty matches and non-existing subpatterns is\n necessary, use the `type` `index` and do the conversion to the final type in\n Erlang code.\n\n When option `global` is speciified, the `capture` specification affects each\n match separately, so that:\n\n ```erlang\n re:run(\"cacb\",\"c(a|b)\",[global,{capture,[1],list}]).\n ```\n\n gives\n\n ```erlang\n {match,[[\"a\"],[\"b\"]]}\n ```\n\nFor a descriptions of options only affecting the compilation step, see\n`compile/2`.","title":"re.run/3","ref":"re.html#run/3"},{"type":"function","doc":"","title":"re.split/2","ref":"re.html#split/2"},{"type":"function","doc":"Splits the input into parts by finding tokens according to the regular\nexpression supplied.\n\nThe splitting is basically done by running a global regular\nexpression match and dividing the initial string wherever a match occurs. The\nmatching part of the string is removed from the output.\n\nAs in `run/3`, an `t:mp/0` compiled with option `unicode` requires `Subject` to\nbe a Unicode `charlist()`. If compilation is done implicitly and the `unicode`\ncompilation option is specified to this function, both the regular expression\nand `Subject` are to be specified as valid Unicode `charlist()`s.\n\nThe result is given as a list of \"strings\", the preferred data type specified in\noption `return` (default `iodata`).\n\nIf subexpressions are specified in the regular expression, the matching\nsubexpressions are returned in the resulting list as well. For example:\n\n```erlang\nre:split(\"Erlang\",\"[ln]\",[{return,list}]).\n```\n\ngives\n\n```erlang\n[\"Er\",\"a\",\"g\"]\n```\n\nwhile\n\n```erlang\nre:split(\"Erlang\",\"([ln])\",[{return,list}]).\n```\n\ngives\n\n```erlang\n[\"Er\",\"l\",\"a\",\"n\",\"g\"]\n```\n\nThe text matching the subexpression (marked by the parentheses in the regular\nexpression) is inserted in the result list where it was found. This means that\nconcatenating the result of a split where the whole regular expression is a\nsingle subexpression (as in the last example) always results in the original\nstring.\n\nAs there is no matching subexpression for the last part in the example (the\n\"g\"), nothing is inserted after that. To make the group of strings and the parts\nmatching the subexpressions more obvious, one can use option `group`, which\ngroups together the part of the subject string with the parts matching the\nsubexpressions when the string was split:\n\n```erlang\nre:split(\"Erlang\",\"([ln])\",[{return,list},group]).\n```\n\ngives\n\n```erlang\n[[\"Er\",\"l\"],[\"a\",\"n\"],[\"g\"]]\n```\n\nHere the regular expression first matched the \"l\", causing \"Er\" to be the first\npart in the result. When the regular expression matched, the (only)\nsubexpression was bound to the \"l\", so the \"l\" is inserted in the group together\nwith \"Er\". The next match is of the \"n\", making \"a\" the next part to be\nreturned. As the subexpression is bound to substring \"n\" in this case, the \"n\"\nis inserted into this group. The last group consists of the remaining string, as\nno more matches are found.\n\nBy default, all parts of the string, including the empty strings, are returned\nfrom the function, for example:\n\n```erlang\nre:split(\"Erlang\",\"[lg]\",[{return,list}]).\n```\n\ngives\n\n```erlang\n[\"Er\",\"an\",[]]\n```\n\nas the matching of the \"g\" in the end of the string leaves an empty rest, which\nis also returned. This behavior differs from the default behavior of the split\nfunction in Perl, where empty strings at the end are by default removed. To get\nthe \"trimming\" default behavior of Perl, specify `trim` as an option:\n\n```erlang\nre:split(\"Erlang\",\"[lg]\",[{return,list},trim]).\n```\n\ngives\n\n```erlang\n[\"Er\",\"an\"]\n```\n\nThe \"trim\" option says; \"give me as many parts as possible except the empty\nones\", which sometimes can be useful. You can also specify how many parts you\nwant, by specifying `{parts,`N`}`:\n\n```erlang\nre:split(\"Erlang\",\"[lg]\",[{return,list},{parts,2}]).\n```\n\ngives\n\n```erlang\n[\"Er\",\"ang\"]\n```\n\nNotice that the last part is \"ang\", not \"an\", as splitting was specified into\ntwo parts, and the splitting stops when enough parts are given, which is why the\nresult differs from that of `trim`.\n\nMore than three parts are not possible with this indata, so\n\n```erlang\nre:split(\"Erlang\",\"[lg]\",[{return,list},{parts,4}]).\n```\n\ngives the same result as the default, which is to be viewed as \"an infinite\nnumber of parts\".\n\nSpecifying `0` as the number of parts gives the same effect as option `trim`. If\nsubexpressions are captured, empty subexpressions matched at the end are also\nstripped from the result if `trim` or `{parts,0}` is specified.\n\nThe `trim` behavior corresponds exactly to the Perl default. `{parts,N}`, where\nN is a positive integer, corresponds exactly to the Perl behavior with a\npositive numerical third parameter. The default behavior of\n[`split/3`](`split/3`) corresponds to the Perl behavior when a negative integer\nis specified as the third parameter for the Perl routine.\n\nSummary of options not previously described for function [`run/3`](`run/3`):\n\n- **`{return,ReturnType}`** - Specifies how the parts of the original string are\n presented in the result list. Valid types:\n\n - **`iodata`** - The variant of `t:iodata/0` that gives the least copying of\n data with the current implementation (often a binary, but do not depend on\n it).\n\n - **`binary`** - All parts returned as binaries.\n\n - **`list`** - All parts returned as lists of characters (\"strings\").\n\n- **`group`** - Groups together the part of the string with the parts of the\n string matching the subexpressions of the regular expression.\n\n The return value from the function is in this case a `t:list/0` of\n `t:list/0`s. Each sublist begins with the string picked out of the subject\n string, followed by the parts matching each of the subexpressions in order of\n occurrence in the regular expression.\n\n- **`{parts,N}`** - Specifies the number of parts the subject string is to be\n split into.\n\n The number of parts is to be a positive integer for a specific maximum number\n of parts, and `infinity` for the maximum number of parts possible (the\n default). Specifying `{parts,0}` gives as many parts as possible disregarding\n empty parts at the end, the same as specifying `trim`.\n\n- **`trim`** - Specifies that empty parts at the end of the result list are to\n be disregarded. The same as specifying `{parts,0}`. This corresponds to the\n default behavior of the `split` built-in function in Perl.","title":"re.split/3","ref":"re.html#split/3"},{"type":"function","doc":"The return of this function is a string with the PCRE version of the system that\nwas used in the Erlang/OTP compilation.","title":"re.version/0","ref":"re.html#version/0"},{"type":"type","doc":"","title":"re.capture/0","ref":"re.html#t:capture/0"},{"type":"type","doc":"","title":"re.compile_option/0","ref":"re.html#t:compile_option/0"},{"type":"type","doc":"","title":"re.compile_options/0","ref":"re.html#t:compile_options/0"},{"type":"type","doc":"Opaque data type containing a compiled regular expression.\n\n`t:mp/0` is guaranteed to be a tuple() having the atom `re_pattern` as its first element, to\nallow for matching in guards. The arity of the tuple or the content of the other\nfields can change in future Erlang/OTP releases.","title":"re.mp/0","ref":"re.html#t:mp/0"},{"type":"type","doc":"","title":"re.nl_spec/0","ref":"re.html#t:nl_spec/0"},{"type":"type","doc":"","title":"re.option/0","ref":"re.html#t:option/0"},{"type":"type","doc":"","title":"re.options/0","ref":"re.html#t:options/0"},{"type":"type","doc":"","title":"re.replace_fun/0","ref":"re.html#t:replace_fun/0"},{"type":"module","doc":"String processing functions.\n\nThis module provides functions for string processing.\n\nA string in this module is represented by `t:unicode:chardata/0`, that is, a\nlist of codepoints, binaries with UTF-8-encoded codepoints (_UTF-8 binaries_),\nor a mix of the two.\n\n```text\n\"abcd\" is a valid string\n<<\"abcd\">> is a valid string\n[\"abcd\"] is a valid string\n<<\"abc..åäö\"/utf8>> is a valid string\n<<\"abc..åäö\">> is NOT a valid string,\n but a binary with Latin-1-encoded codepoints\n[<<\"abc\">>, \"..åäö\"] is a valid string\n[atom] is NOT a valid string\n```\n\nThis module operates on grapheme clusters. A _grapheme cluster_ is a\nuser-perceived character, which can be represented by several codepoints.\n\n```text\n\"å\" [229] or [97, 778]\n\"e̊\" [101, 778]\n```\n\nThe string length of \"ß↑e̊\" is 3, even though it is represented by the codepoints\n`[223,8593,101,778]` or the UTF-8 binary `<<195,159,226,134,145,101,204,138>>`.\n\nGrapheme clusters for codepoints of class `prepend` and non-modern (or\ndecomposed) Hangul is not handled for performance reasons in `find/3`,\n`replace/3`, `split/2`, `split/3` and `trim/3`.\n\nSplitting and appending strings is to be done on grapheme clusters borders.\nThere is no verification that the results of appending strings are valid or\nnormalized.\n\nMost of the functions expect all input to be normalized to one form, see for\nexample `unicode:characters_to_nfc_list/1`.\n\nLanguage or locale specific handling of input is not considered in any function.\n\nThe functions can crash for non-valid input strings. For example, the functions\nexpect UTF-8 binaries but not all functions verify that all binaries are encoded\ncorrectly.\n\nUnless otherwise specified the return value type is the same as the input type.\nThat is, binary input returns binary output, list input returns a list output,\nand mixed input can return a mixed output.\n\n```erlang\n1> string:trim(\" sarah \").\n\"sarah\"\n2> string:trim(<<\" sarah \">>).\n<<\"sarah\">>\n3> string:lexemes(\"foo bar\", \" \").\n[\"foo\",\"bar\"]\n4> string:lexemes(<<\"foo bar\">>, \" \").\n[<<\"foo\">>,<<\"bar\">>]\n```\n\nThis module has been reworked in Erlang/OTP 20 to handle `t:unicode:chardata/0`\nand operate on grapheme clusters. The\n[`old functions`](`m:string#obsolete-api-functions`) that only work on Latin-1\nlists as input are still available but should not be used, they will be\ndeprecated in a future release.","title":"string","ref":"string.html"},{"type":"module","doc":"Some of the general string functions can seem to overlap each other. The reason\nis that this string package is the combination of two earlier packages and all\nfunctions of both packages have been retained.","title":"Notes - string","ref":"string.html#module-notes"},{"type":"function","doc":"Converts `String` to a case-agnostic comparable string. Function\n[`casefold/1`](`casefold/1`) is preferred over [`lowercase/1`](`lowercase/1`)\nwhen two strings are to be compared for equality. See also `equal/4`.\n\n_Example:_\n\n```erlang\n1> string:casefold(\"Ω and ẞ SHARP S\").\n\"ω and ss sharp s\"\n```","title":"string.casefold/1","ref":"string.html#casefold/1"},{"type":"function","doc":"","title":"string.centre/2","ref":"string.html#centre/2"},{"type":"function","doc":"Returns a string, where `String` is centered in the string and surrounded by\nblanks or `Character`. The resulting string has length `Number`.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use `pad/3`.","title":"string.centre/3","ref":"string.html#centre/3"},{"type":"function","doc":"","title":"string.chars/2","ref":"string.html#chars/2"},{"type":"function","doc":"Returns a string consisting of `Number` characters `Character`. Optionally, the\nstring can end with string `Tail`.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use\n`lists:duplicate/2`.","title":"string.chars/3","ref":"string.html#chars/3"},{"type":"function","doc":"Returns a string where any trailing `\\n` or `\\r\\n` have been removed from\n`String`.\n\n_Example:_\n\n```erlang\n182> string:chomp(<<\"\\nHello\\n\\n\">>).\n<<\"\\nHello\">>\n183> string:chomp(\"\\nHello\\r\\r\\n\").\n\"\\nHello\\r\"\n```","title":"string.chomp/1","ref":"string.html#chomp/1"},{"type":"function","doc":"Returns the index of the first occurrence of `Character` in `String`. Returns\n`0` if `Character` does not occur.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use `find/2`.","title":"string.chr/2","ref":"string.html#chr/2"},{"type":"function","doc":"Concatenates `String1` and `String2` to form a new string `String3`, which is\nreturned.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use\n`[String1, String2]` as `Data` argument, and call `unicode:characters_to_list/2`\nor `unicode:characters_to_binary/2` to flatten the output.","title":"string.concat/2","ref":"string.html#concat/2"},{"type":"function","doc":"Returns a string containing `String` repeated `Number` times.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use\n`lists:duplicate/2`.","title":"string.copies/2","ref":"string.html#copies/2"},{"type":"function","doc":"Returns the length of the maximum initial segment of `String`, which consists\nentirely of characters not from `Chars`.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use `take/3`.\n\n_Example:_\n\n```erlang\n1> string:cspan(\"\\t abcdef\", \" \\t\").\n0\n```","title":"string.cspan/2","ref":"string.html#cspan/2"},{"type":"function","doc":"","title":"string.equal/2","ref":"string.html#equal/2"},{"type":"function","doc":"","title":"string.equal/3","ref":"string.html#equal/3"},{"type":"function","doc":"Returns `true` if `A` and `B` are equal, otherwise `false`.\n\nIf `IgnoreCase` is `true` the function does [`casefold`ing](`casefold/1`) on the\nfly before the equality test.\n\nIf `Norm` is not `none` the function applies normalization on the fly before the\nequality test. There are four available normalization forms:\n[`nfc`](`unicode:characters_to_nfc_list/1`),\n[`nfd`](`unicode:characters_to_nfd_list/1`),\n[`nfkc`](`unicode:characters_to_nfkc_list/1`), and\n[`nfkd`](`unicode:characters_to_nfkd_list/1`).\n\n_Example:_\n\n```erlang\n1> string:equal(\"åäö\", <<\"åäö\"/utf8>>).\ntrue\n2> string:equal(\"åäö\", unicode:characters_to_nfd_binary(\"åäö\")).\nfalse\n3> string:equal(\"åäö\", unicode:characters_to_nfd_binary(\"ÅÄÖ\"), true, nfc).\ntrue\n```","title":"string.equal/4","ref":"string.html#equal/4"},{"type":"function","doc":"","title":"string.find/2","ref":"string.html#find/2"},{"type":"function","doc":"Removes anything before `SearchPattern` in `String` and returns the remainder of\nthe string or `nomatch` if `SearchPattern` is not found. `Dir`, which can be\n`leading` or `trailing`, indicates from which direction characters are to be\nsearched.\n\n_Example:_\n\n```erlang\n1> string:find(\"ab..cd..ef\", \".\").\n\"..cd..ef\"\n2> string:find(<<\"ab..cd..ef\">>, \"..\", trailing).\n<<\"..ef\">>\n3> string:find(<<\"ab..cd..ef\">>, \"x\", leading).\nnomatch\n4> string:find(\"ab..cd..ef\", \"x\", trailing).\nnomatch\n```","title":"string.find/3","ref":"string.html#find/3"},{"type":"function","doc":"Returns `true` if `String` is the empty string, otherwise `false`.\n\n_Example:_\n\n```erlang\n1> string:is_empty(\"foo\").\nfalse\n2> string:is_empty([\"\",<<>>]).\ntrue\n```","title":"string.is_empty/1","ref":"string.html#is_empty/1"},{"type":"function","doc":"Returns a float between `+0.0` and `1.0` representing the\n[Jaro similarity](https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance)\nbetween the given strings. Strings with a higher similarity will score closer\nto `1.0`, with `+0.0` meaning no similarity and `1.0` meaning an exact match.\n\n_Example:_\n\n```erlang\n1> string:jaro_similarity(\"ditto\", \"ditto\").\n1.0\n2> string:jaro_similarity(\"foo\", \"bar\").\n+0.0\n3> string:jaro_similarity(\"michelle\", \"michael\").\n0.8690476190476191\n4> string:jaro_similarity(<<\"Édouard\"/utf8>>, <<\"Claude\">>).\n0.5317460317460317\n```\n\nThe Jaro distance between two strings can be calculated with\n`JaroDistance = 1.0 - JaroSimilarity`.","title":"string.jaro_similarity/2","ref":"string.html#jaro_similarity/2"},{"type":"function","doc":"Returns a string with the elements of `StringList` separated by the string in\n`Separator`.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use\n`lists:join/2`.\n\n_Example:_\n\n```erlang\n1> join([\"one\", \"two\", \"three\"], \", \").\n\"one, two, three\"\n```","title":"string.join/2","ref":"string.html#join/2"},{"type":"function","doc":"","title":"string.left/2","ref":"string.html#left/2"},{"type":"function","doc":"Returns `String` with the length adjusted in accordance with `Number`. The left\nmargin is fixed. If [`length(String)`](`length/1`) < `Number`, then `String` is\npadded with blanks or `Character`s.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use `pad/2` or\n`pad/3`.\n\n_Example:_\n\n```erlang\n1> string:left(\"Hello\",10,$.).\n\"Hello.....\"\n```","title":"string.left/3","ref":"string.html#left/3"},{"type":"function","doc":"Returns the number of characters in `String`.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use `length/1`.","title":"string.len/1","ref":"string.html#len/1"},{"type":"function","doc":"Returns the number of grapheme clusters in `String`.\n\n_Example:_\n\n```erlang\n1> string:length(\"ß↑e̊\").\n3\n2> string:length(<<195,159,226,134,145,101,204,138>>).\n3\n```","title":"string.length/1","ref":"string.html#length/1"},{"type":"function","doc":"Returns a list of lexemes in `String`, separated by the grapheme clusters in\n`SeparatorList`.\n\nNotice that, as shown in this example, two or more adjacent separator graphemes\nclusters in `String` are treated as one. That is, there are no empty strings in\nthe resulting list of lexemes. See also `split/3` which returns empty strings.\n\nNotice that `[$\\r,$\\n]` is one grapheme cluster.\n\n_Example:_\n\n```erlang\n1> string:lexemes(\"abc de̊fxxghix jkl\\r\\nfoo\", \"x e\" ++ [[$\\r,$\\n]]).\n[\"abc\",\"de̊f\",\"ghi\",\"jkl\",\"foo\"]\n2> string:lexemes(<<\"abc de̊fxxghix jkl\\r\\nfoo\"/utf8>>, \"x e\" ++ [$\\r,$\\n]).\n[<<\"abc\">>,<<\"de̊f\"/utf8>>,<<\"ghi\">>,<<\"jkl\\r\\nfoo\">>]\n```","title":"string.lexemes/2","ref":"string.html#lexemes/2"},{"type":"function","doc":"Converts `String` to lowercase.\n\nNotice that function `casefold/1` should be used when converting a string to be\ntested for equality.\n\n_Example:_\n\n```erlang\n2> string:lowercase(string:uppercase(\"Michał\")).\n\"michał\"\n```","title":"string.lowercase/1","ref":"string.html#lowercase/1"},{"type":"function","doc":"Returns the first codepoint in `String` and the rest of `String` in the tail.\nReturns an empty list if `String` is empty or an `{error, String}` tuple if the\nnext byte is invalid.\n\n_Example:_\n\n```erlang\n1> string:next_codepoint(unicode:characters_to_binary(\"e̊fg\")).\n[101|<<\"̊fg\"/utf8>>]\n```","title":"string.next_codepoint/1","ref":"string.html#next_codepoint/1"},{"type":"function","doc":"Returns the first grapheme cluster in `String` and the rest of `String` in the\ntail. Returns an empty list if `String` is empty or an `{error, String}` tuple\nif the next byte is invalid.\n\n_Example:_\n\n```erlang\n1> string:next_grapheme(unicode:characters_to_binary(\"e̊fg\")).\n[\"e̊\"|<<\"fg\">>]\n```","title":"string.next_grapheme/1","ref":"string.html#next_grapheme/1"},{"type":"function","doc":"Returns lexeme number `N` in `String`, where lexemes are separated by the\ngrapheme clusters in `SeparatorList`.\n\n_Example:_\n\n```erlang\n1> string:nth_lexeme(\"abc.de̊f.ghiejkl\", 3, \".e\").\n\"ghi\"\n```","title":"string.nth_lexeme/3","ref":"string.html#nth_lexeme/3"},{"type":"function","doc":"","title":"string.pad/2","ref":"string.html#pad/2"},{"type":"function","doc":"","title":"string.pad/3","ref":"string.html#pad/3"},{"type":"function","doc":"Pads `String` to `Length` with grapheme cluster `Char`. `Dir`, which can be\n`leading`, `trailing`, or `both`, indicates where the padding should be added.\n\n_Example:_\n\n```erlang\n1> string:pad(<<\"He̊llö\"/utf8>>, 8).\n[<<72,101,204,138,108,108,195,182>>,32,32,32]\n2> io:format(\"'~ts'~n\",[string:pad(\"He̊llö\", 8, leading)]).\n' He̊llö'\n3> io:format(\"'~ts'~n\",[string:pad(\"He̊llö\", 8, both)]).\n' He̊llö '\n```","title":"string.pad/4","ref":"string.html#pad/4"},{"type":"function","doc":"If `Prefix` is the prefix of `String`, removes it and returns the remainder of\n`String`, otherwise returns `nomatch`.\n\n_Example:_\n\n```erlang\n1> string:prefix(<<\"prefix of string\">>, \"pre\").\n<<\"fix of string\">>\n2> string:prefix(\"pre\", \"prefix\").\nnomatch\n```","title":"string.prefix/2","ref":"string.html#prefix/2"},{"type":"function","doc":"Returns the index of the last occurrence of `Character` in `String`. Returns `0`\nif `Character` does not occur.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use `find/3`.","title":"string.rchr/2","ref":"string.html#rchr/2"},{"type":"function","doc":"","title":"string.replace/3","ref":"string.html#replace/3"},{"type":"function","doc":"Replaces `SearchPattern` in `String` with `Replacement`. `Where`, indicates whether\nthe `leading`, the `trailing` or `all` encounters of `SearchPattern` are to be replaced.\n\nCan be implemented as:\n\n```erlang\nlists:join(Replacement, split(String, SearchPattern, Where)).\n```\n\n_Example:_\n\n```erlang\n1> string:replace(<<\"ab..cd..ef\">>, \"..\", \"*\").\n[<<\"ab\">>,\"*\",<<\"cd..ef\">>]\n2> string:replace(<<\"ab..cd..ef\">>, \"..\", \"*\", all).\n[<<\"ab\">>,\"*\",<<\"cd\">>,\"*\",<<\"ef\">>]\n```","title":"string.replace/4","ref":"string.html#replace/4"},{"type":"function","doc":"Returns the reverse list of the grapheme clusters in `String`.\n\n_Example:_\n\n```erlang\n1> Reverse = string:reverse(unicode:characters_to_nfd_binary(\"ÅÄÖ\")).\n[[79,776],[65,776],[65,778]]\n2> io:format(\"~ts~n\",[Reverse]).\nÖÄÅ\n```","title":"string.reverse/1","ref":"string.html#reverse/1"},{"type":"function","doc":"","title":"string.right/2","ref":"string.html#right/2"},{"type":"function","doc":"Returns `String` with the length adjusted in accordance with `Number`. The right\nmargin is fixed. If the length of `(String)` < `Number`, then `String` is padded\nwith blanks or `Character`s.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use `pad/3`.\n\n_Example:_\n\n```erlang\n1> string:right(\"Hello\", 10, $.).\n\".....Hello\"\n```","title":"string.right/3","ref":"string.html#right/3"},{"type":"function","doc":"Returns the position where the last occurrence of `SubString` begins in\n`String`. Returns `0` if `SubString` does not exist in `String`.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use `find/3`.\n\n_Example:_\n\n```erlang\n1> string:rstr(\" Hello Hello World World \", \"Hello World\").\n8\n```","title":"string.rstr/2","ref":"string.html#rstr/2"},{"type":"function","doc":"","title":"string.slice/2","ref":"string.html#slice/2"},{"type":"function","doc":"Returns a substring of `String` of at most `Length` grapheme clusters, starting\nat position `Start`.\n\n_Example:_\n\n```erlang\n1> string:slice(<<\"He̊llö Wörld\"/utf8>>, 4).\n<<\"ö Wörld\"/utf8>>\n2> string:slice([\"He̊llö \", <<\"Wörld\"/utf8>>], 4,4).\n\"ö Wö\"\n3> string:slice([\"He̊llö \", <<\"Wörld\"/utf8>>], 4,50).\n\"ö Wörld\"\n```","title":"string.slice/3","ref":"string.html#slice/3"},{"type":"function","doc":"Returns the length of the maximum initial segment of `String`, which consists\nentirely of characters from `Chars`.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use `take/2`.\n\n_Example:_\n\n```erlang\n1> string:span(\"\\t abcdef\", \" \\t\").\n5\n```","title":"string.span/2","ref":"string.html#span/2"},{"type":"function","doc":"","title":"string.split/2","ref":"string.html#split/2"},{"type":"function","doc":"Splits `String` where `SearchPattern` is encountered and return the remaining\nparts. `Where`, default `leading`, indicates whether the `leading`, the\n`trailing` or `all` encounters of `SearchPattern` will split `String`.\n\n_Example:_\n\n```erlang\n0> string:split(\"ab..bc..cd\", \"..\").\n[\"ab\",\"bc..cd\"]\n1> string:split(<<\"ab..bc..cd\">>, \"..\", trailing).\n[<<\"ab..bc\">>,<<\"cd\">>]\n2> string:split(<<\"ab..bc....cd\">>, \"..\", all).\n[<<\"ab\">>,<<\"bc\">>,<<>>,<<\"cd\">>]\n```","title":"string.split/3","ref":"string.html#split/3"},{"type":"function","doc":"Returns the position where the first occurrence of `SubString` begins in\n`String`. Returns `0` if `SubString` does not exist in `String`.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use `find/2`.\n\n_Example:_\n\n```erlang\n1> string:str(\" Hello Hello World World \", \"Hello World\").\n8\n```","title":"string.str/2","ref":"string.html#str/2"},{"type":"function","doc":"","title":"string.strip/1","ref":"string.html#strip/1"},{"type":"function","doc":"","title":"string.strip/2","ref":"string.html#strip/2"},{"type":"function","doc":"Returns a string, where leading or trailing, or both, blanks or a number of\n`Character` have been removed.\n\n`Direction`, which can be `left`, `right`, or\n`both`, indicates from which direction blanks are to be removed.\n[`strip/1`](`strip/1`) is equivalent to [`strip(String, both)`](`strip/2`).\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use `trim/3`.\n\n_Example:_\n\n```erlang\n1> string:strip(\"...Hello.....\", both, $.).\n\"Hello\"\n```","title":"string.strip/3","ref":"string.html#strip/3"},{"type":"function","doc":"","title":"string.sub_string/2","ref":"string.html#sub_string/2"},{"type":"function","doc":"Returns a substring of `String`, starting at position `Start` to the end of the\nstring, or to and including position `Stop`.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use `slice/3`.\n\n_Example:_\n\n```erlang\n1> sub_string(\"Hello World\", 4, 8).\n\"lo Wo\"\n```","title":"string.sub_string/3","ref":"string.html#sub_string/3"},{"type":"function","doc":"","title":"string.sub_word/2","ref":"string.html#sub_word/2"},{"type":"function","doc":"Returns the word in position `Number` of `String`. Words are separated by blanks\nor `Character`s.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use\n`nth_lexeme/3`.\n\n_Example:_\n\n```erlang\n1> string:sub_word(\" Hello old boy !\",3,$o).\n\"ld b\"\n```","title":"string.sub_word/3","ref":"string.html#sub_word/3"},{"type":"function","doc":"","title":"string.substr/2","ref":"string.html#substr/2"},{"type":"function","doc":"Returns a substring of `String`, starting at position `Start`, and ending at the\nend of the string or at length `Length`.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use `slice/3`.\n\n_Example:_\n\n```erlang\n1> substr(\"Hello World\", 4, 5).\n\"lo Wo\"\n```","title":"string.substr/3","ref":"string.html#substr/3"},{"type":"function","doc":"","title":"string.take/2","ref":"string.html#take/2"},{"type":"function","doc":"","title":"string.take/3","ref":"string.html#take/3"},{"type":"function","doc":"Takes characters from `String` as long as the characters are members of set\n`Characters` or the complement of set `Characters`. `Dir`, which can be\n`leading` or `trailing`, indicates from which direction characters are to be\ntaken.\n\n_Example:_\n\n```erlang\n5> string:take(\"abc0z123\", lists:seq($a,$z)).\n{\"abc\",\"0z123\"}\n6> string:take(<<\"abc0z123\">>, lists:seq($0,$9), true, leading).\n{<<\"abc\">>,<<\"0z123\">>}\n7> string:take(\"abc0z123\", lists:seq($0,$9), false, trailing).\n{\"abc0z\",\"123\"}\n8> string:take(<<\"abc0z123\">>, lists:seq($a,$z), true, trailing).\n{<<\"abc0z\">>,<<\"123\">>}\n```","title":"string.take/4","ref":"string.html#take/4"},{"type":"function","doc":"Converts `String` to titlecase.\n\n_Example:_\n\n```erlang\n1> string:titlecase(\"ß is a SHARP s\").\n\"Ss is a SHARP s\"\n```","title":"string.titlecase/1","ref":"string.html#titlecase/1"},{"type":"function","doc":"Argument `String` is expected to start with a valid text represented float (the\ndigits are ASCII values). Remaining characters in the string after the float are\nreturned in `Rest`.\n\n_Example:_\n\n```erlang\n1> {F1,Fs} = string:to_float(\"1.0-1.0e-1\"),\n1> {F2,[]} = string:to_float(Fs),\n1> F1+F2.\n0.9\n2> string:to_float(\"3/2=1.5\").\n{error,no_float}\n3> string:to_float(\"-1.5eX\").\n{-1.5,\"eX\"}\n```","title":"string.to_float/1","ref":"string.html#to_float/1"},{"type":"function","doc":"Converts `String` to a list of grapheme clusters.\n\n_Example:_\n\n```erlang\n1> string:to_graphemes(\"ß↑e̊\").\n[223,8593,[101,778]]\n2> string:to_graphemes(<<\"ß↑e̊\"/utf8>>).\n[223,8593,[101,778]]\n```","title":"string.to_graphemes/1","ref":"string.html#to_graphemes/1"},{"type":"function","doc":"Argument `String` is expected to start with a valid text represented integer\n(the digits are ASCII values). Remaining characters in the string after the\ninteger are returned in `Rest`.\n\n_Example:_\n\n```erlang\n1> {I1,Is} = string:to_integer(\"33+22\"),\n1> {I2,[]} = string:to_integer(Is),\n1> I1-I2.\n11\n2> string:to_integer(\"0.5\").\n{0,\".5\"}\n3> string:to_integer(\"x=2\").\n{error,no_integer}\n```","title":"string.to_integer/1","ref":"string.html#to_integer/1"},{"type":"function","doc":"The specified string or character is case-converted. Notice that the supported\ncharacter set is ISO/IEC 8859-1 (also called Latin 1); all values outside this\nset are unchanged.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`) use\n`lowercase/1`, `titlecase/1` or `casefold/1`.","title":"string.to_lower/1","ref":"string.html#to_lower/1"},{"type":"function","doc":"The specified string or character is case-converted. Notice that the supported\ncharacter set is ISO/IEC 8859-1 (also called Latin 1); all values outside this\nset are unchanged.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`) use\n`uppercase/1`, `titlecase/1` or `casefold/1`.","title":"string.to_upper/1","ref":"string.html#to_upper/1"},{"type":"function","doc":"Returns a list of tokens in `String`, separated by the characters in\n`SeparatorList`.\n\n_Example:_\n\n```erlang\n1> tokens(\"abc defxxghix jkl\", \"x \").\n[\"abc\", \"def\", \"ghi\", \"jkl\"]\n```\n\nNotice that, as shown in this example, two or more adjacent separator characters\nin `String` are treated as one. That is, there are no empty strings in the\nresulting list of tokens.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use `lexemes/2`.","title":"string.tokens/2","ref":"string.html#tokens/2"},{"type":"function","doc":"","title":"string.trim/1","ref":"string.html#trim/1"},{"type":"function","doc":"Equivalent to [`trim(String, Dir, Whitespace})`](`trim/3`) where \n`Whitespace` is the set of nonbreakable whitespace codepoints, defined\nas Pattern_White_Space in\n[Unicode Standard Annex #31](http://unicode.org/reports/tr31/).","title":"string.trim/2","ref":"string.html#trim/2"},{"type":"function","doc":"Returns a string, where leading or trailing, or both, `Characters` have been\nremoved.\n\n`Dir` which can be `leading`, `trailing`, or `both`, indicates from\nwhich direction characters are to be removed.\n\nNote that `[$\\r,$\\n]` is one grapheme cluster according to the Unicode\nStandard.\n\n_Example:_\n\n```erlang\n1> string:trim(\"\\t Hello \\n\").\n\"Hello\"\n2> string:trim(<<\"\\t Hello \\n\">>, leading).\n<<\"Hello \\n\">>\n3> string:trim(<<\".Hello.\\n\">>, trailing, \"\\n.\").\n<<\".Hello\">>\n```","title":"string.trim/3","ref":"string.html#trim/3"},{"type":"function","doc":"Converts `String` to uppercase.\n\nSee also `titlecase/1`.\n\n_Example:_\n\n```erlang\n1> string:uppercase(\"Michał\").\n\"MICHAŁ\"\n```","title":"string.uppercase/1","ref":"string.html#uppercase/1"},{"type":"function","doc":"","title":"string.words/1","ref":"string.html#words/1"},{"type":"function","doc":"Returns the number of words in `String`, separated by blanks or `Character`.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use `lexemes/2`.\n\n_Example:_\n\n```erlang\n1> words(\" Hello old boy!\", $o).\n4\n```","title":"string.words/2","ref":"string.html#words/2"},{"type":"type","doc":"","title":"string.direction/0","ref":"string.html#t:direction/0"},{"type":"type","doc":"A user-perceived character, consisting of one or more codepoints.","title":"string.grapheme_cluster/0","ref":"string.html#t:grapheme_cluster/0"},{"type":"module","doc":"Functions for converting Unicode characters.\n\nThis module contains functions for converting between different character\nrepresentations. It converts between ISO Latin-1 characters and Unicode\ncharacters, but it can also convert between different Unicode encodings (like\nUTF-8, UTF-16, and UTF-32).\n\nThe default Unicode encoding in Erlang binaries is UTF-8, which is also the\nformat in which built-in functions and libraries in OTP expect to find binary\nUnicode data. In lists, Unicode data is encoded as integers, each integer\nrepresenting one character and encoded simply as the Unicode code point for the\ncharacter.\n\nOther Unicode encodings than integers representing code points or UTF-8 in\nbinaries are referred to as \"external encodings\". The ISO Latin-1 encoding is in\nbinaries and lists referred to as latin1-encoding.\n\nIt is recommended to only use external encodings for communication with external\nentities where this is required. When working inside the Erlang/OTP environment,\nit is recommended to keep binaries in UTF-8 when representing Unicode\ncharacters. ISO Latin-1 encoding is supported both for backward compatibility\nand for communication with external entities not supporting Unicode character\nsets.\n\nPrograms should always operate on a normalized form and compare\ncanonical-equivalent Unicode characters as equal. All characters should thus be\nnormalized to one form once on the system borders. One of the following\nfunctions can convert characters to their normalized forms\n`characters_to_nfc_list/1`, `characters_to_nfc_binary/1`,\n`characters_to_nfd_list/1` or `characters_to_nfd_binary/1`. For general text\n`characters_to_nfc_list/1` or `characters_to_nfc_binary/1` is preferred, and for\nidentifiers one of the compatibility normalization functions, such as\n`characters_to_nfkc_list/1`, is preferred for security reasons. The\nnormalization functions where introduced in OTP 20. Additional information on\nnormalization can be found in the\n[Unicode FAQ](http://unicode.org/faq/normalization.html).","title":"unicode","ref":"unicode.html"},{"type":"function","doc":"Checks for a UTF Byte Order Mark (BOM) in the beginning of a binary.\n\nIf the supplied binary `Bin` begins with a valid BOM for either UTF-8, UTF-16, or\nUTF-32, the function returns the encoding identified along with the BOM length\nin bytes.\n\nIf no BOM is found, the function returns `{latin1,0}`.","title":"unicode.bom_to_encoding/1","ref":"unicode.html#bom_to_encoding/1"},{"type":"function","doc":"","title":"unicode.characters_to_binary/1","ref":"unicode.html#characters_to_binary/1"},{"type":"function","doc":"","title":"unicode.characters_to_binary/2","ref":"unicode.html#characters_to_binary/2"},{"type":"function","doc":"Behaves as `characters_to_list/2`, but produces a binary instead of a Unicode\nlist.\n\n`InEncoding` defines how input is to be interpreted if binaries are present in\n`Data`\n\n`OutEncoding` defines in what format output is to be generated.\n\nOptions:\n\n- **`unicode`** - An alias for `utf8`, as this is the preferred encoding for\n Unicode characters in binaries.\n\n- **`utf16`** - An alias for `{utf16,big}`.\n\n- **`utf32`** - An alias for `{utf32,big}`.\n\nThe atoms `big` and `little` denote big- or little-endian encoding.\n\nErrors and exceptions occur as in `characters_to_list/2`, but the second element\nin tuple `error` or `incomplete` is a `t:binary/0` and not a `t:list/0`.","title":"unicode.characters_to_binary/3","ref":"unicode.html#characters_to_binary/3"},{"type":"function","doc":"","title":"unicode.characters_to_list/1","ref":"unicode.html#characters_to_list/1"},{"type":"function","doc":"Converts a possibly deep list of integers and binaries into a list of integers\nrepresenting Unicode characters. The binaries in the input can have characters\nencoded as one of the following:\n\n- ISO Latin-1 (0-255, one character per byte). Here, case parameter `InEncoding`\n is to be specified as `latin1`.\n- One of the UTF-encodings, which is specified as parameter `InEncoding`.\n\nNote that integers in the list always represent code points regardless of\n`InEncoding` passed. If `InEncoding latin1` is passed, only code points < 256\nare allowed; otherwise, all valid unicode code points are allowed.\n\nIf `InEncoding` is `latin1`, parameter `Data` corresponds to the `t:iodata/0`\ntype, but for `unicode`, parameter `Data` can contain integers > 255 (Unicode\ncharacters beyond the ISO Latin-1 range), which makes it invalid as\n`t:iodata/0`.\n\nThe purpose of the function is mainly to convert combinations of Unicode\ncharacters into a pure Unicode string in list representation for further\nprocessing. For writing the data to an external entity, the reverse function\n`characters_to_binary/3` comes in handy.\n\nOption `unicode` is an alias for `utf8`, as this is the preferred encoding for\nUnicode characters in binaries. `utf16` is an alias for `{utf16,big}` and\n`utf32` is an alias for `{utf32,big}`. The atoms `big` and `little` denote big-\nor little-endian encoding.\n\nIf the data cannot be converted, either because of illegal Unicode/ISO Latin-1\ncharacters in the list, or because of invalid UTF encoding in any binaries, an\nerror tuple is returned. The error tuple contains the tag `error`, a list\nrepresenting the characters that could be converted before the error occurred\nand a representation of the characters including and after the offending\ninteger/bytes. The last part is mostly for debugging, as it still constitutes a\npossibly deep or mixed list, or both, not necessarily of the same depth as the\noriginal data. The error occurs when traversing the list and whatever is left to\ndecode is returned \"as is\".\n\nHowever, if the input `Data` is a pure binary, the third part of the error tuple\nis guaranteed to be a binary as well.\n\nErrors occur for the following reasons:\n\n- Integers out of range.\n\n If `InEncoding` is `latin1`, an error occurs whenever an integer > 255 is\n found in the lists.\n\n If `InEncoding` is of a Unicode type, an error occurs whenever either of the\n following is found:\n\n - An integer > 16#10FFFF (the maximum Unicode character)\n - An integer in the range 16#D800 to 16#DFFF (invalid range reserved for\n UTF-16 surrogate pairs)\n\n- Incorrect UTF encoding.\n\n If `InEncoding` is one of the UTF types, the bytes in any binaries must be\n valid in that encoding.\n\n Errors can occur for various reasons, including the following:\n\n - \"Pure\" decoding errors (like the upper bits of the bytes being wrong).\n - The bytes are decoded to a too large number.\n - The bytes are decoded to a code point in the invalid Unicode range.\n - Encoding is \"overlong\", meaning that a number should have been encoded in\n fewer bytes.\n\n The case of a truncated UTF is handled specially, see the paragraph about\n incomplete binaries below.\n\n If `InEncoding` is `latin1`, binaries are always valid as long as they contain\n whole bytes, as each byte falls into the valid ISO Latin-1 range.\n\nA special type of error is when no actual invalid integers or bytes are found,\nbut a trailing `t:binary/0` consists of too few bytes to decode the last\ncharacter. This error can occur if bytes are read from a file in chunks or if\nbinaries in other ways are split on non-UTF character boundaries. An\n`incomplete` tuple is then returned instead of the `error` tuple. It consists of\nthe same parts as the `error` tuple, but the tag is `incomplete` instead of\n`error` and the last element is always guaranteed to be a binary consisting of\nthe first part of a (so far) valid UTF character.\n\nIf one UTF character is split over two consecutive binaries in the `Data`, the\nconversion succeeds. This means that a character can be decoded from a range of\nbinaries as long as the whole range is specified as input without errors\noccurring.\n\n_Example:_\n\n```erlang\ndecode_data(Data) ->\n case unicode:characters_to_list(Data,unicode) of\n {incomplete,Encoded, Rest} ->\n More = get_some_more_data(),\n Encoded ++ decode_data([Rest, More]);\n {error,Encoded,Rest} ->\n handle_error(Encoded,Rest);\n List ->\n List\n end.\n```\n\nHowever, bit strings that are not whole bytes are not allowed, so a UTF\ncharacter must be split along 8-bit boundaries to ever be decoded.\n\nA `badarg` exception is thrown for the following cases:\n\n- Any parameters are of the wrong type.\n- The list structure is invalid (a number as tail).\n- The binaries do not contain whole bytes (bit strings).","title":"unicode.characters_to_list/2","ref":"unicode.html#characters_to_list/2"},{"type":"function","doc":"Converts a possibly deep list of characters and binaries into a Normalized Form\nof canonical equivalent Composed characters according to the Unicode standard.\n\nAny binaries in the input must be encoded with utf8 encoding.\n\nThe result is an utf8 encoded binary.\n\n```erlang\n4> unicode:characters_to_nfc_binary([<<\"abc..a\">>,[778],$a,[776],$o,[776]]).\n<<\"abc..åäö\"/utf8>>\n```","title":"unicode.characters_to_nfc_binary/1","ref":"unicode.html#characters_to_nfc_binary/1"},{"type":"function","doc":"Converts a possibly deep list of characters and binaries into a Normalized Form\nof canonical equivalent Composed characters according to the Unicode standard.\n\nAny binaries in the input must be encoded with utf8 encoding.\n\nThe result is a list of characters.\n\n```erlang\n3> unicode:characters_to_nfc_list([<<\"abc..a\">>,[778],$a,[776],$o,[776]]).\n\"abc..åäö\"\n```","title":"unicode.characters_to_nfc_list/1","ref":"unicode.html#characters_to_nfc_list/1"},{"type":"function","doc":"Converts a possibly deep list of characters and binaries into a Normalized Form\nof canonical equivalent Decomposed characters according to the Unicode standard.\n\nAny binaries in the input must be encoded with utf8 encoding.\n\nThe result is an utf8 encoded binary.\n\n```erlang\n2> unicode:characters_to_nfd_binary(\"abc..åäö\").\n<<97,98,99,46,46,97,204,138,97,204,136,111,204,136>>\n```","title":"unicode.characters_to_nfd_binary/1","ref":"unicode.html#characters_to_nfd_binary/1"},{"type":"function","doc":"Converts a possibly deep list of characters and binaries into a Normalized Form\nof canonical equivalent Decomposed characters according to the Unicode standard.\n\nAny binaries in the input must be encoded with utf8 encoding.\n\nThe result is a list of characters.\n\n```erlang\n1> unicode:characters_to_nfd_list(\"abc..åäö\").\n[97,98,99,46,46,97,778,97,776,111,776]\n```","title":"unicode.characters_to_nfd_list/1","ref":"unicode.html#characters_to_nfd_list/1"},{"type":"function","doc":"Converts a possibly deep list of characters and binaries into a Normalized Form\nof compatibly equivalent Composed characters according to the Unicode standard.\n\nAny binaries in the input must be encoded with utf8 encoding.\n\nThe result is an utf8 encoded binary.\n\n```erlang\n4> unicode:characters_to_nfkc_binary([<<\"abc..a\">>,[778],$a,[776],$o,[776],[65299,65298]]).\n<<\"abc..åäö32\"/utf8>>\n```","title":"unicode.characters_to_nfkc_binary/1","ref":"unicode.html#characters_to_nfkc_binary/1"},{"type":"function","doc":"Converts a possibly deep list of characters and binaries into a Normalized Form\nof compatibly equivalent Composed characters according to the Unicode standard.\n\nAny binaries in the input must be encoded with utf8 encoding.\n\nThe result is a list of characters.\n\n```erlang\n3> unicode:characters_to_nfkc_list([<<\"abc..a\">>,[778],$a,[776],$o,[776],[65299,65298]]).\n\"abc..åäö32\"\n```","title":"unicode.characters_to_nfkc_list/1","ref":"unicode.html#characters_to_nfkc_list/1"},{"type":"function","doc":"Converts a possibly deep list of characters and binaries into a Normalized Form\nof compatibly equivalent Decomposed characters according to the Unicode\nstandard.\n\nAny binaries in the input must be encoded with utf8 encoding.\n\nThe result is an utf8 encoded binary.\n\n```erlang\n2> unicode:characters_to_nfkd_binary([\"abc..åäö\",[65299,65298]]).\n<<97,98,99,46,46,97,204,138,97,204,136,111,204,136,51,50>>\n```","title":"unicode.characters_to_nfkd_binary/1","ref":"unicode.html#characters_to_nfkd_binary/1"},{"type":"function","doc":"Converts a possibly deep list of characters and binaries into a Normalized Form\nof compatibly equivalent Decomposed characters according to the Unicode\nstandard.\n\nAny binaries in the input must be encoded with utf8 encoding.\n\nThe result is a list of characters.\n\n```erlang\n1> unicode:characters_to_nfkd_list([\"abc..åäö\",[65299,65298]]).\n[97,98,99,46,46,97,778,97,776,111,776,51,50]\n```","title":"unicode.characters_to_nfkd_list/1","ref":"unicode.html#characters_to_nfkd_list/1"},{"type":"function","doc":"Creates a UTF Byte Order Mark (BOM) as a binary from the supplied `InEncoding`.\n\nThe BOM is, if supported at all, expected to be placed first in UTF encoded\nfiles or messages.\n\nThe function returns `<<>>` for `latin1` encoding, as there is no BOM for ISO\nLatin-1.\n\nNotice that the BOM for UTF-8 is seldom used, and it is really not a _byte\norder_ mark. There are obviously no byte order issues with UTF-8, so the BOM is\nonly there to differentiate UTF-8 encoding from other UTF formats.","title":"unicode.encoding_to_bom/1","ref":"unicode.html#encoding_to_bom/1"},{"type":"type","doc":"","title":"unicode.chardata/0","ref":"unicode.html#t:chardata/0"},{"type":"type","doc":"","title":"unicode.charlist/0","ref":"unicode.html#t:charlist/0"},{"type":"type","doc":"","title":"unicode.encoding/0","ref":"unicode.html#t:encoding/0"},{"type":"type","doc":"","title":"unicode.endian/0","ref":"unicode.html#t:endian/0"},{"type":"type","doc":"","title":"unicode.external_chardata/0","ref":"unicode.html#t:external_chardata/0"},{"type":"type","doc":"","title":"unicode.external_charlist/0","ref":"unicode.html#t:external_charlist/0"},{"type":"type","doc":"A `t:binary/0` with characters coded in a user-specified Unicode encoding other\nthan UTF-8 (that is, UTF-16 or UTF-32).","title":"unicode.external_unicode_binary/0","ref":"unicode.html#t:external_unicode_binary/0"},{"type":"type","doc":"A `t:binary/0` with characters coded in ISO Latin-1.","title":"unicode.latin1_binary/0","ref":"unicode.html#t:latin1_binary/0"},{"type":"type","doc":"An `t:integer/0` representing a valid ISO Latin-1 character (0-255).","title":"unicode.latin1_char/0","ref":"unicode.html#t:latin1_char/0"},{"type":"type","doc":"Equivalent to `t:iodata/0`.","title":"unicode.latin1_chardata/0","ref":"unicode.html#t:latin1_chardata/0"},{"type":"type","doc":"Equivalent to `t:iolist/0`.","title":"unicode.latin1_charlist/0","ref":"unicode.html#t:latin1_charlist/0"},{"type":"type","doc":"A `t:binary/0` with characters encoded in the UTF-8 coding standard.","title":"unicode.unicode_binary/0","ref":"unicode.html#t:unicode_binary/0"},{"type":"module","doc":"URI processing functions.\n\nThis module contains functions for parsing and handling URIs\n([RFC 3986](https://www.ietf.org/rfc/rfc3986.txt)) and form-urlencoded query\nstrings ([HTML 5.2](https://www.w3.org/TR/html52/)).\n\nParsing and serializing non-UTF-8 form-urlencoded query strings are also\nsupported ([HTML 5.0](https://www.w3.org/TR/html50/)).\n\nA URI is an identifier consisting of a sequence of characters matching the\nsyntax rule named _URI_ in [RFC 3986](https://www.ietf.org/rfc/rfc3986.txt).\n\nThe generic URI syntax consists of a hierarchical sequence of components\nreferred to as the scheme, authority, path, query, and fragment:\n\n```text\n URI = scheme \":\" hier-part [ \"?\" query ] [ \"#\" fragment ]\n hier-part = \"//\" authority path-abempty\n / path-absolute\n / path-rootless\n / path-empty\n scheme = ALPHA *( ALPHA / DIGIT / \"+\" / \"-\" / \".\" )\n authority = [ userinfo \"@\" ] host [ \":\" port ]\n userinfo = *( unreserved / pct-encoded / sub-delims / \":\" )\n\n reserved = gen-delims / sub-delims\n gen-delims = \":\" / \"/\" / \"?\" / \"#\" / \"[\" / \"]\" / \"@\"\n sub-delims = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n\n unreserved = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n```\n\nThe interpretation of a URI depends only on the characters used and not on how\nthose characters are represented in a network protocol.\n\nThe functions implemented by this module cover the following use cases:\n\n- Parsing URIs into its components and returing a map: `parse/1`\n- Recomposing a map of URI components into a URI string: `recompose/1`\n- Changing inbound binary and percent-encoding of URIs: `transcode/2`\n- Transforming URIs into a normalized form: `normalize/1`, `normalize/2`\n- Composing form-urlencoded query strings from a list of key-value pairs:\n `compose_query/1`, `compose_query/2`\n- Dissecting form-urlencoded query strings into a list of key-value pairs:\n `dissect_query/1`\n- Decoding percent-encoded triplets in URI map or a specific component of URI:\n `percent_decode/1`\n- Preparing and retrieving application specific data included in URI\n components:\n `quote/1`, `quote/2`, `unquote/1`\n\nThere are four different encodings present during the handling of URIs:\n\n- Inbound binary encoding in binaries\n- Inbound percent-encoding in lists and binaries\n- Outbound binary encoding in binaries\n- Outbound percent-encoding in lists and binaries\n\nFunctions with `t:uri_string/0` argument accept lists, binaries and mixed lists\n(lists with binary elements) as input type. All of the functions but\n[`transcode/2`](`transcode/2`) expects input as lists of unicode codepoints,\nUTF-8 encoded binaries and UTF-8 percent-encoded URI parts (\"%C3%B6\" corresponds\nto the unicode character \"ö\").\n\nUnless otherwise specified the return value type and encoding are the same as\nthe input type and encoding. That is, binary input returns binary output, list\ninput returns a list output but mixed input returns list output.\n\nIn case of lists there is only percent-encoding. In binaries, however, both\nbinary encoding and percent-encoding shall be considered.\n[`transcode/2`](`transcode/2`) provides the means to convert between the\nsupported encodings, it takes a `t:uri_string/0` and a list of options\nspecifying inbound and outbound encodings.\n\n[RFC 3986](https://www.ietf.org/rfc/rfc3986.txt) does not mandate any specific\ncharacter encoding and it is usually defined by the protocol or surrounding\ntext. This library takes the same assumption, binary and percent-encoding are\nhandled as one configuration unit, they cannot be set to different values.\n\nQuoting functions are intended to be used by URI producing application during\ncomponent preparation or retrieval phase to avoid conflicts between data and\ncharacters used in URI syntax. Quoting functions use percent encoding, but with\ndifferent rules than for example during execution of\n[`recompose/1`](`recompose/1`). It is user responsibility to provide quoting\nfunctions with application data only and using their output to combine an URI\ncomponent. \nQuoting functions can for instance be used for constructing a path component\nwith a segment containing '/' character which should not collide with '/' used\nas general delimiter in path component.","title":"uri_string","ref":"uri_string.html"},{"type":"function","doc":"This is a utility function meant to be used in the shell for printing the\nallowed characters in each major URI component, and also in the most important\ncharacters sets.\n\nNote that this function does not replace the ABNF rules defined by the standards,\nthese character sets are derived directly from those aformentioned rules. For more\ninformation see the\n[Uniform Resource Identifiers](uri_string_usage.md#percent_encoding) chapter in\nstdlib's Users Guide.","title":"uri_string.allowed_characters/0","ref":"uri_string.html#allowed_characters/0"},{"type":"function","doc":"Composes a form-urlencoded `QueryString` based on a `QueryList`, a list of\nnon-percent-encoded key-value pairs.\n\nForm-urlencoding is defined in section 4.10.21.6 of the [HTML 5.2](https://www.w3.org/TR/html52/)\nspecification and in section 4.10.22.6 of the [HTML 5.0](https://www.w3.org/TR/html50/)\nspecification for non-UTF-8 encodings.\n\nSee also the opposite operation `dissect_query/1`.\n\n_Example:_\n\n```erlang\n1> uri_string:compose_query([{\"foo bar\",\"1\"},{\"city\",\"örebro\"}]).\n\"foo+bar=1&city=%C3%B6rebro\"\n2> uri_string:compose_query([{<<\"foo bar\">>,<<\"1\">>},\n2> {<<\"city\">>,<<\"örebro\"/utf8>>}]).\n<<\"foo+bar=1&city=%C3%B6rebro\">>\n```","title":"uri_string.compose_query/1","ref":"uri_string.html#compose_query/1"},{"type":"function","doc":"Same as [`compose_query/1`](`compose_query/1`) but with an additional `Options`\nparameter, that controls the encoding (\"charset\") used by the encoding\nalgorithm.\n\nThere are two supported encodings: `utf8` (or `unicode`) and `latin1`.\n\nEach character in the entry's name and value that cannot be expressed using the\nselected character encoding, is replaced by a string consisting of a U+0026\nAMPERSAND character (&), a \"#\" (U+0023) character, one or more ASCII digits\nrepresenting the Unicode code point of the character in base ten, and finally a\n\";\" (U+003B) character.\n\nBytes that are out of the range 0x2A, 0x2D, 0x2E, 0x30 to 0x39, 0x41 to 0x5A,\n0x5F, 0x61 to 0x7A, are percent-encoded (U+0025 PERCENT SIGN character (%)\nfollowed by uppercase ASCII hex digits representing the hexadecimal value of the\nbyte).\n\nSee also the opposite operation `dissect_query/1`.\n\n_Example:_\n\n```erlang\n1> uri_string:compose_query([{\"foo bar\",\"1\"},{\"city\",\"örebro\"}],\n1> [{encoding, latin1}]).\n\"foo+bar=1&city=%F6rebro\"\n2> uri_string:compose_query([{<<\"foo bar\">>,<<\"1\">>},\n2> {<<\"city\">>,<<\"東京\"/utf8>>}], [{encoding, latin1}]).\n<<\"foo+bar=1&city=%26%2326481%3B%26%2320140%3B\">>\n```","title":"uri_string.compose_query/2","ref":"uri_string.html#compose_query/2"},{"type":"function","doc":"Dissects an urlencoded `QueryString` and returns a `QueryList`, a list of\nnon-percent-encoded key-value pairs.\n\nForm-urlencoding is defined in section 4.10.21.6 of the [HTML 5.2](https://www.w3.org/TR/html52/)\nspecification and in section 4.10.22.6 of the [HTML 5.0](https://www.w3.org/TR/html50/)\nspecification for non-UTF-8 encodings.\n\nSee also the opposite operation `compose_query/1`.\n\n_Example:_\n\n```erlang\n1> uri_string:dissect_query(\"foo+bar=1&city=%C3%B6rebro\").\n[{\"foo bar\",\"1\"},{\"city\",\"örebro\"}]\n2> uri_string:dissect_query(<<\"foo+bar=1&city=%26%2326481%3B%26%2320140%3B\">>).\n[{<<\"foo bar\">>,<<\"1\">>},\n {<<\"city\">>,<<230,157,177,228,186,172>>}]\n```","title":"uri_string.dissect_query/1","ref":"uri_string.html#dissect_query/1"},{"type":"function","doc":"Transforms an `URI` into a normalized form using Syntax-Based Normalization as\ndefined by [RFC 3986](https://www.ietf.org/rfc/rfc3986.txt).\n\nThis function implements case normalization, percent-encoding normalization,\npath segment normalization and scheme based normalization for HTTP(S) with basic\nsupport for FTP, SSH, SFTP and TFTP.\n\n_Example:_\n\n```erlang\n1> uri_string:normalize(\"/a/b/c/./../../g\").\n\"/a/g\"\n2> uri_string:normalize(<<\"mid/content=5/../6\">>).\n<<\"mid/6\">>\n3> uri_string:normalize(\"http://localhost:80\").\n\"http://localhost/\"\n4> uri_string:normalize(#{scheme => \"http\",port => 80,path => \"/a/b/c/./../../g\",\n4> host => \"localhost-örebro\"}).\n\"http://localhost-%C3%B6rebro/a/g\"\n```","title":"uri_string.normalize/1","ref":"uri_string.html#normalize/1"},{"type":"function","doc":"Same as [`normalize/1`](`normalize/1`) but with an additional `Options`\nparameter, that controls whether the normalized URI shall be returned as an\nuri_map().\n\nThere is one supported option: `return_map`.\n\n_Example:_\n\n```erlang\n1> uri_string:normalize(\"/a/b/c/./../../g\", [return_map]).\n#{path => \"/a/g\"}\n2> uri_string:normalize(<<\"mid/content=5/../6\">>, [return_map]).\n#{path => <<\"mid/6\">>}\n3> uri_string:normalize(\"http://localhost:80\", [return_map]).\n#{scheme => \"http\",path => \"/\",host => \"localhost\"}\n4> uri_string:normalize(#{scheme => \"http\",port => 80,path => \"/a/b/c/./../../g\",\n4> host => \"localhost-örebro\"}, [return_map]).\n#{scheme => \"http\",path => \"/a/g\",host => \"localhost-örebro\"}\n```","title":"uri_string.normalize/2","ref":"uri_string.html#normalize/2"},{"type":"function","doc":"Parses an [RFC 3986](https://www.ietf.org/rfc/rfc3986.txt) compliant\n`t:uri_string/0` into a `t:uri_map/0`, that holds the parsed components of the\n`URI`. If parsing fails, an error tuple is returned.\n\nSee also the opposite operation `recompose/1`.\n\n_Example:_\n\n```erlang\n1> uri_string:parse(\"foo://user@example.com:8042/over/there?name=ferret#nose\").\n#{fragment => \"nose\",host => \"example.com\",\n path => \"/over/there\",port => 8042,query => \"name=ferret\",\n scheme => foo,userinfo => \"user\"}\n2> uri_string:parse(<<\"foo://user@example.com:8042/over/there?name=ferret\">>).\n#{host => <<\"example.com\">>,path => <<\"/over/there\">>,\n port => 8042,query => <<\"name=ferret\">>,scheme => <<\"foo\">>,\n userinfo => <<\"user\">>}\n```","title":"uri_string.parse/1","ref":"uri_string.html#parse/1"},{"type":"function","doc":"Decodes all percent-encoded triplets in the input that can be both a\n`t:uri_string/0` and a `t:uri_map/0`.\n\nNote, that this function performs raw decoding and it shall be used on already\nparsed URI components. Applying this function directly on a standard URI can\neffectively change it.\n\nIf the input encoding is not UTF-8, an error tuple is returned.\n\n_Example:_\n\n```erlang\n1> uri_string:percent_decode(#{host => \"localhost-%C3%B6rebro\",path => [],\n1> scheme => \"http\"}).\n#{host => \"localhost-örebro\",path => [],scheme => \"http\"}\n2> uri_string:percent_decode(<<\"%C3%B6rebro\">>).\n<<\"örebro\"/utf8>>\n```\n\n> #### Warning {: .warning }\n>\n> Using `uri_string:percent_decode/1` directly on a URI is not safe. This\n> example shows, that after each consecutive application of the function the\n> resulting URI will be changed. None of these URIs refer to the same resource.\n>\n> ```erlang\n> 3> uri_string:percent_decode(<<\"http://local%252Fhost/path\">>).\n> <<\"http://local%2Fhost/path\">>\n> 4> uri_string:percent_decode(<<\"http://local%2Fhost/path\">>).\n> <<\"http://local/host/path\">>\n> ```","title":"uri_string.percent_decode/1","ref":"uri_string.html#percent_decode/1"},{"type":"function","doc":"Replaces characters out of unreserved set with their percent encoded\nequivalents.\n\nUnreserved characters defined in\n[RFC 3986](https://www.ietf.org/rfc/rfc3986.txt) are not quoted.\n\n_Example:_\n\n```erlang\n1> uri_string:quote(\"SomeId/04\").\n\"SomeId%2F04\"\n2> uri_string:quote(<<\"SomeId/04\">>).\n<<\"SomeId%2F04\">>\n```\n\n> #### Warning {: .warning }\n>\n> Function is not aware about any URI component context and should not be used\n> on whole URI. If applied more than once on the same data, might produce\n> unexpected results.","title":"uri_string.quote/1","ref":"uri_string.html#quote/1"},{"type":"function","doc":"Same as [`quote/1`](`quote/1`), but `Safe` allows user to provide a list of\ncharacters to be protected from encoding.\n\n_Example:_\n\n```erlang\n1> uri_string:quote(\"SomeId/04\", \"/\").\n\"SomeId/04\"\n2> uri_string:quote(<<\"SomeId/04\">>, \"/\").\n<<\"SomeId/04\">>\n```\n\n> #### Warning {: .warning }\n>\n> Function is not aware about any URI component context and should not be used\n> on whole URI. If applied more than once on the same data, might produce\n> unexpected results.","title":"uri_string.quote/2","ref":"uri_string.html#quote/2"},{"type":"function","doc":"Creates an [RFC 3986](https://www.ietf.org/rfc/rfc3986.txt) compliant\n`URIString` (percent-encoded), based on the components of `URIMap`. If the\n`URIMap` is invalid, an error tuple is returned.\n\nSee also the opposite operation `parse/1`.\n\n_Example:_\n\n```erlang\n1> URIMap = #{fragment => \"nose\", host => \"example.com\", path => \"/over/there\",\n1> port => 8042, query => \"name=ferret\", scheme => \"foo\", userinfo => \"user\"}.\n#{fragment => \"nose\",host => \"example.com\",\n path => \"/over/there\",port => 8042,query => \"name=ferret\",\n scheme => \"foo\",userinfo => \"user\"}\n\n2> uri_string:recompose(URIMap).\n\"foo://example.com:8042/over/there?name=ferret#nose\"\n```","title":"uri_string.recompose/1","ref":"uri_string.html#recompose/1"},{"type":"function","doc":"Convert a `RefURI` reference that might be relative to a given base URI into the\nparsed components of the reference's target, which can then be recomposed to\nform the target URI.\n\n_Example:_\n\n```erlang\n1> uri_string:resolve(\"/abs/ol/ute\", \"http://localhost/a/b/c?q\").\n\"http://localhost/abs/ol/ute\"\n2> uri_string:resolve(\"../relative\", \"http://localhost/a/b/c?q\").\n\"http://localhost/a/relative\"\n3> uri_string:resolve(\"http://localhost/full\", \"http://localhost/a/b/c?q\").\n\"http://localhost/full\"\n4> uri_string:resolve(#{path => \"path\", query => \"xyz\"}, \"http://localhost/a/b/c?q\").\n\"http://localhost/a/b/path?xyz\"\n```","title":"uri_string.resolve/2","ref":"uri_string.html#resolve/2"},{"type":"function","doc":"Same as [`resolve/2`](`resolve/2`) but with an additional `Options` parameter,\nthat controls whether the target URI shall be returned as an uri_map(). There is\none supported option: `return_map`.\n\n_Example:_\n\n```erlang\n1> uri_string:resolve(\"/abs/ol/ute\", \"http://localhost/a/b/c?q\", [return_map]).\n#{host => \"localhost\",path => \"/abs/ol/ute\",scheme => \"http\"}\n2> uri_string:resolve(#{path => \"/abs/ol/ute\"}, #{scheme => \"http\",\n2> host => \"localhost\", path => \"/a/b/c?q\"}, [return_map]).\n#{host => \"localhost\",path => \"/abs/ol/ute\",scheme => \"http\"}\n```","title":"uri_string.resolve/3","ref":"uri_string.html#resolve/3"},{"type":"function","doc":"Transcodes an [RFC 3986](https://www.ietf.org/rfc/rfc3986.txt) compliant\n`URIString`, where `Options` is a list of tagged tuples, specifying the inbound\n(`in_encoding`) and outbound (`out_encoding`) encodings.\n\n`in_encoding` and `out_encoding` specifies both binary encoding and percent-encoding\nfor the input and output data. Mixed encoding, where binary encoding is not the same as\npercent-encoding, is not supported. If an argument is invalid, an error tuple is\nreturned.\n\n_Example:_\n\n```erlang\n1> uri_string:transcode(<<\"foo%00%00%00%F6bar\"/utf32>>,\n1> [{in_encoding, utf32},{out_encoding, utf8}]).\n<<\"foo%C3%B6bar\"/utf8>>\n2> uri_string:transcode(\"foo%F6bar\", [{in_encoding, latin1},\n2> {out_encoding, utf8}]).\n\"foo%C3%B6bar\"\n```","title":"uri_string.transcode/2","ref":"uri_string.html#transcode/2"},{"type":"function","doc":"Percent decode characters.\n\n_Example:_\n\n```erlang\n1> uri_string:unquote(\"SomeId%2F04\").\n\"SomeId/04\"\n2> uri_string:unquote(<<\"SomeId%2F04\">>).\n<<\"SomeId/04\">>\n```\n\n> #### Warning {: .warning }\n>\n> Function is not aware about any URI component context and should not be used\n> on whole URI. If applied more than once on the same data, might produce\n> unexpected results.","title":"uri_string.unquote/1","ref":"uri_string.html#unquote/1"},{"type":"type","doc":"Error tuple indicating the type of error. Possible values of the second\ncomponent:\n\n- `invalid_character`\n- `invalid_encoding`\n- `invalid_input`\n- `invalid_map`\n- `invalid_percent_encoding`\n- `invalid_scheme`\n- `invalid_uri`\n- `invalid_utf8`\n- `missing_value`\n\nThe third component is a term providing additional information about the cause\nof the error.","title":"uri_string.error/0","ref":"uri_string.html#t:error/0"},{"type":"type","doc":"Map holding the main components of a URI.","title":"uri_string.uri_map/0","ref":"uri_string.html#t:uri_map/0"},{"type":"type","doc":"List of unicode codepoints, a UTF-8 encoded binary, or a mix of the two,\nrepresenting an [RFC 3986](https://www.ietf.org/rfc/rfc3986.txt) compliant URI\n(_percent-encoded form_). A URI is a sequence of characters from a very limited\nset: the letters of the basic Latin alphabet, digits, and a few special\ncharacters.","title":"uri_string.uri_string/0","ref":"uri_string.html#t:uri_string/0"},{"type":"extras","doc":"\n# STDLIB Application","title":"STDLIB Application","ref":"stdlib_app.html"},{"type":"extras","doc":"The STDLIB application is mandatory in the sense that the minimal system based\non Erlang/OTP consists of Kernel and STDLIB. The STDLIB application contains no\nservices.","title":"Description - STDLIB Application","ref":"stdlib_app.html#description"},{"type":"extras","doc":"The following configuration parameters are defined for the STDLIB application.\nFor more information about configuration parameters, see the\n[`app(4)`](`e:kernel:app.md`) module in Kernel.\n\n- **`shell_esc = icl | abort`{: #shell_esc }** - Can be used to change the\n behavior of the Erlang shell when _^G_ is pressed.\n\n- **`restricted_shell = module()`{: #restricted_shell }** - Can be used to run\n the Erlang shell in restricted mode.\n\n- **`shell_catch_exception = boolean()`{: #shell_catch_exception }** - Can be\n used to set the exception handling of the evaluator process of Erlang shell.\n\n- **`shell_docs_columns = pos_integer()`{: #shell_docs_columns }** -\n Configures how wide the documentation should be rendered in the shell.\n\n See also `t:shell_docs:config/0`.\n\n- **`shell_expand_location = above | below`{: #shell_expand_location }** - Sets\n where the tab expansion text should appear in the shell. The default is\n `below`. This will open a pager below the cursor that is scrollable one line\n at a time with `Up/Down` arrow keys or 5 lines at a time with `PgUp/PgDn`.\n\n- **`shell_history_length = integer() >= 0`{: #shell_history_length }** - Can be\n used to determine how many commands are saved by the Erlang shell. See\n `m:edlin` for more.\n\n- **`shell_keymap = #{}`{: #shell_keymap }** - Can be used to override the\n default keymap configuration for the shell.\n\n- **`format_shell_func = {Mod, Func} | string() | default`{: #format_shell_func\n }** - Can be used to set the formatting of the Erlang shell output. This has\n an effect on commands that have been submitted and how it is saved in history\n or if the formatting hotkey is pressed while editing an expression (Alt+F by\n default). You can specify a Mod:Func/1 that expects the whole expression as a\n string and returns a formatted expressions as a string. See\n `shell:format_shell_func/1` for how to set it from inside the shell.\n\n If instead a string is provided, it will be used as a shell command. Your\n command must include `${file}` somewhere in the string, for the shell to know\n where the file goes in the command.\n\n ```text\n -stdlib format_shell_func \"\\\"emacs -batch \\${file} -l ~/erlang-format/emacs-format-file -f emacs-format-function\\\"\"\n ```\n\n ```text\n -stdlib format_shell_func \"{shell, erl_pp_format_func}\"\n ```\n\n- **`shell_prompt_func = {Mod, Func} | default`{: #shell_prompt_func }** - where\n\n - `Mod = atom()`\n - `Func = atom()`\n\n Can be used to set a customized Erlang shell prompt function.\n\n- **`shell_multiline_prompt = {Mod, Func} | string() | default`{:\n #shell_multiline_prompt }** - where\n\n - `Mod = atom()`\n - `Func = atom()`\n\n Can be used to set a customized multiline shell prompt function. The multiline\n prompt function takes the main prompt as its only parameter.\n\n- **`shell_saved_results = integer() >= 0`{: #shell_saved_results }** - Can be\n used to determine how many results are saved by the Erlang shell.\n\n- **`shell_session_slogan = string() | fun() -> string())`{:\n #shell_session_slogan }** - The slogan printed when starting an Erlang shell.\n Example:\n\n ```erlang\n $ erl -stdlib shell_session_slogan '\"Test slogan\"'\n Erlang/OTP 26 [DEVELOPMENT] [erts-13.0.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]\n\n Test slogan\n 1>\n ```\n\n- **`shell_slogan = string() | fun(() -> string())`{: #shell_slogan }** - The\n slogan printed when starting the Erlang shell subsystem. Example:\n\n ```erlang\n $ erl -stdlib shell_slogan '\"Test slogan\"'\n Test slogan\n Eshell V13.0.2 (abort with ^G)\n 1>\n ```\n\n The default is the return value of\n [`erlang:system_info(system_version)`](`m:erlang#system_info_system_version`).\n\n- **`shell_strings = boolean()`{: #shell_strings }** - Can be used to determine\n how the Erlang shell outputs lists of integers.","title":"Configuration - STDLIB Application","ref":"stdlib_app.html#configuration"},{"type":"extras","doc":"[`app(4)`](`e:kernel:app.md`), `m:application`, `m:shell`","title":"See Also - STDLIB Application","ref":"stdlib_app.html#see-also"},{"type":"extras","doc":"\n# STDLIB Release Notes\n\nThis document describes the changes made to the STDLIB application.","title":"STDLIB Release Notes","ref":"notes.html"},{"type":"extras","doc":"","title":"STDLIB 6.1.2 - STDLIB Release Notes","ref":"notes.html#stdlib-6-1-2"},{"type":"extras","doc":"- With this change, uri_string:normalize assumes empty path (do not crash) when no path is provided in the URI map.\n\n Own Id: OTP-19266 Aux Id: ERIERL-1127, [PR-8890]\n\n- Fixed spec for `json:format/3`.\n\n Own Id: OTP-19286 Aux Id: [GH-8880], [PR-8914]\n\n[PR-8890]: https://github.com/erlang/otp/pull/8890\n[GH-8880]: https://github.com/erlang/otp/issues/8880\n[PR-8914]: https://github.com/erlang/otp/pull/8914","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 6.1.1 - STDLIB Release Notes","ref":"notes.html#stdlib-6-1-1"},{"type":"extras","doc":"- Remove whitespace stripping of returned binaries in `json:decode/3`.\n\n Own Id: OTP-19227 Aux Id: ERIERL-1130, [PR-8809]\n\n- 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.\n\n Own Id: OTP-19241 Aux Id: [PR-8836]\n\n- With this change, shutdown procedure handles a race condition between supervisor executing a shutdown and child process termination from other reason.\n\n Own Id: OTP-19256 Aux Id: [PR-8780]\n\n[PR-8809]: https://github.com/erlang/otp/pull/8809\n[PR-8836]: https://github.com/erlang/otp/pull/8836\n[PR-8780]: https://github.com/erlang/otp/pull/8780","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 6.1 - STDLIB Release Notes","ref":"notes.html#stdlib-6-1"},{"type":"extras","doc":"- The help printout for incorrect `t:io:format/0` strings now handles the `k` modifier correctly.\n\n Own Id: OTP-19146 Aux Id: [PR-8611], [GH-8568]\n\n- Fixed a bug that caused the shell completion to crash when keyword and tuple appeared on the same line.\n\n Own Id: OTP-19157 Aux Id: [PR-8638]\n\n- 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.\n\n Own Id: OTP-19164 Aux Id: [GH-8605], [PR-7419], OTP-18671\n\n- Fixed an emulator crash relating to compressed ETS tables.\n\n Own Id: OTP-19176 Aux Id: [PR-8683]\n\n- 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\n\n Own Id: OTP-19189\n\n- Multiple issues have been corrected in the markdown parser that creates documentation for the shell. \n \n 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.\n \n The markdown parser is also used in the creation of other documentation formats, so this was a bug that affected other generated documentation formats.\n\n Own Id: OTP-19200 Aux Id: [GH-8738], [PR-8739]\n\n- Fixed category for some codepoint ranges in `unicode_util`.\n\n Own Id: OTP-19210 Aux Id: [GH-8748]\n\n- Fixed `m:argparse` to print sub-commands help when available.\n\n Own Id: OTP-19222 Aux Id: [PR-8777]\n\n[PR-8611]: https://github.com/erlang/otp/pull/8611\n[GH-8568]: https://github.com/erlang/otp/issues/8568\n[PR-8638]: https://github.com/erlang/otp/pull/8638\n[GH-8605]: https://github.com/erlang/otp/issues/8605\n[PR-7419]: https://github.com/erlang/otp/pull/7419\n[PR-8683]: https://github.com/erlang/otp/pull/8683\n[GH-8738]: https://github.com/erlang/otp/issues/8738\n[PR-8739]: https://github.com/erlang/otp/pull/8739\n[GH-8748]: https://github.com/erlang/otp/issues/8748\n[PR-8777]: https://github.com/erlang/otp/pull/8777","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Class annotation to HTML from fenced blocks have been added.\n\n Own Id: OTP-19105 Aux Id: [PR-8499]\n\n- Added JSON formatting functions for indented output.\n\n Own Id: OTP-19112\n\n- Improved illegal pattern error for accidental map associations.\n\n Own Id: OTP-19128 Aux Id: [PR-8555]\n\n- Progress reports for a dynamically started supervisor will now be logged at debug level.\n\n *** POTENTIAL INCOMPATIBILITY ***\n\n Own Id: OTP-19202 Aux Id: [PR-8261], [GH-8715], [PR-8741]\n\n- The `m:zip` module has been updated with support for:\n \n * zip64 archives - Archives larger than 4GB or with more than 2^32 entries.\n * extended timestamps - Higher resolution and in UTC.\n * UID/GID - Save and extract the original UID/GID.\n * Fixes so that permission mode attributes are correctly read and set for files in archives.\n * `zip:list_dir/2` now also returns directories, not only files. (You can disable this behaviour by using the option `skip_directories`).\n \n Various bugs in the original implementation have also been fixed, such as:\n \n * Correctly encode and decode the DOS timestamps for entries within an archive (that is the non-extended timestamp).\n * Fix DOS timestamps to be set to localtime instead of UTC (use extended timestamps for UTC timestamps).\n * Use the unix file attributes read from disk when creating archives instead of setting everything to 644.\n\n Own Id: OTP-19214 Aux Id: [PR-8765]\n\n[PR-8499]: https://github.com/erlang/otp/pull/8499\n[PR-8555]: https://github.com/erlang/otp/pull/8555\n[PR-8261]: https://github.com/erlang/otp/pull/8261\n[GH-8715]: https://github.com/erlang/otp/issues/8715\n[PR-8741]: https://github.com/erlang/otp/pull/8741\n[PR-8765]: https://github.com/erlang/otp/pull/8765","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 6.0.1 - STDLIB Release Notes","ref":"notes.html#stdlib-6-0-1"},{"type":"extras","doc":"- Fix so that missing `-doc({file, File})` files only result in a warning and not an error.\n\n Own Id: OTP-19099 Aux Id: [PR-8542]\n\n- Fixed `m:json` bugs, `json:encode_key_value_list/2` did not generate arrays and `json:decode/3` did not invoke the user callback for `0`.\n\n Own Id: OTP-19106 Aux Id: [PR-8581], [GH-8580], [PR-8519]\n\n[PR-8542]: https://github.com/erlang/otp/pull/8542\n[PR-8581]: https://github.com/erlang/otp/pull/8581\n[GH-8580]: https://github.com/erlang/otp/issues/8580\n[PR-8519]: https://github.com/erlang/otp/pull/8519","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 6.0 - STDLIB Release Notes","ref":"notes.html#stdlib-6-0"},{"type":"extras","doc":"- The specs in module `m:binary` has been updated to reflect what is allowed by the documentation.\n\n Own Id: OTP-18684 Aux Id: [PR-7481]\n\n- Several functions in the `m: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.\n \n The following functions would accept an invalid pattern if the subject binary was empty or if the `{scope,{0,0}}` option was given:\n [`binary:match/2,3`](`binary:match/3`),\n [`binary:matches/2,3`](`binary:matches/2`),\n [`binary:replace/3,4`](`binary:replace/3`), and\n [`binary:split/2,3`](`binary:split/2`)\n \n The call `binary:copy(<<1:1>>, 0)` would return an empty binary instead of raising an exception. Similarly, calls to [`binary:part/2,3`](`binary:part/2`) attempting to extract 0 bytes at position 0 of a bitstring would return an empty binary instead of raising an exception.\n\n Own Id: OTP-18743 Aux Id: [PR-7607], [PR-7628]\n\n- 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.)\n \n 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.\n\n *** POTENTIAL INCOMPATIBILITY ***\n\n Own Id: OTP-18784 Aux Id: [GH-7706], [PR-7726]\n\n- `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.\n\n Own Id: OTP-18930 Aux Id: [PR-7993], [GH-4992]\n\n- The error handling the `simple_one_for_one` supervisor has been enhanced. A transient child returning `ignore` will no longer cause a crash.\n \n 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.\n\n *** POTENTIAL INCOMPATIBILITY ***\n\n Own Id: OTP-19029 Aux Id: [PR-8230]\n\n- 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.\n\n Own Id: OTP-19073 Aux Id: [PR-8375], [GH-8366], [GH-8365], [GH-8364]\n\n[PR-7481]: https://github.com/erlang/otp/pull/7481\n[PR-7607]: https://github.com/erlang/otp/pull/7607\n[PR-7628]: https://github.com/erlang/otp/pull/7628\n[GH-7706]: https://github.com/erlang/otp/issues/7706\n[PR-7726]: https://github.com/erlang/otp/pull/7726\n[PR-7993]: https://github.com/erlang/otp/pull/7993\n[GH-4992]: https://github.com/erlang/otp/issues/4992\n[PR-8230]: https://github.com/erlang/otp/pull/8230\n[PR-8375]: https://github.com/erlang/otp/pull/8375\n[GH-8366]: https://github.com/erlang/otp/issues/8366\n[GH-8365]: https://github.com/erlang/otp/issues/8365\n[GH-8364]: https://github.com/erlang/otp/issues/8364","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The functions [`is_equal/2`](`sets:is_equal/2`), [`map/2`](`sets:map/2`), and [`filtermap/2`](`sets:filtermap/2`) have been added to the modules `m:sets`, `m:ordsets`, and `m:gb_sets`.\n\n Own Id: OTP-18622 Aux Id: [PR-7183], [PR-7232]\n\n- The compiler now emits nicer error message for function head mismatches.\n For example, given:\n \n ```erlang\n a() -> ok;\n a(_) -> error.\n ```\n \n Erlang/OTP 26 and earlier would emit a diagnostic similar to:\n \n ```text\n t.erl:6:1: head mismatch\n % 6| a(_) -> error.\n % | ^\n ```\n \n while in Erlang/OTP 27 the diagnostic is similar to:\n \n ```text\n 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?\n % 6| a(_) -> error.\n % | ^\n ```\n\n Own Id: OTP-18648 Aux Id: [PR-7383]\n\n- [`zip:create/2,3`](`zip:create/2`) will now tolerate POSIX timestamps in the provided `file_info` records.\n\n Own Id: OTP-18668\n\n- The callback function `c:gen_statem:handle_event/4` has been cached in the `gen_statem` engine to optimize callback call speed.\n\n Own Id: OTP-18671 Aux Id: [PR-7419]\n\n- The type `beam_lib:beam/0` is now exported.\n\n Own Id: OTP-18716 Aux Id: [PR-7534]\n\n- The documentation for the `m:binary` module has been improved.\n\n Own Id: OTP-18741 Aux Id: [PR-7585]\n\n- [`binary:replace/3,4`](`binary:replace/3`) now supports using a fun for supplying the replacement binary.\n\n Own Id: OTP-18742 Aux Id: [PR-7590]\n\n- Triple-Quoted Strings has been implemented as per [EEP 64](https://www.erlang.org/eeps/eep-0064). See [String](`e:system:data_types.md#string`) in the Reference Manual.\n \n Example:\n \n ```erlang\n 1> \"\"\"\n a\n b\n c\n \"\"\".\n \"a\\nb\\nc\"\n ```\n \n Adjacent string literals without intervening white space is now a syntax error, to avoid possible confusion with triple-quoted strings. For example:\n \n ```erlang\n 1> \"abc\"\"xyz\".\n \"xyz\".\n * 1:6: adjacent string literals without intervening white space\n ```\n\n *** POTENTIAL INCOMPATIBILITY ***\n\n Own Id: OTP-18750 Aux Id: OTP-18746, [PR-7313], [PR-7451]\n\n- 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`, `m:observer`, and it will be included in crash reports produced by processes using `m:gen_server`, `m:gen_statem`, `m:gen_event`, and `m:gen_fsm`.\n \n The label for a process can be retrieved by calling `proc_lib:get_label/1`.\n \n Note that those functions work on any process, not only processes that use `m:proc_lib`.\n \n Example:\n \n ```text\n 1> self().\n <0.90.0>\n 2> proc_lib:set_label(my_label).\n ok\n 3> i().\n .\n .\n .\n <0.90.0> erlang:apply/2 2586 75011 0\n my_label c:pinfo/2 51\n 4> proc_lib:get_label(self()).\n my_label\n ```\n\n Own Id: OTP-18789 Aux Id: [PR-7720], [PR-8003]\n\n- `-callback` attributes has been added to modules `m:sys` and `m:erl_error`.\n\n Own Id: OTP-18793 Aux Id: [PR-7703]\n\n- Several new functions that accept funs have been added to module `m:timer`.\n \n Functions [`apply_after/2`](`timer:apply_after/2`), [`apply_interval/2`](`timer:apply_interval/2`), and [`apply_repeatedly/2`](`apply_repeatedly/2`) accept a nullary fun as the second argument, while functions [`apply_after/3`](`timer:apply_after/3`), [`apply_interval/3`](`timer:apply_interval/3`), and [`apply_repeatedly/3`](`apply_repeatedly/3`) accept an n-ary fun as the second and a list of n arguments for the fun as the third argument.\n\n Own Id: OTP-18808 Aux Id: [PR-7649]\n\n- Sigils on string literals have been implemented as per [EEP 66](https://www.erlang.org/eeps/eep-0066), 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](`e:system:data_types.md#sigil`).\n \n Examples:\n \n ```erlang\n 1> ~\"Björn\".\n <<\"Björn\"/utf8>>\n 2> ~b\"Björn\".\n <<\"Björn\"/utf8>>\n 3> ~S\"\\s*(\\w+)\".\n \"\\\\s*(\\\\w+)\"\n 4> ~B\"\\s*(\\w+)\".\n <<\"\\\\s*(\\\\w+)\">>\n ```\n\n Own Id: OTP-18825 Aux Id: OTP-18750, [PR-7684]\n\n- Functions `shell:default_multiline_prompt/1`, `shell:inverted_space_prompt/1`, and \n `shell:prompt_width/1` have been exported to help with custom prompt implementations.\n\n Own Id: OTP-18834 Aux Id: [PR-7675], [PR-7816]\n\n- The shell now pages long output from the documentation help command ([`h(Module)`](`c:h/1`)), auto completions and the search command.\n\n Own Id: OTP-18846 Aux Id: [PR-7845]\n\n- The `M-h` hotkey (Alt/Option-h) now outputs help for the module or function directly before the cursor.\n\n Own Id: OTP-18847 Aux Id: [PR-7846]\n\n- 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`.\n\n Own Id: OTP-18848 Aux Id: [PR-7847]\n\n- Added shell functions for viewing, forgetting and saving locally defined functions, types and records.\n\n Own Id: OTP-18852 Aux Id: [PR-7844]\n\n- Added `string:jaro_similarity/2`, which can be used to calculate the similarity between two strings.\n\n Own Id: OTP-18865 Aux Id: [PR-7879]\n\n- 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.\n\n Own Id: OTP-18870 Aux Id: [PR-7857]\n\n- Added functions to retrieve the next higher or lower key/element from `m:gb_trees` and `m:gb_sets`, as well as returning iterators that start at given keys/elements.\n\n Own Id: OTP-18874 Aux Id: [PR-7745]\n\n- When the shell built-in function [`c/1,2`][c12] is used to re-compile a module, the current working directory of the original compilation is now added to the include path.\n \n [c12]: `\\c:c/1`\n\n Own Id: OTP-18908 Aux Id: [PR-7957]\n\n- The `timer` module now uses a private table for its internal state, slightly improving its performance.\n\n Own Id: OTP-18914 Aux Id: [PR-7973]\n\n- [EEP-59 - Documentation Attributes](https://www.erlang.org/eeps/eep-0059) has been implemented.\n \n Documentation attributes can be used to document functions, types, callbacks, and modules.\n 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.\n \n * 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.\n \n * The documentation from `moduledoc` and `doc` gets added by default to the binary beam file, following the format of [EEP-48](https://www.erlang.org/eeps/eep-0048).\n \n * Using the compiler flag `warn_missing_doc` will raise a warning when\n `-doc` attributes are missing in exported functions, types, and callbacks.\n \n * Using the compiler flag `warn_missing_spec_documented` will raise a warning when\n spec attributes are missing in documented functions, types, and callbacks.\n \n * `moduledoc`s and `doc`s 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.\n \n * 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.\n\n Own Id: OTP-18916 Aux Id: [PR-7936]\n\n- New `m: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.\n\n Own Id: OTP-18923 Aux Id: [PR-6791]\n\n- The `maybe` expression is now enabled by default.\n \n 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:\n \n ```erlang\n -feature(maybe_expr, disable).\n ```\n \n Another way to disable the `maybe_expr` feature is by passing the `-disable-feature` option to `erlc`:\n \n ```text\n erlc -disable-feature maybe_expr some_file.erl\n ```\n\n Own Id: OTP-18944 Aux Id: [PR-8067]\n\n- The compiler will now raise a warning when updating record/map literals. As an example, consider this module:\n \n ```erlang\n -module(t).\n -export([f/0]).\n -record(r, {a,b,c}).\n \n f() ->\n #r{a=1}#r{b=2}.\n ```\n \n The compiler raises the following warning:\n \n ```text\n 1> c(t).\n t.erl:6:12: Warning: expression updates a literal\n % 6| #r{a=1}#r{b=2}.\n % | ^\n ```\n\n Own Id: OTP-18951 Aux Id: [PR-8069]\n\n- The documentation has been migrated to use Markdown and ExDoc.\n\n Own Id: OTP-18955 Aux Id: [PR-8026]\n\n- Optimized `ets:foldl` and `ets:foldr` to use new `ets:next_lookup`. Also made them immune against table renaming.\n\n Own Id: OTP-18993 Aux Id: [PR-8048]\n\n- Windows now supports all functions in `m:math`.\n\n Own Id: OTP-19001 Aux Id: [PR-8164]\n\n- `m:erl_lint` (and by extension the [`compiler`](`m:compile`)) will now warn for code using deprecated callbacks.\n \n The only callback currenly deprecated is `format_status/2` in [`gen_server`](`c:gen_server:format_status/2`), [`gen_event`](`c:gen_event:format_status/2`) and [`gen_statem`](`c:gen_server:format_status/2`).\n \n You can use `nowarn_deprecated_callback` to silence the warning.\n\n Own Id: OTP-19010 Aux Id: [PR-8205]\n\n- There is a new module [`json`](`m:json`) for encoding and decoding [JSON](https://en.wikipedia.org/wiki/JSON).\n \n Both encoding and decoding can be customized. Decoding can be done in a SAX-like fashion and handle multiple documents and streams of data.\n\n Own Id: OTP-19020 Aux Id: [PR-8111]\n\n[PR-7183]: https://github.com/erlang/otp/pull/7183\n[PR-7232]: https://github.com/erlang/otp/pull/7232\n[PR-7383]: https://github.com/erlang/otp/pull/7383\n[PR-7419]: https://github.com/erlang/otp/pull/7419\n[PR-7534]: https://github.com/erlang/otp/pull/7534\n[PR-7585]: https://github.com/erlang/otp/pull/7585\n[PR-7590]: https://github.com/erlang/otp/pull/7590\n[PR-7313]: https://github.com/erlang/otp/pull/7313\n[PR-7451]: https://github.com/erlang/otp/pull/7451\n[PR-7720]: https://github.com/erlang/otp/pull/7720\n[PR-8003]: https://github.com/erlang/otp/pull/8003\n[PR-7703]: https://github.com/erlang/otp/pull/7703\n[PR-7649]: https://github.com/erlang/otp/pull/7649\n[PR-7684]: https://github.com/erlang/otp/pull/7684\n[PR-7675]: https://github.com/erlang/otp/pull/7675\n[PR-7816]: https://github.com/erlang/otp/pull/7816\n[PR-7845]: https://github.com/erlang/otp/pull/7845\n[PR-7846]: https://github.com/erlang/otp/pull/7846\n[PR-7847]: https://github.com/erlang/otp/pull/7847\n[PR-7844]: https://github.com/erlang/otp/pull/7844\n[PR-7879]: https://github.com/erlang/otp/pull/7879\n[PR-7857]: https://github.com/erlang/otp/pull/7857\n[PR-7745]: https://github.com/erlang/otp/pull/7745\n[PR-7957]: https://github.com/erlang/otp/pull/7957\n[PR-7973]: https://github.com/erlang/otp/pull/7973\n[PR-7936]: https://github.com/erlang/otp/pull/7936\n[PR-6791]: https://github.com/erlang/otp/pull/6791\n[PR-8067]: https://github.com/erlang/otp/pull/8067\n[PR-8069]: https://github.com/erlang/otp/pull/8069\n[PR-8026]: https://github.com/erlang/otp/pull/8026\n[PR-8048]: https://github.com/erlang/otp/pull/8048\n[PR-8164]: https://github.com/erlang/otp/pull/8164\n[PR-8205]: https://github.com/erlang/otp/pull/8205\n[PR-8111]: https://github.com/erlang/otp/pull/8111","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 5.2.3.2 - STDLIB Release Notes","ref":"notes.html#stdlib-5-2-3-2"},{"type":"extras","doc":"* With this change, shutdown procedure handles a race condition between supervisor executing a shutdown and child process termination from other reason.\n\n Own Id: OTP-19256 Aux Id: PR-8780\n* With this change, uri_string:normalize assumes empty path (do not crash) when no path is provided in the URI map.\n\n Own Id: OTP-19266 Aux Id: ERIERL-1127, PR-8890","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 5.2.3.1 - STDLIB Release Notes","ref":"notes.html#stdlib-5-2-3-1"},{"type":"extras","doc":"* Fixed a bug that caused the shell completion to crash when keyword and tuple appeared on the same line.\n\n Own Id: OTP-19157 Aux Id: PR-8638","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 5.2.3 - STDLIB Release Notes","ref":"notes.html#stdlib-5-2-3"},{"type":"extras","doc":"* Fix shell expansion of `-type a() :: $a.` in the erlang shell.\n\n Own Id: OTP-19062\n* Fix the shell Job Control Mode to not crash when typing `TAB` or `CTRL+R`.\n\n Own Id: OTP-19072 Aux Id: PR-8391","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 5.2.2 - STDLIB Release Notes","ref":"notes.html#stdlib-5-2-2"},{"type":"extras","doc":"* Attempting to use the `maybe` construct in a macro argument could crash the compiler.\n\n Own Id: OTP-19031 Aux Id: GH-8268","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 5.2.1 - STDLIB Release Notes","ref":"notes.html#stdlib-5-2-1"},{"type":"extras","doc":"* The help texts shown by `argparse` will now display sub-command arguments in the correct order.\n\n Own Id: OTP-18900 Aux Id: PR-7945, GH-7934\n* Clarified the argparse documentation regarding the user-defined help template.\n\n Own Id: OTP-18937\n* Fix shell expansion to not crash when expanding invalid using invalid atoms.\n\n Own Id: OTP-18953 Aux Id: GH-8016 PR-8075","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 5.2 - STDLIB Release Notes","ref":"notes.html#stdlib-5-2"},{"type":"extras","doc":"- Make `shell_docs` correctly trim the newline at the end of code blocks.\n\n Own Id: OTP-18777 Aux Id: PR-7663\n\n- Replaced unintentional Erlang Public License 1.1 headers in some files with\n the intended Apache License 2.0 header.\n\n Own Id: OTP-18815 Aux Id: PR-7780\n\n- Fixed a bug where autocompletion could crash the shell when trying to expand a\n nested tuple.\n\n Own Id: OTP-18822 Aux Id: PR-7796\n\n- Removed auto closing feature, in autocompletion, for function arguments,\n tuples, records and maps, since this could interfere with autocompletion of\n atoms.\n\n Own Id: OTP-18823\n\n- Fixed a bug where autocompletion string formatting would remove suggestions\n that had the same name but different case.\n\n Own Id: OTP-18824\n\n- Fix so that ctrl+h, ctrl+backspace in the shell only removes one character\n instead of a whole word.\n\n Own Id: OTP-18826 Aux Id: PR-7797\n\n- Fix so that its possible to override the default keyboard shortcuts for the\n shell.\n\n Own Id: OTP-18827 Aux Id: PR-7797\n\n- Allow shell local func v(), in a restricted shell\n\n Own Id: OTP-18828 Aux Id: PR-7799\n\n- Report syntax error when writing an invalid attribute like '1> -hej.'\n\n Own Id: OTP-18829 Aux Id: PR-7799\n\n- When attempting to match part of a record in the key of a map generator, the\n entire record would be matched.\n\n Own Id: OTP-18866 Aux Id: GH-7875, PR-7878","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The warning for accidental use of a future triple-quoted string delimiter has\n been upgraded to instead warn for adjacent strings without intervening white\n space, which effectively is the same at a string start, but also covers the\n same situation at a string end.\n\n Own Id: OTP-18821 Aux Id: OTP-18746\n\n- The removal of the deprecated `slave` module, originally planned for OTP 27,\n has been postponed to OTP 29.\n\n Own Id: OTP-18840 Aux Id: PR-7629\n\n- Guards have been added to `gen_*:start*` API functions to catch bad arguments\n earlier. Before this change, in some cases, a bad argument could tag along and\n cause the server to fail later, right after start.\n\n Own Id: OTP-18857 Aux Id: GH-7685","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 5.1.1 - STDLIB Release Notes","ref":"notes.html#stdlib-5-1-1"},{"type":"extras","doc":"- Garbage collect the shell process when reducing the amount of saved history\n and results.\n\n Own Id: OTP-18773 Aux Id: PR-7691","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 5.1 - STDLIB Release Notes","ref":"notes.html#stdlib-5-1"},{"type":"extras","doc":"- The compiler could run forever when compiling a call to\n [`is_record/3`](`is_record/3`) with a huge positive tuple size. The call\n [`is_record(A, a, 0)`](`is_record/3`) would crash the compiler when used in a\n function body. When used in a guard the compiler would emit incorrect code\n that would accept `{a>` as a record.\n\n Own Id: OTP-18605 Aux Id: GH-7298, GH-7317\n\n- Fix bug in `ets:tab2file` that could make it fail if another Erlang process\n created the same file at the same time.\n\n Own Id: OTP-18614 Aux Id: GH-7162, PR-7237\n\n- An `{else_clause,Value}` exception will now be reported nicely in the shell.\n\n Own Id: OTP-18616 Aux Id: GH-7258\n\n- Correct return value for error case, so that it matches the documented and\n intended return value \\{error, \\{already_started, pid()\\} when local\n registered names are used.\n\n Own Id: OTP-18627 Aux Id: PR-7072\n\n- `sys:get_state/1,2` and `sys:replace_state/2,3` has been corrected to handle a\n state named `error` as a state name, not as a failed system callback.\n\n For the standard server behaviours this was an issue only for `gen_statem`\n (and `gen_fsm`) when the state name was `error`, and for `gen_server` if the\n complete state was `{error,_}`.\n\n Own Id: OTP-18633\n\n- Multiple problems were fixed in `filelib:safe_relative_path/2`. If its second\n argument was a path that contained symbolic links, an incorrect result patch\n could be returned. Also, paths were sometimes falsely considered unsafe.\n\n Own Id: OTP-18655 Aux Id: GH-6460, PR-7208\n\n- Fix deadlock when `erl.exe` is used as part of a pipe on Windows and trying to\n set the encoding of the `standard_io` device.\n\n Own Id: OTP-18675 Aux Id: PR-7473 GH-7459\n\n- Expanded the documentation about how to use the `standard_io`,\n `standard_error` and `user` I/O devices.\n\n Added the types [`io:standard_io/0`](`t:io:standard_io/0`),\n `io:standard:error/0` and [`io:user/0`](`t:io:user/0`).\n\n Own Id: OTP-18676 Aux Id: PR-7473 GH-7459\n\n- Fix `h/2,3` to properly render multi-clause documentation.\n\n Own Id: OTP-18683 Aux Id: PR-7502\n\n- Timers created by `timer:apply_after/4`, `apply_interval/4`, and\n `apply_repeatedly/4` would silently fail to do the apply if it was not\n possible to spawn a process when the timer expired. This has now been\n corrected, and if the spawn fails, the system will be taken down producing a\n crash dump.\n\n Own Id: OTP-18759 Aux Id: GH-7606\n\n- When an Erlang source file lacked a module definition, there would be a\n spurious \"module name must not be empty\" diagnostic for each spec in the file.\n\n Own Id: OTP-18763 Aux Id: GH-7655","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The argument descriptions for option types in `argparse` have been made less\n ambiguous.\n\n Own Id: OTP-18679 Aux Id: ERIERL-965\n\n- Clarified the documentation of normal shutdown reason on `gen_server:call/2,3`\n\n Own Id: OTP-18690 Aux Id: PR-7511, GH-7510\n\n- Pattern matching and equivalence (`=:=`, `=/=`) comparisons on `0.0` will now\n raise a warning, as it will no longer be considered equivalent to `-0.0` in\n OTP 27.\n\n If a match on `0.0` specifically is desired (distinct from `-0.0`), the\n warning can be suppressed by writing `+0.0` instead.\n\n The arithmetic comparison operators are unaffected, including arithmetic\n equality (`==`).\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18696\n\n- The semantics of the `gen_{server,statem,event}` behaviour's synchronous start\n behaviour introduced in OTP-26.0 with OTP-18471, has been clarified in the\n documentation.\n\n Own Id: OTP-18705 Aux Id: GH-7524, OTP-18471, GH-6339, PR-6843\n\n- Added functionality to set a custom multiline prompt.\n\n Own Id: OTP-18736 Aux Id: PR-7564\n\n- A warning for (accidental use of) Triple-Quoted Strings has been implemented\n as per\n [EEP 64](https://github.com/erlang/eep/blob/master/eeps/eep-0064.md#backwards-incompatibility).\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18746 Aux Id: PR-7313, PR-7456\n\n- The keyboard shortcuts for the shell are now configurable.\n\n Own Id: OTP-18754 Aux Id: PR-7604 PR-7647","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 5.0.2 - STDLIB Release Notes","ref":"notes.html#stdlib-5-0-2"},{"type":"extras","doc":"- Fix bug where when you entered Alt+Enter in the terminal, the cursor would\n move to the last line, instead of moving to the next line.\n\n Own Id: OTP-18580 Aux Id: PR-7242\n\n- Fix eof handling when reading from stdin when erlang is started using\n `-noshell`.\n\n Own Id: OTP-18640 Aux Id: PR-7384 GH-7368 GH-7286 GH-6881\n\n- Fixed problem where output would disappear if it was received after a prompt\n was written in the shell.\n\n Own Id: OTP-18652 Aux Id: PR-7242\n\n- The following functions are now much faster when given a long list or binary:\n\n - erlang:list_to_integer/1\n - erlang:binary_to_integer/1\n - erlang:binary_to_integer/2\n - erlang:list_to_integer/2\n - string:to_integer/1\n\n Own Id: OTP-18659 Aux Id: PR-7426","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 5.0.1 - STDLIB Release Notes","ref":"notes.html#stdlib-5-0-1"},{"type":"extras","doc":"- The POSIX error `exdev` was sometimes incorrectly described as \"cross domain\n link\" in some error messages.\n\n Own Id: OTP-18578 Aux Id: GH-7213","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 5.0 - STDLIB Release Notes","ref":"notes.html#stdlib-5-0"},{"type":"extras","doc":"- All process calls in `dets` have been updated to use the receive queue\n optimizations.\n\n Own Id: OTP-18275 Aux Id: PR-6045\n\n- `proc_lib:start*/*` has become synchronous when the started process fails.\n This requires that a failing process use a new function\n `proc_lib:init_fail/2,3`, or exits, to indicate failure. All OTP behaviours\n have been fixed to do this.\n\n All these start functions now consume the `'EXIT'` message from a process link\n for all error returns. Previously it was only the `start_link/*` functions\n that did this, and only when the started function exited, not when it used\n `init_ack/1,2` or `init_fail/2,3` to create the return value.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18471 Aux Id: GH-6339, PR-6843\n\n- Fixed a bug where `file:read(standard_io, ...)` unexpectedly returned `eof` in\n binary mode.\n\n Own Id: OTP-18486 Aux Id: PR-6881\n\n- In the shell, `v(N)` would fail to retrieve the command if the command's\n return value was `undefined`.\n\n Own Id: OTP-18548 Aux Id: PR-6967","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The Erlang shell has been improved to support the following features:\n\n - Auto-complete variables, record names, record field names, map keys,\n function parameter types and filenames.\n - Open external editor in the shell (with C-o) to edit the current expression\n in an editor.\n - Support defining records (with types), functions and function typespecs, and\n custom types in the shell.\n - Do not save pager commands, and input to io:getline in history.\n\n Own Id: OTP-14835 Aux Id: PR-5924\n\n- Gen_server now caches external functions for use in handle_call, handle_cast\n and handle_info.\n\n Own Id: OTP-15597 Aux Id: PR-5831\n\n- The TTY/terminal subsystem has been rewritten by moving more code to Erlang\n from the old linked-in driver and implementing all the I/O primitives needed\n in a NIF instead.\n\n On Unix platforms the user should not notice a lot of difference, besides\n better handling of unicode characters and fixing of some long standing bugs.\n\n Windows users will notice that erl.exe has the same functionality as a normal\n Unix shell and that werl.exe has been removed and replaced with a symlink to\n erl.exe. This makes the Windows Erlang terminal experience identical to that\n of Unix.\n\n The re-write brings with it a number of bug fixes and feature additions:\n\n - The TTY is now reset when Erlang exits, fixing zsh to not break when\n terminating an Erlang session.\n - `standard_error` now uses the same unicode mode as `standard_io`.\n - Hitting backspace when searching the shell history with an empty search\n string no longer breaks the shell.\n - Tab expansion now works on remote nodes started using the JCL interface.\n - It is now possible to configure the shell slogan and the session slogans\n (that is the texts that appear when you start an Erlang shell). See the\n kernel documentation for more details.\n - Added shell:start_interactive for starting the interactive shell from a\n non-interactive Erlang session (for example an escript).\n - On Windows, when starting in detached mode the standard handler are now set\n to `nul` devices instead of being unset.\n - Standard I/O now always defaults to `unicode` mode if supported. Previously\n the default was `latin1` if the runtime system had been started with\n `-oldshell` or `-noshell` (for example in an `escript`). To send raw bytes\n over standard out, one now explicitly has to specify\n `io:setopts(standard_io, [{encoding, latin1}]).`\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17932 Aux Id: PR-6144 GH-3150 GH-3390 GH-4343 GH-4225\n\n- Added the `zip:zip_get_crc32/2` function to retrieve the CRC32 checksum from\n an opened ZIP archive.\n\n Own Id: OTP-18159 Aux Id: PR-6904\n\n- Added the options `post_process_args` and `detached` to the `peer:start`\n function.\n\n Own Id: OTP-18176 Aux Id: PR-6118\n\n- The `re:replace/3,4` functions now accept a fun as the replacement argument.\n\n Own Id: OTP-18221 Aux Id: PR-6197\n\n- The performance of the `base64` module has been significantly improved. For\n example, on an x86_64 system with the JIT both encode and decode are more than\n three times faster than in Erlang/OTP 25.\n\n Own Id: OTP-18228 Aux Id: GH-5639\n\n- Improved implementation of `timer:apply_interval/4` reducing load on the timer\n server, and introduction of the new function `timer:apply_repeatedly/4`.\n `timer:apply_repeatedly/4` is similar to `timer:apply_interval/4`, but\n `timer:apply_repeatedly/4` prevents parallel execution of triggered `apply`\n operations which `timer:apply_interval/4` does not.\n\n Own Id: OTP-18236 Aux Id: PR-6256\n\n- The `base64` module now supports encoding and decoding with an alternate URL\n safe alphabet, and an option for accepting or adding missing `=` padding\n characters.\n\n Own Id: OTP-18247 Aux Id: PR-6280, PR-6711\n\n- Add `shell:whereis/0` which can be used to locate the current shell process.\n\n Own Id: OTP-18272 Aux Id: PR-6279\n\n- The Erlang shell's auto-completion when typing `tab` has been changed to\n happen after the editing current line instead of before it.\n\n This behaviour can be configured using a the `shell_expand_location` STDLIB\n configuration parameter.\n\n Own Id: OTP-18278 Aux Id: PR-6260\n\n- New function `ets:lookup_element/4` with a `Default` argument returned if the\n key did not exist in the table. The old `ets:lookup_element/3` raises a\n `badarg` exception which can be both inconvenient and slower.\n\n Own Id: OTP-18279 Aux Id: PR-6234\n\n- Typing `Ctrl+L` in a shell now clears the screen and redraws the current line\n instead of only redrawing the current line. To only redraw the current line,\n you must now type `Alt+L`. This brings the behaviour of `Ctrl+L` closer to how\n bash and other shells work.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18285 Aux Id: PR-6262\n\n- `peer` nodes using `standard_io` connections now include standard error from\n the node in the io stream from the started node.\n\n Own Id: OTP-18287 Aux Id: PR-5955\n\n- A limitation in the binary syntax has been removed. It is now possible to\n match binary patterns in parallel. Example: `< > = < > = Bin`\n\n Own Id: OTP-18297 Aux Id: GH-6348\n\n- Improve type specification of `unicode:characters_to_list()`.\n\n Own Id: OTP-18301 Aux Id: PR-6350\n\n- In the `lists` module, the `zip` family of functions now takes options to\n allow handling lists of different lengths.\n\n Own Id: OTP-18318 Aux Id: PR-6347\n\n- It is documented that `$\\^X` is the ASCII code for Control X, where X is an\n uppercase or lowercase letter. However, this notation would work for any\n character X, even then it didn't make sense.\n\n In Erlang/OTP 26, it is now documented that the following characters are also\n allowed to follow the `\\^` characters: `@`, `[`, `\\`, `]`, `^`, `_`, and `?`.\n Attempt to use other characters will be rejected with a compiler error.\n\n The value for `$\\^?` is now 127 (instead of 31 as in earlier releases).\n\n Own Id: OTP-18337 Aux Id: GH-6477, PR-6503\n\n- The `binary:encode_hex/2` function has been added to allow the encoded\n hexadecimal digits to be in either lower or upper case.\n\n Own Id: OTP-18354 Aux Id: PR-6297\n\n- Variants of `timer:tc()` with user specified time unit have been introduced.\n\n Own Id: OTP-18355 Aux Id: PR-6507\n\n- New function `math:tau/0`. Returns `2*math:pi()`.\n\n Own Id: OTP-18361 Aux Id: PR-6536\n\n- The BIFs [`min/2`](`min/2`) and [`max/2`](`max/2`) are now allowed to be used\n in guards and match specs.\n\n Own Id: OTP-18367 Aux Id: GH-6544\n\n- Optimized `gen_server:multi_call()`.\n\n Own Id: OTP-18385 Aux Id: PR-6698\n\n- Map comprehensions as suggested in EEP 58 has now been implemented.\n\n Own Id: OTP-18413 Aux Id: EEP-58, PR-6727\n\n- Some map operations have been optimized by changing the internal sort order of\n atom keys. This changes the (undocumented) order of how atom keys in small\n maps are printed and returned by `maps:to_list/1` and `maps:next/1`. The new\n order is unpredictable and may change between different invocations of the\n Erlang VM.\n\n For applications where order is important, there is a new function\n `maps:iterator/2` for creating iterators that return the map elements in a\n deterministic order. There are also new modifiers `k` and `K` for the format\n string for [`io:format()`](`t:io:format/0`) to support printing map elements\n ordered.\n\n Own Id: OTP-18414 Aux Id: PR-6151\n\n- Make gen_server fail \"silently\" with a new return value for init/1.\n\n Own Id: OTP-18423 Aux Id: https://github.com/erlang/backlog/issues/142\n\n- Improved the selective receive optimization, which can now be enabled for\n references returned from other functions.\n\n This greatly improves the performance of `gen_server:send_request/3`,\n `gen_server:wait_response/2`, and similar functions.\n\n Own Id: OTP-18431 Aux Id: PR-6739\n\n- It is no longer necessary to enable a feature in the runtime system in order\n to load modules that are using it. It is sufficient to enable the feature in\n the compiler when compiling it.\n\n That means that to use feature `maybe_expr` in Erlang/OTP 26, it is sufficient\n to enable it during compilation.\n\n In Erlang/OTP 27, feature `maybe_expr` will be enabled by default, but it will\n be possible to disable it.\n\n Own Id: OTP-18445\n\n- Static supervisors are very idle processes after they have started so they\n will now be hibernated after start to improve resource management.\n\n Own Id: OTP-18474 Aux Id: PR-6895\n\n- Deprecates `dbg:stop_clear/0` because it is simply a function alias to\n `dbg:stop/0`\n\n Own Id: OTP-18478 Aux Id: GH-6903\n\n- Support has been added in `ms_transform` for the actions `caller_line/0`,\n `current_stacktrace/0`, and `current_stacktrace/1`.\n\n Own Id: OTP-18494 Aux Id: PR-6924\n\n- The family of enumeration functions in module `lists` has been extended with\n `enumerate/3` that allows a step value to be supplied.\n\n Own Id: OTP-18495 Aux Id: PR-6943\n\n- Update Unicode to version 15.0.0.\n\n Own Id: OTP-18500\n\n- The regular expression library powering the `re` module is likely to be\n changed in Erlang/OTP 27. See\n [Upcoming Potential Incompatibilities](`e:general_info:upcoming_incompatibilities.md#new_re_engine`).\n\n Own Id: OTP-18511 Aux Id: PR-7017\n\n- Improved the performance of `sets:subtract/2` when subtracting a small number\n of elements.\n\n Own Id: OTP-18515 Aux Id: GH-6990\n\n- The linter will no longer raise warnings for underspecified opaque types.\n\n Own Id: OTP-18518 Aux Id: GH-7015\n\n- Added the new built-in type `t:dynamic/0` introduced in EEP-61, improving\n support for gradual type checkers.\n\n Own Id: OTP-18522\n\n- The by `gen_statem` previously used call proxy process that was used for\n preventing late replies from reaching the client at timeout or connection loss\n has been removed. It is no longer needed since _process aliases_ take care of\n this, are used, and supported by all Erlang nodes that an OTP 26 Erlang node\n can communicate with.\n\n Own Id: OTP-18537 Aux Id: PR-7081\n\n- Added the `argparse` module for simplified argument handling in escripts and\n similar.\n\n Own Id: OTP-18558 Aux Id: PR-6852\n\n- Added support for multiple line expressions and navigation in the shell. Added\n new keybindings:\n\n - navigate up (ctrl+up)/(alt+up)\n - navigate down (ctrl+down)/(alt+down)\n - insert newline in middle of line (alt+enter)\n - navigate top (alt+<)/(alt+shift+up)\n - navigate bottom (alt+>)/(alt+shift+down)\n - clear current expression (alt+c)\n - cancel search (alt+c)\n - opening editor on mac (option+o)/(alt+o)\n\n Modifies the prompt for new lines to make it clearer that the prompt has\n entered multi-line mode. Supports terminal with small window size, recommend\n not go lower than 7 rows and 40 columns. Modifies the search prompt to support\n multi-line statements. Redraw the prompt after continuing from JCL menu.\n\n Own Id: OTP-18575 Aux Id: PR-7169","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 4.3.1.5 - STDLIB Release Notes","ref":"notes.html#stdlib-4-3-1-5"},{"type":"extras","doc":"* With this change, shutdown procedure handles a race condition between supervisor executing a shutdown and child process termination from other reason.\n\n Own Id: OTP-19256 Aux Id: PR-8780\n* With this change, uri_string:normalize assumes empty path (do not crash) when no path is provided in the URI map.\n\n Own Id: OTP-19266 Aux Id: ERIERL-1127, PR-8890","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 4.3.1.4 - STDLIB Release Notes","ref":"notes.html#stdlib-4-3-1-4"},{"type":"extras","doc":"* Attempting to use the `maybe` construct in a macro argument could crash the compiler.\n\n Own Id: OTP-19031 Aux Id: GH-8268","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 4.3.1.3 - STDLIB Release Notes","ref":"notes.html#stdlib-4-3-1-3"},{"type":"extras","doc":"- Garbage collect the shell process when reducing the amount of saved history\n and results.\n\n Own Id: OTP-18773 Aux Id: PR-7691","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 4.3.1.2 - STDLIB Release Notes","ref":"notes.html#stdlib-4-3-1-2"},{"type":"extras","doc":"- The following functions are now much faster when given a long list or binary:\n\n - erlang:list_to_integer/1\n - erlang:binary_to_integer/1\n - erlang:binary_to_integer/2\n - erlang:list_to_integer/2\n - string:to_integer/1\n\n Own Id: OTP-18659 Aux Id: PR-7426","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 4.3.1.1 - STDLIB Release Notes","ref":"notes.html#stdlib-4-3-1-1"},{"type":"extras","doc":"- Static supervisors are very idle processes after they have started so they\n will now be hibernated after start to improve resource management.\n\n Own Id: OTP-18556","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 4.3.1 - STDLIB Release Notes","ref":"notes.html#stdlib-4-3-1"},{"type":"extras","doc":"- The type specs in the `erl_parse` module has been updated to include the\n `maybe` construct and the `!` operator.\n\n Own Id: OTP-18506 Aux Id: GH-6956","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 4.3 - STDLIB Release Notes","ref":"notes.html#stdlib-4-3"},{"type":"extras","doc":"- Fixed a bug that would cause analysis to crash.\n\n Own Id: OTP-18372 Aux Id: GH-6580\n\n- Fixed a crash when formatting stack traces for error reports.\n\n Own Id: OTP-18375 Aux Id: GH-6591\n\n- Instead of crashing, the [`list_to_integer/1`](`list_to_integer/1`) and\n [`list_to_integer/2`](`list_to_integer/2`) BIFs now raise the `system_limit`\n exception for overlong lists that can't be converted to integers. Similarly,\n the `string:to_integer/1` BIF now returns `{error,system_limit}` for overlong\n lists.\n\n Own Id: OTP-18475 Aux Id: PR-6897","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Removal of non-necessary `undefined` types added to the state's `supervisor`\n record.\n\n Own Id: OTP-18393 Aux Id: PR-6666","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 4.2 - STDLIB Release Notes","ref":"notes.html#stdlib-4-2"},{"type":"extras","doc":"- `erl_tar` can now read gzip-compressed tar files that are padded. There is a\n new option `compressed_one` for `file:open/2` that will read a single member\n from a gzip file,\n\n Own Id: OTP-18289 Aux Id: PR-6343\n\n- A concurrent call to `ets:rename` could cause `ets:delete_all_objects` to fail\n halfway through with badarg.\n\n Own Id: OTP-18292 Aux Id: PR-6366\n\n- It is not allowed to call functions from guards. The compiler failed to reject\n a call in a guard when done by constructing a record with a default\n initialization expression that called a function.\n\n Own Id: OTP-18325 Aux Id: GH-6465, GH-6466\n\n- The compiler could crash when using a record with complex field initialization\n expression as a filter in a list comprehension.\n\n Own Id: OTP-18336 Aux Id: GH-6501, PR-6502\n\n- `unicode:characters_to_binary()` could build unnecessarily large call stack.\n\n Own Id: OTP-18351 Aux Id: ERIERL-885, PR-6529","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Improve error message for ets:new/2 name clash. Say \"name already exists\"\n instead of less specific \"invalid options\".\n\n Own Id: OTP-18283 Aux Id: PR-6338","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 4.1.1 - STDLIB Release Notes","ref":"notes.html#stdlib-4-1-1"},{"type":"extras","doc":"- `m:peer` nodes failed to halt when the process supervising the control\n connection crashed. When an alternative control connection was used, this\n supervision process also quite frequently crashed when the `peer` node was\n stopped by the node that started it which caused the `peer` node to linger\n without ever halting.\n\n Own Id: OTP-18249 Aux Id: PR-6301","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 4.1 - STDLIB Release Notes","ref":"notes.html#stdlib-4-1"},{"type":"extras","doc":"- Fixed inconsistency bugs in `m:global` due to `nodeup`/`nodedown` messages not\n being delivered before/after traffic over connections. Also fixed various\n other inconsistency bugs and deadlocks in both `m:global_group` and `global`.\n\n As building blocks for these fixes, a new BIF `erlang:nodes/2` has been\n introduced and `net_kernel:monitor_nodes/2` has been extended.\n\n The [`-hidden`](`e:erts:erl_cmd.md#hidden`) and\n [`-connect_all`](`e:erts:erl_cmd.md#connect_all`) command line arguments did\n not work if multiple instances were present on the command line which has been\n fixed. The new kernel parameter\n [`connect_all`](`e:kernel:kernel_app.md#connect_all`) has also been introduced\n in order to replace the `-connect_all` command line argument.\n\n Own Id: OTP-17934 Aux Id: PR-6007\n\n- Fix the `public_key:ssh*` functions to be listed under the correct release in\n the Removed Functionality User's Guide.\n\n Own Id: OTP-18139 Aux Id: PR-6060\n\n- The type spec for `format_status/1` in `gen_statem`, `gen_server` and\n `gen_event` has been corrected to state that the return value is of the same\n type as the argument (instead of the same value as the argument).\n\n Own Id: OTP-18142 Aux Id: PR-6078\n\n- If the `timer` server child spec was already present in `kernel_sup` but it\n was not started, the `timer` server would fail to start with an\n `{error, already_present}` error instead of restarting the server.\n\n Own Id: OTP-18146 Aux Id: PR-5983\n\n- When changing callback module in `gen_statem` the state_enter calls flag from\n the old module was used in for the first event in the new module, which could\n confuse the new module and cause malfunction. This bug has been corrected.\n\n With this change some `sys` debug message formats have been modified, which\n can be a problem for debug code relying on the format.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18239","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- There is a new configure option, `--enable-deterministic-build`, which will\n apply the `deterministic` compiler option when building Erlang/OTP. The\n `deterministic` option has been improved to eliminate more sources of\n non-determinism in several applications.\n\n Own Id: OTP-18165 Aux Id: PR-5965\n\n- The `rfc339_to_system_time/1,2` functions now allows the minutes part to be\n omitted from the time zone.\n\n Own Id: OTP-18166 Aux Id: PR-6108\n\n- The `receive` statement in `gen_event` has been optimized to not use selective\n receive (which was never needed, and could cause severe performance\n degradation under heavy load).\n\n Own Id: OTP-18194 Aux Id: PR-6199\n\n- Add new API function erl_features:configurable/0\n\n Own Id: OTP-18199 Aux Id: PR-5790","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 4.0.1 - STDLIB Release Notes","ref":"notes.html#stdlib-4-0-1"},{"type":"extras","doc":"- In the initial release of Erlang/OTP 25, the expression bound to the `_`\n pseudo-field in a record initialization would always be evaluated once, even\n if all other fields in the record were explicitly initialized. That would\n break the use case of binding the expression `error(...)` to `_` in order to\n get an exception if not all fields were initialized.\n\n The behavior of binding to `_` has been reverted to the pre-OTP 25 behavior,\n that is, to not evaluate the expression if all fields have been bound to\n explicit values.\n\n Own Id: OTP-18110 Aux Id: GH-6000","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 4.0 - STDLIB Release Notes","ref":"notes.html#stdlib-4-0"},{"type":"extras","doc":"- Improve the Erlang code linter's check of unused types.\n\n Own Id: OTP-17370 Aux Id: GH-4784\n\n- Fix race condition in `proc_lib:stop/3` where the process is not stopped when\n the timeout given is very short.\n\n Own Id: OTP-17480 Aux Id: GH-4853 PR-4872\n\n- Maps are now fully supported in by `ms_transform`.\n\n Own Id: OTP-17518 Aux Id: GH-4915\n\n- Fix gen_server:call with the first argument as self() to throw an error\n instead of failing with a timeout.\n\n The same fix has also been done for gen_statem:call/3, gen_event:sync_notify/2\n and any other functionality relying on the internal gen:call/3 function.\n\n A similar fix was also done when using io:format/2 and the current\n group_leader was set to the current process.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17544 Aux Id: PR-5008\n\n- erl_pp printed unary - and + operators with a space between the operator and\n the operand. This is fixed by not having any space in between.\n\n Own Id: OTP-17566 Aux Id: PR-5095, GH-5093\n\n- Adjust uri_string:normalize behavior for URIs with undefined port (URI string\n with a port colon but no port value or URI map with port => undefined).\n\n Remove redundant normalization from http_request module.\n\n Before this change, normalize would not remove port subcomponent in such cases\n and could for example return \"http://localhost:\" URI.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17627\n\n- Fix reduction counting bug in `re:run` that caused the function to yield too\n frequently when doing `global` matches.\n\n Own Id: OTP-17661 Aux Id: PR-5165\n\n- Fix the memory value returned from `ets:info(Tid,memory)` when the\n `read_concurrency` option is used.\n\n Before this fix the memory used by the scheduler specific lock cache lines was\n not counted towards the total. This caused the returned memory usage to be\n very incorrect on systems with many schedulers for tables with man locks.\n\n Own Id: OTP-17832 Aux Id: PR-5494\n\n- Avoid confusion by correcting the argument order in the gen_event crash log\n printout.\n\n Own Id: OTP-17878\n\n- Fixed `string:next_grapheme/1` to return an empty binary in the tail for\n binary input for the last grapheme cluster.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18009 Aux Id: PR-5785\n\n- Fixed type specifications of the `supervisor:sup_name/0` and\n [`supervisor:sup_ref/0`](`t:supervisor:sup_ref/0`) types.\n\n Own Id: OTP-18034 Aux Id: PR-4661, GH-4622\n\n- If a default record field initialization (`_ = Expr`) was used even though all\n records fields were explicitly initialized, `Expr` would not be evaluated.\n That would not be a problem, except when `Expr` would bind a variable\n subsequently used, in which case the compiler would crash.\n\n As an example, if record `#r{}` is defined to have only one field `a`, the\n following code would crash the compiler:\n\n `#r{a=[],_=V=42}, V`\n\n To fix that problem, the compiler will make sure that `Expr` is always\n evaluated at least once. The compiler will now rewrite the example to\n essentially:\n\n `V=42, #r{a=[]}, V`\n\n Own Id: OTP-18083","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Users can now configure ETS tables with the `{write_concurrency, auto}`\n option. This option forces tables to automatically change the number of locks\n that are used at run-time depending on how much concurrency is detected. The\n `{decentralized_counters, true}` option is enabled by default when\n `{write_concurrency, auto}` is active.\n\n Benchmark results comparing this option with the other ETS optimization\n options are available here:\n\n https://erlang.org/bench/ets_bench_result_lock_config.html\n\n Own Id: OTP-15991 Aux Id: PR-5208\n\n- The `format_status/2` callback for `gen_server`, `gen_statem` and `gen_event`\n has been deprecated in favor of the new `format_status/1` callback.\n\n The new callback adds the possibility to limit and change many more things\n than the just the state, such as the last received message, the reason for\n terminating and more events specific to each type of behavior. See the\n respective modules documentation for more details.\n\n Own Id: OTP-17351 Aux Id: GH-4673 PR-4952\n\n- The `timer` module has been modernized and made more efficient, which makes\n the timer server less susceptible to being overloaded. The `timer:sleep/1`\n function now accepts an arbitrarily large integer.\n\n Own Id: OTP-17481 Aux Id: PR-4811\n\n- Add `lists:enumerate/[1,2]`.\n\n Own Id: OTP-17523 Aux Id: PR-4928\n\n- The configuration files [`.erlang`](`e:erts:erl_cmd.md`),\n [`.erlang.cookie`](`e:system:distributed.md`) and\n [`.erlang.crypt`](`m:beam_lib#module-erlang-crypt`) can now be located in the XDG\n Config Home directory.\n\n See the documentation for each file and `filename:basedir/2` for more details.\n\n Own Id: OTP-17554 Aux Id: GH-5016 PR-5408 OTP-17821\n\n- Support `native` time unit in `calendar` functions `system_time_to_rfc3339/2`\n and `rfc3339_to_system_time`.\n\n Own Id: OTP-17592 Aux Id: ERIERL-663, PR-5243\n\n- The tagged tuple tests and fun-calls have been optimized and are now a little\n bit cheaper than previously.\n\n These optimizations become possible after making sure that all boxed terms\n have at least one word allocated after the arity word. This has been\n accomplished by letting all empty tuples refer to the same empty tuple literal\n which also reduces memory usage for empty tuples.\n\n Own Id: OTP-17608\n\n- The signal queue benchmark in parallel_messages_SUITE and the ETS benchmark in\n ets_SUITE have benchmark result visualization HTML pages with \"fill-screen\"\n buttons to make the graphs bigger. This button did not work as intended\n before. When pressing the button for a graph, the last graph got replaced with\n a bigger version and not the one over the button. This is now fixed.\n\n Own Id: OTP-17630\n\n- The new module `peer` supersedes the `slave` module. The `slave` module is now\n deprecated and will be removed in OTP 27.\n\n `peer` contains an extended and more robust API for starting erlang nodes.\n\n Own Id: OTP-17720 Aux Id: PR-5162\n\n- This change introduces quote and unquote functions in uri_string module - a\n replacement for deprecated encode and decode functions from http_uri.\n\n Own Id: OTP-17778 Aux Id: GH-5368\n\n- In order to make it easier for the user to manage multiple outstanding\n asynchronous `call` requests, new functionality utilizing request identifier\n collections have been introduced in\n [`erpc`](`t:erpc:request_id_collection/0`),\n [`gen_server`](`t:gen_server:request_id_collection/0`),\n [`gen_statem`](`t:gen_statem:request_id_collection/0`), and\n [`gen_event`](`t:gen_event:request_id_collection/0`).\n\n Own Id: OTP-17784 Aux Id: PR-5792\n\n- Update to the Unicode 14.0 specification.\n\n Own Id: OTP-17869 Aux Id: PR-5595\n\n- The following ets types have been renamed to a clearer name: `tab/0` to\n `table/0` and `comp_match_spec/0` to `compiled_match_spec/0`.\n\n The types `table_access/0` and `table_type/0` have been exported.\n\n Own Id: OTP-17901 Aux Id: GH-4968 PR-5649\n\n- Add support for locating `.asn1` files to the default search rules of\n `filelib:find_file/1` and `filelib:find_source/1`.\n\n Own Id: OTP-17908 Aux Id: GH-5655 PR-5669\n\n- Type specifications have been added to the `gen_server`, and the documentation\n has been updated to utilize this.\n\n This surfaced a few type violations that has been corrected in `global`,\n `logger_olp` and `rpc`.\n\n Own Id: OTP-17915 Aux Id: PR-5751, GH-2375, GH-2690\n\n- The non-local function handler for the `erl_eval` can now be called with\n either two or three arguments. When called with three arguments, the first\n argument is the annotation for the node in the abstract format.\n\n All errors during evaluation will now be passed through `erlang:raise/3`. If\n the restricted shell is active and it does not let `erlang:raise/3` through,\n evaluation errors will be printed in less clear way. See the documentation for\n restricted shell in `shell`.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17925 Aux Id: PR-5631\n\n- Added `filelib:ensure_path/1` that ensures that all directories for the given\n path exists (unlike `filelib:ensure_dir/1`, which will not create the last\n segment of the path).\n\n Own Id: OTP-17953 Aux Id: PR-5621\n\n- The functions `groups_from_list/2` and `groups_from_list/3` have been added to\n the `maps` module.\n\n Own Id: OTP-17969 Aux Id: PR-5588\n\n- `gen_server` has been refactored to throw more readable exceptions when a\n callback returns bad values in the `Timeout` field\n (`timeout() | 'hibernate' | {'continue,_}`), and also to verify that argument\n in the `gen_server:enter_loop/3,4,5` API function.\n\n Own Id: OTP-17974 Aux Id: GH-5683\n\n- The functions `uniq/1` and `uniq/2` for removing duplicates have been added to\n the `lists` module.\n\n Own Id: OTP-17977 Aux Id: GH-5606, PR-5766\n\n- Added support for configurable features as described in EEP-60. Features can\n be enabled/disabled during compilation with options\n (`-enable-feature Feature`, `-disable-feature Feature` and\n `+{feature, Feature, enable|disable}`) to `erlc` as well as with directives\n (`-feature(Feature, enable|disable).`) in the file. Similar options can be\n used to `erl` for enabling/disabling features allowed at runtime. The new\n `maybe` expression (EEP-49) is fully supported as the feature `maybe_expr`.\n The features support is documented in the reference manual.\n\n Own Id: OTP-17988\n\n- The function `filename:safe_relative_path/1`, which has been deprecated since\n OTP 25, has been removed. Use `filelib:safe_relative_path/2` instead.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17991\n\n- A new PRNG have been added to the `rand` module: `mwc59` which has been\n developed in collaboration with Sebastiano Vigna. It is intended for\n applications that need really fast pseudo-random numbers, and it comes with\n two output value scramblers, one fast and one thorough.\n\n Two internal functions for the `exsp` generator have also been exported so\n they can be used outside the `rand` plug-in framework to shave off some\n overhead.\n\n The internal `splitmix64` generator has also been exported which can be useful\n for seeding other kinds of PRNG:s than its own.\n\n Own Id: OTP-18011","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.17.2.4 - STDLIB Release Notes","ref":"notes.html#stdlib-3-17-2-4"},{"type":"extras","doc":"- The following functions are now much faster when given a long list or binary:\n\n - erlang:list_to_integer/1\n - erlang:binary_to_integer/1\n - erlang:binary_to_integer/2\n - erlang:list_to_integer/2\n - string:to_integer/1\n\n Own Id: OTP-18659 Aux Id: PR-7426","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.17.2.3 - STDLIB Release Notes","ref":"notes.html#stdlib-3-17-2-3"},{"type":"extras","doc":"- Static supervisors are very idle processes after they have started so they\n will now be hibernated after start to improve resource management.\n\n Own Id: OTP-18556","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.17.2.2 - STDLIB Release Notes","ref":"notes.html#stdlib-3-17-2-2"},{"type":"extras","doc":"- It is not allowed to call functions from guards. The compiler failed to reject\n a call in a guard when done by constructing a record with a default\n initialization expression that called a function.\n\n Own Id: OTP-18325 Aux Id: GH-6465, GH-6466","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.17.2.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-17-2-1"},{"type":"extras","doc":"- When changing callback module in `gen_statem` the state_enter calls flag from\n the old module was used in for the first event in the new module, which could\n confuse the new module and cause malfunction. This bug has been corrected.\n\n With this change some `sys` debug message formats have been modified, which\n can be a problem for debug code relying on the format.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18239","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.17.2 - STDLIB Release Notes","ref":"notes.html#stdlib-3-17-2"},{"type":"extras","doc":"- The type specifications for `shell_docs:get_doc/3`,\n `shell_docs:get_callback_doc/3`, and `shell_docs:get_type_doc/3` incorrectly\n stated that the returned `Metadata` was an empty map.\n\n Own Id: OTP-18081","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.17.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-17-1"},{"type":"extras","doc":"- The compilation time is no longer recorded in BEAM files. There remained\n several undocumented functions that attempted to retrieve compilation times.\n Those have now been removed.\n\n Own Id: OTP-17962","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.17 - STDLIB Release Notes","ref":"notes.html#stdlib-3-17"},{"type":"extras","doc":"- Fix rendering of nbsp on terminals that do not support unicode.\n\n Own Id: OTP-17662 Aux Id: PR-5206\n\n- Improved the `m:erl_error` printout for when `m:re` fails to compile a regular\n expression to also print hints about why the compilation failed.\n\n Own Id: OTP-17750 Aux Id: PR-5366\n\n- Fixed spec for `supervisor_bridge:start_link()`.\n\n Own Id: OTP-17766 Aux Id: PR-5362\n\n- Added missing shutdown clauses in `supervisor` which could cause erroneous\n error reports.\n\n Own Id: OTP-17767 Aux Id: PR-5344","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add the `no_auto_import_types` to erl_lint to allow a module to define types\n of the same name as a predefined type.\n\n Own Id: OTP-17744 Aux Id: PR-5292","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.16.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-16-1"},{"type":"extras","doc":"- Fixed a bug that could cause a child to become orphaned when a supervisor died\n between unlinking and sending the shutdown signal to this child.\n\n There was also a possibility for erratic supervisor reports caused by a race\n between a supervisor shutting down a child and that child exiting by itself at\n the same time.\n\n Own Id: OTP-17649 Aux Id: GH-5193, PR-5201","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.16 - STDLIB Release Notes","ref":"notes.html#stdlib-3-16"},{"type":"extras","doc":"- Fix `io:format` with `~p` to no longer interpret floats as printable\n characters.\n\n Own Id: OTP-17424 Aux Id: GH-4801 PR-4803\n\n- Fix specs for base64 encode/decode functions to also include 0.\n\n Own Id: OTP-17429 Aux Id: GH-4761\n\n- The failing call `io:format(\"~p\\n\")` would result in a warning for line number\n 0 instead of the correct line and column numbers. This has been corrected, and\n all warnings for failing calls to [`io:format()`](`t:io:format/0`) has been\n rephrased to make it clearer exactly what the problem is.\n\n Own Id: OTP-17430\n\n- When the options `warn_missing_spec` and `export_all` were given, there would\n only be warnings for missing specs for functions that had been explicitly\n exported using an `-export` attribute.\n\n Own Id: OTP-17434 Aux Id: GH-4772\n\n- Calling `c:ls/1` with an atom whose contents is the the name of a file (as\n opposed to a directory) would crash.\n\n Own Id: OTP-17463 Aux Id: GH-4916\n\n- The `MODULE` and `MODULE_STRING` macros would always appear to be defined\n (when tested by `-ifdef`), even though no `-module()` declaration had been\n seen yet. Changed so that `-ifdef ?MODULE.` will not consider ?MODULE defined\n if `-module()` has not been previously seen.\n\n Own Id: OTP-17505 Aux Id: GH-4995\n\n- Fix bug with rendering of missing types and callbacks in shell_docs.\n\n Own Id: OTP-17573 Aux Id: ERL-1264 GH-4270\n\n- When the `deterministic` option was given to the compiler, the `?FILE` macro\n would be expanded to full path of the source file before the first `include`\n directive and to base part of the filename after `include` directive.\n\n Own Id: OTP-17581 Aux Id: PR-5141\n\n- Fixed broken `win32reg:delete_key` and fixed `win32reg:value` for `default`\n value.\n\n Own Id: OTP-17622 Aux Id: PR-5038\n\n- Fixed error information for the call `maps:get(some_key, #{})`.\n\n Own Id: OTP-17634 Aux Id: GH-5196","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Most output functions in the `io` module now print extra error information\n when provided with invalid arguments. The functions are: `io:format`,\n `io:fwrite`, `io:put_chars`, `io:nl` and `io:write`.\n\n Own Id: OTP-17317 Aux Id: PR-4757\n\n- EEP-54 (Provide more information about errors) now includes two new return\n values for the `format_error` callback, `general` and `reason`.\n\n Multi-line error descriptions returned from a `format_error` callback are now\n correctly indented.\n\n The documentation for `m:erl_error`, [`error/3`](`erlang:error/3`) and\n [Errors and Error Handling](`e:system:errors.md`) in the Erlang Reference\n Manual have been extended.\n\n Own Id: OTP-17454 Aux Id: PR-4764\n\n- In the documentation for the `lists` module, it has been clarified that\n predicate funs must return a boolean.\n\n Own Id: OTP-17503 Aux Id: GH-4985\n\n- The documentation for `c:c/1`, `c:c/2`, and `c:c/3` has been clarified.\n\n Own Id: OTP-17571 Aux Id: GH-5103","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.15.2 - STDLIB Release Notes","ref":"notes.html#stdlib-3-15-2"},{"type":"extras","doc":"- Fix a bug that could cause a crash when formatting tuples using the control\n sequences `p` or `P` and limiting the output with the option `chars_limit`.\n\n Own Id: OTP-17525 Aux Id: GH-5053","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.15.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-15-1"},{"type":"extras","doc":"- Fix a bug that could cause a loop when formatting terms using the control\n sequences p or P and limiting the output with the option `chars_limit`.\n\n Own Id: OTP-17459 Aux Id: GH-4824, GH-4842","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.15 - STDLIB Release Notes","ref":"notes.html#stdlib-3-15"},{"type":"extras","doc":"- Time-outs in `gen_statem` with relative time `0` did not behave quite\n according to the intended model. This has now been corrected.\n\n The correction introduces a small potential incompatibility e.g when combining\n a state time-out with inserted events, and the inserted event does a state\n change in the state with the time-out. Before this correction the state\n time-out could be delivered even after the second state change, but now it is\n guaranteed that a state time-out is only delivered in the state it was started\n for, even in this corner case.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15107 Aux Id: ERL-1381, PR-2813\n\n- Fix bugs in `erl_eval` concerning bitstring comprehensions.\n\n Own Id: OTP-16865\n\n- File names that start with a dot (such as \"`.gitignore`\" are now treated as\n file names and not extensions by `filename:extension/1` and\n `filename:rootname/1`.\n\n Own Id: OTP-16905\n\n- Fixed a bug where `beam_lib:chunks/3` with the `allow_missing_chunks` option\n would crash if a named chunk was missing.\n\n Own Id: OTP-16950 Aux Id: ERL-1378\n\n- A floating point zero (0.0) can be both positive (+0.0) and negative (-0.0).\n Multiple bugs in the compiler, runtime system, and STDLIB have been fixed to\n ensure that the minus sign on 0.0 is not lost.\n\n Own Id: OTP-17077 Aux Id: ERL-1431, PR-2903, PR-2905, PR-2906\n\n- Eliminated a Dialyzer crashed when the `-MMD` option is used to generate a\n dependency file and a BEAM file a the same time.\n\n Own Id: OTP-17118 Aux Id: PR-2825\n\n- Fixed bug in `m:shell_docs` and `erl_docgen` that interpreted `em` tags as\n `strong`.\n\n Own Id: OTP-17122\n\n- On Solaris, the `math:acos/1` and `math:asin/1` functions would not fail for\n arguments outside the valid domain.\n\n Own Id: OTP-17133\n\n- Silence `unused_record` warnings when using `ms_transform`. The parse\n transform `ms_transform` replaces records with tuples, which can cause the\n Erlang code linter to emit warnings about unused records.\n\n Own Id: OTP-17186\n\n- Documented a deficiency in the `re` module regarding the `[:ascii:]` character\n class matching Latin-1 characters.\n\n Own Id: OTP-17222 Aux Id: GH-4544\n\n- Fixed `spec` of start functions in generic behaviors.\n\n Own Id: OTP-17342 Aux Id: GH-4725 PR-4726\n\n- Supervisors rejected child specs with a shutdown value of 0.\n\n Own Id: OTP-17364 Aux Id: PR-4747","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- In the `rand` module it is now possible to seed the default algorithm using an\n algorithm alias: `default`.\n\n Generating pseudo random binaries has been implemented with `rand:bytes/1` and\n `rand:bytes_s/2`.\n\n Own Id: OTP-14646 Aux Id: PR-2920\n\n- New functions have been added to the `proplists` module: `to_map/1,2` and\n `from_map/1`.\n\n Own Id: OTP-14647 Aux Id: PR-2910\n\n- New functions have been added to the `queue` module: `all/2`, `any/2`,\n `delete/2`, `delete_r/2`, `delete_with/2`, and `delete_with_r/2`.\n\n Own Id: OTP-14650 Aux Id: PR-2850\n\n- New function have been added to the `queue` module: `fold/2` and\n `filtermap/2`.\n\n Own Id: OTP-14793 Aux Id: PR-2791\n\n- Support for handling abstract code created before OTP R15 has been dropped.\n\n Own Id: OTP-16678 Aux Id: PR-2627\n\n- Extended error information for failing BIF calls as proposed in\n [EEP 54](https://github.com/erlang/eep/blob/master/eeps/eep-0054.md) has been\n implemented.\n\n When a BIF call from the Erlang shell fails, more information about which\n argument or arguments that were in error will be printed. The same extended\n error information will by `proc_lib`, `common_test`, and `qlc` when BIF calls\n fail.\n\n For applications that wish to provide the same extended error information,\n there are new functions `erl_error:format_exception/3` and\n `erl_error:format_exception/4`.\n\n There is a new [`error/3`](`error/3`) BIF that allows applications or\n libraries to provide extended error information in the same way for their own\n exceptions.\n\n Own Id: OTP-16686\n\n- The [_process alias_](`e:system:ref_man_processes.md#process-aliases`) feature\n as outlined by\n [EEP 53](https://github.com/erlang/eep/blob/master/eeps/eep-0053.md) has been\n introduced. It is introduced in order to provide a lightweight mechanism that\n can prevent late replies after timeout or connection loss. For more\n information, see EEP 53 and the documentation of the new\n [`alias/1`](`erlang:alias/1`) BIF and the new options to the\n [`monitor/3`](`erlang:monitor/3`) BIF.\n\n The `call` operation in the framework used by `gen_server`, `gen_statem`, and\n `gen_event` has been updated to utilize alias in order to prevent late\n responses. The `gen_statem` behavior still use a proxy process in the\n distributed case, since it has always prevented late replies and aliases wont\n work against pre OTP 24 nodes. The proxy process can be removed in OTP 26.\n\n The alias feature also made it possible to introduce new functions similar to\n the [`erpc:receive_response()`](`erpc:receive_response/2`) function in the gen\n behaviors, so the new functions\n [`gen_server:receive_response()`](`gen_server:receive_response/2`),\n [`gen_statem:receive_response()`](`gen_statem:receive_response/2`),\n [`gen_event:receive_response()`](`gen_event:receive_response/2`) have also\n been introduced.\n\n Own Id: OTP-16718 Aux Id: PR-2735\n\n- Improved documentation about exit signals emitted when a `gen_server`\n terminates.\n\n Own Id: OTP-16910 Aux Id: PR-2771\n\n- New functions have been added to the `maps` module: `merge_with/3`,\n `intersect/2`, `intersect_with/3`, `filtermap/2`, `from_keys/2`, and\n `maps:foreach/2`.\n\n `maps:merge_with/3` is the same as `merge/2` but takes an extra fun that is\n used to combine items with the same key.\n\n `maps:intersect/2` computes the intersection of two maps.\n\n `maps:intersect_with/3` is the same as `intersect/2` but takes an extra fun\n that is used to combine intersecting items.\n\n `maps:filtermap/2` allows filtering and mapping of a map in a single pass.\n\n `maps:from_keys/2` constructs a map from a list of keys and a single value and\n can be used to to optimize sets operations such as from_list/1, filter/2,\n intersection/2, and subtract/2.\n\n `maps:foreach/2` allows iteration over a map without returning any value.\n\n Own Id: OTP-16936 Aux Id: ERL-1367\n\n- The experimental HiPE application has been removed, together with all related\n functionality in other applications.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-16963\n\n- The `filename:src/1` function which was deprecated in OTP 20 has been removed.\n Use `filelib:find_source/1,3` instead.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-16971\n\n- The pretty printer for floating point number have been changed to make it\n easier to see if the integer part of the number has been rounded. After the\n change the digit that may have been rounded always appears last or just before\n the exponent character (e or E). This is accomplished by always printing the\n number using scientific notation if it is so large that the integer part could\n be rounded.\n\n Own Id: OTP-16980 Aux Id: ERL-1308\n\n- Accept references up to a size of 160-bits from remote nodes. This is the\n first step in an upgrade path toward using references up to 160-bits in a\n future OTP release.\n\n Own Id: OTP-17005 Aux Id: OTP-16718\n\n- Add option `location` to `erl_parse:abstract/2`.\n\n Own Id: OTP-17024\n\n- All long running functions in the maps API are now yielding. In previous\n releases the functions `maps:from_list/1`, `maps:keys/1` and `maps:values/1`\n did not yield. This could cause unfair scheduling of processes.\n\n Own Id: OTP-17057\n\n- The `sets` module now has an optional map-based implementation, as described\n in `EEP 50`.\n\n To use this implementation, pass the `{version,2}` option to `sets:new/1` or\n `sets:from_list/2`.\n\n Own Id: OTP-17059 Aux Id: PR-2864\n\n- Added `shell_docs:supported_tags/0`. This function can be used to retrieve the\n tags currently supported by `shell_docs`.\n\n Own Id: OTP-17120\n\n- The `application/erlang+html` documentation storage format used by\n `m:shell_docs` has been updated to include the tags `b`, `strong`, `h4`, `h5`\n and `h6`.\n\n Own Id: OTP-17121\n\n- Do not pretty-print `catch` expressions with unnecessary parentheses. The\n re-write of the Erlang parser grammar in PR-2584 implies that parentheses\n around `catch` expressions are in many cases no longer required.\n\n Own Id: OTP-17169 Aux Id: PR-2584\n\n- Improved explanation of `{continue,Continue}` in `Module:init/1` of the\n `gen_server` documentation.\n\n Own Id: OTP-17171 Aux Id: PR-3011\n\n- The `erl_eval` module now accepts a map for keeping track of bindings. Using\n an `orddict` for bindings will still work.\n\n Own Id: OTP-17175\n\n- Documented `epp:scan_erl_form/1` and added `epp:scan_file/2`.\n\n Own Id: OTP-17199 Aux Id: PR-2658\n\n- The standard floating point printing algorithm used by the `io` and `io_lib`\n modules has been changed from the algorithm described in \\[1] to the Ryu\n algorithm \\[2]. This gives a significant speed improvement for the printing of\n most floating point numbers and a small memory consumption improvement.\n\n \\[1]: Robert G. Burger and R. Kent Dybvig. 1996. Printing floating-point\n numbers quickly and accurately. In Proceedings of the ACM SIGPLAN 1996\n conference on Programming language design and implementation (PLDI '96).\n Association for Computing Machinery, New York, NY, USA, 108–116.\n DOI:https://doi.org/10.1145/231379.231397\n\n \\[2]: Ulf Adams. 2018. Ryū: fast float-to-string conversion. In Proceedings of\n the 39th ACM SIGPLAN Conference on Programming Language Design and\n Implementation (PLDI 2018). Association for Computing Machinery, New York, NY,\n USA, 270–282. DOI:https://doi.org/10.1145/3192366.3192369\n\n Thanks to Thomas Depierre\n\n Own Id: OTP-17210\n\n- Add hex encoding and decoding functions in the binary module.\n\n Own Id: OTP-17236 Aux Id: PR-3014\n\n- The undocumented and partially broken `ets:filter/3` function has been\n removed.\n\n Own Id: OTP-17263\n\n- Add support in `m:shell_docs` to display any `\"text\"` documentation format.\n This means that `h(Module)` in the shell now can display the `\"text/markdown\"`\n of Elixir documentation.\n\n Own Id: OTP-17267\n\n- The internal hashing of keys within ETS tables of types `set`, `bag`,\n `duplicate_bag` has been salted to diverge from `erlang:phash2`. This to avoid\n bad hashing if `phash2` is used to distribute the keys over separate\n tables/nodes.\n\n Own Id: OTP-17276 Aux Id: PR-2979\n\n- Updated to the Unicode 13.0 specification.\n\n Own Id: OTP-17327 Aux Id: PR-4707\n\n- Add compiler option `{nowarn_unused_record, RecordNames}`. Document compiler\n option `nowarn_unused_type`.\n\n Own Id: OTP-17330\n\n- Implementation of\n [EEP 56](https://github.com/erlang/eep/blob/master/eeps/eep-0056.md) in\n supervisor. It adds the concept of `significant` children as well as the\n `auto_shutdown` supervisor flag.\n\n See the [supervisor manual page](`m:supervisor`) for more information.\n\n Own Id: OTP-17334 Aux Id: PR-4638, EEP-56\n\n- Fixed warnings in code matching on underscore prefixed variables.\n\n Own Id: OTP-17385 Aux Id: OTP-17123","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.14.2.3 - STDLIB Release Notes","ref":"notes.html#stdlib-3-14-2-3"},{"type":"extras","doc":"- It is not allowed to call functions from guards. The compiler failed to reject\n a call in a guard when done by constructing a record with a default\n initialization expression that called a function.\n\n Own Id: OTP-18325 Aux Id: GH-6465, GH-6466","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.14.2.2 - STDLIB Release Notes","ref":"notes.html#stdlib-3-14-2-2"},{"type":"extras","doc":"- Fix a bug that could cause a crash when formatting tuples using the control\n sequences `p` or `P` and limiting the output with the option `chars_limit`.\n\n Own Id: OTP-17525 Aux Id: GH-5053","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.14.2.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-14-2-1"},{"type":"extras","doc":"- Fix a bug that could cause a loop when formatting terms using the control\n sequences p or P and limiting the output with the option `chars_limit`.\n\n Own Id: OTP-17459 Aux Id: GH-4824, GH-4842","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.14.2 - STDLIB Release Notes","ref":"notes.html#stdlib-3-14-2"},{"type":"extras","doc":"- Dictionaries that have become zipped by the zip module did not get executable\n permission (for the file owner) which makes the files inside the dictionary\n inaccessible. This is fixed by giving dictionaries inside a zip archive XRW\n permission.\n\n Own Id: OTP-17295 Aux Id: GH-4687","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.14.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-14-1"},{"type":"extras","doc":"- Handle maps in `erl_parse:tokens()`.\n\n Own Id: OTP-16978\n\n- The erlang shell function `rr` has been fixed to be able to read records from\n files within a code archive.\n\n Own Id: OTP-17182 Aux Id: PR-3002\n\n- If `beam_lib` is asked to return abstract code for a BEAM file produced by\n Elixir and Elixir is not installed on the computer, `beam_lib` will no longer\n crash, but will return an error tuple. The `cover:compile_beam()` and\n `cover:compile_beam_directory()` functions have been updated to also return an\n error tuple in that situation.\n\n Own Id: OTP-17194 Aux Id: GH-4353\n\n- Correct example module `erl_id_trans` regarding the `{char, C}` type.\n\n Own Id: OTP-17273","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.14 - STDLIB Release Notes","ref":"notes.html#stdlib-3-14"},{"type":"extras","doc":"- This change fixes the handling of deep lists in the path component when using\n uri_string:recompose/1.\n\n Own Id: OTP-16941\n\n- Fix `m:shell_docs` to clear shell decorations (bold/underline) when paginating\n output.\n\n Fix various small renderings issues when integrating `m:shell_docs` with edoc.\n\n Own Id: OTP-17047","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Improved the API and documentation of the uri_string module.\n\n Added a new chapter to the Users Guide about Uniform Resource Identifiers and\n their handling with the new API.\n\n Added two new API functions: uri_string:allowed_characters/0 and\n uri_string:percent_decode/1.\n\n This change has been marked as potentially incompatible as\n uri*string:normalize/2 used to decode percent-encoded character triplets that\n corresponded to characters not in the reserved set. After this change,\n uri_string:normalize/2 will only decode those percent-encoded triplets that\n correspond to characters in the unreserved set (ALPHA / DIGIT / \"-\" / \".\" /\n \"*\" / \"~\").\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-16460\n\n- The `shell_docs` module has been expanded with the possibility to configure\n unicode, ansi and column size for the rendered text.\n\n Own Id: OTP-16990","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.13.2 - STDLIB Release Notes","ref":"notes.html#stdlib-3-13-2"},{"type":"extras","doc":"- The functions `digraph:in_edges/2` and `digraph:out_edges/2` would return\n false edges if called for a vertex that had a '\\_' atom in its name term.\n\n Own Id: OTP-16655\n\n- `filelib:wildcard(\"not-a-directory/..\")` should return an empty list. On\n Windows it returned `\"not-a-directory/..\"`.\n\n Own Id: OTP-16700\n\n- Fix the typespec of shell_docs:render to use the correct type for an MFA.\n\n Own Id: OTP-16739\n\n- Fix uri_string:recompose/1 when host is present but input path is not\n absolute.\n\n This change prevents the recompose operation to change the top level domain of\n the host when the path does not start with a slash.\n\n Own Id: OTP-16751 Aux Id: ERL-1283\n\n- The `epp` module would return a badly formed error term when an '`if`'\n preprocessor directive referenced an undefined symbol. `epp:format_error/1`\n would crash when called with the bad error term.\n\n Own Id: OTP-16816 Aux Id: ERL-1310\n\n- `lists:sublist(List, Start, Len)` failed with an exception if\n `Start > length(List) + 1` even though it is explicitly documented that \"It is\n not an error for `Start+Len` to exceed the length of the list\".\n\n Own Id: OTP-16830 Aux Id: ERL-1334, PR-2718","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.13.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-13-1"},{"type":"extras","doc":"- When a temporary child of a `simple_one_for_one supervisor` died, the internal\n state of the supervisor would be corrupted in a way that would cause the\n supervisor to retain the start arguments for subsequent children started by\n the supervisor, causing unnecessary growth of the supervisor's heap. There\n state corruption could potentially cause other problems as well.\n\n Own Id: OTP-16804","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.13 - STDLIB Release Notes","ref":"notes.html#stdlib-3-13"},{"type":"extras","doc":"- Compiling a match specification with excessive nesting caused the runtime\n system to crash due to scheduler stack exhaustion. Instead of crashing the\n runtime system, effected functions will now raise a `system_limit` error\n exception in this situation.\n\n Own Id: OTP-16431 Aux Id: ERL-592\n\n- Initialization of record fields using `_` is no longer allowed if the number\n of affected fields is zero.\n\n Own Id: OTP-16516\n\n- Fix bugs in `eval_bits`.\n\n Own Id: OTP-16545","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Improved the printout of single line logger events for most of the OTP\n behaviours in STDLIB and Kernel. This includes `proc_lib`, `gen_server`,\n `gen_event`, `gen_statem`, `gen_fsm`, `supervisor`, `supervisor_bridge` and\n `application`.\n\n Improved the [`chars_limit`](`m:logger_formatter#chars_limit`) and\n [`depth`](`m:logger_formatter#depth`) handling in `proc_lib` and when\n formatting of exceptions.\n\n Own Id: OTP-15299\n\n- Remove usage and documentation of old requests of the I/O-protocol.\n\n Own Id: OTP-15695\n\n- Improved ETS scalability of concurrent calls that change the size of a table,\n like `ets:insert/2` and `ets:delete/2`.\n\n This performance feature was implemented for `ordered_set` in OTP 22.0 and\n does now apply for all ETS table types.\n\n The improved scalability may come at the cost of longer latency of\n `ets:info(T,size)` and `ets:info(T,memory)`. A new table option\n `decentralized_counters` has therefore been added. It is default `true` for\n `ordered_set` with `write_concurrency` enabled and default `false` for all\n other table types.\n\n Own Id: OTP-15744 Aux Id: OTP-15623, PR-2229\n\n- Handle Unicode filenames in the `zip` module.\n\n Own Id: OTP-16005 Aux Id: ERL-1003, ERL-1150\n\n- Unicode support was updated to the Unicode 12.1 standard.\n\n Own Id: OTP-16073 Aux Id: PR-2339\n\n- All of the modules [`proc_lib`](`proc_lib:start_monitor/3`),\n [`gen_server`](`gen_server:start_monitor/3`),\n [`gen_statem`](`gen_statem:start_monitor/3`), and\n [`gen_event`](`gen_event:start_monitor/0`) have been extended with a\n `start_monitor()` function. For more information, see the documentation of\n `start_monitor()` for these modules.\n\n Own Id: OTP-16120 Aux Id: ERIERL-402, PR-2427\n\n- Updates for new `erlang:term_to_iovec()` BIF.\n\n Own Id: OTP-16128 Aux Id: OTP-15618\n\n- Documented a quirk regarding extraction from file descriptors in `erl_tar`.\n\n Own Id: OTP-16171 Aux Id: ERL-1057\n\n- Added `ok` as return value to `gen_server:reply/2`\n\n Own Id: OTP-16210 Aux Id: PR-2411\n\n- New functions have been added to `m:c` for printing embedded documentation for\n Erlang modules. The functions are:\n\n - **h/1,2,3** - Print the documentation for a Module:Function/Arity.\n\n - **ht/1,2,3** - Print the type documentation for a Module:Type/Arity.\n\n The embedded documentation is created when building the Erlang/OTP\n documentation.\n\n Own Id: OTP-16222\n\n- Add `indent` and `linewidth` to the options of the `erl_pp` module's\n functions.\n\n Own Id: OTP-16276 Aux Id: PR-2443\n\n- Minor updates due to the new spawn improvements made.\n\n Own Id: OTP-16368 Aux Id: OTP-15251\n\n- The compiler will now raise a warning when inlining is used in modules that\n load NIFs.\n\n Own Id: OTP-16429 Aux Id: ERL-303\n\n- Refactored the internal handling of deprecated and removed functions.\n\n Own Id: OTP-16469\n\n- Extend `erl_parse:abstract/1,2` to handle external fun expressions\n (`fun M:F/A`).\n\n Own Id: OTP-16480\n\n- Added `filelib:safe_relative_path/2` to replace\n `filename:safe_relative_path/1`, which did not safely handle symbolic links.\n\n `filename:safe_relative_path/1` has been deprecated.\n\n Own Id: OTP-16483 Aux Id: PR-2542\n\n- The module `shell_docs` has been added. The module contains functions for\n rendering, validating and normalizing embedded documentation.\n\n Own Id: OTP-16500\n\n- Module and function auto-completion in the shell now looks at all available\n modules instead of only those loaded. A module is considered available if it\n either is loaded already or would be loaded if called.\n\n The auto-completion has also been expanded to work in the new `h/1,2,3`\n function in `m:c`.\n\n Own Id: OTP-16501 Aux Id: OTP-16494, OTP-16222, OTP-16406, OTP-16499,\n OTP-16500, PR-2545, ERL-708\n\n- Updated the internal `pcre` library to `8.44`.\n\n Own Id: OTP-16557","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.12.1.2 - STDLIB Release Notes","ref":"notes.html#stdlib-3-12-1-2"},{"type":"extras","doc":"- Fix a bug that could cause a crash when formatting tuples using the control\n sequences `p` or `P` and limiting the output with the option `chars_limit`.\n\n Own Id: OTP-17525 Aux Id: GH-5053","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.12.1.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-12-1-1"},{"type":"extras","doc":"- Fix a bug that could cause a loop when formatting terms using the control\n sequences p or P and limiting the output with the option `chars_limit`.\n\n Own Id: OTP-17459 Aux Id: GH-4824, GH-4842","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.12.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-12-1"},{"type":"extras","doc":"- [re:run(Subject, RE, \\[unicode])](`re:run/3`) returned `nomatch` instead of\n failing with a `badarg` error exception when `Subject` contained illegal utf8\n and `RE` was passed as a binary. This has been corrected along with\n corrections of reduction counting in `re:run()` error cases.\n\n Own Id: OTP-16553","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.12 - STDLIB Release Notes","ref":"notes.html#stdlib-3-12"},{"type":"extras","doc":"- Fix type specification for uri_string:normalize/2 that may also return\n error().\n\n Own Id: OTP-16322\n\n- Improve error handling in uri_string:normalize/2. This change fixes a crash\n when the input URI has faulty percent-encoding.\n\n Own Id: OTP-16351\n\n- Fix minor bugs in the Erlang pretty printer (`erl_pp`).\n\n Own Id: OTP-16435\n\n- Fix the Erlang parser regarding consecutive unary operators.\n\n Own Id: OTP-16439\n\n- Let `calendar:rfc3339_to_system_time()` crash when the time offset is missing.\n\n Own Id: OTP-16514 Aux Id: ERL-1182","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Implement uri_string:resolve/\\{2,3\\} that can be used to resolve a URI\n reference against a base URI.\n\n Own Id: OTP-16321\n\n- In `gen_statem` it is now possible to change the callback module for a running\n server. See `gen_statem`'s documentation for `change_callback_module`,\n `push_callback_module`, and `pop_callback_module`.\n\n Own Id: OTP-16477 Aux Id: PR-2531","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.11.2 - STDLIB Release Notes","ref":"notes.html#stdlib-3-11-2"},{"type":"extras","doc":"- A directory traversal vulnerability has been eliminated in erl_tar. erl_tar\n will now refuse to extract symlinks that points outside the targeted\n extraction directory and will return `{error,{Path,unsafe_symlink}}`. (Thanks\n to Eric Meadows-Jönsson for the bug report and for suggesting a fix.)\n\n Own Id: OTP-16441","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.11.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-11-1"},{"type":"extras","doc":"- The `ets:update_counter/4` core dumped when given an ordered_set with\n write_concurrency enabled and an invalid position. This bug has been fixed.\n\n Own Id: OTP-16378 Aux Id: ERL-1125","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.11 - STDLIB Release Notes","ref":"notes.html#stdlib-3-11"},{"type":"extras","doc":"- The functions [`unicode:characters_to_list()`](`unicode:characters_to_list/2`)\n and [`unicode:characters_to_binary()`](`unicode:characters_to_binary/3`)\n raised a `badarg` exception instead of returning an error tuple when passed\n very large invalid code points as input.\n\n Own Id: OTP-16052\n\n- Fixed a bug in the linter where list and binary comprehensions could suppress\n unsafe variable errors.\n\n Own Id: OTP-16053 Aux Id: ERL-1039\n\n- Fixed incorrect type specifications for `erl_tar:open/2`, `create/2,3`, and\n `add/4`.\n\n Own Id: OTP-16085 Aux Id: PR-2379\n\n- Fixed erroneous type spec for `binary:list_to_bin/1`. Argument type was\n changed from `t:iodata/0` to `t:iolist/0`.\n\n Own Id: OTP-16132 Aux Id: ERL-1041\n\n- Fix a race in `pool:pspawn_link` that caused a `noproc` error to be thrown\n when using it to spawn a very short lived process.\n\n Own Id: OTP-16211\n\n- Fixed a performance issue in ETS lookup when using the `compressed` option and\n the term contained atoms. Before this fix the decompress algorithm for atoms\n would unnecessarily take a global lock to validate the atom.\n\n Own Id: OTP-16316","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Added a new compiler/linter option to disable warnings for unused types\n (`nowarn_unused_type`).\n\n Own Id: OTP-16262 Aux Id: ERIERL-435\n\n- ETS tables have been optimized to not use any locks when running in a system\n with only one scheduler enabled. This can provide significant performance\n gains for applications that use ETS tables heavily.\n\n Own Id: OTP-16315","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.10 - STDLIB Release Notes","ref":"notes.html#stdlib-3-10"},{"type":"extras","doc":"- `re:run()` now yields when validating utf8 in a large subject.\n\n Own Id: OTP-15836 Aux Id: ERL-876\n\n- Upgraded the ERTS internal PCRE library from version 8.42 to version 8.43. See\n [http://pcre.org/original/changelog.txt](http://pcre.org/original/changelog.txt)\n for information about changes made to PCRE. This library implements major\n parts of the `m:re` regular expressions module.\n\n Own Id: OTP-15889\n\n- The bug with ID ERL-717 has been fixed. The functions `io:columns()` and\n `io:rows()` only worked correctly inside interactive erlang shells before this\n fix. These functions returned `{error,enotsup}` before this fix even if stdout\n and stdin were connected to a terminal when they were invoked from an escript\n or a program started with e.g., `erl -noshell`.\n\n Own Id: OTP-15959 Aux Id: ERL-717\n\n- Fixed handling of \"..\" and \"@\" in wildcards. \"..\" would only work when\n preceded by a literal pattern such as in \"a/..\", not when preceded by wildcard\n characters such as in \"\\*/..\". The combination \"@/..\" was also broken, and in\n addition \"@\" in a pattern could degrade performance of the wildcard matching.\n\n Own Id: OTP-15987 Aux Id: ERL-1029\n\n- Make sure `ets:fun2ms()` can handle `++/2` in the head of functions when\n called from the shell.\n\n Own Id: OTP-15992 Aux Id: PR-2322","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Debugging of time-outs in `gen_statem` has been improved. Starting a time-out\n is now logged in `sys:log` and `sys:trace`. Running time-outs are visible in\n server crash logs, and with `sys:get_status`. Due to this system events\n `{start_timer, Action, State}` and `{insert_timout, Event, State}` have been\n added, which may surprise tools that rely on the format of these events.\n\n New features: The `EventContent` of a running time-out can be updated with\n `{TimeoutType, update, NewEventContent}`. Running time-outs can be cancelled\n with `{TimeoutType, cancel}` which is more readable than using\n `Time = infinity`.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15510\n\n- `re:run()` now avoids validating utf8 in the subject more than once in the\n same call. This validation could previously be performed multiple times when\n the `global` option was passed.\n\n Own Id: OTP-15831 Aux Id: ERL-876\n\n- ETS `ordered_set` tables with `write_concurrency` enabled has got a\n performance issue fixed. There were no limits for the values of internal\n statistics counters before this fix. This could result in that the data\n structure sometimes reacted slowly to a change in how many parallel processes\n were using it.\n\n Own Id: OTP-15906\n\n- The `ordsets:union/1` is now faster when passed a long list of ordsets.\n\n Own Id: OTP-15927\n\n- `unicode:characters_to_binary()` could return very small binaries as reference\n counted off heap binaries. This could cause an unnecessary large memory usage\n and an unnecessary load on the binary allocator. Small binaries are now always\n returned as heap binaries.\n\n Own Id: OTP-16002 Aux Id: ERIERL-366\n\n- Display a more meaningful error message when a bad I/O server is used in a\n script written in Erlang (`escript`).\n\n Own Id: OTP-16006 Aux Id: ERL-992\n\n- New feature `ets:info(_, binary)` to get information about all reference\n counted binaries kept by a table. This is the same kind of debug information\n that [`process_info(_, binary)`](`process_info/2`) returns for a process.\n\n Own Id: OTP-16035 Aux Id: ERIERL-366\n\n- Corrected ETS documentation about the behavior of compiled match\n specifications when serialized through external format.\n\n Own Id: OTP-16038 Aux Id: PR-2366","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.9.2 - STDLIB Release Notes","ref":"notes.html#stdlib-3-9-2"},{"type":"extras","doc":"- Fix a bug that could cause a loop when formatting terms using the control\n sequences `p` or `P` and limiting the output with the option `chars_limit`.\n\n Own Id: OTP-15875 Aux Id: ERL-967","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.9.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-9-1"},{"type":"extras","doc":"- Fix a bug that could cause a failure when formatting binaries using the\n control sequences `p` or `P` and limiting the output with the option\n `chars_limit`.\n\n Own Id: OTP-15847 Aux Id: ERL-957","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.9 - STDLIB Release Notes","ref":"notes.html#stdlib-3-9"},{"type":"extras","doc":"- Fix a bug in `string:lexemes/2`.\n\n The bug was found when optimizing the handling of deep lists of Unicode\n characters in the `string` module.\n\n Own Id: OTP-15649\n\n- A bug has been fixed in the `maps` implementation that could cause a crash or\n memory usage to grow until the machine ran out of memory. This could happen\n when inserting a new key-value pair with a key `K1` containing a binary `B1`\n into a map `M` having a key `K2` with a binary `B2` if the following\n conditions were met:\n\n - `B1 =/= B2`\n - `size(B1) >= 4294967296`\n - `size(B2) >= 4294967296`\n - `size(M) >= 32`\n - `(size(B1) rem 4294967296) == (size(B2) rem 4294967296)`\n - the first `(size(B1) rem 4294967296)` bytes are the same both in `B1` and\n `B2`\n - substituting `B1` in `K1` with `B2` would create a term with the same value\n as `K2`\n\n The root cause of the problem is that the `maps` implementation only hashed\n the first `(X rem 4294967296)` bytes of binaries so that different binaries\n could get the same hash value independently of the hash seed.\n\n Own Id: OTP-15707\n\n- Since the introduction of the stack trace variable, the Erlang Pretty Printer\n has left out the exception class `throw` even when the stack trace variable\n cannot be left out, which is not correct Erlang code. The fix is to always\n include the exception class `throw`.\n\n Own Id: OTP-15751\n\n- `record_info/2` is a pseudo-function that requires literal arguments known at\n compile time. Therefore, the following usage is illegal: `fun record/info/2`.\n The compiler would crash when during compilation of that kind of code.\n Corrected to issue a compilation error.\n\n Own Id: OTP-15760 Aux Id: ERL-907","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- A new `rand` module algorithm, `exro928ss` (Xoroshiro928\\*\\*), has been\n implemented. It has got a really long period and good statistical quality for\n all output bits, while still being only about 50% slower than the default\n algorithm.\n\n The same generator is also used as a long period counter in a new `crypto`\n plugin for the `rand` module, algorithm `crypto_aes`. This plugin uses AES-256\n to scramble the counter which buries any detectable statistical artifacts.\n Scrambling is done in chunks which are cached to get good amortized speed\n (about half of the default algorithm).\n\n Own Id: OTP-14461 Aux Id: PR-1857\n\n- Types related to server naming and starting have been exported from\n `gen_statem`. These are: `server_name/0`, `server_ref/0`, `start_opt/0`,\n `start_ret/0` and `enter_loop_opt/0`.\n\n Own Id: OTP-14724 Aux Id: PR-2056\n\n- The default algorithm for the `rand` module has been changed to `exsss`\n (Xorshift116\\*\\*) which is a combination of the Xorshift116 (`exsp`) state\n update and a new scrambler \"StarStar\" from the 2018 paper \"Scrambled Linear\n Pseudorandom Number Generators\" by David Blackman and Sebastiano Vigna. This\n combination should not have the caveat of weak low bits that the previous\n default algorithm(s) have had, with the cost of about 10% lower speed. See\n GitHub pull request #1969.\n\n Own Id: OTP-14731 Aux Id: PR-1969\n\n- The generic state machine behaviour `gen_statem` has gotten code cleanup and\n documentation improvements from GitHub Pull Request #1855, even though the PR\n itself was rejected.\n\n Own Id: OTP-14737 Aux Id: PR-1855\n\n- Update Unicode specification to version 11.0.\n\n Own Id: OTP-15111\n\n- ETS option `write_concurrency` now also affects and improves the scalability\n of `ordered_set` tables. The implementation is based on a data structure\n called contention adapting search tree, where the lock granularity adapts to\n the actual amount of concurrency exploited by the applications in runtime.\n\n Own Id: OTP-15128\n\n- Optimized `maps:new/0` with trivial Erlang implementation, making use of\n literal terms (the empty map) not needing dynamic heap allocation.\n\n Own Id: OTP-15200 Aux Id: PR-1878\n\n- The `gen_*` behaviours have been changed so that if logging of the last N\n messages through `sys:log/2,3` is active for the server, this log is included\n in the terminate report.\n\n To accomplish this the format of \"System Events\" as defined in the man page\n for `sys` has been clarified and cleaned up, a new function `sys:get_log/1`\n has been added, and `sys:get_debug/3` has been deprecated. Due to these\n changes, code that relies on the internal badly documented format of \"System\n Events\", need to be corrected.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15381\n\n- The `gen_statem` behaviour engine loop has been optimized for better\n performance in particular when the callback module returns some actions, that\n is better performance for more realistic applications than the Echo Benchmark.\n\n Own Id: OTP-15452\n\n- Do not allow function specifications for functions residing in other modules.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15563 Aux Id: ERL-845, OTP-15562\n\n- The `persistent_term` functions [`put/2`](`put/2`) and [`erase/1`](`erase/1`)\n are now yielding.\n\n Own Id: OTP-15615\n\n- Previously, all ETS tables used centralized counter variables to keep track of\n the number of items stored and the amount of memory consumed. These counters\n can cause scalability problems (especially on big NUMA systems). This change\n adds an implementation of a decentralized counter and modifies the\n implementation of ETS so that ETS tables of type `ordered_set` with\n `write_concurrency` enabled use the decentralized counter. Experiments\n indicate that this change substantially improves the scalability of ETS\n `ordered_set` tables with `write_concurrency` enabled in scenarios with\n frequent `ets:insert/2` and `ets:delete/2` calls.\n\n Own Id: OTP-15623 Aux Id: PR-2190\n\n- Use `ssh` instead of `rsh` as the default remote shell.\n\n Own Id: OTP-15633 Aux Id: PR-1787\n\n- Added `beam_lib:strip/2` and friends, which accept a list of chunks that\n should be preserved when stripping.\n\n Own Id: OTP-15680 Aux Id: PR-2114\n\n- Optimize printing of maps with `io_lib:write()`. Also optimize pretty printing\n of strings (`~s` and `~ts`) when limiting the output with the `chars_limit`\n option.\n\n Own Id: OTP-15705\n\n- There are new compiler options `nowarn_removed` and `{nowarn_removed,Items}`\n to suppress warnings for functions and modules that have been removed from\n OTP.\n\n Own Id: OTP-15749 Aux Id: ERL-904\n\n- Let the Erlang Pretty Printer put atomic parts on the same line.\n\n Own Id: OTP-15755\n\n- Add option `quote_singleton_atom_types` to the Erlang Pretty Printer's\n functions. Setting the option to `true` adds quotes to all singleton atom\n types.\n\n Own Id: OTP-15756","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.8.2.4 - STDLIB Release Notes","ref":"notes.html#stdlib-3-8-2-4"},{"type":"extras","doc":"- [re:run(Subject, RE, \\[unicode])](`re:run/3`) returned `nomatch` instead of\n failing with a `badarg` error exception when `Subject` contained illegal utf8\n and `RE` was passed as a binary. This has been corrected along with\n corrections of reduction counting in `re:run()` error cases.\n\n Own Id: OTP-16553","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.8.2.3 - STDLIB Release Notes","ref":"notes.html#stdlib-3-8-2-3"},{"type":"extras","doc":"- A directory traversal vulnerability has been eliminated in erl_tar. erl_tar\n will now refuse to extract symlinks that points outside the targeted\n extraction directory and will return `{error,{Path,unsafe_symlink}}`. (Thanks\n to Eric Meadows-Jönsson for the bug report and for suggesting a fix.)\n\n Own Id: OTP-16441","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.8.2.2 - STDLIB Release Notes","ref":"notes.html#stdlib-3-8-2-2"},{"type":"extras","doc":"- Fix a bug that could cause a loop when formatting terms using the control\n sequences `p` or `P` and limiting the output with the option `chars_limit`.\n\n Own Id: OTP-15875 Aux Id: ERL-967","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.8.2.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-8-2-1"},{"type":"extras","doc":"- Fix a bug that could cause a failure when formatting binaries using the\n control sequences `p` or `P` and limiting the output with the option\n `chars_limit`.\n\n Own Id: OTP-15847 Aux Id: ERL-957","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.8.2 - STDLIB Release Notes","ref":"notes.html#stdlib-3-8-2"},{"type":"extras","doc":"- A bug in gen_statem has been fixed where the internal timeout message could\n arrive as an info to the callback module during high load due to incorrect use\n of asynchronous timer cancel.\n\n Own Id: OTP-15295","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.8.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-8-1"},{"type":"extras","doc":"- Fixed a performance regression when reading files opened with the `compressed`\n flag.\n\n Own Id: OTP-15706 Aux Id: ERIERL-336","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.8 - STDLIB Release Notes","ref":"notes.html#stdlib-3-8"},{"type":"extras","doc":"- Fix a bug in the Erlang Pretty Printer: long atom names in combination with\n `<<>>` could cause a crash.\n\n Own Id: OTP-15592 Aux Id: ERL-818\n\n- Fix bugs that could cause wrong results or bad performance when formatting\n lists of characters using the control sequences `p` or `P` and limiting the\n output with the option `chars_limit`.\n\n Own Id: OTP-15639","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Improved ETS documentation about safe table traversal and the partially bound\n key optimization for `ordered_set`.\n\n Own Id: OTP-15545 Aux Id: PR-2103, PR-2139\n\n- Optimize `calendar:gregorian_days_to_date/1`.\n\n Own Id: OTP-15572 Aux Id: PR-2121\n\n- Optimize functions `calendar:rfc3339_to_system_time()` and\n `calendar:system_time_to_rfc3339()`.\n\n Own Id: OTP-15630","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.7.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-7-1"},{"type":"extras","doc":"- Optimize pretty printing of terms. The slower behaviour was introduced in\n Erlang/OTP 20.\n\n Own Id: OTP-15573 Aux Id: ERIERL-306","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.7 - STDLIB Release Notes","ref":"notes.html#stdlib-3-7"},{"type":"extras","doc":"- Document `bit_size` in match specifications and allow it in `ets:fun2ms`.\n\n Own Id: OTP-15343 Aux Id: PR-1962\n\n- The `beam()` type in `beam_lib` is defined as\n `module() | file:filename() | binary()`. The `t:module/0` is misleading.\n Giving the module name as an atom will only work if the BEAM file is in a\n current directory.\n\n To avoid confusion, `t:module/0` has been removed from the type. That means\n that there will be a Dialyzer warning for code that call `beam_lib` with an\n atom as filename, but the calls will still work.\n\n Own Id: OTP-15378 Aux Id: ERL-696\n\n- `unicode_util` crashed on certain emoji grapheme clusters in binary strings.\n\n Own Id: OTP-15428 Aux Id: ERL-777\n\n- When an external fun was used, warnings for unused variables could be\n suppressed.\n\n Own Id: OTP-15437 Aux Id: ERL-762\n\n- Fix reduction count in lists:member/2\n\n Own Id: OTP-15474 Aux Id: ERIERL-229","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- When specified, the `+{source,Name}` option will now override the actual file\n name in stack traces, instead of only affecting the return value of\n `Mod:module_info()`.\n\n The `+deterministic` flag will also affect stack traces now, omitting all path\n information except the file name, fixing a long-standing issue where\n deterministic builds required deterministic paths.\n\n Own Id: OTP-15245 Aux Id: ERL-706\n\n- List subtraction (The `--` operator) will now yield properly on large inputs.\n\n Own Id: OTP-15371\n\n- `calendar:system_time_to_rfc3339/1,2` no longer remove trailing zeros from\n fractions.\n\n Own Id: OTP-15464","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.6 - STDLIB Release Notes","ref":"notes.html#stdlib-3-6"},{"type":"extras","doc":"- The specs of `filename:basedir/2,3` are corrected.\n\n Own Id: OTP-15252 Aux Id: ERL-667","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Let `dets:open_file()` exit with a `badarg` message if given a raw file name\n (a binary).\n\n Own Id: OTP-15253 Aux Id: OTP-13229, ERL-55\n\n- The `Format` argument of the formatting functions in modules `io` and `io_lib`\n is accepted even if it is, for example, a list of binaries. This is how it\n used to be before Erlang/OTP 21.0.\n\n Own Id: OTP-15304","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.5.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-5-1"},{"type":"extras","doc":"- Fix a bug that could cause a crash when formatting a list of non-characters\n using the control sequences `p` or `P` and limiting the output with the option\n `chars_limit`.\n\n Own Id: OTP-15159","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.5 - STDLIB Release Notes","ref":"notes.html#stdlib-3-5"},{"type":"extras","doc":"- `gen_statem` improvements.\n\n When using an exception that is valid but not allowed in a state enter call,\n the reason has been changed from `{bad_action_from_state_function,Action}` to\n `{bad_state_enter_action_from_state_function,Action}`.\n\n Timer parsing has been improved. Many erroneous timeout tuples was not handled\n correctly.\n\n The documentation has been updated, in particular the User's Guide and the\n pointer to it from the Reference Manual is much more obvious.\n\n Own Id: OTP-14015\n\n- The type specifications for [`file:posix/0`](`t:file:posix/0`) and\n [`inet:posix/0`](`t:inet:posix/0`) have been updated according to which errors\n file and socket operations should be able to return.\n\n Own Id: OTP-14019 Aux Id: ERL-550\n\n- File operations used to accept [filenames](`t:file:name_all/0`) containing\n null characters (integer value zero). This caused the name to be truncated and\n in some cases arguments to primitive operations to be mixed up. Filenames\n containing null characters inside the filename are now _rejected_ and will\n cause primitive file operations to fail.\n\n Also environment variable operations used to accept\n [names](`t:os:env_var_name/0`) and [values](`t:os:env_var_value/0`) of\n environment variables containing null characters (integer value zero). This\n caused operations to silently produce erroneous results. Environment variable\n names and values containing null characters inside the name or value are now\n _rejected_ and will cause environment variable operations to fail.\n\n Primitive environment variable operations also used to accept the `$=`\n character in environment variable names causing various problems. `$=`\n characters in environment variable names are now also _rejected_.\n\n Also `os:cmd/1` now reject null characters inside its\n [command](`t:os:os_command/0`).\n\n `erlang:open_port/2` will also reject null characters inside the port name\n from now on.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-14543 Aux Id: ERL-370\n\n- Make `io_lib:unscan_format/1` work with pad char and default precision.\n\n Own Id: OTP-14958 Aux Id: PR-1735\n\n- The control sequence modifiers `t` and `l` can be used together in the same\n control sequence which makes it possible to have Unicode atoms and no\n detection of printable character lists at the same time.\n\n Own Id: OTP-14971 Aux Id: PR-1743\n\n- Fix a bug in the Erlang code linter: the check of guard expressions no longer\n returns `false` if the map syntax is used. The bug affected the Erlang shell,\n the Debugger, and other modules evaluating abstract code.\n\n Own Id: OTP-15035 Aux Id: ERL-613\n\n- A sys debug fun of type \\{Fun,State\\} should not be possible to install twice.\n This was, however, possible if the current State was 'undefined', which was\n mistaken for non-existing fun. This has been corrected.\n\n Own Id: OTP-15049\n\n- Fix `io:putchars/2` stacktrace rewriting at errors to point to a valid\n function.\n\n Own Id: OTP-15101","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The `gen_server` has gotten a new callback `handle_continue/2` for check\n pointing the state. This is useful at least when implementing behaviours on\n top of `gen_server` and for some start up scenarios.\n\n Own Id: OTP-13019 Aux Id: PR-1490\n\n- The semantics of timeout parameter `{clean_timeout,infinity}` to\n `gen_statem:call/3` has been changed to use a proxy process for the call. With\n this change `clean_timeout` implicates a proxy process with no exceptions.\n This may be a hard to observe incompatibility: in the presence of network\n problems a late reply could arrive in the caller's message queue when catching\n errors. That will not happen after this correction.\n\n The semantics of timeout parameter `infinity` has not been changed.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-13073 Aux Id: PR-1595\n\n- A new logging API is added to Erlang/OTP, see the `m:logger` manual page, and\n section [Logging](`e:kernel:logger_chapter.md`) in the Kernel User's Guide.\n\n Calls to `error_logger` are automatically redirected to the new API, and\n legacy error logger event handlers can still be used. It is, however,\n recommended to use the Logger API directly when writing new code.\n\n Notice the following potential incompatibilities:\n\n - Kernel configuration parameters `error_logger` still works, but is overruled\n if the default handler's output destination is configured with Kernel\n configuration parameter `logger`.\n\n In general, parameters for configuring error logger are overwritten by new\n parameters for configuring Logger.\n\n - The concept of SASL error logging is deprecated, meaning that by default the\n SASL application does not affect which log events are logged.\n\n By default, supervisor reports and crash reports are logged by the default\n Logger handler started by Kernel, and end up at the same destination\n (terminal or file) as other standard log event from Erlang/OTP.\n\n Progress reports are not logged by default, but can be enabled by setting\n the primary log level to info, for example with the Kernel configuration\n parameter `logger_level`.\n\n To obtain backwards compatibility with the SASL error logging functionality\n from earlier releases, set Kernel configuration parameter\n `logger_sasl_compatible` to `true`. This prevents the default Logger handler\n from logging any supervisor-, crash-, or progress reports. Instead, SASL\n adds a separate Logger handler during application start, which takes care of\n these log events. The SASL configuration parameters `sasl_error_logger` and\n `sasl_errlog_type` specify the destination (terminal or file) and severity\n level to log for these events.\n\n Since Logger is new in Erlang/OTP 21.0, we do reserve the right to introduce\n changes to the Logger API and functionality in patches following this release.\n These changes might or might not be backwards compatible with the initial\n version.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-13295\n\n- Add functions `calendar:system_time_to_local_time/2` and\n `calendar:system_time_to_universal_time/2`.\n\n Own Id: OTP-13413\n\n- Functions `rand:uniform_real/0` and `rand:uniform_real_s/1` have been added.\n They produce uniformly distributed numbers in the range `0.0 =< X < 1.0` that\n are as close to random real numbers as Normalized IEEE 754 Double Precision\n allows. Because the random real number exactly `0.0` is infinitely improbable\n they will never return exactly `0.0`.\n\n These properties are useful when you need to call for example `math:log(X)` or\n `1 / X` on a random value `X`, since that will never fail with a number from\n these new functions.\n\n Own Id: OTP-13764 Aux Id: PR-1574\n\n- Added maps:iterator/0 and maps:next/1 to be used for iterating over the\n key-value associations in a map.\n\n Own Id: OTP-14012\n\n- Changed the default behaviour of `.erlang` loading: `.erlang` is no longer\n loaded from the current directory. `c:erlangrc(PathList)` can be used to\n search and load an `.erlang` file from user specified directories.\n\n `escript`, `erlc`, `dialyzer` and `typer` no longer load an `.erlang` at all.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-14439\n\n- Added new uri_string module to stdlib for handling URIs (RFC 3986).\n\n Own Id: OTP-14496\n\n- Update Unicode specification to version 10.0.\n\n Own Id: OTP-14503\n\n- `filelib:wildcard()` now allows characters with a special meaning to be\n escaped using backslashes.\n\n This is an incompatible change, but note that the use of backslashes in\n wildcards would already work differently on Windows and Unix. Existing calls\n to `filelib:wildcard()` needs to be updated. On Windows, directory separators\n must always be written as a slash.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-14577\n\n- The supervisor now stores its child specifications in a map instead of a list.\n This causes a significant improvement when starting many children under a\n non-simple_one_for_one supervisor.\n\n Own Id: OTP-14586\n\n- The `base64` module is optimized.\n\n Note that the functions `encode/1`, `decode/1`, and `mime_decode/1` fail\n unless called with an argument of the documented type. They used to accept any\n `t:iodata/0`.\n\n Own Id: OTP-14624 Aux Id: PR-1565\n\n- Add function `lists:search/2`.\n\n Own Id: OTP-14675 Aux Id: PR-102\n\n- uri_string module extended with functions for handling\n application/x-www-form-urlencoded query strings based on the HTML5\n specification.\n\n Own Id: OTP-14747\n\n- Add functions `calendar:rfc3339_to_system_time/1,2` and\n `calendar:system_time_to_rfc3339/1,2`.\n\n Own Id: OTP-14764\n\n- The stack traces returned by the functions of the `erl_eval` module more\n accurately reflect where the exception occurred.\n\n Own Id: OTP-14826 Aux Id: PR 1540\n\n- Add options `atime`, `mtime`, `ctime`, `uid`, and `gid` to the\n `erl_tar:add/3,4` functions.\n\n Own Id: OTP-14834 Aux Id: PR 1608\n\n- Added `ets:whereis/1` for retrieving the table identifier of a named table.\n\n Own Id: OTP-14884\n\n- Improved URI normalization functions in the uri_string module.\n\n Own Id: OTP-14910\n\n- The new functions `io_lib:fwrite/3` and `io_lib:format/3` take a third\n argument, an option list. The only option is `chars_limit`, which is used for\n limiting the number of returned characters. The limit is soft, which means\n that the number of returned characters exceeds the limit with at most a\n smallish amount. If the limit is set, the functions `format/3` and `fwrite/3`\n try to distribute the number of characters evenly over the control sequences\n `pPswW`. Furthermore, the control sequences `pPwP` try to distribute the\n number of characters evenly over substructures.\n\n A modification of the control sequences `pPwW` is that even if there is no\n limit on the number of returned characters, all associations of a map are\n printed to the same depth. The aim is to give a more consistent output as the\n order of map keys is not defined. As before, if the depth is less than the\n number of associations of a map, the selection of associations to print is\n arbitrary.\n\n Own Id: OTP-14983\n\n- Add functions `ordsets:is_empty/1` and `sets:is_empty/1`.\n\n Own Id: OTP-14996 Aux Id: ERL-557, PR-1703\n\n- Improve performance of `string:uppercase/1`, `string:lowercase/1` and\n `string:casefold/1` when handling ASCII characters.\n\n Own Id: OTP-14998\n\n- External funs with literal values for module, name, and arity (e.g.\n `erlang:abs/1`) are now treated as literals. That means more efficient code\n that produces less garbage on the heap.\n\n Own Id: OTP-15003\n\n- sys:statistics(Pid,get) did not report 'out' messages from gen_server. This is\n now corrected.\n\n Own Id: OTP-15047\n\n- A sys debug function can now have the format \\{Id,Fun,State\\} in addition to\n the old \\{Fun,State\\}. This allows installing multiple instances of a debug\n fun.\n\n Own Id: OTP-15048\n\n- The `lib` module is removed:\n\n - `lib:error_message/2` is removed.\n - `lib:flush_receive/0` is removed.\n - `lib:nonl/1` is removed.\n - `lib:progname/0` is replaced by `ct:get_progname/0`.\n - `lib:send/2` is removed.\n - `lib:sendw/2` is removed.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15072 Aux Id: PR 1786, OTP-15114\n\n- Function `ets:delete_all_objects/1` now yields the scheduler thread for large\n tables that take significant time to clear. This to improve real time\n characteristics of other runnable processes.\n\n Own Id: OTP-15078\n\n- In control sequences of the functions `io:fwrite/2,3` and `io_lib:fwrite/2,3`\n containing `p` or `P`, a field width of value `0` means that no line breaks\n are inserted. This is in contrast to the old behaviour, where `0` used to\n insert line breaks after every subterm. To insert line breaks after every\n subterm, a field width of value `1` can be used.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15103 Aux Id: ERL-607","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.4.5.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-4-5-1"},{"type":"extras","doc":"- List subtraction (The `--` operator) will now yield properly on large inputs.\n\n Own Id: OTP-15371","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.4.5 - STDLIB Release Notes","ref":"notes.html#stdlib-3-4-5"},{"type":"extras","doc":"- The `Module:init/1` function in `gen_statem` may return an actions list\n containing any action, but an erroneous check only allowed state enter actions\n so e.g `{next_event,internal,event}` caused a server crash. This bug has been\n fixed.\n\n Own Id: OTP-13995","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.4.4 - STDLIB Release Notes","ref":"notes.html#stdlib-3-4-4"},{"type":"extras","doc":"- Correct `filelib:find_source()` and `filelib:find_file()` to by default also\n search one level below `src`. This is in accordance with the Design Principles\n which states that an application can have Erlang source files one level below\n the `src` directory.\n\n Own Id: OTP-14832 Aux Id: ERL-527\n\n- The contract of `erl_tar:table/2` is corrected.\n\n Own Id: OTP-14860 Aux Id: PR 1670\n\n- Correct a few contracts.\n\n Own Id: OTP-14889\n\n- Fix string:prefix/2 to handle an empty string as second argument.\n\n Own Id: OTP-14942 Aux Id: PR-1702","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.4.3 - STDLIB Release Notes","ref":"notes.html#stdlib-3-4-3"},{"type":"extras","doc":"- Make `ets:i/1` exit cleaner when ^D is input while browsing a table. Only the\n old Erlang shell is affected ([erl](`e:erts:erl_cmd.md`) flag `-oldshell`).\n\n Own Id: OTP-14663\n\n- Fixed handling of windows UNC paths in module `filename`.\n\n Own Id: OTP-14693","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Improve performance of the new string functionality when handling ASCII\n characters.\n\n Own Id: OTP-14670\n\n- Added a clarification to the documentation of `unicode:characters_to_list/2`.\n\n Own Id: OTP-14798","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.4.2 - STDLIB Release Notes","ref":"notes.html#stdlib-3-4-2"},{"type":"extras","doc":"- Fix a bug in the Erlang shell where recursively defined records with typed\n fields could cause a loop.\n\n Own Id: OTP-14488 Aux Id: PR-1489\n\n- Make edlin handle grapheme clusters instead of codepoints to improve the\n handling multi-codepoints characters.\n\n Own Id: OTP-14542\n\n- There could be false warnings for `erlang:get_stacktrace/0` being used outside\n of a `try` block when using multiple `catch` clauses.\n\n Own Id: OTP-14600 Aux Id: ERL-478","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The Erlang code linter no longer checks that the functions mentioned in\n `nowarn_deprecated_function` options are declared in the module.\n\n Own Id: OTP-14378\n\n- General Unicode improvements.\n\n Own Id: OTP-14462","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.4.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-4-1"},{"type":"extras","doc":"- A bug in `proc_lib:format()` introduced in Erlang/OTP 20.0 is corrected.\n\n Own Id: OTP-14482 Aux Id: PR-1488\n\n- Fix string:len/1 to be compatible with previous versions.\n\n Own Id: OTP-14487 Aux Id: ERIERL-40\n\n- In OTP-20.0, the behavior of c, make, and ct_make was changed so that in some\n cases the beam files by default would be written to the directory where the\n source files were found. This is now changed back to the old behavior so beam\n files are by default written to current directory.\n\n Own Id: OTP-14489 Aux Id: ERL-438","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.4 - STDLIB Release Notes","ref":"notes.html#stdlib-3-4"},{"type":"extras","doc":"- For many releases, it has been legal to override a BIF with a local function\n having the same name. However, calling a local function with the same name as\n guard BIF as filter in a list comprehension was not allowed.\n\n Own Id: OTP-13690\n\n- A new (default) pseudo-random number generator algorithm Xoroshiro116+ has\n been implemented in the `rand` module.\n\n The old algorithm implementations had a number of flaws so they are all\n deprecated, but corrected versions of two of them have been added. See the\n documentation.\n\n Own Id: OTP-14295 Aux Id: PR-1372\n\n- The Erlang shell, `qlc:string_to_handle()`, and the Debugger (the Evaluator\n area and Edit variable window of the Bindings area) can parse pids, ports,\n references, and external funs, as long as they can be created in the running\n system.\n\n Own Id: OTP-14296\n\n- Internal code change: Calls to `catch` followed by a call to\n `erlang:get_stacktrace/0` has been rewritten to use `try` instead of `catch`\n to make the code future-proof.\n\n Own Id: OTP-14400\n\n- The `ms_transform` module, used by `ets:fun2ms/1` and `dbg:fun2ms/1`,\n evaluates constant arithmetic expressions. This is necessary since the Erlang\n compiler, which normally evaluates constant expressions, does not recognize\n the format generated by `ms_transform`.\n\n Own Id: OTP-14454 Aux Id: ERIERL-29\n\n- The state machine engine `gen_statem` can now handle generic time-outs\n (multiple named) as well as absolute time-out time. See the documentation.\n\n The `gen_statem` callback `Module:init/1` has become mandatory to harmonize\n with other `gen_*` modules. This may be an incompatibility for `gen_statem`\n callback modules that use `gen_statem:enter_loop/4-6`.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-14531","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Improved unicode support for strings. Added normalization functions in the\n `unicode` module. Extended the `string` module API with new functions with\n improved unicode handling and that works on grapheme clusters. The new\n functions operates on the [`unicode:chardata()`](`t:unicode:chardata/0`) type,\n thus they also accept `UTF-8 binaries` as input.\n\n The old string API have been marked as obsolete. The return values have been\n changed for some error cases.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-10289 Aux Id: OTP-10309\n\n- There are two new guard BIFs '[`floor/1`](`floor/1`)' and\n '[`ceil/1`](`ceil/1`)'. They both return integers. In the '`math`' module,\n there are two new BIFs with the same names that return floating point values.\n\n Own Id: OTP-13692\n\n- Making code_change, terminate and handle_info callbacks optional in the OTP\n behaviours.\n\n Own Id: OTP-13801\n\n- The support for Dets files created with Erlang/OTP R7 and earlier is removed.\n\n Own Id: OTP-13830\n\n- Replaced usage of deprecated symbolic [`time unit`](`t:erlang:time_unit/0`)\n representations.\n\n Own Id: OTP-13831 Aux Id: OTP-13735\n\n- The function `fmod/2` has been added to the `math` module.\n\n Own Id: OTP-14000\n\n- The EXIT signals received from processes using `proc_lib` now looks like EXIT\n signals from processes that were spawned using `spawn_link`. In particular,\n that means that the stack trace is now included in the EXIT signal so that it\n can see where the process crashed.\n\n Own Id: OTP-14001\n\n- `sets:add_element/2` is faster when adding an element that is already present,\n and `sets:del_element/2` is faster when the element to be deleted is not\n present. This optimization can make certain operations, such as sets:union/2\n with many overlapping elements, up to two orders of magnitude faster.\n\n Own Id: OTP-14035\n\n- Add information in doc about supervisor shutdown reason when maximum restart\n frequency is reached.\n\n Own Id: OTP-14037 Aux Id: PR-1233\n\n- Added `rand:jump/[0|1]` functions.\n\n Own Id: OTP-14038 Aux Id: PR-1235\n\n- Functions for detecting changed code has been added. `code:modified_modules/0`\n returns all currently loaded modules that have changed on disk.\n `code:module_status/1` returns the status for a module. In the shell and in\n `c` module, `mm/0` is short for `code:modified_modules/0`, and `lm/0` reloads\n all currently loaded modules that have changed on disk.\n\n Own Id: OTP-14059\n\n- Each assert macro in `assert.hrl` now has a corresponding version with an\n extra argument, for adding comments to assertions. These can for example be\n printed as part of error reports, to clarify the meaning of the check that\n failed.\n\n Own Id: OTP-14066\n\n- `error_logger_tty_h` and `error_logger_file_h` now inserts the node\n information for nonlocal messages before the message itself instead of after,\n both for readability and so as not to change the line termination property at\n the end of the message.\n\n Own Id: OTP-14068\n\n- The Erlang code linter checks for badly formed type constraints.\n\n Own Id: OTP-14070 Aux Id: PR-1214\n\n- By default, there will now be a warning when `export_all` is used. The warning\n can be disabled using `nowarn_export_all`.\n\n Own Id: OTP-14071\n\n- When a `gen_server` process crashes, the stacktrace for the client will be\n printed to facilitate debugging.\n\n Own Id: OTP-14089\n\n- Optimized ETS operations by changing table identifier type from integer to\n reference. The reference enables a more direct mapping to the table with less\n potential lock contention and makes especially creation and deletion of tables\n scale much better.\n\n The change of the opaque type for the ETS table identifiers may cause failure\n in code that make faulty assumptions about this opaque type.\n\n > #### Note {: .info }\n >\n > The number of tables stored at one Erlang node _used_ to be limited. This is\n > no longer the case (except by memory usage). The previous default limit was\n > about 1400 tables and could be increased by setting the environment variable\n > `ERL_MAX_ETS_TABLES` before starting the Erlang runtime system. This hard\n > limit has been removed, but it is currently useful to set the\n > `ERL_MAX_ETS_TABLES` anyway. It should be set to an approximate of the\n > maximum amount of tables used. This since an internal table for named tables\n > is sized using this value. If large amounts of named tables are used and\n > `ERL_MAX_ETS_TABLES` hasn't been increased, the performance of named table\n > lookup will degrade.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-14094\n\n- `take/2` has been added to `dict`, `orddict`, and `gb_trees`. `take_any/2` has\n been added to `gb_trees`.\n\n Own Id: OTP-14102\n\n- Extend gen_event API to handle options as well.\n\n Own Id: OTP-14123\n\n- Advice on how to tune the supervisor restart frequency (intensity and period)\n is added to System Documentation - Design Principles - Supervisor Behaviour.\n\n Own Id: OTP-14168 Aux Id: PR-1289\n\n- gen_fsm is deprecated and is replaced by gen_statem, however for backwards\n compatibility reasons gen_fsm may continue to exist as an undocumented feature\n for quite some time.\n\n Own Id: OTP-14183\n\n- The shell functions `c/1` and `c/2` have been extended so that if the argument\n is a module name instead of a file name, it automatically locates the .beam\n file and the corresponding source file, and then recompiles the module using\n the same compiler options (plus any options passed to c/2). If compilation\n fails, the old beam file is preserved. Also adds `c(Mod, Opts, Filter)`, where\n the Filter argument allows you to remove old compiler options before the new\n options are added.\n\n New utility functions `file_find/2/3` and `find_source/1/2/3` have been added\n to `filelib`.\n\n Own Id: OTP-14190\n\n- `erl_tar` in previous versions of OTP only supports the USTAR format. That\n limited path names to at most 255 bytes, and did not support Unicode\n characters in names in a portable way.\n\n `erl_tar` now has support for reading tar archives in the formats currently in\n common use, such as v7, STAR, USTAR, PAX, and GNU tar's extensions to the\n STAR/USTAR format. When writing tar archives, `erl_tar` can now write them in\n the `PAX` format if necessary (for example, to support very long filenames or\n filenames with Unicode characters). If possible, `erl_tar` will still write\n tar archives in the USTAR for maximum portability.\n\n Own Id: OTP-14226\n\n- `base64:mime_decode/1` has been optimized so that it is now almost as fast\n as`base64:decode/1`; it used be noticeably slower.\n\n Own Id: OTP-14245\n\n- `erl_tar` will now strip any leading '`/`' from pathnames when extracting\n files from a tar archive and write a message to the error logger. There is\n also new check for directory traversal attacks; if a relative path points\n above the current working directory the extraction will be aborted.\n\n Own Id: OTP-14278\n\n- Miscellaneous updates due to atoms containing arbitrary Unicode characters.\n\n Own Id: OTP-14285\n\n- The Crypto application now supports generation of cryptographically strong\n random numbers (floats < 1.0 and integer arbitrary ranges) as a plugin to the\n 'rand' module.\n\n Own Id: OTP-14317 Aux Id: PR-1372\n\n- Add new function `ets:select_replace/2` which performs atomic\n \"compare-and-swap\" operations for ETS objects using match specifications.\n\n Own Id: OTP-14319 Aux Id: PR-1076\n\n- The Erlang code linter checks for bad `dialyzer` attributes. It also checks\n for bad type variables in type declarations.\n\n Own Id: OTP-14323\n\n- Two new functions has been implemented in the `rand` module; `normal/2` and\n `normal_s/3`, that both produce normal distribution (pseudo) random numbers\n with mean value and variance according to arguments.\n\n Own Id: OTP-14328 Aux Id: PR-1382\n\n- Upgraded the OTP internal PCRE library from version 8.33 to version 8.40. This\n library is used for implementation of the `m:re` regular expressions module.\n\n Besides various bug fixes, the new version allows for better stack protection.\n In order to utilize this feature, the stack size of normal scheduler threads\n is now by default set to 128 kilo words on all platforms. The stack size of\n normal scheduler threads can be set upon system start by passing the\n [`+sss`](`e:erts:erl_cmd.md#sched_thread_stack_size`) command line argument to\n the [`erl`](`e:erts:erl_cmd.md`) command.\n\n See\n [http://pcre.org/original/changelog.txt](http://pcre.org/original/changelog.txt)\n for information about changes made to PCRE between the versions 8.33 and 8.40.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-14331 Aux Id: ERL-208\n\n- Added function `re:version/0` which returns information about the OTP internal\n PCRE version used for implementation of the `re` module.\n\n Own Id: OTP-14347 Aux Id: PR-1412\n\n- The format of debug information that is stored in BEAM files (when\n `debug_info` is used) has been changed. The purpose of the change is to better\n support other BEAM-based languages such as Elixir or LFE.\n\n All tools included in OTP (dialyzer, debugger, cover, and so on) will handle\n both the new format and the previous format. Tools that retrieve the debug\n information using `beam_lib:chunk(Beam, [abstract_code])` will continue to\n work with both the new and old format. Tools that call\n `beam_lib:chunk(Beam, [\"Abst\"])` will not work with the new format.\n\n For more information, see the description of `debug_info` in the documentation\n for `beam_lib` and the description of the `{debug_info,{Backend,Data}}` option\n in the documentation for `compile`.\n\n Own Id: OTP-14369 Aux Id: PR-1367\n\n- Add option hibernate_after to gen_server, gen_statem and gen_event. Also added\n to the deprecated gen_fsm behaviour.\n\n Own Id: OTP-14405\n\n- The size of crash reports created by `gen_server`, `gen_statem` and `proc_lib`\n is limited with aid of the Kernel application variable\n `error_logger_format_depth`. The purpose is to limit the size of the messages\n sent to the `error_logger` process when processes with huge message queues or\n states crash.\n\n The crash report generated by `proc_lib` includes the new tag\n `message_queue_len`. The neighbour report also includes the new tag\n `current_stacktrace`. Finally, the neighbour report no longer includes the\n tags `messages` and `dictionary`.\n\n The new function `error_logger:get_format_depth/0` can be used to retrieve the\n value of the Kernel application variable `error_logger_format_depth`.\n\n Own Id: OTP-14417","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.3 - STDLIB Release Notes","ref":"notes.html#stdlib-3-3"},{"type":"extras","doc":"- An escript with only two lines would not work.\n\n Own Id: OTP-14098\n\n- Characters (`$char`) can be used in constant pattern expressions. They can\n also be used in types and contracts.\n\n Own Id: OTP-14103 Aux Id: ERL-313\n\n- The signatures of `erl_parse:anno_to_term/1` and `erl_parse:anno_from_term/1`\n are corrected. Using these functions no longer results in false Dialyzer\n warnings.\n\n Own Id: OTP-14131\n\n- Pretty-printing of maps is improved.\n\n Own Id: OTP-14175 Aux Id: seq13277\n\n- If any of the following functions in the `zip` module crashed, a file would be\n left open: `extract()`, `unzip()`, `create()`, or `zip()`. This has been\n corrected.\n\n A `zip` file having a \"Unix header\" could not be unpacked.\n\n Own Id: OTP-14189 Aux Id: ERL-348, ERL-349\n\n- Improve the Erlang shell's tab-completion of long names.\n\n Own Id: OTP-14200 Aux Id: ERL-352\n\n- The reference manual for `sys` had some faulty information about the\n 'get_modules' message used by processes where modules change dynamically\n during runtime. The documentation is now corrected.\n\n Own Id: OTP-14248 Aux Id: ERL-367","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Bug fixes, new features and improvements to gen_statem:\n\n A new type init_result/1 has replaced the old init_result/0, so if you used\n that old type (that was never documented) you have to change your code, which\n may be regarded as a potential incompatibility.\n\n Changing callback modes after code change did not work since the new callback\n mode was not recorded. This bug has been fixed.\n\n The event types state_timeout and \\{call,From\\} could not be generated with a\n \\{next_event,EventType,EventContent\\} action since they did not pass the\n runtime type check. This bug has now been corrected.\n\n State entry calls can now be repeated using (new) state callback returns\n \\{repeat*state,...\\}, \\{repeat_state_and_data,*\\} and repeat_state_and_data.\n\n There have been lots of code cleanup in particular regarding timer handling.\n For example is async cancel_timer now used. Error handling has also been\n cleaned up.\n\n To align with probable future changes to the rest of gen\\_\\*, terminate/3 has\n now got a fallback and code_change/4 is not mandatory.\n\n Own Id: OTP-14114\n\n- `filename:safe_relative_path/1` to sanitize a relative path has been added.\n\n Own Id: OTP-14215","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.2 - STDLIB Release Notes","ref":"notes.html#stdlib-3-2"},{"type":"extras","doc":"- When a simple_one_for_one supervisor is shutting down, and a child exits with\n an exit reason of the form \\{shutdown, Term\\}, an error report was earlier\n printed. This is now corrected.\n\n Own Id: OTP-13907 Aux Id: PR-1158, ERL-163\n\n- Allow empty list as parameter of the fun used with `dbg:fun2ms/1`.\n\n Own Id: OTP-13974","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The new behaviour gen_statem has been improved with 3 new features: the\n possibility to use old style non-proxy timeouts for gen_statem:call/2,3, state\n entry code, and state timeouts. These are backwards compatible. Minor code and\n documentation improvements has been performed including a borderline semantics\n correction of timeout zero handling.\n\n Own Id: OTP-13929 Aux Id: PR-1170, ERL-284","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-1"},{"type":"extras","doc":"- The `zip:unzip/1,2` and `zip:extract/1,2` functions have been updated to\n handle directory traversal exploits. Any element in the zip file that contains\n a path that points to a directory above the top level working directory,\n `cwd`, will instead be extracted in `cwd`. An error message is printed for any\n such element in the zip file during the unzip operation. The `keep_old_files`\n option determines if a file will overwrite a previous file with the same name\n within the zip file.\n\n Own Id: OTP-13633\n\n- Correct the contracts for `ets:match_object/1,3`.\n\n Own Id: OTP-13721 Aux Id: PR-1113\n\n- Errors in type specification and Emacs template generation for\n `gen_statem:code_change/4` has been fixed from bugs.erlang.org's Jira cases\n ERL-172 and ERL-187.\n\n Own Id: OTP-13746 Aux Id: ERL-172, ERL-187","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- gen_statem has been changed to set the callback mode for a server to what\n Module:callback_mode/0 returns. This facilitates e.g code downgrade since the\n callback mode now becomes a property of the currently active code, not of the\n server process.\n\n Exception handling from Module:init/1 has also been improved.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-13752","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.0.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-0-1"},{"type":"extras","doc":"- Correct a bug regarding typed records in the Erlang shell. The bug was\n introduced in OTP-19.0.\n\n Own Id: OTP-13719 Aux Id: ERL-182","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.0 - STDLIB Release Notes","ref":"notes.html#stdlib-3-0"},{"type":"extras","doc":"- Fix a race bug affecting `dets:open_file/2`.\n\n Own Id: OTP-13260 Aux Id: seq13002\n\n- Don't search for non-existing Map keys twice\n\n For `maps:get/2,3` and `maps:find/2`, searching for an immediate key, e.g. an\n atom, in a small map, the search was performed twice if the key did not exist.\n\n Own Id: OTP-13459\n\n- Avoid stray corner-case math errors on Solaris, e.g. an error is thrown on\n underflows in exp() and pow() when it shouldn't be.\n\n Own Id: OTP-13531\n\n- Fix linting of map key variables\n\n Map keys cannot be unbound and then used in parallel matching.\n\n Example: `#{ K := V } = #{ k := K } = M.` This is illegal if `'K'` is not\n bound.\n\n Own Id: OTP-13534 Aux Id: ERL-135\n\n- Fixed a bug in re on openbsd where sometimes re:run would return an incorrect\n result.\n\n Own Id: OTP-13602\n\n- To avoid potential timer bottleneck on supervisor restart, timer server is no\n longer used when the supervisor is unable to restart a child.\n\n Own Id: OTP-13618 Aux Id: PR-1001\n\n- The Erlang code preprocessor (`epp`) can handle file names spanning over many\n tokens. Example: `-include(\"a\" \"file\" \"name\").`.\n\n Own Id: OTP-13662 Aux Id: seq13136","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The types of The Abstract Format in the `erl_parse` module have been refined.\n\n Own Id: OTP-10292\n\n- Undocumented syntax for function specifications,\n `-spec F/A :: Domain -> Range`, has been removed (without deprecation).\n\n Using the `is_subtype(V, T)` syntax for constraints (in function\n specifications) is no longer documented, and the newer syntax `V :: T` should\n be used instead. The Erlang Parser still recognizes the `is_subtype` syntax,\n and will continue to do so for some time.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-11879\n\n- The '`random`' module has been deprecated. Use the '`rand`' module instead.\n\n Own Id: OTP-12502 Aux Id: OTP-12501\n\n- Background: In record fields with a type declaration but without an\n initializer, the Erlang parser inserted automatically the singleton type\n `'undefined'` to the list of declared types, if that value was not present\n there. That is, the record declaration:\n\n \\-record(rec, \\{f1 :: float(), f2 = 42 :: integer(), f3 ::\n some_mod:some_typ()\\}).\n\n was translated by the parser to:\n\n \\-record(rec, \\{f1 :: float() | 'undefined', f2 = 42 :: integer(), f3 ::\n some_mod:some_typ() | 'undefined'\\}).\n\n The rationale for this was that creation of a \"dummy\" `#rec{}` record should\n not result in a warning from dialyzer that, for example, the implicit\n initialization of the `#rec.f1` field violates its type declaration.\n\n Problems: This seemingly innocent action has some unforeseen consequences.\n\n For starters, there is no way for programmers to declare that e.g. only floats\n make sense for the `f1` field of `#rec{}` records when there is no \"obvious\"\n default initializer for this field. (This also affects tools like PropEr that\n use these declarations produced by the Erlang parser to generate random\n instances of records for testing purposes.)\n\n It also means that dialyzer does not warn if e.g. an\n [`is_atom/1`](`is_atom/1`) test or something more exotic like an\n [`atom_to_list/1`](`atom_to_list/1`) call is performed on the value of the\n `f1` field.\n\n Similarly, there is no way to extend dialyzer to warn if it finds record\n constructions where `f1` is not initialized to some float.\n\n Last but not least, it is semantically problematic when the type of the field\n is an opaque type: creating a union of an opaque and a structured type is very\n problematic for analysis because it fundamentally breaks the opacity of the\n term at that point.\n\n Change: To solve these problems the parser will not automatically insert the\n `'undefined'` value anymore; instead the user has the option to choose the\n places where this value makes sense (for the field) and where it does not and\n insert the `| 'undefined'` there manually.\n\n Consequences of this change: This change means that dialyzer will issue a\n warning for all places where records with uninitialized fields are created and\n those fields have a declared type that is incompatible with `'undefined'`\n (e.g. `t:float/0`). This warning can be suppressed easily by adding\n `| 'undefined'` to the type of this field. This also adds documentation that\n the user really intends to create records where this field is uninitialized.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-12719\n\n- Remove deprecated functions in the modules `erl_scan` and `erl_parse`.\n\n Own Id: OTP-12861\n\n- The pre-processor can now expand the ?FUNCTION_NAME and ?FUNCTION_ARITY\n macros.\n\n Own Id: OTP-13059\n\n- A new behaviour `gen_statem` has been implemented. It has been thoroughly\n reviewed, is stable enough to be used by at least two heavy OTP applications,\n and is here to stay. But depending on user feedback, we do not expect but\n might find it necessary to make minor not backwards compatible changes into\n OTP-20.0, so its state can be designated as \"not quite experimental\"...\n\n The `gen_statem` behaviour is intended to replace `gen_fsm` for new code. It\n has the same features and add some really useful:\n\n - State code is gathered\n - The state can be any term\n - Events can be postponed\n - Events can be self generated\n - A reply can be sent from a later state\n - There can be multiple sys traceable replies\n\n The callback model(s) for `gen_statem` differs from the one for `gen_fsm`, but\n it is still fairly easy to rewrite from `gen_fsm` to `gen_statem`.\n\n Own Id: OTP-13065 Aux Id: PR-960\n\n- Optimize binary:split/2 and binary:split/3 with native BIF implementation.\n\n Own Id: OTP-13082\n\n- Background: The types of record fields have since R12B been put in a separate\n form by `epp:parse_file()`, leaving the record declaration form untyped. The\n separate form, however, does not follow the syntax of type declarations, and\n parse transforms inspecting `-type()` attributes need to know about the\n special syntax. Since the compiler stores the return value of\n `epp:parse_file()` as debug information in the abstract code chunk (`\"Abst\"`\n or `abstract_code`), tools too need to know about the special syntax, if they\n inspect `-type()` attributes in abstract code.\n\n Change: No separate type form is created by `epp:parse_file()`, but the type\n information is kept in the record fields. This means that all parse transforms\n and all tools inspecting `-record()` declarations need to recognize\n `{typed_record_field, Field, Type}`.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-13148\n\n- Unsized fields of the type `bytes` in binary generators are now forbidden.\n (The other ways of writing unsized fields, such as `binary`, are already\n forbidden.)\n\n Own Id: OTP-13152\n\n- The type `t:map/0` is built-in, and cannot be redefined.\n\n Own Id: OTP-13153\n\n- Let `dets:open_file()` exit with a `badarg` message if given a raw file name\n (a binary).\n\n Own Id: OTP-13229 Aux Id: ERL-55\n\n- Add `filename:basedir/2,3`\n\n basedir returns suitable path(s) for 'user_cache', 'user_config', 'user_data',\n 'user_log', 'site_config' and 'site_data'. On linux and linux like systems the\n paths will respect the XDG environment variables.\n\n Own Id: OTP-13392\n\n- There are new preprocessor directives `-error(Term)` and `-warning(Term)` to\n cause a compilation error or a compilation warning, respectively.\n\n Own Id: OTP-13476\n\n- Optimize `'++'` operator and `lists:append/2` by using a single pass to build\n a new list while checking for properness.\n\n Own Id: OTP-13487\n\n- Add `maps:update_with/3,4` and `maps:take/2`\n\n Own Id: OTP-13522 Aux Id: PR-1025\n\n- `lists:join/2` has been added. Similar to `string:join/2` but works with\n arbitrary lists.\n\n Own Id: OTP-13523\n\n- Obfuscate asserts to make Dialyzer shut up.\n\n Own Id: OTP-13524 Aux Id: PR-1002\n\n- Supervisors now explicitly add their callback module in the return from\n sys:get_status/1,2. This is to simplify custom supervisor implementations. The\n Misc part of the return value from sys:get_status/1,2 for a supervisor is now:\n\n \\[\\{data, [\\{\"State\", State\\}]\\},\\{supervisor,\\[\\{\"Callback\",Module\\}]\\}]\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-13619 Aux Id: PR-1000\n\n- Relax translation of initial calls in `proc_lib`, i.e. remove the restriction\n to only do the translation for `gen_server` and `gen_fsm`. This enables user\n defined `gen` based generic callback modules to be displayed nicely in `c:i()`\n and observer.\n\n Own Id: OTP-13623\n\n- The function `queue:lait/1` (misspelling of `liat/1`) is now deprecated.\n\n Own Id: OTP-13658","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 2.8.0.1 - STDLIB Release Notes","ref":"notes.html#stdlib-2-8-0-1"},{"type":"extras","doc":"- List subtraction (The `--` operator) will now yield properly on large inputs.\n\n Own Id: OTP-15371","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 2.8 - STDLIB Release Notes","ref":"notes.html#stdlib-2-8"},{"type":"extras","doc":"- Fix evaluation in matching of bound map key variables in the interpreter.\n\n Prior to this patch, the following code would not evaluate:\n `X = key,(fun(#{X := value}) -> true end)(#{X => value})`\n\n Own Id: OTP-13218\n\n- Fix `erl_eval` not using non-local function handler.\n\n Own Id: OTP-13228 Aux Id: ERL-32\n\n- The Erlang Code Linter no longer crashes if there is a `-deprecated()`\n attribute but no `-module()` declaration.\n\n Own Id: OTP-13230 Aux Id: ERL-62\n\n- The timestamp in the result returned by `dets:info(Tab, safe_fixed)` was\n unintentionally broken as a result of the time API rewrites in OTP 18.0. This\n has now been fixed.\n\n Own Id: OTP-13239 Aux Id: OTP-11997\n\n- A rare race condition in `beam_lib` when using encrypted abstract format has\n been eliminated.\n\n Own Id: OTP-13278\n\n- Improved maps:with/2 and maps:without/2 algorithms\n\n The new implementation speeds up the execution significantly for all sizes of\n input.\n\n Own Id: OTP-13376","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Time warp safety improvements.\n\n Introduced the options `monotonic_timestamp`, and `strict_monotonic_timestamp`\n to the trace, sequential trace, and system profile functionality. This since\n the already existing `timestamp` option is not time warp safe.\n\n Introduced the option `safe_fixed_monotonic_time` to `ets:info/2` and\n `dets:info/2`. This since the already existing `safe_fixed` option is not time\n warp safe.\n\n Own Id: OTP-13222 Aux Id: OTP-11997\n\n- In the shell Ctrl+W (delete word) will no longer consider \".\" as being part of\n a word.\n\n Own Id: OTP-13281","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 2.7 - STDLIB Release Notes","ref":"notes.html#stdlib-2-7"},{"type":"extras","doc":"- The Erlang Pretty Printer uses `::` for function type constraints.\n\n A bug concerning pretty printing of annotated type union elements in map pair\n types has been fixed.\n\n Some minor issues regarding the documentation of types and specs have been\n corrected.\n\n Own Id: OTP-13084\n\n- The shell command `rp` prints strings as lists of integers if pretty printing\n of lists is set to `false`.\n\n Own Id: OTP-13145\n\n- The shell would crash if a bit syntax expression with conflicting types were\n given (e.g. if a field type was given as '`integer-binary`'). (Thanks to\n Aleksei Magusev for reporting this bug.)\n\n Own Id: OTP-13157\n\n- The `rand:export_seed/0` would never return '`undefined`' even if no seed has\n previously been created. Fixed to return '`undefined`' if there is no seed in\n the process dictionary.\n\n Own Id: OTP-13162","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add support for the Delete, Home and End keys in the Erlang shell.\n\n Own Id: OTP-13032\n\n- `beam_lib:all_chunks/1` and `beam_lib:build_module/1` have been documented.\n\n Own Id: OTP-13063","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 2.6 - STDLIB Release Notes","ref":"notes.html#stdlib-2-6"},{"type":"extras","doc":"- In OTP 18.0, `qlc` does not handle syntax errors well. This bug has been\n fixed.\n\n Own Id: OTP-12946\n\n- Optimize zip:unzip/2 when uncompressing to memory.\n\n Own Id: OTP-12950\n\n- The STDLIB reference manual is updated to show correct information about the\n return value of `gen_fsm:reply/2`.\n\n Own Id: OTP-12973\n\n- re:split2,3 and re:replace/3,4 now correctly handles pre-compiled patterns\n that have been compiled using the '`unicode`' option.\n\n Own Id: OTP-12977\n\n- Export `shell:catch_exception/1` as documented.\n\n Own Id: OTP-12990","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- A mechanism for limiting the amount of text that the built-in error logger\n events will produce has been introduced. It is useful for limiting both the\n size of log files and the CPU time used to produce them.\n\n This mechanism is experimental in the sense that it may be changed if it turns\n out that it does not solve the problem it is supposed to solve. In that case,\n there may be backward incompatible improvements to this mechanism.\n\n See the documentation for the config parameter `error_logger_format_depth` in\n the Kernel application for information about how to turn on this feature.\n\n Own Id: OTP-12864","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 2.5 - STDLIB Release Notes","ref":"notes.html#stdlib-2-5"},{"type":"extras","doc":"- Fix handling of single dot in filename:join/2\n\n The reference manual says that filename:join(A,B) is equivalent to\n filename:join(\\[A,B]). In some rare cases this turns out not to be true. For\n example:\n\n `filename:join(\"/a/.\",\"b\") -> \"/a/./b\"` vs\n `filename:join([\"/a/.\",\"b\"]) -> \"/a/b\"`.\n\n This has been corrected. A single dot is now only kept if it occurs at the\n very beginning or the very end of the resulting path.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-12158\n\n- The undocumented option `generic_debug` for `gen_server` has been removed.\n\n Own Id: OTP-12183\n\n- erl_lint:icrt_export/4 has been rewritten to make the code really follow the\n scoping rules of Erlang, and not just in most situations by accident.\n\n Own Id: OTP-12186\n\n- Add 'trim_all' option to binary:split/3\n\n This option can be set to remove \\_ALL\\_ empty parts of the result of a call\n to binary:split/3.\n\n Own Id: OTP-12301\n\n- Correct orddict(3) regarding evaluation order of `fold()` and `t:map/0`.\n\n Own Id: OTP-12651 Aux Id: seq12832\n\n- Correct `maps` module error exceptions\n\n Bad input to maps module function will now yield the following exceptions:\n\n - \\{badmap, NotMap\\}, or\n - badarg.\n\n Own Id: OTP-12657\n\n- It is now possible to paste text in JCL mode (using Ctrl-Y) that has been\n copied in the previous shell session. Also a bug that caused the JCL mode to\n crash when pasting text has been fixed.\n\n Own Id: OTP-12673\n\n- Add `uptime()` shell command.\n\n Own Id: OTP-12752\n\n- Cache nowarn_bif_clash functions in erl_lint.\n\n This patch stores nowarn_bif_clash in the lint record. By using erlc\n +'\\{eprof,lint_module\\}' when compiling the erlang parser, we noticed the time\n spent on nowarn_function/2 reduced from 30% to 0.01%.\n\n Own Id: OTP-12754\n\n- Optimize the Erlang Code Linter by using the cached filename information.\n\n Own Id: OTP-12772\n\n- If a child of a simple_one_for_one returns ignore from its start function no\n longer store the child for any restart type. It is not possible to restart or\n delete the child because the supervisor is a simple_one_for_one.\n\n Own Id: OTP-12793\n\n- Make `ets:file2tab` preserve enabled `read_concurrency` and\n `write_concurrency` options for tables.\n\n Own Id: OTP-12814\n\n- There are many cases where user code needs to be able to distinguish between a\n socket that was closed normally and one that was aborted. Setting the option\n \\{show_econnreset, true\\} enables the user to receive ECONNRESET errors on\n both active and passive sockets.\n\n Own Id: OTP-12841","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Allow maps for supervisor flags and child specs\n\n Earlier, supervisor flags and child specs were given as tuples. While this is\n kept for backwards compatibility, it is now also allowed to give these\n parameters as maps, see [sup_flags](`m:supervisor#sup_flags`) and\n [child_spec](`m:supervisor#child_spec`).\n\n Own Id: OTP-11043\n\n- A new system message, `terminate`, is added. This can be sent with\n `sys:terminate/2,3`. If the receiving process handles system messages properly\n it will terminate shortly after receiving this message.\n\n The new function `proc_lib:stop/1,3` utilizes this new system message and\n monitors the receiving process in order to facilitate a synchronous stop\n mechanism for 'special processes'.\n\n `proc_lib:stop/1,3` is used by the following functions:\n\n - `gen_server:stop/1,3` (new)\n - `gen_fsm:stop/1,3` (new)\n - `gen_event:stop/1,3` (modified to be synchronous)\n - `wx_object:stop/1,3` (new)\n\n Own Id: OTP-11173 Aux Id: seq12353\n\n- Remove the `pg` module, which has been deprecated through OTP-17, is now\n removed from the STDLIB application. This module has been marked experimental\n for more than 15 years, and has largely been superseded by the `pg2` module\n from the Kernel application.\n\n Own Id: OTP-11907\n\n- New BIF: `erlang:get_keys/0`, lists all keys associated with the process\n dictionary. Note: `erlang:get_keys/0` is auto-imported.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-12151 Aux Id: seq12521\n\n- Add three new functions to `io_lib`\\-- `scan_format/2`, `unscan_format/1`, and\n `build_text/1`\\-- which expose the parsed form of the format control sequences\n to make it possible to easily modify or filter the input to `io_lib:format/2`.\n This can e.g. be used in order to replace unbounded-size control sequences\n like `~w` or `~p` with corresponding depth-limited `~W` and `~P` before doing\n the actual formatting.\n\n Own Id: OTP-12167\n\n- Introduce the `erl_anno` module, an abstraction of the second element of\n tokens and tuples in the abstract format.\n\n Own Id: OTP-12195\n\n- Support variables as Map keys in expressions and patterns\n\n Erlang will accept any expression as keys in Map expressions and it will\n accept literals or bound variables as keys in Map patterns.\n\n Own Id: OTP-12218\n\n- The last traces of Mnemosyne Rules have been removed.\n\n Own Id: OTP-12257\n\n- Properly support maps in match_specs\n\n Own Id: OTP-12270\n\n- New function `ets:take/2`. Works the same as `ets:delete/2` but also returns\n the deleted object(s).\n\n Own Id: OTP-12309\n\n- `string:tokens/2` is somewhat faster, especially if the list of separators\n only contains one separator character.\n\n Own Id: OTP-12422 Aux Id: seq12774\n\n- The documentation of the Abstract Format (in the ERTS User's Guide) has been\n updated with types and specification. (Thanks to Anthony Ramine.)\n\n The explicit representation of parentheses used in types of the abstract\n format has been removed. Instead the new functions\n `erl_parse:type_inop_prec()` and `erl_parse:type_preop_prec()` can be used for\n inserting parentheses where needed.\n\n Own Id: OTP-12492\n\n- Prevent zip:zip_open/\\[12] from leaking file descriptors if parent process\n dies.\n\n Own Id: OTP-12566\n\n- Add a new random number generator, see `rand` module. It have better\n characteristics and an improved interface.\n\n Own Id: OTP-12586 Aux Id: OTP-12501, OTP-12502\n\n- `filename:split/1` when given an empty binary will now return an empty list,\n to make it consistent with return value when given an empty list.\n\n Own Id: OTP-12716\n\n- Add `sync` option to `ets:tab2file/3`.\n\n Own Id: OTP-12737 Aux Id: seq12805\n\n- Add functions `gb_sets:iterator_from()` and `gb_trees:iterator_from()`.\n (Thanks to Kirill Kinduk.)\n\n Own Id: OTP-12742\n\n- Add `maps:filter/2` to maps module.\n\n Own Id: OTP-12745\n\n- Change some internal data structures to Maps in order to speed up compilation\n time. Measured speed up is around 10%-15%.\n\n Own Id: OTP-12774\n\n- Update `orddict` to use parameterized types and specs. (Thanks to UENISHI\n Kota.)\n\n Own Id: OTP-12785\n\n- The assert macros in `eunit` has been moved out to\n `stdlib/include/assert.hrl`. This files get included by `eunit.hrl`. Thus,\n nothing changes for eunit users, but the asserts can now also be included\n separately.\n\n Own Id: OTP-12808","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 2.4 - STDLIB Release Notes","ref":"notes.html#stdlib-2-4"},{"type":"extras","doc":"- Behaviour of character types \\\\d, \\\\w and \\\\s has always been to not match\n characters with value above 255, not 128, i.e. they are limited to ISO-Latin-1\n and not ASCII\n\n Own Id: OTP-12521","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- c:m/1 now displays the module's MD5 sum.\n\n Own Id: OTP-12500\n\n- Make ets:i/1 handle binary input from IO server.\n\n Own Id: OTP-12550","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 2.3 - STDLIB Release Notes","ref":"notes.html#stdlib-2-3"},{"type":"extras","doc":"- The documentation of string:tokens/2 now explicitly specifies that adjacent\n separator characters do not give any empty strings in the resulting list of\n tokens.\n\n Own Id: OTP-12036\n\n- Fix broken deprecation warnings in ssh application\n\n Own Id: OTP-12187\n\n- Maps: Properly align union typed assoc values in documentation\n\n Own Id: OTP-12190\n\n- Fix filelib:wildcard/2 when 'Cwd' ends with a dot\n\n Own Id: OTP-12212\n\n- Allow `Name/Arity` syntax in maps values inside attributes.\n\n Own Id: OTP-12213\n\n- Fix edlin to correctly save text killed with ctrl-u. Prior to this fix,\n entering text into the Erlang shell and then killing it with ctrl-u followed\n by yanking it back with ctrl-y would result in the yanked text being the\n reverse of the original killed text.\n\n Own Id: OTP-12224\n\n- If a callback function was terminated with exit/1, there would be no stack\n trace in the ERROR REPORT produced by gen_server. This has been corrected.\n\n To keep the backwards compatibility, the actual exit reason for the process is\n not changed.\n\n Own Id: OTP-12263 Aux Id: seq12733\n\n- Warnings produced by `ms_transform` could point out the wrong line number.\n\n Own Id: OTP-12264","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Supports tar file creation on other media than file systems mounted on the\n local machine.\n\n The `erl_tar` api is extended with `erl_tar:init/3` that enables usage of user\n provided media storage routines. A ssh-specific set of such routines is hidden\n in the new function `ssh_sftp:open_tar/3` to simplify creating a tar archive\n on a remote ssh server.\n\n A chunked file reading option is added to `erl_tar:add/3,4` to save memory on\n e.g small embedded systems. The size of the slices read from a file in that\n case can be specified.\n\n Own Id: OTP-12180 Aux Id: seq12715\n\n- I/O requests are optimized for long message queues in the calling process.\n\n Own Id: OTP-12315","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 2.2 - STDLIB Release Notes","ref":"notes.html#stdlib-2-2"},{"type":"extras","doc":"- The type spec of the FormFunc argument to sys:handle_debug/4 was erroneously\n pointing to dbg_fun(). This is now corrected and the new type is format_fun().\n\n Own Id: OTP-11800\n\n- Behaviors such as gen_fsm and gen_server should always invoke format_status/2\n before printing the state to the logs.\n\n Own Id: OTP-11967\n\n- The documentation of `dets:insert_new/2` has been corrected. (Thanks to Alexei\n Sholik for reporting the bug.)\n\n Own Id: OTP-12024\n\n- Printing a term with io_lib:format and control sequence w, precision P and\n field width F, where F = printed length of the term, an exception would be raised.\n\n These two problems are now corrected.\n\n Own Id: OTP-12041\n\n- The documentation of `maps:values/1` has been corrected.\n\n Own Id: OTP-12055\n\n- Expand shell functions in map expressions.\n\n Own Id: OTP-12063","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add maps:with/2\n\n Own Id: OTP-12137","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 2.1.1 - STDLIB Release Notes","ref":"notes.html#stdlib-2-1-1"},{"type":"extras","doc":"- OTP-11850 fixed filelib:wildcard/1 to work with broken symlinks. This\n correction, however, introduced problems since symlinks were no longer\n followed for functions like filelib:ensure_dir/1, filelib:is_dir/1,\n filelib:file_size/1, etc. This is now corrected.\n\n Own Id: OTP-12054 Aux Id: seq12660","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 2.1 - STDLIB Release Notes","ref":"notes.html#stdlib-2-1"},{"type":"extras","doc":"- `filelib:wildcard(\"broken_symlink\")` would return an empty list if\n \"broken_symlink\" was a symlink that did not point to an existing file.\n\n Own Id: OTP-11850 Aux Id: seq12571\n\n- `erl_tar` can now handle files names that contain Unicode characters. See\n \"UNICODE SUPPORT\" in the documentation for `erl_tar`.\n\n When creating a tar file, `erl_tar` would sometime write a too short end of\n tape marker. GNU tar would correctly extract files from such tar file, but\n would complain about \"A lone zero block at...\".\n\n Own Id: OTP-11854\n\n- When redefining and exporting the type `t:map/0` the Erlang Code Linter\n (`erl_lint`) erroneously emitted an error. This bug has been fixed.\n\n Own Id: OTP-11872\n\n- Fix evaluation of map updates in the debugger and erl_eval\n\n Reported-by: José Valim\n\n Own Id: OTP-11922","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The following native functions now bump an appropriate amount of reductions\n and yield when out of reductions:\n\n - `erlang:binary_to_list/1`\n - `erlang:binary_to_list/3`\n - `erlang:bitstring_to_list/1`\n - `erlang:list_to_binary/1`\n - `erlang:iolist_to_binary/1`\n - `erlang:list_to_bitstring/1`\n - `binary:list_to_bin/1`\n\n Characteristics impact:\n\n - **Performance** - The functions converting from lists got a performance loss\n for very small lists, and a performance gain for very large lists.\n\n - **Priority** - Previously a process executing one of these functions\n effectively got an unfair priority boost. This priority boost depended on\n the input size. The larger the input was, the larger the priority boost got.\n This unfair priority boost is now lost.\n\n Own Id: OTP-11888\n\n- Add `maps:get/3` to maps module. The function will return the supplied default\n value if the key does not exist in the map.\n\n Own Id: OTP-11951","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 2.0 - STDLIB Release Notes","ref":"notes.html#stdlib-2-0"},{"type":"extras","doc":"- The option dupnames did not work as intended in re. When looking for names\n with \\{capture, \\[Name, ...]\\}, re:run returned a random instance of the match\n for that name, instead of the leftmost matching instance, which was what the\n documentation stated. This is now corrected to adhere to the documentation.\n The option \\{capture,all_names\\} along with a re:inspect/2 function is also\n added to further help in using named subpatterns.\n\n Own Id: OTP-11205\n\n- If option 'binary' was set for standard_input, then c:i() would hang if the\n output was more than one page long - i.e. then input after \"(c)ontinue (q)uit\n -->\" could not be read. This has been corrected. (Thanks to José Valim)\n\n Own Id: OTP-11589\n\n- stdlib/lists: Add function droplast/1 This functions drops the last element of\n a non-empty list. lists:last/1 and lists:droplast/1 are the dual of hd/1 and\n tl/1 but for the end of a list. (Thanks to Hans Svensson)\n\n Own Id: OTP-11677\n\n- Allow all auto imports to be suppressed at once. Introducing the\n no_auto_import attribute: -compile(no_auto_import). Useful for code generation\n tools that always use the qualified function names and want to avoid the auto\n imported functions clashing with local ones. (Thanks to José Valim.)\n\n Own Id: OTP-11682\n\n- supervisor_bridge does no longer report normal termination of children. The\n reason is that in some cases, for instance when the restart strategy is\n simple_one_for_one, the log could be completely overloaded with reports about\n normally terminating processes. (Thanks to Artem Ocheredko)\n\n Own Id: OTP-11685\n\n- The type annotations for alternative registries using the \\{via, Module,\n Name\\} syntax for sup_name() and sup_ref() in the supervisor module are now\n consistent with the documentation. Dialyzer should no longer complain about\n valid supervisor:start_link() and supervisor:start_child() calls. (Thanks to\n Caleb Helbling.)\n\n Own Id: OTP-11707\n\n- Two Dets bugs have been fixed. When trying to open a short file that is not a\n Dets file, the file was deleted even with just read access. Calling\n `dets:is_dets_file/1` with a file that is not a Dets file, a file descriptor\n was left open. (Thanks to Håkan Mattsson for reporting the bugs.)\n\n Own Id: OTP-11709\n\n- Fix race bug in `ets:all`. Concurrent creation of tables could cause other\n tables to not be included in the result. (Thanks to Florian Schintke for bug\n report)\n\n Own Id: OTP-11726\n\n- erl_eval now properly evaluates '=='/2 when it is used in guards. (Thanks to\n José Valim)\n\n Own Id: OTP-11747\n\n- Calls to proplists:get_value/3 are replaced by the faster lists:keyfind/3 in\n io_lib_pretty. Elements in the list are always 2-tuples. (Thanks to Andrew\n Thompson)\n\n Own Id: OTP-11752\n\n- A qlc bug where filters were erroneously optimized away has been fixed. Thanks\n to Sam Bobroff for reporting the bug.\n\n Own Id: OTP-11758\n\n- A number of compiler errors where unusual or nonsensical code would crash the\n compiler have been reported by Ulf Norell and corrected by Anthony Ramine.\n\n Own Id: OTP-11770\n\n- Since Erlang/OTP R16B the Erlang Core Linter (`erl_lint`) has not emitted\n errors when built-in types were re-defined. This bug has been fixed. (Thanks\n to Roberto Aloi.)\n\n Own Id: OTP-11772\n\n- The functions `sys:get_state/1,2` and `sys:replace_state/2,3` are fixed so\n they can now be run while the process is sys suspended. To accomplish this,\n the new callbacks `Mod:system_get_state/1` and `Mod:system_replace_state/2`\n are added, which are also implemented by the generic behaviours `gen_server`,\n `gen_event` and `gen_fsm`.\n\n The potential incompatibility refers to:\n\n - The previous behaviour of intercepting the system message and passing a\n tuple of size 2 as the last argument to `sys:handle_system_msg/6` is no\n longer supported.\n - The error handling when `StateFun` in `sys:replace_state/2,3` fails is\n changed from being totally silent to possibly (if the callback module does\n not catch) throw an exception in the client process.\n\n (Thanks to James Fish and Steve Vinoski)\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-11817","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Options to set match_limit and match_limit_recursion are added to re:run. The\n option report_errors is also added to get more information when re:run fails\n due to limits or compilation errors.\n\n Own Id: OTP-10285\n\n- The pre-defined types `array/0`, `dict/0`, `digraph/0`, `gb_set/0`,\n `gb_tree/0`, `queue/0`, `set/0`, and `tid/0` have been deprecated. They will\n be removed in Erlang/OTP 18.0.\n\n Instead the types [`array:array/0`](`t:array:array/0`),\n [`dict:dict/0`](`t:dict:dict/0`), [`digraph:graph/0`](`t:digraph:graph/0`),\n `gb_set:set/0`, `gb_tree:tree/0`, [`queue:queue/0`](`t:queue:queue/0`),\n [`sets:set/0`](`t:sets:set/0`), and [`ets:tid/0`](`t:ets:tid/0`) can be used.\n (Note: it has always been necessary to use [`ets:tid/0`](`t:ets:tid/0`).)\n\n It is allowed in Erlang/OTP 17.0 to locally re-define the types `array/0`,\n `dict/0`, and so on.\n\n New types [`array:array/1`](`t:array:array/1`),\n [`dict:dict/2`](`t:dict:dict/2`), [`gb_sets:set/1`](`t:gb_sets:set/1`),\n [`gb_trees:tree/2`](`t:gb_trees:tree/2`),\n [`queue:queue/1`](`t:queue:queue/1`), and [`sets:set/1`](`t:sets:set/1`) have\n been added.\n\n A compiler option, `nowarn_deprecated_type`, has been introduced. By including\n the attribute\n\n `-compile(nowarn_deprecated_type).`\n\n in an Erlang source file, warnings about deprecated types can be avoided in\n Erlang/OTP 17.0.\n\n The option can also be given as a compiler flag:\n\n `erlc +nowarn_deprecated_type file.erl`\n\n Own Id: OTP-10342\n\n- Calls to erlang:open_port/2 with 'spawn' are updated to handle space in the\n command path.\n\n Own Id: OTP-10842\n\n- Dialyzer's `unmatched_return` warnings have been corrected.\n\n Own Id: OTP-10908\n\n- Forbid unsized fields in patterns of binary generators and simplified\n v3_core's translation of bit string generators. (Thanks to Anthony Ramine.)\n\n Own Id: OTP-11186\n\n- The version of the PCRE library Used by Erlang's re module is raised to 8.33\n from 7.6. This means, among other things, better Unicode and Unicode Character\n Properties support. New options connected to PCRE 8.33 are also added to the\n re module (ucd, notempty_atstart, no_start_optimize). PCRE has extended the\n regular expression syntax between 7.6 and 8.33, why this imposes a potential\n incompatibility. Only very complicated regular expressions may be affected,\n but if you know you are using obscure features, please test run your regular\n expressions and verify that their behavior has not changed.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-11204\n\n- Added dict:is_empty/1 and orddict:is_empty/1. (Thanks to Magnus Henoch.)\n\n Own Id: OTP-11353\n\n- A call to either the [`garbage_collect/1`](`garbage_collect/1`) BIF or the\n [`check_process_code/2`](`check_process_code/2`) BIF may trigger garbage\n collection of another processes than the process calling the BIF. The previous\n implementations performed these kinds of garbage collections without\n considering the internal state of the process being garbage collected. In\n order to be able to more easily and more efficiently implement yielding native\n code, these types of garbage collections have been rewritten. A garbage\n collection like this is now triggered by an asynchronous request signal, the\n actual garbage collection is performed by the process being garbage collected\n itself, and finalized by a reply signal to the process issuing the request.\n Using this approach processes can disable garbage collection and yield without\n having to set up the heap in a state that can be garbage collected.\n\n The [`garbage_collect/2`](`erlang:garbage_collect/2`), and\n [`check_process_code/3`](`erlang:check_process_code/3`) BIFs have been\n introduced. Both taking an option list as last argument. Using these, one can\n issue asynchronous requests.\n\n `code:purge/1` and `code:soft_purge/1` have been rewritten to utilize\n asynchronous `check_process_code` requests in order to parallelize work.\n\n Characteristics impact: A call to the\n [`garbage_collect/1`](`garbage_collect/1`) BIF or the\n [`check_process_code/2`](`check_process_code/2`) BIF will normally take longer\n time to complete while the system as a whole wont be as much negatively\n effected by the operation as before. A call to `code:purge/1` and\n `code:soft_purge/1` may complete faster or slower depending on the state of\n the system while the system as a whole wont be as much negatively effected by\n the operation as before.\n\n Own Id: OTP-11388 Aux Id: OTP-11535, OTP-11648\n\n- Improve the documentation of the supervisor's `via` reference. (Thanks to\n MaximMinin.)\n\n Own Id: OTP-11399\n\n- `orddict:from_list/1` now uses the optimized sort routines in the `lists`\n module instead of (essentially) an insertion sort. Depending on the input\n data, the speed of the new `from_list/1` is anything from slightly faster up\n to several orders of magnitude faster than the old `from_list/1`.\n\n (Thanks to Steve Vinoski.)\n\n Own Id: OTP-11552\n\n- EEP43: New data type - Maps\n\n With Maps you may for instance:\n\n - \\_\\_\\_\\_ - `M0 = #{ a => 1, b => 2}, % create associations`\n\n - \\_\\_\\_\\_ - `M1 = M0#{ a := 10 }, % update values`\n\n - \\_\\_\\_\\_ - `M2 = M1#{ \"hi\" => \"hello\"}, % add new associations`\n\n - \\_\\_\\_\\_ - `#{ \"hi\" := V1, a := V2, b := V3} = M2. % match keys with values`\n\n For information on how to use Maps please see Map Expressions in the\n [Reference Manual](`e:system:expressions.md#map-expressions`).\n\n The current implementation is without the following features:\n\n - \\_\\_\\_\\_ - No variable keys\n\n - \\_\\_\\_\\_ - No single value access\n\n - \\_\\_\\_\\_ - No map comprehensions\n\n Note that Maps is _experimental_ during OTP 17.0.\n\n Own Id: OTP-11616\n\n- When tab completing the erlang shell now expands zero-arity functions all the\n way to closing parenthesis, unless there is another function with the same\n name and a different arity. (Thanks to Pierre Fenoll.)\n\n Own Id: OTP-11684\n\n- The Erlang Code Preprocessor (`epp`) could loop when encountering a circular\n macro definition in an included file. This bug has been fixed.\n\n Thanks to Maruthavanan Subbarayan for reporting the bug, and to Richard\n Carlsson for providing a bug fix.\n\n Own Id: OTP-11728\n\n- The Erlang Code Linter (`erl_lint`) has since Erlang/OTP R13B emitted warnings\n whenever any of the types `t:arity/0`, `t:bitstring/0`, `t:iodata/0`, or\n `t:boolean/0` were re-defined. Now errors are emitted instead.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-11771\n\n- The `encoding` option of `erl_parse:abstract/2` has been extended to include\n `none` and a callback function (a predicate).\n\n Own Id: OTP-11807\n\n- Export zip option types to allow referal from other modules.\n\n Thanks to Pierre Fenoll and Håkan Mattson\n\n Own Id: OTP-11828\n\n- The module `pg` has been deprecated and will be removed in Erlang/OTP 18.\n\n Own Id: OTP-11840","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.19.4 - STDLIB Release Notes","ref":"notes.html#stdlib-1-19-4"},{"type":"extras","doc":"- Fix typo in gen_server.erl. Thanks to Brian L. Troutwine.\n\n Own Id: OTP-11398\n\n- Spec for atan2 should be atan2(Y, X), not atan2(X, Y). Thanks to Ary\n Borenszweig.\n\n Own Id: OTP-11465","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add XML marker for regexp syntax. Thanks to Håkan Mattson.\n\n Own Id: OTP-11442","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.19.3 - STDLIB Release Notes","ref":"notes.html#stdlib-1-19-3"},{"type":"extras","doc":"- The functions `dets:foldl/3`, `dets:foldr/3`, and `dets:traverse/2` did not\n release the table after having traversed the table to the end. The bug was\n introduced in R16B. (Thanks to Manuel Duran Aguete.)\n\n Own Id: OTP-11245\n\n- If the `fun M:F/A` construct was used erroneously the linter could crash.\n (Thanks to Mikhail Sobolev.)\n\n Own Id: OTP-11254\n\n- The specifications of `io_lib:fread/2,3` have been corrected. (Thanks to Chris\n King and Kostis Sagonas for pinpointing the bug.)\n\n Own Id: OTP-11261","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Fixed type typo in gen_server.\n\n Own Id: OTP-11200\n\n- Update type specs in filelib and io_prompt. Thanks to Jose Valim.\n\n Own Id: OTP-11208\n\n- Fix typo in abcast() function comment. Thanks to Johannes Weissl.\n\n Own Id: OTP-11219\n\n- Make edlin understand a few important control keys. Thanks to Stefan\n Zegenhagen.\n\n Own Id: OTP-11251\n\n- Export the edge/0 type from the digraph module. Thanks to Alex Ronne Petersen.\n\n Own Id: OTP-11266\n\n- Fix variable usage tracking in erl_lint and fixed unsafe variable tracking in\n try expressions. Thanks to Anthony Ramine.\n\n Own Id: OTP-11268","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.19.2 - STDLIB Release Notes","ref":"notes.html#stdlib-1-19-2"},{"type":"extras","doc":"- The Erlang scanner no longer accepts floating point numbers in the input\n string.\n\n Own Id: OTP-10990\n\n- When converting a faulty binary to a list with unicode:characters_to_list, the\n error return value could contain a faulty \"rest\", i.e. the io_list of\n characters that could not be converted was wrong. This happened only if input\n was a sub binary and conversion was from utf8. This is now corrected.\n\n Own Id: OTP-11080\n\n- The type `hook_function()` has been corrected in `erl_pp`, the Erlang Pretty\n Printer.\n\n The printing of invalid forms, e.g. record field types, has also been fixed.\n It has been broken since R16B.\n\n (Thanks to Tomáš Janoušek.)\n\n Own Id: OTP-11100\n\n- Fix receive support in erl_eval with a BEAM module. Thanks to Anthony Ramine.\n\n Own Id: OTP-11137","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Delete obsolete note about simple-one-for-one supervisor. Thanks to Magnus\n Henoch.\n\n Own Id: OTP-10938\n\n- When selecting encoding of a script written in Erlang (`escript`) the optional\n directive on the second line is now recognized.\n\n Own Id: OTP-10951\n\n- The function `erl_parse:abstract/2` has been documented.\n\n Own Id: OTP-10992\n\n- Integrate elliptic curve contribution from Andreas Schultz\n\n In order to be able to support elliptic curve cipher suites in SSL/TLS,\n additions to handle elliptic curve infrastructure has been added to public_key\n and crypto.\n\n This also has resulted in a rewrite of the crypto API to gain consistency and\n remove unnecessary overhead. All OTP applications using crypto has been\n updated to use the new API.\n\n Impact: Elliptic curve cryptography (ECC) offers equivalent security with\n smaller key sizes than other public key algorithms. Smaller key sizes result\n in savings for power, memory, bandwidth, and computational cost that make ECC\n especially attractive for constrained environments.\n\n Own Id: OTP-11009\n\n- Added sys:get_state/1,2 and sys:replace_state/2,3. Thanks to Steve Vinoski.\n\n Own Id: OTP-11013\n\n- Optimizations to gen mechanism. Thanks to Loïc Hoguin.\n\n Own Id: OTP-11025\n\n- Optimizations to gen.erl. Thanks to Loïc Hoguin.\n\n Own Id: OTP-11035\n\n- Use erlang:demonitor(Ref, \\[flush]) where applicable. Thanks to Loïc Hoguin.\n\n Own Id: OTP-11039\n\n- Erlang source files with non-ASCII characters are now encoded in UTF-8\n (instead of latin1).\n\n Own Id: OTP-11041 Aux Id: OTP-10907\n\n- Fix rest_for_one and one_for_all restarting a child not terminated. Thanks to\n James Fish.\n\n Own Id: OTP-11042\n\n- Fix excessive CPU consumption of timer_server. Thanks to Aliaksey\n Kandratsenka.\n\n Own Id: OTP-11053\n\n- Rename and document lists:zf/2 as lists:filtermap/2. Thanks to Anthony Ramine.\n\n Own Id: OTP-11078\n\n- Fixed an inconsistent state in epp. Thanks to Anthony Ramine\n\n Own Id: OTP-11079\n\n- c:ls(File) will now print File, similar to ls(1) in Unix. The error messages\n have also been improved. (Thanks to Bengt Kleberg.)\n\n Own Id: OTP-11108\n\n- Support callback attributes in erl_pp. Thanks to Anthony Ramine.\n\n Own Id: OTP-11140\n\n- Improve erl_lint performance. Thanks to José Valim.\n\n Own Id: OTP-11143","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.19.1 - STDLIB Release Notes","ref":"notes.html#stdlib-1-19-1"},{"type":"extras","doc":"- Bugs related to Unicode have been fixed in the `erl_eval` module.\n\n Own Id: OTP-10622 Aux Id: kunagi-351 \\[262]\n\n- `filelib:wildcard(\"some/relative/path/*.beam\", Path)` would fail to match any\n file. That is, filelib:wildcard/2 would not work if the first component of the\n pattern did not contain any wildcard characters. (A previous attempt to fix\n the problem in R15B02 seems to have made matters worse.)\n\n (Thanks to Samuel Rivas and Tuncer Ayaz.)\n\n There is also an incompatible change to the `Path` argument. It is no longer\n allowed to be a binary.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-10812","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The new STDLIB application variable `shell_strings` can be used for\n determining how the Erlang shell outputs lists of integers. The new function\n `shell:strings/1` toggles the value of the variable.\n\n The control sequence modifier `l` can be used for turning off the string\n recognition of `~p` and `~P`.\n\n Own Id: OTP-10755\n\n- Miscellaneous updates due to Unicode support.\n\n Own Id: OTP-10820\n\n- Extend `~ts` to handle binaries with characters coded in ISO-latin-1\n\n Own Id: OTP-10836\n\n- The +pc flag to erl can be used to set the range of characters considered\n printable. This affects how the shell and io:format(\"~tp\",...) functionality\n does heuristic string detection. More can be read in STDLIB users guide.\n\n Own Id: OTP-10884","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.19 - STDLIB Release Notes","ref":"notes.html#stdlib-1-19"},{"type":"extras","doc":"- Wildcards such as \"some/path/\\*\" passed to `filelib:wildcard/2` would fail to\n match any file. (Thanks to Samuel Rivas for reporting this bug.)\n\n Own Id: OTP-6874 Aux Id: kunagi-190 \\[101]\n\n- Fixed error handling in proc_lib:start which could hang if the spawned process\n died in init.\n\n Own Id: OTP-9803 Aux Id: kunagi-209 \\[120]\n\n- Allow \\*\\* in filelib:wildcard\n\n Two adjacent \\* used as a single pattern will match all files and zero or more\n directories and subdirectories. (Thanks to José Valim)\n\n Own Id: OTP-10431\n\n- Add the \\\\gN and \\\\g\\{N\\} syntax for back references in re:replace/3,4 to\n allow use with numeric replacement strings. (Thanks to Vance Shipley)\n\n Own Id: OTP-10455\n\n- Export ets:match_pattern/0 type (Thanks to Joseph Wayne Norton)\n\n Own Id: OTP-10472\n\n- Fix printing the empty binary at depth 1 with ~W (Thanks to Andrew Thompson)\n\n Own Id: OTP-10504\n\n- The type `ascii_string()` in the `base64` module has been corrected. The type\n [`file:file_info()`](`t:file:file_info/0`) has been cleaned up. The type\n [`file:fd()`](`t:file:fd/0`) has been made opaque in the documentation.\n\n Own Id: OTP-10624 Aux Id: kunagi-352 \\[263]","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Dets tables are no longer fixed while traversing with a bound key (when only\n the objects with the right key are matched). This optimization affects the\n functions `match/2`, `match_object/2`, `select/2`, `match_delete/2`, and\n `select_delete/2`.\n\n Own Id: OTP-10097\n\n- Support for Unicode has been implemented.\n\n Own Id: OTP-10302\n\n- The linter now warns for opaque types that are not exported, as well as for\n under-specified opaque types.\n\n Own Id: OTP-10436\n\n- The type [`file:name()`](`t:file:name/0`) has been substituted for the type\n [`file:filename()`](`t:file:filename/0`) in the following functions in the\n `filename` module: `absname/2`, `absname_join/2`, `join/1,2`, and `split/1`.\n\n Own Id: OTP-10474\n\n- If a child process fails in its start function, then the error reason was\n earlier only reported as an error report from the error_handler, and\n supervisor:start_link would only return `{error,shutdown}`. This has been\n changed so the supervisor will now return `{error,{shutdown,Reason}}`, where\n `Reason` identifies the failing child and its error reason. (Thanks to Tomas\n Pihl)\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-10490\n\n- Where necessary a comment stating encoding has been added to Erlang files. The\n comment is meant to be removed in Erlang/OTP R17B when UTF-8 becomes the\n default encoding.\n\n Own Id: OTP-10630\n\n- The contracts and types of the modules `erl_scan` and `sys` have been\n corrected and improved. (Thanks to Kostis Sagonas.)\n\n Own Id: OTP-10658\n\n- The Erlang shell now skips the rest of the line when it encounters an Erlang\n scanner error.\n\n Own Id: OTP-10659\n\n- Clean up some specs in the proplists module. (Thanks to Kostis Sagonas.)\n\n Own Id: OTP-10663\n\n- Some examples overflowing the width of PDF pages have been corrected.\n\n Own Id: OTP-10665\n\n- Enable escript to accept emulator arguments when script file has no shebang.\n Thanks to Magnus Henoch\n\n Own Id: OTP-10691\n\n- Fix bug in queue:out/1, queue:out_r/1 that makes it O(N^2) in worst case.\n Thanks to Aleksandr Erofeev.\n\n Own Id: OTP-10722\n\n- There are new functions in the `epp` module which read the character encoding\n from files. See `m:epp` for more information.\n\n Own Id: OTP-10742 Aux Id: OTP-10302\n\n- The functions in `io_lib` have been adjusted for Unicode. The existing\n functions `write_string()` and so on now take Unicode strings, while the old\n behavior has been taken over by new functions `write_latin1_string()` and so\n on. There are also new functions to write Unicode strings as Latin-1 strings,\n mainly targetted towards the Erlang pretty printer (`erl_pp`).\n\n Own Id: OTP-10745 Aux Id: OTP-10302\n\n- The new functions `proc_lib:format/2` and `erl_parse:abstract/2` accept an\n encoding as second argument.\n\n Own Id: OTP-10749 Aux Id: OTP-10302\n\n- Increased potential concurrency in ETS for `write_concurrency` option. The\n number of internal table locks has increased from 16 to 64. This makes it four\n times less likely that two concurrent processes writing to the same table\n would collide and thereby serialized. The cost is an increased constant memory\n footprint for tables using write_concurrency. The memory consumption per\n inserted record is not affected. The increased footprint can be particularly\n large if `write_concurrency` is combined with `read_concurrency`.\n\n Own Id: OTP-10787","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.18.3 - STDLIB Release Notes","ref":"notes.html#stdlib-1-18-3"},{"type":"extras","doc":"- Minor test updates\n\n Own Id: OTP-10591","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 1.18.2 - STDLIB Release Notes","ref":"notes.html#stdlib-1-18-2"},{"type":"extras","doc":"- Fixed bug where if given an invalid drive letter on windows ensure dir would\n go into an infinite loop.\n\n Own Id: OTP-10104\n\n- Calls to gen_server:enter_loop/4 where ServerName has a global scope and no\n timeout is given now works correctly.\n\n Thanks to Sam Bobroff for reporting the issue.\n\n Own Id: OTP-10130\n\n- fix escript/primary archive reloading\n\n If the mtime of an escript/primary archive file changes after being added to\n the code path, correctly reload the archive and update the cache. (Thanks to\n Tuncer Ayaz)\n\n Own Id: OTP-10151\n\n- Fix bug that in some cases could cause corrupted binaries in ETS tables with\n `compressed` option.\n\n Own Id: OTP-10182\n\n- Fix filename:nativename/1 on Win32\n\n Don't choke on paths given as binary argument on Win32. Thanks to Jan Klötzke\n\n Own Id: OTP-10188\n\n- Fix bug in `ets:test_ms/2` that could cause emulator crash when using `'$_'`\n in match spec.\n\n Own Id: OTP-10190\n\n- Fix bug where zip archives wrongly have a first disk number set to 1\n\n Own Id: OTP-10223","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The message printed by the Erlang shell as an explanation of the `badarith`\n error has been corrected. (Thanks to Matthias Lang.)\n\n Own Id: OTP-10054","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.18.1 - STDLIB Release Notes","ref":"notes.html#stdlib-1-18-1"},{"type":"extras","doc":"- References to `is_constant/1` (which was removed in the R12 release) has been\n removed from documentation and code.\n\n Own Id: OTP-6454 Aux Id: seq10407\n\n- Leave control back to gen_server during supervisor's restart loop\n\n When an attempt to restart a child failed, supervisor would earlier keep the\n execution flow and try to restart the child over and over again until it\n either succeeded or the restart frequency limit was reached. If none of these\n happened, supervisor would hang forever in this loop.\n\n This commit adds a timer of 0 ms where the control is left back to the\n gen_server which implements the supervisor. This way any incoming request to\n the supervisor will be handled - which could help breaking the infinite loop -\n e.g. shutdown request for the supervisor or for the problematic child.\n\n This introduces some incompatibilities in stdlib due to new return values from\n supervisor:\n\n - restart_child/2 can now return \\{error,restarting\\}\n - delete_child/2 can now return \\{error,restarting\\}\n - which_children/1 returns a list of \\{Id,Child,Type,Mods\\}, where Child, in\n addition to the old pid() or 'undefined', now also can be 'restarting'.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-9549\n\n- If a temporary child's start function returned 'ignore', then the supervisor\n would keep it's child specification. This has been corrected. Child\n specifications for non-existing temporary children shall never be kept.\n\n Own Id: OTP-9782 Aux Id: seq11964\n\n- Use universal time as base in error logger\n\n Previous conversion used the deprecated\n calendar:local_time_to_universal_time/1\n\n Own Id: OTP-9854\n\n- Calling a guard test (such as is_list/1) from the top-level in a guard, would\n cause a compiler crash if there was a local definition with the same name.\n Corrected to reject the program with an error message.\n\n Own Id: OTP-9866\n\n- Fix the type spec from the doc of binary:part/3 (Thanks to Ricardo Catalinas\n Jiménez)\n\n Own Id: OTP-9920\n\n- Correct spelling of registered (Thanks to Richard Carlsson)\n\n Own Id: OTP-9925\n\n- Put gb_trees documentation into alphabetical order (Thanks to Aidan Hobson\n Sayers)\n\n Own Id: OTP-9929\n\n- Fix bug in ETS with `compressed` option and insertion of term containing large\n integers (>2G) on 64-bit machines. Seen to cause emulator crash. (Thanks to\n Diego Llarrull for excellent bug report)\n\n Own Id: OTP-9932\n\n- Add plugin support for alternative name lookup This patch introduces a new way\n of locating a behaviour instance: \\{via, Module, Name\\}. (Thanks to Ulf Wiger)\n\n Own Id: OTP-9945\n\n- The function `digraph_utils:condensation/1` used to create a digraph\n containing loops contradicting the documentation which states that the created\n digraph is free of cycles. This bug has been fixed. (Thanks to Kostis Sagonas\n for finding the bug.)\n\n Own Id: OTP-9953\n\n- When an escript ends now all printout to standard output and standard error\n gets out on the terminal. This bug has been corrected by changing the\n behaviour of erlang:halt/0,1, which should fix the same problem for other\n escript-like applications, i.e that data stored in the output port driver\n buffers got lost when printing on a TTY and exiting through erlang:halt/0,1.\n\n The BIF:s erlang:halt/0,1 has gotten improved semantics and there is a new BIF\n erlang:halt/2 to accomplish something like the old semantics. See the\n documentation.\n\n Now erlang:halt/0 and erlang:halt/1 with an integer argument will close all\n ports and allow all pending async threads operations to finish before exiting\n the emulator. Previously erlang:halt/0 and erlang:halt(0) would just wait for\n pending async threads operations but not close ports. And erlang:halt/1 with a\n non-zero integer argument would not even wait for pending async threads\n operations.\n\n To roughly the old behaviour, to not wait for ports and async threads\n operations when you exit the emulator, you use erlang:halt/2 with an integer\n first argument and an option list containing \\{flush,false\\} as the second\n argument. Note that now is flushing not dependant of the exit code, and you\n cannot only flush async threads operations which we deemed as a strange\n behaviour anyway.\n\n Also, erlang:halt/1,2 has gotten a new feature: If the first argument is the\n atom 'abort' the emulator is aborted producing a core dump, if the operating\n system so allows.\n\n Own Id: OTP-9985\n\n- Add escript win32 alternative invocation. escript can now be started as both\n \"escript.exe\" and \"escript\" (Thanks to Pierre Rouleau)\n\n Own Id: OTP-9997","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 1.18 - STDLIB Release Notes","ref":"notes.html#stdlib-1-18"},{"type":"extras","doc":"- Improved algorithm in module `random`. Avoid seed values that are even\n divisors of the primes and by that prevent getting sub-seeds that are stuck on\n zero. Worst case was random:seed(0,0,0) that produced a series of only zeros.\n This is an incompatible change in the sense that applications that relies on\n reproducing a specific series for a given seed will fail. The pseudo random\n output is still deterministic but different compared to earlier versions.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8713\n\n- Calls to `global:whereis_name/1` have been substituted for calls to\n `global:safe_whereis_name/1` since the latter is not safe at all.\n\n The reason for not doing this earlier is that setting a global lock masked out\n a bug concerning the restart of supervised children. The bug has now been\n fixed by a modification of `global:whereis_name/1`. (Thanks to Ulf Wiger for\n code contribution.)\n\n A minor race conditions in `gen_fsm:start*` has been fixed: if one of these\n functions returned `{error, Reason}` or ignore, the name could still be\n registered (either locally or in `global`. (This is the same modification as\n was done for gen_server in OTP-7669.)\n\n The undocumented function `global:safe_whereis_name/1` has been removed.\n\n Own Id: OTP-9212 Aux Id: seq7117, OTP-4174\n\n- If a child of a supervisor terminates with reason \\{shutdown,Term\\} it is now\n handled by the supervisor as if the reason was 'shutdown'.\n\n For children with restart type 'permanent', this implies no change. For\n children with restart type 'transient', the child will no longer be restarted\n and no supervisor report will be written. For children with restart type\n 'temporary', no supervisor report will be written.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-9222\n\n- Minor improvement of documentation regarding supervisor restart strategy for\n temporary and transient child processes.\n\n Own Id: OTP-9381\n\n- A Dets table with sufficiently large buckets could not always be repaired.\n This bug has been fixed.\n\n The format of Dets files has been modified. When downgrading tables created\n with the new system will be repaired. Otherwise the modification should not be\n noticeable.\n\n Own Id: OTP-9607\n\n- A few contracts in the `lists` module have been corrected.\n\n Own Id: OTP-9616\n\n- Add '-callback' attributes in stdlib's behaviours\n\n Replace the behaviour_info(callbacks) export in stdlib's behaviours with\n -callback' attributes for all the callbacks. Update the documentation with\n information on the callback attribute Automatically generate 'behaviour_info'\n function from '-callback' attributes\n\n 'behaviour_info(callbacks)' is a special function that is defined in a module\n which describes a behaviour and returns a list of its callbacks.\n\n This function is now automatically generated using the '-callback' specs. An\n error is returned by lint if user defines both '-callback' attributes and the\n behaviour_info/1 function. If no type info is needed for a callback use a\n generic spec for it. Add '-callback' attribute to language syntax\n\n Behaviours may define specs for their callbacks using the familiar spec\n syntax, replacing the '-spec' keyword with '-callback'. Simple lint checks are\n performed to ensure that no callbacks are defined twice and all types referred\n are declared.\n\n These attributes can be then used by tools to provide documentation to the\n behaviour or find discrepancies in the callback definitions in the callback\n module.\n\n Add callback specs into 'application' module in kernel Add callback specs to\n tftp module following internet documentation Add callback specs to\n inets_service module following possibly deprecated comments\n\n Own Id: OTP-9621\n\n- If a Dets table had been properly closed but the space management data could\n not been read, it was not possible to repair the file. This bug has been\n fixed.\n\n Own Id: OTP-9622\n\n- The Unicode noncharacter code points 16#FFFE and 16#FFFE were not allowed to\n be encoded or decoded using the `unicode` module or bit syntax. That was\n inconsistent with the other noncharacters 16#FDD0 to 16#FDEF that could be\n encoded/decoded. To resolve the inconsistency, 16#FFFE and 16#FFFE can now be\n encoded and decoded. (Thanks to Alisdair Sullivan.)\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-9624\n\n- Make epp search directory of current file first when including another file\n This completes a partial fix in R11 that only worked for include_lib().\n (Thanks to Richard Carlsson)\n\n Own Id: OTP-9645\n\n- ms_transform: Fix incorrect \\`variable shadowed' warnings\n\n This patch removes incorrect passing of variable bindings from one function\n clause to another. (Thanks to Haitao Li)\n\n Own Id: OTP-9646\n\n- Explicitly kill dynamic children in supervisors\n\n According to the supervisor's documentation: \"Important note on\n simple-one-for-one supervisors: The dynamically created child processes of a\n simple-one-for-one supervisor are not explicitly killed, regardless of\n shutdown strategy, but are expected to terminate when the supervisor does\n (that is, when an exit signal from the parent process is received).\"\n\n All is fine as long as we stop simple_one_for_one supervisor manually. Dynamic\n children catch the exit signal from the supervisor and leave. But, if this\n happens when we stop an application, after the top supervisor has stopped, the\n application master kills all remaining processes associated to this\n application. So, dynamic children that trap exit signals can be killed during\n their cleanup (here we mean inside terminate/2). This is unpredictable and\n highly time-dependent.\n\n In this commit, supervisor module is patched to explicitly terminate dynamic\n children accordingly to the shutdown strategy.\n\n NOTE: Order in which dynamic children are stopped is not defined. In fact,\n this is \"almost\" done at the same time.\n\n Stack errors when dynamic children are stopped\n\n Because a simple_one_for_one supervisor can have many workers, we stack errors\n during its shutdown to report only one message for each encountered error\n type. Instead of reporting the child's pid, we use the number of concerned\n children. (Thanks to Christopher Faulet)\n\n Own Id: OTP-9647\n\n- Allow an infinite timeout to shutdown worker processes\n\n Now, in child specification, the shutdown value can also be set to infinity\n for worker children. This restriction was removed because this is not always\n possible to predict the shutdown time for a worker. This is highly\n application-dependent. Add a warning to docs about workers' shutdown strategy\n (Thanks to Christopher Faulet)\n\n Own Id: OTP-9648\n\n- A badarg would sometimes occur in supervisor when printing error reports and\n the child pid was undefined. This has been corrected.\n\n Own Id: OTP-9669\n\n- Fix re:split spec not to accept option 'global'(Thanks to Shunichi Shinohara)\n\n Own Id: OTP-9691","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Fix a few tests that used to fail on the HiPE platform.\n\n Own Id: OTP-9637\n\n- Variables are now now allowed in '`fun M:F/A`' as suggested by Richard O'Keefe\n in EEP-23.\n\n The representation of '`fun M:F/A`' in the abstract format has been changed in\n an incompatible way. Tools that directly read or manipulate the abstract\n format (such as parse transforms) may need to be updated. The compiler can\n handle both the new and the old format (i.e. extracting the abstract format\n from a pre-R15 BEAM file and compiling it using compile:forms/1,2 will work).\n The `syntax_tools` application can also handle both formats.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-9643\n\n- Tuple funs (a two-element tuple with a module name and a function) are now\n officially deprecated and will be removed in R16. Use '`fun M:F/A`' instead.\n To make you aware that your system uses tuple funs, the very first time a\n tuple fun is applied, a warning will be sent to the error logger.\n\n Own Id: OTP-9649\n\n- The deprecated '`regexp`' module has been removed. Use the '`re`' module\n instead.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-9737\n\n- `filename:find_src/1,2` will now work on stripped BEAM files (reported by Per\n Hedeland). The HiPE compiler will also work on stripped BEAM files. The BEAM\n compiler will no longer include compilation options given in the source code\n itself in `M:module_info(compile)` (because those options will be applied\n anyway if the module is re-compiled).\n\n Own Id: OTP-9752","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.17.5 - STDLIB Release Notes","ref":"notes.html#stdlib-1-17-5"},{"type":"extras","doc":"- erl_tar:extract failed when executed inside a directory with some parent\n directory to which the user has no read access. This has been corrected.\n\n Own Id: OTP-9368\n\n- A bug in `erl_scan:set_attribute/3` has been fixed.\n\n Own Id: OTP-9412\n\n- The contract of `io_lib:fread()` has been corrected.\n\n Own Id: OTP-9413 Aux Id: seq11873\n\n- A crash in io*lib:fread/2 when end of input data was encountered while trying\n to match literal characters, which should return \\{more,*,_,_\\} but instead\n crashed, has been corrected. Reported by Klas Johansson.\n\n A similar peculiarity for io:fread when encountering end of file before any\n field data has also been corrected.\n\n Own Id: OTP-9439\n\n- The contract of `timer:now_diff()` has been corrected. (Thanks to Alex\n Morarash).\n\n Own Id: OTP-9450\n\n- Fix minor typo in gen_fsm documentation (Thanks to Haitao Li)\n\n Own Id: OTP-9456\n\n- The contracts of `zip:zip_list_dir/1` and `zip:zip_get/2` have been corrected.\n\n Own Id: OTP-9471 Aux Id: seq11887, OTP-9472\n\n- A bug in `zip:zip_open()` has been fixed.\n\n Own Id: OTP-9472 Aux Id: seq11887, OTP-9471\n\n- Fix trivial documentation errors(Thanks to Matthias Lang)\n\n Own Id: OTP-9498\n\n- Add a proplist() type\n\n Recently I was adding specs to an API and found that there is no canonical\n proplist() type defined. (Thanks to Ryan Zezeski)\n\n Own Id: OTP-9499\n\n- fix supervisors restarting temporary children\n\n In the current implementation of supervisors, temporary children should never\n be restarted. However, when a temporary child is restarted as part of a\n one_for_all or rest_for_one strategy where the failing process is not the\n temporary child, the supervisor still tries to restart it.\n\n Because the supervisor doesn't keep some of the MFA information of temporary\n children, this causes the supervisor to hit its restart limit and crash.\n\n This patch fixes the behaviour by inserting a clause in terminate_children/2-3\n (private function) that will omit temporary children when building a list of\n killed processes, to avoid having the supervisor trying to restart them again.\n\n Only supervisors in need of restarting children used the list, so the change\n should be of no impact for the functions that called terminate_children/2-3\n only to kill all children.\n\n The documentation has been modified to make this behaviour more explicit.\n (Thanks to Fred Hebert)\n\n Own Id: OTP-9502\n\n- fix broken edoc annotations (Thanks to Richard Carlsson)\n\n Own Id: OTP-9516\n\n- XML files have been corrected.\n\n Own Id: OTP-9550 Aux Id: OTP-9541\n\n- Handle rare race in the crypto key server functionality\n\n Own Id: OTP-9586","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Types and specifications have been added.\n\n Own Id: OTP-9356\n\n- The contracts of the `queue` module have been modified.\n\n Own Id: OTP-9418\n\n- Contracts in STDLIB and Kernel have been improved and type errors have been\n corrected.\n\n Own Id: OTP-9485\n\n- Types for several BIFs have been extended/corrected. Also the types for types\n for `lists:keyfind/3`, `lists:keysearch/3`, and `lists:keyemember/3` have been\n corrected. The incorrect/incomplete types could cause false dialyzer warnings.\n\n Own Id: OTP-9496","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.17.4 - STDLIB Release Notes","ref":"notes.html#stdlib-1-17-4"},{"type":"extras","doc":"- The default value `undefined` was added to records field types in such a way\n that the result was not always a well-formed type. This bug has been fixed.\n\n Own Id: OTP-9147\n\n- Update index file atomically\n\n Since the log_mf_h index file might be read by other processes than the error\n handler (e.g. by the rb tool), this file should be updated atomically. This\n will avoid hitting the time gap between opening the file in write mode (and\n thus emptying the file) and the actual update with the new contents. To do\n this, a temporary file is written, and the file:rename/1 used to replace the\n real index file.\n\n Own Id: OTP-9148\n\n- Fixed various typos across the documentation (Thanks to Tuncer Ayaz)\n\n Own Id: OTP-9154\n\n- Supervisors should not save child-specs for temporary processes when they\n terminate as they should not be restarted. Saving the temporary child spec\n will result in that you cannot start a new temporary process with the same\n child spec as an already terminated temporary process. Since R14B02 you cannot\n restart a temporary temporary process as arguments are no longer saved, it has\n however always been semantically incorrect to restart a temporary process.\n Thanks to Filipe David Manana for reporting this and suggesting a solution.\n\n Own Id: OTP-9167 Aux Id: OTP-9064\n\n- Various small documentation fixes (Thanks to Bernard Duggan)\n\n Own Id: OTP-9172\n\n- Fix format_status bug for unregistered gen_event processes\n\n Port the gen_fsm code for format_status to gen_event in order to prevent a\n lists:concat(\\[...,pid()]) crash when calling sys:get_status/1 on an\n unregistered gen_event process.\n\n Refactor format*status header code from gen*\\* behaviours to module gen.\n\n Extend the format_status tests in gen_event_SUITE to cover format_status bugs\n with anonymous gen_event processes. (Thanks To Geoff Cant)\n\n Own Id: OTP-9218\n\n- List of pids changed to 'set' in supervisor for dynamic temporary children.\n Accessing the list would not scale well when adding/deleting many children.\n (Thanks to Evgeniy Khramtsov)\n\n Own Id: OTP-9242\n\n- Change pool module to attempt to attach to nodes that are already running\n\n The pool module prints out an error message and takes no further action for\n nodes that are already running. This patch changes that behavior so that if\n the return from slave:start/3 is \\{already_running, Node\\} then an attempt to\n attach to the node is still made. This makes sense because the node has been\n specified by the user in the .hosts.erlang file indicating a wish for the node\n to be part of the pool and a manual attach can be successfully made after the\n pool is started.(Thanks to Kelly McLaughlin)\n\n Own Id: OTP-9244\n\n- unicode: document 16#FFFE and 16#FFFF (non chars)(Thanks to Tuncer Ayaz)\n\n Own Id: OTP-9256\n\n- re: remove gratuitous \"it \" in manpage (Thanks to Tuncer Ayaz)\n\n Own Id: OTP-9307\n\n- A bug in erl_eval(3) has been fixed.\n\n Own Id: OTP-9322","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add `timer:tc/1` and remove the catch in `tc/2` and `tc/3`. The time measuring\n functions will thus no longer trap exits, errors or throws caused by the\n measured function.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-9169\n\n- Allow supervisor:terminate_child(SupRef,Pid) for simple_one_for_one\n supervisors\n\n supervisor:terminate_child/2 was earlier not allowed if the supervisor used\n restart strategy simple_one_for_one. This is now changed so that children of\n this type of supervisors can be terminated by specifying the child's Pid.\n\n (Thanks to Vance Shipley.)\n\n Own Id: OTP-9201\n\n- Types and specifications have been added.\n\n Own Id: OTP-9267\n\n- Erlang types and specifications are used for documentation.\n\n Own Id: OTP-9271\n\n- Allow Dets tablenames to be arbitrary terms.\n\n Own Id: OTP-9282\n\n- A specification that could cause problems for Dialyzer has been fixed. An\n opaque type in erl_eval has been turned in to a ordinary type. This is a\n temporary fix.\n\n Own Id: OTP-9333","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.17.3 - STDLIB Release Notes","ref":"notes.html#stdlib-1-17-3"},{"type":"extras","doc":"- Two bugs in io:format for ~F.~Ps has been corrected. When length(S) >=\n abs(F) > P, the precision P was incorrectly ignored. When F == P > length(S)\n the result was incorrectly left adjusted. Bug found by Ali Yakout who also\n provided a fix.\n\n Own Id: OTP-8989 Aux Id: seq11741\n\n- Fix exception generation in the io module\n\n Some functions did not generate correct badarg exception on a badarg\n exception.\n\n Own Id: OTP-9045\n\n- Fixes to the dict and orddict module documentation\n\n Fixed grammar and one inconsistency (Key - Value instead of key/value, since\n everywhere else the former is used). (thanks to Filipe David Manana)\n\n Own Id: OTP-9083\n\n- Add ISO week number calculation functions to the calendar module in stdlib\n\n This new feature adds the missing week number function to the calendar module\n of the stdlib application. The implementation conforms to the ISO 8601\n standard. The new feature has been implemented tested and documented (thanks\n to Imre Horvath).\n\n Own Id: OTP-9087","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Implement the 'MAY' clauses from RFC4648 regarding the pad character to make\n mime_decode() and mime_decode_to_string() functions more tolerant of badly\n padded base64. The RFC is quoted below for easy reference.\n\n \"RFC4648 Section 3.3 with reference to MIME decoding: Furthermore, such\n specifications MAY ignore the pad character, \"=\", treating it as non-alphabet\n data, if it is present before the end of the encoded data. If more than the\n allowed number of pad characters is found at the end of the string (e.g., a\n base 64 string terminated with \"===\"), the excess pad characters MAY also be\n ignored.\"\n\n Own Id: OTP-9020\n\n- Supervisors will no longer save start parameters for temporary processes as\n they will not be restarted. In the case of simple_one_for_one workers such as\n ssl-connection processes this will substantial reduce the memory footprint of\n the supervisor.\n\n Own Id: OTP-9064\n\n- When running escript it is now possible to add the -n flag and the escript\n will be compiled using +native.\n\n Own Id: OTP-9076","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.17.2.1 - STDLIB Release Notes","ref":"notes.html#stdlib-1-17-2-1"},{"type":"extras","doc":"- Several type specifications for standard libraries were wrong in the R14B01\n release. This is now corrected. The corrections concern types in\n re,io,filename and the module erlang itself.\n\n Own Id: OTP-9008","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 1.17.2 - STDLIB Release Notes","ref":"notes.html#stdlib-1-17-2"},{"type":"extras","doc":"- When several clients accessed a Dets table simultaneously, one of them calling\n `dets:insert_new/2`, the Dets server could crash. Alternatively, under the\n same conditions, `ok` was sometimes returned instead of `true`. (Thanks to\n John Hughes.)\n\n Own Id: OTP-8856\n\n- When several clients accessed a Dets table simultaneously, inserted or updated\n objects were sometimes lost due to the Dets file being truncated. (Thanks to\n John Hughes.)\n\n Own Id: OTP-8898\n\n- When several clients accessed a Dets table simultaneously, modifications of\n the Dets server's internal state were sometimes thrown away. The symptoms are\n diverse: error with reason `bad_object`; inserted objects not returned by\n `lookup()`; et cetera. (Thanks to John Hughes.)\n\n Own Id: OTP-8899\n\n- If a Dets table was closed after calling `bchunk/2`, `match/1,3`,\n `match_object/1,3`, or `select/1,3` and then opened again, a subsequent call\n using the returned continuation would normally return a reply. This bug has\n fixed; now the call fails with reason `badarg`.\n\n Own Id: OTP-8903\n\n- Cover did not collect coverage data for files such as Yecc parses containing\n include directives. The bug has been fixed by modifying `epp`, the Erlang Code\n Preprocessor.\n\n Own Id: OTP-8911\n\n- If a Dets table with fewer slots than keys was opened and then closed after\n just a lookup, the contents were no longer well-formed. This bug has been\n fixed. (Thanks to Matthew Evans.)\n\n Own Id: OTP-8923\n\n- In a supervisor, when it terminates a child, if that child happens to have\n exited fractionally early, with normal, the supervisor reports this as an\n error. This should not be reported as an error.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8938 Aux Id: seq11615","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The documentation filelib:wildcard/1,2 now describes the character set syntax\n for wildcards.\n\n Own Id: OTP-8879 Aux Id: seq11683\n\n- Buffer overflows have been prevented in `erlc`, `dialyzer`, `typer`,\n `run_test`, `heart`, `escript`, and `erlexec`.\n\n (Thanks to Michael Santos.)\n\n Own Id: OTP-8892\n\n- Using a float for the number of copies for `string:copies/2` resulted in an\n infinite loop. Now it will fail with an exception instead. (Thanks to Michael\n Santos.)\n\n Own Id: OTP-8915\n\n- New ETS option `compressed`, to enable a more compact storage format at the\n expence of heavier table operations. For test and evaluation, `erl +ec` can be\n used to force compression on all ETS tables.\n\n Own Id: OTP-8922 Aux Id: seq11658\n\n- The default maximum number of slots of a Dets table has been changed as to be\n equal to the maximum number of slots. (Thanks to Richard Carlsson.)\n\n Own Id: OTP-8959","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.17.1 - STDLIB Release Notes","ref":"notes.html#stdlib-1-17-1"},{"type":"extras","doc":"- reference() has been substituted for ref() in the documentation.\n\n Own Id: OTP-8733","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The ms_transform now warns if the fun head shadows surrounding variables (just\n like the warnings you would get for an ordinary fun in the same context).\n\n Own Id: OTP-6759\n\n- ets:select_reverse/\\{1,2,3\\} are now documented.\n\n Own Id: OTP-7863\n\n- Large parts of the `ethread` library have been rewritten. The `ethread`\n library is an Erlang runtime system internal, portable thread library used by\n the runtime system itself.\n\n Most notable improvement is a reader optimized rwlock implementation which\n dramatically improve the performance of read-lock/read-unlock operations on\n multi processor systems by avoiding ping-ponging of the rwlock cache lines.\n The reader optimized rwlock implementation is used by miscellaneous rwlocks in\n the runtime system that are known to be read-locked frequently, and can be\n enabled on ETS tables by passing the\n [\\{read_concurrency, true\\}](`m:ets#new_2_read_concurrency`) option upon table\n creation. See the documentation of `ets:new/2` for more information. The\n reader optimized rwlock implementation can be fine tuned when starting the\n runtime system. For more information, see the documentation of the\n [\\+rg](`e:erts:erl_cmd.md#%2Brg`) command line argument of `erl`.\n\n There is also a new implementation of rwlocks that is not optimized for\n readers. Both implementations interleaves readers and writers during\n contention as opposed to, e.g., the NPTL (Linux) pthread rwlock implementation\n which use either a reader or writer preferred strategy. The reader/writer\n preferred strategy is problematic since it starves threads doing the\n non-preferred operation.\n\n The new rwlock implementations in general performs better in ERTS than common\n pthread implementations. However, in some extremely heavily contended cases\n this is not the case. Such heavy contention can more or less only appear on\n ETS tables. This when multiple processes do very large amounts of write locked\n operations simultaneously on the same table. Such use of ETS is bad regardless\n of rwlock implementation, will never scale, and is something we strongly\n advise against.\n\n The new rwlock implementations depend on atomic operations. If no native\n atomic implementation is found, a fallback solution will be used. Using the\n fallback implies a performance degradation. That is, it is more important now\n than before to build OTP with a native atomic implementation.\n\n The `ethread` library contains native atomic implementations for, x86 (32 and\n 64 bit), powerpc (32 bit), sparc V9 (32 and 64 bit), and tilera (32 bit). On\n other hardware gcc's builtin support for atomic memory access will be used if\n such exists. If no such support is found, `configure` will warn about no\n atomic implementation available.\n\n The `ethread` library can now also use the `libatomic_ops` library for atomic\n memory accesses. This makes it possible for the Erlang runtime system to\n utilize optimized native atomic operations on more platforms than before. If\n `configure` warns about no atomic implementation available, try using the\n `libatomic_ops` library. Use the\n [\\--with-libatomic_ops=PATH](`e:system:install.md#advanced-configuration-and-build-of-erlang-otp`)\n `configure` command line argument when specifying where the `libatomic_ops`\n installation is located. The `libatomic_ops` library can be downloaded from:\n [http://www.hpl.hp.com/research/linux/atomic_ops/](http://www.hpl.hp.com/research/linux/atomic_ops/)\n\n The changed API of the `ethread` library has also caused modifications in the\n Erlang runtime system. Preparations for the to come \"delayed deallocation\"\n feature has also been done since it depends on the `ethread` library.\n\n _Note_: When building for x86, the `ethread` library will now use instructions\n that first appeared on the pentium 4 processor. If you want the runtime system\n to be compatible with older processors (back to 486) you need to pass the\n [\\--enable-ethread-pre-pentium4-compatibility](`e:system:install.md#advanced-configuration-and-build-of-erlang-otp`)\n `configure` command line argument when configuring the system.\n\n Own Id: OTP-8544\n\n- Some Built In Functions (BIFs) from the module erlang was never made\n autoimported for backward compatibility reasons. As local functions now\n override autoimports, new autoimports is no longer a problem, why the\n following BIFs are finally made autoimported: monitor/2, monitor/3,\n demonitor/2, demonitor/3, error/1, error/2, integer_to_list/2,\n list_to_integer/2.\n\n Own Id: OTP-8763","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.17 - STDLIB Release Notes","ref":"notes.html#stdlib-1-17"},{"type":"extras","doc":"- The Erlang code preprocessor (`epp`) sent extra messages on the form\n `{eof,Location}` to the client when parsing the `file` attribute. This bug,\n introduced in R11B, has been fixed.\n\n Own Id: OTP-8470\n\n- The abstract type 'fun' could not be printed by the Erlang pretty printer\n (`erl_pp`). This bug has been fixed.\n\n Own Id: OTP-8473\n\n- The function `erl_scan:reserved_word/1` no longer returns `true` when given\n the word `spec`. This bug was introduced in STDLIB-1.15.3 (R12B-3).\n\n Own Id: OTP-8567\n\n- The documentation of `lists:keysort/2` states that the sort is stable.\n\n Own Id: OTP-8628 Aux Id: seq11576\n\n- The shell's line editing has been improved to more resemble the behaviour of\n readline and other shells. (Thanks to Dave Peticolas)\n\n Own Id: OTP-8635\n\n- The Erlang code preprocessor (`epp`) did not correctly handle premature\n end-of-input when defining macros. This bug, introduced in STDLIB 1.16, has\n been fixed.\n\n Own Id: OTP-8665 Aux Id: OTP-7810","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The module binary from EEP31 (and EEP9) is implemented.\n\n Own Id: OTP-8217\n\n- The erlang pretty printer (`erl_pp`) no longer quotes atoms in types.\n\n Own Id: OTP-8501\n\n- The Erlang code preprocessor (`epp`) now considers records with no fields as\n typed.\n\n Own Id: OTP-8503\n\n- Added function `zip:foldl/3` to iterate over zip archives.\n\n Added functions to create and extract escripts. See `escript:create/2` and\n `escript:extract/2`.\n\n The undocumented function `escript:foldl/3` has been removed. The same\n functionality can be achieved with the more flexible functions\n `escript:extract/2` and `zip:foldl/3`.\n\n Record fields has been annotated with type info. Source files as been adapted\n to fit within 80 chars and trailing whitespace has been removed.\n\n Own Id: OTP-8521\n\n- The Erlang parser no longer duplicates the singleton type `undefined` in the\n type of record fields without initial value.\n\n Own Id: OTP-8522\n\n- A regular expression with many levels of parenthesis could cause a buffer\n overflow. That has been corrected. (Thanks to Michael Santos.)\n\n Own Id: OTP-8539\n\n- When defining macros the closing right parenthesis before the dot is now\n mandatory.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8562\n\n- Some properties of a compiled re pattern are defined to allow for guard tests.\n\n Own Id: OTP-8577\n\n- Local and imported functions now override the auto-imported BIFs when the\n names clash. The pre R14 behaviour was that auto-imported BIFs would override\n local functions. To avoid that old programs change behaviour, the following\n will generate an error:\n\n - Doing a call without explicit module name to a local function having a name\n clashing with the name of an auto-imported BIF that was present (and\n auto-imported) before OTP R14A\n - Explicitly importing a function having a name clashing with the name of an\n autoimported BIF that was present (and autoimported) before OTP R14A\n - Using any form of the old compiler directive `nowarn_bif_clash`\n\n If the BIF was added or auto-imported in OTP R14A or later, overriding it with\n an import or a local function will only result in a warning,\n\n To resolve clashes, you can either use the explicit module name `erlang` to\n call the BIF, or you can remove the auto-import of that specific BIF by using\n the new compiler directive `-compile({no_auto_import,[F/A]}).`, which makes\n all calls to the local or imported function without explicit module name pass\n without warnings or errors.\n\n The change makes it possible to add auto-imported BIFs without breaking or\n silently changing old code in the future. However some current code\n ingeniously utilizing the old behaviour or the `nowarn_bif_clash` compiler\n directive, might need changing to be accepted by the compiler.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8579\n\n- The undocumented, unsupport, and deprecated function `lists:flat_length/1` has\n been removed.\n\n Own Id: OTP-8584\n\n- A bug in re that could cause certain regular expression matches never to\n terminate is corrected. (Thanks to Michael Santos and Gordon Guthrie.)\n\n Own Id: OTP-8589\n\n- Nested records can now be accessed without parenthesis. See the Reference\n Manual for examples. (Thanks to YAMASHINA Hio and Tuncer Ayaz.)\n\n Own Id: OTP-8597\n\n- `receive` statements that can only read out a newly created reference are now\n specially optimized so that it will execute in constant time regardless of the\n number of messages in the receive queue for the process. That optimization\n will benefit calls to `gen_server:call()`. (See `gen:do_call/4` for an example\n of a receive statement that will be optimized.)\n\n Own Id: OTP-8623\n\n- The beam_lib:cmp/2 function now compares BEAM files in stricter way. The BEAM\n files will be considered different if there are any changes except in the\n compilation information (\"CInf\") chunk. beam_lib:cmp/2 used to ignore\n differences in the debug information (significant for Dialyzer) and other\n chunks that did not directly change the run-time behavior.\n\n Own Id: OTP-8625\n\n- When a gen_server, gen_fsm process, or gen_event terminates abnormally,\n sometimes the text representation of the process state can occupy many lines\n of the error log, depending on the definition of the state term. A mechanism\n to trim out parts of the state from the log has been added (using a\n format_status/2 callback). See the documentation.\n\n Own Id: OTP-8630\n\n- Calling `sys:get_status()` for processes that have globally registered names\n that were not atoms would cause a crash. Corrected. (Thanks to Steve Vinoski.)\n\n Own Id: OTP-8656\n\n- The Erlang scanner has been augmented with two new tokens: `..` and `...`.\n\n Own Id: OTP-8657\n\n- Expressions evaluating to integers can now be used in types and function\n specifications where hitherto only integers were allowed (\"Erlang_Integer\").\n\n Own Id: OTP-8664\n\n- The compiler optimizes record operations better.\n\n Own Id: OTP-8668\n\n- The recently added BIFs erlang:min/2, erlang:max/2 and erlang:port_command/3\n are now auto-imported (as they were originally intended to be). Due to the\n recent compiler change (OTP-8579), the only impact on old code defining it's\n own min/2, max/2 or port_command/3 functions will be a warning, the local\n functions will still be used. The warning can be removed by using\n -compile(\\{no_auto_import,\\[min/2,max/2,port_command/3]\\}). in the source\n file.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8669 Aux Id: OTP-8579\n\n- Now, binary_to_term/2 is auto-imported. This will cause a compile warning if\n and only if a module has got a local function with that name.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8671\n\n- The predefined builtin type tid() has been removed. Instead, ets:tid() should\n be used.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8687","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.16.5 - STDLIB Release Notes","ref":"notes.html#stdlib-1-16-5"},{"type":"extras","doc":"- Because of a race condition, using filelib:ensure_dir/1 from multiple\n processes to create the same path or parts of the same directory structure,\n filelib:ensure_dir/1 could return a meaningless \\{error,eexist\\}. That race\n condition has been eliminated, and \\{error,eexist\\} will now be returned only\n if there exists a regular file, device file, or some other non-directory file\n with the same name. (Thanks to Tuncer Ayaz.)\n\n Own Id: OTP-8389\n\n- A number of bugs concerning re and unicode are corrected:\n\n re:compile no longer loses unicode option, which also fixes bug in re:split.\n\n re:replace now handles unicode charlist replacement argument\n\n re:replace now handles unicode RE charlist argument correctly\n\n re:replace now handles binary unicode output correctly when nothing is\n replaced.\n\n Most code, testcases and error isolation done by Rory Byrne.\n\n Own Id: OTP-8394\n\n- The loading of native code was not properly atomic in the SMP emulator, which\n could cause crashes. Also a per-MFA information table for the native code has\n now been protected with a lock since it turns that it could be accessed\n concurrently in the SMP emulator. (Thanks to Mikael Pettersson.)\n\n Own Id: OTP-8397\n\n- user.erl (used in oldshell) is updated to handle unicode in prompt strings\n (io:get_line/\\{1,2\\}). io_lib is also updated to format prompts with the 't'\n modifier (i.e. ~ts instead of ~s).\n\n Own Id: OTP-8418 Aux Id: OTP-8393\n\n- The re module: A regular expression with an option change at the start of a\n pattern that had top-level alternatives could cause overwriting and/or a\n crash. (Thanks to Michael Santos.)\n\n Own Id: OTP-8438","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The ability for the gen_server and gen_fsm callback modules to format their\n own state for display under the sys:get_status/1,2 calls has been restored and\n documented. (Thanks to Steve Vinoski.)\n\n Own Id: OTP-8324\n\n- c:nc/\\{1,2\\} used to assume that the beam file was created in the same\n directory as the source code and failed to load the code if it was not.\n Corrected to look for the beam file in the current directory or in the\n directory specified by the `{outdir,Dir}` option. (Thanks to Alex Suraci.)\n\n Own Id: OTP-8337\n\n- The documentation is now possible to build in an open source environment after\n a number of bugs are fixed and some features are added in the documentation\n build process.\n\n \\- The arity calculation is updated.\n\n \\- The module prefix used in the function names for bif's are removed in the\n generated links so the links will look like\n \"http://www.erlang.org/doc/man/erlang.html#append_element-2\" instead of\n \"http://www.erlang.org/doc/man/erlang.html#erlang:append_element-2\".\n\n \\- Enhanced the menu positioning in the html documentation when a new page is\n loaded.\n\n \\- A number of corrections in the generation of man pages (thanks to Sergei\n Golovan)\n\n \\- The legal notice is taken from the xml book file so OTP's build process can\n be used for non OTP applications.\n\n Own Id: OTP-8343\n\n- Shell tab completion now works for quoted module and function names. (Thanks\n to Ulf Wiger.)\n\n Own Id: OTP-8383\n\n- Explicit top directories in archive files are now optional.\n\n For example, if an archive (app-vsn.ez) just contains an app-vsn/ebin/mod.beam\n file, the file info for the app-vsn and app-vsn/ebin directories are faked\n using the file info from the archive file as origin. The virtual direcories\n can also be listed. For short, the top directories are virtual if they does\n not exist.\n\n Own Id: OTP-8387\n\n- Macros overloading has been implemented. (Thanks to Christopher Faulet.)\n\n Own Id: OTP-8388\n\n- The new function `shell:prompt_func/1` and the new application configuration\n parameter `shell_prompt_func` can be used for customizing the Erlang shell\n prompt.\n\n Own Id: OTP-8393\n\n- Improved handling of typed records in escripts\n\n Own Id: OTP-8434\n\n- Added supervisor:count_children/1 to count the number of children being\n managed without the memory impact of which_children/1. (Thanks to Jay Nelson.)\n\n Own Id: OTP-8436","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.16.4 - STDLIB Release Notes","ref":"notes.html#stdlib-1-16-4"},{"type":"extras","doc":"- The documentation is now built with open source tools (xsltproc and fop) that\n exists on most platforms. One visible change is that the frames are removed.\n\n Own Id: OTP-8201\n\n- \\[escript] The restriction that the first line in escripts must begin with\n `#!` has been removed.\n\n \\[escript] Some command line options to the escript executable has now been\n documented. For example you can run an escript in the debugger by just adding\n a command line option.\n\n \\[escript] The documentation of the escript header syntax has been clarified.\n For example the header is optional. This means that it is possible to directly\n \"execute\" `.erl`, `.beam` and`.zip` files.\n\n Own Id: OTP-8215\n\n- Optimized array:from_orddict/1, it is now faster and uses less memory if the\n orddict was sparse.\n\n Changed array:reset/2, it will now never expand the array which it could\n before for non fixed arrays. See the documentation.\n\n Own Id: OTP-8216\n\n- The Erlang Pretty Printer (`erl_pp`) now puts the leading `[` of list\n comprehensions as well as the leading `<<` of bit string comprehensions on a\n separate line in order to expose the Cover counter of the template.\n\n Own Id: OTP-8227\n\n- The extension \".xrl\" used for Leex input files is now recognized by the\n compiler.\n\n Own Id: OTP-8232\n\n- Some clarifications have been made in the documentation regarding\n `gen_server`, `gen_fsm`, and `gen_event` behavior when handling `'EXIT'`\n messages from the parent process. For more information see the `m:gen_server`,\n `m:gen_fsm`, and `m:gen_event` documentation.\n\n Own Id: OTP-8255 Aux Id: seq11419\n\n- The -on_load() directive can be used to run a function when a module is\n loaded. It is documented in the section about code loading in the Reference\n Manual.\n\n Own Id: OTP-8295","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.16.3.1 - STDLIB Release Notes","ref":"notes.html#stdlib-1-16-3-1"},{"type":"extras","doc":"- An erroneous type spec for `gen:start/6` caused dialyzer to erroneously issue\n warnings when `{spawn_opt, SpawnOptionList}` was passed in the option list to\n the `gen_server` and `gen_fsm` start functions.\n\n Own Id: OTP-8068 Aux Id: seq11323, seq11314","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 1.16.3 - STDLIB Release Notes","ref":"notes.html#stdlib-1-16-3"},{"type":"extras","doc":"- The linter used to crash on invalid `-opaque` declarations.\n\n Own Id: OTP-8051\n\n- Bugs in `digraph:add_edge/5` and `digraph:del_path/3` have been fixed. (Thanks\n to Crystal Din.)\n\n Own Id: OTP-8066\n\n- When trying to insert objects with `dets:insert_new()` into a Dets table of\n type `duplicate_bag`, already existing objects would sometimes be duplicated.\n This bug has been fixed. (Thanks to Crystal Din.)\n\n Own Id: OTP-8070\n\n- Running erlc in a very deep directory (with a path length of more 256 or more\n characters) would cause the emulator to crash in a call to\n [`list_to_atom/1`](`list_to_atom/1`). (Thanks to Chris Newcombe.)\n\n Own Id: OTP-8124\n\n- A few minor bugs have been fixed in the Erlang Code Preprocessor (`epp`).\n\n Own Id: OTP-8130\n\n- A bug in The Erlang Meta Interpreter (`erl_eval`) has been fixed: exceptions\n generated in the template of bit string comprehensions were not handled\n properly. (Thanks to Ulf Wiger.)\n\n Own Id: OTP-8133","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Option `{capture,none}` was missing in documentation for `re:run/3`.\n\n Own Id: OTP-8113\n\n- When [`erl_scan:tokens()`](`t:erl_scan:tokens/0`) returns an error tuple\n `{error, ErrorInfo, EndLocation`\\}, the list `LeftOverChars` is the remaining\n characters of the input data, starting from `EndLocation`. It used to be the\n empty list.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8129\n\n- The Erlang Meta Interpreter (`erl_eval`) has been somewhat optimized when it\n comes to interpreting `receive`\\-expressions. (Thanks to Richard Carlsson.)\n\n Own Id: OTP-8139\n\n- The Erlang Pretty Printer (`erl_pp`) has been modified as to handle types.\n\n Own Id: OTP-8150","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.16.2 - STDLIB Release Notes","ref":"notes.html#stdlib-1-16-2"},{"type":"extras","doc":"- The text of tokens returned by the Erlang scanner (`erl_scan`) was sometimes\n empty when the `text` option was given and `StartLocation` was a line. This\n bug has been fixed.\n\n Own Id: OTP-7965\n\n- The documentation for `base64:decode/1` has been updated to point out that it\n strips whitespace.\n\n `base64:decode/1` and `base64:mime_decode/1` would sometimes fail instead of\n stripping away non-base64 characters.\n\n Own Id: OTP-7984\n\n- Two types in the `gen` module were corrected.\n\n Own Id: OTP-8029 Aux Id: seq11296\n\n- `array:from_orddict([])` and `array:from_list([])` would construct fixed\n arrays instead of extendible arrays.\n\n Own Id: OTP-8033","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Interpreted escripts are now tail recursive.\n\n The function erl_eval:expr/5 has been introduced.\n\n Own Id: OTP-7933\n\n- `gen_server:call/2,3` will be somewhat faster if the calling process has a\n many messages in its message queue.\n\n Own Id: OTP-7979\n\n- Random now supports seed with arity one, `random:seed/1`, which takes a\n three-tuple.\n\n Own Id: OTP-8019\n\n- The `regexp` module now recognizes the escape sequences `\\xXY` and `\\x{X...}`.\n\n Own Id: OTP-8024","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.16.1 - STDLIB Release Notes","ref":"notes.html#stdlib-1-16-1"},{"type":"extras","doc":"- The documentation of `dets:open_file/1` now states that the file is repaired\n if it has not been properly closed. (Thanks to Ulf Wiger.)\n\n Own Id: OTP-7895","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The Erlang scanner no longer returns the text of tokens when the start\n location is a pair of a line and column unless the new option `text` is\n supplied (incompatibility with R13A).\n\n There are new functions to access the attributes of tokens:\n `attributes_info/1,2` and `set_attribute/3`.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-7892 Aux Id: OTP-7810\n\n- Several glitches and performance issues in the Unicode and I/O-system\n implementation of R13A have been corrected.\n\n Own Id: OTP-7896 Aux Id: OTP-7648 OTP-7887\n\n- The type spec of filelib:wildcard/2 has been corrected.\n\n Own Id: OTP-7915\n\n- New functions: `gb_sets:is_disjoint/2`, `ordsets:is_disjoint/2`, and\n `gb_sets:is_disjoint/2`.\n\n Own Id: OTP-7947\n\n- The function `gb_trees:map/2` which was added in R13A is now documented.\n\n Own Id: OTP-7948","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.16 - STDLIB Release Notes","ref":"notes.html#stdlib-1-16"},{"type":"extras","doc":"- Fixed a minor race conditions in `gen_server:start*`: if one of these\n functions returned `{error,Reason}` or `ignore`, the name could still be\n registered (either locally or in `global`).\n\n A process started by `proc_lib` in some cases depended on its process\n dictionary not to be erased, and would crash when terminating abnormally and\n not generate a proper crash report. This has been corrected (but the initial\n call will not be shown in the error report if the process dictionary has been\n erased). NOTE: There is no longer any need to erase the process dictionary for\n memory conservation reasons, since the actual call arguments are no longer\n saved in the process dictionary.\n\n Own Id: OTP-7669\n\n- The Erlang preprocessor used wrong line number when stringifying macro\n arguments. (Thanks to John Hughes.)\n\n Own Id: OTP-7702\n\n- A bug in the `qlc` module has been fixed: merge join sometimes failed to\n return all answers. (Thanks to Bernard Duggan.)\n\n Own Id: OTP-7714","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- A new option, `key_equality`, has been added to `qlc:table/2`. This option\n makes it possible for `qlc` to better handle tables that use `==/2` when\n comparing keys for equality (examples of such tables are ordered ETS tables\n and gb_table in qlc(3)).\n\n Own Id: OTP-6674\n\n- The functions `lists:seq/1,2` return the empty list in a few cases when they\n used to generate an exception, for example `lists:seq(1, 0)`. See lists(3) for\n details. (Thanks to Richard O'Keefe.)\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-7230\n\n- The order of objects visited in select for ordered_set is now documented.\n\n Own Id: OTP-7339\n\n- It is now possible to debug code in escripts and archives.\n\n Own Id: OTP-7626\n\n- Support for Unicode is implemented as described in EEP10. Formatting and\n reading of unicode data both from terminals and files is supported by the io\n and io_lib modules. Files can be opened in modes with automatic translation to\n and from different unicode formats. The module 'unicode' contains functions\n for conversion between external and internal unicode formats and the re module\n has support for unicode data. There is also language syntax for specifying\n string and character data beyond the ISO-latin-1 range.\n\n The interactive shell will support input and output of unicode characters when\n the terminal and operating system supports it.\n\n Please see the EEP and the io/io_lib manual pages as well as the stdlib users\n guide for details.\n\n _I/O-protocol incompatibilities:_\n\n The io_protocol between io_Server and client is updated to handle protocol\n data in unicode formats. The updated protocol is now documented. The\n specification resides in the stdlib _users manual_, which is a new part of the\n manual.\n\n _io module incompatibilities:_\n\n The io:put_chars, io:get_chars and io:get_line all handle and return unicode\n data. In the case where binaries can be provided (as to io:put_chars), they\n shall be encoded in UTF-8. When binaries are returned (as by\n io:get_line/get_chars when the io_server is set in _binary mode_) the returned\n data is also _always_ encoded as UTF-8. The file module however still returns\n byte-oriented data, why file:read can be used instead of io:get_chars to read\n binary data in ISO-latin-1.\n\n _io_lib module incompatibilities:_\n\n io_lib:format can, given new format directives (i.e \"~ts\" and \"~tc\"), return\n lists containing integers larger than 255.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-7648 Aux Id: OTP-7580 OTP-7514 OTP-7494 OTP-7443 OTP-7181 EEP10\n EEP11\n\n- The function `pool:attach/1` now returns `already_attached` if the node is\n already attached, rather than `allready_attached` (sic\\!). (Thanks to Edwin\n Fine.)\n\n Own Id: OTP-7653 Aux Id: OTP-7603\n\n- Preprocessor directives are now allowed in escripts. This means that for\n example macros may be used in escripts.\n\n Own Id: OTP-7662\n\n- When a process started with `proc_lib`, `gen_server`, or `gen_fsm` exits with\n reason `{shutdown,Term}`, a crash report will no longer be generated (to allow\n a clean shutdown, but still provide additional information to process that are\n linked to the terminating process).\n\n Own Id: OTP-7740 Aux Id: seq10847\n\n- A new BIF, `lists:keyfind/3`, has been added. It works like\n `lists:keysearch/3` except that it does not wrap the returned tuple in a\n `value` tuple in case of success. (Thanks to James Hague for suggesting this\n function.)\n\n Own Id: OTP-7752\n\n- `lists:suffix(Suffix, List)` used to have a a complexity of\n `length(Suffix)*length(List)` (which could become quite slow for some inputs).\n It has now been re-implemented so that its complexity is\n `length(Suffix)+length(List)`. (Thanks to Richard O'Keefe for the new\n implementation.)\n\n Own Id: OTP-7797\n\n- The Erlang scanner has been augmented as to return white spaces, comments, and\n exact location of tokens. The functions `string/3`, `tokens/4`, and\n `token_info/1,2` are new. See erl_scan(3) for details.\n\n `tokens/3,4` have been modified as to return a list of tokens instead of an\n error when `eof` is encountered before the dot.\n\n Own Id: OTP-7810\n\n- `filelib:fold_files/5` now uses the `re` module instead of the `regexp` module\n for regular expression matching. In practice, this change will not be a\n problem for most regular expressions used for `filelib:fold_files/5`. (The\n major difference in regular expression is that parenthesis and curly brackets\n is treated as literal characters by `regexp` but as special characters by\n `re`; fortunately, those characters are rarely used in filenames.)\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-7819\n\n- `digraph:new(Type)` will now cause a `badarg` exception if `Type` is not a\n valid type. Similarly, `digraph_utils:subgraph/2,3` will now cause a `badarg`\n if the arguments are invalid. (Those functions used to return error tuples if\n something was wrong.)\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-7824\n\n- The argument passed to `random:uniform/1` must now be an integer (as stated in\n the documentation). In previous releases, a floating point number was also\n allowed.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-7827\n\n- The copyright notices have been updated.\n\n Own Id: OTP-7851\n\n- A few missing match spec functions was added to dbg:fun2ms; exception_trace/0\n and trace/2,3.\n\n There is a new function queue:member/2.\n\n A bug in io_lib:fread that made it accidentally concatenate fields separated\n by newline has been corrected. Reported and analyzed by Matthew Palmer to\n erlang-patches.\n\n Own Id: OTP-7865","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.15.5 - STDLIB Release Notes","ref":"notes.html#stdlib-1-15-5"},{"type":"extras","doc":"- A bug in the `qlc` module has been fixed: when merge joining two query handles\n the temporary file used for equivalence classes was not truncated properly\n which could result in poor performance.\n\n Own Id: OTP-7552\n\n- The characters 16#C0 and 16#E0 (\"A\" and \"a\" with grave accent), were not\n properly converted by the `string:to_lower/1` and `string:to_upper/1`\n functions. (Thanks to Richard O'Keefe.)\n\n Own Id: OTP-7589\n\n- The function `pool:attach/1` now returns `already_attached` if the node is\n already attached, rather than `allready_attached` (sic\\!). (Thanks to Edwin\n Fine.)\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-7603\n\n- The documentation for `io:get_line/1,2` now mentions that the return value can\n also be `{error,Reason}`.\n\n Own Id: OTP-7604 Aux Id: seq11063","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The split function is now added to the re library. Exceptions and errors from\n both run, replace and split are made more consistent.\n\n Own Id: OTP-7514 Aux Id: OTP-7494\n\n- Processes spawned using `proc_lib` (including `gen_server` and other library\n modules that use `proc_lib`) no longer keep the entire argument list for the\n initial call, but only the arity.\n\n Also, if `proc_lib:spawn/1` is used to spawn a fun, the actual fun is not\n kept, but only module, function name, and arity of the function that\n implements the fun.\n\n The reason for the change is that keeping the initial fun (or a fun in an\n argument list), would prevent upgrading the code for the module. A secondary\n reason is that keeping the fun and function arguments could waste a\n significant amount of memory.\n\n The drawback with the change is that the crash reports will provide less\n precise information about the initial call (only `Module:Function/Arity`\n instead of `Module:Function(Arguments)`). The function\n `proc_lib:initial_call/1` still returns a list, but each argument has been\n replaced with a dummy atom.\n\n Own Id: OTP-7531 Aux Id: seq11036\n\n- There is now experimental support for loading of code from archive files. See\n the documentation of `code`, `init`, `erl_prim_loader `and `escript` for more\n info.\n\n The error handling of `escripts` has been improved.\n\n An `escript` may now set explicit arguments to the emulator, such as\n `-smp enabled`.\n\n An `escript` may now contain a precompiled beam file.\n\n An `escript` may now contain an archive file containing one or more\n applications (experimental).\n\n The internal module `code_aux` has been removed.\n\n Own Id: OTP-7548 Aux Id: otp-6622\n\n- Enabled explicit control of which types of files that should be compressed in\n a ZIP archive.\n\n Own Id: OTP-7549 Aux Id: otp-6622\n\n- In the job control mode, the \"s\" and \"r\" commands now take an optional\n argument to specify which shell to start. (Thanks to Robert Virding.)\n\n Own Id: OTP-7617","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.15.4 - STDLIB Release Notes","ref":"notes.html#stdlib-1-15-4"},{"type":"extras","doc":"- A bug in the calendar module could cause\n calendar:local_time_to_universal_time_dst/1 to return duplicate identical\n values for local times in timezones without DST. Multiple values should only\n be returned when a local time is within the hour occurring twice due to shift\n from DST to non-DST, and certainly only in timezones with DST. The correct\n behaviour is now implemented.\n\n Own Id: OTP-7344 Aux Id: seq10960\n\n- The documentation of `(d)ets:init_table()` has been corrected. (Thanks to Paul\n Mineiro.)\n\n Own Id: OTP-7413\n\n- The soft upper limit of 60 on the number of non-white characters on a line,\n which was introduced in R12B-0 for the control sequences `p` and `P` of the\n functions `io:fwrite/2,3` and `io_lib:fwrite/2`, has been removed. This means\n that terms whose printed representation fits on a line will have no NEWLINEs.\n The Erlang shell still uses the 60 character limit, though.\n\n Own Id: OTP-7421 Aux Id: OTP-6708\n\n- Some debug code has been removed from Dets.\n\n Own Id: OTP-7424\n\n- The documentation of `dets:match_delete/2` has been corrected. (Thanks to Paul\n Mineiro.)\n\n Own Id: OTP-7445\n\n- Corrections of digraph(3). (Thanks to Vlad Dumitrescu.)\n\n Own Id: OTP-7492\n\n- For the process that an escript runs in, the `trap_exit` process flag is now\n `false` instead of `true` (as in previous releases). Scripts that depend on\n the previous (counter-intuitive) behaviour might not work. (Thanks to Bengt\n Kleberg.)\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-7517","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The documentation of `lists:(u)sort/2` now states what is expected of an\n ordering function.\n\n Own Id: OTP-7489\n\n- The re module is extended with repetitive matches (global option) and\n replacement function.\n\n Own Id: OTP-7494 Aux Id: OTP-7181\n\n- The Erlang shell now displays a nicer error message when evaluating an\n undefined command. (Thanks to Richard Carlsson.)\n\n Own Id: OTP-7495","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.15.3 - STDLIB Release Notes","ref":"notes.html#stdlib-1-15-3"},{"type":"extras","doc":"- zip:unzip to/from binary with empty directories did not work. (Thanks to\n Martin Dvorak.)\n\n Own Id: OTP-7248\n\n- The documentation of the control sequence `w` of the `io_lib` module now\n states that floating point numbers are printed accurately.\n\n Own Id: OTP-7324 Aux Id: OTP-7084\n\n- zip:unzip was not supporting a flavour of the zip format found in jar-files.\n\n Own Id: OTP-7382 Aux Id: seq10970","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- An experimental module \"re\" is added to the emulator which interfaces a\n publicly available regular expression library for Perl-like regular\n expressions (PCRE). The interface is purely experimental and _will_ be subject\n to change.\n\n The implementation is for reference and testing in connection to the relevant\n EEP.\n\n Own Id: OTP-7181","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.15.2 - STDLIB Release Notes","ref":"notes.html#stdlib-1-15-2"},{"type":"extras","doc":"- When inserting many small objects, Dets sometimes crashed when reaching the\n maximum number of slots. (Thanks to Daniel Goertzen.)\n\n Own Id: OTP-7146\n\n- Processes linked to the Erlang shell did not get an exit signal when the\n evaluator process was killed. This bug, introduced in R12B-0, has been fixed.\n\n Own Id: OTP-7184 Aux Id: OTP-6554\n\n- Invalid arguments to `ets:update_counter/3` were not handled correctly. A\n tuple position (`Pos`) less than 1 caused the element directly following the\n key to be updated (as if no position at all had been specified). All invalid\n values for `Pos` will now fail with `badarg`.\n\n Own Id: OTP-7226\n\n- For certain terminals, io:columns/0 could return 0 instead of enotsup. That is\n now corrected.\n\n Own Id: OTP-7229 Aux Id: seq10886\n\n- `qlc:info()` can now handle port identifiers, pids, references, and funs.\n (Thanks to Wojciech Kaczmare for reporting this bug.)\n\n When evaluating the `parent_fun` messages sent to the process calling\n `qlc:cursor()` were sometimes erroneously consumed. This bug has been fixed.\n\n Own Id: OTP-7232\n\n- `erl_parse:abstract()` can now handle bit strings.\n\n Own Id: OTP-7234","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The `queue` module has been rewritten to make it easier to use. Suggestions\n and discussion from and with among others Lev Walkin, Anders Ramsell and Rober\n Virding in december 2007 on erlang-questions@erlang.org. It was also discussed\n to change the internal representation to contain length information which\n would speed up `len/1` but that change has been postponed. Anyone interested\n may write an EEP and try to reach an acceptable compromise for queue overhead\n and thereby the speed of all other operations than `len/1`. The `queue` module\n is now optimized for fast and minimal garbage `in/2` and `out/1` and such. See\n the documentation.\n\n New functions: `is_queue/1`, [`get/1`](`get/1`), `get_r/1`, `peek/1`,\n `peek_r/1`, `drop/1`, `drop_r/1` and `liat/1`. `is_queue/1` is a new\n predicate, `liat/1` is a correction of an old misspelling, and the others\n (`get`\\*, `peek`\\* and `drop`\\*) are new interface functions.\n\n Own Id: OTP-7064\n\n- The functions `io_lib:write/1,2` and `io_lib:print/1,4` have been changed when\n it comes to writing floating point numbers. This change affects the control\n sequences `p`, `P`, `w`, and `W` of the `io_lib` module. (Thanks to Bob\n Ippolito for code contribution.)\n\n Own Id: OTP-7084\n\n- Updated the documentation for `erlang:function_exported/3` and `io:format/2`\n functions to no longer state that those functions are kept mainly for\n backwards compatibility.\n\n Own Id: OTP-7186\n\n- A new BIF ets:update_element/3. To update individual elements within an\n ets-tuple, without having to read, update and write back the entire tuple.\n\n Own Id: OTP-7200\n\n- `string:join/2` now accepts an empty list as first argument.\n\n Own Id: OTP-7231 Aux Id: OTP-6671\n\n- `qlc:info/1,2` accepts a new option, `depth`. The type `SelectedObjects` used\n in the description of `qlc:table/2` has been augmented.\n\n Own Id: OTP-7238\n\n- [`tuple_size/1`](`tuple_size/1`) and [`byte_size/1`](`byte_size/1`) have been\n substituted for [`size/1`](`size/1`) in the documentation.\n\n Own Id: OTP-7244","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.15.1 - STDLIB Release Notes","ref":"notes.html#stdlib-1-15-1"},{"type":"extras","doc":"- Ets:select/3 in combination with ets:repair_continuation/2 and ordered_set\n data tables could result in function_clause although used as intended. This is\n now corrected. Thanks to Paul Mineiro for finding and isolating the bug\\!\n\n Own Id: OTP-7025\n\n- The compiler warning for the deprecated function `ftp:close/1` now mentions\n the correct replacement function.\n\n The warning for the removed functions in the `httpd_util` module have been\n changed to say they have been removed, not merely deprecated. (Thanks to\n Fredrik Thulin.)\n\n Own Id: OTP-7034 Aux Id: seq10825\n\n- In `(Expr)#r{}` (no fields are updated), `Expr` is no longer evaluated more\n than once. There is also a test that `Expr` is of the correct record type.\n (Thanks to Dominic Williams.)\n\n Own Id: OTP-7078 Aux Id: OTP-4962\n\n- Documentation bugfixes and clarifications.\n\n (Thanks to Joern (opendev@gmail.com), Matthias Lang, and Richard Carlsson.)\n\n Own Id: OTP-7079\n\n- Duplicated objects were sometimes not deleted from the list of answers when a\n QLC table was traversed using a match specification. (Thanks to Dmitri\n Girenko.)\n\n Own Id: OTP-7114","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The documentation has been updated so as to reflect the last updates of the\n Erlang shell as well as the minor modifications of the control sequence `p` of\n the `io_lib` module.\n\n Superfluous empty lines have been removed from code examples and from Erlang\n shell examples.\n\n Own Id: OTP-6944 Aux Id: OTP-6554, OTP-6911\n\n- [`tuple_size/1`](`tuple_size/1`) and [`byte_size/1`](`byte_size/1`) have been\n substituted for [`size/1`](`size/1`).\n\n Own Id: OTP-7009\n\n- It is now possible to hibernate a gen_server/gen_event/gen_fsm. In gen_server\n and gen_fsm, hibernation is triggered by returning the atom\n 'hibernate' instead of a timeout value. In the gen_event case hibernation is\n triggered by a event handler returning a tuple with an extra element\n containing the atom 'hibernate'.\n\n Own Id: OTP-7026 Aux Id: seq10817\n\n- Some undocumented debug functionality has been added to Dets.\n\n Own Id: OTP-7066\n\n- The functions `digraph_utils:is_tree/1`, `digraph_utils:is_arborescence/1`,\n and `digraph_utils:arborescence_root/1` are new.\n\n Own Id: OTP-7081\n\n- The compiler could generate suboptimal code for record updates if the record\n update code consisted of multiple source code lines.\n\n Own Id: OTP-7101","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.15 - STDLIB Release Notes","ref":"notes.html#stdlib-1-15"},{"type":"extras","doc":"- Bugs have been fixed in `qlc`:\n\n - Setting the `lookup_fun` option of `qlc:table/2` to `undefined` could cause\n a crash.\n - If a QLC restricted some column of a table in such a way that a traversal\n using a match specification was possible and the QLC also compared the key\n column or some indexed column of the the table with a column of some other\n table, `qlc` always chose to traverse the table first, never considering\n lookup join. This has been changed so that lookup join is always preferred;\n if an initial traversal using the match specification is desired, the query\n needs to be rewritten introducing an extra QLC with the filter(s)\n restricting the column.\n - When trying to find candidates for match specifications and lookup, filters\n using variables from one generator only are ignored unless they are placed\n immediately after the generator and possibly other filters using variables\n from the same generator. In particular, filters joining two tables should\n not be placed between the generator and the filters using the generator\n only.\n - The call-back function `TraverseFun` used for implementing QLC tables is\n allowed to return a term other than a list since STDLIB 1.14 (OTP-5195).\n However, when the returned term was a fun `qlc` often tried to call the fun\n instead of returning it.\n\n A few minor optimizations have been implemented as well.\n\n Own Id: OTP-6673\n\n- A bug concerning the use of parameterized modules from the shell has been\n fixed.\n\n Own Id: OTP-6785\n\n- A bug regarding the size expression of the bit syntax has been fixed in the\n `erl_eval` module.\n\n Own Id: OTP-6787\n\n- The log_mf_h event handler didn't close the index file when it was done\n reading it causing a file descriptor leak.\n\n Own Id: OTP-6800\n\n- Definitions for the `filename()` and `dirname()` types have been added to the\n documentation for the `filelib` module.\n\n Own Id: OTP-6870\n\n- file:write_file/3, file:write/2 and file:read/2 could crash (contrary to\n documentation) for odd enough file system problems, e.g write to full file\n system. This bug has now been corrected.\n\n In this process the file module has been rewritten to produce better error\n codes. Posix error codes now originate from the OS file system calls or are\n generated only for very similar causes (for example 'enomem' is generated if a\n memory allocation fails, and 'einval' is generated if the file handle in\n Erlang is a file handle but currently invalid).\n\n More Erlang-ish error codes are now generated. For example `{error,badarg}` is\n now returned from `file:close/1` if the argument is not of a file handle type.\n See file(3).\n\n The possibility to write a single byte using `file:write/2` instead of a list\n or binary of one byte, contradictory to the documentation, has been removed.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-6967 Aux Id: OTP-6597 OTP-6291\n\n- A bug concerning the evaluation of the `++/2` operator has been fixed in\n `erl_eval`. (Thanks to Matthew Dempsky.)\n\n Own Id: OTP-6977","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The behaviour of the internal functions gen:call/3,4 has been changed slightly\n in the rare case that when the caller was linked to the called server, and the\n server crashed during the call; its exit signal was consumed by the\n gen:call/3,4 code and converted to an exit exception. This exit signal is no\n longer consumed.\n\n To even notice this change, 1) the calling process has to be linked to the\n called server.\n\n 2. the call must not be remote by name that is it must be local or remote by\n pid, local by name or global by name.\n\n 3. the calling process has to have set\n [`process_flag(trap_exit, true)`](`process_flag/2`).\n\n 4. the server has to crash during the call.\n\n 5. the calling process has to be sensitive to getting previously consumed\n `{'EXIT',Pid,Reason}` messages in its message queue.\n\n The old behaviour was once the only way for a client to notice if the server\n died, but has since `erlang:monitor(process, {Name,Node})` was introduced and\n used in gen:call been regarded as an undesired behaviour if not a bug.\n\n The affected user APIs are: `gen_server:call/2,3`,\n `gen_fsm:sync_send_event/2,3`, `gen_fsm:sync_send_all_state_event/2,3`,\n `gen_event:_`, `sys:_` and maybe a few others that hardly will be noticed.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-3954 Aux Id: Seq 4538\n\n- When an exception occurs the Erlang shell now displays the class, the reason,\n and the stacktrace in a clearer way (rather than dumping the raw EXIT tuples\n as before). `proc_lib:format/1` displays the exception of crash reports in the\n same clearer way.\n\n The new shell command `catch_exception` and the new application configuration\n parameter `shell_catch_exception` can be used for catching exceptions that\n would normally exit the Erlang shell.\n\n Own Id: OTP-6554 Aux Id: OTP-6289\n\n- The function `string:join/2` joins strings in a list with a separator.\n Example: '`string:join([\"a\", \"b\", \"c\"], \", \") gives \"a, b, c\"`'\n\n Own Id: OTP-6671\n\n- The control sequence `P` of the `Format` argument of the functions\n `io:fwrite/2,3` and `io_lib:fwrite/2` now inserts fewer line breaks when\n printing tuples and lists. A soft upper limit of 60 on the number of non-white\n characters on a line has been introduced.\n\n Own Id: OTP-6708\n\n- The new module `array` provides a fast functional array implementation.\n\n Own Id: OTP-6733\n\n- Functions that have long been deprecated have now been removed from the\n following modules: `dict`, `erl_eval`, `erl_pp`, `io`, `io_lib`, `lists`,\n `orddict`, `ordsets`, `sets`, and `string`.\n\n The undocumented function `lists:zf/3` has also been removed (use a list\n comprehension or `lists:zf/2` instead).\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-6845\n\n- Minor documentation corrections for file:pread/2 and file:pread/3.\n\n Own Id: OTP-6853\n\n- Contract directives for modules in Kernel and STDLIB.\n\n Own Id: OTP-6895\n\n- The `ets:fixtable/2` function, which has been deprecated for several releases,\n has been removed.\n\n The `ets:info/1` function has been reimplemented as a BIF, which guarantees\n that information returned is consistent.\n\n The `ets:info/2` function now fails with reason `badarg` if the second\n argument is invalid. (Dialyzer can be used to find buggy code where the second\n argument is misspelled.)\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-6906\n\n- The Erlang pretty printer `erl_pp` now inserts more newlines in order to\n facilitate line coverage analysis by `Cover`. (Thanks to Thomas Arts.)\n\n Own Id: OTP-6911\n\n- The documentation for ets:safe_fixtable/2, ets:foldl/3, and ets:foldr/3 is now\n clearer about what will happen if objects are inserted during table\n traversals.\n\n Own Id: OTP-6928 Aux Id: seq10779\n\n- It is now possible to extract files in tar files directly into binaries. It is\n also possible to add files to tar files directly from binaries.\n\n Own Id: OTP-6943\n\n- The functions `keystore/4` and `keytake/3` are new in the `lists` module.\n\n Own Id: OTP-6953\n\n- The new `qlc` option `tmpdir_usage` can be used for outputting messages onto\n the error logger when a temporary file is about to be created, or to prohibit\n the usage of temporary files altogether.\n\n Own Id: OTP-6964","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.14.5.3 - STDLIB Release Notes","ref":"notes.html#stdlib-1-14-5-3"},{"type":"extras","doc":"- The allowed syntax for -type() and -spec() was updated.\n\n Own Id: OTP-6861 Aux Id: OTP-6834","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.14.5.2 - STDLIB Release Notes","ref":"notes.html#stdlib-1-14-5-2"},{"type":"extras","doc":"- The compiler will for forward compatibility ignore the -type() and -spec()\n attributes that will be introduced in the R12B release.\n\n Own Id: OTP-6834","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.14.5.1 - STDLIB Release Notes","ref":"notes.html#stdlib-1-14-5-1"},{"type":"extras","doc":"- The log_mf_h event handler didn't close the index file when it was done\n reading it causing a file descriptor leak.\n\n Own Id: OTP-6800","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The dict:size/1 and orddict:size/1 functions have been documented.\n\n Own Id: OTP-6818","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.14.5 - STDLIB Release Notes","ref":"notes.html#stdlib-1-14-5"},{"type":"extras","doc":"- Bugs have been fixed in Dets concerning comparison (==) and matching (=:=).\n\n The STDLIB manual pages have been updated as to more carefully state when\n terms are matched and when they are compared.\n\n Own Id: OTP-4738 Aux Id: OTP-4685\n\n- The shell has been updated to fix the following flaws: Shell process exit left\n you with an unresponsive initial shell if not using oldshell. Starting a\n restricted shell with a nonexisting callback module resulted in a shell where\n no commands could be used, not even init:stop/0. Fun's could not be used as\n parameters to local shell functions (in shell_default or user_default) when\n restricted_shell was active.\n\n Own Id: OTP-6537\n\n- A bug in QLC's parse transform has been fixed.\n\n Own Id: OTP-6590\n\n- A bug concerning `lists:sort/1` and `lists:keysort/2` and a mix of floating\n point numbers and integers has been fixed.\n\n Own Id: OTP-6606\n\n- When calling `erlang:garbage_collect/0` in the Erlang shell not only the\n evaluator process (the one returned by calling `self/0` in the Erlang shell)\n is garbage collected, but also the process holding the history list.\n\n Own Id: OTP-6659\n\n- Functions of the `beam_lib` module that used to catch exceptions and return a\n tuple `{'EXIT',Reason}` now exit with the reason `Reason`.\n\n Own Id: OTP-6711\n\n- The `erl_eval` module now calls the non-local function handler whenever an\n operator is evaluated (exceptions are `andalso`, `orelse`, and `catch`). The\n non-local function handler is now also called when the function or operator\n occurs in a guard test (such calls used to be ignored).\n\n These changes affect the Erlang shell when running in restricted mode: the\n callback function `non_local_allowed/3` is now called for operators such as\n `'!'/2`. This means that `non_local_allowed/3` may need to\n be changed as to let operators through. Note that `erlang:'!'/2` as well as\n `erlang:send/2,3` have to be restricted in order to stop message passing in\n the shell.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-6714 Aux Id: seq10374","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The new compiler option `warn_obsolete_guard` can be used for turning on\n warnings for calls to old type testing BIFs.\n\n Own Id: OTP-6585\n\n- For scripts written using `escript`, there is a new function\n `escript:script_name/0`, which can be used to retrieve the pathame of the\n script. The documentation has been clarified regarding pre-defined macros such\n as ?MODULE and the module name.\n\n Own Id: OTP-6593\n\n- Minor Makefile changes.\n\n Own Id: OTP-6689 Aux Id: OTP-6742","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.14.4 - STDLIB Release Notes","ref":"notes.html#stdlib-1-14-4"},{"type":"extras","doc":"- The MD5 calculation of a BEAM file done by `code:module_md5/1`,\n `beam_lib:md5/1`, and by the compiler for the default value of the `vsn`\n attribute have all been changed so that its result will be the same on all\n platforms; modules containing funs could get different MD5s on different\n platforms.\n\n Own Id: OTP-6459\n\n- When sorting terms using the `file_sorter` module (the option `Format` set to\n `term`), file errors were not always properly handled. This bug has been\n fixed.\n\n The directory supplied with the `tmpdir` option is no longer checked unless it\n is actually used. The error reason `not_a_directory` can no longer be\n returned; instead a `file_error` tuple is returned\n\n Own Id: OTP-6526\n\n- Bugs regarding `try`/`catch` have been fixed in the `erl_eval` module.\n\n Own Id: OTP-6539\n\n- When sorting the operands of a join operation, QLC called `file:open/3` with\n bad arguments. This bug has been fixed.\n\n Own Id: OTP-6562 Aux Id: seq10606","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The functions `beam_lib:cmp/1` and `beam_lib:strip/1` (and similar functions)\n have been updated to handle optional chunks (such as \"FunT\") in more general\n way in order to be future compatible.\n\n The function `beam_lib:chunks/3` has been added.\n\n The function `beam_lib:md5/1` has been added.\n\n Own Id: OTP-6443\n\n- Added base64 as a module to stdlib, encoding and decoding\n\n Own Id: OTP-6470\n\n- Added the functions to_upper/1 and to_lower/1 to the string module. These\n provide case conversion for ISO/IEC 8859-1 characters (Latin1) and strings.\n\n Own Id: OTP-6472\n\n- The callback function `non_local_allowed/3` used by the restricted shell can\n now return the value `{{restricted,NewFuncSpec,NewArgList},NewState}` which\n can be used for letting the shell call some other function than the one\n specified.\n\n Own Id: OTP-6497 Aux Id: seq10555\n\n- There is a new `escript` program that can be used for writing scripts in\n Erlang. Erlang scripts don't need to be compiled and any arguments can be\n passed to them without risk that they are interpreted by the Erlang system.\n\n Own Id: OTP-6505\n\n- The `Format` argument of the functions `io:fwrite/2,3` and `io_lib:fwrite/2`\n is now allowed to be a binary.\n\n Own Id: OTP-6517","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.14.3.1 - STDLIB Release Notes","ref":"notes.html#stdlib-1-14-3-1"},{"type":"extras","doc":"- The control sequences `p` and `P` of the `Format` argument of the functions\n `io:fwrite/2,3` and `io_lib:fwrite/2` could cause a `badarg` failure when\n applied to binaries. This bug was introduced in STDLIB 1.14.3. (Thanks to\n Denis Bilenko.)\n\n Own Id: OTP-6495","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Added the option \\{cwd, Dir\\} to make zip-archives with relative pathnames\n without having to do (a global) file:set_cwd.\n\n Own Id: OTP-6491 Aux Id: seq10551","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.14.3 - STDLIB Release Notes","ref":"notes.html#stdlib-1-14-3"},{"type":"extras","doc":"- The `spawn_opt/2,3,4,5` option `monitor` \\-- introduced in Kernel 2.11.2 -- is\n currently not possible to use when starting a process using `proc_lib`, that\n is, also when starting a gen_server, gen_fsm etc.\n\n This limitation has now been properly documented and the behavior of the\n `gen_fsm`, `gen_server`, and `proc_lib` `start` and `start_link` functions\n when providing this option has been changed from hanging indefinitely to\n failing with reason `badarg`.\n\n (Thanks to Fredrik Linder)\n\n Own Id: OTP-6345","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The control sequence `P` of the `Format` argument of the functions\n `io:fwrite/2,3` and `io_lib:fwrite/2` now replaces the tail of binary strings\n with `...` when the maximum depth has been reached. For instance,\n `io:fwrite(\"~P\", [<<\"a binary string\">>, 3]).` prints `<<\"a binary\"...>>`.\n\n The indentation takes more care not to exceed the right margin, if possible.\n\n If the maximum depth is reached while printing a tuple, `,...` is printed\n instead of `|...` (this change applies to the control sequence `W` as well).\n\n Own Id: OTP-6354\n\n- The Erlang shell command `h/0` that prints the history list now avoids\n printing (huge) terms referred to by `v/1` but instead just prints the call to\n `v/1`.\n\n Own Id: OTP-6390","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.14.2.2 - STDLIB Release Notes","ref":"notes.html#stdlib-1-14-2-2"},{"type":"extras","doc":"- The functions `dets:select/1,3`, `dets:match/1,3`, and `dets:match_object/1,3`\n have been changed as to never return `{[],Continuation}`. This change affects\n the corresponding functions in Mnesia.\n\n Bugs have been fixed in QLC: `qlc:info()` could crash if the `tmpdir` option\n did not designate a valid directory; the results of looking up keys are kept\n in RAM, which should improve performance.\n\n Own Id: OTP-6359","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 1.14.2.1 - STDLIB Release Notes","ref":"notes.html#stdlib-1-14-2-1"},{"type":"extras","doc":"- A bug in `erl_pp:exprs()` has been fixed.\n\n Own Id: OTP-6321 Aux Id: seq10497","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 1.14.2 - STDLIB Release Notes","ref":"notes.html#stdlib-1-14-2"},{"type":"extras","doc":"- The control sequences `p` and `P` of the `Format` argument of the functions\n `io:format/2,3` and `io_lib:format/2` did not handle binaries very well. This\n bug, introduced in stdlib-1.14, has been fixed.\n\n Own Id: OTP-6230\n\n- `filelib:wildcard(Wc, PathWithRedundantSlashes)`, where\n `PathWithRedundantSlashes` is a directory path containing redundant slashes,\n such as `/tmp/` or `//tmp`, could return incorrect results. (Thanks to Martin\n Bjorklund.)\n\n Own Id: OTP-6271\n\n- The Erlang code preprocessor crashed if the predefined macros ?MODULE or\n ?MODULE_STRING were used before the module declaration. This bug has been\n fixed.\n\n Own Id: OTP-6277","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Support for faster join of two tables has been added to the `qlc` module.\n There are two kinds of fast joins: lookup join that uses existing indices, and\n merge join that takes two sorted inputs. There is a new `join` option that can\n be used to force QLC to use a particular kind of join in some QLC expression.\n\n Several other changes have also been included:\n\n - The new `tmpdir` option of `cursor/2`, `eval/2`, `fold/4`, and `info/2` can\n be used to set the directory that join uses for temporary files. The option\n also overrides the `tmpdir` option of `keysort/3` and `sort/2`.\n - The new `lookup` option can be used to assert that constants are looked up\n when evaluating some QLC expression.\n - The `cache` and `cache_all` options accept new tags: `ets`, `list`, and\n `no`. The tag `list` caches answers in a list using a temporary file if the\n answers cannot be held in RAM. Combining `{cache,list}` and `{unique, true}`\n is equivalent to calling `sort/2` with the option `unique` set to `true`.\n The old tags `true` (equivalent to `ets`) and `false` (equivalent to `no`)\n are recognized for backward compatibility.\n - The new option `max_list_size` can be used to set the limit where merge join\n starts to use temporary files for large equivalence classes and when answers\n cached in lists are put on temporary files.\n - There is a new callback `is_sorted_key` to be supplied as an option to\n `table/2`.\n - QLC analyzes each and every QLC expression when trying to find constants for\n the lookup function. Hitherto only QLC expressions with exactly one\n generator were analyzed.\n\n Note that only filters with guard syntax placed immediately after the\n generator are analyzed. The restriction to guard filters is an incompatible\n change. See `m:qlc` for further details.\n\n - In a similar way several match specifications for traversal of QLC tables\n can be utilized for different generators of one single QLC expression.\n - A bug has been fixed: when caching answers to a sufficiently complex query\n it could happen that some answers were not returned.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-6038\n\n- The Erlang pretty printer (`erl_pp`) is now much faster when the code is\n deeply nested. A few minor bugs have been fixed as well.\n\n Own Id: OTP-6227 Aux Id: OTP-5924\n\n- The Erlang shell now tries to garbage collect large binaries. Under certain\n circumstances such binaries could otherwise linger on for an indefinite amount\n of time.\n\n Own Id: OTP-6239\n\n- To help Dialyzer find more bugs, many functions in the Kernel and STDLIB\n applications now only accept arguments of the type that is documented.\n\n For instance, the functions `lists:prefix/2` and `lists:suffix/2` are\n documented to only accept lists as their arguments, but they actually accepted\n anything and returned `false`. That has been changed so that the functions\n cause an exception if one or both arguments are not lists.\n\n Also, the `string:strip/3` function is documented to take a character argument\n that is a character to strip from one or both ends of the string. Given a list\n instead of a character, it used to do nothing, but will now cause an\n exception.\n\n Dialyzer will find most cases where those functions are passed arguments of\n the wrong type.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-6295","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.14.1 - STDLIB Release Notes","ref":"notes.html#stdlib-1-14-1"},{"type":"extras","doc":"- The functions `c:y/1,2` which call `yecc:file/1,2` are now listed by\n `c:help/0`.\n\n Documentation of `c:y/1,2` has been added to `m:c`.\n\n The fact that the control sequence character `s` recognizes binaries and deep\n character lists has been documented in `m:io`. This feature was added in\n R11B-0 (OTP-5403).\n\n Own Id: OTP-6140\n\n- The shell command rr() sometimes failed to read record definitions from\n file(s). This problem has been fixed.\n\n Own Id: OTP-6166 Aux Id: OTP-5878\n\n- The nonlocal function handler in `erl_eval`, which is used for implementing\n the restricted mode of the Erlang shell, did not handle calls to\n `erlang:apply/3` correctly. This bug has been fixed.\n\n Own Id: OTP-6169 Aux Id: seq10374\n\n- ets:rename/1 could deadlock, or crash the SMP emulator when the table wasn't a\n named table.\n\n ets:next/2, and ets:prev/2 could return erroneous results on the SMP emulator.\n\n Own Id: OTP-6198 Aux Id: seq10392, seq10415\n\n- When closing a Dets table the space management data was sometimes saved in\n such a way that opening the table could not be done without repairing the\n file. This bug has been fixed.\n\n Own Id: OTP-6206","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 1.14 - STDLIB Release Notes","ref":"notes.html#stdlib-1-14"},{"type":"extras","doc":"- A bugfix in QLC: two of the call-back functions used for implementing QLC\n tables, `TraverseFun` and `LookupFun`, are now allowed to return a term other\n than a list. Such a term is immediately returned as the results of the current\n query, and is useful mostly for returning error tuples.\n\n Several other minor bugs have been also been fixed.\n\n Own Id: OTP-5195\n\n- The STDLIB modules `error_logger_file_h` and `error_logger_tty_h` now read the\n environment variable `utc_log` from the SASL application.\n\n Own Id: OTP-5535\n\n- `ets:info/1` has been corrected to behave according to the documentation and\n return a list of tuples, not a tuple with tuples.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-5639\n\n- Referencing a so far undeclared record from the default value of some record\n declaration is from now on considered an error by the linter. It is also an\n error if the default value of a record declaration uses or binds a variable.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-5878\n\n- When a file `.hrl` file is included using `-include_lib`, the include path is\n temporarily updated to include the directory the `.hrl` file was found in,\n which will allow that `.hrl` file to itself include files from the same\n directory as itself using `-include`. (Thanks to Richard Carlsson.)\n\n Own Id: OTP-5944\n\n- Corrected `filelib:ensure_dir/1` which sometimes returned `true` and sometimes\n `ok` to always return `ok` when successful. This goes against the\n documentation which said `true`, but `ok` was judged to be a more logical\n return value.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-5960 Aux Id: seq10240\n\n- The shell now handles records better when used in calls on the form\n `{Module, Function}(ArgList)`.\n\n Own Id: OTP-5990 Aux Id: OTP-5876\n\n- The functions `lists:ukeysort/2` and `lists:ukeymerge/3` have been changed in\n such a way that two tuples are considered equal if their keys match.\n\n For the sake of consistency, `lists:usort/2` and `lists:umerge/3` have been\n modified too: two elements are considered equal if they compare equal.\n\n The `file_sorter` module has been modified in a similar way: the `unique`\n option now applies to the key (`keysort()` and `keymerge()`) and the ordering\n function (the option `{order, Order} `).\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-6019\n\n- Correction in documentation for `ets:update_counter/3`; failure with `badarg`\n also if the counter to be updated is the key.\n\n Own Id: OTP-6072\n\n- When sorting terms using the `file_sorter` module and an ordering fun, the\n sort was not always stable. This bug has been fixed.\n\n Own Id: OTP-6088","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Improvements of the linter:\n\n - The `compile` attribute is recognized after function definitions.\n - The new compiler option `nowarn_deprecated_function` can be used for turning\n off warnings for calls to deprecated functions.\n - The new compiler option `{nowarn_unused_function,[{Name,Arity}]}` turns off\n warnings for unused local functions for the mentioned functions. The new\n options `{nowarn_deprecated_function,[{Module,Name,Arity}]}` and\n `{nowarn_bif_clash,[{Name,Arity}]}` work similarly.\n\n The Erlang code preprocessor `epp` now recognizes the `file` attribute. This\n attribute is meant to be used by tools such as Yecc that generate source code\n files.\n\n Own Id: OTP-5362\n\n- The formatting option `~s` of `io:fwrite` and `io_lib:fwrite` has been\n extended to handle arguments that are binaries or I/O lists.\n\n Own Id: OTP-5403\n\n- The control sequences `p` and `P` of the `Format` argument of the functions\n `io:format/2,3` and `io_lib:format/2` have been changed as to display the\n contents of binaries containing printable characters as strings.\n\n Own Id: OTP-5485\n\n- The linter emits warnings for functions exported more than once in `export`\n attributes.\n\n Own Id: OTP-5494\n\n- A manual for STDLIB has been added, `stdlib(6)`. It mentions the configuration\n parameters for the Erlang shell.\n\n Own Id: OTP-5530\n\n- Added the `zip` module with functions for reading and creating zip archives.\n See `m:zip`.\n\n Own Id: OTP-5786\n\n- Simple-one-for-one supervisors now store the pids of child processes using\n `dict` instead of a list. This significantly improves performance when there\n are many dynamic supervised child processes. (Thanks to Mickaël Rémond et al.)\n\n Own Id: OTP-5898\n\n- When given the new option '`strict_record_tests`', the compiler will generate\n code that verifies the record type for '`R#record.field`' operations in\n guards. Code that verifies record types in bodies has already been generated\n since R10B, but in this release there will be a '`{badrecord,RecordTag}`'\n instead of a '`badmatch`' if the record verification test fails. See the\n documentation for the `compile` module for more information.\n\n The Erlang shell always applies strict record tests.\n\n Own Id: OTP-5915 Aux Id: OTP-5714\n\n- The Erlang pretty printer (`erl_pp`) now tries to insert line breaks at\n appropriate places.\n\n Own Id: OTP-5924\n\n- The `public` option has been removed from `digraph:new/1`. The reason is that\n several functions in the `digraph` module are implemented using multiple ETS\n accesses, which is not thread safe. (Thanks to Ulf Wiger.)\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-5985\n\n- The function `lists:keyreplace/4` checks that the fourth argument (`NewTuple`)\n is a tuple.\n\n Own Id: OTP-6023\n\n- Added an example of how to reconstruct source code from debug info (abstract\n code) to `m:beam_lib`. (Thanks to Mats Cronqvist who wrote the example.)\n\n Own Id: OTP-6073\n\n- The new compiler option `warn_unused_record` is used for finding unused\n locally defined record types.\n\n Own Id: OTP-6105","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.13.12 - STDLIB Release Notes","ref":"notes.html#stdlib-1-13-12"},{"type":"extras","doc":"- `shell_default:xm/1` has been added. It calls `xref:m/1`.\n\n Own Id: OTP-5405 Aux Id: OTP-4101\n\n- Warnings are output whenever so far undeclared records are referenced from\n some default value of a record declaration. In STDLIB 1.14 (R11B) such forward\n references will cause a compilation error.\n\n Own Id: OTP-5878\n\n- The linter's check of the `deprecated` attribute did not take the compile\n option `export_all` into account. This bug has been fixed.\n\n Own Id: OTP-5917\n\n- The Erlang pretty printer did not handle `try/catch` correctly. This bug has\n been fixed.\n\n Own Id: OTP-5926\n\n- Corrected documentation for `lists:nthtail/3`.\n\n Added documentation for `lists:keymap/3`.\n\n Tried to clarify some other type declarations and function descriptions in\n `m:lists`.\n\n Corrected documentation for `timer:now_diff/2`.\n\n Fixed broken links in `m:gen_fsm`, `m:gen_server`, `m:io_lib` and `lib(3)`.\n\n Own Id: OTP-5931\n\n- Type checks have been added to functions in `lists.erl`.\n\n Own Id: OTP-5939","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The new STDLIB module `erl_expand_records` expands records in abstract code.\n It is used by the Erlang shell, which means that Compiler is no longer used by\n the shell.\n\n Own Id: OTP-5876 Aux Id: OTP-5435\n\n- The compiler will now warn that the `megaco:format_versions/1` function is\n deprecated.\n\n Own Id: OTP-5976","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.13.11 - STDLIB Release Notes","ref":"notes.html#stdlib-1-13-11"},{"type":"extras","doc":"- When calling `gen_server:enter_loop` with a registered server name, it was\n only checked that the registered name existed, not that it actually was the\n name of the calling process.\n\n Own Id: OTP-5854","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- More detail on `beam_lib:version/1` in documentation.\n\n Own Id: OTP-5789\n\n- The new function `io:read/3` works like `io:read/1,2` but takes a third\n argument, `StartLine`.\n\n Own Id: OTP-5813\n\n- The new function `gen_fsm:enter_loop/4,5,6`, similar to\n `gen_server:enter_loop/3,4,5`, has been added.\n\n Own Id: OTP-5846 Aux Id: seq10163\n\n- The function `c:i/1` is now exported.\n\n Own Id: OTP-5848 Aux Id: seq10164","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.13.10 - STDLIB Release Notes","ref":"notes.html#stdlib-1-13-10"},{"type":"extras","doc":"- A couple of type errors have been fixed in `sofs`.\n\n Own Id: OTP-5739\n\n- The pre-processor used to complain that the macro definition\n '`-define(S(S), ??S).`' was circular, which it isn't. (Thanks to Richard\n Carlsson.)\n\n Own Id: OTP-5777","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 1.13.9 - STDLIB Release Notes","ref":"notes.html#stdlib-1-13-9"},{"type":"extras","doc":"- The linter, QLC and the module `erl_pp` did not handle the new '`fun M:F/A`'\n construct in all situations. This problem has been fixed.\n\n Own Id: OTP-5644","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The manual pages for most of the Kernel and some of the STDLIB modules have\n been updated, in particular regarding type definitions.\n\n The documentation of the return value for `erts:info/1` has been corrected.\n\n The documentation for `erlang:statistics/1` now lists all possible arguments.\n\n Own Id: OTP-5360\n\n- Replaced some tuple funs with the new `fun M:F/A` construct.\n\n The high-order functions in the lists module no longer accept bad funs under\n any circumstances. '`lists:map(bad_fun, [])`' used to return '`[]`' but now\n causes an exception.\n\n Unused, broken compatibility code in the `ets` module was removed. (Thanks to\n Dialyzer.)\n\n Eliminated 5 discrepancies found by Dialyzer in the Appmon application.\n\n Own Id: OTP-5633\n\n- The `c:i/0` function will now run in a paged mode if there are more than 100\n processes in the system. (Thanks to Ulf Wiger.)\n\n `erlang:system_info(process_count)` has been optimized and does now return\n exactly the same value as [`length(processes())`](`length/1`). Previously\n `erlang:system_info(process_count)` did not include exiting processes which\n are included in [`length(processes())`](`length/1`).\n\n The `+P` flag for `erl`, which sets the maximum number of processes allowed to\n exist at the same, no longer accepts values higher than 134217727. (You will\n still probably run out of memory before you'll be able to reach that limit.)\n\n Own Id: OTP-5645 Aux Id: seq9984","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.13.8 - STDLIB Release Notes","ref":"notes.html#stdlib-1-13-8"},{"type":"extras","doc":"- Very minor corrections in `beam_lib` and its documentation.\n\n Own Id: OTP-5589","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The `erlang:port_info/1` BIF is now documented. Minor corrections of the\n documentation for `erlang:port_info/2`.\n\n Added a note to the documentation of the `math` module that all functions are\n not available on all platforms.\n\n Added more information about the '`+c`' option in the `erl` man page in the\n ERTS documentation.\n\n Own Id: OTP-5555\n\n- The new `fun M:F/A` construct creates a fun that refers to the latest version\n of `M:F/A`. This syntax is meant to replace tuple funs `{M,F}` which have many\n problems.\n\n The new type test [`is_function(Fun,A)`](`is_function/2`) (which may be used\n in guards) test whether `Fun` is a fun that can be applied with `A` arguments.\n (Currently, `Fun` can also be a tuple fun.)\n\n Own Id: OTP-5584","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.13.7 - STDLIB Release Notes","ref":"notes.html#stdlib-1-13-7"},{"type":"extras","doc":"- `filelib:wildcard/2` was broken (it ignored its second argument).\n\n Also, `filelib:wildcard(\"Filename\")` (where the argument does not contain any\n meta-characters) would always return `[\"Filename\"]`. Corrected so that an\n empty list will be returned if `\"Filename\"` does not actually exist. (Same\n correction in `filelib:wildcard/2`.) (This change is a slight\n incompatibility.)\n\n `filelib:wildcard/1,2` will generate a different exception when given bad\n patterns such as `\"{a,\"`. The exception used to be caused by\n '[`exit(missing_delimiter)`](`exit/1`)' but is now\n '`erlang:error({badpattern,missing_delimiter})`'.\n\n Own Id: OTP-5523 Aux Id: seq9824","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Further improvements of encrypted debug info: New option `encrypt_debug_info`\n for compiler.\n\n Own Id: OTP-5541 Aux Id: seq9837","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.13.6 - STDLIB Release Notes","ref":"notes.html#stdlib-1-13-6"},{"type":"extras","doc":"- When opening a Dets table read only an attempt was sometimes made to re-hash\n the table resulting in an error message. This problem has been fixed.\n\n Own Id: OTP-5487 Aux Id: OTP-4989","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- It is now possible to encrypt the debug information in Beam files, to help\n keep the source code secret. See the documentation for `compile` on how to\n provide the key for encrypting, and the documentation for `beam_lib` on how to\n provide the key for decryption so that tools such as the Debugger, Xref, or\n Cover can be used.\n\n The `beam_lib:chunks/2` functions now accepts an additional chunk type\n `compile_info` to retrieve the compilation information directly as a term.\n (Thanks to Tobias Lindahl.)\n\n Own Id: OTP-5460 Aux Id: seq9787","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.13.5 - STDLIB Release Notes","ref":"notes.html#stdlib-1-13-5"},{"type":"extras","doc":"- Closing a Dets table kept in RAM would cause a crash if the file could not be\n written. This problem has been fixed by returning an error tuple.\n\n Own Id: OTP-5402\n\n- `erl_pp` now correctly pretty-prints `fun F/A`.\n\n Own Id: OTP-5412\n\n- The Erlang shell failed if the compiler was not in the code path. This problem\n has been fixed, but in order to evaluate records the compiler is still needed.\n\n Own Id: OTP-5435\n\n- Corrected the example in the documentation for `ets:match/2`. Also clarified\n that `ets:update_counter/3` updates the counter atomically. (Thanks to Anders\n Svensson.)\n\n Own Id: OTP-5452 Aux Id: seq9770, seq9789","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The possibility to start the Erlang shell in parallel with the rest of the\n system was reintroduced for backwards compatibility in STDLIB 1.13.1. The flag\n to be used for this is now called `async_shell_start` and has been documented.\n New shells started from the JCL menu are not synchronized with `init` anymore.\n This makes it possible to start a new shell (e.g. for debugging purposes) even\n if the initial shell has not come up.\n\n Own Id: OTP-5406 Aux Id: OTP-5218\n\n- The compiler will now produce warnings when using the deprecated functions in\n the `snmp` module.\n\n Own Id: OTP-5425\n\n- The function `c:zi/0` has been removed. Use `c:i/0` instead.\n\n Own Id: OTP-5432\n\n- Corrected two minor bugs found by the Dialyzer: Calling a parameterized module\n from a restricted shell (i.e. if `shell:start_restricted/1` has been used)\n would crash the shell evaluator. A debug printout in `gen_fsm` had a clause\n that would never match; causing less information to be printed.\n\n And a somewhat more serious one also found by Dialyzer: `rpc:yield/1` would\n crash unless the call started by `rpc:async_call/4` had already finished;\n `rpc:nb_yield(Key,infinity)` would also crash.\n\n Cleaned up and removed redundant code found by Dialyzer in\n `erlang:dmonitor_p/2`.\n\n Own Id: OTP-5462","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.13.4 - STDLIB Release Notes","ref":"notes.html#stdlib-1-13-4"},{"type":"extras","doc":"- Bugs in the Erlang shell have been fixed.\n\n Own Id: OTP-5327\n\n- Some dead code reported by Dialyzer was eliminated.\n\n A bug in `dbg` when tracing to wrap trace files has been corrected. It failed\n to delete any already existing wrap trace files with the same names when\n starting a new wrap trace.\n\n Own Id: OTP-5329\n\n- The linter could output invalid warnings about bit patterns in record\n initializations. This problem has been fixed.\n\n Own Id: OTP-5338\n\n- `ordsets:is_set(NoList)`, where `NoList` is any term except a list, would\n crash. For consistency with `sets:is_set/1` and `gb_sets:is_set/1`, it now\n returns `false`.\n\n Own Id: OTP-5341\n\n- A BIF `erlang:raise/3` has been added. See the manual for details. It is\n intended for internal system programming only, advanced error handling.\n\n Own Id: OTP-5376 Aux Id: OTP-5257","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The `deprecated` attribute is now checked by the linter. See `m:xref` for a\n description of the `deprecated` attribute.\n\n Own Id: OTP-5276\n\n- The restricted shell will now indicate if the return value from a user\n predicate is on an incorrect form.\n\n Own Id: OTP-5335","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.13.3 - STDLIB Release Notes","ref":"notes.html#stdlib-1-13-3"},{"type":"extras","doc":"- Bugs concerning unused and shadowed variables have been fixed in the linter.\n\n Own Id: OTP-5091\n\n- A bug in the evaluator that caused the shell to choke on bit syntax\n expressions has been fixed.\n\n Own Id: OTP-5237\n\n- `io:format/2` et.al no longer crashes for some combinations of precision and\n value for format character \"g\". Previously it crashed if the precision P was 4\n or lower and the absolute value of the float to print was lower than 10^4 but\n 10^(P-1) or higher. Now it will not crash depending on the value of the float.\n\n Own Id: OTP-5263\n\n- Bugs in the handling of the bit syntax have been fixed in the Erlang shell.\n\n Own Id: OTP-5269\n\n- `gb_sets:del_element/2` was changed to do the same as `gb_sets:delete_any/2`\n which was the original intention, not as `gb_sets:delete/2`. Code that relies\n on `gb_sets:del_element/2` causing an error if the element does not exist must\n be changed to call `gb_sets:delete/2` instead.\n\n The documentation was also updated to explicitly document functions that were\n only referred to as 'aliases' of a documented function. Also, a list of all\n functions common to the `gb_sets`, `sets`, and `ordsets` was added.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-5277\n\n- Debug messages have been removed from the QLC module.\n\n Own Id: OTP-5283","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The size of continuations returned from `dets:match/1,3`,\n `dets:match_object/1,3`, and `dets:select/1,3` has been reduced. This affects\n the amount of data Mnesia sends between nodes while evaluating QLC queries.\n\n Own Id: OTP-5232","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.13.2 - STDLIB Release Notes","ref":"notes.html#stdlib-1-13-2"},{"type":"extras","doc":"- The `-rsh` switch for starting a remote shell (introduced with OTP-5210)\n clashed with an already existing switch used by `slave`. Therefore the switch\n for the remote shell is now instead named `-remsh`.\n\n Own Id: OTP-5248 Aux Id: OTP-5210","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.13.1 - STDLIB Release Notes","ref":"notes.html#stdlib-1-13-1"},{"type":"extras","doc":"- The Pman 'trace shell' functionality was broken as has now been fixed.\n Furthermore, Pman could not correctly find the pid of the active shell if more\n than one shell process was running on the node. This has also been corrected.\n\n Own Id: OTP-5191\n\n- When the undocumented feature \"parameterized modules\" was used, the ?MODULE\n macro did not work correctly.\n\n Own Id: OTP-5224","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- You can now start Erlang with the `-rsh` flag which gives you a remote initial\n shell instead of a local one. Example:\n\n ```text\n erl -sname this_node -rsh other_node@other_host\n ```\n\n Own Id: OTP-5210\n\n- The man page for the `lists` module has been updated with description of the\n new `zip`, `unzip`, and `partition/2` functions.\n\n Own Id: OTP-5213\n\n- The top level group leader used to be listed as job #1 in the job list in JCL\n mode. Since there is no shell associated with this process that can be\n connected to, it will no longer be listed.\n\n Own Id: OTP-5214\n\n- The possibility to start the Erlang shell in parallel with the rest of the\n system has been reintroduced for backwards compatibility. Note that this old\n behaviour is error prone and should not be used unless for some reason\n necessary.\n\n Own Id: OTP-5218 Aux Id: seq9534\n\n- The `shell` commands `rr/1,2,3` now accepts wildcards when reading record\n definitions from BEAM files.\n\n Own Id: OTP-5226","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"\n# Introduction","title":"Introduction","ref":"introduction.html"},{"type":"extras","doc":"The Standard Erlang Libraries application, _STDLIB_, is mandatory in the sense\nthat the minimal system based on Erlang/OTP consists of _STDLIB_ and _Kernel_.\n\n_STDLIB_ contains the following functional areas:\n\n- Erlang shell\n- Command interface\n- Query interface\n- Interface to standard Erlang I/O servers\n- Interface to the Erlang built-in term storage BIFs\n- Regular expression matching functions for strings and binaries\n- Finite state machine\n- Event handling\n- Functions for the server of a client-server relation\n- Function to control applications in a distributed manner\n- Start and control of slave nodes\n- Operations on finite sets and relations represented as sets\n- Library for handling binary data\n- Disk-based term storage\n- List processing\n- Maps processing","title":"Scope - Introduction","ref":"introduction.html#scope"},{"type":"extras","doc":"It is assumed that the reader is familiar with the Erlang programming language.","title":"Prerequisites - Introduction","ref":"introduction.html#prerequisites"},{"type":"extras","doc":"\n# The Erlang I/O Protocol\n\nThe I/O protocol in Erlang enables bi-directional communication between clients\nand servers.\n\n- The I/O server is a process that handles the requests and performs the\n requested task on, for example, an I/O device.\n- The client is any Erlang process wishing to read or write data from/to the I/O\n device.\n\nThe common I/O protocol has been present in OTP since the beginning, but has\nbeen undocumented and has also evolved over the years. In an addendum to Robert\nVirding's rationale, the original I/O protocol is described. This section\ndescribes the current I/O protocol.\n\nThe original I/O protocol was simple and flexible. Demands for memory efficiency\nand execution time efficiency have triggered extensions to the protocol over the\nyears, making the protocol larger and somewhat less easy to implement than the\noriginal. It can certainly be argued that the current protocol is too complex,\nbut this section describes how it looks today, not how it should have looked.\n\nThe basic ideas from the original protocol still hold. The I/O server and client\ncommunicate with one single, rather simplistic protocol and no server state is\never present in the client. Any I/O server can be used together with any client\ncode, and the client code does not need to be aware of the I/O device that the\nI/O server communicates with.","title":"The Erlang I/O Protocol","ref":"io_protocol.html"},{"type":"extras","doc":"As described in Robert's paper, I/O servers and clients communicate using\n`io_request`/`io_reply` tuples as follows:\n\n```erlang\n{io_request, From, ReplyAs, Request}\n{io_reply, ReplyAs, Reply}\n```\n\nThe client sends an `io_request` tuple to the I/O server and the server\neventually sends a corresponding `io_reply` tuple.\n\n- `From` is the `t:pid/0` of the client, the process which the I/O server sends\n the I/O reply to.\n- `ReplyAs` can be any datum and is returned in the corresponding `io_reply`.\n The `m:io` module monitors the I/O server and uses the monitor reference as\n the `ReplyAs` datum. A more complicated client can have many outstanding I/O\n requests to the same I/O server and can use different references (or something\n else) to differentiate among the incoming I/O replies. Element `ReplyAs` is to\n be considered opaque by the I/O server.\n\n Notice that the `t:pid/0` of the I/O server is not explicitly present in tuple\n `io_reply`. The reply can be sent from any process, not necessarily the actual\n I/O server.\n\n- `Request` and `Reply` are described below.\n\nWhen an I/O server receives an `io_request` tuple, it acts upon the `Request`\npart and eventually sends an `io_reply` tuple with the corresponding `Reply`\npart.","title":"Protocol Basics - The Erlang I/O Protocol","ref":"io_protocol.html#protocol-basics"},{"type":"extras","doc":"To output characters on an I/O device, the following `Request`s exist:\n\n```erlang\n{put_chars, Encoding, Characters}\n{put_chars, Encoding, Module, Function, Args}\n```\n\n- `Encoding` is `unicode` or `latin1`, meaning that the characters are (in case\n of binaries) encoded as UTF-8 or ISO Latin-1 (pure bytes). A well-behaved I/O\n server is also to return an error indication if list elements contain\n integers > 255 when `Encoding` is set to `latin1`.\n\n Notice that this does not in any way tell how characters are to be put on the\n I/O device or handled by the I/O server. Different I/O servers can handle the\n characters however they want, this only tells the I/O server which format the\n data is expected to have. In the `Module`/`Function`/`Args` case, `Encoding`\n tells which format the designated function produces.\n\n Notice also that byte-oriented data is simplest sent using the ISO Latin-1\n encoding.\n\n- `Characters` are the data to be put on the I/O device. If `Encoding` is\n `latin1`, this is an `t:iolist/0`. If `Encoding` is `unicode`, this is an\n Erlang standard mixed Unicode list (one integer in a list per character,\n characters in binaries represented as UTF-8).\n- `Module`, `Function`, and `Args` denote a function that is called to produce\n the data (like `io_lib:format/2`).\n\n `Args` is a list of arguments to the function. The function is to produce data\n in the specified `Encoding`. The I/O server is to call the function as\n [`apply(Mod, Func, Args)`](`apply/3`) and put the returned data on the I/O\n device as if it was sent in a `{put_chars, Encoding, Characters}` request. If\n the function returns anything else than a binary or list, or throws an\n exception, an error is to be sent back to the client.\n\nThe I/O server replies to the client with an `io_reply` tuple, where element\n`Reply` is one of:\n\n```erlang\nok\n{error, Error}\n```\n\n- `Error` describes the error to the client, which can do whatever it wants with\n it. The `m:io` module typically returns it \"as is\".","title":"Output Requests - The Erlang I/O Protocol","ref":"io_protocol.html#output-requests"},{"type":"extras","doc":"To read characters from an I/O device, the following `Request`s exist:\n\n```erlang\n{get_until, Encoding, Prompt, Module, Function, ExtraArgs}\n```\n\n- `Encoding` denotes how data is to be sent back to the client and what data is\n sent to the function denoted by `Module`/`Function`/`ExtraArgs`. If the\n function supplied returns data as a list, the data is converted to this\n encoding. If the function supplied returns data in some other format, no\n conversion can be done, and it is up to the client-supplied function to return\n data in a proper way.\n\n If `Encoding` is `latin1`, lists of integers `0..255` or binaries containing\n plain bytes are sent back to the client when possible. If `Encoding` is\n `unicode`, lists with integers in the whole Unicode range or binaries encoded\n in UTF-8 are sent to the client. The user-supplied function always sees lists\n of integers, never binaries, but the list can contain numbers > 255 if\n `Encoding` is `unicode`.\n\n- `Prompt` is a list of characters (not mixed, no binaries) or an atom to be\n output as a prompt for input on the I/O device. `Prompt` is often ignored by\n the I/O server; if set to `''`, it is always to be ignored (and results in\n nothing being written to the I/O device).\n- `Module`, `Function`, and `ExtraArgs` denote a function and arguments to\n determine when enough data is written. The function is to take two more\n arguments, the last state, and a list of characters. The function is to return\n one of:\n\n ```erlang\n {done, Result, RestChars}\n {more, Continuation}\n ```\n\n `Result` can be any Erlang term, but if it is a `t:list/0`, the I/O server can\n convert it to a `t:binary/0` of appropriate format before returning it to the\n client, if the I/O server is set in binary mode (see below).\n\n The function is called with the data the I/O server finds on its I/O device,\n returning one of:\n\n - `{done, Result, RestChars}` when enough data is read. In this case `Result`\n is sent to the client and `RestChars` is kept in the I/O server as a buffer\n for later input.\n - `{more, Continuation}`, which indicates that more characters are needed to\n complete the request.\n\n `Continuation` is sent as the state in later calls to the function when more\n characters are available. When no more characters are available, the function\n must return `{done, eof, Rest}`. The initial state is the empty list. The data\n when an end of file is reached on the IO device is the atom `eof`.\n\n An emulation of the `get_line` request can be (inefficiently) implemented\n using the following functions:\n\n ```erlang\n -module(demo).\n -export([until_newline/3, get_line/1]).\n\n until_newline(_ThisFar,eof,_MyStopCharacter) ->\n {done,eof,[]};\n until_newline(ThisFar,CharList,MyStopCharacter) ->\n case\n lists:splitwith(fun(X) -> X =/= MyStopCharacter end, CharList)\n of\n \t{L,[]} ->\n {more,ThisFar++L};\n \t{L2,[MyStopCharacter|Rest]} ->\n \t {done,ThisFar++L2++[MyStopCharacter],Rest}\n end.\n\n get_line(IoServer) ->\n IoServer ! {io_request,\n self(),\n IoServer,\n {get_until, unicode, '', ?MODULE, until_newline, [$\\n]}},\n receive\n {io_reply, IoServer, Data} ->\n \t Data\n end.\n ```\n\n Notice that the last element in the `Request` tuple (`[$\\n]`) is appended to\n the argument list when the function is called. The function is to be called\n like [`apply(Module, Function, [ State, Data | ExtraArgs ])`](`apply/3`) by\n the I/O server.\n\nA fixed number of characters is requested using the following `Request`:\n\n```erlang\n{get_chars, Encoding, Prompt, N}\n```\n\n- `Encoding` and `Prompt` as for `get_until`.\n- `N` is the number of characters to be read from the I/O device.\n\nA single line (as in former example) is requested with the following `Request`:\n\n```erlang\n{get_line, Encoding, Prompt}\n```\n\n- `Encoding` and `Prompt` as for `get_until`.\n\nClearly, `get_chars` and `get_line` could be implemented with the `get_until`\nrequest (and indeed they were originally), but demands for efficiency have made\nthese additions necessary.\n\nThe I/O server replies to the client with an `io_reply` tuple, where element\n`Reply` is one of:\n\n```erlang\nData\neof\n{error, Error}\n```\n\n- `Data` is the characters read, in list or binary form (depending on the I/O\n server mode, see the next section).\n- `eof` is returned when input end is reached and no more data is available to\n the client process.\n- `Error` describes the error to the client, which can do whatever it wants with\n it. The `m:io` module typically returns it as is.","title":"Input Requests - The Erlang I/O Protocol","ref":"io_protocol.html#input-requests"},{"type":"extras","doc":"Demands for efficiency when reading data from an I/O server has not only lead to\nthe addition of the `get_line` and `get_chars` requests, but has also added the\nconcept of I/O server options. No options are mandatory to implement, but all\nI/O servers in the Erlang standard libraries honor the `binary` option, which\nallows element `Data` of the `io_reply` tuple to be a binary instead of a list\n_when possible_. If the data is sent as a binary, Unicode data is sent in the\nstandard Erlang Unicode format, that is, UTF-8 (notice that the function of the\n`get_until` request still gets list data regardless of the I/O server mode).\n\nNotice that the `get_until` request allows for a function with the data\nspecified as always being a list. Also, the return value data from such a\nfunction can be of any type (as is indeed the case when an\n[`io:fread/2,3`](`io:fread/2`) request is sent to an I/O server). The client\nmust be prepared for data received as answers to those requests to be in various\nforms. However, the I/O server is to convert the results to binaries whenever\npossible (that is, when the function supplied to `get_until` returns a list).\nThis is done in the example in section\n[An Annotated and Working Example I/O Server](io_protocol.md#example_io_server).\n\nAn I/O server in binary mode affects the data sent to the client, so that it\nmust be able to handle binary data. For convenience, the modes of an I/O server\ncan be set and retrieved using the following I/O requests:\n\n```erlang\n{setopts, Opts}\n```\n\n- `Opts` is a list of options in the format recognized by the `m:proplists`\n module (and by the I/O server).\n\nAs an example, the I/O server for the interactive shell (in `group.erl`)\nunderstands the following options:\n\n```erlang\n{binary, boolean()} (or binary/list)\n{echo, boolean()}\n{expand_fun, fun()}\n{encoding, unicode/latin1} (or unicode/latin1)\n```\n\nOptions `binary` and `encoding` are common for all I/O servers in OTP, while\n`echo` and `expand` are valid only for this I/O server. Option `unicode`\nnotifies how characters are put on the physical I/O device, that is, if the\nterminal itself is Unicode-aware. It does not affect how characters are sent in\nthe I/O protocol, where each request contains encoding information for the\nprovided or returned data.\n\nThe I/O server is to send one of the following as `Reply`:\n\n```erlang\nok\n{error, Error}\n```\n\nAn error (preferably `enotsup`) is to be expected if the option is not supported\nby the I/O server (like if an `echo` option is sent in a `setopts` request to a\nplain file).\n\nTo retrieve options, the following request is used:\n\n```erlang\ngetopts\n```\n\nThis request asks for a complete list of all options supported by the I/O server\nas well as their current values.\n\nThe I/O server replies:\n\n```erlang\nOptList\n{error, Error}\n```\n\n- `OptList` is a list of tuples `{Option, Value}`, where `Option` always is an\n atom.","title":"I/O Server Modes - The Erlang I/O Protocol","ref":"io_protocol.html#i-o-server-modes"},{"type":"extras","doc":"The `Request` element can in itself contain many `Request`s by using the\nfollowing format:\n\n```erlang\n{requests, Requests}\n```\n\n- `Requests` is a list of valid `io_request` tuples for the protocol. They must\n be executed in the order that they appear in the list. The execution is to\n continue until one of the requests results in an error or the list is\n consumed. The result of the last request is sent back to the client.\n\nThe I/O server can, for a list of requests, send any of the following valid\nresults in the reply, depending on the requests in the list:\n\n```erlang\nok\n{ok, Data}\n{ok, Options}\n{error, Error}\n```","title":"Multiple I/O Requests - The Erlang I/O Protocol","ref":"io_protocol.html#multiple-i-o-requests"},{"type":"extras","doc":"The following I/O request is optional to implement and a client is to be\nprepared for an error return:\n\n```erlang\n{get_geometry, Geometry}\n```\n\n- `Geometry` is the atom `rows` or the atom `columns`.\n\nThe I/O server is to send one of the following as `Reply`:\n\n```erlang\nN\n{error, Error}\n```\n\n- `N` is the number of character rows or columns that the I/O device has, if\n applicable to the I/O device handled by the I/O server, otherwise\n `{error, enotsup}` is a good answer.","title":"Optional I/O Request - The Erlang I/O Protocol","ref":"io_protocol.html#optional-i-o-request"},{"type":"extras","doc":"If an I/O server encounters a request that it does not recognize (that is, the\n`io_request` tuple has the expected format, but the `Request` is unknown), the\nI/O server is to send a valid reply with the error tuple:\n\n```erlang\n{error, request}\n```\n\nThis makes it possible to extend the protocol with optional requests and for the\nclients to be somewhat backward compatible.","title":"Unimplemented Request Types - The Erlang I/O Protocol","ref":"io_protocol.html#unimplemented-request-types"},{"type":"extras","doc":"[](){: #example_io_server }\n\nAn I/O server is any process capable of handling the I/O protocol. There is no\ngeneric I/O server behavior, but could well be. The framework is simple, a\nprocess handling incoming requests, usually both I/O-requests and other I/O\ndevice-specific requests (positioning, closing, and so on).\n\nThe example I/O server stores characters in an ETS table, making up a fairly\ncrude RAM file.\n\nThe module begins with the usual directives, a function to start the I/O server\nand a main loop handling the requests:\n\n```erlang\n-module(ets_io_server).\n\n-export([start_link/0, init/0, loop/1, until_newline/3, until_enough/3]).\n\n-define(CHARS_PER_REC, 10).\n\n-record(state, {\n\t table,\n\t position, % absolute\n\t mode % binary | list\n\t }).\n\nstart_link() ->\n spawn_link(?MODULE,init,[]).\n\ninit() ->\n Table = ets:new(noname,[ordered_set]),\n ?MODULE:loop(#state{table = Table, position = 0, mode=list}).\n\nloop(State) ->\n receive\n\t{io_request, From, ReplyAs, Request} ->\n\t case request(Request,State) of\n\t\t{Tag, Reply, NewState} when Tag =:= ok; Tag =:= error ->\n\t\t reply(From, ReplyAs, Reply),\n\t\t ?MODULE:loop(NewState);\n\t\t{stop, Reply, _NewState} ->\n\t\t reply(From, ReplyAs, Reply),\n\t\t exit(Reply)\n\t end;\n\t%% Private message\n\t{From, rewind} ->\n\t From ! {self(), ok},\n\t ?MODULE:loop(State#state{position = 0});\n\t_Unknown ->\n\t ?MODULE:loop(State)\n end.\n```\n\nThe main loop receives messages from the client (which can use the the `m:io`\nmodule to send requests). For each request, the function `request/2` is called\nand a reply is eventually sent using function `reply/3`.\n\nThe \"private\" message `{From, rewind}` results in the current position in the\npseudo-file to be reset to `0` (the beginning of the \"file\"). This is a typical\nexample of I/O device-specific messages not being part of the I/O protocol. It\nis usually a bad idea to embed such private messages in `io_request` tuples, as\nthat can confuse the reader.\n\nFirst, we examine the reply function:\n\n```erlang\nreply(From, ReplyAs, Reply) ->\n From ! {io_reply, ReplyAs, Reply}.\n```\n\nIt sends the `io_reply` tuple back to the client, providing element `ReplyAs`\nreceived in the request along with the result of the request, as described\nearlier.\n\nWe need to handle some requests. First the requests for writing characters:\n\n```erlang\nrequest({put_chars, Encoding, Chars}, State) ->\n put_chars(unicode:characters_to_list(Chars,Encoding),State);\nrequest({put_chars, Encoding, Module, Function, Args}, State) ->\n try\n\trequest({put_chars, Encoding, apply(Module, Function, Args)}, State)\n catch\n\t_:_ ->\n\t {error, {error,Function}, State}\n end;\n```\n\nThe `Encoding` says how the characters in the request are represented. We want\nto store the characters as lists in the ETS table, so we convert them to lists\nusing function `unicode:characters_to_list/2`. The conversion function\nconveniently accepts the encoding types `unicode` and `latin1`, so we can use\n`Encoding` directly.\n\nWhen `Module`, `Function`, and `Arguments` are provided, we apply it and do the\nsame with the result as if the data was provided directly.\n\nWe handle the requests for retrieving data:\n\n```erlang\nrequest({get_until, Encoding, _Prompt, M, F, As}, State) ->\n get_until(Encoding, M, F, As, State);\nrequest({get_chars, Encoding, _Prompt, N}, State) ->\n %% To simplify the code, get_chars is implemented using get_until\n get_until(Encoding, ?MODULE, until_enough, [N], State);\nrequest({get_line, Encoding, _Prompt}, State) ->\n %% To simplify the code, get_line is implemented using get_until\n get_until(Encoding, ?MODULE, until_newline, [$\\n], State);\n```\n\nHere we have cheated a little by more or less only implementing `get_until` and\nusing internal helpers to implement `get_chars` and `get_line`. In production\ncode, this can be inefficient, but that depends on the frequency of the\ndifferent requests. Before we start implementing functions `put_chars/2` and\n`get_until/5`, we examine the few remaining requests:\n\n```erlang\nrequest({get_geometry,_}, State) ->\n {error, {error,enotsup}, State};\nrequest({setopts, Opts}, State) ->\n setopts(Opts, State);\nrequest(getopts, State) ->\n getopts(State);\nrequest({requests, Reqs}, State) ->\n multi_request(Reqs, {ok, ok, State});\n```\n\nRequest `get_geometry` has no meaning for this I/O server, so the reply is\n`{error, enotsup}`. The only option we handle is `binary`/`list`, which is done\nin separate functions.\n\nThe multi-request tag (`requests`) is handled in a separate loop function\napplying the requests in the list one after another, returning the last result.\n\n`{error, request}` must be returned if the request is not recognized:\n\n```erlang\nrequest(_Other, State) ->\n {error, {error, request}, State}.\n```\n\nNext we handle the different requests, first the fairly generic multi-request\ntype:\n\n```erlang\nmulti_request([R|Rs], {ok, _Res, State}) ->\n multi_request(Rs, request(R, State));\nmulti_request([_|_], Error) ->\n Error;\nmulti_request([], Result) ->\n Result.\n```\n\nWe loop through the requests one at the time, stopping when we either encounter\nan error or the list is exhausted. The last return value is sent back to the\nclient (it is first returned to the main loop and then sent back by function\n`io_reply`).\n\nRequests `getopts` and `setopts` are also simple to handle. We only change or\nread the state record:\n\n```erlang\nsetopts(Opts0,State) ->\n Opts = proplists:unfold(\n\t proplists:substitute_negations(\n\t [{list,binary}],\n\t Opts0)),\n case check_valid_opts(Opts) of\n\ttrue ->\n\t case proplists:get_value(binary, Opts) of\n\t\t true ->\n\t\t\t{ok,ok,State#state{mode=binary}};\n\t\t false ->\n\t\t\t{ok,ok,State#state{mode=binary}};\n\t\t _ ->\n\t\t\t{ok,ok,State}\n\t\tend;\n\tfalse ->\n\t {error,{error,enotsup},State}\n end.\ncheck_valid_opts([]) ->\n true;\ncheck_valid_opts([{binary,Bool}|T]) when is_boolean(Bool) ->\n check_valid_opts(T);\ncheck_valid_opts(_) ->\n false.\n\ngetopts(#state{mode=M} = S) ->\n {ok,[{binary, case M of\n\t\t binary ->\n\t\t\t true;\n\t\t _ ->\n\t\t\t false\n\t\t end}],S}.\n```\n\nAs a convention, all I/O servers handle both `{setopts, [binary]}`,\n`{setopts, [list]}`, and `{setopts,[{binary, boolean()}]}`, hence the trick with\n`proplists:substitute_negations/2` and `proplists:unfold/1`. If invalid options\nare sent to us, we send `{error, enotsup}` back to the client.\n\nRequest `getopts` is to return a list of `{Option, Value}` tuples. This has the\ntwofold function of providing both the current values and the available options\nof this I/O server. We have only one option, and hence return that.\n\nSo far this I/O server is fairly generic (except for request `rewind` handled in\nthe main loop and the creation of an ETS table). Most I/O servers contain code\nsimilar to this one.\n\nTo make the example runnable, we start implementing the reading and writing of\nthe data to/from the ETS table. First function `put_chars/3`:\n\n```erlang\nput_chars(Chars, #state{table = T, position = P} = State) ->\n R = P div ?CHARS_PER_REC,\n C = P rem ?CHARS_PER_REC,\n [ apply_update(T,U) || U <- split_data(Chars, R, C) ],\n {ok, ok, State#state{position = (P + length(Chars))}}.\n```\n\nWe already have the data as (Unicode) lists and therefore only split the list in\nruns of a predefined size and put each run in the table at the current position\n(and forward). Functions `split_data/3` and `apply_update/2` are implemented\nbelow.\n\nNow we want to read data from the table. Function `get_until/5` reads data and\napplies the function until it says that it is done. The result is sent back to\nthe client:\n\n```erlang\nget_until(Encoding, Mod, Func, As,\n\t #state{position = P, mode = M, table = T} = State) ->\n case get_loop(Mod,Func,As,T,P,[]) of\n\t{done,Data,_,NewP} when is_binary(Data); is_list(Data) ->\n\t if\n\t\tM =:= binary ->\n\t\t {ok,\n\t\t unicode:characters_to_binary(Data, unicode, Encoding),\n\t\t State#state{position = NewP}};\n\t\ttrue ->\n\t\t case check(Encoding,\n\t\t unicode:characters_to_list(Data, unicode))\n of\n\t\t\t{error, _} = E ->\n\t\t\t {error, E, State};\n\t\t\tList ->\n\t\t\t {ok, List,\n\t\t\t State#state{position = NewP}}\n\t\t end\n\t end;\n\t{done,Data,_,NewP} ->\n\t {ok, Data, State#state{position = NewP}};\n\tError ->\n\t {error, Error, State}\n end.\n\nget_loop(M,F,A,T,P,C) ->\n {NewP,L} = get(P,T),\n case catch apply(M,F,[C,L|A]) of\n\t{done, List, Rest} ->\n\t {done, List, [], NewP - length(Rest)};\n\t{more, NewC} ->\n\t get_loop(M,F,A,T,NewP,NewC);\n\t_ ->\n\t {error,F}\n end.\n```\n\nHere we also handle the mode (`binary` or `list`) that can be set by request\n`setopts`. By default, all OTP I/O servers send data back to the client as\nlists, but switching mode to `binary` can increase efficiency if the I/O server\nhandles it in an appropriate way. The implementation of `get_until` is difficult\nto get efficient, as the supplied function is defined to take lists as\narguments, but `get_chars` and `get_line` can be optimized for binary mode.\nHowever, this example does not optimize anything.\n\nIt is important though that the returned data is of the correct type depending\non the options set. We therefore convert the lists to binaries in the correct\nencoding _if possible_ before returning. The function supplied in the\n`get_until` request tuple can, as its final result return anything, so only\nfunctions returning lists can get them converted to binaries. If the request\ncontains encoding tag `unicode`, the lists can contain all Unicode code points\nand the binaries are to be in UTF-8. If the encoding tag is `latin1`, the client\nis only to get characters in the range `0..255`. Function `check/2` takes care\nof not returning arbitrary Unicode code points in lists if the encoding was\nspecified as `latin1`. If the function does not return a list, the check cannot\nbe performed and the result is that of the supplied function untouched.\n\nTo manipulate the table we implement the following utility functions:\n\n```erlang\ncheck(unicode, List) ->\n List;\ncheck(latin1, List) ->\n try\n\t[ throw(not_unicode) || X <- List,\n\t\t\t\tX > 255 ],\n\tList\n catch\n\tthrow:_ ->\n\t {error,{cannot_convert, unicode, latin1}}\n end.\n```\n\nThe function check provides an error tuple if Unicode code points > 255 are to\nbe returned if the client requested `latin1`.\n\nThe two functions `until_newline/3` and `until_enough/3` are helpers used\ntogether with function `get_until/5` to implement `get_chars` and `get_line`\n(inefficiently):\n\n```erlang\nuntil_newline([],eof,_MyStopCharacter) ->\n {done,eof,[]};\nuntil_newline(ThisFar,eof,_MyStopCharacter) ->\n {done,ThisFar,[]};\nuntil_newline(ThisFar,CharList,MyStopCharacter) ->\n case\n lists:splitwith(fun(X) -> X =/= MyStopCharacter end, CharList)\n of\n\t{L,[]} ->\n {more,ThisFar++L};\n\t{L2,[MyStopCharacter|Rest]} ->\n\t {done,ThisFar++L2++[MyStopCharacter],Rest}\n end.\n\nuntil_enough([],eof,_N) ->\n {done,eof,[]};\nuntil_enough(ThisFar,eof,_N) ->\n {done,ThisFar,[]};\nuntil_enough(ThisFar,CharList,N)\n when length(ThisFar) + length(CharList) >= N ->\n {Res,Rest} = my_split(N,ThisFar ++ CharList, []),\n {done,Res,Rest};\nuntil_enough(ThisFar,CharList,_N) ->\n {more,ThisFar++CharList}.\n```\n\nAs can be seen, the functions above are just the type of functions that are to\nbe provided in `get_until` requests.\n\nTo complete the I/O server, we only need to read and write the table in an\nappropriate way:\n\n```erlang\nget(P,Tab) ->\n R = P div ?CHARS_PER_REC,\n C = P rem ?CHARS_PER_REC,\n case ets:lookup(Tab,R) of\n\t[] ->\n\t {P,eof};\n\t[{R,List}] ->\n\t case my_split(C,List,[]) of\n\t\t{_,[]} ->\n\t\t {P+length(List),eof};\n\t\t{_,Data} ->\n\t\t {P+length(Data),Data}\n\t end\n end.\n\nmy_split(0,Left,Acc) ->\n {lists:reverse(Acc),Left};\nmy_split(_,[],Acc) ->\n {lists:reverse(Acc),[]};\nmy_split(N,[H|T],Acc) ->\n my_split(N-1,T,[H|Acc]).\n\nsplit_data([],_,_) ->\n [];\nsplit_data(Chars, Row, Col) ->\n {This,Left} = my_split(?CHARS_PER_REC - Col, Chars, []),\n [ {Row, Col, This} | split_data(Left, Row + 1, 0) ].\n\napply_update(Table, {Row, Col, List}) ->\n case ets:lookup(Table,Row) of\n\t[] ->\n\t ets:insert(Table,{Row, lists:duplicate(Col,0) ++ List});\n\t[{Row, OldData}] ->\n\t {Part1,_} = my_split(Col,OldData,[]),\n\t {_,Part2} = my_split(Col+length(List),OldData,[]),\n\t ets:insert(Table,{Row, Part1 ++ List ++ Part2})\n end.\n```\n\nThe table is read or written in chunks of `?CHARS_PER_REC`, overwriting when\nnecessary. The implementation is clearly not efficient, it is just working.\n\nThis concludes the example. It is fully runnable and you can read or write to\nthe I/O server by using, for example, the `m:io` module or even the `m:file`\nmodule. It is as simple as that to implement a fully fledged I/O server in\nErlang.","title":"An Annotated and Working Example I/O Server - The Erlang I/O Protocol","ref":"io_protocol.html#an-annotated-and-working-example-i-o-server"},{"type":"extras","doc":"\n# Creating a custom shell\n\nThis guide will show how to create a custom shell. The most common\nuse case for this is to support other languages running on the Erlang VM,\nbut it can also be used to create specialized debugging shells a system.\n\nThis guide will build on top of the built-in [Erlang line editor](`m:edlin`),\nwhich means that the keybindings described in [tty - A Command-Line Interface](`e:erts:tty.md`)\ncan be used edit the input before it is passed to the custom shell. This\nsomewhat limits what the custom shell can do, but it also means that we do not\nhave to implement line editing ourselves. If you need more control over the\nshell, then use [Creating a terminal application](terminal_interface.md) as\na starting-point to build your own line editor and shell.","title":"Creating a custom shell","ref":"custom_shell.html"},{"type":"extras","doc":"The custom shell that we are going to build is a process inspection shell\nthat supports the following commands:\n\n* `list` - lists all processes\n* `inspect pid()` - inspect a process\n* `suspend pid()` - suspend a process\n* `resume pid()` - resume a process\n\nLets get started!","title":"A process inspection shell - Creating a custom shell","ref":"custom_shell.html#a-process-inspection-shell"},{"type":"extras","doc":"The custom shell will be implemented in an `m:escript`, but it could just\nas well be in a regular system or as a remote shell. To start a custom shell\nwe first need to start Erlang in `-noinput` or `-noshell` mode. `m:escript` are\nstarted by default in `-noshell` mode, so we don't have to do anything special here.\nTo start the custom shell we then call `shell:start_interactive/1`.\n\n```\n#!/usr/bin/env escript\n%% pshell.es\n-export([start/0]).\nmain(_Args) ->\n shell:start_interactive({?MODULE, start, []}),\n timer:sleep(infinity). %% Make sure the escript does not exit\n\n-spec start() -> pid().\nstart() ->\n spawn(fun() ->\n io:format(~\"Starting process inspection shell~n\"),\n loop()\n end).\n\nloop() ->\n receive _M -> loop() end.\n```\n\nIf we run the above we will get this:\n\n```\n$ ./pshell.es\nErlang/OTP 28 [DEVELOPMENT] [erts-15.0.1] [source-b395339a02] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]\n\nStarting process inspection shell\n\n```\n\nThe `t:io:standard_io/0` of the created shell process will be set to the\nErlang line editor, which means that we can use the normal `m:io` functions\nto read and write data to the terminal.","title":"Starting with a custom shell - Creating a custom shell","ref":"custom_shell.html#starting-with-a-custom-shell"},{"type":"extras","doc":"Let's start adding the shell interface. We will use `io:get_line/1` to read from\n`t:io:standard_io/0` as this shell will be line based. However, for a more complex\nshell it is better to send [`get_until` I/O requests](io_protocol.md#input-requests)\nas commands read that way can span multiple lines. So we expand our `loop/0` with\na `io:get_line/1` and pass the results to our parser.\n\n```\nloop() ->\n case io:get_line(\"> \") of\n eof -> ok;\n {error, Reason} -> exit(Reason);\n Data -> eval(string:trim(Data))\n end,\n loop().\n\neval(\"list\") ->\n Format = \" ~.10ts | ~.10ts | ~.10ts~n\",\n io:format(Format,[\"Pid\", \"Name\", \"MsgQ Len\"]),\n [begin\n [{registered_name,Name},{message_queue_len,Len}]\n = erlang:process_info(Pid, [registered_name, message_queue_len]),\n io:format(Format,[to_list(Pid), to_list(Name), to_list(Len)])\n end || Pid <- processes()];\neval(Unknown) ->\n io:format(\"Unknown command: '~ts'~n\",[Unknown]).\n\nto_list(Pid) when is_pid(Pid) ->\n pid_to_list(Pid);\nto_list(Atom) when is_atom(Atom) ->\n atom_to_list(Atom);\nto_list(Int) when is_integer(Int) ->\n integer_to_list(Int);\nto_list(List) when is_list(List) ->\n List.\n```\n\nIf we run the above we will get this:\n\n```txt\n$ ./pshell.es\nErlang/OTP 28 [DEVELOPMENT] [erts-15.0.1] [source-b395339a02] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]\n\nStarting process inspection shell\n> list\n Pid | Name | MsgQ Len \n <0.0.0> | init | 0 \n <0.1.0> | erts_code_ | 0 \n <0.2.0> | | 0 \n <0.3.0> | | 0 \n <0.4.0> | | 0 \n <0.5.0> | | 0 \n <0.6.0> | | 0 \n <0.7.0> | | 0 \n <0.8.0> | socket_reg | 0 \n <0.10.0> | | 0 \n <0.11.0> | erl_prim_l | 0 \n <0.43.0> | logger | 0 \n <0.45.0> | applicatio | 0\n...\n```\n\nWith this all in place we can now easily add `inspect`, `suspend` and `resume` as well.\n\n```\neval(\"inspect \" ++ PidStr) ->\n case parse_pid(PidStr) of\n invalid -> ok;\n Pid ->\n [{registered_name, Name}, {memory, Memory}, {messages, Messages}, {status, Status}] =\n erlang:process_info(Pid, [registered_name, memory, messages, status]),\n io:format(\"Pid: ~p~nName: ~ts~nStatus: ~p~nMemory: ~p~nMessages: ~p~n\",\n [Pid, to_list(Name), Status, Memory, Messages])\n end;\neval(\"suspend \" ++ PidStr) ->\n case parse_pid(PidStr) of\n invalid -> ok;\n Pid ->\n erlang:suspend_process(Pid),\n io:format(\"Suspeneded ~ts~n\")\n end;\neval(\"resume \" ++ PidStr) ->\n case parse_pid(PidStr) of\n invalid -> ok;\n Pid ->\n erlang:resumne_process(Pid),\n io:format(\"Resumed ~ts~n\")\n end;\n```","title":"Adding our first command - Creating a custom shell","ref":"custom_shell.html#adding-our-first-command"},{"type":"extras","doc":"Wouldn't it be great if we could add some simple auto-completion for our shell? We can do that\nby setting a `m:edlin_expand` fun for our shell. This is done by calling [`io:setopts([{expand_fun, Fun}])`](`io:setopts/2`). The fun that we provide is will receive the reversed current line from\n`m:edlin` and is expected to return possible expansions. Let's start by adding a simple fun to\nexpand our commands.\n\n```\n-spec start() -> pid().\nstart() ->\n spawn(fun() ->\n io:setopts([{expand_fun, fun expand_fun/1}]),\n io:format(~\"Starting process inspection shell~n\"),\n loop()\n end).\n\n-spec expand_fun(ReverseLine :: string()) -> {yes, string(), list(string())} |\n {no, nil(), nil()}.\nexpand_fun(\"\") -> %% If line is empty, we list all available commands\n {yes, \"\", [\"list\", \"inspect\", \"suspend\", \"resume\"]};\nexpand_fun(Curr) ->\n expand_fun(lists:reverse(Curr), [\"list\", \"inspect\", \"suspend\", \"resume\"]).\n\nexpand_fun(_Curr, []) ->\n {no, \"\", []};\nexpand_fun(Curr, [Cmd | T]) ->\n case lists:prefix(Curr, Cmd) of\n true ->\n %% If Curr is a prefix of Cmd we subtract Curr from Cmd to get the\n %% characters we need to complete with.\n {yes, lists:reverse(lists:reverse(Cmd) -- lists:reverse(Curr)), []};\n false ->\n expand_fun(Curr, T)\n end.\n```\n\nWith the above code we will get expansions of our commands if we hit ` ` in the shell.\nIts possible to make very complex completion algorithms, for example the Erlang shell\nhas completions based on the function specifications of your code. It is important though that\nthe shell still feels responsive, so calling out to a LLM model for completion may or may not\nbe a good idea.\n\nThe complete source code for this example can be found [here](assets/pshell.es).","title":"Adding autocompletion - Creating a custom shell","ref":"custom_shell.html#adding-autocompletion"},{"type":"extras","doc":"\n# Creating a terminal application\n\nThis guide will show how to create a very simple tic-tac-toe game in\nthe shell. We will go through how to read key-strokes and how to update\nthe screen to show the tic-tac-toe board. The game will be implemented as an\n`m:escript`, but it can just as well be implemented in a regular system.\n\nLet us start by drawing the board which will look like this:\n\n```txt\n╔═══════╤═══════╤═══════╗\n║┌─────┐│ │ ║\n║│ ││ │ ║ Place an X by pressing Enter\n║└─────┘│ │ ║\n╟───────┼───────┼───────╢\n║ │ │ ║\n║ │ │ ║\n║ │ │ ║\n╟───────┼───────┼───────╢\n║ │ │ ║\n║ │ │ ║\n║ │ │ ║\n╚═══════╧═══════╧═══════╝\n```\n{: .monospace-font }\n\n\nWe will use the alternate screen buffer for our game so first we need to set that up:\n\n```\n#!/usr/bin/env escript\nmain(_Args) ->\n \n io:put_chars(\"\\e[?1049h\"), %% Enable alternate screen buffer\n io:put_chars(\"\\e[?25l\"), %% Hide the cursor\n draw_board(),\n timer:sleep(5000),\n io:put_chars(\"\\e[?25h\"), %% Show the cursor\n io:put_chars(\"\\e[?1049l\"), %% Disable alternate screen buffer\n ok.\n```\n\nWe then use the box drawing parts of Unicode to draw our board:\n\n```\ndraw_board() ->\n io:put_chars(\"\\e[5;0H\"), %% Move cursor to top left\n io:put_chars(\n [\" ╔═══════╤═══════╤═══════╗\\r\\n\",\n \" ║ │ │ ║\\r\\n\",\n \" ║ │ │ ║ Place an X by pressing Enter\\r\\n\",\n \" ║ │ │ ║\\r\\n\",\n \" ╟───────┼───────┼───────╢\\r\\n\",\n \" ║ │ │ ║\\r\\n\",\n \" ║ │ │ ║\\r\\n\",\n \" ║ │ │ ║\\r\\n\",\n \" ╟───────┼───────┼───────╢\\r\\n\",\n \" ║ │ │ ║\\r\\n\",\n \" ║ │ │ ║\\r\\n\",\n \" ║ │ │ ║\\r\\n\",\n \" ╚═══════╧═══════╧═══════╝\\r\\n\"]),\n ok.\n```\n{: .monospace-font }\n\nLet us add some interactivity to our game! To do that we need to change the\nshell from running in `cooked` to `raw` mode. This is done by calling\n[`shell:start_interactive({noshell, raw})`](`shell:start_interactive/1`).\nWe can then use `io:get_chars/2` to read key strokes from the user. The key\nstrokes will be returned as [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code), \nso we will have need to handle the codes for up, down, left, right and enter.\n\nIt could look something like this:\n\n```\nmain(_Args) ->\n ok = shell:start_interactive({noshell, raw}),\n \n io:put_chars(\"\\e[?1049h\"), %% Enable alternate screen buffer\n io:put_chars(\"\\e[?25l\"), %% Hide the cursor\n draw_board(),\n loop(0),\n io:put_chars(\"\\e[?25h\"), %% Show the cursor\n io:put_chars(\"\\e[?1049l\"), %% Disable alternate screen buffer\n ok.\n\nloop(Pos) ->\n io:put_chars(draw_selection(Pos)),\n %% Read at most 1024 characters from stdin.\n {ok, Chars} = io:get_chars(\"\", 1024),\n case handle_input(Chars, Pos) of\n stop -> stop;\n NewPos ->\n io:put_chars(clear_selection(Pos)),\n loop(NewPos)\n end.\n\nhandle_input(\"\\e[A\" ++ Rest, Pos) ->\n %% Up key\n handle_input(Rest, max(0, Pos - 3));\nhandle_input(\"\\e[B\" ++ Rest, Pos) ->\n %% Down key\n handle_input(Rest, min(8, Pos + 3));\nhandle_input(\"\\e[C\" ++ Rest, Pos) ->\n %% right key\n handle_input(Rest, min(8, Pos + 1));\nhandle_input(\"\\e[D\" ++ Rest, Pos) ->\n %% left key\n handle_input(Rest, max(0, Pos - 1));\nhandle_input(\"q\" ++ _, _State) ->\n stop;\nhandle_input([_ | T], State) ->\n handle_input(T, State);\nhandle_input([], State) ->\n State.\n```\n\nNote that when using `io:get_chars/2` with the shell set in `{noshell, raw}` mode\nit will return as soon as any data is available. The number of characters\nis the maximum number that will be returned. We use 1024 here to make sure that\nwe always get all the data in one read.\n\nWe also need to draw the selection marker, we do this using some simple drawing\nroutines.\n\n```\n%% Clear/draw the selection markers, making sure\n%% not to overwrite if a X or O exists.\n%% \\b = Move cursor left\n%% \\e[C = Move cursor right\n%% \\n = Move cursor down\nclear_selection(Pos) ->\n [set_position(Pos),\n \" \",\"\\b\\b\\b\\b\\b\\b\\b\\n\",\n \" \\e[C\\e[C\\e[C\\e[C\\e[C \",\n \"\\b\\b\\b\\b\\b\\b\\b\\n\",\" \"].\n\ndraw_selection(Pos) ->\n [set_position(Pos),\n \"┌─────┐\",\"\\b\\b\\b\\b\\b\\b\\b\\n\",\n \"│\\e[C\\e[C\\e[C\\e[C\\e[C│\",\n \"\\b\\b\\b\\b\\b\\b\\b\\n\",\"└─────┘\"].\n\n%% Set the cursor position to be at the top\n%% left of the field of the given position\nset_position(Pos) ->\n Row = 6 + (Pos div 3) * 4,\n Col = 7 + (Pos rem 3) * 8,\n io_lib:format(\"\\e[~p;~pH\",[Row, Col]).\n```\n{: #monospace-font }\n\nNow we have a program where we can move the marker around the board.\nTo complete the game we need to add some state so that we know which\nsquares are marked and whos turn it is. You can find the final solution\nin [tic-tac-toe.es](assets/tic-tac-toe.es).","title":"Creating a terminal application","ref":"terminal_interface.html"},{"type":"extras","doc":"\n# Using Unicode in Erlang","title":"Using Unicode in Erlang","ref":"unicode_usage.html"},{"type":"extras","doc":"Implementing support for Unicode character sets is an ongoing process. The\nErlang Enhancement Proposal (EEP) 10 outlined the basics of Unicode support and\nspecified a default encoding in binaries that all Unicode-aware modules are to\nhandle in the future.\n\nHere is an overview what has been done so far:\n\n- The functionality described in EEP10 was implemented in Erlang/OTP R13A.\n- Erlang/OTP R14B01 added support for Unicode filenames, but it was not complete\n and was by default disabled on platforms where no guarantee was given for the\n filename encoding.\n- With Erlang/OTP R16A came support for UTF-8 encoded source code, with\n enhancements to many of the applications to support both Unicode encoded\n filenames and support for UTF-8 encoded files in many circumstances. Most\n notable is the support for UTF-8 in files read by `file:consult/1`, release\n handler support for UTF-8, and more support for Unicode character sets in the\n I/O system.\n- In Erlang/OTP 17.0, the encoding default for Erlang source files was switched\n to UTF-8.\n- In Erlang/OTP 20.0, atoms and function can contain Unicode characters. Module\n names, application names, and node names are still restricted to the ISO\n Latin-1 range.\n\n Support was added for normalizations forms in `unicode` and the `string`\n module now handles utf8-encoded binaries.\n\nThis section outlines the current Unicode support and gives some recipes for\nworking with Unicode data.","title":"Unicode Implementation - Using Unicode in Erlang","ref":"unicode_usage.html#unicode-implementation"},{"type":"extras","doc":"Experience with the Unicode support in Erlang has made it clear that\nunderstanding Unicode characters and encodings is not as easy as one would\nexpect. The complexity of the field and the implications of the standard require\nthorough understanding of concepts rarely before thought of.\n\nAlso, the Erlang implementation requires understanding of concepts that were\nnever an issue for many (Erlang) programmers. To understand and use Unicode\ncharacters requires that you study the subject thoroughly, even if you are an\nexperienced programmer.\n\nAs an example, contemplate the issue of converting between upper and lower case\nletters. Reading the standard makes you realize that there is not a simple one\nto one mapping in all scripts, for example:\n\n- In German, the letter \"ß\" (sharp s) is in lower case, but the uppercase\n equivalent is \"SS\".\n- In Greek, the letter \"Σ\" has two different lowercase forms, \"ς\" in word-final\n position and \"σ\" elsewhere.\n- In Turkish, both dotted and dotless \"i\" exist in lower case and upper case\n forms.\n- Cyrillic \"I\" has usually no lowercase form.\n- Languages with no concept of upper case (or lower case).\n\nSo, a conversion function must know not only one character at a time, but\npossibly the whole sentence, the natural language to translate to, the\ndifferences in input and output string length, and so on. Erlang/OTP has\ncurrently no Unicode `uppercase`/`lowercase` functionality with language\nspecific handling, but publicly available libraries address these issues.\n\nAnother example is the accented characters, where the same glyph has two\ndifferent representations. The Swedish letter \"ö\" is one example. The Unicode\nstandard has a code point for it, but you can also write it as \"o\" followed by\n\"U+0308\" (Combining Diaeresis, with the simplified meaning that the last letter\nis to have \"¨\" above). They have the same glyph, user perceived character. They\nare for most purposes the same, but have different representations. For example,\nMacOS X converts all filenames to use Combining Diaeresis, while most other\nprograms (including Erlang) try to hide that by doing the opposite when, for\nexample, listing directories. However it is done, it is usually important to\nnormalize such characters to avoid confusion.\n\nThe list of examples can be made long. One need a kind of knowledge that was not\nneeded when programs only considered one or two languages. The complexity of\nhuman languages and scripts has certainly made this a challenge when\nconstructing a universal standard. Supporting Unicode properly in your program\nwill require effort.","title":"Understanding Unicode - Using Unicode in Erlang","ref":"unicode_usage.html#understanding-unicode"},{"type":"extras","doc":"Unicode is a standard defining code points (numbers) for all known, living or\ndead, scripts. In principle, every symbol used in any language has a Unicode\ncode point. Unicode code points are defined and published by the Unicode\nConsortium, which is a non-profit organization.\n\nSupport for Unicode is increasing throughout the world of computing, as the\nbenefits of one common character set are overwhelming when programs are used in\na global environment. Along with the base of the standard, the code points for\nall the scripts, some _encoding standards_ are available.\n\nIt is vital to understand the difference between encodings and Unicode\ncharacters. Unicode characters are code points according to the Unicode\nstandard, while the encodings are ways to represent such code points. An\nencoding is only a standard for representation. UTF-8 can, for example, be used\nto represent a very limited part of the Unicode character set (for example\nISO-Latin-1) or the full Unicode range. It is only an encoding format.\n\nAs long as all character sets were limited to 256 characters, each character\ncould be stored in one single byte, so there was more or less only one practical\nencoding for the characters. Encoding each character in one byte was so common\nthat the encoding was not even named. With the Unicode system there are much\nmore than 256 characters, so a common way is needed to represent these. The\ncommon ways of representing the code points are the encodings. This means a\nwhole new concept to the programmer, the concept of character representation,\nwhich was a non-issue earlier.\n\nDifferent operating systems and tools support different encodings. For example,\nLinux and MacOS X have chosen the UTF-8 encoding, which is backward compatible\nwith 7-bit ASCII and therefore affects programs written in plain English the\nleast. Windows supports a limited version of UTF-16, namely all the code planes\nwhere the characters can be stored in one single 16-bit entity, which includes\nmost living languages.\n\nThe following are the most widely spread encodings:\n\n- **Bytewise representation** - This is not a proper Unicode representation, but\n the representation used for characters before the Unicode standard. It can\n still be used to represent character code points in the Unicode standard with\n numbers < 256, which exactly corresponds to the ISO Latin-1 character set. In\n Erlang, this is commonly denoted `latin1` encoding, which is slightly\n misleading as ISO Latin-1 is a character code range, not an encoding.\n\n- **UTF-8** - Each character is stored in one to four bytes depending on code\n point. The encoding is backward compatible with bytewise representation of\n 7-bit ASCII, as all 7-bit characters are stored in one single byte in UTF-8.\n The characters beyond code point 127 are stored in more bytes, letting the\n most significant bit in the first character indicate a multi-byte character.\n For details on the encoding, the RFC is publicly available.\n\n Notice that UTF-8 is _not_ compatible with bytewise representation for code\n points from 128 through 255, so an ISO Latin-1 bytewise representation is\n generally incompatible with UTF-8.\n\n- **UTF-16** - This encoding has many similarities to UTF-8, but the basic unit\n is a 16-bit number. This means that all characters occupy at least two bytes,\n and some high numbers four bytes. Some programs, libraries, and operating\n systems claiming to use UTF-16 only allow for characters that can be stored in\n one 16-bit entity, which is usually sufficient to handle living languages. As\n the basic unit is more than one byte, byte-order issues occur, which is why\n UTF-16 exists in both a big-endian and a little-endian variant.\n\n In Erlang, the full UTF-16 range is supported when applicable, like in the\n `m:unicode` module and in the bit syntax.\n\n- **UTF-32** - The most straightforward representation. Each character is stored\n in one single 32-bit number. There is no need for escapes or any variable\n number of entities for one character. All Unicode code points can be stored in\n one single 32-bit entity. As with UTF-16, there are byte-order issues. UTF-32\n can be both big-endian and little-endian.\n\n- **UCS-4** - Basically the same as UTF-32, but without some Unicode semantics,\n defined by IEEE, and has little use as a separate encoding standard. For all\n normal (and possibly abnormal) use, UTF-32 and UCS-4 are interchangeable.\n\nCertain number ranges are unused in the Unicode standard and certain ranges are\neven deemed invalid. The most notable invalid range is 16#D800-16#DFFF, as the\nUTF-16 encoding does not allow for encoding of these numbers. This is possibly\nbecause the UTF-16 encoding standard, from the beginning, was expected to be\nable to hold all Unicode characters in one 16-bit entity, but was then extended,\nleaving a hole in the Unicode range to handle backward compatibility.\n\nCode point 16#FEFF is used for Byte Order Marks (BOMs) and use of that character\nis not encouraged in other contexts. It is valid though, as the character\n\"ZWNBS\" (Zero Width Non Breaking Space). BOMs are used to identify encodings and\nbyte order for programs where such parameters are not known in advance. BOMs are\nmore seldom used than expected, but can become more widely spread as they\nprovide the means for programs to make educated guesses about the Unicode format\nof a certain file.","title":"What Unicode Is - Using Unicode in Erlang","ref":"unicode_usage.html#what-unicode-is"},{"type":"extras","doc":"To support Unicode in Erlang, problems in various areas have been addressed.\nThis section describes each area briefly and more thoroughly later in this\nUser's Guide.\n\n- **Representation** - To handle Unicode characters in Erlang, a common\n representation in both lists and binaries is needed. EEP (10) and the\n subsequent initial implementation in Erlang/OTP R13A settled a standard\n representation of Unicode characters in Erlang.\n\n- **Manipulation** - The Unicode characters need to be processed by the Erlang\n program, which is why library functions must be able to handle them. In some\n cases functionality has been added to already existing interfaces (as the\n `m:string` module now can handle strings with any code points). In some cases\n new functionality or options have been added (as in the `m:io` module, the\n file handling, the `m:unicode` module, and the bit syntax). Today most modules\n in Kernel and STDLIB, as well as the VM are Unicode-aware.\n\n- **File I/O** - I/O is by far the most problematic area for Unicode. A file is\n an entity where bytes are stored, and the lore of programming has been to\n treat characters and bytes as interchangeable. With Unicode characters, you\n must decide on an encoding when you want to store the data in a file. In\n Erlang, you can open a text file with an encoding option, so that you can read\n characters from it rather than bytes, but you can also open a file for\n bytewise I/O.\n\n The Erlang I/O-system has been designed (or at least used) in a way where you\n expect any I/O server to handle any string data. That is, however, no longer\n the case when working with Unicode characters. The Erlang programmer must now\n know the capabilities of the device where the data ends up. Also, ports in\n Erlang are byte-oriented, so an arbitrary string of (Unicode) characters\n cannot be sent to a port without first converting it to an encoding of choice.\n\n- **Terminal I/O** - Terminal I/O is slightly easier than file I/O. The output\n is meant for human reading and is usually Erlang syntax (for example, in the\n shell). There exists syntactic representation of any Unicode character without\n displaying the glyph (instead written as `\\x`\\{`HHH`\\}). Unicode data can\n therefore usually be displayed even if the terminal as such does not support\n the whole Unicode range.\n\n- **Filenames** - Filenames can be stored as Unicode strings in different ways\n depending on the underlying operating system and file system. This can be\n handled fairly easy by a program. The problems arise when the file system is\n inconsistent in its encodings. For example, Linux allows files to be named\n with any sequence of bytes, leaving to each program to interpret those bytes.\n On systems where these \"transparent\" filenames are used, Erlang must be\n informed about the filename encoding by a startup flag. The default is\n bytewise interpretation, which is usually wrong, but allows for interpretation\n of _all_ filenames.\n\n The concept of \"raw filenames\" can be used to handle wrongly encoded filenames\n if one enables Unicode filename translation (`+fnu`) on platforms where this\n is not the default.\n\n- **Source code encoding** - The Erlang source code has support for the UTF-8\n encoding and bytewise encoding. The default in Erlang/OTP R16B was bytewise\n (`latin1`) encoding. It was changed to UTF-8 in Erlang/OTP 17.0. You can\n control the encoding by a comment like the following in the beginning of the\n file:\n\n ```erlang\n %% -*- coding: utf-8 -*-\n ```\n\n This of course requires your editor to support UTF-8 as well. The same comment\n is also interpreted by functions like `file:consult/1`, the release handler,\n and so on, so that you can have all text files in your source directories in\n UTF-8 encoding.\n\n- **The language** - Having the source code in UTF-8 also allows you to write\n string literals, function names, and atoms containing Unicode characters with\n code points > 255. Module names, application names, and node names are still\n restricted to the ISO Latin-1 range. Binary literals, where you use type\n `/utf8`, can also be expressed using Unicode characters > 255. Having module\n names or application names using characters other than 7-bit ASCII can cause\n trouble on operating systems with inconsistent file naming schemes, and can\n hurt portability, so it is not recommended.\n\n EEP 40 suggests that the language is also to allow for Unicode characters >\n 255 in variable names. Whether to implement that EEP is yet to be decided.","title":"Areas of Unicode Support - Using Unicode in Erlang","ref":"unicode_usage.html#areas-of-unicode-support"},{"type":"extras","doc":"In Erlang, strings are lists of integers. A string was until Erlang/OTP R13\ndefined to be encoded in the ISO Latin-1 (ISO 8859-1) character set, which is,\ncode point by code point, a subrange of the Unicode character set.\n\nThe standard list encoding for strings was therefore easily extended to handle\nthe whole Unicode range. A Unicode string in Erlang is a list containing\nintegers, where each integer is a valid Unicode code point and represents one\ncharacter in the Unicode character set.\n\nErlang strings in ISO Latin-1 are a subset of Unicode strings.\n\nOnly if a string contains code points < 256, can it be directly converted to a\nbinary by using, for example, `erlang:iolist_to_binary/1` or can be sent\ndirectly to a port. If the string contains Unicode characters > 255, an encoding\nmust be decided upon and the string is to be converted to a binary in the\npreferred encoding using\n[`unicode:characters_to_binary/1,2,3`](`unicode:characters_to_binary/1`).\nStrings are not generally lists of bytes, as they were before Erlang/OTP R13,\nthey are lists of characters. Characters are not generally bytes, they are\nUnicode code points.\n\nBinaries are more troublesome. For performance reasons, programs often store\ntextual data in binaries instead of lists, mainly because they are more compact\n(one byte per character instead of two words per character, as is the case with\nlists). Using `erlang:list_to_binary/1`, an ISO Latin-1 Erlang string can be\nconverted into a binary, effectively using bytewise encoding: one byte per\ncharacter. This was convenient for those limited Erlang strings, but cannot be\ndone for arbitrary Unicode lists.\n\nAs the UTF-8 encoding is widely spread and provides some backward compatibility\nin the 7-bit ASCII range, it is selected as the standard encoding for Unicode\ncharacters in binaries for Erlang.\n\nThe standard binary encoding is used whenever a library function in Erlang is to\nhandle Unicode data in binaries, but is of course not enforced when\ncommunicating externally. Functions and bit syntax exist to encode and decode\nboth UTF-8, UTF-16, and UTF-32 in binaries. However, library functions dealing\nwith binaries and Unicode in general only deal with the default encoding.\n\nCharacter data can be combined from many sources, sometimes available in a mix\nof strings and binaries. Erlang has for long had the concept of `iodata` or\n`iolist`s, where binaries and lists can be combined to represent a sequence of\nbytes. In the same way, the Unicode-aware modules often allow for combinations\nof binaries and lists, where the binaries have characters encoded in UTF-8 and\nthe lists contain such binaries or numbers representing Unicode code points:\n\n```erlang\nunicode_binary() = binary() with characters encoded in UTF-8 coding standard\n\nchardata() = charlist() | unicode_binary()\n\ncharlist() = maybe_improper_list(char() | unicode_binary() | charlist(),\n unicode_binary() | nil())\n```\n\nThe module `m:unicode` even supports similar mixes with binaries containing\nother encodings than UTF-8, but that is a special case to allow for conversions\nto and from external data:\n\n```erlang\nexternal_unicode_binary() = binary() with characters coded in a user-specified\n Unicode encoding other than UTF-8 (UTF-16 or UTF-32)\n\nexternal_chardata() = external_charlist() | external_unicode_binary()\n\nexternal_charlist() = maybe_improper_list(char() | external_unicode_binary() |\n external_charlist(), external_unicode_binary() | nil())\n```","title":"Standard Unicode Representation - Using Unicode in Erlang","ref":"unicode_usage.html#standard-unicode-representation"},{"type":"extras","doc":"[](){: #unicode_in_erlang } As from Erlang/OTP R16, Erlang source files can be\nwritten in UTF-8 or bytewise (`latin1`) encoding. For information about how to\nstate the encoding of an Erlang source file, see the [`epp`](`m:epp#encoding`)\nmodule. As from Erlang/OTP R16, strings and comments can be written using\nUnicode. As from Erlang/OTP 20, also atoms and functions can be written using\nUnicode. Modules, applications, and nodes must still be named using characters\nfrom the ISO Latin-1 character set. (These restrictions in the language are\nindependent of the encoding of the source file.)","title":"Basic Language Support - Using Unicode in Erlang","ref":"unicode_usage.html#basic-language-support"},{"type":"extras","doc":"The bit syntax contains types for handling binary data in the three main\nencodings. The types are named `utf8`, `utf16`, and `utf32`. The `utf16` and\n`utf32` types can be in a big-endian or a little-endian variant:\n\n```text\n< > = Bin1,\n< > = Bin2,\nBin3 = <<$H/utf32-little, $e/utf32-little, $l/utf32-little, $l/utf32-little,\n$o/utf32-little>>,\n```\n\nFor convenience, literal strings can be encoded with a Unicode encoding in\nbinaries using the following (or similar) syntax:\n\n```text\nBin4 = <<\"Hello\"/utf16>>,\n```","title":"Bit Syntax - Using Unicode in Erlang","ref":"unicode_usage.html#bit-syntax"},{"type":"extras","doc":"For source code, there is an extension to syntax `\\`OOO (backslash followed by\nthree octal numbers) and `\\x`HH (backslash followed by `x`, followed by two\nhexadecimal characters), namely `\\x{`H ...`}` (backslash followed by `x`,\nfollowed by left curly bracket, any number of hexadecimal digits, and a\nterminating right curly bracket). This allows for entering characters of any\ncode point literally in a string even when the encoding of the source file is\nbytewise (`latin1`).\n\nIn the shell, if using a Unicode input device, or in source code stored in\nUTF-8, `$` can be followed directly by a Unicode character producing an integer.\nIn the following example, the code point of a Cyrillic `с` is output:\n\n```text\n7> $с.\n1089\n```","title":"String and Character Literals - Using Unicode in Erlang","ref":"unicode_usage.html#string-and-character-literals"},{"type":"extras","doc":"In certain output functions and in the output of return values in the shell,\nErlang tries to detect string data in lists and binaries heuristically.\nTypically you will see heuristic detection in a situation like this:\n\n```erlang\n1> [97,98,99].\n\"abc\"\n2> <<97,98,99>>.\n<<\"abc\">>\n3> <<195,165,195,164,195,182>>.\n<<\"åäö\"/utf8>>\n```\n\nHere the shell detects lists containing printable characters or binaries\ncontaining printable characters in bytewise or UTF-8 encoding. But what is a\nprintable character? One view is that anything the Unicode standard thinks is\nprintable, is also printable according to the heuristic detection. The result is\nthen that almost any list of integers are deemed a string, and all sorts of\ncharacters are printed, maybe also characters that your terminal lacks in its\nfont set (resulting in some unappreciated generic output). Another way is to\nkeep it backward compatible so that only the ISO Latin-1 character set is used\nto detect a string. A third way is to let the user decide exactly what Unicode\nranges that are to be viewed as characters.\n\nAs from Erlang/OTP R16B you can select the ISO Latin-1 range or the whole\nUnicode range by supplying startup flag `+pc latin1` or `+pc unicode`,\nrespectively. For backward compatibility, `latin1` is default. This only\ncontrols how heuristic string detection is done. More ranges are expected to be\nadded in the future, enabling tailoring of the heuristics to the language and\nregion relevant to the user.\n\nThe following examples show the two startup options:\n\n```erlang\n$ erl +pc latin1\nErlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]\n\nEshell V5.10.1 (abort with ^G)\n1> [1024].\n[1024]\n2> [1070,1085,1080,1082,1086,1076].\n[1070,1085,1080,1082,1086,1076]\n3> [229,228,246].\n\"åäö\"\n4> <<208,174,208,189,208,184,208,186,208,190,208,180>>.\n<<208,174,208,189,208,184,208,186,208,190,208,180>>\n5> <<229/utf8,228/utf8,246/utf8>>.\n<<\"åäö\"/utf8>>\n```\n\n```erlang\n$ erl +pc unicode\nErlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]\n\nEshell V5.10.1 (abort with ^G)\n1> [1024].\n\"Ѐ\"\n2> [1070,1085,1080,1082,1086,1076].\n\"Юникод\"\n3> [229,228,246].\n\"åäö\"\n4> <<208,174,208,189,208,184,208,186,208,190,208,180>>.\n<<\"Юникод\"/utf8>>\n5> <<229/utf8,228/utf8,246/utf8>>.\n<<\"åäö\"/utf8>>\n```\n\nIn the examples, you can see that the default Erlang shell interprets only\ncharacters from the ISO Latin1 range as printable and only detects lists or\nbinaries with those \"printable\" characters as containing string data. The valid\nUTF-8 binary containing the Russian word \"Юникод\", is not printed as a string.\nWhen started with all Unicode characters printable (`+pc unicode`), the shell\noutputs anything containing printable Unicode data (in binaries, either UTF-8 or\nbytewise encoded) as string data.\n\nThese heuristics are also used by `io:format/2`, `io_lib:format/2`, and friends\nwhen modifier `t` is used with `~p` or `~P`:\n\n```erlang\n$ erl +pc latin1\nErlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]\n\nEshell V5.10.1 (abort with ^G)\n1> io:format(\"~tp~n\",[{<<\"åäö\">>, <<\"åäö\"/utf8>>, <<208,174,208,189,208,184,208,186,208,190,208,180>>}]).\n{<<\"åäö\">>,<<\"åäö\"/utf8>>,<<208,174,208,189,208,184,208,186,208,190,208,180>>}\nok\n```\n\n```erlang\n$ erl +pc unicode\nErlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]\n\nEshell V5.10.1 (abort with ^G)\n1> io:format(\"~tp~n\",[{<<\"åäö\">>, <<\"åäö\"/utf8>>, <<208,174,208,189,208,184,208,186,208,190,208,180>>}]).\n{<<\"åäö\">>,<<\"åäö\"/utf8>>,<<\"Юникод\"/utf8>>}\nok\n```\n\nNotice that this only affects _heuristic_ interpretation of lists and binaries\non output. For example, the `~ts` format sequence always outputs a valid list of\ncharacters, regardless of the `+pc` setting, as the programmer has explicitly\nrequested string output.","title":"Heuristic String Detection - Using Unicode in Erlang","ref":"unicode_usage.html#heuristic-string-detection"},{"type":"extras","doc":"The interactive Erlang shell can support Unicode input and output.\n\nOn Windows, proper operation requires that a suitable font is installed and\nselected for the Erlang application to use. If no suitable font is available on\nyour system, try installing the [DejaVu fonts](http://dejavu-fonts.org), which\nare freely available, and then select that font in the Erlang shell application.\n\nOn Unix-like operating systems, the terminal is to be able to handle UTF-8 on\ninput and output (this is done by, for example, modern versions of XTerm, KDE\nKonsole, and the Gnome terminal) and your locale settings must be proper. As an\nexample, a `LANG` environment variable can be set as follows:\n\n```text\n$ echo $LANG\nen_US.UTF-8\n```\n\nMost systems handle variable `LC_CTYPE` before `LANG`, so if that is set, it\nmust be set to `UTF-8`:\n\n```text\n$ echo $LC_CTYPE\nen_US.UTF-8\n```\n\nThe `LANG` or `LC_CTYPE` setting are to be consistent with what the terminal is\ncapable of. There is no portable way for Erlang to ask the terminal about its\nUTF-8 capacity, we have to rely on the language and character type settings.\n\nTo investigate what Erlang thinks about the terminal, the call\n[`io:getopts()`](`io:getopts/1`) can be used when the shell is started:\n\n```erlang\n$ LC_CTYPE=en_US.ISO-8859-1 erl\nErlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]\n\nEshell V5.10.1 (abort with ^G)\n1> lists:keyfind(encoding, 1, io:getopts()).\n{encoding,latin1}\n2> q().\nok\n$ LC_CTYPE=en_US.UTF-8 erl\nErlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]\n\nEshell V5.10.1 (abort with ^G)\n1> lists:keyfind(encoding, 1, io:getopts()).\n{encoding,unicode}\n2>\n```\n\nWhen (finally?) everything is in order with the locale settings, fonts. and the\nterminal emulator, you have probably found a way to input characters in the\nscript you desire. For testing, the simplest way is to add some keyboard\nmappings for other languages, usually done with some applet in your desktop\nenvironment.\n\nIn a KDE environment, select _KDE Control Center (Personal Settings)_ >\n_Regional and Accessibility_ > _Keyboard Layout_.\n\nOn Windows XP, select _Control Panel_ > _Regional and Language Options_, select\ntab _Language_, and click button _Details..._ in the square named _Text Services\nand Input Languages_.\n\nYour environment probably provides similar means of changing the keyboard\nlayout. Ensure that you have a way to switch back and forth between keyboards\neasily if you are not used to this. For example, entering commands using a\nCyrillic character set is not easily done in the Erlang shell.\n\nNow you are set up for some Unicode input and output. The simplest thing to do\nis to enter a string in the shell:\n\n```erlang\n$ erl\nErlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]\n\nEshell V5.10.1 (abort with ^G)\n1> lists:keyfind(encoding, 1, io:getopts()).\n{encoding,unicode}\n2> \"Юникод\".\n\"Юникод\"\n3> io:format(\"~ts~n\", [v(2)]).\nЮникод\nok\n4>\n```\n\nWhile strings can be input as Unicode characters, the language elements are\nstill limited to the ISO Latin-1 character set. Only character constants and\nstrings are allowed to be beyond that range:\n\n```text\n$ erl\nErlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]\n\nEshell V5.10.1 (abort with ^G)\n1> $ξ.\n958\n2> Юникод.\n* 1: illegal character\n2>\n```","title":"The Interactive Shell - Using Unicode in Erlang","ref":"unicode_usage.html#the-interactive-shell"},{"type":"extras","doc":"When Erlang is started without an interactive shell (`-noshell`, `-noinput` or\nas an escript) the unicode support is identified using environment variables\njust as for [interactive shells](unicode_usage.md#the-interactive-shell).\nWorking with unicode in non-interactive sessions works just the same as for\ninteractive sessions.\n\nIn some situations you may need to be able to read and write raw bytes from\n[`standard_io`](`t:io:standard_io/0`). If that is the case, then you want to set\nthe [standard_io_encoding](`e:kernel:kernel_app.md#standard_io_encoding`)\nconfiguration parameter to `latin1` and use the `m:file` API to read and write\ndata (as explained in\n[Unicode Data in Files](unicode_usage.md#unicode-data-in-files)).\n\nIn the example below we first read the character `ξ` from\n[`standard_io`](`t:io:standard_io/0`) and then print the\n[charlist()](`t:unicode:charlist/0`) represented by it.\n\n```erlang\n#!/usr/bin/env escript\n%%! -kernel standard_io_encoding latin1\n\nmain(_) ->\n {ok, Char} = file:read_line(standard_io),\n ok = file:write(standard_io, string:trim(Char)),\n ok = file:write(standard_io, io_lib:format(\": ~w~n\",[string:trim(Char)])),\n ok.\n```\n\n```text\n$ escript test.es\nξ\nξ: [206,190]\n```\n\n`ξ` would normally be represented as the integer 958, but since we are using\nbytewise encoding (`latin1`), it is represented by 206 and 190, which is the\nutf-8 bytes representing `ξ`. When we echo those bytes back to\n[`standard_io`](`t:io:standard_io/0`), the terminal will see the bytes as utf-8\nand show the correct value even though in Erlang we never knew that it was\nindeed a unicode string.\n\n[](){: #unicode_file_names }","title":"Escripts and non-interactive I/O - Using Unicode in Erlang","ref":"unicode_usage.html#escripts-and-non-interactive-i-o"},{"type":"extras","doc":"Most modern operating systems support Unicode filenames in some way. There are\nmany different ways to do this and Erlang by default treats the different\napproaches differently:\n\n- **Mandatory Unicode file naming** - Windows, Android and, for most cases,\n MacOS X enforce Unicode support for filenames. All files created in the file\n system have names that can consistently be interpreted. In MacOS X and\n Android, all filenames are retrieved in UTF-8 encoding. In Windows, each\n system call handling filenames has a special Unicode-aware variant, giving\n much the same effect. There are no filenames on these systems that are not\n Unicode filenames. So, the default behavior of the Erlang VM is to work in\n \"Unicode filename translation mode\". This means that a filename can be\n specified as a Unicode list, which is automatically translated to the proper\n name encoding for the underlying operating system and file system.\n\n Doing, for example, a `file:list_dir/1` on one of these systems can return\n Unicode lists with code points > 255, depending on the content of the file\n system.\n\n- **Transparent file naming** - Most Unix operating systems have adopted a\n simpler approach, namely that Unicode file naming is not enforced, but by\n convention. Those systems usually use UTF-8 encoding for Unicode filenames,\n but do not enforce it. On such a system, a filename containing characters with\n code points from 128 through 255 can be named as plain ISO Latin-1 or use\n UTF-8 encoding. As no consistency is enforced, the Erlang VM cannot do\n consistent translation of all filenames.\n\n By default on such systems, Erlang starts in `utf8` filename mode if the\n terminal supports UTF-8, otherwise in `latin1` mode.\n\n In `latin1` mode, filenames are bytewise encoded. This allows for list\n representation of all filenames in the system. However, a a file named\n \"Östersund.txt\", appears in `file:list_dir/1` either as \"Östersund.txt\" (if\n the filename was encoded in bytewise ISO Latin-1 by the program creating the\n file) or more probably as `[195,150,115,116,101,114,115,117,110,100]`, which\n is a list containing UTF-8 bytes (not what you want). If you use Unicode\n filename translation on such a system, non-UTF-8 filenames are ignored by\n functions like `file:list_dir/1`. They can be retrieved with function\n `file:list_dir_all/1`, but wrongly encoded filenames appear as \"raw\n filenames\".\n\nThe Unicode file naming support was introduced in Erlang/OTP R14B01. A VM\noperating in Unicode filename translation mode can work with files having names\nin any language or character set (as long as it is supported by the underlying\noperating system and file system). The Unicode character list is used to denote\nfilenames or directory names. If the file system content is listed, you also get\nUnicode lists as return value. The support lies in the Kernel and STDLIB\nmodules, which is why most applications (that do not explicitly require the\nfilenames to be in the ISO Latin-1 range) benefit from the Unicode support\nwithout change.\n\nOn operating systems with mandatory Unicode filenames, this means that you more\neasily conform to the filenames of other (non-Erlang) applications. You can also\nprocess filenames that, at least on Windows, were inaccessible (because of\nhaving names that could not be represented in ISO Latin-1). Also, you avoid\ncreating incomprehensible filenames on MacOS X, as the `vfs` layer of the\noperating system accepts all your filenames as UTF-8 does not rewrite them.\n\nFor most systems, turning on Unicode filename translation is no problem even if\nit uses transparent file naming. Very few systems have mixed filename encodings.\nA consistent UTF-8 named system works perfectly in Unicode filename mode. It was\nstill, however, considered experimental in Erlang/OTP R14B01 and is still not\nthe default on such systems.\n\nUnicode filename translation is turned on with switch `+fnu`. On Linux, a VM\nstarted without explicitly stating the filename translation mode defaults to\n`latin1` as the native filename encoding. On Windows, MacOS X and Android, the\ndefault behavior is that of Unicode filename translation. Therefore\n`file:native_name_encoding/0` by default returns `utf8` on those systems\n(Windows does not use UTF-8 on the file system level, but this can safely be\nignored by the Erlang programmer). The default behavior can, as stated earlier,\nbe changed using option `+fnu` or `+fnl` to the VM, see the\n[`erl`](`e:erts:erl_cmd.md`) program. If the VM is started in Unicode filename\ntranslation mode, `file:native_name_encoding/0` returns atom `utf8`. Switch\n`+fnu` can be followed by `w`, `i`, or `e` to control how wrongly encoded\nfilenames are to be reported.\n\n- `w` means that a warning is sent to the `error_logger` whenever a wrongly\n encoded filename is \"skipped\" in directory listings. `w` is the default.\n- `i` means that wrongly encoded filenames are silently ignored.\n- `e` means that the API function returns an error whenever a wrongly encoded\n filename (or directory name) is encountered.\n\nNotice that `file:read_link/1` always returns an error if the link points to an\ninvalid filename.\n\nIn Unicode filename mode, filenames given to BIF [`open_port/2`](`open_port/2`)\nwith option `{spawn_executable,...}` are also interpreted as Unicode. So is the\nparameter list specified in option `args` available when using\n`spawn_executable`. The UTF-8 translation of arguments can be avoided using\nbinaries, see section\n[Notes About Raw Filenames](unicode_usage.md#notes-about-raw-filenames).\n\nNotice that the file encoding options specified when opening a file has nothing\nto do with the filename encoding convention. You can very well open files\ncontaining data encoded in UTF-8, but having filenames in bytewise (`latin1`)\nencoding or conversely.\n\n> #### Note {: .info }\n>\n> Erlang drivers and NIF-shared objects still cannot be named with names\n> containing code points > 127. This limitation will be removed in a future\n> release. However, Erlang modules can, but it is definitely not a good idea and\n> is still considered experimental.","title":"Unicode Filenames - Using Unicode in Erlang","ref":"unicode_usage.html#unicode-filenames"},{"type":"extras","doc":"> #### Note {: .info }\n>\n> Note that raw filenames _not_ necessarily are encoded the same way as on the\n> OS level.\n\nRaw filenames were introduced together with Unicode filename support in ERTS\n5.8.2 (Erlang/OTP R14B01). The reason \"raw filenames\" were introduced in the\nsystem was to be able to represent filenames, specified in different encodings\non the same system, consistently. It can seem practical to have the VM\nautomatically translate a filename that is not in UTF-8 to a list of Unicode\ncharacters, but this would open up for both duplicate filenames and other\ninconsistent behavior.\n\nConsider a directory containing a file named \"björn\" in ISO Latin-1, while the\nErlang VM is operating in Unicode filename mode (and therefore expects UTF-8\nfile naming). The ISO Latin-1 name is not valid UTF-8 and one can be tempted to\nthink that automatic conversion in, for example, `file:list_dir/1` is a good\nidea. But what would happen if we later tried to open the file and have the name\nas a Unicode list (magically converted from the ISO Latin-1 filename)? The VM\nconverts the filename to UTF-8, as this is the encoding expected. Effectively\nthis means trying to open the file named <<\"björn\"/utf8>>. This file does not\nexist, and even if it existed it would not be the same file as the one that was\nlisted. We could even create two files named \"björn\", one named in UTF-8\nencoding and one not. If `file:list_dir/1` would automatically convert the ISO\nLatin-1 filename to a list, we would get two identical filenames as the result.\nTo avoid this, we must differentiate between filenames that are properly encoded\naccording to the Unicode file naming convention (that is, UTF-8) and filenames\nthat are invalid under the encoding. By the common function `file:list_dir/1`,\nthe wrongly encoded filenames are ignored in Unicode filename translation mode,\nbut by function `file:list_dir_all/1` the filenames with invalid encoding are\nreturned as \"raw\" filenames, that is, as binaries.\n\nThe `file` module accepts raw filenames as input.\n`open_port({spawn_executable, ...} ...)` also accepts them. As mentioned\nearlier, the arguments specified in the option list to\n`open_port({spawn_executable, ...} ...)` undergo the same conversion as the\nfilenames, meaning that the executable is provided with arguments in UTF-8 as\nwell. This translation is avoided consistently with how the filenames are\ntreated, by giving the argument as a binary.\n\nTo force Unicode filename translation mode on systems where this is not the\ndefault was considered experimental in Erlang/OTP R14B01. This was because the\ninitial implementation did not ignore wrongly encoded filenames, so that raw\nfilenames could spread unexpectedly throughout the system. As from Erlang/OTP\nR16B, the wrongly encoded filenames are only retrieved by special functions\n(such as `file:list_dir_all/1`). Since the impact on existing code is therefore\nmuch lower it is now supported. Unicode filename translation is expected to be\ndefault in future releases.\n\nEven if you are operating without Unicode file naming translation automatically\ndone by the VM, you can access and create files with names in UTF-8 encoding by\nusing raw filenames encoded as UTF-8. Enforcing the UTF-8 encoding regardless of\nthe mode the Erlang VM is started in can in some circumstances be a good idea,\nas the convention of using UTF-8 filenames is spreading.","title":"Notes About Raw Filenames - Using Unicode in Erlang","ref":"unicode_usage.html#notes-about-raw-filenames"},{"type":"extras","doc":"The `vfs` layer of MacOS X enforces UTF-8 filenames in an aggressive way. Older\nversions did this by refusing to create non-UTF-8 conforming filenames, while\nnewer versions replace offending bytes with the sequence \"%HH\", where HH is the\noriginal character in hexadecimal notation. As Unicode translation is enabled by\ndefault on MacOS X, the only way to come up against this is to either start the\nVM with flag `+fnl` or to use a raw filename in bytewise (`latin1`) encoding. If\nusing a raw filename, with a bytewise encoding containing characters from 127\nthrough 255, to create a file, the file cannot be opened using the same name as\nthe one used to create it. There is no remedy for this behavior, except keeping\nthe filenames in the correct encoding.\n\nMacOS X reorganizes the filenames so that the representation of accents, and so\non, uses the \"combining characters\". For example, character `ö` is represented\nas code points `[111,776]`, where `111` is character `o` and `776` is the\nspecial accent character \"Combining Diaeresis\". This way of normalizing Unicode\nis otherwise very seldom used. Erlang normalizes those filenames in the opposite\nway upon retrieval, so that filenames using combining accents are not passed up\nto the Erlang application. In Erlang, filename \"björn\" is retrieved as\n`[98,106,246,114,110]`, not as `[98,106,117,776,114,110]`, although the file\nsystem can think differently. The normalization into combining accents is redone\nwhen accessing files, so this can usually be ignored by the Erlang programmer.","title":"Notes About MacOS X - Using Unicode in Erlang","ref":"unicode_usage.html#notes-about-macos-x"},{"type":"extras","doc":"[](){: #unicode_in_environment_and_parameters }\n\nEnvironment variables and their interpretation are handled much in the same way\nas filenames. If Unicode filenames are enabled, environment variables as well as\nparameters to the Erlang VM are expected to be in Unicode.\n\nIf Unicode filenames are enabled, the calls to [`os:getenv/0,1`](`os:getenv/0`),\n`os:putenv/2`, and `os:unsetenv/1` handle Unicode strings. On Unix-like\nplatforms, the built-in functions translate environment variables in UTF-8\nto/from Unicode strings, possibly with code points > 255. On Windows, the\nUnicode versions of the environment system API are used, and code points > 255\nare allowed.\n\nOn Unix-like operating systems, parameters are expected to be UTF-8 without\ntranslation if Unicode filenames are enabled.","title":"Unicode in Environment and Parameters - Using Unicode in Erlang","ref":"unicode_usage.html#unicode-in-environment-and-parameters"},{"type":"extras","doc":"Most of the modules in Erlang/OTP are Unicode-unaware in the sense that they\nhave no notion of Unicode and should not have. Typically they handle non-textual\nor byte-oriented data (such as `gen_tcp`).\n\nModules handling textual data (such as `m:io_lib` and `m:string` are sometimes\nsubject to conversion or extension to be able to handle Unicode characters.\n\nFortunately, most textual data has been stored in lists and range checking has\nbeen sparse, so modules like `string` work well for Unicode strings with little\nneed for conversion or extension.\n\nSome modules are, however, changed to be explicitly Unicode-aware. These modules\ninclude:\n\n- **`unicode`** - The `m:unicode` module is clearly Unicode-aware. It contains\n functions for conversion between different Unicode formats and some utilities\n for identifying byte order marks. Few programs handling Unicode data survive\n without this module.\n\n- **`io`** - The `m:io` module has been extended along with the actual I/O\n protocol to handle Unicode data. This means that many functions require\n binaries to be in UTF-8, and there are modifiers to format control sequences\n to allow for output of Unicode strings.\n\n- **`file`, `group`, `user`** - I/O-servers throughout the system can handle\n Unicode data and have options for converting data upon output or input to/from\n the device. As shown earlier, the `m:shell` module has support for Unicode\n terminals and the `m:file` module allows for translation to and from various\n Unicode formats on disk.\n\n Reading and writing of files with Unicode data is, however, not best done with\n the `file` module, as its interface is byte-oriented. A file opened with a\n Unicode encoding (like UTF-8) is best read or written using the `m:io` module.\n\n- **`re`** - The `m:re` module allows for matching Unicode strings as a special\n option. As the library is centered on matching in binaries, the Unicode\n support is UTF-8-centered.\n\n- **`wx`** - The graphical library `m:wx` has extensive support for Unicode\n text.\n\nThe `m:string` module works perfectly for Unicode strings and ISO Latin-1\nstrings, except the language-dependent functions `string:uppercase/1` and\n`string:lowercase/1`. These two functions can never function correctly for\nUnicode characters in their current form, as there are language and locale\nissues to consider when converting text between cases. Converting case in an\ninternational environment is a large subject not yet addressed in OTP.","title":"Unicode-Aware Modules - Using Unicode in Erlang","ref":"unicode_usage.html#unicode-aware-modules"},{"type":"extras","doc":"Although Erlang can handle Unicode data in many forms does not automatically\nmean that the content of any file can be Unicode text. The external entities,\nsuch as ports and I/O servers, are not generally Unicode capable.\n\nPorts are always byte-oriented, so before sending data that you are not sure is\nbytewise-encoded to a port, ensure to encode it in a proper Unicode encoding.\nSometimes this means that only part of the data must be encoded as, for example,\nUTF-8. Some parts can be binary data (like a length indicator) or something else\nthat must not undergo character encoding, so no automatic translation is\npresent.\n\nI/O servers behave a little differently. The I/O servers connected to terminals\n(or `stdout`) can usually cope with Unicode data regardless of the encoding\noption. This is convenient when one expects a modern environment but do not want\nto crash when writing to an archaic terminal or pipe.\n\nA file can have an encoding option that makes it generally usable by the `m:io`\nmodule (for example `{encoding,utf8}`), but is by default opened as a\nbyte-oriented file. The `m:file` module is byte-oriented, so only ISO Latin-1\ncharacters can be written using that module. Use the `io` module if Unicode data\nis to be output to a file with other `encoding` than `latin1` (bytewise\nencoding). It is slightly confusing that a file opened with, for example,\n`file:open(Name,[read,{encoding,utf8}])` cannot be properly read using\n`file:read(File,N)`, but using the `io` module to retrieve the Unicode data from\nit. The reason is that `file:read` and `file:write` (and friends) are purely\nbyte-oriented, and should be, as that is the way to access files other than text\nfiles, byte by byte. As with ports, you can write encoded data into a file by\n\"manually\" converting the data to the encoding of choice (using the `m:unicode`\nmodule or the bit syntax) and then output it on a bytewise (`latin1`) encoded\nfile.\n\nRecommendations:\n\n- Use the `m:file` module for files opened for bytewise access\n (`{encoding,latin1}`).\n- Use the `m:io` module when accessing files with any other encoding (for\n example `{encoding,utf8}`).\n\nFunctions reading Erlang syntax from files recognize the `coding:` comment and\ncan therefore handle Unicode data on input. When writing Erlang terms to a file,\nyou are advised to insert such comments when applicable:\n\n```erlang\n$ erl +fna +pc unicode\nErlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]\n\nEshell V5.10.1 (abort with ^G)\n1> file:write_file(\"test.term\",<<\"%% coding: utf-8\\n[{\\\"Юникод\\\",4711}].\\n\"/utf8>>).\nok\n2> file:consult(\"test.term\").\n{ok,[[{\"Юникод\",4711}]]}\n```","title":"Unicode Data in Files - Using Unicode in Erlang","ref":"unicode_usage.html#unicode-data-in-files"},{"type":"extras","doc":"[](){: #unicode_options_summary }\n\nThe Unicode support is controlled by both command-line switches, some standard\nenvironment variables, and the OTP version you are using. Most options affect\nmainly how Unicode data is displayed, not the functionality of the APIs in the\nstandard libraries. This means that Erlang programs usually do not need to\nconcern themselves with these options, they are more for the development\nenvironment. An Erlang program can be written so that it works well regardless\nof the type of system or the Unicode options that are in effect.\n\nHere follows a summary of the settings affecting Unicode:\n\n- **The `LANG` and `LC_CTYPE` environment variables** - The language setting in\n the operating system mainly affects the shell. The terminal (that is, the\n group leader) operates with `{encoding, unicode}` only if the environment\n tells it that UTF-8 is allowed. This setting is to correspond to the terminal\n you are using.\n\n The environment can also affect filename interpretation, if Erlang is started\n with flag `+fna` (which is default from Erlang/OTP 17.0).\n\n You can check the setting of this by calling [`io:getopts()`](`io:getopts/1`),\n which gives you an option list containing `{encoding,unicode}` or\n `{encoding,latin1}`.\n\n- **The `+pc` \\{`unicode`|`latin1`\\} flag to [`erl(1)`](`e:erts:erl_cmd.md`)** -\n This flag affects what is interpreted as string data when doing heuristic\n string detection in the shell and in `m:io`/\n [`io_lib:format`](`io_lib:format/2`) with the `\"~tp\"` and `~tP` formatting\n instructions, as described earlier.\n\n You can check this option by calling `io:printable_range/0`, which returns\n `unicode` or `latin1`. To be compatible with future (expected) extensions to\n the settings, rather use `io_lib:printable_list/1` to check if a list is\n printable according to the setting. That function takes into account new\n possible settings returned from `io:printable_range/0`.\n\n- **The `+fn`\\{`l`|`u`|`a`\\} [\\{`w`|`i`|`e`\\}] flag to\n [`erl(1)`](`e:erts:erl_cmd.md`)** - This flag affects how the filenames are to\n be interpreted. On operating systems with transparent file naming, this must\n be specified to allow for file naming in Unicode characters (and for correct\n interpretation of filenames containing characters > 255).\n\n - `+fnl` means bytewise interpretation of filenames, which was the usual way\n to represent ISO Latin-1 filenames before UTF-8 file naming got widespread.\n - `+fnu` means that filenames are encoded in UTF-8, which is nowadays the\n common scheme (although not enforced).\n - `+fna` means that you automatically select between `+fnl` and `+fnu`, based\n on environment variables `LANG` and `LC_CTYPE`. This is optimistic\n heuristics indeed, nothing enforces a user to have a terminal with the same\n encoding as the file system, but this is usually the case. This is the\n default on all Unix-like operating systems, except MacOS X.\n\n The filename translation mode can be read with function\n `file:native_name_encoding/0`, which returns `latin1` (bytewise encoding) or\n `utf8`.\n\n- **`epp:default_encoding/0`** - This function returns the default encoding for\n Erlang source files (if no encoding comment is present) in the currently\n running release. In Erlang/OTP R16B, `latin1` (bytewise encoding) was\n returned. As from Erlang/OTP 17.0, `utf8` is returned.\n\n The encoding of each file can be specified using comments as described in the\n [`epp`](`m:epp#encoding`) module.\n\n- **[`io:setopts/1,2`](`io:setopts/1`) and\n [`standard_io_encoding`](`e:kernel:kernel_app.md#standard_io_encoding`)** -\n When Erlang is started the encoding for [`standard_io`](`t:io:standard_io/0`)\n is by default set to what the\n [locale settings indicate](unicode_usage.md#the-interactive-shell). You can\n override the default by setting the kernel configuration parameter\n [`standard_io_encoding`](`e:kernel:kernel_app.md#standard_io_encoding`) to the\n desired encoding.\n\n You can set the encoding of a file or other I/O server with function\n [`io:setopts/2`](`io:setopts/1`). This can also be set when opening a file.\n Setting the terminal (or other [`standard_io`](`t:io:standard_io/0`) server)\n unconditionally to option `{encoding,utf8}` implies that UTF-8 encoded\n characters are written to the device, regardless of how Erlang was started or\n the user's environment.\n\n > #### Note {: .info }\n >\n > If you use [`io:setopts/2`](`io:setopts/1`) to change the encoding of\n > [`standard_io`](`t:io:standard_io/0`) the I/O server may already have read\n > some data using the default encoding. To avoid this you should set the\n > encoding using\n > [`standard_io_encoding`](`e:kernel:kernel_app.md#standard_io_encoding`).\n\n Opening files with option `encoding` is convenient when writing or reading\n text files in a known encoding.\n\n You can retrieve the `encoding` setting for an I/O server with function\n [`io:getopts()`](`io:getopts/1`).","title":"Summary of Options - Using Unicode in Erlang","ref":"unicode_usage.html#summary-of-options"},{"type":"extras","doc":"When starting with Unicode, one often stumbles over some common issues. This\nsection describes some methods of dealing with Unicode data.","title":"Recipes - Using Unicode in Erlang","ref":"unicode_usage.html#recipes"},{"type":"extras","doc":"A common method of identifying encoding in text files is to put a Byte Order\nMark (BOM) first in the file. The BOM is the code point 16#FEFF encoded in the\nsame way as the remaining file. If such a file is to be read, the first few\nbytes (depending on encoding) are not part of the text. This code outlines how\nto open a file that is believed to have a BOM, and sets the files encoding and\nposition for further sequential reading (preferably using the `m:io` module).\n\nNotice that error handling is omitted from the code:\n\n```erlang\nopen_bom_file_for_reading(File) ->\n {ok,F} = file:open(File,[read,binary]),\n {ok,Bin} = file:read(F,4),\n {Type,Bytes} = unicode:bom_to_encoding(Bin),\n file:position(F,Bytes),\n io:setopts(F,[{encoding,Type}]),\n {ok,F}.\n```\n\nFunction `unicode:bom_to_encoding/1` identifies the encoding from a binary of at\nleast four bytes. It returns, along with a term suitable for setting the\nencoding of the file, the byte length of the BOM, so that the file position can\nbe set accordingly. Notice that function `file:position/2` always works on\nbyte-offsets, so that the byte length of the BOM is needed.\n\nTo open a file for writing and place the BOM first is even simpler:\n\n```erlang\nopen_bom_file_for_writing(File,Encoding) ->\n {ok,F} = file:open(File,[write,binary]),\n ok = file:write(File,unicode:encoding_to_bom(Encoding)),\n io:setopts(F,[{encoding,Encoding}]),\n {ok,F}.\n```\n\nThe file is in both these cases then best processed using the `m:io` module, as\nthe functions in that module can handle code points beyond the ISO Latin-1\nrange.","title":"Byte Order Marks - Using Unicode in Erlang","ref":"unicode_usage.html#byte-order-marks"},{"type":"extras","doc":"When reading and writing to Unicode-aware entities, like a file opened for\nUnicode translation, you probably want to format text strings using the\nfunctions in the `m:io` module or the `m:io_lib` module. For backward\ncompatibility reasons, these functions do not accept any list as a string, but\nrequire a special _translation modifier_ when working with Unicode texts. The\nmodifier is `t`. When applied to control character `s` in a formatting string,\nit accepts all Unicode code points and expects binaries to be in UTF-8:\n\n```erlang\n1> io:format(\"~ts~n\",[<<\"åäö\"/utf8>>]).\nåäö\nok\n2> io:format(\"~s~n\",[<<\"åäö\"/utf8>>]).\nåäö\nok\n```\n\nClearly, the second `io:format/2` gives undesired output, as the UTF-8 binary is\nnot in `latin1`. For backward compatibility, the non-prefixed control character\n`s` expects bytewise-encoded ISO Latin-1 characters in binaries and lists\ncontaining only code points < 256.\n\nAs long as the data is always lists, modifier `t` can be used for any string,\nbut when binary data is involved, care must be taken to make the correct choice\nof formatting characters. A bytewise-encoded binary is also interpreted as a\nstring, and printed even when using `~ts`, but it can be mistaken for a valid\nUTF-8 string. Avoid therefore using the `~ts` control if the binary contains\nbytewise-encoded characters and not UTF-8.\n\nFunction `io_lib:format/2` behaves similarly. It is defined to return a deep\nlist of characters and the output can easily be converted to binary data for\noutputting on any device by a simple `erlang:list_to_binary/1`. When the\ntranslation modifier is used, the list can, however, contain characters that\ncannot be stored in one byte. The call to `erlang:list_to_binary/1` then fails.\nHowever, if the I/O server you want to communicate with is Unicode-aware, the\nreturned list can still be used directly:\n\n```erlang\n$ erl +pc unicode\nErlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]\n\nEshell V5.10.1 (abort with ^G)\n1> io_lib:format(\"~ts~n\", [\"Γιούνικοντ\"]).\n[\"Γιούνικοντ\",\"\\n\"]\n2> io:put_chars(io_lib:format(\"~ts~n\", [\"Γιούνικοντ\"])).\nΓιούνικοντ\nok\n```\n\nThe Unicode string is returned as a Unicode list, which is recognized as such,\nas the Erlang shell uses the Unicode encoding (and is started with all Unicode\ncharacters considered printable). The Unicode list is valid input to function\n`io:put_chars/2`, so data can be output on any Unicode-capable device. If the\ndevice is a terminal, characters are output in format `\\x{`H...`}` if encoding\nis `latin1`. Otherwise in UTF-8 (for the non-interactive terminal: \"oldshell\" or\n\"noshell\") or whatever is suitable to show the character properly (for an\ninteractive terminal: the regular shell).\n\nSo, you can always send Unicode data to the\n[`standard_io`](`t:io:standard_io/0`) device. Files, however, accept only\nUnicode code points beyond ISO Latin-1 if `encoding` is set to something else\nthan `latin1`.","title":"Formatted I/O - Using Unicode in Erlang","ref":"unicode_usage.html#formatted-i-o"},{"type":"extras","doc":"While it is strongly encouraged that the encoding of characters in binary data\nis known before processing, that is not always possible. On a typical Linux\nsystem, there is a mix of UTF-8 and ISO Latin-1 text files, and there are seldom\nany BOMs in the files to identify them.\n\nUTF-8 is designed so that ISO Latin-1 characters with numbers beyond the 7-bit\nASCII range are seldom considered valid when decoded as UTF-8. Therefore one can\nusually use heuristics to determine if a file is in UTF-8 or if it is encoded in\nISO Latin-1 (one byte per character). The `m:unicode` module can be used to\ndetermine if data can be interpreted as UTF-8:\n\n```erlang\nheuristic_encoding_bin(Bin) when is_binary(Bin) ->\n case unicode:characters_to_binary(Bin,utf8,utf8) of\n\tBin ->\n\t utf8;\n\t_ ->\n\t latin1\n end.\n```\n\nIf you do not have a complete binary of the file content, you can instead chunk\nthrough the file and check part by part. The return-tuple\n`{incomplete,Decoded,Rest}` from function\n[`unicode:characters_to_binary/1,2,3`](`unicode:characters_to_binary/1`) comes\nin handy. The incomplete rest from one chunk of data read from the file is\nprepended to the next chunk and we therefore avoid the problem of character\nboundaries when reading chunks of bytes in UTF-8 encoding:\n\n```erlang\nheuristic_encoding_file(FileName) ->\n {ok,F} = file:open(FileName,[read,binary]),\n loop_through_file(F,<<>>,file:read(F,1024)).\n\nloop_through_file(_,<<>>,eof) ->\n utf8;\nloop_through_file(_,_,eof) ->\n latin1;\nloop_through_file(F,Acc,{ok,Bin}) when is_binary(Bin) ->\n case unicode:characters_to_binary([Acc,Bin]) of\n\t{error,_,_} ->\n\t latin1;\n\t{incomplete,_,Rest} ->\n\t loop_through_file(F,Rest,file:read(F,1024));\n\tRes when is_binary(Res) ->\n\t loop_through_file(F,<<>>,file:read(F,1024))\n end.\n```\n\nAnother option is to try to read the whole file in UTF-8 encoding and see if it\nfails. Here we need to read the file using function `io:get_chars/3`, as we have\nto read characters with a code point > 255:\n\n```erlang\nheuristic_encoding_file2(FileName) ->\n {ok,F} = file:open(FileName,[read,binary,{encoding,utf8}]),\n loop_through_file2(F,io:get_chars(F,'',1024)).\n\nloop_through_file2(_,eof) ->\n utf8;\nloop_through_file2(_,{error,_Err}) ->\n latin1;\nloop_through_file2(F,Bin) when is_binary(Bin) ->\n loop_through_file2(F,io:get_chars(F,'',1024)).\n```","title":"Heuristic Identification of UTF-8 - Using Unicode in Erlang","ref":"unicode_usage.html#heuristic-identification-of-utf-8"},{"type":"extras","doc":"For various reasons, you can sometimes have a list of UTF-8 bytes. This is not a\nregular string of Unicode characters, as each list element does not contain one\ncharacter. Instead you get the \"raw\" UTF-8 encoding that you have in binaries.\nThis is easily converted to a proper Unicode string by first converting byte per\nbyte into a binary, and then converting the binary of UTF-8 encoded characters\nback to a Unicode string:\n\n```erlang\nutf8_list_to_string(StrangeList) ->\n unicode:characters_to_list(list_to_binary(StrangeList)).\n```","title":"Lists of UTF-8 Bytes - Using Unicode in Erlang","ref":"unicode_usage.html#lists-of-utf-8-bytes"},{"type":"extras","doc":"When working with binaries, you can get the horrible \"double UTF-8 encoding\",\nwhere strange characters are encoded in your binaries or files. In other words,\nyou can get a UTF-8 encoded binary that for the second time is encoded as UTF-8.\nA common situation is where you read a file, byte by byte, but the content is\nalready UTF-8. If you then convert the bytes to UTF-8, using, for example, the\n`m:unicode` module, or by writing to a file opened with option\n`{encoding,utf8}`, you have each _byte_ in the input file encoded as UTF-8, not\neach character of the original text (one character can have been encoded in many\nbytes). There is no real remedy for this other than to be sure of which data is\nencoded in which format, and never convert UTF-8 data (possibly read byte by\nbyte from a file) into UTF-8 again.\n\nBy far the most common situation where this occurs, is when you get lists of\nUTF-8 instead of proper Unicode strings, and then convert them to UTF-8 in a\nbinary or on a file:\n\n```erlang\nwrong_thing_to_do() ->\n {ok,Bin} = file:read_file(\"an_utf8_encoded_file.txt\"),\n MyList = binary_to_list(Bin), %% Wrong! It is an utf8 binary!\n {ok,C} = file:open(\"catastrophe.txt\",[write,{encoding,utf8}]),\n io:put_chars(C,MyList), %% Expects a Unicode string, but get UTF-8\n %% bytes in a list!\n file:close(C). %% The file catastrophe.txt contains more or less unreadable\n %% garbage!\n```\n\nEnsure you know what a binary contains before converting it to a string. If no\nother option exists, try heuristics:\n\n```erlang\nif_you_can_not_know() ->\n {ok,Bin} = file:read_file(\"maybe_utf8_encoded_file.txt\"),\n MyList = case unicode:characters_to_list(Bin) of\n L when is_list(L) ->\n L;\n _ ->\n binary_to_list(Bin) %% The file was bytewise encoded\n end,\n %% Now we know that the list is a Unicode string, not a list of UTF-8 bytes\n {ok,G} = file:open(\"greatness.txt\",[write,{encoding,utf8}]),\n io:put_chars(G,MyList), %% Expects a Unicode string, which is what it gets!\n file:close(G). %% The file contains valid UTF-8 encoded Unicode characters!\n```","title":"Double UTF-8 Encoding - Using Unicode in Erlang","ref":"unicode_usage.html#double-utf-8-encoding"},{"type":"extras","doc":"\n# Uniform Resource Identifiers","title":"Uniform Resource Identifiers","ref":"uri_string_usage.html"},{"type":"extras","doc":"At the time of writing this document, in October 2020, there are two major\nstandards concerning Universal Resource Identifiers and Universal Resource\nLocators:\n\n- [RFC 3986 - Uniform Resource Identifier (URI): Generic Syntax](https://www.ietf.org/rfc/rfc3986.txt)\n- [WHAT WG URL - Living standard](https://url.spec.whatwg.org/)\n\nThe former is a classical standard with a proper formal syntax, using the so\ncalled [Augmented Backus-Naur Form (ABNF)](https://www.ietf.org/rfc/rfc2234.txt)\nfor describing the grammar, while the latter is a living document describing the\ncurrent pratice, that is, how a majority of Web browsers work with URIs. WHAT WG\nURL is Web focused and it has no formal grammar but a plain english description\nof the algorithms that should be followed.\n\nWhat is the difference between them, if any? They provide an overlapping\ndefinition for resource identifiers and they are not compatible. The\n`m:uri_string` module implements\n[RFC 3986](https://www.ietf.org/rfc/rfc3986.txt) and the term URI will be used\nthroughout this document. A URI is an identifier, a string of characters that\nidentifies a particular resource.\n\nFor a more complete problem statement regarding the URIs check the\n[URL Problem Statement and Directions](https://tools.ietf.org/html/draft-ruby-url-problem-01).","title":"Basics - Uniform Resource Identifiers","ref":"uri_string_usage.html#basics"},{"type":"extras","doc":"Let's start with what it is not. It is not the text that you type in the address\nbar in your Web browser. Web browsers do all possible heuristics to convert the\ninput into a valid URI that could be sent over the network.\n\nA URI is an identifier consisting of a sequence of characters matching the\nsyntax rule named `URI` in [RFC 3986](https://www.ietf.org/rfc/rfc3986.txt).\n\nIt is crucial to clarify that a _character_ is a symbol that is displayed on a\nterminal or written to paper and should not be confused with its internal\nrepresentation.\n\nA URI more specifically, is a sequence of characters from a subset of the US\nASCII character set. The generic URI syntax consists of a hierarchical sequence\nof components referred to as the scheme, authority, path, query, and fragment.\nThere is a formal description for each of these components in\n[ABNF](https://www.ietf.org/rfc/rfc2234.txt) notation in\n[RFC 3986](https://www.ietf.org/rfc/rfc3986.txt):\n\n```text\n URI = scheme \":\" hier-part [ \"?\" query ] [ \"#\" fragment ]\n hier-part = \"//\" authority path-abempty\n / path-absolute\n / path-rootless\n / path-empty\n scheme = ALPHA *( ALPHA / DIGIT / \"+\" / \"-\" / \".\" )\n authority = [ userinfo \"@\" ] host [ \":\" port ]\n userinfo = *( unreserved / pct-encoded / sub-delims / \":\" )\n\n reserved = gen-delims / sub-delims\n gen-delims = \":\" / \"/\" / \"?\" / \"#\" / \"[\" / \"]\" / \"@\"\n sub-delims = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n\n unreserved = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n```","title":"What is a URI? - Uniform Resource Identifiers","ref":"uri_string_usage.html#what-is-a-uri"},{"type":"extras","doc":"As producing and consuming standard URIs can get quite complex, Erlang/OTP\nprovides a module, `m:uri_string`, to handle all the most difficult operations\nsuch as parsing, recomposing, normalizing and resolving URIs against a base URI.\n\nThe API functions in `m:uri_string` work on two basic data types\n[`uri_string()`](`t:uri_string:uri_string/0`) and\n[`uri_map()`](`t:uri_string:uri_map/0`).\n[`uri_string()`](`t:uri_string:uri_string/0`) represents a standard URI, while\n[`uri_map()`](`t:uri_string:uri_map/0`) is a wider datatype, that can represent\nURI components using [Unicode](unicode_usage.md#what-unicode-is) characters.\n[`uri_map()`](`t:uri_string:uri_map/0`) is a convenient choice for enabling\noperations such as producing standard compliant URIs out of components that have\nspecial or [Unicode](unicode_usage.md#what-unicode-is) characters. It is easier\nto explain this by an example.\n\nLet's say that we would like to create the following URI and send it over the\nnetwork: `http://cities/örebro?foo bar`. This is not a valid URI as it contains\ncharacters that are not allowed in a URI such as \"ö\" and the space. We can\nverify this by parsing the URI:\n\n```erlang\n 1> uri_string:parse(\"http://cities/örebro?foo bar\").\n {error,invalid_uri,\":\"}\n```\n\nThe URI parser tries all possible combinations to interpret the input and fails\nat the last attempt when it encounters the colon character `\":\"`. Note, that the\ninital fault occurs when the parser attempts to interpret the character `\"ö\"`\nand after a failure back-tracks to the point where it has another possible\nparsing alternative.\n\nThe proper way to solve this problem is to use `uri_string:recompose/1` with a\n[`uri_map()`](`t:uri_string:uri_map/0`) as input:\n\n```erlang\n 2> uri_string:recompose(#{scheme => \"http\", host => \"cities\", path => \"/örebro\",\n query => \"foo bar\"}).\n \"http://cities/%C3%B6rebro?foo%20bar\"\n```\n\nThe result is a valid URI where all the special characters are encoded as\ndefined by the standard. Applying `uri_string:parse/1` and\n`uri_string:percent_decode/1` on the URI returns the original input:\n\n```erlang\n 3> uri_string:percent_decode(uri_string:parse(\"http://cities/%C3%B6rebro?foo%20bar\")).\n #{host => \"cities\",path => \"/örebro\",query => \"foo bar\",\n scheme => \"http\"}\n```\n\nThis symmetric property is heavily used in our property test suite.","title":"The uri_string module - Uniform Resource Identifiers","ref":"uri_string_usage.html#the-uri_string-module"},{"type":"extras","doc":"As you have seen in the previous chapter, a standard URI can only contain a\nstrict subset of the US ASCII character set, moreover the allowed set of\ncharacters is not the same in the different URI components. Percent-encoding is\na mechanism to represent a data octet in a component when that octet's\ncorresponding character is outside of the allowed set or is being used as a\ndelimiter. This is what you see when `\"ö\"` is encoded as `%C3%B6` and `space` as\n`%20`. Most of the API functions are expecting UTF-8 encoding when handling\npercent-encoded triplets. The UTF-8 encoding of the\n[Unicode](unicode_usage.md#what-unicode-is) character `\"ö\"` is two octets:\n`OxC3 0xB6`. The character `space` is in the first 128 characters of\n[Unicode](unicode_usage.md#what-unicode-is) and it is encoded using a single\noctet `0x20`.\n\n> #### Note {: .info }\n>\n> [Unicode](unicode_usage.md#what-unicode-is) is backward compatible with ASCII,\n> the encoding of the first 128 characters is the same binary value as in ASCII.\n\n[](){: #percent_encoding } It is a major source of confusion exactly which\ncharacters will be percent-encoded. In order to make it easier to answer this\nquestion the library provides a utility function,\n[`uri_string:allowed_characters/0 `](`uri_string:allowed_characters/0`), that\nlists the allowed set of characters in each major URI component, and also in the\nmost important standard character sets.\n\n```erlang\n 1> uri_string:allowed_characters().\n [{scheme,\n \"+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\"},\n {userinfo,\n \"!$%&'()*+,-.0123456789:;=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~\"},\n {host,\n \"!$&'()*+,-.0123456789:;=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~\"},\n {ipv4,\".0123456789\"},\n {ipv6,\".0123456789:ABCDEFabcdef\"},\n {regname,\n \"!$%&'()*+,-.0123456789;=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~\"},\n {path,\n \"!$%&'()*+,-./0123456789:;=@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~\"},\n {query,\n \"!$%&'()*+,-./0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~\"},\n {fragment,\n \"!$%&'()*+,-./0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~\"},\n {reserved,\"!#$&'()*+,/:;=?@[]\"},\n {unreserved,\n \"-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~\"}]\n```\n\nIf a URI component has a character that is not allowed, it will be\npercent-encoded when the URI is produced:\n\n```erlang\n 2> uri_string:recompose(#{scheme => \"https\", host => \"local#host\", path => \"\"}).\n \"https://local%23host\"\n```\n\nConsuming a URI containing percent-encoded triplets can take many steps. The\nfollowing example shows how to handle an input URI that is not normalized and\ncontains multiple percent-encoded triplets. First, the input\n[`uri_string()`](`t:uri_string:uri_string/0`) is to be parsed into a\n[`uri_map()`](`t:uri_string:uri_map/0`). The parsing only splits the URI into\nits components without doing any decoding:\n\n```text\n 3> uri_string:parse(\"http://%6C%6Fcal%23host/%F6re%26bro%20\").\n #{host => \"%6C%6Fcal%23host\",path => \"/%F6re%26bro%20\",\n scheme => \"http\"}}\n```\n\nThe input is a valid URI but how can you decode those percent-encoded octets?\nYou can try to normalize the input with `uri_string:normalize/1`. The normalize\noperation decodes those percent-encoded triplets that correspond to a character\nin the unreserved set. Normalization is a safe, idempotent operation that\nconverts a URI into its canonical form:\n\n```erlang\n 4> uri_string:normalize(\"http://%6C%6Fcal%23host/%F6re%26bro%20\").\n \"http://local%23host/%F6re%26bro%20\"\n 5> uri_string:normalize(\"http://%6C%6Fcal%23host/%F6re%26bro%20\", [return_map]).\n #{host => \"local%23host\",path => \"/%F6re%26bro%20\",\n scheme => \"http\"}\n```\n\nThere are still a few percent-encoded triplets left in the output. At this\npoint, when the URI is already parsed, it is safe to apply application specific\ndecoding on the remaining character triplets. Erlang/OTP provides a function,\n`uri_string:percent_decode/1` for raw percent decoding that you can use on the\nhost and path components, or on the whole map:\n\n```erlang\n 6> uri_string:percent_decode(\"local%23host\").\n \"local#host\"\n 7> uri_string:percent_decode(\"/%F6re%26bro%20\").\n {error,invalid_utf8,<<\"/öre&bro \">>}\n 8> uri_string:percent_decode(#{host => \"local%23host\",path => \"/%F6re%26bro%20\",\n scheme => \"http\"}).\n {error,{invalid,{path,{invalid_utf8,<<\"/öre&bro \">>}}}}\n```\n\nThe `host` was successfully decoded but the path contains at least one character\nwith non-UTF-8 encoding. In order to be able to decode this, you have to make\nassumptions about the encoding used in these triplets. The most obvious choice\nis _latin-1_, so you can try `uri_string:transcode/2`, to transcode the path to\nUTF-8 and run the percent-decode operation on the transcoded string:\n\n```erlang\n 9> uri_string:transcode(\"/%F6re%26bro%20\", [{in_encoding, latin1}]).\n \"/%C3%B6re%26bro%20\"\n 10> uri_string:percent_decode(\"/%C3%B6re%26bro%20\").\n \"/öre&bro \"\n```\n\nIt is important to emphasize that it is not safe to apply\n`uri_string:percent_decode/1` directly on an input URI:\n\n```erlang\n 11> uri_string:percent_decode(\"http://%6C%6Fcal%23host/%C3%B6re%26bro%20\").\n \"http://local#host/öre&bro \"\n 12> uri_string:parse(\"http://local#host/öre&bro \").\n {error,invalid_uri,\":\"}\n```\n\n> #### Note {: .info }\n>\n> Percent-encoding is implemented in `uri_string:recompose/1` and it happens\n> when converting a [`uri_map()`](`t:uri_string:uri_map/0`) into a\n> [`uri_string()`](`t:uri_string:uri_string/0`). Applying any percent-encoding\n> directly on an input URI would not be safe just as in the case of\n> `uri_string:percent_decode/1`, the output could be an invalid URI. Quoting\n> functions allow users to perform raw percent encoding and decoding on\n> application data which cannot be handled automatically by\n> `uri_string:recompose/1`. For example in scenario when user would need to use\n> '/' or sub-delimeter as data rather than delimeter in a path component.","title":"Percent-encoding - Uniform Resource Identifiers","ref":"uri_string_usage.html#percent-encoding"},{"type":"extras","doc":"Normalization is the operation of converting the input URI into a _canonical_\nform and keeping the reference to the same underlying resource. The most common\napplication of normalization is determining whether two URIs are equivalent\nwithout accessing their referenced resources.\n\nNormalization has 6 distinct steps. First the input URI is parsed into an\nintermediate form that can handle [Unicode](unicode_usage.md#what-unicode-is)\ncharacters. This datatype is the [`uri_map()`](`t:uri_string:uri_map/0`), that\ncan hold the components of the URI in map elements of type\n`t:unicode:chardata/0`. After having the intermediate form, a sequence of\nnormalization algorithms are applied to the individual URI components:\n\n- **Case normalization** - Converts the `scheme` and `host` components to lower\n case as they are not case sensitive.\n\n- **Percent-encoding normalization** - Decodes percent-encoded triplets that\n correspond to characters in the unreserved set.\n\n- **Scheme-based normalization** - Applying rules for the schemes http, https,\n ftp, ssh, sftp and tftp.\n\n- **Path segment normalization** - Converts the path into a canonical form.\n\nAfter these steps, the intermediate data structure, an\n[`uri_map()`](`t:uri_string:uri_map/0`), is fully normalized. The last step is\napplying `uri_string:recompose/1` that converts the intermediate structure into\na valid canonical URI string.\n\nNotice the order, the\n[`uri_string:normalize(URIMap, [return_map])`](`uri_string:normalize/2`) that we\nused many times in this user guide is a shortcut in the normalization process\nreturning the intermediate datastructure, and allowing us to inspect and apply\nfurther decoding on the remaining percent-encoded triplets.\n\n```text\n 13> uri_string:normalize(\"hTTp://LocalHost:80/%c3%B6rebro/a/../b\").\n \"http://localhost/%C3%B6rebro/b\"\n 14> uri_string:normalize(\"hTTp://LocalHost:80/%c3%B6rebro/a/../b\", [return_map]).\n #{host => \"localhost\",path => \"/%C3%B6rebro/b\",\n scheme => \"http\"}\n```","title":"Normalization - Uniform Resource Identifiers","ref":"uri_string_usage.html#normalization"},{"type":"extras","doc":"The current URI implementation provides support for producing and consuming\nstandard URIs. The API is not meant to be directly exposed in a Web browser's\naddress bar where users can basically enter free text. Application designers\nshall implement proper heuristics to map the input into a parsable URI.","title":"Special considerations - Uniform Resource Identifiers","ref":"uri_string_usage.html#special-considerations"},{"type":"extras","doc":"\n# assert.hrl\n\nAssert macros.","title":"assert.hrl","ref":"assert_hrl.html"},{"type":"extras","doc":"The include file `assert.hrl` provides macros for inserting assertions in your\nprogram code.\n\nInclude the following directive in the module from which the function is called:\n\n```erlang\n-include_lib(\"stdlib/include/assert.hrl\").\n```\n\nWhen an assertion succeeds, the assert macro yields the atom `ok`. When an\nassertion fails, an exception of type `error` is generated. The associated error\nterm has the form `{Macro, Info}`. `Macro` is the macro name, for example,\n`assertEqual`. `Info` is a list of tagged values, such as\n`[{module, M}, {line, L}, ...]`, which gives more information about the location\nand cause of the exception. All entries in the `Info` list are optional; do not\nrely programmatically on any of them being present.\n\nEach assert macro has a corresponding version with an extra argument, for adding\ncomments to assertions. These can for example be printed as part of error\nreports, to clarify the meaning of the check that failed. For example,\n`?assertEqual(0, fib(0), \"Fibonacci is defined for zero\")`. The comment text can\nbe any character data (string, UTF8-binary, or deep list of such data), and will\nbe included in the error term as `{comment, Text}`.\n\nIf the macro `NOASSERT` is defined when `assert.hrl` is read by the compiler,\nthe macros are defined as equivalent to the atom `ok`. The test will not be\nperformed and there is no cost at runtime.\n\nFor example, using `erlc` to compile your modules, the following disables all\nassertions:\n\n```text\nerlc -DNOASSERT=true *.erl\n```\n\n(The value of `NOASSERT` does not matter, only the fact that it is defined.)\n\nA few other macros also have effect on the enabling or disabling of assertions:\n\n- If `NODEBUG` is defined, it implies `NOASSERT` (unless `DEBUG` is also\n defined, which overrides `NODEBUG`).\n- If `ASSERT` is defined, it overrides `NOASSERT`, that is, the assertions\n remain enabled.\n\nIf you prefer, you can thus use only `DEBUG`/`NODEBUG` as the main flags to\ncontrol the behavior of the assertions (which is useful if you have other\ncompiler conditionals or debugging macros controlled by those flags), or you can\nuse `ASSERT`/`NOASSERT` to control only the assert macros.","title":"Description - assert.hrl","ref":"assert_hrl.html#description"},{"type":"extras","doc":"- **`assert(BoolExpr)`**\n\n- **`assert(BoolExpr, Comment)`** - Tests that `BoolExpr` completes normally\n returning `true`.\n\n- **`assertNot(BoolExpr)`**\n\n- **`assertNot(BoolExpr, Comment)`** - Tests that `BoolExpr` completes normally\n returning `false`.\n\n- **`assertMatch(GuardedPattern, Expr)`**\n\n- **`assertMatch(GuardedPattern, Expr, Comment)`** - Tests that `Expr` completes\n normally yielding a value that matches `GuardedPattern`, for example:\n\n ```text\n ?assertMatch({bork, _}, f())\n ```\n\n Notice that a guard `when ...` can be included:\n\n ```erlang\n ?assertMatch({bork, X} when X > 0, f())\n ```\n\n- **`assertNotMatch(GuardedPattern, Expr)`**\n\n- **`assertNotMatch(GuardedPattern, Expr, Comment)`** - Tests that `Expr`\n completes normally yielding a value that does not match `GuardedPattern`.\n\n As in `assertMatch`, `GuardedPattern` can have a `when` part.\n\n- **`assertEqual(ExpectedValue, Expr)`**\n\n- **`assertEqual(ExpectedValue, Expr, Comment)`** - Tests that `Expr` completes\n normally yielding a value that is exactly equal to `ExpectedValue`.\n\n- **`assertNotEqual(ExpectedValue, Expr)`**\n\n- **`assertNotEqual(ExpectedValue, Expr, Comment)`** - Tests that `Expr`\n completes normally yielding a value that is not exactly equal to\n `ExpectedValue`.\n\n- **`assertException(Class, Term, Expr)`**\n\n- **`assertException(Class, Term, Expr, Comment)`** - Tests that `Expr`\n completes abnormally with an exception of type `Class` and with the associated\n `Term`. The assertion fails if `Expr` raises a different exception or if it\n completes normally returning any value.\n\n Notice that both `Class` and `Term` can be guarded patterns, as in\n `assertMatch`.\n\n- **`assertNotException(Class, Term, Expr)`**\n\n- **`assertNotException(Class, Term, Expr, Comment)`** - Tests that `Expr` does\n not evaluate abnormally with an exception of type `Class` and with the\n associated `Term`. The assertion succeeds if `Expr` raises a different\n exception or if it completes normally returning any value.\n\n As in `assertException`, both `Class` and `Term` can be guarded patterns.\n\n- **`assertError(Term, Expr)`**\n\n- **`assertError(Term, Expr, Comment)`** - Equivalent to\n `assertException(error, Term, Expr)`\n\n- **`assertExit(Term, Expr)`**\n\n- **`assertExit(Term, Expr, Comment)`** - Equivalent to\n `assertException(exit, Term, Expr)`\n\n- **`assertThrow(Term, Expr)`**\n\n- **`assertThrow(Term, Expr, Comment)`** - Equivalent to\n `assertException(throw, Term, Expr)`","title":"Macros - assert.hrl","ref":"assert_hrl.html#macros"},{"type":"extras","doc":"`m:compile`, [`erlc(3)`](`e:erts:erlc_cmd.md`)","title":"See Also - assert.hrl","ref":"assert_hrl.html#see-also"}],"content_type":"text/plain","producer":{"name":"ex_doc","version":[48,46,51,52,46,49]}} \ No newline at end of file +searchData={"items":[{"type":"module","doc":"Unix 'tar' utility for reading and writing tar archives.\n\nThis module archives and extract files to and from a tar file. This module\nsupports reading most common tar formats, namely v7, STAR, USTAR, and PAX, as\nwell as some of GNU tar's extensions to the USTAR format (sparse files most\nnotably). It produces tar archives in USTAR format, unless the files being\narchived require PAX format due to restrictions in USTAR (such as unicode\nmetadata, filename length, and more). As such, `erl_tar` supports tar archives\nproduced by most all modern tar utilities, and produces tarballs which should be\nsimilarly portable.\n\nBy convention, the name of a tar file is to end in \"`.tar`\". To abide to the\nconvention, add \"`.tar`\" to the name.\n\nTar files can be created in one operation using function `create/2` or\n`create/3`.\n\nAlternatively, for more control, use functions `open/2`, [`add/3,4`](`add/3`),\nand `close/1`.\n\nTo extract all files from a tar file, use function `extract/1`. To extract only\nsome files or to be able to specify some more options, use function `extract/2`.\n\nTo return a list of the files in a tar file, use function `table/1` or\n`table/2`. To print a list of files to the Erlang shell, use function `t/1` or\n`tt/1`.\n\nTo convert an error term returned from one of the functions above to a readable\nmessage, use function `format_error/1`.","title":"erl_tar","ref":"erl_tar.html"},{"type":"module","doc":"If `file:native_name_encoding/0` returns `utf8`, path names are encoded in UTF-8\nwhen creating tar files, and path names are assumed to be encoded in UTF-8 when\nextracting tar files.\n\nIf `file:native_name_encoding/0` returns `latin1`, no translation of path names\nis done.\n\nUnicode metadata stored in PAX headers is preserved","title":"Unicode Support - erl_tar","ref":"erl_tar.html#module-unicode-support"},{"type":"module","doc":"The `m:ftp` module normally accesses the tar file on disk using the `m:file`\nmodule. When other needs arise, you can define your own low-level Erlang\nfunctions to perform the writing and reading on the storage media; use function\n`init/3`.\n\nAn example of this is the SFTP support in `ssh_sftp:open_tar/3`. This function\nopens a tar file on a remote machine using an SFTP channel.","title":"Other Storage Media - erl_tar","ref":"erl_tar.html#module-other-storage-media"},{"type":"module","doc":"- If you must remain compatible with the USTAR tar format, you must ensure file\n paths being stored are less than 255 bytes in total, with a maximum filename\n component length of 100 bytes. USTAR uses a header field (prefix) in addition\n to the name field, and splits file paths longer than 100 bytes into two parts.\n This split is done on a directory boundary, and is done in such a way to make\n the best use of the space available in those two fields, but in practice this\n will often mean that you have less than 255 bytes for a path. `erl_tar` will\n automatically upgrade the format to PAX to handle longer filenames, so this is\n only an issue if you need to extract the archive with an older implementation\n of `erl_tar` or `tar` which does not support PAX. In this case, the PAX\n headers will be extracted as regular files, and you will need to apply them\n manually.\n- Like the above, if you must remain USTAR compatible, you must also ensure that\n paths for symbolic/hard links are no more than 100 bytes, otherwise PAX\n headers will be used.","title":"Limitations - erl_tar","ref":"erl_tar.html#module-limitations"},{"type":"function","doc":"Equivalent to `add/4`.\n\nIf `Name` is `t:name_in_archive/0`, then [`add(TarDescriptor, Name, Name, Options)`](`add/4`) is called.\n\nIf `Name` is a two tuple then [`add(TarDescriptor, NameInArchive, Name, Options)`](`add/4`) is called.","title":"erl_tar.add/3","ref":"erl_tar.html#add/3"},{"type":"function","doc":"Adds a file to a tar file that has been opened for writing by\n[`open/1`](`open/2`).\n\n`NameInArchive` is the name under which the file becomes stored in the tar file.\nThe file gets this name when it is extracted from the tar file.\n\nOptions:\n\n- **`dereference`** - By default, symbolic links are stored as symbolic links in\n the tar file. To override the default and store the file that the symbolic\n link points to into the tar file, use option `dereference`.\n\n- **`verbose`** - Prints an informational message about the added file.\n\n- **`{chunks,ChunkSize}`** - Reads data in parts from the file. This is intended\n for memory-limited machines that, for example, builds a tar file on a remote\n machine over SFTP, see `ssh_sftp:open_tar/3`.\n\n- **`{atime,non_neg_integer()}`** - Sets the last time, as\n [POSIX time](`e:erts:time_correction.md#posix-time`), when the file was read.\n See also `file:read_file_info/1`.\n\n- **`{mtime,non_neg_integer()}`** - Sets the last time, as\n [POSIX time](`e:erts:time_correction.md#posix-time`), when the file was\n written. See also `file:read_file_info/1`.\n\n- **`{ctime,non_neg_integer()}`** - Sets the time, as\n [POSIX time](`e:erts:time_correction.md#posix-time`), when the file was\n created. See also `file:read_file_info/1`.\n\n- **`{uid,non_neg_integer()}`** - Sets the file owner. `file:read_file_info/1`.\n\n- **`{gid,non_neg_integer()}`** - Sets the group that the file owner belongs to.\n `file:read_file_info/1`.","title":"erl_tar.add/4","ref":"erl_tar.html#add/4"},{"type":"function","doc":"Closes a tar file opened by `open/2`.","title":"erl_tar.close/1","ref":"erl_tar.html#close/1"},{"type":"function","doc":"Creates a tar file and archives the files whose names are specified in\n`FileList` into it. The files can either be read from disk or be specified as\nbinaries.","title":"erl_tar.create/2","ref":"erl_tar.html#create/2"},{"type":"function","doc":"Creates a tar file and archives the files whose names are specified in\n`FileList` into it. The files can either be read from disk or be specified as\nbinaries.\n\nThe options in `OptionList` modify the defaults as follows:\n\n- **`compressed`** - The entire tar file is compressed, as if it has been run\n through the `gzip` program. To abide to the convention that a compressed tar\n file is to end in \"`.tar.gz`\" or \"`.tgz`\", add the appropriate extension.\n\n- **`cooked`** - By default, function [`open/2`](`open/2`) opens the tar file in\n `raw` mode, which is faster but does not allow a remote (Erlang) file server\n to be used. Adding `cooked` to the mode list overrides the default and opens\n the tar file without option `raw`.\n\n- **`dereference`** - By default, symbolic links are stored as symbolic links in\n the tar file. To override the default and store the file that the symbolic\n link points to into the tar file, use option `dereference`.\n\n- **`verbose`** - Prints an informational message about each added file.","title":"erl_tar.create/3","ref":"erl_tar.html#create/3"},{"type":"function","doc":"Extracts all files from a tar archive.\n\nIf argument `Name` is specified as `{binary,Binary}`, the contents of the binary\nis assumed to be a tar archive.\n\nIf argument `Name` is specified as `{file,Fd}`, `Fd` is assumed to be a file\ndescriptor returned from function `file:open/2`.\n\nOtherwise, `Name` is to be a filename.\n\n> #### Note {: .info }\n>\n> Leading slashes in tar member names will be removed before writing the file.\n> That is, absolute paths will be turned into relative paths. There will be an\n> info message written to the error logger when paths are changed in this way.\n\n> #### Warning {: .warning }\n>\n> The `compressed` and `cooked` flags are invalid when passing a file descriptor\n> with `{file,Fd}`. The file is assumed to have been opened with the appropriate\n> flags.","title":"erl_tar.extract/1","ref":"erl_tar.html#extract/1"},{"type":"function","doc":"Extracts files from a tar archive.\n\nIf argument `Name` is specified as `{binary,Binary}`, the contents of the binary\nis assumed to be a tar archive.\n\nIf argument `Name` is specified as `{file,Fd}`, `Fd` is assumed to be a file\ndescriptor returned from function `file:open/2`.\n\nOtherwise, `Name` is to be a filename.\n\nThe following options modify the defaults for the extraction as follows:\n\n- **`{cwd,Cwd}`** - Files with relative filenames are by default extracted to\n the current working directory. With this option, files are instead extracted\n into directory `Cwd`.\n\n- **`{files,FileList}`** - By default, all files are extracted from the tar\n file. With this option, only those files are extracted whose names are\n included in `FileList`.\n\n- **`compressed`** - With this option, the file is uncompressed while\n extracting. If the tar file is not compressed, this option is ignored.\n\n- **`cooked`** - By default, function [`open/2`](`open/2`) function opens the\n tar file in `raw` mode, which is faster but does not allow a remote (Erlang)\n file server to be used. Adding `cooked` to the mode list overrides the default\n and opens the tar file without option `raw`.\n\n- **`memory`** - Instead of extracting to a directory, this option gives the\n result as a list of tuples `{Filename, Binary}`, where `Binary` is a binary\n containing the extracted data of the file named `Filename` in the tar file.\n\n- **`keep_old_files`** - By default, all existing files with the same name as\n files in the tar file are overwritten. With this option, existing files are\n not overwriten.\n\n- **`verbose`** - Prints an informational message for each extracted file.\n\n> #### Warning {: .warning }\n>\n> The `compressed` and `cooked` flags are invalid when passing a file descriptor\n> with `{file,Fd}`. The file is assumed to have been opened with the appropriate\n> flags.","title":"erl_tar.extract/2","ref":"erl_tar.html#extract/2"},{"type":"function","doc":"Converts an error reason term to a human-readable error message string.","title":"erl_tar.format_error/1","ref":"erl_tar.html#format_error/1"},{"type":"function","doc":"The `Fun` is the definition of what to do when the different storage operations\nfunctions are to be called from the higher tar handling functions (such as\n[`add/3`](`add/3`), [`add/4`](`add/4`), and [`close/1`](`close/1`)).\n\nThe `Fun` is called when the tar function wants to do a low-level operation,\nlike writing a block to a file. The `Fun` is called as\n`Fun(Op, {UserData,Parameters...})`, where `Op` is the operation name,\n`UserData` is the term passed as the first argument to `init/1` and\n`Parameters...` are the data added by the tar function to be passed down to the\nstorage handling function.\n\nParameter `UserData` is typically the result of opening a low-level structure\nlike a file descriptor or an SFTP channel id. The different `Fun` clauses\noperate on that very term.\n\nThe following are the fun clauses parameter lists:\n\n- **`(write, {UserData,DataToWrite})`** - Writes term `DataToWrite` using\n `UserData`.\n\n- **`(close, UserData)`** - Closes the access.\n\n- **`(read2, {UserData,Size})`** - Reads using `UserData` but only `Size` bytes.\n Notice that there is only an arity-2 read function, not an arity-1 function.\n\n- **`(position,{UserData,Position})`** - Sets the position of `UserData` as\n defined for files in `file:position/2`\n\n_Example:_\n\nThe following is a complete `Fun` parameter for reading and writing on files\nusing the `m:file` module:\n\n```erlang\nExampleFun =\n fun(write, {Fd,Data}) -> file:write(Fd, Data);\n (position, {Fd,Pos}) -> file:position(Fd, Pos);\n (read2, {Fd,Size}) -> file:read(Fd, Size);\n (close, Fd) -> file:close(Fd)\n end\n```\n\nHere `Fd` was specified to function [`init/3`](`init/3`) as:\n\n```erlang\n{ok,Fd} = file:open(Name, ...).\n{ok,TarDesc} = erl_tar:init(Fd, [write], ExampleFun),\n```\n\n`TarDesc` is then used:\n\n```erlang\nerl_tar:add(TarDesc, SomeValueIwantToAdd, FileNameInTarFile),\n...,\nerl_tar:close(TarDesc)\n```\n\nWhen the `erl_tar` core wants to, for example, write a piece of `Data`, it would\ncall `ExampleFun(write, {UserData,Data})`.\n\n> #### Note {: .info }\n>\n> This example with the `file` module operations is not necessary to use\n> directly, as that is what function `open/2` in principle does.\n\n> #### Warning {: .warning }\n>\n> The `TarDescriptor` term is not a file descriptor. You are advised not to rely\n> on the specific contents of this term, as it can change in future Erlang/OTP\n> releases when more features are added to this module.","title":"erl_tar.init/3","ref":"erl_tar.html#init/3"},{"type":"function","doc":"Creates a tar file for writing (any existing file with the same name is\ntruncated).\n\nBy convention, the name of a tar file is to end in \"`.tar`\". To abide to the\nconvention, add \"`.tar`\" to the name.\n\nExcept for the `write` atom, the following atoms can be added to `OpenModeList`:\n\n- **`compressed`** - The entire tar file is compressed, as if it has been run\n through the `gzip` program. To abide to the convention that a compressed tar\n file is to end in \"`.tar.gz`\" or \"`.tgz`\", add the appropriate extension.\n\n- **`cooked`** - By default, the tar file is opened in `raw` mode, which is\n faster but does not allow a remote (Erlang) file server to be used. Adding\n `cooked` to the mode list overrides the default and opens the tar file without\n option `raw`.\n\nTo add one file at the time into an opened tar file, use function\n[`add/3,4`](`add/3`). When you are finished adding files, use function `close/1`\nto close the tar file.\n\n> #### Warning {: .warning }\n>\n> The `compressed` and `cooked` flags are invalid when passing a file descriptor\n> with `{file,Fd}`. The file must already be opened with the appropriate flags.\n\n> #### Warning {: .warning }\n>\n> The `TarDescriptor` term is not a file descriptor. You are advised not to rely\n> on the specific contents of this term, as it can change in future Erlang/OTP\n> releases when more features are added to this module.","title":"erl_tar.open/2","ref":"erl_tar.html#open/2"},{"type":"function","doc":"Prints the names of all files in the tar file `Name` to the Erlang shell\n(similar to \"`tar t`\").","title":"erl_tar.t/1","ref":"erl_tar.html#t/1"},{"type":"function","doc":"","title":"erl_tar.table/1","ref":"erl_tar.html#table/1"},{"type":"function","doc":"Retrieves the names of all files in the tar file `Name`.","title":"erl_tar.table/2","ref":"erl_tar.html#table/2"},{"type":"function","doc":"Prints names and information about all files in the tar file `Name` to the\nErlang shell (similar to \"`tar tv`\").","title":"erl_tar.tt/1","ref":"erl_tar.html#tt/1"},{"type":"type","doc":"","title":"erl_tar.add_opt/0","ref":"erl_tar.html#t:add_opt/0"},{"type":"type","doc":"","title":"erl_tar.create_opt/0","ref":"erl_tar.html#t:create_opt/0"},{"type":"type","doc":"","title":"erl_tar.extract_opt/0","ref":"erl_tar.html#t:extract_opt/0"},{"type":"type","doc":"","title":"erl_tar.file_op/0","ref":"erl_tar.html#t:file_op/0"},{"type":"type","doc":"","title":"erl_tar.filelist/0","ref":"erl_tar.html#t:filelist/0"},{"type":"type","doc":"","title":"erl_tar.gid/0","ref":"erl_tar.html#t:gid/0"},{"type":"type","doc":"","title":"erl_tar.mode/0","ref":"erl_tar.html#t:mode/0"},{"type":"type","doc":"","title":"erl_tar.name_in_archive/0","ref":"erl_tar.html#t:name_in_archive/0"},{"type":"type","doc":"","title":"erl_tar.open_type/0","ref":"erl_tar.html#t:open_type/0"},{"type":"opaque","doc":"","title":"erl_tar.tar_descriptor/0","ref":"erl_tar.html#t:tar_descriptor/0"},{"type":"type","doc":"","title":"erl_tar.tar_entry/0","ref":"erl_tar.html#t:tar_entry/0"},{"type":"type","doc":"","title":"erl_tar.tar_time/0","ref":"erl_tar.html#t:tar_time/0"},{"type":"type","doc":"","title":"erl_tar.typeflag/0","ref":"erl_tar.html#t:typeflag/0"},{"type":"type","doc":"","title":"erl_tar.uid/0","ref":"erl_tar.html#t:uid/0"},{"type":"type","doc":"","title":"erl_tar.user_data/0","ref":"erl_tar.html#t:user_data/0"},{"type":"module","doc":"Pseudo random number generation\n\nThis module provides pseudo random number generation and implements\na number of base generator algorithms. Most are provided through\na [plug-in framework](#plug-in-framework) that adds\nfeatures to the base generators.\n\nAt the end of this module documentation there are some\n[niche algorithms](#niche-algorithms) that don't use\nthis module's normal [plug-in framework](#plug-in-framework).\nThey may be useful for special purposes like short generation time\nwhen quality is not essential, for seeding other generators, and such.\n\n[](){: #plug-in-framework } Plug-in framework\n---------------------------------------------\n\nThe [plug-in framework](#plug-in-framework-api) implements\na common [API](#plug-in-framework-api) to, and enhancements\nof the base generators:\n\n* Operating on a generator state in the\n [process dictionary](#generator-state).\n* [Automatic](#generator-state) [seeding](`seed/1`).\n* Manual [seeding support](`seed/2`) to avoid common pitfalls.\n* Generating [integers](`t:integer/0`) in any range, with\n [uniform distribution](`uniform/1`), without noticable bias.\n* Generating [integers](`t:integer/0`) in any range, larger than\n the base generator's, with [uniform distribution](`uniform/1`).\n* Generating [floating-point numbers](`t:float/0`) with\n [uniform distribution](`uniform/0`).\n* Generating [floating-point numbers](`t:float/0`) with\n [normal distribution](`normal/0`).\n* Generating any number of [bytes](`bytes/1`).\n\nThe base generator algorithms implements the\n[Xoroshiro and Xorshift algorithms](http://xorshift.di.unimi.it)\nby Sebastiano Vigna. During an iteration they generate a large integer\n(at least 58-bit) and operate on a state of several large integers.\n\nTo create numbers with normal distribution the\n[Ziggurat Method by Marsaglia and Tsang](http://www.jstatsoft.org/v05/i08)\nis used on the output from a base generator.\n\nFor most algorithms, jump functions are provided for generating\nnon-overlapping sequences. A jump function perform a calculation\nequivalent to a large number of repeated state iterations,\nbut execute in a time roughly equivalent to one regular iteration\nper generator bit.\n\n[](){: #algorithms } The following algorithms are provided:\n\n- **`exsss`**, the [_default algorithm_](#default-algorithm)\n *(Since OTP 22.0)* \n Xorshift116\\*\\*, 58 bits precision and period of 2^116-1\n\n Jump function: equivalent to 2^64 calls\n\n This is the Xorshift116 generator combined with the StarStar scrambler from\n the 2018 paper by David Blackman and Sebastiano Vigna:\n [Scrambled Linear Pseudorandom Number Generators](http://vigna.di.unimi.it/ftp/papers/ScrambledLinear.pdf)\n\n The generator doesn't use 58-bit rotates so it is faster than the\n Xoroshiro116 generator, and when combined with the StarStar scrambler\n it doesn't have any weak low bits like `exrop` (Xoroshiro116+).\n\n Alas, this combination is about 10% slower than `exrop`, but despite that\n it is the [_default algorithm_](#default-algorithm) thanks to\n its statistical qualities.\n\n- **`exro928ss`** *(Since OTP 22.0)* \n Xoroshiro928\\*\\*, 58 bits precision and a period of 2^928-1\n\n Jump function: equivalent to 2^512 calls\n\n This is a 58 bit version of Xoroshiro1024\\*\\*, from the 2018 paper by\n David Blackman and Sebastiano Vigna:\n [Scrambled Linear Pseudorandom Number Generators](http://vigna.di.unimi.it/ftp/papers/ScrambledLinear.pdf)\n that on a 64 bit Erlang system executes only about 40% slower than the\n [*default `exsss` algorithm*](#default-algorithm)\n but with much longer period and better statistical properties,\n but on the flip side a larger state.\n\n Many thanks to Sebastiano Vigna for his help with the 58 bit adaption.\n\n- **`exrop`** *(Since OTP 20.0)* \n Xoroshiro116+, 58 bits precision and period of 2^116-1\n\n Jump function: equivalent to 2^64 calls\n\n- **`exs1024s`** *(Since OTP 20.0)* \n Xorshift1024\\*, 64 bits precision and a period of 2^1024-1\n\n Jump function: equivalent to 2^512 calls\n\n- **`exsp`** *(Since OTP 20.0)* \n Xorshift116+, 58 bits precision and period of 2^116-1\n\n Jump function: equivalent to 2^64 calls\n\n This is a corrected version of a previous\n [_default algorithm_](#default-algorithm) (`exsplus`, _deprecated_),\n that was superseded by Xoroshiro116+ (`exrop`). Since this algorithm\n doesn't use rotate it executes a little (say < 15%) faster than `exrop`\n (that has to do a 58 bit rotate, for which there is no native instruction).\n See the [algorithms' homepage](http://xorshift.di.unimi.it).\n\n[](){: #default-algorithm }\n#### Default Algorithm\n\nThe current _default algorithm_ is\n[`exsss` (Xorshift116\\*\\*)](#algorithms). If a specific algorithm is\nrequired, ensure to always use `seed/1` to initialize the state.\n\nWhich algorithm that is the default may change between Erlang/OTP releases,\nand is selected to be one with high speed, small state and \"good enough\"\nstatistical properties.\n\n#### Old Algorithms\n\nUndocumented (old) algorithms are deprecated but still implemented so old code\nrelying on them will produce the same pseudo random sequences as before.\n\n> #### Note {: .info }\n>\n> There were a number of problems in the implementation of\n> the now undocumented algorithms, which is why they are deprecated.\n> The new algorithms are a bit slower but do not have these problems:\n>\n> Uniform integer ranges had a skew in the probability distribution\n> that was not noticable for small ranges but for large ranges\n> less than the generator's precision the probability to produce\n> a low number could be twice the probability for a high.\n>\n> Uniform integer ranges larger than or equal to the generator's precision\n> used a floating point fallback that only calculated with 52 bits\n> which is smaller than the requested range and therefore all numbers\n> in the requested range weren't even possible to produce.\n>\n> Uniform floats had a non-uniform density so small values for example\n> less than 0.5 had got smaller intervals decreasing as the generated value\n> approached 0.0 although still uniformly distributed for sufficiently large\n> subranges. The new algorithms produces uniformly distributed floats\n> on the form `N * 2.0^(-53)` hence they are equally spaced.\n\n[](){: #generator-state }\n#### Generator State\n\nEvery time a random number is generated, a state is used to calculate it,\nproducing a new state. The state can either be implicit\nor be an explicit argument and return value.\n\nThe functions with implicit state operates on a state stored\nin the process dictionary under the key `rand_seed`. If that key\ndoesn't exist when the function is called, `seed/1` is called automatically\nwith the [_default algorithm_](#default-algorithm) and creates\na reasonably unpredictable seed.\n\nThe functions with explicit state don't use the process dictionary.\n\n#### _Examples_\n\nSimple use; create and seed the\n[_default algorithm_](#default-algorithm) with a non-fixed seed,\nif not already done, and generate two uniformly distibuted\nfloating point numbers.\n\n```erlang\nR0 = rand:uniform(),\nR1 = rand:uniform(),\n```\n\nUse a specified algorithm:\n\n```erlang\n_ = rand:seed(exro928ss),\nR2 = rand:uniform(),\n```\n\nUse a specified algorithm with a fixed seed:\n\n```erlang\n_ = rand:seed(exro928ss, {123, 123534, 345345}),\nR3 = rand:uniform(),\n```\n\nUse the functional API with a non-fixed seed:\n\n```erlang\nS0 = rand:seed_s(exsss),\n{R4, S1} = rand:uniform_s(S0),\n```\n\nGenerate a textbook basic form Box-Muller standard normal distribution number:\n\n```erlang\nR5 = rand:uniform_real(),\nR6 = rand:uniform(),\nSND0 = math:sqrt(-2 * math:log(R5)) * math:cos(math:pi() * R6)\n```\n\nGenerate a standard normal distribution number:\n\n```erlang\n{SND1, S2} = rand:normal_s(S1),\n```\n\nGenerate a normal distribution number with with mean -3 and variance 0.5:\n\n```erlang\n{ND0, S3} = rand:normal_s(-3, 0.5, S2),\n```\n\n#### Quality of the Generated Numbers\n\n> #### Note {: .info }\n>\n> The builtin random number generator algorithms are not cryptographically\n> strong. If a cryptographically strong random number generator is needed,\n> use something like `crypto:rand_seed/0`.\n\nFor all these generators except `exro928ss` and `exsss` the lowest bit(s)\nhave got a slightly less random behaviour than all other bits.\n1 bit for `exrop` (and `exsp`), and 3 bits for `exs1024s`. See for example\nthis explanation in the\n[Xoroshiro128+](http://xoroshiro.di.unimi.it/xoroshiro128plus.c)\ngenerator source code:\n\n> Beside passing BigCrush, this generator passes the PractRand test suite\n> up to (and included) 16TB, with the exception of binary rank tests,\n> which fail due to the lowest bit being an LFSR; all other bits pass all\n> tests. We suggest to use a sign test to extract a random Boolean value.\n\nIf this is a problem; to generate a boolean with these algorithms,\nuse something like this:\n\n```erlang\n(rand:uniform(256) > 128) % -> boolean()\n```\n\n```erlang\n((rand:uniform(256) - 1) bsr 7) % -> 0 | 1\n```\n\nFor a general range, with `N = 1` for `exrop`, and `N = 3` for `exs1024s`:\n\n```erlang\n(((rand:uniform(Range bsl N) - 1) bsr N) + 1)\n```\n\nThe floating point generating functions in this module waste the lowest bits\nwhen converting from an integer so they avoid this snag.\n\n\n[](){: #niche-algorithms } Niche algorithms\n-------------------------------------------\n\nThe [niche algorithms API](#niche-algorithms-api) contains\nspecial purpose algorithms that don't use the\n[plug-in framework](#plug-in-framework), mainly for performance reasons.\n\nSince these algorithms lack the plug-in framework support, generating numbers\nin a range other than the base generator's range may become a problem.\n\nThere are at least four ways to do this, assuming the `Range` is less than\nthe generator's range:\n\n[](){: #modulo-method }\n- **Modulo** \n To generate a number `V` in the range `0..Range-1`:\n\n > Generate a number `X`. \n > Use `V = X rem Range` as your value.\n\n This method uses `rem`, that is, the remainder of an integer division,\n which is a slow operation.\n\n Low bits from the generator propagate straight through to\n the generated value, so if the generator has got weaknesses\n in the low bits this method propagates them too.\n\n If `Range` is not a divisor of the generator range, the generated numbers\n have a bias. Example:\n\n Say the generator generates a byte, that is, the generator range\n is `0..255`, and the desired range is `0..99` (`Range = 100`).\n Then there are 3 generator outputs that produce the value `0`,\n these are; `0`, `100` and `200`.\n But there are only 2 generator outputs that produce the value `99`,\n which are; `99` and `199`. So the probability for a value `V` in `0..55`\n is 3/2 times the probability for the other values `56..99`.\n\n If `Range` is much smaller than the generator range, then this bias\n gets hard to detect. The rule of thumb is that if `Range` is smaller\n than the square root of the generator range, the bias is small enough.\n Example:\n\n A byte generator when `Range = 20`. There are 12 (`256 div 20`)\n possibilities to generate the highest numbers and one more to generate\n a number `V < 16` (`256 rem 20`). So the probability is 13/12\n for a low number versus a high. To detect that difference with\n some confidence you would need to generate a lot more numbers\n than the generator range, `256` in this small example.\n\n[](){: #truncated-multiplication-method }\n- **Truncated multiplication** \n To generate a number `V` in the range `0..Range-1`, when you have\n a generator with a power of 2 range (`0..2^Bits-1`):\n\n > Generate a number `X`. \n > Use `V = X * Range bsr Bits` as your value.\n\n If the multiplication `X * Range` creates a bignum\n this method becomes very slow.\n\n High bits from the generator propagate through to the generated value,\n so if the generator has got weaknesses in the high bits this method\n propagates them too.\n\n If `Range` is not a divisor of the generator range, the generated numbers\n have a bias, pretty much as for the [Modulo](#modulo-method) method above.\n\n[](){: #shift-or-mask-method }\n- **Shift or mask** \n To generate a number in a power of 2 range (`0..2^RBits-1`),\n when you have a generator with a power of 2 range (`0..2^Bits`):\n\n > Generate a number `X`. \n > Use `V = X band ((1 bsl RBits)-1)` or `V = X bsr (Bits-RBits)`\n > as your value.\n\n Masking with `band` preserves the low bits, and right shifting\n with `bsr` preserves the high, so if the generator has got weaknesses\n in high or low bits; choose the right operator.\n\n If the generator has got a range that is not a power of 2\n and this method is used anyway, it introduces bias in the same way\n as for the [Modulo](#modulo-method) method above.\n\n[](){: #rejection-method }\n- **Rejection** \n\n > Generate a number `X`. \n > If `X` is in the range, use it as your value,\n > otherwise reject it and repeat.\n\n In theory it is not certain that this method will ever complete,\n but in practice you ensure that the probability of rejection is low.\n Then the probability for yet another iteration decreases exponentially\n so the expected mean number of iterations will often be between 1 and 2.\n Also, since the base generator is a full length generator,\n a value that will break the loop must eventually be generated.\n\n These methods can be combined, such as using\n the [Modulo](#modulo-method) method and only if the generator value\n would create bias use [Rejection](#rejection-method).\n Or using [Shift or mask](#shift-or-mask-method) to reduce the size\n of a generator value so that\n [Truncated multiplication](#truncated-multiplication-method)\n will not create a bignum.\n\n The recommended way to generate a floating point number\n (IEEE 745 Double, that has got a 53-bit mantissa) in the range\n `0..1`, that is `0.0 =< V < 1.0` is to generate a 53-bit number `X`\n and then use `V = X * (1.0/((1 bsl 53)))` as your value.\n This will create a value on the form N*2^-53 with equal probability\n for every possible N for the range.","title":"rand","ref":"rand.html"},{"type":"function","doc":"Generate random bytes as a `t:binary()`,\nusing the state in the process dictionary.\n\nLike `bytes_s/2` but operates on the state stored in\nthe process dictionary. Returns the generated [`Bytes`](`t:binary/0`).","title":"rand.bytes/1","ref":"rand.html#bytes/1"},{"type":"function","doc":"Generate random bytes as a `t:binary()`.\n\nFor a specified integer `N >= 0`, generates a `t:binary/0`\nwith that number of random bytes.\n\nThe selected algorithm is used to generate as many random numbers\nas required to compose the `t:binary/0`. Returns the generated\n[`Bytes`](`t:binary/0`) and a [`NewState`](`t:state/0`).","title":"rand.bytes_s/2","ref":"rand.html#bytes_s/2"},{"type":"function","doc":"Export the seed value.\n\nReturns the random number state in an external format.\nTo be used with `seed/1`.","title":"rand.export_seed/0","ref":"rand.html#export_seed/0"},{"type":"function","doc":"Export the seed value.\n\nReturns the random number generator state in an external format.\nTo be used with `seed/1`.","title":"rand.export_seed_s/1","ref":"rand.html#export_seed_s/1"},{"type":"function","doc":"Jump the generator state forward.\n\nPerforms a [`State`](`t:state/0`) jump calculation\nthat is equvalent to a 2^64 state iterations.\n\nReturns the [`NewState`](`t:state/0`).\n\nThis feature can be used to create many non-overlapping\nrandom number sequences from one start state.\n\nSee the description of jump functions at the top of this module description.\n\nSee `exsp_next/1` about why this internal implementation function\nhas been exposed.","title":"rand.exsp_jump/1","ref":"rand.html#exsp_jump/1"},{"type":"function","doc":"Generate an Xorshift116+ random integer and new algorithm state.\n\nFrom the specified [`AlgState`](`t:exsplus_state/0`),\ngenerates a random 58-bit integer [`X`](`t:uint58/0`)\nand a new algorithm state [`NewAlgState`](`t:exsplus_state/0`),\naccording to the Xorshift116+ algorithm.\n\nThis is an API function exposing the internal implementation of the\n[`exsp`](#algorithms) algorithm that enables using it without the\noverhead of the plug-in framework, which might be useful for time critial\napplications. On a typical 64 bit Erlang VM this approach executes\nin just above 30% (1/3) of the time for the default algorithm through\nthis module's normal plug-in framework.\n\nTo seed this generator use [`{_, AlgState} = rand:seed_s(exsp)`](`seed_s/1`)\nor [`{_, AlgState} = rand:seed_s(exsp, Seed)`](`seed_s/1`)\nwith a specific [`Seed`](`t:seed/0`).\n\n> #### Note {: .info }\n>\n> This function offers no help in generating a number on a selected range,\n> nor in generating floating point numbers. It is easy to accidentally\n> mess up the statistical properties of this generator or to loose\n> the performance advantage when doing either.\n> See the recepies at the start of this\n> [Niche algorithms API](#niche-algorithms-api) description.\n>\n> Note also the caveat about weak low bits that this generator suffers from.\n>\n> The generator is exported in this form primarily for performance reasons.","title":"rand.exsp_next/1","ref":"rand.html#exsp_next/1"},{"type":"function","doc":"Jump the generator state forward.\n\nLike `jump/1` but operates on the state stored in\nthe process dictionary. Returns the [`NewState`](`t:state/0`).","title":"rand.jump/0","ref":"rand.html#jump/0"},{"type":"function","doc":"Jump the generator state forward.\n\nPerforms an algorithm specific [`State`](`t:state/0`) jump calculation\nthat is equvalent to a large number of state iterations.\nSee this module's [algorithms list](#algorithms).\n\nReturns the [`NewState`](`t:state/0`).\n\nThis feature can be used to create many non-overlapping\nrandom number sequences from one start state.\n\nThis function raises a `not_implemented` error exception if there is\nno jump function implemented for the [`State`](`t:state/0`)'s algorithm.","title":"rand.jump/1","ref":"rand.html#jump/1"},{"type":"function","doc":"Generate a new MWC59 state.\n\nFrom the specified generator state [`CX0`](`t:mwc59_state/0`) generate\na new state [`CX1`](`t:mwc59_state/0`), according to a Multiply With Carry\ngenerator, which is an efficient implementation of\na Multiplicative Congruential Generator with a power of 2 multiplier\nand a prime modulus.\n\nThis generator uses the multiplier `2^32` and the modulus\n`16#7fa6502 * 2^32 - 1`, which have been selected, in collaboration with\nSebastiano Vigna, to avoid bignum operations and still get\ngood statistical quality. It has been named \"MWC59\" and can be written as:\n\n```erlang\nC = CX0 bsr 32\nX = CX0 band ((1 bsl 32)-1))\nCX1 = 16#7fa6502 * X + C\n```\n\nBecause the generator uses a multiplier that is a power of 2 it gets\nstatistical flaws for collision tests and birthday spacings tests\nin 2 and 3 dimensions, and these caveats apply even when looking\nonly at the MWC \"digit\", that is the low 32 bits (the multiplier)\nof the generator state. The higher bits of the state are worse.\n\nThe quality of the output value improves much by using a scrambler,\ninstead of just taking the low bits.\nFunction [`mwc59_value32`](`mwc59_value32/1`) is a fast scrambler\nthat returns a decent 32-bit number. The slightly slower\n[`mwc59_value`](`mwc59_value/1`) scrambler returns 59 bits of\nvery good quality, and [`mwc59_float`](`mwc59_float/1`) returns\na `t:float/0` of very good quality.\n\nThe low bits of the base generator are surprisingly good, so the lowest\n16 bits actually pass fairly strict PRNG tests, despite the generator's\nweaknesses that lie in the high bits of the 32-bit MWC \"digit\".\nIt is recommended to use `rem` on the the generator state, or bit mask\nextracting the lowest bits to produce numbers in a range 16 bits or less.\nSee the recepies at the start of this\n[Niche algorithms API](#niche-algorithms-api) description.\n\nOn a typical 64 bit Erlang VM this generator executes in below 8% (1/13)\nof the time for the default algorithm in the\n[plug-in framework API](#plug-in-framework-api) of this module.\nWith the [`mwc59_value32`](`mwc59_value32/1`) scrambler the total time\nbecomes 16% (1/6), and with [`mwc59_value`](`mwc59_value/1`)\nit becomes 20% (1/5) of the time for the default algorithm.\nWith [`mwc59_float`](`mwc59_float/1`) the total time\nis 60% of the time for the default algorithm generating a `t:float/0`.\n\n> #### Note {: .info }\n>\n> This generator is a niche generator for high speed applications.\n> It has a much shorter period than the default generator, which in itself\n> is a quality concern, although when used with the value scramblers\n> it passes strict PRNG tests. The generator is much faster than\n> `exsp_next/1` but with a bit lower quality and much shorter period.","title":"rand.mwc59/1","ref":"rand.html#mwc59/1"},{"type":"function","doc":"Calculate a scrambled `t:float/0` from a [MWC59 state](`t:mwc59_state/0`).\n\nReturns a value `V ::` `t:float/0` from a generator state `CX`,\nin the range `0.0 =< V < 1.0` like for example `uniform_s/1`.\n\nThe generator state is scrambled as with\n[`mwc59_value/1`](`mwc59_value/1`) before converted to a `t:float/0`.","title":"rand.mwc59_float/1","ref":"rand.html#mwc59_float/1"},{"type":"function","doc":"Create a [MWC59 generator state](`t:mwc59_state/0`).\n\nLike `mwc59_seed/1` but it hashes the default seed value\nof [`seed_s(atom())`](`seed_s/1`).","title":"rand.mwc59_seed/0","ref":"rand.html#mwc59_seed/0"},{"type":"function","doc":"Create a [MWC59 generator state](`t:mwc59_state/0`).\n\nReturns a generator state [`CX`](`t:mwc59_state/0`).\nThe 58-bit seed value `S` is hashed to create the generator state,\nto avoid that similar seeds create similar sequences.","title":"rand.mwc59_seed/1","ref":"rand.html#mwc59_seed/1"},{"type":"function","doc":"Calculate a 32-bit scrambled value from a [MWC59 state](`t:mwc59_state/0`).\n\nReturns a 32-bit value [`V`](`t:integer/0`) from a generator state `CX`.\nThe generator state is scrambled using an 8-bit xorshift which masks\nthe statistical imperfecions of the base generator [`mwc59`](`mwc59/1`)\nenough to produce numbers of decent quality. Still some problems\nin 2- and 3-dimensional birthday spacing and collision tests show through.\n\nWhen using this scrambler it is in general better to use the high bits of the\nvalue than the low. The lowest 8 bits are of good quality and are passed\nright through from the base generator. They are combined with the next 8\nin the xorshift making the low 16 good quality, but in the range\n16..31 bits there are weaker bits that should not become high bits\nof the generated values.\n\nTherefore it is in general safer to shift out low bits. See the recepies\nat the start of this [Niche algorithms API](#niche-algorithms-api)\ndescription.\n\nFor a non power of 2 range less than about 16 bits (to not get\ntoo much bias and to avoid bignums) truncated multiplication can be used,\nthat is: `(Range*V) bsr 32`, which is much faster than using `rem`.","title":"rand.mwc59_value32/1","ref":"rand.html#mwc59_value32/1"},{"type":"function","doc":"Calculate a 59-bit scrambled value from a [MWC59 state](`t:mwc59_state/0`).\n\nReturns a 59-bit value [`V`](`t:integer/0`) from a generator state `CX`.\nThe generator state is scrambled using an 4-bit followed by a 27-bit xorshift,\nwhich masks the statistical imperfecions of the [MWC59](`mwc59/1`)\nbase generator enough that all 59 bits are of very good quality.\n\nBe careful to not accidentaly create a bignum when handling the value `V`.\n\nIt is in general general better to use the high bits from this scrambler than\nthe low. See the recepies at the start of this\n[Niche algorithms API](#niche-algorithms-api) description.\n\nFor a non power of 2 range less than about 29 bits (to not get\ntoo much bias and to avoid bignums) truncated multiplication can be used,\nwhich is much faster than using `rem`. Example for range 1'000'000'000;\nthe range is 30 bits, we use 29 bits from the generator,\nadding up to 59 bits, which is not a bignum (on a 64-bit VM ):\n`(1000000000 * (V bsr (59-29))) bsr 29`.","title":"rand.mwc59_value/1","ref":"rand.html#mwc59_value/1"},{"type":"function","doc":"Generate a random number with standard normal distribution.\n\nLike `normal_s/1` but operates on the state stored in\nthe process dictionary. Returns the generated number `X`.","title":"rand.normal/0","ref":"rand.html#normal/0"},{"type":"function","doc":"Generate a random number with specified normal distribution 𝒩 *(μ, σ²)*.\n\nLike `normal_s/3` but operates on the state stored in\nthe process dictionary. Returns the generated number `X`.","title":"rand.normal/2","ref":"rand.html#normal/2"},{"type":"function","doc":"Generate a random number with standard normal distribution.\n\nFrom the specified `State`, generates a random number `X ::` `t:float/0`,\nwith standard normal distribution, that is with mean value `0.0`\nand variance `1.0`.\n\nReturns the generated number [`X`](`t:float/0`)\nand the [`NewState`](`t:state/0`).","title":"rand.normal_s/1","ref":"rand.html#normal_s/1"},{"type":"function","doc":"Generate a random number with specified normal distribution 𝒩 *(μ, σ²)*.\n\nFrom the specified `State`, generates a random number `X ::` `t:float/0`,\nwith normal distribution 𝒩 *(μ, σ²)*, that is 𝒩 (Mean, Variance)\nwhere `Variance >= 0.0`.\n\nReturns [`X`](`t:float/0`) and the [`NewState`](`t:state/0`).","title":"rand.normal_s/3","ref":"rand.html#normal_s/3"},{"type":"function","doc":"Seed the random number generator and select algorithm.\n\nThe same as [`seed_s(Alg_or_State)`](`seed_s/1`),\nbut also stores the generated state in the process dictionary.\n\nThe argument `default` is an alias for the\n[_default algorithm_](#default-algorithm)\nthat has been implemented *(Since OTP 24.0)*.","title":"rand.seed/1","ref":"rand.html#seed/1"},{"type":"function","doc":"Seed the random number generator and select algorithm.\n\nThe same as [`seed_s(Alg, Seed)`](`seed_s/2`),\nbut also stores the generated state in the process dictionary.\n\n`Alg = default` is an alias for the\n[_default algorithm_](#default-algorithm)\nthat has been implemented *(Since OTP 24.0)*.","title":"rand.seed/2","ref":"rand.html#seed/2"},{"type":"function","doc":"Seed the random number generator and select algorithm.\n\nWith the argument `Alg`, select that algorithm and seed random number\ngeneration with reasonably unpredictable time dependent data.\n\n`Alg = default` is an alias for the\n[_default algorithm_](#default-algorithm)\n*(Since OTP 24.0)*.\n\nWith the argument `State`, re-creates the state and returns it.\nSee also `export_seed/0`.","title":"rand.seed_s/1","ref":"rand.html#seed_s/1"},{"type":"function","doc":"Seed the random number generator and select algorithm.\n\nCreates and returns a generator state for the specified algorithm\nfrom the specified `t:seed/0` integers.\n\n`Alg = default` is an alias for the [_default algorithm_](#default-algorithm)\nthat has been implemented *since OTP 24.0*.","title":"rand.seed_s/2","ref":"rand.html#seed_s/2"},{"type":"function","doc":"Generate a SplitMix64 random 64-bit integer and new algorithm state.\n\nFrom the specified `AlgState` generates a random 64-bit integer\n[`X`](`t:uint64/0`) and a new generator state\n[`NewAlgState`](`t:splitmix64_state/0`),\naccording to the SplitMix64 algorithm.\n\nThis generator is used internally in the `rand` module for seeding other\ngenerators since it is of a quite different breed which reduces\nthe probability for creating an accidentally bad seed.","title":"rand.splitmix64_next/1","ref":"rand.html#splitmix64_next/1"},{"type":"function","doc":"Generate a uniformly distributed random number `0.0 =< X < 1.0`,\nusing the state in the process dictionary.\n\nLike `uniform_s/1` but operates on the state stored in\nthe process dictionary. Returns the generated number `X`.","title":"rand.uniform/0","ref":"rand.html#uniform/0"},{"type":"function","doc":"Generate a uniformly distributed random integer `1 =< X =< N`,\nusing the state in the process dictionary.\n\nLike `uniform_s/2` but operates on the state stored in\nthe process dictionary. Returns the generated number `X`.","title":"rand.uniform/1","ref":"rand.html#uniform/1"},{"type":"function","doc":"Generate a uniformly distributed random number `0.0 < X < 1.0`,\nusing the state in the process dictionary.\n\nLike `uniform_real_s/1` but operates on the state stored in\nthe process dictionary. Returns the generated number `X`.\n\nSee `uniform_real_s/1`.","title":"rand.uniform_real/0","ref":"rand.html#uniform_real/0"},{"type":"function","doc":"Generate a uniformly distributed random number `0.0 < X < 1.0`.\n\nFrom the specified state, generates a random float, uniformly distributed\nin the value range `DBL_MIN = #### Note {: .info }\n>\n> The generated numbers from this function has got better granularity\n> for small numbers than the regular `uniform_s/1` because all bits\n> in the mantissa are random. This property, in combination with the fact\n> that exactly zero is never returned is useful for algorithms doing\n> for example `1.0 / X` or `math:log(X)`.\n\nThe concept implicates that the probability to get exactly zero is extremely\nlow; so low that this function in fact never returns `0.0`.\nThe smallest number that it might return is `DBL_MIN`,\nwhich is `2.0^(-1022)`.\n\nThe value range stated at the top of this function description is\ntechnically correct, but `0.0 =< X < 1.0` is a better description\nof the generated numbers' statistical distribution, and that\nthis function never returns exactly `0.0` is impossible to observe.\n\nFor all sub ranges `N*2.0^(-53) =< X < (N+1)*2.0^(-53)` where\n`0 =< integer(N) < 2.0^53`, the probability to generate a number\nin the range is the same. Compare with the numbers\ngenerated by `uniform_s/1`.\n\nHaving to generate extra random bits for occasional small numbers\ncosts a little performance. This function is about 20% slower\nthan the regular `uniform_s/1`","title":"rand.uniform_real_s/1","ref":"rand.html#uniform_real_s/1"},{"type":"function","doc":"Generate a uniformly distributed random number `0.0 =< X < 1.0`.\n\nFrom the specified `State`, generates a random number `X ::` `t:float/0`,\nuniformly distributed in the value range `0.0 = #### Warning {: .warning }\n>\n> This function may return exactly `0.0` which can be fatal for certain\n> applications. If that is undesired you can use `(1.0 - rand:uniform())`\n> to get the interval `0.0 < X =< 1.0`, or instead use `uniform_real/0`.\n>\n> If neither endpoint is desired you can achieve the range\n> `0.0 < X < 1.0` using test and re-try like this:\n>\n> ```erlang\n> my_uniform() ->\n> case rand:uniform() of\n> X when 0.0 X;\n> _ -> my_uniform()\n> end.\n> ```","title":"rand.uniform_s/1","ref":"rand.html#uniform_s/1"},{"type":"function","doc":"Generate a uniformly distributed random integer `1 =< X =< N`.\n\nFrom the specified `State`, generates a random number `X ::` `t:integer/0`,\nuniformly distributed in the specified range `1 =< X =< N`.\nReturns the number `X` and the updated `NewState`.","title":"rand.uniform_s/2","ref":"rand.html#uniform_s/2"},{"type":"type","doc":"","title":"rand.alg/0","ref":"rand.html#t:alg/0"},{"type":"type","doc":"","title":"rand.alg_handler/0","ref":"rand.html#t:alg_handler/0"},{"type":"type","doc":"","title":"rand.alg_state/0","ref":"rand.html#t:alg_state/0"},{"type":"type","doc":"","title":"rand.builtin_alg/0","ref":"rand.html#t:builtin_alg/0"},{"type":"type","doc":"Algorithm specific internal state","title":"rand.dummy_state/0","ref":"rand.html#t:dummy_state/0"},{"type":"type","doc":"Algorithm-dependent state that can be printed or saved to file.","title":"rand.export_state/0","ref":"rand.html#t:export_state/0"},{"type":"opaque","doc":"Algorithm specific internal state","title":"rand.exro928_state/0","ref":"rand.html#t:exro928_state/0"},{"type":"opaque","doc":"Algorithm specific internal state","title":"rand.exrop_state/0","ref":"rand.html#t:exrop_state/0"},{"type":"opaque","doc":"Algorithm specific internal state","title":"rand.exs64_state/0","ref":"rand.html#t:exs64_state/0"},{"type":"opaque","doc":"Algorithm specific internal state","title":"rand.exs1024_state/0","ref":"rand.html#t:exs1024_state/0"},{"type":"opaque","doc":"Algorithm specific internal state","title":"rand.exsplus_state/0","ref":"rand.html#t:exsplus_state/0"},{"type":"type","doc":"`1 .. (16#1ffb072 bsl 29) - 2`","title":"rand.mwc59_state/0","ref":"rand.html#t:mwc59_state/0"},{"type":"type","doc":"Generator seed value.\n\nA list of integers sets the generator's internal state directly, after\nalgorithm-dependent checks of the value and masking to the proper word size.\nThe number of integers must be equal to the number of state words\nin the generator.\n\nA single integer is used as the initial state for a SplitMix64 generator.\nThe sequential output values of that is then used for setting\nthe generator's internal state after masking to the proper word size\nand if needed avoiding zero values.\n\nA traditional 3-tuple of integers seed is passed through algorithm-dependent\nhashing functions to create the generator's initial state.","title":"rand.seed/0","ref":"rand.html#t:seed/0"},{"type":"type","doc":"Algorithm specific state","title":"rand.splitmix64_state/0","ref":"rand.html#t:splitmix64_state/0"},{"type":"type","doc":"Algorithm-dependent state.","title":"rand.state/0","ref":"rand.html#t:state/0"},{"type":"type","doc":"`0 .. (2^58 - 1)`","title":"rand.uint58/0","ref":"rand.html#t:uint58/0"},{"type":"type","doc":"`0 .. (2^64 - 1)`","title":"rand.uint64/0","ref":"rand.html#t:uint64/0"},{"type":"module","doc":"Pseudo-random number generation.\n\nThis module provides a random number generator. The method is attributed to B.A.\nWichmann and I.D. Hill in 'An efficient and portable pseudo-random number\ngenerator', Journal of Applied Statistics. AS183. 1982. Also Byte March 1987.\n\nThe algorithm is a modification of the version attributed to Richard A. O'Keefe\nin the standard Prolog library.\n\nEvery time a random number is requested, a state is used to calculate it, and a\nnew state is produced. The state can either be implicit (kept in the process\ndictionary) or be an explicit argument and return value. In this implementation,\nthe state (the type `t:ran/0`) consists of a tuple of three integers.\n\n> #### Note {: .info }\n>\n> This random number generator is not cryptographically strong. If a strong\n> cryptographic random number generator is needed, use one of functions in the\n> `m:crypto` module, for example, [`crypto:strong_rand_bytes/1`](`m:crypto`).\n\n> #### Note {: .info }\n>\n> The improved `m:rand` module is to be used instead of this module.","title":"random","ref":"random.html"},{"type":"module","doc":"Some of the functions use the process dictionary variable `random_seed` to\nremember the current seed.\n\nIf a process calls `uniform/0` or `uniform/1` without setting a seed first,\n`seed/0` is called automatically.\n\nThe implementation changed in Erlang/OTP R15. Upgrading to R15 breaks\napplications that expect a specific output for a specified seed. The output is\nstill deterministic number series, but different compared to releases older than\nR15. Seed `{0,0,0}` does, for example, no longer produce a flawed series of only\nzeros.","title":"Note - random","ref":"random.html#module-note"},{"type":"function","doc":"Returns the default state.","title":"random.seed0/0","ref":"random.html#seed0/0"},{"type":"function","doc":"Seeds random number generation with default (fixed) values in the process\ndictionary and returns the old state.","title":"random.seed/0","ref":"random.html#seed/0"},{"type":"function","doc":"[`seed({A1, A2, A3})`](`seed/1`) is equivalent to\n[`seed(A1, A2, A3)`](`seed/3`).","title":"random.seed/1","ref":"random.html#seed/1"},{"type":"function","doc":"Seeds random number generation with integer values in the process dictionary and\nreturns the old state.\n\nThe following is an easy way of obtaining a unique value to seed with:\n\n```erlang\nrandom:seed(erlang:phash2([node()]),\n erlang:monotonic_time(),\n erlang:unique_integer())\n```\n\nFor details, see `erlang:phash2/1`, `erlang:node/0`, `erlang:monotonic_time/0`,\nand `erlang:unique_integer/0`.","title":"random.seed/3","ref":"random.html#seed/3"},{"type":"function","doc":"Returns a random float uniformly distributed between `0.0` and `1.0`, updating\nthe state in the process dictionary.","title":"random.uniform/0","ref":"random.html#uniform/0"},{"type":"function","doc":"Returns, for a specified integer `N >= 1`, a random integer uniformly\ndistributed between `1` and `N`, updating the state in the process dictionary.","title":"random.uniform/1","ref":"random.html#uniform/1"},{"type":"function","doc":"Returns, for a specified state, a random float uniformly distributed between\n`0.0` and `1.0`, and a new state.","title":"random.uniform_s/1","ref":"random.html#uniform_s/1"},{"type":"function","doc":"Returns, for a specified integer `N >= 1` and a state, a random integer\nuniformly distributed between `1` and `N`, and a new state.","title":"random.uniform_s/2","ref":"random.html#uniform_s/2"},{"type":"type","doc":"The state.","title":"random.ran/0","ref":"random.html#t:ran/0"},{"type":"module","doc":"Utility for reading and creating 'zip' archives.\n\nThis module archives and extracts files to and from a zip archive. The zip\nformat is specified by the \"ZIP Appnote.txt\" file, available on the PKWARE web\nsite [www.pkware.com](http://www.pkware.com).\n\nThe zip module supports zip archive versions up to 6.1. However,\npassword-protection is not supported.\n\nBy convention, the name of a zip file is to end with `.zip`. To abide to the\nconvention, add `.zip` to the filename.\n\n- To create zip archives, use function `zip/2` or `zip/3`. They are\n also available as [`create/2,3`](`create/3`), to resemble the `m:erl_tar` module.\n- To extract files from a zip archive, use function `unzip/1` or `unzip/2`. They\n are also available as [`extract/1,2`](`extract/1`), to resemble the `m:erl_tar` module.\n- To fold a function over all files in a zip archive, use function `foldl/3`.\n- To return a list of the files in a zip archive, use function `list_dir/1` or\n `list_dir/2`. They are also available as [`table/1,2`](`table/1`), to resemble the\n `m:erl_tar` module.\n- To print a list of files to the Erlang shell, use function `t/1` or `tt/1`.\n- Sometimes it is desirable to open a zip archive, and to unzip files from it\n file by file, without having to reopen the archive. This can be done by\n functions [`zip_open/1,2`](`zip_open/1`), [`zip_get/1,2`](`zip_get/1`),\n `zip_list_dir/1`, and `zip_close/1`.\n- The ZIP extensions 0x5355 \"extended timestamps\" and 0x7875 \"UID+GID handling\"\n are supported. Both extensions are by default enabled when creating an archive,\n but only \"extended timestamps\" are enabled when extracting. Use the `t:extra/0`\n option to change how these extensions are used.","title":"zip","ref":"zip.html"},{"type":"module","doc":"- Password-protected and encrypted archives are not supported.\n- Only the DEFLATE (zlib-compression) and the STORE (uncompressed data) zip\n methods are supported.\n- Comments for individual files are not supported when creating zip archives.\n The zip archive comment for the whole zip archive is supported.\n- Changing a zip archive is not supported. To add or remove a file from an\n archive, the whole archive must be recreated.","title":"Limitations - zip","ref":"zip.html#module-limitations"},{"type":"function","doc":"","title":"zip.create/2","ref":"zip.html#create/2"},{"type":"function","doc":"","title":"zip.create/3","ref":"zip.html#create/3"},{"type":"function","doc":"","title":"zip.extract/1","ref":"zip.html#extract/1"},{"type":"function","doc":"","title":"zip.extract/2","ref":"zip.html#extract/2"},{"type":"function","doc":"Calls `Fun(FileInArchive, GetInfo, GetBin, AccIn)` on successive files in the\n`Archive`, starting with `AccIn == Acc0`.\n\n`FileInArchive` is the name that the file has in the archive.\n\n`GetInfo` is a fun that returns information about the file.\n\n`GetBin` returns the file contents.\n\nBoth `GetInfo` and `GetBin` must be called within the `Fun`. Their behavior is\nundefined if they are called outside the context of `Fun`.\n\nThe `Fun` must return a new accumulator, which is passed to the next call.\n[`foldl/3`](`foldl/3`) returns the final accumulator value. `Acc0` is returned\nif the archive is empty. It is not necessary to iterate over all files in the\narchive. The iteration can be ended prematurely in a controlled manner by\nthrowing an exception.\n\n_Example:_\n\n```erlang\n> Name = \"dummy.zip\".\n\"dummy.zip\"\n> {ok, {Name, Bin}} = zip:create(Name, [{\"foo\", <<\"FOO\">>}, {\"bar\", <<\"BAR\">>}], [memory]).\n{ok,{\"dummy.zip\",\n <<80,75,3,4,20,0,0,0,0,0,74,152,97,60,171,39,212,26,3,0,\n 0,0,3,0,0,...>>}}\n> {ok, FileSpec} = zip:foldl(fun(N, I, B, Acc) -> [{N, B(), I()} | Acc] end, [], {Name, Bin}).\n{ok,[{\"bar\",<<\"BAR\">>,\n {file_info,3,regular,read_write,\n {{2010,3,1},{19,2,10}},\n {{2010,3,1},{19,2,10}},\n {{2010,3,1},{19,2,10}},\n 54,1,0,0,0,0,0}},\n {\"foo\",<<\"FOO\">>,\n {file_info,3,regular,read_write,\n {{2010,3,1},{19,2,10}},\n {{2010,3,1},{19,2,10}},\n {{2010,3,1},{19,2,10}},\n 54,1,0,0,0,0,0}}]}\n> {ok, {Name, Bin}} = zip:create(Name, lists:reverse(FileSpec), [memory]).\n{ok,{\"dummy.zip\",\n <<80,75,3,4,20,0,0,0,0,0,74,152,97,60,171,39,212,26,3,0,\n 0,0,3,0,0,...>>}}\n> catch zip:foldl(fun(\"foo\", _, B, _) -> throw(B()); (_,_,_,Acc) -> Acc end, [], {Name, Bin}).\n<<\"FOO\">>\n```","title":"zip.foldl/3","ref":"zip.html#foldl/3"},{"type":"function","doc":"","title":"zip.list_dir/1","ref":"zip.html#list_dir/1"},{"type":"function","doc":"Retrieves all filenames in the zip archive `Archive`.\n\nThe result value is the tuple `{ok, List}`, where `List` contains the zip\narchive comment as the first element.\n\nOne option is available:\n\n- **`cooked`** - By default, this function opens the zip file in `raw` mode,\n which is faster but does not allow a remote (Erlang) file server to be used.\n Adding `cooked` to the mode list overrides the default and opens the zip file\n without option `raw`.\n\n- **`skip_directories`** - By default empty directories within zip archives are\n listed. With option `skip_directories` set, empty directories are no longer\n listed.\n\n- **`{extra, Extras}`** - The zip \"extra\" features to respect. The supported\n \"extra\" features are \"extended timestamps\" and \"UID and GID\" handling.\n By default only \"extended timestamps\" is enabled when listing files.\n See `t:extra/0` for more details.","title":"zip.list_dir/2","ref":"zip.html#list_dir/2"},{"type":"function","doc":"Prints all filenames in the zip archive `Archive` to the Erlang shell. (Similar\nto `tar t`.)","title":"zip.t/1","ref":"zip.html#t/1"},{"type":"function","doc":"","title":"zip.table/1","ref":"zip.html#table/1"},{"type":"function","doc":"","title":"zip.table/2","ref":"zip.html#table/2"},{"type":"function","doc":"Prints filenames and information about all files in the zip archive `Archive` to\nthe Erlang shell. (Similar to `tar tv`.)","title":"zip.tt/1","ref":"zip.html#tt/1"},{"type":"function","doc":"","title":"zip.unzip/1","ref":"zip.html#unzip/1"},{"type":"function","doc":"Extracts all files from a zip archive.\n\nIf argument `Archive` is specified as a `t:binary/0`, the contents of the binary is\nassumed to be a zip archive, otherwise a filename.\n\nOptions:\n\n- **`{file_list, FileList}`** - By default, all files are extracted from the zip\n archive. With option `{file_list, FileList}`, function [`unzip/2`](`unzip/2`)\n only extracts the files whose names are included in `FileList`. The full\n paths, including the names of all subdirectories within the zip archive, must\n be specified.\n\n- **`cooked`** - By default, this function opens the zip file in `raw` mode,\n which is faster but does not allow a remote (Erlang) file server to be used.\n Adding `cooked` to the mode list overrides the default and opens the zip file\n without option `raw`. The same applies for the files extracted.\n\n- **`keep_old_files`** - By default, all files with the same name as files in\n the zip archive are overwritten. With option `keep_old_files` set, function\n [`unzip/2`](`unzip/2`) does not overwrite existing files. Notice that even\n with option `memory` specified, which means that no files are overwritten,\n existing files are excluded from the result.\n\n- **`skip_directories`** - By default empty directories within zip archives are\n extracted. With option `skip_directories` set, empty directories are no longer\n created.\n\n- **`{extra, Extras}`** - The zip \"extra\" features to respect. The supported\n \"extra\" features are \"extended timestamps\" and \"UID and GID\" handling.\n By default only \"extended timestamps\" is enabled when unzipping.\n See `t:extra/0` for more details.\n\n- **`verbose`** - Prints an informational message for each extracted file.\n\n- **`memory`** - Instead of extracting to the current directory, the result is\n given as a list of tuples `{Filename, Binary}`, where `Binary` is a binary\n containing the extracted data of file `Filename` in the zip archive.\n\n- **`{cwd, CWD}`** - Uses the specified directory as current directory. It is\n prepended to filenames when extracting them from the zip archive. (Acting like\n `file:set_cwd/1` in Kernel, but without changing the global `cwd` property.)","title":"zip.unzip/2","ref":"zip.html#unzip/2"},{"type":"function","doc":"","title":"zip.zip/2","ref":"zip.html#zip/2"},{"type":"function","doc":"Creates a zip archive containing the files specified in `FileList`.\n\n`FileList` is a list of files, with paths relative to the current directory,\nwhich are stored with this path in the archive. File system operations are\nperformed to read the file metadata and, when compression is enabled, to stream\nthe file contents without loading whole files into memory. Files can also be\nspecified as binaries to create an archive directly from data. In such cases, no\nmetadata or file system reads are performed.\n\nFiles are compressed using the DEFLATE compression, as described in the\n\"Appnote.txt\" file. However, files are stored without compression if they are\nalready compressed. [`zip/2`](`zip/2`) and [`zip/3`](`zip/3`) check the file\nextension to determine if the file is to be stored without compression. Files\nwith the following extensions are not compressed: `.Z`, `.zip`, `.zoo`, `.arc`,\n`.lzh`, `.arj`.\n\nIt is possible to override the default behavior and control what types of files\nthat are to be compressed by using options `{compress, What}` and\n`{uncompress, What}`. It is also possible to use many `compress` and\n`uncompress` options.\n\nTo trigger file compression, its extension must match with the `compress`\ncondition and must not match the `uncompress` condition. For example, if\n`compress` is set to `[\"gif\", \"jpg\"]` and `uncompress` is set to `[\"jpg\"]`, only\nfiles with extension `\"gif\"` are compressed.\n\n[](){: #zip_options }\n\nOptions:\n\n- **`cooked`** - By default, this function opens the zip file in mode `raw`,\n which is faster but does not allow a remote (Erlang) file server to be used.\n Adding `cooked` to the mode list overrides the default and opens the zip file\n without the `raw` option. The same applies for the files added.\n\n- **`verbose`** - Prints an informational message about each added file.\n\n- **`memory`** - The output is not to a file, but instead as a tuple\n `{FileName, binary()}`. The binary is a full zip archive with header and can\n be extracted with, for example, `unzip/2`.\n\n- **`{comment, Comment}`** - Adds a comment to the zip archive.\n\n- **`{cwd, CWD}`** - Uses the specified directory as current work directory\n (`cwd`). This is prepended to filenames when adding them, although not in the\n zip archive (acting like `file:set_cwd/1` in Kernel, but without changing the\n global `cwd` property.).\n\n- **`{extra, Extras}`** - The zip \"extra\" features to respect. The supported\n \"extra\" features are \"extended timestamps\" and \"UID and GID\" handling.\n By default both these \"extra\" features are enabled.\n See `t:extra/0` for more details.\n\n- **`{compress, What}`** - Controls what types of files to be compressed.\n Defaults to `all`. The following values of `What` are allowed:\n\n - **`all`** - All files are compressed (as long as they pass the `uncompress`\n condition).\n\n - **`[Extension]`** - Only files with exactly these extensions are compressed.\n\n - **`{add,[Extension]}`** - Adds these extensions to the list of compress\n extensions.\n\n - **`{del,[Extension]}`** - Deletes these extensions from the list of compress\n extensions.\n\n- **`{uncompress, What}`** - Controls what types of files to be uncompressed.\n Defaults to `[\".Z\", \".zip\", \".zoo\", \".arc\", \".lzh\", \".arj\"]`. The following\n values of `What` are allowed:\n\n - **`all`** - No files are compressed.\n\n - **`[Extension]`** - Files with these extensions are uncompressed.\n\n - **`{add,[Extension]}`** - Adds these extensions to the list of uncompress\n extensions.\n\n - **`{del,[Extension]}`** - Deletes these extensions from the list of\n uncompress extensions.","title":"zip.zip/3","ref":"zip.html#zip/3"},{"type":"function","doc":"Closes a zip archive, previously opened with [`zip_open/1,2`](`zip_open/1`). All\nresources are closed, and the handle is not to be used after closing.","title":"zip.zip_close/1","ref":"zip.html#zip_close/1"},{"type":"function","doc":"","title":"zip.zip_get/1","ref":"zip.html#zip_get/1"},{"type":"function","doc":"Extracts one or all files from an open archive.\n\nThe files are unzipped to memory or to file, depending on the options specified\nto function [`zip_open/1,2`](`zip_open/1`) when opening the archive.","title":"zip.zip_get/2","ref":"zip.html#zip_get/2"},{"type":"function","doc":"Extracts one crc32 checksum from an open archive.","title":"zip.zip_get_crc32/2","ref":"zip.html#zip_get_crc32/2"},{"type":"function","doc":"Returns the file list of an open zip archive. The first returned element is the\nzip archive comment.","title":"zip.zip_list_dir/1","ref":"zip.html#zip_list_dir/1"},{"type":"function","doc":"","title":"zip.zip_open/1","ref":"zip.html#zip_open/1"},{"type":"function","doc":"Opens a zip archive, and reads and saves its directory. This means that later\nreading files from the archive is faster than unzipping files one at a time with\n[`unzip/1,2`](`unzip/1`).\n\nThe options are equivalent to those in `unzip/2`.\n\nThe archive must be closed with `zip_close/1`.\n\nThe `ZipHandle` is closed if the process that originally opened the archive\ndies.","title":"zip.zip_open/2","ref":"zip.html#zip_open/2"},{"type":"type","doc":"These options are described in [`create/3`](`m:zip#zip_options`).","title":"zip.create_option/0","ref":"zip.html#t:create_option/0"},{"type":"type","doc":"A filename extension, for example \".txt\".","title":"zip.extension/0","ref":"zip.html#t:extension/0"},{"type":"type","doc":"","title":"zip.extension_spec/0","ref":"zip.html#t:extension_spec/0"},{"type":"type","doc":"The possible extra extension that can be used.\n\n- **`extended_timestamp`** - enables the 0x5455 \"extended timestamps\" zip extension\n that embeds POSIX timestamps for access and modification times for each file in the\n archive. This makes the timestamps to be in UTC instead of local time and also increases\n the time resolution from 2 seconds to 1 second.\n- **`uid_gid`** - enables 0x7875 \"UNIX 3rd generation\" zip extension that embeds the\n UID and GID for each file into the archive.","title":"zip.extra/0","ref":"zip.html#t:extra/0"},{"type":"type","doc":"The name of a zip file.","title":"zip.filename/0","ref":"zip.html#t:filename/0"},{"type":"opaque","doc":"As returned by `zip_open/2`.","title":"zip.handle/0","ref":"zip.html#t:handle/0"},{"type":"type","doc":"The record `zip_comment` only contains the archive comment for a zip archive.","title":"zip.zip_comment/0","ref":"zip.html#t:zip_comment/0"},{"type":"type","doc":"The record `zip_file` contains the following fields:\n\n- **`name`** - The filename\n\n- **`info`** - File information as in `file:read_file_info/1` in Kernel.\n `mtime`, `atime` and `ctime` are expected to be\n in [`local time`](`erlang:localtime/0`) if represented using `t:calendar:datetime/0`,\n or in [OS system time](`e:erts:time_correction.md#os-system-time`) if represented by an integer.\n\n- **`comment`** - The comment for the file in the zip archive\n\n- **`offset`** - The file offset in the zip archive (used internally)\n\n- **`comp_size`** - The size of the compressed file (the size of the\n uncompressed file is found in `info`)","title":"zip.zip_file/0","ref":"zip.html#t:zip_file/0"},{"type":"module","doc":"This module provides an interface to files created by the BEAM Compiler (\"BEAM\nfiles\").\n\nThe format used, a variant of \"EA IFF 1985\" Standard for Interchange Format Files,\ndivides data into chunks.\n\nChunk data can be returned as binaries or as compound terms. Compound terms are\nreturned when chunks are referenced by names (atoms) rather than identifiers\n(strings). The recognized names and the corresponding identifiers are as\nfollows:\n\n- `atoms (\"Atom\")`\n- `attributes (\"Attr\")`\n- `compile_info (\"CInf\")`\n- `debug_info (\"Dbgi\")`\n- `exports (\"ExpT\")`\n- `imports (\"ImpT\")`\n- `indexed_imports (\"ImpT\")`\n- `labeled_exports (\"ExpT\")`\n- `labeled_locals (\"LocT\")`\n- `literals (\"LitT\")`\n- `locals (\"LocT\")`\n- `documentation (\"Docs\")`\n\n[](){: #debug_info }","title":"beam_lib","ref":"beam_lib.html"},{"type":"module","doc":"Option `debug_info` can be specified to the Compiler (see\n[`compile`](`m:compile#debug_info`)) to have debug information, such as\n[Erlang Abstract Format](`e:erts:absform.md`), stored in the `debug_info` chunk.\nTools such as Debugger and Xref require the debug information to be included.\n\n> #### Warning {: .warning }\n>\n> Source code can be reconstructed from the debug information. To prevent this,\n> use encrypted debug information (see below).\n\nThe debug information can also be removed from BEAM files using `strip/1`,\n`strip_files/1`, and/or `strip_release/1`.","title":"Debug Information/Abstract Code - beam_lib","ref":"beam_lib.html#module-debug-information-abstract-code"},{"type":"module","doc":"The following example shows how to reconstruct Erlang source code from the debug\ninformation in a BEAM file `Beam`:\n\n```erlang\n{ok,{_,[{abstract_code,{_,AC}}]}} = beam_lib:chunks(Beam,[abstract_code]).\nio:fwrite(\"~s~n\", [erl_prettypr:format(erl_syntax:form_list(AC))]).\n```","title":"Reconstruct Source Code - beam_lib","ref":"beam_lib.html#module-reconstruct-source-code"},{"type":"module","doc":"The debug information can be encrypted to keep the source code secret, but still\nbe able to use tools such as Debugger or Xref.\n\nTo use encrypted debug information, a key must be provided to the compiler and\n`beam_lib`. The key is specified as a string. It is recommended that the string\ncontains at least 32 characters and that both upper and lower case letters as\nwell as digits and special characters are used.\n\nThe default type (and currently the only type) of crypto algorithm is\n`des3_cbc`, three rounds of DES. The key string is scrambled using\n`erlang:md5/1` to generate the keys used for `des3_cbc`.\n\n> #### Note {: .info }\n>\n> As far as we know by the time of writing, it is infeasible to break `des3_cbc`\n> encryption without any knowledge of the key. Therefore, as long as the key is\n> kept safe and is unguessable, the encrypted debug information _should_ be safe\n> from intruders.\n\nThe key can be provided in the following two ways:\n\n1. Use Compiler option `{debug_info_key,Key}`, see\n [`compile`](`m:compile#debug_info_key`) and function `crypto_key_fun/1` to\n register a fun that returns the key whenever `beam_lib` must decrypt the\n debug information.\n\nIf no such fun is registered, `beam_lib` instead searches for an `.erlang.crypt`\nfile, see the next section.\n\n1. Store the key in a text file named `.erlang.crypt`.\n\nIn this case, Compiler option `encrypt_debug_info` can be used, see\n[`compile`](`m:compile#encrypt_debug_info`).\n\n## .erlang.crypt\n\n`beam_lib` searches for `.erlang.crypt` in the current directory, then the\n[user's home directory](`m:init#home`) and then\n[`filename:basedir(user_config, \"erlang\")`](`m:filename#user_config`). If the\nfile is found and contains a key, `beam_lib` implicitly creates a crypto key fun\nand registers it.\n\nFile `.erlang.crypt` is to contain a single list of tuples:\n\n```erlang\n{debug_info, Mode, Module, Key}\n```\n\n`Mode` is the type of crypto algorithm; currently, the only allowed value is\n`des3_cbc`. `Module` is either an atom, in which case `Key` is only used for the\nmodule `Module`, or `[]`, in which case `Key` is used for all modules. `Key` is\nthe non-empty key string.\n\n`Key` in the first tuple where both `Mode` and `Module` match is used.\n\nThe following is an example of an `.erlang.crypt` file that returns the same key\nfor all modules:\n\n```erlang\n[{debug_info, des3_cbc, [], \"%>7}|pc/DM6Cga*68$Mw]L#&_Gejr]G^\"}].\n```\n\nThe following is a slightly more complicated example of an `.erlang.crypt`\nproviding one key for module `t` and another key for all other modules:\n\n```erlang\n[{debug_info, des3_cbc, t, \"My KEY\"},\n {debug_info, des3_cbc, [], \"%>7}|pc/DM6Cga*68$Mw]L#&_Gejr]G^\"}].\n```\n\n> #### Note {: .info }\n>\n> Do not use any of the keys in these examples. Use your own keys.","title":"Encrypted Debug Information - beam_lib","ref":"beam_lib.html#module-encrypted-debug-information"},{"type":"function","doc":"Reads chunk data for all chunks.","title":"beam_lib.all_chunks/1","ref":"beam_lib.html#all_chunks/1"},{"type":"function","doc":"Builds a BEAM module (as a binary) from a list of chunks.","title":"beam_lib.build_module/1","ref":"beam_lib.html#build_module/1"},{"type":"function","doc":"Reads chunk data for selected chunks references. The order of the returned list\nof chunk data is determined by the order of the list of chunks references.","title":"beam_lib.chunks/2","ref":"beam_lib.html#chunks/2"},{"type":"function","doc":"Reads chunk data for selected chunks references. The order of the returned list\nof chunk data is determined by the order of the list of chunks references.\n\nBy default, if any requested chunk is missing in `Beam`, an `error` tuple is\nreturned. However, if option `allow_missing_chunks` is specified, a result is\nreturned even if chunks are missing. In the result list, any missing chunks are\nrepresented as `{ChunkRef,missing_chunk}`. Notice however that if chunk `\"Atom\"`\nis missing, that is considered a fatal error and the return value is an `error`\ntuple.","title":"beam_lib.chunks/3","ref":"beam_lib.html#chunks/3"},{"type":"function","doc":"Unregisters the crypto key fun and terminates the process holding it, started by\n`crypto_key_fun/1`.\n\nReturns either `{ok, undefined}` if no crypto key fun is registered, or\n`{ok, Term}`, where `Term` is the return value from `CryptoKeyFun(clear)`, see\n[`crypto_key_fun/1`](`crypto_key_fun/1`).","title":"beam_lib.clear_crypto_key_fun/0","ref":"beam_lib.html#clear_crypto_key_fun/0"},{"type":"function","doc":"Compares the contents of two BEAM files.\n\nIf the module names are the same, and all chunks except for chunk `\"CInf\"`\n(the chunk containing the compilation information that is returned by\n`Module:module_info(compile)`) have the same contents in both files, `ok` is\nreturned. Otherwise an error message is returned.","title":"beam_lib.cmp/2","ref":"beam_lib.html#cmp/2"},{"type":"function","doc":"Compares the BEAM files in two directories.\n\nOnly files with extension `\".beam\"` are compared. BEAM files that exist only in\ndirectory `Dir1` (`Dir2`) are returned in `Only1` (`Only2`). BEAM files that\nexist in both directories but are considered different by [`cmp/2`](`cmp/2`) are\n returned as pairs \\{`Filename1`, `Filename2`\\}, where `Filename1` (`Filename2`)\nexists in directory `Dir1` (`Dir2`).","title":"beam_lib.cmp_dirs/2","ref":"beam_lib.html#cmp_dirs/2"},{"type":"function","doc":"Registers an unary fun that is called if `beam_lib` must read an `debug_info`\nchunk that has been encrypted. The fun is held in a process that is started by\nthe function.\n\nIf a fun is already registered when attempting to register a fun,\n`{error, exists}` is returned.\n\nThe fun must handle the following arguments:\n\n```erlang\nCryptoKeyFun(init) -> ok | {ok, NewCryptoKeyFun} | {error, Term}\n```\n\nCalled when the fun is registered, in the process that holds the fun. Here the\ncrypto key fun can do any necessary initializations. If `{ok, NewCryptoKeyFun}`\nis returned, `NewCryptoKeyFun` is registered instead of `CryptoKeyFun`. If\n`{error, Term}` is returned, the registration is aborted and\n[`crypto_key_fun/1`](`crypto_key_fun/1`) also returns `{error, Term}`.\n\n```erlang\nCryptoKeyFun({debug_info, Mode, Module, Filename}) -> Key\n```\n\nCalled when the key is needed for module `Module` in the file named `Filename`.\n`Mode` is the type of crypto algorithm; currently, the only possible value is\n`des3_cbc`. The call is to fail (raise an exception) if no key is available.\n\n```text\nCryptoKeyFun(clear) -> term()\n```\n\nCalled before the fun is unregistered. Here any cleaning up can be done. The\nreturn value is not important, but is passed back to the caller of\n`clear_crypto_key_fun/0` as part of its return value.","title":"beam_lib.crypto_key_fun/1","ref":"beam_lib.html#crypto_key_fun/1"},{"type":"function","doc":"Compares the BEAM files in two directories as `cmp_dirs/2`, but the names of\nfiles that exist in only one directory or are different are presented on\nstandard output.","title":"beam_lib.diff_dirs/2","ref":"beam_lib.html#diff_dirs/2"},{"type":"function","doc":"For a specified error returned by any function in this module, this function\nreturns a descriptive string of the error in English. For file errors, function\n[`file:format_error(Posix)`](`file:format_error/1`) is to be called.","title":"beam_lib.format_error/1","ref":"beam_lib.html#format_error/1"},{"type":"function","doc":"Returns a list containing some information about a BEAM file as tuples\n`{Item, Info}`:\n\n- **`{file, Filename} | {binary, Binary}`** - The name (string) of the BEAM\n file, or the binary from which the information was extracted.\n\n- **`{module, Module}`** - The name (atom) of the module.\n\n- **`{chunks, [{ChunkId, Pos, Size}]}`** - For each chunk, the identifier\n (string) and the position and size of the chunk data, in bytes.","title":"beam_lib.info/1","ref":"beam_lib.html#info/1"},{"type":"function","doc":"Calculates an MD5 redundancy check for the code of the module (compilation date\nand other attributes are not included).","title":"beam_lib.md5/1","ref":"beam_lib.html#md5/1"},{"type":"function","doc":"Removes all chunks from a BEAM file except those used by the loader.\n\nIn particular, the debug information (chunk `debug_info` and `abstract_code`) is\nremoved.","title":"beam_lib.strip/1","ref":"beam_lib.html#strip/1"},{"type":"function","doc":"Removes all chunks from a BEAM file except those used by the loader or mentioned\nin `AdditionalChunks`.\n\nIn particular, the debug information (chunk `debug_info` and `abstract_code`) is removed.","title":"beam_lib.strip/2","ref":"beam_lib.html#strip/2"},{"type":"function","doc":"Removes all chunks except those used by the loader from `Files`.\n\nIn particular, the debug information (chunk `debug_info` and `abstract_code`) is\nremoved. The returned list contains one element for each specified filename, in\nthe same order as in `Files`.","title":"beam_lib.strip_files/1","ref":"beam_lib.html#strip_files/1"},{"type":"function","doc":"Removes all chunks except those used by the loader or mentioned in\n`AdditionalChunks` from `Files`.\n\nIn particular, the debug information (chunk `debug_info` and `abstract_code`) is\nremoved. The returned list contains one element for each specified filename,\nin the same order as in `Files`.","title":"beam_lib.strip_files/2","ref":"beam_lib.html#strip_files/2"},{"type":"function","doc":"Removes all chunks except those used by the loader from the BEAM files of a\nrelease.\n\n`Dir` is to be the installation root directory. For example, the current OTP\nrelease can be stripped with the call `beam_lib:strip_release(code:root_dir())`.","title":"beam_lib.strip_release/1","ref":"beam_lib.html#strip_release/1"},{"type":"function","doc":"Removes all chunks except those used by the loader or mentioned in\n`AdditionalChunks`.\n\n`Dir` is to be the installation root directory. For example, the current OTP\nrelease can be stripped with the call `beam_lib:strip_release(code:root_dir(),[documentation])`.","title":"beam_lib.strip_release/2","ref":"beam_lib.html#strip_release/2"},{"type":"function","doc":"Returns the module version or versions. A version is defined by module attribute\n`-vsn(Vsn)`.\n\nIf this attribute is not specified, the version defaults to the\nchecksum of the module. Notice that if version `Vsn` is not a list, it is made\ninto one, that is `{ok,{Module,[Vsn]}}` is returned. If there are many `-vsn`\nmodule attributes, the result is the concatenated list of versions.\n\n_Examples:_\n\n```erlang\n1> beam_lib:version(a). % -vsn(1).\n{ok,{a,[1]}}\n2> beam_lib:version(b). % -vsn([1]).\n{ok,{b,[1]}}\n3> beam_lib:version(c). % -vsn([1]). -vsn(2).\n{ok,{c,[1,2]}}\n4> beam_lib:version(d). % no -vsn attribute\n{ok,{d,[275613208176997377698094100858909383631]}}\n```","title":"beam_lib.version/1","ref":"beam_lib.html#version/1"},{"type":"type","doc":"It is not checked that the forms conform to the abstract format indicated by\n`AbstVersion`. `no_abstract_code` means that chunk `\"Abst\"` is present, but\nempty.\n\nFor modules compiled with OTP 20 onwards, the `abst_code` chunk is automatically\ncomputed from the `debug_info` chunk.","title":"beam_lib.abst_code/0","ref":"beam_lib.html#t:abst_code/0"},{"type":"type","doc":"","title":"beam_lib.attrib_entry/0","ref":"beam_lib.html#t:attrib_entry/0"},{"type":"type","doc":"Each of the functions described below accept either the filename (as a string)\nor a binary containing the BEAM module.","title":"beam_lib.beam/0","ref":"beam_lib.html#t:beam/0"},{"type":"type","doc":"","title":"beam_lib.chnk_rsn/0","ref":"beam_lib.html#t:chnk_rsn/0"},{"type":"type","doc":"The list of attributes is sorted on `Attribute` (in `t:attrib_entry/0`) and each\nattribute name occurs once in the list. The attribute values occur in the same\norder as in the file. The lists of functions are also sorted.","title":"beam_lib.chunkdata/0","ref":"beam_lib.html#t:chunkdata/0"},{"type":"type","doc":"`\"Attr\" | \"CInf\" | \"Dbgi\" | \"ExpT\" | \"ImpT\" | \"LocT\" | \"AtU8\" | \"Docs\"`","title":"beam_lib.chunkid/0","ref":"beam_lib.html#t:chunkid/0"},{"type":"type","doc":"","title":"beam_lib.chunkname/0","ref":"beam_lib.html#t:chunkname/0"},{"type":"type","doc":"","title":"beam_lib.chunkref/0","ref":"beam_lib.html#t:chunkref/0"},{"type":"type","doc":"","title":"beam_lib.cmp_rsn/0","ref":"beam_lib.html#t:cmp_rsn/0"},{"type":"type","doc":"","title":"beam_lib.compinfo_entry/0","ref":"beam_lib.html#t:compinfo_entry/0"},{"type":"type","doc":"","title":"beam_lib.crypto_fun/0","ref":"beam_lib.html#t:crypto_fun/0"},{"type":"type","doc":"","title":"beam_lib.crypto_fun_arg/0","ref":"beam_lib.html#t:crypto_fun_arg/0"},{"type":"type","doc":"","title":"beam_lib.dataB/0","ref":"beam_lib.html#t:dataB/0"},{"type":"type","doc":"The format stored in the `debug_info` chunk.\n\nTo retrieve particular code representation from the backend,\n`Backend:debug_info(Format, Module, Data, Opts)` must be invoked. `Format` is an\natom, such as `erlang_v1` for the Erlang Abstract Format or `core_v1` for Core\nErlang. `Module` is the module represented by the beam file and `Data` is the\nvalue stored in the debug info chunk. `Opts` is any list of values supported by\nthe `Backend`. `Backend:debug_info/4` must return `{ok, Code}` or\n`{error, Term}`.\n\nDevelopers must always invoke the `debug_info/4` function and never rely on the\n`Data` stored in the `debug_info` chunk, as it is opaque and may change at any\nmoment. `no_debug_info` means that chunk `\"Dbgi\"` is present, but empty.","title":"beam_lib.debug_info/0","ref":"beam_lib.html#t:debug_info/0"},{"type":"type","doc":"[EEP-48 documentation format](`e:kernel:eep48_chapter.md#the-docs-format`)","title":"beam_lib.docs/0","ref":"beam_lib.html#t:docs/0"},{"type":"type","doc":"","title":"beam_lib.forms/0","ref":"beam_lib.html#t:forms/0"},{"type":"type","doc":"","title":"beam_lib.index/0","ref":"beam_lib.html#t:index/0"},{"type":"type","doc":"","title":"beam_lib.info_rsn/0","ref":"beam_lib.html#t:info_rsn/0"},{"type":"type","doc":"","title":"beam_lib.label/0","ref":"beam_lib.html#t:label/0"},{"type":"type","doc":"","title":"beam_lib.labeled_entry/0","ref":"beam_lib.html#t:labeled_entry/0"},{"type":"type","doc":"","title":"beam_lib.literals/0","ref":"beam_lib.html#t:literals/0"},{"type":"type","doc":"","title":"beam_lib.mode/0","ref":"beam_lib.html#t:mode/0"},{"type":"module","doc":"An Erlang code preprocessor.\n\nThe Erlang code preprocessor includes functions that are used by the `m:compile`\nmodule to preprocess macros and include files before the parsing takes place.\n\nThe Erlang source file _encoding_{: #encoding } is selected by a comment in one\nof the first two lines of the source file. The first string matching the regular\nexpression `coding\\s*[:=]\\s*([-a-zA-Z0-9])+` selects the encoding. If the\nmatching string is not a valid encoding, it is ignored. The valid encodings are\n`Latin-1` and `UTF-8`, where the case of the characters can be chosen freely.\n\n_Examples:_\n\n```erlang\n%% coding: utf-8\n```\n\n```erlang\n%% For this file we have chosen encoding = Latin-1\n```\n\n```erlang\n%% -*- coding: latin-1 -*-\n```","title":"epp","ref":"epp.html"},{"type":"module","doc":"`ErrorInfo` is the standard `ErrorInfo` structure that is returned from all I/O\nmodules. The format is as follows:\n\n```erlang\n{ErrorLine, Module, ErrorDescriptor}\n```\n\nA string describing the error is obtained with the following call:\n\n```erlang\nModule:format_error(ErrorDescriptor)\n```","title":"Error Information - epp","ref":"epp.html#module-error-information"},{"type":"module","doc":"`m:erl_parse`","title":"See Also - epp","ref":"epp.html#module-see-also"},{"type":"function","doc":"Closes the preprocessing of a file.","title":"epp.close/1","ref":"epp.html#close/1"},{"type":"function","doc":"Returns the default encoding of Erlang source files.","title":"epp.default_encoding/0","ref":"epp.html#default_encoding/0"},{"type":"function","doc":"Returns a string representation of an encoding. The string is recognized by\n[`read_encoding/1,2`](`read_encoding/1`),\n[`read_encoding_from_binary/1,2`](`read_encoding_from_binary/1`), and\n[`set_encoding/1,2`](`set_encoding/1`) as a valid encoding.","title":"epp.encoding_to_string/1","ref":"epp.html#encoding_to_string/1"},{"type":"function","doc":"Takes an `ErrorDescriptor` and returns a string that describes the error or\nwarning. This function is usually called implicitly when processing an\n`ErrorInfo` structure (see section [Error Information](`m:epp#module-error-information`)).","title":"epp.format_error/1","ref":"epp.html#format_error/1"},{"type":"function","doc":"Opens a file for preprocessing.\n\nIf you want to change the file name of the implicit -file() attributes inserted\nduring preprocessing, you can do with `{source_name, SourceName}`. If unset it\nwill default to the name of the opened file.\n\nSetting `{deterministic, Enabled}` will additionally reduce the file name of the\nimplicit -file() attributes inserted during preprocessing to only the basename\nof the path.\n\nIf `extra` is specified in `Options`, the return value is `{ok, Epp, Extra}`\ninstead of `{ok, Epp}`.\n\nThe option `location` is forwarded to the Erlang token scanner, see\n[`erl_scan:tokens/3,4`](`erl_scan:tokens/3`).\n\nThe `{compiler_internal,term()}` option is forwarded to the Erlang token\nscanner, see [`{compiler_internal,term()}`](`m:erl_scan#compiler_interal`).","title":"epp.open/1","ref":"epp.html#open/1"},{"type":"function","doc":"Equivalent to `epp:open([{name, FileName}, {includes, IncludePath}])`.","title":"epp.open/2","ref":"epp.html#open/2"},{"type":"function","doc":"Equivalent to\n`epp:open([{name, FileName}, {includes, IncludePath}, {macros, PredefMacros}])`.","title":"epp.open/3","ref":"epp.html#open/3"},{"type":"function","doc":"Returns the next Erlang form from the opened Erlang source file. Tuple\n`{eof, Location}` is returned at the end of the file. The first form corresponds\nto an implicit attribute `-file(File,1).`, where `File` is the file name.","title":"epp.parse_erl_form/1","ref":"epp.html#parse_erl_form/1"},{"type":"function","doc":"Preprocesses and parses an Erlang source file. Notice that tuple\n`{eof, Location}` returned at the end of the file is included as a \"form\".\n\nIf you want to change the file name of the implicit -file() attributes inserted\nduring preprocessing, you can do with `{source_name, SourceName}`. If unset it\nwill default to the name of the opened file.\n\nIf `extra` is specified in `Options`, the return value is `{ok, [Form], Extra}`\ninstead of `{ok, [Form]}`.\n\nThe option `location` is forwarded to the Erlang token scanner, see\n[`erl_scan:tokens/3,4`](`erl_scan:tokens/3`).\n\nThe `{compiler_internal,term()}` option is forwarded to the Erlang token\nscanner, see [`{compiler_internal,term()}`](`m:erl_scan#compiler_interal`).","title":"epp.parse_file/2","ref":"epp.html#parse_file/2"},{"type":"function","doc":"Equivalent to\n`epp:parse_file(FileName, [{includes, IncludePath}, {macros, PredefMacros}])`.","title":"epp.parse_file/3","ref":"epp.html#parse_file/3"},{"type":"function","doc":"","title":"epp.read_encoding/1","ref":"epp.html#read_encoding/1"},{"type":"function","doc":"Read the [encoding](`m:epp#encoding`) from a file. Returns the read encoding, or\n`none` if no valid encoding is found.\n\nOption `in_comment_only` is `true` by default, which is correct for Erlang\nsource files. If set to `false`, the encoding string does not necessarily have\nto occur in a comment.","title":"epp.read_encoding/2","ref":"epp.html#read_encoding/2"},{"type":"function","doc":"","title":"epp.read_encoding_from_binary/1","ref":"epp.html#read_encoding_from_binary/1"},{"type":"function","doc":"Read the [encoding](`m:epp#encoding`) from a binary. Returns the read encoding,\nor `none` if no valid encoding is found.\n\nOption `in_comment_only` is `true` by default, which is correct for Erlang\nsource files. If set to `false`, the encoding string does not necessarily have\nto occur in a comment.","title":"epp.read_encoding_from_binary/2","ref":"epp.html#read_encoding_from_binary/2"},{"type":"function","doc":"Returns the raw tokens of the next Erlang form from the opened Erlang source\nfile. A tuple `{eof, Line}` is returned at the end of the file. The first form\ncorresponds to an implicit attribute `-file(File,1).`, where `File` is the file\nname.","title":"epp.scan_erl_form/1","ref":"epp.html#scan_erl_form/1"},{"type":"function","doc":"Preprocesses an Erlang source file returning a list of the lists of raw tokens\nof each form. Notice that the tuple `{eof, Line}` returned at the end of the\nfile is included as a \"form\", and any failures to scan a form are included in\nthe list as tuples `{error, ErrorInfo}`.","title":"epp.scan_file/2","ref":"epp.html#scan_file/2"},{"type":"function","doc":"Reads the [encoding](`m:epp#encoding`) from an I/O device and sets the encoding\nof the device accordingly. The position of the I/O device referenced by `File`\nis not affected. If no valid encoding can be read from the I/O device, the\nencoding of the I/O device is set to the default encoding.\n\nReturns the read encoding, or `none` if no valid encoding is found.","title":"epp.set_encoding/1","ref":"epp.html#set_encoding/1"},{"type":"function","doc":"Reads the [encoding](`m:epp#encoding`) from an I/O device and sets the encoding\nof the device accordingly. The position of the I/O device referenced by `File`\nis not affected. If no valid encoding can be read from the I/O device, the\nencoding of the I/O device is set to the [encoding](`m:epp#encoding`) specified\nby `Default`.\n\nReturns the read encoding, or `none` if no valid encoding is found.","title":"epp.set_encoding/2","ref":"epp.html#set_encoding/2"},{"type":"type","doc":"Handle to the `epp` server.","title":"epp.epp_handle/0","ref":"epp.html#t:epp_handle/0"},{"type":"type","doc":"","title":"epp.macros/0","ref":"epp.html#t:macros/0"},{"type":"type","doc":"","title":"epp.source_encoding/0","ref":"epp.html#t:source_encoding/0"},{"type":"type","doc":"","title":"epp.warning_info/0","ref":"epp.html#t:warning_info/0"},{"type":"module","doc":"Abstract datatype for the annotations of the Erlang Compiler.\n\nThis module provides an abstract type that is used by the Erlang Compiler and\nits helper modules for holding data such as column, line number, and text. The\ndata type is a collection of _annotations_{: #annotations } as described in the\nfollowing.\n\nThe Erlang Token Scanner returns tokens with a subset of the following\nannotations, depending on the options:\n\n- **`column`** - The column where the token begins.\n\n- **`location`** - The line and column where the token begins, or just the line\n if the column is unknown.\n\n- **`text`** - The token's text.\n\nFrom this, the following annotation is derived:\n\n- **`line`** - The line where the token begins.\n\nThis module also supports the following annotations, which are used by various\nmodules:\n\n- **`file`** - A filename.\n\n- **`generated`** - A Boolean indicating if the abstract code is\n compiler-generated. The Erlang Compiler does not emit warnings for such code.\n\n- **`record`** - A Boolean indicating if the origin of the abstract code is a\n record. Used by [Dialyzer](`m:dialyzer`) to assign types to tuple elements.\n\nThe functions [`column()`](`erl_scan:column/1`),\n[`end_location()`](`erl_scan:end_location/1`), [`line()`](`erl_scan:line/1`),\n[`location()`](`erl_scan:location/1`), and [`text()`](`erl_scan:text/1`) in the\n`erl_scan` module can be used for inspecting annotations in tokens.\n\nThe functions [`anno_from_term()`](`erl_parse:anno_from_term/1`),\n[`anno_to_term()`](`erl_parse:anno_to_term/1`),\n[`fold_anno()`](`erl_parse:fold_anno/3`),\n[`map_anno()`](`erl_parse:map_anno/2`),\n[`mapfold_anno()`](`erl_parse:mapfold_anno/3`), and\n[`new_anno()`](`erl_parse:new_anno/1`), in the `erl_parse` module can be used\nfor manipulating annotations in abstract code.","title":"erl_anno","ref":"erl_anno.html"},{"type":"module","doc":"`m:erl_parse`, `m:erl_scan`","title":"See Also - erl_anno","ref":"erl_anno.html#module-see-also"},{"type":"function","doc":"Returns the column of the annotations Anno.","title":"erl_anno.column/1","ref":"erl_anno.html#column/1"},{"type":"function","doc":"Returns the end location of the annotations Anno.\n\nIf the end location annotation is present, its value is returned. Otherwise,\nif the text annotation is present, the end location is inferred from the\nlocation and the text. Finally, if there is no text, `undefined` is returned.","title":"erl_anno.end_location/1","ref":"erl_anno.html#end_location/1"},{"type":"function","doc":"Returns the filename of the annotations Anno. If there is no filename,\n`undefined` is returned.","title":"erl_anno.file/1","ref":"erl_anno.html#file/1"},{"type":"function","doc":"Returns annotations with representation Term.\n\nSee also [to_term()](`to_term/1`).","title":"erl_anno.from_term/1","ref":"erl_anno.html#from_term/1"},{"type":"function","doc":"Returns `true` if annotations Anno is marked as generated. The default is to\nreturn `false`.","title":"erl_anno.generated/1","ref":"erl_anno.html#generated/1"},{"type":"function","doc":"Returns `true` if Term is a collection of annotations, otherwise `false`.","title":"erl_anno.is_anno/1","ref":"erl_anno.html#is_anno/1"},{"type":"function","doc":"Returns the line of the annotations Anno.","title":"erl_anno.line/1","ref":"erl_anno.html#line/1"},{"type":"function","doc":"Returns the location of the annotations Anno.","title":"erl_anno.location/1","ref":"erl_anno.html#location/1"},{"type":"function","doc":"Creates a new collection of annotations given a location.","title":"erl_anno.new/1","ref":"erl_anno.html#new/1"},{"type":"function","doc":"Modifies the end location of the annotations Anno.","title":"erl_anno.set_end_location/2","ref":"erl_anno.html#set_end_location/2"},{"type":"function","doc":"Modifies the filename of the annotations Anno.","title":"erl_anno.set_file/2","ref":"erl_anno.html#set_file/2"},{"type":"function","doc":"Modifies the generated marker of the annotations Anno.","title":"erl_anno.set_generated/2","ref":"erl_anno.html#set_generated/2"},{"type":"function","doc":"Modifies the line of the annotations Anno.","title":"erl_anno.set_line/2","ref":"erl_anno.html#set_line/2"},{"type":"function","doc":"Modifies the location of the annotations Anno.","title":"erl_anno.set_location/2","ref":"erl_anno.html#set_location/2"},{"type":"function","doc":"Modifies the record marker of the annotations Anno.","title":"erl_anno.set_record/2","ref":"erl_anno.html#set_record/2"},{"type":"function","doc":"Modifies the text of the annotations Anno.","title":"erl_anno.set_text/2","ref":"erl_anno.html#set_text/2"},{"type":"function","doc":"Returns the text of the annotations Anno. If there is no text, `undefined` is\nreturned.","title":"erl_anno.text/1","ref":"erl_anno.html#text/1"},{"type":"function","doc":"Returns the term representing the annotations Anno.\n\nSee also [from_term()](`from_term/1`).","title":"erl_anno.to_term/1","ref":"erl_anno.html#to_term/1"},{"type":"opaque","doc":"A collection of annotations.","title":"erl_anno.anno/0","ref":"erl_anno.html#t:anno/0"},{"type":"type","doc":"The term representing a collection of annotations. It is either a `t:location/0`\nor a list of key-value pairs.","title":"erl_anno.anno_term/0","ref":"erl_anno.html#t:anno_term/0"},{"type":"type","doc":"","title":"erl_anno.column/0","ref":"erl_anno.html#t:column/0"},{"type":"type","doc":"","title":"erl_anno.filename/0","ref":"erl_anno.html#t:filename/0"},{"type":"type","doc":"","title":"erl_anno.generated/0","ref":"erl_anno.html#t:generated/0"},{"type":"type","doc":"","title":"erl_anno.line/0","ref":"erl_anno.html#t:line/0"},{"type":"type","doc":"","title":"erl_anno.location/0","ref":"erl_anno.html#t:location/0"},{"type":"type","doc":"","title":"erl_anno.record/0","ref":"erl_anno.html#t:record/0"},{"type":"type","doc":"","title":"erl_anno.text/0","ref":"erl_anno.html#t:text/0"},{"type":"module","doc":"The Erlang meta interpreter.\n\nThis module provides an interpreter for Erlang expressions. The expressions are\nin the abstract syntax as returned by `m:erl_parse`, the Erlang parser, or\n`m:io`.","title":"erl_eval","ref":"erl_eval.html"},{"type":"module","doc":"During evaluation of a function, no calls can be made to local functions. An\nundefined function error would be generated. However, the optional argument\n`LocalFunctionHandler` can be used to define a function that is called when\nthere is a call to a local function. The argument can have the following\nformats:\n\n- **`{value,Func}`** - This defines a local function handler that is called\n with:\n\n ```erlang\n Func(Name, Arguments)\n ```\n\n `Name` is the name of the local function (an atom) and `Arguments` is a list\n of the _evaluated_ arguments. The function handler returns the value of the\n local function. In this case, the current bindings cannot be accessed. To\n signal an error, the function handler calls [`exit/1`](`exit/1`) with a\n suitable exit value.\n\n- **`{eval,Func}`** - This defines a local function handler that is called with:\n\n ```erlang\n Func(Name, Arguments, Bindings)\n ```\n\n `Name` is the name of the local function (an atom), `Arguments` is a list of\n the _unevaluated_ arguments, and `Bindings` are the current variable bindings.\n The function handler returns:\n\n ```erlang\n {value,Value,NewBindings}\n ```\n\n `Value` is the value of the local function and `NewBindings` are the updated\n variable bindings. In this case, the function handler must itself evaluate all\n the function arguments and manage the bindings. To signal an error, the\n function handler calls [`exit/1`](`exit/1`) with a suitable exit value.\n\n- **`none`** - There is no local function handler.","title":"Local Function Handler - erl_eval","ref":"erl_eval.html#module-local-function-handler"},{"type":"module","doc":"The optional argument `NonLocalFunctionHandler` can be used to define a function\nthat is called in the following cases:\n\n- A functional object (fun) is called.\n- A built-in function is called.\n- A function is called using the `M:F` syntax, where `M` and `F` are atoms or\n expressions.\n- An operator `Op/A` is called (this is handled as a call to function\n `erlang:Op/A`).\n\nExceptions are calls to `erlang:apply/2,3`; neither of the function handlers are\ncalled for such calls. The argument can have the following formats:\n\n- **`{value,Func}`** - This defines a non-local function handler. The function\n may be called with two arguments:\n\n ```erlang\n Func(FuncSpec, Arguments)\n ```\n\n or three arguments:\n\n ```erlang\n Func(Anno, FuncSpec, Arguments)\n ```\n\n `Anno` is the [`erl_anno:anno()`](`t:erl_anno:anno/0`) of the node, `FuncSpec`\n is the name of the function on the form `{Module,Function}` or a fun, and\n `Arguments` is a list of the _evaluated_ arguments. The function handler\n returns the value of the function. To signal an error, the function handler\n calls [`exit/1`](`exit/1`) with a suitable exit value.\n\n- **`none`** - There is no non-local function handler.\n\n> #### Note {: .info }\n>\n> For calls such as `erlang:apply(Fun, Args)` or\n> `erlang:apply(Module, Function, Args)`, the call of the non-local function\n> handler corresponding to the call to `erlang:apply/2,3` itself\n> (`Func({erlang, apply}, [Fun, Args])` or\n> `Func({erlang, apply}, [Module, Function, Args])`) never takes place.\n>\n> The non-local function handler _is_ however called with the evaluated\n> arguments of the call to `erlang:apply/2,3`: `Func(Fun, Args)` or\n> `Func({Module, Function}, Args)` (assuming that `{Module, Function}` is not\n> `{erlang, apply}`).\n>\n> Calls to functions defined by evaluating fun expressions `\"fun ... end\"` are\n> also hidden from non-local function handlers.\n\nThe non-local function handler argument is probably not used as frequently as\nthe local function handler argument. A possible use is to call\n[`exit/1`](`exit/1`) on calls to functions that for some reason are not allowed\nto be called.","title":"Non-Local Function Handler - erl_eval","ref":"erl_eval.html#module-non-local-function-handler"},{"type":"function","doc":"Adds binding `Name=Value` to `BindingStruct`. Returns an updated binding\nstructure.","title":"erl_eval.add_binding/3","ref":"erl_eval.html#add_binding/3"},{"type":"function","doc":"Returns the binding of `Name` in `BindingStruct`.","title":"erl_eval.binding/2","ref":"erl_eval.html#binding/2"},{"type":"function","doc":"Returns the list of bindings contained in the binding structure.","title":"erl_eval.bindings/1","ref":"erl_eval.html#bindings/1"},{"type":"function","doc":"Removes the binding of `Name` in `BindingStruct`. Returns an updated binding\nstructure.","title":"erl_eval.del_binding/2","ref":"erl_eval.html#del_binding/2"},{"type":"function","doc":"","title":"erl_eval.expr/2","ref":"erl_eval.html#expr/2"},{"type":"function","doc":"","title":"erl_eval.expr/3","ref":"erl_eval.html#expr/3"},{"type":"function","doc":"","title":"erl_eval.expr/4","ref":"erl_eval.html#expr/4"},{"type":"function","doc":"Evaluates `Expression` with the set of bindings `Bindings`. `Expression` is an\nexpression in abstract syntax.\n\nFor an explanation of when and how to use arguments `LocalFunctionHandler` and\n`NonLocalFunctionHandler`, see sections\n[Local Function Handler](`m:erl_eval#module-local-function-handler`) and\n[Non-Local Function Handler](`m:erl_eval#module-non-local-function-handler`) in this\nmodule.\n\nReturns `{value, Value, NewBindings}` by default. If `ReturnFormat` is `value`,\nonly `Value` is returned.","title":"erl_eval.expr/5","ref":"erl_eval.html#expr/5"},{"type":"function","doc":"","title":"erl_eval.expr_list/2","ref":"erl_eval.html#expr_list/2"},{"type":"function","doc":"","title":"erl_eval.expr_list/3","ref":"erl_eval.html#expr_list/3"},{"type":"function","doc":"Evaluates a list of expressions in parallel, using the same initial bindings for\neach expression. Attempts are made to merge the bindings returned from each\nevaluation.\n\nThis function is useful in `LocalFunctionHandler`, see section\n[Local Function Handler](`m:erl_eval#module-local-function-handler`) in this module.\n\nReturns `{ValueList, NewBindings}`.","title":"erl_eval.expr_list/4","ref":"erl_eval.html#expr_list/4"},{"type":"function","doc":"","title":"erl_eval.exprs/2","ref":"erl_eval.html#exprs/2"},{"type":"function","doc":"","title":"erl_eval.exprs/3","ref":"erl_eval.html#exprs/3"},{"type":"function","doc":"Evaluates `Expressions` with the set of bindings `Bindings`, where `Expressions`\nis a sequence of expressions (in abstract syntax) of a type that can be returned\nby `io:parse_erl_exprs/2`.\n\nFor an explanation of when and how to use arguments\n`LocalFunctionHandler` and `NonLocalFunctionHandler`, see sections\n[Local Function Handler](`m:erl_eval#module-local-function-handler`) and\n[Non-Local Function Handler](`m:erl_eval#module-non-local-function-handler`) in this\nmodule.\n\nReturns `{value, Value, NewBindings}`","title":"erl_eval.exprs/4","ref":"erl_eval.html#exprs/4"},{"type":"function","doc":"Returns an empty binding structure.","title":"erl_eval.new_bindings/0","ref":"erl_eval.html#new_bindings/0"},{"type":"function","doc":"","title":"erl_eval.new_bindings/1","ref":"erl_eval.html#new_bindings/1"},{"type":"type","doc":"A binding structure. It is either a `map` or an `orddict`. `erl_eval` will\nalways return the same type as the one given.","title":"erl_eval.binding_struct/0","ref":"erl_eval.html#t:binding_struct/0"},{"type":"type","doc":"","title":"erl_eval.bindings/0","ref":"erl_eval.html#t:bindings/0"},{"type":"type","doc":"","title":"erl_eval.expression/0","ref":"erl_eval.html#t:expression/0"},{"type":"type","doc":"","title":"erl_eval.expression_list/0","ref":"erl_eval.html#t:expression_list/0"},{"type":"type","doc":"As returned by `erl_parse:parse_exprs/1` or `io:parse_erl_exprs/2`.","title":"erl_eval.expressions/0","ref":"erl_eval.html#t:expressions/0"},{"type":"type","doc":"","title":"erl_eval.func_spec/0","ref":"erl_eval.html#t:func_spec/0"},{"type":"type","doc":"","title":"erl_eval.lfun_eval_handler/0","ref":"erl_eval.html#t:lfun_eval_handler/0"},{"type":"type","doc":"","title":"erl_eval.lfun_value_handler/0","ref":"erl_eval.html#t:lfun_value_handler/0"},{"type":"type","doc":"Further described in section\n[Local Function Handler](`m:erl_eval#module-local-function-handler`) in this module","title":"erl_eval.local_function_handler/0","ref":"erl_eval.html#t:local_function_handler/0"},{"type":"type","doc":"","title":"erl_eval.name/0","ref":"erl_eval.html#t:name/0"},{"type":"type","doc":"","title":"erl_eval.nlfun_handler/0","ref":"erl_eval.html#t:nlfun_handler/0"},{"type":"type","doc":"Further described in section\n[Non-Local Function Handler](`m:erl_eval#module-non-local-function-handler`) in this\nmodule.","title":"erl_eval.non_local_function_handler/0","ref":"erl_eval.html#t:non_local_function_handler/0"},{"type":"type","doc":"","title":"erl_eval.value/0","ref":"erl_eval.html#t:value/0"},{"type":"module","doc":"This module expands records in a module.","title":"erl_expand_records","ref":"erl_expand_records.html"},{"type":"module","doc":"Section [The Abstract Format](`e:erts:absform.md`) in ERTS User's Guide.","title":"See Also - erl_expand_records","ref":"erl_expand_records.html#module-see-also"},{"type":"function","doc":"Expands all records in a module to use explicit tuple operations and adds\nexplicit module names to calls to BIFs and imported functions. The returned\nmodule has no references to records, attributes, or code.","title":"erl_expand_records.module/2","ref":"erl_expand_records.html#module/2"},{"type":"module","doc":"This module contains functions for supporting features that can be\nenabled/disabled in Erlang.\n\nIt should be considered as mostly for internal use, although there are some\nfunctions that might be useful when writing tools.","title":"erl_features","ref":"erl_features.html"},{"type":"function","doc":"Return a list of all known features. This list will include features that have\nbeen removed (status `rejected`) and features that are no longer configurable\n(status `permanent`).","title":"erl_features.all/0","ref":"erl_features.html#all/0"},{"type":"function","doc":"Return a list of all configurable features, that is, features with status\n`experimental` or `approved`. These are the features that can be enabled or\ndisabled.","title":"erl_features.configurable/0","ref":"erl_features.html#configurable/0"},{"type":"function","doc":"Return a list of the features that are currently enabled. Note that the set of\nenabled is set during startup and can then not be changed.","title":"erl_features.enabled/0","ref":"erl_features.html#enabled/0"},{"type":"function","doc":"Return a map containing information about the given feature.","title":"erl_features.info/1","ref":"erl_features.html#info/1"},{"type":"function","doc":"Return the list of features enabled when compiling the module. The module need\nnot be loaded, but is found if it exists in the loadpath. If not all features\nused by the module are enabled in the runtime, loading the module is not\nallowed.","title":"erl_features.used/1","ref":"erl_features.html#used/1"},{"type":"type","doc":"","title":"erl_features.feature/0","ref":"erl_features.html#t:feature/0"},{"type":"type","doc":"","title":"erl_features.release/0","ref":"erl_features.html#t:release/0"},{"type":"type","doc":"","title":"erl_features.status/0","ref":"erl_features.html#t:status/0"},{"type":"type","doc":"","title":"erl_features.type/0","ref":"erl_features.html#t:type/0"},{"type":"module","doc":"This module performs an identity parse transformation of Erlang code.\n\nIt is included as an example for users who wants to write their own\nparse transformers. If option `{parse_transform,Module}` is passed\nto the compiler, a user-written function `parse_transform/2`\nis called by the compiler before the code is checked for errors.\n\nBefore the function `parse_transform/2` is called, the Erlang\nCompiler checks if the parse transformation can handle abstract code\nwith column numbers: If the function `parse_transform_info/0`\nis implemented and returns a map where the key `error_location` is\nassociated with the value `line`, the compiler removes\ncolumn numbers from the abstract code before calling the parse\ntransform. Otherwise, the compiler passes the abstract code on\nwithout modification.","title":"erl_id_trans","ref":"erl_id_trans.html"},{"type":"module","doc":"Parse transformations are used if a programmer wants to use\nErlang syntax, but with different semantics. The original Erlang\ncode is then transformed into other Erlang code.\n\n> #### Note {: .info }\n>\n> Programmers are strongly advised not to engage in parse\n> transformations. No support is offered for problems encountered.\n>","title":"Parse Transformations - erl_id_trans","ref":"erl_id_trans.html#module-parse-transformations"},{"type":"module","doc":"`m:erl_parse` and `m:compile`.","title":"See Also - erl_id_trans","ref":"erl_id_trans.html#module-see-also"},{"type":"function","doc":"Performs an identity transformation on Erlang forms, as an example.","title":"erl_id_trans.parse_transform/2","ref":"erl_id_trans.html#parse_transform/2"},{"type":"function","doc":"Returns information about the parse transform itself.","title":"erl_id_trans.parse_transform_info/0","ref":"erl_id_trans.html#parse_transform_info/0"},{"type":"module","doc":"Internal Erlang definitions.\n\nThis module defines Erlang BIFs, guard tests, and operators. This module is only\nof interest to programmers who manipulate Erlang code.","title":"erl_internal","ref":"erl_internal.html"},{"type":"function","doc":"Adds to `Forms` the code for the standard pre-defined functions (such as\n`module_info/0`) that are to be included in every module.","title":"erl_internal.add_predefined_functions/1","ref":"erl_internal.html#add_predefined_functions/1"},{"type":"function","doc":"Returns `true` if `OpName/Arity` is an arithmetic operator, otherwise `false`.","title":"erl_internal.arith_op/2","ref":"erl_internal.html#arith_op/2"},{"type":"function","doc":"Returns `true` if `Name/Arity` is an Erlang BIF that is automatically recognized\nby the compiler, otherwise `false`.","title":"erl_internal.bif/2","ref":"erl_internal.html#bif/2"},{"type":"function","doc":"Returns `true` if `OpName/Arity` is a Boolean operator, otherwise `false`.","title":"erl_internal.bool_op/2","ref":"erl_internal.html#bool_op/2"},{"type":"function","doc":"Returns `true` if `OpName/Arity` is a comparison operator, otherwise `false`.","title":"erl_internal.comp_op/2","ref":"erl_internal.html#comp_op/2"},{"type":"function","doc":"Returns `true` if `Name/Arity` is an Erlang BIF that is allowed in guards,\notherwise `false`.","title":"erl_internal.guard_bif/2","ref":"erl_internal.html#guard_bif/2"},{"type":"function","doc":"Returns `true` if `OpName/Arity` is a list operator, otherwise `false`.","title":"erl_internal.list_op/2","ref":"erl_internal.html#list_op/2"},{"type":"function","doc":"Returns the `Type` of operator that `OpName/Arity` belongs to, or generates a\n`function_clause` error if it is not an operator.","title":"erl_internal.op_type/2","ref":"erl_internal.html#op_type/2"},{"type":"function","doc":"Returns `true` if `OpName/Arity` is a send operator, otherwise `false`.","title":"erl_internal.send_op/2","ref":"erl_internal.html#send_op/2"},{"type":"function","doc":"Returns `true` if `Name/Arity` is a valid Erlang type test, otherwise `false`.","title":"erl_internal.type_test/2","ref":"erl_internal.html#type_test/2"},{"type":"module","doc":"The Erlang code linter.\n\nThis module is used to check Erlang code for illegal syntax and other bugs. It\nalso warns against coding practices that are not recommended.\n\nThe errors detected include:\n\n- Redefined and undefined functions\n- Unbound and unsafe variables\n- Illegal record use\n\nThe warnings detected include:\n\n- Unused functions and imports\n- Unused variables\n- Variables imported into matches\n- Variables exported from `if`/`case`/`receive`\n- Variables shadowed in funs and list comprehensions\n\nSome of the warnings are optional, and can be turned on by specifying the\nappropriate option, described below.\n\nThe functions in this module are invoked automatically by the Erlang compiler.\nThere is no reason to invoke these functions separately unless you have written\nyour own Erlang compiler.","title":"erl_lint","ref":"erl_lint.html"},{"type":"module","doc":"`ErrorInfo` is the standard `ErrorInfo` structure that is returned from all I/O\nmodules. The format is as follows:\n\n```erlang\n{ErrorLine, Module, ErrorDescriptor}\n```\n\nA string describing the error is obtained with the following call:\n\n```erlang\nModule:format_error(ErrorDescriptor)\n```","title":"Error Information - erl_lint","ref":"erl_lint.html#module-error-information"},{"type":"module","doc":"`m:epp`, `m:erl_parse`","title":"See Also - erl_lint","ref":"erl_lint.html#module-see-also"},{"type":"function","doc":"Takes an `ErrorDescriptor` and returns a string that describes the error or\nwarning. This function is usually called implicitly when processing an\n`ErrorInfo` structure (see section [Error Information](`m:erl_lint#module-error-information`)).","title":"erl_lint.format_error/1","ref":"erl_lint.html#format_error/1"},{"type":"function","doc":"Tests if `Expr` is a legal guard test. `Expr` is an Erlang term representing the\nabstract form for the expression.\n[`erl_parse:parse_exprs(Tokens)`](`erl_parse:parse_exprs/1`) can be used to\ngenerate a list of `Expr`.","title":"erl_lint.is_guard_test/1","ref":"erl_lint.html#is_guard_test/1"},{"type":"function","doc":"","title":"erl_lint.module/1","ref":"erl_lint.html#module/1"},{"type":"function","doc":"","title":"erl_lint.module/2","ref":"erl_lint.html#module/2"},{"type":"function","doc":"Checks all the forms in a module for errors. It returns:\n\n- **`{ok,Warnings}`** - There are no errors in the module.\n\n- **`{error,Errors,Warnings}`** - There are errors in the module.\n\nAs this module is of interest only to the maintainers of the compiler, and to\navoid the same description in two places, the elements of `Options` that control\nthe warnings are only described in the [`compile`](`m:compile#erl_lint_options`)\nmodule.\n\n`AbsForms` of a module, which comes from a file that is read through `epp`, the\nErlang preprocessor, can come from many files. This means that any references to\nerrors must include the filename, see the `m:epp` module or parser (see the\n`m:erl_parse` module). The returned errors and warnings have the following\nformat:\n\n```text\n[{SourceFile,[ErrorInfo]}]\n```\n\nThe errors and warnings are listed in the order in which they are encountered in\nthe forms. The errors from one file can therefore be split into different\nentries in the list of errors.","title":"erl_lint.module/3","ref":"erl_lint.html#module/3"},{"type":"type","doc":"","title":"erl_lint.error_description/0","ref":"erl_lint.html#t:error_description/0"},{"type":"type","doc":"","title":"erl_lint.error_info/0","ref":"erl_lint.html#t:error_info/0"},{"type":"type","doc":"","title":"erl_lint.fa/0","ref":"erl_lint.html#t:fa/0"},{"type":"type","doc":"","title":"erl_lint.fun_used_vars/0","ref":"erl_lint.html#t:fun_used_vars/0"},{"type":"module","doc":"This module is the basic Erlang parser that converts tokens into the abstract\nform of either forms (that is, top-level constructs), expressions, or terms.\n\nThe Abstract Format is described in the ERTS User's Guide. Notice that a token\nlist must end with the dot token to be acceptable to the parse functions\n(see the `m:erl_scan`) module.","title":"erl_parse","ref":"erl_parse.html"},{"type":"module","doc":"ErrorInfo is the standard ErrorInfo structure that is returned from all I/O modules.\nThe format is as follows:\n\n```\n{ErrorLine, Module, ErrorDescriptor}\n```\n\nA string describing the error is obtained with the following call:\n\n```\nModule:format_error(ErrorDescriptor)\n```","title":"Error Information - erl_parse","ref":"erl_parse.html#module-error-information"},{"type":"module","doc":"`m:erl_anno`, `m:erl_scan`, `m:io`, section [The Abstract Format](`e:erts:absform`)\nin the ERTS User's Guide.","title":"See Also - erl_parse","ref":"erl_parse.html#module-see-also"},{"type":"function","doc":"Converts the Erlang data structure `Data` into an abstract form of type\n`AbsTerm`. This function is the inverse of `normalise/1`.\n\n`erl_parse:abstract(T)` is equivalent to `erl_parse:abstract(T, 0)`.","title":"erl_parse.abstract/1","ref":"erl_parse.html#abstract/1"},{"type":"function","doc":"Converts the Erlang data structure `Data` into an abstract form of type\n`AbsTerm`.\n\nEach node of `AbsTerm` is assigned an annotation, see `m:erl_anno`. The\nannotation contains the location given by option `location` or by option `line`.\nOption `location` overrides option `line`. If neither option `location` nor\noption `line` is given, `0` is used as location.\n\nOption `Encoding` is used for selecting which integer lists to be considered as\nstrings. The default is to use the encoding returned by function\n`epp:default_encoding/0`. Value `none` means that no integer lists are\nconsidered as strings. `encoding_func()` is called with one integer of a list at\na time; if it returns `true` for every integer, the list is considered a string.","title":"erl_parse.abstract/2","ref":"erl_parse.html#abstract/2"},{"type":"function","doc":"Assumes that `Term` is a term with the same structure as a `erl_parse` tree, but\nwith terms, say `T`, where a `erl_parse` tree has collections of annotations.\n\nReturns a `erl_parse` tree where each term `T` is replaced by the value returned\nby [`erl_anno:from_term(T)`](`erl_anno:from_term/1`). The term `Term` is\ntraversed in a depth-first, left-to-right fashion.","title":"erl_parse.anno_from_term/1","ref":"erl_parse.html#anno_from_term/1"},{"type":"function","doc":"Returns a term where each collection of annotations `Anno` of the nodes of the\n`erl_parse` tree `Abstr` is replaced by the term returned by\n[`erl_anno:to_term(Anno)`](`erl_anno:to_term/1`). The `erl_parse` tree is\ntraversed in a depth-first, left-to-right fashion.","title":"erl_parse.anno_to_term/1","ref":"erl_parse.html#anno_to_term/1"},{"type":"function","doc":"Updates an accumulator by applying `Fun` on each collection of annotations of\nthe `erl_parse` tree `Abstr`.\n\nThe first call to `Fun` has `AccIn` as argument, the returned accumulator\n`AccOut` is passed to the next call, and so on. The\nfinal value of the accumulator is returned. The `erl_parse` tree is traversed in\na depth-first, left-to-right fashion.","title":"erl_parse.fold_anno/3","ref":"erl_parse.html#fold_anno/3"},{"type":"function","doc":"Uses an ErrorDescriptor and returns a string that describes the error.\n\nThis function is usually called implicitly when an ErrorInfo structure is\nprocessed (see section [Error Information](#module-error-information)).","title":"erl_parse.format_error/1","ref":"erl_parse.html#format_error/1"},{"type":"function","doc":"Modifies the `erl_parse` tree `Abstr` by applying `Fun` on each collection of\nannotations of the nodes of the `erl_parse` tree. The `erl_parse` tree is\ntraversed in a depth-first, left-to-right fashion.","title":"erl_parse.map_anno/2","ref":"erl_parse.html#map_anno/2"},{"type":"function","doc":"Modifies the `erl_parse` tree `Abstr` by applying `Fun` on each collection of\nannotations of the nodes of the `erl_parse` tree, while at the same time\nupdating an accumulator.\n\nThe first call to `Fun` has `AccIn` as second argument,\nthe returned accumulator `AccOut` is passed to the next call, and so on. The\nmodified `erl_parse` tree and the final value of the accumulator are returned.\nThe `erl_parse` tree is traversed in a depth-first, left-to-right fashion.","title":"erl_parse.mapfold_anno/3","ref":"erl_parse.html#mapfold_anno/3"},{"type":"function","doc":"Assumes that `Term` is a term with the same structure as a `erl_parse` tree, but\nwith [locations](`t:erl_anno:location/0`) where a `erl_parse` tree has\ncollections of annotations.\n\nReturns a `erl_parse` tree where each location `L`\nis replaced by the value returned by [`erl_anno:new(L)`](`erl_anno:new/1`). The\nterm `Term` is traversed in a depth-first, left-to-right fashion.","title":"erl_parse.new_anno/1","ref":"erl_parse.html#new_anno/1"},{"type":"function","doc":"Converts the abstract form `AbsTerm` of a term into a conventional Erlang data\nstructure (that is, the term itself). This function is the inverse of\n`abstract/1`.","title":"erl_parse.normalise/1","ref":"erl_parse.html#normalise/1"},{"type":"function","doc":"Parses `Tokens` as if it was a list of expressions.\n\nReturns one of the following:\n\n- **`{ok, ExprList}`** - The parsing was successful. `ExprList` is a list of the\n abstract forms of the parsed expressions.\n\n- **`{error, ErrorInfo}`** - An error occurred.","title":"erl_parse.parse_exprs/1","ref":"erl_parse.html#parse_exprs/1"},{"type":"function","doc":"Parses `Tokens` as if it was a form.\n\nReturns one of the following:\n\n- **`{ok, AbsForm}`** - The parsing was successful. `AbsForm` is the abstract\n form of the parsed form.\n\n- **`{error, ErrorInfo}`** - An error occurred.","title":"erl_parse.parse_form/1","ref":"erl_parse.html#parse_form/1"},{"type":"function","doc":"Parses `Tokens` as if it was a term.\n\nReturns one of the following:\n\n- **`{ok, Term}`** - The parsing was successful. `Term` is the Erlang term\n corresponding to the token list.\n\n- **`{error, ErrorInfo}`** - An error occurred.","title":"erl_parse.parse_term/1","ref":"erl_parse.html#parse_term/1"},{"type":"function","doc":"","title":"erl_parse.tokens/1","ref":"erl_parse.html#tokens/1"},{"type":"function","doc":"Generates a list of tokens representing the abstract form `AbsTerm` of an\nexpression. Optionally, `MoreTokens` is appended.","title":"erl_parse.tokens/2","ref":"erl_parse.html#tokens/2"},{"type":"type","doc":"Abstract form of an Erlang clause.","title":"erl_parse.abstract_clause/0","ref":"erl_parse.html#t:abstract_clause/0"},{"type":"type","doc":"Abstract form of an Erlang expression.","title":"erl_parse.abstract_expr/0","ref":"erl_parse.html#t:abstract_expr/0"},{"type":"type","doc":"Abstract form of an Erlang form.","title":"erl_parse.abstract_form/0","ref":"erl_parse.html#t:abstract_form/0"},{"type":"type","doc":"Abstract form of an Erlang type.","title":"erl_parse.abstract_type/0","ref":"erl_parse.html#t:abstract_type/0"},{"type":"type","doc":"","title":"erl_parse.af_anno/0","ref":"erl_parse.html#t:af_anno/0"},{"type":"type","doc":"","title":"erl_parse.af_annotated_type/0","ref":"erl_parse.html#t:af_annotated_type/0"},{"type":"type","doc":"","title":"erl_parse.af_args/0","ref":"erl_parse.html#t:af_args/0"},{"type":"type","doc":"","title":"erl_parse.af_assoc/1","ref":"erl_parse.html#t:af_assoc/1"},{"type":"type","doc":"","title":"erl_parse.af_assoc_exact/1","ref":"erl_parse.html#t:af_assoc_exact/1"},{"type":"type","doc":"","title":"erl_parse.af_assoc_type/0","ref":"erl_parse.html#t:af_assoc_type/0"},{"type":"type","doc":"","title":"erl_parse.af_atom/0","ref":"erl_parse.html#t:af_atom/0"},{"type":"type","doc":"","title":"erl_parse.af_behavior/0","ref":"erl_parse.html#t:af_behavior/0"},{"type":"type","doc":"","title":"erl_parse.af_behaviour/0","ref":"erl_parse.html#t:af_behaviour/0"},{"type":"type","doc":"","title":"erl_parse.af_bin/1","ref":"erl_parse.html#t:af_bin/1"},{"type":"type","doc":"","title":"erl_parse.af_binary_comprehension/0","ref":"erl_parse.html#t:af_binary_comprehension/0"},{"type":"type","doc":"","title":"erl_parse.af_binary_op/1","ref":"erl_parse.html#t:af_binary_op/1"},{"type":"type","doc":"Abstract representation of an element of a bitstring.","title":"erl_parse.af_binelement/1","ref":"erl_parse.html#t:af_binelement/1"},{"type":"type","doc":"","title":"erl_parse.af_binelement_size/0","ref":"erl_parse.html#t:af_binelement_size/0"},{"type":"type","doc":"","title":"erl_parse.af_bitstring_type/0","ref":"erl_parse.html#t:af_bitstring_type/0"},{"type":"type","doc":"","title":"erl_parse.af_block/0","ref":"erl_parse.html#t:af_block/0"},{"type":"type","doc":"","title":"erl_parse.af_body/0","ref":"erl_parse.html#t:af_body/0"},{"type":"type","doc":"","title":"erl_parse.af_case/0","ref":"erl_parse.html#t:af_case/0"},{"type":"type","doc":"","title":"erl_parse.af_catch/0","ref":"erl_parse.html#t:af_catch/0"},{"type":"type","doc":"","title":"erl_parse.af_character/0","ref":"erl_parse.html#t:af_character/0"},{"type":"type","doc":"","title":"erl_parse.af_clause/0","ref":"erl_parse.html#t:af_clause/0"},{"type":"type","doc":"","title":"erl_parse.af_clause_seq/0","ref":"erl_parse.html#t:af_clause_seq/0"},{"type":"type","doc":"","title":"erl_parse.af_compile/0","ref":"erl_parse.html#t:af_compile/0"},{"type":"type","doc":"","title":"erl_parse.af_cons/1","ref":"erl_parse.html#t:af_cons/1"},{"type":"type","doc":"","title":"erl_parse.af_constrained_function_type/0","ref":"erl_parse.html#t:af_constrained_function_type/0"},{"type":"type","doc":"","title":"erl_parse.af_constraint/0","ref":"erl_parse.html#t:af_constraint/0"},{"type":"type","doc":"","title":"erl_parse.af_empty_list_type/0","ref":"erl_parse.html#t:af_empty_list_type/0"},{"type":"type","doc":"","title":"erl_parse.af_export/0","ref":"erl_parse.html#t:af_export/0"},{"type":"type","doc":"","title":"erl_parse.af_export_type/0","ref":"erl_parse.html#t:af_export_type/0"},{"type":"type","doc":"","title":"erl_parse.af_fa_list/0","ref":"erl_parse.html#t:af_fa_list/0"},{"type":"type","doc":"","title":"erl_parse.af_field/0","ref":"erl_parse.html#t:af_field/0"},{"type":"type","doc":"Abstract representation of a record field.","title":"erl_parse.af_field_decl/0","ref":"erl_parse.html#t:af_field_decl/0"},{"type":"type","doc":"","title":"erl_parse.af_field_name/0","ref":"erl_parse.html#t:af_field_name/0"},{"type":"type","doc":"","title":"erl_parse.af_file/0","ref":"erl_parse.html#t:af_file/0"},{"type":"type","doc":"","title":"erl_parse.af_filter/0","ref":"erl_parse.html#t:af_filter/0"},{"type":"type","doc":"","title":"erl_parse.af_float/0","ref":"erl_parse.html#t:af_float/0"},{"type":"type","doc":"","title":"erl_parse.af_fun/0","ref":"erl_parse.html#t:af_fun/0"},{"type":"type","doc":"","title":"erl_parse.af_fun_type/0","ref":"erl_parse.html#t:af_fun_type/0"},{"type":"type","doc":"","title":"erl_parse.af_function_constraint/0","ref":"erl_parse.html#t:af_function_constraint/0"},{"type":"type","doc":"","title":"erl_parse.af_function_decl/0","ref":"erl_parse.html#t:af_function_decl/0"},{"type":"type","doc":"","title":"erl_parse.af_function_spec/0","ref":"erl_parse.html#t:af_function_spec/0"},{"type":"type","doc":"","title":"erl_parse.af_function_type/0","ref":"erl_parse.html#t:af_function_type/0"},{"type":"type","doc":"","title":"erl_parse.af_function_type_list/0","ref":"erl_parse.html#t:af_function_type_list/0"},{"type":"type","doc":"Abstract representation of a list, bitstring or map generator.","title":"erl_parse.af_generator/0","ref":"erl_parse.html#t:af_generator/0"},{"type":"type","doc":"","title":"erl_parse.af_guard/0","ref":"erl_parse.html#t:af_guard/0"},{"type":"type","doc":"","title":"erl_parse.af_guard_call/0","ref":"erl_parse.html#t:af_guard_call/0"},{"type":"type","doc":"","title":"erl_parse.af_guard_seq/0","ref":"erl_parse.html#t:af_guard_seq/0"},{"type":"type","doc":"","title":"erl_parse.af_guard_test/0","ref":"erl_parse.html#t:af_guard_test/0"},{"type":"type","doc":"","title":"erl_parse.af_if/0","ref":"erl_parse.html#t:af_if/0"},{"type":"type","doc":"","title":"erl_parse.af_import/0","ref":"erl_parse.html#t:af_import/0"},{"type":"type","doc":"","title":"erl_parse.af_integer/0","ref":"erl_parse.html#t:af_integer/0"},{"type":"type","doc":"","title":"erl_parse.af_integer_range_type/0","ref":"erl_parse.html#t:af_integer_range_type/0"},{"type":"type","doc":"","title":"erl_parse.af_list_comprehension/0","ref":"erl_parse.html#t:af_list_comprehension/0"},{"type":"type","doc":"","title":"erl_parse.af_lit_atom/1","ref":"erl_parse.html#t:af_lit_atom/1"},{"type":"type","doc":"","title":"erl_parse.af_literal/0","ref":"erl_parse.html#t:af_literal/0"},{"type":"type","doc":"","title":"erl_parse.af_local_call/0","ref":"erl_parse.html#t:af_local_call/0"},{"type":"type","doc":"","title":"erl_parse.af_local_fun/0","ref":"erl_parse.html#t:af_local_fun/0"},{"type":"type","doc":"","title":"erl_parse.af_local_function/0","ref":"erl_parse.html#t:af_local_function/0"},{"type":"type","doc":"","title":"erl_parse.af_map_comprehension/0","ref":"erl_parse.html#t:af_map_comprehension/0"},{"type":"type","doc":"","title":"erl_parse.af_map_creation/1","ref":"erl_parse.html#t:af_map_creation/1"},{"type":"type","doc":"","title":"erl_parse.af_map_pattern/0","ref":"erl_parse.html#t:af_map_pattern/0"},{"type":"type","doc":"","title":"erl_parse.af_map_type/0","ref":"erl_parse.html#t:af_map_type/0"},{"type":"type","doc":"","title":"erl_parse.af_map_update/1","ref":"erl_parse.html#t:af_map_update/1"},{"type":"type","doc":"","title":"erl_parse.af_match/1","ref":"erl_parse.html#t:af_match/1"},{"type":"type","doc":"","title":"erl_parse.af_maybe/0","ref":"erl_parse.html#t:af_maybe/0"},{"type":"type","doc":"","title":"erl_parse.af_maybe_else/0","ref":"erl_parse.html#t:af_maybe_else/0"},{"type":"type","doc":"","title":"erl_parse.af_maybe_match/0","ref":"erl_parse.html#t:af_maybe_match/0"},{"type":"type","doc":"","title":"erl_parse.af_module/0","ref":"erl_parse.html#t:af_module/0"},{"type":"type","doc":"","title":"erl_parse.af_named_fun/0","ref":"erl_parse.html#t:af_named_fun/0"},{"type":"type","doc":"","title":"erl_parse.af_nil/0","ref":"erl_parse.html#t:af_nil/0"},{"type":"type","doc":"","title":"erl_parse.af_pattern/0","ref":"erl_parse.html#t:af_pattern/0"},{"type":"type","doc":"","title":"erl_parse.af_predefined_type/0","ref":"erl_parse.html#t:af_predefined_type/0"},{"type":"type","doc":"","title":"erl_parse.af_qualifier/0","ref":"erl_parse.html#t:af_qualifier/0"},{"type":"type","doc":"","title":"erl_parse.af_qualifier_seq/0","ref":"erl_parse.html#t:af_qualifier_seq/0"},{"type":"type","doc":"","title":"erl_parse.af_receive/0","ref":"erl_parse.html#t:af_receive/0"},{"type":"type","doc":"","title":"erl_parse.af_record_creation/1","ref":"erl_parse.html#t:af_record_creation/1"},{"type":"type","doc":"","title":"erl_parse.af_record_decl/0","ref":"erl_parse.html#t:af_record_decl/0"},{"type":"type","doc":"","title":"erl_parse.af_record_field/1","ref":"erl_parse.html#t:af_record_field/1"},{"type":"type","doc":"","title":"erl_parse.af_record_field_access/1","ref":"erl_parse.html#t:af_record_field_access/1"},{"type":"type","doc":"","title":"erl_parse.af_record_field_type/0","ref":"erl_parse.html#t:af_record_field_type/0"},{"type":"type","doc":"","title":"erl_parse.af_record_index/0","ref":"erl_parse.html#t:af_record_index/0"},{"type":"type","doc":"","title":"erl_parse.af_record_type/0","ref":"erl_parse.html#t:af_record_type/0"},{"type":"type","doc":"","title":"erl_parse.af_record_update/1","ref":"erl_parse.html#t:af_record_update/1"},{"type":"type","doc":"","title":"erl_parse.af_remote_call/0","ref":"erl_parse.html#t:af_remote_call/0"},{"type":"type","doc":"","title":"erl_parse.af_remote_fun/0","ref":"erl_parse.html#t:af_remote_fun/0"},{"type":"type","doc":"Abstract representation of a remote function call.","title":"erl_parse.af_remote_function/0","ref":"erl_parse.html#t:af_remote_function/0"},{"type":"type","doc":"","title":"erl_parse.af_remote_guard_call/0","ref":"erl_parse.html#t:af_remote_guard_call/0"},{"type":"type","doc":"","title":"erl_parse.af_remote_type/0","ref":"erl_parse.html#t:af_remote_type/0"},{"type":"type","doc":"","title":"erl_parse.af_singleton_integer_type/0","ref":"erl_parse.html#t:af_singleton_integer_type/0"},{"type":"type","doc":"","title":"erl_parse.af_string/0","ref":"erl_parse.html#t:af_string/0"},{"type":"type","doc":"","title":"erl_parse.af_ta_list/0","ref":"erl_parse.html#t:af_ta_list/0"},{"type":"type","doc":"","title":"erl_parse.af_template/0","ref":"erl_parse.html#t:af_template/0"},{"type":"type","doc":"","title":"erl_parse.af_try/0","ref":"erl_parse.html#t:af_try/0"},{"type":"type","doc":"","title":"erl_parse.af_tuple/1","ref":"erl_parse.html#t:af_tuple/1"},{"type":"type","doc":"","title":"erl_parse.af_tuple_type/0","ref":"erl_parse.html#t:af_tuple_type/0"},{"type":"type","doc":"","title":"erl_parse.af_type_decl/0","ref":"erl_parse.html#t:af_type_decl/0"},{"type":"type","doc":"","title":"erl_parse.af_type_union/0","ref":"erl_parse.html#t:af_type_union/0"},{"type":"type","doc":"","title":"erl_parse.af_type_variable/0","ref":"erl_parse.html#t:af_type_variable/0"},{"type":"type","doc":"","title":"erl_parse.af_typed_field/0","ref":"erl_parse.html#t:af_typed_field/0"},{"type":"type","doc":"","title":"erl_parse.af_unary_op/1","ref":"erl_parse.html#t:af_unary_op/1"},{"type":"type","doc":"","title":"erl_parse.af_user_defined_type/0","ref":"erl_parse.html#t:af_user_defined_type/0"},{"type":"type","doc":"","title":"erl_parse.af_variable/0","ref":"erl_parse.html#t:af_variable/0"},{"type":"type","doc":"","title":"erl_parse.af_wild_attribute/0","ref":"erl_parse.html#t:af_wild_attribute/0"},{"type":"type","doc":"","title":"erl_parse.af_zip_generator/0","ref":"erl_parse.html#t:af_zip_generator/0"},{"type":"type","doc":"","title":"erl_parse.anno/0","ref":"erl_parse.html#t:anno/0"},{"type":"type","doc":"","title":"erl_parse.behaviour/0","ref":"erl_parse.html#t:behaviour/0"},{"type":"type","doc":"","title":"erl_parse.binary_op/0","ref":"erl_parse.html#t:binary_op/0"},{"type":"type","doc":"","title":"erl_parse.encoding_func/0","ref":"erl_parse.html#t:encoding_func/0"},{"type":"type","doc":"","title":"erl_parse.endianness/0","ref":"erl_parse.html#t:endianness/0"},{"type":"type","doc":"","title":"erl_parse.erl_parse_tree/0","ref":"erl_parse.html#t:erl_parse_tree/0"},{"type":"type","doc":"","title":"erl_parse.error_description/0","ref":"erl_parse.html#t:error_description/0"},{"type":"type","doc":"","title":"erl_parse.error_info/0","ref":"erl_parse.html#t:error_info/0"},{"type":"type","doc":"Tuples `{error, error_info()}` and `{warning, error_info()}`, denoting\nsyntactically incorrect forms and warnings, and `{eof, line()}`, denoting an\nend-of-stream encountered before a complete form had been parsed.","title":"erl_parse.form_info/0","ref":"erl_parse.html#t:form_info/0"},{"type":"type","doc":"","title":"erl_parse.fun_name/0","ref":"erl_parse.html#t:fun_name/0"},{"type":"type","doc":"","title":"erl_parse.function_name/0","ref":"erl_parse.html#t:function_name/0"},{"type":"type","doc":"","title":"erl_parse.record_name/0","ref":"erl_parse.html#t:record_name/0"},{"type":"type","doc":"","title":"erl_parse.signedness/0","ref":"erl_parse.html#t:signedness/0"},{"type":"type","doc":"","title":"erl_parse.spec_attr/0","ref":"erl_parse.html#t:spec_attr/0"},{"type":"type","doc":"","title":"erl_parse.token/0","ref":"erl_parse.html#t:token/0"},{"type":"type","doc":"","title":"erl_parse.type/0","ref":"erl_parse.html#t:type/0"},{"type":"type","doc":"","title":"erl_parse.type_attr/0","ref":"erl_parse.html#t:type_attr/0"},{"type":"type","doc":"","title":"erl_parse.type_name/0","ref":"erl_parse.html#t:type_name/0"},{"type":"type","doc":"","title":"erl_parse.type_specifier/0","ref":"erl_parse.html#t:type_specifier/0"},{"type":"type","doc":"","title":"erl_parse.type_specifier_list/0","ref":"erl_parse.html#t:type_specifier_list/0"},{"type":"type","doc":"","title":"erl_parse.unary_op/0","ref":"erl_parse.html#t:unary_op/0"},{"type":"type","doc":"","title":"erl_parse.unit/0","ref":"erl_parse.html#t:unit/0"},{"type":"module","doc":"The Erlang pretty printer.\n\nThe functions in this module are used to generate aesthetically attractive\nrepresentations of abstract forms, which are suitable for printing. All\nfunctions return (possibly deep) lists of characters and generate an error if\nthe form is wrong.\n\nAll functions can have an optional argument, which specifies a hook that is\ncalled if an attempt is made to print an unknown form.\n\nNote that if the functions in this module are used to convert abstract code back\nto Erlang source code, the enclosing function should first be processed by\n`legalize_vars/1` in order to ensure that the output is semantically equivalent\nto the abstract code.","title":"erl_pp","ref":"erl_pp.html"},{"type":"module","doc":"It is not possible to have hook functions for unknown forms at other places than\nexpressions.","title":"Known Limitations - erl_pp","ref":"erl_pp.html#module-known-limitations"},{"type":"module","doc":"`m:erl_eval`, `m:erl_parse`, `m:io`","title":"See Also - erl_pp","ref":"erl_pp.html#module-see-also"},{"type":"function","doc":"","title":"erl_pp.attribute/1","ref":"erl_pp.html#attribute/1"},{"type":"function","doc":"Same as [`form/1,2`](`form/1`), but only for attribute `Attribute`.","title":"erl_pp.attribute/2","ref":"erl_pp.html#attribute/2"},{"type":"function","doc":"","title":"erl_pp.expr/1","ref":"erl_pp.html#expr/1"},{"type":"function","doc":"","title":"erl_pp.expr/2","ref":"erl_pp.html#expr/2"},{"type":"function","doc":"","title":"erl_pp.expr/3","ref":"erl_pp.html#expr/3"},{"type":"function","doc":"Prints one expression.\n\nIt is useful for implementing hooks (see section\n[Known Limitations](`m:erl_pp#module-known-limitations`)).","title":"erl_pp.expr/4","ref":"erl_pp.html#expr/4"},{"type":"function","doc":"","title":"erl_pp.exprs/1","ref":"erl_pp.html#exprs/1"},{"type":"function","doc":"","title":"erl_pp.exprs/2","ref":"erl_pp.html#exprs/2"},{"type":"function","doc":"Same as [`form/1,2`](`form/1`), but only for the sequence of expressions in\n`Expressions`.","title":"erl_pp.exprs/3","ref":"erl_pp.html#exprs/3"},{"type":"function","doc":"","title":"erl_pp.form/1","ref":"erl_pp.html#form/1"},{"type":"function","doc":"Pretty prints a `Form`, which is an abstract form of a type that is returned by\n`erl_parse:parse_form/1`.","title":"erl_pp.form/2","ref":"erl_pp.html#form/2"},{"type":"function","doc":"","title":"erl_pp.function/1","ref":"erl_pp.html#function/1"},{"type":"function","doc":"Same as [`form/1,2`](`form/1`), but only for function `Function`.","title":"erl_pp.function/2","ref":"erl_pp.html#function/2"},{"type":"function","doc":"","title":"erl_pp.guard/1","ref":"erl_pp.html#guard/1"},{"type":"function","doc":"Same as [`form/1,2`](`form/1`), but only for the guard test `Guard`.","title":"erl_pp.guard/2","ref":"erl_pp.html#guard/2"},{"type":"function","doc":"The Erlang compiler will, when expanding records to tuples, introduce new\nvariables in the abstract representation. As the expansion is done on the\nabstract representation, the compiler can safely name the new variables with\nnames that are not syntactically valid in Erlang source code (the name starts\nwith a lowercase letter), thus ensuring the uniqueness of the new names.\n\nThe above strategy leads to problems if a user wants to convert the abstract\nrepresentation, using the functions of this module back to Erlang source code.\nTypically, pattern variables are output as atoms thus changing the sematics of\nthe program. To solve this problem [`legalize_vars/1`](`legalize_vars/1`), when\nrun on the abstract representation of a function, will return an equivalent\nfunction where all variables will have syntactically valid names.","title":"erl_pp.legalize_vars/1","ref":"erl_pp.html#legalize_vars/1"},{"type":"type","doc":"Optional argument `HookFunction`{: #hook_function }, shown in the functions\ndescribed in this module, defines a function that is called when an unknown form\noccurs where there is to be a valid expression. If `HookFunction` is equal to\n`none`, there is no hook function.\n\nThe called hook function is to return a (possibly deep) list of characters.\nFunction `expr/4` is useful in a hook.\n\nIf `CurrentIndentation` is negative, there are no line breaks and only a space\nis used as a separator.","title":"erl_pp.hook_function/0","ref":"erl_pp.html#t:hook_function/0"},{"type":"type","doc":"The option `quote_singleton_atom_types` is used to add quotes to all singleton\natom types.\n\nThe option `linewidth` controls the maximum line width for formatted lines\n(defaults to 72 characters).\n\nThe option `indent` controls the indention for formatted lines (defaults to 4\nspaces).","title":"erl_pp.option/0","ref":"erl_pp.html#t:option/0"},{"type":"type","doc":"","title":"erl_pp.options/0","ref":"erl_pp.html#t:options/0"},{"type":"module","doc":"The Erlang token scanner.\n\nThis module contains functions for tokenizing (scanning) characters into Erlang\ntokens.","title":"erl_scan","ref":"erl_scan.html"},{"type":"module","doc":"`ErrorInfo` is the standard `ErrorInfo` structure that is returned from all I/O\nmodules. The format is as follows:\n\n```erlang\n{ErrorLocation, Module, ErrorDescriptor}\n```\n\nA string describing the error is obtained with the following call:\n\n```erlang\nModule:format_error(ErrorDescriptor)\n```","title":"Error Information - erl_scan","ref":"erl_scan.html#module-error-information"},{"type":"module","doc":"The continuation of the first call to the re-entrant input functions must be\n`[]`. For a complete description of how the re-entrant input scheme works, see\nArmstrong, Virding and Williams: 'Concurrent Programming in Erlang', Chapter 13.","title":"Notes - erl_scan","ref":"erl_scan.html#module-notes"},{"type":"module","doc":"`m:erl_anno`, `m:erl_parse`, `m:io`","title":"See Also - erl_scan","ref":"erl_scan.html#module-see-also"},{"type":"function","doc":"Returns the category of `Token`.","title":"erl_scan.category/1","ref":"erl_scan.html#category/1"},{"type":"function","doc":"Returns the column of `Token`'s collection of annotations.","title":"erl_scan.column/1","ref":"erl_scan.html#column/1"},{"type":"function","doc":"Returns the end location of the text of `Token`'s collection of annotations. If\nthere is no text, `undefined` is returned.","title":"erl_scan.end_location/1","ref":"erl_scan.html#end_location/1"},{"type":"function","doc":"Uses an `ErrorDescriptor` and returns a string that describes the error or\nwarning. This function is usually called implicitly when an `ErrorInfo`\nstructure is processed (see section\n[Error Information](`m:erl_scan#module-error-information`)).","title":"erl_scan.format_error/1","ref":"erl_scan.html#format_error/1"},{"type":"function","doc":"Returns the line of `Token`'s collection of annotations.","title":"erl_scan.line/1","ref":"erl_scan.html#line/1"},{"type":"function","doc":"Returns the location of `Token`'s collection of annotations.","title":"erl_scan.location/1","ref":"erl_scan.html#location/1"},{"type":"function","doc":"Returns `true` if `Atom` is an Erlang reserved word, otherwise `false`.","title":"erl_scan.reserved_word/1","ref":"erl_scan.html#reserved_word/1"},{"type":"function","doc":"","title":"erl_scan.string/1","ref":"erl_scan.html#string/1"},{"type":"function","doc":"","title":"erl_scan.string/2","ref":"erl_scan.html#string/2"},{"type":"function","doc":"Takes the list of characters `String` and tries to scan (tokenize) them.\n\nReturns one of the following:\n\n- **`{ok, Tokens, EndLocation}`** - `Tokens` are the Erlang tokens from\n `String`. `EndLocation` is the first location after the last token.\n\n- **`{error, ErrorInfo, ErrorLocation}`** - An error occurred. `ErrorLocation`\n is the first location after the erroneous token.\n\n`StartLocation` indicates the initial location when scanning starts. If\n`StartLocation` is a line, `Anno`, `EndLocation`, and `ErrorLocation` are lines.\nIf `StartLocation` is a pair of a line and a column, `Anno` takes the form of an\nopaque compound data type, and `EndLocation` and `ErrorLocation` are pairs of a\nline and a column. The _token annotations_ contain information about the column\nand the line where the token begins, as well as the text of the token (if option\n`text` is specified), all of which can be accessed by calling `column/1`,\n`line/1`, `location/1`, and `text/1`.\n\nA _token_ is a tuple containing information about syntactic category, the token\nannotations, and the terminal symbol. For punctuation characters (such as `;`\nand `|`) and reserved words, the category and the symbol coincide, and the token\nis represented by a two-tuple. Three-tuples have one of the following forms:\n\n- `{atom, Anno, atom()}`\n- `{char, Anno, char()}`\n- `{comment, Anno, string()}`\n- `{float, Anno, float()}`\n- `{integer, Anno, integer()}`\n- `{var, Anno, atom()}`\n- `{white_space, Anno, string()}`\n\nValid options:\n\n- **`{reserved_word_fun, reserved_word_fun()}`** - A callback function that is\n called when the scanner has found an unquoted atom. If the function returns\n `true`, the unquoted atom itself becomes the category of the token. If the\n function returns `false`, `atom` becomes the category of the unquoted atom.\n\n- **`return_comments`** - Return comment tokens.\n\n- **`return_white_spaces`** - Return white space tokens. By convention, a\n newline character, if present, is always the first character of the text\n (there cannot be more than one newline in a white space token).\n\n- **`return`** - Short for `[return_comments, return_white_spaces]`.\n\n- **`text`{: #text }** - Include the token text in the token annotation. The\n text is the part of the input corresponding to the token. See also\n [`text_fun`](`m:erl_scan#text_fun`).\n\n- **`{text_fun, text_fun()}`{: #text_fun }** - A callback function used to\n determine whether the full text for the token shall be included in the token\n annotation. Arguments of the function are the category of the token and the\n full token string. This is only used when [`text`](`m:erl_scan#text`) is not\n present. If neither are present the text will not be saved in the token\n annotation.\n\n- **`{compiler_internal, term()}`{: #compiler_interal }** - Pass\n compiler-internal options to the scanner. The set of internal options\n understood by the scanner should be considered experimental and can thus be\n changed at any time without prior warning.\n\n The following options are currently understood:\n\n - **`ssa_checks`** - Tokenizes source code annotations used for encoding tests\n on the BEAM SSA code produced by the compiler.","title":"erl_scan.string/3","ref":"erl_scan.html#string/3"},{"type":"function","doc":"Returns the symbol of `Token`.","title":"erl_scan.symbol/1","ref":"erl_scan.html#symbol/1"},{"type":"function","doc":"Returns the text of `Token`'s collection of annotations. If there is no text,\n`undefined` is returned.","title":"erl_scan.text/1","ref":"erl_scan.html#text/1"},{"type":"function","doc":"","title":"erl_scan.tokens/3","ref":"erl_scan.html#tokens/3"},{"type":"function","doc":"This is the re-entrant scanner, which scans characters until either a _dot_ ('.'\nfollowed by a white space) or `eof` is reached.\n\nIt returns:\n\n- **`{done, Result, LeftOverChars}`** - Indicates that there is sufficient input\n data to get a result. `Result` is:\n\n - **`{ok, Tokens, EndLocation}`** - The scanning was successful. `Tokens` is\n the list of tokens including _dot_.\n\n - **`{eof, EndLocation}`** - End of file was encountered before any more\n tokens.\n\n - **`{error, ErrorInfo, EndLocation}`** - An error occurred. `LeftOverChars`\n is the remaining characters of the input data, starting from `EndLocation`.\n\n- **`{more, Continuation1}`** - More data is required for building a term.\n `Continuation1` must be passed in a new call to `tokens/3,4` when more data is\n available.\n\nThe `CharSpec` `eof` signals end of file. `LeftOverChars` then takes the value\n`eof` as well.\n\nFor a description of the options, see `string/3`.","title":"erl_scan.tokens/4","ref":"erl_scan.html#tokens/4"},{"type":"type","doc":"","title":"erl_scan.category/0","ref":"erl_scan.html#t:category/0"},{"type":"type","doc":"","title":"erl_scan.char_spec/0","ref":"erl_scan.html#t:char_spec/0"},{"type":"type","doc":"","title":"erl_scan.error_description/0","ref":"erl_scan.html#t:error_description/0"},{"type":"type","doc":"","title":"erl_scan.error_info/0","ref":"erl_scan.html#t:error_info/0"},{"type":"type","doc":"","title":"erl_scan.option/0","ref":"erl_scan.html#t:option/0"},{"type":"type","doc":"","title":"erl_scan.options/0","ref":"erl_scan.html#t:options/0"},{"type":"type","doc":"","title":"erl_scan.resword_fun/0","ref":"erl_scan.html#t:resword_fun/0"},{"type":"opaque","doc":"","title":"erl_scan.return_cont/0","ref":"erl_scan.html#t:return_cont/0"},{"type":"type","doc":"","title":"erl_scan.symbol/0","ref":"erl_scan.html#t:symbol/0"},{"type":"type","doc":"","title":"erl_scan.text_fun/0","ref":"erl_scan.html#t:text_fun/0"},{"type":"type","doc":"","title":"erl_scan.token/0","ref":"erl_scan.html#t:token/0"},{"type":"type","doc":"","title":"erl_scan.tokens/0","ref":"erl_scan.html#t:tokens/0"},{"type":"type","doc":"","title":"erl_scan.tokens_result/0","ref":"erl_scan.html#t:tokens_result/0"},{"type":"module","doc":"A parse transformation that translates fun syntax into match specifications.\n\nThis module provides the parse transformation that makes calls to `m:ets` and\n`dbg:fun2ms/1` translate into literal match specifications. It also provides the\nback end for the same functions when called from the Erlang shell.\n\nThe translation from funs to match specifications is accessed through the two\n\"pseudo functions\" `ets:fun2ms/1` and `dbg:fun2ms/1`.\n\nAs everyone trying to use [`ets:select/2`](`ets:select/1`) or `m:dbg` seems to\nend up reading this manual page, this description is an introduction to the\nconcept of match specifications.\n\nRead the whole manual page if it is the first time you are using the\ntransformations.\n\nMatch specifications are used more or less as filters. They resemble usual\nErlang matching in a list comprehension or in a fun used with `lists:foldl/3`,\nand so on. However, the syntax of pure match specifications is awkward, as they\nare made up purely by Erlang terms, and the language has no syntax to make the\nmatch specifications more readable.\n\nAs the execution and structure of the match specifications are like that of a\nfun, it is more straightforward to write it using the familiar fun syntax and to\nhave that translated into a match specification automatically. A real fun is\nclearly more powerful than the match specifications allow, but bearing the match\nspecifications in mind, and what they can do, it is still more convenient to\nwrite it all as a fun. This module contains the code that translates the fun\nsyntax into match specification terms.","title":"ms_transform","ref":"ms_transform.html"},{"type":"module","doc":"Using `ets:select/2` and a match specification, one can filter out rows of a\ntable and construct a list of tuples containing relevant parts of the data in\nthese rows. One can use `ets:foldl/3` instead, but the `ets:select/2` call is\nfar more efficient. Without the translation provided by `ms_transform`, one must\nstruggle with writing match specifications terms to accommodate this.\n\nConsider a simple table of employees:\n\n```erlang\n-record(emp, {empno, %Employee number as a string, the key\n surname, %Surname of the employee\n givenname, %Given name of employee\n dept, %Department, one of {dev,sales,prod,adm}\n empyear}). %Year the employee was employed\n```\n\nWe create the table using:\n\n```text\nets:new(emp_tab, [{keypos,#emp.empno},named_table,ordered_set]).\n```\n\nWe fill the table with randomly chosen data:\n\n```erlang\n[{emp,\"011103\",\"Black\",\"Alfred\",sales,2000},\n {emp,\"041231\",\"Doe\",\"John\",prod,2001},\n {emp,\"052341\",\"Smith\",\"John\",dev,1997},\n {emp,\"076324\",\"Smith\",\"Ella\",sales,1995},\n {emp,\"122334\",\"Weston\",\"Anna\",prod,2002},\n {emp,\"535216\",\"Chalker\",\"Samuel\",adm,1998},\n {emp,\"789789\",\"Harrysson\",\"Joe\",adm,1996},\n {emp,\"963721\",\"Scott\",\"Juliana\",dev,2003},\n {emp,\"989891\",\"Brown\",\"Gabriel\",prod,1999}]\n```\n\nAssuming that we want the employee numbers of everyone in the sales department,\nthere are several ways.\n\n`ets:match/2` can be used:\n\n```erlang\n1> ets:match(emp_tab, {'_', '$1', '_', '_', sales, '_'}).\n[[\"011103\"],[\"076324\"]]\n```\n\n`ets:match/2` uses a simpler type of match specification, but it is still\nunreadable, and one has little control over the returned result. It is always a\nlist of lists.\n\n`ets:foldl/3` or `ets:foldr/3` can be used to avoid the nested lists:\n\n```erlang\nets:foldr(fun(#emp{empno = E, dept = sales},Acc) -> [E | Acc];\n (_,Acc) -> Acc\n end,\n [],\n emp_tab).\n```\n\nThe result is `[\"011103\",\"076324\"]`. The fun is straightforward, so the only\nproblem is that all the data from the table must be transferred from the table\nto the calling process for filtering. That is inefficient compared to the\n`ets:match/2` call where the filtering can be done \"inside\" the emulator and\nonly the result is transferred to the process.\n\nConsider a \"pure\" `ets:select/2` call that does what `ets:foldr` does:\n\n```erlang\nets:select(emp_tab, [{#emp{empno = '$1', dept = sales, _='_'},[],['$1']}]).\n```\n\nAlthough the record syntax is used, it is still hard to read and even harder to\nwrite. The first element of the tuple,\n`#emp{empno = '$1', dept = sales, _='_'}`, tells what to match. Elements not\nmatching this are not returned, as in the `ets:match/2` example. The second\nelement, the empty list, is a list of guard expressions, which we do not need.\nThe third element is the list of expressions constructing the return value (in\nETS this is almost always a list containing one single term). In our case `'$1'`\nis bound to the employee number in the head (first element of the tuple), and\nhence the employee number is returned. The result is `[\"011103\",\"076324\"]`, as\nin the `ets:foldr/3` example, but the result is retrieved much more efficiently\nin terms of execution speed and memory consumption.\n\nUsing `ets:fun2ms/1`, we can combine the ease of use of the `ets:foldr/3` and\nthe efficiency of the pure `ets:select/2` example:\n\n```erlang\n-include_lib(\"stdlib/include/ms_transform.hrl\").\n\nets:select(emp_tab, ets:fun2ms(\n fun(#emp{empno = E, dept = sales}) ->\n E\n end)).\n```\n\nThis example requires no special knowledge of match specifications to\nunderstand. The head of the fun matches what you want to filter out and the body\nreturns what you want returned. As long as the fun can be kept within the limits\nof the match specifications, there is no need to transfer all table data to the\nprocess for filtering as in the `ets:foldr/3` example. It is easier to read than\nthe `ets:foldr/3` example, as the select call in itself discards anything that\ndoes not match, while the fun of the `ets:foldr/3` call needs to handle both the\nelements matching and the ones not matching.\n\nIn the `ets:fun2ms/1` example above, it is needed to include `ms_transform.hrl`\nin the source code, as this is what triggers the parse transformation of the\n`ets:fun2ms/1` call to a valid match specification. This also implies that the\ntransformation is done at compile time (except when called from the shell) and\ntherefore takes no resources in runtime. That is, although you use the more\nintuitive fun syntax, it gets as efficient in runtime as writing match\nspecifications by hand.","title":"Example 1 - ms_transform","ref":"ms_transform.html#module-example-1"},{"type":"module","doc":"Assume that we want to get all the employee numbers of employees hired before\nyear 2000. Using `ets:match/2` is not an alternative here, as relational\noperators cannot be expressed there. Once again, `ets:foldr/3` can do it\n(slowly, but correct):\n\n```erlang\nets:foldr(fun(#emp{empno = E, empyear = Y},Acc) when Y < 2000 -> [E | Acc];\n (_,Acc) -> Acc\n end,\n [],\n emp_tab).\n```\n\nThe result is `[\"052341\",\"076324\",\"535216\",\"789789\",\"989891\"]`, as expected. The\nequivalent expression using a handwritten match specification would look like\nthis:\n\n```erlang\nets:select(emp_tab, [{#emp{empno = '$1', empyear = '$2', _='_'},\n [{'<', '$2', 2000}],\n ['$1']}]).\n```\n\nThis gives the same result. `[{'<', '$2', 2000}]` is in the guard part and\ntherefore discards anything that does not have an `empyear` (bound to `'$2'` in\nthe head) less than 2000, as the guard in the `foldr/3` example.\n\nWe write it using `ets:fun2ms/1`:\n\n```erlang\n-include_lib(\"stdlib/include/ms_transform.hrl\").\n\nets:select(emp_tab, ets:fun2ms(\n fun(#emp{empno = E, empyear = Y}) when Y < 2000 ->\n E\n end)).\n```","title":"Example 2 - ms_transform","ref":"ms_transform.html#module-example-2"},{"type":"module","doc":"Assume that we want the whole object matching instead of only one element. One\nalternative is to assign a variable to every part of the record and build it up\nonce again in the body of the fun, but the following is easier:\n\n```erlang\nets:select(emp_tab, ets:fun2ms(\n fun(Obj = #emp{empno = E, empyear = Y})\n when Y < 2000 ->\n Obj\n end)).\n```\n\nAs in ordinary Erlang matching, you can bind a variable to the whole matched\nobject using a \"match inside the match\", that is, a `=`. Unfortunately in funs\ntranslated to match specifications, it is allowed only at the \"top-level\", that\nis, matching the _whole_ object arriving to be matched into a separate variable.\nIf you are used to writing match specifications by hand, we mention that\nvariable A is simply translated into '$\\_'. Alternatively, pseudo function\n`object/0` also returns the whole matched object, see section\n[Warnings and Restrictions](`m:ms_transform#warnings_and_restrictions`).","title":"Example 3 - ms_transform","ref":"ms_transform.html#module-example-3"},{"type":"module","doc":"This example concerns the body of the fun. Assume that all employee numbers\nbeginning with zero (`0`) must be changed to begin with one (`1`) instead, and\nthat we want to create the list `[{ , }]`:\n\n```erlang\nets:select(emp_tab, ets:fun2ms(\n fun(#emp{empno = [$0 | Rest] }) ->\n {[$0|Rest],[$1|Rest]}\n end)).\n```\n\nThis query hits the feature of partially bound keys in table type `ordered_set`,\nso that not the whole table needs to be searched, only the part containing keys\nbeginning with `0` is looked into.","title":"Example 4 - ms_transform","ref":"ms_transform.html#module-example-4"},{"type":"module","doc":"The fun can have many clauses. Assume that we want to do the following:\n\n- If an employee started before 1997, return the tuple\n `{inventory, }`.\n- If an employee started 1997 or later, but before 2001, return\n `{rookie, }`.\n- For all other employees, return `{newbie, }`, except for\n those named `Smith` as they would be affronted by anything other than the tag\n `guru` and that is also what is returned for their numbers:\n `{guru, }`.\n\nThis is accomplished as follows:\n\n```erlang\nets:select(emp_tab, ets:fun2ms(\n fun(#emp{empno = E, surname = \"Smith\" }) ->\n {guru,E};\n (#emp{empno = E, empyear = Y}) when Y < 1997 ->\n {inventory, E};\n (#emp{empno = E, empyear = Y}) when Y > 2001 ->\n {newbie, E};\n (#emp{empno = E, empyear = Y}) -> % 1997 -- 2001\n {rookie, E}\n end)).\n```\n\nThe result is as follows:\n\n```erlang\n[{rookie,\"011103\"},\n {rookie,\"041231\"},\n {guru,\"052341\"},\n {guru,\"076324\"},\n {newbie,\"122334\"},\n {rookie,\"535216\"},\n {inventory,\"789789\"},\n {newbie,\"963721\"},\n {rookie,\"989891\"}]\n```","title":"Example 5 - ms_transform","ref":"ms_transform.html#module-example-5"},{"type":"module","doc":"What more can you do? A simple answer is: see the documentation of\n[match specifications](`e:erts:match_spec.md`) in ERTS User's Guide. However,\nthe following is a brief overview of the most useful \"built-in functions\" that\nyou can use when the fun is to be translated into a match specification by\n`ets:fun2ms/1`. It is not possible to call other functions than those allowed in\nmatch specifications. No \"usual\" Erlang code can be executed by the fun that is\ntranslated by `ets:fun2ms/1`. The fun is limited exactly to the power of the\nmatch specifications, which is unfortunate, but the price one must pay for the\nexecution speed of `ets:select/2` compared to `ets:foldl/foldr`.\n\nThe head of the fun is a head matching (or mismatching) _one_ parameter, one\nobject of the table we select from. The object is always a single variable (can\nbe `_`) or a tuple, as ETS, Dets, and Mnesia tables include that. The match\nspecification returned by `ets:fun2ms/1` can be used with `dets:select/2` and\n`mnesia:select/2`, and with `ets:select/2`. The use of `=` in the head is\nallowed (and encouraged) at the top-level.\n\nThe guard section can contain any guard expression of Erlang. The following is a\nlist of BIFs and expressions:\n\n- Type tests: `is_atom`, `is_float`, `is_integer`, `is_list`, `is_number`,\n `is_pid`, `is_port`, `is_reference`, `is_tuple`, `is_binary`, `is_function`,\n `is_record`\n- Boolean operators: `not`, `and`, `or`, `andalso`, `orelse`\n- Relational operators: `>`, `>=`, `<`, `=<`, `=:=`, `==`, `=/=`, `/=`\n- Arithmetic: `+`, `-`, `*`, `div`, `rem`\n- Bitwise operators: `band`, `bor`, `bxor`, `bnot`, `bsl`, `bsr`\n- The guard BIFs: `abs`, `element`, `hd`, `length`, `node`, `round`, `size`,\n `byte_size`, `tl`, `trunc`, `binary_part`, `self`\n\nContrary to the fact with \"handwritten\" match specifications, the `is_record`\nguard works as in ordinary Erlang code.\n\nSemicolons (`;`) in guards are allowed, the result is (as expected) one \"match\nspecification clause\" for each semicolon-separated part of the guard. The\nsemantics is identical to the Erlang semantics.\n\nThe body of the fun is used to construct the resulting value. When selecting\nfrom tables, one usually construct a suiting term here, using ordinary Erlang\nterm construction, like tuple parentheses, list brackets, and variables matched\nout in the head, possibly with the occasional constant. Whatever expressions are\nallowed in guards are also allowed here, but no special functions exist except\n`object` and `bindings` (see further down), which returns the whole matched\nobject and all known variable bindings, respectively.\n\nThe `dbg` variants of match specifications have an imperative approach to the\nmatch specification body, the ETS dialect has not. The fun body for\n`ets:fun2ms/1` returns the result without side effects. As matching (`=`) in the\nbody of the match specifications is not allowed (for performance reasons) the\nonly thing left, more or less, is term construction.","title":"Useful BIFs - ms_transform","ref":"ms_transform.html#module-useful-bifs"},{"type":"module","doc":"This section describes the slightly different match specifications translated by\n`dbg:fun2ms/1`.\n\nThe same reasons for using the parse transformation apply to `dbg`, maybe even\nmore, as filtering using Erlang code is not a good idea when tracing (except\nafterwards, if you trace to file). The concept is similar to that of\n`ets:fun2ms/1` except that you usually use it directly from the shell (which can\nalso be done with `ets:fun2ms/1`).\n\nThe following is an example module to trace on:\n\n```erlang\n-module(toy).\n\n-export([start/1, store/2, retrieve/1]).\n\nstart(Args) ->\n toy_table = ets:new(toy_table, Args).\n\nstore(Key, Value) ->\n ets:insert(toy_table, {Key,Value}).\n\nretrieve(Key) ->\n [{Key, Value}] = ets:lookup(toy_table, Key),\n Value.\n```\n\nDuring model testing, the first test results in `{badmatch,16}` in\n`{toy,start,1}`, why?\n\nWe suspect the `ets:new/2` call, as we match hard on the return value, but want\nonly the particular `new/2` call with `toy_table` as first parameter. So we\nstart a default tracer on the node:\n\n```text\n1> dbg:tracer().\n{ok,<0.88.0>}\n```\n\nWe turn on call tracing for all processes, we want to make a pretty restrictive\ntrace pattern, so there is no need to call trace only a few processes (usually\nit is not):\n\n```text\n2> dbg:p(all,call).\n{ok,[{matched,nonode@nohost,25}]}\n```\n\nWe specify the filter, we want to view calls that resemble\n`ets:new(toy_table, )`:\n\n```erlang\n3> dbg:tp(ets,new,dbg:fun2ms(fun([toy_table,_]) -> true end)).\n{ok,[{matched,nonode@nohost,1},{saved,1}]}\n```\n\nAs can be seen, the fun used with `dbg:fun2ms/1` takes a single list as\nparameter instead of a single tuple. The list matches a list of the parameters\nto the traced function. A single variable can also be used. The body of the fun\nexpresses, in a more imperative way, actions to be taken if the fun head (and\nthe guards) matches. `true` is returned here, only because the body of a fun\ncannot be empty. The return value is discarded.\n\nThe following trace output is received during test:\n\n```erlang\n(<0.86.0>) call ets:new(toy_table, [ordered_set])\n```\n\nAssume that we have not found the problem yet, and want to see what `ets:new/2`\nreturns. We use a slightly different trace pattern:\n\n```erlang\n4> dbg:tp(ets,new,dbg:fun2ms(fun([toy_table,_]) -> return_trace() end)).\n```\n\nThe following trace output is received during test:\n\n```erlang\n(<0.86.0>) call ets:new(toy_table,[ordered_set])\n(<0.86.0>) returned from ets:new/2 -> 24\n```\n\nThe call to `return_trace` results in a trace message when the function returns.\nIt applies only to the specific function call triggering the match specification\n(and matching the head/guards of the match specification). This is by far the\nmost common call in the body of a `dbg` match specification.\n\nThe test now fails with `{badmatch,24}` because the atom `toy_table` does not\nmatch the number returned for an unnamed table. So, the problem is found, the\ntable is to be named, and the arguments supplied by the test program do not\ninclude `named_table`. We rewrite the start function:\n\n```erlang\nstart(Args) ->\n toy_table = ets:new(toy_table, [named_table|Args]).\n```\n\nWith the same tracing turned on, the following trace output is received:\n\n```erlang\n(<0.86.0>) call ets:new(toy_table,[named_table,ordered_set])\n(<0.86.0>) returned from ets:new/2 -> toy_table\n```\n\nAssume that the module now passes all testing and goes into the system. After a\nwhile, it is found that table `toy_table` grows while the system is running and\nthat there are many elements with atoms as keys. We expected only integer keys\nand so does the rest of the system, but clearly not the entire system. We turn\non call tracing and try to see calls to the module with an atom as the key:\n\n```erlang\n1> dbg:tracer().\n{ok,<0.88.0>}\n2> dbg:p(all,call).\n{ok,[{matched,nonode@nohost,25}]}\n3> dbg:tpl(toy,store,dbg:fun2ms(fun([A,_]) when is_atom(A) -> true end)).\n{ok,[{matched,nonode@nohost,1},{saved,1}]}\n```\n\nWe use `dbg:tpl/3` to ensure to catch local calls (assume that the module has\ngrown since the smaller version and we are unsure if this inserting of atoms is\nnot done locally). When in doubt, always use local call tracing.\n\nAssume that nothing happens when tracing in this way. The function is never\ncalled with these parameters. We conclude that someone else (some other module)\nis doing it and realize that we must trace on `ets:insert/2` and want to see the\ncalling function. The calling function can be retrieved using the match\nspecification function `caller`. To get it into the trace message, the match\nspecification function `message` must be used. The filter call looks like this\n(looking for calls to `ets:insert/2`):\n\n```erlang\n4> dbg:tpl(ets,insert,dbg:fun2ms(fun([toy_table,{A,_}]) when is_atom(A) ->\n message(caller())\n end)).\n{ok,[{matched,nonode@nohost,1},{saved,2}]}\n```\n\nThe caller is now displayed in the \"additional message\" part of the trace\noutput, and the following is displayed after a while:\n\n```erlang\n(<0.86.0>) call ets:insert(toy_table,{garbage,can}) ({evil_mod,evil_fun,2})\n```\n\nYou have realized that function `evil_fun` of the `evil_mod` module, with arity\n`2`, is causing all this trouble.\n\nThis example illustrates the most used calls in match specifications for `dbg`.\nThe other, more esoteric, calls are listed and explained in\n[Match specifications in Erlang](`e:erts:match_spec.md`) in ERTS User's Guide,\nas they are beyond the scope of this description.","title":"Example with dbg - ms_transform","ref":"ms_transform.html#module-example-with-dbg"},{"type":"module","doc":"[](){: #warnings_and_restrictions }\n\nThe following warnings and restrictions apply to the funs used in with\n`ets:fun2ms/1` and `dbg:fun2ms/1`.\n\n> #### Warning {: .warning }\n>\n> To use the pseudo functions triggering the translation, ensure to include the\n> header file `ms_transform.hrl` in the source code. Failure to do so possibly\n> results in runtime errors rather than compile time, as the expression can be\n> valid as a plain Erlang program without translation.\n\n> #### Warning {: .warning }\n>\n> The fun must be literally constructed inside the parameter list to the pseudo\n> functions. The fun cannot be bound to a variable first and then passed to\n> `ets:fun2ms/1` or `dbg:fun2ms/1`. For example, `ets:fun2ms(fun(A) -> A end)`\n> works, but not `F = fun(A) -> A end, ets:fun2ms(F)`. The latter results in a\n> compile-time error if the header is included, otherwise a runtime error.\n\nMany restrictions apply to the fun that is translated into a match\nspecification. To put it simple: you cannot use anything in the fun that you\ncannot use in a match specification. This means that, among others, the\nfollowing restrictions apply to the fun itself:\n\n- Functions written in Erlang cannot be called, neither can local functions,\n global functions, or real funs.\n- Everything that is written as a function call is translated into a match\n specification call to a built-in function, so that the call\n [`is_list(X)`](`is_list/1`) is translated to `{'is_list', '$1'}` (`'$1'` is\n only an example, the numbering can vary). If one tries to call a function that\n is not a match specification built-in, it causes an error.\n- Variables occurring in the head of the fun are replaced by match specification\n variables in the order of occurrence, so that fragment `fun({A,B,C})` is\n replaced by `{'$1', '$2', '$3'}`, and so on. Every occurrence of such a\n variable in the match specification is replaced by a match specification\n variable in the same way, so that the fun\n `fun({A,B}) when is_atom(A) -> B end` is translated into\n `[{{'$1','$2'},[{is_atom,'$1'}],['$2']}]`.\n- Variables that are not included in the head are imported from the environment\n and made into match specification `const` expressions. Example from the shell:\n\n ```erlang\n 1> X = 25.\n 25\n 2> ets:fun2ms(fun({A,B}) when A > X -> B end).\n [{{'$1','$2'},[{'>','$1',{const,25}}],['$2']}]\n ```\n\n- Matching with `=` cannot be used in the body. It can only be used on the\n top-level in the head of the fun. Example from the shell again:\n\n ```erlang\n 1> ets:fun2ms(fun({A,[B|C]} = D) when A > B -> D end).\n [{{'$1',['$2'|'$3']},[{'>','$1','$2'}],['$_']}]\n 2> ets:fun2ms(fun({A,[B|C]=D}) when A > B -> D end).\n Error: fun with head matching ('=' in head) cannot be translated into\n match_spec\n {error,transform_error}\n 3> ets:fun2ms(fun({A,[B|C]}) when A > B -> D = [B|C], D end).\n Error: fun with body matching ('=' in body) is illegal as match_spec\n {error,transform_error}\n ```\n\n All variables are bound in the head of a match specification, so the\n translator cannot allow multiple bindings. The special case when matching is\n done on the top-level makes the variable bind to `'$_'` in the resulting match\n specification. It is to allow a more natural access to the whole matched\n object. Pseudo function `object()` can be used instead, see below.\n\n The following expressions are translated equally:\n\n ```erlang\n ets:fun2ms(fun({a,_} = A) -> A end).\n ets:fun2ms(fun({a,_}) -> object() end).\n ```\n\n- The special match specification variables `'$_'` and `'$*'` can be accessed\n through the pseudo functions `object()` (for `'$_'`) and `bindings()` (for\n `'$*'`). As an example, one can translate the following `ets:match_object/2`\n call to a `ets:select/2` call:\n\n ```erlang\n ets:match_object(Table, {'$1',test,'$2'}).\n ```\n\n This is the same as:\n\n ```erlang\n ets:select(Table, ets:fun2ms(fun({A,test,B}) -> object() end)).\n ```\n\n In this simple case, the former expression is probably preferable in terms of\n readability.\n\n The `ets:select/2` call conceptually looks like this in the resulting code:\n\n ```erlang\n ets:select(Table, [{{'$1',test,'$2'},[],['$_']}]).\n ```\n\n Matching on the top-level of the fun head can be a more natural way to access\n `'$_'`, see above.\n\n- Term constructions/literals are translated as much as is needed to get them\n into valid match specification. This way tuples are made into match\n specification tuple constructions (a one element tuple containing the tuple)\n and constant expressions are used when importing variables from the\n environment. Records are also translated into plain tuple constructions, calls\n to element, and so on. The guard test [`is_record/2`](`is_record/2`) is\n translated into match specification code using the three parameter version\n that is built into match specification, so that\n [`is_record(A,t)`](`is_record/2`) is translated into `{is_record,'$1',t,5}` if\n the record size of record type `t` is 5.\n- Language constructions such as `case`, `if`, and `catch` that are not present\n in match specifications are not allowed.\n- If header file `ms_transform.hrl` is not included, the fun is not translated,\n which can result in a _runtime error_ (depending on whether the fun is valid\n in a pure Erlang context).\n\n Ensure that the header is included when using `ets` and `dbg:fun2ms/1` in\n compiled code.\n\n- If pseudo function triggering the translation is `ets:fun2ms/1`, the head of\n the fun must contain a single variable or a single tuple. If the pseudo\n function is `dbg:fun2ms/1`, the head of the fun must contain a single variable\n or a single list.\n\nThe translation from funs to match specifications is done at compile time, so\nruntime performance is not affected by using these pseudo functions.\n\nFor more information about match specifications, see the\n[Match specifications in Erlang](`e:erts:match_spec.md`) in ERTS User's Guide.","title":"Warnings and Restrictions - ms_transform","ref":"ms_transform.html#module-warnings-and-restrictions"},{"type":"function","doc":"Takes an error code returned by one of the other functions in the module and\ncreates a textual description of the error.","title":"ms_transform.format_error/1","ref":"ms_transform.html#format_error/1"},{"type":"function","doc":"Implements the transformation at compile time. This function is called by the\ncompiler to do the source code transformation if and when header file\n`ms_transform.hrl` is included in the source code.\n\nFor information about how to use this parse transformation, see `m:ets` and\n`dbg:fun2ms/1`.\n\nFor a description of match specifications, see section\n[Match Specification in Erlang](`e:erts:match_spec.md`) in ERTS User's Guide.","title":"ms_transform.parse_transform/2","ref":"ms_transform.html#parse_transform/2"},{"type":"function","doc":"Implements the transformation when the `fun2ms/1` functions are called from the\nshell. In this case, the abstract form is for one single fun (parsed by the\nErlang shell). All imported variables are to be in the key-value list passed as\n`BoundEnvironment`. The result is a term, normalized, that is, not in abstract\nformat.","title":"ms_transform.transform_from_shell/3","ref":"ms_transform.html#transform_from_shell/3"},{"type":"module","doc":"Functional, extendible arrays.\n\nArrays can have fixed size, or can grow automatically as needed. A default value\nis used for entries that have not been explicitly set.\n\nArrays uses _zero_-based indexing. This is a deliberate design choice and\ndiffers from other Erlang data structures, for example, tuples.\n\nUnless specified by the user when the array is created, the default value is the\natom `undefined`. There is no difference between an unset entry and an entry\nthat has been explicitly set to the same value as the default one (compare\n`reset/2`). If you need to differentiate between unset and set entries, ensure\nthat the default value cannot be confused with the values of set entries.\n\nThe array never shrinks automatically. If an index `I` has been used to set an\nentry successfully, all indices in the range `[0,I]` stay accessible unless the\narray size is explicitly changed by calling `resize/2`.\n\n_Examples:_\n\nCreate a fixed-size array with entries 0-9 set to `undefined`:\n\n```\nA0 = array:new(10).\n10 = array:size(A0).\n```\n\nCreate an extendible array and set entry 17 to `true`, causing the array to grow\nautomatically:\n\n```\nA1 = array:set(17, true, array:new()).\n18 = array:size(A1).\n```\n\nRead back a stored value:\n\n```\ntrue = array:get(17, A1).\n```\n\nAccessing an unset entry returns default value:\n\n```\nundefined = array:get(3, A1)\n```\n\nAccessing an entry beyond the last set entry also returns the default value, if\nthe array does not have fixed size:\n\n```\nundefined = array:get(18, A1).\n```\n\n\"Sparse\" functions ignore default-valued entries:\n\n```\nA2 = array:set(4, false, A1).\n[{4, false}, {17, true}] = array:sparse_to_orddict(A2).\n```\n\nAn extendible array can be made fixed-size later:\n\n```\nA3 = array:fix(A2).\n```\n\nA fixed-size array does not grow automatically and does not allow accesses\nbeyond the last set entry:\n\n```\n{'EXIT',{badarg,_}} = (catch array:set(18, true, A3)).\n{'EXIT',{badarg,_}} = (catch array:get(18, A3)).\n```","title":"array","ref":"array.html"},{"type":"function","doc":"Gets the value used for uninitialized entries.\n\nSee also `new/2`.","title":"array.default/1","ref":"array.html#default/1"},{"type":"function","doc":"Fixes the array size. This prevents it from growing automatically upon\ninsertion.\n\nSee also `set/3` and `relax/1`.","title":"array.fix/1","ref":"array.html#fix/1"},{"type":"function","doc":"Folds the array elements using the specified function and initial accumulator\nvalue. The elements are visited in order from the lowest index to the highest.\n\nIf `Function` is not a function, the call fails with reason `badarg`.\n\nSee also `foldr/3`, `map/2`, `sparse_foldl/3`.","title":"array.foldl/3","ref":"array.html#foldl/3"},{"type":"function","doc":"Folds the array elements right-to-left using the specified function and initial\naccumulator value. The elements are visited in order from the highest index to\nthe lowest.\n\nIf `Function` is not a function, the call fails with reason `badarg`.\n\nSee also `foldl/3`, `map/2`.","title":"array.foldr/3","ref":"array.html#foldr/3"},{"type":"function","doc":"Equivalent to [`from_list(List, undefined)`](`from_list/2`).","title":"array.from_list/1","ref":"array.html#from_list/1"},{"type":"function","doc":"Converts a list to an extendible array. `Default` is used as the value for\nuninitialized entries of the array.\n\nIf `List` is not a proper list, the call fails with reason `badarg`.\n\nSee also `new/2`, `to_list/1`.","title":"array.from_list/2","ref":"array.html#from_list/2"},{"type":"function","doc":"Equivalent to [`from_orddict(Orddict, undefined)`](`from_orddict/2`).","title":"array.from_orddict/1","ref":"array.html#from_orddict/1"},{"type":"function","doc":"Converts an ordered list of pairs `{Index, Value}` to a corresponding extendible\narray. `Default` is used as the value for uninitialized entries of the array.\n\nIf `Orddict` is not a proper, ordered list of pairs whose first elements are\nnon-negative integers, the call fails with reason `badarg`.\n\nSee also `new/2`, `to_orddict/1`.","title":"array.from_orddict/2","ref":"array.html#from_orddict/2"},{"type":"function","doc":"Gets the value of entry `I`.\n\nIf `I` is not a non-negative integer, or if the array has fixed size and `I` is\nlarger than the maximum index, the call fails with reason `badarg`.\n\nIf the array does not have fixed size, the default value for any index `I`\ngreater than `size(Array)-1` is returned.\n\nSee also `set/3`.","title":"array.get/2","ref":"array.html#get/2"},{"type":"function","doc":"Returns `true` if `X` is an array, otherwise `false`.\n\nNotice that the check is only shallow, as there is no guarantee that `X` is a\nwell-formed array representation even if this function returns `true`.","title":"array.is_array/1","ref":"array.html#is_array/1"},{"type":"function","doc":"Checks if the array has fixed size. Returns `true` if the array is fixed,\notherwise `false`.\n\nSee also `fix/1`.","title":"array.is_fix/1","ref":"array.html#is_fix/1"},{"type":"function","doc":"Maps the specified function onto each array element. The elements are visited in\norder from the lowest index to the highest.\n\nIf `Function` is not a function, the call fails with reason `badarg`.\n\nSee also `foldl/3`, `foldr/3`, `sparse_map/2`.","title":"array.map/2","ref":"array.html#map/2"},{"type":"function","doc":"Creates a new, extendible array with initial size zero.\n\nSee also `new/1`, `new/2`.","title":"array.new/0","ref":"array.html#new/0"},{"type":"function","doc":"Creates a new array according to the specified options. By default, the array is\nextendible and has initial size zero. Array indices start at `0`.\n\n`Options` is a single term or a list of terms, selected from the following:\n\n- **`N::integer() >= 0` or `{size, N::integer() >= 0}`** - Specifies the initial\n array size; this also implies `{fixed, true}`. If `N` is not a non-negative\n integer, the call fails with reason `badarg`.\n\n- **`fixed` or `{fixed, true}`** - Creates a fixed-size array. See also `fix/1`.\n\n- **`{fixed, false}`** - Creates an extendible (non-fixed-size) array.\n\n- **`{default, Value}`** - Sets the default value for the array to `Value`.\n\nOptions are processed in the order they occur in the list, that is, later\noptions have higher precedence.\n\nThe default value is used as the value of uninitialized entries, and cannot be\nchanged once the array has been created.\n\n_Examples:_\n\n```\narray:new(100)\n```\n\ncreates a fixed-size array of size 100.\n\n```\narray:new({default,0})\n```\n\ncreates an empty, extendible array whose default value is `0`.\n\n```\narray:new([{size,10},{fixed,false},{default,-1}])\n```\n\ncreates an extendible array with initial size 10 whose default value is `-1`.\n\nSee also `fix/1`, `from_list/2`, `get/2`, `new/0`, `new/2`, `set/3`.","title":"array.new/1","ref":"array.html#new/1"},{"type":"function","doc":"Creates a new array according to the specified size and options.\n\nIf `Size` is not a non-negative integer, the call fails with reason `badarg`.\nBy default, the array has fixed size. Notice that any size specifications in\n`Options` override parameter `Size`.\n\nIf `Options` is a list, this is equivalent to\n[`new([{size, Size} | Options])`](`new/1`), otherwise it is equivalent to\n[`new([{size, Size} | [Options]])`](`new/1`). However, using this function\ndirectly is more efficient.\n\n_Example:_\n\n```\narray:new(100, {default,0})\n```\n\ncreates a fixed-size array of size 100, whose default value is `0`.\n\nSee also `new/1`.","title":"array.new/2","ref":"array.html#new/2"},{"type":"function","doc":"Makes the array resizable. (Reverses the effects of `fix/1`.)\n\nSee also `fix/1`.","title":"array.relax/1","ref":"array.html#relax/1"},{"type":"function","doc":"Resets entry `I` to the default value for the array. If the value of entry `I`\nis the default value, the array is returned unchanged.\n\nReset never changes the array size. Shrinking can be done explicitly by calling\n`resize/2`.\n\nIf `I` is not a non-negative integer, or if the array has fixed size and `I` is\nlarger than the maximum index, the call fails with reason `badarg`; compare\n`set/3`\n\nSee also `new/2`, `set/3`.","title":"array.reset/2","ref":"array.html#reset/2"},{"type":"function","doc":"Changes the array size to that reported by `sparse_size/1`. If the specified\narray has fixed size, also the resulting array has fixed size.\n\nSee also `resize/2`, `sparse_size/1`.","title":"array.resize/1","ref":"array.html#resize/1"},{"type":"function","doc":"Change the array size.\n\nIf `Size` is not a non-negative integer, the call fails with reason `badarg`. If\nthe specified array has fixed size, also the resulting array has fixed size.","title":"array.resize/2","ref":"array.html#resize/2"},{"type":"function","doc":"Sets entry `I` of the array to `Value`.\n\nIf `I` is not a non-negative integer, or if the array has fixed size and `I` is\nlarger than the maximum index, the call fails with reason `badarg`.\n\nIf the array does not have fixed size, and `I` is greater than `size(Array)-1`,\nthe array grows to size `I+1`.\n\nSee also `get/2`, `reset/2`.","title":"array.set/3","ref":"array.html#set/3"},{"type":"function","doc":"Gets the number of entries in the array. Entries are numbered from `0` to\n`size(Array)-1`. Hence, this is also the index of the first entry that is\nguaranteed to not have been previously set.\n\nSee also `set/3`, `sparse_size/1`.","title":"array.size/1","ref":"array.html#size/1"},{"type":"function","doc":"Folds the array elements using the specified function and initial accumulator\nvalue, skipping default-valued entries. The elements are visited in order from\nthe lowest index to the highest.\n\nIf `Function` is not a function, the call fails with reason `badarg`.\n\nSee also `foldl/3`, `sparse_foldr/3`.","title":"array.sparse_foldl/3","ref":"array.html#sparse_foldl/3"},{"type":"function","doc":"Folds the array elements right-to-left using the specified function and initial\naccumulator value, skipping default-valued entries. The elements are visited in\norder from the highest index to the lowest.\n\nIf `Function` is not a function, the call fails with reason `badarg`.\n\nSee also `foldr/3`, `sparse_foldl/3`.","title":"array.sparse_foldr/3","ref":"array.html#sparse_foldr/3"},{"type":"function","doc":"Maps the specified function onto each array element, skipping default-valued\nentries. The elements are visited in order from the lowest index to the highest.\n\nIf `Function` is not a function, the call fails with reason `badarg`.\n\nSee also `map/2`.","title":"array.sparse_map/2","ref":"array.html#sparse_map/2"},{"type":"function","doc":"Gets the number of entries in the array up until the last non-default-valued\nentry. That is, returns `I+1` if `I` is the last non-default-valued entry in the\narray, or zero if no such entry exists.\n\nSee also `resize/1`, `size/1`.","title":"array.sparse_size/1","ref":"array.html#sparse_size/1"},{"type":"function","doc":"Converts the array to a list, skipping default-valued entries.\n\nSee also `to_list/1`.","title":"array.sparse_to_list/1","ref":"array.html#sparse_to_list/1"},{"type":"function","doc":"Converts the array to an ordered list of pairs `{Index, Value}`, skipping\ndefault-valued entries.\n\nSee also `to_orddict/1`.","title":"array.sparse_to_orddict/1","ref":"array.html#sparse_to_orddict/1"},{"type":"function","doc":"Converts the array to a list.\n\nSee also `from_list/2`, `sparse_to_list/1`.","title":"array.to_list/1","ref":"array.html#to_list/1"},{"type":"function","doc":"Converts the array to an ordered list of pairs `{Index, Value}`.\n\nSee also `from_orddict/2`, `sparse_to_orddict/1`.","title":"array.to_orddict/1","ref":"array.html#to_orddict/1"},{"type":"type","doc":"","title":"array.array/0","ref":"array.html#t:array/0"},{"type":"opaque","doc":"A functional, extendible array. The representation is not documented and is\nsubject to change without notice. Notice that arrays cannot be directly compared\nfor equality.","title":"array.array/1","ref":"array.html#t:array/1"},{"type":"type","doc":"","title":"array.array_indx/0","ref":"array.html#t:array_indx/0"},{"type":"type","doc":"","title":"array.array_opt/0","ref":"array.html#t:array_opt/0"},{"type":"type","doc":"","title":"array.array_opts/0","ref":"array.html#t:array_opts/0"},{"type":"type","doc":"","title":"array.indx_pair/1","ref":"array.html#t:indx_pair/1"},{"type":"type","doc":"","title":"array.indx_pairs/1","ref":"array.html#t:indx_pairs/1"},{"type":"module","doc":"A disk-based term storage.\n\nThis module provides a term storage on file. The stored terms, in this module\ncalled _objects_, are tuples such that one element is defined to be the key. A\nDets _table_ is a collection of objects with the key at the same position stored\non a file.\n\nThis module is used by the Mnesia application, and is provided \"as is\" for users\nwho are interested in efficient storage of Erlang terms on disk only. Many\napplications only need to store some terms in a file. Mnesia adds transactions,\nqueries, and distribution. The size of Dets files cannot exceed 2 GB. If larger\ntables are needed, table fragmentation in Mnesia can be used.\n\nThree types of Dets tables exist:\n\n- `set`. A table of this type has at most one object with a given key. If an\n object with a key already present in the table is inserted, the existing\n object is overwritten by the new object.\n- `bag`. A table of this type has zero or more different objects with a given\n key.\n- `duplicate_bag`. A table of this type has zero or more possibly matching\n objects with a given key.\n\nDets tables must be opened before they can be updated or read, and when finished\nthey must be properly closed. If a table is not properly closed, Dets\nautomatically repairs the table. This can take a substantial time if the table\nis large. A Dets table is closed when the process which opened the table\nterminates. If many Erlang processes (users) open the same Dets table, they\nshare the table. The table is properly closed when all users have either\nterminated or closed the table. Dets tables are not properly closed if the\nErlang runtime system terminates abnormally.\n\n> #### Note {: .info }\n>\n> A `^C` command abnormally terminates an Erlang runtime system in a Unix\n> environment with a break-handler.\n\nAs all operations performed by Dets are disk operations, it is important to\nrealize that a single look-up operation involves a series of disk seek and read\noperations. The Dets functions are therefore much slower than the corresponding\n`m:ets` functions, although Dets exports a similar interface.\n\nDets organizes data as a linear hash list and the hash list grows gracefully as\nmore data is inserted into the table. Space management on the file is performed\nby what is called a buddy system. The current implementation keeps the entire\nbuddy system in RAM, which implies that if the table gets heavily fragmented,\nquite some memory can be used up. The only way to defragment a table is to close\nit and then open it again with option `repair` set to `force`.\n\nNotice that type `ordered_set` in Ets is not yet provided by Dets, neither is\nthe limited support for concurrent updates that makes a sequence of `first` and\n`next` calls safe to use on fixed ETS tables. Both these features may be\nprovided by Dets in a future release of Erlang/OTP. Until then, the Mnesia\napplication (or some user-implemented method for locking) must be used to\nimplement safe concurrency. Currently, no Erlang/OTP library has support for\nordered disk-based term storage.\n\nAll Dets functions return `{error, Reason}` if an error occurs (`first/1` and\n`next/2` are exceptions, they exit the process with the error tuple). If badly\nformed arguments are specified, all functions exit the process with a `badarg`\nmessage.","title":"dets","ref":"dets.html"},{"type":"module","doc":"`m:ets`, `m:mnesia`, `m:qlc`","title":"See Also - dets","ref":"dets.html#module-see-also"},{"type":"function","doc":"Returns a list of the names of all open tables on this node.","title":"dets.all/0","ref":"dets.html#all/0"},{"type":"function","doc":"Returns a list of objects stored in a table. The exact representation of the\nreturned objects is not public.\n\nThe lists of data can be used for initializing a table by specifying value\n`bchunk` to option `format` of function `init_table/3`. The Mnesia application\nuses this function for copying open tables.\n\nUnless the table is protected using [`safe_fixtable/2`](`safe_fixtable/2`),\ncalls to [`bchunk/2`](`bchunk/2`) do possibly not work as expected if concurrent\nupdates are made to the table.\n\nThe first time [`bchunk/2`](`bchunk/2`) is called, an initial continuation, the\natom `start`, must be provided.\n\n[`bchunk/2`](`bchunk/2`) returns a tuple `{Continuation2, Data}`, where `Data`\nis a list of objects. `Continuation2` is another continuation that is to be\npassed on to a subsequent call to [`bchunk/2`](`bchunk/2`). With a series of\ncalls to [`bchunk/2`](`bchunk/2`), all table objects can be extracted.\n\n[`bchunk/2`](`bchunk/2`) returns `'$end_of_table'` when all objects are\nreturned, or `{error, Reason}` if an error occurs.","title":"dets.bchunk/2","ref":"dets.html#bchunk/2"},{"type":"function","doc":"Closes a table. Only processes that have opened a table are allowed to close it.\n\nAll open tables must be closed before the system is stopped. If an attempt is\nmade to open a table that is not properly closed, Dets automatically tries to\nrepair it.","title":"dets.close/1","ref":"dets.html#close/1"},{"type":"function","doc":"Deletes all objects with key `Key` from table `Name`.","title":"dets.delete/2","ref":"dets.html#delete/2"},{"type":"function","doc":"Deletes all objects from a table in almost constant time. However, if the table\nif fixed, [`delete_all_objects(T)`](`delete_all_objects/1`) is equivalent to\n[`match_delete(T, '_')`](`match_delete/2`).","title":"dets.delete_all_objects/1","ref":"dets.html#delete_all_objects/1"},{"type":"function","doc":"Deletes all instances of a specified object from a table. If a table is of type\n`bag` or `duplicate_bag`, this function can be used to delete only some of the\nobjects with a specified key.","title":"dets.delete_object/2","ref":"dets.html#delete_object/2"},{"type":"function","doc":"Returns the first key stored in table `Name` according to the internal order of\nthe table, or `'$end_of_table'` if the table is empty.\n\nUnless the table is protected using [`safe_fixtable/2`](`safe_fixtable/2`),\nsubsequent calls to `next/2` do possibly not work as expected if concurrent\nupdates are made to the table.\n\nIf an error occurs, the process is exited with an error tuple `{error, Reason}`.\nThe error tuple is not returned, as it cannot be distinguished from a key.\n\nThere are two reasons why [`first/1`](`first/1`) and [`next/2`](`next/2`) are\nnot to be used: they are not efficient, and they prevent the use of key\n`'$end_of_table'`, as this atom is used to indicate the end of the table. If\npossible, use functions [`match`](`match/1`),\n[`match_object`](`match_object/1`), and [`select`](`select/1`) for traversing\ntables.","title":"dets.first/1","ref":"dets.html#first/1"},{"type":"function","doc":"","title":"dets.foldl/3","ref":"dets.html#foldl/3"},{"type":"function","doc":"Calls `Function` on successive elements of table `Name` together with an extra\nargument `AccIn`. The table elements are traversed in unspecified order.\n`Function` must return a new accumulator that is passed to the next call. `Acc0`\nis returned if the table is empty.","title":"dets.foldr/3","ref":"dets.html#foldr/3"},{"type":"function","doc":"Deletes all objects of table `Name` and then inserts all the objects of the ETS\ntable `EtsTab`. The objects are inserted in unspecified order. As\n`ets:safe_fixtable/2` is called, the ETS table must be public or owned by the\ncalling process.","title":"dets.from_ets/2","ref":"dets.html#from_ets/2"},{"type":"function","doc":"Returns information about table `Name` as a list of tuples:\n\n- `{file_size, integer() >= 0}}` \\- The file size, in bytes.\n- `{filename,` `t:file:name/0` `}` \\- The name of the file where objects are\n stored.\n- `{keypos,` `t:keypos/0` `}` \\- The key position.\n- `{size, integer() >= 0}` \\- The number of objects stored in the table.\n- `{type,` `t:type/0` `}` \\- The table type.","title":"dets.info/1","ref":"dets.html#info/1"},{"type":"function","doc":"Returns the information associated with `Item` for table `Name`. In addition to\nthe `{Item, Value}` pairs defined for `info/1`, the following items are allowed:\n\n- `{access,` `t:access/0` `}` \\- The access mode.\n- `{auto_save,` `t:auto_save/0` `}` \\- The autosave interval.\n- `{bchunk_format, binary()}` \\- An opaque binary describing the format of the\n objects returned by [`bchunk/2`](`bchunk/2`). The binary can be used as\n argument to\n [`is_compatible_bchunk_format/2`](`is_compatible_bchunk_format/2`).\n- `{hash, Hash}` \\- Describes which BIF is used to calculate the hash values of\n the objects stored in the Dets table. Possible values of `Hash`:\n\n - `phash` \\- Implies that the `erlang:phash/2` BIF is used.\n - `phash2` \\- Implies that the `erlang:phash2/1` BIF is used.\n\n- `{memory, integer() >= 0}` \\- The file size, in bytes. The same value is\n associated with item `file_size`.\n- `{no_keys, integer >= 0()}` \\- The number of different keys stored in the\n table.\n- `{no_objects, integer >= 0()}` \\- The number of objects stored in the table.\n- `{no_slots, {Min, Used, Max}}` \\- The number of slots of the table. `Min` is\n the minimum number of slots, `Used` is the number of currently used slots, and\n `Max` is the maximum number of slots.\n- `{owner, pid()}` \\- The pid of the process that handles requests to the Dets\n table.\n- `{ram_file, boolean()}` \\- Whether the table is kept in RAM.\n- `{safe_fixed_monotonic_time, SafeFixed}` \\- If the table is fixed, `SafeFixed`\n is a tuple `{FixedAtTime, [{Pid,RefCount}]}`. `FixedAtTime` is the time when\n the table was first fixed, and `Pid` is the pid of the process that fixes the\n table `RefCount` times. There can be any number of processes in the list. If\n the table is not fixed, `SafeFixed` is the atom `false`.\n\n `FixedAtTime` corresponds to the result returned by `erlang:monotonic_time/0`\n at the time of fixation. The use of `safe_fixed_monotonic_time` is\n [time warp safe](`e:erts:time_correction.md#time-warp-safe-code`).\n\n- `{safe_fixed, SafeFixed}` \\- The same as\n `{safe_fixed_monotonic_time, SafeFixed}` except the format and value of\n `FixedAtTime`.\n\n `FixedAtTime` corresponds to the result returned by `erlang:timestamp/0` at\n the time of fixation. Notice that when the system uses single or multi\n [time warp modes](`e:erts:time_correction.md#time-warp-modes`), this can\n produce strange results. This is because the use of `safe_fixed` is not\n [time warp safe](`e:erts:time_correction.md#time-warp-safe-code`). Time warp\n safe code must use `safe_fixed_monotonic_time` instead.","title":"dets.info/2","ref":"dets.html#info/2"},{"type":"function","doc":"","title":"dets.init_table/2","ref":"dets.html#init_table/2"},{"type":"function","doc":"Replaces the existing objects of table `Name` with objects created by calling\nthe input function `InitFun`.\n\nThe reason for using this function rather than calling [`insert/2`](`insert/2`)\nis that of efficiency. Notice that the input functions are called by the process\nthat handles requests to the Dets table, not by the calling process.\n\nWhen called with argument `read`, function `InitFun` is assumed to return\n`end_of_input` when there is no more input, or `{Objects, Fun}`, where `Objects`\nis a list of objects and `Fun` is a new input function. Any other value `Value`\nis returned as an error `{error, {init_fun, Value}}`. Each input function is\ncalled exactly once, and if an error occurs, the last function is called with\nargument `close`, the reply of which is ignored.\n\nIf the table type is `set` and more than one object exists with a given key, one\nof the objects is chosen. This is not necessarily the last object with the given\nkey in the sequence of objects returned by the input functions. Avoid duplicate\nkeys, otherwise the file becomes unnecessarily fragmented. This holds also for\nduplicated objects stored in tables of type `bag`.\n\nIt is important that the table has a sufficient number of slots for the objects.\nIf not, the hash list starts to grow when [`init_table/2`](`init_table/2`)\nreturns, which significantly slows down access to the table for a period of\ntime. The minimum number of slots is set by the [`open_file/2`](`open_file/2`)\noption `min_no_slots` and returned by the [`info/2`](`info/2`) item `no_slots`.\nSee also option `min_no_slots` below.\n\nArgument `Options` is a list of `{Key, Val}` tuples, where the following values\nare allowed:\n\n- `{min_no_slots, no_slots()}` \\- Specifies the estimated number of different\n keys to be stored in the table. The [`open_file/2`](`open_file/2`) option with\n the same name is ignored, unless the table is created, in which case\n performance can be enhanced by supplying an estimate when initializing the\n table.\n- `{format, Format}` \\- Specifies the format of the objects returned by function\n `InitFun`. If `Format` is `term` (the default), `InitFun` is assumed to return\n a list of tuples. If `Format` is `bchunk`, `InitFun` is assumed to return\n `Data` as returned by `bchunk/2`. This option overrides option `min_no_slots`.","title":"dets.init_table/3","ref":"dets.html#init_table/3"},{"type":"function","doc":"Inserts one or more objects into the table `Name`. If there already exists an\nobject with a key matching the key of some of the given objects and the table\ntype is `set`, the old object will be replaced.","title":"dets.insert/2","ref":"dets.html#insert/2"},{"type":"function","doc":"Inserts one or more objects into table `Name`. If there already exists some\nobject with a key matching the key of any of the specified objects, the table is\nnot updated and `false` is returned. Otherwise the objects are inserted and\n`true` returned.","title":"dets.insert_new/2","ref":"dets.html#insert_new/2"},{"type":"function","doc":"Returns `true` if it would be possible to initialize table `Name`, using\n`init_table/3` with option `{format, bchunk}`, with objects read with `bchunk/2`\nfrom some table `T`, such that calling [`info(T, bchunk_format)`](`info/2`)\nreturns `BchunkFormat`.","title":"dets.is_compatible_bchunk_format/2","ref":"dets.html#is_compatible_bchunk_format/2"},{"type":"function","doc":"Returns `true` if file `Filename` is a Dets table, otherwise `false`.","title":"dets.is_dets_file/1","ref":"dets.html#is_dets_file/1"},{"type":"function","doc":"Returns a list of all objects with key `Key` stored in table `Name`, for\nexample:\n\n```erlang\n2> dets:open_file(abc, [{type, bag}]).\n{ok,abc}\n3> dets:insert(abc, {1,2,3}).\nok\n4> dets:insert(abc, {1,3,4}).\nok\n5> dets:lookup(abc, 1).\n[{1,2,3},{1,3,4}]\n```\n\nIf the table type is `set`, the function returns either the empty list or a list\nwith one object, as there cannot be more than one object with a given key. If\nthe table type is `bag` or `duplicate_bag`, the function returns a list of\narbitrary length.\n\nNotice that the order of objects returned is unspecified. In particular, the\norder in which objects were inserted is not reflected.","title":"dets.lookup/2","ref":"dets.html#lookup/2"},{"type":"function","doc":"Matches some objects stored in a table and returns a non-empty list of the\nbindings matching a specified pattern in some unspecified order. The table, the\npattern, and the number of objects that are matched are all defined by\n`Continuation`, which has been returned by a previous call to\n[`match/1`](`match/1`) or [`match/3`](`match/3`).\n\nWhen all table objects are matched, `'$end_of_table'` is returned.","title":"dets.match/1","ref":"dets.html#match/1"},{"type":"function","doc":"Returns for each object of table `Name` that matches `Pattern` a list of\nbindings in some unspecified order. For a description of patterns, see\n`ets:match/2`. If the keypos'th element of `Pattern` is unbound, all table\nobjects are matched. If the keypos'th element is bound, only the objects with\nthe correct key are matched.","title":"dets.match/2","ref":"dets.html#match/2"},{"type":"function","doc":"Matches some or all objects of table `Name` and returns a non-empty list of the\nbindings that match `Pattern` in some unspecified order. For a description of\npatterns, see `ets:match/2`.\n\nA tuple of the bindings and a continuation is returned, unless the table is\nempty, in which case `'$end_of_table'` is returned. The continuation is to be\nused when matching further objects by calling `match/1`.\n\nIf the keypos'th element of `Pattern` is bound, all table objects are matched.\nIf the keypos'th element is unbound, all table objects are matched, `N` objects\nat a time, until at least one object matches or the end of the table is reached.\nThe default, indicated by giving `N` the value `default`, is to let the number\nof objects vary depending on the sizes of the objects. All objects with the same\nkey are always matched at the same time, which implies that more than N objects\ncan sometimes be matched.\n\nThe table is always to be protected using `safe_fixtable/2` before calling\n[`match/3`](`match/3`), otherwise errors can occur when calling\n[`match/1`](`match/1`).","title":"dets.match/3","ref":"dets.html#match/3"},{"type":"function","doc":"Deletes all objects that match `Pattern` from table `Name`. For a description of\npatterns, see `ets:match/2`.\n\nIf the keypos'th element of `Pattern` is bound, only the objects with the\ncorrect key are matched.","title":"dets.match_delete/2","ref":"dets.html#match_delete/2"},{"type":"function","doc":"Returns a non-empty list of some objects stored in a table that match a given\npattern in some unspecified order. The table, the pattern, and the number of\nobjects that are matched are all defined by `Continuation`, which has been\nreturned by a previous call to [`match_object/1`](`match_object/1`) or\n[`match_object/3`](`match_object/3`).\n\nWhen all table objects are matched, `'$end_of_table'` is returned.","title":"dets.match_object/1","ref":"dets.html#match_object/1"},{"type":"function","doc":"Returns a list of all objects of table `Name` that match `Pattern` in some\nunspecified order. For a description of patterns, see `ets:match/2`.\n\nIf the keypos'th element of `Pattern` is unbound, all table objects are matched.\nIf the keypos'th element of `Pattern` is bound, only the objects with the\ncorrect key are matched.\n\nUsing the `match_object` functions for traversing all table objects is more\nefficient than calling [`first/1`](`first/1`) and [`next/2`](`next/2`) or\n[`slot/2`](`slot/2`).","title":"dets.match_object/2","ref":"dets.html#match_object/2"},{"type":"function","doc":"Matches some or all objects stored in table `Name` and returns a non-empty list\nof the objects that match `Pattern` in some unspecified order. For a description\nof patterns, see `ets:match/2`.\n\nA list of objects and a continuation is returned, unless the table is empty, in\nwhich case `'$end_of_table'` is returned. The continuation is to be used when\nmatching further objects by calling `match_object/1`.\n\nIf the keypos'th element of `Pattern` is bound, all table objects are matched.\nIf the keypos'th element is unbound, all table objects are matched, `N` objects\nat a time, until at least one object matches or the end of the table is reached.\nThe default, indicated by giving `N` the value `default`, is to let the number\nof objects vary depending on the sizes of the objects. All matching objects with\nthe same key are always returned in the same reply, which implies that more than\nN objects can sometimes be returned.\n\nThe table is always to be protected using `safe_fixtable/2` before calling\n[`match_object/3`](`match_object/3`), otherwise errors can occur when calling\n[`match_object/1`](`match_object/1`).","title":"dets.match_object/3","ref":"dets.html#match_object/3"},{"type":"function","doc":"Works like `lookup/2`, but does not return the objects. Returns `true` if one or\nmore table elements has key `Key`, otherwise `false`.","title":"dets.member/2","ref":"dets.html#member/2"},{"type":"function","doc":"Returns either the key following `Key1` in table `Name` according to the\ninternal order of the table, or `'$end_of_table'` if there is no next key.\n\nIf an error occurs, the process is exited with an error tuple `{error, Reason}`.\n\nTo find the first key in the table, use `first/1`.","title":"dets.next/2","ref":"dets.html#next/2"},{"type":"function","doc":"Opens an existing table. If the table is not properly closed, it is repaired.\nThe returned reference is to be used as the table name. This function is most\nuseful for debugging purposes.","title":"dets.open_file/1","ref":"dets.html#open_file/1"},{"type":"function","doc":"Opens a table. An empty Dets table is created if no file exists.\n\nThe atom `Name` is the table name. The table name must be provided in all\nsubsequent operations on the table. The name can be used by other processes as\nwell, and many processes can share one table.\n\nIf two processes open the same table by giving the same name and arguments, the\ntable has two users. If one user closes the table, it remains open until the\nsecond user closes it.\n\nArgument `Args` is a list of `{Key, Val}` tuples, where the following values are\nallowed:\n\n- `{access,` `t:access/0` `}` \\- Existing tables can be opened in read-only mode.\n A table that is opened in read-only mode is not subjected to the automatic\n file reparation algorithm if it is later opened after a crash. Defaults to\n `read_write`.\n- `{auto_save,` `t:auto_save/0` `}` \\- The autosave interval. If the interval is\n an integer `Time`, the table is flushed to disk whenever it is not accessed\n for `Time` milliseconds. A table that has been flushed requires no reparation\n when reopened after an uncontrolled emulator halt. If the interval is the atom\n `infinity`, autosave is disabled. Defaults to 180000 (3 minutes).\n- `{estimated_no_objects,` `t:no_slots/0` `}` \\- Equivalent to option\n `min_no_slots`.\n- `{file,` `t:file:name/0` `}` \\- The name of the file to be opened. Defaults to\n the table name.\n- `{max_no_slots,` `t:no_slots/0` `}` \\- The maximum number of slots to be used.\n Defaults to 32 M, which is the maximal value. Notice that a higher value can\n increase the table fragmentation, and a smaller value can decrease the\n fragmentation, at the expense of execution time.\n- `{min_no_slots,` `t:no_slots/0` `}` \\- Application performance can be enhanced\n with this flag by specifying, when the table is created, the estimated number\n of different keys to be stored in the table. Defaults to 256, which is the\n minimum value.\n- `{keypos,` `t:keypos/0` `}` \\- The position of the element of each object to be\n used as key. Defaults to 1. The ability to explicitly state the key position\n is most convenient when we want to store Erlang records in which the first\n position of the record is the name of the record type.\n- `{ram_file, boolean()}` \\- Whether the table is to be kept in RAM. Keeping the\n table in RAM can sound like an anomaly, but can enhance the performance of\n applications that open a table, insert a set of objects, and then close the\n table. When the table is closed, its contents are written to the disk file.\n Defaults to `false`.\n- `{repair, Value}` \\- `Value` can be either a `t:boolean/0` or the atom\n `force`. The flag specifies if the Dets server is to invoke the automatic file\n reparation algorithm. Defaults to `true`. If `false` is specified, no attempt\n is made to repair the file, and `{error, {needs_repair, FileName}}` is\n returned if the table must be repaired.\n\n Value `force` means that a reparation is made even if the table is properly\n closed. This is a seldom needed option.\n\n Option `repair` is ignored if the table is already open.\n\n- `{type,` `t:type/0` `}` \\- The table type. Defaults to `set`.","title":"dets.open_file/2","ref":"dets.html#open_file/2"},{"type":"function","doc":"Returns the table name given the pid of a process that handles requests to a\ntable, or `undefined` if there is no such table.\n\nThis function is meant to be used for debugging only.","title":"dets.pid2name/1","ref":"dets.html#pid2name/1"},{"type":"function","doc":"This function can be used to restore an opaque continuation returned by\n`select/3` or `select/1` if the continuation has passed through external term\nformat (been sent between nodes or stored on disk).\n\nThe reason for this function is that continuation terms contain compiled match\nspecifications and therefore are invalidated if converted to external term\nformat. Given that the original match specification is kept intact, the\ncontinuation can be restored, meaning it can once again be used in subsequent\n[`select/1`](`select/1`) calls even though it has been stored on disk or on\nanother node.\n\nFor more information and examples, see the `m:ets` module.\n\n> #### Note {: .info }\n>\n> This function is rarely needed in application code. It is used by application\n> Mnesia to provide distributed [`select/3`](`select/3`) and\n> [`select/1`](`select/1`) sequences. A normal application would either use\n> Mnesia or keep the continuation from being converted to external format.\n>\n> The reason for not having an external representation of compiled match\n> specifications is performance. It can be subject to change in future releases,\n> while this interface remains for backward compatibility.","title":"dets.repair_continuation/2","ref":"dets.html#repair_continuation/2"},{"type":"function","doc":"If `Fix` is `true`, table `Name` is fixed (once more) by the calling process,\notherwise the table is released. The table is also released when a fixing\nprocess terminates.\n\nIf many processes fix a table, the table remains fixed until all processes have\nreleased it or terminated. A reference counter is kept on a per process basis,\nand N consecutive fixes require N releases to release the table.\n\nIt is not guaranteed that calls to [`first/1`](`first/1`), [`next/2`](`next/2`),\nor select and match functions work as expected even if the table is fixed; the\nlimited support for concurrency provided by the `m:ets` module is not yet\nprovided by Dets. Fixing a table currently only disables resizing of the hash\nlist of the table.\n\nIf objects have been added while the table was fixed, the hash list starts to\ngrow when the table is released, which significantly slows down access to the\ntable for a period of time.","title":"dets.safe_fixtable/2","ref":"dets.html#safe_fixtable/2"},{"type":"function","doc":"Applies a match specification to some objects stored in a table and returns a\nnon-empty list of the results. The table, the match specification, and the\nnumber of objects that are matched are all defined by `Continuation`, which is\nreturned by a previous call to `select/1` or `select/3`.\n\nWhen all objects of the table have been matched, `'$end_of_table'` is returned.","title":"dets.select/1","ref":"dets.html#select/1"},{"type":"function","doc":"Returns the results of applying match specification `MatchSpec` to all or some\nobjects stored in table `Name`. The order of the objects is not specified. For a\ndescription of match specifications, see the\n[ERTS User's Guide](`e:erts:match_spec.md`).\n\nIf the keypos'th element of `MatchSpec` is unbound, the match specification is\napplied to all objects of the table. If the keypos'th element is bound, the\nmatch specification is applied to the objects with the correct key(s) only.\n\nUsing the `select` functions for traversing all objects of a table is more\nefficient than calling [`first/1`](`first/1`) and [`next/2`](`next/2`) or\n[`slot/2`](`slot/2`).","title":"dets.select/2","ref":"dets.html#select/2"},{"type":"function","doc":"Returns the results of applying match specification `MatchSpec` to some or all\nobjects stored in table `Name`. The order of the objects is not specified. For a\ndescription of match specifications, see the\n[ERTS User's Guide](`e:erts:match_spec.md`).\n\nA tuple of the results of applying the match specification and a continuation is\nreturned, unless the table is empty, in which case `'$end_of_table'` is\nreturned. The continuation is to be used when matching more objects by calling\n`select/1`.\n\nIf the keypos'th element of `MatchSpec` is bound, the match specification is\napplied to all objects of the table with the correct key(s). If the keypos'th\nelement of `MatchSpec` is unbound, the match specification is applied to all\nobjects of the table, `N` objects at a time, until at least one object matches\nor the end of the table is reached. The default, indicated by giving `N` the\nvalue `default`, is to let the number of objects vary depending on the sizes of\nthe objects. All objects with the same key are always handled at the same time,\nwhich implies that the match specification can be applied to more than N\nobjects.\n\nThe table is always to be protected using `safe_fixtable/2` before calling\n[`select/3`](`select/3`), otherwise errors can occur when calling\n[`select/1`](`select/1`).","title":"dets.select/3","ref":"dets.html#select/3"},{"type":"function","doc":"Deletes each object from table `Name` such that applying match specification\n`MatchSpec` to the object returns value `true`. For a description of match\nspecifications, see the [ERTS User's Guide](`e:erts:match_spec.md`). Returns the\nnumber of deleted objects.\n\nIf the keypos'th element of `MatchSpec` is bound, the match specification is\napplied to the objects with the correct key(s) only.","title":"dets.select_delete/2","ref":"dets.html#select_delete/2"},{"type":"function","doc":"The objects of a table are distributed among slots, starting with slot `0` and\nending with slot `n`. Returns the list of objects associated with slot `I`. If\n`I` > `n`, `'$end_of_table'` is returned.","title":"dets.slot/2","ref":"dets.html#slot/2"},{"type":"function","doc":"Ensures that all updates made to table `Name` are written to disk. This also\napplies to tables that have been opened with flag `ram_file` set to `true`. In\nthis case, the contents of the RAM file are flushed to disk.\n\nNotice that the space management data structures kept in RAM, the buddy system,\nis also written to the disk. This can take some time if the table is fragmented.","title":"dets.sync/1","ref":"dets.html#sync/1"},{"type":"function","doc":"","title":"dets.table/1","ref":"dets.html#table/1"},{"type":"function","doc":"Returns a Query List Comprehension (QLC) query handle. The `m:qlc` module\nprovides a query language aimed mainly for Mnesia, but ETS tables, Dets tables,\nand lists are also recognized by `qlc` as sources of data. Calling\n[`dets:table/1,2`](`table/1`) is the means to make Dets table `Name` usable to\n`qlc`.\n\nWhen there are only simple restrictions on the key position, `qlc` uses\n[`dets:lookup/2`](`lookup/2`) to look up the keys. When that is not possible,\nthe whole table is traversed. Option `traverse` determines how this is done:\n\n- `first_next` \\- The table is traversed one key at a time by calling\n `dets:first/1` and `dets:next/2`.\n- `select` \\- The table is traversed by calling [`dets:select/3`](`select/3`)\n and [`dets:select/1`](`select/1`). Option `n_objects` determines the number of\n objects returned (the third argument of [`select/3`](`select/3`)). The match\n specification (the second argument of [`select/3`](`select/3`)) is assembled\n by `qlc`:\n\n - Simple filters are translated into equivalent match specifications.\n - More complicated filters must be applied to all objects returned by\n [`select/3`](`select/3`) given a match specification that matches all\n objects.\n\n- `{select,` `t:match_spec/0` `}` \\- As for `select`, the table is traversed by\n calling `dets:select/3` and `dets:select/1`. The difference is that the match\n specification is specified explicitly. This is how to state match\n specifications that cannot easily be expressed within the syntax provided by\n `qlc`.\n\nThe following example uses an explicit match specification to traverse the\ntable:\n\n```erlang\n1> dets:open_file(t, []),\nok = dets:insert(t, [{1,a},{2,b},{3,c},{4,d}]),\nMS = ets:fun2ms(fun({X,Y}) when (X > 1) or (X < 5) -> {Y} end),\nQH1 = dets:table(t, [{traverse, {select, MS}}]).\n```\n\nAn example with implicit match specification:\n\n```erlang\n2> QH2 = qlc:q([{Y} || {X,Y} <- dets:table(t), (X > 1) or (X < 5)]).\n```\n\nThe latter example is equivalent to the former, which can be verified using\nfunction `qlc:info/1`:\n\n```erlang\n3> qlc:info(QH1) =:= qlc:info(QH2).\ntrue\n```\n\n`qlc:info/1` returns information about a query handle. In this case identical\ninformation is returned for the two query handles.","title":"dets.table/2","ref":"dets.html#table/2"},{"type":"function","doc":"Inserts the objects of the Dets table `Name` into the ETS table `EtsTab`. The\norder in which the objects are inserted is not specified. The existing objects\nof the ETS table are kept unless overwritten.","title":"dets.to_ets/2","ref":"dets.html#to_ets/2"},{"type":"function","doc":"Applies `Fun` to each object stored in table `Name` in some unspecified order.\nDifferent actions are taken depending on the return value of `Fun`. The\nfollowing `Fun` return values are allowed:\n\n- **`continue`** - Continue to perform the traversal. For example, the following\n function can be used to print the contents of a table:\n\n ```erlang\n fun(X) -> io:format(\"~p~n\", [X]), continue end.\n ```\n\n- **`{continue, Val}`** - Continue the traversal and accumulate `Val`. The\n following function is supplied to collect all objects of a table in a list:\n\n ```text\n fun(X) -> {continue, X} end.\n ```\n\n- **`{done, Value}`** - Terminate the traversal and return `[Value | Acc]`.\n\nAny other value `OtherValue` returned by `Fun` terminates the traversal and is\nreturned immediately.","title":"dets.traverse/2","ref":"dets.html#traverse/2"},{"type":"function","doc":"Updates the object with key `Key` stored in table `Name` of type `set` by adding\n`Incr` to the element at the `Pos`:th position. The new counter value is\nreturned. If no position is specified, the element directly following the key is\nupdated.\n\nThis functions provides a way of updating a counter, without having to look up\nan object, update the object by incrementing an element, and insert the\nresulting object into the table again.","title":"dets.update_counter/3","ref":"dets.html#update_counter/3"},{"type":"type","doc":"","title":"dets.access/0","ref":"dets.html#t:access/0"},{"type":"type","doc":"","title":"dets.auto_save/0","ref":"dets.html#t:auto_save/0"},{"type":"opaque","doc":"Opaque continuation used by `match/1` and `match/3`.","title":"dets.bindings_cont/0","ref":"dets.html#t:bindings_cont/0"},{"type":"opaque","doc":"Opaque continuation used by `bchunk/2`.","title":"dets.cont/0","ref":"dets.html#t:cont/0"},{"type":"type","doc":"","title":"dets.keypos/0","ref":"dets.html#t:keypos/0"},{"type":"type","doc":"Match specifications, see section\n[Match Specification in Erlang](`e:erts:match_spec.md`) in ERTS User's Guide and\nthe `m:ms_transform` module.","title":"dets.match_spec/0","ref":"dets.html#t:match_spec/0"},{"type":"type","doc":"","title":"dets.no_slots/0","ref":"dets.html#t:no_slots/0"},{"type":"type","doc":"","title":"dets.object/0","ref":"dets.html#t:object/0"},{"type":"opaque","doc":"Opaque continuation used by `match_object/1` and `match_object/3`.","title":"dets.object_cont/0","ref":"dets.html#t:object_cont/0"},{"type":"type","doc":"For a description of patterns, see `ets:match/2`.","title":"dets.pattern/0","ref":"dets.html#t:pattern/0"},{"type":"opaque","doc":"Opaque continuation used by `select/1` and `select/3`.","title":"dets.select_cont/0","ref":"dets.html#t:select_cont/0"},{"type":"type","doc":"","title":"dets.tab_name/0","ref":"dets.html#t:tab_name/0"},{"type":"type","doc":"","title":"dets.type/0","ref":"dets.html#t:type/0"},{"type":"module","doc":"A Key-value dictionary.\n\nThe representation of a dictionary is not defined.\n\nThis module provides the same interface as the `m:orddict` module. One\ndifference is that while this module considers two keys as different if they do\nnot match (`=:=`), `orddict` considers two keys as different if and only if they\ndo not compare equal (`==`).","title":"dict","ref":"dict.html"},{"type":"module","doc":"[](){: #notes }\n\nFunctions `append` and `append_list` are included so that keyed values can be\nstored in a list _accumulator_, for example:\n\n```erlang\n> D0 = dict:new(),\n D1 = dict:store(files, [], D0),\n D2 = dict:append(files, f1, D1),\n D3 = dict:append(files, f2, D2),\n D4 = dict:append(files, f3, D3),\n dict:fetch(files, D4).\n[f1,f2,f3]\n```\n\nThis saves the trouble of first fetching a keyed value, appending a new value to\nthe list of stored values, and storing the result.\n\nFunction `fetch` is to be used if the key is known to be in the dictionary,\notherwise function `find`.","title":"Notes - dict","ref":"dict.html#module-notes"},{"type":"module","doc":"`m:gb_trees`, `m:orddict`","title":"See Also - dict","ref":"dict.html#module-see-also"},{"type":"function","doc":"Appends a new `Value` to the current list of values associated with `Key`.\n\nSee also section [Notes](`m:dict#module-notes`).","title":"dict.append/3","ref":"dict.html#append/3"},{"type":"function","doc":"Appends a list of values `ValList` to the current list of values associated with\n`Key`. An exception is generated if the initial value associated with `Key` is\nnot a list of values.\n\nSee also section [Notes](`m:dict#module-notes`).","title":"dict.append_list/3","ref":"dict.html#append_list/3"},{"type":"function","doc":"Erases all items with a given key from a dictionary.","title":"dict.erase/2","ref":"dict.html#erase/2"},{"type":"function","doc":"Returns the value associated with `Key` in dictionary `Dict`. This function\nassumes that `Key` is present in dictionary `Dict`, and an exception is\ngenerated if `Key` is not in the dictionary.\n\nSee also section [Notes](`m:dict#module-notes`).","title":"dict.fetch/2","ref":"dict.html#fetch/2"},{"type":"function","doc":"Returns a list of all keys in dictionary `Dict`.","title":"dict.fetch_keys/1","ref":"dict.html#fetch_keys/1"},{"type":"function","doc":"`Dict2` is a dictionary of all keys and values in `Dict1` for which\n`Pred(Key, Value)` is `true`.","title":"dict.filter/2","ref":"dict.html#filter/2"},{"type":"function","doc":"Searches for a key in dictionary `Dict`. Returns `{ok, Value}`, where `Value` is\nthe value associated with `Key`, or `error` if the key is not present in the\ndictionary.\n\nSee also section [Notes](`m:dict#module-notes`).","title":"dict.find/2","ref":"dict.html#find/2"},{"type":"function","doc":"Calls `Fun` on successive keys and values of dictionary `Dict` together with an\nextra argument `Acc` (short for accumulator). `Fun` must return a new\naccumulator that is passed to the next call. `Acc0` is returned if the\ndictionary is empty. The evaluation order is undefined.","title":"dict.fold/3","ref":"dict.html#fold/3"},{"type":"function","doc":"Converts the `Key`-`Value` list `List` to dictionary `Dict`.","title":"dict.from_list/1","ref":"dict.html#from_list/1"},{"type":"function","doc":"Returns `true` if dictionary `Dict` has no elements, otherwise `false`.","title":"dict.is_empty/1","ref":"dict.html#is_empty/1"},{"type":"function","doc":"Tests if `Key` is contained in dictionary `Dict`.","title":"dict.is_key/2","ref":"dict.html#is_key/2"},{"type":"function","doc":"Calls `Fun` on successive keys and values of dictionary `Dict1` to return a new\nvalue for each key. The evaluation order is undefined.","title":"dict.map/2","ref":"dict.html#map/2"},{"type":"function","doc":"Merges two dictionaries, `Dict1` and `Dict2`, to create a new dictionary. All\nthe `Key`-`Value` pairs from both dictionaries are included in the new\ndictionary. If a key occurs in both dictionaries, `Fun` is called with the key\nand both values to return a new value. `merge` can be defined as follows, but is\nfaster:\n\n```erlang\nmerge(Fun, D1, D2) ->\n fold(fun (K, V1, D) ->\n update(K, fun (V2) -> Fun(K, V1, V2) end, V1, D)\n end, D2, D1).\n```","title":"dict.merge/3","ref":"dict.html#merge/3"},{"type":"function","doc":"Creates a new dictionary.","title":"dict.new/0","ref":"dict.html#new/0"},{"type":"function","doc":"Returns the number of elements in dictionary `Dict`.","title":"dict.size/1","ref":"dict.html#size/1"},{"type":"function","doc":"Stores a `Key`-`Value` pair in dictionary `Dict2`. If `Key` already exists in\n`Dict1`, the associated value is replaced by `Value`.","title":"dict.store/3","ref":"dict.html#store/3"},{"type":"function","doc":"This function returns value from dictionary and a new dictionary without this\nvalue. Returns `error` if the key is not present in the dictionary.","title":"dict.take/2","ref":"dict.html#take/2"},{"type":"function","doc":"Converts dictionary `Dict` to a list representation.","title":"dict.to_list/1","ref":"dict.html#to_list/1"},{"type":"function","doc":"Updates a value in a dictionary by calling `Fun` on the value to get a new\nvalue. An exception is generated if `Key` is not present in the dictionary.","title":"dict.update/3","ref":"dict.html#update/3"},{"type":"function","doc":"Updates a value in a dictionary by calling `Fun` on the value to get a new\nvalue. If `Key` is not present in the dictionary, `Initial` is stored as the\nfirst value. For example, [`append/3`](`append/3`) can be defined as:\n\n```erlang\nappend(Key, Val, D) ->\n update(Key, fun (Old) -> Old ++ [Val] end, [Val], D).\n```","title":"dict.update/4","ref":"dict.html#update/4"},{"type":"function","doc":"Adds `Increment` to the value associated with `Key` and stores this value. If\n`Key` is not present in the dictionary, `Increment` is stored as the first\nvalue.\n\nThis can be defined as follows, but is faster:\n\n```erlang\nupdate_counter(Key, Incr, D) ->\n update(Key, fun (Old) -> Old + Incr end, Incr, D).\n```","title":"dict.update_counter/3","ref":"dict.html#update_counter/3"},{"type":"type","doc":"","title":"dict.dict/0","ref":"dict.html#t:dict/0"},{"type":"opaque","doc":"Dictionary as returned by `new/0`.","title":"dict.dict/2","ref":"dict.html#t:dict/2"},{"type":"module","doc":"This module provides a version of labeled directed graphs (\"digraphs\").\n\nThe digraphs managed by this module are stored in [ETS tables](`m:ets`). That\nimplies the following:\n\n- Only the process that created the digraph is allowed to update it.\n- Digraphs will not be garbage collected. The ETS tables used for a digraph will\n only be deleted when `delete/1` is called or the process that created the\n digraph terminates.\n- A digraph is a mutable data structure.\n\nWhat makes the graphs provided here non-proper directed graphs is that multiple\nedges between vertices are allowed. However, the customary definition of\ndirected graphs is used here.\n\n- A _directed graph_{: #digraph } (or just \"digraph\") is a pair (V, E) of a\n finite set V of _vertices_{: #vertex } and a finite set E of _directed\n edges_{: #edge } (or just \"edges\"). The set of edges E is a subset of V × V\n (the Cartesian product of V with itself).\n\n In this module, V is allowed to be empty. The so obtained unique digraph is\n called the _empty digraph_{: #empty_digraph }. Both vertices and edges are\n represented by unique Erlang terms.\n\n- Digraphs can be annotated with more information. Such information can be\n attached to the vertices and to the edges of the digraph. An annotated digraph\n is called a _labeled digraph_, and the information attached to a vertex or an\n edge is called a _label_{: #label }. Labels are Erlang terms.\n- An edge e = (v, w) is said to _emanate_{: #emanate } from vertex v and to be\n _incident_{: #incident } on vertex w.\n- The _out-degree_{: #out_degree } of a vertex is the number of edges emanating\n from that vertex.\n- The _in-degree_{: #in_degree } of a vertex is the number of edges incident on\n that vertex.\n- If an edge is emanating from v and incident on w, then w is said to be an\n _out-neighbor_{: #out_neighbour } of v, and v is said to be an _in-neighbor_{:\n #in_neighbour } of w.\n- A _path_{: #path } P from v\\[1] to v\\[k] in a digraph (V, E) is a non-empty\n sequence v\\[1], v\\[2], ..., v\\[k] of vertices in V such that there is an edge\n (v\\[i],v\\[i+1]) in E for 1 <= i < k.\n- The _length_{: #length } of path P is k-1.\n- Path P is _simple_{: #simple_path } if all vertices are distinct, except that\n the first and the last vertices can be the same.\n- Path P is a _cycle_{: #cycle } if the length of P is not zero and v\\[1] =\n v\\[k].\n- A _loop_{: #loop } is a cycle of length one.\n- A _simple cycle_{: #simple_cycle } is a path that is both a cycle and simple.\n- An _acyclic digraph_{: #acyclic_digraph } is a digraph without cycles.","title":"digraph","ref":"digraph.html"},{"type":"module","doc":"`m:digraph_utils`, `m:ets`","title":"See Also - digraph","ref":"digraph.html#module-see-also"},{"type":"function","doc":"","title":"digraph.add_edge/3","ref":"digraph.html#add_edge/3"},{"type":"function","doc":"Equivalent to [`add_edge(G, E, V1, V2, Label)`](`add_edge/5`), where `E` is a created edge.\n\nThe created edge is represented by term `['$e' | N]`, where `N` is an integer >= 0.\n\nSee `t:add_edge_err_rsn/0` for details on possible errors.","title":"digraph.add_edge/4","ref":"digraph.html#add_edge/4"},{"type":"function","doc":"Creates (or modifies) an edge with the identifier\n`E` of digraph `G`, using `Label` as the (new) [label](`m:digraph#label`) of the\nedge. The edge is [emanating](`m:digraph#emanate`) from `V1` and\n[incident](`m:digraph#incident`) on `V2`. Returns `E`.\n\nSee `t:add_edge_err_rsn/0` for details on possible errors.","title":"digraph.add_edge/5","ref":"digraph.html#add_edge/5"},{"type":"function","doc":"Creates a vertex using the empty list as label, and returns the created vertex.\n\nThe created vertex is represented by term `['$v' | N]`, where `N` is an integer >= 0.","title":"digraph.add_vertex/1","ref":"digraph.html#add_vertex/1"},{"type":"function","doc":"","title":"digraph.add_vertex/2","ref":"digraph.html#add_vertex/2"},{"type":"function","doc":"Creates (or modifies) vertex `V` of digraph `G`, using `Label` as the (new)\n[label](`m:digraph#label`) of the vertex. Returns the new vertex `V`.","title":"digraph.add_vertex/3","ref":"digraph.html#add_vertex/3"},{"type":"function","doc":"Deletes edge `E` from digraph `G`.","title":"digraph.del_edge/2","ref":"digraph.html#del_edge/2"},{"type":"function","doc":"Deletes the edges in list `Edges` from digraph `G`.","title":"digraph.del_edges/2","ref":"digraph.html#del_edges/2"},{"type":"function","doc":"Deletes edges from digraph `G` until there are no [paths](`m:digraph#path`) from\nvertex `V1` to vertex `V2`.\n\nA sketch of the procedure employed:\n\n- Find an arbitrary [simple path](`m:digraph#simple_path`)\n v\\[1], v\\[2], ..., v\\[k] from `V1` to `V2` in `G`.\n- Remove all edges of `G` [emanating](`m:digraph#emanate`) from v\\[i] and\n [incident](`m:digraph#incident`) to v\\[i+1] for 1 <= i < k (including multiple\n edges).\n- Repeat until there is no path between `V1` and `V2`.","title":"digraph.del_path/3","ref":"digraph.html#del_path/3"},{"type":"function","doc":"Deletes vertex `V` from digraph `G`. Any edges [emanating](`m:digraph#emanate`)\nfrom `V` or [incident](`m:digraph#incident`) on `V` are also deleted.","title":"digraph.del_vertex/2","ref":"digraph.html#del_vertex/2"},{"type":"function","doc":"Deletes the vertices in list `Vertices` from digraph `G`.","title":"digraph.del_vertices/2","ref":"digraph.html#del_vertices/2"},{"type":"function","doc":"Deletes digraph `G`. This call is important as digraphs are implemented with\nETS. There is no garbage collection of ETS tables. However, the digraph is\ndeleted if the process that created the digraph terminates.","title":"digraph.delete/1","ref":"digraph.html#delete/1"},{"type":"function","doc":"Returns `{E, V1, V2, Label}`, where `Label` is the [label](`m:digraph#label`) of\nedge `E` [emanating](`m:digraph#emanate`) from `V1` and\n[incident](`m:digraph#incident`) on `V2` of digraph `G`. If no edge `E` of\ndigraph `G` exists, `false` is returned.","title":"digraph.edge/2","ref":"digraph.html#edge/2"},{"type":"function","doc":"Returns a list of all edges of digraph `G`, in some unspecified order.","title":"digraph.edges/1","ref":"digraph.html#edges/1"},{"type":"function","doc":"Returns a list of all edges [emanating](`m:digraph#emanate`) from or\n[incident](`m:digraph#incident`) on `V` of digraph `G`, in some unspecified\norder.","title":"digraph.edges/2","ref":"digraph.html#edges/2"},{"type":"function","doc":"If a [simple cycle](`m:digraph#simple_cycle`) of length two or more exists\nthrough vertex `V`, the cycle is returned as a list `[V, ..., V]` of vertices.\nIf a [loop](`m:digraph#loop`) through `V` exists, the loop is returned as a list\n`[V]`. If no cycles through `V` exist, `false` is returned.\n\n`get_path/3` is used for finding a simple cycle through `V`.","title":"digraph.get_cycle/2","ref":"digraph.html#get_cycle/2"},{"type":"function","doc":"Tries to find a [simple path](`m:digraph#simple_path`) from vertex `V1` to\nvertex `V2` of digraph `G`. Returns the path as a list `[V1, ..., V2]` of\nvertices, or `false` if no simple path from `V1` to `V2` of length one or more\nexists.\n\nDigraph `G` is traversed in a depth-first manner, and the first found path is\nreturned.","title":"digraph.get_path/3","ref":"digraph.html#get_path/3"},{"type":"function","doc":"Tries to find an as short as possible [simple cycle](`m:digraph#simple_cycle`)\nthrough vertex `V` of digraph `G`. Returns the cycle as a list `[V, ..., V]` of\nvertices, or `false` if no simple cycle through `V` exists. Notice that a\n[loop](`m:digraph#loop`) through `V` is returned as list `[V, V]`.\n\n`get_short_path/3` is used for finding a simple cycle through `V`.","title":"digraph.get_short_cycle/2","ref":"digraph.html#get_short_cycle/2"},{"type":"function","doc":"Tries to find an as short as possible [simple path](`m:digraph#simple_path`)\nfrom vertex `V1` to vertex `V2` of digraph `G`. Returns the path as a list\n`[V1, ..., V2]` of vertices, or `false` if no simple path from `V1` to `V2` of\nlength one or more exists.\n\nDigraph `G` is traversed in a breadth-first manner, and the first found path is\nreturned.","title":"digraph.get_short_path/3","ref":"digraph.html#get_short_path/3"},{"type":"function","doc":"Returns the [in-degree](`m:digraph#in_degree`) of vertex `V` of digraph `G`.","title":"digraph.in_degree/2","ref":"digraph.html#in_degree/2"},{"type":"function","doc":"Returns a list of all edges [incident](`m:digraph#incident`) on `V` of digraph\n`G`, in some unspecified order.","title":"digraph.in_edges/2","ref":"digraph.html#in_edges/2"},{"type":"function","doc":"Returns a list of all [in-neighbors](`m:digraph#in_neighbour`) of `V` of digraph\n`G`, in some unspecified order.","title":"digraph.in_neighbours/2","ref":"digraph.html#in_neighbours/2"},{"type":"function","doc":"Returns a list of `{Tag, Value}` pairs describing digraph `G`. The following\npairs are returned:\n\n- `{cyclicity, Cyclicity}`, where `Cyclicity` is `cyclic` or `acyclic`,\n according to the options given to `new`.\n- `{memory, NoWords}`, where `NoWords` is the number of words allocated to the\n ETS tables.\n- `{protection, Protection}`, where `Protection` is `protected` or `private`,\n according to the options given to `new`.","title":"digraph.info/1","ref":"digraph.html#info/1"},{"type":"function","doc":"","title":"digraph.new/0","ref":"digraph.html#new/0"},{"type":"function","doc":"Returns an [empty digraph](`m:digraph#empty_digraph`) with properties according\nto the options in `Type`:\n\n- **`cyclic`** - Allows [cycles](`m:digraph#cycle`) in the digraph (default).\n\n- **`acyclic`** - The digraph is to be kept\n [acyclic](`m:digraph#acyclic_digraph`).\n\n- **`protected`** - Other processes can read the digraph (default).\n\n- **`private`** - The digraph can be read and modified by the creating process\n only.\n\nIf an unrecognized type option `T` is specified or `Type` is not a proper list,\na `badarg` exception is raised.","title":"digraph.new/1","ref":"digraph.html#new/1"},{"type":"function","doc":"Returns the number of edges of digraph `G`.","title":"digraph.no_edges/1","ref":"digraph.html#no_edges/1"},{"type":"function","doc":"Returns the number of vertices of digraph `G`.","title":"digraph.no_vertices/1","ref":"digraph.html#no_vertices/1"},{"type":"function","doc":"Returns the [out-degree](`m:digraph#out_degree`) of vertex `V` of digraph `G`.","title":"digraph.out_degree/2","ref":"digraph.html#out_degree/2"},{"type":"function","doc":"Returns a list of all edges [emanating](`m:digraph#emanate`) from `V` of digraph\n`G`, in some unspecified order.","title":"digraph.out_edges/2","ref":"digraph.html#out_edges/2"},{"type":"function","doc":"Returns a list of all [out-neighbors](`m:digraph#out_neighbour`) of `V` of\ndigraph `G`, in some unspecified order.","title":"digraph.out_neighbours/2","ref":"digraph.html#out_neighbours/2"},{"type":"function","doc":"Returns `{V, Label}`, where `Label` is the [label](`m:digraph#label`) of the\nvertex `V` of digraph `G`, or `false` if no vertex `V` of digraph `G` exists.","title":"digraph.vertex/2","ref":"digraph.html#vertex/2"},{"type":"function","doc":"Returns a list of all vertices of digraph `G`, in some unspecified order.","title":"digraph.vertices/1","ref":"digraph.html#vertices/1"},{"type":"type","doc":"The error reason for when an edge could not be added to a graph.\n\nIf the edge would create a cycle in an\n[acyclic digraph](`m:digraph#acyclic_digraph`), `{error, {bad_edge, Path}}` is\nreturned. If `G` already has an edge with value `E` connecting a different pair\nof vertices, `{error, {bad_edge, [V1, V2]}}` is returned. If either of `V1` or\n`V2` is not a vertex of digraph `G`, `{error, {bad_vertex, `V`}}` is returned,\nV = `V1` or V = `V2`.","title":"digraph.add_edge_err_rsn/0","ref":"digraph.html#t:add_edge_err_rsn/0"},{"type":"type","doc":"","title":"digraph.d_cyclicity/0","ref":"digraph.html#t:d_cyclicity/0"},{"type":"type","doc":"","title":"digraph.d_protection/0","ref":"digraph.html#t:d_protection/0"},{"type":"type","doc":"","title":"digraph.d_type/0","ref":"digraph.html#t:d_type/0"},{"type":"type","doc":"Serves as the identifier or \"name\" of an edge. This is distinct from an edge\n\"label\" which attaches ancillary information to the edge rather than identifying\nthe edge itself.","title":"digraph.edge/0","ref":"digraph.html#t:edge/0"},{"type":"opaque","doc":"A digraph as returned by [`new/0,1`](`new/0`).","title":"digraph.graph/0","ref":"digraph.html#t:graph/0"},{"type":"type","doc":"","title":"digraph.label/0","ref":"digraph.html#t:label/0"},{"type":"type","doc":"","title":"digraph.vertex/0","ref":"digraph.html#t:vertex/0"},{"type":"module","doc":"This module provides algorithms based on depth-first traversal of directed\ngraphs.\n\nFor basic functions on directed graphs, see the `m:digraph` module.\n\n- A _directed graph_{: #digraph } (or just \"digraph\") is a pair (V, E) of a\n finite set V of _vertices_{: #vertex } and a finite set E of _directed\n edges_{: #edge } (or just \"edges\"). The set of edges E is a subset of V × V\n (the Cartesian product of V with itself).\n- Digraphs can be annotated with more information. Such information can be\n attached to the vertices and to the edges of the digraph. An annotated digraph\n is called a _labeled digraph_, and the information attached to a vertex or an\n edge is called a _label_{: #label }.\n- An edge e = (v, w) is said to _emanate_{: #emanate } from vertex v and to be\n _incident_{: #incident } on vertex w.\n- If an edge is emanating from v and incident on w, then w is said to be an\n _out-neighbor_{: #out_neighbour } of v, and v is said to be an _in-neighbor_{:\n #in_neighbour } of w.\n- A _path_{: #path } P from v\\[1] to v\\[k] in a digraph (V, E) is a non-empty\n sequence v\\[1], v\\[2], ..., v\\[k] of vertices in V such that there is an edge\n (v\\[i],v\\[i+1]) in E for 1 <= i < k.\n- The _length_{: #length } of path P is k-1.\n- Path P is a _cycle_{: #cycle } if the length of P is not zero and v\\[1] =\n v\\[k].\n- A _loop_{: #loop } is a cycle of length one.\n- An _acyclic digraph_{: #acyclic_digraph } is a digraph without cycles.\n- A _depth-first traversal_{: #depth_first_traversal } of a directed digraph can\n be viewed as a process that visits all vertices of the digraph. Initially, all\n vertices are marked as unvisited. The traversal starts with an arbitrarily\n chosen vertex, which is marked as visited, and follows an edge to an unmarked\n vertex, marking that vertex. The search then proceeds from that vertex in the\n same fashion, until there is no edge leading to an unvisited vertex. At that\n point the process backtracks, and the traversal continues as long as there are\n unexamined edges. If unvisited vertices remain when all edges from the first\n vertex have been examined, some so far unvisited vertex is chosen, and the\n process is repeated.\n- A _partial ordering_{: #partial_ordering } of a set S is a transitive,\n antisymmetric, and reflexive relation between the objects of S.\n- The problem of _topological sorting_{: #topsort } is to find a total ordering\n of S that is a superset of the partial ordering. A digraph G = (V, E) is\n equivalent to a relation E on V (we neglect that the version of directed\n graphs provided by the `digraph` module allows multiple edges between\n vertices). If the digraph has no cycles of length two or more, the reflexive\n and transitive closure of E is a partial ordering.\n- A _subgraph_{: #subgraph } G' of G is a digraph whose vertices and edges form\n subsets of the vertices and edges of G.\n- G' is _maximal_ with respect to a property P if all other subgraphs that\n include the vertices of G' do not have property P.\n- A _strongly connected component_{: #strong_components } is a maximal subgraph\n such that there is a path between each pair of vertices.\n- A _connected component_{: #components } is a maximal subgraph such that there\n is a path between each pair of vertices, considering all edges undirected.\n- An _arborescence_{: #arborescence } is an acyclic digraph with a vertex V, the\n _root_{: #root }, such that there is a unique path from V to every other\n vertex of G.\n- A _tree_{: #tree } is an acyclic non-empty digraph such that there is a unique\n path between every pair of vertices, considering all edges undirected.","title":"digraph_utils","ref":"digraph_utils.html"},{"type":"module","doc":"`m:digraph`","title":"See Also - digraph_utils","ref":"digraph_utils.html#module-see-also"},{"type":"function","doc":"Returns `{yes, Root}` if `Root` is the [root](`m:digraph_utils#root`) of the\narborescence `Digraph`, otherwise `no`.","title":"digraph_utils.arborescence_root/1","ref":"digraph_utils.html#arborescence_root/1"},{"type":"function","doc":"Returns a list of [connected components](`m:digraph_utils#components`). Each\ncomponent is represented by its vertices. The order of the vertices and the\norder of the components are arbitrary. Each vertex of digraph `Digraph` occurs\nin exactly one component.","title":"digraph_utils.components/1","ref":"digraph_utils.html#components/1"},{"type":"function","doc":"Creates a digraph where the vertices are the\n[strongly connected components](`m:digraph_utils#strong_components`) of\n`Digraph` as returned by `strong_components/1`. If X and Y are two different\nstrongly connected components, and vertices x and y exist in X and Y,\nrespectively, such that there is an edge [emanating](`m:digraph_utils#emanate`)\nfrom x and [incident](`m:digraph_utils#incident`) on y, then an edge emanating\nfrom X and incident on Y is created.\n\nThe created digraph has the same type as `Digraph`. All vertices and edges have\nthe default [label](`m:digraph_utils#label`) `[]`.\n\nEach [cycle](`m:digraph_utils#cycle`) is included in some strongly connected\ncomponent, which implies that a\n[topological ordering](`m:digraph_utils#topsort`) of the created digraph always\nexists.","title":"digraph_utils.condensation/1","ref":"digraph_utils.html#condensation/1"},{"type":"function","doc":"Returns a list of\n[strongly connected components](`m:digraph_utils#strong_components`). Each\nstrongly component is represented by its vertices. The order of the vertices and\nthe order of the components are arbitrary. Only vertices that are included in\nsome [cycle](`m:digraph_utils#cycle`) in `Digraph` are returned, otherwise the\nreturned list is equal to that returned by `strong_components/1`.","title":"digraph_utils.cyclic_strong_components/1","ref":"digraph_utils.html#cyclic_strong_components/1"},{"type":"function","doc":"Returns `true` if and only if digraph `Digraph` is\n[acyclic](`m:digraph_utils#acyclic_digraph`).","title":"digraph_utils.is_acyclic/1","ref":"digraph_utils.html#is_acyclic/1"},{"type":"function","doc":"Returns `true` if and only if digraph `Digraph` is an\n[arborescence](`m:digraph_utils#arborescence`).","title":"digraph_utils.is_arborescence/1","ref":"digraph_utils.html#is_arborescence/1"},{"type":"function","doc":"Returns `true` if and only if digraph `Digraph` is a\n[tree](`m:digraph_utils#tree`).","title":"digraph_utils.is_tree/1","ref":"digraph_utils.html#is_tree/1"},{"type":"function","doc":"Returns a list of all vertices of `Digraph` that are included in some\n[loop](`m:digraph_utils#loop`).","title":"digraph_utils.loop_vertices/1","ref":"digraph_utils.html#loop_vertices/1"},{"type":"function","doc":"Returns all vertices of digraph `Digraph`. The order is given by a\n[depth-first traversal](`m:digraph_utils#depth_first_traversal`) of the digraph,\ncollecting visited vertices in postorder. More precisely, the vertices visited\nwhile searching from an arbitrarily chosen vertex are collected in postorder,\nand all those collected vertices are placed before the subsequently visited\nvertices.","title":"digraph_utils.postorder/1","ref":"digraph_utils.html#postorder/1"},{"type":"function","doc":"Returns all vertices of digraph `Digraph`. The order is given by a\n[depth-first traversal](`m:digraph_utils#depth_first_traversal`) of the digraph,\ncollecting visited vertices in preorder.","title":"digraph_utils.preorder/1","ref":"digraph_utils.html#preorder/1"},{"type":"function","doc":"Returns an unsorted list of digraph vertices such that for each vertex in the\nlist, there is a [path](`m:digraph_utils#path`) in `Digraph` from some vertex of\n`Vertices` to the vertex. In particular, as paths can have length zero, the\nvertices of `Vertices` are included in the returned list.","title":"digraph_utils.reachable/2","ref":"digraph_utils.html#reachable/2"},{"type":"function","doc":"Returns an unsorted list of digraph vertices such that for each vertex in the\nlist, there is a [path](`m:digraph_utils#path`) in `Digraph` of length one or\nmore from some vertex of `Vertices` to the vertex. As a consequence, only those\nvertices of `Vertices` that are included in some\n[cycle](`m:digraph_utils#cycle`) are returned.","title":"digraph_utils.reachable_neighbours/2","ref":"digraph_utils.html#reachable_neighbours/2"},{"type":"function","doc":"Returns an unsorted list of digraph vertices such that for each vertex in the\nlist, there is a [path](`m:digraph_utils#path`) from the vertex to some vertex\nof `Vertices`. In particular, as paths can have length zero, the vertices of\n`Vertices` are included in the returned list.","title":"digraph_utils.reaching/2","ref":"digraph_utils.html#reaching/2"},{"type":"function","doc":"Returns an unsorted list of digraph vertices such that for each vertex in the\nlist, there is a [path](`m:digraph_utils#path`) of length one or more from the\nvertex to some vertex of `Vertices`. Therefore only those vertices of `Vertices`\nthat are included in some [cycle](`m:digraph_utils#cycle`) are returned.","title":"digraph_utils.reaching_neighbours/2","ref":"digraph_utils.html#reaching_neighbours/2"},{"type":"function","doc":"Returns a list of\n[strongly connected components](`m:digraph_utils#strong_components`). Each\nstrongly component is represented by its vertices. The order of the vertices and\nthe order of the components are arbitrary. Each vertex of digraph `Digraph`\noccurs in exactly one strong component.","title":"digraph_utils.strong_components/1","ref":"digraph_utils.html#strong_components/1"},{"type":"function","doc":"","title":"digraph_utils.subgraph/2","ref":"digraph_utils.html#subgraph/2"},{"type":"function","doc":"Creates a maximal [subgraph](`m:digraph_utils#subgraph`) of `Digraph` having as\nvertices those vertices of `Digraph` that are mentioned in `Vertices`.\n\nIf the value of option `type` is `inherit`, which is the default, the type of\n`Digraph` is used for the subgraph as well. Otherwise the option value of `type`\nis used as argument to `digraph:new/1`.\n\nIf the value of option `keep_labels` is `true`, which is the default, the\n[labels](`m:digraph_utils#label`) of vertices and edges of `Digraph` are used\nfor the subgraph as well. If the value is `false`, default label `[]` is used\nfor the vertices and edges of the subgroup.\n\n[`subgraph(Digraph, Vertices)`](`subgraph/2`) is equivalent to\n[`subgraph(Digraph, Vertices, [])`](`subgraph/3`).\n\nIf any of the arguments are invalid, a `badarg` exception is raised.","title":"digraph_utils.subgraph/3","ref":"digraph_utils.html#subgraph/3"},{"type":"function","doc":"Returns a [topological ordering](`m:digraph_utils#topsort`) of the vertices of\ndigraph `Digraph` if such an ordering exists, otherwise `false`. For each vertex\nin the returned list, no [out-neighbors](`m:digraph_utils#out_neighbour`) occur\nearlier in the list.","title":"digraph_utils.topsort/1","ref":"digraph_utils.html#topsort/1"},{"type":"module","doc":"Built-in term storage.\n\nThis module is an interface to the Erlang built-in term storage BIFs. These\nprovide the ability to store very large quantities of data in an Erlang runtime\nsystem, and to have constant access time to the data. (In the case of\n`ordered_set`, see below, access time is proportional to the logarithm of the\nnumber of stored objects.)\n\nData is organized as a set of dynamic tables, which can store tuples. Each table\nis created by a process. When the process terminates, the table is automatically\ndestroyed. Every table has access rights set at creation.\n\nTables are divided into four different types, `set`, `ordered_set`, `bag`, and\n`duplicate_bag`. A `set` or `ordered_set` table can only have one object\nassociated with each key. A `bag` or `duplicate_bag` table can have many objects\nassociated with each key.\n\nInsert and lookup times in tables of type `set` are constant, regardless of the\ntable size. For table types `bag` and `duplicate_bag` time is proportional to\nthe number of objects with the same key. Even seemingly unrelated keys may\ninflict linear search to be skipped past while looking for the key of interest\n(due to hash collision).\n\n> #### Warning {: .warning }\n>\n> For tables of type `bag` and `duplicate_bag`, avoid inserting an extensive\n> amount of objects with the same key. It will hurt insert and lookup\n> performance as well as real time characteristics of the runtime environment\n> (hash bucket linear search do not yield).\n\nThe `ordered_set` table type uses a binary search tree. Insert and lookup times\nare proportional to the logarithm of the number of objects in the table.\n\n[](){: #max_ets_tables }\n\n> #### Note {: .info }\n>\n> The number of tables stored at one Erlang node _used_ to be limited. This is\n> no longer the case (except by memory usage). The previous default limit was\n> about 1400 tables and could be increased by setting the environment variable\n> `ERL_MAX_ETS_TABLES` or the command line option\n> [`+e`](`e:erts:erl_cmd.md#%2Be`) before starting the Erlang runtime system.\n> This hard limit has been removed, but it is currently useful to set the\n> `ERL_MAX_ETS_TABLES` anyway. It should be set to an approximate of the maximum\n> amount of tables used since an internal table for named tables is sized using\n> this value. If large amounts of named tables are used and `ERL_MAX_ETS_TABLES`\n> hasn't been increased, the performance of named table lookup will degrade.\n\nNotice that there is no automatic garbage collection for tables. Even if there\nare no references to a table from any process, it is not automatically destroyed\nunless the owner process terminates. To destroy a table explicitly, use function\n`delete/1`. The default owner is the process that created the table. To transfer\ntable ownership at process termination, use option [`heir`](`m:ets#heir`) or\ncall `give_away/3`.\n\nSome implementation details:\n\n- In the current implementation, every object insert and look-up operation\n results in a copy of the object.\n- `'$end_of_table'` is not to be used as a key, as this atom is used to mark the\n end of the table when using functions `first/1` and `next/2`.\n\nNotice the subtle difference between _matching_ and _comparing equal_, which is\ndemonstrated by table types `set` and `ordered_set`:\n\n- Two Erlang terms `match` if they are of the same type and have the same value,\n so that `1` matches `1`, but not `1.0` (as `1.0` is a `t:float/0` and not an\n `t:integer/0`).\n- Two Erlang terms _compare equal_ if they either are of the same type and\n value, or if both are numeric types and extend to the same value, so that `1`\n compares equal to both `1` and `1.0`.\n- The `ordered_set` works on the _Erlang term order_ and no defined order exists\n between an `t:integer/0` and a `t:float/0` that extends to the same value.\n Hence the key `1` and the key `1.0` are regarded as equal in an `ordered_set`\n table.\n\n[](){: #ets_failures }","title":"ets","ref":"ets.html"},{"type":"module","doc":"Functions in this module fail by raising an error exception with error reason:\n\n- **`badarg`** - If any argument has the wrong format.\n\n- **`badarg`** - If the table identifier is invalid.\n\n- **`badarg`** - If the operation is denied because of table access rights\n ([protected](`m:ets#protected`) or [private](`m:ets#private`)).\n\n- **`system_limit`** - Modification of a value causes it to not be representable\n internally in the VM. For example, incrementation of a counter past the\n largest integer representable.\n\n- **`system_limit`** - If a match specification passed as argument has excessive\n nesting which causes scheduler stack exhaustion for the scheduler that the\n calling process is executing on.\n [Scheduler stack size](`e:erts:erl_cmd.md#sched_thread_stack_size`) can be\n configured when starting the runtime system.\n\n[](){: #concurrency }","title":"Failures - ets","ref":"ets.html#module-failures"},{"type":"module","doc":"This module provides some limited support for concurrent access. All updates to\nsingle objects are guaranteed to be both _atomic_ and _isolated_. This means\nthat an updating operation to a single object either succeeds or fails\ncompletely without any effect (atomicity) and that no intermediate results of\nthe update can be seen by other processes (isolation). Some functions that\nupdate many objects state that they even guarantee atomicity and isolation for\nthe entire operation. In database terms the isolation level can be seen as\n\"serializable\", as if all isolated operations are carried out serially, one\nafter the other in a strict order.\n\n[](){: #traversal }","title":"Concurrency - ets","ref":"ets.html#module-concurrency"},{"type":"module","doc":"There are different ways to traverse through the objects of a table.\n\n- _Single-step_ traversal one key at at time, using `first/1`, `next/2`,\n `last/1` and `prev/2`.\n- _Single-step_ traversal one key at at time, but using `first_lookup/1`,\n `next_lookup/2`, `last_lookup/1` and `prev_lookup/2`. This is more efficient\n when you also need to lookup the objects for the keys.\n- Search with simple _match patterns_, using [`match/1/2/3`](`match/1`),\n `match_delete/2` and [`match_object/1/2/3`](`match_object/1`).\n- Search with more powerful _match specifications_, using\n [`select/1/2/3`](`select/1`), `select_count/2`, `select_delete/2`,\n `select_replace/2` and [`select_reverse/1/2/3`](`select_reverse/1`).\n- _Table conversions_, using [`tab2file/2/3`](`tab2file/2`) and `tab2list/1`.\n\nNo table traversal will guarantee a consistent snapshot of the entire table if\nthe table is also updated by concurrent processes during the traversal. The\nresult of each concurrently updated object may be seen (or not) depending on if\nit has happened when the traversal visits that part of the table. The only way\nto guarantee a full consistent table snapshot (if you really need that) is to\ndisallow concurrent updates during the entire traversal.\n\nMoreover, traversals not done in a _safe_ way, on tables where keys are inserted\nor deleted during the traversal, may yield the following undesired effects:\n\n- Any key may be missed.\n- Any key may be found more than once.\n- The traversal may fail with `badarg` exception if keys are deleted.\n\nA table traversal is _safe_ if either\n\n- the table is of type `ordered_set`.\n- the entire table traversal is done within one ETS function call.\n- function `safe_fixtable/2` is used to keep the table fixated during the entire\n traversal.\n\n> #### Note {: .info }\n>\n> Even though the access of a single object is always guaranteed to be\n> [atomic and isolated](`m:ets#module-concurrency`), each traversal through a table to\n> find the next key is not done with such guarantees. This is often not a\n> problem, but may cause rare subtle \"unexpected\" effects if a concurrent\n> process inserts objects during a traversal. For example, consider one process\n> doing\n>\n> ```erlang\n> ets:new(t, [ordered_set, named_table]),\n> ets:insert(t, {1}),\n> ets:insert(t, {2}),\n> ets:insert(t, {3}),\n> ```\n>\n> A concurrent call to `ets:first(t)`, done by another process, may then in rare\n> cases return `2` even though `2` has never existed in the table ordered as the\n> first key. In the same way, a concurrent call to `ets:next(t, 1)` may return\n> `3` even though `3` never existed in the table ordered directly after `1`.\n>\n> Effects like this are improbable but possible. The probability will further be\n> reduced (if not vanish) if table option\n> [`write_concurrency`](`m:ets#new_2_write_concurrency`) is not enabled. This\n> can also only be a potential concern for `ordered_set` where the traversal\n> order is defined.\n\nTraversals using `match` and `select` functions may not need to scan the entire\ntable depending on how the key is specified. A match pattern with a _fully bound\nkey_ (without any match variables) will optimize the operation to a single key\nlookup without any table traversal at all. For `ordered_set` a _partially bound\nkey_ will limit the traversal to only scan a subset of the table based on term\norder. A partially bound key is either a list or a tuple with a prefix that is\nfully bound. Example:\n\n```erlang\n1> T = ets:new(t,[ordered_set]), ets:insert(T, {\"555-1234\", \"John Smith\"}).\ntrue\n2> %% Efficient search of all with area code 555\n2> ets:match(T,{[$5,$5,$5,$- |'$1'],'$2'}).\n[[\"1234\",\"John Smith\"]]\n```\n\n[](){: #match_spec }","title":"Table traversal - ets","ref":"ets.html#module-table-traversal"},{"type":"module","doc":"Some of the functions use a _match specification_, `match_spec`. For a brief\nexplanation, see `select/2`. For a detailed description, see section\n[Match Specifications in Erlang](`e:erts:match_spec.md`) in ERTS User's Guide.\n\nA match specifications with excessive nesting will cause a\n[`system_limit`](`m:ets#ets_failures`) error exception to be raised.","title":"Match Specifications - ets","ref":"ets.html#module-match-specifications"},{"type":"function","doc":"Returns a list of all tables at the node. Named tables are specified by their\nnames, unnamed tables are specified by their table identifiers.\n\nThere is no guarantee of consistency in the returned list. Tables created or\ndeleted by other processes \"during\" the `ets:all()` call either are or are not\nincluded in the list. Only tables created/deleted _before_ `ets:all()` is called\nare guaranteed to be included/excluded.","title":"ets.all/0","ref":"ets.html#all/0"},{"type":"function","doc":"Deletes the entire table `Table`.","title":"ets.delete/1","ref":"ets.html#delete/1"},{"type":"function","doc":"Deletes all objects with key `Key` from table `Table`. This function succeeds\neven if no objects with key `Key` exist.","title":"ets.delete/2","ref":"ets.html#delete/2"},{"type":"function","doc":"Delete all objects in the ETS table `Table`. The operation is guaranteed to be\n[atomic and isolated](`m:ets#module-concurrency`).","title":"ets.delete_all_objects/1","ref":"ets.html#delete_all_objects/1"},{"type":"function","doc":"Delete the exact object `Object` from the ETS table, leaving objects with the\nsame key but other differences (useful for type `bag`). In a `duplicate_bag`\ntable, all instances of the object are deleted.","title":"ets.delete_object/2","ref":"ets.html#delete_object/2"},{"type":"function","doc":"Reads a file produced by `tab2file/2` or `tab2file/3` and creates the\ncorresponding table `Table`.\n\nEquivalent to [`file2tab(Filename, [])`](`file2tab/2`).","title":"ets.file2tab/1","ref":"ets.html#file2tab/1"},{"type":"function","doc":"Reads a file produced by `tab2file/2` or `tab2file/3` and creates the\ncorresponding table `Table`.\n\nThe only supported option is `{verify,boolean()}`. If verification is turned on\n(by specifying `{verify,true}`), the function uses whatever information is\npresent in the file to assert that the information is not damaged. How this is\ndone depends on which `extended_info` was written using `tab2file/3`.\n\nIf no `extended_info` is present in the file and `{verify,true}` is specified,\nthe number of objects written is compared to the size of the original table when\nthe dump was started. This can make verification fail if the table was `public`\nand objects were added or removed while the table was dumped to file. To avoid\nthis problem, either do not verify files dumped while updated simultaneously or\nuse option `{extended_info, [object_count]}` to `tab2file/3`, which extends the\ninformation in the file with the number of objects written.\n\nIf verification is turned on and the file was written with option\n`{extended_info, [md5sum]}`, reading the file is slower and consumes radically\nmore CPU time than otherwise.\n\n`{verify,false}` is the default.","title":"ets.file2tab/2","ref":"ets.html#file2tab/2"},{"type":"function","doc":"Returns the first key `Key` in table `Table`. For an `ordered_set` table, the\nfirst key in Erlang term order is returned. For other table types, the first key\naccording to the internal order of the table is returned. If the table is empty,\n`'$end_of_table'` is returned.\n\nTo find subsequent keys in the table, use `next/2`.","title":"ets.first/1","ref":"ets.html#first/1"},{"type":"function","doc":"Similar to `first/1` except that it returns the object(s) along with the key\nstored in the table. This is equivalent to doing `first/1` followed by a\n`lookup/2`. If the table is empty, `'$end_of_table'` is returned.\n\nTo find subsequent objects in the table, use `next_lookup/2`.","title":"ets.first_lookup/1","ref":"ets.html#first_lookup/1"},{"type":"function","doc":"`Acc0` is returned if the table is empty. This function is similar to\n`lists:foldl/3`. The table elements are traversed in an unspecified order,\nexcept for `ordered_set` tables, where they are traversed first to last.\n\nIf `Function` inserts objects into the table, or another process inserts objects\ninto the table, those objects _can_ (depending on key ordering) be included in\nthe traversal.","title":"ets.foldl/3","ref":"ets.html#foldl/3"},{"type":"function","doc":"`Acc0` is returned if the table is empty. This function is similar to\n`lists:foldr/3`. The table elements are traversed in an unspecified order,\nexcept for `ordered_set` tables, where they are traversed last to first.\n\nIf `Function` inserts objects into the table, or another process inserts objects\ninto the table, those objects _can_ (depending on key ordering) be included in\nthe traversal.","title":"ets.foldr/3","ref":"ets.html#foldr/3"},{"type":"function","doc":"Fills an already created ETS table with the objects in the already opened Dets\ntable `DetsTab`. Existing objects in the ETS table are kept unless overwritten.\n\nIf any of the tables does not exist or the Dets table is not open, a `badarg`\nexception is raised.","title":"ets.from_dets/2","ref":"ets.html#from_dets/2"},{"type":"function","doc":"Pseudo function that by a `parse_transform` translates `LiteralFun` typed as\nparameter in the function call to a [match specification](`m:ets#match_spec`).\nWith \"literal\" is meant that the fun must textually be written as the parameter\nof the function, it cannot be held in a variable that in turn is passed to the\nfunction.\n\nThe parse transform is provided in the `ms_transform` module and the source\n_must_ include file `ms_transform.hrl` in STDLIB for this pseudo function to\nwork. Failing to include the hrl file in the source results in a runtime error,\nnot a compile time error. The include file is easiest included by adding line\n`-include_lib(\"stdlib/include/ms_transform.hrl\").` to the source file.\n\nThe fun is very restricted, it can take only a single parameter (the object to\nmatch): a sole variable or a tuple. It must use the `is_` guard tests. Language\nconstructs that have no representation in a match specification (`if`, `case`,\n`receive`, and so on) are not allowed.\n\nThe return value is the resulting match specification.\n\n_Example:_\n\n```erlang\n1> ets:fun2ms(fun({M,N}) when N > 3 -> M end).\n[{{'$1','$2'},[{'>','$2',3}],['$1']}]\n```\n\nVariables from the environment can be imported, so that the following works:\n\n```erlang\n2> X=3.\n3\n3> ets:fun2ms(fun({M,N}) when N > X -> M end).\n[{{'$1','$2'},[{'>','$2',{const,3}}],['$1']}]\n```\n\nThe imported variables are replaced by match specification `const` expressions,\nwhich is consistent with the static scoping for Erlang funs. However, local or\nglobal function calls cannot be in the guard or body of the fun. Calls to\nbuilt-in match specification functions is of course allowed:\n\n```erlang\n4> ets:fun2ms(fun({M,N}) when N > X, my_fun(M) -> M end).\nError: fun containing local Erlang function calls\n('my_fun' called in guard) cannot be translated into match_spec\n{error,transform_error}\n5> ets:fun2ms(fun({M,N}) when N > X, is_atom(M) -> M end).\n[{{'$1','$2'},[{'>','$2',{const,3}},{is_atom,'$1'}],['$1']}]\n```\n\nAs shown by the example, the function can be called from the shell also. The fun\nmust be literally in the call when used from the shell as well.\n\n> #### Warning {: .warning }\n>\n> If the `parse_transform` is not applied to a module that calls this pseudo\n> function, the call fails in runtime (with a `badarg`). The `ets` module\n> exports a function with this name, but it is never to be called except when\n> using the function in the shell. If the `parse_transform` is properly applied\n> by including header file `ms_transform.hrl`, compiled code never calls the\n> function, but the function call is replaced by a literal match specification.\n\nFor more information, see [`ms_transform`](`m:ms_transform`).","title":"ets.fun2ms/1","ref":"ets.html#fun2ms/1"},{"type":"function","doc":"Make process `Pid` the new owner of table `Table`. If successful, message\n`{'ETS-TRANSFER',Table,FromPid,GiftData}` is sent to the new owner.\n\nThe process `Pid` must be alive, local, and not already the owner of the table.\nThe calling process must be the table owner.\n\nNotice that this function does not affect option [`heir`](`m:ets#heir`) of the\ntable. A table owner can, for example, set `heir` to itself, give the table\naway, and then get it back if the receiver terminates.","title":"ets.give_away/3","ref":"ets.html#give_away/3"},{"type":"function","doc":"Displays information about all ETS tables on a terminal.","title":"ets.i/0","ref":"ets.html#i/0"},{"type":"function","doc":"Browses table `Table` on a terminal.","title":"ets.i/1","ref":"ets.html#i/1"},{"type":"function","doc":"Returns information about table `Table` as a list of tuples. If `Table` has the\ncorrect type for a table identifier, but does not refer to an existing ETS\ntable, `undefined` is returned. If `Table` is not of the correct type, a\n`badarg` exception is raised.\n\n- **`{compressed, boolean()}`** - Indicates if the table is compressed.\n\n- **`{decentralized_counters, boolean()}`** - Indicates whether the table uses\n `decentralized_counters`.\n\n- **`{heir, pid() | none}`** - The pid of the heir of the table, or `none` if no\n heir is set.\n\n- **`{id,`[ `tid()`](`t:tid/0`)`}`** - The table identifier.\n\n- **`{keypos, integer() >= 1}`** - The key position.\n\n- **`{memory, integer() >= 0}`** - The number of words allocated to the table.\n\n- **`{name, atom()}`** - The table name.\n\n- **`{named_table, boolean()}`** - Indicates if the table is named.\n\n- **`{node, node()}`** - The node where the table is stored. This field is no\n longer meaningful, as tables cannot be accessed from other nodes.\n\n- **`{owner, pid()}`** - The pid of the owner of the table.\n\n- **`{protection,` [`access()`](`t:table_access/0`)`}`** - The table access\n rights.\n\n- **`{size, integer() >= 0}`** - The number of objects inserted in the table.\n\n- **`{type,` [`type()`](`t:table_type/0`)`}`** - The table type.\n\n- **`{read_concurrency, boolean()}`** - Indicates whether the table uses\n `read_concurrency` or not.\n\n- **`{write_concurrency, WriteConcurrencyAlternative}`** - Indicates which\n `write_concurrency` option the table uses.\n\n> #### Note {: .info }\n>\n> The execution time of this function is affected by the\n> [`decentralized_counters`](`m:ets#new_2_decentralized_counters`) table option.\n> The execution time is much longer when the `decentralized_counters` option is\n> set to `true` than when the `decentralized_counters` option is set to `false`.","title":"ets.info/1","ref":"ets.html#info/1"},{"type":"function","doc":"Returns the information associated with `Item` for table `Table`, or returns\n`undefined` if `Table` does not refer an existing ETS table. If `Table` is not\nof the correct type, or if `Item` is not one of the allowed values, a `badarg`\nexception is raised.\n\nIn addition to the `{Item,Value}` pairs defined for `info/1`, the following\nitems are allowed:\n\n- `Item=binary, Value=BinInfo`\n\n `BinInfo` is a list containing miscellaneous information about binaries kept\n by the table. This `Item` can be changed or removed without prior notice. In\n the current implementation `BinInfo` is a list of tuples\n `{BinaryId,BinarySize,BinaryRefcCount}`.\n\n- `Item=fixed, Value=boolean()`\n\n Indicates if the table is fixed by any process.\n\n- [](){: #info_2_safe_fixed_monotonic_time }\n\n `Item=safe_fixed|safe_fixed_monotonic_time, Value={FixationTime,Info}|false`\n\n If the table is fixed using `safe_fixtable/2`, the call returns a tuple where\n `FixationTime` is the last time when the table changed from unfixed to fixed.\n\n The format and value of `FixationTime` depends on `Item`:\n\n - **`safe_fixed`** - `FixationTime` corresponds to the result returned by\n `erlang:timestamp/0` at the time of fixation. Notice that when the system\n uses single or multi\n [time warp modes](`e:erts:time_correction.md#time-warp-modes`) this can\n produce strange results, as the use of `safe_fixed` is not\n [time warp safe](`e:erts:time_correction.md#time-warp-safe-code`). Time warp\n safe code must use `safe_fixed_monotonic_time` instead.\n\n - **`safe_fixed_monotonic_time`** - `FixationTime` corresponds to the result\n returned by `erlang:monotonic_time/0` at the time of fixation. The use of\n `safe_fixed_monotonic_time` is\n [time warp safe](`e:erts:time_correction.md#time-warp-safe-code`).\n\n `Info` is a possibly empty lists of tuples `{Pid,RefCount}`, one tuple for\n every process the table is fixed by now. `RefCount` is the value of the\n reference counter and it keeps track of how many times the table has been\n fixed by the process.\n\n Table fixations are not limited to `safe_fixtable/2`. Temporary fixations may\n also be done by for example [traversing functions](`m:ets#traversal`) like\n `select` and `match`. Such table fixations are automatically released before\n the corresponding functions returns, but they may be seen by a concurrent call\n to `ets:info(T,safe_fixed|safe_fixed_monotonic_time)`.\n\n If the table is not fixed at all, the call returns `false`.\n\n- `Item=stats, Value=tuple()`\n\n Returns internal statistics about tables on an internal format used by OTP\n test suites. Not for production use.\n\n> #### Note {: .info }\n>\n> The execution time of this function is affected by the\n> [`decentralized_counters`](`m:ets#new_2_decentralized_counters`) table option\n> when the second argument of the function is `size` or `memory`. The execution\n> time is much longer when the `decentralized_counters` option is set to `true`\n> than when the `decentralized_counters` option is set to `false`.","title":"ets.info/2","ref":"ets.html#info/2"},{"type":"function","doc":"Replaces the existing objects of table `Table` with objects created by calling\nthe input function `InitFun`, see below. This function is provided for\ncompatibility with the `dets` module, it is not more efficient than filling a\ntable by using `insert/2`.\n\nWhen called with argument `read`, the function `InitFun` is assumed to return\n`end_of_input` when there is no more input, or `{Objects, Fun}`, where `Objects`\nis a list of objects and `Fun` is a new input function. Any other value `Value`\nis returned as an error `{error, {init_fun, Value}}`. Each input function is\ncalled exactly once, and if an error occur, the last function is called with\nargument `close`, the reply of which is ignored.\n\nIf the table type is `set` and more than one object exists with a given key, one\nof the objects is chosen. This is not necessarily the last object with the given\nkey in the sequence of objects returned by the input functions. This holds also\nfor duplicated objects stored in tables of type `bag`.","title":"ets.init_table/2","ref":"ets.html#init_table/2"},{"type":"function","doc":"Inserts the object or all of the objects in list `ObjectOrObjects` into table\n`Table`.\n\n- If the table type is `set` and the key of the inserted objects _matches_ the\n key of any object in the table, the old object is replaced.\n- If the table type is `ordered_set` and the key of the inserted object\n _compares equal_ to the key of any object in the table, the old object is\n replaced.\n- If the table type is `bag` and the object _matches_ any whole object in the\n table, the object is not inserted.\n- If the list contains more than one object with _matching_ keys and the table\n type is `set`, one is inserted, which one is not defined. The same holds for\n table type `ordered_set` if the keys _compare equal_.\n\nThe entire operation is guaranteed to be\n[atomic and isolated](`m:ets#module-concurrency`), even when a list of objects is\ninserted.\n\n[](){: #insert_list_order }\n\nFor `bag` and `duplicate_bag`, objects in the list with identical keys will be\ninserted in list order (from head to tail). That is, a subsequent call to\n[`lookup(T,Key)`](`lookup/2`) will return them in that inserted order.\n\n> #### Note {: .info }\n>\n> For `bag` the insertion order of indentical keys described above was\n> accidentally reverted in OTP 23.0 and later fixed in OTP 25.3. That is, from\n> OTP 23.0 up until OTP 25.3 the objects in a list are inserted in reverse order\n> (from tail to head).\n>\n> For `duplicate_bag` the same faulty reverse insertion exist from OTP 23.0\n> until OTP 25.3. However, it is unpredictable and may or may not happen. A\n> longer list will increase the probabiliy of the insertion being done in\n> reverse.","title":"ets.insert/2","ref":"ets.html#insert/2"},{"type":"function","doc":"Same as `insert/2` except that instead of overwriting objects with the same key\n(for `set` or `ordered_set`) or adding more objects with keys already existing\nin the table (for `bag` and `duplicate_bag`), `false` is returned.\n\nIf `ObjectOrObjects` is a list, the function checks _every_ key before inserting\nanything. Nothing is inserted unless _all_ keys present in the list are absent\nfrom the table. Like [`insert/2`](`insert/2`), the entire operation is\nguaranteed to be [atomic and isolated](`m:ets#module-concurrency`).","title":"ets.insert_new/2","ref":"ets.html#insert_new/2"},{"type":"function","doc":"Checks if a term represent a valid compiled\n[match specification](`m:ets#match_spec`). A compiled match specification is\nonly valid on the Erlang node where it was compiled by calling\n`match_spec_compile/1`.\n\n> #### Note {: .info }\n>\n> Before STDLIB 3.4 (OTP 20.0) compiled match specifications did not have an\n> external representation. If passed through\n> [`binary_to_term(term_to_binary(CMS))`](`binary_to_term/1`) or sent to another\n> node and back, the result was always an empty binary `<<>>`.\n>\n> After STDLIB 3.4 (OTP 20.0) compiled match specifications have an external\n> representation as a node specific reference to the original compiled match\n> specification. If passed through\n> [`binary_to_term(term_to_binary(CMS))`](`binary_to_term/1`) or sent to another\n> node and back, the result _may or may not_ be a valid compiled match\n> specification depending on if the original compiled match specification was\n> still alive.","title":"ets.is_compiled_ms/1","ref":"ets.html#is_compiled_ms/1"},{"type":"function","doc":"Returns the last key `Key` according to Erlang term order in table `Table` of\ntype `ordered_set`. For other table types, the function is synonymous to\n`first/1`. If the table is empty, `'$end_of_table'` is returned.\n\nTo find preceding keys in the table, use `prev/2`.","title":"ets.last/1","ref":"ets.html#last/1"},{"type":"function","doc":"Similar to `last/1` except that it returns the object(s) along with the key\nstored in the table. This is equivalent to doing `last/1` followed by a\n`lookup/2`. If the table is empty, `'$end_of_table'` is returned.\n\nTo find preceding objects in the table, use `prev_lookup/2`.","title":"ets.last_lookup/1","ref":"ets.html#last_lookup/1"},{"type":"function","doc":"Returns a list of all objects with key `Key` in table `Table`.\n\n- For tables of type `set`, `bag`, or `duplicate_bag`, an object is returned\n only if the specified key _matches_ the key of the object in the table.\n- For tables of type `ordered_set`, an object is returned if the specified key\n _compares equal_ to the key of an object in the table.\n\nThe difference is the same as between `=:=` and `==`.\n\nAs an example, one can insert an object with `t:integer/0` `1` as a key in an\n`ordered_set` and get the object returned as a result of doing a\n[`lookup/2`](`lookup/2`) with `t:float/0` `1.0` as the key to search for.\n\nFor tables of type `set` or `ordered_set`, the function returns either the empty\nlist or a list with one element, as there cannot be more than one object with\nthe same key. For tables of type `bag` or `duplicate_bag`, the function returns\na list of arbitrary length.\n\nNotice that the sequential order of object insertions is preserved; the first\nobject inserted with the specified key is the first in the resulting list, and\nso on. See also the note about\n[list insertion order](`m:ets#insert_list_order`).","title":"ets.lookup/2","ref":"ets.html#lookup/2"},{"type":"function","doc":"For a table `Table` of type `set` or `ordered_set`, the function returns the\n`Pos`:th element of the object with key `Key`.\n\nFor tables of type `bag` or `duplicate_bag`, the functions returns a list with\nthe `Pos`:th element of every object with key `Key`.\n\nIf no object with key `Key` exists, the function exits with reason `badarg`.\n\nIf `Pos` is larger than the size of the tuple, the function exits with reason\n`badarg`.\n\nThe difference between `set`, `bag`, and `duplicate_bag` on one hand, and\n`ordered_set` on the other, regarding the fact that `ordered_set` view keys as\nequal when they _compare equal_ whereas the other table types regard them equal\nonly when they _match_, holds for [`lookup_element/3`](`lookup_element/3`).","title":"ets.lookup_element/3","ref":"ets.html#lookup_element/3"},{"type":"function","doc":"For a table `Table` of type `set` or `ordered_set`, the function returns the\n`Pos`:th element of the object with key `Key`.\n\nFor tables of type `bag` or `duplicate_bag`, the functions returns a list with\nthe `Pos`:th element of every object with key `Key`.\n\nIf no object with key `Key` exists, the function returns `Default`.\n\nIf `Pos` is larger than the size of any tuple with a matching key, the function\nexits with reason `badarg`.\n\nThe difference between `set`, `bag`, and `duplicate_bag` on one hand, and\n`ordered_set` on the other, regarding the fact that `ordered_set` view keys as\nequal when they _compare equal_ whereas the other table types regard them equal\nonly when they _match_, holds for [`lookup_element/4`](`lookup_element/4`).","title":"ets.lookup_element/4","ref":"ets.html#lookup_element/4"},{"type":"function","doc":"Continues a match started with `match/3`. The next chunk of the size specified\nin the initial [`match/3`](`match/3`) call is returned together with a new\n`Continuation`, which can be used in subsequent calls to this function.\n\nWhen there are no more objects in the table, `'$end_of_table'` is returned.","title":"ets.match/1","ref":"ets.html#match/1"},{"type":"function","doc":"Matches the objects in table `Table` against pattern `Pattern`.\n\nA pattern is a term that can contain:\n\n- Bound parts (Erlang terms)\n- `'_'` that matches any Erlang term\n- Pattern variables `'$N'`, where `N`=0,1,...\n\nThe function returns a list with one element for each matching object, where\neach element is an ordered list of pattern variable bindings, for example:\n\n```erlang\n6> ets:match(T, '$1'). % Matches every object in table\n[[{rufsen,dog,7}],[{brunte,horse,5}],[{ludde,dog,5}]]\n7> ets:match(T, {'_',dog,'$1'}).\n[[7],[5]]\n8> ets:match(T, {'_',cow,'$1'}).\n[]\n```\n\nIf the key is specified in the pattern, the match is very efficient. If the key\nis not specified, that is, if it is a variable or an underscore, the entire\ntable must be searched. The search time can be substantial if the table is very\nlarge.\n\nFor tables of type `ordered_set`, the result is in the same order as in a\n`first`/`next` traversal.","title":"ets.match/2","ref":"ets.html#match/2"},{"type":"function","doc":"Works like `match/2`, but returns only a limited (`Limit`) number of matching\nobjects. Term `Continuation` can then be used in subsequent calls to `match/1`\nto get the next chunk of matching objects. This is a space-efficient way to work\non objects in a table, which is faster than traversing the table object by\nobject using `first/1` and `next/2`.\n\nIf the table is empty, `'$end_of_table'` is returned.\n\nUse `safe_fixtable/2` to guarantee [safe traversal](`m:ets#traversal`) for\nsubsequent calls to `match/1`.","title":"ets.match/3","ref":"ets.html#match/3"},{"type":"function","doc":"Deletes all objects that match pattern `Pattern` from table `Table`. For a\ndescription of patterns, see `match/2`.","title":"ets.match_delete/2","ref":"ets.html#match_delete/2"},{"type":"function","doc":"Continues a match started with `match_object/3`. The next chunk of the size\nspecified in the initial [`match_object/3`](`match_object/3`) call is returned\ntogether with a new `Continuation`, which can be used in subsequent calls to\nthis function.\n\nWhen there are no more objects in the table, `'$end_of_table'` is returned.","title":"ets.match_object/1","ref":"ets.html#match_object/1"},{"type":"function","doc":"Matches the objects in table `Table` against pattern `Pattern`. For a\ndescription of patterns, see `match/2`. The function returns a list of all\nobjects that match the pattern.\n\nIf the key is specified in the pattern, the match is very efficient. If the key\nis not specified, that is, if it is a variable or an underscore, the entire\ntable must be searched. The search time can be substantial if the table is very\nlarge.\n\nFor tables of type `ordered_set`, the result is in the same order as in a\n`first`/`next` traversal.","title":"ets.match_object/2","ref":"ets.html#match_object/2"},{"type":"function","doc":"Works like `match_object/2`, but only returns a limited (`Limit`) number of\nmatching objects. Term `Continuation` can then be used in subsequent calls to\n`match_object/1` to get the next chunk of matching objects. This is a\nspace-efficient way to work on objects in a table, which is faster than\ntraversing the table object by object using `first/1` and `next/2`.\n\nIf the table is empty, `'$end_of_table'` is returned.\n\nUse `safe_fixtable/2` to guarantee [safe traversal](`m:ets#traversal`) for\nsubsequent calls to `match_object/1`.","title":"ets.match_object/3","ref":"ets.html#match_object/3"},{"type":"function","doc":"Transforms a [match specification](`m:ets#match_spec`) into an internal\nrepresentation that can be used in subsequent calls to `match_spec_run/2`. The\ninternal representation is opaque. To check the validity of a compiled match\nspecification, use `is_compiled_ms/1`.\n\nIf term `MatchSpec` does not represent a valid match specification, a `badarg`\nexception is raised.\n\n> #### Note {: .info }\n>\n> This function has limited use in normal code. It is used by the `m:dets`\n> module to perform the `dets:select/1` operations.","title":"ets.match_spec_compile/1","ref":"ets.html#match_spec_compile/1"},{"type":"function","doc":"Executes the matching specified in a compiled\n[match specification](`m:ets#match_spec`) on a list of terms. Term\n`CompiledMatchSpec` is to be the result of a call to `match_spec_compile/1` and\nis hence the internal representation of the match specification one wants to\nuse.\n\nThe matching is executed on each element in `List` and the function returns a\nlist containing all results. If an element in `List` does not match, nothing is\nreturned for that element. The length of the result list is therefore equal or\nless than the length of parameter `List`.\n\n_Example:_\n\nThe following two calls give the same result (but certainly not the same\nexecution time):\n\n```erlang\nTable = ets:new...\nMatchSpec = ...\n% The following call...\nets:match_spec_run(ets:tab2list(Table),\n ets:match_spec_compile(MatchSpec)),\n% ...gives the same result as the more common (and more efficient)\nets:select(Table, MatchSpec),\n```\n\n> #### Note {: .info }\n>\n> This function has limited use in normal code. It is used by the `m:dets`\n> module to perform the `dets:select/1` operations and by Mnesia during\n> transactions.","title":"ets.match_spec_run/2","ref":"ets.html#match_spec_run/2"},{"type":"function","doc":"Works like `lookup/2`, but does not return the objects. Returns `true` if one or\nmore elements in the table has key `Key`, otherwise `false`.","title":"ets.member/2","ref":"ets.html#member/2"},{"type":"function","doc":"Creates a new table and returns a table identifier that can be used in\nsubsequent operations. The table identifier can be sent to other processes so\nthat a table can be shared between different processes within a node.\n\nParameter `Options` is a list of options that specifies table type, access\nrights, key position, and whether the table is named. Default values are used\nfor omitted options. This means that not specifying any options (`[]`) is the\nsame as specifying\n`[set, protected, {keypos,1}, {heir,none}, {write_concurrency,false}, {read_concurrency,false}, {decentralized_counters,false}]`.\n\n- **`set`** - The table is a `set` table: one key, one object, no order among\n objects. This is the default table type.\n\n- **`ordered_set`** - The table is a `ordered_set` table: one key, one object,\n ordered in Erlang term order, which is the order implied by the \n operators. Tables of this type have a somewhat different behavior in some\n situations than tables of other types. Most notably, the `ordered_set` tables\n regard keys as equal when they _compare equal_, not only when they match. This\n means that to an `ordered_set` table, `t:integer/0` `1` and `t:float/0` `1.0`\n are regarded as equal. This also means that the key used to lookup an element\n does not necessarily _match_ the key in the returned elements, if\n `t:float/0`'s and `t:integer/0`'s are mixed in keys of a table.\n\n- **`bag`** - The table is a `bag` table, which can have many objects, but only\n one instance of each object, per key.\n\n- **`duplicate_bag`** - The table is a `duplicate_bag` table, which can have\n many objects, including multiple copies of the same object, per key.\n\n- **`public`** - Any process can read or write to the table.\n\n [](){: #protected }\n\n- **`protected`** - The owner process can read and write to the table. Other\n processes can only read the table. This is the default setting for the access\n rights.\n\n [](){: #private }\n\n- **`private`** - Only the owner process can read or write to the table.\n\n- **`named_table`** - If this option is present, the table is registered under\n its `Name` which can then be used instead of the table identifier in\n subsequent operations.\n\n The function will also return the `Name` instead of the table identifier. To\n get the table identifier of a named table, use `whereis/1`.\n\n- **`{keypos,Pos}`** - Specifies which element in the stored tuples to use as\n key. By default, it is the first element, that is, `Pos=1`. However, this is\n not always appropriate. In particular, we do not want the first element to be\n the key if we want to store Erlang records in a table.\n\n Notice that any tuple stored in the table must have at least `Pos` number of\n elements.\n\n [](){: #heir }\n\n- **`{heir,Pid,HeirData} | {heir,none}`** - Set a process as heir. The heir\n inherits the table if the owner terminates. Message\n `{'ETS-TRANSFER',tid(),FromPid,HeirData}` is sent to the heir when that\n occurs. The heir must be a local process. Default heir is `none`, which\n destroys the table when the owner terminates.\n\n [](){: #new_2_write_concurrency }\n\n- **`{write_concurrency,WriteConcurrencyAlternative}`** - Performance tuning.\n Defaults to `false`, in which case an operation that mutates (writes to) the\n table obtains exclusive access, blocking any concurrent access of the same\n table until finished. If set to `true`, the table is optimized for concurrent\n write access. Different objects of the same table can be mutated (and read) by\n concurrent processes. This is achieved to some degree at the expense of memory\n consumption and the performance of sequential access and concurrent reading.\n\n The `auto` alternative for the `write_concurrency` option is similar to the\n `true` option but automatically adjusts the synchronization granularity during\n runtime depending on how the table is used. This is the recommended\n `write_concurrency` option when using Erlang/OTP 25 and above as it performs\n well in most scenarios.\n\n The `write_concurrency` option can be combined with the options\n [`read_concurrency`](`m:ets#new_2_read_concurrency`) and\n [`decentralized_counters`](`m:ets#new_2_decentralized_counters`). You\n typically want to combine `write_concurrency` with `read_concurrency` when\n large concurrent read bursts and large concurrent write bursts are common; for\n more information, see option\n [`read_concurrency`](`m:ets#new_2_read_concurrency`). It is almost always a\n good idea to combine the `write_concurrency` option with the\n [`decentralized_counters`](`m:ets#new_2_decentralized_counters`) option.\n\n Notice that this option does not change any guarantees about\n [atomicity and isolation](`m:ets#module-concurrency`). Functions that makes such\n promises over many objects (like `insert/2`) gain less (or nothing) from this\n option.\n\n The memory consumption inflicted by both `write_concurrency` and\n `read_concurrency` is a constant overhead per table for `set`, `bag` and\n `duplicate_bag` when the `true` alternative for the `write_concurrency` option\n is not used. For all tables with the `auto` alternative and `ordered_set`\n tables with `true` alternative the memory overhead depends on the amount of\n actual detected concurrency during runtime. The memory overhead can be\n especially large when both `write_concurrency` and `read_concurrency` are\n combined.\n\n > #### Note {: .info }\n >\n > Prior to stdlib-3.7 (OTP-22.0) `write_concurrency` had no effect on\n > `ordered_set`.\n\n > #### Note {: .info }\n >\n > The `auto` alternative for the `write_concurrency` option is only available\n > in OTP-25.0 and above.\n\n [](){: #new_2_read_concurrency }\n\n- **`{read_concurrency,boolean()}`**(Since OTP R14B) \n Performance tuning. Defaults to `false`. When set to `true`, the table is\n optimized for concurrent read operations. When this option is enabled read\n operations become much cheaper; especially on systems with multiple physical\n processors. However, switching between read and write operations becomes more\n expensive.\n\n You typically want to enable this option when concurrent read operations are\n much more frequent than write operations, or when concurrent reads and writes\n comes in large read and write bursts (that is, many reads not interrupted by\n writes, and many writes not interrupted by reads).\n\n You typically do _not_ want to enable this option when the common access\n pattern is a few read operations interleaved with a few write operations\n repeatedly. In this case, you would get a performance degradation by enabling\n this option.\n\n Option `read_concurrency` can be combined with option\n [`write_concurrency`](`m:ets#new_2_write_concurrency`). You typically want to\n combine these when large concurrent read bursts and large concurrent write\n bursts are common.\n\n [](){: #new_2_decentralized_counters }\n\n- **`{decentralized_counters,boolean()}`**(Since OTP 23.0) \n Performance tuning. Defaults to `true` for all tables with the\n `write_concurrency` option set to `auto`. For tables of type `ordered_set` the\n option also defaults to true when the `write_concurrency` option is set to\n `true`. The option defaults to `false` for all other configurations. This\n option has no effect if the `write_concurrency` option is set to `false`.\n\n When this option is set to `true`, the table is optimized for frequent\n concurrent calls to operations that modify the tables size and/or its memory\n consumption (e.g., `insert/2` and `delete/2`). The drawback is that calls to\n `info/1` and `info/2` with `size` or `memory` as the second argument can get\n much slower when the `decentralized_counters` option is turned on.\n\n When this option is enabled the counters for the table size and memory\n consumption are distributed over several cache lines and the scheduling\n threads are mapped to one of those cache lines. The `erl` option\n [`+dcg`](`e:erts:erl_cmd.md#%2Bdcg`) can be used to control the number of\n cache lines that the counters are distributed over.\n\n [](){: #new_2_compressed }\n\n- **`compressed`**(Since OTP R14B01) \n If this option is present, the table data is stored in a more compact format\n to consume less memory. However, it will make table operations slower.\n Especially operations that need to inspect entire objects, such as `match` and\n `select`, get much slower. The key element is not compressed.","title":"ets.new/2","ref":"ets.html#new/2"},{"type":"function","doc":"Returns the next key `Key2`, following key `Key1` in table `Table`. For table\ntype `ordered_set`, the next key in Erlang term order is returned. For other\ntable types, the next key according to the internal order of the table is\nreturned. If no next key exists, `'$end_of_table'` is returned.\n\nTo find the first key in the table, use `first/1`.\n\nUnless a table of type `set`, `bag`, or `duplicate_bag` is fixated using\n`safe_fixtable/2`, a call to [`next/2`](`next/2`) will fail if `Key1` no longer\nexists in the table. For table type `ordered_set`, the function always returns\nthe next key after `Key1` in term order, regardless whether `Key1` ever existed\nin the table.","title":"ets.next/2","ref":"ets.html#next/2"},{"type":"function","doc":"Similar to `next/2` except that it returns the object(s) along with the key\nstored in the table. This is equivalent to doing `next/2` followed by a\n`lookup/2`. If no next key exists, `'$end_of_table'` is returned.\n\nIt can be interleaved with `next/2` during traversal.","title":"ets.next_lookup/2","ref":"ets.html#next_lookup/2"},{"type":"function","doc":"Returns the previous key `Key2`, preceding key `Key1` according to Erlang term\norder in table `Table` of type `ordered_set`. For other table types, the\nfunction is synonymous to `next/2`. If no previous key exists, `'$end_of_table'`\nis returned.\n\nTo find the last key in an `ordered_set` table, use `last/1`.","title":"ets.prev/2","ref":"ets.html#prev/2"},{"type":"function","doc":"Similar to `prev/2` except that it returns the object(s) along with the key\nstored in the table. This is equivalent to doing `prev/2` followed by a\n`lookup/2`. If no previous key exists, `'$end_of_table'` is returned.\n\nIt can be interleaved with `prev/2` during traversal.","title":"ets.prev_lookup/2","ref":"ets.html#prev_lookup/2"},{"type":"function","doc":"Renames the named table `Table` to the new name `Name`. Afterwards, the old name\ncannot be used to access the table. Renaming an unnamed table has no effect.","title":"ets.rename/2","ref":"ets.html#rename/2"},{"type":"function","doc":"Restores an opaque continuation returned by `select/3` or `select/1` if the\ncontinuation has passed through external term format (been sent between nodes or\nstored on disk).\n\nThe reason for this function is that continuation terms contain compiled match\nspecifications and may therefore be invalidated if converted to external term\nformat. Given that the original match specification is kept intact, the\ncontinuation can be restored, meaning it can once again be used in subsequent\n[`select/1`](`select/1`) calls even though it has been stored on disk or on\nanother node.\n\n_Examples:_\n\nThe following sequence of calls may fail:\n\n```erlang\nT=ets:new(x,[]),\n...\nMS = ets:fun2ms(fun({N,_}=A) when (N rem 10) =:= 0 -> A end),\n{_,C} = ets:select(T, MS, 10),\nMaybeBroken = binary_to_term(term_to_binary(C)),\nets:select(MaybeBroken).\n```\n\nThe following sequence works, as the call to\n[`repair_continuation/2`](`repair_continuation/2`) reestablishes the\n`MaybeBroken` continuation.\n\n```erlang\nT=ets:new(x,[]),\n...\nMS = ets:fun2ms(fun({N,_}=A) when (N rem 10) =:= 0 -> A end),\n{_,C} = ets:select(T,MS,10),\nMaybeBroken = binary_to_term(term_to_binary(C)),\nets:select(ets:repair_continuation(MaybeBroken,MS)).\n```\n\n> #### Note {: .info }\n>\n> This function is rarely needed in application code. It is used by Mnesia to\n> provide distributed [`select/3`](`select/3`) and [`select/1`](`select/1`)\n> sequences. A normal application would either use Mnesia or keep the\n> continuation from being converted to external format.\n>\n> The actual behavior of compiled match specifications when recreated from\n> external format has changed and may change in future releases, but this\n> interface remains for backward compatibility. See `is_compiled_ms/1`.","title":"ets.repair_continuation/2","ref":"ets.html#repair_continuation/2"},{"type":"function","doc":"Fixes a table of type `set`, `bag`, or `duplicate_bag` for\n[safe traversal](`m:ets#traversal`) using `first/1` & `next/2`, `match/3` &\n`match/1`, `match_object/3` & `match_object/1`, or `select/3` & `select/1`.\n\nA process fixes a table by calling\n[`safe_fixtable(Table, true)`](`safe_fixtable/2`). The table remains fixed until\nthe process releases it by calling\n[`safe_fixtable(Table, false)`](`safe_fixtable/2`), or until the process\nterminates.\n\nIf many processes fix a table, the table remains fixed until all processes have\nreleased it (or terminated). A reference counter is kept on a per process basis,\nand N consecutive fixes requires N releases to release the table.\n\nWhen a table is fixed, a sequence of `first/1` and `next/2` calls are guaranteed\nto succeed even if keys are removed during the traversal. The keys for objects\ninserted or deleted during a traversal may or may not be returned by\n[`next/2`](`next/2`) depending on the ordering of keys within the table and if\nthe key exists at the time [`next/2`](`next/2`) is called.\n\n_Example:_\n\n```erlang\nclean_all_with_value(Table,X) ->\n safe_fixtable(Table,true),\n clean_all_with_value(Table,X,ets:first(Table)),\n safe_fixtable(Table,false).\n\nclean_all_with_value(Table,X,'$end_of_table') ->\n true;\nclean_all_with_value(Table,X,Key) ->\n case ets:lookup(Table,Key) of\n [{Key,X}] ->\n ets:delete(Table,Key);\n _ ->\n true\n end,\n clean_all_with_value(Table,X,ets:next(Table,Key)).\n```\n\nNotice that deleted objects are not freed from a fixed table until it has been\nreleased. If a process fixes a table but never releases it, the memory used by\nthe deleted objects is never freed. The performance of operations on the table\nalso degrades significantly.\n\nTo retrieve information about which processes have fixed which tables, use\n[`info(Table, safe_fixed_monotonic_time)`](`m:ets#info_2_safe_fixed_monotonic_time`).\nA system with many processes fixing tables can need a monitor that sends alarms\nwhen tables have been fixed for too long.\n\nNotice that [`safe_fixtable/2`](`safe_fixtable/2`) is not necessary for table\ntype `ordered_set` and for traversals done by a single ETS function call, like\n`select/2`.","title":"ets.safe_fixtable/2","ref":"ets.html#safe_fixtable/2"},{"type":"function","doc":"Continues a match started with `select/3`. The next chunk of the size specified\nin the initial [`select/3`](`select/3`) call is returned together with a new\n`Continuation`, which can be used in subsequent calls to this function.\n\nWhen there are no more objects in the table, `'$end_of_table'` is returned.","title":"ets.select/1","ref":"ets.html#select/1"},{"type":"function","doc":"Matches the objects in table `Table` using a\n[match specification](`m:ets#match_spec`). This is a more general call than\n`match/2` and `match_object/2` calls. In its simplest form, the match\nspecification is as follows:\n\n```text\nMatchSpec = [MatchFunction]\nMatchFunction = {MatchHead, [Guard], [Result]}\nMatchHead = \"Pattern as in ets:match\"\nGuard = {\"Guardtest name\", ...}\nResult = \"Term construct\"\n```\n\nThis means that the match specification is always a list of one or more tuples\n(of arity 3). The first element of the tuple is to be a pattern as described in\n`match/2`. The second element of the tuple is to be a list of 0 or more guard\ntests (described below). The third element of the tuple is to be a list\ncontaining a description of the value to return. In almost all normal cases, the\nlist contains exactly one term that fully describes the value to return for each\nobject.\n\nThe return value is constructed using the \"match variables\" bound in `MatchHead`\nor using the special match variables `'$_'` (the whole matching object) and\n`'$$'` (all match variables in a list), so that the following\n[`match/2`](`match/2`) expression:\n\n```text\nets:match(Table,{'$1','$2','$3'})\n```\n\nis exactly equivalent to:\n\n```text\nets:select(Table,[{{'$1','$2','$3'},[],['$$']}])\n```\n\nAnd that the following [`match_object/2`](`match_object/2`) call:\n\n```text\nets:match_object(Table,{'$1','$2','$1'})\n```\n\nis exactly equivalent to\n\n```text\nets:select(Table,[{{'$1','$2','$1'},[],['$_']}])\n```\n\nComposite terms can be constructed in the `Result` part either by simply writing\na list, so that the following code:\n\n```text\nets:select(Table,[{{'$1','$2','$3'},[],['$$']}])\n```\n\ngives the same output as:\n\n```text\nets:select(Table,[{{'$1','$2','$3'},[],[['$1','$2','$3']]}])\n```\n\nThat is, all the bound variables in the match head as a list. If tuples are to\nbe constructed, one has to write a tuple of arity 1 where the single element in\nthe tuple is the tuple one wants to construct (as an ordinary tuple can be\nmistaken for a `Guard`).\n\nTherefore the following call:\n\n```text\nets:select(Table,[{{'$1','$2','$1'},[],['$_']}])\n```\n\ngives the same output as:\n\n```erlang\nets:select(Table,[{{'$1','$2','$1'},[],[{{'$1','$2','$3'}}]}])\n```\n\nThis syntax is equivalent to the syntax used in the trace patterns (see the\n`m:dbg`) module in Runtime_Tools.\n\nThe `Guard`s are constructed as tuples, where the first element is the test name\nand the remaining elements are the test parameters. To check for a specific type\n(say a list) of the element bound to the match variable `'$1'`, one would write\nthe test as `{is_list, '$1'}`. If the test fails, the object in the table does\nnot match and the next `MatchFunction` (if any) is tried. Most guard tests\npresent in Erlang can be used, but only the new versions prefixed `is_` are\nallowed (`is_float`, `is_atom`, and so on).\n\nThe `Guard` section can also contain logic and arithmetic operations, which are\nwritten with the same syntax as the guard tests (prefix notation), so that the\nfollowing guard test written in Erlang:\n\n```text\nis_integer(X), is_integer(Y), X + Y < 4711\n```\n\nis expressed as follows (`X` replaced with `'$1'` and `Y` with `'$2'`):\n\n```text\n[{is_integer, '$1'}, {is_integer, '$2'}, {'<', {'+', '$1', '$2'}, 4711}]\n```\n\nFor tables of type `ordered_set`, objects are visited in the same order as in a\n`first`/`next` traversal. This means that the match specification is executed\nagainst objects with keys in the `first`/`next` order and the corresponding\nresult list is in the order of that execution.","title":"ets.select/2","ref":"ets.html#select/2"},{"type":"function","doc":"Works like `select/2`, but only returns a limited (`Limit`) number of matching\nobjects. Term `Continuation` can then be used in subsequent calls to `select/1`\nto get the next chunk of matching objects. This is a space-efficient way to work\non objects in a table, which is still faster than traversing the table object by\nobject using `first/1` and `next/2`.\n\nIf the table is empty, `'$end_of_table'` is returned.\n\nUse `safe_fixtable/2` to guarantee [safe traversal](`m:ets#traversal`) for\nsubsequent calls to `select/1`.","title":"ets.select/3","ref":"ets.html#select/3"},{"type":"function","doc":"Matches the objects in table `Table` using a\n[match specification](`m:ets#match_spec`). If and only if the match specification\nreturns `true` for an object, that object is considered a match and is counted.\nFor any other result from the match specification the object is not considered a\nmatch and is therefore not counted.\n\nThe function returns the number of objects matched.","title":"ets.select_count/2","ref":"ets.html#select_count/2"},{"type":"function","doc":"Matches the objects in table `Table` using a\n[match specification](`m:ets#match_spec`). If and only if the match\nspecification returns `true` for an object, that object is removed from the\ntable. For any other result from the match specification the object is\nretained. This is a more general function than `match_delete/2`.\n\nThe function returns the number of objects deleted from the table.\n\n> #### Note {: .info }\n>\n> The match specification has to return the atom `true` if the object is to be\n> deleted. No other return value gets the object deleted. So one cannot use the\n> same match specification for looking up elements as for deleting them.","title":"ets.select_delete/2","ref":"ets.html#select_delete/2"},{"type":"function","doc":"Matches the objects in the table `Table` using a\n[match specification](`m:ets#match_spec`). For each matched object, the existing\nobject is replaced with the match specification result.\n\nThe match-and-replace operation for each individual object is guaranteed to be\n[atomic and isolated](`m:ets#module-concurrency`). The `select_replace` table traversal\nas a whole, like all other select functions, does not give such guarantees.\n\nThe match specification must be guaranteed to _retain the key_ of any matched\nobject. If not, `select_replace` will fail with `badarg` without updating any\nobjects.\n\nFor the moment, due to performance and semantic constraints, tables of type\n`bag` are not yet supported.\n\nThe function returns the total number of replaced objects.\n\n_Example_\n\nFor all 2-tuples with a list in second position, add atom `'marker'` first in\nthe list:\n\n```erlang\n1> T = ets:new(x,[]), ets:insert(T, {key, [1, 2, 3]}).\ntrue\n2> MS = ets:fun2ms(fun({K, L}) when is_list(L) -> {K, [marker | L]} end).\n[{{'$1','$2'},[{is_list,'$2'}],[{{'$1',[marker|'$2']}}]}]\n3> ets:select_replace(T, MS).\n1\n4> ets:tab2list(T).\n[{key,[marker,1,2,3]}]\n```\n\nA generic single object compare-and-swap operation:\n\n```erlang\n[Old] = ets:lookup(T, Key),\nNew = update_object(Old),\nSuccess = (1 =:= ets:select_replace(T, [{Old, [], [{const, New}]}])),\n```","title":"ets.select_replace/2","ref":"ets.html#select_replace/2"},{"type":"function","doc":"Continues a match started with `select_reverse/3`. For tables of type\n`ordered_set`, the traversal of the table continues to objects with keys earlier\nin the Erlang term order. The returned list also contains objects with keys in\nreverse order. For all other table types, the behavior is exactly that of\n`select/1`.\n\n_Example:_\n\n```erlang\n1> T = ets:new(x,[ordered_set]).\n2> [ ets:insert(T,{N}) || N <- lists:seq(1,10) ].\n...\n3> {R0,C0} = ets:select_reverse(T,[{'_',[],['$_']}],4).\n...\n4> R0.\n[{10},{9},{8},{7}]\n5> {R1,C1} = ets:select_reverse(C0).\n...\n6> R1.\n[{6},{5},{4},{3}]\n7> {R2,C2} = ets:select_reverse(C1).\n...\n8> R2.\n[{2},{1}]\n9> '$end_of_table' = ets:select_reverse(C2).\n...\n```","title":"ets.select_reverse/1","ref":"ets.html#select_reverse/1"},{"type":"function","doc":"Works like `select/2`, but returns the list in reverse order for table type\n`ordered_set`. For all other table types, the return value is identical to that\nof [`select/2`](`select/2`).","title":"ets.select_reverse/2","ref":"ets.html#select_reverse/2"},{"type":"function","doc":"Works like `select/3`, but for table type `ordered_set` traversing is done\nstarting at the last object in Erlang term order and moves to the first. For all\nother table types, the return value is identical to that of\n[`select/3`](`select/3`).\n\nNotice that this is _not_ equivalent to reversing the result list of a\n[`select/3`](`select/3`) call, as the result list is not only reversed, but also\ncontains the last `Limit` matching objects in the table, not the first.","title":"ets.select_reverse/3","ref":"ets.html#select_reverse/3"},{"type":"function","doc":"Sets table options. The only allowed option to be set after the table has been\ncreated is [`heir`](`m:ets#heir`). The calling process must be the table owner.","title":"ets.setopts/2","ref":"ets.html#setopts/2"},{"type":"function","doc":"This function is mostly for debugging purposes, normally `first`/`next` or\n`last`/`prev` are to be used instead.\n\nReturns all objects in slot `I` of table `Table`. A table can be traversed by\nrepeatedly calling the function, starting with the first slot `I=0` and ending\nwhen `'$end_of_table'` is returned. If argument `I` is out of range, the\nfunction fails with reason `badarg`.\n\nUnless a table of type `set`, `bag`, or `duplicate_bag` is protected using\n`safe_fixtable/2`, a traversal can fail if concurrent updates are made to the\ntable. For table type `ordered_set`, the function returns a list containing\nobject `I` in Erlang term order.","title":"ets.slot/2","ref":"ets.html#slot/2"},{"type":"function","doc":"Dumps table `Table` to file `Filename`.\n\nEquivalent to [`tab2file(Table, Filename,[])`](`tab2file/3`)","title":"ets.tab2file/2","ref":"ets.html#tab2file/2"},{"type":"function","doc":"Dumps table `Table` to file `Filename`.\n\nWhen dumping the table, some information about the table is dumped to a header\nat the beginning of the dump. This information contains data about the table\ntype, name, protection, size, version, and if it is a named table. It also\ncontains notes about what extended information is added to the file, which can\nbe a count of the objects in the file or a MD5 sum of the header and records in\nthe file.\n\nThe size field in the header might not correspond to the number of records in\nthe file if the table is public and records are added or removed from the table\nduring dumping. Public tables updated during dump, and that one wants to verify\nwhen reading, needs at least one field of extended information for the read\nverification process to be reliable later.\n\nOption `extended_info` specifies what extra information is written to the table\ndump:\n\n- **`object_count`** - The number of objects written to the file is noted in the\n file footer, so file truncation can be verified even if the file was updated\n during dump.\n\n- **`md5sum`** - The header and objects in the file are checksummed using the\n built-in MD5 functions. The MD5 sum of all objects is written in the file\n footer, so that verification while reading detects the slightest bitflip in\n the file data. Using this costs a fair amount of CPU time.\n\nWhenever option `extended_info` is used, it results in a file not readable by\nversions of ETS before that in STDLIB 1.15.1\n\nIf option `sync` is set to `true`, it ensures that the content of the file is\nwritten to the disk before `tab2file` returns. Defaults to `{sync, false}`.","title":"ets.tab2file/3","ref":"ets.html#tab2file/3"},{"type":"function","doc":"Returns a list of all objects in table `Table`.","title":"ets.tab2list/1","ref":"ets.html#tab2list/1"},{"type":"function","doc":"Returns information about the table dumped to file by `tab2file/2` or\n`tab2file/3`.\n\nThe following items are returned:\n\n- **`name`** - The name of the dumped table. If the table was a named table, a\n table with the same name cannot exist when the table is loaded from file with\n `file2tab/2`. If the table is not saved as a named table, this field has no\n significance when loading the table from file.\n\n- **`type`** - The ETS type of the dumped table (that is, `set`, `bag`,\n `duplicate_bag`, or `ordered_set`). This type is used when loading the table\n again.\n\n- **`protection`** - The protection of the dumped table (that is, `private`,\n `protected`, or `public`). A table loaded from the file gets the same\n protection.\n\n- **`named_table`** - `true` if the table was a named table when dumped to file,\n otherwise `false`. Notice that when a named table is loaded from a file, there\n cannot exist a table in the system with the same name.\n\n- **`keypos`** - The `keypos` of the table dumped to file, which is used when\n loading the table again.\n\n- **`size`** - The number of objects in the table when the table dump to file\n started. For a `public` table, this number does not need to correspond to the\n number of objects saved to the file, as objects can have been added or deleted\n by another process during table dump.\n\n- **`extended_info`** - The extended information written in the file footer to\n allow stronger verification during table loading from file, as specified to\n `tab2file/3`. Notice that this function only tells _which_ information is\n present, not the values in the file footer. The value is a list containing one\n or more of the atoms `object_count` and `md5sum`.\n\n- **`version`** - A tuple `{Major,Minor}` containing the major and minor version\n of the file format for ETS table dumps. This version field was added beginning\n with STDLIB 1.5.1. Files dumped with older versions return `{0,0}` in this\n field.\n\nAn error is returned if the file is inaccessible, badly damaged, or not produced\nwith `tab2file/2` or `tab2file/3`.","title":"ets.tabfile_info/1","ref":"ets.html#tabfile_info/1"},{"type":"function","doc":"","title":"ets.table/1","ref":"ets.html#table/1"},{"type":"function","doc":"Returns a Query List Comprehension (QLC) query handle. The `m:qlc` module\nprovides a query language aimed mainly at Mnesia, but ETS tables, Dets tables,\nand lists are also recognized by QLC as sources of data. Calling `table/1,2` is\nthe means to make the ETS table `Table` usable to QLC.\n\nWhen there are only simple restrictions on the key position, QLC uses `lookup/2`\nto look up the keys. When that is not possible, the whole table is traversed.\nOption `traverse` determines how this is done:\n\n- **`first_next`** - The table is traversed one key at a time by calling\n `first/1` and `next/2`.\n\n- **`last_prev`** - The table is traversed one key at a time by calling `last/1`\n and `prev/2`.\n\n- **`select`** - The table is traversed by calling `select/3` and `select/1`.\n Option `n_objects` determines the number of objects returned (the third\n argument of [`select/3`](`select/3`)); the default is to return `100` objects\n at a time. The [match specification](`m:ets#match_spec`) (the second argument\n of [`select/3`](`select/3`)) is assembled by QLC: simple filters are\n translated into equivalent match specifications while more complicated filters\n must be applied to all objects returned by [`select/3`](`select/3`) given a\n match specification that matches all objects.\n\n- **`{select, MatchSpec}`** - As for `select`, the table is traversed by calling\n `select/3` and `select/1`. The difference is that the match specification is\n explicitly specified. This is how to state match specifications that cannot\n easily be expressed within the syntax provided by QLC.\n\n_Examples:_\n\nAn explicit match specification is here used to traverse the table:\n\n```erlang\n9> true = ets:insert(Table = ets:new(t, []), [{1,a},{2,b},{3,c},{4,d}]),\nMS = ets:fun2ms(fun({X,Y}) when (X > 1) or (X < 5) -> {Y} end),\nQH1 = ets:table(Table, [{traverse, {select, MS}}]).\n```\n\nAn example with an implicit match specification:\n\n```erlang\n10> QH2 = qlc:q([{Y} || {X,Y} <- ets:table(Table), (X > 1) or (X < 5)]).\n```\n\nThe latter example is equivalent to the former, which can be verified using\nfunction `qlc:info/1`:\n\n```erlang\n11> qlc:info(QH1) =:= qlc:info(QH2).\ntrue\n```\n\n`qlc:info/1` returns information about a query handle, and in this case\nidentical information is returned for the two query handles.","title":"ets.table/2","ref":"ets.html#table/2"},{"type":"function","doc":"Returns and removes a list of all objects with key `Key` in table `Table`.\n\nThe specified `Key` is used to identify the object by either _comparing equal_\nthe key of an object in an `ordered_set` table, or _matching_ in other types of\ntables (for details on the difference, see `lookup/2` and `new/2`).","title":"ets.take/2","ref":"ets.html#take/2"},{"type":"function","doc":"This function is a utility to test a [match specification](`m:ets#match_spec`)\nused in calls to `select/2`. The function both tests `MatchSpec` for \"syntactic\"\ncorrectness and runs the match specification against object `Tuple`.\n\nIf the match specification is syntactically correct, the function either returns\n`{ok,Result}`, where `Result` is what would have been the result in a real\n[`select/2`](`select/2`) call, or `false` if the match specification does not\nmatch object `Tuple`.\n\nIf the match specification contains errors, tuple `{error, Errors}` is returned,\nwhere `Errors` is a list of natural language descriptions of what was wrong with\nthe match specification.\n\nThis is a useful debugging and test tool, especially when writing complicated\n[`select/2`](`select/2`) calls.\n\nSee also: `erlang:match_spec_test/3`.","title":"ets.test_ms/2","ref":"ets.html#test_ms/2"},{"type":"function","doc":"Fills an already created/opened Dets table with the objects in the already\nopened ETS table named `Table`. The Dets table is emptied before the objects are\ninserted.","title":"ets.to_dets/2","ref":"ets.html#to_dets/2"},{"type":"function","doc":"","title":"ets.update_counter/3","ref":"ets.html#update_counter/3"},{"type":"function","doc":"This function provides an efficient way to update one or more counters, without\nthe trouble of having to look up an object, update the object by incrementing an\nelement, and insert the resulting object into the table again. The operation is\nguaranteed to be [atomic and isolated](`m:ets#module-concurrency`).\n\nThis function destructively updates the object with key `Key` in table `Table`\nby adding `Incr` to the element at position `Pos`. The new counter value is\nreturned. If no position is specified, the element directly following key\n(` +1`) is updated.\n\nIf a `Threshold` is specified, the counter is reset to value `SetValue` if the\nfollowing conditions occur:\n\n- `Incr` is not negative (`>= 0`) and the result would be greater than (`>`)\n `Threshold`.\n- `Incr` is negative (`< 0`) and the result would be less than (`<`)\n `Threshold`.\n\nA list of `UpdateOp` can be supplied to do many update operations within the\nobject. The operations are carried out in the order specified in the list. If\nthe same counter position occurs more than once in the list, the corresponding\ncounter is thus updated many times, each time based on the previous result. The\nreturn value is a list of the new counter values from each update operation in\nthe same order as in the operation list. If an empty list is specified, nothing\nis updated and an empty list is returned. If the function fails, no updates are\ndone.\n\nThe specified `Key` is used to identify the object by either _matching_ the key\nof an object in a `set` table, or _compare equal_ to the key of an object in an\n`ordered_set` table (for details on the difference, see `lookup/2` and `new/2`).\n\nIf a default object `Default` is specified, it is used as the object to be\nupdated if the key is missing from the table. The value in place of the key is\nignored and replaced by the proper key value. The return value is as if the\ndefault object had not been used, that is, a single updated element or a list of\nthem.\n\nThe function fails with reason `badarg` in the following situations:\n\n- The table type is not `set` or `ordered_set`.\n- No object with the correct key exists and no default object was supplied.\n- The object has the wrong arity.\n- The default object arity is smaller than ` `.\n- Any field from the default object that is updated is not an integer.\n- The element to update is not an integer.\n- The element to update is also the key.\n- Any of `Pos`, `Incr`, `Threshold`, or `SetValue` is not an integer.","title":"ets.update_counter/4","ref":"ets.html#update_counter/4"},{"type":"function","doc":"","title":"ets.update_element/3","ref":"ets.html#update_element/3"},{"type":"function","doc":"This function provides an efficient way to update one or more elements within an\nobject, without the trouble of having to look up, update, and write back the\nentire object.\n\nThis function destructively updates the object with key `Key` in table `Table`.\nThe element at position `Pos` is given the value `Value`.\n\nA list of `{Pos,Value}` can be supplied to update many elements within the same\nobject. If the same position occurs more than once in the list, the last value\nin the list is written. If the list is empty or the function fails, no updates\nare done. The function is also atomic in the sense that other processes can\nnever see any intermediate results.\n\nReturns `true` if an object with key `Key` is found, otherwise `false`.\n\nThe specified `Key` is used to identify the object by either _matching_ the key\nof an object in a `set` table, or _compare equal_ to the key of an object in an\n`ordered_set` table (for details on the difference, see `lookup/2` and `new/2`).\n\nIf a default object `Default` is specified, it is used as the object to be\nupdated if the key is missing from the table. The value in place of the key is\nignored and replaced by the proper key value.\n\nThe function fails with reason `badarg` in the following situations:\n\n- The table type is not `set` or `ordered_set`.\n- `Pos` < 1.\n- `Pos` > object arity.\n- The default object arity is smaller than ` `.\n- The element to update is also the key.","title":"ets.update_element/4","ref":"ets.html#update_element/4"},{"type":"function","doc":"This function returns the `t:tid/0` of the named table identified by\n`TableName`, or `undefined` if no such table exists. The `t:tid/0` can be used\nin place of the table name in all operations, which is slightly faster since the\nname does not have to be resolved on each call.\n\nIf the table is deleted, the `t:tid/0` will be invalid even if another named\ntable is created with the same name.","title":"ets.whereis/1","ref":"ets.html#whereis/1"},{"type":"type","doc":"","title":"ets.comp_match_spec/0","ref":"ets.html#t:comp_match_spec/0"},{"type":"opaque","doc":"A compiled match specification.","title":"ets.compiled_match_spec/0","ref":"ets.html#t:compiled_match_spec/0"},{"type":"type","doc":"Opaque continuation used by [`select/1,3`](`select/1`),\n[`select_reverse/1,3`](`select_reverse/1`), [`match/1,3`](`match/1`), and\n[`match_object/1,3`](`match_object/1`).","title":"ets.continuation/0","ref":"ets.html#t:continuation/0"},{"type":"type","doc":"","title":"ets.match_pattern/0","ref":"ets.html#t:match_pattern/0"},{"type":"type","doc":"A match specification, see [Match Specifications](`m:ets#match_spec`).","title":"ets.match_spec/0","ref":"ets.html#t:match_spec/0"},{"type":"type","doc":"","title":"ets.tab/0","ref":"ets.html#t:tab/0"},{"type":"type","doc":"","title":"ets.table/0","ref":"ets.html#t:table/0"},{"type":"type","doc":"","title":"ets.table_access/0","ref":"ets.html#t:table_access/0"},{"type":"type","doc":"","title":"ets.table_type/0","ref":"ets.html#t:table_type/0"},{"type":"opaque","doc":"A table identifier, as returned by `new/2`.","title":"ets.tid/0","ref":"ets.html#t:tid/0"},{"type":"module","doc":"Sets represented by general balanced trees.\n\nThis module provides ordered sets using Prof. Arne Andersson's General Balanced\nTrees. Ordered sets can be much more efficient than using ordered lists, for\nlarger sets, but depends on the application.\n\nThe data representing a set as used by this module is to be regarded as opaque\nby other modules. In abstract terms, the representation is a composite type of\nexisting Erlang terms. See note on\n[data types](`e:system:data_types.md#no_user_types`). Any code assuming\nknowledge of the format is running on thin ice.\n\nThis module considers two elements as different if and only if they do not\ncompare equal (`==`).","title":"gb_sets","ref":"gb_sets.html"},{"type":"module","doc":"The complexity on set operations is bounded by either _O(|S|)_ or _O(|T| _\nlog(|S|))\\*, where S is the largest given set, depending on which is fastest for\nany particular function call. For operating on sets of almost equal size, this\nimplementation is about 3 times slower than using ordered-list sets directly.\nFor sets of very different sizes, however, this solution can be arbitrarily much\nfaster; in practical cases, often 10-100 times. This implementation is\nparticularly suited for accumulating elements a few at a time, building up a\nlarge set (> 100-200 elements), and repeatedly testing for membership in the\ncurrent set.\n\nAs with normal tree structures, lookup (membership testing), insertion, and\ndeletion have logarithmic complexity.","title":"Complexity Note - gb_sets","ref":"gb_sets.html#module-complexity-note"},{"type":"module","doc":"See the [Compatibility Section in the `sets` module](`m:sets#module-compatibility`)\nfor information about the compatibility of the different implementations of sets\nin the Standard Library.","title":"Compatibility - gb_sets","ref":"gb_sets.html#module-compatibility"},{"type":"module","doc":"`m:gb_trees`, `m:ordsets`, `m:sets`","title":"See Also - gb_sets","ref":"gb_sets.html#module-see-also"},{"type":"function","doc":"","title":"gb_sets.add/2","ref":"gb_sets.html#add/2"},{"type":"function","doc":"Returns a new set formed from `Set1` with `Element` inserted. If `Element` is\nalready an element in `Set1`, nothing is changed.","title":"gb_sets.add_element/2","ref":"gb_sets.html#add_element/2"},{"type":"function","doc":"Rebalances the tree representation of `Set1`.\n\nNotice that this is rarely necessary, but can be motivated when a large number of\nelements have been deleted from the tree without further insertions. Rebalancing\n can then be forced to minimise lookup times, as deletion does not rebalance the\ntree.","title":"gb_sets.balance/1","ref":"gb_sets.html#balance/1"},{"type":"function","doc":"","title":"gb_sets.del_element/2","ref":"gb_sets.html#del_element/2"},{"type":"function","doc":"Returns a new set formed from `Set1` with `Element` removed. Assumes that\n`Element` is present in `Set1`.","title":"gb_sets.delete/2","ref":"gb_sets.html#delete/2"},{"type":"function","doc":"Returns a new set formed from `Set1` with `Element` removed. If `Element` is not\nan element in `Set1`, nothing is changed.","title":"gb_sets.delete_any/2","ref":"gb_sets.html#delete_any/2"},{"type":"function","doc":"","title":"gb_sets.difference/2","ref":"gb_sets.html#difference/2"},{"type":"function","doc":"Returns a new empty set.","title":"gb_sets.empty/0","ref":"gb_sets.html#empty/0"},{"type":"function","doc":"Filters elements in `Set1` using predicate function `Pred`.","title":"gb_sets.filter/2","ref":"gb_sets.html#filter/2"},{"type":"function","doc":"Filters and maps elements in `Set1` using function `Fun`.","title":"gb_sets.filtermap/2","ref":"gb_sets.html#filtermap/2"},{"type":"function","doc":"Folds `Function` over every element in `Set` returning the final value of the\naccumulator.","title":"gb_sets.fold/3","ref":"gb_sets.html#fold/3"},{"type":"function","doc":"Returns a set of the elements in `List`, where `List` can be unordered and\ncontain duplicates.","title":"gb_sets.from_list/1","ref":"gb_sets.html#from_list/1"},{"type":"function","doc":"Turns an ordered-set list `List` into a set. The list must not contain\nduplicates.","title":"gb_sets.from_ordset/1","ref":"gb_sets.html#from_ordset/1"},{"type":"function","doc":"Returns a new set formed from `Set1` with `Element` inserted. Assumes that\n`Element` is not present in `Set1`.","title":"gb_sets.insert/2","ref":"gb_sets.html#insert/2"},{"type":"function","doc":"Returns the intersection of the non-empty list of sets.","title":"gb_sets.intersection/1","ref":"gb_sets.html#intersection/1"},{"type":"function","doc":"Returns the intersection of `Set1` and `Set2`.","title":"gb_sets.intersection/2","ref":"gb_sets.html#intersection/2"},{"type":"function","doc":"Returns `true` if `Set1` and `Set2` are disjoint (have no elements in common),\notherwise `false`.","title":"gb_sets.is_disjoint/2","ref":"gb_sets.html#is_disjoint/2"},{"type":"function","doc":"","title":"gb_sets.is_element/2","ref":"gb_sets.html#is_element/2"},{"type":"function","doc":"Returns `true` if `Set` is an empty set, otherwise `false`.","title":"gb_sets.is_empty/1","ref":"gb_sets.html#is_empty/1"},{"type":"function","doc":"Returns `true` if `Set1` and `Set2` are equal, that is when every element of one\nset is also a member of the respective other set, otherwise `false`.","title":"gb_sets.is_equal/2","ref":"gb_sets.html#is_equal/2"},{"type":"function","doc":"Returns `true` if `Element` is an member of `Set`, otherwise `false`.","title":"gb_sets.is_member/2","ref":"gb_sets.html#is_member/2"},{"type":"function","doc":"Returns `true` if `Term` appears to be a set, otherwise `false`. This function\nwill return `true` for any term that coincides with the representation of a\n`gb_set`, while not really being a `gb_set`, thus it might return false positive\nresults. See also note on [data types](`e:system:data_types.md#no_user_types`).","title":"gb_sets.is_set/1","ref":"gb_sets.html#is_set/1"},{"type":"function","doc":"Returns `true` when every element of `Set1` is also a member of `Set2`,\notherwise `false`.","title":"gb_sets.is_subset/2","ref":"gb_sets.html#is_subset/2"},{"type":"function","doc":"Returns an iterator that can be used for traversing the entries of `Set`; see\n`next/1`.\n\nEquivalent to [`iterator(Set, ordered)`](`iterator/2`).","title":"gb_sets.iterator/1","ref":"gb_sets.html#iterator/1"},{"type":"function","doc":"Returns an iterator that can be used for traversing the entries of `Set` in\neither `ordered` or `reversed` direction; see `next/1`.\n\nThe implementation of this is very efficient; traversing the whole set using\n[`next/1`](`next/1`) is only slightly slower than getting the list of all\n elements using `to_list/1` and traversing that. The main advantage of the\niterator approach is that it does not require the complete list of all elements\nto be built in memory at one time.","title":"gb_sets.iterator/2","ref":"gb_sets.html#iterator/2"},{"type":"function","doc":"Returns an iterator that can be used for traversing the entries of `Set`; see\n`next/1`. The difference as compared to the iterator returned by `iterator/1` is\nthat the iterator starts with the first element greater than or equal to\n`Element`.\n\nEquivalent to [`iterator_from(Element, Set, ordered)`](`iterator_from/3`).","title":"gb_sets.iterator_from/2","ref":"gb_sets.html#iterator_from/2"},{"type":"function","doc":"Returns an iterator that can be used for traversing the entries of `Set`; see\n`next/1`. The difference as compared to the iterator returned by `iterator/2` is\nthat the iterator starts with the first element next to or equal to `Element`.","title":"gb_sets.iterator_from/3","ref":"gb_sets.html#iterator_from/3"},{"type":"function","doc":"Returns `{found, Element2}`, where `Element2` is the least element strictly\ngreater than `Element1`.\n\nReturns `none` if no such element exists.","title":"gb_sets.larger/2","ref":"gb_sets.html#larger/2"},{"type":"function","doc":"Returns the largest element in `Set`. Assumes that `Set` is not empty.","title":"gb_sets.largest/1","ref":"gb_sets.html#largest/1"},{"type":"function","doc":"Maps elements in `Set1` using mapping function `Fun`.","title":"gb_sets.map/2","ref":"gb_sets.html#map/2"},{"type":"function","doc":"Returns a new empty set.","title":"gb_sets.new/0","ref":"gb_sets.html#new/0"},{"type":"function","doc":"Returns `{Element, Iter2}`, where `Element` is the smallest element referred to\nby iterator `Iter1`, and `Iter2` is the new iterator to be used for traversing\nthe remaining elements, or the atom `none` if no elements remain.","title":"gb_sets.next/1","ref":"gb_sets.html#next/1"},{"type":"function","doc":"Returns a set containing only element `Element`.","title":"gb_sets.singleton/1","ref":"gb_sets.html#singleton/1"},{"type":"function","doc":"Returns the number of elements in `Set`.","title":"gb_sets.size/1","ref":"gb_sets.html#size/1"},{"type":"function","doc":"Returns `{found, Element2}`, where `Element2` is the greatest element strictly\nless than `Element1`.\n\nReturns `none` if no such element exists.","title":"gb_sets.smaller/2","ref":"gb_sets.html#smaller/2"},{"type":"function","doc":"Returns the smallest element in `Set`. Assumes that `Set` is not empty.","title":"gb_sets.smallest/1","ref":"gb_sets.html#smallest/1"},{"type":"function","doc":"Returns only the elements of `Set1` that are not also elements of `Set2`.","title":"gb_sets.subtract/2","ref":"gb_sets.html#subtract/2"},{"type":"function","doc":"Returns `{Element, Set2}`, where `Element` is the largest element in `Set1`, and\n`Set2` is this set with `Element` deleted. Assumes that `Set1` is not empty.","title":"gb_sets.take_largest/1","ref":"gb_sets.html#take_largest/1"},{"type":"function","doc":"Returns `{Element, Set2}`, where `Element` is the smallest element in `Set1`,\nand `Set2` is this set with `Element` deleted. Assumes that `Set1` is not empty.","title":"gb_sets.take_smallest/1","ref":"gb_sets.html#take_smallest/1"},{"type":"function","doc":"Returns the elements of `Set` as a list.","title":"gb_sets.to_list/1","ref":"gb_sets.html#to_list/1"},{"type":"function","doc":"Returns the merged (union) set of the list of sets.","title":"gb_sets.union/1","ref":"gb_sets.html#union/1"},{"type":"function","doc":"Returns the merged (union) set of `Set1` and `Set2`.","title":"gb_sets.union/2","ref":"gb_sets.html#union/2"},{"type":"type","doc":"","title":"gb_sets.iter/0","ref":"gb_sets.html#t:iter/0"},{"type":"opaque","doc":"A general balanced set iterator.","title":"gb_sets.iter/1","ref":"gb_sets.html#t:iter/1"},{"type":"type","doc":"","title":"gb_sets.set/0","ref":"gb_sets.html#t:set/0"},{"type":"opaque","doc":"A general balanced set.","title":"gb_sets.set/1","ref":"gb_sets.html#t:set/1"},{"type":"module","doc":"General balanced trees.\n\nThis module provides Prof. Arne Andersson's General Balanced Trees. These have\nno storage overhead compared to unbalanced binary trees, and their performance\nis better than AVL trees.\n\nThis module considers two keys as different if and only if they do not compare\nequal (`==`).","title":"gb_trees","ref":"gb_trees.html"},{"type":"module","doc":"Trees and iterators are built using opaque data structures that should not be\npattern-matched from outside this module.\n\nThere is no attempt to balance trees after deletions. As deletions do not\nincrease the height of a tree, this should be OK.\n\nThe original balance condition `h(T) <= ceil(c * log(|T|))` has been changed to\nthe similar (but not quite equivalent) condition `2 ^ h(T) <= |T| ^ c`. This\nshould also be OK.","title":"Data Structure - gb_trees","ref":"gb_trees.html#module-data-structure"},{"type":"module","doc":"`m:dict`, `m:gb_sets`","title":"See Also - gb_trees","ref":"gb_trees.html#module-see-also"},{"type":"function","doc":"Rebalances `Tree1`.\n\nNotice that this is rarely necessary, but can be motivated\nwhen many nodes have been deleted from the tree without further insertions.\nRebalancing can then be forced to minimize lookup times, as deletion does not\nrebalance the tree.","title":"gb_trees.balance/1","ref":"gb_trees.html#balance/1"},{"type":"function","doc":"Removes the node with key `Key` from `Tree1` and returns the new tree. Assumes\nthat the key is present in the tree, crashes otherwise.","title":"gb_trees.delete/2","ref":"gb_trees.html#delete/2"},{"type":"function","doc":"Removes the node with key `Key` from `Tree1` if the key is present in the tree,\notherwise does nothing. Returns the new tree.","title":"gb_trees.delete_any/2","ref":"gb_trees.html#delete_any/2"},{"type":"function","doc":"Returns a new empty tree.","title":"gb_trees.empty/0","ref":"gb_trees.html#empty/0"},{"type":"function","doc":"Inserts `Key` with value `Value` into `Tree1` if the key is not present in the\ntree, otherwise updates `Key` to value `Value` in `Tree1`. Returns the new tree.","title":"gb_trees.enter/3","ref":"gb_trees.html#enter/3"},{"type":"function","doc":"Turns an ordered list `List` of key-value tuples into a tree. The list must not\ncontain duplicate keys.","title":"gb_trees.from_orddict/1","ref":"gb_trees.html#from_orddict/1"},{"type":"function","doc":"Retrieves the value stored with `Key` in `Tree`. Assumes that the key is present\nin the tree, crashes otherwise.","title":"gb_trees.get/2","ref":"gb_trees.html#get/2"},{"type":"function","doc":"Inserts `Key` with value `Value` into `Tree1` and returns the new tree. Assumes\nthat the key is not present in the tree, crashes otherwise.","title":"gb_trees.insert/3","ref":"gb_trees.html#insert/3"},{"type":"function","doc":"Returns `true` if `Key` is present in `Tree`, otherwise `false`.","title":"gb_trees.is_defined/2","ref":"gb_trees.html#is_defined/2"},{"type":"function","doc":"Returns `true` if `Tree` is an empty tree, othwewise `false`.","title":"gb_trees.is_empty/1","ref":"gb_trees.html#is_empty/1"},{"type":"function","doc":"Returns an iterator that can be used for traversing the entries of `Tree`; see\n`next/1`.\n\nEquivalent to [`iterator(Tree, ordered)`](`iterator/2`).","title":"gb_trees.iterator/1","ref":"gb_trees.html#iterator/1"},{"type":"function","doc":"Returns an iterator that can be used for traversing the entries of `Tree` in\neither `ordered` or `reversed` direction; see `next/1`.\n\nThe implementation of this is very efficient; traversing the whole tree using\n[`next/1`](`next/1`) is only slightly slower than getting the list of all\nelements using `to_list/1` and traversing that. The main advantage of the\niterator approach is that it does not require the complete list of all elements\nto be built in memory at one time.","title":"gb_trees.iterator/2","ref":"gb_trees.html#iterator/2"},{"type":"function","doc":"Returns an iterator that can be used for traversing the entries of `Tree`; see\n`next/1`. The difference as compared to the iterator returned by `iterator/1` is\nthat the iterator starts with the first key greater than or equal to `Key`.\n\nEquivalent to [`iterator_from(Key, Tree, ordered)`](`iterator_from/3`).","title":"gb_trees.iterator_from/2","ref":"gb_trees.html#iterator_from/2"},{"type":"function","doc":"Returns an iterator that can be used for traversing the entries of `Tree` in\neither `ordered` or `reversed` direction; see `next/1`. The difference as\ncompared to the iterator returned by `iterator/2` is that the iterator starts\nwith the first key next to or equal to `Key`.","title":"gb_trees.iterator_from/3","ref":"gb_trees.html#iterator_from/3"},{"type":"function","doc":"Returns the keys in `Tree` as an ordered list.","title":"gb_trees.keys/1","ref":"gb_trees.html#keys/1"},{"type":"function","doc":"Returns `{Key2, Value}`, where `Key2` is the least key strictly greater than\n`Key1`, `Value` is the value associated with this key.\n\nReturns `none` if no such pair exists.","title":"gb_trees.larger/2","ref":"gb_trees.html#larger/2"},{"type":"function","doc":"Returns `{Key, Value}`, where `Key` is the largest key in `Tree`, and `Value` is\nthe value associated with this key. Assumes that the tree is not empty.","title":"gb_trees.largest/1","ref":"gb_trees.html#largest/1"},{"type":"function","doc":"Looks up `Key` in `Tree`. Returns `{value, Value}`, or `none` if `Key` is not\npresent.","title":"gb_trees.lookup/2","ref":"gb_trees.html#lookup/2"},{"type":"function","doc":"Maps function F(K, V1) -> V2 to all key-value pairs of tree `Tree1`. Returns a\nnew tree `Tree2` with the same set of keys as `Tree1` and the new set of values\n`V2`.","title":"gb_trees.map/2","ref":"gb_trees.html#map/2"},{"type":"function","doc":"Returns `{Key, Value, Iter2}`, where `Key` is the next key referred to by\niterator `Iter1`, and `Iter2` is the new iterator to be used for traversing the\nremaining nodes, or the atom `none` if no nodes remain.","title":"gb_trees.next/1","ref":"gb_trees.html#next/1"},{"type":"function","doc":"Returns the number of nodes in `Tree`.","title":"gb_trees.size/1","ref":"gb_trees.html#size/1"},{"type":"function","doc":"Returns `{Key2, Value}`, where `Key2` is the greatest key strictly less than\n`Key1`, `Value` is the value associated with this key.\n\nReturns `none` if no such pair exists.","title":"gb_trees.smaller/2","ref":"gb_trees.html#smaller/2"},{"type":"function","doc":"Returns `{Key, Value}`, where `Key` is the smallest key in `Tree`, and `Value`\nis the value associated with this key. Assumes that the tree is not empty.","title":"gb_trees.smallest/1","ref":"gb_trees.html#smallest/1"},{"type":"function","doc":"Returns a value `Value` from node with key `Key` and new `Tree2` without the\nnode with this value. Assumes that the node with key is present in the tree,\ncrashes otherwise.","title":"gb_trees.take/2","ref":"gb_trees.html#take/2"},{"type":"function","doc":"Returns a value `Value` from node with key `Key` and new `Tree2` without the\nnode with this value. Returns `error` if the node with the key is not present in\nthe tree.","title":"gb_trees.take_any/2","ref":"gb_trees.html#take_any/2"},{"type":"function","doc":"Returns `{Key, Value, Tree2}`, where `Key` is the largest key in `Tree1`,\n`Value` is the value associated with this key, and `Tree2` is this tree with the\ncorresponding node deleted. Assumes that the tree is not empty.","title":"gb_trees.take_largest/1","ref":"gb_trees.html#take_largest/1"},{"type":"function","doc":"Returns `{Key, Value, Tree2}`, where `Key` is the smallest key in `Tree1`,\n`Value` is the value associated with this key, and `Tree2` is this tree with the\ncorresponding node deleted. Assumes that the tree is not empty.","title":"gb_trees.take_smallest/1","ref":"gb_trees.html#take_smallest/1"},{"type":"function","doc":"Converts a tree into an ordered list of key-value tuples.","title":"gb_trees.to_list/1","ref":"gb_trees.html#to_list/1"},{"type":"function","doc":"Updates `Key` to value `Value` in `Tree1` and returns the new tree. Assumes that\nthe key is present in the tree.","title":"gb_trees.update/3","ref":"gb_trees.html#update/3"},{"type":"function","doc":"Returns the values in `Tree` as an ordered list, sorted by their corresponding\nkeys. Duplicates are not removed.","title":"gb_trees.values/1","ref":"gb_trees.html#values/1"},{"type":"type","doc":"","title":"gb_trees.iter/0","ref":"gb_trees.html#t:iter/0"},{"type":"opaque","doc":"A general balanced tree iterator.","title":"gb_trees.iter/2","ref":"gb_trees.html#t:iter/2"},{"type":"type","doc":"","title":"gb_trees.tree/0","ref":"gb_trees.html#t:tree/0"},{"type":"opaque","doc":"A general balanced tree.","title":"gb_trees.tree/2","ref":"gb_trees.html#t:tree/2"},{"type":"module","doc":"A library for encoding and decoding JSON.\n\nThis module implements [EEP68](https://github.com/erlang/eep/blob/master/eeps/eep-0068.md).\n\nBoth encoder and decoder fully conform to\n[RFC 8259](https://tools.ietf.org/html/rfc8259) and\n[ECMA 404](https://ecma-international.org/publications-and-standards/standards/ecma-404/)\nstandards. The decoder is tested using [JSONTestSuite](https://github.com/nst/JSONTestSuite).","title":"json","ref":"json.html"},{"type":"function","doc":"Parses a JSON value from `Binary`.\n\nSupports basic data mapping:\n\n| **JSON** | **Erlang** |\n|----------|------------------------|\n| Number | `integer() \\| float()` |\n| Boolean | `true \\| false` |\n| Null | `null` |\n| String | `binary()` |\n| Object | `#{binary() => _}` |","title":"json.decode/1","ref":"json.html#decode/1"},{"type":"function","doc":"* `error(unexpected_end)` if `Binary` contains incomplete JSON value\n* `error({invalid_byte, Byte})` if `Binary` contains unexpected byte or invalid UTF-8 byte\n* `error({unexpected_sequence, Bytes})` if `Binary` contains invalid UTF-8 escape","title":"Errors - json.decode/1","ref":"json.html#decode/1-errors"},{"type":"function","doc":"```erlang\n> json:decode(<<\"{\\\"foo\\\": 1}\">>).\n#{<<\"foo\">> => 1}\n```","title":"Example - json.decode/1","ref":"json.html#decode/1-example"},{"type":"function","doc":"Parses a JSON value from `Binary`.\n\nSimilar to `decode/1` except the decoding process\ncan be customized with the callbacks specified in\n`Decoders`. The callbacks will use the `Acc` value\nas the initial accumulator.\n\nAny leftover, unparsed data in `Binary` will be returned.","title":"json.decode/3","ref":"json.html#decode/3"},{"type":"function","doc":"All callbacks are optional. If not provided, they will fall back to\nimplementations used by the `decode/1` function:\n\n* for `array_start`: `fun(_) -> [] end`\n* for `array_push`: `fun(Elem, Acc) -> [Elem | Acc] end`\n* for `array_finish`: `fun(Acc, OldAcc) -> {lists:reverse(Acc), OldAcc} end`\n* for `object_start`: `fun(_) -> [] end`\n* for `object_push`: `fun(Key, Value, Acc) -> [{Key, Value} | Acc] end`\n* for `object_finish`: `fun(Acc, OldAcc) -> {maps:from_list(Acc), OldAcc} end`\n* for `float`: `fun erlang:binary_to_float/1`\n* for `integer`: `fun erlang:binary_to_integer/1`\n* for `string`: `fun (Value) -> Value end`\n* for `null`: the atom `null`","title":"Default callbacks - json.decode/3","ref":"json.html#decode/3-default-callbacks"},{"type":"function","doc":"* `error({invalid_byte, Byte})` if `Binary` contains unexpected byte or invalid UTF-8 byte\n* `error({unexpected_sequence, Bytes})` if `Binary` contains invalid UTF-8 escape\n* `error(unexpected_end)` if `Binary` contains incomplete JSON value","title":"Errors - json.decode/3","ref":"json.html#decode/3-errors"},{"type":"function","doc":"Decoding object keys as atoms:\n\n```erlang\n> Push = fun(Key, Value, Acc) -> [{binary_to_existing_atom(Key), Value} | Acc] end.\n> json:decode(<<\"{\\\"foo\\\": 1}\">>, ok, #{object_push => Push}).\n{#{foo => 1},ok,<<>>}\n```","title":"Example - json.decode/3","ref":"json.html#decode/3-example"},{"type":"function","doc":"Continue parsing a stream of bytes of a JSON value.\n\nSimilar to `decode_start/3`, if the function returns `{continue, State}` and\nthere is no more data, use `end_of_input` instead of a binary.\n\n```erlang\n> {continue, State} = json:decode_start(<<\"{\\\"foo\\\":\">>, ok, #{}).\n> json:decode_continue(<<\"1}\">>, State).\n{#{foo => 1},ok,<<>>}\n```\n```erlang\n> {continue, State} = json:decode_start(<<\"123\">>, ok, #{}).\n> json:decode_continue(end_of_input, State).\n{123,ok,<<>>}\n```","title":"json.decode_continue/2","ref":"json.html#decode_continue/2"},{"type":"function","doc":"Begin parsing a stream of bytes of a JSON value.\n\nSimilar to `decode/3` but returns when a complete JSON value can be parsed or\nreturns `{continue, State}` for incomplete data,\nthe `State` can be fed to the `decode_continue/2` function when more data is available.","title":"json.decode_start/3","ref":"json.html#decode_start/3"},{"type":"function","doc":"Generates JSON corresponding to `Term`.\n\nSupports basic data mapping:\n\n| **Erlang** | **JSON** |\n|------------------------|----------|\n| `integer() \\| float()` | Number |\n| `true \\| false ` | Boolean |\n| `null` | Null |\n| `binary()` | String |\n| `atom()` | String |\n| `list()` | Array |\n| `#{binary() => _}` | Object |\n| `#{atom() => _}` | Object |\n| `#{integer() => _}` | Object |\n\nThis is equivalent to `encode(Term, fun json:encode_value/2)`.","title":"json.encode/1","ref":"json.html#encode/1"},{"type":"function","doc":"```erlang\n> iolist_to_binary(json:encode(#{foo => <<\"bar\">>})).\n<<\"{\\\"foo\\\":\\\"bar\\\"}\">>\n```","title":"Examples - json.encode/1","ref":"json.html#encode/1-examples"},{"type":"function","doc":"Generates JSON corresponding to `Term`.\n\nCan be customised with the `Encoder` callback.\nThe callback will be recursively called for all the data\nto be encoded and is expected to return the corresponding\nencoded JSON as iodata.\n\nVarious `encode_*` functions in this module can be used\nto help in constructing such callbacks.","title":"json.encode/2","ref":"json.html#encode/2"},{"type":"function","doc":"An encoder that uses a heuristic to differentiate object-like\nlists of key-value pairs from plain lists:\n\n```erlang\n> encoder([{_, _} | _] = Value, Encode) -> json:encode_key_value_list(Value, Encode);\n> encoder(Other, Encode) -> json:encode_value(Other, Encode).\n> custom_encode(Value) -> json:encode(Value, fun(Value, Encode) -> encoder(Value, Encode) end).\n> iolist_to_binary(custom_encode([{a, []}, {b, 1}])).\n<<\"{\\\"a\\\":[],\\\"b\\\":1}\">>\n```","title":"Examples - json.encode/2","ref":"json.html#encode/2-examples"},{"type":"function","doc":"Default encoder for atoms used by `json:encode/1`.\n\nEncodes the atom `null` as JSON `null`,\natoms `true` and `false` as JSON booleans,\nand everything else as JSON strings calling the `Encode`\ncallback with the corresponding binary.","title":"json.encode_atom/2","ref":"json.html#encode_atom/2"},{"type":"function","doc":"Default encoder for binaries as JSON strings used by `json:encode/1`.","title":"json.encode_binary/1","ref":"json.html#encode_binary/1"},{"type":"function","doc":"* `error(unexpected_end)` if the binary contains incomplete UTF-8 sequences.\n* `error({invalid_byte, Byte})` if the binary contains invalid UTF-8 sequences.","title":"Errors - json.encode_binary/1","ref":"json.html#encode_binary/1-errors"},{"type":"function","doc":"Encoder for binaries as JSON strings producing pure-ASCII JSON.\n\nFor any non-ASCII unicode character, a corresponding `\\\\uXXXX` sequence is used.","title":"json.encode_binary_escape_all/1","ref":"json.html#encode_binary_escape_all/1"},{"type":"function","doc":"* `error(unexpected_end)` if the binary contains incomplete UTF-8 sequences.\n* `error({invalid_byte, Byte})` if the binary contains invalid UTF-8 sequences.","title":"Errors - json.encode_binary_escape_all/1","ref":"json.html#encode_binary_escape_all/1-errors"},{"type":"function","doc":"Default encoder for floats as JSON numbers used by `json:encode/1`.","title":"json.encode_float/1","ref":"json.html#encode_float/1"},{"type":"function","doc":"Default encoder for integers as JSON numbers used by `json:encode/1`.","title":"json.encode_integer/1","ref":"json.html#encode_integer/1"},{"type":"function","doc":"Encoder for lists of key-value pairs as JSON objects.\n\nAccepts lists with atom, binary, integer, or float keys.","title":"json.encode_key_value_list/2","ref":"json.html#encode_key_value_list/2"},{"type":"function","doc":"Encoder for lists of key-value pairs as JSON objects.\n\nAccepts lists with atom, binary, integer, or float keys.\nVerifies that no duplicate keys will be produced in the\nresulting JSON object.","title":"json.encode_key_value_list_checked/2","ref":"json.html#encode_key_value_list_checked/2"},{"type":"function","doc":"Raises `error({duplicate_key, Key})` if there are duplicates.","title":"Errors - json.encode_key_value_list_checked/2","ref":"json.html#encode_key_value_list_checked/2-errors"},{"type":"function","doc":"Default encoder for lists as JSON arrays used by `json:encode/1`.","title":"json.encode_list/2","ref":"json.html#encode_list/2"},{"type":"function","doc":"Default encoder for maps as JSON objects used by `json:encode/1`.\n\nAccepts maps with atom, binary, integer, or float keys.","title":"json.encode_map/2","ref":"json.html#encode_map/2"},{"type":"function","doc":"Encoder for maps as JSON objects.\n\nAccepts maps with atom, binary, integer, or float keys.\nVerifies that no duplicate keys will be produced in the\nresulting JSON object.","title":"json.encode_map_checked/2","ref":"json.html#encode_map_checked/2"},{"type":"function","doc":"Raises `error({duplicate_key, Key})` if there are duplicates.","title":"Errors - json.encode_map_checked/2","ref":"json.html#encode_map_checked/2-errors"},{"type":"function","doc":"Default encoder used by `json:encode/1`.\n\nRecursively calls `Encode` on all the values in `Value`.","title":"json.encode_value/2","ref":"json.html#encode_value/2"},{"type":"function","doc":"Generates formatted JSON corresponding to `Term`.\n\nSimiliar to `encode/1` but with added whitespaces for formatting.\n\n```erlang\n> io:put_chars(json:format(#{foo => <<\"bar\">>, baz => 52})).\n{\n \"baz\": 52,\n \"foo\": \"bar\"\n}\nok\n```","title":"json.format/1","ref":"json.html#format/1"},{"type":"function","doc":"Generates formatted JSON corresponding to `Term`.\n\nEquivalent to `format(Term, fun json:format_value/3, Options)` or `format(Term, Encoder, #{})`","title":"json.format/2","ref":"json.html#format/2"},{"type":"function","doc":"Generates formatted JSON corresponding to `Term`.\n\nSimilar to `encode/2`, can be customised with the `Encoder` callback and `Options`.\n\n`Options` can include 'indent' to specify number of spaces per level and 'max' which loosely limits\nthe width of lists.\n\nThe `Encoder` will get a 'State' argument which contains the 'Options' maps merged with other data\nwhen recursing through 'Term'.\n\n`format_value/3` or various `encode_*` functions in this module can be used\nto help in constructing such callbacks.\n\n```erlang\n> formatter({posix_time, SysTimeSecs}, Encode, State) ->\n TimeStr = calendar:system_time_to_rfc3339(SysTimeSecs, [{offset, \"Z\"}]),\n json:format_value(unicode:characters_to_binary(TimeStr), Encode, State);\n> formatter(Other, Encode, State) -> json:format_value(Other, Encode, State).\n>\n> Fun = fun(Value, Encode, State) -> formatter(Value, Encode, State) end.\n> Options = #{indent => 4}.\n> Term = #{id => 1, time => {posix_time, erlang:system_time(seconds)}}.\n>\n> io:put_chars(json:format(Term, Fun, Options)).\n{\n \"id\": 1,\n \"time\": \"2024-05-23T16:07:48Z\"\n}\nok\n```","title":"json.format/3","ref":"json.html#format/3"},{"type":"function","doc":"Format function for lists of key-value pairs as JSON objects.\n\nAccepts lists with atom, binary, integer, or float keys.","title":"json.format_key_value_list/3","ref":"json.html#format_key_value_list/3"},{"type":"function","doc":"Format function for lists of key-value pairs as JSON objects.\n\nAccepts lists with atom, binary, integer, or float keys.\nVerifies that no duplicate keys will be produced in the\nresulting JSON object.","title":"json.format_key_value_list_checked/3","ref":"json.html#format_key_value_list_checked/3"},{"type":"function","doc":"Raises `error({duplicate_key, Key})` if there are duplicates.","title":"Errors - json.format_key_value_list_checked/3","ref":"json.html#format_key_value_list_checked/3-errors"},{"type":"function","doc":"Default format function used by `json:format/1`.\n\nRecursively calls `Encode` on all the values in `Value`,\nand indents objects and lists.","title":"json.format_value/3","ref":"json.html#format_value/3"},{"type":"type","doc":"","title":"json.array_finish_fun/0","ref":"json.html#t:array_finish_fun/0"},{"type":"type","doc":"","title":"json.array_push_fun/0","ref":"json.html#t:array_push_fun/0"},{"type":"type","doc":"","title":"json.array_start_fun/0","ref":"json.html#t:array_start_fun/0"},{"type":"opaque","doc":"","title":"json.continuation_state/0","ref":"json.html#t:continuation_state/0"},{"type":"type","doc":"","title":"json.decode_value/0","ref":"json.html#t:decode_value/0"},{"type":"type","doc":"","title":"json.decoders/0","ref":"json.html#t:decoders/0"},{"type":"type","doc":"","title":"json.encode_map/1","ref":"json.html#t:encode_map/1"},{"type":"type","doc":"Simple JSON value encodeable with `json:encode/1`.","title":"json.encode_value/0","ref":"json.html#t:encode_value/0"},{"type":"type","doc":"","title":"json.encoder/0","ref":"json.html#t:encoder/0"},{"type":"type","doc":"","title":"json.formatter/0","ref":"json.html#t:formatter/0"},{"type":"type","doc":"","title":"json.from_binary_fun/0","ref":"json.html#t:from_binary_fun/0"},{"type":"type","doc":"","title":"json.object_finish_fun/0","ref":"json.html#t:object_finish_fun/0"},{"type":"type","doc":"","title":"json.object_push_fun/0","ref":"json.html#t:object_push_fun/0"},{"type":"type","doc":"","title":"json.object_start_fun/0","ref":"json.html#t:object_start_fun/0"},{"type":"module","doc":"Key-value dictionary as ordered list.\n\nThis module provides a `Key`-`Value` dictionary. An `orddict` is a\nrepresentation of a dictionary, where a list of pairs is used to store the keys\nand values. The list is ordered after the keys in the\n[Erlang term order](`e:system:expressions.md#term-comparisons`).\n\nThis module provides the same interface as the `m:dict` module but with a\ndefined representation. One difference is that while `dict` considers two keys\nas different if they do not match (`=:=`), this module considers two keys as\ndifferent if and only if they do not compare equal (`==`).","title":"orddict","ref":"orddict.html"},{"type":"module","doc":"[](){: #notes }\n\nFunctions [`append/3`](`append/3`) and [`append_list/3`](`append_list/3`) are\nincluded so that keyed values can be stored in a list _accumulator_, for\nexample:\n\n```erlang\n> D0 = orddict:new(),\n D1 = orddict:store(files, [], D0),\n D2 = orddict:append(files, f1, D1),\n D3 = orddict:append(files, f2, D2),\n D4 = orddict:append(files, f3, D3),\n orddict:fetch(files, D4).\n[f1,f2,f3]\n```\n\nThis saves the trouble of first fetching a keyed value, appending a new value to\nthe list of stored values, and storing the result.\n\nFunction [`fetch/2`](`fetch/2`) is to be used if the key is known to be in the\ndictionary, otherwise function [`find/2`](`find/2`).","title":"Notes - orddict","ref":"orddict.html#module-notes"},{"type":"module","doc":"`m:dict`, `m:gb_trees`","title":"See Also - orddict","ref":"orddict.html#module-see-also"},{"type":"function","doc":"Appends a new `Value` to the current list of values associated with `Key`. An\nexception is generated if the initial value associated with `Key` is not a list\nof values.\n\nSee also section [Notes](`m:orddict#module-notes`).\n\n_Example 1:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{x, []}]).\n[{x,[]}]\n2> OrdDict2 = orddict:append(x, 1, OrdDict1).\n[{x,[1]}]\n3> OrdDict3 = orddict:append(x, 2, OrdDict2).\n[{x,[1,2]}]\n4> orddict:append(y, 3, OrdDict3).\n[{x,[1,2]},{y,[3]}]\n```\n\n_Example 2:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{a, no_list}]).\n[{a,no_list}]\n2> orddict:append(a, 1, OrdDict1).\n** exception error: bad argument\n in operator ++/2\n called as no_list ++ [1]\n```","title":"orddict.append/3","ref":"orddict.html#append/3"},{"type":"function","doc":"Appends a list of values `ValList` to the current list of values associated with\n`Key`. An exception is generated if the initial value associated with `Key` is\nnot a list of values.\n\nSee also section [Notes](`m:orddict#module-notes`).\n\n_Example:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{x, []}]).\n[{x,[]}]\n2> OrdDict2 = orddict:append_list(x, [1,2], OrdDict1).\n[{x,[1,2]}]\n3> OrdDict3 = orddict:append_list(y, [3,4], OrdDict2).\n[{x,[1,2]},{y,[3,4]}]\n```","title":"orddict.append_list/3","ref":"orddict.html#append_list/3"},{"type":"function","doc":"Erases all items with a specified key from a dictionary.\n\n_Example:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).\n[{a,1},{b,2}]\n2> orddict:erase(a, OrdDict1).\n[{b,2}]\n```","title":"orddict.erase/2","ref":"orddict.html#erase/2"},{"type":"function","doc":"Returns the value associated with `Key` in dictionary `Orddict`. This function\nassumes that the `Key` is present in the dictionary. An exception is generated\nif `Key` is not in the dictionary.\n\nSee also section [Notes](`m:orddict#module-notes`).\n\n_Example:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).\n[{a,1},{b,2}]\n2> orddict:fetch(a, OrdDict1).\n1\n3> orddict:fetch(missing, OrdDict1).\n** exception error: no function clause matching orddict:fetch(missing,[])\n```","title":"orddict.fetch/2","ref":"orddict.html#fetch/2"},{"type":"function","doc":"Returns a list of all keys in a dictionary.\n\n_Example:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).\n[{a,1},{b,2}]\n2> orddict:fetch_keys(OrdDict1).\n[a,b]\n```","title":"orddict.fetch_keys/1","ref":"orddict.html#fetch_keys/1"},{"type":"function","doc":"`Orddict2` is a dictionary of all keys and values in `Orddict1` for which\n`Pred(Key, Value)` is `true`.\n\n_Example:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).\n[{a,1},{b,2}]\n2> orddict:filter(fun (K, V) -> V > 1 end, OrdDict1).\n[{b,2}]\n```","title":"orddict.filter/2","ref":"orddict.html#filter/2"},{"type":"function","doc":"Searches for a key in a dictionary. Returns `{ok, Value}`, where `Value` is the\nvalue associated with `Key`, or `error` if the key is not present in the\ndictionary.\n\nSee also section [Notes](`m:orddict#module-notes`).\n\n_Example:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).\n[{a,1},{b,2}]\n2> orddict:find(a, OrdDict1).\n{ok,1}\n3> orddict:find(c, OrdDict1).\nerror\n```","title":"orddict.find/2","ref":"orddict.html#find/2"},{"type":"function","doc":"Calls `Fun` on successive keys and values of `Orddict` together with an extra\nargument `Acc` (short for accumulator). `Fun` must return a new accumulator that\nis passed to the next call. `Acc0` is returned if the list is empty.\n\n_Example:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).\n[{a,1},{b,2}]\n2> orddict:fold(fun (K, V, Acc) -> [{K, V+100} | Acc] end, [], OrdDict1).\n[{b,102},{a,101}]\n```","title":"orddict.fold/3","ref":"orddict.html#fold/3"},{"type":"function","doc":"Converts the `Key`-`Value` list `List` to a dictionary.","title":"orddict.from_list/1","ref":"orddict.html#from_list/1"},{"type":"function","doc":"Returns `true` if `Orddict` has no elements, otherwise `false`.","title":"orddict.is_empty/1","ref":"orddict.html#is_empty/1"},{"type":"function","doc":"Tests if `Key` is contained in dictionary `Orddict`.","title":"orddict.is_key/2","ref":"orddict.html#is_key/2"},{"type":"function","doc":"Calls `Fun` on successive keys and values of `Orddict1` to return a new value\nfor each key.\n\n_Example:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).\n[{a,1},{b,2}]\n2> orddict:map(fun (_K, V) -> V + 100 end, OrdDict1).\n[{a,101},{b,102}]\n```","title":"orddict.map/2","ref":"orddict.html#map/2"},{"type":"function","doc":"Merges two dictionaries, `Orddict1` and `Orddict2`, to create a new dictionary.\nAll the `Key`-`Value` pairs from both dictionaries are included in the new\ndictionary.\n\nIf a key occurs in both dictionaries, `Fun` is called with the key\nand both values to return a new value.\n\n[`merge/3`](`merge/3`) can be defined as follows, but is faster:\n\n```erlang\nmerge(Fun, D1, D2) ->\n fold(fun (K, V1, D) ->\n update(K, fun (V2) -> Fun(K, V1, V2) end, V1, D)\n end, D2, D1).\n```\n\n_Example:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).\n[{a,1},{b,2}]\n2> OrdDict2 = orddict:from_list([{b, 7}, {c, 8}]).\n[{b,7},{c,8}]\n3> orddict:merge(fun (K, V1, V2) -> V1 * V2 end, OrdDict1, OrdDict2).\n[{a,1},{b,14},{c,8}]\n```","title":"orddict.merge/3","ref":"orddict.html#merge/3"},{"type":"function","doc":"Creates a new dictionary.","title":"orddict.new/0","ref":"orddict.html#new/0"},{"type":"function","doc":"Returns the number of elements in an `Orddict`.","title":"orddict.size/1","ref":"orddict.html#size/1"},{"type":"function","doc":"Stores a `Key`-`Value` pair in a dictionary. If the `Key` already exists in\n`Orddict1`, the associated value is replaced by `Value`.\n\n_Example:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).\n[{a,1},{b,2}]\n2> orddict:store(a, 99, OrdDict1).\n[{a,99},{b,2}]\n3> orddict:store(c, 100, OrdDict1).\n[{a,1},{b,2},{c,100}]\n```","title":"orddict.store/3","ref":"orddict.html#store/3"},{"type":"function","doc":"This function returns value from dictionary and new dictionary without this\nvalue. Returns `error` if the key is not present in the dictionary.\n\n_Example:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).\n[{a,1},{b,2}]\n2> orddict:take(a, OrdDict1).\n{1,[{b,2}]}\n3> orddict:take(missing, OrdDict1).\nerror\n```","title":"orddict.take/2","ref":"orddict.html#take/2"},{"type":"function","doc":"Converts a dictionary to a list representation.","title":"orddict.to_list/1","ref":"orddict.html#to_list/1"},{"type":"function","doc":"Updates a value in a dictionary by calling `Fun` on the value to get a new\nvalue. An exception is generated if `Key` is not present in the dictionary.\n\n_Example:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).\n[{a,1},{b,2}]\n2> orddict:update(a, fun (V) -> V + 100 end, OrdDict1).\n[{a,101},{b,2}]\n```","title":"orddict.update/3","ref":"orddict.html#update/3"},{"type":"function","doc":"Updates a value in a dictionary by calling `Fun` on the value to get a new\nvalue. If `Key` is not present in the dictionary, `Initial` is stored as the\nfirst value.\n\nFor example, [`append/3`](`append/3`) can be defined as follows:\n\n```erlang\nappend(Key, Val, D) ->\n update(Key, fun (Old) -> Old ++ [Val] end, [Val], D).\n```\n\n_Example 1:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).\n[{a,1},{b,2}]\n2> orddict:update(c, fun (V) -> V + 100 end, 99, OrdDict1).\n[{a,1},{b,2},{c,99}]\n```\n\n_Example 2:_\n\n```erlang\n1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).\n[{a,1},{b,2}]\n2> orddict:update(a, fun (V) -> V + 100 end, 99, OrdDict1).\n[{a,101},{b,2}]\n```","title":"orddict.update/4","ref":"orddict.html#update/4"},{"type":"function","doc":"Adds `Increment` to the value associated with `Key` and store this value. If\n`Key` is not present in the dictionary, `Increment` is stored as the first\nvalue.\n\nThis can be defined as follows, but is faster:\n\n```erlang\nupdate_counter(Key, Incr, D) ->\n update(Key, fun (Old) -> Old + Incr end, Incr, D).\n```","title":"orddict.update_counter/3","ref":"orddict.html#update_counter/3"},{"type":"type","doc":"","title":"orddict.orddict/0","ref":"orddict.html#t:orddict/0"},{"type":"type","doc":"Dictionary as returned by `new/0`.","title":"orddict.orddict/2","ref":"orddict.html#t:orddict/2"},{"type":"module","doc":"Functions for manipulating sets as ordered lists.\n\nSets are collections of elements with no duplicate elements. An `ordset` is a\nrepresentation of a set, where an ordered list is used to store the elements of\nthe set. An ordered list is more efficient than an unordered list. Elements are\nordered according to the _Erlang term order_.\n\nThis module provides the same interface as the `m:sets` module but with a\ndefined representation. One difference is that while `sets` considers two\nelements as different if they do not match (`=:=`), this module considers two\nelements as different if and only if they do not compare equal (`==`).\n\nSee the [Compatibility Section in the `sets` module](`m:sets#module-compatibility`)\nfor more information about the compatibility of the different implementations of\nsets in the Standard Library.","title":"ordsets","ref":"ordsets.html"},{"type":"module","doc":"`m:gb_sets`, `m:sets`","title":"See Also - ordsets","ref":"ordsets.html#module-see-also"},{"type":"function","doc":"Returns a new ordered set formed from `Ordset1` with `Element` inserted.","title":"ordsets.add_element/2","ref":"ordsets.html#add_element/2"},{"type":"function","doc":"Returns `Ordset1`, but with `Element` removed.","title":"ordsets.del_element/2","ref":"ordsets.html#del_element/2"},{"type":"function","doc":"Filters elements in `Ordset1` with boolean function `Pred`.","title":"ordsets.filter/2","ref":"ordsets.html#filter/2"},{"type":"function","doc":"Filters and maps elements in `Ordset1` with function `Fun`.","title":"ordsets.filtermap/2","ref":"ordsets.html#filtermap/2"},{"type":"function","doc":"Folds `Function` over every element in `Ordset` and returns the final value of\nthe accumulator.","title":"ordsets.fold/3","ref":"ordsets.html#fold/3"},{"type":"function","doc":"Returns an ordered set of the elements in `List`.","title":"ordsets.from_list/1","ref":"ordsets.html#from_list/1"},{"type":"function","doc":"Returns the intersection of the non-empty list of sets.","title":"ordsets.intersection/1","ref":"ordsets.html#intersection/1"},{"type":"function","doc":"Returns the intersection of `Ordset1` and `Ordset2`.","title":"ordsets.intersection/2","ref":"ordsets.html#intersection/2"},{"type":"function","doc":"Returns `true` if `Ordset1` and `Ordset2` are disjoint (have no elements in\ncommon), otherwise `false`.","title":"ordsets.is_disjoint/2","ref":"ordsets.html#is_disjoint/2"},{"type":"function","doc":"Returns `true` if `Element` is an element of `Ordset`, otherwise `false`.","title":"ordsets.is_element/2","ref":"ordsets.html#is_element/2"},{"type":"function","doc":"Returns `true` if `Ordset` is an empty set, otherwise `false`.","title":"ordsets.is_empty/1","ref":"ordsets.html#is_empty/1"},{"type":"function","doc":"Returns `true` if `Ordset1` and `Ordset2` are equal, that is when every element\nof one set is also a member of the respective other set, otherwise `false`.","title":"ordsets.is_equal/2","ref":"ordsets.html#is_equal/2"},{"type":"function","doc":"Returns `true` if `Ordset` is an ordered set of elements, otherwise `false`.\nThis function will return `true` for any ordered list, even when not constructed\nby the functions in this module.","title":"ordsets.is_set/1","ref":"ordsets.html#is_set/1"},{"type":"function","doc":"Returns `true` when every element of `Ordset1` is also a member of `Ordset2`,\notherwise `false`.","title":"ordsets.is_subset/2","ref":"ordsets.html#is_subset/2"},{"type":"function","doc":"Maps elements in `Ordset1` with mapping function `Fun`.","title":"ordsets.map/2","ref":"ordsets.html#map/2"},{"type":"function","doc":"Returns a new empty ordered set.","title":"ordsets.new/0","ref":"ordsets.html#new/0"},{"type":"function","doc":"Returns the number of elements in `Ordset`.","title":"ordsets.size/1","ref":"ordsets.html#size/1"},{"type":"function","doc":"Returns only the elements of `Ordset1` that are not also elements of `Ordset2`.","title":"ordsets.subtract/2","ref":"ordsets.html#subtract/2"},{"type":"function","doc":"Returns the elements of `Ordset` as a list.","title":"ordsets.to_list/1","ref":"ordsets.html#to_list/1"},{"type":"function","doc":"Returns the merged (union) set of the list of sets.","title":"ordsets.union/1","ref":"ordsets.html#union/1"},{"type":"function","doc":"Returns the merged (union) set of `Ordset1` and `Ordset2`.","title":"ordsets.union/2","ref":"ordsets.html#union/2"},{"type":"type","doc":"As returned by `new/0`.","title":"ordsets.ordset/1","ref":"ordsets.html#t:ordset/1"},{"type":"module","doc":"Support functions for property lists.\n\nProperty lists are ordinary lists containing entries in the form of either\ntuples, whose first elements are keys used for lookup and insertion, or atoms,\nwhich work as shorthand for tuples `{Atom, true}`. (Other terms are allowed in\nthe lists, but are ignored by this module.) If there is more than one entry in a\nlist for a certain key, the first occurrence normally overrides any later\n(irrespective of the arity of the tuples).\n\nProperty lists are useful for representing inherited properties, such as options\npassed to a function where a user can specify options overriding the default\nsettings, object properties, annotations, and so on.\n\nTwo keys are considered equal if they match (`=:=`). That is, numbers are\ncompared literally rather than by value, so that, for example, `1` and `1.0` are\ndifferent keys.","title":"proplists","ref":"proplists.html"},{"type":"function","doc":"Similar to `get_all_values/2`, but each value is wrapped in a list unless it is\nalready itself a list. The resulting list of lists is concatenated. This is\noften useful for \"incremental\" options.\n\n_Example:_\n\n```erlang\nappend_values(a, [{a, [1,2]}, {b, 0}, {a, 3}, {c, -1}, {a, [4]}])\n```\n\nreturns:\n\n```erlang\n[1,2,3,4]\n```","title":"proplists.append_values/2","ref":"proplists.html#append_values/2"},{"type":"function","doc":"Minimizes the representation of all entries in the list. This is equivalent to\n`[property(P) || P <- ListIn]`.\n\nSee also `property/1`, `unfold/1`.","title":"proplists.compact/1","ref":"proplists.html#compact/1"},{"type":"function","doc":"Deletes all entries associated with `Key` from `List`.","title":"proplists.delete/2","ref":"proplists.html#delete/2"},{"type":"function","doc":"Expands particular properties to corresponding sets of properties (or other\nterms).\n\nFor each pair `{Property, Expansion}` in `Expansions`: if `E` is the\nfirst entry in `ListIn` with the same key as `Property`, and `E` and `Property`\nhave equivalent normal forms, then `E` is replaced with the terms in\n`Expansion`, and any following entries with the same key are deleted from\n`ListIn`.\n\nFor example, the following expressions all return `[fie, bar, baz, fum]`:\n\n```erlang\nexpand([{foo, [bar, baz]}], [fie, foo, fum])\nexpand([{{foo, true}, [bar, baz]}], [fie, foo, fum])\nexpand([{{foo, false}, [bar, baz]}], [fie, {foo, false}, fum])\n```\n\nHowever, no expansion is done in the following call because `{foo, false}`\nshadows `foo`:\n\n```erlang\nexpand([{{foo, true}, [bar, baz]}], [{foo, false}, fie, foo, fum])\n```\n\nNotice that if the original property term is to be preserved in the result when\nexpanded, it must be included in the expansion list. The inserted terms are not\nexpanded recursively. If `Expansions` contains more than one property with the\nsame key, only the first occurrence is used.\n\nSee also `normalize/2`.","title":"proplists.expand/2","ref":"proplists.html#expand/2"},{"type":"function","doc":"Converts the map `Map` to a property list.","title":"proplists.from_map/1","ref":"proplists.html#from_map/1"},{"type":"function","doc":"Similar to `get_value/2`, but returns the list of values for _all_ entries\n`{Key, Value}` in `List`. If no such entry exists, the result is the empty list.","title":"proplists.get_all_values/2","ref":"proplists.html#get_all_values/2"},{"type":"function","doc":"Returns the value of a boolean key/value option. If\n[`lookup(Key, List)`](`lookup/2`) would yield `{Key, true}`, this function\nreturns `true`, otherwise `false`.\n\nSee also `get_value/2`, `lookup/2`.","title":"proplists.get_bool/2","ref":"proplists.html#get_bool/2"},{"type":"function","doc":"Returns an unordered list of the keys used in `List`, not containing duplicates.","title":"proplists.get_keys/1","ref":"proplists.html#get_keys/1"},{"type":"function","doc":"","title":"proplists.get_value/2","ref":"proplists.html#get_value/2"},{"type":"function","doc":"Returns the value of a simple key/value property in `List`. If\n[`lookup(Key, List)`](`lookup/2`) would yield `{Key, Value}`, this function\nreturns the corresponding `Value`, otherwise `Default`.\n\nSee also `get_all_values/2`, `get_bool/2`, `get_value/2`, `lookup/2`.","title":"proplists.get_value/3","ref":"proplists.html#get_value/3"},{"type":"function","doc":"Returns `true` if `List` contains at least one entry associated with `Key`,\notherwise `false`.","title":"proplists.is_defined/2","ref":"proplists.html#is_defined/2"},{"type":"function","doc":"Returns the first entry associated with `Key` in `List`, if one exists,\notherwise returns `none`. For an atom `A` in the list, the tuple `{A, true}` is\nthe entry associated with `A`.\n\nSee also `get_bool/2`, `get_value/2`, `lookup_all/2`.","title":"proplists.lookup/2","ref":"proplists.html#lookup/2"},{"type":"function","doc":"Returns the list of all entries associated with `Key` in `List`. If no such\nentry exists, the result is the empty list.\n\nSee also `lookup/2`.","title":"proplists.lookup_all/2","ref":"proplists.html#lookup_all/2"},{"type":"function","doc":"Passes `ListIn` through a sequence of substitution/expansion stages. For an\n`aliases` operation, function `substitute_aliases/2` is applied using the\nspecified list of aliases:\n\n- For a `negations` operation,\n [`substitute_negations/2`](`substitute_negations/2`) is applied using the\n specified negation list.\n- For an `expand` operation, function `expand/2` is applied using the specified\n list of expansions.\n\nThe final result is automatically compacted (compare `compact/1`).\n\nTypically you want to substitute negations first, then aliases, then perform one\nor more expansions (sometimes you want to pre-expand particular entries before\ndoing the main expansion). You might want to substitute negations and/or aliases\nrepeatedly, to allow such forms in the right-hand side of aliases and expansion\nlists.\n\nSee also `substitute_negations/2`.","title":"proplists.normalize/2","ref":"proplists.html#normalize/2"},{"type":"function","doc":"Creates a normal form (minimal) representation of a property. If `PropertyIn` is\n`{Key, true}`, where `Key` is an atom, `Key` is returned, otherwise the whole\nterm `PropertyIn` is returned.\n\nSee also `property/2`.","title":"proplists.property/1","ref":"proplists.html#property/1"},{"type":"function","doc":"Creates a normal form (minimal) representation of a simple key/value property.\nReturns `Key` if `Value` is `true` and `Key` is an atom, otherwise a tuple\n`{Key, Value}` is returned.\n\nSee also `property/1`.","title":"proplists.property/2","ref":"proplists.html#property/2"},{"type":"function","doc":"Partitions `List` into a list of sublists and a remainder.\n\n`Lists` contains one sublist for each key in `Keys`, in the corresponding order.\nThe relative order of the elements in each sublist is preserved from the original `List`.\n`Rest` contains the elements in `List` that are not associated with any of the\nspecified keys, also with their original relative order preserved.\n\n_Example:_\n\n```erlang\nsplit([{c, 2}, {e, 1}, a, {c, 3, 4}, d, {b, 5}, b], [a, b, c])\n```\n\nreturns:\n\n```erlang\n{[[a], [{b, 5}, b],[{c, 2}, {c, 3, 4}]], [{e, 1}, d]}\n```","title":"proplists.split/2","ref":"proplists.html#split/2"},{"type":"function","doc":"Substitutes keys of properties. For each entry in `ListIn`, if it is associated\nwith some key `K1` such that `{K1, K2}` occurs in `Aliases`, the key of the\nentry is changed to `K2`. If the same `K1` occurs more than once in `Aliases`,\nonly the first occurrence is used.\n\nFor example,\n[`substitute_aliases([{color, colour}], L)`](`substitute_aliases/2`) replaces\nall tuples `{color, ...}` in `L` with `{colour, ...}`, and all atoms `color`\nwith `colour`.\n\nSee also `normalize/2`, `substitute_negations/2`.","title":"proplists.substitute_aliases/2","ref":"proplists.html#substitute_aliases/2"},{"type":"function","doc":"Substitutes keys of boolean-valued properties and simultaneously negates their\nvalues.\n\nFor each entry in `ListIn`, if it is associated with some key `K1` such\nthat `{K1, K2}` occurs in `Negations`: if the entry was `{K1, true}`, it is\nreplaced with `{K2, false}`, otherwise with `K2`, thus changing the name of the\noption and simultaneously negating the value specified by\n[`get_bool(Key, ListIn)`](`get_bool/2`). If the same `K1` occurs more than once\nin `Negations`, only the first occurrence is used.\n\nFor example,\n[`substitute_negations([{no_foo, foo}], L)`](`substitute_negations/2`) replaces\nany atom `no_foo` or tuple `{no_foo, true}` in `L` with `{foo, false}`, and any\nother tuple `{no_foo, ...}` with `foo`.\n\nSee also `get_bool/2`, `normalize/2`, `substitute_aliases/2`.","title":"proplists.substitute_negations/2","ref":"proplists.html#substitute_negations/2"},{"type":"function","doc":"Converts the property list `List` to a map.\n\nShorthand atom values in `List` will be expanded to an association of the form\n`Atom => true`. Tuples of the form `{Key, Value}` in `List` will be converted to\nan association of the form `Key => Value`. Anything else will be silently\nignored.\n\nIf the same key appears in `List` multiple times, the value of the one appearing\nnearest to the head of `List` will be in the result map, that is the value that\nwould be returned by a call to [`get_value(Key, List)`](`get_value/2`).\n\n_Example:_\n\n```erlang\nto_map([a, {b, 1}, {c, 2}, {c, 3}])\n```\n\nreturns:\n\n```erlang\n#{a => true, b => 1, c => 2}\n```","title":"proplists.to_map/1","ref":"proplists.html#to_map/1"},{"type":"function","doc":"Converts the property list `List` to a map after applying the normalizations\ngiven in `Stages`.\n\nSee also `normalize/2`, `to_map/1`.","title":"proplists.to_map/2","ref":"proplists.html#to_map/2"},{"type":"function","doc":"Unfolds all occurrences of atoms in `ListIn` to tuples `{Atom, true}`.\n\nSee also `compact/1`.","title":"proplists.unfold/1","ref":"proplists.html#unfold/1"},{"type":"type","doc":"A property item within a list","title":"proplists.property/0","ref":"proplists.html#t:property/0"},{"type":"type","doc":"A list of `t:property/0`, also knows as a proplist.","title":"proplists.proplist/0","ref":"proplists.html#t:proplist/0"},{"type":"module","doc":"This module provides a query interface to [Mnesia](`m:mnesia`), [ETS](`m:ets`),\n[Dets](`m:dets`), and other data structures that provide an iterator style\ntraversal of objects.","title":"qlc","ref":"qlc.html"},{"type":"module","doc":"This module provides a query interface to _QLC tables_. Typical QLC tables are\nMnesia, ETS, and Dets tables. Support is also provided for user-defined tables,\nsee section [Implementing a QLC Table](`m:qlc#implementing_a_qlc_table`). [](){:\n#query_list_comprehension } A _query_ is expressed using _Query List\nComprehensions_ (QLCs). The answers to a query are determined by data in QLC\ntables that fulfill the constraints expressed by the QLCs of the query. QLCs are\nsimilar to ordinary list comprehensions as described in\n[Erlang Reference Manual](`e:system:expressions.md#lcs`) and\n[Programming Examples](`e:system:list_comprehensions.md`), except that variables\nintroduced in patterns cannot be used in list expressions. In the absence of\noptimizations and options such as `cache` and `unique` (see section\n[Common Options](`m:qlc#common_options`), every QLC free of QLC tables evaluates\nto the same list of answers as the identical ordinary list comprehension.\n\nWhile ordinary list comprehensions evaluate to lists, calling [`q/1,2`](`q/1`)\nreturns a _query handle_{: #query_handle }. To obtain all the answers to a\nquery, [`eval/1,2`](`eval/1`) is to be called with the query handle as first\nargument. Query handles are essentially functional objects (funs) created in the\nmodule calling `q/1,2`. As the funs refer to the module code, be careful not to\nkeep query handles too long if the module code is to be replaced. Code\nreplacement is described in section\n[Compilation and Code Loading](`e:system:code_loading.md`) in the Erlang\nReference Manual. The list of answers can also be traversed in chunks by use of\na _query cursor_{: #query_cursor }. Query cursors are created by calling\n[`cursor/1,2`](`cursor/1`) with a query handle as first argument. Query cursors\nare essentially Erlang processes. One answer at a time is sent from the query\ncursor process to the process that created the cursor.","title":"Overview - qlc","ref":"qlc.html#module-overview"},{"type":"module","doc":"Syntactically QLCs have the same parts as ordinary list comprehensions:\n\n```text\n[Expression || Qualifier1, Qualifier2, ...]\n```\n\n`Expression` (the _template_) is any Erlang expression. Qualifiers are either\n_filters_ or _generators_. Filters are Erlang expressions returning\n`t:boolean/0`. Generators have the form `Pattern <- ListExpression`, where\n`ListExpression` is an expression evaluating to a query handle or a list. Query\nhandles are returned from [`append/1,2`](`append/1`),\n[`keysort/2,3`](`keysort/2`), [`q/1,2`](`q/1`), [`sort/1,2`](`sort/1`),\n[`string_to_handle/1,2,3`](`string_to_handle/1`), and `table/2`.","title":"Syntax - qlc","ref":"qlc.html#module-syntax"},{"type":"module","doc":"A query handle is evaluated in the following order:\n\n- Inspection of options and the collection of information about tables. As a\n result, qualifiers are modified during the optimization phase.\n- All list expressions are evaluated. If a cursor has been created, evaluation\n takes place in the cursor process. For list expressions that are QLCs, the\n list expressions of the generators of the QLCs are evaluated as well. Be\n careful if list expressions have side effects, as list expressions are\n evaluated in unspecified order.\n- The answers are found by evaluating the qualifiers from left to right,\n backtracking when some filter returns `false`, or collecting the template when\n all filters return `true`.\n\nFilters that do not return `t:boolean/0` but fail are handled differently\ndepending on their syntax: if the filter is a guard, it returns `false`,\notherwise the query evaluation fails. This behavior makes it possible for the\n`qlc` module to do some optimizations without affecting the meaning of a query.\nFor example, when testing some position of a table and one or more constants for\nequality, only the objects with equal values are candidates for further\nevaluation. The other objects are guaranteed to make the filter return `false`,\nbut never fail. The (small) set of candidate objects can often be found by\nlooking up some key values of the table or by traversing the table using a match\nspecification. It is necessary to place the guard filters immediately after the\ntable generator, otherwise the candidate objects are not restricted to a small\nset. The reason is that objects that could make the query evaluation fail must\nnot be excluded by looking up a key or running a match specification.","title":"Evaluation - qlc","ref":"qlc.html#module-evaluation"},{"type":"module","doc":"The `qlc` module supports fast join of two query handles. Fast join is possible\nif some position `P1` of one query handler and some position `P2` of another\nquery handler are tested for equality. Two fast join methods are provided:\n\n- _Lookup join_ traverses all objects of one query handle and finds objects of\n the other handle (a QLC table) such that the values at `P1` and `P2` match or\n compare equal. The `qlc` module does not create any indexes but looks up\n values using the key position and the indexed positions of the QLC table.\n- _Merge join_ sorts the objects of each query handle if necessary and filters\n out objects where the values at `P1` and `P2` do not compare equal. If many\n objects with the same value of `P2` exist, a temporary file is used for the\n equivalence classes.\n\nThe `qlc` module warns at compile time if a QLC combines query handles in such a\nway that more than one join is possible. That is, no query planner is provided\nthat can select a good order between possible join operations. It is up to the\nuser to order the joins by introducing query handles.\n\nThe join is to be expressed as a guard filter. The filter must be placed\nimmediately after the two joined generators, possibly after guard filters that\nuse variables from no other generators but the two joined generators. The `qlc`\nmodule inspects the operands of `=:=/2`, `==/2`, [`is_record/2`](`is_record/2`),\n[`element/2`](`element/2`), and logical operators (`and/2`, `or/2`, `andalso/2`,\n`orelse/2`, `xor/2`) when determining which joins to consider.\n\n[](){: #common_options }","title":"Join - qlc","ref":"qlc.html#module-join"},{"type":"module","doc":"The following options are accepted by `cursor/2`, `eval/2`, `fold/4`, and\n`info/2`:\n\n- `{cache_all, Cache}`, where `Cache` is equal to `ets` or `list` adds a\n `{cache, Cache}` option to every list expression of the query except tables\n and lists. Defaults to `{cache_all, no}`. Option `cache_all` is equivalent to\n `{cache_all, ets}`.\n- `{max_list_size, MaxListSize}`{: #max_list_size }, where `MaxListSize` is the\n size in bytes of terms on the external format. If the accumulated size of\n collected objects exceeds `MaxListSize`, the objects are written onto a\n temporary file. This option is used by option `{cache, list}` and by the merge\n join method. Defaults to 512\\*1024 bytes.\n- `{tmpdir_usage, TmpFileUsage}` determines the action taken when `qlc` is about\n to create temporary files on the directory set by option `tmpdir`. If the\n value is `not_allowed`, an error tuple is returned, otherwise temporary files\n are created as needed. Default is `allowed`, which means that no further\n action is taken. The values `info_msg`, `warning_msg`, and `error_msg` mean\n that the function with the corresponding name in module `m:error_logger` is\n called for printing some information (currently the stacktrace).\n- `{tmpdir, TempDirectory}` sets the directory used by merge join for temporary\n files and by option `{cache, list}`. The option also overrides option `tmpdir`\n of `keysort/3` and `sort/2`. Defaults to `\"\"`, which means that the directory\n returned by `file:get_cwd()` is used.\n- `{unique_all, true}` adds a `{unique, true}` option to every list expression\n of the query. Defaults to `{unique_all, false}`. Option `unique_all` is\n equivalent to `{unique_all, true}`.\n\n[](){: #getting_started }","title":"Common Options - qlc","ref":"qlc.html#module-common-options"},{"type":"module","doc":"As mentioned earlier, queries are expressed in the list comprehension syntax as\ndescribed in section [Expressions](`e:system:expressions.md`) in Erlang\nReference Manual. In the following, some familiarity with list comprehensions is\nassumed. The examples in section\n[List Comprehensions](`e:system:list_comprehensions.md`) in Programming Examples\ncan get you started. Notice that list comprehensions do not add any\ncomputational power to the language; anything that can be done with list\ncomprehensions can also be done without them. But they add syntax for expressing\nsimple search problems, which is compact and clear once you get used to it.\n\nMany list comprehension expressions can be evaluated by the `qlc` module.\nExceptions are expressions, such that variables introduced in patterns (or\nfilters) are used in some generator later in the list comprehension. As an\nexample, consider an implementation of `lists:append(L)`:\n`[X ||Y <- L, X <- Y]`. `Y` is introduced in the first generator and used in the\nsecond. The ordinary list comprehension is normally to be preferred when there\nis a choice as to which to use. One difference is that [`eval/1,2`](`eval/1`)\ncollects answers in a list that is finally reversed, while list comprehensions\ncollect answers on the stack that is finally unwound.\n\nWhat the `qlc` module primarily adds to list comprehensions is that data can be\nread from QLC tables in small chunks. A QLC table is created by calling\n[`qlc:table/2`](`table/2`). Usually `qlc:table/2` is not called directly from\nthe query but through an interface function of some data structure. Erlang/OTP\nincludes a few examples of such functions:\n[`mnesia:table/1,2`](`mnesia:table/1`), [`ets:table/1,2`](`ets:table/1`), and\n[`dets:table/1,2`](`dets:table/1`). For a given data structure, many functions\ncan create QLC tables, but common for these functions is that they return a\nquery handle created by [`qlc:table/2`](`table/2`). Using the QLC tables\nprovided by Erlang/OTP is usually probably sufficient, but for the more advanced\nuser section [Implementing a QLC Table](`m:qlc#implementing_a_qlc_table`)\ndescribes the implementation of a function calling `qlc:table/2`.\n\nBesides `qlc:table/2`, other functions return query handles. They are used more\nseldom than tables, but are sometimes useful. [`qlc:append/1,2`](`append/1`)\ntraverses objects from many tables or lists after each other. If, for example,\nyou want to traverse all answers to a query `QH` and then finish off by a term\n`{finished}`, you can do that by calling `qlc:append(QH, [{finished}])`.\n[`append/2`](`append/2`) first returns all objects of `QH`, then `{finished}`.\nIf a tuple `{finished}` exists among the answers to `QH`, it is returned twice\nfrom [`append/2`](`append/2`).\n\nAs another example, consider concatenating the answers to two queries `QH1` and\n`QH2` while removing all duplicates. This is accomplished by using option\n`unique`:\n\n```erlang\nqlc:q([X || X <- qlc:append(QH1, QH2)], {unique, true})\n```\n\nThe cost is substantial: every returned answer is stored in an ETS table. Before\nreturning an answer, it is looked up in the ETS table to check if it has already\nbeen returned. Without the `unique` option, all answers to `QH1` would be\nreturned followed by all answers to `QH2`. The `unique` option keeps the order\nbetween the remaining answers.\n\nIf the order of the answers is not important, there is an alternative to the\n`unique` option, namely to sort the answers uniquely:\n\n```erlang\nqlc:sort(qlc:q([X || X <- qlc:append(QH1, QH2)], {unique, true})).\n```\n\nThis query also removes duplicates but the answers are sorted. If there are many\nanswers, temporary files are used. Notice that to get the first unique answer,\nall answers must be found and sorted. Both alternatives find duplicates by\ncomparing answers, that is, if `A1` and `A2` are answers found in that order,\nthen `A2` is a removed if `A1 == A2`.\n\nTo return only a few answers, cursors can be used. The following code returns no\nmore than five answers using an ETS table for storing the unique answers:\n\n```erlang\nC = qlc:cursor(qlc:q([X || X <- qlc:append(QH1, QH2)],{unique,true})),\nR = qlc:next_answers(C, 5),\nok = qlc:delete_cursor(C),\nR.\n```\n\nQLCs are convenient for stating constraints on data from two or more tables. The\nfollowing example does a natural join on two query handles on position 2:\n\n```erlang\nqlc:q([{X1,X2,X3,Y1} ||\n {X1,X2,X3} <- QH1,\n {Y1,Y2} <- QH2,\n X2 =:= Y2])\n```\n\nThe `qlc` module evaluates this differently depending on the query handles `QH1`\nand `QH2`. If, for example, `X2` is matched against the key of a QLC table, the\nlookup join method traverses the objects of `QH2` while looking up key values in\nthe table. However, if not `X2` or `Y2` is matched against the key or an indexed\nposition of a QLC table, the merge join method ensures that `QH1` and `QH2` are\nboth sorted on position 2 and next do the join by traversing the objects one by\none.\n\nOption `join` can be used to force the `qlc` module to use a certain join\nmethod. For the rest of this section it is assumed that the excessively slow\njoin method called \"nested loop\" has been chosen:\n\n```erlang\nqlc:q([{X1,X2,X3,Y1} ||\n {X1,X2,X3} <- QH1,\n {Y1,Y2} <- QH2,\n X2 =:= Y2],\n {join, nested_loop})\n```\n\nIn this case the filter is applied to every possible pair of answers to `QH1`\nand `QH2`, one at a time. If there are M answers to `QH1` and N answers to\n`QH2`, the filter is run M\\*N times.\n\nIf `QH2` is a call to the function for `m:gb_trees`, as defined in section\n[Implementing a QLC Table](`m:qlc#implementing_a_qlc_table`), then\n[`gb_table:table/1` ](`m:qlc#gb_table`), the iterator for the gb-tree is\ninitiated for each answer to `QH1`. The objects of the gb-tree are then returned\none by one. This is probably the most efficient way of traversing the table in\nthat case, as it takes minimal computational power to get the following object.\nBut if `QH2` is not a table but a more complicated QLC, it can be more efficient\nto use some RAM memory for collecting the answers in a cache, particularly if\nthere are only a few answers. It must then be assumed that evaluating `QH2` has\nno side effects so that the meaning of the query does not change if `QH2` is\nevaluated only once. One way of caching the answers is to evaluate `QH2` first\nof all and substitute the list of answers for `QH2` in the query. Another way is\nto use option `cache`. It is expressed like this:\n\n```erlang\nQH2' = qlc:q([X || X <- QH2], {cache, ets})\n```\n\nor only\n\n```text\nQH2' = qlc:q([X || X <- QH2], cache)\n```\n\nThe effect of option `cache` is that when generator `QH2'` is run the first\ntime, every answer is stored in an ETS table. When the next answer of `QH1` is\ntried, answers to `QH2'` are copied from the ETS table, which is very fast. As\nfor option `unique` the cost is a possibly substantial amount of RAM memory.\n\nOption `{cache, list}` offers the possibility to store the answers in a list on\nthe process heap. This has the potential of being faster than ETS tables, as\nthere is no need to copy answers from the table. However, it can often result in\nslower evaluation because of more garbage collections of the process heap and\nincreased RAM memory consumption because of larger heaps. Another drawback with\ncache lists is that if the list size exceeds a limit, a temporary file is used.\nReading the answers from a file is much slower than copying them from an ETS\ntable. But if the available RAM memory is scarce, setting the\n[limit](`m:qlc#max_list_size`) to some low value is an alternative.\n\nOption `cache_all` can be set to `ets` or `list` when evaluating a query. It\nadds a `cache` or `{cache, list}` option to every list expression except QLC\ntables and lists on all levels of the query. This can be used for testing if\ncaching would improve efficiency at all. If the answer is yes, further testing\nis needed to pinpoint the generators that are to be cached.\n\n[](){: #implementing_a_qlc_table }","title":"Getting Started - qlc","ref":"qlc.html#module-getting-started"},{"type":"module","doc":"As an example of how to use function `table/2`, the implementation of a QLC\ntable for the `m:gb_trees` module is given:\n\n[](){: #gb_table }\n\n```erlang\n-module(gb_table).\n\n-export([table/1]).\n\ntable(T) ->\n TF = fun() -> qlc_next(gb_trees:next(gb_trees:iterator(T))) end,\n InfoFun = fun(num_of_objects) -> gb_trees:size(T);\n (keypos) -> 1;\n (is_sorted_key) -> true;\n (is_unique_objects) -> true;\n (_) -> undefined\n end,\n LookupFun =\n fun(1, Ks) ->\n lists:flatmap(fun(K) ->\n case gb_trees:lookup(K, T) of\n {value, V} -> [{K,V}];\n none -> []\n end\n end, Ks)\n end,\n FormatFun =\n fun({all, NElements, ElementFun}) ->\n ValsS = io_lib:format(\"gb_trees:from_orddict(~w)\",\n [gb_nodes(T, NElements, ElementFun)]),\n io_lib:format(\"gb_table:table(~s)\", [ValsS]);\n ({lookup, 1, KeyValues, _NElements, ElementFun}) ->\n ValsS = io_lib:format(\"gb_trees:from_orddict(~w)\",\n [gb_nodes(T, infinity, ElementFun)]),\n io_lib:format(\"lists:flatmap(fun(K) -> \"\n \"case gb_trees:lookup(K, ~s) of \"\n \"{value, V} -> [{K,V}];none -> [] end \"\n \"end, ~w)\",\n [ValsS, [ElementFun(KV) || KV <- KeyValues]])\n end,\n qlc:table(TF, [{info_fun, InfoFun}, {format_fun, FormatFun},\n {lookup_fun, LookupFun},{key_equality,'=='}]).\n\nqlc_next({X, V, S}) ->\n [{X,V} | fun() -> qlc_next(gb_trees:next(S)) end];\nqlc_next(none) ->\n [].\n\ngb_nodes(T, infinity, ElementFun) ->\n gb_nodes(T, -1, ElementFun);\ngb_nodes(T, NElements, ElementFun) ->\n gb_iter(gb_trees:iterator(T), NElements, ElementFun).\n\ngb_iter(_I, 0, _EFun) ->\n '...';\ngb_iter(I0, N, EFun) ->\n case gb_trees:next(I0) of\n {X, V, I} ->\n [EFun({X,V}) | gb_iter(I, N-1, EFun)];\n none ->\n []\n end.\n```\n\n`TF` is the traversal function. The `qlc` module requires that there is a way of\ntraversing all objects of the data structure. `gb_trees` has an iterator\nfunction suitable for that purpose. Notice that for each object returned, a new\nfun is created. As long as the list is not terminated by `[]`, it is assumed\nthat the tail of the list is a nullary function and that calling the function\nreturns further objects (and functions).\n\nThe lookup function is optional. It is assumed that the lookup function always\nfinds values much faster than it would take to traverse the table. The first\nargument is the position of the key. As `qlc_next/1` returns the objects as\n`{Key, Value}` pairs, the position is 1. Notice that the lookup function is to\nreturn `{Key, Value}` pairs, as the traversal function does.\n\nThe format function is also optional. It is called by [`info/1,2`](`info/1`) to\ngive feedback at runtime of how the query is to be evaluated. Try to give as\ngood feedback as possible without showing too much details. In the example, at\nmost seven objects of the table are shown. The format function handles two\ncases: `all` means that all objects of the table are traversed;\n`{lookup, 1, KeyValues}` means that the lookup function is used for looking up\nkey values.\n\nWhether the whole table is traversed or only some keys looked up depends on how\nthe query is expressed. If the query has the form\n\n```text\nqlc:q([T || P <- LE, F])\n```\n\nand `P` is a tuple, the `qlc` module analyzes `P` and `F` in compile time to\nfind positions of tuple `P` that are tested for equality to constants. If such a\nposition at runtime turns out to be the key position, the lookup function can be\nused, otherwise all objects of the table must be traversed. The info function\n`InfoFun` returns the key position. There can be indexed positions as well, also\nreturned by the info function. An index is an extra table that makes lookup on\nsome position fast. Mnesia maintains indexes upon request, and introduces so\ncalled secondary keys. The `qlc` module prefers to look up objects using the key\nbefore secondary keys regardless of the number of constants to look up.","title":"Implementing a QLC Table - qlc","ref":"qlc.html#module-implementing-a-qlc-table"},{"type":"module","doc":"Erlang/OTP has two operators for testing term equality: `==/2` and `=:=/2`. The\ndifference is all about the integers that can be represented by floats. For\nexample, `2 == 2.0` evaluates to `true` while `2 =:= 2.0` evaluates to `false`.\nNormally this is a minor issue, but the `qlc` module cannot ignore the\ndifference, which affects the user's choice of operators in QLCs.\n\nIf the `qlc` module at compile time can determine that some constant is free of\nintegers, it does not matter which one of `==/2` or `=:=/2` is used:\n\n```erlang\n1> E1 = ets:new(t, [set]), % uses =:=/2 for key equality\nQ1 = qlc:q([K ||\n{K} <- ets:table(E1),\nK == 2.71 orelse K == a]),\nio:format(\"~s~n\", [qlc:info(Q1)]).\nets:match_spec_run(\n lists:flatmap(fun(V) ->\n\t\t\t ets:lookup(#Ref<0.3098908599.2283929601.256025>,\n\t\t\t\t V)\n\t\t end,\n\t\t [a, 2.71]),\n ets:match_spec_compile([{{'$1'}, [], ['$1']}]))\n```\n\nIn the example, operator `==/2` has been handled exactly as `=:=/2` would have\nbeen handled. However, if it cannot be determined at compile time that some\nconstant is free of integers, and the table uses `=:=/2` when comparing keys for\nequality (see option [key_equality](`m:qlc#key_equality`)), then the `qlc`\nmodule does not try to look up the constant. The reason is that there is in the\ngeneral case no upper limit on the number of key values that can compare equal\nto such a constant; every combination of integers and floats must be looked up:\n\n```erlang\n2> E2 = ets:new(t, [set]),\ntrue = ets:insert(E2, [{{2,2},a},{{2,2.0},b},{{2.0,2},c}]),\nF2 = fun(I) ->\nqlc:q([V || {K,V} <- ets:table(E2), K == I])\nend,\nQ2 = F2({2,2}),\nio:format(\"~s~n\", [qlc:info(Q2)]).\nets:table(#Ref<0.3098908599.2283929601.256125>,\n [{traverse,\n {select,\n [{{'$1', '$2'}, [{'==', '$1', {const, {2, 2}}}], ['$2']}]}}])\n3> lists:sort(qlc:e(Q2)).\n[a,b,c]\n```\n\nLooking up only `{2,2}` would not return `b` and `c`.\n\nIf the table uses `==/2` when comparing keys for equality, the `qlc` module\nlooks up the constant regardless of which operator is used in the QLC. However,\n`==/2` is to be preferred:\n\n```erlang\n4> E3 = ets:new(t, [ordered_set]), % uses ==/2 for key equality\ntrue = ets:insert(E3, [{{2,2.0},b}]),\nF3 = fun(I) ->\nqlc:q([V || {K,V} <- ets:table(E3), K == I])\nend,\nQ3 = F3({2,2}),\nio:format(\"~s~n\", [qlc:info(Q3)]).\nets:match_spec_run(ets:lookup(#Ref<0.3098908599.2283929601.256211>,\n {2, 2}),\n ets:match_spec_compile([{{'$1', '$2'}, [], ['$2']}]))\n5> qlc:e(Q3).\n[b]\n```\n\nLookup join is handled analogously to lookup of constants in a table: if the\njoin operator is `==/2`, and the table where constants are to be looked up uses\n`=:=/2` when testing keys for equality, then the `qlc` module does not consider\nlookup join for that table.","title":"Key Equality - qlc","ref":"qlc.html#module-key-equality"},{"type":"module","doc":"`m:dets`, `m:erl_eval`, `m:erlang`, `m:error_logger`, `m:ets`, `m:file`,\n`m:file_sorter`, `m:mnesia`, `m:shell`,\n[Erlang Reference Manual](`e:system:index.html`),\n[Programming Examples](`e:system:index.html`)","title":"See Also - qlc","ref":"qlc.html#module-see-also"},{"type":"function","doc":"Returns a query handle. When evaluating query handle `QH`, all answers to the\nfirst query handle in `QHL` are returned, followed by all answers to the\nremaining query handles in `QHL`.","title":"qlc.append/1","ref":"qlc.html#append/1"},{"type":"function","doc":"Returns a query handle. When evaluating query handle `QH3`, all answers to `QH1`\nare returned, followed by all answers to `QH2`.\n\n[`append(QH1, QH2)`](`append/2`) is equivalent to\n[`append([QH1, QH2])`](`append/1`).","title":"qlc.append/2","ref":"qlc.html#append/2"},{"type":"function","doc":"","title":"qlc.cursor/1","ref":"qlc.html#cursor/1"},{"type":"function","doc":"Creates a query cursor and makes the calling process the owner of the cursor.\n\nThe cursor is to be used as argument to [`next_answers/1,2`](`next_answers/1`)\nand (eventually) `delete_cursor/1`. Calls `erlang:spawn_opt/2` to spawn and link\nto a process that evaluates the query handle. The value of option\n`spawn_options` is used as last argument when calling\n[`spawn_opt/2`](`spawn_opt/2`). Defaults to `[link]`.\n\n_Example:_\n\n```erlang\n1> QH = qlc:q([{X,Y} || X <- [a,b], Y <- [1,2]]),\nQC = qlc:cursor(QH),\nqlc:next_answers(QC, 1).\n[{a,1}]\n2> qlc:next_answers(QC, 1).\n[{a,2}]\n3> qlc:next_answers(QC, all_remaining).\n[{b,1},{b,2}]\n4> qlc:delete_cursor(QC).\nok\n```","title":"qlc.cursor/2","ref":"qlc.html#cursor/2"},{"type":"function","doc":"Deletes a query cursor. Only the owner of the cursor can delete the cursor.","title":"qlc.delete_cursor/1","ref":"qlc.html#delete_cursor/1"},{"type":"function","doc":"","title":"qlc.e/1","ref":"qlc.html#e/1"},{"type":"function","doc":"","title":"qlc.e/2","ref":"qlc.html#e/2"},{"type":"function","doc":"","title":"qlc.eval/1","ref":"qlc.html#eval/1"},{"type":"function","doc":"Evaluates a query handle in the calling process and collects all answers in a\nlist.\n\n_Example:_\n\n```erlang\n1> QH = qlc:q([{X,Y} || X <- [a,b], Y <- [1,2]]),\nqlc:eval(QH).\n[{a,1},{a,2},{b,1},{b,2}]\n```","title":"qlc.eval/2","ref":"qlc.html#eval/2"},{"type":"function","doc":"","title":"qlc.fold/3","ref":"qlc.html#fold/3"},{"type":"function","doc":"Calls `Function` on successive answers to the query handle together with an\nextra argument `AccIn`.\n\nThe query handle and the function are evaluated in the\ncalling process. `Function` must return a new accumulator, which is passed to\nthe next call. `Acc0` is returned if there are no answers to the query handle.\n\n_Example:_\n\n```erlang\n1> QH = [1,2,3,4,5,6],\nqlc:fold(fun(X, Sum) -> X + Sum end, 0, QH).\n21\n```","title":"qlc.fold/4","ref":"qlc.html#fold/4"},{"type":"function","doc":"Returns a descriptive string in English of an error tuple returned by some of\nthe functions of the `qlc` module or the parse transform. This function is\nmainly used by the compiler invoking the parse transform.","title":"qlc.format_error/1","ref":"qlc.html#format_error/1"},{"type":"function","doc":"","title":"qlc.info/1","ref":"qlc.html#info/1"},{"type":"function","doc":"Returns information about a query handle. The information describes the\nsimplifications and optimizations that are the results of preparing the query\nfor evaluation. This function is probably mainly useful during debugging.\n\nThe information has the form of an Erlang expression where QLCs most likely\noccur. Depending on the format functions of mentioned QLC tables, it is not\ncertain that the information is absolutely accurate.\n\nOptions:\n\n- The default is to return a sequence of QLCs in a block, but if option\n `{flat, false}` is specified, one single QLC is returned.\n- The default is to return a string, but if option `{format, abstract_code}` is\n specified, abstract code is returned instead. In the abstract code, port\n identifiers, references, and pids are represented by strings.\n- The default is to return all elements in lists, but if option\n `{n_elements, NElements}` is specified, only a limited number of elements are\n returned.\n- The default is to show all parts of objects and match specifications, but if\n option `{depth, Depth}` is specified, parts of terms below a certain depth are\n replaced by `'...'`.\n\n_Examples:_\n\nIn the following example two simple QLCs are inserted only to hold option\n`{unique, true}`:\n\n```erlang\n1> QH = qlc:q([{X,Y} || X <- [x,y], Y <- [a,b]]),\nio:format(\"~s~n\", [qlc:info(QH, unique_all)]).\nbegin\n V1 =\n qlc:q([\n SQV ||\n SQV <- [x, y]\n ],\n [{unique, true}]),\n V2 =\n qlc:q([\n SQV ||\n SQV <- [a, b]\n ],\n [{unique, true}]),\n qlc:q([\n {X,Y} ||\n X <- V1,\n Y <- V2\n ],\n [{unique, true}])\nend\n```\n\nIn the following example QLC `V2` has been inserted to show the joined\ngenerators and the join method chosen. A convention is used for lookup join: the\nfirst generator (`G2`) is the one traversed, the second (`G1`) is the table\nwhere constants are looked up.\n\n```erlang\n1> E1 = ets:new(e1, []),\nE2 = ets:new(e2, []),\ntrue = ets:insert(E1, [{1,a},{2,b}]),\ntrue = ets:insert(E2, [{a,1},{b,2}]),\nQ = qlc:q([{X,Z,W} ||\n{X, Z} <- ets:table(E1),\n{W, Y} <- ets:table(E2),\nX =:= Y]),\nio:format(\"~s~n\", [qlc:info(Q)]).\nbegin\n V1 =\n qlc:q([\n P0 ||\n P0 = {W, Y} <-\n ets:table(#Ref<0.3098908599.2283929601.256549>)\n ]),\n V2 =\n qlc:q([\n [G1 | G2] ||\n G2 <- V1,\n G1 <-\n ets:table(#Ref<0.3098908599.2283929601.256548>),\n element(2, G1) =:= element(1, G2)\n ],\n [{join, lookup}]),\n qlc:q([\n {X, Z, W} ||\n [{X, Z} | {W, Y}] <- V2\n ])\nend\n```","title":"qlc.info/2","ref":"qlc.html#info/2"},{"type":"function","doc":"","title":"qlc.keysort/2","ref":"qlc.html#keysort/2"},{"type":"function","doc":"Returns a query handle. When evaluating query handle `QH2`, the answers to query\nhandle `QH1` are sorted by `file_sorter:keysort/4` according to the options.\n\nThe sorter uses temporary files only if `QH1` does not evaluate to a list and\nthe size of the binary representation of the answers exceeds `Size` bytes, where\n`Size` is the value of option `size`.","title":"qlc.keysort/3","ref":"qlc.html#keysort/3"},{"type":"function","doc":"","title":"qlc.next_answers/1","ref":"qlc.html#next_answers/1"},{"type":"function","doc":"Returns some or all of the remaining answers to a query cursor. Only the owner\nof `QueryCursor` can retrieve answers.\n\nArgument `NumberOfAnswers` determines the maximum number of answers\nreturned. If less than the requested number of answers is\nreturned, subsequent calls to `next_answers` return `[]`.","title":"qlc.next_answers/2","ref":"qlc.html#next_answers/2"},{"type":"function","doc":"","title":"qlc.q/1","ref":"qlc.html#q/1"},{"type":"function","doc":"Returns a query handle for a QLC. The QLC must be the first argument to this\nfunction, otherwise it is evaluated as an ordinary list comprehension. It is\nalso necessary to add the following line to the source code:\n\n```erlang\n-include_lib(\"stdlib/include/qlc.hrl\").\n```\n\nThis causes a parse transform to substitute a fun for the QLC. The (compiled)\nfun is called when the query handle is evaluated.\n\nWhen calling `qlc:q/1,2` from the Erlang shell, the parse transform is\nautomatically called. When this occurs, the fun substituted for the QLC is not\ncompiled but is evaluated by `m:erl_eval`. This is also true when expressions\nare evaluated by `file:eval/1,2` or in the debugger.\n\nTo be explicit, this does not work:\n\n```erlang\n...\nA = [X || {X} <- [{1},{2}]],\nQH = qlc:q(A),\n...\n```\n\nVariable `A` is bound to the evaluated value of the list comprehension\n(`[1,2]`). The compiler complains with an error message (\"argument is not a\nquery list comprehension\"); the shell process stops with a `badarg` reason.\n\nOptions:\n\n- Option `{cache, ets}` can be used to cache the answers to a QLC. The answers\n are stored in one ETS table for each cached QLC. When a cached QLC is\n evaluated again, answers are fetched from the table without any further\n computations. Therefore, when all answers to a cached QLC have been found, the\n ETS tables used for caching answers to the qualifiers of the QLC can be\n emptied. Option `cache` is equivalent to `{cache, ets}`.\n- Option `{cache, list}` can be used to cache the answers to a QLC like\n `{cache, ets}`. The difference is that the answers are kept in a list (on the\n process heap). If the answers would occupy more than a certain amount of RAM\n memory, a temporary file is used for storing the answers. Option\n `max_list_size` sets the limit in bytes and the temporary file is put on the\n directory set by option `tmpdir`.\n\n Option `cache` has no effect if it is known that the QLC is to be evaluated at\n most once. This is always true for the top-most QLC and also for the list\n expression of the first generator in a list of qualifiers. Notice that in the\n presence of side effects in filters or callback functions, the answers to QLCs\n can be affected by option `cache`.\n\n- Option `{unique, true}` can be used to remove duplicate answers to a QLC. The\n unique answers are stored in one ETS table for each QLC. The table is emptied\n every time it is known that there are no more answers to the QLC. Option\n `unique` is equivalent to `{unique, true}`. If option `unique` is combined\n with option `{cache, ets}`, two ETS tables are used, but the full answers are\n stored in one table only. If option `unique` is combined with option\n `{cache, list}`, the answers are sorted twice using `keysort/3`; once to\n remove duplicates and once to restore the order.\n\nOptions `cache` and `unique` apply not only to the QLC itself but also to the\nresults of looking up constants, running match specifications, and joining\nhandles.\n\n_Example:_\n\nIn the following example the cached results of the merge join are traversed for\neach value of `A`. Notice that without option `cache` the join would have been\ncarried out three times, once for each value of `A`.\n\n```erlang\n1> Q = qlc:q([{A,X,Z,W} ||\nA <- [a,b,c],\n{X,Z} <- [{a,1},{b,4},{c,6}],\n{W,Y} <- [{2,a},{3,b},{4,c}],\nX =:= Y],\n{cache, list}),\nio:format(\"~s~n\", [qlc:info(Q)]).\nbegin\n V1 =\n qlc:q([\n P0 ||\n P0 = {X, Z} <-\n qlc:keysort(1, [{a, 1}, {b, 4}, {c, 6}], [])\n ]),\n V2 =\n qlc:q([\n P0 ||\n P0 = {W, Y} <-\n qlc:keysort(2, [{2, a}, {3, b}, {4, c}], [])\n ]),\n V3 =\n qlc:q([\n [G1 | G2] ||\n G1 <- V1,\n G2 <- V2,\n element(1, G1) == element(2, G2)\n ],\n [{join, merge}, {cache, list}]),\n qlc:q([\n {A, X, Z, W} ||\n A <- [a, b, c],\n [{X, Z} | {W, Y}] <- V3,\n X =:= Y\n ])\nend\n```\n\n[`sort/1,2`](`sort/1`) and [`keysort/2,3`](`keysort/2`) can also be used for\ncaching answers and for removing duplicates. When sorting answers are cached in\na list, possibly stored on a temporary file, and no ETS tables are used.\n\nSometimes (see `table/2`) traversal of tables can be done by looking up key\nvalues, which is assumed to be fast. Under certain (rare) circumstances there\ncan be too many key values to look up. [](){: #max_lookup } Option\n`{max_lookup, MaxLookup}` can then be used to limit the number of lookups: if\nmore than `MaxLookup` lookups would be required, no lookups are done but the\ntable is traversed instead. Defaults to `infinity`, which means that there is no\nlimit on the number of keys to look up.\n\n_Example:_\n\nIn the following example, using the `gb_table` module from section\n[Implementing a QLC Table](`m:qlc#implementing_a_qlc_table`), there are six keys\nto look up: `{1,a}`, `{1,b}`, `{1,c}`, `{2,a}`, `{2,b}`, and `{2,c}`. The reason\nis that the two elements of key `{X, Y}` are compared separately.\n\n```erlang\n1> T = gb_trees:empty(),\nQH = qlc:q([X || {{X,Y},_} <- gb_table:table(T),\n((X == 1) or (X == 2)) andalso\n((Y == a) or (Y == b) or (Y == c))]),\nio:format(\"~s~n\", [qlc:info(QH)]).\nets:match_spec_run(\n lists:flatmap(fun(K) ->\n case\n gb_trees:lookup(K,\n gb_trees:from_orddict([]))\n of\n {value, V} ->\n [{K, V}];\n none ->\n []\n end\n end,\n [{1, a},\n {1, b},\n {1, c},\n {2, a},\n {2, b},\n {2, c}]),\n ets:match_spec_compile([{{{'$1', '$2'}, '_'},\n [],\n ['$1']}]))\n```\n\nOptions:\n\n- Option `{lookup, true}` can be used to ensure that the `qlc` module looks up\n constants in some QLC table. If there are more than one QLC table among the\n list expressions of the generators, constants must be looked up in at least\n one of the tables. The evaluation of the query fails if there are no constants\n to look up. This option is useful when it would be unacceptable to traverse\n all objects in some table. Setting option `lookup` to `false` ensures that no\n constants are looked up (`{max_lookup, 0}` has the same effect). Defaults to\n `any`, which means that constants are looked up whenever possible.\n- Option `{join, Join}` can be used to ensure that a certain join method is\n used:\n\n - `{join, lookup}` invokes the lookup join method.\n - `{join, merge}` invokes the merge join method.\n - `{join, nested_loop}` invokes the method of matching every pair of objects\n from two handles. This method is mostly very slow.\n\n The evaluation of the query fails if the `qlc` module cannot carry out the\n chosen join method. Defaults to `any`, which means that some fast join method\n is used if possible.","title":"qlc.q/2","ref":"qlc.html#q/2"},{"type":"function","doc":"","title":"qlc.sort/1","ref":"qlc.html#sort/1"},{"type":"function","doc":"Returns a query handle. When evaluating query handle `QH2`, the answers to query\nhandle `QH1` are sorted by `file_sorter:sort/3` according to the options.\n\nThe sorter uses temporary files only if `QH1` does not evaluate to a list and\nthe size of the binary representation of the answers exceeds `Size` bytes, where\n`Size` is the value of option `size`.","title":"qlc.sort/2","ref":"qlc.html#sort/2"},{"type":"function","doc":"","title":"qlc.string_to_handle/1","ref":"qlc.html#string_to_handle/1"},{"type":"function","doc":"","title":"qlc.string_to_handle/2","ref":"qlc.html#string_to_handle/2"},{"type":"function","doc":"A string version of [`q/1,2`](`q/1`). When the query handle is evaluated, the\nfun created by the parse transform is interpreted by `m:erl_eval`. The query\nstring is to be one single QLC terminated by a period.\n\n_Example:_\n\n```erlang\n1> L = [1,2,3],\nBs = erl_eval:add_binding('L', L, erl_eval:new_bindings()),\nQH = qlc:string_to_handle(\"[X+1 || X <- L].\", [], Bs),\nqlc:eval(QH).\n[2,3,4]\n```\n\nThis function is probably mainly useful when called from outside of Erlang, for\nexample from a driver written in C.\n\n> #### Note {: .info }\n>\n> Query handles created this way may have worse performance than when created\n> directly via [`q/1,2`](`q/1`).","title":"qlc.string_to_handle/3","ref":"qlc.html#string_to_handle/3"},{"type":"function","doc":"Returns a query handle for a QLC table. In Erlang/OTP there is support for ETS,\nDets, and Mnesia tables, but many other data structures can be turned into QLC\ntables. This is accomplished by letting function(s) in the module implementing\nthe data structure create a query handle by calling `qlc:table/2`.\n\nThe different ways to traverse the table and properties of the table are handled\nby callback functions provided as options to `qlc:table/2`.\n\n- Callback function `TraverseFun` is used for traversing the table. It is to\n return a list of objects terminated by either `[]` or a nullary fun to be used\n for traversing the not yet traversed objects of the table. Any other return\n value is immediately returned as value of the query evaluation. Unary\n `TraverseFun`s are to accept a match specification as argument. The match\n specification is created by the parse transform by analyzing the pattern of\n the generator calling `qlc:table/2` and filters using variables introduced in\n the pattern. If the parse transform cannot find a match specification\n equivalent to the pattern and filters, `TraverseFun` is called with a match\n specification returning every object.\n\n - Modules that can use match specifications for optimized traversal of tables\n are to call `qlc:table/2` with an unary `TraverseFun`. An example is\n `ets:table/2`.\n - Other modules can provide a nullary `TraverseFun`. An example is\n [`gb_table:table/1`](`m:qlc#gb_table`) in section\n [Implementing a QLC Table](`m:qlc#implementing_a_qlc_table`).\n\n- Unary callback function `PreFun` is called once before the table is read for\n the first time. If the call fails, the query evaluation fails.\n\n Argument `PreArgs` is a list of tagged values. There are two tags,\n `parent_value` and `stop_fun`, used by Mnesia for managing transactions.\n\n - The value of `parent_value` is the value returned by `ParentFun`, or\n `undefined` if there is no `ParentFun`. `ParentFun` is called once just\n before the call of `PreFun` in the context of the process calling\n [`eval/1,2`](`eval/1`), [`fold/3,4`](`fold/3`), or\n [`cursor/1,2`](`cursor/1`).\n - The value of `stop_fun` is a nullary fun that deletes the cursor if called\n from the parent, or `undefined` if there is no cursor.\n\n- Nullary callback function `PostFun` is called once after the table was last\n read. The return value, which is caught, is ignored. If `PreFun` has been\n called for a table, `PostFun` is guaranteed to be called for that table, even\n if the evaluation of the query fails for some reason.\n\n The pre (post) functions for different tables are evaluated in unspecified\n order.\n\n Other table access than reading, such as calling `InfoFun`, is assumed to be\n OK at any time.\n\n- [](){: #lookup_fun } Binary callback function `LookupFun` is used for looking\n up objects in the table. The first argument `Position` is the key position or\n an indexed position and the second argument `Keys` is a sorted list of unique\n values. The return value is to be a list of all objects (tuples), such that\n the element at `Position` is a member of `Keys`. Any other return value is\n immediately returned as value of the query evaluation. `LookupFun` is called\n instead of traversing the table if the parse transform at compile time can\n determine that the filters match and compare the element at `Position` in such\n a way that only `Keys` need to be looked up to find all potential answers.\n\n The key position is obtained by calling `InfoFun(keypos)` and the indexed\n positions by calling `InfoFun(indices)`. If the key position can be used for\n lookup, it is always chosen, otherwise the indexed position requiring the\n least number of lookups is chosen. If there is a tie between two indexed\n positions, the one occurring first in the list returned by `InfoFun` is\n chosen. Positions requiring more than [max_lookup](`m:qlc#max_lookup`) lookups\n are ignored.\n\n- Unary callback function `InfoFun` is to return information about the table.\n `undefined` is to be returned if the value of some tag is unknown:\n\n - **`indices`** - Returns a list of indexed positions, a list of positive\n integers.\n\n - **`is_unique_objects`** - Returns `true` if the objects returned by\n `TraverseFun` are unique.\n\n - **`keypos`** - Returns the position of the table key, a positive integer.\n\n - **`is_sorted_key`** - Returns `true` if the objects returned by\n `TraverseFun` are sorted on the key.\n\n - **`num_of_objects`** - Returns the number of objects in the table, a\n non-negative integer.\n\n- Unary callback function `FormatFun` is used by [`info/1,2`](`info/1`) for\n displaying the call that created the query handle of the table. Defaults to\n `undefined`, which means that `info/1,2` displays a call to `'$MOD':'$FUN'/0`.\n It is up to `FormatFun` to present the selected objects of the table in a\n suitable way. However, if a character list is chosen for presentation, it must\n be an Erlang expression that can be scanned and parsed (a trailing dot is\n added by `info/1,2` though).\n\n `FormatFun` is called with an argument that describes the selected objects\n based on optimizations done as a result of analyzing the filters of the QLC\n where the call to `qlc:table/2` occurs. The argument can have the following\n values:\n\n - **`{lookup, Position, Keys, NElements, DepthFun}`.** - `LookupFun` is used\n for looking up objects in the table.\n\n - **`{match_spec, MatchExpression}`** - No way of finding all possible answers\n by looking up keys was found, but the filters could be transformed into a\n match specification. All answers are found by calling\n `TraverseFun(MatchExpression)`.\n\n - **`{all, NElements, DepthFun}`** - No optimization was found. A match\n specification matching all objects is used if `TraverseFun` is unary.\n\n `NElements` is the value of the `info/1,2` option `n_elements`.\n\n `DepthFun` is a function that can be used for limiting the size of terms;\n calling `DepthFun(Term)` substitutes `'...'` for parts of `Term` below the\n depth specified by the `info/1,2` option `depth`.\n\n If calling `FormatFun` with an argument including `NElements` and `DepthFun`\n fails, `FormatFun` is called once again with an argument excluding\n `NElements` and `DepthFun` (`{lookup, Position, Keys}` or `all`).\n\n- [](){: #key_equality } The value of option `key_equality` is to be `'=:='` if\n the table considers two keys equal if they match, and to be `'=='` if two keys\n are equal if they compare equal. Defaults to `'=:='`.\n\nFor the various options recognized by `table/1,2` in respective module, see\n[`ets`](`ets:table/1`), [`dets`](`dets:table/1`), and\n[`mnesia`](`mnesia:table/1`).","title":"qlc.table/2","ref":"qlc.html#table/2"},{"type":"type","doc":"Parse trees for Erlang expression, see section\n[The Abstract Format](`e:erts:absform.md`) in the ERTS User's Guide.","title":"qlc.abstract_expr/0","ref":"qlc.html#t:abstract_expr/0"},{"type":"type","doc":"","title":"qlc.answer/0","ref":"qlc.html#t:answer/0"},{"type":"type","doc":"","title":"qlc.answers/0","ref":"qlc.html#t:answers/0"},{"type":"type","doc":"","title":"qlc.cache/0","ref":"qlc.html#t:cache/0"},{"type":"type","doc":"","title":"qlc.key_pos/0","ref":"qlc.html#t:key_pos/0"},{"type":"type","doc":"Match specification, see section\n[Match Specifications in Erlang](`e:erts:match_spec.md`) in the ERTS User's\nGuide and `m:ms_transform`.","title":"qlc.match_expression/0","ref":"qlc.html#t:match_expression/0"},{"type":"type","doc":"","title":"qlc.max_list_size/0","ref":"qlc.html#t:max_list_size/0"},{"type":"type","doc":"An integer > 1.","title":"qlc.no_files/0","ref":"qlc.html#t:no_files/0"},{"type":"type","doc":"","title":"qlc.order/0","ref":"qlc.html#t:order/0"},{"type":"type","doc":"","title":"qlc.order_fun/0","ref":"qlc.html#t:order_fun/0"},{"type":"opaque","doc":"A [query cursor](`m:qlc#query_cursor`).","title":"qlc.query_cursor/0","ref":"qlc.html#t:query_cursor/0"},{"type":"opaque","doc":"A [query handle](`m:qlc#query_handle`).","title":"qlc.query_handle/0","ref":"qlc.html#t:query_handle/0"},{"type":"type","doc":"","title":"qlc.query_handle_or_list/0","ref":"qlc.html#t:query_handle_or_list/0"},{"type":"type","doc":"A literal [query list comprehension](`m:qlc#query_list_comprehension`).","title":"qlc.query_list_comprehension/0","ref":"qlc.html#t:query_list_comprehension/0"},{"type":"type","doc":"See `m:file_sorter` for a description of the options.","title":"qlc.sort_option/0","ref":"qlc.html#t:sort_option/0"},{"type":"type","doc":"","title":"qlc.sort_options/0","ref":"qlc.html#t:sort_options/0"},{"type":"type","doc":"","title":"qlc.spawn_options/0","ref":"qlc.html#t:spawn_options/0"},{"type":"type","doc":"","title":"qlc.tmp_directory/0","ref":"qlc.html#t:tmp_directory/0"},{"type":"type","doc":"","title":"qlc.tmp_file_usage/0","ref":"qlc.html#t:tmp_file_usage/0"},{"type":"module","doc":"Abstract data type for FIFO queues.\n\nThis module provides (double-ended) FIFO queues in an efficient manner.\n\nAll functions fail with reason `badarg` if arguments are of wrong type, for\nexample, queue arguments are not queues, indexes are not integers, and list\narguments are not lists. Improper lists cause internal crashes. An index out of\nrange for a queue also causes a failure with reason `badarg`.\n\nSome functions, where noted, fail with reason `empty` for an empty queue.\n\nThe data representing a queue as used by this module is to be regarded as opaque\nby other modules. In abstract terms, the representation is a composite type of\nexisting Erlang terms. See note on\n[data types](`e:system:data_types.md#no_user_types`). Any code assuming\nknowledge of the format is running on thin ice.\n\nAll operations have an amortized O(1) running time, except `all/2`, `any/2`,\n`delete/2`, `delete_r/2`, `delete_with/2`, `delete_with_r/2`, `filter/2`,\n`filtermap/2`, `fold/3`, `join/2`, `len/1`, `member/2`, `split/2` that have\nO(n). To minimize the size of a queue minimizing the amount of garbage built by\nqueue operations, the queues do not contain explicit length information, and\nthat is why [`len/1`](`len/1`) is O(n). If better performance for this\nparticular operation is essential, it is easy for the caller to keep track of\nthe length.\n\nQueues are double-ended. The mental picture of a queue is a line of people\n(items) waiting for their turn. The queue front is the end with the item that\nhas waited the longest. The queue rear is the end an item enters when it starts\nto wait. If instead using the mental picture of a list, the front is called head\nand the rear is called tail.\n\nEntering at the front and exiting at the rear are reverse operations on the\nqueue.\n\nThis module has three sets of interface functions: the _\"Original API\"_, the\n_\"Extended API\"_, and the _\"Okasaki API\"_.\n\nThe \"Original API\" and the \"Extended API\" both use the mental picture of a\nwaiting line of items. Both have reverse operations suffixed \"\\_r\".\n\nThe \"Original API\" item removal functions return compound terms with both the\nremoved item and the resulting queue. The \"Extended API\" contains alternative\nfunctions that build less garbage and functions for just inspecting the queue\nends. Also the \"Okasaki API\" functions build less garbage.\n\nThe \"Okasaki API\" is inspired by \"Purely Functional Data Structures\" by Chris\nOkasaki. It regards queues as lists. This API is by many regarded as strange and\navoidable. For example, many reverse operations have lexically reversed names,\nsome with more readable but perhaps less understandable aliases.","title":"queue","ref":"queue.html"},{"type":"function","doc":"Returns `true` if `Pred(Item)` returns `true` for all items `Item` in `Q`,\notherwise `false`.\n\n_Example:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5]).\n2> queue:all(fun (E) -> E > 3 end, Queue).\nfalse\n3> queue:all(fun (E) -> E > 0 end, Queue).\ntrue\n```","title":"queue.all/2","ref":"queue.html#all/2"},{"type":"function","doc":"Returns `true` if `Pred(Item)` returns `true` for at least one item `Item` in\n`Q`, otherwise `false`.\n\n_Example:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5]).\n2> queue:any(fun (E) -> E > 10 end, Queue).\nfalse\n3> queue:any(fun (E) -> E > 3 end, Queue).\ntrue\n```","title":"queue.any/2","ref":"queue.html#any/2"},{"type":"function","doc":"Inserts `Item` at the head of queue `Q1`. Returns the new queue `Q2`.\n\n_Example:_\n\n```erlang\n1> Queue = queue:cons(0, queue:from_list([1,2,3])).\n{[3,2],[0,1]}\n2> queue:to_list(Queue).\n[0,1,2,3]\n```","title":"queue.cons/2","ref":"queue.html#cons/2"},{"type":"function","doc":"Returns the tail item of queue `Q`.\n\nFails with reason `empty` if `Q` is empty.\n\n_Example 1:_\n\n```erlang\n1> queue:daeh(queue:from_list([1,2,3])).\n3\n```","title":"queue.daeh/1","ref":"queue.html#daeh/1"},{"type":"function","doc":"Returns a copy of `Q1` where the first item matching `Item` is deleted, if there\nis such an item.\n\n_Example:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5]).\n2> Queue1 = queue:delete(3, Queue).\n3> queue:member(3, Queue1).\nfalse\n```","title":"queue.delete/2","ref":"queue.html#delete/2"},{"type":"function","doc":"Returns a copy of `Q1` where the last item matching `Item` is deleted, if there\nis such an item.\n\n_Example:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,3,5]).\n2> Queue1 = queue:delete_r(3, Queue).\n3> queue:to_list(Queue1).\n[1,2,3,4,5]\n```","title":"queue.delete_r/2","ref":"queue.html#delete_r/2"},{"type":"function","doc":"Returns a copy of `Q1` where the first item for which `Pred` returns `true` is\ndeleted, if there is such an item.\n\n_Example:_\n\n```erlang\n1> Queue = queue:from_list([100,1,2,3,4,5]).\n2> Queue1 = queue:delete_with(fun (E) -> E > 0, Queue).\n3> queue:to_list(Queue1).\n[1,2,3,4,5]\n```","title":"queue.delete_with/2","ref":"queue.html#delete_with/2"},{"type":"function","doc":"Returns a copy of `Q1` where the last item for which `Pred` returns `true` is\ndeleted, if there is such an item.\n\n_Example:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5,100]).\n2> Queue1 = queue:delete_with(fun (E) -> E > 10, Queue).\n3> queue:to_list(Queue1).\n[1,2,3,4,5]\n```","title":"queue.delete_with_r/2","ref":"queue.html#delete_with_r/2"},{"type":"function","doc":"Returns a queue `Q2` that is the result of removing the front item from `Q1`.\n\nFails with reason `empty` if `Q1` is empty.\n\n_Example:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5]).\n{[5,4,3],[1,2]}\n2> Queue = queue:drop(Queue).\n{[5,4,3],[2]}\n3> queue:to_list(Queue1).\n[2,3,4,5]\n```","title":"queue.drop/1","ref":"queue.html#drop/1"},{"type":"function","doc":"Returns a queue `Q2` that is the result of removing the rear item from `Q1`.\n\nFails with reason `empty` if `Q1` is empty.\n\n_Example:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5]).\n{[5,4,3],[1,2]}\n2> Queue = queue:drop_r(Queue).\n{[4,3],[1,2]}\n3> queue:to_list(Queue1).\n[1,2,3,4]\n```","title":"queue.drop_r/1","ref":"queue.html#drop_r/1"},{"type":"function","doc":"Returns a queue `Q2` that is the result of calling `Fun(Item)` on all items in\n`Q1`.\n\nIf `Fun(Item)` returns `true`, `Item` is copied to the result queue. If it\nreturns `false`, `Item` is not copied. If it returns a list, the list elements\nare inserted instead of `Item` in the result queue.\n\n_Example 1:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5]).\n{[5,4,3],[1,2]}\n2> Queue1 = queue:filter(fun (E) -> E > 2 end, Queue).\n{[5],[3,4]}\n3> queue:to_list(Queue1).\n[3,4,5]\n```\n\nSo, `Fun(Item)` returning `[Item]` is thereby semantically equivalent to\nreturning `true`, just as returning `[]` is semantically equivalent to returning\n`false`. But returning a list builds more garbage than returning an atom.\n\n_Example 2:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5]).\n{[5,4,3],[1,2]}\n2> Queue1 = queue:filter(fun (E) -> [E, E+1] end, Queue).\n{[6,5,5,4,4,3],[1,2,2,3]}\n3> queue:to_list(Queue1).\n[1,2,2,3,3,4,4,5,5,6]\n```","title":"queue.filter/2","ref":"queue.html#filter/2"},{"type":"function","doc":"Returns a queue `Q2` that is the result of calling `Fun(Item)` on all items in\n`Q1`.\n\nIf `Fun(Item)` returns `true`, `Item` is copied to the result queue. If it\nreturns `false`, `Item` is not copied. If it returns `{true, NewItem}`, the\nqueue element at this position is replaced with `NewItem` in the result queue.\n\n_Example 1:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5]).\n{[5,4,3],[1,2]}\n2> Queue1 = queue:filtermap(fun (E) -> E > 2 end, Queue).\n{[5],[3,4]}\n3> queue:to_list(Queue1).\n[3,4,5]\n4> Queue1 = queue:filtermap(fun (E) -> {true, E+100} end, Queue).\n{\"ihg\",\"ef\"}\n5> queue:to_list(Queue1).\n\"efghi\n```","title":"queue.filtermap/2","ref":"queue.html#filtermap/2"},{"type":"function","doc":"Calls `Fun(Item, AccIn)` on successive items `Item` of `Queue`, starting with\n`AccIn == Acc0`. The queue is traversed in queue order, that is, from front to\nrear. `Fun/2` must return a new accumulator, which is passed to the next call.\nThe function returns the final value of the accumulator. `Acc0` is returned if\nthe queue is empty.\n\n_Example:_\n\n```erlang\n1> queue:fold(fun(X, Sum) -> X + Sum end, 0, queue:from_list([1,2,3,4,5])).\n15\n2> queue:fold(fun(X, Prod) -> X * Prod end, 1, queue:from_list([1,2,3,4,5])).\n120\n```","title":"queue.fold/3","ref":"queue.html#fold/3"},{"type":"function","doc":"Returns a queue containing the items in `L` in the same order; the head item of\nthe list becomes the front item of the queue.","title":"queue.from_list/1","ref":"queue.html#from_list/1"},{"type":"function","doc":"Returns `Item` at the front of queue `Q`.\n\nFails with reason `empty` if `Q` is empty.\n\n_Example 1:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5]).\n{[5,4,3],[1,2]}\n2> 1 == queue:get(Queue).\ntrue\n```","title":"queue.get/1","ref":"queue.html#get/1"},{"type":"function","doc":"Returns `Item` at the rear of queue `Q`.\n\nFails with reason `empty` if `Q` is empty.\n\n_Example 1:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5]).\n{[5,4,3],[1,2]}\n2> 5 == queue:get_r(Queue).\ntrue\n```","title":"queue.get_r/1","ref":"queue.html#get_r/1"},{"type":"function","doc":"Returns `Item` from the head of queue `Q`.\n\nFails with reason `empty` if `Q` is empty.\n\n_Example 1:_\n\n```erlang\n1> queue:head(queue:from_list([1,2,3])).\n1\n```","title":"queue.head/1","ref":"queue.html#head/1"},{"type":"function","doc":"Inserts `Item` at the rear of queue `Q1`. Returns the resulting queue `Q2`.\n\n_Example:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5]).\n{[5,4,3],[1,2]}\n2> Queue1 = queue:in(100, Queue).\n{[100,5,4,3],[1,2]}\n3> queue:to_list(Queue1).\n[1,2,3,4,5,100]\n```","title":"queue.in/2","ref":"queue.html#in/2"},{"type":"function","doc":"Inserts `Item` at the front of queue `Q1`. Returns the resulting queue `Q2`.\n\n_Example:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5]).\n{[5,4,3],[1,2]}\n2> Queue1 = queue:in_r(100, Queue).\n{[5,4,3],[100,1,2]}\n3> queue:to_list(Queue1).\n[100,1,2,3,4,5]\n```","title":"queue.in_r/2","ref":"queue.html#in_r/2"},{"type":"function","doc":"Returns a queue `Q2` that is the result of removing the tail item from `Q1`.\n\nFails with reason `empty` if `Q1` is empty.\n\n_Example:_\n\n```erlang\n1> Queue = queue:init(queue:from_list([1,2,3])).\n{[2],[1]}\n2> queue:to_list(Queue).\n[1,2]\n```","title":"queue.init/1","ref":"queue.html#init/1"},{"type":"function","doc":"Tests if `Q` is empty and returns `true` if so, otherwise `false`.","title":"queue.is_empty/1","ref":"queue.html#is_empty/1"},{"type":"function","doc":"Tests if `Term` is a queue and returns `true` if so, otherwise `false`. Note\nthat the test will return `true` for a term coinciding with the representation\nof a queue, even when not constructed by thus module. See also note on\n[data types](`e:system:data_types.md#no_user_types`).","title":"queue.is_queue/1","ref":"queue.html#is_queue/1"},{"type":"function","doc":"Returns a queue `Q3` that is the result of joining `Q1` and `Q2` with `Q1` in\nfront of `Q2`.\n\n_Example:_\n\n```erlang\n1> Queue1 = queue:from_list([1,3]).\n{[3],[1]}\n2> Queue2 = queue:from_list([2,4]).\n{[4],[2]}\n3> queue:to_list(queue:join(Queue1, Queue2)).\n[1,3,2,4]\n```","title":"queue.join/2","ref":"queue.html#join/2"},{"type":"function","doc":"Returns a queue `Q2` that is the result of removing the tail item from `Q1`.\n\nFails with reason `empty` if `Q1` is empty.\n\nThe name [`lait/1`](`lait/1`) is a misspelling - do not use it anymore.","title":"queue.lait/1","ref":"queue.html#lait/1"},{"type":"function","doc":"Returns the tail item of queue `Q`.\n\nFails with reason `empty` if `Q` is empty.\n\n_Example:_\n\n```erlang\n1> queue:last(queue:from_list([1,2,3])).\n3\n```","title":"queue.last/1","ref":"queue.html#last/1"},{"type":"function","doc":"Calculates and returns the length of queue `Q`.","title":"queue.len/1","ref":"queue.html#len/1"},{"type":"function","doc":"Returns a queue `Q2` that is the result of removing the tail item from `Q1`.\n\nFails with reason `empty` if `Q1` is empty.\n\n_Example:_\n\n```erlang\n1> Queue = queue:liat(queue:from_list([1,2,3])).\n{[2],[1]}\n2> queue:to_list(Queue).\n[1,2]\n```","title":"queue.liat/1","ref":"queue.html#liat/1"},{"type":"function","doc":"Returns `true` if `Item` matches some element in `Q`, otherwise `false`.","title":"queue.member/2","ref":"queue.html#member/2"},{"type":"function","doc":"Returns an empty queue.","title":"queue.new/0","ref":"queue.html#new/0"},{"type":"function","doc":"Removes the item at the front of queue `Q1`. Returns tuple\n`{{value, Item}, Q2}`, where `Item` is the item removed and `Q2` is the\nresulting queue. If `Q1` is empty, tuple `{empty, Q1}` is returned.\n\n_Example:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5]).\n{[5,4,3],[1,2]}\n2> {{value, 1=Item}, Queue1} = queue:out(Queue).\n{{value,1},{[5,4,3],[2]}}\n3> queue:to_list(Queue1).\n[2,3,4,5]\n```","title":"queue.out/1","ref":"queue.html#out/1"},{"type":"function","doc":"Removes the item at the rear of queue `Q1`. Returns tuple `{{value, Item}, Q2}`,\nwhere `Item` is the item removed and `Q2` is the new queue. If `Q1` is empty,\ntuple `{empty, Q1}` is returned.\n\n_Example:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5]).\n{[5,4,3],[1,2]}\n2> {{value, 5=Item}, Queue1} = queue:out_r(Queue).\n{{value,5},{[4,3],[1,2]}}\n3> queue:to_list(Queue1).\n[1,2,3,4]\n```","title":"queue.out_r/1","ref":"queue.html#out_r/1"},{"type":"function","doc":"Returns tuple `{value, Item}`, where `Item` is the front item of `Q`, or `empty`\nif `Q` is empty.\n\n_Example 1:_\n\n```erlang\n1> queue:peek(queue:new()).\nempty\n2> Queue = queue:from_list([1,2,3,4,5]).\n{[5,4,3],[1,2]}\n3> queue:peek(Queue).\n{value, 1}\n```","title":"queue.peek/1","ref":"queue.html#peek/1"},{"type":"function","doc":"Returns tuple `{value, Item}`, where `Item` is the rear item of `Q`, or `empty`\nif `Q` is empty.\n\n_Example 1:_\n\n```erlang\n1> queue:peek_r(queue:new()).\nempty\n2> Queue = queue:from_list([1,2,3,4,5]).\n{[5,4,3],[1,2]}\n3> queue:peek_r(Queue).\n{value, 5}\n```","title":"queue.peek_r/1","ref":"queue.html#peek_r/1"},{"type":"function","doc":"Returns a queue `Q2` containing the items of `Q1` in the reverse order.","title":"queue.reverse/1","ref":"queue.html#reverse/1"},{"type":"function","doc":"Inserts `Item` as the tail item of queue `Q1`. Returns the new queue `Q2`.\n\n_Example:_\n\n```erlang\n1> Queue = queue:snoc(queue:from_list([1,2,3]), 4).\n{[4,3,2],[1]}\n2> queue:to_list(Queue).\n[1,2,3,4]\n```","title":"queue.snoc/2","ref":"queue.html#snoc/2"},{"type":"function","doc":"Splits `Q1` in two. The `N` front items are put in `Q2` and the rest in `Q3`.","title":"queue.split/2","ref":"queue.html#split/2"},{"type":"function","doc":"Returns a queue `Q2` that is the result of removing the head item from `Q1`.\n\nFails with reason `empty` if `Q1` is empty.","title":"queue.tail/1","ref":"queue.html#tail/1"},{"type":"function","doc":"Returns a list of the items in the queue in the same order; the front item of\nthe queue becomes the head of the list.\n\n_Example:_\n\n```erlang\n1> Queue = queue:from_list([1,2,3,4,5]).\n{[5,4,3],[1,2]}\n2> List == queue:to_list(Queue).\ntrue\n```","title":"queue.to_list/1","ref":"queue.html#to_list/1"},{"type":"type","doc":"","title":"queue.queue/0","ref":"queue.html#t:queue/0"},{"type":"opaque","doc":"As returned by `new/0`.","title":"queue.queue/1","ref":"queue.html#t:queue/1"},{"type":"module","doc":"Sets are collections of elements with no duplicate elements.\n\nThe data representing a set as used by this module is to be regarded as opaque\nby other modules. In abstract terms, the representation is a composite type of\nexisting Erlang terms. See note on\n[data types](`e:system:data_types.md#no_user_types`). Any code assuming\nknowledge of the format is running on thin ice.\n\nThis module provides the same interface as the `m:ordsets` module but with an\nundefined representation. One difference is that while this module considers two\nelements as different if they do not match (`=:=`), `ordsets` considers two\nelements as different if and only if they do not compare equal (`==`).\n\nErlang/OTP 24.0 introduced a new more performant representation for sets which\nhas become the default in Erlang/OTP 28. Developers can use the old representation\nby passing the `{version, 1}` flag to `new/1` and `from_list/2`. Functions that\nwork on two sets, such as `union/2`, will work with sets of different\nversions. In such cases, there is no guarantee about the version of the returned set.\nExplicit conversion from the old version to the new one can be done with\n`sets:from_list(sets:to_list(Old), [{version,2}])`.","title":"sets","ref":"sets.html"},{"type":"module","doc":"The following functions in this module also exist and provide the same\nfunctionality in the `m:gb_sets` and `m:ordsets` modules. That is, by only\nchanging the module name for each call, you can try out different set\nrepresentations.\n\n- `add_element/2`\n- `del_element/2`\n- `filter/2`\n- `filtermap/2`\n- `fold/3`\n- `from_list/1`\n- `intersection/1`\n- `intersection/2`\n- `is_element/2`\n- `is_empty/1`\n- `is_equal/2`\n- `is_set/1`\n- `is_subset/2`\n- `map/2`\n- `new/0`\n- `size/1`\n- `subtract/2`\n- `to_list/1`\n- `union/1`\n- `union/2`\n\n> #### Note {: .info }\n>\n> While the three set implementations offer the same _functionality_ with\n> respect to the aforementioned functions, their overall _behavior_ may differ.\n> As mentioned, this module considers elements as different if and only if they\n> do not match (`=:=`), while both `m:ordsets` and `m:gb_sets` consider elements\n> as different if and only if they do not compare equal (`==`).\n>\n> _Example:_\n>\n> ```erlang\n> 1> sets:is_element(1.0, sets:from_list([1])).\n> false\n> 2> ordsets:is_element(1.0, ordsets:from_list([1])).\n> true\n> 2> gb_sets:is_element(1.0, gb_sets:from_list([1])).\n> true\n> ```","title":"Compatibility - sets","ref":"sets.html#module-compatibility"},{"type":"module","doc":"`m:gb_sets`, `m:ordsets`","title":"See Also - sets","ref":"sets.html#module-see-also"},{"type":"function","doc":"Returns a new set formed from `Set1` with `Element` inserted.","title":"sets.add_element/2","ref":"sets.html#add_element/2"},{"type":"function","doc":"Returns `Set1`, but with `Element` removed.","title":"sets.del_element/2","ref":"sets.html#del_element/2"},{"type":"function","doc":"Filters elements in `Set1` with boolean function `Pred`.","title":"sets.filter/2","ref":"sets.html#filter/2"},{"type":"function","doc":"Filters and maps elements in `Set1` with function `Fun`.","title":"sets.filtermap/2","ref":"sets.html#filtermap/2"},{"type":"function","doc":"Folds `Function` over every element in `Set` and returns the final value of the\naccumulator. The evaluation order is undefined.","title":"sets.fold/3","ref":"sets.html#fold/3"},{"type":"function","doc":"Returns a set of the elements in `List`.","title":"sets.from_list/1","ref":"sets.html#from_list/1"},{"type":"function","doc":"Returns a set of the elements in `List` at the given version.","title":"sets.from_list/2","ref":"sets.html#from_list/2"},{"type":"function","doc":"Returns the intersection of the non-empty list of sets.","title":"sets.intersection/1","ref":"sets.html#intersection/1"},{"type":"function","doc":"Returns the intersection of `Set1` and `Set2`.","title":"sets.intersection/2","ref":"sets.html#intersection/2"},{"type":"function","doc":"Returns `true` if `Set1` and `Set2` are disjoint (have no elements in common),\notherwise `false`.","title":"sets.is_disjoint/2","ref":"sets.html#is_disjoint/2"},{"type":"function","doc":"Returns `true` if `Element` is an element of `Set`, otherwise `false`.","title":"sets.is_element/2","ref":"sets.html#is_element/2"},{"type":"function","doc":"Returns `true` if `Set` is an empty set, otherwise `false`.","title":"sets.is_empty/1","ref":"sets.html#is_empty/1"},{"type":"function","doc":"Returns `true` if `Set1` and `Set2` are equal, that is when every element of one\nset is also a member of the respective other set, otherwise `false`.","title":"sets.is_equal/2","ref":"sets.html#is_equal/2"},{"type":"function","doc":"Returns `true` if `Set` appears to be a set of elements, otherwise `false`.\n\nNote that the test is shallow and will return `true` for any term that coincides with\nthe possible representations of a set. See also note on [data types](`e:system:data_types.md#no_user_types`).","title":"sets.is_set/1","ref":"sets.html#is_set/1"},{"type":"function","doc":"Returns `true` when every element of `Set1` is also a member of `Set2`,\notherwise `false`.","title":"sets.is_subset/2","ref":"sets.html#is_subset/2"},{"type":"function","doc":"Maps elements in `Set1` with mapping function `Fun`.","title":"sets.map/2","ref":"sets.html#map/2"},{"type":"function","doc":"Returns a new empty set.","title":"sets.new/0","ref":"sets.html#new/0"},{"type":"function","doc":"Returns a new empty set at the given version.","title":"sets.new/1","ref":"sets.html#new/1"},{"type":"function","doc":"Returns the number of elements in `Set`.","title":"sets.size/1","ref":"sets.html#size/1"},{"type":"function","doc":"Returns only the elements of `Set1` that are not also elements of `Set2`.","title":"sets.subtract/2","ref":"sets.html#subtract/2"},{"type":"function","doc":"Returns the elements of `Set` as a list. The order of the returned elements is\nundefined.","title":"sets.to_list/1","ref":"sets.html#to_list/1"},{"type":"function","doc":"Returns the merged (union) set of the list of sets.","title":"sets.union/1","ref":"sets.html#union/1"},{"type":"function","doc":"Returns the merged (union) set of `Set1` and `Set2`.","title":"sets.union/2","ref":"sets.html#union/2"},{"type":"type","doc":"","title":"sets.set/0","ref":"sets.html#t:set/0"},{"type":"opaque","doc":"As returned by `new/0`.","title":"sets.set/1","ref":"sets.html#t:set/1"},{"type":"module","doc":"Functions for manipulating sets of sets.\n\nThis module provides operations on finite sets and relations represented as\nsets. Intuitively, a set is a collection of elements; every element belongs to\nthe set, and the set contains every element.\n\nThe data representing `sofs` as used by this module is to be regarded as opaque\nby other modules. In abstract terms, the representation is a composite type of\nexisting Erlang terms. See note on\n[data types](`e:system:data_types.md#no_user_types`). Any code assuming\nknowledge of the format is running on thin ice.\n\nGiven a set A and a sentence S(x), where x is a free variable, a new set B whose\nelements are exactly those elements of A for which S(x) holds can be formed,\nthis is denoted B = \\{x in A : S(x)\\}. Sentences are expressed using the logical\noperators \"for some\" (or \"there exists\"), \"for all\", \"and\", \"or\", \"not\". If the\nexistence of a set containing all the specified elements is known (as is always\nthe case in this module), this is denoted B = \\{x : S(x)\\}.\n\n- The _unordered set_ containing the elements a, b, and c is denoted\n \\{a, b, c\\}. This notation is not to be confused with tuples.\n\n The _ordered pair_ of a and b, with first _coordinate_ a and second coordinate\n b, is denoted (a, b). An ordered pair is an _ordered set_ of two elements. In\n this module, ordered sets can contain one, two, or more elements, and\n parentheses are used to enclose the elements.\n\n Unordered sets and ordered sets are orthogonal, again in this module; there is\n no unordered set equal to any ordered set.\n\n- The _empty set_ contains no elements.\n\n Set A is _equal_{: #equal } to set B if they contain the same elements, which\n is denoted A = B. Two ordered sets are equal if they contain the same number\n of elements and have equal elements at each coordinate.\n\n Set B is a _subset_{: #subset } of set A if A contains all elements that B\n contains.\n\n The _union_{: #union } of two sets A and B is the smallest set that contains\n all elements of A and all elements of B.\n\n The _intersection_{: #intersection } of two sets A and B is the set that\n contains all elements of A that belong to B.\n\n Two sets are _disjoint_{: #disjoint } if their intersection is the empty set.\n\n The _difference_{: #difference } of two sets A and B is the set that contains\n all elements of A that do not belong to B.\n\n The _symmetric difference_{: #symmetric_difference } of two sets is the set\n that contains those element that belong to either of the two sets, but not\n both.\n\n The _union_{: #union_n } of a collection of sets is the smallest set that\n contains all the elements that belong to at least one set of the collection.\n\n The _intersection_{: #intersection_n } of a non-empty collection of sets is\n the set that contains all elements that belong to every set of the collection.\n\n- The _Cartesian product_{: #Cartesian_product } of two sets X and Y, denoted\n X × Y, is the set \\{a : a = (x, y) for some x in X and for some y in Y\\}.\n\n A _relation_{: #relation } is a subset of X × Y. Let R be a relation. The fact\n that (x, y) belongs to R is written as x R y. As relations are sets, the\n definitions of the last item (subset, union, and so on) apply to relations as\n well.\n\n The _domain_{: #domain } of R is the set \\{x : x R y for some y in Y\\}.\n\n The _range_{: #range } of R is the set \\{y : x R y for some x in X\\}.\n\n The _converse_{: #converse } of R is the set \\{a : a = (y, x) for some\n (x, y) in R\\}.\n\n If A is a subset of X, the _image_{: #image } of A under R is the set \\{y :\n x R y for some x in A\\}. If B is a subset of Y, the _inverse image_{:\n #inverse_image } of B is the set \\{x : x R y for some y in B\\}.\n\n If R is a relation from X to Y, and S is a relation from Y to Z, the _relative\n product_{: #relative_product } of R and S is the relation T from X to Z\n defined so that x T z if and only if there exists an element y in Y such that\n x R y and y S z.\n\n The _restriction_{: #restriction } of R to A is the set S defined so that\n x S y if and only if there exists an element x in A such that x R y.\n\n If S is a restriction of R to A, then R is an _extension_{: #extension } of S\n to X.\n\n If X = Y, then R is called a relation _in_ X.\n\n The _field_{: #field } of a relation R in X is the union of the domain of R\n and the range of R.\n\n If R is a relation in X, and if S is defined so that x S y if x R y and not\n x = y, then S is the _strict_{: #strict_relation } relation corresponding to\n R. Conversely, if S is a relation in X, and if R is defined so that x R y if\n x S y or x = y, then R is the _weak_{: #weak_relation } relation corresponding\n to S.\n\n A relation R in X is _reflexive_ if x R x for every element x of X, it is\n _symmetric_ if x R y implies that y R x, and it is _transitive_ if x R y and\n y R z imply that x R z.\n\n- A _function_{: #function } F is a relation, a subset of X × Y, such that the\n domain of F is equal to X and such that for every x in X there is a unique\n element y in Y with (x, y) in F. The latter condition can be formulated as\n follows: if x F y and x F z, then y = z. In this module, it is not required\n that the domain of F is equal to X for a relation to be considered a function.\n\n Instead of writing (x, y) in F or x F y, we write F(x) = y when F is a\n function, and say that F maps x onto y, or that the value of F at x is y.\n\n As functions are relations, the definitions of the last item (domain, range,\n and so on) apply to functions as well.\n\n If the converse of a function F is a function F', then F' is called the\n _inverse_{: #inverse } of F.\n\n The relative product of two functions F1 and F2 is called the _composite_{:\n #composite } of F1 and F2 if the range of F1 is a subset of the domain of F2.\n\n- Sometimes, when the range of a function is more important than the function\n itself, the function is called a _family_.\n\n The domain of a family is called the _index set_, and the range is called the\n _indexed set_.\n\n If x is a family from I to X, then x\\[i] denotes the value of the function at\n index i. The notation \"a family in X\" is used for such a family.\n\n When the indexed set is a set of subsets of a set X, we call x a _family of\n subsets_{: #family } of X.\n\n If x is a family of subsets of X, the union of the range of x is called the\n _union of the family_ x.\n\n If x is non-empty (the index set is non-empty), the _intersection of the\n family_ x is the intersection of the range of x.\n\n In this module, the only families that are considered are families of subsets\n of some set X; in the following, the word \"family\" is used for such families\n of subsets.\n\n- A _partition_{: #partition } of a set X is a collection S of non-empty subsets\n of X whose union is X and whose elements are pairwise disjoint.\n\n A relation in a set is an _equivalence relation_ if it is reflexive,\n symmetric, and transitive.\n\n If R is an equivalence relation in X, and x is an element of X, the\n _equivalence class_{: #equivalence_class } of x with respect to R is the set\n of all those elements y of X for which x R y holds. The equivalence classes\n constitute a partitioning of X. Conversely, if C is a partition of X, the\n relation that holds for any two elements of X if they belong to the same\n equivalence class, is an equivalence relation induced by the partition C.\n\n If R is an equivalence relation in X, the _canonical map_{: #canonical_map }\n is the function that maps every element of X onto its equivalence class.\n\n- [](){: #binary_relation } Relations as defined above (as sets of ordered\n pairs) are from now on referred to as _binary relations_.\n\n We call a set of ordered sets (x\\[1], ..., x\\[n]) an _(n-ary) relation_{:\n #n_ary_relation }, and say that the relation is a subset of the [](){:\n #Cartesian_product_tuple } Cartesian product X\\[1] × ... × X\\[n], where x\\[i]\n is an element of X\\[i], 1 <= i <= n.\n\n The _projection_{: #projection } of an n-ary relation R onto coordinate i is\n the set \\{x\\[i] : (x\\[1], ..., x\\[i], ..., x\\[n]) in R for some\n x\\[j] in X\\[j], 1 <= j <= n and not i = j\\}. The projections of a binary\n relation R onto the first and second coordinates are the domain and the range\n of R, respectively.\n\n The relative product of binary relations can be generalized to n-ary relations\n as follows. Let TR be an ordered set (R\\[1], ..., R\\[n]) of binary relations\n from X to Y\\[i] and S a binary relation from (Y\\[1] × ... × Y\\[n]) to Z. The\n _relative product_{: #tuple_relative_product } of TR and S is the binary\n relation T from X to Z defined so that x T z if and only if there exists an\n element y\\[i] in Y\\[i] for each 1 <= i <= n such that x R\\[i] y\\[i] and\n (y\\[1], ..., y\\[n]) S z. Now let TR be a an ordered set (R\\[1], ..., R\\[n]) of\n binary relations from X\\[i] to Y\\[i] and S a subset of X\\[1] × ... × X\\[n].\n The _multiple relative product_{: #multiple_relative_product } of TR and S is\n defined to be the set \\{z : z = ((x\\[1], ..., x\\[n]), (y\\[1],...,y\\[n])) for\n some (x\\[1], ..., x\\[n]) in S and for some (x\\[i], y\\[i]) in R\\[i],\n 1 <= i <= n\\}.\n\n The _natural join_{: #natural_join } of an n-ary relation R and an m-ary\n relation S on coordinate i and j is defined to be the set \\{z : z =\n (x\\[1], ..., x\\[n],  y\\[1], ..., y\\[j-1], y\\[j+1], ..., y\\[m]) for some\n (x\\[1], ..., x\\[n]) in R and for some (y\\[1], ..., y\\[m]) in S such that\n x\\[i] = y\\[j]\\}.\n\n- [](){: #sets_definition } The sets recognized by this module are represented\n by elements of the relation Sets, which is defined as the smallest set such\n that:\n\n - For every atom T, except '\\_', and for every term X, (T, X) belongs to Sets\n (_atomic sets_).\n - (\\['\\_'], []) belongs to Sets (the _untyped empty set_).\n - For every tuple T = \\{T\\[1], ..., T\\[n]\\} and for every tuple X =\n \\{X\\[1], ..., X\\[n]\\}, if (T\\[i], X\\[i]) belongs to Sets for every\n 1 <= i <= n, then (T, X) belongs to Sets (_ordered sets_).\n - For every term T, if X is the empty list or a non-empty sorted list\n \\[X[1], ..., X\\[n]] without duplicates such that (T, X\\[i]) belongs to Sets\n for every 1 <= i <= n, then (\\[T], X) belongs to Sets (_typed unordered\n sets_).\n\n An _external set_{: #external_set } is an element of the range of Sets.\n\n A _type_{: #type } is an element of the domain of Sets.\n\n If S is an element (T, X) of Sets, then T is a _valid type_{: #valid_type } of\n X, T is the type of S, and X is the external set of S. `from_term/2` creates a\n set from a type and an Erlang term turned into an external set.\n\n The sets represented by Sets are the elements of the range of function Set\n from Sets to Erlang terms and sets of Erlang terms:\n\n - Set(T,Term) = Term, where T is an atom\n - Set(\\{T\\[1], ..., T\\[n]\\}, \\{X\\[1], ...,  X\\[n]\\}) =\n (Set(T\\[1], X\\[1]), ...,  Set(T\\[n], X\\[n]))\n - Set(\\[T], \\[X[1], ..., X\\[n]]) = \\{Set(T, X\\[1]), ..., Set(T, X\\[n])\\}\n - Set(\\[T], []) = \\{\\}\n\n When there is no risk of confusion, elements of Sets are identified with the\n sets they represent. For example, if U is the result of calling `union/2` with\n S1 and S2 as arguments, then U is said to be the union of S1 and S2. A more\n precise formulation is that Set(U) is the union of Set(S1) and Set(S2).\n\nThe types are used to implement the various conditions that sets must fulfill.\nAs an example, consider the relative product of two sets R and S, and recall\nthat the relative product of R and S is defined if R is a binary relation to Y\nand S is a binary relation from Y. The function that implements the relative\nproduct, `relative_product/2`, checks that the arguments represent binary\nrelations by matching \\[\\{A,B\\}] against the type of the first argument (Arg1\nsay), and \\[\\{C,D\\}] against the type of the second argument (Arg2 say). The\nfact that \\[\\{A,B\\}] matches the type of Arg1 is to be interpreted as Arg1\nrepresenting a binary relation from X to Y, where X is defined as all sets\nSet(x) for some element x in Sets the type of which is A, and similarly for Y.\nIn the same way Arg2 is interpreted as representing a binary relation from W to\nZ. Finally it is checked that B matches C, which is sufficient to ensure that W\nis equal to Y. The untyped empty set is handled separately: its type, \\['\\_'],\nmatches the type of any unordered set.\n\nA few functions of this module (`drestriction/3`, `family_projection/2`,\n`partition/2`, `partition_family/2`, `projection/2`, `restriction/3`,\n`substitution/2`) accept an Erlang function as a means to modify each element of\na given unordered set. [](){: #set_fun } Such a function, called SetFun in the\nfollowing, can be specified as a functional object (fun), a tuple\n`{external, Fun}`, or an integer:\n\n- If SetFun is specified as a fun, the fun is applied to each element of the\n given set and the return value is assumed to be a set.\n- If SetFun is specified as a tuple `{external, Fun}`, Fun is applied to the\n external set of each element of the given set and the return value is assumed\n to be an external set. Selecting the elements of an unordered set as external\n sets and assembling a new unordered set from a list of external sets is in the\n present implementation more efficient than modifying each element as a set.\n However, this optimization can only be used when the elements of the unordered\n set are atomic or ordered sets. It must also be the case that the type of the\n elements matches some clause of Fun (the type of the created set is the result\n of applying Fun to the type of the given set), and that Fun does nothing but\n selecting, duplicating, or rearranging parts of the elements.\n- Specifying a SetFun as an integer I is equivalent to specifying\n `{external, fun(X) -> element(I, X) end}`, but is to be preferred, as it makes\n it possible to handle this case even more efficiently.\n\nExamples of SetFuns:\n\n```erlang\nfun sofs:union/1\nfun(S) -> sofs:partition(1, S) end\n{external, fun(A) -> A end}\n{external, fun({A,_,C}) -> {C,A} end}\n{external, fun({_,{_,C}}) -> C end}\n{external, fun({_,{_,{_,E}=C}}) -> {E,{E,C}} end}\n2\n```\n\nThe order in which a SetFun is applied to the elements of an unordered set is\nnot specified, and can change in future versions of this module.\n\nThe execution time of the functions of this module is dominated by the time it\ntakes to sort lists. When no sorting is needed, the execution time is in the\nworst case proportional to the sum of the sizes of the input arguments and the\nreturned value. A few functions execute in constant time: `from_external/2`,\n`is_empty_set/1`, `is_set/1`, `is_sofs_set/1`, `to_external/1` `type/1`.\n\nThe functions of this module exit the process with a `badarg`, `bad_function`,\nor `type_mismatch` message when given badly formed arguments or sets the types\nof which are not compatible.\n\nWhen comparing external sets, operator `==/2` is used.","title":"sofs","ref":"sofs.html"},{"type":"module","doc":"`m:dict`, `m:digraph`, `m:orddict`, `m:ordsets`, `m:sets`","title":"See Also - sofs","ref":"sofs.html#module-see-also"},{"type":"function","doc":"","title":"sofs.a_function/1","ref":"sofs.html#a_function/1"},{"type":"function","doc":"Creates a [function](`m:sofs#function`).\n\n[`a_function(F, T)`](`a_function/2`) is equivalent to\n[`from_term(F, T)`](`from_term/2`) if the result is a function.","title":"sofs.a_function/2","ref":"sofs.html#a_function/2"},{"type":"function","doc":"Returns the binary relation containing the elements (E, Set) such that Set\nbelongs to `SetOfSets` and E belongs to Set.\n\nIf `SetOfSets` is a [partition](`m:sofs#partition`) of a set X and R is the\nequivalence relation in X induced by `SetOfSets`, then the returned relation is the\n[canonical map](`m:sofs#canonical_map`) from X onto the equivalence classes with\nrespect to R.\n\n```erlang\n1> Ss = sofs:from_term([[a,b],[b,c]]),\nCR = sofs:canonical_relation(Ss),\nsofs:to_external(CR).\n[{a,[a,b]},{b,[a,b]},{b,[b,c]},{c,[b,c]}]\n```","title":"sofs.canonical_relation/1","ref":"sofs.html#canonical_relation/1"},{"type":"function","doc":"Returns the [composite](`m:sofs#composite`) of the functions `Function1` and\n`Function2`.\n\n```erlang\n1> F1 = sofs:a_function([{a,1},{b,2},{c,2}]),\nF2 = sofs:a_function([{1,x},{2,y},{3,z}]),\nF = sofs:composite(F1, F2),\nsofs:to_external(F).\n[{a,x},{b,y},{c,y}]\n```","title":"sofs.composite/2","ref":"sofs.html#composite/2"},{"type":"function","doc":"Creates the [function](`m:sofs#function`) that maps each element of set `Set`\nonto `AnySet`.\n\n```erlang\n1> S = sofs:set([a,b]),\nE = sofs:from_term(1),\nR = sofs:constant_function(S, E),\nsofs:to_external(R).\n[{a,1},{b,1}]\n```","title":"sofs.constant_function/2","ref":"sofs.html#constant_function/2"},{"type":"function","doc":"Returns the [converse](`m:sofs#converse`) of the binary relation `BinRel1`.\n\n```erlang\n1> R1 = sofs:relation([{1,a},{2,b},{3,a}]),\nR2 = sofs:converse(R1),\nsofs:to_external(R2).\n[{a,1},{a,3},{b,2}]\n```","title":"sofs.converse/1","ref":"sofs.html#converse/1"},{"type":"function","doc":"Returns the [difference](`m:sofs#difference`) of the sets `Set1` and `Set2`.","title":"sofs.difference/2","ref":"sofs.html#difference/2"},{"type":"function","doc":"","title":"sofs.digraph_to_family/1","ref":"sofs.html#digraph_to_family/1"},{"type":"function","doc":"Creates a [family](`m:sofs#family`) from the directed graph `Graph`. Each vertex\na of `Graph` is represented by a pair (a, \\{b\\[1], ..., b\\[n]\\}), where the\nb\\[i]:s are the out-neighbors of a. It is assumed that `Type` is\na [valid type](`m:sofs#valid_type`) of the external set of the family.\n\nIf G is a directed graph, it holds that the vertices and edges of G are the same\nas the vertices and edges of\n[`family_to_digraph(digraph_to_family(G))`](`family_to_digraph/1`).","title":"sofs.digraph_to_family/2","ref":"sofs.html#digraph_to_family/2"},{"type":"function","doc":"Returns the [domain](`m:sofs#domain`) of the binary relation `BinRel`.\n\n```erlang\n1> R = sofs:relation([{1,a},{1,b},{2,b},{2,c}]),\nS = sofs:domain(R),\nsofs:to_external(S).\n[1,2]\n```","title":"sofs.domain/1","ref":"sofs.html#domain/1"},{"type":"function","doc":"Returns the difference between the binary relation `BinRel1` and the\n[restriction](`m:sofs#restriction`) of `BinRel1` to `Set`.\n\n```erlang\n1> R1 = sofs:relation([{1,a},{2,b},{3,c}]),\nS = sofs:set([2,4,6]),\nR2 = sofs:drestriction(R1, S),\nsofs:to_external(R2).\n[{1,a},{3,c}]\n```\n\n[`drestriction(R, S)`](`drestriction/2`) is equivalent to\n[`difference(R, restriction(R, S))`](`difference/2`).","title":"sofs.drestriction/2","ref":"sofs.html#drestriction/2"},{"type":"function","doc":"Returns a subset of `Set1` containing those elements that do not give an element\nin `Set2` as the result of applying `SetFun`.\n\n```erlang\n1> SetFun = {external, fun({_A,B,C}) -> {B,C} end},\nR1 = sofs:relation([{a,aa,1},{b,bb,2},{c,cc,3}]),\nR2 = sofs:relation([{bb,2},{cc,3},{dd,4}]),\nR3 = sofs:drestriction(SetFun, R1, R2),\nsofs:to_external(R3).\n[{a,aa,1}]\n```\n\n[`drestriction(F, S1, S2)`](`drestriction/3`) is equivalent to\n[`difference(S1, restriction(F, S1, S2))`](`difference/2`).","title":"sofs.drestriction/3","ref":"sofs.html#drestriction/3"},{"type":"function","doc":"Returns the [untyped empty set](`m:sofs#sets_definition`). `empty_set/0` is\nequivalent to [`from_term([], ['_'])`](`from_term/2`).","title":"sofs.empty_set/0","ref":"sofs.html#empty_set/0"},{"type":"function","doc":"Returns the [extension](`m:sofs#extension`) of `BinRel1` such that for each\nelement E in `Set` that does not belong to the [domain](`m:sofs#domain`) of\n`BinRel1`, `BinRel2` contains the pair (E, `AnySet`).\n\n```erlang\n1> S = sofs:set([b,c]),\nA = sofs:empty_set(),\nR = sofs:family([{a,[1,2]},{b,[3]}]),\nX = sofs:extension(R, S, A),\nsofs:to_external(X).\n[{a,[1,2]},{b,[3]},{c,[]}]\n```","title":"sofs.extension/3","ref":"sofs.html#extension/3"},{"type":"function","doc":"","title":"sofs.family/1","ref":"sofs.html#family/1"},{"type":"function","doc":"Creates a [family of subsets](`m:sofs#family`). [`family(F, T)`](`family/2`) is\nequivalent to [`from_term(F, T)`](`from_term/2`) if the result is a family.","title":"sofs.family/2","ref":"sofs.html#family/2"},{"type":"function","doc":"If `Family1` and `Family2` are [families](`m:sofs#family`), then `Family3` is\nthe family such that the index set is equal to the index set of `Family1`, and\n`Family3`\\[i] is the difference between `Family1`\\[i] and `Family2`\\[i] if\n`Family2` maps i, otherwise `Family1[i]`.\n\n```erlang\n1> F1 = sofs:family([{a,[1,2]},{b,[3,4]}]),\nF2 = sofs:family([{b,[4,5]},{c,[6,7]}]),\nF3 = sofs:family_difference(F1, F2),\nsofs:to_external(F3).\n[{a,[1,2]},{b,[3]}]\n```","title":"sofs.family_difference/2","ref":"sofs.html#family_difference/2"},{"type":"function","doc":"If `Family1` is a [family](`m:sofs#family`) and `Family1`\\[i] is a binary\nrelation for every i in the index set of `Family1`, then `Family2` is the family\nwith the same index set as `Family1` such that `Family2`\\[i] is the\n[domain](`m:sofs#domain`) of `Family1[i]`.\n\n```erlang\n1> FR = sofs:from_term([{a,[{1,a},{2,b},{3,c}]},{b,[]},{c,[{4,d},{5,e}]}]),\nF = sofs:family_domain(FR),\nsofs:to_external(F).\n[{a,[1,2,3]},{b,[]},{c,[4,5]}]\n```","title":"sofs.family_domain/1","ref":"sofs.html#family_domain/1"},{"type":"function","doc":"If `Family1` is a [family](`m:sofs#family`) and `Family1`\\[i] is a binary\nrelation for every i in the index set of `Family1`, then `Family2` is the family\nwith the same index set as `Family1` such that `Family2`\\[i] is the\n[field](`m:sofs#field`) of `Family1`\\[i].\n\n```erlang\n1> FR = sofs:from_term([{a,[{1,a},{2,b},{3,c}]},{b,[]},{c,[{4,d},{5,e}]}]),\nF = sofs:family_field(FR),\nsofs:to_external(F).\n[{a,[1,2,3,a,b,c]},{b,[]},{c,[4,5,d,e]}]\n```\n\n[`family_field(Family1)`](`family_field/1`) is equivalent to\n[`family_union(family_domain(Family1), family_range(Family1))`](`family_union/2`).","title":"sofs.family_field/1","ref":"sofs.html#family_field/1"},{"type":"function","doc":"If `Family1` is a [family](`m:sofs#family`) and `Family1`\\[i] is a set of sets\nfor every i in the index set of `Family1`, then `Family2` is the family with the\nsame index set as `Family1` such that `Family2`\\[i] is the\n[intersection](`m:sofs#intersection_n`) of `Family1`\\[i].\n\nIf `Family1`\\[i] is an empty set for some i, the process exits with a `badarg`\nmessage.\n\n```erlang\n1> F1 = sofs:from_term([{a,[[1,2,3],[2,3,4]]},{b,[[x,y,z],[x,y]]}]),\nF2 = sofs:family_intersection(F1),\nsofs:to_external(F2).\n[{a,[2,3]},{b,[x,y]}]\n```","title":"sofs.family_intersection/1","ref":"sofs.html#family_intersection/1"},{"type":"function","doc":"If `Family1` and `Family2` are [families](`m:sofs#family`), then `Family3` is\nthe family such that the index set is the intersection of `Family1`:s and\n`Family2`:s index sets, and `Family3`\\[i] is the intersection of `Family1`\\[i]\nand `Family2`\\[i].\n\n```erlang\n1> F1 = sofs:family([{a,[1,2]},{b,[3,4]},{c,[5,6]}]),\nF2 = sofs:family([{b,[4,5]},{c,[7,8]},{d,[9,10]}]),\nF3 = sofs:family_intersection(F1, F2),\nsofs:to_external(F3).\n[{b,[4]},{c,[]}]\n```","title":"sofs.family_intersection/2","ref":"sofs.html#family_intersection/2"},{"type":"function","doc":"If `Family1` is a [family](`m:sofs#family`), then `Family2` is the family with\nthe same index set as `Family1` such that `Family2`\\[i] is the result of calling\n`SetFun` with `Family1`\\[i] as argument.\n\n```erlang\n1> F1 = sofs:from_term([{a,[[1,2],[2,3]]},{b,[[]]}]),\nF2 = sofs:family_projection(fun sofs:union/1, F1),\nsofs:to_external(F2).\n[{a,[1,2,3]},{b,[]}]\n```","title":"sofs.family_projection/2","ref":"sofs.html#family_projection/2"},{"type":"function","doc":"If `Family1` is a [family](`m:sofs#family`) and `Family1`\\[i] is a binary\nrelation for every i in the index set of `Family1`, then `Family2` is the family\nwith the same index set as `Family1` such that `Family2`\\[i] is the\n[range](`m:sofs#range`) of `Family1`\\[i].\n\n```erlang\n1> FR = sofs:from_term([{a,[{1,a},{2,b},{3,c}]},{b,[]},{c,[{4,d},{5,e}]}]),\nF = sofs:family_range(FR),\nsofs:to_external(F).\n[{a,[a,b,c]},{b,[]},{c,[d,e]}]\n```","title":"sofs.family_range/1","ref":"sofs.html#family_range/1"},{"type":"function","doc":"If `Family1` is a [family](`m:sofs#family`), then `Family2` is the\n[restriction](`m:sofs#restriction`) of `Family1` to those elements i of the\nindex set for which `Fun` applied to `Family1`\\[i] returns `true`. If `Fun` is a\ntuple `{external, Fun2}`, then `Fun2` is applied to the\n[external set](`m:sofs#external_set`) of `Family1`\\[i], otherwise `Fun` is\napplied to `Family1`\\[i].\n\n```erlang\n1> F1 = sofs:family([{a,[1,2,3]},{b,[1,2]},{c,[1]}]),\nSpecFun = fun(S) -> sofs:no_elements(S) =:= 2 end,\nF2 = sofs:family_specification(SpecFun, F1),\nsofs:to_external(F2).\n[{b,[1,2]}]\n```","title":"sofs.family_specification/2","ref":"sofs.html#family_specification/2"},{"type":"function","doc":"","title":"sofs.family_to_digraph/1","ref":"sofs.html#family_to_digraph/1"},{"type":"function","doc":"Creates a directed graph from [family](`m:sofs#family`) `Family`. For each pair\n(a, \\{b\\[1], ..., b\\[n]\\}) of `Family`, vertex a and the edges (a, b\\[i]) for\n1 <= i <= n are added to a newly created directed graph.\n\n`GraphType` is passed on to `digraph:new/1`.\n\nIt F is a family, it holds that F is a subset of\n[`digraph_to_family(family_to_digraph(F), type(F))`](`digraph_to_family/2`).\nEquality holds if [`union_of_family(F)`](`union_of_family/1`) is a subset of\n[`domain(F)`](`domain/1`).\n\nCreating a cycle in an acyclic graph exits the process with a `cyclic` message.","title":"sofs.family_to_digraph/2","ref":"sofs.html#family_to_digraph/2"},{"type":"function","doc":"If `Family` is a [family](`m:sofs#family`), then `BinRel` is the binary relation\ncontaining all pairs (i, x) such that i belongs to the index set of `Family` and\nx belongs to `Family`\\[i].\n\n```erlang\n1> F = sofs:family([{a,[]}, {b,[1]}, {c,[2,3]}]),\nR = sofs:family_to_relation(F),\nsofs:to_external(R).\n[{b,1},{c,2},{c,3}]\n```","title":"sofs.family_to_relation/1","ref":"sofs.html#family_to_relation/1"},{"type":"function","doc":"If `Family1` is a [family](`m:sofs#family`) and `Family1`\\[i] is a set of sets\nfor each i in the index set of `Family1`, then `Family2` is the family with the\nsame index set as `Family1` such that `Family2`\\[i] is the\n[union](`m:sofs#union_n`) of `Family1`\\[i].\n\n```erlang\n1> F1 = sofs:from_term([{a,[[1,2],[2,3]]},{b,[[]]}]),\nF2 = sofs:family_union(F1),\nsofs:to_external(F2).\n[{a,[1,2,3]},{b,[]}]\n```\n\n[`family_union(F)`](`family_union/1`) is equivalent to\n[`family_projection(fun sofs:union/1, F)`](`family_projection/2`).","title":"sofs.family_union/1","ref":"sofs.html#family_union/1"},{"type":"function","doc":"If `Family1` and `Family2` are [families](`m:sofs#family`), then `Family3` is\nthe family such that the index set is the union of `Family1`:s and `Family2`:s\nindex sets, and `Family3`\\[i] is the union of `Family1`\\[i] and `Family2`\\[i] if\nboth map i, otherwise `Family1`\\[i] or `Family2`\\[i].\n\n```erlang\n1> F1 = sofs:family([{a,[1,2]},{b,[3,4]},{c,[5,6]}]),\nF2 = sofs:family([{b,[4,5]},{c,[7,8]},{d,[9,10]}]),\nF3 = sofs:family_union(F1, F2),\nsofs:to_external(F3).\n[{a,[1,2]},{b,[3,4,5]},{c,[5,6,7,8]},{d,[9,10]}]\n```","title":"sofs.family_union/2","ref":"sofs.html#family_union/2"},{"type":"function","doc":"Returns the [field](`m:sofs#field`) of the binary relation `BinRel`.\n\n```erlang\n1> R = sofs:relation([{1,a},{1,b},{2,b},{2,c}]),\nS = sofs:field(R),\nsofs:to_external(S).\n[1,2,a,b,c]\n```\n\n[`field(R)`](`field/1`) is equivalent to\n[`union(domain(R), range(R))`](`union/2`).","title":"sofs.field/1","ref":"sofs.html#field/1"},{"type":"function","doc":"Creates a set from the [external set](`m:sofs#external_set`) `ExternalSet` and\nthe [type](`m:sofs#type`) `Type`. It is assumed that `Type` is a\n[valid type](`m:sofs#valid_type`) of `ExternalSet`.","title":"sofs.from_external/2","ref":"sofs.html#from_external/2"},{"type":"function","doc":"Returns the [unordered set](`m:sofs#sets_definition`) containing the sets of\nlist `ListOfSets`.\n\n```erlang\n1> S1 = sofs:relation([{a,1},{b,2}]),\nS2 = sofs:relation([{x,3},{y,4}]),\nS = sofs:from_sets([S1,S2]),\nsofs:to_external(S).\n[[{a,1},{b,2}],[{x,3},{y,4}]]\n```\n\nReturns the [ordered set](`m:sofs#sets_definition`) containing the sets of the\nnon-empty tuple `TupleOfSets`.","title":"sofs.from_sets/1","ref":"sofs.html#from_sets/1"},{"type":"function","doc":"","title":"sofs.from_term/1","ref":"sofs.html#from_term/1"},{"type":"function","doc":"Creates an element of [Sets](`m:sofs#sets_definition`) by\ntraversing term `Term`, sorting lists, removing duplicates, and deriving or\nverifying a [valid type](`m:sofs#valid_type`) for the so obtained external set.\n\nAn explicitly specified [type](`m:sofs#type`) `Type` can be used to limit the\ndepth of the traversal; an atomic type stops the traversal, as shown by the\nfollowing example where `\"foo\"` and `{\"foo\"}` are left unmodified:\n\n```erlang\n1> S = sofs:from_term([{{\"foo\"},[1,1]},{\"foo\",[2,2]}],\n [{atom,[atom]}]),\n sofs:to_external(S).\n[{{\"foo\"},[1]},{\"foo\",[2]}]\n```\n\n`from_term` can be used for creating atomic or ordered sets. The only purpose of\nsuch a set is that of later building unordered sets, as all functions in this\nmodule that _do_ anything operate on unordered sets. Creating unordered sets\nfrom a collection of ordered sets can be the way to go if the ordered sets are\nbig and one does not want to waste heap by rebuilding the elements of the\nunordered set. The following example shows that a set can be built \"layer by\nlayer\":\n\n```erlang\n1> A = sofs:from_term(a),\nS = sofs:set([1,2,3]),\nP1 = sofs:from_sets({A,S}),\nP2 = sofs:from_term({b,[6,5,4]}),\nSs = sofs:from_sets([P1,P2]),\nsofs:to_external(Ss).\n[{a,[1,2,3]},{b,[4,5,6]}]\n```\n\nOther functions that create sets are `from_external/2` and `from_sets/1`.\nSpecial cases of [`from_term/2`](`from_term/2`) are\n[`a_function/1,2`](`a_function/1`), `empty_set/0`, [`family/1,2`](`family/1`),\n[`relation/1,2`](`relation/1`), and [`set/1,2`](`set/1`).","title":"sofs.from_term/2","ref":"sofs.html#from_term/2"},{"type":"function","doc":"Returns the [image](`m:sofs#image`) of set `Set1` under the binary relation\n`BinRel`.\n\n```erlang\n1> R = sofs:relation([{1,a},{2,b},{2,c},{3,d}]),\nS1 = sofs:set([1,2]),\nS2 = sofs:image(R, S1),\nsofs:to_external(S2).\n[a,b,c]\n```","title":"sofs.image/2","ref":"sofs.html#image/2"},{"type":"function","doc":"Returns the [intersection](`m:sofs#intersection_n`) of the set of sets\n`SetOfSets`.\n\nIntersecting an empty set of sets exits the process with a `badarg` message.","title":"sofs.intersection/1","ref":"sofs.html#intersection/1"},{"type":"function","doc":"Returns the [intersection](`m:sofs#intersection`) of `Set1` and `Set2`.","title":"sofs.intersection/2","ref":"sofs.html#intersection/2"},{"type":"function","doc":"Returns the intersection of [family](`m:sofs#family`) `Family`.\n\nIntersecting an empty family exits the process with a `badarg` message.\n\n```erlang\n1> F = sofs:family([{a,[0,2,4]},{b,[0,1,2]},{c,[2,3]}]),\nS = sofs:intersection_of_family(F),\nsofs:to_external(S).\n[2]\n```","title":"sofs.intersection_of_family/1","ref":"sofs.html#intersection_of_family/1"},{"type":"function","doc":"Returns the [inverse](`m:sofs#inverse`) of function `Function1`.\n\n```erlang\n1> R1 = sofs:relation([{1,a},{2,b},{3,c}]),\nR2 = sofs:inverse(R1),\nsofs:to_external(R2).\n[{a,1},{b,2},{c,3}]\n```","title":"sofs.inverse/1","ref":"sofs.html#inverse/1"},{"type":"function","doc":"Returns the [inverse image](`m:sofs#inverse_image`) of `Set1` under the binary\nrelation `BinRel`.\n\n```erlang\n1> R = sofs:relation([{1,a},{2,b},{2,c},{3,d}]),\nS1 = sofs:set([c,d,e]),\nS2 = sofs:inverse_image(R, S1),\nsofs:to_external(S2).\n[2,3]\n```","title":"sofs.inverse_image/2","ref":"sofs.html#inverse_image/2"},{"type":"function","doc":"Returns `true` if the binary relation `BinRel` is a\n[function](`m:sofs#function`) or the untyped empty set, otherwise `false`.","title":"sofs.is_a_function/1","ref":"sofs.html#is_a_function/1"},{"type":"function","doc":"Returns `true` if `Set1` and `Set2` are [disjoint](`m:sofs#disjoint`), otherwise\n`false`.","title":"sofs.is_disjoint/2","ref":"sofs.html#is_disjoint/2"},{"type":"function","doc":"Returns `true` if `AnySet` is an empty unordered set, otherwise `false`.","title":"sofs.is_empty_set/1","ref":"sofs.html#is_empty_set/1"},{"type":"function","doc":"Returns `true` if `AnySet1` and `AnySet2` are [equal](`m:sofs#equal`), otherwise\n`false`. The following example shows that `==/2` is used when comparing sets for\nequality:\n\n```erlang\n1> S1 = sofs:set([1.0]),\nS2 = sofs:set([1]),\nsofs:is_equal(S1, S2).\ntrue\n```","title":"sofs.is_equal/2","ref":"sofs.html#is_equal/2"},{"type":"function","doc":"Returns `true` if `AnySet` appears to be an\n[unordered set](`m:sofs#sets_definition`), and `false` if `AnySet` is an ordered\nset or an atomic set or any other term.\n\nNote that the test is shallow and this function will return `true` for any term\nthat coincides with the representation of an unordered set. See also note on\n[data types](`e:system:data_types.md#no_user_types`).","title":"sofs.is_set/1","ref":"sofs.html#is_set/1"},{"type":"function","doc":"Returns `true` if `Term` appears to be an\n[unordered set](`m:sofs#sets_definition`), an ordered set, or an atomic set,\notherwise `false`.\n\nNote that this function will return `true` for any term that\ncoincides with the representation of a `sofs` set. See also note on\n[data types](`e:system:data_types.md#no_user_types`).","title":"sofs.is_sofs_set/1","ref":"sofs.html#is_sofs_set/1"},{"type":"function","doc":"Returns `true` if `Set1` is a [subset](`m:sofs#subset`) of `Set2`, otherwise\n`false`.","title":"sofs.is_subset/2","ref":"sofs.html#is_subset/2"},{"type":"function","doc":"Returns `true` if term `Term` is a [type](`m:sofs#type`).","title":"sofs.is_type/1","ref":"sofs.html#is_type/1"},{"type":"function","doc":"Returns the [natural join](`m:sofs#natural_join`) of the relations `Relation1`\nand `Relation2` on coordinates `I` and `J`.\n\n```erlang\n1> R1 = sofs:relation([{a,x,1},{b,y,2}]),\nR2 = sofs:relation([{1,f,g},{1,h,i},{2,3,4}]),\nJ = sofs:join(R1, 3, R2, 1),\nsofs:to_external(J).\n[{a,x,1,f,g},{a,x,1,h,i},{b,y,2,3,4}]\n```","title":"sofs.join/4","ref":"sofs.html#join/4"},{"type":"function","doc":"If `TupleOfBinRels` is a non-empty tuple \\{R\\[1], ..., R\\[n]\\} of binary\nrelations and `BinRel1` is a binary relation, then `BinRel2` is the\n[multiple relative product](`m:sofs#multiple_relative_product`) of the ordered\nset (R\\[i], ..., R\\[n]) and `BinRel1`.\n\n```erlang\n1> Ri = sofs:relation([{a,1},{b,2},{c,3}]),\nR = sofs:relation([{a,b},{b,c},{c,a}]),\nMP = sofs:multiple_relative_product({Ri, Ri}, R),\nsofs:to_external(sofs:range(MP)).\n[{1,2},{2,3},{3,1}]\n```","title":"sofs.multiple_relative_product/2","ref":"sofs.html#multiple_relative_product/2"},{"type":"function","doc":"Returns the number of elements of the ordered or unordered set `ASet`.","title":"sofs.no_elements/1","ref":"sofs.html#no_elements/1"},{"type":"function","doc":"Returns the [partition](`m:sofs#partition`) of the union of the set of sets\n`SetOfSets` such that two elements are considered equal if they belong to the\nsame elements of `SetOfSets`.\n\n```erlang\n1> Sets1 = sofs:from_term([[a,b,c],[d,e,f],[g,h,i]]),\nSets2 = sofs:from_term([[b,c,d],[e,f,g],[h,i,j]]),\nP = sofs:partition(sofs:union(Sets1, Sets2)),\nsofs:to_external(P).\n[[a],[b,c],[d],[e,f],[g],[h,i],[j]]\n```","title":"sofs.partition/1","ref":"sofs.html#partition/1"},{"type":"function","doc":"Returns the [partition](`m:sofs#partition`) of `Set` such that two elements are\nconsidered equal if the results of applying `SetFun` are equal.\n\n```erlang\n1> Ss = sofs:from_term([[a],[b],[c,d],[e,f]]),\nSetFun = fun(S) -> sofs:from_term(sofs:no_elements(S)) end,\nP = sofs:partition(SetFun, Ss),\nsofs:to_external(P).\n[[[a],[b]],[[c,d],[e,f]]]\n```","title":"sofs.partition/2","ref":"sofs.html#partition/2"},{"type":"function","doc":"Returns a pair of sets that, regarded as constituting a set, forms a\n[partition](`m:sofs#partition`) of `Set1`. If the result of applying `SetFun` to\nan element of `Set1` gives an element in `Set2`, the element belongs to `Set3`,\notherwise the element belongs to `Set4`.\n\n```erlang\n1> R1 = sofs:relation([{1,a},{2,b},{3,c}]),\nS = sofs:set([2,4,6]),\n{R2,R3} = sofs:partition(1, R1, S),\n{sofs:to_external(R2),sofs:to_external(R3)}.\n{[{2,b}],[{1,a},{3,c}]}\n```\n\n[`partition(F, S1, S2)`](`partition/3`) is equivalent to\n`{restriction(F, S1, S2), drestriction(F, S1, S2)}`.","title":"sofs.partition/3","ref":"sofs.html#partition/3"},{"type":"function","doc":"Returns [family](`m:sofs#family`) `Family` where the indexed set is a\n[partition](`m:sofs#partition`) of `Set` such that two elements are considered\nequal if the results of applying `SetFun` are the same value i. This i is the\nindex that `Family` maps onto the\n[equivalence class](`m:sofs#equivalence_class`).\n\n```erlang\n1> S = sofs:relation([{a,a,a,a},{a,a,b,b},{a,b,b,b}]),\nSetFun = {external, fun({A,_,C,_}) -> {A,C} end},\nF = sofs:partition_family(SetFun, S),\nsofs:to_external(F).\n[{{a,a},[{a,a,a,a}]},{{a,b},[{a,a,b,b},{a,b,b,b}]}]\n```","title":"sofs.partition_family/2","ref":"sofs.html#partition_family/2"},{"type":"function","doc":"Returns the [Cartesian product](`m:sofs#Cartesian_product_tuple`) of the\nnon-empty tuple of sets `TupleOfSets`. If (x\\[1], ..., x\\[n]) is an element of\nthe n-ary relation `Relation`, then x\\[i] is drawn from element i of\n`TupleOfSets`.\n\n```erlang\n1> S1 = sofs:set([a,b]),\nS2 = sofs:set([1,2]),\nS3 = sofs:set([x,y]),\nP3 = sofs:product({S1,S2,S3}),\nsofs:to_external(P3).\n[{a,1,x},{a,1,y},{a,2,x},{a,2,y},{b,1,x},{b,1,y},{b,2,x},{b,2,y}]\n```","title":"sofs.product/1","ref":"sofs.html#product/1"},{"type":"function","doc":"Returns the [Cartesian product](`m:sofs#Cartesian_product`) of `Set1` and\n`Set2`.\n\n```erlang\n1> S1 = sofs:set([1,2]),\nS2 = sofs:set([a,b]),\nR = sofs:product(S1, S2),\nsofs:to_external(R).\n[{1,a},{1,b},{2,a},{2,b}]\n```\n\n[`product(S1, S2)`](`product/2`) is equivalent to\n[`product({S1, S2})`](`product/1`).","title":"sofs.product/2","ref":"sofs.html#product/2"},{"type":"function","doc":"Returns the set created by substituting each element of `Set1` by the result of\napplying `SetFun` to the element.\n\nIf `SetFun` is a number i >= 1 and `Set1` is a relation, then the returned set\nis the [projection](`m:sofs#projection`) of `Set1` onto coordinate i.\n\n```erlang\n1> S1 = sofs:from_term([{1,a},{2,b},{3,a}]),\nS2 = sofs:projection(2, S1),\nsofs:to_external(S2).\n[a,b]\n```","title":"sofs.projection/2","ref":"sofs.html#projection/2"},{"type":"function","doc":"Returns the [range](`m:sofs#range`) of the binary relation `BinRel`.\n\n```erlang\n1> R = sofs:relation([{1,a},{1,b},{2,b},{2,c}]),\nS = sofs:range(R),\nsofs:to_external(S).\n[a,b,c]\n```","title":"sofs.range/1","ref":"sofs.html#range/1"},{"type":"function","doc":"Equivalent to [`relation(Tuples, Type)`](`relation/2`) where `Type` is the size\nof the first tuple of `Tuples` is used if there is such a tuple.\n\nIf tuples is `[]`, then `Type` is `2`.","title":"sofs.relation/1","ref":"sofs.html#relation/1"},{"type":"function","doc":"Creates a [relation](`m:sofs#relation`). [`relation(R, T)`](`relation/2`) is\nequivalent to [`from_term(R, T)`](`from_term/2`), if T is a\n[type](`m:sofs#type`) and the result is a relation.\n\nIf `Type` is an integer N, then `[{atom, ..., atom}])`, where the tuple size is N,\nis used as type of the relation.","title":"sofs.relation/2","ref":"sofs.html#relation/2"},{"type":"function","doc":"Returns [family](`m:sofs#family`) `Family` such that the index set is equal to\nthe [domain](`m:sofs#domain`) of the binary relation `BinRel`, and `Family`\\[i]\nis the [image](`m:sofs#image`) of the set of i under `BinRel`.\n\n```erlang\n1> R = sofs:relation([{b,1},{c,2},{c,3}]),\nF = sofs:relation_to_family(R),\nsofs:to_external(F).\n[{b,[1]},{c,[2,3]}]\n```","title":"sofs.relation_to_family/1","ref":"sofs.html#relation_to_family/1"},{"type":"function","doc":"Returns the [relative product](`m:sofs#relative_product`) of the\n[converse](`m:sofs#converse`) of the binary relation `BinRel1` and the binary\nrelation `BinRel2`.\n\n```erlang\n1> R1 = sofs:relation([{1,a},{1,aa},{2,b}]),\nR2 = sofs:relation([{1,u},{2,v},{3,c}]),\nR3 = sofs:relative_product1(R1, R2),\nsofs:to_external(R3).\n[{a,u},{aa,u},{b,v}]\n```\n\n[`relative_product1(R1, R2)`](`relative_product1/2`) is equivalent to\n[`relative_product(converse(R1), R2)`](`relative_product/2`).","title":"sofs.relative_product1/2","ref":"sofs.html#relative_product1/2"},{"type":"function","doc":"","title":"sofs.relative_product/1","ref":"sofs.html#relative_product/1"},{"type":"function","doc":"If `ListOfBinRels` is a non-empty list \\[R[1], ..., R\\[n]] of binary relations\nand `BinRel1` is a binary relation, then `BinRel2` is the\n[relative product](`m:sofs#tuple_relative_product`) of the ordered set\n(R\\[i], ..., R\\[n]) and `BinRel1`.\n\nIf `BinRel1` is omitted, the relation of equality between the elements of the\n[Cartesian product](`m:sofs#Cartesian_product_tuple`) of the ranges of R\\[i],\nrange R\\[1] × ... × range R\\[n], is used instead (intuitively, nothing is\n\"lost\").\n\n```erlang\n1> TR = sofs:relation([{1,a},{1,aa},{2,b}]),\nR1 = sofs:relation([{1,u},{2,v},{3,c}]),\nR2 = sofs:relative_product([TR, R1]),\nsofs:to_external(R2).\n[{1,{a,u}},{1,{aa,u}},{2,{b,v}}]\n```\n\nNotice that [`relative_product([R1], R2)`](`relative_product/2`) is different\nfrom [`relative_product(R1, R2)`](`relative_product/2`); the list of one element\nis not identified with the element itself.\n\nReturns the [relative product](`m:sofs#relative_product`) of the binary\nrelations `BinRel1` and `BinRel2`.","title":"sofs.relative_product/2","ref":"sofs.html#relative_product/2"},{"type":"function","doc":"Returns the [restriction](`m:sofs#restriction`) of the binary relation `BinRel1`\nto `Set`.\n\n```erlang\n1> R1 = sofs:relation([{1,a},{2,b},{3,c}]),\nS = sofs:set([1,2,4]),\nR2 = sofs:restriction(R1, S),\nsofs:to_external(R2).\n[{1,a},{2,b}]\n```","title":"sofs.restriction/2","ref":"sofs.html#restriction/2"},{"type":"function","doc":"Returns a subset of `Set1` containing those elements that gives an element in\n`Set2` as the result of applying `SetFun`.\n\n```erlang\n1> S1 = sofs:relation([{1,a},{2,b},{3,c}]),\nS2 = sofs:set([b,c,d]),\nS3 = sofs:restriction(2, S1, S2),\nsofs:to_external(S3).\n[{2,b},{3,c}]\n```","title":"sofs.restriction/3","ref":"sofs.html#restriction/3"},{"type":"function","doc":"","title":"sofs.set/1","ref":"sofs.html#set/1"},{"type":"function","doc":"Creates an [unordered set](`m:sofs#sets_definition`). [`set(L, T)`](`set/2`) is\nequivalent to [`from_term(L, T)`](`from_term/2`), if the result is an unordered\nset.","title":"sofs.set/2","ref":"sofs.html#set/2"},{"type":"function","doc":"Returns the set containing every element of `Set1` for which `Fun` returns\n`true`. If `Fun` is a tuple `{external, Fun2}`, `Fun2` is applied to the\n[external set](`m:sofs#external_set`) of each element, otherwise `Fun` is\napplied to each element.\n\n```erlang\n1> R1 = sofs:relation([{a,1},{b,2}]),\nR2 = sofs:relation([{x,1},{x,2},{y,3}]),\nS1 = sofs:from_sets([R1,R2]),\nS2 = sofs:specification(fun sofs:is_a_function/1, S1),\nsofs:to_external(S2).\n[[{a,1},{b,2}]]\n```","title":"sofs.specification/2","ref":"sofs.html#specification/2"},{"type":"function","doc":"Returns the [strict relation](`m:sofs#strict_relation`) corresponding to the\nbinary relation `BinRel1`.\n\n```erlang\n1> R1 = sofs:relation([{1,1},{1,2},{2,1},{2,2}]),\nR2 = sofs:strict_relation(R1),\nsofs:to_external(R2).\n[{1,2},{2,1}]\n```","title":"sofs.strict_relation/1","ref":"sofs.html#strict_relation/1"},{"type":"function","doc":"Returns a function, the domain of which is `Set1`. The value of an element of\nthe domain is the result of applying `SetFun` to the element.\n\n```erlang\n1> L = [{a,1},{b,2}].\n[{a,1},{b,2}]\n2> sofs:to_external(sofs:projection(1,sofs:relation(L))).\n[a,b]\n3> sofs:to_external(sofs:substitution(1,sofs:relation(L))).\n[{{a,1},a},{{b,2},b}]\n4> SetFun = {external, fun({A,_}=E) -> {E,A} end},\nsofs:to_external(sofs:projection(SetFun,sofs:relation(L))).\n[{{a,1},a},{{b,2},b}]\n```\n\nThe relation of equality between the elements of \\{a,b,c\\}:\n\n```erlang\n1> I = sofs:substitution(fun(A) -> A end, sofs:set([a,b,c])),\nsofs:to_external(I).\n[{a,a},{b,b},{c,c}]\n```\n\nLet `SetOfSets` be a set of sets and `BinRel` a binary relation. The function\nthat maps each element `Set` of `SetOfSets` onto the [image](`m:sofs#image`) of\n`Set` under `BinRel` is returned by the following function:\n\n```erlang\nimages(SetOfSets, BinRel) ->\n Fun = fun(Set) -> sofs:image(BinRel, Set) end,\n sofs:substitution(Fun, SetOfSets).\n```\n\nExternal unordered sets are represented as sorted lists. So, creating the image\nof a set under a relation R can traverse all elements of R (to that comes the\nsorting of results, the image). In `image/2`, `BinRel` is traversed once for\neach element of `SetOfSets`, which can take too long. The following efficient\nfunction can be used instead under the assumption that the image of each element\nof `SetOfSets` under `BinRel` is non-empty:\n\n```erlang\nimages2(SetOfSets, BinRel) ->\n CR = sofs:canonical_relation(SetOfSets),\n R = sofs:relative_product1(CR, BinRel),\n sofs:relation_to_family(R).\n```","title":"sofs.substitution/2","ref":"sofs.html#substitution/2"},{"type":"function","doc":"Returns the [symmetric difference](`m:sofs#symmetric_difference`) (or the\nBoolean sum) of `Set1` and `Set2`.\n\n```erlang\n1> S1 = sofs:set([1,2,3]),\nS2 = sofs:set([2,3,4]),\nP = sofs:symdiff(S1, S2),\nsofs:to_external(P).\n[1,4]\n```","title":"sofs.symdiff/2","ref":"sofs.html#symdiff/2"},{"type":"function","doc":"Returns a triple of sets:\n\n- `Set3` contains the elements of `Set1` that do not belong to `Set2`.\n- `Set4` contains the elements of `Set1` that belong to `Set2`.\n- `Set5` contains the elements of `Set2` that do not belong to `Set1`.","title":"sofs.symmetric_partition/2","ref":"sofs.html#symmetric_partition/2"},{"type":"function","doc":"Returns the [external set](`m:sofs#external_set`) of an atomic, ordered, or\nunordered set.","title":"sofs.to_external/1","ref":"sofs.html#to_external/1"},{"type":"function","doc":"Returns the elements of the ordered set `ASet` as a tuple of sets, and the\nelements of the unordered set `ASet` as a sorted list of sets without\nduplicates.","title":"sofs.to_sets/1","ref":"sofs.html#to_sets/1"},{"type":"function","doc":"Returns the [type](`m:sofs#type`) of an atomic, ordered, or unordered set.","title":"sofs.type/1","ref":"sofs.html#type/1"},{"type":"function","doc":"Returns the [union](`m:sofs#union_n`) of the set of sets `SetOfSets`.","title":"sofs.union/1","ref":"sofs.html#union/1"},{"type":"function","doc":"Returns the [union](`m:sofs#union`) of `Set1` and `Set2`.","title":"sofs.union/2","ref":"sofs.html#union/2"},{"type":"function","doc":"Returns the union of [family](`m:sofs#family`) `Family`.\n\n```erlang\n1> F = sofs:family([{a,[0,2,4]},{b,[0,1,2]},{c,[2,3]}]),\nS = sofs:union_of_family(F),\nsofs:to_external(S).\n[0,1,2,3,4]\n```","title":"sofs.union_of_family/1","ref":"sofs.html#union_of_family/1"},{"type":"function","doc":"Returns a subset S of the [weak relation](`m:sofs#weak_relation`) W\ncorresponding to the binary relation `BinRel1`. Let F be the\n[field](`m:sofs#field`) of `BinRel1`. The subset S is defined so that x S y if x\nW y for some x in F and for some y in F.\n\n```erlang\n1> R1 = sofs:relation([{1,1},{1,2},{3,1}]),\nR2 = sofs:weak_relation(R1),\nsofs:to_external(R2).\n[{1,1},{1,2},{2,2},{3,1},{3,3}]\n```","title":"sofs.weak_relation/1","ref":"sofs.html#weak_relation/1"},{"type":"type","doc":"A [function](`m:sofs#function`).","title":"sofs.a_function/0","ref":"sofs.html#t:a_function/0"},{"type":"opaque","doc":"An [unordered set](`m:sofs#sets_definition`).","title":"sofs.a_set/0","ref":"sofs.html#t:a_set/0"},{"type":"type","doc":"Any kind of set (also included are the atomic sets).","title":"sofs.anyset/0","ref":"sofs.html#t:anyset/0"},{"type":"type","doc":"A [binary relation](`m:sofs#binary_relation`).","title":"sofs.binary_relation/0","ref":"sofs.html#t:binary_relation/0"},{"type":"type","doc":"An [external set](`m:sofs#external_set`).","title":"sofs.external_set/0","ref":"sofs.html#t:external_set/0"},{"type":"type","doc":"A [family](`m:sofs#family`) (of subsets).","title":"sofs.family/0","ref":"sofs.html#t:family/0"},{"type":"opaque","doc":"An [ordered set](`m:sofs#sets_definition`).","title":"sofs.ordset/0","ref":"sofs.html#t:ordset/0"},{"type":"type","doc":"An [n-ary relation](`m:sofs#n_ary_relation`).","title":"sofs.relation/0","ref":"sofs.html#t:relation/0"},{"type":"type","doc":"A [SetFun](`m:sofs#set_fun`).","title":"sofs.set_fun/0","ref":"sofs.html#t:set_fun/0"},{"type":"type","doc":"An [unordered set](`m:sofs#sets_definition`) of unordered sets.","title":"sofs.set_of_sets/0","ref":"sofs.html#t:set_of_sets/0"},{"type":"type","doc":"","title":"sofs.spec_fun/0","ref":"sofs.html#t:spec_fun/0"},{"type":"type","doc":"A tuple where the elements are of type `T`.","title":"sofs.tuple_of/1","ref":"sofs.html#t:tuple_of/1"},{"type":"type","doc":"A [type](`m:sofs#type`).","title":"sofs.type/0","ref":"sofs.html#t:type/0"},{"type":"module","doc":"Library for handling binary data.\n\nThis module contains functions for manipulating byte-oriented binaries. Although\nthe majority of functions could be provided using bit-syntax, the functions in\nthis library are highly optimized and are expected to either execute faster or\nconsume less memory, or both, than a counterpart written in pure Erlang.\n\nThe module is provided according to Erlang Enhancement Proposal (EEP) 31.\n\n> #### Note {: .info }\n>\n> The library handles byte-oriented data. For bitstrings that are not binaries\n> (does not contain whole octets of bits) a `badarg` exception is thrown from\n> any of the functions in this module.","title":"binary","ref":"binary.html"},{"type":"function","doc":"Returns the byte at position `Pos` (zero-based) in binary `Subject` as an\ninteger.\n\nIf `Pos` >= [`byte_size(Subject)`](`byte_size/1`), a `badarg` exception\nis raised.","title":"binary.at/2","ref":"binary.html#at/2"},{"type":"function","doc":"Converts `Subject` to a list of `t:byte/0`s, each representing the value of one byte.\n\n_Example:_\n\n```erlang\n1> binary:bin_to_list(<<\"erlang\">>).\n\"erlang\"\n%% or [101,114,108,97,110,103] in list notation.\n```","title":"binary.bin_to_list/1","ref":"binary.html#bin_to_list/1"},{"type":"function","doc":"","title":"binary.bin_to_list/2","ref":"binary.html#bin_to_list/2"},{"type":"function","doc":"Converts `Subject` to a list of `t:byte/0`s, each representing the value of one\nbyte. `PosLen` or alternatively `Pos` and `Len` denote which part of the\n`Subject` binary to convert. By default, the entire `Subject` binary is\nconverted.\n\n_Example:_\n\n```erlang\n1> binary:bin_to_list(<<\"erlang\">>, {1,3}).\n\"rla\"\n%% or [114,108,97] in list notation.\n```\n\nIf `PosLen` or alternatively `Pos` and `Len` in any way reference outside the\nbinary, a `badarg` exception is raised.","title":"binary.bin_to_list/3","ref":"binary.html#bin_to_list/3"},{"type":"function","doc":"Builds an internal structure representing a compilation of a search pattern,\nlater to be used in functions `match/3`, `matches/3`, `split/3`, or `replace/4`.\n\nThe `t:cp/0` returned is guaranteed to be a `t:tuple/0` to allow programs to\ndistinguish it from non-precompiled search patterns.\n\nWhen a list of binaries is specified, it denotes a set of alternative binaries\nto search for. For example, if `[<<\"functional\">>,<<\"programming\">>]` is\nspecified as `Pattern`, this means either `<<\"functional\">>` or\n`<<\"programming\">>`\". The pattern is a set of alternatives; when only a single\nbinary is specified, the set has only one element. The order of alternatives in\na pattern is not significant.\n\nThe list of binaries used for search alternatives must be flat, proper and\nnon-empty.\n\nIf `Pattern` is not a binary or a flat proper non-empty list of binaries with\nlength > 0, a `badarg` exception is raised.","title":"binary.compile_pattern/1","ref":"binary.html#compile_pattern/1"},{"type":"function","doc":"","title":"binary.copy/1","ref":"binary.html#copy/1"},{"type":"function","doc":"Creates a binary with the content of `Subject` duplicated `N` times.\n\nThis function always creates a new binary, even if `N = 1`. By using `copy/1` on\na binary referencing a larger binary, one can free up the larger binary for\ngarbage collection.\n\n> #### Note {: .info }\n>\n> By deliberately copying a single binary to avoid referencing a larger binary,\n> one can, instead of freeing up the larger binary for later garbage collection,\n> create much more binary data than needed. Sharing binary data is usually good.\n> Only in special cases, when small parts reference large binaries and the large\n> binaries are no longer used in any process, deliberate copying can be a good\n> idea.","title":"binary.copy/2","ref":"binary.html#copy/2"},{"type":"function","doc":"Decodes a hex encoded binary into a binary.\n\n_Example_\n\n```erlang\n1> binary:decode_hex(<<\"66\">>).\n<<\"f\">>\n```","title":"binary.decode_hex/1","ref":"binary.html#decode_hex/1"},{"type":"function","doc":"","title":"binary.decode_unsigned/1","ref":"binary.html#decode_unsigned/1"},{"type":"function","doc":"Converts the binary digit representation, in big endian or little endian, of a\npositive integer in `Subject` to an Erlang `t:integer/0`.\n\n_Example:_\n\n```erlang\n1> binary:decode_unsigned(<<169,138,199>>).\n11111111\n2> binary:decode_unsigned(<<169,138,199>>, big).\n11111111\n3> binary:decode_unsigned(<<169,138,199>>, little).\n13077161\n```","title":"binary.decode_unsigned/2","ref":"binary.html#decode_unsigned/2"},{"type":"function","doc":"","title":"binary.encode_hex/1","ref":"binary.html#encode_hex/1"},{"type":"function","doc":"Encodes a binary into a hex encoded binary using the specified case for the\nhexadecimal digits \"a\" to \"f\".\n\nThe default case is `uppercase`.\n\n_Example:_\n\n```erlang\n1> binary:encode_hex(<<\"f\">>).\n<<\"66\">>\n2> binary:encode_hex(<<\"/\">>).\n<<\"2F\">>\n3> binary:encode_hex(<<\"/\">>, lowercase).\n<<\"2f\">>\n4> binary:encode_hex(<<\"/\">>, uppercase).\n<<\"2F\">>\n```","title":"binary.encode_hex/2","ref":"binary.html#encode_hex/2"},{"type":"function","doc":"","title":"binary.encode_unsigned/1","ref":"binary.html#encode_unsigned/1"},{"type":"function","doc":"Converts a positive integer to the smallest possible representation in a binary\ndigit representation, either big endian or little endian.\n\n_Example:_\n\n```erlang\n1> binary:encode_unsigned(11111111).\n<<169,138,199>>\n2> binary:encode_unsigned(11111111, big).\n<<169,138,199>>\n2> binary:encode_unsigned(11111111, little).\n<<199,138,169>>\n```","title":"binary.encode_unsigned/2","ref":"binary.html#encode_unsigned/2"},{"type":"function","doc":"Returns the first byte of binary `Subject` as an integer. If the size of\n`Subject` is zero, a `badarg` exception is raised.","title":"binary.first/1","ref":"binary.html#first/1"},{"type":"function","doc":"Joins a list of binaries together by a specified `Separator`.\n\nEquivalent to `iolist_to_binary(lists:join(Separator, Binaries))`, but faster.\n\n_Example:_\n\n```erlang\n1> binary:join([<<\"a\">>, <<\"b\">>, <<\"c\">>], <<\", \">>).\n<<\"a, b, c\">>\n```","title":"binary.join/2","ref":"binary.html#join/2"},{"type":"function","doc":"Returns the last byte of binary `Subject` as an integer. If the size of\n`Subject` is zero, a `badarg` exception is raised.","title":"binary.last/1","ref":"binary.html#last/1"},{"type":"function","doc":"Works exactly as `erlang:list_to_binary/1`, added for completeness.","title":"binary.list_to_bin/1","ref":"binary.html#list_to_bin/1"},{"type":"function","doc":"Returns the length of the longest common prefix of the binaries in list\n`Binaries`.\n\n_Example:_\n\n```erlang\n1> binary:longest_common_prefix([<<\"erlang\">>, <<\"ergonomy\">>]).\n2\n2> binary:longest_common_prefix([<<\"erlang\">>, <<\"perl\">>]).\n0\n```\n\nIf `Binaries` is not a flat non-empty list of binaries, a `badarg` exception is\nraised.","title":"binary.longest_common_prefix/1","ref":"binary.html#longest_common_prefix/1"},{"type":"function","doc":"Returns the length of the longest common suffix of the binaries in list\n`Binaries`.\n\n_Example:_\n\n```erlang\n1> binary:longest_common_suffix([<<\"erlang\">>, <<\"fang\">>]).\n3\n2> binary:longest_common_suffix([<<\"erlang\">>, <<\"perl\">>]).\n0\n```\n\nIf `Binaries` is not a flat non-empty list of binaries, a `badarg` exception is\nraised.","title":"binary.longest_common_suffix/1","ref":"binary.html#longest_common_suffix/1"},{"type":"function","doc":"","title":"binary.match/2","ref":"binary.html#match/2"},{"type":"function","doc":"Searches for the first occurrence of `Pattern` in `Subject` and returns the\nposition and length.\n\nThe function returns `{Pos, Length}` for the binary in `Pattern`, starting at\nthe lowest position in `Subject`.\n\n_Example:_\n\n```erlang\n1> binary:match(<<\"abcde\">>, [<<\"bcde\">>, <<\"cd\">>],[]).\n{1,4}\n```\n\nEven though `<<\"cd\">>` ends before `<<\"bcde\">>`, `<<\"bcde\">>` begins first and\nis therefore the first match. If two overlapping matches begin at the same\nposition, the longest is returned.\n\nSummary of the options:\n\n- **\\{scope, \\{Start, Length\\}\\}** - Only the specified part is searched. Return\n values still have offsets from the beginning of `Subject`. A negative `Length`\n is allowed as described in section Data Types in this manual.\n\nIf none of the strings in `Pattern` is found, the atom `nomatch` is returned.\n\nFor a description of `Pattern`, see function `compile_pattern/1`.\n\nIf `{scope, {Start,Length}}` is specified in the options such that `Start` >\nsize of `Subject`, `Start` \\+ `Length` < 0 or `Start` \\+ `Length` > size of\n`Subject`, a `badarg` exception is raised.","title":"binary.match/3","ref":"binary.html#match/3"},{"type":"function","doc":"","title":"binary.matches/2","ref":"binary.html#matches/2"},{"type":"function","doc":"As `match/2`, but `Subject` is searched until exhausted and a list of all\nnon-overlapping parts matching `Pattern` is returned (in order).\n\nThe first and longest match is preferred to a shorter, which is illustrated by\nthe following example:\n\n```erlang\n1> binary:matches(<<\"abcde\">>,\n [<<\"bcde\">>,<<\"bc\">>,<<\"de\">>],[]).\n[{1,4}]\n```\n\nThe result shows that <<\"bcde\">> is selected instead of the shorter match\n<<\"bc\">> (which would have given raise to one more match, <<\"de\">>). This\ncorresponds to the behavior of POSIX regular expressions (and programs like\nawk), but is not consistent with alternative matches in `re` (and Perl), where\ninstead lexical ordering in the search pattern selects which string matches.\n\nIf none of the strings in a pattern is found, an empty list is returned.\n\nFor a description of `Pattern`, see `compile_pattern/1`. For a description of\navailable options, see `match/3`.\n\nIf `{scope, {Start,Length}}` is specified in the options such that `Start` >\nsize of `Subject`, `Start + Length` < 0 or `Start + Length` is > size of\n`Subject`, a `badarg` exception is raised.","title":"binary.matches/3","ref":"binary.html#matches/3"},{"type":"function","doc":"","title":"binary.part/2","ref":"binary.html#part/2"},{"type":"function","doc":"Extracts the part of binary `Subject` described by `PosLen`.\n\nA negative length can be used to extract bytes at the end of a binary:\n\n```erlang\n1> Bin = <<1,2,3,4,5,6,7,8,9,10>>.\n2> binary:part(Bin, {byte_size(Bin), -5}).\n<<6,7,8,9,10>>\n```\n\n> #### Note {: .info }\n>\n> `part/2` and `part/3` are also available in the `m:erlang` module under the\n> names [`binary_part/2`](`binary_part/2`) and\n> [`binary_part/3`](`binary_part/3`). Those BIFs are allowed in guard tests.\n\nIf `PosLen` in any way references outside the binary, a `badarg` exception is\nraised.","title":"binary.part/3","ref":"binary.html#part/3"},{"type":"function","doc":"Get the size of the underlying binary referenced by `Binary`.\n\nIf a binary references a larger binary (often described as being a subbinary),\nit can be useful to get the size of the referenced binary. This function can be\nused in a program to trigger the use of `copy/1`. By copying\n a binary, one can dereference the original, possibly large, binary that a\nsmaller binary is a reference to.\n\n_Example:_\n\n```erlang\nstore(Binary, GBSet) ->\n NewBin =\n case binary:referenced_byte_size(Binary) of\n Large when Large > 2 * byte_size(Binary) ->\n binary:copy(Binary);\n _ ->\n Binary\n end,\n gb_sets:insert(NewBin,GBSet).\n```\n\nIn this example, we chose to copy the binary content before inserting it in\n[`gb_sets:set()`](`t:gb_sets:set/0`) if it references a binary more than twice\nthe data size we want to keep. Of course, different rules apply when copying to\ndifferent programs.\n\nBinary sharing occurs whenever binaries are taken apart. This is the fundamental\nreason why binaries are fast, decomposition can always be done with O(1)\ncomplexity. In rare circumstances this data sharing is however undesirable, why\nthis function together with [`copy/1`](`copy/1`) can be useful when optimizing\nfor memory use.\n\nExample of binary sharing:\n\n```erlang\n1> A = binary:copy(<<1>>, 100).\n<<1,1,1,1,1 ...\n2> byte_size(A).\n100\n3> binary:referenced_byte_size(A).\n100\n4> < > = A.\n<<1,1,1,1,1 ...\n5> {byte_size(B), binary:referenced_byte_size(B)}.\n{10,10}\n6> {byte_size(C), binary:referenced_byte_size(C)}.\n{90,100}\n```\n\nIn the above example, the small binary `B` was copied while the larger binary\n`C` references binary `A`.\n\n> #### Note {: .info }\n>\n> Binary data is shared among processes. If another process still references the\n> larger binary, copying the part this process uses only consumes more memory\n> and does not free up the larger binary for garbage collection. Use this kind\n> of intrusive functions with extreme care and only if a real problem is\n> detected.","title":"binary.referenced_byte_size/1","ref":"binary.html#referenced_byte_size/1"},{"type":"function","doc":"","title":"binary.replace/3","ref":"binary.html#replace/3"},{"type":"function","doc":"Constructs a new binary by replacing the parts in `Subject` matching `Pattern`\nwith `Replacement` if given as a literal `t:binary/0` or with the result of\napplying `Replacement` to a matching subpart if given as a `fun`.\n\nIf `Replacement` is given as a `t:binary/0` and the matching subpart of\n`Subject` giving raise to the replacement is to be inserted in the result,\noption `{insert_replaced, InsPos}` inserts the matching part into `Replacement`\nat the specified position (or positions) before inserting `Replacement` into\n`Subject`. If `Replacement` is given as a `fun` instead, this option is ignored.\n\nIf any position specified in `InsPos` > size of the replacement binary, a\n`badarg` exception is raised.\n\nOptions `global` and `{scope, part()}` work as for `split/3`. The return type is\nalways a `t:binary/0`.\n\nFor a description of `Pattern`, see `compile_pattern/1`.\n\n_Examples:_\n\n```erlang\n1> binary:replace(<<\"abcde\">>, [<<\"b\">>, <<\"d\">>], <<\"X\">>, []).\n<<\"aXcde\">>\n\n2> binary:replace(<<\"abcde\">>, [<<\"b\">>, <<\"d\">>], <<\"X\">>, [global]).\n<<\"aXcXe\">>\n\n3> binary:replace(<<\"abcde\">>, <<\"b\">>, <<\"[]\">>, [{insert_replaced, 1}]).\n<<\"a[b]cde\">>\n\n4> binary:replace(<<\"abcde\">>, [<<\"b\">>, <<\"d\">>], <<\"[]\">>, [global, {insert_replaced, 1}]).\n<<\"a[b]c[d]e\">>\n\n5> binary:replace(<<\"abcde\">>, [<<\"b\">>, <<\"d\">>], <<\"[]\">>, [global, {insert_replaced, [1, 1]}]).\n<<\"a[bb]c[dd]e\">>\n\n6> binary:replace(<<\"abcde\">>, [<<\"b\">>, <<\"d\">>], <<\"[-]\">>, [global, {insert_replaced, [1, 2]}]).\n<<\"a[b-b]c[d-d]e\">>\n\n7> binary:replace(<<\"abcde\">>, [<<\"b\">>, <<\"d\">>], fun(M) -> <<$[, M/binary, $]>> end, []).\n<<\"a[b]cde\">>\n\n8> binary:replace(<<\"abcde\">>, [<<\"b\">>, <<\"d\">>], fun(M) -> <<$[, M/binary, $]>> end, [global]).\n<<\"a[b]c[d]e\">>\n```","title":"binary.replace/4","ref":"binary.html#replace/4"},{"type":"function","doc":"","title":"binary.split/2","ref":"binary.html#split/2"},{"type":"function","doc":"Splits `Subject` into a list of binaries based on `Pattern`.\n\nIf option `global` is not specified, only the first occurrence of `Pattern` in\n`Subject` gives rise to a split.\n\nThe parts of `Pattern` found in `Subject` are not included in the result.\n\n_Example:_\n\n```erlang\n1> binary:split(<<1,255,4,0,0,0,2,3>>, [<<0,0,0>>,<<2>>],[]).\n[<<1,255,4>>, <<2,3>>]\n2> binary:split(<<0,1,0,0,4,255,255,9>>, [<<0,0>>, <<255,255>>],[global]).\n[<<0,1>>,<<4>>,<<9>>]\n```\n\nSummary of options:\n\n- **\\{scope, part()\\}** - Works as in `match/3` and `matches/3`. Notice that\n this only defines the scope of the search for matching strings, it does not\n cut the binary before splitting. The bytes before and after the scope are kept\n in the result. See the example below.\n\n- **trim** - Removes trailing empty parts of the result (as does `trim` in\n `re:split/3`.\n\n- **trim_all** - Removes all empty parts of the result.\n\n- **global** - Repeats the split until `Subject` is exhausted. Conceptually\n option `global` makes split work on the positions returned by `matches/3`,\n while it normally works on the position returned by `match/3`.\n\nExample of the difference between a scope and taking the binary apart before\nsplitting:\n\n```erlang\n1> binary:split(<<\"banana\">>, [<<\"a\">>],[{scope,{2,3}}]).\n[<<\"ban\">>,<<\"na\">>]\n2> binary:split(binary:part(<<\"banana\">>,{2,3}), [<<\"a\">>],[]).\n[<<\"n\">>,<<\"n\">>]\n```\n\nThe return type is always a list of binaries that are all referencing `Subject`.\nThis means that the data in `Subject` is not copied to new binaries, and that\n`Subject` cannot be garbage collected until the results of the split are no\nlonger referenced.\n\nFor a description of `Pattern`, see `compile_pattern/1`.","title":"binary.split/3","ref":"binary.html#split/3"},{"type":"opaque","doc":"Opaque data type representing a compiled search pattern.\n\nGuaranteed to be a `t:tuple/0` to allow programs to distinguish it from\nnon-precompiled search patterns.","title":"binary.cp/0","ref":"binary.html#t:cp/0"},{"type":"type","doc":"A representation of a part (or range) in a binary. `Start` is a zero-based\noffset into a `t:binary/0` and `Length` is the length of that part.\n\nAs input to functions in this module, a reverse part specification is allowed, constructed\nwith a negative `Length`, so that the part of the binary begins at `Start` \\+\n`Length` and is -`Length` long. This is useful for referencing the last `N`\nbytes of a binary as `{size(Binary), -N}`. The functions in this module always\nreturn `t:part/0`s with positive `Length`.","title":"binary.part/0","ref":"binary.html#t:part/0"},{"type":"module","doc":"List processing functions.\n\nThis module contains functions for list processing.\n\nUnless otherwise stated, all functions assume that position numbering starts\nat 1. That is, the first element of a list is at position 1.\n\nTwo terms `T1` and `T2` compare equal if `T1 == T2` evaluates to `true`. They\nmatch if `T1 =:= T2` evaluates to `true`.\n\nWhenever an _ordering function_{: #ordering_function } `F` is expected as\nargument, it is assumed that the following properties hold of `F` for all x, y,\nand z:\n\n- If x `F` y and y `F` x, then x = y (`F` is antisymmetric).\n- If x `F` y and y `F` z, then x `F` z (`F` is transitive).\n- x `F` y or y `F` x (`F` is total).\n\nAn example of a typical ordering function is less than or equal to: `= lists:append([[1, 2, 3], [a, b], [4, 5, 6]]).\n[1,2,3,a,b,4,5,6]\n```","title":"lists.append/1","ref":"lists.html#append/1"},{"type":"function","doc":"Returns a new list `List3`, which is made from the elements of `List1` followed\nby the elements of `List2`.\n\n_Example:_\n\n```erlang\n> lists:append(\"abc\", \"def\").\n\"abcdef\"\n```\n\n`lists:append(A, B)` is equivalent to `A ++ B`.","title":"lists.append/2","ref":"lists.html#append/2"},{"type":"function","doc":"Concatenates the text representation of the elements of `Things`. The elements\nof `Things` can be atoms, integers, floats, or strings.\n\n_Example:_\n\n```erlang\n> lists:concat([doc, '/', file, '.', 3]).\n\"doc/file.3\"\n```","title":"lists.concat/1","ref":"lists.html#concat/1"},{"type":"function","doc":"Returns a copy of `List1` where the first element matching `Elem` is deleted, if\nthere is such an element.","title":"lists.delete/2","ref":"lists.html#delete/2"},{"type":"function","doc":"Drops the last element of a `List`. The list is to be non-empty, otherwise the\nfunction crashes with a `function_clause`.","title":"lists.droplast/1","ref":"lists.html#droplast/1"},{"type":"function","doc":"Drops elements `Elem` from `List1` while `Pred(Elem)` returns `true` and returns\nthe remaining list. The `Pred` function must return a boolean.","title":"lists.dropwhile/2","ref":"lists.html#dropwhile/2"},{"type":"function","doc":"Returns a list containing `N` copies of term `Elem`.\n\n_Example:_\n\n```erlang\n> lists:duplicate(5, xx).\n[xx,xx,xx,xx,xx]\n```","title":"lists.duplicate/2","ref":"lists.html#duplicate/2"},{"type":"function","doc":"","title":"lists.enumerate/1","ref":"lists.html#enumerate/1"},{"type":"function","doc":"","title":"lists.enumerate/2","ref":"lists.html#enumerate/2"},{"type":"function","doc":"Returns `List1` with each element `H` replaced by a tuple of form `{I, H}` where\n`I` is the position of `H` in `List1`. The enumeration starts with `Index` and\nincreases by `Step` in each step.\n\nThat is, [`enumerate/3`](`enumerate/3`) behaves as if it had been defined as\nfollows:\n\n```erlang\nenumerate(I, S, List) ->\n {List1, _ } = lists:mapfoldl(fun(T, Acc) -> {{Acc, T}, Acc+S} end, I, List),\n List1.\n```\n\nThe default values for `Index` and `Step` are both `1`.\n\n_Examples:_\n\n```erlang\n> lists:enumerate([a,b,c]).\n[{1,a},{2,b},{3,c}]\n```\n\n```erlang\n> lists:enumerate(10, [a,b,c]).\n[{10,a},{11,b},{12,c}]\n```\n\n```erlang\n> lists:enumerate(0, -2, [a,b,c]).\n[{0,a},{-2,b},{-4,c}]\n```","title":"lists.enumerate/3","ref":"lists.html#enumerate/3"},{"type":"function","doc":"`List2` is a list of all elements `Elem` in `List1` for which `Pred(Elem)`\nreturns `true`. The `Pred` function must return a boolean.","title":"lists.filter/2","ref":"lists.html#filter/2"},{"type":"function","doc":"Calls `Fun(Elem)` on successive elements `Elem` of `List1` in order to update or\nremove elements from `List1`.\n\n`Fun/1` must return either a Boolean or a tuple `{true, Value}`. The function\nreturns the list of elements for which `Fun` returns a new value, where a value\nof `true` is synonymous with `{true, Elem}`.\n\nThat is, `filtermap` behaves as if it had been defined as follows:\n\n```erlang\nfiltermap(Fun, List1) ->\n lists:foldr(fun(Elem, Acc) ->\n case Fun(Elem) of\n false -> Acc;\n true -> [Elem|Acc];\n {true,Value} -> [Value|Acc]\n end\n end, [], List1).\n```\n\n_Example:_\n\n```erlang\n> lists:filtermap(fun(X) -> case X rem 2 of 0 -> {true, X div 2}; _ -> false end end, [1,2,3,4,5]).\n[1,2]\n```","title":"lists.filtermap/2","ref":"lists.html#filtermap/2"},{"type":"function","doc":"Equivalent to [`length(flatten(DeepList))`](`length/1`), but more efficient.","title":"lists.flatlength/1","ref":"lists.html#flatlength/1"},{"type":"function","doc":"Takes a function from `A`s to lists of `B`s, and a list of `A`s (`List1`) and\nproduces a list of `B`s by applying the function to every element in `List1` and\nappending the resulting lists.\n\nThat is, `flatmap` behaves as if it had been defined as follows:\n\n```erlang\nflatmap(Fun, List1) ->\n append(map(Fun, List1)).\n```\n\n_Example:_\n\n```erlang\n> lists:flatmap(fun(X)->[X,X] end, [a,b,c]).\n[a,a,b,b,c,c]\n```","title":"lists.flatmap/2","ref":"lists.html#flatmap/2"},{"type":"function","doc":"Returns a flattened version of `DeepList`.","title":"lists.flatten/1","ref":"lists.html#flatten/1"},{"type":"function","doc":"Returns a flattened version of `DeepList` with tail `Tail` appended.","title":"lists.flatten/2","ref":"lists.html#flatten/2"},{"type":"function","doc":"Calls `Fun(Elem, AccIn)` on successive elements `A` of `List`, starting with\n`AccIn == Acc0`. `Fun/2` must return a new accumulator, which is passed to the\nnext call. The function returns the final value of the accumulator. `Acc0` is\nreturned if the list is empty.\n\n_Example:_\n\n```erlang\n> lists:foldl(fun(X, Sum) -> X + Sum end, 0, [1,2,3,4,5]).\n15\n> lists:foldl(fun(X, Prod) -> X * Prod end, 1, [1,2,3,4,5]).\n120\n```","title":"lists.foldl/3","ref":"lists.html#foldl/3"},{"type":"function","doc":"Like `foldl/3`, but the list is traversed from right to left.\n\n_Example:_\n\n```erlang\n> P = fun(A, AccIn) -> io:format(\"~p \", [A]), AccIn end.\n#Fun \n> lists:foldl(P, void, [1,2,3]).\n1 2 3 void\n> lists:foldr(P, void, [1,2,3]).\n3 2 1 void\n```\n\n[`foldl/3`](`foldl/3`) is tail recursive and is usually preferred to\n[`foldr/3`](`foldr/3`).","title":"lists.foldr/3","ref":"lists.html#foldr/3"},{"type":"function","doc":"Calls `Fun(Elem)` for each element `Elem` in `List`. This function is used for\nits side effects and the evaluation order is defined to be the same as the order\nof the elements in the list.","title":"lists.foreach/2","ref":"lists.html#foreach/2"},{"type":"function","doc":"Inserts `Sep` between each element in `List1`. Has no effect on the empty list\nand on a singleton list. For example:\n\n```erlang\n> lists:join(x, [a,b,c]).\n[a,x,b,x,c]\n> lists:join(x, [a]).\n[a]\n> lists:join(x, []).\n[]\n```","title":"lists.join/2","ref":"lists.html#join/2"},{"type":"function","doc":"Returns a copy of `TupleList1` where the first occurrence of a tuple whose `N`th\nelement compares equal to `Key` is deleted, if there is such a tuple.","title":"lists.keydelete/3","ref":"lists.html#keydelete/3"},{"type":"function","doc":"Searches the list of tuples `TupleList` for a tuple whose `N`th element compares\nequal to `Key`. Returns `Tuple` if such a tuple is found, otherwise `false`.","title":"lists.keyfind/3","ref":"lists.html#keyfind/3"},{"type":"function","doc":"Returns a list of tuples where, for each tuple in `TupleList1`, the `N`th\nelement `Term1` of the tuple has been replaced with the result of calling\n`Fun(Term1)`.\n\n_Examples:_\n\n```erlang\n> Fun = fun(Atom) -> atom_to_list(Atom) end.\n#Fun \n2> lists:keymap(Fun, 2, [{name,jane,22},{name,lizzie,20},{name,lydia,15}]).\n[{name,\"jane\",22},{name,\"lizzie\",20},{name,\"lydia\",15}]\n```","title":"lists.keymap/3","ref":"lists.html#keymap/3"},{"type":"function","doc":"Returns `true` if there is a tuple in `TupleList` whose `N`th element compares\nequal to `Key`, otherwise `false`.","title":"lists.keymember/3","ref":"lists.html#keymember/3"},{"type":"function","doc":"Returns the sorted list formed by merging `TupleList1` and `TupleList2`.\n\nThe merge is performed on the `N`th element of each tuple. Both `TupleList1` and\n`TupleList2` must be key-sorted before evaluating this function. When two tuples\ncompare equal, the tuple from `TupleList1` is picked before the tuple from\n`TupleList2`.","title":"lists.keymerge/3","ref":"lists.html#keymerge/3"},{"type":"function","doc":"Returns a copy of `TupleList1` where the first occurrence of a `T` tuple whose\n`N`th element compares equal to `Key` is replaced with `NewTuple`, if there is\nsuch a tuple `T`.","title":"lists.keyreplace/4","ref":"lists.html#keyreplace/4"},{"type":"function","doc":"Searches the list of tuples `TupleList` for a tuple whose `N`th element compares\nequal to `Key`. Returns `{value, Tuple}` if such a tuple is found, otherwise\n`false`.\n\n> #### Note {: .info }\n>\n> This function is retained for backward compatibility. Function `keyfind/3` is\n> usually more convenient.","title":"lists.keysearch/3","ref":"lists.html#keysearch/3"},{"type":"function","doc":"Returns a list containing the sorted elements of list `TupleList1`. Sorting is\nperformed on the `N`th element of the tuples. The sort is stable.","title":"lists.keysort/2","ref":"lists.html#keysort/2"},{"type":"function","doc":"Returns a copy of `TupleList1` where the first occurrence of a tuple `T` whose\n`N`th element compares equal to `Key` is replaced with `NewTuple`, if there is\nsuch a tuple `T`. If there is no such tuple `T`, a copy of `TupleList1` where\n[`NewTuple`] has been appended to the end is returned.","title":"lists.keystore/4","ref":"lists.html#keystore/4"},{"type":"function","doc":"Searches the list of tuples `TupleList1` for a tuple whose `N`th element\ncompares equal to `Key`. Returns `{value, Tuple, TupleList2}` if such a tuple is\nfound, otherwise `false`. `TupleList2` is a copy of `TupleList1` where the first\noccurrence of `Tuple` has been removed.","title":"lists.keytake/3","ref":"lists.html#keytake/3"},{"type":"function","doc":"Returns the last element in `List`.","title":"lists.last/1","ref":"lists.html#last/1"},{"type":"function","doc":"Takes a function from `A`s to `B`s, and a list of `A`s and produces a list of\n`B`s by applying the function to every element in the list. This function is\nused to obtain the return values. The evaluation order depends on the\nimplementation.","title":"lists.map/2","ref":"lists.html#map/2"},{"type":"function","doc":"Combines the operations of `map/2` and `foldl/3` into one pass.\n\n_Example:_\n\nSumming the elements in a list and double them at the same time:\n\n```erlang\n> lists:mapfoldl(fun(X, Sum) -> {2*X, X+Sum} end,\n0, [1,2,3,4,5]).\n{[2,4,6,8,10],15}\n```","title":"lists.mapfoldl/3","ref":"lists.html#mapfoldl/3"},{"type":"function","doc":"Combines the operations of `map/2` and `foldr/3` into one pass.","title":"lists.mapfoldr/3","ref":"lists.html#mapfoldr/3"},{"type":"function","doc":"Returns the first element of `List` that compares greater than or equal to all\nother elements of `List`.","title":"lists.max/1","ref":"lists.html#max/1"},{"type":"function","doc":"Returns `true` if `Elem` matches some element of `List`, otherwise `false`.","title":"lists.member/2","ref":"lists.html#member/2"},{"type":"function","doc":"Returns the sorted list formed by merging `List1`, `List2`, and `List3`. All of\n`List1`, `List2`, and `List3` must be sorted before evaluating this function.\n\nWhen two elements compare equal, the element from `List1`, if there is such an\nelement, is picked before the other element, otherwise the element from `List2`\nis picked before the element from `List3`.","title":"lists.merge3/3","ref":"lists.html#merge3/3"},{"type":"function","doc":"Returns the sorted list formed by merging all the sublists of `ListOfLists`. All\nsublists must be sorted before evaluating this function.\n\nWhen two elements compare equal, the element from the sublist with the lowest\nposition in `ListOfLists` is picked before the other element.","title":"lists.merge/1","ref":"lists.html#merge/1"},{"type":"function","doc":"Returns the sorted list formed by merging `List1` and `List2`. Both `List1` and\n`List2` must be sorted before evaluating this function.\n\nWhen two elements compare equal, the element from `List1` is picked before the\nelement from `List2`.","title":"lists.merge/2","ref":"lists.html#merge/2"},{"type":"function","doc":"Returns the sorted list formed by merging `List1` and `List2`. Both `List1` and\n`List2` must be sorted according to the\n[ordering function](`m:lists#ordering_function`) `Fun` before evaluating this\nfunction.\n\n`Fun(A, B)` is to return `true` if `A` compares less than or equal to\n`B` in the ordering, otherwise `false`. When two elements compare equal, the\nelement from `List1` is picked before the element from `List2`.","title":"lists.merge/3","ref":"lists.html#merge/3"},{"type":"function","doc":"Returns the first element of `List` that compares less than or equal to all\nother elements of `List`.","title":"lists.min/1","ref":"lists.html#min/1"},{"type":"function","doc":"Returns the `N`th element of `List`.\n\n_Example:_\n\n```erlang\n> lists:nth(3, [a, b, c, d, e]).\nc\n```","title":"lists.nth/2","ref":"lists.html#nth/2"},{"type":"function","doc":"Returns the `N`th tail of `List`, that is, the sublist of `List` starting at\n`N+1` and continuing up to the end of the list.\n\n_Example_\n\n```erlang\n> lists:nthtail(3, [a, b, c, d, e]).\n[d,e]\n> tl(tl(tl([a, b, c, d, e]))).\n[d,e]\n> lists:nthtail(0, [a, b, c, d, e]).\n[a,b,c,d,e]\n> lists:nthtail(5, [a, b, c, d, e]).\n[]\n```","title":"lists.nthtail/2","ref":"lists.html#nthtail/2"},{"type":"function","doc":"Partitions `List` into two lists, where the first list contains all elements for\nwhich `Pred(Elem)` returns `true`, and the second list contains all elements for\nwhich `Pred(Elem)` returns `false`.\n\n_Examples:_\n\n```erlang\n> lists:partition(fun(A) -> A rem 2 == 1 end, [1,2,3,4,5,6,7]).\n{[1,3,5,7],[2,4,6]}\n> lists:partition(fun(A) -> is_atom(A) end, [a,b,1,c,d,2,3,4,e]).\n{[a,b,c,d,e],[1,2,3,4]}\n```\n\nFor a different way to partition a list, see `splitwith/2`.","title":"lists.partition/2","ref":"lists.html#partition/2"},{"type":"function","doc":"Returns `true` if `List1` is a prefix of `List2`, otherwise `false`.","title":"lists.prefix/2","ref":"lists.html#prefix/2"},{"type":"function","doc":"Returns a list with the elements in `List1` in reverse order.","title":"lists.reverse/1","ref":"lists.html#reverse/1"},{"type":"function","doc":"Returns a list with the elements in `List1` in reverse order, with tail `Tail`\nappended.\n\n_Example:_\n\n```erlang\n> lists:reverse([1, 2, 3, 4], [a, b, c]).\n[4,3,2,1,a,b,c]\n```","title":"lists.reverse/2","ref":"lists.html#reverse/2"},{"type":"function","doc":"If there is a `Value` in `List` such that `Pred(Value)` returns `true`, returns\n`{value, Value}` for the first such `Value`, otherwise returns `false`. The\n`Pred` function must return a boolean.","title":"lists.search/2","ref":"lists.html#search/2"},{"type":"function","doc":"","title":"lists.seq/2","ref":"lists.html#seq/2"},{"type":"function","doc":"Returns a sequence of integers that starts with `From` and contains the\nsuccessive results of adding `Incr` to the previous element, until `To` is\nreached or passed (in the latter case, `To` is not an element of the sequence).\n`Incr` defaults to 1.\n\nFailures:\n\n- If `To 0`.\n- If `To > From - Incr` and `Incr < 0`.\n- If `Incr =:= 0` and `From =/= To`.\n\nThe following equalities hold for all sequences:\n\n```erlang\nlength(lists:seq(From, To)) =:= To - From + 1\nlength(lists:seq(From, To, Incr)) =:= (To - From + Incr) div Incr\n```\n\n_Examples:_\n\n```erlang\n> lists:seq(1, 10).\n[1,2,3,4,5,6,7,8,9,10]\n> lists:seq(1, 20, 3).\n[1,4,7,10,13,16,19]\n> lists:seq(1, 0, 1).\n[]\n> lists:seq(10, 6, 4).\n[]\n> lists:seq(1, 1, 0).\n[1]\n```","title":"lists.seq/3","ref":"lists.html#seq/3"},{"type":"function","doc":"Returns a list containing the sorted elements of `List1`.","title":"lists.sort/1","ref":"lists.html#sort/1"},{"type":"function","doc":"Returns a list containing the sorted elements of `List1`, according to the\n[ordering function](`m:lists#ordering_function`) `Fun`. `Fun(A, B)` is to return\n`true` if `A` compares less than or equal to `B` in the ordering, otherwise\n`false`.","title":"lists.sort/2","ref":"lists.html#sort/2"},{"type":"function","doc":"Splits `List1` into `List2` and `List3`. `List2` contains the first `N` elements\nand `List3` the remaining elements (the `N`th tail).","title":"lists.split/2","ref":"lists.html#split/2"},{"type":"function","doc":"Partitions `List` into two lists according to `Pred`.\n[`splitwith/2`](`splitwith/2`) behaves as if it is defined as follows:\n\n```erlang\nsplitwith(Pred, List) ->\n {takewhile(Pred, List), dropwhile(Pred, List)}.\n```\n\n_Examples:_\n\n```erlang\n> lists:splitwith(fun(A) -> A rem 2 == 1 end, [1,2,3,4,5,6,7]).\n{[1],[2,3,4,5,6,7]}\n> lists:splitwith(fun(A) -> is_atom(A) end, [a,b,1,c,d,2,3,4,e]).\n{[a,b],[1,c,d,2,3,4,e]}\n```\n\nThe `Pred` function must return a boolean. For a different way to partition a\nlist, see `partition/2`.","title":"lists.splitwith/2","ref":"lists.html#splitwith/2"},{"type":"function","doc":"Returns the sublist of `List1` starting at position 1 and with (maximum) `Len`\nelements. It is not an error for `Len` to exceed the length of the list, in that\ncase the whole list is returned.","title":"lists.sublist/2","ref":"lists.html#sublist/2"},{"type":"function","doc":"Returns the sublist of `List1` starting at `Start` and with (maximum) `Len`\nelements. It is not an error for `Start+Len` to exceed the length of the list.\n\n_Examples:_\n\n```erlang\n> lists:sublist([1,2,3,4], 2, 2).\n[2,3]\n> lists:sublist([1,2,3,4], 2, 5).\n[2,3,4]\n> lists:sublist([1,2,3,4], 5, 2).\n[]\n```","title":"lists.sublist/3","ref":"lists.html#sublist/3"},{"type":"function","doc":"Returns a new list `List3` that is a copy of `List1`, subjected to the following\nprocedure: for each element in `List2`, its first occurrence in `List1` is\ndeleted.\n\n_Example:_\n\n```erlang\n> lists:subtract(\"123212\", \"212\").\n\"312\".\n```\n\n`lists:subtract(A, B)` is equivalent to `A -- B`.","title":"lists.subtract/2","ref":"lists.html#subtract/2"},{"type":"function","doc":"Returns `true` if `List1` is a suffix of `List2`, otherwise `false`.","title":"lists.suffix/2","ref":"lists.html#suffix/2"},{"type":"function","doc":"Returns the sum of the elements in `List`.","title":"lists.sum/1","ref":"lists.html#sum/1"},{"type":"function","doc":"Takes elements `Elem` from `List1` while `Pred(Elem)` returns `true`, that is,\nthe function returns the longest prefix of the list for which all elements\nsatisfy the predicate. The `Pred` function must return a boolean.","title":"lists.takewhile/2","ref":"lists.html#takewhile/2"},{"type":"function","doc":"Returns the sorted list formed by merging `TupleList1` and `TupleList2`. The\nmerge is performed on the `N`th element of each tuple. Both `TupleList1` and\n`TupleList2` must be key-sorted without duplicates before evaluating this\nfunction.\n\nWhen two tuples compare equal, the tuple from `TupleList1` is picked\nand the one from `TupleList2` is deleted.","title":"lists.ukeymerge/3","ref":"lists.html#ukeymerge/3"},{"type":"function","doc":"Returns a list containing the sorted elements of list `TupleList1` where all\nexcept the first tuple of the tuples comparing equal have been deleted. Sorting\nis performed on the `N`th element of the tuples.","title":"lists.ukeysort/2","ref":"lists.html#ukeysort/2"},{"type":"function","doc":"Returns the sorted list formed by merging `List1`, `List2`, and `List3`. All of\n`List1`, `List2`, and `List3` must be sorted and contain no duplicates before\nevaluating this function.\n\nWhen two elements compare equal, the element from\n`List1` is picked if there is such an element, otherwise the element from\n`List2` is picked, and the other is deleted.","title":"lists.umerge3/3","ref":"lists.html#umerge3/3"},{"type":"function","doc":"Returns the sorted list formed by merging all the sublists of `ListOfLists`. All\nsublists must be sorted and contain no duplicates before evaluating this\nfunction.\n\nWhen two elements compare equal, the element from the sublist with the\nlowest position in `ListOfLists` is picked and the other is deleted.","title":"lists.umerge/1","ref":"lists.html#umerge/1"},{"type":"function","doc":"Returns the sorted list formed by merging `List1` and `List2`. Both `List1` and\n`List2` must be sorted and contain no duplicates before evaluating this\nfunction.\n\nWhen two elements compare equal, the element from `List1` is picked\nand the one from `List2` is deleted.","title":"lists.umerge/2","ref":"lists.html#umerge/2"},{"type":"function","doc":"Returns the sorted list formed by merging `List1` and `List2`. Both `List1` and\n`List2` must be sorted according to the\n[ordering function](`m:lists#ordering_function`) `Fun` and contain no duplicates\nbefore evaluating this function.\n\n`Fun(A, B)` is to return `true` if `A` compares\nless than or equal to `B` in the ordering, otherwise `false`. When two elements\ncompare equal, the element from `List1` is picked and the one from `List2` is\ndeleted.","title":"lists.umerge/3","ref":"lists.html#umerge/3"},{"type":"function","doc":"Returns a list containing the elements of `List1` with duplicated elements\nremoved (preserving the order of the elements). The first occurrence of each\nelement is kept.\n\n_Examples:_\n\n```erlang\n> lists:uniq([3,3,1,2,1,2,3]).\n[3,1,2]\n> lists:uniq([a, a, 1, b, 2, a, 3]).\n[a, 1, b, 2, 3]\n```","title":"lists.uniq/1","ref":"lists.html#uniq/1"},{"type":"function","doc":"Returns a list containing the elements of `List1` without the elements for which\n`Fun` returned duplicate values (preserving the order of the elements). The\nfirst occurrence of each element is kept.\n\n_Examples:_\n\n```erlang\n> lists:uniq(fun({X, _}) -> X end, [{b, 2}, {a, 1}, {c, 3}, {a, 2}]).\n[{b, 2}, {a, 1}, {c, 3}]\n```","title":"lists.uniq/2","ref":"lists.html#uniq/2"},{"type":"function","doc":"\"Unzips\" a list of three-tuples into three lists, where the first list contains\nthe first element of each tuple, the second list contains the second element of\neach tuple, and the third list contains the third element of each tuple.","title":"lists.unzip3/1","ref":"lists.html#unzip3/1"},{"type":"function","doc":"\"Unzips\" a list of two-tuples into two lists, where the first list contains the\nfirst element of each tuple, and the second list contains the second element of\neach tuple.","title":"lists.unzip/1","ref":"lists.html#unzip/1"},{"type":"function","doc":"Returns a list containing the sorted elements of `List1` where all except the\nfirst element of the elements comparing equal have been deleted.","title":"lists.usort/1","ref":"lists.html#usort/1"},{"type":"function","doc":"Returns a list containing the sorted elements of `List1` where all except the\nfirst element of the elements comparing equal according to the\n[ordering function](`m:lists#ordering_function`) `Fun` have been deleted.\n`Fun(A, B)` is to return `true` if `A` compares less than or equal to `B` in the\nordering, otherwise `false`.","title":"lists.usort/2","ref":"lists.html#usort/2"},{"type":"function","doc":"","title":"lists.zip3/3","ref":"lists.html#zip3/3"},{"type":"function","doc":"\"Zips\" three lists into one list of three-tuples, where the first element of\neach tuple is taken from the first list, the second element is taken from the\ncorresponding element in the second list, and the third element is taken from\nthe corresponding element in the third list.\n\nFor a description of the `How` parameter, see `zip/3`.","title":"lists.zip3/4","ref":"lists.html#zip3/4"},{"type":"function","doc":"","title":"lists.zip/2","ref":"lists.html#zip/2"},{"type":"function","doc":"\"Zips\" two lists into one list of two-tuples, where the first element of each\ntuple is taken from the first list and the second element is taken from the\ncorresponding element in the second list.\n\nThe `How` parameter specifies the behavior if the given lists are of different\nlengths.\n\n- **`fail`** - The call will fail if the given lists are not of equal length.\n This is the default.\n\n- **`trim`** - Surplus elements from the longer list will be ignored.\n\n _Examples:_\n\n ```erlang\n > lists:zip([a, b], [1, 2, 3], trim).\n [{a,1},{b,2}]\n > lists:zip([a, b, c], [1, 2], trim).\n [{a,1},{b,2}]\n ```\n\n- **`{pad, Defaults}`** - The shorter list will be padded to the length of the\n longer list, using the respective elements from the given `Defaults` tuple.\n\n _Examples:_\n\n ```erlang\n > lists:zip([a, b], [1, 2, 3], {pad, {x, 0}}).\n [{a,1},{b,2},{x,3}]\n > lists:zip([a, b, c], [1, 2], {pad, {x, 0}}).\n [{a,1},{b,2},{c,0}]\n ```","title":"lists.zip/3","ref":"lists.html#zip/3"},{"type":"function","doc":"","title":"lists.zipwith3/4","ref":"lists.html#zipwith3/4"},{"type":"function","doc":"Combines the elements of three lists into one list. For each triple `X, Y, Z` of\nlist elements from the three lists, the element in the result list is\n`Combine(X, Y, Z)`.\n\nFor a description of the `How` parameter, see `zip/3`.\n\n[`zipwith3(fun(X, Y, Z) -> {X,Y,Z} end, List1, List2, List3)`](`zipwith3/4`) is\nequivalent to [`zip3(List1, List2, List3)`](`zip3/3`).\n\n_Examples:_\n\n```erlang\n> lists:zipwith3(fun(X, Y, Z) -> X+Y+Z end, [1,2,3], [4,5,6], [7,8,9]).\n[12,15,18]\n> lists:zipwith3(fun(X, Y, Z) -> [X,Y,Z] end, [a,b,c], [x,y,z], [1,2,3]).\n[[a,x,1],[b,y,2],[c,z,3]]\n```","title":"lists.zipwith3/5","ref":"lists.html#zipwith3/5"},{"type":"function","doc":"","title":"lists.zipwith/3","ref":"lists.html#zipwith/3"},{"type":"function","doc":"Combines the elements of two lists into one list. For each pair `X, Y` of list\nelements from the two lists, the element in the result list is `Combine(X, Y)`.\n\nFor a description of the `How` parameter, see `zip/3`.\n\n[`zipwith(fun(X, Y) -> {X,Y} end, List1, List2)`](`zipwith/3`) is equivalent to\n[`zip(List1, List2)`](`zip/2`).\n\n_Example:_\n\n```erlang\n> lists:zipwith(fun(X, Y) -> X+Y end, [1,2,3], [4,5,6]).\n[5,7,9]\n```","title":"lists.zipwith/4","ref":"lists.html#zipwith/4"},{"type":"module","doc":"Maps processing functions.\n\nThis module contains functions for maps processing. The Efficiency Guide\ncontains a chapter that describes\n[how to use maps efficiently](`e:system:maps.md`).","title":"maps","ref":"maps.html"},{"type":"function","doc":"Returns a map `Map` for which predicate `Pred` holds true in `MapOrIter`.\n\nThe call fails with a `{badmap,Map}` exception if `MapOrIter` is not a map or\nvalid iterator, or with `badarg` if `Pred` is not a function of arity 2.\n\n_Example:_\n\n```erlang\n> M = #{a => 2, b => 3, c=> 4, \"a\" => 1, \"b\" => 2, \"c\" => 4},\n Pred = fun(K,V) -> is_atom(K) andalso (V rem 2) =:= 0 end,\n maps:filter(Pred,M).\n#{a => 2,c => 4}\n```","title":"maps.filter/2","ref":"maps.html#filter/2"},{"type":"function","doc":"Returns a map `Map` that is the result of calling `Fun(Key, Value1)` for every\n`Key` to value `Value1` association in `MapOrIter` in any order.\n\nIf `Fun(Key, Value1)` returns `true`, the association is copied to the result\nmap. If it returns `false`, the association is not copied. If it returns\n`{true, NewValue}`, the value for `Key` is replaced with `NewValue` in the\nresult map.\n\nThe call fails with a `{badmap,Map}` exception if `MapOrIter` is not a map or\nvalid iterator, or with `badarg` if `Fun` is not a function of arity 2.\n\n_Example:_\n\n```erlang\n> Fun = fun(K,V) when is_atom(K) -> {true, V*2}; (_,V) -> (V rem 2) =:= 0 end,\n Map = #{k1 => 1, \"k2\" => 2, \"k3\" => 3},\n maps:filtermap(Fun,Map).\n#{k1 => 2,\"k2\" => 2}\n```","title":"maps.filtermap/2","ref":"maps.html#filtermap/2"},{"type":"function","doc":"Returns a tuple `{ok, Value}`, where `Value` is the value associated with `Key`,\nor `error` if no value is associated with `Key` in `Map`.\n\nThe call fails with a `{badmap,Map}` exception if `Map` is not a map.\n\n_Example:_\n\n```erlang\n> Map = #{\"hi\" => 42},\n Key = \"hi\",\n maps:find(Key,Map).\n{ok,42}\n```","title":"maps.find/2","ref":"maps.html#find/2"},{"type":"function","doc":"Calls `F(Key, Value, AccIn)` for every `Key` to value `Value` association in\n`MapOrIter` in any order. Function `fun F/3` must return a new accumulator,\nwhich is passed to the next successive call. This function returns the final\nvalue of the accumulator. The initial accumulator value `Init` is returned if\nthe map is empty.\n\nThe call fails with a `{badmap,Map}` exception if `MapOrIter` is not a map or\nvalid iterator, or with `badarg` if `Fun` is not a function of arity 3.\n\n_Example:_\n\n```erlang\n> Fun = fun(K,V,AccIn) when is_list(K) -> AccIn + V end,\n Map = #{\"k1\" => 1, \"k2\" => 2, \"k3\" => 3},\n maps:fold(Fun,0,Map).\n6\n```","title":"maps.fold/3","ref":"maps.html#fold/3"},{"type":"function","doc":"Calls `fun F(Key, Value)` for every `Key` to value `Value` association in\n`MapOrIter` in any order.\n\nThe call fails with a `{badmap,Map}` exception if `MapOrIter` is not a map or\nvalid iterator, or with `badarg` if `Fun` is not a function of arity 2.","title":"maps.foreach/2","ref":"maps.html#foreach/2"},{"type":"function","doc":"Takes a list of keys and a value and builds a map where all keys point to the\nsame value. The key can be in any order, and keys and value can be of any term.\n\n_Example:_\n\n```erlang\n> Keys = [\"a\", \"b\", \"c\"], maps:from_keys(Keys, ok).\n#{\"a\" => ok,\"b\" => ok,\"c\" => ok}\n```","title":"maps.from_keys/2","ref":"maps.html#from_keys/2"},{"type":"function","doc":"Takes a list of key-value tuples elements and builds a map. The associations can\nbe in any order, and both keys and values in the association can be of any term.\n\n\nIf the same key appears more than once, the latter (right-most) value is used\nand the previous values are ignored.\n\n_Example:_\n\n```erlang\n> List = [{\"a\",ignored},{1337,\"value two\"},{42,value_three},{\"a\",1}],\n maps:from_list(List).\n#{42 => value_three,1337 => \"value two\",\"a\" => 1}\n```","title":"maps.from_list/1","ref":"maps.html#from_list/1"},{"type":"function","doc":"Returns value `Value` associated with `Key` if `Map` contains `Key`.\n\nThe call fails with a `{badmap,Map}` exception if `Map` is not a map, or with a\n`{badkey,Key}` exception if no value is associated with `Key`.\n\n_Example:_\n\n```erlang\n> Key = 1337,\n Map = #{42 => value_two,1337 => \"value one\",\"a\" => 1},\n maps:get(Key,Map).\n\"value one\"\n```","title":"maps.get/2","ref":"maps.html#get/2"},{"type":"function","doc":"Returns value `Value` associated with `Key` if `Map` contains `Key`. If no value\nis associated with `Key`, `Default` is returned.\n\nThe call fails with a `{badmap,Map}` exception if `Map` is not a map.\n\n_Example:_\n\n```erlang\n> Map = #{ key1 => val1, key2 => val2 }.\n#{key1 => val1,key2 => val2}\n> maps:get(key1, Map, \"Default value\").\nval1\n> maps:get(key3, Map, \"Default value\").\n\"Default value\"\n```","title":"maps.get/3","ref":"maps.html#get/3"},{"type":"function","doc":"Partitions the given `List` into a map of groups.\n\nThe result is a map where each key is given by `KeyFun` and each value is a list\nof elements from the given `List` for which `KeyFun` returned the same key.\n\nThe order of elements within each group list is preserved from the original\nlist.\n\n_Examples:_\n\n```erlang\n> EvenOdd = fun(X) -> case X rem 2 of 0 -> even; 1 -> odd end end,\nmaps:groups_from_list(EvenOdd, [1, 2, 3]).\n#{even => [2], odd => [1, 3]}\n> maps:groups_from_list(fun erlang:length/1, [\"ant\", \"buffalo\", \"cat\", \"dingo\"]).\n#{3 => [\"ant\", \"cat\"], 5 => [\"dingo\"], 7 => [\"buffalo\"]}\n```","title":"maps.groups_from_list/2","ref":"maps.html#groups_from_list/2"},{"type":"function","doc":"Partitions the given `List` into a map of groups.\n\nThe result is a map where each key is given by `KeyFun` and each value is a list\nof elements from the given `List`, mapped via `ValueFun`, for which `KeyFun`\nreturned the same key.\n\nThe order of elements within each group list is preserved from the original\nlist.\n\n_Examples:_\n\n```erlang\n> EvenOdd = fun(X) -> case X rem 2 of 0 -> even; 1 -> odd end end,\n> Square = fun(X) -> X * X end,\n> maps:groups_from_list(EvenOdd, Square, [1, 2, 3]).\n#{even => [4], odd => [1, 9]}\n> maps:groups_from_list(\n fun erlang:length/1,\n fun lists:reverse/1,\n [\"ant\", \"buffalo\", \"cat\", \"dingo\"]).\n#{3 => [\"tna\", \"tac\"],5 => [\"ognid\"],7 => [\"olaffub\"]}\n```","title":"maps.groups_from_list/3","ref":"maps.html#groups_from_list/3"},{"type":"function","doc":"Intersects two maps into a single map `Map3`. If a key exists in both maps, the\nvalue in `Map1` is superseded by the value in `Map2`.\n\nThe call fails with a `{badmap,Map}` exception if `Map1` or `Map2` is not a map.\n\n_Example:_\n\n```erlang\n> Map1 = #{a => \"value_one\", b => \"value_two\"},\n Map2 = #{a => 1, c => 2},\n maps:intersect(Map1,Map2).\n#{a => 1}\n```","title":"maps.intersect/2","ref":"maps.html#intersect/2"},{"type":"function","doc":"Intersects two maps into a single map `Map3`. If a key exists in both maps, the\nvalue in `Map1` is combined with the value in `Map2` by the `Combiner` fun.\n\nWhen `Combiner` is applied the key that exists in both maps is the first parameter,\nthe value from `Map1` is the second parameter, and the value from `Map2` is the\nthird parameter.\n\nThe call fails with a `{badmap,Map}` exception if `Map1` or `Map2` is not a map.\nThe call fails with a `badarg` exception if `Combiner` is not a fun that takes\nthree arguments.\n\n_Example:_\n\n```erlang\n> Map1 = #{a => \"value_one\", b => \"value_two\"},\n Map2 = #{a => 1, c => 2},\n maps:intersect_with(fun(_Key, Value1, Value2) -> {Value1, Value2} end, Map1, Map2).\n#{a => {\"value_one\",1}}\n```","title":"maps.intersect_with/3","ref":"maps.html#intersect_with/3"},{"type":"function","doc":"Returns `true` if map `Map` contains `Key` and returns `false` if it does not\ncontain the `Key`.\n\nThe call fails with a `{badmap,Map}` exception if `Map` is not a map.\n\n_Example:_\n\n```erlang\n> Map = #{\"42\" => value}.\n#{\"42\" => value}\n> maps:is_key(\"42\",Map).\ntrue\n> maps:is_key(value,Map).\nfalse\n```","title":"maps.is_key/2","ref":"maps.html#is_key/2"},{"type":"function","doc":"Returns a map iterator `Iterator` that can be used by [`maps:next/1`](`next/1`)\nto traverse the key-value associations in a map. When iterating over a map, the\nmemory usage is guaranteed to be bounded no matter the size of the map.\n\nThe call fails with a `{badmap,Map}` exception if `Map` is not a map.\n\n_Example:_\n\n```erlang\n> M = #{ a => 1, b => 2 }.\n#{a => 1,b => 2}\n> I = maps:iterator(M), ok.\nok\n> {K1, V1, I2} = maps:next(I), {K1, V1}.\n{a,1}\n> {K2, V2, I3} = maps:next(I2),{K2, V2}.\n{b,2}\n> maps:next(I3).\nnone\n```","title":"maps.iterator/1","ref":"maps.html#iterator/1"},{"type":"function","doc":"Returns a map iterator `Iterator` that can be used by [`maps:next/1`](`next/1`)\nto traverse the key-value associations in a map sorted by key using the given\n`Order`.\n\nThe call fails with a `{badmap,Map}` exception if `Map` is not a map or if\n`Order` is invalid.\n\n_Example (when _`Order`_ is _`ordered`_):_\n\n```erlang\n> M = #{ a => 1, b => 2 }.\n#{a => 1,b => 2}\n> OrdI = maps:iterator(M, ordered), ok.\nok\n> {K1, V1, OrdI2} = maps:next(OrdI), {K1, V1}.\n{a,1}\n> {K2, V2, OrdI3} = maps:next(OrdI2),{K2, V2}.\n{b,2}\n> maps:next(OrdI3).\nnone\n```\n\n_Example (when _`Order`_ is _`reversed`_):_\n\n```erlang\n> M = #{ a => 1, b => 2 }.\n#{a => 1,b => 2}\n> RevI = maps:iterator(M, reversed), ok.\nok\n> {K2, V2, RevI2} = maps:next(RevI), {K2, V2}.\n{b,2}\n> {K1, V1, RevI3} = maps:next(RevI2),{K1, V1}.\n{a,1}\n> maps:next(RevI3).\nnone\n```\n\n_Example (when _`Order`_ is an arithmetic sorting function):_\n\n```erlang\n> M = #{ -1 => a, -1.0 => b, 0 => c, 0.0 => d }.\n#{-1 => a,0 => c,-1.0 => b,0.0 => d}\n> ArithOrdI = maps:iterator(M, fun(A, B) -> A = maps:to_list(ArithOrdI).\n[{-1,a},{-1.0,b},{0,c},{0.0,d}]\n> ArithRevI = maps:iterator(M, fun(A, B) -> B maps:to_list(ArithRevI).\n[{0.0,d},{0,c},{-1.0,b},{-1,a}]\n```","title":"maps.iterator/2","ref":"maps.html#iterator/2"},{"type":"function","doc":"Returns a complete list of keys, in any order, which resides within `Map`.\n\nThe call fails with a `{badmap,Map}` exception if `Map` is not a map.\n\n_Example:_\n\n```erlang\n> Map = #{42 => value_three,1337 => \"value two\",\"a\" => 1},\n maps:keys(Map).\n[42,1337,\"a\"]\n```","title":"maps.keys/1","ref":"maps.html#keys/1"},{"type":"function","doc":"Produces a new map `Map` by calling function `fun F(Key, Value1)` for every\n`Key` to value `Value1` association in `MapOrIter` in any order. Function\n`fun Fun/2` must return value `Value2` to be associated with key `Key` for the\nnew map `Map`.\n\nThe call fails with a `{badmap,Map}` exception if `MapOrIter` is not a map or\nvalid iterator, or with `badarg` if `Fun` is not a function of arity 2.\n\n_Example:_\n\n```erlang\n> Fun = fun(K,V1) when is_list(K) -> V1*2 end,\n Map = #{\"k1\" => 1, \"k2\" => 2, \"k3\" => 3},\n maps:map(Fun,Map).\n#{\"k1\" => 2,\"k2\" => 4,\"k3\" => 6}\n```","title":"maps.map/2","ref":"maps.html#map/2"},{"type":"function","doc":"Merges two maps into a single map `Map3`. If two keys exist in both maps, the\nvalue in `Map1` is superseded by the value in `Map2`.\n\nThe call fails with a `{badmap,Map}` exception if `Map1` or `Map2` is not a map.\n\n_Example:_\n\n```erlang\n> Map1 = #{a => \"value_one\", b => \"value_two\"},\n Map2 = #{a => 1, c => 2},\n maps:merge(Map1,Map2).\n#{a => 1,b => \"value_two\",c => 2}\n```","title":"maps.merge/2","ref":"maps.html#merge/2"},{"type":"function","doc":"Merges two maps into a single map `Map3`. If a key exists in both maps, the\nvalue in `Map1` is combined with the value in `Map2` by the `Combiner` fun.\n\nWhen `Combiner` is applied the key that exists in both maps is the first parameter,\nthe value from `Map1` is the second parameter, and the value from `Map2` is the\nthird parameter.\n\nThe call fails with a `{badmap,Map}` exception if `Map1` or `Map2` is not a map.\nThe call fails with a `badarg` exception if `Combiner` is not a fun that takes\nthree arguments.\n\n_Example:_\n\n```erlang\n> Map1 = #{a => \"value_one\", b => \"value_two\"},\n Map2 = #{a => 1, c => 2},\n maps:merge_with(fun(_Key, Value1, Value2) -> {Value1, Value2} end, Map1, Map2).\n#{a => {\"value_one\",1},b => \"value_two\",c => 2}\n```","title":"maps.merge_with/3","ref":"maps.html#merge_with/3"},{"type":"function","doc":"Returns a new empty map.\n\n_Example:_\n\n```text\n> maps:new().\n#{}\n```","title":"maps.new/0","ref":"maps.html#new/0"},{"type":"function","doc":"Returns the next key-value association in `Iterator` and a new iterator for the\nremaining associations in the iterator.\n\nIf there are no more associations in the iterator, `none` is returned.\n\n_Example:_\n\n```erlang\n> Map = #{a => 1, b => 2, c => 3}.\n#{a => 1,b => 2,c => 3}\n> I = maps:iterator(Map), ok.\nok\n> {K1, V1, I1} = maps:next(I), {K1, V1}.\n{a,1}\n> {K2, V2, I2} = maps:next(I1), {K2, V2}.\n{b,2}\n> {K3, V3, I3} = maps:next(I2), {K3, V3}.\n{c,3}\n> maps:next(I3).\nnone\n```","title":"maps.next/1","ref":"maps.html#next/1"},{"type":"function","doc":"Associates `Key` with value `Value` and inserts the association into map `Map2`.\nIf key `Key` already exists in map `Map1`, the old associated value is replaced\nby value `Value`. The function returns a new map `Map2` containing the new\nassociation and the old associations in `Map1`.\n\nThe call fails with a `{badmap,Map}` exception if `Map1` is not a map.\n\n_Example:_\n\n```erlang\n> Map = #{\"a\" => 1}.\n#{\"a\" => 1}\n> maps:put(\"a\", 42, Map).\n#{\"a\" => 42}\n> maps:put(\"b\", 1337, Map).\n#{\"a\" => 1,\"b\" => 1337}\n```","title":"maps.put/3","ref":"maps.html#put/3"},{"type":"function","doc":"Removes the `Key`, if it exists, and its associated value from `Map1` and\nreturns a new map `Map2` without key `Key`.\n\nThe call fails with a `{badmap,Map}` exception if `Map1` is not a map.\n\n_Example:_\n\n```erlang\n> Map = #{\"a\" => 1}.\n#{\"a\" => 1}\n> maps:remove(\"a\",Map).\n#{}\n> maps:remove(\"b\",Map).\n#{\"a\" => 1}\n```","title":"maps.remove/2","ref":"maps.html#remove/2"},{"type":"function","doc":"Returns the number of key-value associations in `Map`. This operation occurs in\nconstant time.\n\n_Example:_\n\n```erlang\n> Map = #{42 => value_two,1337 => \"value one\",\"a\" => 1},\n maps:size(Map).\n3\n```","title":"maps.size/1","ref":"maps.html#size/1"},{"type":"function","doc":"The function removes the `Key`, if it exists, and its associated value from\n`Map1` and returns a tuple with the removed `Value` and the new map `Map2`\nwithout key `Key`. If the key does not exist `error` is returned.\n\nThe call will fail with a `{badmap,Map}` exception if `Map1` is not a map.\n\nExample:\n\n```erlang\n> Map = #{\"a\" => \"hello\", \"b\" => \"world\"}.\n#{\"a\" => \"hello\", \"b\" => \"world\"}\n> maps:take(\"a\",Map).\n{\"hello\",#{\"b\" => \"world\"}}\n> maps:take(\"does not exist\",Map).\nerror\n```","title":"maps.take/2","ref":"maps.html#take/2"},{"type":"function","doc":"Returns a list of pairs representing the key-value associations of\n`MapOrIterator`, where the pairs `[{K1,V1}, ..., {Kn,Vn}]` are returned in\narbitrary order.\n\nThe call fails with a `{badmap,Map}` exception if `MapOrIterator` is not a map\nor an iterator obtained by a call to `iterator/1` or `iterator/2`.\n\n_Example:_\n\n```erlang\n> Map = #{42 => value_three,1337 => \"value two\",\"a\" => 1},\n maps:to_list(Map).\n[{42,value_three},{1337,\"value two\"},{\"a\",1}]\n```\n\n_Example (using _`iterator/2`_):_\n\n```erlang\n> Map = #{ z => 1, y => 2, x => 3 }.\n#{x => 3,y => 2,z => 1}\n> maps:to_list(maps:iterator(Map, ordered)).\n[{x,3},{y,2},{z,1}]\n```","title":"maps.to_list/1","ref":"maps.html#to_list/1"},{"type":"function","doc":"If `Key` exists in `Map1`, the old associated value is replaced by value\n`Value`. The function returns a new map `Map2` containing the new associated\nvalue.\n\nThe call fails with a `{badmap,Map}` exception if `Map1` is not a map, or with a\n`{badkey,Key}` exception if no value is associated with `Key`.\n\n_Example:_\n\n```erlang\n> Map = #{\"a\" => 1}.\n#{\"a\" => 1}\n> maps:update(\"a\", 42, Map).\n#{\"a\" => 42}\n```","title":"maps.update/3","ref":"maps.html#update/3"},{"type":"function","doc":"Update a value in a `Map1` associated with `Key` by calling `Fun` on the old\nvalue to get a new value. An exception `{badkey,Key}` is generated if `Key` is\nnot present in the map.\n\nExample:\n\n```erlang\n> Map = #{\"counter\" => 1},\n Fun = fun(V) -> V + 1 end,\n maps:update_with(\"counter\",Fun,Map).\n#{\"counter\" => 2}\n```","title":"maps.update_with/3","ref":"maps.html#update_with/3"},{"type":"function","doc":"Update a value in a `Map1` associated with `Key` by calling `Fun` on the old\nvalue to get a new value. If `Key` is not present in `Map1` then `Init` will be\nassociated with `Key`.\n\nExample:\n\n```erlang\n> Map = #{\"counter\" => 1},\n Fun = fun(V) -> V + 1 end,\n maps:update_with(\"new counter\",Fun,42,Map).\n#{\"counter\" => 1,\"new counter\" => 42}\n```","title":"maps.update_with/4","ref":"maps.html#update_with/4"},{"type":"function","doc":"Returns a complete list of values, in arbitrary order, contained in map `Map`.\n\nThe call fails with a `{badmap,Map}` exception if `Map` is not a map.\n\n_Example:_\n\n```erlang\n> Map = #{42 => value_three,1337 => \"value two\",\"a\" => 1},\n maps:values(Map).\n[value_three,\"value two\",1]\n```","title":"maps.values/1","ref":"maps.html#values/1"},{"type":"function","doc":"Returns a new map `Map2` with the keys `K1` through `Kn` and their associated\nvalues from map `Map1`. Any key in `Ks` that does not exist in `Map1` is\nignored.\n\n_Example:_\n\n```erlang\n> Map = #{42 => value_three,1337 => \"value two\",\"a\" => 1},\n Ks = [\"a\",42,\"other key\"],\n maps:with(Ks,Map).\n#{42 => value_three,\"a\" => 1}\n```","title":"maps.with/2","ref":"maps.html#with/2"},{"type":"function","doc":"Returns a new map `Map2` without keys `K1` through `Kn` and their associated\nvalues from map `Map1`. Any key in `Ks` that does not exist in `Map1` is ignored\n\n_Example:_\n\n```erlang\n> Map = #{42 => value_three,1337 => \"value two\",\"a\" => 1},\n Ks = [\"a\",42,\"other key\"],\n maps:without(Ks,Map).\n#{1337 => \"value two\"}\n```","title":"maps.without/2","ref":"maps.html#without/2"},{"type":"type","doc":"","title":"maps.iterator/0","ref":"maps.html#t:iterator/0"},{"type":"opaque","doc":"An iterator representing the associations in a map with keys of type `Key` and\nvalues of type `Value`.\n\nCreated using [`maps:iterator/1`](`iterator/1`) or\n[`maps:iterator/2`](`iterator/2`).\n\nConsumed by:\n\n- [`maps:next/1`](`next/1`)\n- [`maps:filter/2`](`filter/2`)\n- [`maps:filtermap/2`](`filtermap/2`)\n- [`maps:fold/3`](`fold/3`)\n- [`maps:foreach/2`](`foreach/2`)\n- [`maps:map/2`](`map/2`)\n- [`maps:to_list/1`](`to_list/1`)","title":"maps.iterator/2","ref":"maps.html#t:iterator/2"},{"type":"type","doc":"","title":"maps.iterator_order/0","ref":"maps.html#t:iterator_order/0"},{"type":"type","doc":"Key-based iterator order option that can be one of `undefined` (default for\n[`maps:iterator/1`](`iterator/1`)), `ordered` (sorted in map-key order),\n`reversed`, or a custom sorting function.\n\nUsed by [`maps:iterator/2`](`iterator/2`).\n\nThe [Expressions section](`e:system:expressions.md#term-comparisons`) contains\ndescriptions of how terms are ordered.","title":"maps.iterator_order/1","ref":"maps.html#t:iterator_order/1"},{"type":"module","doc":"Mathematical functions.\n\nThis module provides an interface to a number of mathematical functions.\nFor details about what each function does, see the the C library documentation\non your system. On Unix systems the easiest way it to run `man sin`. On\nWindows you should check the [Math and floating-point support](https://learn.microsoft.com/en-us/cpp/c-runtime-library/floating-point-support)\ndocumentation.","title":"math","ref":"math.html"},{"type":"module","doc":"As these are the C library, the same limitations apply.","title":"Limitations - math","ref":"math.html#module-limitations"},{"type":"function","doc":"Inverse cosine of `X`, return value is in radians.","title":"math.acos/1","ref":"math.html#acos/1"},{"type":"function","doc":"Inverse hyperbolic cosine of `X`.","title":"math.acosh/1","ref":"math.html#acosh/1"},{"type":"function","doc":"Inverse sine of `X`, return value is in radians.","title":"math.asin/1","ref":"math.html#asin/1"},{"type":"function","doc":"Inverse hyperbolic sine of `X`.","title":"math.asinh/1","ref":"math.html#asinh/1"},{"type":"function","doc":"Inverse 2-argument tangent of `X`, return value is in radians.","title":"math.atan2/2","ref":"math.html#atan2/2"},{"type":"function","doc":"Inverse tangent of `X`, return value is in radians.","title":"math.atan/1","ref":"math.html#atan/1"},{"type":"function","doc":"Inverse hyperbolic tangent of `X`.","title":"math.atanh/1","ref":"math.html#atanh/1"},{"type":"function","doc":"The ceiling of `X`.","title":"math.ceil/1","ref":"math.html#ceil/1"},{"type":"function","doc":"The cosine of `X` in radians.","title":"math.cos/1","ref":"math.html#cos/1"},{"type":"function","doc":"The hyperbolic cosine of `X`.","title":"math.cosh/1","ref":"math.html#cosh/1"},{"type":"function","doc":"Returns the error function (or Gauss error function) of `X`.\n\nWhere:\n\n```text\nerf(X) = 2/sqrt(pi)*integral from 0 to X of exp(-t*t) dt.\n```","title":"math.erf/1","ref":"math.html#erf/1"},{"type":"function","doc":"[`erfc(X)`](`erfc/1`) returns `1.0` - [`erf(X)`](`erf/1`), computed by methods\nthat avoid cancellation for large `X`.","title":"math.erfc/1","ref":"math.html#erfc/1"},{"type":"function","doc":"Raise e by `X`, that is `eˣ`.\n\nWhere e is the base of the natural logarithm.","title":"math.exp/1","ref":"math.html#exp/1"},{"type":"function","doc":"The floor of `X`.","title":"math.floor/1","ref":"math.html#floor/1"},{"type":"function","doc":"Returns `X` modulus `Y`.","title":"math.fmod/2","ref":"math.html#fmod/2"},{"type":"function","doc":"The base-2 logarithm of `X`.","title":"math.log2/1","ref":"math.html#log2/1"},{"type":"function","doc":"The base-10 logarithm of `X`.","title":"math.log10/1","ref":"math.html#log10/1"},{"type":"function","doc":"The natural (base-e) logarithm of `X`.","title":"math.log/1","ref":"math.html#log/1"},{"type":"function","doc":"Ratio of the circumference of a circle to its diameter.\n\nFloating point approximation of mathematical constant pi.","title":"math.pi/0","ref":"math.html#pi/0"},{"type":"function","doc":"Raise `X` by `N`, that is `xⁿ`.","title":"math.pow/2","ref":"math.html#pow/2"},{"type":"function","doc":"Sine of `X` in radians.","title":"math.sin/1","ref":"math.html#sin/1"},{"type":"function","doc":"Hyperbolic sine of `X`.","title":"math.sinh/1","ref":"math.html#sinh/1"},{"type":"function","doc":"Square root of `X`.","title":"math.sqrt/1","ref":"math.html#sqrt/1"},{"type":"function","doc":"Tangent of `X` in radians.","title":"math.tan/1","ref":"math.html#tan/1"},{"type":"function","doc":"Hyperbolic tangent of `X`.","title":"math.tanh/1","ref":"math.html#tanh/1"},{"type":"function","doc":"Ratio of the circumference of a circle to its radius.\n\nThis constant is equivalent to a full turn when described in radians.\n\nThe same as `2 * pi()`.","title":"math.tau/0","ref":"math.html#tau/0"},{"type":"module","doc":"Local and universal time, day of the week, date and time conversions.\n\nThis module provides computation of local and universal time, day of the week,\nand many time conversion functions.\n\nTime is local when it is adjusted in accordance with the current time zone and\ndaylight saving. Time is universal when it reflects the time at longitude zero,\nwithout any adjustment for daylight saving. Universal Coordinated Time (UTC)\ntime is also called Greenwich Mean Time (GMT).\n\nThe time functions `local_time/0` and `universal_time/0` in this module both\nreturn date and time. This is because separate functions for date and time can\nresult in a date/time combination that is displaced by 24 hours. This occurs if\none of the functions is called before midnight, and the other after midnight.\nThis problem also applies to the Erlang BIFs `date/0` and `time/0`, and their\nuse is strongly discouraged if a reliable date/time stamp is required.\n\nAll dates conform to the Gregorian calendar. This calendar was introduced by\nPope Gregory XIII in 1582 and was used in all Catholic countries from this year.\nProtestant parts of Germany and the Netherlands adopted it in 1698, England\nfollowed in 1752, and Russia in 1918 (the October revolution of 1917 took place\nin November according to the Gregorian calendar).\n\nThe Gregorian calendar in this module is extended back to year 0. For a given\ndate, the _gregorian days_ is the number of days up to and including the date\nspecified. Similarly, the _gregorian seconds_ for a specified date and time is\nthe number of seconds up to and including the specified date and time.\n\nFor computing differences between epochs in time, use the functions counting\ngregorian days or seconds. If epochs are specified as local time, they must be\nconverted to universal time to get the correct value of the elapsed time between\nepochs. Use of function [`time_difference/2`](`time_difference/2`) is\ndiscouraged.\n\nDifferent definitions exist for the week of the year. This module contains a\nweek of the year implementation conforming to the ISO 8601 standard. As the week\nnumber for a specified date can fall on the previous, the current, or on the\nnext year, it is important to specify both the year and the week number.\nFunctions `iso_week_number/0` and [`iso_week_number/1`](`iso_week_number/1`)\nreturn a tuple of the year and the week number.","title":"calendar","ref":"calendar.html"},{"type":"module","doc":"The notion that every fourth year is a leap year is not completely true. By the\nGregorian rule, a year Y is a leap year if one of the following rules is valid:\n\n- Y is divisible by 4, but not by 100.\n- Y is divisible by 400.\n\nHence, 1996 is a leap year, 1900 is not, but 2000 is.","title":"Leap Years - calendar","ref":"calendar.html#module-leap-years"},{"type":"module","doc":"Local time is obtained from the Erlang BIF `localtime/0`. Universal time is\ncomputed from the BIF `universaltime/0`.\n\nThe following apply:\n\n- There are 86400 seconds in a day.\n- There are 365 days in an ordinary year.\n- There are 366 days in a leap year.\n- There are 1461 days in a 4 year period.\n- There are 36524 days in a 100 year period.\n- There are 146097 days in a 400 year period.\n- There are 719528 days between Jan 1, 0 and Jan 1, 1970.","title":"Date and Time Source - calendar","ref":"calendar.html#module-date-and-time-source"},{"type":"function","doc":"Computes the number of gregorian days starting with year 0 and ending at the\nspecified date.","title":"calendar.date_to_gregorian_days/1","ref":"calendar.html#date_to_gregorian_days/1"},{"type":"function","doc":"","title":"calendar.date_to_gregorian_days/3","ref":"calendar.html#date_to_gregorian_days/3"},{"type":"function","doc":"Computes the number of gregorian seconds starting with year 0 and ending at the\nspecified date and time.","title":"calendar.datetime_to_gregorian_seconds/1","ref":"calendar.html#datetime_to_gregorian_seconds/1"},{"type":"function","doc":"Computes the day of the week from the specified `Year`, `Month`, and `Day`.\nReturns the day of the week as `1`: Monday, `2`: Tuesday, and so on.","title":"calendar.day_of_the_week/1","ref":"calendar.html#day_of_the_week/1"},{"type":"function","doc":"","title":"calendar.day_of_the_week/3","ref":"calendar.html#day_of_the_week/3"},{"type":"function","doc":"Computes the date from the specified number of gregorian days.","title":"calendar.gregorian_days_to_date/1","ref":"calendar.html#gregorian_days_to_date/1"},{"type":"function","doc":"Computes the date and time from the specified number of gregorian seconds.","title":"calendar.gregorian_seconds_to_datetime/1","ref":"calendar.html#gregorian_seconds_to_datetime/1"},{"type":"function","doc":"Checks if the specified year is a leap year.","title":"calendar.is_leap_year/1","ref":"calendar.html#is_leap_year/1"},{"type":"function","doc":"Returns tuple `{Year, WeekNum}` representing the ISO week number for the actual\ndate. To determine the actual date, use function `local_time/0`.","title":"calendar.iso_week_number/0","ref":"calendar.html#iso_week_number/0"},{"type":"function","doc":"Returns tuple `{Year, WeekNum}` representing the ISO week number for the\nspecified date.","title":"calendar.iso_week_number/1","ref":"calendar.html#iso_week_number/1"},{"type":"function","doc":"Computes the number of days in a month.","title":"calendar.last_day_of_the_month/2","ref":"calendar.html#last_day_of_the_month/2"},{"type":"function","doc":"Returns the local time reported by the underlying operating system.","title":"calendar.local_time/0","ref":"calendar.html#local_time/0"},{"type":"function","doc":"Converts from local time to Universal Coordinated Time (UTC). `DateTime1` must\nrefer to a local date after Jan 1, 1970.\n\n> #### Warning {: .warning }\n>\n> This function is deprecated. Use `local_time_to_universal_time_dst/1` instead,\n> as it gives a more correct and complete result. Especially for the period that\n> does not exist, as it is skipped during the switch _to_ daylight saving time,\n> this function still returns a result.","title":"calendar.local_time_to_universal_time/1","ref":"calendar.html#local_time_to_universal_time/1"},{"type":"function","doc":"Converts from local time to Universal Coordinated Time (UTC). `DateTime1` must\nrefer to a local date after Jan 1, 1970.\n\nThe return value is a list of 0, 1, or 2 possible UTC times:\n\n- **`[]`** - For a local `{Date1, Time1}` during the period that is skipped when\n switching _to_ daylight saving time, there is no corresponding UTC, as the\n local time is illegal (it has never occured).\n\n- **`[DstDateTimeUTC, DateTimeUTC]`** - For a local `{Date1, Time1}` during the\n period that is repeated when switching _from_ daylight saving time, two\n corresponding UTCs exist; one for the first instance of the period when\n daylight saving time is still active, and one for the second instance.\n\n- **`[DateTimeUTC]`** - For all other local times only one corresponding UTC\n exists.","title":"calendar.local_time_to_universal_time_dst/1","ref":"calendar.html#local_time_to_universal_time_dst/1"},{"type":"function","doc":"Returns Universal Coordinated Time (UTC) converted from the return value from\n`erlang:timestamp/0`.","title":"calendar.now_to_datetime/1","ref":"calendar.html#now_to_datetime/1"},{"type":"function","doc":"Returns local date and time converted from the return value from\n`erlang:timestamp/0`.","title":"calendar.now_to_local_time/1","ref":"calendar.html#now_to_local_time/1"},{"type":"function","doc":"Returns Universal Coordinated Time (UTC) converted from the return value from\n`erlang:timestamp/0`.","title":"calendar.now_to_universal_time/1","ref":"calendar.html#now_to_universal_time/1"},{"type":"function","doc":"","title":"calendar.rfc3339_to_system_time/1","ref":"calendar.html#rfc3339_to_system_time/1"},{"type":"function","doc":"Converts an RFC 3339 timestamp into system time. The data format of RFC 3339\ntimestamps is described by [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt).\nStarting from OTP 25.1, the minutes part of the time zone is optional.\n\nValid option:\n\n- **`{unit, Unit}`** - The time unit of the return value. The default is\n `second`.\n\n```erlang\n1> calendar:rfc3339_to_system_time(\"2018-02-01T16:17:58+01:00\").\n1517498278\n2> calendar:rfc3339_to_system_time(\"2018-02-01 15:18:02.088Z\",\n [{unit, nanosecond}]).\n1517498282088000000\n3> calendar:rfc3339_to_system_time(<<\"2018-02-01 15:18:02.088Z\">>,\n [{unit, nanosecond}]).\n1517498282088000000\n```","title":"calendar.rfc3339_to_system_time/2","ref":"calendar.html#rfc3339_to_system_time/2"},{"type":"function","doc":"Converts a specified number of seconds into days, hours, minutes, and seconds.\n`Time` is always non-negative, but `Days` is negative if argument `Seconds` is.","title":"calendar.seconds_to_daystime/1","ref":"calendar.html#seconds_to_daystime/1"},{"type":"function","doc":"Computes the time from the specified number of seconds. `Seconds` must be less\nthan the number of seconds per day (86400).","title":"calendar.seconds_to_time/1","ref":"calendar.html#seconds_to_time/1"},{"type":"function","doc":"Converts a specified system time into local date and time.","title":"calendar.system_time_to_local_time/2","ref":"calendar.html#system_time_to_local_time/2"},{"type":"function","doc":"","title":"calendar.system_time_to_rfc3339/1","ref":"calendar.html#system_time_to_rfc3339/1"},{"type":"function","doc":"Converts a system time into an RFC 3339 timestamp.\n\nThe data format of RFC 3339 timestamps is described by [RFC 3339].\nThe data format of offsets is also described by [RFC 3339].\n\nValid options:\n\n- **`{offset, Offset}`** - The offset, either a string or an integer, to be\n included in the formatted string. An empty string, which is the default, is\n interpreted as local time. A non-empty string is included as is. The time unit\n of the integer is the same as the one of `Time`.\n\n- **`{time_designator, Character}`** - The character used as time designator,\n that is, the date and time separator. The default is `$T`.\n\n- **`{unit, Unit}`** - The time unit of `Time`. The default is `second`. If some\n other unit is given (`millisecond`, `microsecond`, `nanosecond`, or `native`),\n the formatted string includes a fraction of a second. The number of fractional\n second digits is three, six, or nine depending on what time unit is chosen.\n For `native` three fractional digits are included. Notice that trailing zeros\n are not removed from the fraction.\n\n- **`{return, Return}`** - The desired encoding type for the output,\n whether a string or a binary is desired. Defaults to string.\n\n```erlang\n1> calendar:system_time_to_rfc3339(erlang:system_time(second)).\n\"2018-04-23T14:56:28+02:00\"\n2> calendar:system_time_to_rfc3339(erlang:system_time(second),\n [{offset, \"-02:00\"}]).\n\"2018-04-23T10:56:52-02:00\"\n3> calendar:system_time_to_rfc3339(erlang:system_time(second),\n [{offset, -7200}]).\n\"2018-04-23T10:57:05-02:00\"\n4> calendar:system_time_to_rfc3339(erlang:system_time(millisecond),\n [{unit, millisecond}, {time_designator, $\\s}, {offset, \"Z\"}]).\n\"2018-04-23 12:57:20.482Z\"\n5> calendar:system_time_to_rfc3339(erlang:system_time(millisecond),\n [{unit, millisecond}, {time_designator, $\\s}, {offset, \"Z\"}, {return, binary}]).\n<<\"2018-04-23 12:57:20.482Z\">>\n```\n[RFC 3339]: https://www.ietf.org/rfc/rfc3339.txt","title":"calendar.system_time_to_rfc3339/2","ref":"calendar.html#system_time_to_rfc3339/2"},{"type":"function","doc":"Converts a specified system time into universal date and time.","title":"calendar.system_time_to_universal_time/2","ref":"calendar.html#system_time_to_universal_time/2"},{"type":"function","doc":"Returns the difference between two `{Date, Time}` tuples. `T2` is to refer to an\nepoch later than `T1`.\n\n> #### Warning {: .warning }\n>\n> This function is obsolete. Use the conversion functions for gregorian days and\n> seconds instead.","title":"calendar.time_difference/2","ref":"calendar.html#time_difference/2"},{"type":"function","doc":"Returns the number of seconds since midnight up to the specified time.","title":"calendar.time_to_seconds/1","ref":"calendar.html#time_to_seconds/1"},{"type":"function","doc":"Returns the Universal Coordinated Time (UTC) reported by the underlying\noperating system. Returns local time if universal time is unavailable.","title":"calendar.universal_time/0","ref":"calendar.html#universal_time/0"},{"type":"function","doc":"Converts from Universal Coordinated Time (UTC) to local time. `DateTime` must\nrefer to a date after Jan 1, 1970.","title":"calendar.universal_time_to_local_time/1","ref":"calendar.html#universal_time_to_local_time/1"},{"type":"function","doc":"This function checks if a date is a valid.","title":"calendar.valid_date/1","ref":"calendar.html#valid_date/1"},{"type":"function","doc":"","title":"calendar.valid_date/3","ref":"calendar.html#valid_date/3"},{"type":"type","doc":"A date using the Gregorian calendar.\n\nAll APIs expect this to be a valid date. If the source of the date\nis unknown, then verify that is it valid by calling `valid_date/1`\nbefore using it.","title":"calendar.date/0","ref":"calendar.html#t:date/0"},{"type":"type","doc":"","title":"calendar.datetime1970/0","ref":"calendar.html#t:datetime1970/0"},{"type":"type","doc":"","title":"calendar.datetime/0","ref":"calendar.html#t:datetime/0"},{"type":"type","doc":"","title":"calendar.day/0","ref":"calendar.html#t:day/0"},{"type":"type","doc":"","title":"calendar.daynum/0","ref":"calendar.html#t:daynum/0"},{"type":"type","doc":"","title":"calendar.hour/0","ref":"calendar.html#t:hour/0"},{"type":"type","doc":"The last day of the month.","title":"calendar.ldom/0","ref":"calendar.html#t:ldom/0"},{"type":"type","doc":"","title":"calendar.minute/0","ref":"calendar.html#t:minute/0"},{"type":"type","doc":"","title":"calendar.month/0","ref":"calendar.html#t:month/0"},{"type":"type","doc":"","title":"calendar.offset/0","ref":"calendar.html#t:offset/0"},{"type":"type","doc":"","title":"calendar.rfc3339_string/0","ref":"calendar.html#t:rfc3339_string/0"},{"type":"type","doc":"The time unit used by the rfc3339 conversion functions.\n\n> #### Note {: .info }\n>\n> The `native` time unit was added to `t:rfc3339_time_unit/0` in OTP 25.0.","title":"calendar.rfc3339_time_unit/0","ref":"calendar.html#t:rfc3339_time_unit/0"},{"type":"type","doc":"","title":"calendar.second/0","ref":"calendar.html#t:second/0"},{"type":"type","doc":"","title":"calendar.secs_per_day/0","ref":"calendar.html#t:secs_per_day/0"},{"type":"type","doc":"","title":"calendar.time/0","ref":"calendar.html#t:time/0"},{"type":"type","doc":"","title":"calendar.weeknum/0","ref":"calendar.html#t:weeknum/0"},{"type":"type","doc":"","title":"calendar.year1970/0","ref":"calendar.html#t:year1970/0"},{"type":"type","doc":"The year using the Gregorian calendar.\n\nYear cannot be abbreviated. For example, 93 denotes year 93, not 1993. The valid\nrange depends on the underlying operating system.","title":"calendar.year/0","ref":"calendar.html#t:year/0"},{"type":"type","doc":"","title":"calendar.yearweeknum/0","ref":"calendar.html#t:yearweeknum/0"},{"type":"module","doc":"Timer functions.\n\nThis module provides useful functions related to time. Unless otherwise stated,\ntime is always measured in _milliseconds_. All timer functions return\nimmediately, regardless of work done by another process.\n\nSuccessful evaluations of the timer functions give return values containing a\ntimer reference, denoted `TRef`. By using `cancel/1`, the returned reference can\nbe used to cancel any requested action. A `TRef` is an Erlang term, which\ncontents must not be changed.\n\nThe time-outs are not exact, but are _at least_ as long as requested.\n\nCreating timers using `erlang:send_after/3` and `erlang:start_timer/3` is more\nefficient than using the timers provided by this module. However, the timer\nmodule has been improved in OTP 25, making it more efficient and less\nsusceptible to being overloaded. See\n[the Timer Module section in the Efficiency Guide](`e:system:commoncaveats.md#timer-module`).\n\nFor more information on timers in Erlang in general, see the\n[*Timers*](`e:erts:time_correction.md#timers`) section of the\n[*Time and Time Correction in Erlang*](`e:erts:time_correction.md`)\nERTS User's guide.","title":"timer","ref":"timer.html"},{"type":"module","doc":"_Example 1_\n\nThe following example shows how to print \"Hello World\\!\" in 5 seconds:\n\n```erlang\n1> timer:apply_after(5000, io, format, [\"~nHello World!~n\", []]).\n{ok,TRef}\nHello World!\n```\n\n_Example 2_\n\nThe following example shows a process performing a certain action, and if this\naction is not completed within a certain limit, the process is killed:\n\n```erlang\nPid = spawn(mod, fun, [foo, bar]),\n%% If pid is not finished in 10 seconds, kill him\n{ok, R} = timer:kill_after(timer:seconds(10), Pid),\n...\n%% We change our mind...\ntimer:cancel(R),\n...\n```","title":"Examples - timer","ref":"timer.html#module-examples"},{"type":"module","doc":"A timer can always be removed by calling `cancel/1`.\n\nAn interval timer, that is, a timer created by evaluating any of the functions\n`apply_interval/2`, `apply_interval/3`, `apply_interval/4`,\n`apply_repeatedly/2`, `apply_repeatedly/3`, `apply_repeatedly/4`,\n`send_interval/2`, and `send_interval/3` is linked to the process to which the\ntimer performs its task.\n\nA one-shot timer, that is, a timer created by evaluating any of the functions\n`apply_after/2`, `apply_after/3`, `apply_after/4`, `send_after/2`,\n`send_after/3`, `exit_after/2`, `exit_after/3`, `kill_after/1`, and\n`kill_after/2` is not linked to any process. Hence, such a timer is removed only\nwhen it reaches its time-out, or if it is explicitly removed by a call to\n`cancel/1`.\n\nThe functions given to `apply_after/2`, `apply_after/3`, `apply_interval/2`,\n`apply_interval/3`, `apply_repeatedly/2`, and `apply_repeatedly/3`, or denoted\nby `Module`, `Function` and `Arguments` given to `apply_after/4`,\n`apply_interval/4`, and `apply_repeatedly/4` are executed in a freshly-spawned\nprocess, and therefore calls to `self/0` in those functions will return the Pid\nof this process, which is different from the process that called\n`timer:apply_*`.\n\n_Example_\n\nIn the following example, the intention is to set a timer to execute a function\nafter 1 second, which performs a fictional task, and then wants to inform the\nprocess which set the timer about its completion, by sending it a `done`\nmessage.\n\nUsing `self/0` _inside_ the timed function, the code below does not work as\nintended. The task gets done, but the `done` message gets sent to the wrong\nprocess and is lost.\n\n```erlang\n1> timer:apply_after(1000, fun() -> do_something(), self() ! done end).\n{ok,TRef}\n2> receive done -> done after 5000 -> timeout end.\n%% ... 5s pass...\ntimeout\n```\n\nThe code below calls `self/0` in the process which sets the timer and assigns it\nto a variable, which is then used in the function to send the `done` message to,\nand so works as intended.\n\n```erlang\n1> Target = self()\n<0.82.0>\n2> timer:apply_after(1000, fun() -> do_something(), Target ! done end).\n{ok,TRef}\n3> receive done -> done after 5000 -> timeout end.\n%% ... 1s passes...\ndone\n```\n\nAnother option is to pass the message target as a parameter to the function.\n\n```erlang\n1> timer:apply_after(1000, fun(Target) -> do_something(), Target ! done end, [self()]).\n{ok,TRef}\n2> receive done -> done after 5000 -> timeout end.\n%% ... 1s passes...\ndone\n```","title":"Notes - timer","ref":"timer.html#module-notes"},{"type":"function","doc":"Evaluates [`spawn(erlang, apply, [Function, []])`](`spawn/3`) after `Time`\nmilliseconds.","title":"timer.apply_after/2","ref":"timer.html#apply_after/2"},{"type":"function","doc":"Evaluates [`spawn(erlang, apply, [Function, Arguments])`](`spawn/3`) after\n`Time` milliseconds.","title":"timer.apply_after/3","ref":"timer.html#apply_after/3"},{"type":"function","doc":"Evaluates [`spawn(Module, Function, Arguments)`](`spawn/3`) after `Time`\nmilliseconds.","title":"timer.apply_after/4","ref":"timer.html#apply_after/4"},{"type":"function","doc":"Evaluates [`spawn(erlang, apply, [Function, []])`](`spawn/3`) repeatedly at\nintervals of `Time`, irrespective of whether a previously spawned process has\nfinished or not.","title":"timer.apply_interval/2","ref":"timer.html#apply_interval/2"},{"type":"function","doc":"Evaluates [`spawn(erlang, apply, [Function, Arguments])`](`spawn/3`) repeatedly\nat intervals of `Time`, irrespective of whether a previously spawned process has\nfinished or not.","title":"timer.apply_interval/3","ref":"timer.html#apply_interval/3"},{"type":"function","doc":"Evaluates [`spawn(Module, Function, Arguments)`](`spawn/3`) repeatedly at\nintervals of `Time`, irrespective of whether a previously spawned process has\nfinished or not.\n\n> #### Warning {: .warning }\n>\n> If the execution time of the spawned process is, on average, greater than the\n> given `Time`, multiple such processes will run at the same time. With long\n> execution times, short intervals, and many interval timers running, this may\n> even lead to exceeding the number of allowed processes. As an extreme example,\n> consider\n> `[timer:apply_interval(1, timer, sleep, [1000]) || _ <- lists:seq(1, 1000)]`,\n> that is, 1,000 interval timers executing a process that takes 1s to complete,\n> started in intervals of 1ms, which would result in 1,000,000 processes running\n> at the same time, far more than a node started with default settings allows\n> (see the\n> [System Limits section in the Effiency Guide](`e:system:system_limits.md`)).","title":"timer.apply_interval/4","ref":"timer.html#apply_interval/4"},{"type":"function","doc":"Evaluates [`spawn(erlang, apply, [Function, []])`](`spawn/3`) repeatedly at\nintervals of `Time`, waiting for the spawned process to finish before starting\nthe next.","title":"timer.apply_repeatedly/2","ref":"timer.html#apply_repeatedly/2"},{"type":"function","doc":"Evaluates [`spawn(erlang, apply, [Function, Arguments])`](`spawn/3`) repeatedly\nat intervals of `Time`, waiting for the spawned process to finish before\nstarting the next.","title":"timer.apply_repeatedly/3","ref":"timer.html#apply_repeatedly/3"},{"type":"function","doc":"Evaluates [`spawn(Module, Function, Arguments)`](`spawn/3`) repeatedly at\nintervals of `Time`, waiting for the spawned process to finish before starting\nthe next.\n\nIf the execution time of the spawned process is greater than the given `Time`,\nthe next process is spawned immediately after the one currently running has\nfinished. Assuming that execution times of the spawned processes performing the\napplies on average are smaller than `Time`, the amount of applies made over a\nlarge amount of time will be the same even if some individual execution times\nare larger than `Time`. The system will try to catch up as soon as possible. For\nexample, if one apply takes `2.5*Time`, the following two applies will be made\nimmediately one after the other in sequence.","title":"timer.apply_repeatedly/4","ref":"timer.html#apply_repeatedly/4"},{"type":"function","doc":"Cancels a previously requested time-out. `TRef` is a unique timer reference\nreturned by the related timer function.\n\nReturns `{ok, cancel}`, or `{error, Reason}` when `TRef` is not a timer\nreference.","title":"timer.cancel/1","ref":"timer.html#cancel/1"},{"type":"function","doc":"","title":"timer.exit_after/2","ref":"timer.html#exit_after/2"},{"type":"function","doc":"Sends an exit signal with reason `Reason1` to `Target`, which can be a local\nprocess identifier or an atom of a registered name.","title":"timer.exit_after/3","ref":"timer.html#exit_after/3"},{"type":"function","doc":"Returns the number of milliseconds in `Hours + Minutes + Seconds`.","title":"timer.hms/3","ref":"timer.html#hms/3"},{"type":"function","doc":"Returns the number of milliseconds in `Hours`.","title":"timer.hours/1","ref":"timer.html#hours/1"},{"type":"function","doc":"","title":"timer.kill_after/1","ref":"timer.html#kill_after/1"},{"type":"function","doc":"","title":"timer.kill_after/2","ref":"timer.html#kill_after/2"},{"type":"function","doc":"Returns the number of milliseconds in `Minutes`.","title":"timer.minutes/1","ref":"timer.html#minutes/1"},{"type":"function","doc":"Calculates the time difference `Tdiff = T2 - T1` in _microseconds_, where `T1`\nand `T2` are time-stamp tuples on the same format as returned from\n`erlang:timestamp/0` or `os:timestamp/0`.","title":"timer.now_diff/2","ref":"timer.html#now_diff/2"},{"type":"function","doc":"Returns the number of milliseconds in `Seconds`.","title":"timer.seconds/1","ref":"timer.html#seconds/1"},{"type":"function","doc":"","title":"timer.send_after/2","ref":"timer.html#send_after/2"},{"type":"function","doc":"Evaluates `Destination ! Message` after `Time` milliseconds.\n\n`Destination` can be a remote or local process identifier, an atom of a\nregistered name or a tuple `{RegName, Node}` for a registered name at another node.\n\nSee also [the Timer Module section in the Efficiency Guide](`e:system:commoncaveats.md#timer-module`).","title":"timer.send_after/3","ref":"timer.html#send_after/3"},{"type":"function","doc":"","title":"timer.send_interval/2","ref":"timer.html#send_interval/2"},{"type":"function","doc":"Evaluates `Destination ! Message` repeatedly after `Time` milliseconds.\n\n`Destination` can be a remote or local process identifier, an atom of a registered\nname or a tuple `{RegName, Node}` for a registered name at another node.","title":"timer.send_interval/3","ref":"timer.html#send_interval/3"},{"type":"function","doc":"Suspends the process calling this function for `Time` milliseconds and then\nreturns `ok`, or suspends the process forever if `Time` is the atom `infinity`.\nNaturally, this function does _not_ return immediately.\n\n> #### Note {: .info }\n>\n> Before OTP 25, `timer:sleep/1` did not accept integer timeout values greater\n> than `16#ffffffff`, that is, `2^32-1`. Since OTP 25, arbitrarily high integer\n> values are accepted.","title":"timer.sleep/1","ref":"timer.html#sleep/1"},{"type":"function","doc":"Starts the timer server.\n\nNormally, the server does not need to be started explicitly. It is started dynamically\nif it is needed. This is useful during development, but in a target system the server\nis to be started explicitly. Use configuration parameters for [Kernel](`e:kernel:index.html`)\nfor this.","title":"timer.start/0","ref":"timer.html#start/0"},{"type":"function","doc":"","title":"timer.tc/1","ref":"timer.html#tc/1"},{"type":"function","doc":"Measures the execution time of `Fun`.\n\nEquivalent to [`tc(Fun, Arguments, microsecond)`](`tc/3`) if called as `tc(Fun, Arguments)`.\n\nMeasures the execution time of `Fun` in `TimeUnit` if called as `tc(Fun, TimeUnit)`. Added in OTP 26.0.","title":"timer.tc/2","ref":"timer.html#tc/2"},{"type":"function","doc":"Measures the execution time of `Fun` or `apply(Module, Function, Arguments)`.\n\nEquivalent to [`tc(Module, Function, Arguments, microsecond)`](`tc/4`) if called as `tc(Module, Function, Arguments)`.\n\nEquivalent to [`tc(erlang, apply, [Fun, Arguments], TimeUnit)`](`tc/4`) if called as `tc(Fun, Arguments, TimeUnit)`. Added in OTP 26.0","title":"timer.tc/3","ref":"timer.html#tc/3"},{"type":"function","doc":"Evaluates [`apply(Module, Function, Arguments)`](`apply/3`) and measures the elapsed\nreal time as reported by `erlang:monotonic_time/0`.\n\nReturns `{Time, Value}`, where `Time` is the elapsed real time in the\nspecified `TimeUnit`, and `Value` is what is returned from the apply.","title":"timer.tc/4","ref":"timer.html#tc/4"},{"type":"type","doc":"Time in milliseconds.","title":"timer.time/0","ref":"timer.html#t:time/0"},{"type":"opaque","doc":"A timer reference.","title":"timer.tref/0","ref":"timer.html#t:tref/0"},{"type":"module","doc":"Command line arguments parser.\n\nThis module implements command line parser. Parser operates with _commands_ and\n_arguments_ represented as a tree. Commands are branches, and arguments are\nleaves of the tree. Parser always starts with the root command, named after\n`progname` (the name of the program which started Erlang).\n\nA [`command specification`](`t:command/0`) may contain handler definition for\neach command, and a number argument specifications. When parser is successful,\n`argparse` calls the matching handler, passing arguments extracted from the\ncommand line. Arguments can be positional (occupying specific position in the\ncommand line), and optional, residing anywhere but prefixed with a specified\ncharacter.\n\n`argparse` automatically generates help and usage messages. It will also issue\nerrors when users give the program invalid arguments.","title":"argparse","ref":"argparse.html"},{"type":"module","doc":"`argparse` is designed to work with [`escript`](`e:erts:escript_cmd.md`). The\nexample below is a fully functioning Erlang program accepting two command line\narguments and printing their product.\n\n```erlang\n#!/usr/bin/env escript\n\nmain(Args) ->\n argparse:run(Args, cli(), #{progname => mul}).\n\ncli() ->\n #{\n arguments => [\n #{name => left, type => integer},\n #{name => right, type => integer}\n ],\n handler =>\n fun (#{left := Left, right := Right}) ->\n io:format(\"~b~n\", [Left * Right])\n end\n }.\n```\n\nRunning this script with no arguments results in an error, accompanied by the\nusage information.\n\nThe `cli` function defines a single command with embedded handler accepting a\nmap. Keys of the map are argument names as defined by the `argument` field of\nthe command, `left` and `right` in the example. Values are taken from the\ncommand line, and converted into integers, as requested by the type\nspecification. Both arguments in the example above are required (and therefore\ndefined as positional).","title":"Quick start - argparse","ref":"argparse.html#module-quick-start"},{"type":"module","doc":"A command may contain nested commands, forming a hierarchy. Arguments defined at\nthe upper level command are automatically added to all nested commands. Nested\ncommands example (assuming `progname` is `nested`):\n\n```erlang\ncli() ->\n #{\n %% top level argument applicable to all commands\n arguments => [#{name => top}],\n commands => #{\n \"first\" => #{\n %% argument applicable to \"first\" command and\n %% all commands nested into \"first\"\n arguments => [#{name => mid}],\n commands => #{\n \"second\" => #{\n %% argument only applicable for \"second\" command\n arguments => [#{name => bottom}],\n handler => fun (A) -> io:format(\"~p~n\", [A]) end\n }\n }\n }\n }\n }.\n```\n\nIn the example above, a 3-level hierarchy is defined. First is the script itself\n(`nested`), accepting the only argument `top`. Since it has no associated\nhandler, `run/3` will not accept user input omitting nested command selection.\nFor this example, user has to supply 5 arguments in the command line, two being\ncommand names, and another 3 - required positional arguments:\n\n```text\n./nested.erl one first second two three\n#{top => \"one\",mid => \"two\",bottom => \"three\"}\n```\n\nCommands have preference over positional argument values. In the example above,\ncommands and positional arguments are interleaving, and `argparse` matches\ncommand name first.","title":"Command hierarchy - argparse","ref":"argparse.html#module-command-hierarchy"},{"type":"module","doc":"`argparse` supports positional and optional arguments. Optional arguments, or\noptions for short, must be prefixed with a special character (`-` is the default\non all operating systems). Both options and positional arguments have 1 or more\nassociated values. See [`argument specification`](`t:argument/0`) to find more\ndetails about supported combinations.\n\nIn the user input, short options may be concatenated with their values. Long\noptions support values separated by `=`. Consider this definition:\n\n```erlang\ncli() ->\n #{\n arguments => [\n #{name => long, long => \"-long\"},\n #{name => short, short => $s}\n ],\n handler => fun (Args) -> io:format(\"~p~n\", [Args]) end\n }.\n```\n\nRunning `./args --long=VALUE` prints `#{long => \"VALUE\"}`, running\n`./args -sVALUE` prints `#{short => \"VALUE\"}`\n\n`argparse` supports boolean flags concatenation: it is possible to shorten\n`-r -f -v` to `-rfv`.\n\nShortened option names are not supported: it is not possible to use `--my-argum`\ninstead of `--my-argument-name` even when such option can be unambiguously\nfound.","title":"Arguments - argparse","ref":"argparse.html#module-arguments"},{"type":"function","doc":"Generates human-readable text for [`parser error`](`t:parser_error/0`). Does not\ninclude help/usage information, and does not provide localisation.","title":"argparse.format_error/1","ref":"argparse.html#format_error/1"},{"type":"function","doc":"","title":"argparse.help/1","ref":"argparse.html#help/1"},{"type":"function","doc":"Generates help/usage information text for the command supplied, or any nested\ncommand when `command` option is specified. Arguments are displayed in the same\norder as specified in `Command`. Does not provide localisation. Expects\n`progname` to be set, otherwise defaults to return value of\n`init:get_argument(progname)`.","title":"argparse.help/2","ref":"argparse.html#help/2"},{"type":"function","doc":"","title":"argparse.parse/2","ref":"argparse.html#parse/2"},{"type":"function","doc":"Parses command line arguments according to the command specification. Raises an\nexception if the command specification is not valid. Use\n[`erl_error:format_exception/3,4` ](`erl_error:format_exception/3`)to see a\nfriendlier message. Invalid command line input does not raise an exception, but\nmakes `parse/2,3` to return a tuple\n[`{error, parser_error()}`](`t:parser_error/0`).\n\nThis function does not call command handler.","title":"argparse.parse/3","ref":"argparse.html#parse/3"},{"type":"function","doc":"Parses command line arguments and calls the matching command handler. Prints\nhuman-readable error, help/usage information for the discovered command, and\nhalts the emulator with code 1 if there is any error in the command\nspecification or user-provided command line input.\n\n> #### Warning {: .warning }\n>\n> This function is designed to work as an entry point to a standalone\n> [`escript`](`e:erts:escript_cmd.md`). Therefore, it halts the emulator for any\n> error detected. Do not use this function through remote procedure call, or it\n> may result in an unexpected shutdown of a remote node.","title":"argparse.run/3","ref":"argparse.html#run/3"},{"type":"type","doc":"Arguments map is the map of argument names to the values extracted from the\ncommand line. It is passed to the matching command handler. If an argument is\nomitted, but has the default value is specified, it is added to the map. When no\ndefault value specified, and argument is not present in the command line,\ncorresponding key is not present in the resulting map.","title":"argparse.arg_map/0","ref":"argparse.html#t:arg_map/0"},{"type":"type","doc":"Defines type conversion applied to the string retrieved from the user input. If\nthe conversion is successful, resulting value is validated using optional\n`Choices`, or minimums and maximums (for integer and floating point values\nonly). Strings and binary values may be validated using regular expressions.\nIt's possible to define custom type conversion function, accepting a string and\nreturning Erlang term. If this function raises error with `badarg` reason,\nargument is treated as invalid.","title":"argparse.arg_type/0","ref":"argparse.html#t:arg_type/0"},{"type":"type","doc":"List of command line arguments to be parsed.","title":"argparse.args/0","ref":"argparse.html#t:args/0"},{"type":"type","doc":"Argument specification. Defines a single named argument that is returned in the\n[`argument map`](`t:arg_map/0`). The only required field is `name`, all other\nfields have defaults.\n\nIf either of the `short` or `long` fields is specified, the argument is treated\nas optional. Optional arguments do not have specific order and may appear\nanywhere in the command line. Positional arguments are ordered the same way as\nthey appear in the arguments list of the command specification.\n\nBy default, all positional arguments must be present in the command line. The\nparser will return an error otherwise. Options, however, may be omitted, in\nwhich case resulting argument map will either contain the default value, or not\nhave the key at all.\n\n- **`name`** - Sets the argument name in the parsed argument map. If `help` is\n not defined, name is also used to generate the default usage message.\n\n- **`short`** - Defines a short (single character) form of an optional argument.\n\n ```erlang\n %% Define a command accepting argument named myarg, with short form $a:\n 1> Cmd = #{arguments => [#{name => myarg, short => $a}]}.\n %% Parse command line \"-a str\":\n 2> {ok, ArgMap, _, _} = argparse:parse([\"-a\", \"str\"], Cmd), ArgMap.\n\n #{myarg => \"str\"}\n\n %% Option value can be concatenated with the switch: \"-astr\"\n 3> {ok, ArgMap, _, _} = argparse:parse([\"-astr\"], Cmd), ArgMap.\n\n #{myarg => \"str\"}\n ```\n\n By default all options expect a single value following the option switch. The\n only exception is an option of a boolean type.\n\n- **`long`** - Defines a long form of an optional argument.\n\n ```erlang\n 1> Cmd = #{arguments => [#{name => myarg, long => \"name\"}]}.\n %% Parse command line \"-name Erlang\":\n 2> {ok, ArgMap, _, _} = argparse:parse([\"-name\", \"Erlang\"], Cmd), ArgMap.\n\n #{myarg => \"Erlang\"}\n %% Or use \"=\" to separate the switch and the value:\n 3> {ok, ArgMap, _, _} = argparse:parse([\"-name=Erlang\"], Cmd), ArgMap.\n\n #{myarg => \"Erlang\"}\n ```\n\n If neither `short` not `long` is defined, the argument is treated as\n positional.\n\n- **`required`** - Forces the parser to expect the argument to be present in the\n command line. By default, all positional argument are required, and all\n options are not.\n\n- **`default`** - Specifies the default value to put in the parsed argument map\n if the value is not supplied in the command line.\n\n ```erlang\n 1> argparse:parse([], #{arguments => [#{name => myarg, short => $m}]}).\n\n {ok,#{}, ...\n 2> argparse:parse([], #{arguments => [#{name => myarg, short => $m, default => \"def\"}]}).\n\n {ok,#{myarg => \"def\"}, ...\n ```\n\n- **`type`** - Defines type conversion and validation routine. The default is\n `string`, assuming no conversion.\n\n- **`nargs`** - Defines the number of following arguments to consume from the\n command line. By default, the parser consumes the next argument and converts\n it into an Erlang term according to the specified type.\n\n - **`t:pos_integer/0`** - Consume exactly this number of positional arguments,\n fail if there is not enough. Value in the argument map contains a list of\n exactly this length. Example, defining a positional argument expecting 3\n integer values:\n\n ```erlang\n 1> Cmd = #{arguments => [#{name => ints, type => integer, nargs => 3}]},\n argparse:parse([\"1\", \"2\", \"3\"], Cmd).\n\n {ok, #{ints => [1, 2, 3]}, ...\n ```\n\n Another example defining an option accepted as `-env` and expecting two\n string arguments:\n\n ```erlang\n 1> Cmd = #{arguments => [#{name => env, long => \"env\", nargs => 2}]},\n argparse:parse([\"-env\", \"key\", \"value\"], Cmd).\n\n {ok, #{env => [\"key\", \"value\"]}, ...\n ```\n\n - **`list`** - Consume all following arguments until hitting the next option\n (starting with an option prefix). May result in an empty list added to the\n arguments map.\n\n ```erlang\n 1> Cmd = #{arguments => [\n #{name => nodes, long => \"nodes\", nargs => list},\n #{name => verbose, short => $v, type => boolean}\n ]},\n argparse:parse([\"-nodes\", \"one\", \"two\", \"-v\"], Cmd).\n\n {ok, #{nodes => [\"one\", \"two\"], verbose => true}, ...\n ```\n\n - **`nonempty_list`** - Same as `list`, but expects at least one argument.\n Returns an error if the following command line argument is an option switch\n (starting with the prefix).\n\n - **`'maybe'`** - Consumes the next argument from the command line, if it does\n not start with an option prefix. Otherwise, adds a default value to the\n arguments map.\n\n ```erlang\n 1> Cmd = #{arguments => [\n #{name => level, short => $l, nargs => 'maybe', default => \"error\"},\n #{name => verbose, short => $v, type => boolean}\n ]},\n argparse:parse([\"-l\", \"info\", \"-v\"], Cmd).\n\n {ok,#{level => \"info\",verbose => true}, ...\n\n %% When \"info\" is omitted, argument maps receives the default \"error\"\n 2> argparse:parse([\"-l\", \"-v\"], Cmd).\n\n {ok,#{level => \"error\",verbose => true}, ...\n ```\n\n - **`{'maybe', term()}`** - Consumes the next argument from the command line,\n if it does not start with an option prefix. Otherwise, adds a specified\n Erlang term to the arguments map.\n\n - **`all`** - Fold all remaining command line arguments into a list, ignoring\n any option prefixes or switches. Useful for proxying arguments into another\n command line utility.\n\n ```erlang\n 1> Cmd = #{arguments => [\n #{name => verbose, short => $v, type => boolean},\n #{name => raw, long => \"-\", nargs => all}\n ]},\n argparse:parse([\"-v\", \"--\", \"-kernel\", \"arg\", \"opt\"], Cmd).\n\n {ok,#{raw => [\"-kernel\",\"arg\",\"opt\"],verbose => true}, ...\n ```\n\n- **`action`** - Defines an action to take when the argument is found in the\n command line. The default action is `store`.\n\n - **`store`** - Store the value in the arguments map. Overwrites the value\n previously written.\n\n ```erlang\n 1> Cmd = #{arguments => [#{name => str, short => $s}]},\n argparse:parse([\"-s\", \"one\", \"-s\", \"two\"], Cmd).\n\n {ok, #{str => \"two\"}, ...\n ```\n\n - **`{store, term()}`** - Stores the specified term instead of reading the\n value from the command line.\n\n ```erlang\n 1> Cmd = #{arguments => [#{name => str, short => $s, action => {store, \"two\"}}]},\n argparse:parse([\"-s\"], Cmd).\n\n {ok, #{str => \"two\"}, ...\n ```\n\n - **`append`** - Appends the repeating occurrences of the argument instead of\n overwriting.\n\n ```erlang\n 1> Cmd = #{arguments => [#{name => node, short => $n, action => append}]},\n argparse:parse([\"-n\", \"one\", \"-n\", \"two\", \"-n\", \"three\"], Cmd).\n\n {ok, #{node => [\"one\", \"two\", \"three\"]}, ...\n\n %% Always produces a list - even if there is one occurrence\n 2> argparse:parse([\"-n\", \"one\"], Cmd).\n\n {ok, #{node => [\"one\"]}, ...\n ```\n\n - **`{append, term()}`** - Same as `append`, but instead of consuming the\n argument from the command line, appends a provided `t:term/0`.\n\n - **`count`** - Puts a counter as a value in the arguments map. Useful for\n implementing verbosity option:\n\n ```erlang\n 1> Cmd = #{arguments => [#{name => verbose, short => $v, action => count}]},\n argparse:parse([\"-v\"], Cmd).\n\n {ok, #{verbose => 1}, ...\n\n 2> argparse:parse([\"-vvvv\"], Cmd).\n\n {ok, #{verbose => 4}, ...\n ```\n\n - **`extend`** - Works as `append`, but flattens the resulting list. Valid\n only for `nargs` set to `list`, `nonempty_list`, `all` or `t:pos_integer/0`.\n\n ```erlang\n 1> Cmd = #{arguments => [#{name => duet, short => $d, nargs => 2, action => extend}]},\n argparse:parse([\"-d\", \"a\", \"b\", \"-d\", \"c\", \"d\"], Cmd).\n\n {ok, #{duet => [\"a\", \"b\", \"c\", \"d\"]}, ...\n\n %% 'append' would result in {ok, #{duet => [[\"a\", \"b\"],[\"c\", \"d\"]]},\n ```\n\n- **`help`** - Specifies help/usage text for the argument. `argparse` provides\n automatic generation based on the argument name, type and default value, but\n for better usability it is recommended to have a proper description. Setting\n this field to `hidden` suppresses usage output for this argument.","title":"argparse.argument/0","ref":"argparse.html#t:argument/0"},{"type":"type","doc":"User-defined help template to print in the command usage. First element of a\ntuple must be a string. It is printed as a part of the usage header. Second\nelement of the tuple can be either a list containing strings, `type` and\n`default` atoms, or a user-defined function that must return a string. A plain\nstring should be wrapped as a list such as `[\"string is nested\"]`.","title":"argparse.argument_help/0","ref":"argparse.html#t:argument_help/0"},{"type":"type","doc":"Argument name is used to populate argument map.","title":"argparse.argument_name/0","ref":"argparse.html#t:argument_name/0"},{"type":"type","doc":"Path to the nested command. First element is always the `progname`, subsequent\nelements are nested command names.","title":"argparse.cmd_path/0","ref":"argparse.html#t:cmd_path/0"},{"type":"type","doc":"Command specification. May contain nested commands, forming a hierarchy.\n\n- **`commands`** - Maps of nested commands. Keys must be strings, matching\n command line input. Basic utilities do not need to specify any nested\n commands.\n\n- **`arguments`** - List of arguments accepted by this command, and all nested\n commands in the hierarchy.\n\n- **`help`** - Specifies help/usage text for this command. Pass `hidden` to\n remove this command from the usage output.\n\n- **`handler`** - Specifies a callback function to call by `run/3` when the\n parser is successful.","title":"argparse.command/0","ref":"argparse.html#t:command/0"},{"type":"type","doc":"User-defined help template. Use this option to mix custom and predefined usage\ntext. Help template may contain unicode strings, and following atoms:\n\n- **usage** - Formatted command line usage text, e.g. `rm [-rf] `.\n\n- **commands** - Expanded list of sub-commands.\n\n- **arguments** - Detailed description of positional arguments.\n\n- **options** - Detailed description of optional arguments.","title":"argparse.command_help/0","ref":"argparse.html#t:command_help/0"},{"type":"type","doc":"Command handler specification. Called by [`run/3` ](`run/3`)upon successful\nparser return.\n\n- **`fun((arg_map()) -> term())`** - Function accepting\n [`argument map`](`t:arg_map/0`). See the basic example in the\n [Quick Start](`m:argparse#module-quick-start`) section.\n\n- **`{Module :: module(), Function :: atom()}`** - Function named `Function`,\n exported from `Module`, accepting [`argument map`](`t:arg_map/0`).\n\n- **`{fun(() -> term()), Default :: term()}`** - Function accepting as many\n arguments as there are in the `arguments` list for this command. Arguments\n missing from the parsed map are replaced with the `Default`. Convenient way to\n expose existing functions.\n\n ```erlang\n 1> Cmd = #{arguments => [\n #{name => x, type => float},\n #{name => y, type => float, short => $p}],\n handler => {fun math:pow/2, 1}},\n argparse:run([\"2\", \"-p\", \"3\"], Cmd, #{}).\n\n 8.0\n\n %% default term 1 is passed to math:pow/2\n 2> argparse:run([\"2\"], Cmd, #{}).\n\n 2.0\n ```\n\n- **`{Module :: module(), Function :: atom(), Default :: term()}`** - Function\n named `Function`, exported from `Module`, accepting as many arguments as\n defined for this command. Arguments missing from the parsed map are replaced\n with the `Default`. Effectively, just a different syntax to the same\n functionality as demonstrated in the code above.","title":"argparse.handler/0","ref":"argparse.html#t:handler/0"},{"type":"type","doc":"Returned from [`parse/2,3`](`parse/3`). Contains arguments extracted from the\ncommand line, path to the nested command (if any), and a (potentially nested)\ncommand specification that was considered when the parser finished successfully.\nIt is expected that the command contains a handler definition, that will be\ncalled passing the argument map.","title":"argparse.parse_result/0","ref":"argparse.html#t:parse_result/0"},{"type":"type","doc":"Returned from [`parse/2,3`](`parse/3`) when the user input cannot be parsed\naccording to the command specification.\n\nFirst element is the path to the command that was considered when the parser\ndetected an error. Second element, `Expected`, is the argument specification\nthat caused an error. It could be `undefined`, meaning that `Actual` argument\nhad no corresponding specification in the arguments list for the current\ncommand.\n\nWhen `Actual` is set to `undefined`, it means that a required argument is\nmissing from the command line. If both `Expected` and `Actual` have values, it\nmeans validation error.\n\nUse `format_error/1` to generate a human-readable error description, unless\nthere is a need to provide localised error messages.","title":"argparse.parser_error/0","ref":"argparse.html#t:parser_error/0"},{"type":"type","doc":"Options changing parser behaviour.\n\n- **`prefixes`** - Changes the option prefix (the default is `-`).\n\n- **`default`** - Specifies the default value for all optional arguments. When\n this field is set, resulting argument map will contain all argument names.\n Useful for easy pattern matching on the argument map in the handler function.\n\n- **`progname`** - Specifies the program (root command) name. Returned as the\n first element of the command path, and printed in help/usage text. It is\n recommended to have this value set, otherwise the default one is determined\n with `init:get_argument(progname)` and is often set to `erl` instead of the\n actual script name.\n\n- **`command`** - Specifies the path to the nested command for `help/2`. Useful\n to limit output for complex utilities with multiple commands, and used by the\n default error handling logic.\n\n- **`columns`** - Specifies the help/usage text width (characters) for `help/2`.\n Default value is 80.","title":"argparse.parser_options/0","ref":"argparse.html#t:parser_options/0"},{"type":"module","doc":"This module provides functions to create and inspect escripts.\n\nSee the [escript](`e:erts:escript_cmd.md`) program documentation\nfor more details on how to use escripts.","title":"escript","ref":"escript.html"},{"type":"function","doc":"Creates an escript from a list of sections.\n\nThe sections can be specified in any order. An escript begins with an optional\n`Header` followed by a mandatory `Body`. If the header is present, it does always\n begin with a `shebang`, possibly followed by a `comment` and `emu_args`. The\n`shebang` defaults to `\"/usr/bin/env escript\"`. The `comment` defaults to\n`\"This is an -*- erlang -*- file\"`. The created escript can either be returned\nas a binary or written to file.\n\nAs an example of how the function can be used, we create an interpreted escript\nthat uses `emu_args` to set some emulator flag. In this case, it happens to set\nnumber of schedulers with `+S3`. We also extract the different sections from the\nnewly created script:\n\n```erlang\n> Source = \"%% Demo\\nmain(_Args) ->\\n io:format(\\\"~p\\\",[erlang:system_info(schedulers)]).\\n\".\n\"%% Demo\\nmain(_Args) ->\\n io:format(erlang:system_info(schedulers)).\\n\"\n> io:format(\"~s\\n\", [Source]).\n%% Demo\nmain(_Args) ->\n io:format(erlang:system_info(schedulers)).\n\nok\n> {ok, Bin} = escript:create(binary, [shebang, comment, {emu_args, \"+S3\"},\n {source, list_to_binary(Source)}]).\n{ok,<<\"#!/usr/bin/env escript\\n%% This is an -*- erlang -*- file\\n%%!+S3\"...>>}\n> file:write_file(\"demo.escript\", Bin).\nok\n> os:cmd(\"escript demo.escript\").\n\"3\"\n> escript:extract(\"demo.escript\", []).\n{ok,[{shebang,default}, {comment,default}, {emu_args,\"+S3\"},\n {source,<<\"%% Demo\\nmain(_Args) ->\\n io:format(erlang:system_info(schedu\"...>>}]}\n```\n\nAn escript without header can be created as follows:\n\n```erlang\n> file:write_file(\"demo.erl\",\n [\"%% demo.erl\\n-module(demo).\\n-export([main/1]).\\n\\n\", Source]).\nok\n> {ok, _, BeamCode} = compile:file(\"demo.erl\", [binary, debug_info]).\n{ok,demo,\n <<70,79,82,49,0,0,2,208,66,69,65,77,65,116,111,109,0,0,0,\n 79,0,0,0,9,4,100,...>>}\n> escript:create(\"demo.beam\", [{beam, BeamCode}]).\nok\n> escript:extract(\"demo.beam\", []).\n{ok,[{shebang,undefined}, {comment,undefined}, {emu_args,undefined},\n {beam,<<70,79,82,49,0,0,3,68,66,69,65,77,65,116,\n 111,109,0,0,0,83,0,0,0,9,...>>}]}\n> os:cmd(\"escript demo.beam\").\n\"true\"\n```\n\nHere we create an archive script containing both Erlang code and Beam code, then\nwe iterate over all files in the archive and collect their contents and some\ninformation about them:\n\n```erlang\n> {ok, SourceCode} = file:read_file(\"demo.erl\").\n{ok,<<\"%% demo.erl\\n-module(demo).\\n-export([main/1]).\\n\\n%% Demo\\nmain(_Arg\"...>>}\n> escript:create(\"demo.escript\",\n [shebang,\n {archive, [{\"demo.erl\", SourceCode},\n {\"demo.beam\", BeamCode}], []}]).\nok\n> {ok, [{shebang,default}, {comment,undefined}, {emu_args,undefined},\n {archive, ArchiveBin}]} = escript:extract(\"demo.escript\", []).\n{ok,[{shebang,default}, {comment,undefined}, {emu_args,undefined},\n {{archive,<<80,75,3,4,20,0,0,0,8,0,118,7,98,60,105,\n 152,61,93,107,0,0,0,118,0,...>>}]}\n> file:write_file(\"demo.zip\", ArchiveBin).\nok\n> zip:foldl(fun(N, I, B, A) -> [{N, I(), B()} | A] end, [], \"demo.zip\").\n{ok,[{\"demo.beam\",\n {file_info,748,regular,read_write,\n {{2010,3,2},{0,59,22}},\n {{2010,3,2},{0,59,22}},\n {{2010,3,2},{0,59,22}},\n 54,1,0,0,0,0,0},\n <<70,79,82,49,0,0,2,228,66,69,65,77,65,116,111,109,0,0,0,\n 83,0,0,...>>},\n {\"demo.erl\",\n {file_info,118,regular,read_write,\n {{2010,3,2},{0,59,22}},\n {{2010,3,2},{0,59,22}},\n {{2010,3,2},{0,59,22}},\n 54,1,0,0,0,0,0},\n <<\"%% demo.erl\\n-module(demo).\\n-export([main/1]).\\n\\n%% Demo\\nmain(_Arg\"...>>}]}\n```","title":"escript.create/2","ref":"escript.html#create/2"},{"type":"function","doc":"Parses an escript and extracts its sections. This is the reverse of `create/2`.\n\nAll sections are returned even if they do not exist in the escript. If a\nparticular section happens to have the same value as the default value, the\nextracted value is set to the atom `default`. If a section is missing, the\nextracted value is set to the atom `undefined`.\n\nOption `compile_source` only affects the result if the escript contains `source`\ncode. In this case the Erlang code is automatically compiled and\n`{source, BeamCode}` is returned instead of `{source, SourceCode}`.\n\nExample:\n\n```erlang\n> escript:create(\"demo.escript\",\n [shebang, {archive, [{\"demo.erl\", SourceCode},\n {\"demo.beam\", BeamCode}], []}]).\nok\n> {ok, [{shebang,default}, {comment,undefined}, {emu_args,undefined},\n {archive, ArchiveBin}]} =\n escript:extract(\"demo.escript\", []).\n{ok,[{{archive,<<80,75,3,4,20,0,0,0,8,0,118,7,98,60,105,\n 152,61,93,107,0,0,0,118,0,...>>}\n {emu_args,undefined}]}\n```","title":"escript.extract/2","ref":"escript.html#extract/2"},{"type":"function","doc":"Returns the name of the escript that is executed.\n\nIf the function is invoked outside the context of an escript,\nthe behavior is undefined.","title":"escript.script_name/0","ref":"escript.html#script_name/0"},{"type":"type","doc":"","title":"escript.comment/0","ref":"escript.html#t:comment/0"},{"type":"type","doc":"Any arguments that should be passed to [erl](`e:erts:erl_cmd.md`) when starting.","title":"escript.emu_args/0","ref":"escript.html#t:emu_args/0"},{"type":"type","doc":"","title":"escript.extract_option/0","ref":"escript.html#t:extract_option/0"},{"type":"type","doc":"","title":"escript.section/0","ref":"escript.html#t:section/0"},{"type":"type","doc":"","title":"escript.section_name/0","ref":"escript.html#t:section_name/0"},{"type":"type","doc":"The initial `#!` line.\n\nFor example:\n\n```text\n#!/usr/bin/env escript\n```","title":"escript.shebang/0","ref":"escript.html#t:shebang/0"},{"type":"type","doc":"","title":"escript.zip_file/0","ref":"escript.html#t:zip_file/0"},{"type":"module","doc":"Start and control linked Erlang nodes.\n\nThis module provides functions for starting linked Erlang nodes. The node\nspawning new nodes is called _origin_, and newly started nodes are _peer_ nodes,\nor peers. A peer node automatically terminates when it loses the _control\nconnection_ to the origin. This connection could be an Erlang distribution\nconnection, or an alternative - TCP or standard I/O. The alternative connection\nprovides a way to execute remote procedure calls even when Erlang Distribution\nis not available, allowing to test the distribution itself.\n\nPeer node terminal input/output is relayed through the origin. If a standard I/O\nalternative connection is requested, console output also goes via the origin,\nallowing debugging of node startup and boot script execution (see\n[`-init_debug`](`e:erts:erl_cmd.md#init_debug`)). File I/O is not redirected,\ncontrary to `m:slave` behaviour.\n\nThe peer node can start on the same or a different host (via `ssh`) or in a\nseparate container (for example Docker). When the peer starts on the same host\nas the origin, it inherits the current directory and environment variables from\nthe origin.\n\n> #### Note {: .info }\n>\n> This module is designed to facilitate multi-node testing with Common Test. Use\n> the `?CT_PEER()` macro to start a linked peer node according to Common Test\n> conventions: crash dumps written to specific location, node name prefixed with\n> module name, calling function, and origin OS process ID). Use `random_name/1`\n> to create sufficiently unique node names if you need more control.\n>\n> A peer node started without alternative connection behaves similarly to\n> `m:slave`. When an alternative connection is requested, the behaviour is\n> similar to `test_server:start_node(Name, peer, Args).`","title":"peer","ref":"peer.html"},{"type":"module","doc":"The following example implements a test suite starting extra Erlang nodes. It\nemploys a number of techniques to speed up testing and reliably shut down peer\nnodes:\n\n- peers start linked to test runner process. If the test case fails, the peer\n node is stopped automatically, leaving no rogue nodes running in the\n background\n- arguments used to start the peer are saved in the control process state for\n manual analysis. If the test case fails, the CRASH REPORT contains these\n arguments\n- multiple test cases can run concurrently speeding up overall testing process,\n peer node names are unique even when there are multiple instances of the same\n test suite running in parallel\n\n```erlang\n-module(my_SUITE).\n-behaviour(ct_suite).\n-export([all/0, groups/0]).\n-export([basic/1, args/1, named/1, restart_node/1, multi_node/1]).\n\n-include_lib(\"common_test/include/ct.hrl\").\n\ngroups() ->\n [{quick, [parallel],\n [basic, args, named, restart_node, multi_node]}].\n\nall() ->\n [{group, quick}].\n\nbasic(Config) when is_list(Config) ->\n {ok, Peer, _Node} = ?CT_PEER(),\n peer:stop(Peer).\n\nargs(Config) when is_list(Config) ->\n %% specify additional arguments to the new node\n {ok, Peer, _Node} = ?CT_PEER([\"-emu_flavor\", \"smp\"]),\n peer:stop(Peer).\n\nnamed(Config) when is_list(Config) ->\n %% pass test case name down to function starting nodes\n Peer = start_node_impl(named_test),\n peer:stop(Peer).\n\nstart_node_impl(ActualTestCase) ->\n {ok, Peer, Node} = ?CT_PEER(#{name => ?CT_PEER_NAME(ActualTestCase)}),\n %% extra setup needed for multiple test cases\n ok = rpc:call(Node, application, set_env, [kernel, key, value]),\n Peer.\n\nrestart_node(Config) when is_list(Config) ->\n Name = ?CT_PEER_NAME(),\n {ok, Peer, Node} = ?CT_PEER(#{name => Name}),\n peer:stop(Peer),\n %% restart the node with the same name as before\n {ok, Peer2, Node} = ?CT_PEER(#{name => Name, args => [\"+fnl\"]}),\n peer:stop(Peer2).\n```\n\nThe next example demonstrates how to start multiple nodes concurrently:\n\n```erlang\nmulti_node(Config) when is_list(Config) ->\n Peers = [?CT_PEER(#{wait_boot => {self(), tag}})\n || _ <- lists:seq(1, 4)],\n %% wait for all nodes to complete boot process, get their names:\n _Nodes = [receive {tag, {started, Node, Peer}} -> Node end\n || {ok, Peer} <- Peers],\n [peer:stop(Peer) || {ok, Peer} <- Peers].\n```\n\nStart a peer on a different host. Requires `ssh` key-based authentication set\nup, allowing \"another_host\" connection without password prompt.\n\n```erlang\nSsh = os:find_executable(\"ssh\"),\npeer:start_link(#{exec => {Ssh, [\"another_host\", \"erl\"]},\n connection => standard_io}),\n```\n\nThe following Common Test case demonstrates Docker integration, starting two\ncontainers with hostnames \"one\" and \"two\". In this example Erlang nodes running\ninside containers form an Erlang cluster.\n\n```erlang\ndocker(Config) when is_list(Config) ->\n Docker = os:find_executable(\"docker\"),\n PrivDir = proplists:get_value(priv_dir, Config),\n build_release(PrivDir),\n build_image(PrivDir),\n\n %% start two Docker containers\n {ok, Peer, Node} = peer:start_link(#{name => lambda,\n connection => standard_io,\n exec => {Docker, [\"run\", \"-h\", \"one\", \"-i\", \"lambda\"]}}),\n {ok, Peer2, Node2} = peer:start_link(#{name => lambda,\n connection => standard_io,\n exec => {Docker, [\"run\", \"-h\", \"two\", \"-i\", \"lambda\"]}}),\n\n %% find IP address of the second node using alternative connection RPC\n {ok, Ips} = peer:call(Peer2, inet, getifaddrs, []),\n {\"eth0\", Eth0} = lists:keyfind(\"eth0\", 1, Ips),\n {addr, Ip} = lists:keyfind(addr, 1, Eth0),\n\n %% make first node to discover second one\n ok = peer:call(Peer, inet_db, set_lookup, [[file]]),\n ok = peer:call(Peer, inet_db, add_host, [Ip, [\"two\"]]),\n\n %% join a cluster\n true = peer:call(Peer, net_kernel, connect_node, [Node2]),\n %% verify that second peer node has only the first node visible\n [Node] = peer:call(Peer2, erlang, nodes, []),\n\n %% stop peers, causing containers to also stop\n peer:stop(Peer2),\n peer:stop(Peer).\n\nbuild_release(Dir) ->\n %% load sasl.app file, otherwise application:get_key will fail\n application:load(sasl),\n %% create *.rel - release file\n RelFile = filename:join(Dir, \"lambda.rel\"),\n Release = {release, {\"lambda\", \"1.0.0\"},\n {erts, erlang:system_info(version)},\n [{App, begin {ok, Vsn} = application:get_key(App, vsn), Vsn end}\n || App <- [kernel, stdlib, sasl]]},\n ok = file:write_file(RelFile, list_to_binary(lists:flatten(\n io_lib:format(\"~tp.\", [Release])))),\n RelFileNoExt = filename:join(Dir, \"lambda\"),\n\n %% create boot script\n {ok, systools_make, []} = systools:make_script(RelFileNoExt,\n [silent, {outdir, Dir}]),\n %% package release into *.tar.gz\n ok = systools:make_tar(RelFileNoExt, [{erts, code:root_dir()}]).\n\nbuild_image(Dir) ->\n %% Create Dockerfile example, working only for Ubuntu 20.04\n %% Expose port 4445, and make Erlang distribution to listen\n %% on this port, and connect to it without EPMD\n %% Set cookie on both nodes to be the same.\n BuildScript = filename:join(Dir, \"Dockerfile\"),\n Dockerfile =\n \"FROM ubuntu:20.04 as runner\\n\"\n \"EXPOSE 4445\\n\"\n \"WORKDIR /opt/lambda\\n\"\n \"COPY lambda.tar.gz /tmp\\n\"\n \"RUN tar -zxvf /tmp/lambda.tar.gz -C /opt/lambda\\n\"\n \"ENTRYPOINT [\\\"/opt/lambda/erts-\" ++ erlang:system_info(version) ++\n \"/bin/dyn_erl\\\", \\\"-boot\\\", \\\"/opt/lambda/releases/1.0.0/start\\\",\"\n \" \\\"-kernel\\\", \\\"inet_dist_listen_min\\\", \\\"4445\\\",\"\n \" \\\"-erl_epmd_port\\\", \\\"4445\\\",\"\n \" \\\"-setcookie\\\", \\\"secret\\\"]\\n\",\n ok = file:write_file(BuildScript, Dockerfile),\n os:cmd(\"docker build -t lambda \" ++ Dir).\n```","title":"Example - peer","ref":"peer.html#module-example"},{"type":"function","doc":"","title":"peer.call/4","ref":"peer.html#call/4"},{"type":"function","doc":"Uses the alternative connection to evaluate\n[`apply(Module, Function, Args)`](`apply/3`) on the peer node and returns the\ncorresponding value `Result`.\n\n`Timeout` is an integer representing the timeout in milliseconds or the atom\n`infinity` which prevents the operation from ever timing out.\n\nWhen an alternative connection is not requested, this function will raise `exit`\nsignal with the `noconnection` reason. Use `m:erpc` module to communicate over\nErlang distribution.","title":"peer.call/5","ref":"peer.html#call/5"},{"type":"function","doc":"Uses the alternative connection to evaluate\n[`apply(Module, Function, Args)`](`apply/3`) on the peer node. No response is\ndelivered to the calling process.\n\n`peer:cast/4` fails silently when the alternative connection is not configured.\nUse `m:erpc` module to communicate over Erlang distribution.","title":"peer.cast/4","ref":"peer.html#cast/4"},{"type":"function","doc":"Returns the peer node state.\n\nThe initial state is `booting`; the node stays in that state until then boot\nscript is complete, and then the node progresses to `running`. If the node stops\n(gracefully or not), the state changes to `down`.","title":"peer.get_state/1","ref":"peer.html#get_state/1"},{"type":"function","doc":"","title":"peer.random_name/0","ref":"peer.html#random_name/0"},{"type":"function","doc":"Creates a sufficiently unique node name for the current host, combining a\nprefix, a unique number, and the current OS process ID.\n\n> #### Note {: .info }\n>\n> Use the `?CT_PEER([\"erl_arg1\"])` macro provided by Common Test\n> `-include_lib(\"common_test/include/ct.hrl\")` for convenience. It starts a new\n> peer using Erlang distribution as the control channel, supplies thes calling\n> module's code path to the peer, and uses the calling function name for the\n> name prefix.","title":"peer.random_name/1","ref":"peer.html#random_name/1"},{"type":"function","doc":"Uses the alternative connection to send Message to a process on the the peer node.\n\nSilently fails if no alternative connection is configured. The process can\nbe referenced by process ID or registered name.","title":"peer.send/3","ref":"peer.html#send/3"},{"type":"function","doc":"Starts a peer node with the specified `t:start_options/0`. Returns the\ncontrolling process and the full peer node name, unless `wait_boot` is not\nrequested and the host name is not known in advance.","title":"peer.start/1","ref":"peer.html#start/1"},{"type":"function","doc":"The same as [`start_link(#{name => random_name()})`](`start_link/1`).","title":"peer.start_link/0","ref":"peer.html#start_link/0"},{"type":"function","doc":"Starts a peer node in the same way as `start/1`, except that the peer node is\nlinked to the currently executing process. If that process terminates, the peer\nnode also terminates.\n\nAccepts `t:start_options/0`. Returns the controlling process and the full peer\nnode name, unless `wait_boot` is not requested and host name is not known in\nadvance.\n\nWhen the `standard_io` alternative connection is requested, and `wait_boot` is\nnot set to `false`, a failed peer boot sequence causes the caller to exit with\nthe `{boot_failed, {exit_status, ExitCode}}` reason.","title":"peer.start_link/1","ref":"peer.html#start_link/1"},{"type":"function","doc":"Stops a peer node. How the node is stopped depends on the\n[`shutdown`](`t:start_options/0`) option passed when starting the peer node.\nCurrently the following `shutdown` options are supported:\n\n- **`halt`** - This is the default shutdown behavior. It behaves as `shutdown`\n option `{halt, DefaultTimeout}` where `DefaultTimeout` currently equals\n `5000`.\n\n- **`{halt, Timeout :: disconnect_timeout()}`** - Triggers a call to\n [`erlang:halt()`](`erlang:halt/0`) on the peer node and then waits for the\n Erlang distribution connection to the peer node to be taken down. If this\n connection has not been taken down after `Timeout` milliseconds, it will\n forcefully be taken down by `peer:stop/1`. See the\n [warning](`m:peer#dist_connection_close`) below for more info about this.\n\n- **`Timeout :: disconnect_timeout()`** - Triggers a call to\n [`init:stop()`](`init:stop/0`) on the peer node and then waits for the Erlang\n distribution connection to the peer node to be taken down. If this connection\n has not been taken down after `Timeout` milliseconds, it will forcefully be\n taken down by `peer:stop/1`. See the [warning](`m:peer#dist_connection_close`)\n below for more info about this.\n\n- **`close`** - Close the _control connection_ to the peer node and return. This\n is the fastest way for the caller of `peer:stop/1` to stop a peer node.\n\n Note that if the Erlang distribution connection is not used as control\n connection it might not have been taken down when `peer:stop/1` returns. Also\n note that the [warning](`m:peer#dist_connection_close`) below applies when the\n Erlang distribution connection is used as control connection.\n\n[](){: #dist_connection_close }\n\n> #### Warning {: .warning }\n>\n> In the cases where the Erlang distribution connection is taken down by\n> `peer:stop/1`, other code independent of the peer code might react to the\n> connection loss before the peer node is stopped which might cause undesirable\n> effects. For example, [`global`](`m:global#prevent_overlapping_partitions`)\n> might trigger even more Erlang distribution connections to other nodes to be\n> taken down. The potential undesirable effects are, however, not limited to\n> this. It is hard to say what the effects will be since these effects can be\n> caused by any code with links or monitors to something on the origin node, or\n> code monitoring the connection to the origin node.","title":"peer.stop/1","ref":"peer.html#stop/1"},{"type":"type","doc":"Alternative connection between the origin and the peer. When the connection\ncloses, the peer node terminates automatically.\n\nIf the `peer_down` startup flag is set to `crash`, the controlling process on\nthe origin node exits with corresponding reason, effectively providing a two-way link.\n\nWhen `connection` is set to a port number, the origin starts listening on the\nrequested TCP port, and the peer node connects to the port. When it is set to an\n`{IP, Port}` tuple, the origin listens only on the specified IP. The port number\ncan be set to 0 for automatic selection.\n\nUsing the `standard_io` alternative connection starts the peer attached to the\norigin (other connections use `-detached` flag to erl). In this mode peer and\norigin communicate via stdin/stdout.","title":"peer.connection/0","ref":"peer.html#t:connection/0"},{"type":"type","doc":"Disconnect timeout. See [`stop()`](`stop/1`).","title":"peer.disconnect_timeout/0","ref":"peer.html#t:disconnect_timeout/0"},{"type":"type","doc":"Overrides executable to start peer nodes with.\n\nBy default it is the path to \"erl\", taken from `init:get_argument(progname)`.\nIf `progname` is not known, `peer` makes best guess given the current ERTS version.\n\nWhen a tuple is passed, the first element is the path to executable, and the\nsecond element is prepended to the final command line. This can be used to start\npeers on a remote host or in a Docker container. See the examples above.\n\nThis option is useful for testing backwards compatibility with previous\nreleases, installed at specific paths, or when the Erlang installation location\nis missing from the `PATH`.","title":"peer.exec/0","ref":"peer.html#t:exec/0"},{"type":"type","doc":"Peer node state.","title":"peer.peer_state/0","ref":"peer.html#t:peer_state/0"},{"type":"type","doc":"Identifies the controlling process of a peer node.","title":"peer.server_ref/0","ref":"peer.html#t:server_ref/0"},{"type":"type","doc":"Options that can be used when starting a `peer` node through `start/1` and\n[`start_link/0,1`](`start_link/0`).\n\n- **`name`** - Node name (the part before \"@\"). When `name` is not specified,\n but `host` is, `peer` follows compatibility behaviour and uses the origin node\n name.\n\n- **`longnames`** - Use long names to start a node. Default is taken from the\n origin using `net_kernel:longnames()`. If the origin is not distributed, short\n names is the default.\n\n- **`host`** - Enforces a specific host name. Can be used to override the\n default behaviour and start \"node@localhost\" instead of \"node@realhostname\".\n\n- **`peer_down`** - Defines the peer control process behaviour when the control\n connection is closed from the peer node side (for example when the peer\n crashes or dumps core). When set to `stop` (default), a lost control\n connection causes the control process to exit normally. Setting `peer_down` to\n `continue` keeps the control process running, and `crash` will cause the\n controlling process to exit abnormally.\n\n- **`connection`** - Alternative connection specification. See the\n [`connection` datatype](`t:connection/0`).\n\n- **`exec`** - Alternative mechanism to start peer nodes with, for example, ssh\n instead of the default bash.\n\n- **`detached`** - Defines whether to pass the `-detached` flag to the started\n peer. This option cannot be set to `false` using the `standard_io` alternative\n connection type. Default is `true`.\n\n- **`args`** - Extra command line arguments to append to the \"erl\" command.\n Arguments are passed as is, no escaping or quoting is needed or accepted.\n\n- **`post_process_args`** - Allows the user to change the arguments passed to\n `exec` before the peer is started. This can for example be useful when the\n `exec` program wants the arguments to \"erl\" as a single argument. Example:\n\n ```erlang\n peer:start(#{ name => peer:random_name(),\n exec => {os:find_executable(\"bash\"),[\"-c\",\"erl\"]},\n post_process_args =>\n fun([\"-c\"|Args]) -> [\"-c\", lists:flatten(lists:join($\\s, Args))] end\n }).\n ```\n\n- **`env`** - List of environment variables with their values. This list is\n applied to a locally started executable. If you need to change the environment\n of the remote peer, adjust `args` to contain `-env ENV_KEY ENV_VALUE`.\n\n- **`wait_boot`** - Specifies the start/start_link timeout. See\n [`wait_boot` datatype](`t:wait_boot/0`).\n\n- **`shutdown`** - Specifies the peer node stopping behaviour. See\n [`stop()`](`stop/1`).","title":"peer.start_options/0","ref":"peer.html#t:start_options/0"},{"type":"type","doc":"Specifies start/start_link timeout in milliseconds. Can be set to `false`,\nallowing the peer to start asynchronously. If `{Pid, Tag}` is specified instead\nof a timeout, the peer will send `Tag` to the requested process.\n\nThe default is `15_000` ms.","title":"peer.wait_boot/0","ref":"peer.html#t:wait_boot/0"},{"type":"module","doc":"This module provides functions for starting Erlang slave nodes.\n\nAll slave nodes that are started by a master terminate automatically when the\nmaster terminates. All terminal output produced at the slave is sent back to\nthe master node. File I/O is done through the master.\n\nSlave nodes on other hosts than the current one are started with the `ssh`\nprogram. The user must be allowed to `ssh` to the remote hosts without being\nprompted for a password. This can be arranged in a number of ways (for details,\nsee the `ssh` documentation). A slave node started on the same host as the\nmaster inherits certain environment values from the master, such as the current\ndirectory and the environment variables. For what can be assumed about the\nenvironment when a slave is started on another host, see the documentation for\nthe `ssh` program.\n\nAn alternative to the `ssh` program can be specified on the command line to\n[`erl(1)`](`e:erts:erl_cmd.md`) as follows:\n\n```text\n-rsh Program\n```\n\nNote that the command specified with the `-rsh` flag is treated as a file name\nwhich may contain spaces. It is thus not possible to include any command line\noptions. The remote node will be launched as\n`\"$RSH\" \"$REMOTE_HOSTNAME\" erl -detached -noinput ...`, so the `erl` command\nmust be found in the path on the remote host.\n\nThe slave node is to use the same file system at the master. At least,\nErlang/OTP is to be installed in the same place on both computers and the same\nversion of Erlang is to be used.\n\nA node running on Windows can only start slave nodes on the host on which it is\nrunning.\n\nThe master node must be alive.","title":"slave","ref":"slave.html"},{"type":"function","doc":"Calls [`pseudo(Master, ServerList)`](`pseudo/2`). If you want to start a node\nfrom the command line and set up a number of pseudo servers, an Erlang runtime\nsystem can be started as follows:\n\n```text\n% erl -name abc -s slave pseudo klacke@super x --\n```","title":"slave.pseudo/1","ref":"slave.html#pseudo/1"},{"type":"function","doc":"Starts a number of pseudo servers. A pseudo server is a server with a registered\nname that does nothing but pass on all message to the real server that executes\nat a master node. A pseudo server is an intermediary that only has the same\nregistered name as the real server.\n\nFor example, if you have started a slave node `N` and want to execute `pxw`\ngraphics code on this node, you can start server `pxw_server` as a pseudo server\nat the slave node. This is illustrated as follows:\n\n```erlang\nrpc:call(N, slave, pseudo, [node(), [pxw_server]]).\n```","title":"slave.pseudo/2","ref":"slave.html#pseudo/2"},{"type":"function","doc":"Runs a pseudo server. This function never returns any value and the process that\nexecutes the function receives messages. All messages received are simply passed\non to `Pid`.","title":"slave.relay/1","ref":"slave.html#relay/1"},{"type":"function","doc":"Equivalent to [`start(Host, Name)`](`start/2`) where `Name` is the same\nas the node that executes this call.","title":"slave.start/1","ref":"slave.html#start/1"},{"type":"function","doc":"","title":"slave.start/2","ref":"slave.html#start/2"},{"type":"function","doc":"Starts a slave node on host `Host`. Host names need not necessarily be specified\nas fully qualified names; short names can also be used. This is the same\ncondition that applies to names of distributed Erlang nodes.\n\nThe name of the started node becomes `Name@Host`.\n\nThe slave node resets its `t:io:user/0` process so that all terminal I/O that is\nproduced at the slave is automatically relayed to the master. Also, the file\nserver is relayed to the master.\n\nArgument `Args` is used to set `erl` command-line arguments. It is\npassed to the new node and can be used for a variety of purposes; see\n[`erl(1)`](`e:erts:erl_cmd.md`).\n\nAs an example, suppose that you want to start a slave node at host `H` with node\nname `Name@H` and want the slave node to have the following properties:\n\n- Directory `Dir` is to be added to the code path.\n- The Mnesia directory is to be set to `M`.\n- The Unix `DISPLAY` environment variable is to be set to the display of the\n master node.\n\nThe following code is executed to achieve this:\n\n```erlang\nE = \" -env DISPLAY \" ++ net_adm:localhost() ++ \":0 \",\nArg = \"-mnesia_dir \" ++ M ++ \" -pa \" ++ Dir ++ E,\nslave:start(H, Name, Arg).\n```\n\nThe function returns `{ok, Node}`, where `Node` is the name of the new node,\notherwise `{error, Reason}`, where `Reason` can be one of:\n\n- **`timeout`** - The master node failed to get in contact with the slave node.\n This can occur in a number of circumstances:\n\n - Erlang/OTP is not installed on the remote host.\n - The file system on the other host has a different structure to the the\n master.\n - The Erlang nodes have different cookies.\n\n- **`no_rsh`** - No remote shell program was found on the computer. Note that\n `ssh` is used by default, but this can be overridden with the `-rsh` flag.\n\n- **`{already_running, Node}`** - A node with name `Name@Host` already exists.","title":"slave.start/3","ref":"slave.html#start/3"},{"type":"function","doc":"","title":"slave.start_link/1","ref":"slave.html#start_link/1"},{"type":"function","doc":"","title":"slave.start_link/2","ref":"slave.html#start_link/2"},{"type":"function","doc":"Starts a slave node in the same way as `start/1,2,3`, except that the slave node\nis linked to the currently executing process. If that process terminates, the\nslave node also terminates.\n\nFor a description of arguments and return values, see\n[`start/1,2,3`](`start/1`).","title":"slave.start_link/3","ref":"slave.html#start_link/3"},{"type":"function","doc":"Stops (kills) a node.","title":"slave.stop/1","ref":"slave.html#stop/1"},{"type":"module","doc":"Provides access to the registry on Windows.\n\nThis module provides read and write access to the registry on Windows. It is\nessentially a port driver wrapped around the Win32 API calls for accessing the\nregistry.\n\nThe registry is a hierarchical database, used to store various system and\nsoftware information in Windows. It contains installation data, and is updated\nby installers and system programs. The Erlang installer updates the registry by\nadding data that Erlang needs.\n\nThe registry contains keys and values. Keys are like the directories in a file\nsystem, they form a hierarchy. Values are like files, they have a name and a\nvalue, and also a type.\n\nPaths to keys are left to right, with subkeys to the right and backslash between\nkeys. (Remember that backslashes must be doubled in Erlang strings.) Case is\npreserved but not significant.\n\nFor example, `\"\\\\hkey_local_machine\\\\software\\\\Ericsson\\\\Erlang\\\\5.0\"` is the\nkey for the installation data for the latest Erlang release.\n\nThere are six entry points in the Windows registry, top-level keys. They can be\nabbreviated in this module as follows:\n\n```text\nAbbreviation Registry key\n============ ============\nhkcr HKEY_CLASSES_ROOT\ncurrent_user HKEY_CURRENT_USER\nhkcu HKEY_CURRENT_USER\nlocal_machine HKEY_LOCAL_MACHINE\nhklm HKEY_LOCAL_MACHINE\nusers HKEY_USERS\nhku HKEY_USERS\ncurrent_config HKEY_CURRENT_CONFIG\nhkcc HKEY_CURRENT_CONFIG\ndyn_data HKEY_DYN_DATA\nhkdd HKEY_DYN_DATA\n```\n\nThe key above can be written as `\"\\\\hklm\\\\software\\\\ericsson\\\\erlang\\\\5.0\"`.\n\nThis module uses a current key. It works much like the current directory. From\nthe current key, values can be fetched, subkeys can be listed, and so on.\n\nUnder a key, any number of named values can be stored. They have names, types,\nand data.\n\n`win32reg` supports storing of the following types:\n\n- `REG_DWORD`, which is an integer\n- `REG_SZ`, which is a string\n- `REG_BINARY`, which is a binary\n\nOther types can be read, and are returned as binaries.\n\nThere is also a \"default\" value, which has the empty string as name. It is read\nand written with the atom `default` instead of the name.\n\nSome registry values are stored as strings with references to environment\nvariables, for example, `%SystemRoot%Windows`. `SystemRoot` is an environment\nvariable, and is to be replaced with its value. Function `expand/1` is provided\nso that environment variables surrounded by `%` can be expanded to their values.\n\nFor more information on the Windows registry, see consult the Win32 Programmer's\nReference.","title":"win32reg","ref":"win32reg.html"},{"type":"module","doc":"`erl_posix_msg`, The Windows 95 Registry (book from O'Reilly), Win32\nProgrammer's Reference (from Microsoft)","title":"See Also - win32reg","ref":"win32reg.html#module-see-also"},{"type":"function","doc":"Changes the current key to another key. Works like `cd`. The key can be\nspecified as a relative path or as an absolute path, starting with `\\.`","title":"win32reg.change_key/2","ref":"win32reg.html#change_key/2"},{"type":"function","doc":"Creates a key, or just changes to it, if it is already there. Works like a\ncombination of `mkdir` and `cd`. Calls the Win32 API function\n`RegCreateKeyEx()`.\n\nThe registry must have been opened in write mode.","title":"win32reg.change_key_create/2","ref":"win32reg.html#change_key_create/2"},{"type":"function","doc":"Closes the registry. After that, the `RegHandle` cannot be used.","title":"win32reg.close/1","ref":"win32reg.html#close/1"},{"type":"function","doc":"Returns the path to the current key. This is the equivalent of `pwd`.\n\nNotice that the current key is stored in the driver, and can be invalid (for\nexample, if the key has been removed).","title":"win32reg.current_key/1","ref":"win32reg.html#current_key/1"},{"type":"function","doc":"Deletes the current key, if it is valid. Calls the Win32 API function\n`RegDeleteKey()`. Notice that this call does not change the current key (unlike\n`change_key_create/2`). This means that after the call, the current key is\ninvalid.","title":"win32reg.delete_key/1","ref":"win32reg.html#delete_key/1"},{"type":"function","doc":"Deletes a named value on the current key. The atom `default` is used for the\ndefault value.\n\nThe registry must have been opened in write mode.","title":"win32reg.delete_value/2","ref":"win32reg.html#delete_value/2"},{"type":"function","doc":"Expands a string containing environment variables between percent characters.\nAnything between two `%` is taken for an environment variable, and is replaced\nby the value. Two consecutive `%` are replaced by one `%`.\n\nA variable name that is not in the environment results in an error.","title":"win32reg.expand/1","ref":"win32reg.html#expand/1"},{"type":"function","doc":"Converts a POSIX error code to a string (by calling `file:format_error/1`).","title":"win32reg.format_error/1","ref":"win32reg.html#format_error/1"},{"type":"function","doc":"Opens the registry for reading or writing. The current key is the root\n(`HKEY_CLASSES_ROOT`). Flag `read` in the mode list can be omitted.\n\nUse `change_key/2` with an absolute path after [`open`](`open/1`).","title":"win32reg.open/1","ref":"win32reg.html#open/1"},{"type":"function","doc":"Sets the named (or default) value to `value`. Calls the Win32 API function\n`RegSetValueEx()`. The value can be of three types, and the corresponding\nregistry type is used. The supported types are the following:\n\n- `REG_DWORD` for integers\n- `REG_SZ` for strings\n- `REG_BINARY` for binaries\n\nOther types cannot be added or changed.\n\nThe registry must have been opened in write mode.","title":"win32reg.set_value/3","ref":"win32reg.html#set_value/3"},{"type":"function","doc":"Returns a list of subkeys to the current key. Calls the Win32 API function\n`EnumRegKeysEx()`.\n\nAvoid calling this on the root keys, as it can be slow.","title":"win32reg.sub_keys/1","ref":"win32reg.html#sub_keys/1"},{"type":"function","doc":"Retrieves the named value (or default) on the current key. Registry values of\ntype `REG_SZ` are returned as strings. Type `REG_DWORD` values are returned as\nintegers. All other types are returned as binaries.","title":"win32reg.value/2","ref":"win32reg.html#value/2"},{"type":"function","doc":"Retrieves a list of all values on the current key. The values have types\ncorresponding to the registry types, see `value/2`. Calls the Win32 API function\n`EnumRegValuesEx()`.","title":"win32reg.values/1","ref":"win32reg.html#values/1"},{"type":"type","doc":"","title":"win32reg.name/0","ref":"win32reg.html#t:name/0"},{"type":"opaque","doc":"As returned by `open/1`.","title":"win32reg.reg_handle/0","ref":"win32reg.html#t:reg_handle/0"},{"type":"type","doc":"","title":"win32reg.value/0","ref":"win32reg.html#t:value/0"},{"type":"behaviour","doc":"Generic event handling behavior.\n\nThis behavior module provides event handling functionality.\nIt consists of a generic event manager process with any number of\nevent handlers that are added and deleted dynamically.\n\nAn event manager implemented using this module has a standard set of\ninterface functions and includes functionality for tracing\nand error reporting. It also fits into an OTP supervision tree.\nFor more information, see [OTP Design Principles](`e:system:events.md`).\n\nEach event handler is implemented as a callback module\nexporting a predefined set of functions. The relationship between\nthe behavior functions and the callback functions is as follows:\n\n```text\ngen_event module Callback module\n---------------- ---------------\ngen_event:start\ngen_event:start_monitor\ngen_event:start_link -----> -\n\ngen_event:add_handler\ngen_event:add_sup_handler -----> Module:init/1\n\ngen_event:notify\ngen_event:sync_notify -----> Module:handle_event/2\n\ngen_event:send_request\ngen_event:call -----> Module:handle_call/2\n\n- -----> Module:handle_info/2\n\ngen_event:delete_handler -----> Module:terminate/2\n\ngen_event:swap_handler\ngen_event:swap_sup_handler -----> Module1:terminate/2\n Module2:init/1\n\ngen_event:which_handlers -----> -\n\ngen_event:stop -----> Module:terminate/2\n\n- -----> Module:code_change/3\n```\n\nAs each event handler is one callback module, an event manager\nhas many callback modules that are added and deleted dynamically.\n`gen_event` is therefore more tolerant of callback module errors\nthan the other behaviors. If a callback function for an installed\nevent handler fails with `Reason`, or returns a bad value `Term`,\nthe event manager does not fail. It deletes the event handler\nby calling callback function [`Module:terminate/2`](`c:terminate/2`),\ngiving as argument `{error, {'EXIT', Reason}}` or `{error, Term}`,\nrespectively. No other event handler is affected.\n\nA `gen_event` process handles system messages as described in `m:sys`.\nThe `sys` module can be used for debugging an event manager.\n\nNotice that an event manager _does_ trap exit signals automatically.\n\nThe `gen_event` process can go into hibernation\n(see `erlang:hibernate/3`) if a callback function in a handler module\nspecifies `hibernate` in its return value. This can be useful\nif the server is expected to be idle for a long time.\nHowever, use this feature with care, as hibernation implies\nat least two garbage collections (when hibernating\nand shortly after waking up) and is not something you want to do\nbetween each event handled by a busy event manager.\n\nNotice that when multiple event handlers are invoked,\nit is sufficient that one single event handler returns a `hibernate`\nrequest for the whole event manager to go into hibernation.\n\nUnless otherwise stated, all functions in this module fail\nif the specified event manager does not exist\nor if bad arguments are specified.\n\n> #### Note {: .info }\n>\n> For some important information about distributed signals, see the\n> [_Blocking Signaling Over Distribution_\n> ](`e:system:ref_man_processes.md#blocking-signaling-over-distribution`)\n> section in the _Processes_ chapter of the _Erlang Reference Manual_.\n> Blocking signaling can, for example, cause call timeouts in `gen_event`\n> to be significantly delayed.","title":"gen_event","ref":"gen_event.html"},{"type":"behaviour","doc":"`m:supervisor`, `m:sys`","title":"See Also - gen_event","ref":"gen_event.html#module-see-also"},{"type":"function","doc":"Add a new event handler to an event manager.\n\nThe new event handler is added to event manager `EventMgrRef`.\nThe event manager calls [`Module:init/1`](`c:init/1`)\nto initiate the event handler and its internal state.\n\n`Handler` is the name of the callback module `Module`\nor a tuple `{Module, Id}`, where `Id` is any term.\nThe `{Module, Id}` representation makes it possible to\nidentify a specific event handler, when many event handlers\nuse the same callback module.\n\n`Args` is any term that is passed as the argument to\n[`Module:init/1`](`c:init/1`).\n\nIf [`Module:init/1`](`c:init/1`) returns a correct value\nindicating successful completion, the event manager\nadds the event handler and this function returns `ok`.\nIf [`Module:init/1`](`c:init/1`) fails with `Reason` or returns\n`{error,Reason}`, the event handler is ignored and this function\nreturns `{'EXIT',Reason}` or `{error,Reason}`, respectively.","title":"gen_event.add_handler/3","ref":"gen_event.html#add_handler/3"},{"type":"function","doc":"Add a new event handler to an event manager, supervised.\n\nThe new event handler is added as for `add_handler/3`,\nbut the event manager also supervises the connection\nby linking the event handler and the calling process.\n\n- If the calling process later terminates with `Reason`,\n the event manager deletes any supervised event handlers by calling\n [`Module:terminate/2`](`c:terminate/2`), then calls\n [`Module:handle_info/2`](`c:handle_info/2`) for each remaining handler.\n\n- If the event handler is deleted later, the event manager\n sends a message `{gen_event_EXIT,Handler,Reason}`\n to the calling process. `Reason` is one of the following:\n\n + `normal`, if the event handler has been removed because of\n a call to [`delete_handler/3`](`delete_handler/3`),\n or `remove_handler` has been returned by a callback function\n (see below).\n + `shutdown`, if the event handler has been removed\n because the event manager is terminating.\n + `{swapped, NewHandler, Pid}`, if the process `Pid` has replaced\n the event handler with another event handler `NewHandler`,\n through a call to `swap_handler/3` or `swap_sup_handler/3`.\n + Other `t:term/0`, if the event handler is removed\n because of an error. Which term depends on the error.\n\nFor a description of the arguments and return values, see `add_handler/3`.","title":"gen_event.add_sup_handler/3","ref":"gen_event.html#add_sup_handler/3"},{"type":"function","doc":"","title":"gen_event.call/3","ref":"gen_event.html#call/3"},{"type":"function","doc":"Make a synchronous call to an event handler.\n\nThe call is sent to `Handler`, installed in event manager `EventMgrRef`,\nby sending a request and waiting until a reply arrives,\nor a time-out occurs. The event manager calls\n[`Module:handle_call/2`](`c:handle_call/2`) to handle the request.\n\n`Request` is any term that is passed as one of the arguments to\n[`Module:handle_call/2`](`c:handle_call/2`).\n\n`Timeout` is an integer greater than zero that specifies\nhow many milliseconds to wait for a reply, or the atom `infinity`\nto wait indefinitely. Defaults to 5000. If no reply is received\nwithin the specified time, the function call fails.\n\nThe return value `Reply` is defined in the return value of\n[`Module:handle_call/2`](`c:handle_call/2`). If the specified\nevent handler is not installed, the function returns\n`{error, bad_module}`. If the callback function fails with `Reason`,\nor returns an unexpected value `Term`, this function returns\n`{error, {'EXIT', Reason}}` or `{error, Term}`, respectively.\n\nWhen this call fails it [exits](`erlang:exit/1`) the calling process.\nThe exit term is on the form `{Reason, Location}` where\n`Location = {gen_event, call, ArgList}`. See `gen_server:call/3`\nthat has a description of relevant values for the `Reason`\nin the exit term.","title":"gen_event.call/4","ref":"gen_event.html#call/4"},{"type":"function","doc":"Check if a received message is a request response.\n\nCheck if `Msg` is a response corresponding to\nthe request identifier `ReqId`. The request must have been made\nby `send_request/3`, and by the same process calling this function.\n\nIf `Msg` is a response corresponding to `ReqId` the response is returned\nin `Reply`. Otherwise this function returns `no_reply`\nand no cleanup is done. Thus this function must be invoked repeatedly\nuntil a response is returned.\n\nIf the specified event handler is not installed, the function returns\n`{error, bad_module}`. If the callback function fails with `Reason`\nor returns an unexpected value `Term`, this function returns\n`{error, {'EXIT', Reason}}` or `{error, Term}`, respectively.\nIf the event manager has died before this function is called,\nthat is; `Msg` reports the server's death, this function returns\n`{error,{Reason, EventMgrRef}}` where `Reason` is the exit reason.","title":"gen_event.check_response/2","ref":"gen_event.html#check_response/2"},{"type":"function","doc":"Check if a received message is a request response in a collection.\n\nCheck if `Msg` is a response corresponding to a request identifier\nstored in `ReqIdCollection`. All request identifiers of `ReqIdCollection`\nmust correspond to requests that have been made using `send_request/3`\nor `send_request/5`, and all requests must have been made\nby the process calling this function.\n\nThe `Label` in the response is the `Label` associated with\nthe request identifier that the response corresponds to.\nThe `Label` of a request identifier is associated\nwhen [storing the request id](`reqids_add/3`) in a collection,\nor when sending the request using `send_request/5`.\n\nCompared to `check_response/2`, the returned result or exception\nassociated with a specific request identifier will be wrapped\nin a 3-tuple `{Response, Label, NewReqIdCollection}`.\n`Response` is the value that would have been produced\nby `check_response/2`, `Label` is the value associated with\nthe specific [request identifier](`t:request_id/0`)\nand `NewReqIdCollection` is a possibly modified\nrequest identifier collection.\n\nIf `ReqIdCollection` is empty, `no_request` will be returned.\n\nIf `Msg` does not correspond to any of the request identifiers\nin `ReqIdCollection`, `no_reply` is returned.\n\nIf `Delete` is `true`, the association with `Label` has been deleted\nfrom `ReqIdCollection` in the resulting `NewReqIdCollection`.\nIf `Delete` is `false`, `NewReqIdCollection` will equal `ReqIdCollection`.\nNote that deleting an association is not for free and that\na collection containing already handled requests\ncan still be used by subsequent calls to `check_response/3`),\n`receive_response/3`, and `wait_response/3`.\n\nHowever, without deleting handled associations, the above calls\nwill not be able to detect when there are no more outstanding requests\nto handle, so you will have to keep track of this some other way\nthan relying on a `no_request` return. Note that if you pass\na collection only containing associations of already handled\nor abandoned requests to `check_response/3`,\nit will always return `no_reply`.","title":"gen_event.check_response/3","ref":"gen_event.html#check_response/3"},{"type":"callback","doc":"Update the event handler state after code change.\n\nThis function is called for an installed event handler\nthat is to update its internal state during a release upgrade/downgrade,\nthat is, when the instruction `{update, Module, Change,...}`,\nis specified in the [`appup`](`e:sasl:appup.md`) file.\n\nFor more information, see [OTP Design Principles](`e:system:index.html`).\n\nFor an upgrade, `OldVsn` is `Vsn`, and for a downgrade,\n`OldVsn` is `{down, Vsn}`. `Vsn` is defined by the `vsn` attribute(s)\nof the old version of the callback module `Module`. If no such attribute\nis defined, the version is the checksum of the Beam file.\n\n`State` is the internal state of the event handler.\n\n`Extra` is passed \"as is\" from the `{advanced, Extra}` part\nof the update instruction.\n\nThe function is to return the updated internal state.\n\n> #### Note {: .info }\n>\n> If a release upgrade/downgrade with `Change={advanced, Extra}`\n> specified in the [`.appup`](`e:sasl:appup.md`) file is made\n> when `c:code_change/3` is not implemented the event handler will crash\n> with an `undef` error reason.","title":"gen_event.code_change/3","ref":"gen_event.html#c:code_change/3"},{"type":"function","doc":"Deletes an event handler from an event manager.\n\nThis function deletes event handler `Handler` from event manager\n`EventMgrRef`. The event manager calls\n[`Module:terminate/2`](`c:terminate/2`) to terminate the event handler.\n\n`Args` is any term that is passed as one of the arguments to\n[`Module:terminate/2`](`c:terminate/2`).\n\nThe return value is the return value of\n[`Module:terminate/2`](`c:terminate/2`). If the specified\nevent handler is not installed, the function returns\n`{error, module_not_found}`. If the callback function fails\nwith `Reason`, the function returns `{'EXIT', Reason}`.","title":"gen_event.delete_handler/3","ref":"gen_event.html#delete_handler/3"},{"type":"callback","doc":"Format/limit the status value.\n\nThis function is called by a `gen_event` process in in order to\nformat/limit the server state for debugging and logging purposes.\n\nIt is called in the following situations:\n\n- One of [`sys:get_status/1,2`](`sys:get_status/1`) is invoked\n to get the `gen_event` status.\n\n- The event handler terminates abnormally and `gen_event` logs an error.\n\nThis callback is used to limit the status of the event handler returned by\n[`sys:get_status/1,2`](`sys:get_status/1`) or sent to `m:logger`.\n\nThe callback gets a map `Status` describing the current status\nand shall return a map `NewStatus` with the same keys,\nbut it may transform some values.\n\nTwo possible use cases for this callback is to remove\nsensitive information from the state to prevent it from being printed\nin log files, or to compact large irrelevant status items\nthat would only clutter the logs.\n\n_Example_:\n\n```erlang\nformat_status(Status) ->\n maps:map(\n fun(state,State) ->\n maps:remove(private_key, State);\n (message,{password, _Pass}) ->\n {password, removed};\n (_,Value) ->\n Value\n end, Status).\n```\n\n> #### Note {: .info }\n>\n> This callback is optional, so event handler modules need not export it.\n> If a handler does not export this function, the `gen_event` module\n> uses the handler state directly for the purposes described below.\n>\n> If this callback is exported but fails, to hide possibly sensitive data,\n> the default function will instead return the fact that\n> [`format_status/1`](`c:format_status/1`) has crashed.","title":"gen_event.format_status/1","ref":"gen_event.html#c:format_status/1"},{"type":"callback","doc":"Format/limit the status value.\n\nThis function is called by a `gen_event` process in in order to\nformat/limit the server state for debugging and logging purposes.\n\nIt is called in the following situations:\n\n- One of [`sys:get_status/1,2`](`sys:get_status/1`) is invoked\n to get the `gen_event` status. `Opt` is set to the atom `normal`\n for this case.\n\n- The event handler terminates abnormally and `gen_event` logs an error.\n `Opt` is set to the atom `terminate` for this case.\n\nThis function is useful for changing the form and appearance of the event\nhandler state for these cases. An event handler callback module\nwishing to change the `sys:get_status/1,2` return value as well as\nhow its state appears in termination error logs, exports an instance of\n[`format_status/2`](`c:format_status/2`) that returns a term\ndescribing the current state of the event handler.\n\n`PDict` is the current value of the process dictionary of `gen_event`.\n\n`State` is the internal state of the event handler.\n\nThe function is to return `Status`, a term that change the details of\nthe current state of the event handler. Any term is allowed for `Status`.\nThe `gen_event` module uses `Status` as follows:\n\n- When `sys:get_status/1,2` is called, `gen_event` ensures that\n its return value contains `Status` in place of the state term\n of the event handler.\n\n- When an event handler terminates abnormally, `gen_event` logs `Status`\n in place of the state term of the event handler.\n\nOne use for this function is to return compact alternative\nstate representations to avoid that large state terms\nare printed in log files.\n\n> #### Note {: .info }\n>\n> This callback is optional, so event handler modules need not export it.\n> If a handler does not export this function, the `gen_event` module\n> uses the handler state directly for the purposes described below.","title":"gen_event.format_status/2","ref":"gen_event.html#c:format_status/2"},{"type":"callback","doc":"Handle a call.\n\nWhenever an event manager receives a request sent using\n[`call/3,4`](`call/3`), this function is called\nfor the specified event handler to handle the request.\n\n`Request` is the `Request` argument of `call/3,4`.\n\n`State` is the internal state of the event handler.\n\nThe return values are the same as for\n[`Module:handle_event/2`](`c:handle_event/2`) except that\nthey also contain a term `Reply`, which is the reply to the client\nas the return value of `call/3,4`.","title":"gen_event.handle_call/2","ref":"gen_event.html#c:handle_call/2"},{"type":"callback","doc":"Handle an event.\n\nWhenever an event manager receives an event sent using `notify/2` or\n`sync_notify/2`, this function is called for each installed event handler\nto handle the event.\n\n`Event` is the `Event` argument of `notify/2` / `sync_notify/2`.\n\n`State` is the internal state of the event handler.\n\n- If `{ok, NewState}` or `{ok, NewState, hibernate}` is returned,\n the event handler remains in the event manager with the possibly\n updated internal state `NewState`.\n\n- If `{ok, NewState, hibernate}` is returned, the event manager\n also goes into hibernation (by calling `proc_lib:hibernate/3`),\n waiting for the next event to occur. It is sufficient\n that one of the event handlers return `{ok, NewState, hibernate}`\n for the whole event manager process to hibernate.\n\n- If `{swap_handler, Args1, NewState, Handler2, Args2}` is returned,\n the event handler is replaced by `Handler2` by first calling\n [`Module:terminate(Args1, NewState)`](`c:terminate/2`) and then\n [`Module2:init({Args2, Term})`](`c:init/1`), where `Term`\n is the return value of [`Module:terminate/2`](`c:terminate/2`).\n For more information, see `swap_handler/3`.\n\n- If `remove_handler` is returned, the event handler is deleted by calling\n [`Module:terminate(remove_handler, State)`](`c:terminate/2`).","title":"gen_event.handle_event/2","ref":"gen_event.html#c:handle_event/2"},{"type":"callback","doc":"Handle an info message (regular process message).\n\nThis function is called for each installed event handler when\nan event manager receives any other message than an event\nor a synchronous request (or a system message).\n\n`Info` is the received message.\n\nIn particular, this callback will be made when a process terminated\nafter calling `add_sup_handler/3`. Any event handler attached to\nan event manager which in turn has a supervised handler\nshould expect callbacks of the shape\n[`Module:handle_info({'EXIT', Pid, Reason}, State)`](`c:handle_info/2`).\n\nFor a description of `State` and possible return values,\nsee [`Module:handle_event/2`](`c:handle_event/2`).\n\n> #### Note {: .info }\n>\n> This callback is optional, so callback modules need not export it.\n> The `gen_event` module provides a default implementation\n> of this function that logs about the unexpected `Info` message,\n> drops it and returns `{ok, State}`.","title":"gen_event.handle_info/2","ref":"gen_event.html#c:handle_info/2"},{"type":"callback","doc":"Initialize the event handler.\n\nWhenever a new event handler is added to an event manager,\nthis function is called to initialize the event handler.\n\nIf the event handler is added because of a call to `add_handler/3` or\n`add_sup_handler/3`, `InitArgs` is the `Args` argument of these functions.\n\nIf the event handler replaces another event handler because of\na call to `swap_handler/3` or `swap_sup_handler/3`, or because of\na `swap` return tuple from one of the other callback functions,\n`InitArgs` is a tuple `{Args, Term}`, where `Args` is the argument\nprovided in the function call/return tuple and `Term` is the result\nof terminating the old event handler, see `swap_handler/3`.\n\nIf successful, the function returns `{ok, State}` or\n`{ok, State, hibernate}`, where `State` is the initial internal state\nof the event handler.\n\nIf `{ok, State, hibernate}` is returned, the event manager\ngoes into hibernation (by calling `proc_lib:hibernate/3`),\nwaiting for the next event to occur.","title":"gen_event.init/1","ref":"gen_event.html#c:init/1"},{"type":"function","doc":"Send an asynchronous event notification to an event manager.\n\nThe event is sent to `EventMgrRef`, that calls\n[`Module:handle_event/2`](`c:handle_event/2`) for each installed\nevent handler to handle the event.\n\n`Event` is any term that is passed as one of the arguments to\n[`Module:handle_event/2`](`c:handle_event/2`).\n\n`notify/1` does not fail even if the specified event manager\ndoes not exist, unless it is specified as `Name`.","title":"gen_event.notify/2","ref":"gen_event.html#notify/2"},{"type":"function","doc":"Receive a request response.\n\nReceive a response corresponding to the request identifier `ReqId`.\nThe request must have been made by `send_request/3`,\nand it must have been made from the same process calling this function.\n\n`Timeout` specifies how long to wait for a response.\nIf no response is received within the specified time,\nthis function returns `timeout`. Assuming that the\nserver executes on a node supporting aliases (introduced in OTP 24)\nthe request will also be abandoned. That is,\nno response will be received after a timeout.\nOtherwise, a stray response might be received at a later time.\n\nThe return value `Reply` is defined in the return value of\n[`Module:handle_call/2`](`c:handle_call/2`).\n\nIf the specified event handler is not installed, this function returns\n`{error, bad_module}`. If the callback function fails\nwith `Reason` or returns an unexpected value `Term`,\nthis function returns `{error, {'EXIT', Reason}}` or`{error,Term}`,\nrespectively. If the event manager dies before or during the\nrequest this function returns `{error, {Reason, EventMgrRef}}`.\n\nThe difference between `wait_response/2` and `receive_response/2`\nis that `receive_response/2` abandons the request at time-out\nso that a potential future response is ignored,\nwhile [`wait_response/2`](`wait_response/2`) does not.","title":"gen_event.receive_response/2","ref":"gen_event.html#receive_response/2"},{"type":"function","doc":"Receive a request response in a collection.\n\nReceive a response in `ReqIdCollection`. All request identifiers\nof `ReqIdCollection` must correspond to requests that have been\nmade using `send_request/3` or `send_request/5`, and all requests\nmust have been made by the process calling this function.\n\nThe `Label` in the response is the `Label` associated with\nthe request identifier that the response corresponds to.\nThe `Label` of a request identifier is associated\nwhen [adding the request id](`reqids_add/3`) to a collection,\nor when sending the request using `send_request/5`.\n\nCompared to `receive_response/2`, the returned result or exception\nassociated with a specific request identifier will be wrapped\nin a 3-tuple `{Response, Label, NewReqIdCollection}`.\n`Response` is the value that would have been produced\nby `receive_response/2`, `Label` is the value associated with\nthe specific [request identifier](`t:request_id/0`)\nand `NewReqIdCollection` is a possibly modified\nrequest identifier collection.\n\nIf `ReqIdCollection` is empty, `no_request` will be returned.\n\n`Timeout` specifies how long to wait for a response. If no response\nis received within the specified time, the function returns `timeout`.\nAssuming that the server executes on a node supporting aliases\n(introduced in OTP 24) all requests identified by `ReqIdCollection`\nwill also be abandoned. That is, no responses will be received\nafter a time-out. Otherwise, stray responses might be received\nat a later time.\n\nThe difference between `receive_response/3` and `wait_response/3`\nis that `receive_response/3` abandons the requests at time-out\nso that potential future responses are ignored,\nwhile `wait_response/3` does not.\n\nIf `Delete` is `true`, the association with `Label`\nis deleted from `ReqIdCollection` in the resulting\n`NewReqIdCollection`. If `Delete` is `false`, `NewReqIdCollection`\nwill equal `ReqIdCollection`. Note that deleting an association\nis not for free and that a collection containing already handled\nrequests can still be used by subsequent calls to\n`receive_response/3`, `check_response/3`, and `wait_response/3`.\n\nHowever, without deleting handled associations,\nthe above calls will not be able to detect when there are\nno more outstanding requests to handle, so you will have to keep track\nof this some other way than relying on a `no_request` return.\nNote that if you pass a collection only containing\nassociations of already handled or abandoned requests to\n`receive_response/3`, it will always block until `Timeout` expires\nand then return `timeout`.","title":"gen_event.receive_response/3","ref":"gen_event.html#receive_response/3"},{"type":"function","doc":"Store a request identifier in a colletion.\n\nStores `ReqId` and associates a `Label` with the request identifier\nby adding this information to `ReqIdCollection` and returning\nthe resulting request identifier collection.","title":"gen_event.reqids_add/3","ref":"gen_event.html#reqids_add/3"},{"type":"function","doc":"Create an empty request identifier collection.\n\nReturns a new empty request identifier collection.\nA request identifier collection can be utilized to handle\nmultiple outstanding requests.\n\nRequest identifiers of requests made by `send_request/3`\ncan be saved in a request identifier collection using `reqids_add/3`.\nSuch a collection of request identifiers can later be used\nin order to get one response corresponding to a request\nin the collection by passing the collection as argument to\n`receive_response/3`, `wait_response/3`, or, `check_response/3`.\n\n`reqids_size/1` can be used to determine the number of\nrequest identifiers in a collection.","title":"gen_event.reqids_new/0","ref":"gen_event.html#reqids_new/0"},{"type":"function","doc":"Returns the number of request identifiers in `ReqIdCollection`.","title":"gen_event.reqids_size/1","ref":"gen_event.html#reqids_size/1"},{"type":"function","doc":"Convert a request identifier collection to a list.\n\nReturns a list of `{ReqId, Label}` tuples which corresponds to\nall request identifiers with their associated labels\nin [`ReqIdCollection`](`t:request_id_collection/0`).","title":"gen_event.reqids_to_list/1","ref":"gen_event.html#reqids_to_list/1"},{"type":"function","doc":"Send an asynchronous `call` request to an event handler.\n\nThis function sends the call request `Request` to the event handler\n`Handler` installed in the event manager identified by `EventMgrRef`,\nand returns a request identifier `ReqId`. The return value `ReqId`\nshall later be used with `receive_response/2`, `wait_response/2`,\nor `check_response/2` to fetch the actual result of the request.\n\nBesides passing the request identifier directly to these functions,\nit can also be stored in a request identifier collection\nusing `reqids_add/3`. Such a collection of request identifiers\ncan later be used in order to get one response corresponding to\na request in the collection by passing the collection as argument to\n`receive_response/3`, `wait_response/3`, or `check_response/3`.\nIf you are about to store the request identifier in a collection,\nyou may want to consider using `send_request/5` instead.\n\nThe calls\n`gen_event:receive_response(gen_event:send_request(EventMgrRef,\nHandler, Request), Timeout)`\ncan be seen as equivalent to\n[`gen_event:call(EventMgrRef, Handler, Request, Timeout)`](`call/3`),\nignoring the error handling.\n\nThe event manager calls [`Module:handle_call/2`](`c:handle_call/2`)\nto handle the request.\n\n`Request` may be any term and is passed as one of the arguments to\n[`Module:handle_call/2`](`c:handle_call/2`).","title":"gen_event.send_request/3","ref":"gen_event.html#send_request/3"},{"type":"function","doc":"Send an asynchronous `call` request to an event handler,\nstoring it in a request identifier collection.\n\nThis function sends the call request `Request` to the event handler\n`Handler` installed in the event manager identified by `EventMgrRef`.\nThe `Label` will be associated with the request identifier\nof the operation and added to the returned\nrequest identifier collection `NewReqIdCollection`.\n\nThe collection can later be used in order to get one response\ncorresponding to a request in the collection by passing the collection\nas argument to `receive_response/3`, `wait_response/3`,\nor `check_response/3`.\n\nThe same as calling\n[`gen_event:reqids_add`](`reqids_add/3`)`(`[`gen_event:send_request`](`send_request/3`)`(EventMgrRef, Handler, Request), Label, ReqIdCollection)`,\nbut slightly more efficient.","title":"gen_event.send_request/5","ref":"gen_event.html#send_request/5"},{"type":"function","doc":"","title":"gen_event.start/0","ref":"gen_event.html#start/0"},{"type":"function","doc":"Create a stand-alone event manager process, possibly nameless.\n\nEquivalent to [`start(EventMgrName, Options)`](`start/2`).\n\nWith argument `EventMgrName`, `Options` is `[]`.\n\nWith argument `Options` a nameless event manager is created.\n\nFor a description of the arguments and return values, see `start_link/2`.","title":"gen_event.start/1","ref":"gen_event.html#start/1"},{"type":"function","doc":"Create a stand-alone event manager process.\n\nThe created event manager process is not part of a supervision tree\nand thus has no supervisor.\n\nFor a description of the arguments and return values, see `start_link/2`.","title":"gen_event.start/2","ref":"gen_event.html#start/2"},{"type":"function","doc":"","title":"gen_event.start_link/0","ref":"gen_event.html#start_link/0"},{"type":"function","doc":"Create an event manager process as part of a supervision tree,\npossibly nameless.\n\nEquivalent to [`start_link(EventMgrName, Options)`](`start_link/2`).\n\nWith argument `EventMgrName`, `Options` is `[]`.\n\nWith argument `Options` a nameless event manager is created.\n\nFor a description of the arguments and return values, see `start_link/2`.","title":"gen_event.start_link/1","ref":"gen_event.html#start_link/1"},{"type":"function","doc":"Create an event manager process as part of a supervision tree.\n\nThe function is to be called, directly or indirectly, by the supervisor.\nFor example, it ensures that the event manager is linked\nto the caller (supervisor).\n\n- If option `{hibernate_after, HibernateAfterTimeout}` is present, the\n `gen_event` process awaits any message for `HibernateAfterTimeout`\n milliseconds and if no message is received, the process\n goes into hibernation automatically (by calling `proc_lib:hibernate/3`).\n\nIf the event manager is successfully created,\nthe function returns `{ok, Pid}` where `Pid` is the `t:pid/0`\nof the event manager.\n\nIf a process with the specified `EventMgrName` exists already,\nthe function returns `{error,{already_started,OtherPid}}`,\nwhere `OtherPid` is the pid of that process, and the event manager process\nexits with reason `normal`.\n\nIf the event manager fails to start within the specified start timeout\n`{timeout, Time}`, which is very unlikely since the start\ndoes not interact with other processes, the function returns\n`{error, timeout}` and the failed event manager is killed with\n[`exit(_, kill)`](`erlang:exit/2`).\n\nIf `start_link/1,2` returns `{error, _}`, the started event manager process\nhas terminated. If an `'EXIT'` message was delivered\nto the calling process (due to the process link), that message\nhas been consumed.\n\n> #### Warning {: .warning }\n>\n> Before OTP 26.0, if the started event manager failed to register\n> its name, this founction could return\n> `{error, {already_started, OtherPid}}` _before_\n> the started event manager process had terminated,\n> so starting again might fail because the registered name\n> was not yet unregistered, and an `'EXIT'` message could arrive later\n> to the process calling this function.\n>\n> But if the start timed out, this function killed\n> the started event manager process and returned `{error, timeout}`,\n> and then the process link `{'EXIT', Pid, killed}` message _was_ consumed.\n>\n> The start was made synchronous in OTP 26.0 and a guarantee\n> was implemented that no process link `'EXIT'` message\n> from a failed start will linger in the caller's inbox.","title":"gen_event.start_link/2","ref":"gen_event.html#start_link/2"},{"type":"function","doc":"","title":"gen_event.start_monitor/0","ref":"gen_event.html#start_monitor/0"},{"type":"function","doc":"Creates a stand-alone event manager process,\nmonitored, possibly nameless.\n\nEquivalent to [`start_monitor(EventMgrName, Options)`](`start_monitor/2`).\n\nWith argument `EventMgrName`, `Options` is `[]`.\n\nWith argument `Options` a nameless event manager is created.\n\nFor a description of the arguments and return values,\nsee `start_monitor/2` and `start_link/1`.","title":"gen_event.start_monitor/1","ref":"gen_event.html#start_monitor/1"},{"type":"function","doc":"Creates a stand-alone event manager process, monitored.\n\nThe created event manager process is not part of a supervision tree\nand thus has no supervisor. A monitor is atomically set up\nto the newly created process.\n\nFor a description of the arguments and return values, see\n[`start_link/2`](`start_link/2`). Note that the return value\nfor a successful start differs from `start_link/2`.\n`start_monitor/0,1,2` will return `{ok, {Pid, Mon}}`\nwhere `Pid` is the process identifier of the process,\nand `Mon` is a reference to the monitor set up to monitor the process.\nIf the start is not successful, the caller will be blocked\nuntil the `DOWN` message has been received and removed\nfrom the message queue.","title":"gen_event.start_monitor/2","ref":"gen_event.html#start_monitor/2"},{"type":"function","doc":"","title":"gen_event.stop/1","ref":"gen_event.html#stop/1"},{"type":"function","doc":"Stop an event manager.\n\nOrders event manager `EventMgrRef` to exit with the specifies `Reason`,\nand waits for it to terminate. Before terminating, `gen_event` calls\n[`Module:terminate(stop,...)`](`c:terminate/2`)\nfor each installed event handler.\n\nThe function returns `ok` if the event manager terminates\nwith the expected reason. Any other reason than `normal`,\n`shutdown`, or `{shutdown, Term}` causes an error report\nto be issued using `m:logger`.\n\n`Timeout` is an integer greater than zero that specifies\nhow many milliseconds to wait for the event manager to terminate,\nor the atom `infinity` to wait indefinitely. If the event manager\nhas not terminated within the specified time, the call exits\nthe calling process with reason `timeout`.\n\nIf the process does not exist,\nthe call exits the calling process with reason `noproc`,\nand with reason `{nodedown, Node}` if the connection fails\nto the remote `Node` where the server runs.","title":"gen_event.stop/3","ref":"gen_event.html#stop/3"},{"type":"function","doc":"Replace an event handler.\n\nThis function replaces an event handler in event manager `EventMgrRef`.\n\nFor a description of `OldHandler` and `NewHandler`, see `add_handler/3`.\n\nFirst the old event handler `OldHandler` is deleted. The event manager\ncalls `OldModule:terminate(Args1, ...)`, where `OldModule`\nis the callback module of `OldHandler`, and collects the return value.\n\nThen the new event handler `NewHandler` is added and initiated\nby calling [`NewModule:init({Args2,Term})`](`c:init/1`), where `NewModule`\nis the callback module of `NewHandler`, and `Term` is the return value\nof [`OldModule:terminate/2`](`c:terminate/2`). This makes it possible\nto transfer information from `OldHandler` to `NewHandler`.\n\nThe new handler is added even if the the specified old event handler\nis not installed, in which case `Term = error`, or if\n[`OldModule:terminate/2`](`c:terminate/2`) fails with `Reason`,\nin which case `Term = {'EXIT', Reason}`. The old handler\nis deleted even if [`NewModule:init/1`](`c:init/1`) fails.\n\nIf there was a supervised connection\nbetween `OldHandler` and a process `Pid`,\nthere is a supervised connection between `NewHandler` and `Pid` instead.\n\nIf [`NewModule:init/1`](`c:init/1`) returns a correct value,\nthis function returns `ok`. If [`NewModule:init/1`](`c:init/1`) fails\nwith `Reason` or returns an unexpected value `Term`,\nthis function returns `{error, {'EXIT', Reason}}` or\n`{error, Term}`, respectively.","title":"gen_event.swap_handler/3","ref":"gen_event.html#swap_handler/3"},{"type":"function","doc":"Replace an event handler, and supervise it.\n\nReplaces an event handler in event manager `EventMgrRef`\nin the same way as [`swap_handler/3`](`swap_handler/3`),\nbut also supervises the connection between `NewHandler`\nand the calling process.\n\nFor a description of the arguments and return values, see `swap_handler/3`.","title":"gen_event.swap_sup_handler/3","ref":"gen_event.html#swap_sup_handler/3"},{"type":"function","doc":"Send a synchronous event notification to an event manager.\n\nThe event is sent to `EventMgrRef` that callsr calls\n[`Module:handle_event/2`](`c:handle_event/2`) for each installed\nevent handler to handle the event. This function will return `ok`\nafter the event has been handled by all event handlers.\n\n`Event` is any term that is passed as one of the arguments to\n[`Module:handle_event/2`](`c:handle_event/2`).","title":"gen_event.sync_notify/2","ref":"gen_event.html#sync_notify/2"},{"type":"callback","doc":"Handle event handler termination.\n\nWhenever an event handler is deleted from an event manager,\nthis function is called. It is to be the opposite\nof [`Module:init/1`](`c:init/1`) and do any necessary cleaning up.\n\nIf the event handler is deleted because of a call to `delete_handler/3`,\n`swap_handler/3`, or `swap_sup_handler/3`, `Arg` is\nthe `Args` argument of this function call.\n\n`Arg = {stop, Reason}` if the event handler has a supervised connection\nto a process that has terminated with reason `Reason`.\n\n`Arg = stop` if the event handler is deleted because\nthe event manager is terminating.\n\nThe event manager terminates if it is part of a supervision tree\nand it is ordered by its supervisor to terminate. Even if\nit is _not_ part of a supervision tree, it terminates if it receives\nan `'EXIT'` message from its parent.\n\n`Arg = remove_handler` if the event handler is deleted\nbecause another callback function has returned `remove_handler`\nor `{remove_handler, Reply}`.\n\n`Arg = {error, Term}` if the event handler is deleted because\na callback function returned an unexpected value `Term`,\nor `Arg = {error, {'EXIT', Reason}}` if a callback function failed.\n\n`State` is the internal state of the event handler.\n\nThe function can return any term. If the event handler\nis deleted because of a call to `gen_event:delete_handler/3`,\nthe return value of that function becomes the return value\nof this function. If the event handler is to be replaced with\nanother event handler because of a swap, the return value\nis passed to the `init` function of the new event handler.\nOtherwise the return value is ignored.\n\n> #### Note {: .info }\n>\n> This callback is optional, so callback modules need not export it.\n> The `gen_event` module provides a default implementation\n> without cleanup.","title":"gen_event.terminate/2","ref":"gen_event.html#c:terminate/2"},{"type":"function","doc":"Wait for a request resonse.\n\nWait for the response to the request identifier `ReqId`. The request\nmust have been made by `send_request/3`, from the same process\nthat called `send_request/3`.\n\n`WaitTime` specifies how long to wait for a response.\nIf no response is received within the specified time,\nthe function returns `timeout` and no cleanup is done,\nThus the function can be invoked repeatedly until a reply is returned.\n\nThe return value `Reply` is defined in the return value of\n[`Module:handle_call/2`](`c:handle_call/2`).\n\nIf the specified event handler is not installed, the function returns\n`{error, bad_module}`. If the callback function fails with `Reason`,\nor returns an unexpected value `Term`, this function returns\n`{error,{'EXIT',Reason}}` or `{error,Term}`, respectively.\nIf the event manager dies before or during the request\nthis function returns `{error, {Reason, EventMgrRef}}`.\n\nThe difference between `receive_response/2` and\n`wait_response/2` is that `receive_response/2` abandons the request\nat timeout so that a potential future response is ignored,\nwhile [`wait_response/2`](`wait_response/2`) does not.","title":"gen_event.wait_response/2","ref":"gen_event.html#wait_response/2"},{"type":"function","doc":"Wait for any request response in a collection.\n\nWait for a response in a `ReqIdCollection`. All request identifiers\nof `ReqIdCollection` must correspond to requests that have been made\nusing `send_request/3` or `send_request/5`, and all requests\nmust have been made by the process calling this function.\n\nThe `Label` in the response is the `Label` associated with\nthe request identifier that the response corresponds to.\nThe `Label` of a request identifier is associated\nwhen [adding the request id](`reqids_add/3`) to a collection,\nor when sending the request using `send_request/5`.\n\nCompared to `wait_response/2`, the returned result or exception\nassociated with a specific request identifier will be wrapped\nin a 3-tuple `{Response, Label, NewReqIdCollection}`.\n`Response` is the value that would have been produced\nby `wait_response/2`, `Label` is the value associated with\nthe specific [request identifier](`t:request_id/0`)\nand `NewReqIdCollection` is a possibly modified\nrequest identifier collection.\n\nIf `ReqIdCollection` is empty, `no_request` will be returned.\n\nIf no response is received before the `WaitTime` has expired,\n`timeout` is returned. It is valid to continue waiting\nfor a response as many times as needed up until a response\nhas been received and completed by `check_response()`,\n`receive_response()`, or `wait_response()`.\n\nThe difference between `receive_response/3` and `wait_response/3`\nis that `receive_response/3` abandons requests at time-out\nso that potential future responses are ignored, while\n[`wait_response/3`](`wait_response/3`) does not.\n\nIf `Delete` is `true`, the association with `Label`\nhas been deleted from `ReqIdCollection` in the resulting\n`NewReqIdCollection`. If `Delete` is`false`, `NewReqIdCollection`\nwill equal `ReqIdCollection`. Note that deleting an association\nis not for free and that a collection containing already handled\nrequests can still be used by subsequent calls to\n`wait_response/3`, `check_response/3`, and `receive_response/3`.\n\nHowever, without deleting handled associations, the above\ncalls will not be able to detect when there are\nno more outstanding requests to handle, so you will have to keep track\nof this some other way than relying on a `no_request` return.\nNote that if you pass a collection only containing\nassociations of already handled or abandoned requests\nto this function, it will always block until `WaitTime` expires\nand then return `timeout`.","title":"gen_event.wait_response/3","ref":"gen_event.html#wait_response/3"},{"type":"function","doc":"Return all event handlers in an event manager.\n\nThis function returns a list of all event handlers\ninstalled in event manager `EventMgrRef`.\n\nFor a description of `Handler`, see `add_handler/3`.","title":"gen_event.which_handlers/1","ref":"gen_event.html#which_handlers/1"},{"type":"type","doc":"","title":"gen_event.add_handler_ret/0","ref":"gen_event.html#t:add_handler_ret/0"},{"type":"type","doc":"","title":"gen_event.debug_flag/0","ref":"gen_event.html#t:debug_flag/0"},{"type":"type","doc":"","title":"gen_event.del_handler_ret/0","ref":"gen_event.html#t:del_handler_ret/0"},{"type":"type","doc":"Event manager name specification: `local`, `global`, or `via` registered.\n\n- *`{local, Name}`* - the event manager is registered locally as\n `Name` using [`register/2`](`register/2`).\n- *`{global, GlobalName}`* - The event manager is registered\n globally as `GlobalName` using `global:register_name/2`.\n If no name is provided, the event manager is not registered.\n- *`{via, Module, ViaName}`*, the event manager registers with the\n registry represented by `Module`. The `Module` callback is to export\n the functions `register_name/2`, `unregister_name/1`, `whereis_name/1`,\n and `send/2`, which are to behave as the corresponding functions\n in `m:global`. Thus, `{via, global, GlobalName}` is a valid reference.","title":"gen_event.emgr_name/0","ref":"gen_event.html#t:emgr_name/0"},{"type":"type","doc":"A reference used to locate an event manager.\n\nThe reference can be any of the following:\n\n- The pid of the event manager\n- `Name`, if the event manager is locally registered\n- `{Name, Node}`, if the event manager is locally registered\n at another node\n- `{global, GlobalName}`, if the event manager is globally registered\n- `{via, Module, ViaName}`, if the event manager is registered through\n an alternative process registry","title":"gen_event.emgr_ref/0","ref":"gen_event.html#t:emgr_ref/0"},{"type":"type","doc":"A map that describes the `gen_event` process status.\n\nThe keys are:\n- **`state`** - The internal state of the event handler.\n- **`message`** - The message that caused the event handler to terminate.\n- **`reason`** - The reason that caused the event handler to terminate.\n- **`log`** - The [sys log](`sys:log/2`) of the server.\n\nNew associations may be added into the status map without prior notice.","title":"gen_event.format_status/0","ref":"gen_event.html#t:format_status/0"},{"type":"type","doc":"","title":"gen_event.handler/0","ref":"gen_event.html#t:handler/0"},{"type":"type","doc":"","title":"gen_event.handler_args/0","ref":"gen_event.html#t:handler_args/0"},{"type":"type","doc":"Options that can be used to configure an event handler\nwhen it is started.","title":"gen_event.options/0","ref":"gen_event.html#t:options/0"},{"type":"opaque","doc":"An opaque request identifier. See `send_request/3` for details.","title":"gen_event.request_id/0","ref":"gen_event.html#t:request_id/0"},{"type":"opaque","doc":"An opaque collection of request identifiers (`t:request_id/0`).\n\nEach request identifier can be associated with a label\nchosen by the user. For more information see `reqids_new/0`.","title":"gen_event.request_id_collection/0","ref":"gen_event.html#t:request_id_collection/0"},{"type":"type","doc":"Response time-out for an asynchronous call.\n\nUsed to set a time limit on how long to wait for a response using either\n`receive_response/2`, `receive_response/3`, `wait_response/2`, or\n`wait_response/3`. The time unit used is `millisecond`.\nCurrently valid values:\n\n- **`0..4294967295`** - Timeout relative to current time in milliseconds.\n\n- **`infinity`** - Infinite timeout. That is, the operation\n will never time out.\n\n- **`{abs, Timeout}`** - An absolute\n [Erlang monotonic time](`erlang:monotonic_time/1`) timeout\n in milliseconds. That is, the operation will time out when\n [`erlang:monotonic_time(millisecond)`](`erlang:monotonic_time/1`)\n returns a value larger than or equal to `Timeout`.\n `Timeout` is not allowed to identify a time further into the future\n than `4294967295` milliseconds. Identifying the timeout using\n an absolute timeout value is especially handy when you have a\n deadline for responses corresponding to a complete collection\n of requests (`t:request_id_collection/0`) , since you do not have to\n recalculate the relative time until the deadline over and over again.","title":"gen_event.response_timeout/0","ref":"gen_event.html#t:response_timeout/0"},{"type":"type","doc":"","title":"gen_event.start_mon_ret/0","ref":"gen_event.html#t:start_mon_ret/0"},{"type":"type","doc":"","title":"gen_event.start_ret/0","ref":"gen_event.html#t:start_ret/0"},{"type":"behaviour","doc":"Deprecated and replaced by `m:gen_statem` in OTP 20.\n\nMigration to gen_statem\n-----------------------\n\nHere follows a simple example of turning a gen_fsm into a `m:gen_statem`.\nThe example comes from the previous User's Guide for `gen_fsm`\n\n```erlang\n-module(code_lock).\n-define(NAME, code_lock).\n%-define(BEFORE_REWRITE, true).\n\n-ifdef(BEFORE_REWRITE).\n-behaviour(gen_fsm).\n-else.\n-behaviour(gen_statem).\n-endif.\n\n-export([start_link/1, button/1, stop/0]).\n\n-ifdef(BEFORE_REWRITE).\n-export([init/1, locked/2, open/2, handle_sync_event/4, handle_event/3,\n handle_info/3, terminate/3, code_change/4]).\n-else.\n-export([init/1, callback_mode/0, locked/3, open/3,\n terminate/3, code_change/4]).\n%% Add callback__mode/0\n%% Change arity of the state functions\n%% Remove handle_info/3\n-endif.\n\n-ifdef(BEFORE_REWRITE).\nstart_link(Code) ->\n gen_fsm:start_link({local, ?NAME}, ?MODULE, Code, []).\n-else.\nstart_link(Code) ->\n gen_statem:start_link({local,?NAME}, ?MODULE, Code, []).\n-endif.\n\n-ifdef(BEFORE_REWRITE).\nbutton(Digit) ->\n gen_fsm:send_event(?NAME, {button, Digit}).\n-else.\nbutton(Digit) ->\n gen_statem:cast(?NAME, {button,Digit}).\n %% send_event is asynchronous and becomes a cast\n-endif.\n\n-ifdef(BEFORE_REWRITE).\nstop() ->\n gen_fsm:sync_send_all_state_event(?NAME, stop).\n-else.\nstop() ->\n gen_statem:call(?NAME, stop).\n %% sync_send is synchronous and becomes call\n %% all_state is handled by callback code in gen_statem\n-endif.\n\ninit(Code) ->\n do_lock(),\n Data = #{code => Code, remaining => Code},\n {ok, locked, Data}.\n\n-ifdef(BEFORE_REWRITE).\n-else.\ncallback_mode() ->\n state_functions.\n%% state_functions mode is the mode most similar to\n%% gen_fsm. There is also handle_event mode which is\n%% a fairly different concept.\n-endif.\n\n-ifdef(BEFORE_REWRITE).\nlocked({button, Digit}, Data0) ->\n case analyze_lock(Digit, Data0) of\n {open = StateName, Data} ->\n {next_state, StateName, Data, 10000};\n {StateName, Data} ->\n {next_state, StateName, Data}\n end.\n-else.\nlocked(cast, {button,Digit}, Data0) ->\n case analyze_lock(Digit, Data0) of\n {open = StateName, Data} ->\n {next_state, StateName, Data, 10000};\n {StateName, Data} ->\n {next_state, StateName, Data}\n end;\nlocked({call, From}, Msg, Data) ->\n handle_call(From, Msg, Data);\nlocked({info, Msg}, StateName, Data) ->\n handle_info(Msg, StateName, Data).\n%% Arity differs\n%% All state events are dispatched to handle_call and handle_info help\n%% functions. If you want to handle a call or cast event specifically\n%% for this state you would add a special clause for it above.\n-endif.\n\n-ifdef(BEFORE_REWRITE).\nopen(timeout, State) ->\n do_lock(),\n {next_state, locked, State};\nopen({button,_}, Data) ->\n {next_state, locked, Data}.\n-else.\nopen(timeout, _, Data) ->\n do_lock(),\n {next_state, locked, Data};\nopen(cast, {button,_}, Data) ->\n {next_state, locked, Data};\nopen({call, From}, Msg, Data) ->\n handle_call(From, Msg, Data);\nopen(info, Msg, Data) ->\n handle_info(Msg, open, Data).\n%% Arity differs\n%% All state events are dispatched to handle_call and handle_info help\n%% functions. If you want to handle a call or cast event specifically\n%% for this state you would add a special clause for it above.\n-endif.\n\n-ifdef(BEFORE_REWRITE).\nhandle_sync_event(stop, _From, _StateName, Data) ->\n {stop, normal, ok, Data}.\n\nhandle_event(Event, StateName, Data) ->\n {stop, {shutdown, {unexpected, Event, StateName}}, Data}.\n\nhandle_info(Info, StateName, Data) ->\n {stop, {shutdown, {unexpected, Info, StateName}}, StateName, Data}.\n-else.\n-endif.\n\nterminate(_Reason, State, _Data) ->\n State =/= locked andalso do_lock(),\n ok.\ncode_change(_Vsn, State, Data, _Extra) ->\n {ok, State, Data}.\n\n%% Internal functions\n-ifdef(BEFORE_REWRITE).\n-else.\nhandle_call(From, stop, Data) ->\n {stop_and_reply, normal, {reply, From, ok}, Data}.\n\nhandle_info(Info, StateName, Data) ->\n {stop, {shutdown, {unexpected, Info, StateName}}, StateName, Data}.\n%% These are internal functions for handling all state events\n%% and not behaviour callbacks as in gen_fsm\n-endif.\n\nanalyze_lock(Digit, #{code := Code, remaining := Remaining} = Data) ->\n case Remaining of\n [Digit] ->\n do_unlock(),\n {open, Data#{remaining := Code}};\n [Digit|Rest] -> % Incomplete\n {locked, Data#{remaining := Rest}};\n _Wrong ->\n {locked, Data#{remaining := Code}}\n end.\n\ndo_lock() ->\n io:format(\"Lock~n\", []).\ndo_unlock() ->\n io:format(\"Unlock~n\", []).\n```\n\nOTP 19 Documentation\n--------------------","title":"gen_fsm","ref":"gen_fsm.html"},{"type":"behaviour","doc":"`gen_fsm`","title":"Module - gen_fsm","ref":"gen_fsm.html#module-module"},{"type":"behaviour","doc":"Generic finite state machine behavior.","title":"Module Summary - gen_fsm","ref":"gen_fsm.html#module-module-summary"},{"type":"behaviour","doc":"This behavior module provides a finite state machine.\nA generic finite state machine process (`gen_fsm`) implemented\nusing this module has a standard set of interface functions\nand includes functionality for tracing and error reporting.\nIt also fits into an OTP supervision tree. For more information,\nsee [OTP Design Principles](`e:system:design_principles`).\n\nA `gen_fsm` process assumes all specific parts to be located\nin a callback module exporting a predefined set of functions.\nThe relationship between the behavior functions\nand the callback functions is as follows:\n\n``` text\ngen_fsm module Callback module\n-------------- ---------------\ngen_fsm:start\ngen_fsm:start_link -----> Module:init/1\n\ngen_fsm:stop -----> Module:terminate/3\n\ngen_fsm:send_event -----> Module:StateName/2\n\ngen_fsm:send_all_state_event -----> Module:handle_event/3\n\ngen_fsm:sync_send_event -----> Module:StateName/3\n\ngen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4\n\n- -----> Module:handle_info/3\n\n- -----> Module:terminate/3\n\n- -----> Module:code_change/4\n```\n\nIf a callback function fails or returns a bad value,\nthe `gen_fsm` process terminates.\n\nA `gen_fsm` process handles system messages as described\nin [sys(3)](`m:sys`). The sys module can be used for\ndebugging a `gen_fsm` process.\n\nNotice that a `gen_fsm` process does not trap exit signals automatically,\nthis must be explicitly initiated in the callback module.\n\nUnless otherwise stated, all functions in this module fail\nif the specified `gen_fsm` process does not exist\nor if bad arguments are specified.\n\nThe gen_fsm process can go into hibernation (see `erlang:hibernate/3`)\nif a callback function specifies `hibernate` instead of a time-out value.\nThis can be useful if the server is expected to be idle for a long time.\nHowever, use this feature with care, as hibernation implies at least\ntwo garbage collections (when hibernating and shortly after waking up)\nand is not something you want to do between each call\nto a busy state machine.","title":"Description - gen_fsm","ref":"gen_fsm.html#module-description"},{"type":"behaviour","doc":"See the [Callback Functions](#callbacks-deprecated) section\nfor the functions to be exported from a `gen_fsm` callback module.\n\n[]() {: #state-name }\n**State name** denotes a state of the state machine.\n\n[]() {: #state-data }\n**State data** denotes the internal state of the Erlang process\nthat implements the state machine.","title":"Callback Functions - gen_fsm","ref":"gen_fsm.html#module-callback-functions"},{"type":"function","doc":"Cancel an internal timer in a generic FSM.\n\nCancels an internal timer referred by `Ref` in the `gen_fsm` process\nthat calls this function.\n\n`Ref` is a reference returned from `send_event_after/2`\nor `start_timer/2`.\n\nIf the timer has already timed out, but the event not yet been delivered,\nit is cancelled as if it had not timed out, so there is no false\ntimer event after returning from this function.\n\nReturns the remaining time in milliseconds until the timer\nwould have expired if `Ref` referred to an active timer,\notherwise `false`.","title":"gen_fsm.cancel_timer/1","ref":"gen_fsm.html#cancel_timer/1"},{"type":"callback","doc":"Update the internal [*state data*](#state-data) during upgrade/downgrade.\n\nThis function is called by a `gen_fsm` process when it is to update\nits internal [*state data*](#state-data)\nduring a release upgrade/downgrade, that is,\nwhen instruction `{update, Module, Change, ...}`,\nwhere `Change = {advanced, Extra}`, is given in the appup file;\nsee section Release Handling Instructions in OTP Design Principles.\n[OTP Design Principles](`e:system:release_handling.md#instr`).\n\nFor an upgrade, `OldVsn` is `Vsn`, and for a downgrade,\n`OldVsn` is `{down, Vsn}`. `Vsn` is defined by the vsn attribute(s)\nof the old version of the callback module `Module`. If no such\n attribute is defined, the version is the checksum of the Beam file.\n\n`StateName` is the current [*state name*](#state-name)\n and `StateData` the internal [*state data*](#state-data)\n of the `gen_fsm` process.\n\n`Extra` is passed \"as is\" from the `{advanced, Extra}` part\n of the update instruction.\n\nThe function is to return the new current [*state name*](#state-name)\nand updated internal data.","title":"gen_fsm.code_change/4","ref":"gen_fsm.html#c:code_change/4"},{"type":"function","doc":"Enter the `gen_fsm` receive loop.\n\nEquivalent to `enter_loop/6` with `Timeout = infinity`\nbut the started server is not registered as for `start_link/3`.","title":"gen_fsm.enter_loop/4","ref":"gen_fsm.html#enter_loop/4"},{"type":"function","doc":"Enter the `gen_fsm` receive loop.\n\nWith argument `FsmName` equivalent to `enter_loop/6`\nwith `Timeout = infinity`.\n\nWith argument `Timeout` equivalent to `enter_loop/6`\nbut the started server is not registered as for `start_link/3`.","title":"gen_fsm.enter_loop/5","ref":"gen_fsm.html#enter_loop/5"},{"type":"function","doc":"Enter the `gen_fsm` receive loop.\n\nMakes an existing process into a `gen_fsm` process. Does not return,\ninstead the calling process enters the `gen_fsm` receive loop\nand becomes a `gen_fsm` process. The process must have been started\nusing one of the start functions in `m:proc_lib`. The user is responsible\nfor any initialization of the process, including registering a name for it.\n\nThis function is useful when a more complex initialization procedure\nis needed than the `gen_fsm` behavior provides.\n\n`Module`, `Options`, and `FsmName` have the same meanings\nas when calling [`start[_link]/3,4`](`start_link/4`).\nHowever, the process must have been registered according to\n`FsmName` before this function is called.\n\n`StateName`, `StateData`, and `Timeout` have the same meanings\nas in the return value of [`Module:init/1`](`c:init/1`).\nThe callback module `Module` does not need to export\nan `c:init/1` function.\n\nThe function fails if the calling process was not started\nby a `m:proc_lib` start function, or if it is not registered\naccording to `FsmName`.","title":"gen_fsm.enter_loop/6","ref":"gen_fsm.html#enter_loop/6"},{"type":"callback","doc":"Optional function for providing a term describing\nthe current `gen_fsm` process status.\n\nThe second argument is `[PDict, StateData]`, that is, a list\nwith the 2 elements, in that order.\n\n> #### Note {: .info }\n>\n> This callback is optional, so callback modules need not export it.\n> The `gen_fsm` module provides a default implementation\n> of this function that returns the callback module\n> [*state data*](#state-data).\n\nThis function is called by a `gen_fsm` process\nin the following situations:\n\n- One of [`sys:get_status/1,2`](`sys:get_status/1`) is invoked to get\n the `gen_fsm` status. `Opt` is set to the atom `normal` for this case.\n- The `gen_fsm` process terminates abnormally and logs an error.\n `Opt` is set to the atom terminate for this case.\n\nThis function is useful for changing the form and appearance\nof the `gen_fsm` status for these cases. A callback module\nwishing to change the [`sys:get_status/1,2`](`sys:get_status/1`)\nreturn value as well as how its status appears in termination error logs,\nexports an instance of `c:format_status/2` that returns a term\ndescribing the current status of the `gen_fsm` process.\n\n`PDict` is the current value of the process dictionary\nof the `gen_fsm` process.\n\n`StateData` is the internal [*state data*](#state-data)\nof the `gen_fsm` process.\n\nThe function is to return `Status`, a term that change the details\nof the current state and status of the `gen_fsm` process.\nThere are no restrictions on the form `Status` can take,\nbut for the [`sys:get_status/1,2`](`sys:get_status/1`) case\n(when `Opt` is `normal`), the recommended form for the `Status` value\nis `[{data, [{\"StateData\", Term}]}]`, where `Term` provides\nrelevant details of the `gen_fsm` [*state data*](#state-data).\nFollowing this recommendation is not required, but it makes\nthe callback module status consistent with the rest of\nthe [`sys:get_status/1,2`](`sys:get_status/1`) return value.\n\nOne use for this function is to return compact alternative\n[*state data*](#state-data) representations to avoid\nthat large state terms are printed in log files.","title":"gen_fsm.format_status/2","ref":"gen_fsm.html#c:format_status/2"},{"type":"callback","doc":"Handle an asynchronous event.\n\nWhenever a `gen_fsm` process receives an event sent using\n`send_all_state_event/2`, this function is called to handle the event.\n\n`StateName` is the current [*state name*](#state-name)\nof the `gen_fsm` process.\n\nFor a description of the other arguments and possible return values,\nsee [`Module:StateName/2`](`c:'StateName'/2`).","title":"gen_fsm.handle_event/3","ref":"gen_fsm.html#c:handle_event/3"},{"type":"callback","doc":"Handle an incoming message\n\nThis function is called by a `gen_fsm` process when it receives\nany other message than a synchronous or asynchronous event\n(or a system message).\n\n`Info` is the received message.\n\nFor a description of the other arguments and possible return values,\nsee [`Module:StateName/2`](`c:'StateName'/2`).","title":"gen_fsm.handle_info/3","ref":"gen_fsm.html#c:handle_info/3"},{"type":"callback","doc":"Handle a synchronous event.\n\nWhenever a `gen_fsm` process receives an event sent using\n[`sync_send_all_state_event/2,3`](`sync_send_all_state_event/3`),\nthis function is called to handle the event.\n\n`StateName` is the current [*state name*](#state-name)\nof the `gen_fsm` process.\n\nFor a description of the other arguments and possible return values,\nsee [`Module:StateName/3`](`c:'StateName'/3`).","title":"gen_fsm.handle_sync_event/4","ref":"gen_fsm.html#c:handle_sync_event/4"},{"type":"callback","doc":"Initialize process and internal [*state name*](#state-name)\nand [*state data*](#state-data).\n\nWhenever a `gen_fsm` process is started using\n[`start/3,4`](`start/4`) or [`start_link/3,4`](`start_link/4`),\nthis function is called by the new process to initialize.\n\n`Args` is the `Args` argument provided to the start function.\n\nIf initialization is successful, the function is to return\n{ok, StateName, StateData}, {ok, StateName, StateData, Timeout},\nor {ok, StateName, StateData, hibernate}, where `StateName`\nis the initial [*state name*](#state-name) and `StateData`\nthe initial [*state data*](#state-data) of the `gen_fsm` process.\n\nIf an `t:integer/0` time-out value is provided, a time-out occurs\nunless an event or a message is received within `Timeout` milliseconds.\nA time-out is represented by the atom `timeout` and is to be handled\nby the [`Module:StateName/2`](`c:'StateName'/2`) callback functions.\nThe atom `infinity` can be used to wait indefinitely, this is\nthe default value.\n\nIf `hibernate` is specified instead of a time-out value,\nthe process goes into hibernation when waiting for the next message\nto arrive (by calling `proc_lib:hibernate/3`).\n\nIf the initialization fails, the function returns `{stop, Reason}`,\nwhere `Reason` is any term, or `ignore`.","title":"gen_fsm.init/1","ref":"gen_fsm.html#c:init/1"},{"type":"function","doc":"Send a reply to a caller.\n\nThis function can be used by a `gen_fsm` process to explicitly send\na reply to a client process that called\n[`sync_send_event/2,3`](`sync_send_event/3`) or\n[`sync_send_all_state_event/2,3`](`sync_send_all_state_event/3`)\nwhen the reply cannot be defined in the return value of\n[`Module:StateName/3`](`c:'StateName'/3`) or\n[`Module:handle_sync_event/4`](`c:handle_sync_event/4`).\n\n`Caller` must be the `From` argument provided to the callback function.\n`Reply` is any term given back to the client as the return value of\n[`sync_send_event/2,3`](`sync_send_event/3`) or\n[`sync_send_all_state_event/2,3`](`sync_send_all_state_event/3`).\n\nReturn value `Result` is not further defined, and is always to be ignored.","title":"gen_fsm.reply/2","ref":"gen_fsm.html#reply/2"},{"type":"callback","doc":"Handle an asynchronous event.\n\nThere is to be one instance of this function\nfor each possible [*state name*](#state-name).\nWhenever a `gen_fsm` process receives an event sent using `send_event/2`,\nthe instance of this function with the same name as the current\n[*state name*](#state-name) `StateName` is called to handle the event.\nIt is also called if a time-out occurs.\n\n`Event` is either the atom `timeout`, if a time-out has occurred,\nor the `Event` argument provided to `send_event/2`.\n\n`StateData` is the [*state data*](#state-data) of the `gen_fsm` process.\n\nIf the function returns `{next_state, NextStateName, NewStateData},\n{next_state, NextStateName, NewStateData, Timeout},\nor {next_state, NextStateName, NewStateData, hibernate},\nthe `gen_fsm` process continues executing with\nthe current [*state name*](#state-name) set to `NextStateName`\nand with the possibly updated [*state data*](#state-data)\n`NewStateData`. For a description of `Timeout` and `hibernate`,\nsee [`Module:init/1`](`c:init/1`).\n\nIf the function returns `{stop ,Reason, NewStateData},\nthe `gen_fsm` process calls\n[`Module:terminate(Reason, StateName, NewStateData)`](`c:terminate/3`)\nand terminates.","title":"gen_fsm.StateName/2","ref":"gen_fsm.html#c:StateName/2"},{"type":"callback","doc":"Handle a synchronous event.\n\nThere is to be one instance of this function\nfor each possible [*state name*](#state-name).\nWhenever a `gen_fsm` process receives an event sent using\n[`sync_send_event/2,3`](`sync_send_event/3`),\nthe instance of this function with the same name\nas the current [*state name*](#state-name) `StateName` is called\nto handle the event.\n\n`Event` is the `Event` argument provided to\n[`sync_send_event/2,3`](`sync_send_event/3`).\n\n`From` is a tuple `{Pid, Tag}` where `Pid` is the `t:pid/0`\nof the process that called [`sync_send_event/2,3`](`sync_send_event/3`),\n`Tag` is a unique tag.\n\n`StateData` is the [*state data*](#state-data) of the `gen_fsm` process.\n\n- If `{reply, Reply, NextStateName, NewStateData}`,\n `{reply, Reply, NextStateName, NewStateData, Timeout}`,\n or `{reply, Reply, NextStateName, NewStateData, hibernate}` is returned,\n `Reply` is given back to `From` as the return value of\n [`sync_send_event/2,3`](`sync_send_event/3`).\n The `gen_fsm` process then continues executing\n with the current [*state name*](#state-name) set to `NextStateName`\n and with the possibly updated [*state data*](#state-data) `NewStateData`.\n For a description of `Timeout` and `hibernate`,\n see [`Module:init/1`](`c:init/1`).\n\n- If `{next_state, NextStateName, NewStateData}`,\n `{next_state, NextStateName, NewStateData, Timeout}`,\n or `{next_state, NextStateName, NewStateData, hibernate}` is returned,\n the `gen_fsm` process continues executing in `NextStateName`\n with `NewStateData`. Any reply to `From`\n must be specified explicitly using `reply/2`.\n\n- If the function returns `{stop, Reason, Reply, NewStateData}`,\n `Reply` is given back to `From`. If the function returns\n {stop, Reason, NewStateData}, any reply to `From` must be specified\n explicitly using `reply/2`. The `gen_fsm` process then calls\n [`Module:terminate(Reason, StateName, NewStateData)`](`c:terminate/3`)\n and terminates.","title":"gen_fsm.StateName/3","ref":"gen_fsm.html#c:StateName/3"},{"type":"function","doc":"Send an event asynchronously to a generic FSM.\n\nSends an event asynchronously to the `FsmRef` of the `gen_fsm` process\nand returns `ok` immediately. The `gen_fsm` process calls\n[`Module:handle_event/3`](`c:handle_event/3`) to handle the event.\n\nFor a description of the arguments, see `send_event/2`.\n\nThe difference between `send_event/2` and `send_all_state_event/2`\nis which callback function is used to handle the event.\nThis function is useful when sending events that are handled\nthe same way in every state, as only one `handle_event` clause\nis needed to handle the event instead of one clause\nin each state name function.","title":"gen_fsm.send_all_state_event/2","ref":"gen_fsm.html#send_all_state_event/2"},{"type":"function","doc":"Send an event asynchronously to a generic FSM.\n\nSends `Event` to the `FsmRef` of the `gen_fsm` process\nand returns `ok` immediately. The `gen_fsm` process calls\n[`Module:StateName/2`](`c:'StateName'/2`) to handle the event,\nwhere `StateName` is the name of the current state\nof the `gen_fsm` process.\n\n[](){: #fsm-ref }\n`FsmRef` can be any of the following:\n\n- The `t:pid/0`\n- `Name`, if the `gen_fsm` process is locally registered\n- `{Name, Node}`, if the `gen_fsm` process is locally registered\n at another node\n- `{global, GlobalName}`, if the `gen_fsm` process is globally registered\n- `{via, Module, ViaName}`, if the `gen_fsm` process is registered\n through an alternative process registry\n\n`Event` is any term that is passed as one of the arguments\nto `Module:StateName/2`.","title":"gen_fsm.send_event/2","ref":"gen_fsm.html#send_event/2"},{"type":"function","doc":"Send a delayed event internally in a generic FSM.\n\nSends a delayed event internally in the `gen_fsm` process\nthat calls this function after `Time` milliseconds.\nReturns immediately a reference that can be used to cancel\nthe delayed send using `cancel_timer/1`.\n\nThe `gen_fsm` process calls [`Module:StateName/2`](`c:'StateName'/2`)\nto handle the event, where `'StateName'` is the name of\nthe current state of the `gen_fsm` process at the time\nthe delayed event is delivered.\n\n`Event` is any term that is passed as one of the arguments\nto [`Module:StateName/2`](`c:'StateName'/2`).","title":"gen_fsm.send_event_after/2","ref":"gen_fsm.html#send_event_after/2"},{"type":"function","doc":"Create a standalone `gen_fsm` process, not registered.\n\nEquivalent to [`start(Name, Mod, Args, Options)`](`start/4`)\nwithout registering a `Name`.\n\nFor a description of arguments and return values,\nsee [`start_link/3,4`](`start_link/3`).","title":"gen_fsm.start/3","ref":"gen_fsm.html#start/3"},{"type":"function","doc":"Create a standalone `gen_fsm` process.\n\nThe created process is not part of a supervision tree\nand thus has no supervisor.\n\nFor a description of arguments and return values,\nsee [`start_link/3,4`](`start_link/4`).","title":"gen_fsm.start/4","ref":"gen_fsm.html#start/4"},{"type":"function","doc":"Create a `gen_fsm` process in a supervision tree, not registered.\n\nEquivalent to [`start_link(Name, Mod, Args, Options)`](`start_link/4`)\nwithout registering a `Name`.","title":"gen_fsm.start_link/3","ref":"gen_fsm.html#start_link/3"},{"type":"function","doc":"Create a `gen_fsm` process in a supervision tree.\n\nThe process is created as part of a supervision tree. The function\nis to be called, directly or indirectly, by the supervisor.\nFor example, it ensures that the `gen_fsm` process\nis linked to the supervisor.\n\nThe `gen_fsm` process calls [`Module:init/1`](`c:init/1`) to initialize.\nTo ensure a synchronized startup procedure,\n[`start_link/3,4`](`start_link/4`) does not return\nuntil `Module:init/1` has returned.\n\n[]() {: #fsm-name }\n\n- If **`FsmName = {local, Name}`**, the `gen_fsm` process\n is registered locally as `Name` using `register/2`.\n\n- If **`FsmName = {global, GlobalName}`**, the `gen_fsm` process\n is registered globally as `GlobalName` using `global:register_name/2`.\n\n- If **`FsmName = {via, Module, ViaName}`**,\n the `gen_fsm` process registers with the registry\n represented by `Module`. The `Module` callback is to export\n the functions `register_name/2`, `unregister_name/1`,\n `whereis_name/1`, and `send/2`, which are to behave like\n the corresponding functions in `m:global`.\n Thus, `{via, global, GlobalName}` is a valid reference.\n\n`Module` is the name of the callback module.\n\n`Args` is any term that is passed as the argument to `Module:init/1`.\n\n[]() {: #start-options }\n\nIf option **`{timeout, Time}`** is present, the `gen_fsm` process\nis allowed to spend `Time` milliseconds initializing or it terminates\nand the start function returns `{error, timeout}`.\n\nIf option **`{debug, Dbgs}`** is present, the corresponding `sys` function\nis called for each item in `Dbgs`; see [`sys(3)`](`m:sys`).\n\nIf option **`{spawn_opt, SOpts}`** is present, `SOpts` is passed\nas option list to the `spawn_opt` BIF that is used\nto spawn the `gen_fsm` process; see `spawn_opt/2`.\n\n> #### Note {: .info }\n> Using spawn option `monitor` is not allowed, it causes\n> the function to fail with reason `badarg`.\n\nIf the `gen_fsm` process is successfully created and initialized,\nthe function returns `{ok, Pid}`, where `Pid` is the pid\nof the `gen_fsm` process. If a process with the specified `FsmName`\nexists already, the function returns `{error, {already_started, Pid}}`,\nwhere `Pid` is the pid of that process.\n\nIf `Module:init/1` fails with `Reason`, the function returns\n`{error, Reason}`. If `Module:init/1` returns `{stop, Reason}`\nor `ignore`, the process is terminated and the function returns\n`{error, Reason}` or `ignore`, respectively.","title":"gen_fsm.start_link/4","ref":"gen_fsm.html#start_link/4"},{"type":"function","doc":"Send a time-out event internally in a generic FSM.\n\nSends a time-out event internally in the `gen_fsm process`\nthat calls this function after `Time` milliseconds.\nReturns immediately a reference that can be used to cancel the timer\nusing `cancel_timer/1`.\n\nThe `gen_fsm` process calls [`Module:StateName/2`](`c:'StateName'/2`)\nto handle the event, where `'StateName'` is the name\nof the current state of the `gen_fsm` process at the time\nthe time-out message is delivered.\n\n`Msg` is any term that is passed in the time-out message,\n`{timeout, Ref, Msg}`, as one of the arguments\nto [`Module:StateName/2`](`c:'StateName'/2`).","title":"gen_fsm.start_timer/2","ref":"gen_fsm.html#start_timer/2"},{"type":"function","doc":"","title":"gen_fsm.stop/1","ref":"gen_fsm.html#stop/1"},{"type":"function","doc":"Synchronously stop a generic FSM.\n\nOrders a generic finite state machine to exit with the specified `Reason`\nand waits for it to terminate. The `gen_fsm` process calls\n[`Module:terminate/3`](`c:terminate/3`) before exiting.\n\nThe function returns `ok` if the generic finite state machine terminates\nwith the expected reason. Any other reason than `normal`, `shutdown`,\nor `{shutdown, Term}` causes an error report to be issued using\n`error_logger:format/2`.\n\n`Timeout` is an integer greater than zero that specifies\nhow many milliseconds to wait for the generic FSM to terminate,\nor the atom `infinity` to wait indefinitely.\nIf the generic finite state machine has not terminated\nwithin the specified time, a `timeout` exception is raised.\n\nIf the process does not exist, a `noproc` exception is raised.","title":"gen_fsm.stop/3","ref":"gen_fsm.html#stop/3"},{"type":"function","doc":"","title":"gen_fsm.sync_send_all_state_event/2","ref":"gen_fsm.html#sync_send_all_state_event/2"},{"type":"function","doc":"Send an event synchronously to a generic FSM.\n\nSends an event to the `FsmRef` of the `gen_fsm` process and waits\nuntil a reply arrives or a time-out occurs. The `gen_fsm` process calls\n[`Module:handle_sync_event/4`](`c:handle_sync_event/4`)\nto handle the event.\n\nFor a description of `FsmRef` and `Event`, see `send_event/2`.\nFor a description of `Timeout` and `Reply`, see `sync_send_event/3`.\n\nFor a discussion about the difference between `sync_send_event`\nand `sync_send_all_state_event`, see `send_all_state_event/2`.","title":"gen_fsm.sync_send_all_state_event/3","ref":"gen_fsm.html#sync_send_all_state_event/3"},{"type":"function","doc":"","title":"gen_fsm.sync_send_event/2","ref":"gen_fsm.html#sync_send_event/2"},{"type":"function","doc":"Send an event synchronously to a generic FSM.\n\nSends an event to the `FsmRef` of the `gen_fsm` process\nand waits until a reply arrives or a time-out occurs.\nThe `gen_fsm` process calls [`Module:StateName/3`](`c:'StateName'/3`)\nto handle the event, where `'StateName'` is the name\nof the current state of the `gen_fsm` process.\n\nFor a description of `FsmRef` and `Event`, see `send_event/2`.\n\n`Timeout` is an integer greater than zero that specifies\nhow many milliseconds to wait for a reply, or the atom `infinity`\nto wait indefinitely. If no reply is received within the specified time,\nthe function call fails.\n\nReturn value `Reply` is defined in the return value of\n[`Module:StateName/3`](`c:'StateName'/3`)\n\n> #### Note {: .info }\n> The ancient behavior of sometimes consuming the server exit message\n> if the server died during the call while linked to the client\n> was removed in Erlang 5.6/OTP R12B.","title":"gen_fsm.sync_send_event/3","ref":"gen_fsm.html#sync_send_event/3"},{"type":"callback","doc":"Clean up before termination.\n\nThis function is called by a `gen_fsm` process\nwhen it is about to terminate. It is to be the opposite of\n[`Module:init/1`](`c:init/1`) and do any necessary cleaning up.\nWhen it returns, the `gen_fsm` process terminates with `Reason`.\nThe return value is ignored.\n\n`Reason` is a term denoting the stop reason, `StateName` is\nthe current [*state name*](#state-name),\nand `StateData` is the [*state data*](#state-data)\nof the `gen_fsm` process.\n\n`Reason` depends on why the `gen_fsm` process is terminating.\nIf it is because another callback function has returned a stop tuple\n`{stop, ...}`, `Reason` has the value specified in that tuple.\nIf it is because of a failure, `Reason` is the error reason.\n\nIf the `gen_fsm` process is part of a supervision tree\nand is ordered by its supervisor to terminate, this function\nis called with `Reason = shutdown` if the following conditions apply:\n\n- The gen_fsm process has been set to trap exit signals.\n\n- The shutdown strategy as defined in the child specification\n of the supervisor is an integer time-out value, not brutal_kill.\n\nEven if the gen_fsm process is **not** part of a supervision tree,\nthis function is called if it receives an `'EXIT'` message\nfrom its parent. `Reason` is the same as in the `'EXIT'` message.\n\nOtherwise, the gen_fsm process terminates immediately.\n\nNotice that for any other reason than `normal`, `shutdown`,\nor `{shutdown, Term}` the `gen_fsm` process is assumed to terminate\nbecause of an error and an error report is issued\nusing `error_logger:format/2`.","title":"gen_fsm.terminate/3","ref":"gen_fsm.html#c:terminate/3"},{"type":"type","doc":"[Start options](#start-options) for the\n[`enter_loop/4,5,6`](`enter_loop/6`), [`start/3,4`](`start/3`),\nand [`start_link/3,4`](`start_link/3`) functions.\n\nSee `start_link/4`.","title":"gen_fsm.enter_loop_opt/0","ref":"gen_fsm.html#t:enter_loop_opt/0"},{"type":"type","doc":"Reply destination. See `reply/2`","title":"gen_fsm.from/0","ref":"gen_fsm.html#t:from/0"},{"type":"type","doc":"[FSM name](#fsm-name) specification:\n`local`, `global`, or `via` registered.\n\nTo be used when starting a `gen_fsm`. See `start_link/4`.","title":"gen_fsm.fsm_name/0","ref":"gen_fsm.html#t:fsm_name/0"},{"type":"type","doc":"[FSM reference](#fsm-ref) `t:pid/0` or registered `t:fsm_name/0`.\n\nTo be used in for example `send_event/2` to specify the server.","title":"gen_fsm.fsm_ref/0","ref":"gen_fsm.html#t:fsm_ref/0"},{"type":"type","doc":"[Start options](#start-options) for the [`start/3,4`](`start/3`),\nand [`start_link/3,4`](`start_link/3`) functions.\n\nSee `start_link/4`.","title":"gen_fsm.start_opt/0","ref":"gen_fsm.html#t:start_opt/0"},{"type":"behaviour","doc":"Generic server behavior.\n\nThis behavior module provides the server in a client-server relation.\nA generic server process (`gen_server`) implemented using this module\nhas a standard set of interface functions and includes functionality\nfor tracing and error reporting. It also fits into\nan OTP supervision tree. For more information, see section\n[gen_server Behaviour](`e:system:gen_server_concepts.md`)\nin OTP Design Principles.\n\nA `gen_server` process assumes all specific parts to be located\nin a callback module exporting a predefined set of functions.\nThe relationship between the behavior functions\nand the callback functions is as follows:\n\n```text\ngen_server module Callback module\n----------------- ---------------\ngen_server:start\ngen_server:start_monitor\ngen_server:start_link -----> Module:init/1\n\ngen_server:stop -----> Module:terminate/2\n\ngen_server:call\ngen_server:send_request\ngen_server:multi_call -----> Module:handle_call/3\n\ngen_server:cast\ngen_server:abcast -----> Module:handle_cast/2\n\n- -----> Module:handle_info/2\n\n- -----> Module:handle_continue/2\n\n- -----> Module:terminate/2\n\n- -----> Module:code_change/3\n```\n\nIf a callback function fails or returns a bad value,\nthe `gen_server` process terminates. However, an exception of class\n[`throw`](`erlang:throw/1`) is not regarded as an error\nbut as a valid return, from all callback functions.\n\nA `gen_server` process handles system messages as described in `m:sys`.\nThe `m:sys` module can be used for debugging a `gen_server` process.\n\nNotice that a `gen_server` process does not trap exit signals\nautomatically, this must be explicitly initiated in the callback module.\n\nUnless otherwise stated, all functions in this module fail\nif the specified `gen_server` process does not exist\nor if bad arguments are specified.\n\nThe `gen_server` process can go into hibernation (see `erlang:hibernate/3`)\nif a callback function specifies `'hibernate'` instead of a time-out value.\nThis can be useful if the server is expected to be idle for a long time.\nHowever, use this feature with care, as hibernation implies at least\ntwo garbage collections (when hibernating and shortly after waking up)\nand is not something you want to do between each call to a busy server.\n\nIf the `gen_server` process needs to perform an action after\ninitialization or to break the execution of a callback into multiple steps,\nit can return `{continue, Continue}` in place of\nthe time-out or hibernation value, which will invoke\nthe [`Module:handle_continue/2`](`c:handle_continue/2`) callback,\nbefore receiving any external message / request.\n\nIf the `gen_server` process terminates, e.g. as a result of a function\nin the callback module returning `{stop,Reason,NewState}`,\nan exit signal with this `Reason` is sent to linked processes and ports.\nSee [Processes](`e:system:ref_man_processes.md#errors`)\nin the Reference Manual for details regarding error handling\nusing exit signals.\n\n> #### Note {: .info }\n>\n> For some important information about distributed signals, see the\n> [_Blocking Signaling Over Distribution_][1]\n> section in the _Processes_ chapter of the _Erlang Reference Manual_.\n> Blocking signaling can, for example, cause call time-outs\n> in `gen_server` to be significantly delayed.\n\n[1]: `e:system:ref_man_processes.md#blocking-signaling-over-distribution`","title":"gen_server","ref":"gen_server.html"},{"type":"behaviour","doc":"`m:gen_event`, `m:gen_statem`, `m:proc_lib`, `m:supervisor`, `m:sys`","title":"See Also - gen_server","ref":"gen_server.html#module-see-also"},{"type":"function","doc":"Cast a request to multiple nodes.\n\nEquivalent to [`abcast(Nodes, Name, Request)`](`abcast/3`)\nwhere `Nodes` is all nodes connected to the calling node,\nincluding the calling node itself.","title":"gen_server.abcast/2","ref":"gen_server.html#abcast/2"},{"type":"function","doc":"Cast a request to multiple nodes.\n\nSends an asynchronous request to the `gen_server` processes\nlocally registered as `Name` at the specified nodes.\nThe function returns immediately and ignores nodes that do not exist,\nor where the `gen_server` `Name` does not exist. The `gen_server`\nprocesses call [`Module:handle_cast/2`](`c:handle_cast/2`)\nto handle the request.\n\nFor a description of the arguments,\nsee [`multi_call/2,3,4`](`multi_call/2`).","title":"gen_server.abcast/3","ref":"gen_server.html#abcast/3"},{"type":"function","doc":"","title":"gen_server.call/2","ref":"gen_server.html#call/2"},{"type":"function","doc":"Call a server: send request and wait for response.\n\nMakes a synchronous call to the `ServerRef` of the `gen_server` process\nby sending a request and waiting until a reply arrives\nor a time-out occurs. The `gen_server` process calls\n[`Module:handle_call/3`](`c:handle_call/3`) to handle the request.\n\nSee also `ServerRef`'s type `t:server_ref/0`.\n\n`Request` is any term that is passed as the first argument to\n[`Module:handle_call/3`](`c:handle_call/3`).\n\n`Timeout` is an integer that specifies how many milliseconds to wait\nfor a reply, or the atom `infinity` to wait indefinitely. If no reply\nis received within the specified time, this function exits the calling\nprocess with an exit term containing `Reason = timeout` as described below.\n\n> #### Note {: .info }\n>\n> Before OTP 24, if the caller uses (`try`...)`catch`\n> to avoid process exit, and the server happens to just be late\n> with the reply, it may arrive to the process message queue\n> any time later. The calling process must therefore after\n> catching a time-out exit be prepared to receive garbage message(s)\n> on the form `{reference(), _}` and deal with them appropriately\n> (discard them) so they do not clog the process message queue,\n> or gets mistaken for other messages.\n>\n> Starting with OTP 24, `gen_server:call` uses process aliases,\n> so late replies will not be received.\n\nThe return value `Reply` is passed from the return value of\n[`Module:handle_call/3`](`c:handle_call/3`).\n\nThis call may exit the calling process with an exit term on the form\n`{Reason, Location}` where `Location = {gen_server, call, ArgList}`\nand `Reason` can be (at least) one of:\n\n- **`timeout`** - The call was aborted after waiting `Timeout` milliseconds\n for a reply, as described above.\n\n- **`noproc`** - The `ServerRef` refers to a server by name (it is not a\n `t:pid/0`) and looking up the server process failed, or the `t:pid/0`\n was already terminated.\n\n- **`{nodedown,Node}`** - The `ServerRef` refers to a server\n on the remote node `Node` and the connection to that node failed.\n\n- **`calling_self`** - A call to `self/0` would hang indefinitely.\n\n- **`shutdown`** - The server was stopped during the call\n by its supervisor. See also `stop/3`.\n\n- **`normal`\\\n `{shutdown,Term}`** - The server stopped during the call\n by returning `{stop,Reason,_}` from one of its callbacks\n without replying to this call. See also `stop/3`.\n\n- **`_OtherTerm`** - The server process exited during the call,\n with reason `Reason`. Either by returning `{stop,Reason,_}`\n from one of its callbacks (without replying to this call),\n by raising an exception, or due to getting an exit signal\n it did not trap.","title":"gen_server.call/3","ref":"gen_server.html#call/3"},{"type":"function","doc":"Cast a request to a server.\n\nSends an asynchronous request to the `gen_server`\n[`ServerRef`](`t:server_ref/0`) and returns `ok` immediately,\nignoring if the destination node or `gen_server`\nprocess does not exist.\n\nThe `gen_server` process calls\n[`Module:handle_cast(Request, _)`](`c:handle_cast/2`)\nto handle the request.","title":"gen_server.cast/2","ref":"gen_server.html#cast/2"},{"type":"function","doc":"Check if a received message is a request response.\n\nChecks if `Msg` is a response corresponding to\nthe request identifier `ReqId`. The request must have been made\nby `send_request/2`, and by the same process calling this function.\n\nIf `Msg` is a reply to the handle `ReqId` the result of the request\nis returned in `Reply`. Otherwise this function returns `no_reply`\nand no cleanup is done, and thus the function shall be invoked repeatedly\nuntil the response is returned.\n\nThe return value `Reply` is passed from the return value of\n[`Module:handle_call/3`](`c:handle_call/3`).\n\nIf the `gen_statem` server process has died when this function\nis called, that is; `Msg` reports the server's death,\nthis function returns an `error` return with the exit `Reason`.","title":"gen_server.check_response/2","ref":"gen_server.html#check_response/2"},{"type":"function","doc":"Check if a received message is a request response in a collection.\n\nCheck if `Msg` is a response corresponding to a request identifier\nstored in `ReqIdCollection`. All request identifiers of `ReqIdCollection`\nmust correspond to requests that have been made using `send_request/2`\nor `send_request/4`, by the process calling this function.\n\nThe `Label` in the response equals the `Label` associated\nwith the request identifier that the response corresponds to.\nThe `Label` of a request identifier is associated\nwhen [storing the request id](`reqids_add/3`) in a collection,\nor when sending the request using `send_request/4`.\n\nCompared to `check_response/2`, the returned result or exception\nassociated with a specific request identifier will be wrapped\nin a 3-tuple `{Response, Label, NewReqIdCollection}`.\n`Response` is the value that would have been produced\nby `check_response/2`, `Label` is the value associated with\nthe specific [request identifier](`t:request_id/0`)\nand `NewReqIdCollection` is a possibly modified\nrequest identifier collection.\n\nIf `ReqIdCollection` is empty, `no_request` will be returned.\n\nIf `Msg` does not correspond to any of the request identifiers\nin `ReqIdCollection`, `no_reply` is returned.\n\nIf `Delete` is `true`, the association with `Label`\nhas been deleted from `ReqIdCollection` in the resulting\n`NewReqIdCollection`. If `Delete` is `false`, `NewReqIdCollection`\nwill equal `ReqIdCollection`. Note that deleting an association\nis not for free and that a collection containing already handled\nrequests can still be used by subsequent calls to\n`check_response/3`, `receive_response/3`, and `wait_response/3`.\n\nHowever, without deleting handled associations,\nthe above calls will not be able to detect when there are\nno more outstanding requests to handle, so you will have to keep track\nof this some other way than relying on a `no_request` return.\nNote that if you pass a collection only containing\nassociations of already handled or abandoned requests to\nthis function, it will always return `no_reply`.","title":"gen_server.check_response/3","ref":"gen_server.html#check_response/3"},{"type":"callback","doc":"Update the server state after code change.\n\nThis function is called by a `gen_server` process when it is to update\nits internal state during a release upgrade/downgrade, that is,\nwhen the instruction `{update, Module, Change, ...}`, is specified\nin the [`appup`](`e:sasl:appup.md`) file.\n\nFor more information, see section\n[Release Handling Instructions](`e:system:release_handling.md#instr`)\nin OTP Design Principles.\n\nFor an upgrade, `OldVsn` is `Vsn`, and for a downgrade, `OldVsn` is\n`{down,Vsn}`. `Vsn` is defined by the `vsn` attribute(s)\nof the old version of the callback module `Module`. If no such attribute\nis defined, the version is the checksum of the Beam file.\n\n`State` is the internal state of the `gen_server` process.\n\n`Extra` is passed \"as is\" from the `{advanced,Extra}` part\nof the update instruction.\n\nIf successful, the function must return the updated internal state.\n\nIf the function returns `{error,Reason}`,\nthe ongoing upgrade fails and rolls back to the old release.\n\n> #### Note {: .info }\n>\n> If a release upgrade/downgrade with `Change = {advanced, Extra}`\n> specified in the [`.appup`](`e:sasl:appup.md`) file is made when\n> [`Module:code_change/3`](`c:code_change/3`) is not implemented,\n> the callback call will crash with an `undef` error reason.","title":"gen_server.code_change/3","ref":"gen_server.html#c:code_change/3"},{"type":"function","doc":"","title":"gen_server.enter_loop/3","ref":"gen_server.html#enter_loop/3"},{"type":"function","doc":"Make the calling process become a `gen_server` process.\n\nWith argument `ServerName` equivalent to\n[`enter_loop(Module, Options,\n State, ServerName, infinity)`](`enter_loop/5`).\n\nWith argument `How` equivalent to\n[`enter_loop(Module, Options, State, self(), How)`](`enter_loop/5`).","title":"gen_server.enter_loop/4","ref":"gen_server.html#enter_loop/4"},{"type":"function","doc":"Make the calling process become a `gen_server` process.\n\nDoes not return, instead the calling process enters the `gen_server`\nprocess receive loop and becomes a `gen_server` process.\nThe process _must_ have been started using one of the start functions\nin `m:proc_lib`. The user is responsible for any initialization\nof the process, including registering a name for it.\n\nThis function is useful when a more complex initialization procedure\nis needed than the `gen_server` [`Module:init/1`](`c:init/1`);\ncallback provides.\n\n`Module`, `Options`, and `ServerName` have the same meanings\nas when calling [`start[_link|_monitor]/3,4`](`start_link/3`)\nor `ServerName` can be `self/0` for an anonymous server,\nwhich is the same as calling an `enter_loop/3,4` function\nwithout a `ServerName` argument. However, if `ServerName`\nis specified (and not as `self/0`), the process must have been registered\naccordingly _before_ this function is called.\n\n`State`, `Timeout`, `Hibernate` and `Cont` have the same meanings\nas in the return value of [`Module:init/1`](`c:init/1`),\nwhich is _not_ called when `enter_loop/3,4,5` is used. Note that\nto adhere to the [gen_server Behaviour](`e:system:gen_server_concepts.md`)\nsuch a callback function needs to be defined, and it might as well\nbe the one used when starting the `gen_server` process\nthrough `proc_lib`, and then be the one that calls `enter_loop/3,4,5`.\nBut if such a [`Module:init/1`](`c:init/1`) function,\nin for example error cases, cannot call `enter_loop/3,4,5`,\nit should return a value that follows the type specification\nfor [`Module:init/1`](`c:init/1`) such as `ignore`,\nalthough that value will be lost when returning to the spawning function.\n\nThis function fails if the calling process was not started\nby a `proc_lib` start function, or if it is not registered\naccording to `ServerName`.","title":"gen_server.enter_loop/5","ref":"gen_server.html#enter_loop/5"},{"type":"callback","doc":"Format/limit the status value.\n\nThis function is called by a `gen_server` process in in order to\nformat/limit the server state for debugging and logging purposes.\n\nIt is called in the following situations:\n\n- [`sys:get_status/1,2`](`sys:get_status/1`) is invoked\n to get the `gen_server` status.\n- The `gen_server` process terminates abnormally and logs an error.\n\nThis callback is used to limit the status of the process returned by\n[`sys:get_status/1,2`](`sys:get_status/1`) or sent to `m:logger`.\n\nThe callback gets a map `Status` describing the current status\nand shall return a map `NewStatus` with the same keys,\nbut it may transform some values.\n\nTwo possible use cases for this callback is to remove\nsensitive information from the state to prevent it from being printed\nin log files, or to compact large irrelevant status items\nthat would only clutter the logs.\n\nExample:\n\n```erlang\nformat_status(Status) ->\n maps:map(\n fun(state,State) ->\n maps:remove(private_key, State);\n (message,{password, _Pass}) ->\n {password, removed};\n (_,Value) ->\n Value\n end, Status).\n```\n\n> #### Note {: .info }\n>\n> This callback is optional, so callback modules need not export it. The\n> `gen_server` module provides a default implementation\n> of this function that returns the callback module state.\n>\n> If this callback is exported but fails,\n> to hide possibly sensitive data,\n> the default function will instead return the fact that\n> [`Module:format_status/1`](`c:format_status/1`) has crashed.","title":"gen_server.format_status/1","ref":"gen_server.html#c:format_status/1"},{"type":"callback","doc":"Format/limit the status value.\n\nThis function is called by a `gen_server` process\nin in order to format/limit the server state\nfor debugging and logging purposes.\n\nIt is called in the following situations:\n\n- One of [`sys:get_status/1,2`](`sys:get_status/1`) is invoked to get the\n `gen_server` status. `Opt` is set to the atom `normal`.\n- The `gen_server` process terminates abnormally and logs an error.\n `Opt` is set to the atom `terminate`.\n\nThis function is useful for changing the form and appearance\nof the `gen_server` status for these cases. A callback module\nwishing to change the `sys:get_status/1,2` return value,\nas well as how its status appears in termination error logs,\nexports an instance of [`Module:format_status/2`](`c:format_status/2`)\nthat returns a term describing the current status\nof the `gen_server` process.\n\n`PDict` is the current value of the process dictionary\nof the `gen_server` process..\n\n`State` is the internal state of the `gen_server` process.\n\nThe function is to return `Status`, a term that changes the details\nof the current state and status of the `gen_server` process.\nThere are no restrictions on the form `Status` can take,\nbut for the `sys:get_status/1,2` case (when `Opt` is `normal`),\nthe recommended form for the `Status` value is\n`[{data, [{\"State\", Term}]}]`, where `Term` provides relevant details\nof the `gen_server` state. Following this recommendation is not required,\nbut it makes the callback module status consistent with the rest of\nthe `sys:get_status/1,2` return value.\n\nOne use for this function is to return compact alternative\nstate representations to avoid that large state terms are printed\nin log files.\n\n> #### Note {: .info }\n>\n> This callback is optional, so callback modules need not export it.\n> The `gen_server` module provides a default implementation\n> of this function that returns the callback module state.","title":"gen_server.format_status/2","ref":"gen_server.html#c:format_status/2"},{"type":"callback","doc":"Handle a call.\n\nWhenever a `gen_server` process receives a request sent using\n[`call/2,3`](`call/3`), [`multi_call/2,3,4`](`multi_call/4`),\nor [`send_request/2,4`](`send_request/4`), this function is called\nto handle the request.\n\n`State` is the internal state of the `gen_server` process,\nand `NewState` a possibly updated one.\n\n`Request` is passed from the same argument provided\nto `call` or `multi_call`.\n\nThe return value `Result` is interpreted as follows:\n\n- **`{reply,Reply,NewState}`\\\n `{reply,Reply,NewState,_}`** - The `Reply` value is sent back\n to the client request and there becomes its return value.\n\n The `gen_server` process continues executing with the possibly updated\n internal state `NewState`.\n\n- **`{noreply,NewState}`\\\n `{noreply,NewState,_}`** - The `gen_server` process\n continues executing with the possibly updated internal state `NewState`.\n\n A reply to the client request has to be created by calling\n [`reply(From, Reply)`](`reply/2`), either in this\n or in a later callback.\n\n- **`{reply,_,_,Timeout}`\\\n `{noreply,_,Timeout}`** - If an integer `Timeout` is provided,\n a time-out occurs unless a request or a message is received\n within that many milliseconds. A time-out is represented\n by the atom `timeout` to be handled by the\n [`Module:handle_info/2`](`c:handle_info/2`) callback function.\n `Timeout =:= infinity` can be used to wait indefinitely,\n which is the same as returning a value without a `Timeout` member.\n\n- **`{reply,_,_,hibernate}`\\\n `{noreply,_,hibernate}`** - The process goes into hibernation,\n by calling `proc_lib:hibernate/3`, waiting for\n the next message to arrive\n\n- **`{reply,_,_,{continue,Continue}}`\\\n `{noreply,_,{continue,Continue}}`** - The process will execute the\n [`Module:handle_continue/2`](`c:handle_continue/2`) callback function,\n with `Continue` as the first argument.\n\n- **`{stop,Reason,NewState}`\\\n `{stop,Reason,Reply,NewState}`** - The `gen_server` process will call\n [`Module:terminate(Reason,NewState)`](`c:terminate/2`),\n and then terminate.\n\n `{stop,_,Reply,_}` will create a reply to the client request just as\n `{reply,Reply,...}` while `{stop,_,_}` will not, so just as for\n `{noreply,NewState,...}` a reply has to be created by calling\n [`reply(From, Reply)`](`reply/2`) before returning `{stop,_,_}`.","title":"gen_server.handle_call/3","ref":"gen_server.html#c:handle_call/3"},{"type":"callback","doc":"Handle a cast message.\n\nWhenever a `gen_server` process receives a request sent using `cast/2`\nor [`abcast/2,3`](`abcast/2`), this function is called\nto handle the request.\n\nFor a description of the arguments and possible return values,\nsee [`Module:handle_call/3`](`c:handle_call/3`).","title":"gen_server.handle_cast/2","ref":"gen_server.html#c:handle_cast/2"},{"type":"callback","doc":"Handle a callback continuation.\n\nThis function is called by a `gen_server` process whenever\na previous callback returns one of the tuples containing\n`{continue, Continue}`. The call is invoked immediately after\nthe previous callback, which makes it useful for performing work\nafter initialization or, for splitting the work in a callback\ninto multiple steps, updating the process state along the way.\n\nFor a description of the other arguments and possible return values,\nsee [`Module:handle_call/3`](`c:handle_call/3`).\n\n> #### Note {: .info }\n>\n> This callback is optional, so callback modules need to export it\n> only if theyreturn one of the tuples containing `{continue,Continue}`\n> from another callback. If such a `{continue,_}` tuple is used\n> and the callback is not implemented, the process will exit\n> with `undef` error.","title":"gen_server.handle_continue/2","ref":"gen_server.html#c:handle_continue/2"},{"type":"callback","doc":"Handle an info message (regular process message).\n\nThis function is called by a `gen_server` process when a time-out occurs\nor when it receives any other message than a synchronous\nor asynchronous request (or a system message).\n\n`Info` is either the atom `timeout`, if a time-out has occurred,\nor the received message.\n\nFor a description of the other arguments and possible return values,\nsee [`Module:handle_call/3`](`c:handle_call/3`).\n\n> #### Note {: .info }\n>\n> This callback is optional, so callback modules need not export it.\n> The `gen_server` module provides a default implementation\n> of this function that logs about the unexpected `Info` message,\n> drops it and returns `{noreply, State}`.","title":"gen_server.handle_info/2","ref":"gen_server.html#c:handle_info/2"},{"type":"callback","doc":"Initialize the server.\n\nWhenever a `gen_server` process is started using [`start/3,4`](`start/3`),\n[`start_monitor/3,4`](`start_monitor/3`),\nor [`start_link/3,4`](`start_link/3`), this function is called\nby the new process to initialize the server.\n\n`Args` is the `Args` argument provided to the start function.\n\nThe return value `Result` is interpreted as follows:\n\n- **`{ok,State}`\\\n `{ok,State,_}`** - Initialization was succesful\n and `State` is the internal state of the `gen_server` process.\n\n- **`{ok,_,Timeout}`\\\n `{ok,_,hibernate}`\\\n `{ok,_,{continue,Continue}}`** - See the corresponding return values from\n [`Module:handle_call/3`](`c:handle_call/3`) for a description\n of this tuple member.\n\n- **`{stop,Reason}`** - Initialization failed. The `gen_server`\n process exits with reason `Reason`.\n\n- **`{error,Reason}` _since OTP 26.0_\\\n `ignore`** - Initialization failed. The `gen_server` process exits\n with reason `normal`.\n\nSee function [`start_link/3,4`](`start_link/3`)'s return value\n`t:start_ret/0` in these different cases.","title":"gen_server.init/1","ref":"gen_server.html#c:init/1"},{"type":"function","doc":"Call servers on multiple nodes in parallel.\n\nEquivalent to [`multi_call(Nodes, Name, Request)`](`multi_call/3`)\nwhere `Nodes` is all nodes connected to the calling node,\nincluding the calling node itself.","title":"gen_server.multi_call/2","ref":"gen_server.html#multi_call/2"},{"type":"function","doc":"","title":"gen_server.multi_call/3","ref":"gen_server.html#multi_call/3"},{"type":"function","doc":"Call servers on multiple nodes in parallel.\n\nMakes a synchronous call to all `gen_server` processes\nlocally registered as `Name` at the specified nodes,\nby first sending the request to the nodes, and then waiting\nfor the replies. The `gen_server` processes on the nodes call\n[`Module:handle_call/3`](`c:handle_call/3`) to handle the request.\n\nThe function returns a tuple `{Replies, BadNodes}`,\nwhere `Replies` is a list of `{Node, Reply}` tuples,\nand `BadNodes` is a list of nodes that either did not exist,\nwhere `Name` was not a registered `gen_server`,\nor where it did not reply.\n\n`Nodes` is a list of node names to which the request is to be sent.\n\n`Name` is the locally registered name for each `gen_server` process.\n\n`Request` is any term that is passed as the first argument to\n[`Module:handle_call/3`](`c:handle_call/3`).\n\n`Timeout` is an integer that specifies how many milliseconds\nto wait for all replies, or the atom `infinity` to wait indefinitely.\nIf no reply is received from a node within the specified time,\nthe node is added to `BadNodes`.\n\nWhen a reply `Reply` is received from the `gen_server` process\nat a node `Node`, `{Node,Reply}` is added to `Replies`.\n`Reply` is passed from the return value of\n[`Module:handle_call/3`](`c:handle_call/3`).\n\n> #### Warning {: .warning }\n>\n> If one of the nodes cannot process monitors, for example,\n> C or Java nodes, and the `gen_server` process is not started\n> when the requests are sent, but starts within 2 seconds,\n> this function waits the whole `Timeout`, which may be infinity.\n>\n> This problem does not exist if all nodes are Erlang nodes.\n\nTo prevent late answers (after the time-out)\nfrom polluting the message queue of the caller,\na middleman process is used to do the calls.\nLate answers are then discarded when they arrive to\nthe terminated middleman process.","title":"gen_server.multi_call/4","ref":"gen_server.html#multi_call/4"},{"type":"function","doc":"Receive a request response.\n\nReceive a response corresponding to the request identifier `ReqId`.\nThe request must have been made by `send_request/2`,\nand it must have been made by the same process calling this function.\n\n`Timeout` specifies how long to wait for a response.\nIf no response is received within the specified time,\nthis function returns `timeout`. Assuming that the\nserver executes on a node supporting aliases (introduced in OTP 24)\nthe request will also be abandoned. That is,\nno response will be received after a time-out.\nOtherwise, a stray response might be received at a later time.\n\nThe return value `Reply` is passed from the return value of\n[`Module:handle_call/3`](`c:handle_call/3`).\n\nThe function returns an error if the `gen_server` died\nbefore a reply was sent.\n\nThe difference between `receive_response/2` and `wait_response/2`\nis that `receive_response/2` abandons the request at time-out\nso that a potential future response is ignored,\nwhile `wait_response/2` does not.","title":"gen_server.receive_response/2","ref":"gen_server.html#receive_response/2"},{"type":"function","doc":"Receive a request response in a collection.\n\nReceive a response in `ReqIdCollection`. All request identifiers\nof `ReqIdCollection` must correspond to requests that have been made\nusing `send_request/2` or `send_request/4`, and all requests\nmust have been made by the process calling this function.\n\nThe `Label` in the response is the `Label` associated with\nthe request identifier that the response corresponds to.\nThe `Label` of a request identifier is associated\nwhen [adding the request id](`reqids_add/3`) to a collection,\nor when sending the request using `send_request/4`.\n\nCompared to `receive_response/2`, the returned result or exception\nassociated with a specific request identifier will be wrapped\nin a 3-tuple `{Response, Label, NewReqIdCollection}`.\n`Response` is the value that would have been produced\nby `receive_response/2`, `Label` is the value associated with\nthe specific [request identifier](`t:request_id/0`)\nand `NewReqIdCollection` is a possibly modified\nrequest identifier collection.\n\nIf `ReqIdCollection` is empty, `no_request` will be returned.\n\n`Timeout` specifies how long to wait for a response. If no response\nis received within the specified time, the function returns `timeout`.\nAssuming that the server executes on a node supporting aliases\n(introduced in OTP 24) all requests identified by `ReqIdCollection`\nwill also be abandoned. That is, no responses will be received\nafter a time-out. Otherwise, stray responses might be received\nat a later time.\n\nThe difference between `receive_response/3` and `wait_response/3`\nis that `receive_response/3` abandons the requests at time-out\nso that potential future responses are ignored,\nwhile [`wait_response/3`](`wait_response/3`) does not.\n\nIf `Delete` is `true`, the association with `Label`\nis deleted from `ReqIdCollection` in the resulting\n`NewReqIdCollection`. If `Delete` is `false`, `NewReqIdCollection`\nwill equal `ReqIdCollection`. Note that deleting an association\nis not for free and that a collection containing already handled\nrequests can still be used by subsequent calls to\n`receive_response/3`, `check_response/3`, and `wait_response/3`.\n\nHowever, without deleting handled associations,\nthe above calls will not be able to detect when there are\nno more outstanding requests to handle, so you will have to keep track\nof this some other way than relying on a `no_request` return.\nNote that if you pass a collection only containing\nassociations of already handled or abandoned requests to\nthis function, it will always block until `Timeout` expires\nand then return `timeout`.","title":"gen_server.receive_response/3","ref":"gen_server.html#receive_response/3"},{"type":"function","doc":"Send a reply to a client.\n\nThis function can be used by a `gen_server` process to explicitly send\na reply to a client that called [`call/2,3`](`call/2`) or\n[`multi_call/2,3,4`](`multi_call/2`), when the reply cannot be passed\nin the return value of [`Module:handle_call/3`](`c:handle_call/3`).\n\n`Client` must be the `From` argument provided to the `c:handle_call/3`\ncallback function. `Reply` is any term passed back to the client\nas the return value of `call/2,3` or `multi_call/2,3,4`.","title":"gen_server.reply/2","ref":"gen_server.html#reply/2"},{"type":"function","doc":"Store a request identifier in a colletion.\n\nStores `ReqId` and associates a `Label` with the request identifier\nby adding this information to `ReqIdCollection` and returning\nthe resulting request identifier collection.","title":"gen_server.reqids_add/3","ref":"gen_server.html#reqids_add/3"},{"type":"function","doc":"Create an empty request identifier collection.\n\nReturns a new empty request identifier collection.\nA request identifier collection can be utilized to handle\nmultiple outstanding requests.\n\nRequest identifiers of requests made by `send_request/2`\ncan be stored in a collection using `reqids_add/3`.\nSuch a collection of request identifiers can later be used\nin order to get one response corresponding to a request\nin the collection by passing the collection as argument to\n`receive_response/3`, `wait_response/3`, or, `check_response/3`.\n\n`reqids_size/1` can be used to determine the number of\nrequest identifiers in a collection.","title":"gen_server.reqids_new/0","ref":"gen_server.html#reqids_new/0"},{"type":"function","doc":"Returns the number of request identifiers in `ReqIdCollection`.","title":"gen_server.reqids_size/1","ref":"gen_server.html#reqids_size/1"},{"type":"function","doc":"Convert a request identifier collection to a list.\n\nReturns a list of `{ReqId, Label}` tuples which corresponds to\nall request identifiers with their associated labels\nin [`ReqIdCollection`](`t:request_id_collection/0`).","title":"gen_server.reqids_to_list/1","ref":"gen_server.html#reqids_to_list/1"},{"type":"function","doc":"Send an asynchronous `call` request.\n\nSends `Request` to the `gen_server` process identified by `ServerRef`\nand returns a request identifier `ReqId`.\n\nThe return value `ReqId` shall later be used with `receive_response/2`,\n`wait_response/2`, or `check_response/2` to fetch the actual result\nof the request. Besides passing the request identifier directly\nto these functions, it can also be stored in\na request identifier collection using `reqids_add/3`.\nSuch a collection of request identifiers can later be used\nin order to get one response corresponding to a\nrequest in the collection by passing the collection\nas argument to `receive_response/3`, `wait_response/3`,\nor `check_response/3`. If you are about to store the request identifier\nin a collection, you may want to consider using `send_request/4` instead.\n\nThe call\n`gen_server:receive_response(gen_server:send_request(ServerRef, Request), Timeout)`\ncan be seen as equivalent to\n[`gen_server:call(ServerRef, Request, Timeout)`](`call/3`),\nignoring the error handling.\n\nThe `gen_server` process calls [`Module:handle_call/3`](`c:handle_call/3`) to\nhandle the request.\n\nSee the type `t:server_ref/0` for the possible values for `ServerRef`.\n\n`Request` is any term that is passed as the first argument to\n[`Module:handle_call/3`](`c:handle_call/3`).","title":"gen_server.send_request/2","ref":"gen_server.html#send_request/2"},{"type":"function","doc":"Send an asynchronous `call` request and add it\nto a request identifier collection.\n\nSends `Request` to the `gen_server` process identified by `ServerRef`.\nThe `Label` will be associated with the request identifier\nof the operation and added to the returned request identifier collection\n`NewReqIdCollection`. The collection can later be used in order to\nget one response corresponding to a request in the collection\nby passing the collection as argument to `receive_response/3`,\n`wait_response/3`, or `check_response/3`.\n\nThe same as calling\n[`reqids_add`](`reqids_add/3`)`(`[`send_request`](`send_request/2`)`(ServerRef, Request), Label, ReqIdCollection)`,\nbut slightly more efficient.","title":"gen_server.send_request/4","ref":"gen_server.html#send_request/4"},{"type":"function","doc":"Start a server, neither linked nor registered.\n\nEquivalent to `start/4` except that the `gen_server` process is not\nregistered with any [name service](`t:server_name/0`).","title":"gen_server.start/3","ref":"gen_server.html#start/3"},{"type":"function","doc":"Start a server, neither linked nor registered.\n\nCreates a standalone `gen_server` process, that is,\na `gen_server` process that is not part of a supervision tree,\nand thus has no supervisor.\n\nOther than that see `start_link/4`.","title":"gen_server.start/4","ref":"gen_server.html#start/4"},{"type":"function","doc":"Start a server, linked but not registered.\n\nEquivalent to `start_link/4` except that the `gen_server` process is\nnot registered with any [name service](`t:server_name/0`).","title":"gen_server.start_link/3","ref":"gen_server.html#start_link/3"},{"type":"function","doc":"Start a server, linked but not registered.\n\nCreates a `gen_server` process as part of a supervision tree.\nThis function is to be called, directly or indirectly, by the supervisor.\nFor example, it ensures that the `gen_server` process is spawned\nas linked to the caller (supervisor).\n\nThe `gen_server` process calls [`Module:init/1`](`c:init/1`)\nto initialize. To ensure a synchronized startup procedure,\n`start_link/3,4` does not return until [`Module:init/1`](`c:init/1`)\nhas returned or failed.\n\n[`ServerName`](`t:server_name/0`) specifies with what name\nand now to register the server name. See type `t:server_name/0`\nfor different name registrations.\n\n`Module` is the name of the callback module.\n\n`Args` is any term that is passed as the argument to\n[`Module:init/1`](`c:init/1`).\n\nSee type `t:start_opt/0` for `Options` for starting\nthe `gen_server` process.\n\nSee type `t:start_ret/0` for a description this function's return values.\n\nIf `start_link/3,4` returns `ignore` or `{error, _}`,\nthe started `gen_server` process has terminated. If an `'EXIT'` message\nwas delivered to the calling process (due to the process link),\nthat message has been consumed.\n\n> #### Warning {: .warning }\n>\n> Before OTP 26.0, if the started `gen_server` process returned e.g.\n> `{stop, Reason}` from [`Module:init/1`](`c:init/1`), this function\n> could return `{error, Reason}` _before_ the started `m:gen_server` process\n> had terminated so starting again might fail because VM resources\n> such as the registered name was not yet unregistered. An `'EXIT'` message\n> could arrive later to the process calling this function.\n>\n> But if the started `gen_server` process instead failed during\n> [`Module:init/1`](`c:init/1`), a process link `{'EXIT', Pid, Reason}`\n> message caused this function to return `{error, Reason}`,\n> so the `'EXIT'` message had been consumed and the started\n> `m:gen_server` process had terminated.\n>\n> Since it was impossible to tell the difference between these two cases\n> from `start_link/3,4`'s return value, this inconsistency was cleaned up\n> in OTP 26.0.\n\nThe difference between returning `{stop, _}` and `{error, _}` from\n[`Module:init/1`](`c:init/1`), is that `{error, _}` results in a graceful\n(\"silent\") termination since the `gen_server` process exits\nwith reason `normal`.","title":"gen_server.start_link/4","ref":"gen_server.html#start_link/4"},{"type":"function","doc":"Start a server, monitored but neither linked nor registered.\n\nEquivalent to `start_monitor/4` except that the `gen_server` process\nis not registered with any [name service](`t:server_name/0`).","title":"gen_server.start_monitor/3","ref":"gen_server.html#start_monitor/3"},{"type":"function","doc":"Start a server, monitored and registered, but not linked.\n\nCreates a standalone `gen_server` process, that is,\na `gen_server` process that is not part of a supervision tree\n(and thus has no supervisor) and atomically sets up a monitor\nto the newly created server.\n\nOther than that see [`start_link/3,4`](`start_link/3`).\nNote that the return value for a successful start differs in that\nit returns a monitor `reference`. See type `t:start_mon_ret/0`.\n\nIf the start is not successful, the caller will be blocked\nuntil the monitor's `'DOWN'` message has been received\nand removed from the message queue.","title":"gen_server.start_monitor/4","ref":"gen_server.html#start_monitor/4"},{"type":"function","doc":"","title":"gen_server.stop/1","ref":"gen_server.html#stop/1"},{"type":"function","doc":"Stop a server.\n\nOrders the generic server specified by `ServerRef` to exit\nwith the specified `Reason` and waits for it to terminate.\nThe `gen_server` process calls [`Module:terminate/2`](`c:terminate/2`)\nbefore exiting.\n\nThe function returns `ok` if the server terminates\nwith the expected reason. Any other reason than `normal`, `shutdown`,\nor `{shutdown,Term}` causes an error report to be issued using `m:logger`.\nAn exit signal with the same reason is sent to linked processes and ports.\n\n`Timeout` is an integer that specifies how many milliseconds to wait\nfor the server to terminate, or the atom `infinity` to wait indefinitely.\nIf the server has not terminated within the specified time,\nthe call exits the calling process with reason `timeout`.\n\nIf the process does not exist, the call exits the calling process\nwith reason `noproc`, or with reason `{nodedown,Node}`\nif the connection fails to the remote `Node` where the server runs.","title":"gen_server.stop/3","ref":"gen_server.html#stop/3"},{"type":"callback","doc":"Handle server termination.\n\nThis function is called by a `gen_server` process\nwhen it is about to terminate.\n\nIt is to be the opposite of [`Module:init/1`](`c:init/1`)\nand do any necessary cleaning up. When it returns,\nthe `gen_server` process terminates with `Reason`.\nThe return value is ignored.\n\n`Reason` is a term denoting the stop reason and `State`\nis the internal state of the `gen_server` process.\n\n`Reason` depends on why the `gen_server` process is terminating.\nIf it is because another callback function has returned a stop tuple\n`{stop,..}`, `Reason` has the value specified in that tuple.\nIf it is because of a failure, `Reason` is the error reason.\n\nIf the `gen_server` process is part of a supervision tree\nand is ordered by its supervisor to terminate, this function is called\nwith `Reason=shutdown` if the following conditions apply:\n\n- The `gen_server` process has been set to trap exit signals.\n- The shutdown strategy as defined in the child specification\n of the supervisor is an integer time-out value, not `brutal_kill`.\n\nEven if the `gen_server` process is _not_ part of a supervision tree,\nthis function is called if it receives an `'EXIT'` message from its parent.\n`Reason` is the same as in the `'EXIT'` message.\n\nIf the `gen_server` process does not trap exits,\nthe `gen_server` process terminates immediately.\n\nNotice that for any other reason than `normal`, `shutdown`, or\n`{shutdown,Term}`, see `stop/3`, the `gen_server` process is assumed\nto terminate because of an error, and an error report is issued\nusing `m:logger`.\n\nWhen the gen_server process exits, an exit signal with the same reason\nis sent to linked processes and ports.\n\n> #### Note {: .info }\n>\n> This callback is optional, so callback modules need not export it.\n> The `gen_server` module provides a default implementation\n> with no cleanup.","title":"gen_server.terminate/2","ref":"gen_server.html#c:terminate/2"},{"type":"function","doc":"Wait for a request response.\n\nWait for the response to the request identifier `ReqId`. The request\nmust have been made by `send_request/2`, and it must have been made\nby the same process calling this function.\n\n`WaitTime` specifies how long to wait for a reply.\nIf no reply is received within the specified time,\nthe function returns `timeout` and no cleanup is done.\nThus the function can be invoked repeatedly until a reply is returned.\n\nThe return value `Reply` is passed from the return value of\n[`Module:handle_call/3`](`c:handle_call/3`).\n\nThe function returns an error if the `gen_server`\ndied before a reply was sent.\n\nThe difference between `receive_response/2` and\n`wait_response/2` is that `receive_response/2` abandons\nthe request at time-out so that a potential future response is ignored,\nwhile [`wait_response/2`](`wait_response/2`) does not.","title":"gen_server.wait_response/2","ref":"gen_server.html#wait_response/2"},{"type":"function","doc":"Wait for any request response in a collection.\n\nWait for a response in a `ReqIdCollection`. All request identifiers\nof `ReqIdCollection` must correspond to requests that have been made\nusing `send_request/2` or `send_request/4`, and all requests\nmust have been made by the process calling this function.\n\nThe `Label` in the response is the `Label` associated with\nthe request identifier that the response corresponds to.\nThe `Label` of a request identifier is associated\nwhen [adding the request id](`reqids_add/3`) to a collection,\nor when sending the request using `send_request/4`.\n\nCompared to `wait_response/2`, the returned result or exception\nassociated with a specific request identifier will be wrapped\nin a 3-tuple `{Response, Label, NewReqIdCollection}`.\n`Response` is the value that would have been produced\nby `wait_response/2`, `Label` is the value associated with\nthe specific [request identifier](`t:request_id/0`)\nand `NewReqIdCollection` is a possibly modified\nrequest identifier collection.\n\nIf `ReqIdCollection` is empty, `no_request` will be returned.\n\nIf no response is received before `WaitTime` has expired,\n`timeout` is returned. It is valid to continue waiting\nfor a response as many times as needed up until a response\nhas been received and completed by `check_response()`,\n`receive_response()`, or `wait_response()`.\n\nThe difference between `receive_response/3` and `wait_response/3`\nis that `receive_response/3` abandons requests at time-out\nso that potential future responses are ignored, while\n`wait_response/3` does not.\n\nIf `Delete` is `true`, the association with `Label`\nhas been deleted from `ReqIdCollection` in the resulting\n`NewReqIdCollection`. If `Delete` is `false`, `NewReqIdCollection`\nwill equal `ReqIdCollection`. Note that deleting an association\nis not for free and that a collection containing already handled\nrequests can still be used by subsequent calls to\n`wait_response/3`, `check_response/3`, and `receive_response/3`.\n\nHowever, without deleting handled associations, the above\ncalls will not be able to detect when there are\nno more outstanding requests to handle, so you will have to keep track\nof this some other way than relying on a `no_request` return.\nNote that if you pass a collection only containing\nassociations of already handled or abandoned requests\nto this function, it will always block until `WaitTime` expires\nand then return `timeout`.","title":"gen_server.wait_response/3","ref":"gen_server.html#wait_response/3"},{"type":"type","doc":"Server start options for the [`start`](`start_link/4`) or\n[`enter_loop`](`enter_loop/5`) functions.\n\nOptions that can be used when starting a `gen_server` server through\n[`enter_loop/3-5`](`enter_loop/5`) or the start functions such as\n[`start_link/3,4`](`start_link/4`).\n\n- **`{hibernate_after, HibernateAfterTimeout}`** - Specifies that the\n `gen_server` process awaits any message for `HibernateAfterTimeout`\n milliseconds and if no message is received, the process goes into\n hibernation automatically (by calling `proc_lib:hibernate/3`).\n\n- **`{debug, Dbgs}`** - For every entry in `Dbgs`,\n the corresponding function in `m:sys` is called.","title":"gen_server.enter_loop_opt/0","ref":"gen_server.html#t:enter_loop_opt/0"},{"type":"type","doc":"A map that describes the `gen_server` status.\n\nThe keys are:\n- **`state`** - The internal state of the `gen_server` process.\n- **`message`** - The message that caused the server to terminate.\n- **`reason`** - The reason that caused the server to terminate.\n- **`log`** - The [sys log](`sys:log/2`) of the server.\n\nNew associations may be added to the status map without prior notice.","title":"gen_server.format_status/0","ref":"gen_server.html#t:format_status/0"},{"type":"type","doc":"A call's reply destination.\n\nDestination, given to the `gen_server` as the first argument\nto the callback function [`Module:handle_call/3`](`c:handle_call/3`),\nto be used by the when replying through `reply/2` (instead of\nthrough the callback function's return value), to the process `Client`\nthat has called the `gen_server` using [`call/2,3`](`call/2`).\n`Tag` is a term that is unique for this call/request instance.","title":"gen_server.from/0","ref":"gen_server.html#t:from/0"},{"type":"opaque","doc":"A handle that associates a reply to the corresponding request.","title":"gen_server.reply_tag/0","ref":"gen_server.html#t:reply_tag/0"},{"type":"opaque","doc":"An opaque request identifier. See `send_request/2` for details.","title":"gen_server.request_id/0","ref":"gen_server.html#t:request_id/0"},{"type":"opaque","doc":"An opaque collection of request identifiers (`t:request_id/0`).\n\nEach request identifier can be associated with a label\nchosen by the user. For more information see `reqids_new/0`.","title":"gen_server.request_id_collection/0","ref":"gen_server.html#t:request_id_collection/0"},{"type":"type","doc":"Response time-out for an asynchronous call.\n\nUsed to set a time limit on how long to wait for a response using either\n`receive_response/2`, `receive_response/3`, `wait_response/2`, or\n`wait_response/3`. The time unit used is `millisecond`.\n\nCurrently valid values:\n\n- **`0..4294967295`** - Time-out relative to current time in milliseconds.\n\n- **`infinity`** - Infinite time-out. That is,\n the operation will never time out.\n\n- **`{abs, Timeout}`** - An absolute\n [Erlang monotonic time](`erlang:monotonic_time/1`)\n time-out in milliseconds. That is, the operation will time out when\n [`erlang:monotonic_time(millisecond)`](`erlang:monotonic_time/1`)\n returns a value larger than or equal to `Timeout`.\n `Timeout` is not allowed to identify a time further into the future\n than `4294967295` milliseconds. Specifying the time-out\n using an absolute value is especially handy when you have\n a deadline for responses corresponding to a complete collection\n of requests (`t:request_id_collection/0`), since you do not have to\n recalculate the relative time until the deadline over and over again.","title":"gen_server.response_timeout/0","ref":"gen_server.html#t:response_timeout/0"},{"type":"type","doc":"Server name specification: `local`, `global`, or `via` registered.\n\nTo be used when starting a `gen_server`. See functions\n[`start/3,4`](`start/3`),\n[`start_link/3,4`](`start_link/3`),\n[`start_monitor/3,4`](`start_monitor/3`),\n[`enter_loop/3,4,5`](`enter_loop/3`), and the type `t:server_ref/0`.\n\n- **`{local, LocalName}`** - Register the `gen_server` locally\n as `LocalName` using [`register/2`](`erlang:register/2`).\n\n- **`{global, GlobalName}`** - Register the `gen_server` process id\n globally as `GlobalName` using `global:register_name/2`.\n\n- **`{via, RegMod, ViaName}`** - Register the `gen_server` process\n with the registry represented by `RegMod`. The `RegMod` callback\n is to export the functions `register_name/2`, `unregister_name/1`,\n `whereis_name/1`, and `send/2`, which are to behave like\n the corresponding functions in `m:global`.\n Thus, `{via, global, GlobalName}` is a valid reference\n equivalent to `{global, GlobalName}`.","title":"gen_server.server_name/0","ref":"gen_server.html#t:server_name/0"},{"type":"type","doc":"Server specification: `t:pid/0` or registered `t:server_name/0`.\n\nTo be used when addressing a `gen_server`. See [`call/2,3`](`call/2`),\n`cast/2`, `send_request/2`, `check_response/2`, `wait_response/2`,\n[`stop/2,3`](`stop/1`) and the type `t:server_name/0`.\n\nIt can be:\n\n- **`t:pid/0`** - The `gen_server`'s process identifier.\n\n- **`LocalName`** - The `gen_server` is locally registered\n as `LocalName` with [`register/2`](`erlang:register/2`).\n\n- **`{Name,Node}`** - The `gen_server` is locally registered\n on another node.\n\n- **`{global, GlobalName}`** - The `gen_server` is globally registered\n in `m:global`.\n\n- **`{via, RegMod, ViaName}`** - The `gen_server` is registered\n in an alternative process registry. See the same term\n described for `t:server_name/0`.","title":"gen_server.server_ref/0","ref":"gen_server.html#t:server_ref/0"},{"type":"type","doc":"Return value from the [`start_monitor/3,4`](`start_monitor/3`) functions.\n\nThe same as type `t:start_ret/0` except that for a succesful start\nit returns both the process identifier `Pid`\nand a [`monitor/2,3`](`erlang:monitor/2`) [`MonRef`](`t:reference/0`).","title":"gen_server.start_mon_ret/0","ref":"gen_server.html#t:start_mon_ret/0"},{"type":"type","doc":"Server start options for the [`start` functions](`start_link/3`).\n\nOptions that can be used when starting a `gen_server` server through,\nfor example, [`start_link/3,4`](`start_link/4`).\n\n- **`{timeout, Timeout}`** - How many milliseconds\n the `gen_server` process is allowed to spend initializing\n or it is terminated and the start function returns `{error, timeout}`.\n\n- **`{spawn_opt, SpawnOptions}`** - The `SpawnOptions` option list\n is passed to the function used to spawn the `gen_server`;\n see `t:proc_lib:start_spawn_option/0`).\n\n > #### Note {: .info }\n >\n > Using spawn option `monitor` is not allowed -\n > it causes a `badarg` failure.\n\n- **`t:enter_loop_opt/0`** - See the type `t:enter_loop_opt/0`\n below for more start options that are also allowed\n by [`enter_loop/3,4,5`](`enter_loop/3`).","title":"gen_server.start_opt/0","ref":"gen_server.html#t:start_opt/0"},{"type":"type","doc":"Return value from the [`start/3,4`](`start/3`) and\n[`start_link/3,4`](`start_link/3`) functions.\n\n- **`{ok, Pid}`** - The `gen_server` process was succesfully created and\n initialized, with the process identifier `Pid`.\n\n- **`{error, {already_started, OtherPid}}`** - A process with the specified\n `ServerName` exists already with the process identifier `OtherPid`.\n This function failed to start a `gen_server`. It exited with reason\n `normal` before calling [`Module:init/1`](`c:init/1`).\n\n- **`{error, timeout}`** - The `gen_server` process failed to initialize\n since [`Module:init/1`](`c:init/1`) did not return within the\n [start time-out](`t:start_opt/0`). The `gen_server` process was killed\n with [`exit(_, kill)`](`erlang:exit/2`).\n\n- **`ignore`** - The `gen_server` process failed to initialize since\n [`Module:init/1`](`c:init/1`) returned `ignore`.\n\n- **`{error,Reason}`** - The `gen_server` process failed to initialize since\n [`Module:init/1`](`c:init/1`) returned `{stop,Reason}`, `{error,Reason}`,\n or it failed with reason `Reason`.\n\nSee [`Module:init/1`](`c:init/1`) about the exit reason\nfor the `gen_server` process when it fails to initialize.","title":"gen_server.start_ret/0","ref":"gen_server.html#t:start_ret/0"},{"type":"behaviour","doc":"Generic state machine behavior.\n\n`gen_statem` provides a generic state machine behaviour\nthat since Erlang/OTP 20.0 replaces its predecessor `m:gen_fsm`,\nand should be used for new code. The `gen_fsm` behaviour\nremains in OTP \"as is\" to not break old code using it.\n\nA generic state machine server process (`gen_statem`) implemented\nusing this module has a standard set of interface functions\nand includes functionality for tracing and error reporting.\nIt also fits into an OTP supervision tree. For more information,\nsee [OTP Design Principles](`e:system:statem.md`).\n\n> #### Note {: .info }\n>\n> If you are new to `gen_statem` and want an overview\n> of concepts and operation the section\n> [`gen_statem` Behaviour](`e:system:statem.md`) located in\n> the User's Guide [OTP Design Principles](`e:system:index.html`)\n> is recommended to read. This reference manual focuses on\n> being correct and complete, which might make it hard to see\n> the forest for all the trees.\n\n#### Features\n\n`gen_statem` has got the same features that `m:gen_fsm` had\nand adds some really useful:\n\n- [Co-located state code](#state_functions)\n- [Arbitrary term state](#handle_event_function)\n- [Event postponing](#event-postponing)\n- [Self-generated events](#event-insertion)\n- [State time-out](`t:state_timeout/0`)\n- [Multiple generic named time-outs](`t:generic_timeout/0`)\n- [Absolute time-out time](`t:timeout_option/0`)\n- [Automatic state enter calls](#state-enter-calls)\n- [Reply from other state than the request](#reply-to-a-call),\n traceable with `m:sys`\n- [Multiple replies](#reply-to-a-call), traceable with `m:sys`\n- [Changing the callback module](#change_callback_module)\n\nTwo [_callback modes_](`t:callback_mode/0`) are supported:\n\n- `state_functions` - for finite-state machines (`m:gen_fsm` like),\n which requires the state to be an atom and uses that state\n as the name of the current callback function, arity 3.\n- `handle_event_function` - that allows the state to be any term\n and that uses `c:handle_event/4` as callback function for all states.\n\nThe callback modes for `gen_statem` differs from the one for\n`gen_fsm`, but it is still fairly easy to\nrewrite from `gen_fsm` to `gen_statem`. See the\n[rewrite guide](`m:gen_fsm#module-migration-to-gen_statem`)\nat the start of the `m:gen_fsm` documentation.\n\n#### Callback module\n\nA `gen_statem` assumes all specific parts to be located\nin a callback module exporting a predefined set of functions.\nThe relationship between the behavior functions\nand the callback functions is as follows:\n\n```\ngen_statem module Callback module\n----------------- ---------------\ngen_statem:start\ngen_statem:start_monitor\ngen_statem:start_link -----> Module:init/1\n\nServer start or code change\n -----> Module:callback_mode/0\n selects callback mode\n\ngen_statem:stop\nSupervisor exit\nCallback failure -----> Module:terminate/3\n\ngen_statem:call\ngen_statem:cast\ngen_statem:send_request\nerlang:send\nerlang:'!' -----> Module:StateName/3\n or -----> Module:handle_event/4\n depending on callback mode\n\nRelease upgrade/downgrade\n(code change)\n -----> Module:code_change/4\n```\n\n#### State callback {: #state-callback }\n\nThe _state callback_ for a specific [state](`t:state/0`) in a `gen_statem`\nis the callback function that is called for all events in this state.\nIt is selected depending on which [_callback mode_](`t:callback_mode/0`)\nthat the callback module defines with the callback function\n[`Module:callback_mode/0`](`c:callback_mode/0`).\n\n[](){: #state_functions }\nWhen the [_callback mode_](`t:callback_mode/0`) is `state_functions`,\nthe state must be an atom and is used as the _state callback_ name;\nsee [`Module:StateName/3`](`c:'StateName'/3`). This co-locates all code\nfor a specific state in one function as the `gen_statem` engine branches\ndepending on state name. Note the fact that the callback function\n[`Module:terminate/3`](`c:terminate/3`) makes the state name `terminate`\nunusable in this mode.\n\n[](){: #handle_event_function }\nWhen the [_callback mode_](`t:callback_mode/0`) is `handle_event_function`,\nthe state can be any term and the _state callback_ name is\n[`Module:handle_event/4`](`c:handle_event/4`). This makes it easy\nto branch depending on state or event as you desire. Be careful about\nwhich events you handle in which states so that you do not accidentally\npostpone an event forever creating an infinite busy loop.\n\n#### Event types\n\nEvents are of different [types](`t:event_type/0`),\ntherefore the callback functions can know the origin of an event\nwhen handling it. [External events](`t:external_event_type/0`) are\n`call`, `cast`, and `info`. Internal events are\n[`timeout`](`t:timeout_event_type/0`) and `internal`.\n\n#### Event handling\n\nWhen `gen_statem` receives a process message it is transformed\ninto an event and the [_state callback_](#state-callback)\nis called with the event as two arguments: type and content. When the\n[_state callback_](#state-callback) has processed the event\nit returns to `gen_statem` which does a _state transition_. If this\n_state transition_ is to a different state, that is: `NextState =/= State`,\nit is a _state change_.\n\n#### Transition actions\n\nThe [_state callback_](#state-callback) may return\n[_transition actions_](`t:action/0`) for `gen_statem` to execute\nduring the _state transition_, for example to set a time-out\nor reply to a call.\n\n#### Reply to a call {: #reply-to-a-call }\n\nSee [`gen_statem:call/2,3`](#call-reply) about how to reply\nto a call. A reply can be sent from any _state callback_,\nnot just the one that got the request event.\n\n#### Event postponing {: #event-postponing }\n\nOne of the possible _transition actions_ is to postpone the current event.\nThen it will not be handled in the current state. The `gen_statem` engine\nkeeps a queue of events divided into postponed events and\nevents still to process (not presented yet). After a _state change_\nthe queue restarts with the postponed events.\n\nThe `gen_statem` event queue model is sufficient to emulate\nthe normal process message queue with selective receive.\nPostponing an event corresponds to not matching it\nin a receive statement, and changing states corresponds to\nentering a new receive statement.\n\n#### Event insertion {: #event-insertion }\n\nThe [_state callback_](#state-callback) can insert\nevents using the [_transition action_](`t:action/0`) `next_event`,\nand such an event is inserted in the event queue as the next to call the\n[_state callback_](#state-callback) with. That is,\nas if it is the oldest incoming event. A dedicated `t:event_type/0`\n`internal` can be used for such events making it possible to\nsafely distinguish them from external events.\n\nInserting an event replaces the trick of calling your own state handling\nfunctions that you often would have to resort to in, for example,\n`m:gen_fsm` to force processing an inserted event before others.\n\n> #### Note {: .info }\n>\n> If you postpone an event and (against good practice) directly call\n> a different _state callback_, the postponed event is not retried,\n> since there was no _state change_.\n>\n> Instead of directly calling a _state callback_, do a _state change_.\n> This makes the `gen_statem` engine retry postponed events.\n>\n> Inserting an event in a _state change_ also triggers\n> the new _state callback_ to be called with that event\n> before receiving any external events.\n\n#### State enter calls {: #state-enter-calls }\n\nThe `gen_statem` engine can automatically make a special call to the\n[_state callback_](#state-callback) whenever a new state is\nentered; see `t:state_enter/0`. This is for writing code common\nto all state entries. Another way to do it is to explicitly insert\nan event at the _state transition_, and/or to use a dedicated\n_state transition_ function, but that is something you will have to\nremember at every _state transition_ to the state(s) that need it.\n\nFor the details of a _state transition_, see type `t:transition_option/0`.\n\n#### Hibernation\n\nThe `gen_statem` process can go into hibernation;\nsee `proc_lib:hibernate/3`. It is done when\na [_state callback_](#state-callback) or\n[`Module:init/1`](`c:init/1`) specifies `hibernate`\nin the returned [`Actions`](`t:enter_action/0`) list. This feature\ncan be useful to reclaim process heap memory while the server\nis expected to be idle for a long time. However, use it with care,\nas hibernation can be too costly to use after every event;\nsee `erlang:hibernate/3`.\n\nThere is also a server start option\n[`{hibernate_after, Timeout}`](`t:enter_loop_opt/0`)\nfor [`start/3,4`](`start/3`), [`start_link/3,4`](`start_link/3`),\n[`start_monitor/3,4`](`start_monitor/3`),\nor [`enter_loop/4,5,6`](`enter_loop/6`), that may be used\nto automatically hibernate the server.\n\n#### Callback failure\n\nIf a callback function fails or returns a bad value,\nthe `gen_statem` terminates. However, an exception of class\n[`throw`](`erlang:throw/1`) is not regarded as an error\nbut as a valid return, from all callback functions.\n\n#### System messages and the `m:sys` module\n\nA `gen_statem` handles system messages as described in `m:sys`.\nThe `m:sys` module can be used for debugging a `gen_statem`.\nReplies sent through [_transition actions_](`t:action/0`)\ngets logged, but not replies sent through [`reply/1,2`](`reply/2`).\n\n#### Trapping exit\n\nA `gen_statem` process, like all `gen_`\\* behaviours,\ndoes not trap exit signals automatically;\nthis must be explicitly initiated in the callback module\n(by calling [`process_flag(trap_exit, true)`](`erlang:process_flag/2`)\npreferably from `c:init/1`.\n\n#### Server termination\n\nIf the `gen_statem` process terminates, e.g. as a result\nof a callback function returning `{stop, Reason}`, an exit signal\nwith this `Reason` is sent to linked processes and ports.\nSee [Processes](`e:system:ref_man_processes.md#errors`)\nin the Reference Manual for details regarding error handling\nusing exit signals.\n\n> #### Note {: .info }\n>\n> For some important information about distributed signals, see the\n> [_Blocking Signaling Over Distribution_\n> ](`e:system:ref_man_processes.md#blocking-signaling-over-distribution`)\n> section in the _Processes_ chapter of the _Erlang Reference Manual_.\n> Blocking signaling can, for example, cause call time-outs in `gen_statem`\n> to be significantly delayed.\n\n#### Bad argument\n\nUnless otherwise stated, all functions in this module fail if the specified\n`gen_statem` does not exist or if bad arguments are specified.","title":"gen_statem","ref":"gen_statem.html"},{"type":"behaviour","doc":"The following example shows a simple pushbutton model\nfor a toggling pushbutton implemented with\n[_callback mode_](`t:callback_mode/0`) `state_functions`.\nYou can push the button and it replies if it went on or off,\nand you can ask for a count of how many times it has been pushed\nto switch on.","title":"Example - gen_statem","ref":"gen_statem.html#module-example"},{"type":"behaviour","doc":"```mermaid\n---\ntitle: Pushbutton State Diagram\n---\nstateDiagram-v2\n [*] --> off\n off --> on : push\\n* Increment count\\n* Reply 'on'\n on --> off : push\\n* Reply 'off'\n```\n\nNot shown in the state diagram:\n* The API function `push()` generates an event `push` of type `call`.\n* The API function `get_count()` generates an event `get_count`\n of type `call` that is handled in all states by replying with\n the current count value.\n* Unknown events are ignored and discarded.\n* There is boilerplate code for start, stop, terminate, code change,\n init, to set the callback mode to `state_functions`, etc...","title":"Pushbutton State Diagram - gen_statem","ref":"gen_statem.html#module-pushbutton-state-diagram"},{"type":"behaviour","doc":"The following is the complete callback module file `pushbutton.erl`:\n\n```erlang\n-module(pushbutton).\n-behaviour(gen_statem).\n\n-export([start/0,push/0,get_count/0,stop/0]).\n-export([terminate/3,code_change/4,init/1,callback_mode/0]).\n-export([on/3,off/3]).\n\nname() -> pushbutton_statem. % The registered server name\n\n%% API. This example uses a registered name name()\n%% and does not link to the caller.\nstart() ->\n gen_statem:start({local,name()}, ?MODULE, [], []).\npush() ->\n gen_statem:call(name(), push).\nget_count() ->\n gen_statem:call(name(), get_count).\nstop() ->\n gen_statem:stop(name()).\n\n%% Mandatory callback functions\nterminate(_Reason, _State, _Data) ->\n void.\ncode_change(_Vsn, State, Data, _Extra) ->\n {ok,State,Data}.\ninit([]) ->\n %% Set the initial state + data. Data is used only as a counter.\n State = off, Data = 0,\n {ok,State,Data}.\ncallback_mode() -> state_functions.\n\n%%% state callback(s)\n\noff({call,From}, push, Data) ->\n %% Go to 'on', increment count and reply\n %% that the resulting status is 'on'\n {next_state,on,Data+1,[{reply,From,on}]};\noff(EventType, EventContent, Data) ->\n handle_event(EventType, EventContent, Data).\n\non({call,From}, push, Data) ->\n %% Go to 'off' and reply that the resulting status is 'off'\n {next_state,off,Data,[{reply,From,off}]};\non(EventType, EventContent, Data) ->\n handle_event(EventType, EventContent, Data).\n\n%% Handle events common to all states\nhandle_event({call,From}, get_count, Data) ->\n %% Reply with the current count\n {keep_state,Data,[{reply,From,Data}]};\nhandle_event(_, _, Data) ->\n %% Ignore all other events\n {keep_state,Data}.\n```\n\nThe following is a shell session when running it:\n\n```erlang\n1> pushbutton:start().\n{ok,<0.36.0>}\n2> pushbutton:get_count().\n0\n3> pushbutton:push().\non\n4> pushbutton:get_count().\n1\n5> pushbutton:push().\noff\n6> pushbutton:get_count().\n1\n7> pushbutton:stop().\nok\n8> pushbutton:push().\n** exception exit: {noproc,{gen_statem,call,[pushbutton_statem,push,infinity]}}\n in function gen:do_for_proc/2 (gen.erl, line 261)\n in call from gen_statem:call/3 (gen_statem.erl, line 386)\n```\n\nTo compare styles, here follows the same example using\n[_callback mode_](`t:callback_mode/0`) `handle_event_function`,\nor rather, the code to replace after function [`init/1`](`c:init/1`)\nof the `pushbutton.erl` example file above:\n\n```erlang\ncallback_mode() -> handle_event_function.\n\n%%% state callback(s)\n\nhandle_event({call,From}, push, off, Data) ->\n %% Go to 'on', increment count and reply\n %% that the resulting status is 'on'\n {next_state,on,Data+1,[{reply,From,on}]};\nhandle_event({call,From}, push, on, Data) ->\n %% Go to 'off' and reply that the resulting status is 'off'\n {next_state,off,Data,[{reply,From,off}]};\n%%\n%% Event handling common to all states\nhandle_event({call,From}, get_count, State, Data) ->\n %% Reply with the current count\n {next_state,State,Data,[{reply,From,Data}]};\nhandle_event(_, _, State, Data) ->\n %% Ignore all other events\n {next_state,State,Data}.\n```\n\n> #### Note {: .info }\n>","title":"Pushbutton Code - gen_statem","ref":"gen_statem.html#module-pushbutton-code"},{"type":"behaviour","doc":"> - This behavior appeared in Erlang/OTP 19.0 as experimental.\n> - In OTP 19.1 a backwards incompatible change of the return tuple from\n> [`Module:init/1`](`c:init/1`) was made,\n> the mandatory callback function\n> [`Module:callback_mode/0`](`c:callback_mode/0`) was introduced,\n> and `enter_loop/4` was added.\n> - In OTP 19.2 [_state enter calls_](`t:state_enter/0`) were added.\n> - In OTP 19.3 [state time-outs](`t:state_timeout/0`) were added.\n> - In OTP 20.0 [generic time-outs](`t:generic_timeout/0`) were added\n> and `gen_statem` was stated to be no longer experimental and\n> preferred over `gen_fsm`.\n> - In OTP 22.1 time-out content [`update`](`t:timeout_update_action/0`)\n> and explicit time-out [`cancel`](`t:timeout_cancel_action/0`)\n> were added.\n> - In OTP 22.3 the possibility to change the callback module with actions\n> [`change_callback_module`](#change_callback_module),\n> [`push_callback_module`](#push_callback_module) and\n> [`pop_callback_module`](#pop_callback_module), was added.\n> - In OTP 23.0 [`start_monitor/3,4`](`start_monitor/3`) were added,\n> as well as functions for asynchronous calls: `send_request/2`,\n> [`wait_response/1,2`](`wait_response/2`), and `check_response/2`.\n> - In OTP 24.0 [`receive_response/1,2`](`receive_response/2`) were added.\n> - In OTP 25.0 [`Module:format_status/1`](`c:format_status/1`)\n> was added to replace [`Module:format_status/2`](`c:format_status/2`),\n> as well as functions for collections of asynchronous calls:\n> `send_request/4`, `wait_response/3`, `receive_response/3`,\n> `check_response/3`, `reqids_new/0`, `reqids_size/1`,\n> `reqids_add/3`, `reqids_to_list/1`.\n> - In OTP 26.0 the possibility to return `{error, Reason}` from\n> [`Module:init/1`](`c:init/1`) was added.\n> - In OTP 27.0 [`Module:format_status/2`](`c:format_status/2`)\n> was deprecated.","title":"API changes - gen_statem","ref":"gen_statem.html#module-api-changes"},{"type":"behaviour","doc":"`m:gen_event`, `m:gen_fsm`, `m:gen_server`, `m:proc_lib`, `m:supervisor`,\n`m:sys`.","title":"See Also - gen_statem","ref":"gen_statem.html#module-see-also"},{"type":"function","doc":"","title":"gen_statem.call/2","ref":"gen_statem.html#call/2"},{"type":"function","doc":"Call a server: send request and wait for response.\n\nMakes a synchronous call to the `gen_statem`\n[`ServerRef`](`t:server_ref/0`) by sending a request\nand waiting until the response arrives.\n\n[](){: #call-reply }\nThe `gen_statem` calls the\n[_state callback_](#state-callback)\nwith `t:event_type/0` `{call, From}` and event content `Request`.\n\nThe server's reply is sent from a [_state callback_](#state-callback),\nby returning a [_transition action_](`t:action/0`) `{reply, From, Reply}`,\ncalling [`reply(Replies)`](`reply/1`) with such a reply action\nin the `Replies` list, or calling [`reply(From, Reply)`](`reply/2`).\n\n`Timeout` is an integer > 0, which specifies how many milliseconds\nto wait for a reply, or the atom `infinity` to wait indefinitely,\nwhich is the default. If no reply is received within the specified time,\nthe function call fails.\n\nPrevious issue with late replies that could occur\nwhen having network issues or using `dirty_timeout`\nis now prevented by use of\n[_process aliases_](`e:system:ref_man_processes.md#process-aliases`).\n`{clean_timeout, T}` and `{dirty_timeout, T}` therefore\nno longer serves any purpose and will work the same as `Timeout`\nwhile all of them also being equally efficient.\n\nThe call can also fail, for example, if the `gen_statem`\ndies before or during this function call.\n\nWhen this call fails it [exits](`erlang:exit/1`)\nthe calling process. The exit term is on the form\n`{Reason, Location}` where `Location = {gen_statem, call, ArgList}`.\nSee [`gen_server:call/3`](`gen_server:call/3`) that has a description\nof relevant values for the `Reason` in the exit term.","title":"gen_statem.call/3","ref":"gen_statem.html#call/3"},{"type":"callback","doc":"Select the _callback mode_ and possibly\n[_state enter calls_](`t:state_enter/0`).\n\nThis function is called by a `gen_statem` when it needs to find out the\n[_callback mode_](`t:callback_mode/0`) of the callback module.\n\nThe value is cached by `gen_statem` for efficiency reasons,\nso this function is only called once after server start,\nafter code change, and after changing the callback module,\nbut before the first [_state callback_](#state-callback)\nin the current callback module's code is called. More occasions may be\nadded in future versions of `gen_statem`.\n\nServer start happens either when [`Module:init/1`](`c:init/1`)\nreturns or when [`enter_loop/4,5,6`](`enter_loop/6`) is called.\nCode change happens when [`Module:code_change/4`](`c:code_change/4`)\nreturns. A change of the callback module happens when\na [_state callback_](#state-callback) returns\nany of the actions [`change_callback_module`](#push_callback_module),\n[`push_callback_module`](#push_callback_module) or\n[`pop_callback_module`](#pop_callback_module).\n\nThe `CallbackMode` is either just `t:callback_mode/0`\nor a list containing `t:callback_mode/0` and possibly\nthe atom [`state_enter`](`t:state_enter/0`).\n\n> #### Note {: .info }\n>\n> If this function's body does not return an inline constant value\n> the callback module is doing something strange.","title":"gen_statem.callback_mode/0","ref":"gen_statem.html#c:callback_mode/0"},{"type":"function","doc":"Cast an event to a server.\n\nSends an asynchronous `cast` event to the `gen_statem`\n[`ServerRef`](`t:server_ref/0`) and returns `ok` immediately,\nignoring if the destination node or `gen_statem` does not exist.\n\nThe `gen_statem` calls the\n[_state callback_](#state-callback)\nwith `t:event_type/0` `cast` and event content `Msg`.","title":"gen_statem.cast/2","ref":"gen_statem.html#cast/2"},{"type":"function","doc":"Check if a received message is a request response.\n\nChecks if `Msg` is a response corresponding to\nthe request identifier `ReqId`. The request must have been made\nby `send_request/2` and by the same process calling this function.\n\nIf `Msg` is a reply to the handle `ReqId` the result of the request\nis returned in `Reply`. Otherwise this function returns `no_reply`\nand no cleanup is done, and thus the function shall be invoked repeatedly\nuntil the response is returned.\n\nSee [`call/3`](#call-reply) about how the request is handled\nand the `Reply` is sent by the `gen_statem` server.\n\nIf the `gen_statem` server process has died when this function\nis called, that is; `Msg` reports the server's death,\nthis function returns an `error` return with the exit `Reason`.","title":"gen_statem.check_response/2","ref":"gen_statem.html#check_response/2"},{"type":"function","doc":"Check if a received message is a request response in a collection.\n\nCheck if `Msg` is a response corresponding to a request identifier\nstored in `ReqIdCollection`. All request identifiers of `ReqIdCollection`\nmust correspond to requests that have been made using `send_request/2`\nor `send_request/4`, by the process calling this function.\n\nThe `Label` in the response equals the `Label` associated\nwith the request identifier that the response corresponds to.\nThe `Label` of a request identifier is associated\nwhen [storing the request id](`reqids_add/3`) in a collection,\nor when sending the request using `send_request/4`.\n\nCompared to `check_response/2`, the returned result or exception\nassociated with a specific request identifier will be wrapped\nin a 3-tuple `{Response, Label, NewReqIdCollection}`.\n`Response` is the value that would have been produced\nby `check_response/2`, `Label` is the value associated with\nthe specific [request identifier](`t:request_id/0`)\nand `NewReqIdCollection` is a possibly modified\nrequest identifier collection.\n\nIf `ReqIdCollection` is empty, `no_request` is returned.\n\nIf `Msg` does not correspond to any of the request identifiers\nin `ReqIdCollection`, `no_reply` is returned.\n\nIf `Delete` equals `true`, the association with `Label`\nhas been deleted from `ReqIdCollection` in the resulting\n`NewReqIdCollection`. If `Delete` is `false`, `NewReqIdCollection`\nwill equal `ReqIdCollection`. Note that deleting an association\nis not for free and that a collection containing already handled\nrequests can still be used by subsequent calls to\n`wait_response/3`, `check_response/3`, and `receive_response/3`.\n\nHowever, without deleting handled associations,\nthe above calls will not be able to detect when there are\nno more outstanding requests to handle, so you will have to keep track\nof this some other way than relying on a `no_request` return.\nNote that if you pass a collection only containing\nassociations of already handled or abandoned requests to\nthis function, it will always return `no_reply`.","title":"gen_statem.check_response/3","ref":"gen_statem.html#check_response/3"},{"type":"callback","doc":"Update the [state](`t:state/0`) and [data](`t:data/0`)\nafter code change.\n\nThis function is called by a `gen_statem` when it is to update\nits internal state during a release upgrade/downgrade, that is,\nwhen the instruction `{update, Module, Change, ...}`,\nwhere `Change = {advanced, Extra}`, is specified in\nthe [`appup`](`e:sasl:appup.md`) file. For more information, see\n[OTP Design Principles](`e:system:release_handling.md#instr`).\n\nFor an upgrade, `OldVsn` is `Vsn`, and for a downgrade, `OldVsn` is\n`{down, Vsn}`. `Vsn` is defined by the `vsn` attribute(s)\nof the old version of the callback module `Module`.\nIf no such attribute is defined, the version is the checksum\nof the Beam file.\n\n`OldState` and `OldData` is the internal state of the `gen_statem`.\n\n`Extra` is passed \"as is\" from the `{advanced, Extra}` part\nof the update instruction.\n\nIf successful, the function must return the updated internal state\nin an `{ok, NewState, NewData}` tuple.\n\nIf the function returns a failure `Reason`, the ongoing upgrade fails\nand rolls back to the old release. Note that `Reason` cannot be\nan `{ok, _, _}` tuple since that will be regarded\nas a `{ok, NewState, NewData}` tuple, and that a tuple matching `{ok, _}`\nis an also invalid failure `Reason`. It is recommended to use\nan atom as `Reason` since it will be wrapped in an `{error, Reason}` tuple.\n\nAlso note when upgrading a `gen_statem`, this function and hence the\n`Change = {advanced, Extra}` parameter\nin the [`appup`](`e:sasl:appup.md`) file is not only needed\nto update the internal state or to act on the `Extra`\nargument. It is also needed if an upgrade or downgrade should change\n[_callback mode_](`t:callback_mode/0`), or else the _callback mode_\nafter the code change will not be honoured, most probably causing\na server crash.\n\nIf the server changes callback module using any of the actions\n[`change_callback_module`](#change_callback_module),\n[`push_callback_module`](#push_callback_module), or\n[`pop_callback_module`](#pop_callback_module), be aware that it is always\nthe current callback module that will get this callback call.\nThat the current callback module handles the current\nstate and data update should be no surprise, but it\nmust be able to handle even parts of the state and data\nthat it is not familiar with, somehow.\n\nIn the supervisor\n[child specification](`e:system:sup_princ.md#child-specification`)\nthere is a list of modules which is recommended to contain\nonly the callback module. For a `gen_statem`\nwith multiple callback modules there is no real need to list\nall of them, it may not even be possible since the list could change\nafter code upgrade. If this list would contain only\nthe start callback module, as recommended, what is important\nis to upgrade _that_ module whenever\na _synchronized code replacement_ is done.\nThen the release handler concludes that\nan upgrade that upgrades _that_ module needs to suspend,\ncode change, and resume any server whose child specification declares\nthat it is using _that_ module.\nAnd again; the _current_ callback module will get the\n[`Module:code_change/4`](`c:code_change/4`) call.\n\n> #### Note {: .info }\n>\n> If a release upgrade/downgrade with `Change = {advanced, Extra}`\n> specified in the `.appup` file is made\n> when [`Module:code_change/4`](`c:code_change/4`) is not implemented\n> the process will crash with exit reason `undef`.","title":"gen_statem.code_change/4","ref":"gen_statem.html#c:code_change/4"},{"type":"function","doc":"","title":"gen_statem.enter_loop/4","ref":"gen_statem.html#enter_loop/4"},{"type":"function","doc":"Make the calling process become a `gen_statem` server.\n\nWith argument `Actions`, equivalent to\n[`enter_loop(Module, Opts, State, Data, self(), Actions)`](`enter_loop/6`).\n\nOtherwise equivalent to\n[`enter_loop(Module, Opts, State, Data, Server, [])`](`enter_loop/6`).","title":"gen_statem.enter_loop/5","ref":"gen_statem.html#enter_loop/5"},{"type":"function","doc":"Make the calling process become a `gen_statem` server.\n\nDoes not return, instead the calling process enters the `gen_statem`\nreceive loop and becomes a `gen_statem` server. The process\n_must_ have been started using one of the start functions\nin `m:proc_lib`. The user is responsible for any initialization\nof the process, including registering a name for it.\n\nThis function is useful when a more complex initialization procedure\nis needed than the `gen_statem` [`Module:init/1`](`c:init/1`)\ncallback offers.\n\n`Module` and `Opts` have the same meanings as when calling\n[`start[link | monitor]/3,4`](`start_link/3`).\n\nIf `Server` is `self/0` an anonymous server is created just as when using\n[`start[link |_monitor]/3`](`start_link/3`). If `Server`\nis a `t:server_name/0` a named server is created just as when using\n[`start[link |_monitor]/4`](`start_link/4`). However,\nthe `t:server_name/0` name must have been registered accordingly\n_before_ this function is called.\n\n`State`, `Data`, and `Actions` have the same meanings\nas in the return value of [`Module:init/1`](`c:init/1`).\nAlso, the callback module does not need to export\na [`Module:init/1`](`c:init/1`) function.\n\nThe function fails if the calling process was not started\nby a `m:proc_lib` start function, or if it is not registered\naccording to `t:server_name/0`.","title":"gen_statem.enter_loop/6","ref":"gen_statem.html#enter_loop/6"},{"type":"callback","doc":"Format/limit the status value.\n\nThis function is called by a `gen_statem` process\nin order to format/limit the server status\nfor debugging and logging purposes.\n\nIt is called in the following situations:\n\n- [`sys:get_status/1,2`](`sys:get_status/1`) is invoked\n to get the `gen_statem` status.\n- The `gen_statem` process terminates abnormally and logs an error.\n\nThis function is useful for changing the form and appearance\nof the `gen_statem` status for these cases. A callback module\nwishing to change the [`sys:get_status/1,2`](`sys:get_status/1`)\nreturn value and how its status appears in termination error logs,\nexports an instance of [`Module:format_status/1`](`c:format_status/1`),\nwhich will get a map `Status` that describes the current state\nof the `gen_statem`, and shall return a map `NewStatus`\ncontaining the same keys as the input map,\nbut it may transform some values.\n\nOne use case for this function is to return compact alternative state\nrepresentations to avoid having large state terms printed in log files.\nAnother is to hide sensitive data from being written to the error log.\n\nExample:\n\n```erlang\nformat_status(Status) ->\n maps:map(\n fun(state,State) ->\n maps:remove(private_key, State);\n (message,{password, _Pass}) ->\n {password, removed};\n (_,Value) ->\n Value\n end, Status).\n```\n\n> #### Note {: .info }\n>\n> This callback is optional, so a callback module does not need\n> to export it. The `gen_statem` module provides\n> a default implementation of this function that returns `{State, Data}`.\n>\n> If this callback is exported but fails, to hide possibly sensitive data,\n> the default function will instead return `{State, Info}`,\n> where `Info` says nothing but the fact that\n> [`Module:format_status/2`](`c:format_status/2`) has crashed.","title":"gen_statem.format_status/1","ref":"gen_statem.html#c:format_status/1"},{"type":"callback","doc":"Format/limit the status value.\n\nThis function is called by a `gen_statem` process\nin in order to format/limit the server state\nfor debugging and logging purposes.\n\nIt is called in the following situations:\n\n- One of [`sys:get_status/1,2`](`sys:get_status/1`) is invoked to get the\n `gen_statem` status. `Opt` is set to the atom `normal` for this case.\n\n- The `gen_statem` terminates abnormally and logs an error.\n `Opt` is set to the atom `terminate` for this case.\n\nThis function is useful for changing the form and appearance of\nthe `gen_statem` status for these cases. A callback module wishing to\nchange the [`sys:get_status/1,2`](`sys:get_status/1`) return value\nand how its status appears in termination error logs, should export\nan instance of [`Module:format_status/2`](`c:format_status/2`),\nthat returns a term describing the current status of the `gen_statem`.\n\n`PDict` is the current value of the process dictionary of the `gen_statem`.\n\n[`State`](`t:state/0`) is the internal state of the `gen_statem`.\n\n[`Data`](`t:data/0`) is the internal server data of the `gen_statem`.\n\nThe function is to return `Status`, a term that contains\nthe appropriate details of the current state and status\nof the `gen_statem`. There are no restrictions on the form `Status`\ncan take, but for the [`sys:get_status/1,2`](`sys:get_status/1`) case\n(when `Opt` is `normal`), the recommended form for the `Status` value\nis `[{data, [{\"State\", Term}]}]`, where `Term` provides relevant details\nof the `gen_statem` state. Following this recommendation is not required,\nbut it makes the callback module status consistent\nwith the rest of the [`sys:get_status/1,2`](`sys:get_status/1`)\nreturn value.\n\nOne use for this function is to return compact alternative\nstate representations to avoid having large state terms printed\nin log files. Another use is to hide sensitive data\nfrom being written to the error log.\n\n> #### Note {: .info }\n>\n> This callback is optional, so a callback module does not need\n> to export it. The `gen_statem` module provides a default\n> implementation of this function that returns `{State, Data}`.\n>\n> If this callback is exported but fails, to hide possibly sensitive data,\n> the default function will instead return `{State, Info}`,\n> where `Info` says nothing but the fact that\n> [`Module:format_status/2`](`c:format_status/2`) has crashed.","title":"gen_statem.format_status/2","ref":"gen_statem.html#c:format_status/2"},{"type":"callback","doc":"[_State callback_](#state-callback) in\n[_callback mode_](`t:callback_mode/0`) `handle_event_function`.\n\nWhenever a `gen_statem` receives an event from [`call/2,3`](`call/3`),\n`cast/2`, or as a normal process message, this function is called.\n\nIf `EventType` is [`{call, From}`](`t:event_type/0`),\nthe caller waits for a reply. The reply can be sent from this\nor from any other [_state callback_](#state-callback)\nby returning with `{reply, From, Reply}` in [`Actions`](`t:action/0`),\nin [`Replies`](`t:reply_action/0`), or by calling\n[`reply(From, Reply)`](`reply/2`).\n\nIf this function returns with a next state\nthat does not match equal (`=/=`) to the current state,\nall postponed events are retried in the next state.\n\nFor options that can be set and actions that can be done\nby `gen_statem` after returning from this function, see `t:action/0`.\n\nWhen the `gen_statem` runs with [_state enter calls_](`t:state_enter/0`),\nthis function is also called with arguments `(enter, OldState, ...)`\nduring every _state change_. In this case there are some restrictions\non the [actions](`t:action/0`) that may be returned:\n\n- `t:postpone/0` is not allowed since a _state enter call_\n is not an event so there is no event to postpone.\n- [`{next_event, _, _}`](`t:action/0`) is not allowed since\n using _state enter calls_ should not affect how events\n are consumed and produced.\n- It is not allowed to change states from this call.\n Should you return `{next_state, NextState, ...}`\n with `NextState =/= State` the `gen_statem` crashes.\n\n Note that it is actually allowed to use `{repeat_state, NewData, ...}`\n although it makes little sense since you immediately\n will be called again with a new _state enter call_ making this\n just a weird way of looping, and there are better ways to loop in Erlang.\n\n If you do not update `NewData` and have some loop termination condition,\n or if you use `{repeat_state_and_data, _}` or `repeat_state_and_data`\n you have an infinite loop\\!\n\n You are advised to use `{keep_state, ...}`, `{keep_state_and_data, _}`\n or `keep_state_and_data` since changing states\n from a _state enter call_ is not possible anyway.\n\nNote the fact that you can use [`throw`](`erlang:throw/1`)\nto return the result, which can be useful. For example to bail out with\n[`throw(keep_state_and_data)`](`throw/1`) from deep within complex code\nthat cannot return `{next_state, State, Data}` because `State` or `Data`\nis no longer in scope.","title":"gen_statem.handle_event/4","ref":"gen_statem.html#c:handle_event/4"},{"type":"callback","doc":"Initialize the state machine.\n\nWhenever a `gen_statem` is started using\n[`start_link/3,4`](`start_link/3`),\n[`start_monitor/3,4`](`start_monitor/3`), or\n[`start/3,4`](`start/3`), this function is called by the new process\nto initialize the implementation state and server data.\n\n`Args` is the `Args` argument provided to that start function.\n\n> #### Note {: .info }\n>\n> Note that if the `gen_statem` is started through `m:proc_lib`\n> and [`enter_loop/4,5,6`](`enter_loop/6`), this callback\n> will never be called. Since this callback is not optional\n> it can in that case be implemented as:\n>\n> ```erlang\n> -spec init(_) -> no_return().\n> init(Args) -> erlang:error(not_implemented, [Args]).\n> ```","title":"gen_statem.init/1","ref":"gen_statem.html#c:init/1"},{"type":"function","doc":"","title":"gen_statem.receive_response/1","ref":"gen_statem.html#receive_response/1"},{"type":"function","doc":"Receive a request response.\n\nReceive a response corresponding to the request identifier `ReqId`.\nThe request must have been made by `send_request/2`\nto the `gen_statem` process. This function must be called\nfrom the same process from which `send_request/2` was made.\n\n`Timeout` specifies how long to wait for a response.\nIf no response is received within the specified time,\nthis function returns `timeout`. Assuming that the server executes\non a node supporting aliases (introduced in OTP 24)\nthe request will also be abandoned. That is,\nno response will be received after a time-out.\nOtherwise, a stray response might be received at a later time.\n\nSee [`call/3`](#call-reply) about how the request is handled\nand the `Reply` is sent by the `gen_statem` server.\n\nIf the `gen_statem` server process is dead or dies while\nthis function waits for the reply, it returns an `error` return\nwith the exit `Reason`.\n\nThe difference between `wait_response/2` and `receive_response/2`\nis that `receive_response/2` abandons the request at time-out\nso that a potential future response is ignored,\nwhile `wait_response/2` does not.","title":"gen_statem.receive_response/2","ref":"gen_statem.html#receive_response/2"},{"type":"function","doc":"Receive a request response in a collection.\n\nReceive a response in `ReqIdCollection`. All request identifiers\nof `ReqIdCollection` must correspond to requests that have been made\nusing `send_request/2` or `send_request/4`, and all requests\nmust have been made by the process calling this function.\n\nThe `Label` in the response is the `Label` associated with\nthe request identifier that the response corresponds to.\nThe `Label` of a request identifier is associated\nwhen [adding the request id](`reqids_add/3`) to a collection,\nor when sending the request using `send_request/4`.\n\nCompared to `receive_response/2`, the returned result or exception\nassociated with a specific request identifier will be wrapped\nin a 3-tuple `{Response, Label, NewReqIdCollection}`.\n`Response` is the value that would have been produced\nby `receive_response/2`, `Label` is the value associated with\nthe specific [request identifier](`t:request_id/0`)\nand `NewReqIdCollection` is a possibly modified\nrequest identifier collection.\n\nIf `ReqIdCollection` is empty, `no_request` will be returned.\n\n`Timeout` specifies how long to wait for a response. If no response\nis received within the specified time, the function returns `timeout`.\nAssuming that the server executes on a node supporting aliases\n(introduced in OTP 24) all requests identified by `ReqIdCollection`\nwill also be abandoned. That is, no responses will be received\nafter a time-out. Otherwise, stray responses might be received\nat a later time.\n\nThe difference between `receive_response/3` and `wait_response/3`\nis that `receive_response/3` abandons requests at time-out\nso that potential future responses are ignored,\nwhile `wait_response/3` does not.\n\nIf `Delete` is `true`, the association with `Label`\nis deleted from `ReqIdCollection` in the resulting\n`NewReqIdCollection`. If `Delete` is `false`, `NewReqIdCollection`\nwill equal`ReqIdCollection`. Note that deleting an association\nis not for free and that a collection containing already handled\nrequests can still be used by subsequent calls to\n`wait_response/3`, `check_response/3`, and `receive_response/3`.\n\nHowever, without deleting handled associations,\nthe above calls will not be able to detect when there are\nno more outstanding requests to handle, so you will have to keep track\nof this some other way than relying on a `no_request` return.\nNote that if you pass a collection only containing\nassociations of already handled or abandoned requests to\nthis function, it will always block until `Timeout` expires\nand then return `timeout`.","title":"gen_statem.receive_response/3","ref":"gen_statem.html#receive_response/3"},{"type":"function","doc":"Send one or multiple `call` replies.\n\nThis funcion can be used by a `gen_statem` callback to explicitly send\none or multiple replies to processes waiting for `call` requests' replies,\nwhen it is impractical or impossible to return `t:reply_action/0`s\nfrom a [_state callback_](#state-callback).\n\n> #### Note {: .info }\n>\n> A reply sent with this function is not visible in `m:sys` debug output.","title":"gen_statem.reply/1","ref":"gen_statem.html#reply/1"},{"type":"function","doc":"Send a `call` `Reply` to `From`.\n\nThis funcion can be used by a `gen_statem` callback to explicitly send\na reply to a process waiting for a `call` requests' reply,\nwhen it is impractical or impossible to return a `t:reply_action/0`\nfrom a [_state callback_](#state-callback).\n\n> #### Note {: .info }\n>\n> A reply sent with this function is not visible in `m:sys` debug output.","title":"gen_statem.reply/2","ref":"gen_statem.html#reply/2"},{"type":"function","doc":"Store a request identifier in a colletion.\n\nStores `ReqId` and associates a `Label` with the request identifier\nby adding this information to `ReqIdCollection` and returning\nthe resulting request identifier collection.","title":"gen_statem.reqids_add/3","ref":"gen_statem.html#reqids_add/3"},{"type":"function","doc":"Create an empty request identifier collection.\n\nReturns a new empty request identifier collection.\nA request identifier collection can be used to handle\nmultiple outstanding requests.\n\nRequest identifiers of requests made by `send_request/2`\ncan be stored in a collection using `reqids_add/3`.\nSuch a collection of request identifiers can later be used\nin order to get one response corresponding to a request\nin the collection by passing the collection as argument to\n`receive_response/3`, `wait_response/3`, or, `check_response/3`.\n\n`reqids_size/1` can be used to determine the number of\nrequest identifiers in a collection.","title":"gen_statem.reqids_new/0","ref":"gen_statem.html#reqids_new/0"},{"type":"function","doc":"Return the number of request identifiers in `ReqIdCollection`.","title":"gen_statem.reqids_size/1","ref":"gen_statem.html#reqids_size/1"},{"type":"function","doc":"Convert a request identifier collection to a list.\n\nReturns a list of `{ReqId, Label}` tuples which corresponds to\nall request identifiers with their associated labels\nin [`ReqIdCollection`](`t:request_id_collection/0`).","title":"gen_statem.reqids_to_list/1","ref":"gen_statem.html#reqids_to_list/1"},{"type":"callback","doc":"[_State callback_](#state-callback) in\n[_callback mode_](`t:callback_mode/0`) `state_functions`.\n\nState callback that handles all events in state `StateName`, where\n[`StateName :: state_name()`](`t:state_name/0`)\nhas to be an `t:atom/0`.\n\n`StateName` cannot be `terminate` since that would collide\nwith the callback function [`Module:terminate/3`](`c:terminate/3`).\n\nBesides that when doing a [_state change_](#state-callback)\nthe next state always has to be an `t:atom/0`,\nthis function is equivalent to\n[`Module:handle_event(​EventType, EventContent,\n?FUNCTION_NAME, Data)`](`c:handle_event/4`),\nwhich is the [_state callback_](#state-callback) in\n[_callback mode_](`t:callback_mode/0`) `handle_event_function`.","title":"gen_statem.StateName/3","ref":"gen_statem.html#c:StateName/3"},{"type":"function","doc":"Send an asynchronous `call` request.\n\nSends `Request` to the `gen_statem` process identified by `ServerRef`\nand returns a request identifier `ReqId`.\n\nThe return value `ReqId` shall later be used with `receive_response/2`,\n`wait_response/2`, or `check_response/2` to fetch the actual result\nof the request. Besides passing the request identifier directly\nto these functions, it can also be stored in\na request identifier collection using `reqids_add/3`.\nSuch a collection of request identifiers can later be used\nin order to get one response corresponding to a\nrequest in the collection by passing the collection\nas argument to `receive_response/3`, `wait_response/3`,\nor `check_response/3`. If you are about to store the request identifier\nin a collection, you may want to consider using `send_request/4` instead.\n\nThe call\n`gen_statem:wait_response(gen_statem:send_request(ServerRef,\nRequest), Timeout)` can be seen as equivalent to\n[`gen_statem:call(Server, Request, Timeout)`](`call/3`),\nignoring the error handling.\n\nSee [`call/3`](#call-reply) about how the request is handled\nand the `Reply` is sent by the `gen_statem` server.\n\nThe server's `Reply` is returned by one of the\n[`receive_response/1,2`](`receive_response/2`),\n[`wait_response/1,2`](`wait_response/2`),\nor `check_response/2` functions.","title":"gen_statem.send_request/2","ref":"gen_statem.html#send_request/2"},{"type":"function","doc":"Send an asynchronous `call` request and add it\nto a request identifier collection.\n\nSends `Request` to the `gen_statem` process identified by `ServerRef`.\nThe `Label` will be associated with the request identifier\nof the operation and added to the returned request identifier collection\n`NewReqIdCollection`. The collection can later be used in order to\nget one response corresponding to a request in the collection\nby passing the collection as argument to `receive_response/3`,\n`wait_response/3`, or `check_response/3`.\n\nThe same as calling\n[`reqids_add(​`](`reqids_add/3`)[`send_request(ServerRef, Request),\n`](`send_request/2`)[`Label, ReqIdCollection)`](`reqids_add/3`),\nbut slightly more efficient.","title":"gen_statem.send_request/4","ref":"gen_statem.html#send_request/4"},{"type":"function","doc":"Start a server, neither linked nor registered.\n\nEquivalent to `start/4` except that the `gen_statem` process\nis not registered with any [name service](`t:server_name/0`).","title":"gen_statem.start/3","ref":"gen_statem.html#start/3"},{"type":"function","doc":"Start a server, registered but not linked.\n\nCreates a standalone `gen_statem` process according to\nOTP design principles (using `m:proc_lib` primitives).\nAs it does not get linked to the calling process,\nthis start function cannot be used by a supervisor to start a child.\n\nFor a description of arguments and return values,\nsee [`start_link/4`](`start_link/4`).","title":"gen_statem.start/4","ref":"gen_statem.html#start/4"},{"type":"function","doc":"Start a server, linked but not registered.\n\nEquivalent to `start_link/4` except that the `gen_statem` process\nis not registered with any [name service](`t:server_name/0`).","title":"gen_statem.start_link/3","ref":"gen_statem.html#start_link/3"},{"type":"function","doc":"Start a server, linked and registered.\n\nCreates a `gen_statem` process according to OTP design principles\n(using `m:proc_lib` primitives) that is spawned linked to\nthe calling process. This is essential when the `gen_statem`\nmust be part of a supervision tree so it gets linked to its supervisor.\n\nThe spawned `gen_statem` process calls [`Module:init/1`](`c:init/1`)\nto initialize the server. To ensure a synchronized startup procedure,\n`start_link/3,4` does not return until [`Module:init/1`](`c:init/1`)\nhas returned or failed.\n\n`ServerName` specifies the `t:server_name/0` to register\nfor the `gen_statem` process. If the `gen_statem` process is started with\n[`start_link/3`](`start_link/3`), no `ServerName` is provided and the\n`gen_statem` process is not registered.\n\n`Module` is the name of the callback module.\n\n`Args` is an arbitrary term that is passed as the argument to\n[`Module:init/1`](`c:init/1`).\n\n#### Start options in `Opts` {: #start-options }\n\n- **[`{timeout, Time}`](`t:start_opt/0`)** - The `gen_statem` process\n is allowed to spend `Time` milliseconds before returning\n from [`Module:init/1`](`c:init/1`), or it is terminated\n and this start function returns [`{error, timeout}`](`t:start_ret/0`).\n\n- **[`{spawn_opt, SpawnOpts}`](`t:start_opt/0`)** -\n `SpawnOpts` is passed as option list to `erlang:spawn_opt/2`,\n which is used to spawn the `gen_statem` process.\n See `t:proc_lib:start_spawn_option/0`.\n\n > #### Note {: .info }\n >\n > Using spawn option `monitor` is not allowed,\n > it causes a `badarg` failure.\n\n- **[`{hibernate_after, HibernateAfterTimeout}`](`t:enter_loop_opt/0`)** -\n When the `gen_statem` process waits for a message, if no message\n is received within `HibernateAfterTimeout` milliseconds,\n the process goes into hibernation automatically\n (by calling `proc_lib:hibernate/3`). This option is also\n allowed for the [`enter_loop`](`enter_loop/6`) functions.\n\n Note that there is also a `t:transition_option/0`\n to explicitly hibernate the server from a\n [_state callback_](#state-callback).\n\n- **[`{debug, Dbgs}`](`t:enter_loop_opt/0`)** - Activates\n debugging through `m:sys`. For every entry in `Dbgs`,\n the corresponding function in `m:sys` is called. This option is also\n allowed for the [`enter_loop`](`enter_loop/6`) functions.\n\n#### Return values {: #start-return-values }\n\n- **[`{ok, Pid}`](`t:start_ret/0`)** -\n The `gen_statem` server process was successfully created and\n initialized. `Pid` is the `t:pid/0` of the process.\n\n- **[`ignore`](`t:start_ret/0`)** -\n [`Module:init/1`](`c:init/1`) returned [`ignore`](`t:init_result/1`).\n The `gen_statem` process has exited with reason `normal`.\n\n- **[`{error, {already_started, OtherPid}}`](`t:start_ret/0`)** -\n A process with the specified [`ServerName`](`t:server_name/0`)\n already exists. `OtherPid` is the `t:pid/0` of that process.\n The `gen_statem` process exited with reason `normal`\n before calling [`Module:init/1`](`c:init/1`).\n\n- **[`{error, timeout}`](`t:start_ret/0`)** -\n [`Module:init/1`](`c:init/1`) did not return within\n the [start time-out](`t:start_opt/0`). The `gen_statem` process\n has been killed with [`exit(_, kill)`](`erlang:exit/2`).\n\n- **[`{error, Reason}`](`t:start_ret/0`)**\n + Either [`Module:init/1`](`c:init/1`) returned\n [`{stop, Reason}`](`t:init_result/1`) or failed with reason `Reason`,\n The `gen_statem` process exited with reason `Reason`.\n + Or [`Module:init/1`](`c:init/1`) returned\n [`{error, Reason}`](`t:init_result/1`).\n The `gen_statem` process did a graceful exit with reason `normal`.\n\nIf the return value is `ignore` or `{error, _}`, the started\n`gen_statem` process has terminated. If an `'EXIT'` message\nwas delivered to the calling process (due to the process link),\nthat message has been consumed.\n\n> #### Warning {: .warning }\n>\n> Before OTP 26.0, if the started `gen_statem` process returned e.g.\n> `{stop, Reason}` from [`Module:init/1`](`c:init/1`),\n> this function could return `{error, Reason}`\n> _before_ the started `gen_statem` process had terminated,\n> so starting again might fail because VM resources\n> such as the registered name was not yet unregistered,\n> and an `'EXIT'` message could arrive later to the\n> process calling this function.\n>\n> But if the started `gen_statem` process instead failed during\n> [`Module:init/1`](`c:init/1`), a process link `{'EXIT', Pid, Reason}`\n> message caused this function to return `{error, Reason}`,\n> so the `'EXIT'` message had been consumed and\n> the started `gen_statem` process had terminated.\n>\n> Since it was impossible to tell the difference between these two cases\n> from `start_link/3,4`'s return value, this inconsistency\n> was cleaned up in OTP 26.0.","title":"gen_statem.start_link/4","ref":"gen_statem.html#start_link/4"},{"type":"function","doc":"Start a server, monitored but neither linked nor registered.\n\nEquivalent to `start_monitor/4` except that the `gen_statem`\nprocess is not registered with any [name service](`t:server_name/0`).","title":"gen_statem.start_monitor/3","ref":"gen_statem.html#start_monitor/3"},{"type":"function","doc":"Start a server, monitored and registered, but not linked.\n\nCreates a standalone `gen_statem` process according to\nOTP design principles (using `m:proc_lib` primitives),\nand atomically sets up a monitor to the newly created process.\n\nAs the started process does not get linked to the calling process,\nthis start function cannot be used by a supervisor to start a child.\n\nFor a description of arguments and return values, see\n[`start_link/4`](`start_link/4`), but note that for a succesful start\nthe return value differs since this function returns `{ok, {Pid, Mon}}`,\nwhere `Pid` is the process identifier of the process,\nand `Mon` is the monitor reference for the process.\nIf the start is not successful, the caller will be blocked\nuntil the `DOWN` message has been received\nand removed from the caller's message queue.","title":"gen_statem.start_monitor/4","ref":"gen_statem.html#start_monitor/4"},{"type":"function","doc":"","title":"gen_statem.stop/1","ref":"gen_statem.html#stop/1"},{"type":"function","doc":"Stop a server.\n\nOrders the `gen_statem` [`ServerRef`](`t:server_ref/0`) to exit with the\nspecified `Reason` and waits for it to terminate. The `gen_statem` calls\n[`Module:terminate/3`](`c:terminate/3`) before exiting.\n\nThis function returns `ok` if the server terminates\nwith the expected reason. Any other reason than `normal`, `shutdown`,\nor `{shutdown, Term}` causes an error report to be issued\nthrough `m:logger`. An exit signal with the same reason is\nsent to linked processes and ports. The default `Reason` is `normal`.\n\n`Timeout` is an integer > 0, which specifies how many milliseconds\nto wait for the server to terminate, or the atom `infinity`\nto wait indefinitely. Defaults to `infinity`.\nIf the server does not terminate within the specified time,\nthe call exits the calling process with reason `timeout`.\n\nIf the process does not exist, the call exits the calling process\nwith reason `noproc`, or with reason `{nodedown, Node}`\nif the connection fails to the remote `Node` where the server runs.","title":"gen_statem.stop/3","ref":"gen_statem.html#stop/3"},{"type":"callback","doc":"Handle state machine termination.\n\nThis function is called by a `gen_statem` when it is about to terminate.\nIt is to be the opposite of [`Module:init/1`](`c:init/1`)\nand do any necessary cleaning up. When it returns, the `gen_statem`\nterminates with `Reason`. The return value is ignored.\n\n`Reason` is a term denoting the stop reason and [`State`](`t:state/0`)\nis the internal state of the `gen_statem`.\n\n`Reason` depends on why the `gen_statem` is terminating. If it is because\nanother callback function has returned, a stop tuple `{stop, Reason}` in\n[`Actions`](`t:action/0`), `Reason` has the value specified in that tuple.\nIf it is because of a failure, `Reason` is the error reason.\n\nIf the `gen_statem` is part of a supervision tree and is ordered by its\nsupervisor to terminate, this function is called with `Reason = shutdown`\nif both the following conditions apply:\n\n- The `gen_statem` process has been set to trap exit signals.\n- The shutdown strategy as defined in the supervisor's\n child specification is an integer time-out value, not `brutal_kill`.\n\nEven if the `gen_statem` is _not_ part of a supervision tree,\nthis function is called if it receives an `'EXIT'` message\nfrom its parent. `Reason` is the same as in the `'EXIT'` message.\n\nIf the `gen_statem` process is not set up to trap\nexit signals it is immediately terminated, just like any process,\nand this function is not called.\n\nNotice that for any other reason than `normal`, `shutdown`, or\n`{shutdown, Term}`, the `gen_statem` is assumed to terminate\nbecause of an error and an error report is issued using `m:logger`.\n\nWhen the `gen_statem` process exits, an exit signal\nwith the same reason is sent to linked processes and ports,\njust as for any process.","title":"gen_statem.terminate/3","ref":"gen_statem.html#c:terminate/3"},{"type":"function","doc":"","title":"gen_statem.wait_response/1","ref":"gen_statem.html#wait_response/1"},{"type":"function","doc":"Wait for a request response.\n\nWaits for the response to the request identifier `ReqId`. The request\nmust have been made by `send_request/2` to the `gen_statem` process.\nThis function must be called from the same process from which\n`send_request/2` was called.\n\n`WaitTime` specifies how long to wait for a reply.\nIf no reply is received within the specified time,\nthe function returns `timeout` and no cleanup is done,\nThus the function can be invoked repeatedly until a reply is returned.\n\nSee [`call/3`](#call-reply) about how the request is handled\nand the `Reply` is sent by the `gen_statem` server.\n\nIf the `gen_statem` server process is dead or dies while\nthis function waits for the reply, it returns an `error` return\nwith the exit `Reason`.\n\nThe difference between `receive_response/2` and\n`wait_response/2` is that `receive_response/2` abandons\nthe request at time-out so that a potential future response is ignored,\nwhile `wait_response/2` does not.","title":"gen_statem.wait_response/2","ref":"gen_statem.html#wait_response/2"},{"type":"function","doc":"Wait for any request response in a collection.\n\nWaits for a response in `ReqIdCollection`. All request identifiers\nof `ReqIdCollection` must correspond to requests that have been made\nusing `send_request/2` or `send_request/4`, and all requests\nmust have been made by the process calling this function.\n\nThe `Label` in the response is the `Label` associated with\nthe request identifier that the response corresponds to.\nThe `Label` of a request identifier is associated\nwhen [adding the request id](`reqids_add/3`) to a collection,\nor when sending the request using `send_request/4`.\n\nCompared to `wait_response/2`, the returned result or exception\nassociated with a specific request identifier will be wrapped\nin a 3-tuple `{Response, Label, NewReqIdCollection}`.\n`Response` is the value that would have been produced\nby `wait_response/2`, `Label` is the value associated with\nthe specific [request identifier](`t:request_id/0`)\nand `NewReqIdCollection` is a possibly modified\nrequest identifier collection.\n\nIf `ReqIdCollection` is empty, `no_request` is returned.\n\nIf no response is received before `WaitTime` has expired,\n`timeout` is returned. It is valid to continue waiting\nfor a response as many times as needed up until a response\nhas been received and completed by `check_response()`,\n`receive_response()`, or `wait_response()`.\n\nThe difference between `receive_response/3` and `wait_response/3`\nis that `receive_response/3` abandons requests at time-out\nso that potential future responses are ignored,\nwhile `wait_response/3` does not.\n\nIf `Delete` is `true`, the association with `Label`\nhas been deleted from `ReqIdCollection` in the resulting\n`NewReqIdCollection`. If `Delete` is `false`, `NewReqIdCollection`\nwill equal`ReqIdCollection`. Note that deleting an association\nis not for free and that a collection containing already handled\nrequests can still be used by subsequent calls to\n`wait_response/3`, `check_response/3`, and `receive_response/3`.\n\nHowever, without deleting handled associations,\nthe above calls will not be able to detect when there are\nno more outstanding requests to handle, so you will have to keep track\nof this some other way than relying on a `no_request` return.\nNote that if you pass a collection only containing\nassociations of already handled or abandoned requests\nto this function, it will always block until `WaitTime` expires\nand then return `timeout`.","title":"gen_statem.wait_response/3","ref":"gen_statem.html#wait_response/3"},{"type":"type","doc":"Actions for a _state transition_, or when starting the server.\n\nThese _transition actions_ can be invoked by returning them from the\n[_state callback_](#state-callback) when it is called\nwith an [event](`t:event_type/0`), from [`Module:init/1`](`c:init/1`)\nor by passing them to [`enter_loop/4,5,6`](`enter_loop/6`).\nThey are **not allowed** from _state enter calls_.\n\nActions are executed in the containing list order.\n\nActions that set [transition options](`t:transition_option/0`)\noverride any previous of the same type, so the last\nin the containing list wins. For example, the last `t:postpone/0`\noverrides any previous `t:postpone/0` in the list.\n\n- **`{postpone, Value}`** - Sets the\n [`transition_option()` ](`t:transition_option/0`)`t:postpone/0`\n for this _state transition_. This action is ignored when returned from\n [`Module:init/1`](`c:init/1`) or passed to\n [`enter_loop/4,5,6`](`enter_loop/6`), as there is no event to postpone\n in those cases.\n\n `postpone` is equivalent to `{postpone, true}`.\n\n- **`{next_event, EventType, EventContent}`** - This action\n does not set any [`transition_option()`](`t:transition_option/0`)\n but instead stores the specified `EventType` and `EventContent`\n for insertion after all actions have been executed.\n\n The stored events are inserted in the queue as the next to process\n before any already queued events. The order of these stored events\n is preserved, so the first `next_event` in the containing list\n becomes the first to process.\n\n An event of type [`internal`](`t:event_type/0`) should be used\n when you want to reliably distinguish an event inserted this way\n from any external event.\n\n- **`{change_callback_module, NewModule}`** {: #change_callback_module } -\n Changes the callback module to `NewModule` which will be used\n when calling all subsequent [state callbacks](#state-callback).\\\n **Since OTP 22.3.**\n\n The `gen_statem` engine will find out the\n [_callback mode_](`t:callback_mode/0`) of `NewModule` by calling\n [`NewModule:callback_mode/0`](`c:callback_mode/0`) before the next\n [state callback](#state-callback).\n\n Changing the callback module does not affect the _state transition_\n in any way, it only changes which module that handles the events.\n Be aware that all relevant callback functions in `NewModule` such as\n the [state callback](#state-callback),\n [`NewModule:code_change/4`](`c:code_change/4`),\n [`NewModule:format_status/1`](`c:format_status/1`) and\n [`NewModule:terminate/3`](`c:terminate/3`) must be able to handle\n the state and data from the old module.\n\n- **`{push_callback_module, NewModule}`** {: #push_callback_module } -\n Pushes the current callback module to the top of an internal stack\n of callback modules, and changes the callback module to `NewModule`.\n Otherwise like `{change_callback_module, NewModule}` above.\\\n **Since OTP 22.3.**\n\n- **`pop_callback_module`** {: #pop_callback_module } -\n Pops the top module from the internal stack of callback modules\n and changes the callback module to be the popped module.\n If the stack is empty the server fails.\n Otherwise like `{change_callback_module, NewModule}` above.\\\n **Since OTP 22.3.**","title":"gen_statem.action/0","ref":"gen_statem.html#t:action/0"},{"type":"type","doc":"One function per state or one common event handler.\n\nThe _callback mode_ is selected with the return value from\n[`Module:callback_mode/0`](`c:callback_mode/0`):\n\n- **`state_functions`** - The state must be of type `t:state_name/0`\n and one callback function per state, that is,\n [`Module:StateName/3`](`c:'StateName'/3`), is used.\n\n- **`handle_event_function`** - The state can be any term and the callback\n function [`Module:handle_event/4`](`c:handle_event/4`)\n is used for all states.\n\nThe function [`Module:callback_mode/0`](`c:callback_mode/0`) is called\nwhen starting the `gen_statem`, after code change and after changing\nthe callback module with any of the actions\n[`change_callback_module`](#change_callback_module),\n[`push_callback_module`](#push_callback_module),\nor [`pop_callback_module`](#pop_callback_module).\nThe result is cached for subsequent calls to\n[_state callbacks_](#state-callback).","title":"gen_statem.callback_mode/0","ref":"gen_statem.html#t:callback_mode/0"},{"type":"type","doc":"Return value from [`Module:callback_mode/0`](`c:callback_mode/0`).\n\nThis is the return type from\n[`Module:callback_mode/0`](`c:callback_mode/0`)\nwhich selects [_callback mode_](`t:callback_mode/0`)\nand whether to do [_state enter calls_](`t:state_enter/0`),\nor not.","title":"gen_statem.callback_mode_result/0","ref":"gen_statem.html#t:callback_mode_result/0"},{"type":"type","doc":"Generic state data for the server.\n\nA term in which the state machine implementation is to store\nany server data it needs. The difference between this and the `t:state/0`\nitself is that a change in this data does not cause postponed events\nto be retried. Hence, if a change in this data would change\nthe set of events that are handled, then that data item\nshould be part of the `t:state/0` instead.","title":"gen_statem.data/0","ref":"gen_statem.html#t:data/0"},{"type":"type","doc":"Actions for any callback: hibernate, time-outs or replies.\n\nThese _transition actions_ are allowed when a `t:action/0` is allowed,\nand also from a _state enter call_, and can be invoked\nby returning them from the [_state callback_](#state-callback), from\n[`Module:init/1`](`c:init/1`) or by passing them to\n[`enter_loop/4,5,6`](`enter_loop/6`).\n\nActions are executed in the containing list order.\n\nActions that set [transition options](`t:transition_option/0`)\noverride any previous of the same type,\nso the last in the containing list wins. For example,\nthe last `t:event_timeout/0` overrides any previous\n`t:event_timeout/0` in the list.\n\n- **`{hibernate, Value}`** - Sets the `t:transition_option/0`\n `t:hibernate/0` for this _state transition_.\n\n `hibernate` is equivalent to `{hibernate, true}`.","title":"gen_statem.enter_action/0","ref":"gen_statem.html#t:enter_action/0"},{"type":"type","doc":"Server [start options](#start-options) for the\n[`enter_loop/4,5,6`](`enter_loop/6`),\n[`start/3,4`](`start/3`), [`start_link/3,4`](`start_link/3`),\nand [`start_monitor/3,4`](`start_monitor/3`), functions.\n\nSee [`start_link/4`](#start-options).","title":"gen_statem.enter_loop_opt/0","ref":"gen_statem.html#t:enter_loop_opt/0"},{"type":"type","doc":"Event payload from the event's origin, delivered to\nthe [_state callback_](#state-callback).\n\nSee [`event_type`](`t:event_type/0`) that describes the origins of\nthe different event types, which is also where the event's content\ncomes from.","title":"gen_statem.event_content/0","ref":"gen_statem.html#t:event_content/0"},{"type":"type","doc":"","title":"gen_statem.event_handler_result/1","ref":"gen_statem.html#t:event_handler_result/1"},{"type":"type","doc":"Return value from a [_state callback_](#state-callback)\nafter handling an event.\n\n`StateType` is `t:state_name/0`\nif [_callback mode_](`t:callback_mode/0`) is `state_functions`,\nor `t:state/0`\nif [_callback mode_](`t:callback_mode/0`) is `handle_event_function`.\n\n- **`{next_state, NextState, NewData [, Actions]}`** -\n The `gen_statem` does a _state transition_ to `NextState`\n (which may be the same as the current state), sets `NewData`\n as the current server `t:data/0`, and executes all `Actions`.\n If `NextState =/= CurrentState` the _state transition_\n is a _state change_.","title":"gen_statem.event_handler_result/2","ref":"gen_statem.html#t:event_handler_result/2"},{"type":"type","doc":"How long to wait for an event.\n\nStarts a timer set by `t:timeout_action/0`\n`Time`, or `{timeout, Time, EventContent [, Options]}`.\n\nWhen the timer expires an event of `t:event_type/0` `timeout`\nwill be generated. See `erlang:start_timer/4` for how `Time`\nand [`Options`](`t:timeout_option/0`) are interpreted. Future\n`erlang:start_timer/4` `Options` will not necessarily be supported.\n\nAny event that arrives cancels this time-out. Note that a retried\nor inserted event counts as arrived. So does a state time-out zero event,\nif it was generated before this time-out is requested.\n\nIf `Time` is `infinity`, no timer is started,\nas it never would expire anyway.\n\nIf `Time` is relative and `0` no timer is actually started,\ninstead the the time-out event is enqueued to ensure\nthat it gets processed before any not yet received external event,\nbut after already queued events.\n\nNote that it is not possible nor needed to cancel this time-out,\nas it is cancelled automatically by any other event, meaning that\nwhenever a callback is invoked that may want to cancel this time-out,\nthe timer is already cancelled or expired.\n\nThe timer `EventContent` can be updated with the\n[`{timeout, update, NewEventContent}`](`t:timeout_update_action/0`)\naction without affecting the time of expiry.","title":"gen_statem.event_timeout/0","ref":"gen_statem.html#t:event_timeout/0"},{"type":"type","doc":"All event types: [external](`t:external_event_type/0`),\n[time-out](`t:timeout_event_type/0`), or `internal`.\n\n`internal` events can only be generated by the state machine itself\nthrough the _transition action_ [`next_event`](`t:action/0`).","title":"gen_statem.event_type/0","ref":"gen_statem.html#t:event_type/0"},{"type":"type","doc":"Event from a [call](`call/3`), [cast](`cast/2`),\nor regular process message; \"info\".\n\nType `{call, From}` originates from the API functions\n[`call/2,3`](`call/3`) or `send_request/2`. The event contains\n[`From`](`t:from/0`), which is whom to reply to\nby a `t:reply_action/0` or [`reply/2,3`](`reply/2`) call.\n\nType `cast` originates from the API function `cast/2`.\n\nType `info` originates from regular process messages\nsent to the `gen_statem` process.","title":"gen_statem.external_event_type/0","ref":"gen_statem.html#t:external_event_type/0"},{"type":"type","doc":"A map that describes the server's status.\n\nThe keys are:\n- **`state`** - The current state.\n- **`data`** - The state data.\n- **`reason`** - The reason that caused the process to terminate.\n- **`queue`** - The event queue.\n- **`postponed`** - The queue of [postponed](`t:postpone/0`) events.\n- **`timeouts`** - The active [time-outs](`t:timeout_action/0`).\n- **`log`** - The [sys log](`sys:log/2`) of the server.\n\nNew associations may be added to the status map without prior notice.","title":"gen_statem.format_status/0","ref":"gen_statem.html#t:format_status/0"},{"type":"type","doc":"A [`call`](`t:external_event_type/0`) event's reply destination.\n\nDestination to use when replying through, for example,\nthe action [`{reply, From, Reply}`](`t:reply_action/0`)\nto a process that has called the `gen_statem` server\nusing [`call/2,3`](`call/3`).","title":"gen_statem.from/0","ref":"gen_statem.html#t:from/0"},{"type":"type","doc":"How long to wait for a named time-out event.\n\nStarts a timer set by `t:timeout_action/0`\n`{{timeout, Name}, Time, EventContent [, Options]}`.\n\nWhen the timer expires an event of `t:event_type/0` `{timeout, Name}`\nwill be generated. See `erlang:start_timer/4` for how `Time`\nand [`Options`](`t:timeout_option/0`) are interpreted. Future\n`erlang:start_timer/4` `Options` will not necessarily be supported.\n\nIf `Time` is `infinity`, no timer is started,\nas it never would expire anyway.\n\nIf `Time` is relative and `0` no timer is actually started,\ninstead the time-out event is enqueued to ensure\nthat it gets processed before any not yet received external event.\n\nSetting a timer with the same `Name` while it is running\nwill restart it with the new time-out value. Therefore it is possible\nto cancel a specific time-out by setting it to `infinity`.\nIt can also be cancelled more explicitly with the\n[`{{timeout, Name}, cancel}`](`t:timeout_cancel_action/0`) action.\n\nThe timer `EventContent` can be updated with the\n[`{{timeout, Name}, update, NewEventContent}`](`t:timeout_update_action/0`)\naction without affecting the time of expiry.","title":"gen_statem.generic_timeout/0","ref":"gen_statem.html#t:generic_timeout/0"},{"type":"type","doc":"Hibernate the server process.\n\nIf `true`, hibernates the `gen_statem` by calling `proc_lib:hibernate/3`\nbefore going into `receive` to wait for a new external event.\n\nThere is also a server start option\n[`{hibernate_after, Timeout}`](`t:enter_loop_opt/0`)\nfor automatic hibernation.\n\n> #### Note {: .info }\n>\n> If there are enqueued events to process when hibernation is requested,\n> this is optimized by not hibernating but instead calling\n> [`erlang:garbage_collect/0`](`erlang:garbage_collect/0`) to simulate,\n> in a more effective way, that the `gen_statem` entered hibernation\n> and immediately got awakened by an enqueued event.","title":"gen_statem.hibernate/0","ref":"gen_statem.html#t:hibernate/0"},{"type":"type","doc":"","title":"gen_statem.init_result/1","ref":"gen_statem.html#t:init_result/1"},{"type":"type","doc":"The return value from [`Module:init/1`](`c:init/1`).\n\nFor a succesful initialization, `State` is the initial `t:state/0`,\nand `Data` the initial server `t:data/0` of the `gen_statem`.\n\nThe [`Actions`](`t:action/0`) are executed when entering the first\n[state](`t:state/0`) just as for a\n[_state callback_](#state-callback), except that the action\n`postpone` is forced to `false` since there is no event to postpone.\n\nFor an unsuccesful initialization, `{stop, Reason}`, `{error, Reason}`,\nor `ignore` should be used; see [`start_link/3,4`](`start_link/3`).\n\n`{error, Reason}` has been allowed **since OTP 26.0**.\n\nThe `{ok, ...}` tuples have existed **since OTP 19.1**,\nbefore that they were not `ok` tagged. This was before\n`gen_statem` replaced `gen_fsm` in OTP 20.0.","title":"gen_statem.init_result/2","ref":"gen_statem.html#t:init_result/2"},{"type":"type","doc":"Postpone an event to handle it later.\n\nIf `true`, postpones the current event.\nAfter a _state change_ (`NextState =/= State`), it is retried.","title":"gen_statem.postpone/0","ref":"gen_statem.html#t:postpone/0"},{"type":"type","doc":"Reply to a [`call/2,3`](`call/3`).\n\nThis _transition action_ can be invoked by returning it from the\n[_state callback_](#state-callback), from\n[`Module:init/1`](`c:init/1`) or by passing it to\n[`enter_loop/4,5,6`](`enter_loop/6`).\n\nIt does not set any [`transition_option()`](`t:transition_option/0`)\nbut instead replies to a caller waiting for a reply in `call/3`.\n`From` must be the term from argument [`{call, From}`](`t:event_type/0`)\nin a call to a [_state callback_](#state-callback).\n\nNote that using this action from [`Module:init/1`](`c:init/1`) or\n[`enter_loop/4,5,6`](`enter_loop/6`) would be weird\non the border of witchcraft since there has been no earlier call to a\n[_state callback_](#state-callback) in this server.","title":"gen_statem.reply_action/0","ref":"gen_statem.html#t:reply_action/0"},{"type":"opaque","doc":"A handle that associates a reply to the corresponding request.","title":"gen_statem.reply_tag/0","ref":"gen_statem.html#t:reply_tag/0"},{"type":"opaque","doc":"An opaque request identifier. See `send_request/2` for details.","title":"gen_statem.request_id/0","ref":"gen_statem.html#t:request_id/0"},{"type":"opaque","doc":"An opaque collection of request identifiers (`t:request_id/0`).\n\nEach request identifier can be associated with\na label chosen by the user. For more information see `reqids_new/0`.","title":"gen_statem.request_id_collection/0","ref":"gen_statem.html#t:request_id_collection/0"},{"type":"type","doc":"Response time-out for an asynchronous call.\n\nUsed to set a time limit on how long to wait for a response using either\n`receive_response/2`, `receive_response/3`, `wait_response/2`, or\n`wait_response/3`. The time unit used is `millisecond`.\n\n Currently valid values:\n\n- **`0..4294967295`** - Time-out relative to current time in milliseconds.\n\n- **`infinity`** - Infinite time-out. That is,\n the operation will never time out.\n\n- **`{abs, Timeout}`** - An absolute\n [Erlang monotonic time](`erlang:monotonic_time/1`)\n time-out in milliseconds. That is, the operation will time out when\n [`erlang:monotonic_time(millisecond)`](`erlang:monotonic_time/1`)\n returns a value larger than or equal to `Timeout`.\n `Timeout` is not allowed to identify a time further into the future\n than `4294967295` milliseconds. Specifying the time-out\n using an absolute value is especially handy when you have\n a deadline for responses corresponding to a complete collection\n of requests (`t:request_id_collection/0`), since you do not have to\n recalculate the relative time until the deadline over and over again.","title":"gen_statem.response_timeout/0","ref":"gen_statem.html#t:response_timeout/0"},{"type":"type","doc":"Server name specification: `local`, `global`, or `via` registered.\n\nName specification to use when starting a `gen_statem` server.\nSee `start_link/3` and `t:server_ref/0` below.","title":"gen_statem.server_name/0","ref":"gen_statem.html#t:server_name/0"},{"type":"type","doc":"Server specification: `t:pid/0` or registered `t:server_name/0`.\n\nTo be used in [`call/2,3`](`call/3`) to specify the server.\n\nIt can be:\n\n- **`pid() | LocalName`** - The `gen_statem` is locally registered.\n\n- **`{Name, Node}`** - The `gen_statem` is locally registered\n on another node.\n\n- **`{global, GlobalName}`** - The `gen_statem` is globally registered\n in `m:global`.\n\n- **`{via, RegMod, ViaName}`** - The `gen_statem` is registered\n in an alternative process registry. The registry callback module\n `RegMod` is to export functions `register_name/2`, `unregister_name/1`,\n `whereis_name/1`, and `send/2`, which are to behave like\n the corresponding functions in `m:global`.\n Thus, `{via, global, GlobalName}` is the same as `{global, GlobalName}`.","title":"gen_statem.server_ref/0","ref":"gen_statem.html#t:server_ref/0"},{"type":"type","doc":"Return value from the [`start_monitor/3,4`](`start_monitor/3`) functions.\n\nAs for [`start_link/4`](#start-return-values) but a succesful return\nwraps the process ID and the [monitor reference](`erlang:monitor/2`) in a\n`{ok, {`[`pid()`](`t:pid/0`)`, `[`reference()`](`t:reference/0`)`}}`\ntuple.","title":"gen_statem.start_mon_ret/0","ref":"gen_statem.html#t:start_mon_ret/0"},{"type":"type","doc":"Server [start options](#start-options) for the\n[`start/3,4`](`start/3`), [`start_link/3,4`](`start_link/3`),\nand [`start_monitor/3,4`](`start_monitor/3`) functions.\n\nSee [`start_link/4`](#start-options).","title":"gen_statem.start_opt/0","ref":"gen_statem.html#t:start_opt/0"},{"type":"type","doc":"[Return value](#start-return-values) from the [`start/3,4`](`start/3`)\nand [`start_link/3,4`](`start_link/3`) functions.\n\nSee [`start_link/4`](#start-return-values).","title":"gen_statem.start_ret/0","ref":"gen_statem.html#t:start_ret/0"},{"type":"type","doc":"State name or state term.\n\nIf the [_callback mode_](`t:callback_mode/0`) is `handle_event_function`,\nthe state can be any term. After a _state change_ (`NextState =/= State`),\nall postponed events are retried.\n\nComparing two states for strict equality is assumed to be a fast operation,\nsince for every _state transition_ the `gen_statem` engine has to deduce\nif it is a _state change_.\n\n> #### Note {: .info }\n> The smaller the state term, in general, the faster the comparison.\n>\n> Note that if the \"same\" state term is returned for a state transition\n> (or a return action without a `NextState` field is used),\n> the comparison for equality is always fast because that can be seen\n> from the term handle.\n>\n> But if a newly constructed state term is returned,\n> both the old and the new state terms will have to be traversed\n> until an inequality is found, or until both terms\n> have been fully traversed.\n>\n> So it is possible to use large state terms that are fast to compare,\n> but very easy to accidentally mess up. Using small state terms is\n> the safe choice.","title":"gen_statem.state/0","ref":"gen_statem.html#t:state/0"},{"type":"type","doc":"Return value from any [_state callback_](#state-callback).\n\n`ActionType` is `t:enter_action/0` if the state callback\nwas called with a [_state enter call_](`t:state_enter/0`),\nand `t:action/0` if the state callback was called with an event.\n\n- **`{keep_state, NewData [, Actions]}`** - The same as\n `{next_state, CurrentState, NewData [, Actions]}`.\n\n- **`keep_state_and_data | {keep_state_and_data, Actions}`** -\n The same as `{keep_state, CurrentData [, Actions]}`.\n\n- **`{repeat_state, NewData [, Actions]}`** - If the `gen_statem`\n runs with [_state enter calls_](`t:state_enter/0`),\n the _state enter call_ is repeated, see type `t:transition_option/0`.\n Other than that `{repeat_state, NewData [, Actions]}` is the same as\n `{keep_state, NewData [, Actions]}`.\n\n- **`repeat_state_and_data | {repeat_state_and_data, Actions}`** -\n The same as `{repeat_state, CurrentData [, Actions]}`.\n\n- **`{stop, Reason [, NewData]}`** - Terminates the `gen_statem`\n by calling [`Module:terminate/3`](`c:terminate/3`)\n with `Reason` and `NewData`, if specified. An exit signal\n with this reason is sent to linked processes and ports.\n\n- **`stop`** - The same as `{stop, normal}`.\n\n- **`{stop_and_reply, Reason, Replies [, NewData]}`** -\n Sends all `Replies`, then terminates the `gen_statem`\n like with `{stop, Reason [, NewData]}`.\n\nAll these terms are tuples or atoms and will be so\nin all future versions of `gen_statem`.","title":"gen_statem.state_callback_result/2","ref":"gen_statem.html#t:state_callback_result/2"},{"type":"type","doc":"[_Callback mode_](`t:callback_mode/0`) modifier\nfor _state enter calls_: the atom `state_enter`.\n\nBoth _callback modes_ can use _state enter calls_,\nand this is selected by adding this `state_enter` flag\nto the [_callback mode_](`t:callback_mode/0`) return value from\n[`Module:callback_mode/0`](`c:callback_mode/0`).\n\nIf [`Module:callback_mode/0`](`c:callback_mode/0`) returns\na list containing `state_enter`, the `gen_statem` engine will,\nat every _state change_, that is; `NextState =/= CurrentState`,\ncall the [_state callback_](#state-callback) with arguments\n`(enter, OldState, Data)` or `(enter, OldState, State, Data)`,\ndepending on the [_callback mode_](`t:callback_mode/0`).\n\nThis may look like an event but is really a call performed\nafter the previous [_state callback_](#state-callback) returned,\nand before any event is delivered to the new\n[_state callback_](#state-callback).\nSee [`Module:StateName/3`](`c:'StateName'/3`) and\n[`Module:handle_event/4`](`c:handle_event/4`). A _state enter call_\nmay be repeated without doing a _state change_ by returning\na [`repeat_state`](`t:state_callback_result/2`) or\n[`repeat_state_and_data`](`t:state_callback_result/2`) action\nfrom the _state callback_.\n\nIf [`Module:callback_mode/0`](`c:callback_mode/0`) does not return\na list containing `state_enter`, no _state enter calls_ are done.\n\nIf [`Module:code_change/4`](`c:code_change/4`) should transform the state,\nit is regarded as a state rename and not a _state change_,\nwhich will not cause a _state enter call_.\n\nNote that a _state enter call_ **will** be done right before entering\nthe initial state, which may be seen as a state change from no state\nto the initial state. In this case `OldState =:= State`,\nwhich cannot happen for a subsequent state change,\nbut will happen when repeating the _state enter call_.","title":"gen_statem.state_enter/0","ref":"gen_statem.html#t:state_enter/0"},{"type":"type","doc":"","title":"gen_statem.state_enter_result/1","ref":"gen_statem.html#t:state_enter_result/1"},{"type":"type","doc":"Return value from a [_state callback_](#state-callback)\nafter a _state enter call_.\n\n`State` is the current state and it cannot be changed\nsince the state callback was called with a\n[_state enter call_](`t:state_enter/0`).\n\n- **`{next_state, State, NewData [, Actions]}`** -\n The `gen_statem` does a state transition to `State`, which has to be\n equal to the current state, sets `NewData`, and executes all `Actions`.","title":"gen_statem.state_enter_result/2","ref":"gen_statem.html#t:state_enter_result/2"},{"type":"type","doc":"State name in [_callback mode_](`t:callback_mode/0`) `state_functions`.\n\nIf the [_callback mode_](`t:callback_mode/0`) is `state_functions`,\nthe state must be an atom. After a _state change_ (`NextState =/= State`),\nall postponed events are retried. Note that the state `terminate`\nis not possible to use since it would collide with the optional\ncallback function [`Module:terminate/3`](`c:terminate/3`).","title":"gen_statem.state_name/0","ref":"gen_statem.html#t:state_name/0"},{"type":"type","doc":"How long to wait in the current state.\n\nStarts a timer set by `t:timeout_action/0`, or\n`{state_timeout, Time, EventContent [, Options]}`.\n\nWhen the timer expires an event of `t:event_type/0` `state_timeout`\nwill be generated. See `erlang:start_timer/4` for how `Time`\nand [`Options`](`t:timeout_option/0`) are interpreted. Future\n`erlang:start_timer/4` `Options` will not necessarily be supported.\n\nA _state change_ cancels this timer, if it is running.\nThat is, if the `t:timeout_action/0` that starts this timer\nis part of a list of `t:action/0`s for a _state change_,\n`NextState =/= CurrentState`, the timer runs in the **`NextState`**.\n\nIf the state machine stays in that new state, now the current state,\nthe timer will run until it expires, which creates the time-out event.\nIf the state machine changes states from the now current state,\nthe timer is cancelled. During the _state change_ from\nthe now current state, a new _state time-out_ may be started\nfor the next **`NextState`**.\n\nIf the `t:timeout_action/0` that starts this timer\nis part of a list of `t:action/0`s for a _state transition_\nthat is not a _state change_, the timer runs in the current state.\n\nIf `Time` is `infinity`, no timer is started,\nas it never would expire anyway.\n\nIf `Time` is relative and `0` no timer is actually started,\ninstead the the time-out event is enqueued to ensure\nthat it gets processed before any not yet received external event.\n\nSetting this timer while it is running will restart it\nwith the new time-out value. Therefore it is possible\nto cancel this time-out by setting it to `infinity`.\nIt can also be cancelled more explicitly with\n[`{state_timeout, cancel}`](`t:timeout_cancel_action/0`).\n\nThe timer `EventContent` can be updated with the\n[`{state_timeout, update, NewEventContent}`](`t:timeout_update_action/0`)\naction without affecting the time of expiry.","title":"gen_statem.state_timeout/0","ref":"gen_statem.html#t:state_timeout/0"},{"type":"type","doc":"Event time-out, generic time-outs or state time-out.\n\nThese _transition actions_ can be invoked by returning them from the\n[_state callback_](#state-callback), from\n[`Module:init/1`](`c:init/1`) or by passing them to\n[`enter_loop/4,5,6`](`enter_loop/6`).\n\nThese time-out actions sets time-out\n[transition options](`t:transition_option/0`).\n\n- **`Time`** - Short for `{timeout, Time, Time}`, that is,\n the time-out message is the time-out time. This form exists to allow the\n [_state callback_](#state-callback) return value\n `{next_state, NextState, NewData, Time}` like in `gen_fsm`.\n\n- **`{timeout, Time, EventContent [, Options]}`** -\n Sets the `t:transition_option/0` `t:event_timeout/0` to `Time`\n with `EventContent`, and time-out options\n [`Options`](`t:timeout_option/0`).\n\n- **`{{timeout,Name}, Time, EventContent [, Options]}`** -\n Sets the `t:transition_option/0` `t:generic_timeout/0` to `Time`\n for time-out `Name` with `EventContent`, and time-out options\n [`Options`](`t:timeout_option/0`).\\\n **Since OTP 20.0**.\n\n- **`{state_timeout, Time, EventContent [, Options]}`** -\n Sets the `t:transition_option/0` `t:state_timeout/0` to `Time`\n with `EventContent`, and time-out options\n [`Options`](`t:timeout_option/0`).\\\n **Since OTP 19.3**.","title":"gen_statem.timeout_action/0","ref":"gen_statem.html#t:timeout_action/0"},{"type":"type","doc":"Clearer way to cancel a time-out than the original\nsetting it to 'infinity'.\n\nIt has always been possible to cancel a time-out using\n`t:timeout_action/0` with `Time = infinity`, since setting a new\ntime-out time overrides a running timer, and since setting the time\nto `infinity` is optimized to not setting a timer (that never\nwill expire). Using this action shows the intention more clearly.","title":"gen_statem.timeout_cancel_action/0","ref":"gen_statem.html#t:timeout_cancel_action/0"},{"type":"type","doc":"[Event time-out](`t:event_timeout/0`),\n[generic time-out](`t:generic_timeout/0`),\nor [state time-out](`t:state_timeout/0`).\n\nThe time-out event types that the state machine can generate\nfor itself with the corresponding `t:timeout_action/0`s:\n\n| Time-out type | Action | Event type |\n|-------------------|--------------------------------|-------------------|\n| Event time-out | `{timeout, Time, ...}` | `timeout` |\n| Generic time-out | `{{timeout, Name}, Time, ...}` | `{timeout, Name}` |\n| State time-out | `{state_timeout, Time, ...}` | `state_timeout` |\n\nIn short; the action to set a time-out with\n[`EventType`](`t:timeout_event_type/0`) is `{EventType, Time, ...}`.","title":"gen_statem.timeout_event_type/0","ref":"gen_statem.html#t:timeout_event_type/0"},{"type":"type","doc":"Time-out timer start option, to select absolute time of expiry.\n\nIf `Abs` is `true` an absolute timer is started,\nand if it is `false` a relative, which is the default.\nSee [`erlang:start_timer/4`](`erlang:start_timer/4`) for details.","title":"gen_statem.timeout_option/0","ref":"gen_statem.html#t:timeout_option/0"},{"type":"type","doc":"Update the `EventContent` without affecting the time of expiry.\n\nSets a new `EventContent` for a running time-out timer.\nSee [timeout_action()](`t:timeout_action/0`) for how to start a time-out.\n\nIf no time-out of this type is active, instead inserts\nthe time-out event just like when starting a time-out\nwith relative `Time = 0`. This is a time-out autostart with\nimmediate expiry, so there will be noise for example\nif a generic time-out name was misspelled.","title":"gen_statem.timeout_update_action/0","ref":"gen_statem.html#t:timeout_update_action/0"},{"type":"type","doc":"_State transition_ options set by [actions](`t:action/0`).\n\nThese determine what happens during the _state transition_.\nThe _state transition_ takes place when the\n[_state callback_](#state-callback) has processed an event\nand returns. Here are the sequence of steps for a _state transition_:\n\n1. All returned [actions](`t:action/0`) are processed\n in order of appearance. In this step all replies generated\n by any `t:reply_action/0` are sent. Other actions set\n `t:transition_option/0`s that come into play in subsequent steps.\n\n2. If [_state enter calls_](`t:state_enter/0`) are used,\n it is either the initial state or one of the callback results\n [`repeat_state`](`t:state_callback_result/2`) or\n [`repeat_state_and_data`](`t:state_callback_result/2`) is used the\n `gen_statem` engine calls the current _state callback_ with arguments\n [`(enter, State, Data)`](`t:state_enter/0`) or\n [`(enter, State, State, Data)`](`t:state_enter/0`) (depending on\n [_callback mode_](`t:callback_mode/0`)) and when it returns\n starts again from the top of this sequence.\n\n If [_state enter calls_](`t:state_enter/0`) are used,\n and the state changes, the `gen_statem` engine calls\n the new _state callback_ with arguments\n [`(enter, OldState, Data)`](`t:state_enter/0`) or\n [`(enter, OldState, State, Data)`](`t:state_enter/0`) (depending on\n [_callback mode_](`t:callback_mode/0`)) and when it returns\n starts again from the top of this sequence.\n\n3. If `t:postpone/0` is `true`, the current event is postponed.\n\n4. If this is a _state change_, the queue of incoming events is reset\n to start with the oldest postponed.\n\n5. All events stored with `t:action/0` `next_event` are inserted\n to be processed before previously queued events.\n\n6. Time-out timers `t:event_timeout/0`, `t:generic_timeout/0` and\n `t:state_timeout/0` are handled. Time-outs with zero time\n are guaranteed to be delivered to the state machine\n before any external not yet received event so if there is\n such a time-out requested, the corresponding time-out zero event\n is enqueued as the newest received event; that is after\n already queued events such as inserted and postponed events.\n\n Any event cancels an `t:event_timeout/0` so a zero time event time-out\n is only generated if the event queue is empty.\n\n A _state change_ cancels a `t:state_timeout/0` and any new transition\n option of this type belongs to the new state, that is;\n a `t:state_timeout/0` applies to the state the state machine enters.\n\n7. If there are enqueued events the\n [_state callback_](#state-callback) for the possibly\n new state is called with the oldest enqueued event, and we start again\n from the top of this sequence.\n\n8. Otherwise the `gen_statem` goes into `receive` or hibernation\n (if `t:hibernate/0` is `true`) to wait for the next message.\n In hibernation the next non-system event awakens the `gen_statem`,\n or rather the next incoming message awakens the `gen_statem`,\n but if it is a system event it goes right back into hibernation.\n When a new message arrives the\n [_state callback_](#state-callback) is called with\n the corresponding event, and we start again\n from the top of this sequence.\n\n> #### Note {: .info }\n> The behaviour of a zero time-out (a time-out with time `0`)\n> differs subtly from Erlang's `receive ... after 0 ... end`.\n>\n> The latter receives one message if there is one,\n> while using the `t:timeout_action/0` `{timeout, 0}` does not\n> receive any external event.\n>\n> `m:gen_server`'s time-out works like Erlang's\n> `receive ... after 0 ... end`, in contrast to `gen_statem`.","title":"gen_statem.transition_option/0","ref":"gen_statem.html#t:transition_option/0"},{"type":"module","doc":"An event handler that logs events to disk.\n\nThis module is a `gen_event` handler module that can be installed in any\n`gen_event` process. It logs onto disk all events that are sent to an event\nmanager. Each event is written as a binary, which makes the logging very fast.\nHowever, a tool such as the Report Browser (`m:rb`) must be used to read the\nfiles. The events are written to multiple files. When all files have been used,\nthe first one is reused and overwritten. The directory location, the number of\nfiles, and the size of each file are configurable. The directory will include\none file called `index`, and report files `1, 2, ...`.","title":"log_mf_h","ref":"log_mf_h.html"},{"type":"module","doc":"`m:gen_event`, `m:rb`","title":"See Also - log_mf_h","ref":"log_mf_h.html#module-see-also"},{"type":"function","doc":"","title":"log_mf_h.init/3","ref":"log_mf_h.html#init/3"},{"type":"function","doc":"Initiates the event handler. Returns `Args`, which is to be used in a call to\n[`gen_event:add_handler(EventMgr, log_mf_h, Args)`](`gen_event:add_handler/3`).\n\n`Dir` specifies which directory to use for the log files. `MaxBytes` specifies\nthe size of each individual file. `MaxFiles` specifies how many files are used.\n`Pred` is a predicate function used to filter the events. If no predicate\nfunction is specified, all events are logged.","title":"log_mf_h.init/4","ref":"log_mf_h.html#init/4"},{"type":"opaque","doc":"Term to be sent to `gen_event:add_handler/3`.","title":"log_mf_h.args/0","ref":"log_mf_h.html#t:args/0"},{"type":"type","doc":"","title":"log_mf_h.b/0","ref":"log_mf_h.html#t:b/0"},{"type":"type","doc":"","title":"log_mf_h.f/0","ref":"log_mf_h.html#t:f/0"},{"type":"type","doc":"","title":"log_mf_h.pred/0","ref":"log_mf_h.html#t:pred/0"},{"type":"module","doc":"Load distribution facility.\n\nThis module can be used to run a set of Erlang nodes as a pool of computational\nprocessors. It is organized as a master and a set of slave nodes and includes\nthe following features:\n\n- The slave nodes send regular reports to the master about their current load.\n- Queries can be sent to the master to determine which node will have the least\n load.\n\nThe BIF [`statistics(run_queue)`](`statistics/1`) is used for estimating future\nloads. It returns the length of the queue of ready to run processes in the\nErlang runtime system.\n\nThe slave nodes are started with the `m:slave` module. This effects terminal\nI/O, file I/O, and code loading.\n\nIf the master node fails, the entire pool exits.\n\n[](){: #files }","title":"pool","ref":"pool.html"},{"type":"module","doc":"`.hosts.erlang` is used to pick hosts where nodes can be started. For\ninformation about format and location of this file, see `net_adm:host_file/0`.\n\n`$HOME/.erlang.slave.out.HOST` is used for all extra I/O that can come from the\nslave nodes on standard I/O. If the startup procedure does not work, this file\ncan indicate the reason.","title":"Files - pool","ref":"pool.html#module-files"},{"type":"function","doc":"Ensures that a pool master is running and includes `Node` in the pool master's\npool of nodes.","title":"pool.attach/1","ref":"pool.html#attach/1"},{"type":"function","doc":"Returns the node with the expected lowest future load.","title":"pool.get_node/0","ref":"pool.html#get_node/0"},{"type":"function","doc":"Returns a list of the current member nodes of the pool.","title":"pool.get_nodes/0","ref":"pool.html#get_nodes/0"},{"type":"function","doc":"Spawns a process on the pool node that is expected to have the lowest future\nload.","title":"pool.pspawn/3","ref":"pool.html#pspawn/3"},{"type":"function","doc":"Spawns and links to a process on the pool node that is expected to have the\nlowest future load.","title":"pool.pspawn_link/3","ref":"pool.html#pspawn_link/3"},{"type":"function","doc":"","title":"pool.start/1","ref":"pool.html#start/1"},{"type":"function","doc":"Starts a new pool.\n\nThe file `.hosts.erlang` is read to find host names where the\npool nodes can be started; see section [Files](`m:pool#module-files`). The startup\nprocedure fails if the file is not found.\n\nThe slave nodes are started with [`slave:start/2,3`](`slave:start/2`), passing\nalong `Name` and, if provided, `Args`. `Name` is used as the first part of the\nnode names, `Args` is used to specify command-line arguments.\n\nAccess rights must be set so that all nodes in the pool have the authority to\naccess each other.\n\nThe function is synchronous and all the nodes, and all the system servers, are\nrunning when it returns a value.","title":"pool.start/2","ref":"pool.html#start/2"},{"type":"function","doc":"Stops the pool and kills all the slave nodes.","title":"pool.stop/0","ref":"pool.html#stop/0"},{"type":"module","doc":"Functions for asynchronous and synchronous start of processes adhering to the\nOTP design principles.\n\nThis module is used to start processes adhering to the\n[OTP Design Principles](`e:system:design_principles.md`). Specifically, the\nfunctions in this module are used by the OTP standard behaviors (for example,\n`m:gen_server` and `m:gen_statem`) when starting new processes. The functions can\nalso be used to start _special processes_, user-defined processes that comply to\nthe OTP design principles. For an example, see section\n[sys and proc_lib](`e:system:spec_proc.md`) in OTP Design Principles.\n\nSome useful information is initialized when a process starts. The registered\nnames, or the process identifiers, of the parent process, and the parent\nancestors, are stored together with information about the function initially\ncalled in the process.\n\nWhile in \"plain Erlang\", a process is said to terminate normally only for exit\nreason `normal`, a process started using `m:proc_lib` is also said to terminate\nnormally if it exits with reason `shutdown` or `{shutdown,Term}`. `shutdown` is\nthe reason used when an application (supervision tree) is stopped.\n\nWhen a process that is started using `m:proc_lib` terminates abnormally (that is,\nwith another exit reason than `normal`, `shutdown`, or `{shutdown,Term}`), a\n_crash report_ is generated, which is written to terminal by the default logger\nhandler setup by Kernel. For more information about how crash reports were\nlogged prior to Erlang/OTP 21.0, see\n[SASL Error Logging](`e:sasl:error_logging.md`) in the SASL User's Guide.\n\nUnlike in \"plain Erlang\", `m:proc_lib` processes will not generate _error\nreports_, which are written to the terminal by the emulator. All exceptions are\nconverted to _exits_ which are ignored by the default `logger` handler.\n\nThe crash report contains the previously stored information, such as ancestors\nand initial function, the termination reason, and information about other\nprocesses that terminate as a result of this process terminating.","title":"proc_lib","ref":"proc_lib.html"},{"type":"module","doc":"`m:logger`","title":"See Also - proc_lib","ref":"proc_lib.html#module-see-also"},{"type":"function","doc":"Equivalent to [`format(CrashReport, latin1)`](`format/2`).","title":"proc_lib.format/1","ref":"proc_lib.html#format/1"},{"type":"function","doc":"> #### Note {: .info }\n>\n> This function is deprecated in the sense that the `error_logger` is no longer\n> the preferred interface for logging in Erlang/OTP. A new\n> [logging API](`e:kernel:logger_chapter.md`) was added in Erlang/OTP 21.0, but\n> legacy `error_logger` handlers can still be used. New Logger handlers do not\n> need to use this function, since the formatting callback (`report_cb`) is\n> included as metadata in the log event.\n\nThis function can be used by a user-defined legacy `error_logger` event handler\nto format a crash report. The crash report is sent using `m:logger`, and the\nevent to be handled is of the format\n`{error_report, GL, {Pid, crash_report, CrashReport}}`, where `GL` is the group\nleader pid of process `Pid` that sent the crash report.","title":"proc_lib.format/2","ref":"proc_lib.html#format/2"},{"type":"function","doc":"> #### Note {: .info }\n>\n> This function is deprecated in the sense that the `error_logger` is no longer\n> the preferred interface for logging in Erlang/OTP. A new\n> [logging API](`e:kernel:logger_chapter.md`) was added in Erlang/OTP 21.0, but\n> legacy `error_logger` handlers can still be used. New Logger handlers do not\n> need to used this function, since the formatting callback (`report_cb`) is\n> included as metadata in the log event.\n\nThis function can be used by a user-defined legacy `error_logger` event handler\nto format a crash report. When Depth is specified as a positive integer, it is\nused in the format string to limit the output as follows:\n`io_lib:format(\"~P\", [Term,Depth])`.","title":"proc_lib.format/3","ref":"proc_lib.html#format/3"},{"type":"function","doc":"Returns either `undefined` or the label for the process Pid set with\n[`proc_lib:set_label/1`](`set_label/1`).","title":"proc_lib.get_label/1","ref":"proc_lib.html#get_label/1"},{"type":"function","doc":"This function does the same as (and does call) the\n[`hibernate/3`](`erlang:hibernate/3`) BIF, but ensures that exception handling\nand logging continues to work as expected when the process wakes up.\n\nAlways use this function instead of the BIF for processes started using\n`proc_lib` functions.","title":"proc_lib.hibernate/3","ref":"proc_lib.html#hibernate/3"},{"type":"function","doc":"Equivalent to [`init_ack(Parent, Ret)`](`init_ack/2`) where `Parent` is\nthe process that called `start/5`.","title":"proc_lib.init_ack/1","ref":"proc_lib.html#init_ack/1"},{"type":"function","doc":"This function must only be used by a process that has been started by a\n[`start[_link|_monitor]/3,4,5`](`start/5`) function. It tells `Parent` that the\nprocess has initialized itself and started.\n\nFunction [`init_ack/1`](`init_ack/1`) uses the parent value previously stored by\nthe start function used.\n\nIf neither this function nor [`init_fail/2,3`](`init_fail/3`) is called by the\nstarted process, the start function returns an error tuple when the started\nprocess exits, or when the start function time-out (if used) has passed, see\n[`start/3,4,5`](`start/5`).\n\n> #### Warning {: .warning }\n>\n> Do not use this function to return an error indicating that the process start\n> failed. When doing so the start function can return before the failing process\n> has exited, which may block VM resources required for a new start attempt to\n> succeed. Use [`init_fail/2,3`](`init_fail/3`) for that purpose.\n\nThe following example illustrates how this function and `proc_lib:start_link/3`\nare used:\n\n```erlang\n-module(my_proc).\n-export([start_link/0]).\n-export([init/1]).\n\nstart_link() ->\n proc_lib:start_link(my_proc, init, [self()]).\n\ninit(Parent) ->\n case do_initialization() of\n ok ->\n proc_lib:init_ack(Parent, {ok, self()});\n {error, Reason} ->\n exit(Reason)\n end,\n loop().\n\n...\n```","title":"proc_lib.init_ack/2","ref":"proc_lib.html#init_ack/2"},{"type":"function","doc":"Equivalent to [`init_fail(Parent, Return, Exception)`](`init_fail/3`) where\n`Parent` is the process that called `start/5`.","title":"proc_lib.init_fail/2","ref":"proc_lib.html#init_fail/2"},{"type":"function","doc":"This function must only be used by a process that has been started by a\n[`start[_link|_monitor]/3,4,5`](`start/3`) function. It tells `Parent` that the\nprocess has failed to initialize, and immediately raises an exception according\nto `Exception`. The start function then returns `Ret`.\n\nSee `erlang:raise/3` for a description of `Class`, `Reason` and `Stacktrace`.\n\n> #### Warning {: .warning }\n>\n> Do not consider catching the exception from this function. That would defeat\n> its purpose. A process started by a [`start[_link|_monitor]/3,4,5`](`start/3`)\n> function should end in a value (that will be ignored) or an exception that\n> will be handled by this module. See [Description](`m:proc_lib`).\n\nIf neither this function nor [`init_ack/1,2`](`init_ack/1`) is called by the\nstarted process, the start function returns an error tuple when the started\nprocess exits, or when the start function time-out (if used) has passed, see\n[`start/3,4,5`](`start/3`).\n\nThe following example illustrates how this function and `proc_lib:start_link/3`\ncan be used:\n\n```erlang\n-module(my_proc).\n-export([start_link/0]).\n-export([init/1]).\n\nstart_link() ->\n proc_lib:start_link(my_proc, init, [self()]).\n\ninit(Parent) ->\n case do_initialization() of\n ok ->\n proc_lib:init_ack(Parent, {ok, self()});\n {error, Reason} = Error ->\n proc_lib:init_fail(Parent, Error, {exit, normal})\n end,\n loop().\n\n...\n```","title":"proc_lib.init_fail/3","ref":"proc_lib.html#init_fail/3"},{"type":"function","doc":"Extracts the initial call of a process that was started using one of the spawn\nor start functions in this module. `Process` can either be a pid, an integer\ntuple (from which a pid can be created), or the process information of a process\n`Pid` fetched through an `erlang:process_info(Pid)` function call.\n\n> #### Note {: .info }\n>\n> The list `Args` no longer contains the arguments, but the same number of atoms\n> as the number of arguments; the first atom is `'Argument__1'`, the second\n> `'Argument__2'`, and so on. The reason is that the argument list could waste a\n> significant amount of memory, and if the argument list contained funs, it\n> could be impossible to upgrade the code for the module.\n>\n> If the process was spawned using a fun, [`initial_call/1`](`initial_call/1`)\n> no longer returns the fun, but the module, function for the local function\n> implementing the fun, and the arity, for example,\n> `{some_module,-work/3-fun-0-,0}` (meaning that the fun was created in function\n> `some_module:work/3`). The reason is that keeping the fun would prevent code\n> upgrade for the module, and that a significant amount of memory could be\n> wasted.","title":"proc_lib.initial_call/1","ref":"proc_lib.html#initial_call/1"},{"type":"function","doc":"Set a label for the current process. The primary purpose is to aid in debugging\nunregistered processes. The process label can be used in tools and crash reports\nto identify processes but it doesn't have to be unique or an atom, as a\nregistered name needs to be. The process label can be any term, for example\n`{worker_process, 1..N}`.\n\nUse [`proc_lib:get_label/1`](`get_label/1`) to lookup the process description.","title":"proc_lib.set_label/1","ref":"proc_lib.html#set_label/1"},{"type":"function","doc":"","title":"proc_lib.spawn/1","ref":"proc_lib.html#spawn/1"},{"type":"function","doc":"","title":"proc_lib.spawn/2","ref":"proc_lib.html#spawn/2"},{"type":"function","doc":"","title":"proc_lib.spawn/3","ref":"proc_lib.html#spawn/3"},{"type":"function","doc":"Spawns a new process and initializes it as described in the beginning of this\nmanual page. The process is spawned using the [`spawn`](`erlang:spawn/1`) BIFs.","title":"proc_lib.spawn/4","ref":"proc_lib.html#spawn/4"},{"type":"function","doc":"","title":"proc_lib.spawn_link/1","ref":"proc_lib.html#spawn_link/1"},{"type":"function","doc":"","title":"proc_lib.spawn_link/2","ref":"proc_lib.html#spawn_link/2"},{"type":"function","doc":"","title":"proc_lib.spawn_link/3","ref":"proc_lib.html#spawn_link/3"},{"type":"function","doc":"Spawns a new process and initializes it as described in the beginning of this\nmanual page. The process is spawned using the\n[`spawn_link`](`erlang:spawn_link/1`) BIFs.","title":"proc_lib.spawn_link/4","ref":"proc_lib.html#spawn_link/4"},{"type":"function","doc":"","title":"proc_lib.spawn_opt/2","ref":"proc_lib.html#spawn_opt/2"},{"type":"function","doc":"","title":"proc_lib.spawn_opt/3","ref":"proc_lib.html#spawn_opt/3"},{"type":"function","doc":"","title":"proc_lib.spawn_opt/4","ref":"proc_lib.html#spawn_opt/4"},{"type":"function","doc":"Spawns a new process and initializes it as described in the beginning of this\nmanual page. The process is spawned using the\n[`erlang:spawn_opt`](`erlang:spawn_opt/2`) BIFs.","title":"proc_lib.spawn_opt/5","ref":"proc_lib.html#spawn_opt/5"},{"type":"function","doc":"","title":"proc_lib.start/3","ref":"proc_lib.html#start/3"},{"type":"function","doc":"","title":"proc_lib.start/4","ref":"proc_lib.html#start/4"},{"type":"function","doc":"Starts a new process synchronously. Spawns the process and waits for it to\nstart.\n\nTo indicate a succesful start, the started process _must_ call\n[`init_ack(Parent, Ret)`](`init_ack/2`) where `Parent` is the process that\nevaluates this function, or [`init_ack(Ret)`](`init_ack/1`). `Ret` is then\nreturned by this function.\n\nIf the process fails to start, it _must_ fail; preferably by calling\n[`init_fail(Parent, Ret, Exception)` ](`init_fail/3`) where `Parent` is the\nprocess that evaluates this function, or\n[`init_fail(Ret, Exception)`](`init_fail/2`). `Ret` is then returned by this\nfunction, and the started process fails with `Exception`.\n\nIf the process instead fails before calling `init_ack/1,2` or `init_fail/2,3`,\nthis function returns `{error, Reason}` where `Reason` depends a bit on the\nexception just like for a process link `{'EXIT',Pid,Reason}` message.\n\nIf `Time` is specified as an integer, this function waits for `Time`\nmilliseconds for the new process to call `init_ack/1,2` or `init_fail/2,3`,\notherwise the process gets killed and `Ret = {error, timeout}` is returned.\n\nArgument `SpawnOpts`, if specified, is passed as the last argument to the\n[`spawn_opt/4`](`erlang:spawn_opt/4`) BIF.\n\n> #### Note {: .info }\n>\n> Using spawn option `monitor` is not allowed. It causes the function to fail\n> with reason `badarg`.\n>\n> Using spawn option `link` will set a link to the spawned process, just like\n> [start_link/3,4,5](`start_link/3`).","title":"proc_lib.start/5","ref":"proc_lib.html#start/5"},{"type":"function","doc":"","title":"proc_lib.start_link/3","ref":"proc_lib.html#start_link/3"},{"type":"function","doc":"","title":"proc_lib.start_link/4","ref":"proc_lib.html#start_link/4"},{"type":"function","doc":"Starts a new process synchronously. Spawns the process and waits for it to\nstart. A link is atomically set on the newly spawned process.\n\n> #### Note {: .info }\n>\n> If the started process gets killed or crashes with a reason that is not\n> `normal`, the process link will kill the calling process so this function does\n> not return, unless the calling process traps exits. For example, if this\n> function times out it will kill the spawned process, and then the link might\n> kill the calling process.\n\nBesides setting a link on the spawned process this function behaves like\n[start/5](`start/5`).\n\nWhen the calling process traps exits; if this function returns due to the\nspawned process exiting (any error return), this function receives (consumes)\nthe `'EXIT'` message, also when this function times out and kills the spawned\nprocess.\n\n> #### Note {: .info }\n>\n> Using spawn option `monitor` is not allowed. It causes the function to fail\n> with reason `badarg`.","title":"proc_lib.start_link/5","ref":"proc_lib.html#start_link/5"},{"type":"function","doc":"","title":"proc_lib.start_monitor/3","ref":"proc_lib.html#start_monitor/3"},{"type":"function","doc":"","title":"proc_lib.start_monitor/4","ref":"proc_lib.html#start_monitor/4"},{"type":"function","doc":"Starts a new process synchronously. Spawns the process and waits for it to\nstart. A monitor is atomically set on the newly spawned process.\n\nBesides setting a monitor on the spawned process this function behaves like\n[start/5](`start/5`).\n\nThe return value is `{Ret, Mon}` where `Ret` corresponds to the `Ret` argument\nin the call to `init_ack/1,2` or `init_fail/2,3`, and `Mon` is the monitor\nreference of the monitor that has been set up.\n\nIf this function returns due to the spawned process exiting, that is returns any\nerror value, a `'DOWN'` message will be delivered to the calling process, also\nwhen this function times out and kills the spawned process.\n\n> #### Note {: .info }\n>\n> Using spawn option `monitor` is not allowed. It causes the function to fail\n> with reason `badarg`.\n>\n> Using spawn option `link` will set a link to the spawned process, just like\n> [start_link/3,4,5](`start_link/3`).","title":"proc_lib.start_monitor/5","ref":"proc_lib.html#start_monitor/5"},{"type":"function","doc":"Equivalent to [`stop(Process, normal, infinity)`](`stop/3`).","title":"proc_lib.stop/1","ref":"proc_lib.html#stop/1"},{"type":"function","doc":"Orders the process to exit with the specified `Reason` and waits for it to\nterminate.\n\nReturns `ok` if the process exits with the specified `Reason` within `Timeout`\nmilliseconds.\n\nIf the call times out, a `timeout` exception is raised.\n\nIf the process does not exist, a `noproc` exception is raised.\n\nThe implementation of this function is based on the `terminate` system message,\nand requires that the process handles system messages correctly. For information\nabout system messages, see `m:sys` and section\n[sys and proc_lib](`e:system:spec_proc.md`) in OTP Design Principles.","title":"proc_lib.stop/3","ref":"proc_lib.html#stop/3"},{"type":"function","doc":"This function is used by functions `\\c:i/0` and `\\c:regs/0` to present process\ninformation.\n\nThis function extracts the initial call of a process that was started using one\nof the spawn or start functions in this module, and translates it to more useful\ninformation. `Process` can either be a pid, an integer tuple (from which a pid\ncan be created), or the process information of a process `Pid` fetched through\nan `erlang:process_info(Pid)` function call.\n\nIf the initial call is to one of the system-defined behaviors such as\n`gen_server` or `gen_event`, it is translated to more useful information. If a\n`gen_server` is spawned, the returned `Module` is the name of the callback\nmodule and `Function` is `init` (the function that initiates the new server).\n\nA `supervisor` and a `supervisor_bridge` are also `gen_server` processes. To\nreturn information that this process is a supervisor and the name of the\ncallback module, `Module` is `supervisor` and `Function` is the name of the\nsupervisor callback module. `Arity` is `1`, as the `init/1` function is called\ninitially in the callback module.\n\nBy default, `{proc_lib,init_p,5}` is returned if no information about the\ninitial call can be found. It is assumed that the caller knows that the process\nhas been spawned with the `proc_lib` module.","title":"proc_lib.translate_initial_call/1","ref":"proc_lib.html#translate_initial_call/1"},{"type":"type","doc":"","title":"proc_lib.dict_or_pid/0","ref":"proc_lib.html#t:dict_or_pid/0"},{"type":"type","doc":"An exception passed to `init_fail/3`. See `erlang:raise/3` for a description\nof `Class`, `Reason` and `Stacktrace`.","title":"proc_lib.exception/0","ref":"proc_lib.html#t:exception/0"},{"type":"type","doc":"Equivalent to `t:erlang:spawn_opt_option/0`.","title":"proc_lib.spawn_option/0","ref":"proc_lib.html#t:spawn_option/0"},{"type":"type","doc":"A restricted set of [spawn options](`t:spawn_option/0`). Most notably `monitor`\nis _not_ part of these options.","title":"proc_lib.start_spawn_option/0","ref":"proc_lib.html#t:start_spawn_option/0"},{"type":"behaviour","doc":"Generic supervisor behavior.\n\nThis behavior module provides a supervisor, a process that supervises other\nprocesses called child processes. A child process can either be another\nsupervisor or a worker process. Worker processes are normally implemented using\none of the `m:gen_event`, `m:gen_server`, or `m:gen_statem` behaviors. A\nsupervisor implemented using this module has a standard set of interface\nfunctions and includes functionality for tracing and error reporting.\nSupervisors are used to build a hierarchical process structure called a\nsupervision tree, a nice way to structure a fault-tolerant application. For more\ninformation, see [Supervisor Behaviour](`e:system:sup_princ.md`) in OTP Design\nPrinciples.\n\nA supervisor expects the definition of which child processes to supervise to be\nspecified in a callback module exporting a predefined set of functions.\n\nUnless otherwise stated, all functions in this module fail if the specified\nsupervisor does not exist or if bad arguments are specified.\n\n[](){: #supervision_princ }","title":"supervisor","ref":"supervisor.html"},{"type":"behaviour","doc":"The supervisor is responsible for starting, stopping, and monitoring its child\nprocesses. The basic idea of a supervisor is that it must keep its child\nprocesses alive by restarting them when necessary.\n\nThe children of a supervisor are defined as a list of _child specifications_.\nWhen the supervisor is started, the child processes are started in order from\nleft to right according to this list. When the supervisor is going to terminate,\nit first terminates its child processes in reversed start order, from right to\nleft.\n\n[](){: #sup_flags }","title":"Supervision Principles - supervisor","ref":"supervisor.html#module-supervision-principles"},{"type":"behaviour","doc":"The supervisor properties are defined by the supervisor flags. The type\ndefinition for the supervisor flags is as follows:\n\n```erlang\nsup_flags() = #{strategy => strategy(), % optional\n intensity => non_neg_integer(), % optional\n period => pos_integer(), % optional\n auto_shutdown => auto_shutdown()} % optional\n```\n\n#### Restart Strategies\n\nA supervisor can have one of the following _restart strategies_ specified with\nthe `strategy` key in the above map:\n\n- `one_for_one` \\- If one child process terminates and is to be restarted, only\n that child process is affected. This is the default restart strategy.\n- `one_for_all` \\- If one child process terminates and is to be restarted, all\n other child processes are terminated and then all child processes are\n restarted.\n- `rest_for_one` \\- If one child process terminates and is to be restarted, the\n 'rest' of the child processes (that is, the child processes after the\n terminated child process in the start order) are terminated. Then the\n terminated child process and all child processes after it are restarted.\n- `simple_one_for_one` \\- A simplified `one_for_one` supervisor, where all child\n processes are dynamically added instances of the same process type, that is,\n running the same code.\n\n Functions `delete_child/2` and `restart_child/2` are invalid for\n `simple_one_for_one` supervisors and return `{error,simple_one_for_one}` if\n the specified supervisor uses this restart strategy.\n\n Function `terminate_child/2` can be used for children under\n `simple_one_for_one` supervisors by specifying the child's `t:pid/0` as the\n second argument. If instead the child specification identifier is used,\n [`terminate_child/2`](`terminate_child/2`) return\n `{error,simple_one_for_one}`.\n\n As a `simple_one_for_one` supervisor can have many children, it shuts them all\n down asynchronously. This means that the children do their cleanup in\n parallel, and therefore the order in which they are stopped is not defined.\n\n#### Restart intensity and period\n\nTo prevent a supervisor from getting into an infinite loop of child process\nterminations and restarts, a _maximum restart intensity_ is defined using two\ninteger values specified with keys `intensity` and `period` in the above map.\nAssuming the values `MaxR` for `intensity` and `MaxT` for `period`, then, if\nmore than `MaxR` restarts occur within `MaxT` seconds, the supervisor terminates\nall child processes and then itself. The termination reason for the supervisor\nitself in that case will be `shutdown`. `intensity` defaults to `1` and `period`\ndefaults to `5`.\n\n[](){: #auto_shutdown }\n\n#### Automatic Shutdown\n\nA supervisor can be configured to automatically shut itself down with exit\nreason `shutdown` when [significant children](`m:supervisor#significant_child`)\nterminate with the `auto_shutdown` key in the above map:\n\n- `never` \\- Automic shutdown is disabled. This is the default setting.\n\n With `auto_shutdown` set to `never`, child specs with the `significant` flag\n set to `true` are considered invalid and will be rejected.\n\n- `any_significant` \\- The supervisor will shut itself down when _any_\n significant child terminates, that is, when a `transient` significant child\n terminates normally or when a `temporary` significant child terminates\n normally or abnormally.\n- `all_significant` \\- The supervisor will shut itself down when _all_\n significant children have terminated, that is, when the _last active_\n significant child terminates. The same rules as for `any_significant` apply.\n\nFor more information, see the section\n[Automatic Shutdown](`e:system:sup_princ.md#automatic-shutdown`) in Supervisor\nBehavior in OTP Design Principles.\n\n> #### Warning {: .warning }\n>\n> The automatic shutdown feature appeared in OTP 24.0, but applications using\n> this feature will also compile and run with older OTP versions.\n>\n> However, such applications, when compiled with an OTP version that predates\n> the appearance of the automatic shutdown feature, will leak processes because\n> the automatic shutdowns they rely on will not happen.\n>\n> It is up to implementors to take proper precautions if they expect that their\n> applications may be compiled with older OTP versions.\n\n[](){: #child_spec }","title":"Supervisor flags - supervisor","ref":"supervisor.html#module-supervisor-flags"},{"type":"behaviour","doc":"The type definition of a child specification is as follows:\n\n```erlang\nchild_spec() = #{id => child_id(), % mandatory\n start => mfargs(), % mandatory\n restart => restart(), % optional\n significant => significant(), % optional\n shutdown => shutdown(), % optional\n type => worker(), % optional\n modules => modules()} % optional\n```\n\nThe old tuple format is kept for backwards compatibility, see `t:child_spec/0`,\nbut the map is preferred.\n\n- `id` is used to identify the child specification internally by the supervisor.\n\n The `id` key is mandatory.\n\n Notice that this identifier on occations has been called \"name\". As far as\n possible, the terms \"identifier\" or \"id\" are now used but to keep backward\n compatibility, some occurences of \"name\" can still be found, for example in\n error messages.\n\n- `start` defines the function call used to start the child process. It must be\n a module-function-arguments tuple `{M,F,A}` used as\n [`apply(M,F,A)`](`apply/3`).\n\n The start function _must create and link to_ the child process, and must\n return `{ok,Child}` or `{ok,Child,Info}`, where `Child` is the pid of the\n child process and `Info` any term that is ignored by the supervisor.\n\n The start function can also return `ignore` if the child process for some\n reason cannot be started, in which case the child specification is kept by the\n supervisor (unless it is a temporary child) but the non-existing child process\n is ignored.\n\n If something goes wrong, the function can also return an error tuple\n `{error,Error}`.\n\n Notice that the `start_link` functions of the different behavior modules\n fulfill the above requirements.\n\n The `start` key is mandatory.\n\n- [](){: #restart } `restart` defines when a terminated child process must be\n restarted. A `permanent` child process is always restarted. A `temporary`\n child process is never restarted (even when the supervisor's restart strategy\n is `rest_for_one` or `one_for_all` and a sibling's death causes the temporary\n process to be terminated). A `transient` child process is restarted only if it\n terminates abnormally, that is, with another exit reason than `normal`,\n `shutdown`, or `{shutdown,Term}`.\n\n The `restart` key is optional. If it is not specified, it defaults to\n `permanent`.\n\n- [](){: #significant_child } `significant` defines if a child is considered\n significant for [automatic self-shutdown](`m:supervisor#auto_shutdown`) of the\n supervisor.\n\n Setting this option to `true` when the [restart type](`m:supervisor#restart`)\n is `permanent` is invalid. Also, it is considered invalid to start children\n with this option set to `true` in a supervisor when the\n [`auto_shutdown`](`m:supervisor#auto_shutdown`) supervisor flag is set to\n `never`.\n\n The `significant` key is optional. If it is not specified, it defaults to\n `false`.\n\n- `shutdown` defines how a child process must be terminated. `brutal_kill` means\n that the child process is unconditionally terminated using\n [`exit(Child,kill)`](`exit/2`). An integer time-out value means that the\n supervisor tells the child process to terminate by calling\n [`exit(Child,shutdown)`](`exit/2`) and then wait for an exit signal with\n reason `shutdown` back from the child process. If no exit signal is received\n within the specified number of milliseconds, the child process is\n unconditionally terminated using [`exit(Child,kill)`](`exit/2`).\n\n If the child process is another supervisor, the shutdown time must be set to\n `infinity` to give the subtree ample time to shut down.\n\n > #### Warning {: .warning }\n >\n > Setting the shutdown time to anything other than `infinity` for a child of\n > type `supervisor` can cause a race condition where the child in question\n > unlinks its own children, but fails to terminate them before it is killed.\n\n It is also allowed to set it to `infinity`, if the child process is a worker.\n\n > #### Warning {: .warning }\n >\n > Be careful when setting the shutdown time to `infinity` when the child\n > process is a worker. Because, in this situation, the termination of the\n > supervision tree depends on the child process, it must be implemented in a\n > safe way and its cleanup procedure must always return.\n\n Notice that all child processes implemented using the standard OTP behavior\n modules automatically adhere to the shutdown protocol.\n\n The `shutdown` key is optional. If it is not specified, it defaults to `5000`\n if the child is of type `worker` and it defaults to `infinity` if the child is\n of type `supervisor`.\n\n- `type` specifies if the child process is a supervisor or a worker.\n\n The `type` key is optional. If it is not specified, it defaults to `worker`.\n\n- `modules` is used by the release handler during code replacement to determine\n which processes are using a certain module. As a rule of thumb, if the child\n process is a `m:supervisor`, `m:gen_server` or, `m:gen_statem`, this is to be a list\n with one element `[Module]`, where `Module` is the callback module. If the\n child process is an event manager (`m:gen_event`) with a dynamic set of callback\n modules, value `dynamic` must be used. For more information about release\n handling, see [Release Handling](`e:system:release_handling.md`) in OTP Design\n Principles.\n\n The `modules` key is optional. If it is not specified, it defaults to `[M]`,\n where `M` comes from the child's start `{M,F,A}`.\n\n- Internally, the supervisor also keeps track of the pid `Child` of the child\n process, or `undefined` if no pid exists.","title":"Child specification - supervisor","ref":"supervisor.html#module-child-specification"},{"type":"behaviour","doc":"`m:gen_event`, `m:gen_statem`, `m:gen_server`, `m:sys`","title":"See Also - supervisor","ref":"supervisor.html#module-see-also"},{"type":"function","doc":"","title":"supervisor.check_childspecs/1","ref":"supervisor.html#check_childspecs/1"},{"type":"function","doc":"Takes a list of child specification as argument and returns `ok` if all of them\nare syntactically correct, otherwise `{error,Error}`.\n\nIf the `AutoShutdown` argument is not `undefined`, also\nchecks if the child specifications are allowed for the given\n[auto_shutdown](`m:supervisor#auto_shutdown`) option.","title":"supervisor.check_childspecs/2","ref":"supervisor.html#check_childspecs/2"},{"type":"function","doc":"Returns a [property list](`t:proplists:proplist/0`) containing the counts for each of\nthe following elements of the supervisor's child specifications and managed\nprocesses:\n\n- `specs` \\- The total count of children, dead or alive.\n- `active` \\- The count of all actively running child processes managed by this\n supervisor. For a `simple_one_for_one` supervisors, no check is done to ensure\n that each child process is still alive, although the result provided here is\n likely to be very accurate unless the supervisor is heavily overloaded.\n- `supervisors` \\- The count of all children marked as `child_type = supervisor`\n in the specification list, regardless if the child process is still alive.\n- `workers` \\- The count of all children marked as `child_type = worker` in the\n specification list, regardless if the child process is still alive.","title":"supervisor.count_children/1","ref":"supervisor.html#count_children/1"},{"type":"function","doc":"Tells supervisor `SupRef` to delete the child specification identified by `Id`.\nThe corresponding child process must not be running. Use `terminate_child/2` to\nterminate it.\n\nIf successful, the function returns `ok`. If the child specification identified\nby `Id` exists but the corresponding child process is running or is about to be\nrestarted, the function returns `{error,running}` or `{error,restarting}`,\nrespectively. If the child specification identified by `Id` does not exist, the\nfunction returns `{error,not_found}`.","title":"supervisor.delete_child/2","ref":"supervisor.html#delete_child/2"},{"type":"function","doc":"Returns the child specification map for the child identified by `Id` under\nsupervisor `SupRef`. The returned map contains all keys, both mandatory and\noptional.","title":"supervisor.get_childspec/2","ref":"supervisor.html#get_childspec/2"},{"type":"callback","doc":"Whenever a supervisor is started using [`start_link/2,3`](`start_link/2`), this\nfunction is called by the new process to find out about restart strategy,\nmaximum restart intensity, and child specifications.\n\n`Args` is the `Args` argument provided to the start function.\n\n`SupFlags` is the supervisor flags defining the restart strategy and maximum\nrestart intensity for the supervisor. `[ChildSpec]` is a list of valid child\nspecifications defining which child processes the supervisor must start and\nmonitor. See the discussion in section\n[`Supervision Principles`](`m:supervisor#supervision_princ`) earlier.\n\nNotice that when the restart strategy is `simple_one_for_one`, the list of child\nspecifications must be a list with one child specification only. (The child\nspecification identifier is ignored.) No child process is then started during\nthe initialization phase, but all children are assumed to be started dynamically\nusing `start_child/2`.\n\nThe function can also return `ignore`.\n\nNotice that this function can also be called as a part of a code upgrade\nprocedure. Therefore, the function is not to have any side effects. For more\ninformation about code upgrade of supervisors, see section\n[Changing a Supervisor](`e:system:appup_cookbook.md#sup`) in OTP Design\nPrinciples.","title":"supervisor.init/1","ref":"supervisor.html#c:init/1"},{"type":"function","doc":"Tells supervisor `SupRef` to restart a child process corresponding to the child\nspecification identified by `Id`. The child specification must exist, and the\ncorresponding child process must not be running.\n\nNotice that for temporary children, the child specification is automatically\ndeleted when the child terminates; thus, it is not possible to restart such\nchildren.\n\nIf the child specification identified by `Id` does not exist, the function\nreturns `{error,not_found}`. If the child specification exists but the\ncorresponding process is already running, the function returns\n`{error,running}`.\n\nIf the child process start function returns `{ok,Child}` or `{ok,Child,Info}`,\nthe pid is added to the supervisor and the function returns the same value.\n\nIf the child process start function returns `ignore`, the pid remains set to\n`undefined` and the function returns `{ok,undefined}`.\n\nIf the child process start function returns an error tuple or an erroneous\nvalue, or if it fails, the function returns `{error,Error}`, where `Error` is a\nterm containing information about the error.","title":"supervisor.restart_child/2","ref":"supervisor.html#restart_child/2"},{"type":"function","doc":"Dynamically adds a child specification to supervisor `SupRef`, which starts the\ncorresponding child process.\n\nFor `one_for_one`, `one_for_all` and `rest_for_one` supervisors, the second\nargument must be a valid child specification `ChildSpec`. The child process\nis started by using the start function as defined in the child specification.\n\nFor `simple_one_for_one` supervisors, the child specification defined in\n[`Module:init/1`](`c:init/1`) is used, and the second argument must instead\nbe an arbitrary list of terms `ExtraArgs`. The child process is then started\nby appending `ExtraArgs` to the existing start function arguments, that is, by\ncalling [`apply(M, F, A++ExtraArgs)`](`apply/3`), where `{M,F,A}` is the start\nfunction defined in the child specification.\n\n- If there already exists a child specification with the specified identifier,\n `ChildSpec` is discarded, and the function returns `{error,already_present}`\n or `{error,{already_started,Child}}`, depending on if the corresponding child\n process is running or not.\n- If the child process start function returns `{ok,Child}` or `{ok,Child,Info}`,\n the child specification and pid are added to the supervisor and the function\n returns the same value.\n- If the child process start function returns `ignore`, the child specification\n `ChildSpec` is added to the supervisor if it is an `one_for_one`, `one_for_all`\n or `rest_for_one` supervisor, and the pid is set to `undefined`. For\n `simple_one_for_one` supervisors, no child is added to the supervisor. The\n function returns `{ok,undefined}`.\n\nIf the child process start function returns an error tuple or an erroneous\nvalue, or if it fails, the child specification is discarded, and the function\nreturns `{error,Error}`, where `Error` is a term containing information about\nthe error and child specification.","title":"supervisor.start_child/2","ref":"supervisor.html#start_child/2"},{"type":"function","doc":"Creates a nameless supervisor process as part of a supervision tree.\n\nEquivalent to `start_link/3` except that the supervisor process is not\n[`registered`](`erlang:register/2`).","title":"supervisor.start_link/2","ref":"supervisor.html#start_link/2"},{"type":"function","doc":"Creates a supervisor process as part of a supervision tree.\n\nFor example, the function ensures that the supervisor is linked to the calling\nprocess (its supervisor).\n\nThe created supervisor process calls [`Module:init/1`](`c:init/1`) to find out\nabout restart strategy, maximum restart intensity, and child processes. To\nensure a synchronized startup procedure, `start_link/2,3` does not return until\n[`Module:init/1`](`c:init/1`) has returned and all child processes have been\nstarted.\n\n- If `SupName={local,Name}`, the supervisor is registered locally as `Name`\n using [`register/2`](`register/2`).\n- If `SupName={global,Name}`, the supervisor is registered globally as `Name`\n using `global:register_name/2`.\n- If `SupName={via,Module,Name}`, the supervisor is registered as `Name` using\n the registry represented by `Module`. The `Module` callback must export the\n functions `register_name/2`, `unregister_name/1`, and `send/2`, which must\n behave like the corresponding functions in `m:global`. Thus,\n `{via,global,Name}` is a valid reference.\n\n`Module` is the name of the callback module.\n\n`Args` is any term that is passed as the argument to\n[`Module:init/1`](`c:init/1`).\n\n- If the supervisor and its child processes are successfully created (that is,\n if all child process start functions return `{ok,Child}`, `{ok,Child,Info}`,\n or `ignore`), the function returns `{ok,Pid}`, where `Pid` is the pid of the\n supervisor.\n- If there already exists a process with the specified `SupName`, the function\n returns `{error,{already_started,Pid}}`, where `Pid` is the pid of that\n process.\n- If [`Module:init/1`](`c:init/1`) returns `ignore`, this function returns\n `ignore` as well, and the supervisor terminates with reason `normal`.\n- If [`Module:init/1`](`c:init/1`) fails or returns an incorrect value, this\n function returns `{error,Term}`, where `Term` is a term with information about\n the error, and the supervisor terminates with reason `Term`.\n- If any child process start function fails or returns an error tuple or an\n erroneous value, the supervisor first terminates all already started child\n processes with reason `shutdown` and then terminate itself and returns\n `{error, {shutdown, Reason}}`.","title":"supervisor.start_link/3","ref":"supervisor.html#start_link/3"},{"type":"function","doc":"Tells supervisor `SupRef` to terminate the specified child.\n\nIf the supervisor is not `simple_one_for_one`, `Id` must be the child\nspecification identifier. The process, if any, is terminated and, unless it is a\ntemporary child, the child specification is kept by the supervisor. The child\nprocess can later be restarted by the supervisor. The child process can also be\nrestarted explicitly by calling `restart_child/2`. Use `delete_child/2` to\nremove the child specification.\n\nIf the child is temporary, the child specification is deleted as soon as the\nprocess terminates. This means that [`delete_child/2`](`delete_child/2`) has no\nmeaning and [`restart_child/2`](`restart_child/2`) cannot be used for these\nchildren.\n\nIf the supervisor is `simple_one_for_one`, `Id` must be the `t:pid/0` of the\nchild process. If the specified process is alive, but is not a child of the\nspecified supervisor, the function returns `{error,not_found}`. If the child\nspecification identifier is specified instead of a `t:pid/0`, the function\nreturns `{error,simple_one_for_one}`.\n\nIf successful, the function returns `ok`. If there is no child specification\nwith the specified `Id`, the function returns `{error,not_found}`.","title":"supervisor.terminate_child/2","ref":"supervisor.html#terminate_child/2"},{"type":"function","doc":"Returns information about the child specification and child process identified\nby the given `Id`.\n\nSee `which_children/1` for an explanation of the information returned.\n\nIf no child with the given `Id` exists, returns `{error, not_found}`.","title":"supervisor.which_child/2","ref":"supervisor.html#which_child/2"},{"type":"function","doc":"Returns a newly created list with information about all child specifications and\nchild processes belonging to supervisor `SupRef`.\n\nNotice that calling this function when supervising many children under low\nmemory conditions can cause an out of memory exception.\n\nThe following information is given for each child specification/process:\n\n- `Id` \\- As defined in the child specification or `undefined` for a\n `simple_one_for_one` supervisor.\n- `Child` \\- The pid of the corresponding child process, the atom `restarting`\n if the process is about to be restarted, or `undefined` if there is no such\n process.\n- `Type` \\- As defined in the child specification.\n- `Modules` \\- As defined in the child specification.","title":"supervisor.which_children/1","ref":"supervisor.html#which_children/1"},{"type":"type","doc":"","title":"supervisor.auto_shutdown/0","ref":"supervisor.html#t:auto_shutdown/0"},{"type":"type","doc":"","title":"supervisor.child/0","ref":"supervisor.html#t:child/0"},{"type":"type","doc":"Not a `t:pid/0`.","title":"supervisor.child_id/0","ref":"supervisor.html#t:child_id/0"},{"type":"type","doc":"","title":"supervisor.child_rec/0","ref":"supervisor.html#t:child_rec/0"},{"type":"type","doc":"The tuple format is kept for backward compatibility only. A map is preferred;\nsee more details [above](`m:supervisor#child_spec`).","title":"supervisor.child_spec/0","ref":"supervisor.html#t:child_spec/0"},{"type":"type","doc":"","title":"supervisor.children/0","ref":"supervisor.html#t:children/0"},{"type":"type","doc":"Value `undefined` for `A` (the argument list) is only to be used internally in\n`m:supervisor`. If the restart type of the child is `temporary`, the process is\nnever to be restarted and therefore there is no need to store the real argument\nlist. Value `undefined` is then stored instead.","title":"supervisor.mfargs/0","ref":"supervisor.html#t:mfargs/0"},{"type":"type","doc":"","title":"supervisor.modules/0","ref":"supervisor.html#t:modules/0"},{"type":"type","doc":"","title":"supervisor.restart/0","ref":"supervisor.html#t:restart/0"},{"type":"type","doc":"","title":"supervisor.shutdown/0","ref":"supervisor.html#t:shutdown/0"},{"type":"type","doc":"","title":"supervisor.significant/0","ref":"supervisor.html#t:significant/0"},{"type":"type","doc":"","title":"supervisor.startchild_err/0","ref":"supervisor.html#t:startchild_err/0"},{"type":"type","doc":"","title":"supervisor.startchild_ret/0","ref":"supervisor.html#t:startchild_ret/0"},{"type":"type","doc":"","title":"supervisor.startlink_err/0","ref":"supervisor.html#t:startlink_err/0"},{"type":"type","doc":"","title":"supervisor.startlink_ret/0","ref":"supervisor.html#t:startlink_ret/0"},{"type":"type","doc":"","title":"supervisor.strategy/0","ref":"supervisor.html#t:strategy/0"},{"type":"type","doc":"The tuple format is kept for backward compatibility only. A map is preferred;\nsee more details [above](`m:supervisor#sup_flags`).","title":"supervisor.sup_flags/0","ref":"supervisor.html#t:sup_flags/0"},{"type":"type","doc":"Name specification to use when starting a `supervisor`. See function\n[`start_link/2,3`](`start_link/2`) and the type `t:sup_ref/0` below.\n\n- **`{local,LocalName}`** - Register the `supervisor` locally as `LocalName`\n using [`register/2`](`erlang:register/2`).\n\n- **`{global,GlobalName}`** - Register the `supervisor` process id globally as\n `GlobalName` using `global:register_name/2`.\n\n- **`{via,RegMod,ViaName}`** - Register the `supervisor` process with the\n registry represented by `RegMod`. The `RegMod` callback is to export the\n functions `register_name/2`, `unregister_name/1`, `whereis_name/1`, and\n `send/2`, which are to behave like the corresponding functions in `m:global`.\n Thus, `{via,global,GlobalName}` is a valid reference equivalent to\n `{global,GlobalName}`.","title":"supervisor.sup_name/0","ref":"supervisor.html#t:sup_name/0"},{"type":"type","doc":"Supervisor specification to use when addressing a `supervisor`. See\n[`count_children/1`](`count_children/1`), [`delete_child/2`](`delete_child/2`),\n[`get_childspec/2`](`get_childspec/2`), [`restart_child/2`](`restart_child/2`),\n[`start_child/2`](`start_child/2`), [`terminate_child/2`](`terminate_child/2`),\n[`which_children/1`](`which_children/1`) and the type `t:sup_name/0` above.\n\nIt can be:\n\n- **`t:pid/0`** - The `supervisor`'s process identifier.\n\n- **`LocalName`** - The `supervisor` is locally registered as `LocalName` with\n [`register/2`](`erlang:register/2`).\n\n- **`{Name,Node}`** - The `supervisor` is locally registered on another node.\n\n- **`{global,GlobalName}`** - The `supervisor` is globally registered in\n `m:global`.\n\n- **`{via,RegMod,ViaName}`** - The `supervisor` is registered in an alternative\n process registry. The registry callback module `RegMod` is to export functions\n `register_name/2`, `unregister_name/1`, `whereis_name/1`, and `send/2`, which\n are to behave like the corresponding functions in `m:global`. Thus,\n `{via,global,GlobalName}` is the same as `{global,GlobalName}`.","title":"supervisor.sup_ref/0","ref":"supervisor.html#t:sup_ref/0"},{"type":"type","doc":"","title":"supervisor.worker/0","ref":"supervisor.html#t:worker/0"},{"type":"behaviour","doc":"Generic supervisor bridge behavior.\n\nThis behavior module provides a supervisor bridge, a process that connects a\nsubsystem not designed according to the OTP design principles to a supervision\ntree. The supervisor bridge sits between a supervisor and the subsystem. It\nbehaves like a real supervisor to its own supervisor, but has a different\ninterface than a real supervisor to the subsystem. For more information, see\n[Supervisor Behaviour](`e:system:sup_princ.md`) in OTP Design Principles.\n\nA supervisor bridge assumes the functions for starting and stopping the\nsubsystem to be located in a callback module exporting a predefined set of\nfunctions.\n\nThe `m:sys` module can be used for debugging a supervisor bridge.\n\nUnless otherwise stated, all functions in this module fail if the specified\nsupervisor bridge does not exist or if bad arguments are specified.","title":"supervisor_bridge","ref":"supervisor_bridge.html"},{"type":"behaviour","doc":"`m:supervisor`, `m:sys`","title":"See Also - supervisor_bridge","ref":"supervisor_bridge.html#module-see-also"},{"type":"callback","doc":"Whenever a supervisor bridge is started using\n[`start_link/2,3`](`start_link/2`), this function is called by the new process\nto start the subsystem and initialize.\n\n`Args` is the `Args` argument provided to the start function.\n\nThe function is to return `{ok,Pid,State}`, where `Pid` is the pid of the main\nprocess in the subsystem and `State` is any term.\n\nIf later `Pid` terminates with a reason `Reason`, the supervisor bridge\nterminates with reason `Reason` as well. If later the supervisor bridge is\nstopped by its supervisor with reason `Reason`, it calls\n[`Module:terminate(Reason,State)`](`c:terminate/2`) to terminate.\n\nIf the initialization fails, the function is to return `{error,Error}`, where\n`Error` is any term, or `ignore`.","title":"supervisor_bridge.init/1","ref":"supervisor_bridge.html#c:init/1"},{"type":"function","doc":"Creates a nameless supervisor bridge process as part of a supervision tree.\n\nEquivalent to `start_link/3` except that the supervisor process is not\n[`registered`](`erlang:register/2`).","title":"supervisor_bridge.start_link/2","ref":"supervisor_bridge.html#start_link/2"},{"type":"function","doc":"Creates a supervisor bridge process, linked to the calling process, which calls\n[`Module:init/1`](`c:init/1`) to start the subsystem.\n\nTo ensure a synchronized startup procedure, this function does not return until\n[`Module:init/1`](`c:init/1`) has returned.\n\n- If `SupBridgeName={local,Name}`, the supervisor bridge is registered locally\n as `Name` using [`register/2`](`register/2`).\n- If `SupBridgeName={global,GlobalName}`, the supervisor bridge is registered\n globally as `GlobalName` using `global:register_name/2`.\n- If `SupBridgeName={via,Module,ViaName}`, the supervisor bridge is registered\n as `ViaName` using a registry represented by Module. The `Module` callback is\n to export functions `register_name/2`, `unregister_name/1`, and `send/2`,\n which are to behave like the corresponding functions in `m:global`. Thus,\n `{via,global,GlobalName}` is a valid reference.\n\n`Module` is the name of the callback module.\n\n`Args` is an arbitrary term that is passed as the argument to\n[`Module:init/1`](`c:init/1`).\n\n- If the supervisor bridge and the subsystem are successfully started, the\n function returns `{ok,Pid}`, where `Pid` is is the pid of the supervisor\n bridge.\n- If there already exists a process with the specified `SupBridgeName`, the\n function returns `{error,{already_started,Pid}}`, where `Pid` is the pid of\n that process.\n- If [`Module:init/1`](`c:init/1`) returns `ignore`, this function returns\n `ignore` as well and the supervisor bridge terminates with reason `normal`.\n- If [`Module:init/1`](`c:init/1`) fails or returns an error tuple or an\n incorrect value, this function returns `{error,Error}`, where `Error` is a\n term with information about the error, and the supervisor bridge terminates\n with reason `Error`.","title":"supervisor_bridge.start_link/3","ref":"supervisor_bridge.html#start_link/3"},{"type":"callback","doc":"This function is called by the supervisor bridge when it is about to terminate.\nIt is to be the opposite of [`Module:init/1`](`c:init/1`) and stop the subsystem\nand do any necessary cleaning up. The return value is ignored.\n\n`Reason` is `shutdown` if the supervisor bridge is terminated by its supervisor.\nIf the supervisor bridge terminates because a a linked process (apart from the\nmain process of the subsystem) has terminated with reason `Term`, then `Reason`\nbecomes `Term`.\n\n`State` is taken from the return value of [`Module:init/1`](`c:init/1`).","title":"supervisor_bridge.terminate/2","ref":"supervisor_bridge.html#c:terminate/2"},{"type":"behaviour","doc":"A functional interface to system messages.\n\nThis module contains functions for sending system messages used by programs, and\nmessages used for debugging purposes.\n\nFunctions used for implementation of processes are also expected to understand\nsystem messages, such as debug messages and code change. These functions must be\nused to implement the use of system messages for a process; either directly, or\nthrough standard behaviors, such as `m:gen_server`.\n\nThe default time-out is 5000 ms, unless otherwise specified. `timeout` defines\nthe time to wait for the process to respond to a request. If the process does\nnot respond, the function evaluates [`exit({timeout, {M, F, A}})`](`exit/1`).\n\n[](){: #dbg_opt }\n\nThe functions make references to a debug structure. The debug structure is a\nlist of `t:dbg_opt/0`, which is an internal data type used by function\n`handle_system_msg/6`. No debugging is performed if it is an empty list.","title":"sys","ref":"sys.html"},{"type":"behaviour","doc":"Processes that are not implemented as one of the standard behaviors must still\nunderstand system messages. The following three messages must be understood:\n\n- Plain system messages. These are received as `{system, From, Msg}`. The\n content and meaning of this message are not interpreted by the receiving\n process module. When a system message is received, function\n `handle_system_msg/6` is called to handle the request.\n- Shutdown messages. If the process traps exits, it must be able to handle a\n shutdown request from its parent, the supervisor. The message\n `{'EXIT', Parent, Reason}` from the parent is an order to terminate. The\n process must terminate when this message is received, normally with the same\n `Reason` as `Parent`.\n- If the modules used to implement the process change dynamically during\n runtime, the process must understand one more message. An example is the\n `m:gen_event` processes. The message is `{_Label, {From, Ref}, get_modules}`.\n The reply to this message is `From ! {Ref, Modules}`, where `Modules` is a\n list of the currently active modules in the process.\n\n This message is used by the release handler to find which processes that\n execute a certain module. The process can later be suspended and ordered to\n perform a code change for one of its modules.","title":"System Messages - sys","ref":"sys.html#module-system-messages"},{"type":"behaviour","doc":"When debugging a process with the functions of this module, the process\ngenerates _system_events_, which are then treated in the debug function. For\nexample, `trace` formats the system events to the terminal.\n\nFour predefined system events are used when a process receives or sends a\nmessage. The process can also define its own system events. It is always up to\nthe process itself to format these events.","title":"System Events - sys","ref":"sys.html#module-system-events"},{"type":"function","doc":"","title":"sys.change_code/4","ref":"sys.html#change_code/4"},{"type":"function","doc":"Tells the process to change code.\n\nThe process must be suspended to handle this message.\nArgument `Extra` is reserved for each process to use as its own.\nFunction [`Module:system_code_change/4`](`c:system_code_change/4`) is called.\n`OldVsn` is the old version of the `Module`.","title":"sys.change_code/5","ref":"sys.html#change_code/5"},{"type":"function","doc":"Can be used by a process that initiates a debug structure from a list of\noptions. The values of argument `Opt` are the same as for the corresponding\nfunctions.","title":"sys.debug_options/1","ref":"sys.html#debug_options/1"},{"type":"function","doc":"Gets the data associated with a debug option. `Default` is returned if `Item` is\nnot found. Can be used by the process to retrieve debug data for printing before\nit terminates.","title":"sys.get_debug/3","ref":"sys.html#get_debug/3"},{"type":"function","doc":"Returns the logged system events in the debug structure, that is the last\nargument to `handle_debug/4`.","title":"sys.get_log/1","ref":"sys.html#get_log/1"},{"type":"function","doc":"","title":"sys.get_state/1","ref":"sys.html#get_state/1"},{"type":"function","doc":"Gets the state of the process.\n\n> #### Note {: .info }\n>\n> These functions are intended only to help with debugging. They are provided\n> for convenience, allowing developers to avoid having to create their own state\n> extraction functions and also avoid having to interactively extract the state\n> from the return values of `get_status/1` or `get_status/2` while debugging.\n\nThe value of `State` varies for different types of processes, as follows:\n\n- For a `m:gen_server` process, the returned `State` is the state of the\n callback module.\n- For a `m:gen_statem` process, `State` is the tuple\n `{CurrentState,CurrentData}`.\n- For a `m:gen_event` process, `State` is a list of tuples, where each tuple\n corresponds to an event handler registered in the process and contains\n `{Module, Id, HandlerState}`, as follows:\n\n - **`Module`** - The module name of the event handler.\n\n - **`Id`** - The ID of the handler (which is `false` if it was registered\n without an ID).\n\n - **`HandlerState`** - The state of the handler.\n\nIf the callback module exports a function\n[`system_get_state/1`](`c:system_get_state/1`), it is called in the target\nprocess to get its state. Its argument is the same as the `Misc` value returned\nby [`get_status/1,2`](`get_status/1`), and function\n[`Module:system_get_state/1`](`c:system_get_state/1`) is expected to extract the\nstate of the callback module from it. Function\n[`system_get_state/1`](`c:system_get_state/1`) must return `{ok, State}`, where\n`State` is the state of the callback module.\n\nIf the callback module does not export a\n[`system_get_state/1`](`c:system_get_state/1`) function, `get_state/1,2` assumes\nthat the `Misc` value is the state of the callback module and returns it\ndirectly instead.\n\nIf the callback module's [`system_get_state/1`](`c:system_get_state/1`) function\ncrashes or throws an exception, the caller exits with error\n`{callback_failed, {Module, system_get_state}, {Class, Reason}}`, where `Module`\nis the name of the callback module and `Class` and `Reason` indicate details of\nthe exception.\n\nFunction [`system_get_state/1`](`c:system_get_state/1`) is primarily useful for\nuser-defined behaviors and modules that implement OTP\n[special processes](`m:sys#process-implementation-functions`). The `m:gen_server`,\n`m:gen_statem`, and `m:gen_event` OTP behavior modules export this function, so\ncallback modules for those behaviors need not to supply their own.\n\nFor more information about a process, including its state, see `get_status/1`\nand `get_status/2`.","title":"sys.get_state/2","ref":"sys.html#get_state/2"},{"type":"function","doc":"","title":"sys.get_status/1","ref":"sys.html#get_status/1"},{"type":"function","doc":"Gets the status of the process.\n\nThe value of `Misc` varies for different types of processes, for example:\n\n- A `m:gen_server` process returns the state of the callback module.\n- A `m:gen_statem` process returns information, such as its current state name\n and state data.\n- A `m:gen_event` process returns information about each of its registered\n handlers.\n- A bare `m:sys` process returns the value passed as `Misc` to\n `handle_system_message/6`.\n\nCallback modules for `m:gen_server`, `m:gen_statem`, and `m:gen_event` can also change\nthe value of `Misc` by exporting a function `format_status/1`, which contributes\nmodule-specific information. For details, see `c:gen_server:format_status/1`,\n`c:gen_statem:format_status/1`, and `c:gen_event:format_status/1`.","title":"sys.get_status/2","ref":"sys.html#get_status/2"},{"type":"function","doc":"This function is called by a process when it generates a system event.\n`FormFunc` is a formatting function, called as `FormFunc(Device, Event, Extra)`\nto print the events, which is necessary if tracing is activated. `Extra` is any\nextra information that the process needs in the format function, for example,\nthe process name.","title":"sys.handle_debug/4","ref":"sys.html#handle_debug/4"},{"type":"function","doc":"This function is used by a process module to take care of system messages. The\nprocess receives a `{system, From, Msg}` message and passes `Msg` and `From` to\nthis function.\n\nThis function _never_ returns. It calls either of the following functions:\n\n- [`Module:system_continue(Parent, NDebug, Misc)`](`c:system_continue/3`), where\n the process continues the execution.\n- [`Module:system_terminate(Reason, Parent, Debug, Misc)`](`c:system_terminate/4`),\n if the process is to terminate.\n\n`Module` must export the following:\n\n- [`system_continue/3`](`c:system_continue/3`)\n- [`system_terminate/4`](`c:system_terminate/4`)\n- [`system_code_change/4`](`c:system_code_change/4`)\n- [`system_get_state/1`](`c:system_get_state/1`)\n- [`system_replace_state/2`](`c:system_replace_state/2`)\n\nArgument `Misc` can be used to save internal data in a process, for example, its\nstate. It is sent to [`Module:system_continue/3`](`c:system_continue/3`) or\n[`Module:system_terminate/4`](`c:system_terminate/4`).","title":"sys.handle_system_msg/6","ref":"sys.html#handle_system_msg/6"},{"type":"function","doc":"","title":"sys.install/2","ref":"sys.html#install/2"},{"type":"function","doc":"Enables installation of alternative debug functions. An example of such a\nfunction is a trigger, a function that waits for some special event and performs\nsome action when the event is generated. For example, turning on low-level\ntracing.\n\n`Func` is called whenever a system event is generated. This function is to\nreturn `done`, or a new `Func` state. In the first case, the function is\nremoved. It is also removed if the function fails. If one debug function should\nbe installed more times, a unique `FuncId` must be specified for each\ninstallation.","title":"sys.install/3","ref":"sys.html#install/3"},{"type":"function","doc":"","title":"sys.log/2","ref":"sys.html#log/2"},{"type":"function","doc":"Turns the logging of system events on or off. If on, a maximum of `N` events are\nkept in the debug structure (default is 10).\n\nIf `Flag` is `get`, a list of all logged events is returned.\n\nIf `Flag` is `print`, the logged events are printed to\n[`standard_io`](`t:io:standard_io/0`).\n\nThe events are formatted with a function that is defined by the process that\ngenerated the event (with a call to [`handle_debug/4`)](`handle_debug/4`).","title":"sys.log/3","ref":"sys.html#log/3"},{"type":"function","doc":"","title":"sys.log_to_file/2","ref":"sys.html#log_to_file/2"},{"type":"function","doc":"Enables or disables the logging of all system events in text format to the file.\nThe events are formatted with a function that is defined by the process that\ngenerated the event (with a call to `handle_debug/4`). The file is opened with\nencoding UTF-8.","title":"sys.log_to_file/3","ref":"sys.html#log_to_file/3"},{"type":"function","doc":"","title":"sys.no_debug/1","ref":"sys.html#no_debug/1"},{"type":"function","doc":"Turns off all debugging for the process. This includes functions that are\ninstalled explicitly with function [`install/2,3`](`install/2`), for example,\ntriggers.","title":"sys.no_debug/2","ref":"sys.html#no_debug/2"},{"type":"function","doc":"Prints the logged system events in the debug structure, using `FormFunc` as\ndefined when the event was generated by a call to `handle_debug/4`.","title":"sys.print_log/1","ref":"sys.html#print_log/1"},{"type":"function","doc":"","title":"sys.remove/2","ref":"sys.html#remove/2"},{"type":"function","doc":"Removes an installed debug function from the process. `Func` or `FuncId` must be\nthe same as previously installed.","title":"sys.remove/3","ref":"sys.html#remove/3"},{"type":"function","doc":"","title":"sys.replace_state/2","ref":"sys.html#replace_state/2"},{"type":"function","doc":"Replaces the state of the process, and returns the new state.\n\n> #### Note {: .info }\n>\n> These functions are intended only to help with debugging, and are not to be\n> called from normal code. They are provided for convenience, allowing\n> developers to avoid having to create their own custom state replacement\n> functions.\n\nFunction `StateFun` provides a new state for the process. Argument `State` and\nthe `NewState` return value of `StateFun` vary for different types of processes\nas follows:\n\n- For a `m:gen_server` process, `State` is the state of the callback module and\n `NewState` is a new instance of that state.\n- For a `m:gen_statem` process, `State` is the tuple\n `{CurrentState,CurrentData}`, and `NewState` is a similar tuple, which can\n contain a new current state, new state data, or both.\n- For a `m:gen_event` process, `State` is the tuple `{Module, Id, HandlerState}`\n as follows:\n\n - **`Module`** - The module name of the event handler.\n\n - **`Id`** - The ID of the handler (which is `false` if it was registered\n without an ID).\n\n - **`HandlerState`** - The state of the handler.\n\n `NewState` is a similar tuple where `Module` and `Id` are to have the same\n values as in `State`, but the value of `HandlerState` can be different.\n Returning a `NewState`, whose `Module` or `Id` values differ from those of\n `State`, leaves the state of the event handler unchanged. For a `m:gen_event`\n process, `StateFun` is called once for each event handler registered in the\n `m:gen_event` process.\n\nIf a `StateFun` function decides not to effect any change in process state, then\nregardless of process type, it can return its `State` argument.\n\nIf a `StateFun` function crashes or throws an exception, the original state of\nthe process is unchanged for `m:gen_server`, and `m:gen_statem` processes. For\n`m:gen_event` processes, a crashing or failing `StateFun` function means that only\nthe state of the particular event handler it was working on when it failed or\ncrashed is unchanged; it can still succeed in changing the states of other event\nhandlers registered in the same `m:gen_event` process.\n\nIf the callback module exports a `c:system_replace_state/2` function, it is\ncalled in the target process to replace its state using `StateFun`. Its two\narguments are `StateFun` and `Misc`, where `Misc` is the same as the `Misc`\nvalue returned by [`get_status/1,2`](`get_status/1`). A\n[`system_replace_state/2`](`c:system_replace_state/2`) function is expected to\nreturn `{ok, NewState, NewMisc}`, where `NewState` is the new state of the\ncallback module, obtained by calling `StateFun`, and `NewMisc` is a possibly new\nvalue used to replace the original `Misc` (required as `Misc` often contains the\nstate of the callback module within it).\n\nIf the callback module does not export a\n[`system_replace_state/2`](`c:system_replace_state/2`) function,\n[`replace_state/2,3`](`replace_state/2`) assumes that `Misc` is the state of the\ncallback module, passes it to `StateFun` and uses the return value as both the\nnew state and as the new value of `Misc`.\n\nIf the callback module's function\n[`system_replace_state/2`](`c:system_replace_state/2`) crashes or throws an\nexception, the caller exits with error\n`{callback_failed, {Module, system_replace_state}, {Class, Reason}}`, where\n`Module` is the name of the callback module and `Class` and `Reason` indicate\ndetails of the exception. If the callback module does not provide a\n[`system_replace_state/2`](`c:system_replace_state/2`) function and `StateFun`\ncrashes or throws an exception, the caller exits with error\n`{callback_failed, StateFun, {Class, Reason}}`.\n\nFunction [`system_replace_state/2`](`c:system_replace_state/2`) is primarily\nuseful for user-defined behaviors and modules that implement OTP\n[special processes](`m:sys#process-implementation-functions`). The OTP behavior\nmodules `m:gen_server`, `m:gen_statem`, and `m:gen_event` export this function, so\ncallback modules for those behaviors need not to supply their own.","title":"sys.replace_state/3","ref":"sys.html#replace_state/3"},{"type":"function","doc":"","title":"sys.resume/1","ref":"sys.html#resume/1"},{"type":"function","doc":"Resumes a suspended process.","title":"sys.resume/2","ref":"sys.html#resume/2"},{"type":"function","doc":"","title":"sys.statistics/2","ref":"sys.html#statistics/2"},{"type":"function","doc":"Enables or disables the collection of statistics. If `Flag` is `get`, the\nstatistical collection is returned.","title":"sys.statistics/3","ref":"sys.html#statistics/3"},{"type":"function","doc":"","title":"sys.suspend/1","ref":"sys.html#suspend/1"},{"type":"function","doc":"Suspends the process. When the process is suspended, it only responds to other\nsystem messages, but not other messages.","title":"sys.suspend/2","ref":"sys.html#suspend/2"},{"type":"callback","doc":"Called from `handle_system_msg/6` when the process is to perform a code change.\nThe code change is used when the internal data structure has changed. This\nfunction converts argument `Misc` to the new data structure. `OldVsn` is\nattribute _vsn_ of the old version of the `Module`. If no such attribute is\ndefined, the atom `undefined` is sent.","title":"sys.system_code_change/4","ref":"sys.html#c:system_code_change/4"},{"type":"callback","doc":"Called from `handle_system_msg/6` when the process is to continue its execution\n(for example, after it has been suspended). This function never returns.","title":"sys.system_continue/3","ref":"sys.html#c:system_continue/3"},{"type":"callback","doc":"Called from `handle_system_msg/6` when the process is to return a term that\nreflects its current state. `State` is the value returned by `get_state/2`.","title":"sys.system_get_state/1","ref":"sys.html#c:system_get_state/1"},{"type":"callback","doc":"Called from `handle_system_msg/6` when the process is to replace its current\nstate. `NState` is the value returned by `replace_state/3`.","title":"sys.system_replace_state/2","ref":"sys.html#c:system_replace_state/2"},{"type":"callback","doc":"Called from `handle_system_msg/6` when the process is to terminate. For example,\nthis function is called when the process is suspended and its parent orders\nshutdown. It gives the process a chance to do a cleanup. This function never\nreturns.","title":"sys.system_terminate/4","ref":"sys.html#c:system_terminate/4"},{"type":"function","doc":"","title":"sys.terminate/2","ref":"sys.html#terminate/2"},{"type":"function","doc":"Orders the process to terminate with the specified `Reason`. The termination is\ndone asynchronously, so it is not guaranteed that the process is terminated when\nthe function returns.","title":"sys.terminate/3","ref":"sys.html#terminate/3"},{"type":"function","doc":"","title":"sys.trace/2","ref":"sys.html#trace/2"},{"type":"function","doc":"Prints all system events on [`standard_io`](`t:io:standard_io/0`). The events\nare formatted with a function that is defined by the process that generated the\nevent (with a call to `handle_debug/4`).","title":"sys.trace/3","ref":"sys.html#trace/3"},{"type":"type","doc":"","title":"sys.dbg_fun/0","ref":"sys.html#t:dbg_fun/0"},{"type":"opaque","doc":"See the introduction of this manual page.","title":"sys.dbg_opt/0","ref":"sys.html#t:dbg_opt/0"},{"type":"type","doc":"","title":"sys.debug_option/0","ref":"sys.html#t:debug_option/0"},{"type":"type","doc":"","title":"sys.format_fun/0","ref":"sys.html#t:format_fun/0"},{"type":"type","doc":"","title":"sys.name/0","ref":"sys.html#t:name/0"},{"type":"type","doc":"Debug events produced by `m:gen_server`, `m:gen_statem` and `m:gen_event`\n\n- **`{in,Msg}`** - Is produced by `m:gen_server` and `m:gen_event` when the message\n `Msg` arrives.\n\n- **`{in,Msg,State}`** - Is produced by `m:gen_statem` when the message `Msg`\n arrives in state `State`.\n\n For `m:gen_statem` the `Msg` term is an `{EventType,EventContent}` tuple.\n\n- **`{out,Msg,To}`** - Is produced by `m:gen_statem` when the reply `Msg` is sent\n back to `To` by returning a `{reply,To,Msg}` action from the callback module.\n\n `To` is of the same type as the first argument to `gen_statem:reply/2`.\n\n- **`{out,Msg,To,State}`** - Is produced by `m:gen_server` when the reply `Msg` is\n sent back to `To` by returning a `{reply,...}` tuple from the callback module.\n\n `To` is of the same type as the first argument to `gen_server:reply/2`.\n\n `State` is the new server state.\n\n- **`{noreply,State}`** - Is produced by `m:gen_server` when a `{noreply,...}`\n tuple is returned from the callback module.\n\n `State` is the new server state.\n\n- **`{continue,Continuation}`** - Is produced by `m:gen_server` when a\n `{continue,Continuation}` tuple is returned from the callback module.\n\n- **`{postpone,Event,State,NextState}`** - Is produced by `m:gen_statem` when the\n message `Event` is postponed in state `State`. `NextState` is the new state.\n\n `Event` is an `{EventType,EventContent}` tuple.\n\n- **`{consume,Event,State,NextState}`** - Is produced by `m:gen_statem` when the\n message `Event` is consumed in state `State`. `NextState` is the new state.\n\n `Event` is an `{EventType,EventContent}` tuple.\n\n- **`{start_timer,Action,State}`** - Is produced by `m:gen_statem` when the action\n `Action` starts a timer in state `State`.\n\n- **`{insert_timeout,Event,State}`** - Is produced by `m:gen_statem` when a\n timeout zero action inserts event `Event` in state `State`.\n\n `Event` is an `{EventType,EventContent}` tuple.\n\n- **`{enter,Module,State}`** - Is produced by `m:gen_statem` when module `Module`\n enters the first state `State`.\n\n- **`{module,Module,State}`** - Is produced by `m:gen_statem` when setting module\n `Module` in state `State`.\n\n- **`{terminate,Reason,State}`** - Is produced by `m:gen_statem` when it\n terminates with reason `Reason` in state `State`.","title":"sys.system_event/0","ref":"sys.html#t:system_event/0"},{"type":"module","doc":"Command line interface module.\n\nThis module enables users to enter the short form of some commonly used\ncommands.\n\n> #### Note {: .info }\n>\n> These functions are intended for interactive use in the Erlang shell only. The\n> module prefix can be omitted.","title":"c","ref":"c.html"},{"type":"module","doc":"`m:filename`, `m:compile`, `m:erlang`, `m:yecc`, `m:xref`","title":"See Also - c","ref":"c.html#module-see-also"},{"type":"function","doc":"Stack backtrace for a process. Equivalent to\n`erlang:process_display(Pid, backtrace)`.","title":"c.bt/1","ref":"c.html#bt/1"},{"type":"function","doc":"Works like [`c(Module, [])`](`c/2`).","title":"c.c/1","ref":"c.html#c/1"},{"type":"function","doc":"Compiles and then purges and loads the code for a module. `Module` can be either\na module name or a source file path, with or without `.erl` extension.\n\nIf `Module` is a string, it is assumed to be a source file path, and the\ncompiler will attempt to compile the source file with the options `Options`. If\ncompilation fails, the old object file (if any) is deleted.\n\nIf `Module` is an atom, a source file with that exact name or with `.erl`\nextension will be looked for. If found, the source file is compiled with the\noptions `Options`. If compilation fails, the old object file (if any) is\ndeleted.\n\nIf `Module` is an atom and is not the path of a source file, then the code path\nis searched to locate the object file for the module and extract its original\ncompiler options and source path. If the source file is not found in the\noriginal location, `filelib:find_source/1` is used to search for it relative to\nthe directory of the object file.\n\nThe source file is compiled with the the original options appended to the given\n`Options`, the output replacing the old object file if and only if compilation\nsucceeds.\n\nNotice that purging the code means that any processes lingering in old code for\nthe module are killed without warning. For more information, see the `m:code`\nmodule.","title":"c.c/2","ref":"c.html#c/2"},{"type":"function","doc":"Compiles and then purges and loads the code for module `Module`, which must be\nan atom.\n\nThe code path is searched to locate the object file for module `Module` and\nextract its original compiler options and source path. If the source file is not\nfound in the original location, `filelib:find_source/1` is used to search for it\nrelative to the directory of the object file.\n\nThe source file is compiled with the the original options appended to the given\n`Options`, the output replacing the old object file if and only if compilation\nsucceeds. The function `Filter` specifies which elements to remove from the\noriginal compiler options before the new options are added. The `Filter` fun\nshould return `true` for options to keep, and `false` for options to remove.\n\nNotice that purging the code means that any processes lingering in old code for\nthe module are killed without warning. For more information, see the `m:code`\nmodule.","title":"c.c/3","ref":"c.html#c/3"},{"type":"function","doc":"Changes working directory to `Dir`, which can be a relative name, and then\nprints the name of the new working directory.\n\n_Example:_\n\n```text\n2> cd(\"../erlang\").\n/home/ron/erlang\n```","title":"c.cd/1","ref":"c.html#cd/1"},{"type":"function","doc":"Search `PathList` and load `.erlang` resource file if found.","title":"c.erlangrc/1","ref":"c.html#erlangrc/1"},{"type":"function","doc":"Flushes any messages sent to the shell.","title":"c.flush/0","ref":"c.html#flush/0"},{"type":"function","doc":"Print the documentation for `Module`","title":"c.h/1","ref":"c.html#h/1"},{"type":"function","doc":"Print the documentation for all `Module:Function`s (regardless of arity).","title":"c.h/2","ref":"c.html#h/2"},{"type":"function","doc":"Print the documentation for `Module:Function/Arity`.","title":"c.h/3","ref":"c.html#h/3"},{"type":"function","doc":"Print the callback documentation for `Module`","title":"c.hcb/1","ref":"c.html#hcb/1"},{"type":"function","doc":"Print the callback documentation for all `Module:Callback`s (regardless of\narity).","title":"c.hcb/2","ref":"c.html#hcb/2"},{"type":"function","doc":"Print the callback documentation for `Module:Callback/Arity`.","title":"c.hcb/3","ref":"c.html#hcb/3"},{"type":"function","doc":"Displays help information: all valid shell internal commands, and commands in\nthis module.","title":"c.help/0","ref":"c.html#help/0"},{"type":"function","doc":"Print the type documentation for `Module`","title":"c.ht/1","ref":"c.html#ht/1"},{"type":"function","doc":"Print the type documentation for `Type` in `Module` regardless of arity.","title":"c.ht/2","ref":"c.html#ht/2"},{"type":"function","doc":"Print the type documentation for `Type/Arity` in `Module`.","title":"c.ht/3","ref":"c.html#ht/3"},{"type":"function","doc":"","title":"c.i/0","ref":"c.html#i/0"},{"type":"function","doc":"Displays information about a process, Equivalent to\n[`process_info(pid(X, Y, Z))`](`process_info/1`), but location transparent.","title":"c.i/3","ref":"c.html#i/3"},{"type":"function","doc":"Purges and loads, or reloads, a module by calling `code:purge(Module)` followed\nby `code:load_file(Module)`.\n\nNotice that purging the code means that any processes lingering in old code for\nthe module are killed without warning. For more information, see `code/3`.","title":"c.l/1","ref":"c.html#l/1"},{"type":"function","doc":"Compiles a list of files by calling\n`compile:file(File, [report_errors, report_warnings])` for each `File` in\n`Files`.\n\nFor information about `File`, see `t:file:filename/0`.","title":"c.lc/1","ref":"c.html#lc/1"},{"type":"function","doc":"Reloads all currently loaded modules that have changed on disk (see `mm/0`).\nReturns the list of results from calling [`l(M)`](`l/1`) for each such `M`.","title":"c.lm/0","ref":"c.html#lm/0"},{"type":"function","doc":"Lists files in the current directory.","title":"c.ls/0","ref":"c.html#ls/0"},{"type":"function","doc":"Lists files in directory `Dir` or, if `Dir` is a file, only lists it.","title":"c.ls/1","ref":"c.html#ls/1"},{"type":"function","doc":"Displays information about the loaded modules, including the files from which\nthey have been loaded.","title":"c.m/0","ref":"c.html#m/0"},{"type":"function","doc":"Displays information about `Module`.","title":"c.m/1","ref":"c.html#m/1"},{"type":"function","doc":"Memory allocation information. Equivalent to `erlang:memory/0`.","title":"c.memory/0","ref":"c.html#memory/0"},{"type":"function","doc":"Memory allocation information. Equivalent to `erlang:memory/1`.","title":"c.memory/1","ref":"c.html#memory/1"},{"type":"function","doc":"Lists all modified modules. Shorthand for `code:modified_modules/0`.","title":"c.mm/0","ref":"c.html#mm/0"},{"type":"function","doc":"","title":"c.nc/1","ref":"c.html#nc/1"},{"type":"function","doc":"Compiles and then loads the code for a file on all nodes. `Options` defaults to\n`[]`. Compilation is equivalent to:\n\n```erlang\ncompile:file(File, Options ++ [report_errors, report_warnings])\n```","title":"c.nc/2","ref":"c.html#nc/2"},{"type":"function","doc":"`i/0` displays system information, listing information about all processes.\n`ni/0` does the same, but for all nodes in the network.","title":"c.ni/0","ref":"c.html#ni/0"},{"type":"function","doc":"Loads `Module` on all nodes.","title":"c.nl/1","ref":"c.html#nl/1"},{"type":"function","doc":"","title":"c.nregs/0","ref":"c.html#nregs/0"},{"type":"function","doc":"Converts `X`, `Y`, `Z` to pid ` `. This function is only to be used when\ndebugging.","title":"c.pid/3","ref":"c.html#pid/3"},{"type":"function","doc":"Prints the name of the working directory.","title":"c.pwd/0","ref":"c.html#pwd/0"},{"type":"function","doc":"This function is shorthand for `init:stop()`, that is, it causes the node to\nstop in a controlled fashion.","title":"c.q/0","ref":"c.html#q/0"},{"type":"function","doc":"`regs/0` displays information about all registered processes. `nregs/0` does the\nsame, but for all nodes in the network.","title":"c.regs/0","ref":"c.html#regs/0"},{"type":"function","doc":"Prints the node uptime (as specified by `erlang:statistics(wall_clock)`) in\nhuman-readable form.","title":"c.uptime/0","ref":"c.html#uptime/0"},{"type":"function","doc":"Finds undefined functions, unused functions, and calls to deprecated functions\nin a module by calling `xref:m/1`.","title":"c.xm/1","ref":"c.html#xm/1"},{"type":"function","doc":"Generates an LALR-1 parser. Equivalent to:\n\n```text\nyecc:file(File)\n```\n\nFor information about `File = name()`, see `m:filename`. For information about\n`YeccRet`, see [`yecc:file/2`](`yecc:file/1`).","title":"c.y/1","ref":"c.html#y/1"},{"type":"function","doc":"Generates an LALR-1 parser. Equivalent to:\n\n```text\nyecc:file(File, Options)\n```\n\nFor information about `File = name()`, see `m:filename`. For information about\n`Options` and `YeccRet`, see [`yecc:file/2`](`yecc:file/1`).","title":"c.y/2","ref":"c.html#y/2"},{"type":"type","doc":"","title":"c.cmd_line_arg/0","ref":"c.html#t:cmd_line_arg/0"},{"type":"type","doc":"","title":"c.h_return/0","ref":"c.html#t:h_return/0"},{"type":"type","doc":"","title":"c.hcb_return/0","ref":"c.html#t:hcb_return/0"},{"type":"type","doc":"","title":"c.hf_return/0","ref":"c.html#t:hf_return/0"},{"type":"type","doc":"","title":"c.ht_return/0","ref":"c.html#t:ht_return/0"},{"type":"module","doc":"Line and input interpretter for the erlang shell.\n\nThis module reads input, handles any escape sequences that have been configured\nvia edlin_key and outputs action requests. The action requests are handled\neither by modules `group` or the `user_drv`.","title":"edlin","ref":"edlin.html"},{"type":"module","doc":"You can setup a custom key configuration that overrides the default key\nconfiguration. This is done by setting the stdlib application parameter\n[`shell_keymap`](stdlib_app.md#shell_keymap) before Erlang is started. If you\nwant to have the same keymap in all Erlang shells you can do so by putting a\n[config](`e:kernel:config.md`) file in your user's home directory and then set\n[ERL_FLAGS](`e:erts:erl_cmd.md#ERL_FLAGS`) to load it at startup. For example:\n\n```text\n$ cat $HOME/.erlang_keymap.config\n[{stdlib,\n [{shell_keymap,\n #{ normal => #{ \"\\^[A\" => clear } }\n }]\n}].\n$ ERL_FLAGS=\"-config $HOME/.erlang_keymap\" erl\n```\n\nThe current keymap configuration can be fetched through\n[edlin:keymap()](`keymap/0`). If a custom keymap or keymap file is specified,\nthen it will be merged with the default keymap.\n\nThe keymap is a map of maps where the keys in the parent map corresponds to\ndifferent editing modes in the shell. The valid modes currently supported are\n`normal` and `search`.\n\nThe keys in the child maps are the escape sequences that are sent from the\nterminal when a key is pressed and each value is a valid action as seen below.\n\nThe default atom is used to specify that an action should happen when a key is\npressed that does not have any mapping. Typically used to exit a mode.\n\nSee [tty - A Command-Line Interface](`e:erts:tty.md`) for more information about\nthe default keymap.","title":"Key configuration - edlin","ref":"edlin.html#module-key-configuration"},{"type":"module","doc":"The commands below are the built-in action requests for switching input modes on\nthe normal shell or navigating, or manipulating the line feed. The line feed\nsupports multiple lines.\n\n- **`auto_blink`** - Automatically close the closest matching opening\n parenthesis.\n\n- **`backward_char`** - Move backward one character.\n\n- **`backward_delete_char`** - Delete the character behind the cursor.\n\n- **`backward_delete_word`** - Delete the word behind the cursor.\n\n- **`backward_kill_line`** - Delete all characters from the cursor to the\n beginning of the line and save them in the kill buffer.\n\n- **`backward_kill_word`** - Delete the word behind the cursor and save it in\n the kill buffer.\n\n- **`backward_line`** - Move backward one line.\n\n- **`backward_word`** - Move backward one word.\n\n- **`beginning_of_expression`** - Move to the beginning of the expression.\n\n- **`beginning_of_line`** - Move to the beginning of the line.\n\n- **`clear`** - Clear the screen.\n\n- **`clear_line`** - Clear the current expression.\n\n- **`end_of_expression`** - Move to the end of the expression.\n\n- **`end_of_line`** - Move to the end of the line.\n\n- **`forward_char`** - Move forward one character.\n\n- **`forward_delete_char`** - Delete the character under the cursor.\n\n- **`forward_line`** - Move forward one line.\n\n- **`forward_word`** - Move forward one word.\n\n- **`help`** - Display help for the module or function closest on the left of\n the cursor.\n\n- **`help_full`** - Display the whole help text for the module or function closest on the left of\n the cursor.\n\n- **`history_down`** - Move to the next item in the history.\n\n- **`history_up`** - Move to the previous item in the history.\n\n- **`kill_line`** - Delete all characters from the cursor to the end of the line\n and save them in the kill buffer.\n\n- **`kill_word`** - Delete the word under the cursor and save it in the kill\n buffer.\n\n- **`move_expand_down`** - Move down one line in the expand area e.g. help or\n tab completion pager.\n\n- **`move_expand_up`** - Move up one line in the expand area e.g. help or tab\n completion pager.\n\n- **`new_line_finish`** - Add a newline at the end of the line and try to\n evaluate the current expression.\n\n- **`newline`** - Add a newline at the cursor position.\n\n- **`open_editor`** - Open the current line in an editor e.g. EDITOR=\"code -w\"\n opens a buffer in vs code. Note that you need to pass a flag to the editor so\n that it signals the shell when you close the buffer.\n\n- **`redraw_line`** - Redraw the current line.\n\n- **`scroll_expand_down`** - Scroll down five lines in the expand area e.g. help\n or tab completion pager.\n\n- **`scroll_expand_up`** - Scroll up five lines in the expand area e.g. help or\n tab completion pager.\n\n- **`search_cancel`** - Cancel the current search.\n\n- **`search_found`** - Accept the current search result and submit it.\n\n- **`search_quit`** - Accept the current search result, but edit it before\n submitting.\n\n- **`search`** - Enter search mode, search the history.\n\n- **`skip_down`** - Skip to the next line in the history that matches the\n current search expression.\n\n- **`skip_up`** - Skip to the previous line in the history that matches the\n current search expression.\n\n- **`tab_expand_full`** - Output all possible tab completions.\n\n- **`tab_expand_quit`** - Go back to normal mode.\n\n- **`tab_expand`** - Autocomplete the current word, or show 5 lines of possible\n completions.\n\n- **`transpose_char`** - Swap the character behind the cursor with the one in\n front of it.\n\n- **`transpose_word`** - Swap the word behind the cursor with the one in front\n of it.\n\n- **`yank`** - Insert the contents of the kill buffer at the cursor position.","title":"Actions - edlin","ref":"edlin.html#module-actions"},{"type":"function","doc":"Get the current keymap used in the shell. Each key in the parent map represents\na _shell mode_ e.g. `normal` or `search`. Each map associated with the _shell\nmodes_ contains _key sequences_ represented as strings, paired with an _action_,\nwhich is one of the valid actions mentioned above.","title":"edlin.keymap/0","ref":"edlin.html#keymap/0"},{"type":"type","doc":"A map of maps for each shell mode containing key, action pairs.","title":"edlin.keymap/0","ref":"edlin.html#t:keymap/0"},{"type":"module","doc":"Shell expansion and formatting of expansion suggestions.\n\nThis module provides an expand_fun for the erlang shell\n[`expand/1,2`](`expand/1`). It is possible to override this expand_fun\n[`io:setopts/1,2`](`io:setopts/1`).","title":"edlin_expand","ref":"edlin_expand.html"},{"type":"function","doc":"","title":"edlin_expand.expand/1","ref":"edlin_expand.html#expand/1"},{"type":"function","doc":"The standard expansion function is able to expand strings to valid erlang terms.\nThis includes module names:\n\n```text\n1> erla\nmodules\nerlang:\n```\n\nfunction names:\n\n```text\n1> is_ato\nfunctions\nis_atom(\n2> erlang:is_ato\nfunctions\nis_atom(\n```\n\nfunction types:\n\n```text\n1> erlang:is_atom(\ntypespecs\nerlang:is_atom(Term)\nany()\n```\n\nand automatically add , or closing parenthesis when no other valid expansion is\npossible. The expand function also completes: shell bindings, record names,\nrecord fields and map keys.\n\nAs seen below, function headers are grouped together if they've got the same\nexpansion suggestion, in this case all had the same suggestions, that is '\\}'.\nThere is also limited support for filtering out function typespecs that that\ndoes not match the types on the terms on the prompt. Only 4 suggestions are\nshown below but there exists plenty more typespecs for `erlang:system_info`.\n\n```text\n1> erlang:system_info({allocator, my_allocator\ntypespecs\nerlang:system_info(wordsize | {wordsize, ...} | {wordsize, ...})\nerlang:system_info({allocator, ...})\nerlang:system_info({allocator_sizes, ...})\nerlang:system_info({cpu_topology, ...})\n}\n```\n\nThe return type of `expand` function specifies either a list of `Element` tuples\nor a list of `Section` maps. The section concept was introduced to enable more\nformatting options for the expansion results. For example, the shell expansion\nhas support to highlight text and hide suggestions. There are also a\n`{highlight, Text}` that highlights all occurances of `Text` in the title, and a\n`highlight_all` for simplicity which highlights the whole title, as can be seen\nabove for `functions` and `typespecs`.\n\nBy setting the `{hide, result}` or `{hide, title}` options you may hide\nsuggestions. Sometimes the title isn't useful and just produces text noise, in\nthe example above the `t:any/0` result is part of a section with title `Types`.\nHiding results is currently not in use, but the idea is that a section can be\nselected in the expand area and all the other section entries should be\ncollapsed.\n\nIts possible to set a custom separator between the title and the results. This\ncan be done with `{separator, Separator}`. By default its set to be `\\n`, some\nresults display a `type_name() :: `followed by all types that define\n`type_name()`.\n\nThe `{ending, Text}` ElementOption just appends Text to the `Element`.","title":"edlin_expand.expand/2","ref":"edlin_expand.html#expand/2"},{"type":"module","doc":"The Erlang shell.\n\nThe shell is a user interface program for entering expression sequences. The\nexpressions are evaluated and a value is returned. The shell provides an Emacs\nlike set of shortcuts for editing the text of the current line. See\n[tty - A Command-Line Interface](`e:erts:tty.md`) in the ERTS User's Guide for a\nlist of all available shortcuts. You may also change the shortcuts to suit your\npreferences more, see [edlin - line editor in the shell](`m:edlin`).\n\nA history mechanism saves previous commands and their values, which can then be\nincorporated in later commands. How many commands and results to save can be\ndetermined by the user, either interactively, by calling `history/1` and\n`results/1`, or by setting the application configuration parameters\n[`shell_history_length`](stdlib_app.md#shell_history_length) and\n[`shell_saved_results`](stdlib_app.md#shell_saved_results) for the STDLIB\napplication. The shell history can be saved to disk by setting the application\nconfiguration parameter\n[`shell_history`](`e:kernel:kernel_app.md#shell_history`) for the Kernel\napplication.\n\nThe shell uses a helper process for evaluating commands to protect the history\nmechanism from exceptions. By default the evaluator process is killed when an\nexception occurs, but by calling `catch_exception/1` or by setting the\napplication configuration parameter `shell_catch_exception` for the STDLIB\napplication this behavior can be changed. See also the example below.\n\nVariable bindings, and local process dictionary changes that are generated in\nuser expressions are preserved, and the variables can be used in later commands\nto access their values. The bindings can also be forgotten so the variables can\nbe reused.\n\nThe special shell commands all have the syntax of (local) function calls. They\nare evaluated as normal function calls and many commands can be used in one\nexpression sequence.\n\nIf a command (local function call) is not recognized by the shell, an attempt is\nfirst made to find the function in module `user_default`, where customized local\ncommands can be placed. If found, the function is evaluated, otherwise an\nattempt is made to evaluate the function in module `shell_default`. Module\n`user_default` must be explicitly loaded.\n\nThe shell also permits the user to start multiple concurrent jobs. A job can be\nregarded as a set of processes that can communicate with the shell.\n\nThere is some support for reading and printing records in the shell. During\ncompilation record expressions are translated to tuple expressions. In runtime\nit is not known whether a tuple represents a record, and the record definitions\nused by the compiler are unavailable at runtime. So, to read the record syntax\nand print tuples as records when possible, record definitions must be maintained\nby the shell itself.\n\nThe shell commands for reading, defining, forgetting, listing, and printing\nrecords are described below. Notice that each job has its own set of record\ndefinitions. To facilitate matters, record definitions in modules\n`shell_default` and `user_default` (if loaded) are read each time a new job is\nstarted. For example, adding the following line to `user_default` makes the\ndefinition of `file_info` readily available in the shell:\n\n```erlang\n-include_lib(\"kernel/include/file.hrl\").\n```\n\nThe shell runs in two modes:\n\n- `Normal (possibly restricted)` mode, in which commands can be edited and\n expressions evaluated\n- Job Control Mode, `JCL`, in which jobs can be started, killed, detached, and\n connected\n\nOnly the currently connected job can 'talk' to the shell.","title":"shell","ref":"shell.html"},{"type":"module","doc":"The commands below are the built-in shell commands that are always available. In\nmost system the commands listed in the `m:c` module are also available in the\nshell.\n\n- **`b()`** - Prints the current variable bindings.\n\n- **`f()`** - Removes all variable bindings.\n\n- **`f(X)`** - Removes the binding of variable `X`.\n\n > #### Note {: .info }\n >\n > If a huge value is stored in a variable binding, you have to both call\n > `f(X)` and call [`history(0)`](`history/1`) or [`results(0)`](`results/1`)\n > to free up that memory.\n\n- **`h()`** - Prints the history list.\n\n- **[`history(N)`](`history/1`)** - Sets the number of previous commands to keep\n in the history list to `N`. The previous number is returned. Defaults to 20.\n\n- **[`results(N)`](`results/1`)** - Sets the number of results from previous\n commands to keep in the history list to `N`. The previous number is returned.\n Defaults to 20.\n\n- **`e(N)`** - Repeats command `N`, if `N` is positive. If it is negative, the\n `N`th previous command is repeated (that is, `e(-1)` repeats the previous\n command).\n\n- **`v(N)`** - Uses the return value of command `N` in the current command, if\n `N` is positive. If it is negative, the return value of the `N`th previous\n command is used (that is, `v(-1)` uses the value of the previous command).\n\n- **`help()`** - Evaluates `shell_default:help()`.\n\n- **`h(Module, Function)`** - Print the documentation for `Module:Function` in\n the shell if available.\n\n- **`ht(Module, Type)`** - Print the documentation for `Module:Type` in the\n shell if available.\n\n- **`hcb(Module, Callback)`** - Print the documentation for `Module:Callback` in\n the shell if available.\n\n- **`c(Mod)`** - Evaluates `shell_default:c(Mod)`. This compiles and loads the\n module `Mod` and purges old versions of the code, if necessary. `Mod` can be\n either a module name or a a source file path, with or without `.erl`\n extension.\n\n- **[`catch_exception(Bool)`](`catch_exception/1`)** - Sets the exception\n handling of the evaluator process. The previous exception handling is\n returned. The default (`false`) is to kill the evaluator process when an\n exception occurs, which causes the shell to create a new evaluator process.\n When the exception handling is set to `true`, the evaluator process lives on.\n This means, for example, that ports and ETS tables as well as processes linked\n to the evaluator process survive the exception.\n\n- **`rd(RecordName, RecordDefinition)`** - Defines a record in the shell.\n `RecordName` is an atom and `RecordDefinition` lists the field names and the\n default values. Usually record definitions are made known to the shell by use\n of the `rr/1,2,3` commands described below, but sometimes it is handy to\n define records on the fly.\n\n- **`rf()`** - Removes all record definitions, then reads record definitions\n from the modules `shell_default` and `user_default` (if loaded). Returns the\n names of the records defined.\n\n- **`rf(RecordNames)`** - Removes selected record definitions. `RecordNames` is\n a record name or a list of record names. To remove all record definitions, use\n `'_'`.\n\n- **`rl()`** - Prints all record definitions.\n\n- **`rl(RecordNames)`** - Prints selected record definitions. `RecordNames` is a\n record name or a list of record names.\n\n- **`rp(Term)`** - Prints a term using the record definitions known to the\n shell. All of `Term` is printed; the depth is not limited as is the case when\n a return value is printed.\n\n- **`rr(Module)`** - Reads record definitions from a module's BEAM file. If\n there are no record definitions in the BEAM file, the source file is located\n and read instead. Returns the names of the record definitions read. `Module`\n is an atom.\n\n- **`rr(Wildcard)`** - Reads record definitions from files. Existing definitions\n of any of the record names read are replaced. `Wildcard` is a wildcard string\n as defined in `m:filelib`, but not an atom.\n\n- **`rr(WildcardOrModule, RecordNames)`** - Reads record definitions from files\n but discards record names not mentioned in `RecordNames` (a record name or a\n list of record names).\n\n- **`rr(WildcardOrModule, RecordNames, Options)`** - Reads record definitions\n from files. The compiler options `{i, Dir}`, `{d, Macro}`, and\n `{d, Macro, Value}` are recognized and used for setting up the include path\n and macro definitions. To read all record definitions, use `'_'` as value of\n `RecordNames`.\n\n- **`lf()`** - Outputs locally defined function with function specs if they\n exist.\n\n- **`lt()`** - Outputs locally defined types.\n\n- **`lr()`** - Outputs locally defined records.\n\n- **`ff()`** - Forget locally defined functions (including function specs if\n they exist).\n\n- **`ff({FunName,Arity})`** - Forget a locally defined function (including\n function spec if it exist). Where `FunName` is the name of the function as an\n atom and `Arity` is an integer.\n\n- **`tf()`** - Forget locally defined types.\n\n- **`tf(Type)`** - Forget locally defined type where `Type` is the name of the\n type represented as an atom.\n\n- **`fl()`** - Forget locally defined functions, types and records.\n\n- **`save_module(FilePath)`** - Saves all locally defined functions, types and\n records to a module file, where `FilePath` should include both the path to the\n file and the name of the module with `.erl` suffix.\n\n Example: `src/my_module.erl`","title":"Shell Commands - shell","ref":"shell.html#module-shell-commands"},{"type":"module","doc":"The following example is a long dialog with the shell. Commands starting with\n`>` are inputs to the shell. All other lines are output from the shell.\n\n```erlang\nstrider 1> erl\nErlang (BEAM) emulator version 5.3 [hipe] [threads:0]\n\nEshell V5.3 (abort with ^G)\n1> Str = \"abcd\".\n\"abcd\"\n```\n\nCommand 1 sets variable `Str` to string `\"abcd\"`.\n\n```erlang\n2> L = length(Str).\n4\n```\n\nCommand 2 sets `L` to the length of string `Str`.\n\n```erlang\n3> Descriptor = {L, list_to_atom(Str)}.\n{4,abcd}\n```\n\nCommand 3 builds the tuple `Descriptor`, evaluating the BIF\n[`list_to_atom/1` ](`erlang:list_to_atom/1`).\n\n```erlang\n4> L.\n4\n```\n\nCommand 4 prints the value of variable `L`.\n\n```erlang\n5> b().\nDescriptor = {4,abcd}\nL = 4\nStr = \"abcd\"\nok\n```\n\nCommand 5 evaluates the internal shell command `b()`, which is an abbreviation\nof \"bindings\". This prints the current shell variables and their bindings. `ok`\nat the end is the return value of function `b()`.\n\n```erlang\n6> f(L).\nok\n```\n\nCommand 6 evaluates the internal shell command `f(L)` (abbreviation of\n\"forget\"). The value of variable `L` is removed.\n\n```erlang\n7> b().\nDescriptor = {4,abcd}\nStr = \"abcd\"\nok\n```\n\nCommand 7 prints the new bindings.\n\n```erlang\n8> f(L).\nok\n```\n\nCommand 8 has no effect, as `L` has no value.\n\n```erlang\n9> {L, _} = Descriptor.\n{4,abcd}\n```\n\nCommand 9 performs a pattern matching operation on `Descriptor`, binding a new\nvalue to `L`.\n\n```erlang\n10> L.\n4\n```\n\nCommand 10 prints the current value of `L`.\n\n```erlang\n11> {P, Q, R} = Descriptor.\n** exception error: no match of right hand side value {4,abcd}\n```\n\nCommand 11 tries to match `{P, Q, R}` against `Descriptor`, which is `{4, abc}`.\nThe match fails and none of the new variables become bound. The printout\nstarting with \"`** exception error:`\" is not the value of the expression (the\nexpression had no value because its evaluation failed), but a warning printed by\nthe system to inform the user that an error has occurred. The values of the\nother variables (`L`, `Str`, and so on) are unchanged.\n\n```erlang\n12> P.\n* 1:1: variable 'P' is unbound\n13> Descriptor.\n{4,abcd}\n```\n\nCommands 12 and 13 show that `P` is unbound because the previous command failed,\nand that `Descriptor` has not changed.\n\n```erlang\n14>{P, Q} = Descriptor.\n{4,abcd}\n15> P.\n4\n```\n\nCommands 14 and 15 show a correct match where `P` and `Q` are bound.\n\n```erlang\n16> f().\nok\n```\n\nCommand 16 clears all bindings.\n\nThe next few commands assume that `test1:demo(X)` is defined as follows:\n\n```erlang\ndemo(X) ->\n    put(aa, worked),\n    X = 1,\n    X + 10.\n```\n\n```erlang\n17> put(aa, hello).\nundefined\n18> get(aa).\nhello\n```\n\nCommands 17 and 18 set and inspect the value of item `aa` in the process\ndictionary.\n\n```erlang\n19> Y = test1:demo(1).\n11\n```\n\nCommand 19 evaluates `test1:demo(1)`. The evaluation succeeds and the changes\nmade in the process dictionary become visible to the shell. The new value of\ndictionary item `aa` can be seen in command 20.\n\n```erlang\n20> get().\n[{aa,worked}]\n21> put(aa, hello).\nworked\n22> Z = test1:demo(2).\n** exception error: no match of right hand side value 1\n in function test1:demo/1\n```\n\nCommands 21 and 22 change the value of dictionary item `aa` to `hello` and call\n`test1:demo(2)`. Evaluation fails and the changes made to the dictionary in\n`test1:demo(2)`, before the error occurred, are discarded.\n\n```erlang\n23> Z.\n* 1:1: variable 'Z' is unbound\n24> get(aa).\nhello\n```\n\nCommands 23 and 24 show that `Z` was not bound and that dictionary item `aa` has\nretained its original value.\n\n```erlang\n25> erase(), put(aa, hello).\nundefined\n26> spawn(test1, demo, [1]).\n<0.57.0>\n27> get(aa).\nhello\n```\n\nCommands 25, 26, and 27 show the effect of evaluating `test1:demo(1)` in the\nbackground. In this case, the expression is evaluated in a newly spawned\nprocess. Any changes made in the process dictionary are local to the newly\nspawned process and therefore not visible to the shell.\n\n```erlang\n28> io:format(\"hello hello\\n\").\nhello hello\nok\n29> e(28).\nhello hello\nok\n30> v(28).\nok\n```\n\nCommands 28, 29 and 30 use the history facilities of the shell. Command 29\nre-evaluates command 28. Command 30 uses the value (result) of command 28. In\nthe cases of a pure function (a function with no side effects), the result is\nthe same. For a function with side effects, the result can be different.\n\nThe next few commands show some record manipulation. It is assumed that `ex.erl`\ndefines a record as follows:\n\n`-record(rec, {a, b = val()}).`\n\n`val() ->` \n    `3.`\n\n```erlang\n31> c(ex).\n{ok,ex}\n32> rr(ex).\n[rec]\n```\n\nCommands 31 and 32 compile file `ex.erl` and read the record definitions in\n`ex.beam`. If the compiler did not output any record definitions on the BEAM\nfile, `rr(ex)` tries to read record definitions from the source file instead.\n\n```erlang\n33> rl(rec).\n-record(rec,{a,b = val()}).\nok\n```\n\nCommand 33 prints the definition of the record named `rec`.\n\n```erlang\n34> #rec{}.\n** exception error: undefined shell command val/0\n```\n\nCommand 34 tries to create a `rec` record, but fails as function `val/0` is\nundefined.\n\n```erlang\n35> #rec{b = 3}.\n#rec{a = undefined,b = 3}\n```\n\nCommand 35 shows the workaround: explicitly assign values to record fields that\ncannot otherwise be initialized.\n\n```erlang\n36> rp(v(-1)).\n#rec{a = undefined,b = 3}\nok\n```\n\nCommand 36 prints the newly created record using record definitions maintained\nby the shell.\n\n```erlang\n37> rd(rec, {f = orddict:new()}).\nrec\n```\n\nCommand 37 defines a record directly in the shell. The definition replaces the\none read from file `ex.beam`.\n\n```erlang\n38> #rec{}.\n#rec{f = []}\nok\n```\n\nCommand 38 creates a record using the new definition, and prints the result.\n\n```erlang\n39> rd(rec, {c}), A.\n* 1:15: variable 'A' is unbound\n40> #rec{}.\n#rec{c = undefined}\nok\n```\n\nCommand 39 and 40 show that record definitions are updated as side effects. The\nevaluation of the command fails, but the definition of `rec` has been carried\nout.\n\nFor the next command, it is assumed that `test1:loop(N)` is defined as follows:\n\n`loop(N) ->` \n    `io:format(\"Hello Number: ~w~n\", [N]),` \n    `loop(N+1).`\n\n```text\n41> test1:loop(0).\nHello Number: 0\nHello Number: 1\nHello Number: 2\nHello Number: 3\n\nUser switch command\n --> i\n --> c\n.\n.\n.\nHello Number: 3374\nHello Number: 3375\nHello Number: 3376\nHello Number: 3377\nHello Number: 3378\n** exception exit: killed\n```\n\nCommand 41 evaluates `test1:loop(0)`, which puts the system into an infinite\nloop. At this point the user types `^G` (Control G), which suspends output from\nthe current process, which is stuck in a loop, and activates `JCL` mode. In\n`JCL` mode the user can start and stop jobs.\n\nIn this particular case, command `i` (\"interrupt\") terminates the looping\nprogram, and command `c` connects to the shell again. As the process was running\nin the background before we killed it, more printouts occur before message\n\"`** exception exit: killed`\" is shown.\n\n```erlang\n42> E = ets:new(t, []).\n#Ref<0.1662103692.2407923716.214192>\n```\n\nCommand 42 creates an ETS table.\n\n```erlang\n43> ets:insert({d,1,2}).\n** exception error: undefined function ets:insert/1\n```\n\nCommand 43 tries to insert a tuple into the ETS table, but the first argument\n(the table) is missing. The exception kills the evaluator process.\n\n```erlang\n44> ets:insert(E, {d,1,2}).\n** exception error: argument is of wrong type\n in function ets:insert/2\n called as ets:insert(16,{d,1,2})\n```\n\nCommand 44 corrects the mistake, but the ETS table has been destroyed as it was\nowned by the killed evaluator process.\n\n```erlang\n45> f(E).\nok\n46> catch_exception(true).\nfalse\n```\n\nCommand 46 sets the exception handling of the evaluator process to `true`. The\nexception handling can also be set when starting Erlang by\n`erl -stdlib shell_catch_exception true`.\n\n```erlang\n47> E = ets:new(t, []).\n#Ref<0.1662103692.2407923716.214197>\n48> ets:insert({d,1,2}).\n* exception error: undefined function ets:insert/1\n```\n\nCommand 48 makes the same mistake as in command 43, but this time the evaluator\nprocess lives on. The single star at the beginning of the printout signals that\nthe exception has been caught.\n\n```erlang\n49> ets:insert(E, {d,1,2}).\ntrue\n```\n\nCommand 49 successfully inserts the tuple into the ETS table.\n\n```erlang\n50> ets:insert(#Ref<0.1662103692.2407923716.214197>, {e,3,4}).\ntrue\n```\n\nCommand 50 inserts another tuple into the ETS table. This time the first\nargument is the table identifier itself. The shell can parse commands with pids\n(`<0.60.0>`), ports (`#Port<0.536>`), references\n(`#Ref<0.1662103692.2407792644.214210>`), and external functions\n(`#Fun `), but the command fails unless the corresponding pid, port,\nreference, or function can be created in the running system.\n\n```erlang\n51> halt().\nstrider 2>\n```\n\nCommand 51 exits the Erlang runtime system.","title":"Example - shell","ref":"shell.html#module-example"},{"type":"module","doc":"When the shell starts, it starts a single evaluator process. This process,\ntogether with any local processes that it spawns, is referred to as a `job`.\nOnly the current job, which is said to be `connected`, can perform operations\nwith standard I/O. All other jobs, which are said to be `detached`, are\n`blocked` if they attempt to use standard I/O.\n\nAll jobs that do not use standard I/O run in the normal way.\n\nThe shell escape key `^G` (Control G) detaches the current job and activates\n`JCL` mode. The `JCL` mode prompt is `\"-->\"`. If `\"?\"` is entered at the prompt,\nthe following help message is displayed:\n\n```text\n--> ?\nc [nn] - connect to job\ni [nn] - interrupt job\nk [nn] - kill job\nj - list all jobs\ns [shell] - start local shell\nr [node [shell]] - start remote shell\nq - quit erlang\n? | h - this message\n```\n\nThe `JCL` commands have the following meaning:\n\n- **`c [nn]`** - Connects to job number ` ` or the current job. The standard\n shell is resumed. Operations that use standard I/O by the current job are\n interleaved with user inputs to the shell.\n\n- **`i [nn]`** - Stops the current evaluator process for job number `nn` or the\n current job, but does not kill the shell process. So, any variable bindings\n and the process dictionary are preserved and the job can be connected again.\n This command can be used to interrupt an endless loop.\n\n- **`k [nn]`** - Kills job number `nn` or the current job. All spawned processes\n in the job are killed, provided they have not evaluated the `group_leader/1`\n BIF and are located on the local machine. Processes spawned on remote nodes\n are not killed.\n\n- **`j`** - Lists all jobs. A list of all known jobs is printed. The current job\n name is prefixed with '\\*'.\n\n- **`s`** - Starts a new job. This is assigned the new index `[nn]`, which can\n be used in references.\n\n- **`s [shell]`** - Starts a new job. This is assigned the new index `[nn]`,\n which can be used in references. If optional argument `shell` is specified, it\n is assumed to be a module that implements an alternative shell.\n\n- **`r [node]`** - Starts a remote job on `node`. This is used in distributed\n Erlang to allow a shell running on one node to control a number of\n applications running on a network of nodes. If optional argument `shell` is\n specified, it is assumed to be a module that implements an alternative shell.\n\n- **`q`** - Quits Erlang. Notice that this option is disabled if Erlang is\n started with the ignore break, `+Bi`, system flag (which can be useful, for\n example when running a restricted shell, see the next section).\n\n- **`?`** - Displays the help message above.\n\nThe behavior of shell escape can be changed by the STDLIB application variable\n`shell_esc`. The value of the variable can be either `jcl`\n(`erl -stdlib shell_esc jcl`) or `abort` (`erl -stdlib shell_esc abort`). The\nfirst option sets `^G` to activate `JCL` mode (which is also default behavior).\nThe latter sets `^G` to terminate the current shell and start a new one. `JCL`\nmode cannot be invoked when `shell_esc` is set to `abort`.\n\nIf you want an Erlang node to have a remote job active from the start (rather\nthan the default local job), start Erlang with flag\n[`-remsh`](`e:erts:erl_cmd.md#remsh`), for example,\n`erl -remsh other_node@other_host`","title":"JCL Mode - shell","ref":"shell.html#module-jcl-mode"},{"type":"module","doc":"The shell can be started in a restricted mode. In this mode, the shell evaluates\na function call only if allowed. This feature makes it possible to, for example,\nprevent a user from accidentally calling a function from the prompt that could\nharm a running system (useful in combination with system flag `+Bi`).\n\nWhen the restricted shell evaluates an expression and encounters a function call\nor an operator application, it calls a callback function (with information about\nthe function call in question). This callback function returns `true` to let the\nshell go ahead with the evaluation, or `false` to abort it. There are two\npossible callback functions for the user to implement:\n\n- `local_allowed(Func, ArgList, State) -> {boolean(),NewState}`\n\n This is used to determine if the call to the local function `Func` with\n arguments `ArgList` is to be allowed.\n\n- `non_local_allowed(FuncSpec, ArgList, State) -> {boolean(),NewState} | {{redirect,NewFuncSpec,NewArgList},NewState}`\n\n This is used to determine if the call to non-local function `FuncSpec`\n (`{Module,Func}` or a fun) with arguments `ArgList` is to be allowed. The\n return value `{redirect,NewFuncSpec,NewArgList}` can be used to let the shell\n evaluate some other function than the one specified by `FuncSpec` and\n `ArgList`.\n\nThese callback functions are called from local and non-local evaluation function\nhandlers, described in the `m:erl_eval` manual page. (Arguments in `ArgList` are\nevaluated before the callback functions are called.)\n\nFrom OTP 25.0, if there are errors evaluating Erlang constructs, such as\n`badmatch` during pattern matching or `bad_generator` in a comprehension, the\nevaluator will dispatch to `erlang:raise(error, Reason, Stacktrace)`. This call\nwill be checked against the `non_local_allowed/3` callback function. You can\neither forbid it, allow it, or redirect to another call of your choice.\n\nArgument `State` is a tuple `{ShellState,ExprState}`. The return value\n`NewState` has the same form. This can be used to carry a state between calls to\nthe callback functions. Data saved in `ShellState` lives through an entire shell\nsession. Data saved in `ExprState` lives only through the evaluation of the\ncurrent expression.\n\nThere are two ways to start a restricted shell session:\n\n- Use STDLIB application variable `restricted_shell` and specify, as its value,\n the name of the callback module. Example (with callback functions implemented\n in `callback_mod.erl`): `$ erl -stdlib restricted_shell callback_mod`.\n- From a normal shell session, call function `start_restricted/1`. This exits\n the current evaluator and starts a new one in restricted mode.\n\n_Notes:_\n\n- When restricted shell mode is activated or deactivated, new jobs started on\n the node run in restricted or normal mode, respectively.\n- If restricted mode has been enabled on a particular node, remote shells\n connecting to this node also run in restricted mode.\n- The callback functions cannot be used to allow or disallow execution of\n functions called from compiled code (only functions called from expressions\n entered at the shell prompt).\n\nErrors when loading the callback module is handled in different ways depending\non how the restricted shell is activated:\n\n- If the restricted shell is activated by setting the STDLIB variable during\n emulator startup, and the callback module cannot be loaded, a default\n restricted shell allowing only the commands `q()` and `init:stop()` is used as\n fallback.\n- If the restricted shell is activated using `start_restricted/1` and the\n callback module cannot be loaded, an error report is sent to the error logger\n and the call returns `{error,Reason}`.","title":"Restricted Shell - shell","ref":"shell.html#module-restricted-shell"},{"type":"module","doc":"The default shell prompt function displays the name of the node (if the node can\nbe part of a distributed system) and the current command number. The user can\ncustomize the prompt function by calling `prompt_func/1` or by setting\napplication configuration parameter `shell_prompt_func` for the STDLIB\napplication. Similarly the multiline prompt can be configured as well, by\ncalling `multiline_prompt_func/1` or by setting the application parameter\n`shell_multiline_prompt` for the STDLIB application.\n\nA customized prompt function is stated as a tuple `{Mod, Func}`. The function is\ncalled as `Mod:Func(L)`, where `L` is a list of key-value pairs created by the\nshell. Currently there is only one pair: `{history, N}`, where `N` is the\ncurrent command number. The function is to return a list of characters or an\natom. This constraint is because of the Erlang I/O protocol. Unicode characters\nbeyond code point 255 are allowed in the list and the atom. Notice that in\nrestricted mode the call `Mod:Func(L)` must be allowed or the default shell\nprompt function is called.","title":"Prompting - shell","ref":"shell.html#module-prompting"},{"type":"function","doc":"Sets the exception handling of the evaluator process. The previous exception\nhandling is returned. The default (`false`) is to kill the evaluator process\nwhen an exception occurs, which causes the shell to create a new evaluator\nprocess. When the exception handling is set to `true`, the evaluator process\nlives on, which means that, for example, ports and ETS tables as well as\nprocesses linked to the evaluator process survive the exception.","title":"shell.catch_exception/1","ref":"shell.html#catch_exception/1"},{"type":"function","doc":"Configures the multiline prompt as two trailing dots. This is the default\nfunction but it may also be set explicitly as\n`-stdlib shell_multiline_prompt {shell, default_multiline_prompt}`.","title":"shell.default_multiline_prompt/1","ref":"shell.html#default_multiline_prompt/1"},{"type":"function","doc":"A formatting function that can be set with `format_shell_func/1` that will make\nexpressions submitted to the shell prettier.\n\n> #### Note {: .info }\n>\n> This formatting function filter comments away from the expressions.","title":"shell.erl_pp_format_func/1","ref":"shell.html#erl_pp_format_func/1"},{"type":"function","doc":"Can be used to set the formatting of the Erlang shell output.\n\nThis has an effect on commands that have been submitted, and how it is saved in history.\nOr if the formatting hotkey is pressed while editing an expression (Alt+R by default). You\ncan specify a `Mod:Func/1` that expects the whole expression as a string and\nreturns a formatted expressions as a string. See\n[`stdlib app config`](stdlib_app.md#format_shell_func) for how to set it before\nshell started.\n\nIf instead a string is provided, it will be used as a shell command. Your\ncommand must include `${file}` somewhere in the string, for the shell to know\nwhere the file goes in the command.\n\n```erlang\nshell:format_shell_func(\"\\\"emacs -batch \\${file} -l ~/erlang-format/emacs-format-file -f emacs-format-function\\\"\").\n```\n\n```erlang\nshell:format_shell_func({shell, erl_pp_format_func}).\n```","title":"shell.format_shell_func/1","ref":"shell.html#format_shell_func/1"},{"type":"function","doc":"Sets the number of previous commands to keep in the history list to `N`. The\nprevious number is returned. Defaults to 20.","title":"shell.history/1","ref":"shell.html#history/1"},{"type":"function","doc":"Configures the multiline prompt as inverted space. It may be set explicitly as\n`-stdlib shell_multiline_prompt {shell, inverted_space_prompt}` or calling\n`multiline_prompt_func({shell, inverted_space_prompt}).`","title":"shell.inverted_space_prompt/1","ref":"shell.html#inverted_space_prompt/1"},{"type":"function","doc":"Sets the shell multiline prompt function to `PromptFunc`. The previous prompt\nfunction is returned.","title":"shell.multiline_prompt_func/1","ref":"shell.html#multiline_prompt_func/1"},{"type":"function","doc":"Sets the shell prompt function to `PromptFunc`. The previous prompt function is\nreturned.","title":"shell.prompt_func/1","ref":"shell.html#prompt_func/1"},{"type":"function","doc":"Equivalent to `prompt_width/2` with `Encoding` set to the encoding used by\n`t:io:user/0`.","title":"shell.prompt_width/1","ref":"shell.html#prompt_width/1"},{"type":"function","doc":"It receives a prompt and computes its width, considering its Unicode characters\nand ANSI escapes.\n\nUseful for creating custom multiline prompts.\n\nExample:\n\n```erlang\n1> shell:prompt_width(\"olá> \", unicode).\n5\n%% \"olá> \" is printed as \"ol\\341> \" on a latin1 systems\n2> shell:prompt_width(\"olá> \", latin1).\n8\n%% Ansi escapes are ignored\n3> shell:prompt_width(\"\\e[32molá\\e[0m> \", unicode).\n5\n%% Double width characters count as 2\n4> shell:prompt_width(\"😀> \", unicode).\n4\n%% \"😀> \" is printed as \"\\x{1F600}> \" on latin1 systems\n5> shell:prompt_width(\"😀> \", latin1).\n11\n```","title":"shell.prompt_width/2","ref":"shell.html#prompt_width/2"},{"type":"function","doc":"Sets the number of results from previous commands to keep in the history list to\n`N`. The previous number is returned. Defaults to 20.","title":"shell.results/1","ref":"shell.html#results/1"},{"type":"function","doc":"Starts the interactive shell if it has not already been started. It can be used\nto programatically start the shell from an escript or when erl is started with\nthe -noinput or -noshell flags.\n\nCalling this function will start a remote shell if `-remsh` is given on the\ncommand line or a local shell if not.","title":"shell.start_interactive/0","ref":"shell.html#start_interactive/0"},{"type":"function","doc":"Starts the interactive shell if it has not already been started. It can be used\nto programatically start the shell from an [`escript`](`e:erts:escript_cmd.md`)\nor when [`erl`](`e:erts:erl_cmd.md`) is started with the\n[`-noinput`](`e:erts:erl_cmd.md#noinput`) or\n[`-noshell`](`e:erts:erl_cmd.md#noshell`) flags. The following options are\nallowed:\n\n- **noshell | {noshell, Mode}** - Starts the interactive shell\n as if [`-noshell`](`e:erts:erl_cmd.md#noshell`) was given to\n [`erl`](`e:erts:erl_cmd.md`).\n\n It is possible to give a `Mode` indicating if the input should be set\n in `cooked` or `raw` mode. `Mode` only has en effect if `t:io:user/0` is a tty.\n If no `Mode` is given, it defaults is `cooked`.\n\n When in `raw` mode all key presses are passed to `t:io:user/0` as they are\n typed when they are typed and the characters are not echoed to the terminal.\n It is possible to set the `echo` to `true` using `io:setopts/2` to enabling\n echoing again.\n\n When in `cooked` mode the OS will handle the line editing and all data is\n passed to `t:io:user/0` when a newline is entered.\n\n- **[mfa()](`t:erlang:mfa/0`)** - Starts the interactive shell using\n [`mfa()`](`t:erlang:mfa/0`) as the default shell. The `t:mfa/0` should\n return the `t:pid/0` of the created shell process.\n\n- **\\{[node()](`t:erlang:node/0`), [mfa()](`t:erlang:mfa/0`)\\}** - Starts the\n interactive shell using [`mfa()`](`t:erlang:mfa/0`) on\n [`node()`](`t:erlang:node/0`) as the default shell. The `t:mfa/0` should\n return the `t:pid/0` of the created shell process.\n\n- **\\{remote, [`string()`](`t:erlang:string/0`)\\}** - Starts the interactive\n shell using as if [`-remsh`](`e:erts:erl_cmd.md#remsh`) was given to\n [`erl`](`e:erts:erl_cmd.md`).\n\n- **\\{remote, [`string()`](`t:erlang:string/0`),\n [`mfa()`](`t:erlang:mfa/0`)\\}** - Starts the interactive shell using as if\n [`-remsh`](`e:erts:erl_cmd.md#remsh`) was given to\n [`erl`](`e:erts:erl_cmd.md`) but with an alternative shell implementation.\n\nOn error this function will return:\n\n- **already_started** - if an interactive shell is already started.\n\n- **noconnection** - if a remote shell was requested but it could not be\n connected to.\n\n- **badfile | nofile | on_load_failure** - if a remote shell was requested with\n a custom [mfa()](`t:erlang:mfa/0`), but the module could not be loaded. See\n [Error Reasons for Code-Loading Functions](`m:code#error_reasons`) for a\n description of the error reasons.","title":"shell.start_interactive/1","ref":"shell.html#start_interactive/1"},{"type":"function","doc":"Exits a normal shell and starts a restricted shell. `Module` specifies the\ncallback module for the functions `local_allowed/3` and `non_local_allowed/3`.\nThe function is meant to be called from the shell.\n\nIf the callback module cannot be loaded, an error tuple is returned. The\n`Reason` in the error tuple is the one returned by the code loader when trying\nto load the code of the callback module.","title":"shell.start_restricted/1","ref":"shell.html#start_restricted/1"},{"type":"function","doc":"Exits a restricted shell and starts a normal shell. The function is meant to be\ncalled from the shell.","title":"shell.stop_restricted/0","ref":"shell.html#stop_restricted/0"},{"type":"function","doc":"Sets pretty printing of lists to `Strings`. The previous value of the flag is\nreturned.\n\nThe flag can also be set by the STDLIB application variable `shell_strings`.\nDefaults to `true`, which means that lists of integers are printed using the\nstring syntax, when possible. Value `false` means that no lists are printed\nusing the string syntax.","title":"shell.strings/1","ref":"shell.html#strings/1"},{"type":"function","doc":"Returns the current shell process on the node where the calling process'\ngroup_leader is located. If that node has no shell this function will return\nundefined.","title":"shell.whereis/0","ref":"shell.html#whereis/0"},{"type":"module","doc":"Customizing the Erlang environment.\n\nThe functions in this module are called when no module name is specified in a\nshell command.\n\nConsider the following shell dialog:\n\n```erlang\n1> lists:reverse(\"abc\").\n\"cba\"\n2> c(foo).\n{ok, foo}\n```\n\nIn command one, module `m:lists` is called. In command two, no module name is\nspecified. The shell searches module `user_default` followed by module\n`shell_default` for function `c/1`.\n\n`shell_default` is intended for \"system wide\" customizations to the shell.\n`user_default` is intended for \"local\" or individual user customizations.","title":"shell_default","ref":"shell_default.html"},{"type":"module","doc":"To add your own commands to the shell, create a module called `user_default` and\nadd the commands you want. Then add the following line as the _first_ line in\nyour `.erlang` file in your home directory.\n\n```text\ncode:load_abs(\"$PATH/user_default\").\n```\n\n`$PATH` is the directory where your `user_default` module can be found.","title":"Hint - shell_default","ref":"shell_default.html#module-hint"},{"type":"function","doc":"Print the help for all shell commands.","title":"shell_default.help/0","ref":"shell_default.html#help/0"},{"type":"module","doc":"Functions used to render [EEP-48](`e:kernel:eep48_chapter.md`) style documentation for a shell.\n\nThis module can be used to render function and type documentation to be printed\nin a shell. This is the module that is used to render the documentation accessed through\nthe shell through [`c:h/1,2,3`](`\\\\c:h/1`). Example:\n\n```txt\n1> h(maps,new,0).\n\n -spec new() -> Map when Map :: #{}.\n\nSince:\n OTP 17.0\n\n Returns a new empty map.\n\n Example:\n\n > maps:new().\n #{}\n```\n\nThis module formats and renders EEP-48 documentation of the format\n`application/erlang+html`. For more information about this format see\n[Documentation Storage](`e:edoc:doc_storage.md`) in EDoc's User's\nGuide. It can also render any other format of \"text\" type, although those will\nbe rendered as is.","title":"shell_docs","ref":"shell_docs.html"},{"type":"function","doc":"This function can be used to do whitespace normalization of\n`application/erlang+html` documentation.","title":"shell_docs.normalize/1","ref":"shell_docs.html#normalize/1"},{"type":"function","doc":"","title":"shell_docs.render/2","ref":"shell_docs.html#render/2"},{"type":"function","doc":"Render module or function documentation.\n\nRenders the module documentation if called as `render(Module, Docs, Config)`.\n\nEquivalent to [`render(Module, Function, Docs, #{})`](`render/4`) if called\nas `render(Module, Function, Docs)`.","title":"shell_docs.render/3","ref":"shell_docs.html#render/3"},{"type":"function","doc":"Render function documentation.\n\nRenders the function documentation if called as `render(Module, Function, Docs, Config)`.\n\nEquivalent to [`render(Module, Function, Arity, Docs, #{})`](`render/4`) if called\nas `render(Module, Function, Arity, Docs)`.","title":"shell_docs.render/4","ref":"shell_docs.html#render/4"},{"type":"function","doc":"Render the documentation for a function.","title":"shell_docs.render/5","ref":"shell_docs.html#render/5"},{"type":"function","doc":"","title":"shell_docs.render_callback/2","ref":"shell_docs.html#render_callback/2"},{"type":"function","doc":"Render all callbacks in a module or callback documentation.\n\nRenders a list with all callbacks if called as `render_callback(Module, Docs, Config)`.\n\nEquivalent to [`render_callback(Module, Callback, Docs, #{})`](`render_callback/4`) if called\nas `render_callback(Module, Callback, Docs)`.","title":"shell_docs.render_callback/3","ref":"shell_docs.html#render_callback/3"},{"type":"function","doc":"Render callback documentation.\n\nRenders the callback documentation if called as `render_callback(Module, Callback, Docs, Config)`.\n\nEquivalent to [`render_callback(Module, Callback, Arity, Docs, #{})`](`render_callback/4`) if called\nas `render_callback(Module, Callback, Arity, Docs)`.","title":"shell_docs.render_callback/4","ref":"shell_docs.html#render_callback/4"},{"type":"function","doc":"Render the documentation of a callback in a module.","title":"shell_docs.render_callback/5","ref":"shell_docs.html#render_callback/5"},{"type":"function","doc":"","title":"shell_docs.render_type/2","ref":"shell_docs.html#render_type/2"},{"type":"function","doc":"Render all types in a module or type documentation.\n\nRenders a list with all types if called as `render_type(Module, Docs, Config)`.\n\nEquivalent to [`render_type(Module, Type, Docs, #{})`](`render_type/4`) if called\nas `render_type(Module, Type, Docs)`.","title":"shell_docs.render_type/3","ref":"shell_docs.html#render_type/3"},{"type":"function","doc":"Render type documentation.\n\nRenders the type documentation if called as `render_type(Module, Type, Docs, Config)`.\n\nEquivalent to [`render_type(Module, Type, Arity, Docs, #{})`](`render_type/4`) if called\nas `render_type(Module, Type, Arity, Docs)`.","title":"shell_docs.render_type/4","ref":"shell_docs.html#render_type/4"},{"type":"function","doc":"Render the documentation of a type in a module.","title":"shell_docs.render_type/5","ref":"shell_docs.html#render_type/5"},{"type":"function","doc":"This function can be used to find out which tags are supported by\n`application/erlang+html` documentation.","title":"shell_docs.supported_tags/0","ref":"shell_docs.html#supported_tags/0"},{"type":"function","doc":"This function can be used to do a basic validation of the doc content of\n`application/erlang+html` format.","title":"shell_docs.validate/1","ref":"shell_docs.html#validate/1"},{"type":"type","doc":"","title":"shell_docs.chunk_element/0","ref":"shell_docs.html#t:chunk_element/0"},{"type":"type","doc":"","title":"shell_docs.chunk_element_attr/0","ref":"shell_docs.html#t:chunk_element_attr/0"},{"type":"type","doc":"","title":"shell_docs.chunk_element_attrs/0","ref":"shell_docs.html#t:chunk_element_attrs/0"},{"type":"type","doc":"","title":"shell_docs.chunk_element_block_type/0","ref":"shell_docs.html#t:chunk_element_block_type/0"},{"type":"type","doc":"","title":"shell_docs.chunk_element_inline_type/0","ref":"shell_docs.html#t:chunk_element_inline_type/0"},{"type":"type","doc":"The HTML tags allowed in `application/erlang+html`.","title":"shell_docs.chunk_element_type/0","ref":"shell_docs.html#t:chunk_element_type/0"},{"type":"type","doc":"","title":"shell_docs.chunk_elements/0","ref":"shell_docs.html#t:chunk_elements/0"},{"type":"type","doc":"The configuration of how the documentation should be rendered.\n\n- **encoding** - Configure the encoding that should be used by the renderer for\n graphical details such as bullet-points. By default `shell_docs` uses the\n value returned by [`io:getopts()`](`io:getopts/0`).\n\n- **ansi** - Configure whether\n [ansi escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code) should be\n used to render graphical details such as bold and underscore. By default\n `shell_docs` will try to determine if the receiving shell supports ansi escape\n codes. It is possible to override the automated check by setting the kernel\n configuration parameter `shell_docs_ansi` to a `t:boolean/0` value.\n\n- **columns** - Configure how wide the target documentation should be rendered.\n By default `shell_docs` used the value returned by\n [`io:columns()`](`io:columns/0`). It is possible to override this default\n by setting the stdlib configuration parameter `shell_docs_columns`\n to a `t:pos_integer/0` value.","title":"shell_docs.config/0","ref":"shell_docs.html#t:config/0"},{"type":"type","doc":"The record holding EEP-48 documentation for a module. You can use\n`code:get_doc/1` to fetch this information from a module.","title":"shell_docs.docs_v1/0","ref":"shell_docs.html#t:docs_v1/0"},{"type":"module","doc":"Provides base64 encode and decode, see\n[RFC 2045](https://www.ietf.org/rfc/rfc2045.txt).","title":"base64","ref":"base64.html"},{"type":"function","doc":"","title":"base64.decode/1","ref":"base64.html#decode/1"},{"type":"function","doc":"Decodes a base64 string encoded using the standard alphabet according to\n[RFC 4648 Section 4](https://datatracker.ietf.org/doc/html/rfc4648#section-4) to\nplain ASCII.\n\nThe function will strips away any whitespace characters and check for the\nthe correct number of `=` padding characters at the end of the encoded string.\n\nSee `t:decode_options/0` for details on which options can be passed.\n\n_Example_:\n```erlang\n1> base64:decode(\"AQIDBA==\").\n<<1,2,3,4>>\n2> base64:decode(\"AQ ID BA==\").\n<<1,2,3,4>>\n3> base64:decode(\"AQIDBA=\").\n** exception error: missing_padding\n in function base64:decode_list/7 (base64.erl, line 734)\n *** data to decode is missing final = padding characters, if this is intended, use the `padding => false` option\n4> base64:decode(\"AQIDBA=\", #{ padding => false }).\n<<1,2,3,4>>\n```","title":"base64.decode/2","ref":"base64.html#decode/2"},{"type":"function","doc":"Equivalent to [`decode(Base64)`](`decode/1`), but returns a `t:byte_string/0`.","title":"base64.decode_to_string/1","ref":"base64.html#decode_to_string/1"},{"type":"function","doc":"Equivalent to [`decode(Base64, Options)`](`decode/2`), but returns a `t:byte_string/0`.","title":"base64.decode_to_string/2","ref":"base64.html#decode_to_string/2"},{"type":"function","doc":"","title":"base64.encode/1","ref":"base64.html#encode/1"},{"type":"function","doc":"Encodes a plain ASCII string into base64 using the alphabet indicated by the\n`mode` option. The result is 33% larger than the data.\n\nSee `t:encode_options/0` for details on which options can be passed.","title":"base64.encode/2","ref":"base64.html#encode/2"},{"type":"function","doc":"Equivalent to [`encode(Data)`](`encode/1`), but returns a `t:byte_string/0`.","title":"base64.encode_to_string/1","ref":"base64.html#encode_to_string/1"},{"type":"function","doc":"Equivalent to [`encode(Data, Options)`](`encode/2`), but returns a `t:byte_string/0`.","title":"base64.encode_to_string/2","ref":"base64.html#encode_to_string/2"},{"type":"function","doc":"","title":"base64.mime_decode/1","ref":"base64.html#mime_decode/1"},{"type":"function","doc":"Decodes a base64 \"mime\" string encoded using the standard alphabet according to\n[RFC 4648 Section 4](https://datatracker.ietf.org/doc/html/rfc4648#section-4) to\nplain ASCII.\n\nThe function will strips away any illegal characters. It does *not* check for the\nthe correct number of `=` padding characters at the end of the encoded string.\n\nSee `t:decode_options/0` for details on which options can be passed.\n\n_Example_:\n```erlang\n1> base64:mime_decode(\"AQIDBA==\").\n<<1,2,3,4>>\n2> base64:mime_decode(\"AQIDB=A=\").\n<<1,2,3,4>>\n```","title":"base64.mime_decode/2","ref":"base64.html#mime_decode/2"},{"type":"function","doc":"Equivalent to [`mime_decode(Base64)`](`mime_decode/1`),\nbut returns a `t:byte_string/0`.","title":"base64.mime_decode_to_string/1","ref":"base64.html#mime_decode_to_string/1"},{"type":"function","doc":"Equivalent to [`mime_decode(Base64, Options)`](`mime_decode/2`),\nbut returns a `t:byte_string/0`.","title":"base64.mime_decode_to_string/2","ref":"base64.html#mime_decode_to_string/2"},{"type":"type","doc":"Base 64 Encoding alphabet, see\n[RFC 4648](https://datatracker.ietf.org/doc/html/rfc4648).","title":"base64.base64_alphabet/0","ref":"base64.html#t:base64_alphabet/0"},{"type":"type","doc":"Base 64 encoded binary.","title":"base64.base64_binary/0","ref":"base64.html#t:base64_binary/0"},{"type":"type","doc":"Selector for the Base 64 Encoding alphabet used for [encoding](`encode/2`) and\n[decoding](`decode/2`). See\n[RFC 4648](https://datatracker.ietf.org/doc/html/rfc4648) Sections\n[4](https://datatracker.ietf.org/doc/html/rfc4648#section-4) and\n[5](https://datatracker.ietf.org/doc/html/rfc4648#section-5).","title":"base64.base64_mode/0","ref":"base64.html#t:base64_mode/0"},{"type":"type","doc":"Base 64 encoded string.","title":"base64.base64_string/0","ref":"base64.html#t:base64_string/0"},{"type":"type","doc":"Arbitrary sequences of octets.","title":"base64.byte_string/0","ref":"base64.html#t:byte_string/0"},{"type":"type","doc":"Customizes the behaviour of the decode functions.\n\nDefault value if omitted entirely or partially is `#{mode => standard, padding => true}`.\n\nThe `mode` option can be one of the following:\n\n- **`standard`** - Default. Decode the given string using the standard base64\n alphabet according to\n [RFC 4648 Section 4](https://datatracker.ietf.org/doc/html/rfc4648#section-4),\n that is `\"+\"` and `\"/\"` are representing bytes `62` and `63` respectively,\n while `\"-\"` and `\"_\"` are illegal characters.\n\n- **`urlsafe`** - Decode the given string using the alternative \"URL and\n Filename safe\" base64 alphabet according to\n [RFC 4648 Section 5](https://datatracker.ietf.org/doc/html/rfc4648#section-5),\n that is `\"-\"` and `\"_\"` are representing bytes `62` and `63` respectively,\n while `\"+\"` and `\"/\"` are illegal characters.\n\nThe `padding` option can be one of the following:\n\n- **`true`** - Default. Checks the correct number of `=` padding characters at\n the end of the encoded string.\n\n- **`false`** - Accepts an encoded string with missing `=` padding characters at\n the end.","title":"base64.decode_options/0","ref":"base64.html#t:decode_options/0"},{"type":"type","doc":"Customizes the behaviour of the decode functions.\n\nDefault value if omitted entirely or partially is `#{mode => standard, padding => true}`.\n\nThe `mode` option can be one of the following:\n\n- **`standard`** - Default. Encode the given string using the standard base64\n alphabet according to\n [RFC 4648 Section 4](https://datatracker.ietf.org/doc/html/rfc4648#section-4).\n\n- **`urlsafe`** - Encode the given string using the alternative \"URL and\n Filename safe\" base64 alphabet according to\n [RFC 4648 Section 5](https://datatracker.ietf.org/doc/html/rfc4648#section-5).\n\nThe `padding` option can be one of the following:\n\n- **`true`** - Default. Appends correct number of `=` padding characters to the\n encoded string.\n\n- **`false`** - Skips appending `=` padding characters to the encoded string.","title":"base64.encode_options/0","ref":"base64.html#t:encode_options/0"},{"type":"behaviour","doc":"This module provides functions for pretty-printing errors and exceptions. It is\nused by both the `m:shell` and by `m:proc_lib` to print exceptions.\n\nIt is possible for the module raising an error to provide additional information\nby calling [`error/3`](`erlang:error/3`) with extra error information. More\ndetails about this mechanism is described in\n[EEP-54](https://www.erlang.org/erlang-enhancement-proposals/eep-0054.html).","title":"erl_error","ref":"erl_error.html"},{"type":"behaviour","doc":"The following functions are to be exported from an Error Info handler.","title":"Callback Functions - erl_error","ref":"erl_error.html#module-callback-functions"},{"type":"callback","doc":"This callback is called when `format_exception/4` or similar functionality wants\nto provide extra information about an error. The `Module`:`Function` called is\nthe one specificed by the `error_info` map.\n\nThe function should return a map with additional information about what have\ncaused the exception. The possible keys of the map are:\n\n- **`ArgumentPosition = pos_integer()`** - The position of the argument that\n caused the error starting at 1.\n\n- **`general`** - An error that is not associated with any argument caused the\n error.\n\n- **`reason`** - If the `Reason` should be printed differently than the default\n way.\n\nIf the text returned includes new-lines, `format_exception/4` will indent the\ntext correctly.\n\nExample:\n\n```erlang\n-module(my_error_module).\n-export([atom_to_string/1, format_error/2]).\n\natom_to_string(Arg) when is_atom(Arg) ->\n atom_to_list(Arg);\natom_to_string(Arg) ->\n erlang:error(badarg,[Arg],\n [{error_info,#{ module => ?MODULE,\n cause => #{ 1 => \"should be an atom\" }}}]).\n\nformat_error(Reason, [{_M,_F,_As,Info}|_]) ->\n ErrorInfo = proplists:get_value(error_info, Info, #{}),\n ErrorMap = maps:get(cause, ErrorInfo),\n ErrorMap#{ general => \"optional general information\",\n reason => io_lib:format(\"~p: ~p\",[?MODULE, Reason]) }.\n```\n\n```erlang\n1> c(my_error_module).\n{ok,my_error_module}\n2> my_error_module:atom_to_string(1).\n** exception error: my_error_module: badarg\n in function my_error_module:atom_to_string/1\n called as my_error_module:atom_to_string(1)\n *** argument 1: should be an atom\n *** optional general information\n```","title":"erl_error.format_error/2","ref":"erl_error.html#c:format_error/2"},{"type":"function","doc":"","title":"erl_error.format_exception/3","ref":"erl_error.html#format_exception/3"},{"type":"function","doc":"Format the error reason and stack back-trace caught using `try` ... `catch` in\nthe same style as the shell formats them.\n\nExample:\n\n```erlang\ntry\n do_something()\ncatch\n C:R:Stk ->\n Message = erl_error:format_exception(C, R, Stk),\n io:format(LogFile, \"~ts\\n\", [Message])\nend\n```\n\nIf `error_info` is provided with the exception, `format_exception` will use that\ninformation to provide additional information about the exception.\n\nExample:\n\n```erlang\ntry\n erlang:raise(badarg,[],[{error_info,#{}}])\ncatch\n C:R:Stk ->\n Message = erl_error:format_exception(C, R, Stk),\n io:format(LogFile, \"~ts\\n\", [Message])\nend\n```\n\nSee `erlang:error/3` for details on how to raise an exception with `error_info`\nincluded.","title":"erl_error.format_exception/4","ref":"erl_error.html#format_exception/4"},{"type":"type","doc":"Start column number. Default is 1.","title":"erl_error.column/0","ref":"erl_error.html#t:column/0"},{"type":"type","doc":"A fun used to format function arguments for BIF and function calls. By default\nthe following fun will be used:\n\n```erlang\nfun(Term, I) -> io_lib:print(Term, I, 80, 30) end\n```","title":"erl_error.format_fun/0","ref":"erl_error.html#t:format_fun/0"},{"type":"type","doc":"A map with formatting options.","title":"erl_error.format_options/0","ref":"erl_error.html#t:format_options/0"},{"type":"type","doc":"A fun used to trim the end of the stacktrace. It is called with module,\nfunction, and arity from an entry from the stacktrace. The fun is to return\n`true` if the entry should be trimmed, and `false` otherwise. The default value\nis:\n\n```text\nfun(_, _, _) -> false end\n```","title":"erl_error.stack_trim_fun/0","ref":"erl_error.html#t:stack_trim_fun/0"},{"type":"module","doc":"File sorter.\n\nThis module contains functions for sorting terms on files, merging already\nsorted files, and checking files for sortedness. Chunks containing binary terms\nare read from a sequence of files, sorted internally in memory and written on\ntemporary files, which are merged producing one sorted file as output. Merging\nis provided as an optimization; it is faster when the files are already sorted,\nbut it always works to sort instead of merge.\n\nOn a file, a term is represented by a header and a binary. Two options define\nthe format of terms on files:\n\n- **`{header, HeaderLength}`** - `HeaderLength` determines the number of bytes\n preceding each binary and containing the length of the binary in bytes.\n Defaults to 4. The order of the header bytes is defined as follows: if `B` is\n a binary containing a header only, size `Size` of the binary is calculated as\n `< > = B`.\n\n- **`{format, Format}`** - Option `Format` determines the function that is\n applied to binaries to create the terms to be sorted. Defaults to\n `binary_term`, which is equivalent to `fun binary_to_term/1`. Value `binary`\n is equivalent to `fun(X) -> X end`, which means that the binaries are sorted\n as they are. This is the fastest format. If `Format` is `term`, `io:read/2` is\n called to read terms. In that case, only the default value of option `header`\n is allowed.\n\n Option `format` also determines what is written to the sorted output file: if\n `Format` is `term`, then `io:format/3` is called to write each term, otherwise\n the binary prefixed by a header is written. Notice that the binary written is\n the same binary that was read; the results of applying function `Format` are\n thrown away when the terms have been sorted. Reading and writing terms using\n the `io` module is much slower than reading and writing binaries.\n\nOther options are:\n\n- **`{order, Order}`** - The default is to sort terms in ascending order, but\n that can be changed by value `descending` or by specifying an ordering\n function `Fun`. An ordering function is antisymmetric, transitive, and total.\n `Fun(A, B)` is to return `true` if `A` comes before `B` in the ordering,\n otherwise `false`. An example of a typical ordering function is less than or\n equal to, `=\n {ok, _} = disk_log:open([{name,Log}, {mode,read_only}]),\n Input = input(Log, start),\n Output = output([]),\n Reply = file_sorter:sort(Input, Output, {format,term}),\n ok = disk_log:close(Log),\n Reply.\n\ninput(Log, Cont) ->\n fun(close) ->\n ok;\n (read) ->\n case disk_log:chunk(Log, Cont) of\n {error, Reason} ->\n {error, Reason};\n {Cont2, Terms} ->\n {Terms, input(Log, Cont2)};\n {Cont2, Terms, _Badbytes} ->\n {Terms, input(Log, Cont2)};\n eof ->\n end_of_input\n end\n end.\n\noutput(L) ->\n fun(close) ->\n lists:append(lists:reverse(L));\n (Terms) ->\n output([Terms | L])\n end.\n```\n\nFor more examples of functions as input and output, see the end of the\n`file_sorter` module; the `term` format is implemented with functions.\n\nThe possible values of `Reason` returned when an error occurs are:\n\n- `bad_object`, `{bad_object, FileName}` \\- Applying the format function failed\n for some binary, or the key(s) could not be extracted from some term.\n- `{bad_term, FileName}` \\- `io:read/2` failed to read some term.\n- `{file_error, FileName, file:posix()}` \\- For an explanation of\n [`file:posix()`](`t:file:posix/0`), see `m:file`.\n- `{premature_eof, FileName}` \\- End-of-file was encountered inside some binary\n term.","title":"file_sorter","ref":"file_sorter.html"},{"type":"function","doc":"","title":"file_sorter.check/1","ref":"file_sorter.html#check/1"},{"type":"function","doc":"Checks files for sortedness. If a file is not sorted, the first out-of-order\nelement is returned. The first term on a file has position 1.","title":"file_sorter.check/2","ref":"file_sorter.html#check/2"},{"type":"function","doc":"","title":"file_sorter.keycheck/2","ref":"file_sorter.html#keycheck/2"},{"type":"function","doc":"Checks files for sortedness. If a file is not sorted, the first out-of-order\nelement is returned. The first term on a file has position 1.","title":"file_sorter.keycheck/3","ref":"file_sorter.html#keycheck/3"},{"type":"function","doc":"","title":"file_sorter.keymerge/3","ref":"file_sorter.html#keymerge/3"},{"type":"function","doc":"Merges tuples on files. Each input file is assumed to be sorted on key(s).","title":"file_sorter.keymerge/4","ref":"file_sorter.html#keymerge/4"},{"type":"function","doc":"Sorts tuples on files.","title":"file_sorter.keysort/2","ref":"file_sorter.html#keysort/2"},{"type":"function","doc":"","title":"file_sorter.keysort/3","ref":"file_sorter.html#keysort/3"},{"type":"function","doc":"Sorts tuples on files. The sort is performed on the element(s) mentioned in\n`KeyPos`. If two tuples compare equal (`==`) on one element, the next element\naccording to `KeyPos` is compared. The sort is stable.","title":"file_sorter.keysort/4","ref":"file_sorter.html#keysort/4"},{"type":"function","doc":"","title":"file_sorter.merge/2","ref":"file_sorter.html#merge/2"},{"type":"function","doc":"Merges terms on files. Each input file is assumed to be sorted.","title":"file_sorter.merge/3","ref":"file_sorter.html#merge/3"},{"type":"function","doc":"Sorts terms on files.","title":"file_sorter.sort/1","ref":"file_sorter.html#sort/1"},{"type":"function","doc":"","title":"file_sorter.sort/2","ref":"file_sorter.html#sort/2"},{"type":"function","doc":"Sorts terms on files.","title":"file_sorter.sort/3","ref":"file_sorter.html#sort/3"},{"type":"type","doc":"","title":"file_sorter.file_name/0","ref":"file_sorter.html#t:file_name/0"},{"type":"type","doc":"","title":"file_sorter.file_names/0","ref":"file_sorter.html#t:file_names/0"},{"type":"type","doc":"","title":"file_sorter.format/0","ref":"file_sorter.html#t:format/0"},{"type":"type","doc":"","title":"file_sorter.format_fun/0","ref":"file_sorter.html#t:format_fun/0"},{"type":"type","doc":"","title":"file_sorter.header_length/0","ref":"file_sorter.html#t:header_length/0"},{"type":"type","doc":"","title":"file_sorter.i_command/0","ref":"file_sorter.html#t:i_command/0"},{"type":"type","doc":"","title":"file_sorter.i_reply/0","ref":"file_sorter.html#t:i_reply/0"},{"type":"type","doc":"","title":"file_sorter.infun/0","ref":"file_sorter.html#t:infun/0"},{"type":"type","doc":"","title":"file_sorter.input/0","ref":"file_sorter.html#t:input/0"},{"type":"type","doc":"","title":"file_sorter.input_reply/0","ref":"file_sorter.html#t:input_reply/0"},{"type":"type","doc":"","title":"file_sorter.key_pos/0","ref":"file_sorter.html#t:key_pos/0"},{"type":"type","doc":"","title":"file_sorter.no_files/0","ref":"file_sorter.html#t:no_files/0"},{"type":"type","doc":"","title":"file_sorter.o_command/0","ref":"file_sorter.html#t:o_command/0"},{"type":"type","doc":"","title":"file_sorter.o_reply/0","ref":"file_sorter.html#t:o_reply/0"},{"type":"type","doc":"","title":"file_sorter.object/0","ref":"file_sorter.html#t:object/0"},{"type":"type","doc":"","title":"file_sorter.option/0","ref":"file_sorter.html#t:option/0"},{"type":"type","doc":"","title":"file_sorter.options/0","ref":"file_sorter.html#t:options/0"},{"type":"type","doc":"","title":"file_sorter.order/0","ref":"file_sorter.html#t:order/0"},{"type":"type","doc":"","title":"file_sorter.order_fun/0","ref":"file_sorter.html#t:order_fun/0"},{"type":"type","doc":"","title":"file_sorter.outfun/0","ref":"file_sorter.html#t:outfun/0"},{"type":"type","doc":"","title":"file_sorter.output/0","ref":"file_sorter.html#t:output/0"},{"type":"type","doc":"","title":"file_sorter.output_reply/0","ref":"file_sorter.html#t:output_reply/0"},{"type":"type","doc":"","title":"file_sorter.reason/0","ref":"file_sorter.html#t:reason/0"},{"type":"type","doc":"","title":"file_sorter.size/0","ref":"file_sorter.html#t:size/0"},{"type":"type","doc":"","title":"file_sorter.tmp_directory/0","ref":"file_sorter.html#t:tmp_directory/0"},{"type":"type","doc":"","title":"file_sorter.value/0","ref":"file_sorter.html#t:value/0"},{"type":"module","doc":"File utilities, such as wildcard matching of filenames.\n\nThis module contains utilities on a higher level than the `m:file` module.\n\nThis module does not support \"raw\" filenames (that is, files whose names do not\ncomply with the expected encoding). Such files are ignored by the functions in\nthis module.\n\nFor more information about raw filenames, see the `m:file` module.\n\n> #### Note {: .info }\n>\n> Functionality in this module generally assumes valid input and does not\n> necessarily fail on input that does not use a valid encoding, but may instead\n> very likely produce invalid output.\n>\n> File operations used to accept filenames containing null characters (integer\n> value zero). This caused the name to be truncated and in some cases arguments\n> to primitive operations to be mixed up. Filenames containing null characters\n> inside the filename are now _rejected_ and will cause primitive file\n> operations to fail.\n\n> #### Warning {: .warning }\n>\n> Currently null characters at the end of the filename will be accepted by\n> primitive file operations. Such filenames are however still documented as\n> invalid. The implementation will also change in the future and reject such\n> filenames.","title":"filelib","ref":"filelib.html"},{"type":"function","doc":"Ensures that all parent directories for the specified file or directory name\n`Name` exist, trying to create them if necessary.\n\nReturns `ok` if all parent directories already exist or can be created. Returns\n`{error, Reason}` if some parent directory does not exist and cannot be created.","title":"filelib.ensure_dir/1","ref":"filelib.html#ensure_dir/1"},{"type":"function","doc":"Ensures that all parent directories for the specified path `Path` exist, trying\nto create them if necessary.\n\nUnlike `ensure_dir/1`, this function will attempt to create all path segments as\na directory, including the last segment.\n\nReturns `ok` if all parent directories already exist or can be created. Returns\n`{error, Reason}` if some parent directory does not exist and cannot be created.","title":"filelib.ensure_path/1","ref":"filelib.html#ensure_path/1"},{"type":"function","doc":"Returns the size of the specified file.","title":"filelib.file_size/1","ref":"filelib.html#file_size/1"},{"type":"function","doc":"","title":"filelib.find_file/2","ref":"filelib.html#find_file/2"},{"type":"function","doc":"Looks for a file of the given name by applying suffix rules to the given\ndirectory path.\n\nFor example, a rule `{\"ebin\", \"src\"}` means that if the directory path ends with\n `\"ebin\"`, the corresponding path ending in `\"src\"` should be searched.\n\nIf `Rules` is left out or is an empty list, the default system rules are used.\nSee also the Kernel application parameter\n[`source_search_rules`](`e:kernel:kernel_app.md#source_search_rules`).","title":"filelib.find_file/3","ref":"filelib.html#find_file/3"},{"type":"function","doc":"Equivalent to [`find_source(Base, Dir)`](`find_source/2`), where `Dir` is\n`filename:dirname(FilePath)` and `Base` is `filename:basename(FilePath)`.","title":"filelib.find_source/1","ref":"filelib.html#find_source/1"},{"type":"function","doc":"","title":"filelib.find_source/2","ref":"filelib.html#find_source/2"},{"type":"function","doc":"Applies file extension specific rules to find the source file for a given object\nfile relative to the object directory.\n\nFor example, for a file with the extension `.beam`, the default rule is to look\nfor a file with a corresponding extension `.erl` by replacing the suffix `\"ebin\"`\nof the object directory path with `\"src\"` or `\"src/*\"`. The file search is done\nthrough `find_file/3`. The directory of the object file is always tried before\nany other directory specified by the rules.\n\nIf `Rules` is left out or is an empty list, the default system rules are used.\nSee also the Kernel application parameter\n[`source_search_rules`](`e:kernel:kernel_app.md#source_search_rules`).","title":"filelib.find_source/3","ref":"filelib.html#find_source/3"},{"type":"function","doc":"Folds function `Fun` over all (regular) files `F` in directory `Dir` whose\nbasename (for example, just `\"baz.erl\"` in `\"foo/bar/baz.erl\"`) matches the\nregular expression `RegExp` (for a description of the allowed regular\nexpressions, see the `m:re` module).\n\nIf `Recursive` is `true`, all subdirectories to `Dir` are processed.\nThe regular expression matching is only done on the filename without the directory part.\n\nIf Unicode filename translation is in effect and the file system is transparent,\nfilenames that cannot be interpreted as Unicode can be encountered, in which\ncase the `fun()` must be prepared to handle raw filenames (that is, binaries).\nIf the regular expression contains codepoints > 255, it does not match filenames\nthat do not conform to the expected character encoding (that is, are not encoded\nin valid UTF-8).\n\nFor more information about raw filenames, see the `m:file` module.","title":"filelib.fold_files/5","ref":"filelib.html#fold_files/5"},{"type":"function","doc":"Returns `true` if `Name` refers to a directory, otherwise `false`.","title":"filelib.is_dir/1","ref":"filelib.html#is_dir/1"},{"type":"function","doc":"Returns `true` if `Name` refers to a file or a directory, otherwise `false`.","title":"filelib.is_file/1","ref":"filelib.html#is_file/1"},{"type":"function","doc":"Returns `true` if `Name` refers to a (regular) file, otherwise `false`.","title":"filelib.is_regular/1","ref":"filelib.html#is_regular/1"},{"type":"function","doc":"Returns the date and time the specified file or directory was last modified, or\n`0` if the file does not exist.","title":"filelib.last_modified/1","ref":"filelib.html#last_modified/1"},{"type":"function","doc":"Sanitizes the relative path by eliminating \"..\" and \".\" components to protect\nagainst directory traversal attacks.\n\nEither returns the sanitized path name, or the atom `unsafe` if the path is unsafe.\nThe path is considered unsafe in the following circumstances:\n\n- The path is not relative.\n- A \"..\" component would climb up above the root of the relative path.\n- A symbolic link in the path points above the root of the relative path.\n\n_Examples:_\n\n```erlang\n1> {ok, Cwd} = file:get_cwd().\n...\n2> filelib:safe_relative_path(\"dir/sub_dir/..\", Cwd).\n\"dir\"\n3> filelib:safe_relative_path(\"dir/..\", Cwd).\n[]\n4> filelib:safe_relative_path(\"dir/../..\", Cwd).\nunsafe\n5> filelib:safe_relative_path(\"/abs/path\", Cwd).\nunsafe\n```","title":"filelib.safe_relative_path/2","ref":"filelib.html#safe_relative_path/2"},{"type":"function","doc":"Returns a list of all files that match Unix-style wildcard string `Wildcard`.\n\nThe wildcard string looks like an ordinary filename, except that the following\n\"wildcard characters\" are interpreted in a special way:\n\n- **?** - Matches one character.\n\n- **\\*** - Matches any number of characters up to the end of the filename, the\n next dot, or the next slash.\n\n- **\\*\\*** - Two adjacent `*` used as a single pattern match all files and zero\n or more directories and subdirectories.\n\n- **\\[Character1,Character2,...]** - Matches any of the characters listed. Two\n characters separated by a hyphen match a range of characters. Example: `[A-Z]`\n matches any uppercase letter.\n\n- **\\{Item,...\\}** - Alternation. Matches one of the alternatives.\n\nOther characters represent themselves. Only filenames that have exactly the same\ncharacter in the same position match. Matching is case-sensitive, for example,\n\"a\" does not match \"A\".\n\nDirectory separators must always be written as `/`, even on Windows.\n\nA character preceded by `\\` loses its special meaning. Note that `\\` must be\nwritten as `\\\\` in a string literal. For example, \"\\\\\\\\?\\*\" will match any\nfilename starting with `?`.\n\nNotice that multiple \"\\*\" characters are allowed (as in Unix wildcards, but\nopposed to Windows/DOS wildcards).\n\n_Examples:_\n\nThe following examples assume that the current directory is the top of an\nErlang/OTP installation.\n\nTo find all `.beam` files in all applications, use the following line:\n\n```text\nfilelib:wildcard(\"lib/*/ebin/*.beam\").\n```\n\nTo find `.erl` or `.hrl` in all applications `src` directories, use either of\nthe following lines:\n\n```text\nfilelib:wildcard(\"lib/*/src/*.?rl\")\n```\n\n```text\nfilelib:wildcard(\"lib/*/src/*.{erl,hrl}\")\n```\n\nTo find all `.hrl` files in `src` or `include` directories:\n\n```text\nfilelib:wildcard(\"lib/*/{src,include}/*.hrl\").\n```\n\nTo find all `.erl` or `.hrl` files in either `src` or `include` directories:\n\n```text\nfilelib:wildcard(\"lib/*/{src,include}/*.{erl,hrl}\")\n```\n\nTo find all `.erl` or `.hrl` files in any subdirectory:\n\n```text\nfilelib:wildcard(\"lib/**/*.{erl,hrl}\")\n```","title":"filelib.wildcard/1","ref":"filelib.html#wildcard/1"},{"type":"function","doc":"Same as `wildcard/1`, except that `Cwd` is used instead of the working\ndirectory.","title":"filelib.wildcard/2","ref":"filelib.html#wildcard/2"},{"type":"type","doc":"","title":"filelib.dirname/0","ref":"filelib.html#t:dirname/0"},{"type":"type","doc":"","title":"filelib.dirname_all/0","ref":"filelib.html#t:dirname_all/0"},{"type":"type","doc":"","title":"filelib.filename/0","ref":"filelib.html#t:filename/0"},{"type":"type","doc":"","title":"filelib.filename_all/0","ref":"filelib.html#t:filename_all/0"},{"type":"type","doc":"","title":"filelib.find_file_rule/0","ref":"filelib.html#t:find_file_rule/0"},{"type":"type","doc":"","title":"filelib.find_source_rule/0","ref":"filelib.html#t:find_source_rule/0"},{"type":"module","doc":"Filename manipulation functions.\n\nThis module provides functions for analyzing and manipulating filenames. These\nfunctions are designed so that the Erlang code can work on many different\nplatforms with different filename formats. With filename is meant all strings\nthat can be used to denote a file. The filename can be a short relative name\nlike `foo.erl`, a long absolute name including a drive designator, a directory\nname like `D:\\usr/local\\bin\\erl/lib\\tools\\foo.erl`, or any variations in\nbetween.\n\nIn Windows, all functions return filenames with forward slashes only, even if\nthe arguments contain backslashes. To normalize a filename by removing redundant\ndirectory separators, use `join/1`.\n\nThe module supports [raw filenames](unicode_usage.md#notes-about-raw-filenames)\nin the way that if a binary is present, or the filename cannot be interpreted\naccording to the return value of `file:native_name_encoding/0`, a raw filename\nis also returned. For example, [`join/1`](`join/1`) provided with a path\ncomponent that is a binary (and cannot be interpreted under the current native\nfilename encoding) results in a raw filename that is returned (the join\noperation is performed of course). For more information about raw filenames, see\nthe `m:file` module.\n\n> #### Note {: .info }\n>\n> Functionality in this module generally assumes valid input and does not\n> necessarily fail on input that does not use a valid encoding, but may instead\n> very likely produce invalid output.\n>\n> File operations used to accept filenames containing null characters (integer\n> value zero). This caused the name to be truncated and in some cases arguments\n> to primitive operations to be mixed up. Filenames containing null characters\n> inside the filename are now _rejected_ and will cause primitive file\n> operations to fail.\n\n> #### Warning {: .warning }\n>\n> Currently null characters at the end of the filename will be accepted by\n> primitive file operations. Such filenames are however still documented as\n> invalid. The implementation will also change in the future and reject such\n> filenames.","title":"filename","ref":"filename.html"},{"type":"function","doc":"Converts a relative `Filename` and returns an absolute name. No attempt is made\nto create the shortest absolute name, as this can give incorrect results on file\nsystems that allow links.\n\n_Unix examples:_\n\n```erlang\n1> pwd().\n\"/usr/local\"\n2> filename:absname(\"foo\").\n\"/usr/local/foo\"\n3> filename:absname(\"../x\").\n\"/usr/local/../x\"\n4> filename:absname(\"/\").\n\"/\"\n```\n\n_Windows examples:_\n\n```erlang\n1> pwd().\n\"D:/usr/local\"\n2> filename:absname(\"foo\").\n\"D:/usr/local/foo\"\n3> filename:absname(\"../x\").\n\"D:/usr/local/../x\"\n4> filename:absname(\"/\").\n\"D:/\"\n```","title":"filename.absname/1","ref":"filename.html#absname/1"},{"type":"function","doc":"Same as `absname/1`, except that the directory to which the filename is to be\nmade relative is specified in argument `Dir`.","title":"filename.absname/2","ref":"filename.html#absname/2"},{"type":"function","doc":"Joins an absolute directory with a relative filename.\n\nSimilar to `join/2`, but on platforms with tight restrictions on raw filename length\nand no support for symbolic links, leading parent directory components in `Filename` are matched\nagainst trailing directory components in `Dir` so they can be removed from the\nresult - minimizing its length.","title":"filename.absname_join/2","ref":"filename.html#absname_join/2"},{"type":"function","doc":"Equivalent to [basedir(PathType, Application, #\\{\\})](`m:filename#basedir_3_1`)\nor [basedir(PathsType, Application, #\\{\\})](`m:filename#basedir_3_2`).","title":"filename.basedir/2","ref":"filename.html#basedir/2"},{"type":"function","doc":"[](){: #basedir_3_1 } [](){: #basedir_3_2 }\n\nReturns a suitable path, or paths, for a given type. If `os` is not set in\n`Opts` the function will default to the native option, that is `'linux'`,\n`'darwin'` or `'windows'`, as understood by `os:type/0`. Anything not recognized\nas `'darwin'` or `'windows'` is interpreted as `'linux'`.\n\nThe options `'author'` and `'version'` are only used with `'windows'` option\nmode.\n\n- `user_cache`{: #user_cache }\n\n The path location is intended for transient data files on a local machine.\n\n On Linux: Respects the os environment variable `XDG_CACHE_HOME`.\n\n ```erlang\n 1> filename:basedir(user_cache, \"my_application\", #{os=>linux}).\n \"/home/otptest/.cache/my_application\"\n ```\n\n On Darwin:\n\n ```erlang\n 1> filename:basedir(user_cache, \"my_application\", #{os=>darwin}).\n \"/home/otptest/Library/Caches/my_application\"\n ```\n\n On Windows:\n\n ```erlang\n 1> filename:basedir(user_cache, \"My App\").\n \"c:/Users/otptest/AppData/Local/My App/Cache\"\n 2> filename:basedir(user_cache, \"My App\").\n \"c:/Users/otptest/AppData/Local/My App/Cache\"\n 3> filename:basedir(user_cache, \"My App\", #{author=>\"Erlang\"}).\n \"c:/Users/otptest/AppData/Local/Erlang/My App/Cache\"\n 4> filename:basedir(user_cache, \"My App\", #{version=>\"1.2\"}).\n \"c:/Users/otptest/AppData/Local/My App/1.2/Cache\"\n 5> filename:basedir(user_cache, \"My App\", #{author=>\"Erlang\",version=>\"1.2\"}).\n \"c:/Users/otptest/AppData/Local/Erlang/My App/1.2/Cache\"\n ```\n\n- `user_config`{: #user_config }\n\n The path location is intended for persistent configuration files.\n\n On Linux: Respects the os environment variable `XDG_CONFIG_HOME`.\n\n ```erlang\n 2> filename:basedir(user_config, \"my_application\", #{os=>linux}).\n \"/home/otptest/.config/my_application\"\n ```\n\n On Darwin:\n\n ```erlang\n 2> filename:basedir(user_config, \"my_application\", #{os=>darwin}).\n \"/home/otptest/Library/Application Support/my_application\"\n ```\n\n On Windows:\n\n ```erlang\n 1> filename:basedir(user_config, \"My App\").\n \"c:/Users/otptest/AppData/Roaming/My App\"\n 2> filename:basedir(user_config, \"My App\", #{author=>\"Erlang\", version=>\"1.2\"}).\n \"c:/Users/otptest/AppData/Roaming/Erlang/My App/1.2\"\n ```\n\n- `user_data`{: #user_data }\n\n The path location is intended for persistent data files.\n\n On Linux: Respects the os environment variable `XDG_DATA_HOME`.\n\n ```erlang\n 3> filename:basedir(user_data, \"my_application\", #{os=>linux}).\n \"/home/otptest/.local/my_application\"\n ```\n\n On Darwin:\n\n ```erlang\n 3> filename:basedir(user_data, \"my_application\", #{os=>darwin}).\n \"/home/otptest/Library/Application Support/my_application\"\n ```\n\n On Windows:\n\n ```erlang\n 8> filename:basedir(user_data, \"My App\").\n \"c:/Users/otptest/AppData/Local/My App\"\n 9> filename:basedir(user_data, \"My App\",#{author=>\"Erlang\",version=>\"1.2\"}).\n \"c:/Users/otptest/AppData/Local/Erlang/My App/1.2\"\n ```\n\n- `user_log`{: #user_log }\n\n The path location is intended for transient log files on a local machine.\n\n On Linux: Respects the os environment variable `XDG_CACHE_HOME`.\n\n ```erlang\n 4> filename:basedir(user_log, \"my_application\", #{os=>linux}).\n \"/home/otptest/.cache/my_application/log\"\n ```\n\n On Darwin:\n\n ```erlang\n 4> filename:basedir(user_log, \"my_application\", #{os=>darwin}).\n \"/home/otptest/Library/Logs/my_application\"\n ```\n\n On Windows:\n\n ```erlang\n 12> filename:basedir(user_log, \"My App\").\n \"c:/Users/otptest/AppData/Local/My App/Logs\"\n 13> filename:basedir(user_log, \"My App\",#{author=>\"Erlang\",version=>\"1.2\"}).\n \"c:/Users/otptest/AppData/Local/Erlang/My App/1.2/Logs\"\n ```\n\n- `site_config`{: #site_config }\n\n On Linux: Respects the os environment variable `XDG_CONFIG_DIRS`.\n\n ```erlang\n 5> filename:basedir(site_config, \"my_application\", #{os=>linux}).\n [\"/usr/local/share/my_application\",\n \"/usr/share/my_application\"]\n 6> os:getenv(\"XDG_CONFIG_DIRS\").\n \"/etc/xdg/xdg-ubuntu:/usr/share/upstart/xdg:/etc/xdg\"\n 7> filename:basedir(site_config, \"my_application\", #{os=>linux}).\n [\"/etc/xdg/xdg-ubuntu/my_application\",\n \"/usr/share/upstart/xdg/my_application\",\n \"/etc/xdg/my_application\"]\n 8> os:unsetenv(\"XDG_CONFIG_DIRS\").\n true\n 9> filename:basedir(site_config, \"my_application\", #{os=>linux}).\n [\"/etc/xdg/my_application\"]\n ```\n\n On Darwin:\n\n ```erlang\n 5> filename:basedir(site_config, \"my_application\", #{os=>darwin}).\n [\"/Library/Application Support/my_application\"]\n ```\n\n- `site_data`{: #site_data }\n\n On Linux: Respects the os environment variable `XDG_DATA_DIRS`.\n\n ```erlang\n 10> os:getenv(\"XDG_DATA_DIRS\").\n \"/usr/share/ubuntu:/usr/share/gnome:/usr/local/share/:/usr/share/\"\n 11> filename:basedir(site_data, \"my_application\", #{os=>linux}).\n [\"/usr/share/ubuntu/my_application\",\n \"/usr/share/gnome/my_application\",\n \"/usr/local/share/my_application\",\n \"/usr/share/my_application\"]\n 12> os:unsetenv(\"XDG_DATA_DIRS\").\n true\n 13> filename:basedir(site_data, \"my_application\", #{os=>linux}).\n [\"/usr/local/share/my_application\",\n \"/usr/share/my_application\"]\n ```\n\n On Darwin:\n\n ```erlang\n 5> filename:basedir(site_data, \"my_application\", #{os=>darwin}).\n [\"/Library/Application Support/my_application\"]\n ```","title":"filename.basedir/3","ref":"filename.html#basedir/3"},{"type":"function","doc":"Returns the last component of `Filename`, or `Filename` itself if it does not\ncontain any directory separators.\n\n_Examples:_\n\n```erlang\n5> filename:basename(\"foo\").\n\"foo\"\n6> filename:basename(\"/usr/foo\").\n\"foo\"\n7> filename:basename(\"/\").\n[]\n```","title":"filename.basename/1","ref":"filename.html#basename/1"},{"type":"function","doc":"Returns the last component of `Filename` with extension `Ext` stripped.\n\nThis function is to be used to remove a (possible) specific extension.\nTo remove an existing extension when you are unsure which one it is, use\n[`rootname(basename(Filename))`](`rootname/1`).\n\n_Examples:_\n\n```erlang\n8> filename:basename(\"~/src/kalle.erl\", \".erl\").\n\"kalle\"\n9> filename:basename(\"~/src/kalle.beam\", \".erl\").\n\"kalle.beam\"\n10> filename:basename(\"~/src/kalle.old.erl\", \".erl\").\n\"kalle.old\"\n11> filename:rootname(filename:basename(\"~/src/kalle.erl\")).\n\"kalle\"\n12> filename:rootname(filename:basename(\"~/src/kalle.beam\")).\n\"kalle\"\n```","title":"filename.basename/2","ref":"filename.html#basename/2"},{"type":"function","doc":"Returns the directory part of `Filename`.\n\n_Examples:_\n\n```erlang\n13> filename:dirname(\"/usr/src/kalle.erl\").\n\"/usr/src\"\n14> filename:dirname(\"kalle.erl\").\n\".\"\n```\n\n```erlang\n5> filename:dirname(\"\\\\usr\\\\src/kalle.erl\"). % Windows\n\"/usr/src\"\n```","title":"filename.dirname/1","ref":"filename.html#dirname/1"},{"type":"function","doc":"Returns the file extension of `Filename`, including the period. Returns an empty\nstring if no extension exists.\n\n_Examples:_\n\n```erlang\n15> filename:extension(\"foo.erl\").\n\".erl\"\n16> filename:extension(\"beam.src/kalle\").\n[]\n```","title":"filename.extension/1","ref":"filename.html#extension/1"},{"type":"function","doc":"Converts a possibly deep list filename consisting of characters and atoms into\nthe corresponding flat string filename.","title":"filename.flatten/1","ref":"filename.html#flatten/1"},{"type":"function","doc":"Joins a list of filename `Components` with directory separators. If one of the\nelements of `Components` includes an absolute path, such as `\"/xxx\"`, the\npreceding elements, if any, are removed from the result.\n\nThe result is \"normalized\":\n\n- Redundant directory separators are removed.\n- In Windows, all directory separators are forward slashes and the drive letter\n is in lower case.\n\n_Examples:_\n\n```erlang\n17> filename:join([\"/usr\", \"local\", \"bin\"]).\n\"/usr/local/bin\"\n18> filename:join([\"a/b///c/\"]).\n\"a/b/c\"\n```\n\n```erlang\n6> filename:join([\"B:a\\\\b///c/\"]). % Windows\n\"b:a/b/c\"\n```","title":"filename.join/1","ref":"filename.html#join/1"},{"type":"function","doc":"Joins two filename components with directory separators. Equivalent to\n[`join([Name1, Name2])`](`join/1`).","title":"filename.join/2","ref":"filename.html#join/2"},{"type":"function","doc":"Converts `Path` to a form accepted by the command shell and native applications\non the current platform. On Windows, forward slashes are converted to backward\nslashes. On all platforms, the name is normalized as done by `join/1`.\n\n_Examples:_\n\n```erlang\n19> filename:nativename(\"/usr/local/bin/\"). % Unix\n\"/usr/local/bin\"\n```\n\n```erlang\n7> filename:nativename(\"/usr/local/bin/\"). % Windows\n\"\\\\usr\\\\local\\\\bin\"\n```","title":"filename.nativename/1","ref":"filename.html#nativename/1"},{"type":"function","doc":"Returns the path type, which is one of the following:\n\n- **`absolute`** - The path name refers to a specific file on a specific volume.\n\n Unix example: `/usr/local/bin`\n\n Windows example: `D:/usr/local/bin`\n\n- **`relative`** - The path name is relative to the current working directory on\n the current volume.\n\n Example: `foo/bar, ../src`\n\n- **`volumerelative`** - The path name is relative to the current working\n directory on a specified volume, or it is a specific file on the current\n working volume.\n\n Windows example: `D:bar.erl, /bar/foo.erl`","title":"filename.pathtype/1","ref":"filename.html#pathtype/1"},{"type":"function","doc":"Removes the filename extension.\n\n_Examples:_\n\n```erlang\n1> filename:rootname(\"/beam.src/kalle\").\n\"/beam.src/kalle\"\n2> filename:rootname(\"/beam.src/foo.erl\").\n\"/beam.src/foo\"\n```","title":"filename.rootname/1","ref":"filename.html#rootname/1"},{"type":"function","doc":"Removes the filename extension `Ext` from `Filename`.\n\n_Examples:_\n\n```erlang\n1> filename:rootname(\"/beam.src/foo.erl\", \".erl\").\n\"/beam.src/foo\"\n2> filename:rootname(\"/beam.src/foo.beam\", \".erl\").\n\"/beam.src/foo.beam\"\n```","title":"filename.rootname/2","ref":"filename.html#rootname/2"},{"type":"function","doc":"Returns a list whose elements are the path components of `Filename`.\n\n_Examples:_\n\n```erlang\n24> filename:split(\"/usr/local/bin\").\n[\"/\",\"usr\",\"local\",\"bin\"]\n25> filename:split(\"foo/bar\").\n[\"foo\",\"bar\"]\n26> filename:split(\"a:\\\\msdev\\\\include\").\n[\"a:/\",\"msdev\",\"include\"]\n```","title":"filename.split/1","ref":"filename.html#split/1"},{"type":"type","doc":"","title":"filename.basedir_opts/0","ref":"filename.html#t:basedir_opts/0"},{"type":"type","doc":"","title":"filename.basedir_path_type/0","ref":"filename.html#t:basedir_path_type/0"},{"type":"type","doc":"","title":"filename.basedir_paths_type/0","ref":"filename.html#t:basedir_paths_type/0"},{"type":"module","doc":"Standard I/O server interface functions.\n\nThis module provides an interface to standard Erlang I/O servers. The output\nfunctions all return `ok` if they are successful, or exit if they are not.\n\nAll functions in this module have an optional parameter\n[`IoDevice`](`t:device/0`). If included, it must be the pid of a process that\nhandles the I/O protocols. Normally, it is an [`IoDevice`](`t:device/0`) returned by\n`file:open/2`. If no [`IoDevice`](`t:device/0`) is given,\n[`standard_io`](`t:standard_io/0`) is used.\n\nFor a description of the I/O protocols, see section\n[The Erlang I/O Protocol](io_protocol.md) in the User's Guide.\n\n> #### Warning {: .warning }\n>\n> The data supplied to function `put_chars/2` is to be in\n> the `t:unicode:chardata/0` format. This means that programs supplying binaries\n> to this function must convert them to UTF-8 before trying to output the data\n> on an I/O device.\n>\n> If an I/O device is set in binary mode, functions\n> [`get_chars/2,3`](`get_chars/2`) and [`get_line/1,2`](`get_line/1`) can return\n> binaries instead of lists. The binaries are encoded in UTF-8.\n>\n> To work with binaries in ISO Latin-1 encoding, use the `m:file` module\n> instead.\n>\n> For conversion functions between character encodings, see the `m:unicode`\n> module.","title":"io","ref":"io.html"},{"type":"module","doc":"The `ErrorInfo` mentioned in this module is the standard `ErrorInfo` structure\nthat is returned from all I/O modules. It has the following format:\n\n```erlang\n{ErrorLocation, Module, ErrorDescriptor}\n```\n\nA string that describes the error is obtained with the following call:\n\n```erlang\nModule:format_error(ErrorDescriptor)\n```","title":"Error Information - io","ref":"io.html#module-error-information"},{"type":"function","doc":"","title":"io.columns/0","ref":"io.html#columns/0"},{"type":"function","doc":"Retrieves the number of columns of the [`IoDevice`](`t:device/0`) (that is, the width of a\nterminal).\n\nThe function succeeds for terminal devices and returns `{error, enotsup}` for\nall other I/O devices.","title":"io.columns/1","ref":"io.html#columns/1"},{"type":"function","doc":"","title":"io.format/1","ref":"io.html#format/1"},{"type":"function","doc":"","title":"io.format/2","ref":"io.html#format/2"},{"type":"function","doc":"","title":"io.format/3","ref":"io.html#format/3"},{"type":"function","doc":"","title":"io.fread/2","ref":"io.html#fread/2"},{"type":"function","doc":"Reads characters from [`IoDevice`](`t:device/0`), prompting it with `Prompt`. Interprets the\ncharacters in accordance with `Format`.\n\n`Format` can contain the following:\n\n- Whitespace characters (_Space_, _Tab_, and _Newline_) that cause input to be\n read to the next non-whitespace character.\n- Ordinary characters that must match the next input character.\n- Control sequences, which have the general format `~*FMC`, where:\n\n - Character `*` is an optional return suppression character. It provides a\n method to specify a field that is to be omitted.\n - `F` is the `field width` of the input field.\n - `M` is an optional translation modifier (of which `t` is the only supported,\n meaning Unicode translation).\n - `C` determines the type of control sequence.\n\n Unless otherwise specified, leading whitespace is ignored for all control\n sequences. An input field cannot be more than one line wide.\n\n _Available control sequences:_\n\n - **`~`** - A single `~` is expected in the input.\n\n - **`d`** - A decimal integer is expected.\n\n - **`u`** - An unsigned integer in base 2-36 is expected. The field width\n parameter is used to specify base. Leading whitespace characters are not\n skipped.\n\n - **`-`** - An optional sign character is expected. A sign character `-` gives\n return value `-1`. Sign character `+` or none gives `1`. The field width\n parameter is ignored. Leading whitespace characters are not skipped.\n\n - **`#`** - An integer in base 2-36 with Erlang-style base prefix (for\n example, `\"16#ffff\"`) is expected.\n\n - **`f`** - A floating point number is expected. It must follow the Erlang\n floating point number syntax.\n\n - **`s`** - A string of non-whitespace characters is read. If a field width\n has been specified, this number of characters are read and all trailing\n whitespace characters are stripped. An Erlang string (list of characters) is\n returned.\n\n If Unicode translation is in effect (`~ts`), characters > 255 are accepted,\n otherwise not. With the translation modifier, the returned list can as a\n consequence also contain integers > 255:\n\n ```erlang\n 1> io:fread(\"Prompt> \",\"~s\").\n Prompt> \n {error,{fread,string}}\n 2> io:fread(\"Prompt> \",\"~ts\").\n Prompt> \n {ok,[[1091,1085,1080,1094,1086,1076,1077]]}\n ```\n\n - **`a`** - Similar to `s`, but the resulting string is converted into an\n atom.\n\n - **`c`** - The number of characters equal to the field width are read\n (default is 1) and returned as an Erlang string. However, leading and\n trailing whitespace characters are not omitted as they are with `s`. All\n characters are returned.\n\n The Unicode translation modifier works as with `s`:\n\n ```erlang\n 1> io:fread(\"Prompt> \",\"~c\").\n Prompt> \n {error,{fread,string}}\n 2> io:fread(\"Prompt> \",\"~tc\").\n Prompt> \n {ok,[[1091]]}\n ```\n\n - **`l`** - Returns the number of characters that have been scanned up to that\n point, including whitespace characters.\n\n The function returns:\n\n - **`{ok, Terms}`** - The read was successful and `Terms` is the list of\n successfully matched and read items.\n\n - **`eof`** - End of file was encountered.\n\n - **`{error, FreadError}`** - The reading failed and `FreadError` gives a hint\n about the error.\n\n - **`{error, ErrorDescription}`** - The read operation failed and parameter\n `ErrorDescription` gives a hint about the error.\n\n_Examples:_\n\n```erlang\n20> io:fread('enter>', \"~f~f~f\").\nenter>1.9 35.5e3 15.0\n{ok,[1.9,3.55e4,15.0]}\n21> io:fread('enter>', \"~10f~d\").\nenter> 5.67899\n{ok,[5.678,99]}\n22> io:fread('enter>', \":~10s:~10c:\").\nenter>: alan : joe :\n{ok, [\"alan\", \" joe \"]}\n```","title":"io.fread/3","ref":"io.html#fread/3"},{"type":"function","doc":"","title":"io.fwrite/1","ref":"io.html#fwrite/1"},{"type":"function","doc":"","title":"io.fwrite/2","ref":"io.html#fwrite/2"},{"type":"function","doc":"Writes the items in `Data` on the [`IoDevice`](`t:device/0`) in accordance with `Format`.\n\n`Format` contains plain characters that are copied to\nthe output device, and control sequences for formatting, see below. If `Format`\nis an atom or a binary, it is first converted to a list with the aid of\n[`atom_to_list/1`](`atom_to_list/1`) or\n[`binary_to_list/1`](`binary_to_list/1`). Example:\n\n```erlang\n1> io:fwrite(\"Hello world!~n\", []).\nHello world!\nok\n```\n\nThe general format of a control sequence is `~F.P.PadModC`.\n\nThe character `C` determines the type of control sequence to be used. It is the\nonly required field. All of `F`, `P`, `Pad`, and `Mod` are optional. For\nexample, to use a `#` for `Pad` but use the default values for `F` and `P`, you\ncan write `~..#C`.\n\n- `F` is the `field width` of the printed argument. A negative value means that\n the argument is left-justified within the field, otherwise right-justified. If\n no field width is specified, the required print width is used. If the field\n width specified is too small, the whole field is filled with `*` characters.\n- `P` is the `precision` of the printed argument. A default value is used if no\n precision is specified. The interpretation of precision depends on the control\n sequences. Unless otherwise specified, argument `within` is used to determine\n print width.\n- `Pad` is the padding character. This is the character used to pad the printed\n representation of the argument so that it conforms to the specified field\n width and precision. Only one padding character can be specified and, whenever\n applicable, it is used for both the field width and precision. The default\n padding character is `' '` (space).\n- `Mod` is the control sequence modifier. This is one or more characters that\n change the interpretation of `Data`.\n\n The current modifiers are:\n\n - **`t`** - For Unicode translation.\n\n - **`l`** - For stopping `p` and `P` from detecting printable characters.\n\n - **`k`** - For use with `p`, `P`, `w`, and `W` to format maps in map-key\n `ordered` order (see `t:maps:iterator_order/0`).\n\n - **`K`** - Similar to `k`, for formatting maps in map-key order, but takes an\n extra argument that specifies the `t:maps:iterator_order/0`.\n\n For example:\n\n ```erlang\n > M = #{ a => 1, b => 2 }.\n #{a => 1,b => 2}\n > io:format(\"~Kp~n\", [reversed, M]).\n #{b => 2,a => 1}\n ok\n ```\n\nIf `F`, `P`, or `Pad` is a `*` character, the next argument in `Data` is used as\nthe value. For example:\n\n```erlang\n1> io:fwrite(\"~*.*.0f~n\",[9, 5, 3.14159265]).\n003.14159\nok\n```\n\nTo use a literal `*` character as `Pad`, it must be passed as an argument:\n\n```erlang\n2> io:fwrite(\"~*.*.*f~n\",[9, 5, $*, 3.14159265]).\n**3.14159\nok\n```\n\n_Available control sequences:_\n\n- **`~`** - Character `~` is written.\n\n- **`c`** - The argument is a number that is interpreted as an ASCII code. The\n precision is the number of times the character is printed and defaults to the\n field width, which in turn defaults to 1. Example:\n\n ```erlang\n 1> io:fwrite(\"|~10.5c|~-10.5c|~5c|~n\", [$a, $b, $c]).\n | aaaaa|bbbbb |ccccc|\n ok\n ```\n\n If the Unicode translation modifier (`t`) is in effect, the integer argument\n can be any number representing a valid Unicode codepoint, otherwise it is to\n be an integer less than or equal to 255, otherwise it is masked with 16#FF:\n\n ```erlang\n 2> io:fwrite(\"~tc~n\",[1024]).\n \\x{400}\n ok\n 3> io:fwrite(\"~c~n\",[1024]).\n ^@\n ok\n ```\n\n- **`f`** - The argument is a float that is written as `[-]ddd.ddd`, where the\n precision is the number of digits after the decimal point. The default\n precision is 6 and it cannot be < 1.\n\n- **`e`** - The argument is a float that is written as `[-]d.ddde+-ddd`, where\n the precision is the number of digits written. The default precision is 6 and\n it cannot be < 2.\n\n- **`g`** - The argument is a float that is written as `f`, if it is >= 0.1 and\n < 10000.0. Otherwise, it is written in the `e` format. The precision is the\n number of significant digits. It defaults to 6 and is not to be < 2. If the\n absolute value of the float does not allow it to be written in the `f` format\n with the desired number of significant digits, it is also written in the `e`\n format.\n\n- **`s`** - Prints the argument with the string syntax. The argument is, if no\n Unicode translation modifier is present, an `t:iolist/0`, a `t:binary/0`, or\n an `t:atom/0`. If the Unicode translation modifier (`t`) is in effect, the\n argument is [`unicode:chardata()`](`t:unicode:chardata/0`), meaning that\n binaries are in UTF-8. The characters are printed without quotes. The string\n is first truncated by the specified precision and then padded and justified to\n the specified field width. The default precision is the field width.\n\n This format can be used for printing any object and truncating the output so\n it fits a specified field:\n\n ```erlang\n 1> io:fwrite(\"|~10w|~n\", [{hey, hey, hey}]).\n |**********|\n ok\n 2> io:fwrite(\"|~10s|~n\", [io_lib:write({hey, hey, hey})]).\n |{hey,hey,h|\n 3> io:fwrite(\"|~-10.8s|~n\", [io_lib:write({hey, hey, hey})]).\n |{hey,hey |\n ok\n ```\n\n A list with integers > 255 is considered an error if the Unicode translation\n modifier is not specified:\n\n ```erlang\n 4> io:fwrite(\"~ts~n\",[[1024]]).\n \\x{400}\n ok\n 5> io:fwrite(\"~s~n\",[[1024]]).\n ** exception error: bad argument\n in function io:format/3\n called as io:format(<0.53.0>,\"~s~n\",[[1024]])\n ```\n\n- **`w`** - Writes data with the standard syntax. This is used to output Erlang\n terms. Atoms are printed within quotes if they contain embedded non-printable\n characters. Atom characters > 255 are escaped unless the Unicode translation\n modifier (`t`) is used. Floats are printed accurately as the shortest,\n correctly rounded string.\n\n- **`p`**{: #tilde_p } - Writes the data with standard syntax in the same way as `~w`, but\n breaks terms whose printed representation is longer than one line into many\n lines and indents each line sensibly. Left-justification is not supported. It\n also tries to detect flat lists of printable characters and output these as\n strings. For example:\n\n ```erlang\n 1> T = [{attributes,[[{id,age,1.50000},{mode,explicit},\n {typename,\"INTEGER\"}], [{id,cho},{mode,explicit},{typename,'Cho'}]]},\n {typename,'Person'},{tag,{'PRIVATE',3}},{mode,implicit}].\n ...\n 2> io:fwrite(\"~w~n\", [T]).\n [{attributes,[[{id,age,1.5},{mode,explicit},{typename,\n [73,78,84,69,71,69,82]}],[{id,cho},{mode,explicit},{typena\n me,'Cho'}]]},{typename,'Person'},{tag,{'PRIVATE',3}},{mode\n ,implicit}]\n ok\n 3> io:fwrite(\"~62p~n\", [T]).\n [{attributes,[[{id,age,1.5},\n {mode,explicit},\n {typename,\"INTEGER\"}],\n [{id,cho},{mode,explicit},{typename,'Cho'}]]},\n {typename,'Person'},\n {tag,{'PRIVATE',3}},\n {mode,implicit}]\n ok\n ```\n\n The field width specifies the maximum line length. It defaults to 80. The\n precision specifies the initial indentation of the term. It defaults to the\n number of characters printed on this line in the _same_ call to `write/1` or\n [`format/1,2,3`](`format/1`). For example, using `T` above:\n\n ```erlang\n 4> io:fwrite(\"Here T = ~62p~n\", [T]).\n Here T = [{attributes,[[{id,age,1.5},\n {mode,explicit},\n {typename,\"INTEGER\"}],\n [{id,cho},\n {mode,explicit},\n {typename,'Cho'}]]},\n {typename,'Person'},\n {tag,{'PRIVATE',3}},\n {mode,implicit}]\n ok\n ```\n\n As from Erlang/OTP 21.0, a field width of value `0` can be used for specifying\n that a line is infinitely long, which means that no line breaks are inserted.\n For example:\n\n ```erlang\n 5> io:fwrite(\"~0p~n\", [lists:seq(1, 30)]).\n [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30]\n ok\n ```\n\n When the modifier `l` is specified, no detection of printable character lists\n takes place, for example:\n\n ```erlang\n 6> S = [{a,\"a\"}, {b, \"b\"}],\n io:fwrite(\"~15p~n\", [S]).\n [{a,\"a\"},\n {b,\"b\"}]\n ok\n 7> io:fwrite(\"~15lp~n\", [S]).\n [{a,[97]},\n {b,[98]}]\n ok\n ```\n\n The Unicode translation modifier `t` specifies how to treat characters outside\n the Latin-1 range of codepoints, in atoms, strings, and binaries. For example,\n printing an atom containing a character > 255:\n\n ```erlang\n 8> io:fwrite(\"~p~n\",[list_to_atom([1024])]).\n '\\x{400}'\n ok\n 9> io:fwrite(\"~tp~n\",[list_to_atom([1024])]).\n 'Ѐ'\n ok\n ```\n\n By default, Erlang only detects lists of characters in the Latin-1 range as\n strings, but the `+pc unicode` flag can be used to change this (see\n `printable_range/0` for details). For example:\n\n ```erlang\n 10> io:fwrite(\"~p~n\",[[214]]).\n \"Ö\"\n ok\n 11> io:fwrite(\"~p~n\",[[1024]]).\n [1024]\n ok\n 12> io:fwrite(\"~tp~n\",[[1024]]).\n [1024]\n ok\n ```\n\n but if Erlang was started with `+pc unicode`:\n\n ```erlang\n 13> io:fwrite(\"~p~n\",[[1024]]).\n [1024]\n ok\n 14> io:fwrite(\"~tp~n\",[[1024]]).\n \"Ѐ\"\n ok\n ```\n\n Similarly, binaries that look like UTF-8 encoded strings are output with the\n binary string syntax if the `t` modifier is specified:\n\n ```erlang\n 15> io:fwrite(\"~p~n\", [<<208,128>>]).\n <<208,128>>\n ok\n 16> io:fwrite(\"~tp~n\", [<<208,128>>]).\n <<\"Ѐ\"/utf8>>\n ok\n 17> io:fwrite(\"~tp~n\", [<<128,128>>]).\n <<128,128>>\n ok\n ```\n\n- **`W`** - Writes data in the same way as `~w`, but takes an extra argument\n that is the maximum depth to which terms are printed. Anything below this\n depth is replaced with `...`. For example, using `T` above:\n\n ```erlang\n 8> io:fwrite(\"~W~n\", [T,9]).\n [{attributes,[[{id,age,1.5},{mode,explicit},{typename,...}],\n [{id,cho},{mode,...},{...}]]},{typename,'Person'},\n {tag,{'PRIVATE',3}},{mode,implicit}]\n ok\n ```\n\n If the maximum depth is reached, it cannot be read in the resultant output.\n Also, the `,...` form in a tuple denotes that there are more elements in the\n tuple but these are below the print depth.\n\n- **`P`** - Writes data in the same way as `~p`, but takes an extra argument\n that is the maximum depth to which terms are printed. Anything below this\n depth is replaced with `...`, for example:\n\n ```erlang\n 9> io:fwrite(\"~62P~n\", [T,9]).\n [{attributes,[[{id,age,1.5},{mode,explicit},{typename,...}],\n [{id,cho},{mode,...},{...}]]},\n {typename,'Person'},\n {tag,{'PRIVATE',3}},\n {mode,implicit}]\n ok\n ```\n\n- **`B`** - Writes an integer in base 2-36, the default base is 10. A leading\n dash is printed for negative integers.\n\n The precision field selects base, for example:\n\n ```erlang\n 1> io:fwrite(\"~.16B~n\", [31]).\n 1F\n ok\n 2> io:fwrite(\"~.2B~n\", [-19]).\n -10011\n ok\n 3> io:fwrite(\"~.36B~n\", [5*36+35]).\n 5Z\n ok\n ```\n\n- **`X`** - Like `B`, but takes an extra argument that is a prefix to insert\n before the number, but after the leading dash, if any.\n\n The prefix can be a possibly deep list of characters or an atom. Example:\n\n ```erlang\n 1> io:fwrite(\"~X~n\", [31,\"10#\"]).\n 10#31\n ok\n 2> io:fwrite(\"~.16X~n\", [-31,\"0x\"]).\n -0x1F\n ok\n ```\n\n- **`#`** - Like `B`, but prints the number with an Erlang style `#`\\-separated\n base prefix. Example:\n\n ```erlang\n 1> io:fwrite(\"~.10#~n\", [31]).\n 10#31\n ok\n 2> io:fwrite(\"~.16#~n\", [-31]).\n -16#1F\n ok\n ```\n\n- **`b`** - Like `B`, but prints lowercase letters.\n\n- **`x`** - Like `X`, but prints lowercase letters.\n\n- **`+`** - Like `#`, but prints lowercase letters.\n\n- **`n`** - Writes a new line.\n\n- **`i`** - Ignores the next term.\n\nThe function returns:\n\n- **`ok`** - The formatting succeeded.\n\nIf an error occurs, there is no output. Example:\n\n```erlang\n1> io:fwrite(\"~s ~w ~i ~w ~c ~n\",['abc def', 'abc def', {foo, 1},{foo, 1}, 65]).\nabc def 'abc def' {foo,1} A\nok\n2> io:fwrite(\"~s\", [65]).\n** exception error: bad argument\n in function io:format/3\n called as io:format(<0.53.0>,\"~s\",\"A\")\n```\n\nIn this example, an attempt was made to output the single character 65 with the\naid of the string formatting directive `\"~s\"`.","title":"io.fwrite/3","ref":"io.html#fwrite/3"},{"type":"function","doc":"","title":"io.get_chars/2","ref":"io.html#get_chars/2"},{"type":"function","doc":"Reads `Count` characters from [`IoDevice`](`t:device/0`), prompting it with `Prompt`.\n\nThe function returns:\n\n- **`Data`** - The input characters. If the I/O device supports Unicode, the\n data can represent codepoints > 255 (the `latin1` range). If the I/O server is\n set to deliver binaries, they are encoded in UTF-8 (regardless of whether the\n I/O device supports Unicode). If you want the data to be returned as a latin1\n encoded binary you should use `file:read/2` instead.\n\n- **`eof`** - End of file was encountered.\n\n- **`{error, ErrorDescription}`** - Other (rare) error condition, such as\n `{error, estale}` if reading from an NFS file system.","title":"io.get_chars/3","ref":"io.html#get_chars/3"},{"type":"function","doc":"","title":"io.get_line/1","ref":"io.html#get_line/1"},{"type":"function","doc":"Reads a line from [`IoDevice`](`t:device/0`), prompting it with `Prompt`.\n\nThe function returns:\n\n- **`Data`** - The characters in the line terminated by a line feed (or end of\n file). If the I/O device supports Unicode, the data can represent codepoints >\n 255 (the `latin1` range). If the I/O server is set to deliver binaries, they\n are encoded in UTF-8 (regardless of if the I/O device supports Unicode). If\n you want the data to be returned as a latin1 encoded binary you should use\n `file:read_line/1` instead.\n\n- **`eof`** - End of file was encountered.\n\n- **`{error, ErrorDescription}`** - Other (rare) error condition, such as\n `{error, estale}` if reading from an NFS file system.","title":"io.get_line/2","ref":"io.html#get_line/2"},{"type":"function","doc":"","title":"io.getopts/0","ref":"io.html#getopts/0"},{"type":"function","doc":"Requests all available options and their current values for a [`IoDevice`](`t:device/0`).\n\nFor example:\n\n```erlang\n1> {ok,F} = file:open(\"/dev/null\",[read]).\n{ok,<0.42.0>}\n2> io:getopts(F).\n[{binary,false},{encoding,latin1}]\n```\n\nHere the file I/O server returns all available options for a file, which are the\nexpected ones, `encoding` and `binary`. However, the standard shell has some\nmore options:\n\n```erlang\n3> io:getopts().\n[{expand_fun,#Fun },\n {echo,true},\n {binary,false},\n {encoding,unicode},\n {terminal,true},\n {stdout,true},\n {stderr,true},\n {stdin,true}]\n```\n\nThis example is, as can be seen, run in an environment where the terminal\nsupports Unicode input and output.\n\nThe `stdin`, `stdout` and `stderr` options are read only and indicates\nwhether the stream is a terminal or not. When it is a terminal, most systems that\nErlang runs on allows the use of [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code)\nto control what the terminal inputs or outputs.\n\n`terminal` is an alias for `stdout`.\n\nSee `setopts/2` for a description of the other options.","title":"io.getopts/1","ref":"io.html#getopts/1"},{"type":"function","doc":"","title":"io.nl/0","ref":"io.html#nl/0"},{"type":"function","doc":"Writes new line to the standard output (`IoDevice`).","title":"io.nl/1","ref":"io.html#nl/1"},{"type":"function","doc":"","title":"io.parse_erl_exprs/1","ref":"io.html#parse_erl_exprs/1"},{"type":"function","doc":"","title":"io.parse_erl_exprs/2","ref":"io.html#parse_erl_exprs/2"},{"type":"function","doc":"","title":"io.parse_erl_exprs/3","ref":"io.html#parse_erl_exprs/3"},{"type":"function","doc":"Reads data from [`IoDevice`](`t:device/0`), prompting it with `Prompt`.\n\nStarts reading at location `StartLocation`. Argument `Options` is passed\non as argument `Options` of function `erl_scan:tokens/4`. The data is tokenized\nand parsed as if it was a sequence of Erlang expressions until a final dot (`.`)\nis reached.\n\nThe function returns:\n\n- **`{ok, ExprList, EndLocation}`** - The parsing was successful.\n\n- **`{eof, EndLocation}`** - End of file was encountered by the tokenizer.\n\n- **`eof`** - End of file was encountered by the I/O server.\n\n- **`{error, ErrorInfo, ErrorLocation}`** - An error occurred while tokenizing\n or parsing.\n\n- **`{error, ErrorDescription}`** - Other (rare) error condition, such as\n `{error, estale}` if reading from an NFS file system.\n\nExample:\n\n```erlang\n25> io:parse_erl_exprs('enter>').\nenter>abc(), \"hey\".\n{ok, [{call,1,{atom,1,abc},[]},{string,1,\"hey\"}],2}\n26> io:parse_erl_exprs('enter>').\nenter>abc(\"hey\".\n{error,{1,erl_parse,[\"syntax error before: \",[\"'.'\"]]},2}\n```","title":"io.parse_erl_exprs/4","ref":"io.html#parse_erl_exprs/4"},{"type":"function","doc":"","title":"io.parse_erl_form/1","ref":"io.html#parse_erl_form/1"},{"type":"function","doc":"","title":"io.parse_erl_form/2","ref":"io.html#parse_erl_form/2"},{"type":"function","doc":"","title":"io.parse_erl_form/3","ref":"io.html#parse_erl_form/3"},{"type":"function","doc":"Reads data from [`IoDevice`](`t:device/0`), prompting it with `Prompt`.\n\nStarts reading at location `StartLocation`. Argument `Options` is passed\non as argument `Options` of function `erl_scan:tokens/4`. The data is tokenized\nand parsed as if it was an Erlang form (one of the valid Erlang expressions in\nan Erlang source file) until a final dot (`.`) is reached.\n\nThe function returns:\n\n- **`{ok, AbsForm, EndLocation}`** - The parsing was successful.\n\n- **`{eof, EndLocation}`** - End of file was encountered by the tokenizer.\n\n- **`eof`** - End of file was encountered by the I/O server.\n\n- **`{error, ErrorInfo, ErrorLocation}`** - An error occurred while tokenizing\n or parsing.\n\n- **`{error, ErrorDescription}`** - Other (rare) error condition, such as\n `{error, estale}` if reading from an NFS file system.","title":"io.parse_erl_form/4","ref":"io.html#parse_erl_form/4"},{"type":"function","doc":"Returns the user-requested range of printable Unicode characters.\n\nThe user can request a range of characters that are to be considered printable\nin heuristic detection of strings by the shell and by the formatting functions.\nThis is done by supplying `+pc ` when starting Erlang.\n\nThe only valid values for ` ` are `latin1` and `unicode`. `latin1` means\nthat only code points < 256 (except control characters, and so on) are\nconsidered printable. `unicode` means that all printable characters in all\nUnicode character ranges are considered printable by the I/O functions.\n\nBy default, Erlang is started so that only the `latin1` range of characters\nindicate that a list of integers is a string.\n\nThe simplest way to use the setting is to call `io_lib:printable_list/1`, which\nuses the return value of this function to decide if a list is a string of\nprintable characters.\n\n> #### Note {: .info }\n>\n> In a future release, this function may return more values and ranges. To avoid\n> compatibility problems, it is recommended to use function\n> `io_lib:printable_list/1`.","title":"io.printable_range/0","ref":"io.html#printable_range/0"},{"type":"function","doc":"","title":"io.put_chars/1","ref":"io.html#put_chars/1"},{"type":"function","doc":"Writes the characters of `CharData` to the [`IoDevice`](`t:device/0`).\n\nIf you want to write latin1 encoded bytes to the [`IoDevice`](`t:device/0`) you should use\n`file:write/2` instead.","title":"io.put_chars/2","ref":"io.html#put_chars/2"},{"type":"function","doc":"","title":"io.read/1","ref":"io.html#read/1"},{"type":"function","doc":"Reads a term `Term` from the standard input (`IoDevice`), prompting it with\n`Prompt`.\n\nThe function returns:\n\n- **`{ok, Term}`** - The parsing was successful.\n\n- **`eof`** - End of file was encountered.\n\n- **`{error, ErrorInfo}`** - The parsing failed.\n\n- **`{error, ErrorDescription}`** - Other (rare) error condition, such as\n `{error, estale}` if reading from an NFS file system.","title":"io.read/2","ref":"io.html#read/2"},{"type":"function","doc":"","title":"io.read/3","ref":"io.html#read/3"},{"type":"function","doc":"Reads a term `Term` from [`IoDevice`](`t:device/0`), prompting it with `Prompt`.\n\nReading starts at location `StartLocation`. Argument `Options` is passed on as\nargument `Options` of function `erl_scan:tokens/4`.\n\nThe function returns:\n\n- **`{ok, Term, EndLocation}`** - The parsing was successful.\n\n- **`{eof, EndLocation}`** - End of file was encountered.\n\n- **`{error, ErrorInfo, ErrorLocation}`** - The parsing failed.\n\n- **`{error, ErrorDescription}`** - Other (rare) error condition, such as\n `{error, estale}` if reading from an NFS file system.","title":"io.read/4","ref":"io.html#read/4"},{"type":"function","doc":"","title":"io.rows/0","ref":"io.html#rows/0"},{"type":"function","doc":"Retrieves the number of rows of [`IoDevice`](`t:device/0`) (that is, the height of a terminal).\n\nThe function only succeeds for terminal devices, for all other I/O devices the\nfunction returns `{error, enotsup}`.","title":"io.rows/1","ref":"io.html#rows/1"},{"type":"function","doc":"","title":"io.scan_erl_exprs/1","ref":"io.html#scan_erl_exprs/1"},{"type":"function","doc":"","title":"io.scan_erl_exprs/2","ref":"io.html#scan_erl_exprs/2"},{"type":"function","doc":"","title":"io.scan_erl_exprs/3","ref":"io.html#scan_erl_exprs/3"},{"type":"function","doc":"Reads data from [`IoDevice`](`t:device/0`), prompting it with `Prompt`.\n\nReading starts at location `StartLocation`. Argument `Options` is passed on as\nargument `Options` of function `erl_scan:tokens/4`. The data is tokenized\nas if it were a sequence of Erlang expressions until a final dot (`.`) is\nreached. This token is also returned.\n\nThe function returns:\n\n- **`{ok, Tokens, EndLocation}`** - The tokenization succeeded.\n\n- **`{eof, EndLocation}`** - End of file was encountered by the tokenizer.\n\n- **`eof`** - End of file was encountered by the I/O server.\n\n- **`{error, ErrorInfo, ErrorLocation}`** - An error occurred while tokenizing.\n\n- **`{error, ErrorDescription}`** - Other (rare) error condition, such as\n `{error, estale}` if reading from an NFS file system.\n\n_Example:_\n\n```erlang\n23> io:scan_erl_exprs('enter>').\nenter>abc(), \"hey\".\n{ok,[{atom,1,abc},{'(',1},{')',1},{',',1},{string,1,\"hey\"},{dot,1}],2}\n24> io:scan_erl_exprs('enter>').\nenter>1.0er.\n{error,{1,erl_scan,{illegal,float}},2}\n```","title":"io.scan_erl_exprs/4","ref":"io.html#scan_erl_exprs/4"},{"type":"function","doc":"","title":"io.scan_erl_form/1","ref":"io.html#scan_erl_form/1"},{"type":"function","doc":"","title":"io.scan_erl_form/2","ref":"io.html#scan_erl_form/2"},{"type":"function","doc":"","title":"io.scan_erl_form/3","ref":"io.html#scan_erl_form/3"},{"type":"function","doc":"Reads data from [`IoDevice`](`t:device/0`), prompting it with `Prompt`.\n\nStarts reading at location `StartLocation` (`1`). Argument `Options` is passed\non as argument `Options` of function `erl_scan:tokens/4`. The data is tokenized\nas if it was an Erlang form (one of the valid Erlang expressions in an Erlang\nsource file) until a final dot (`.`) is reached. This last token is also\nreturned.\n\nThe return values are the same as for [`scan_erl_exprs/4`](`scan_erl_exprs/4`).","title":"io.scan_erl_form/4","ref":"io.html#scan_erl_form/4"},{"type":"function","doc":"","title":"io.setopts/1","ref":"io.html#setopts/1"},{"type":"function","doc":"Set options for [`IoDevice`](`t:device/0`). Possible options and values vary\ndepending on the I/O device.\n\nFor a list of supported options and their current values on a specific I/O\ndevice, use function `getopts/1`.\n\nThe options and values supported by the OTP I/O devices are as follows:\n\n- **`binary`, `list`, or `{binary, boolean()}`** - If set in binary mode\n (`binary` or `{binary, true}`), the I/O server sends binary data (encoded in\n UTF-8) as answers to the `get_line`, `get_chars`, and, if possible,\n `get_until` requests (for details, see section\n [The Erlang I/O Protocol](io_protocol.md)) in the User's Guide). The immediate\n effect is that [`get_chars/2,3`](`get_chars/2`) and\n [`get_line/1,2`](`get_line/1`) return UTF-8 binaries instead of lists of\n characters for the affected I/O device.\n\n By default, all I/O devices in OTP are set in `list` mode. However, the I/O\n functions can handle any of these modes and so should other, user-written,\n modules behaving as clients to I/O servers.\n\n This option is supported by the `t:standard_io/0`, `t:user/0` and `t:file:io_server/0`\n I/O servers.\n\n- **`{echo, boolean()}`** - Denotes if the terminal is to echo input. Only\n supported for the standard shell I/O server (`group.erl`)\n\n- **`{expand_fun, expand_fun()}`** - Provides a function for tab-completion\n (expansion) like the Erlang shell. This function is called when the user\n presses the _Tab_ key. The expansion is active when calling line-reading\n functions, such as [`get_line/1,2`](`get_line/1`).\n\n The function is called with the current line, up to the cursor, as a reversed\n string. It is to return a three-tuple: `{yes|no, string(), list()}`. The first\n element gives a beep if `no`, otherwise the expansion is silent; the second is\n a string that will be entered at the cursor position; the third is a list of\n possible expansions. If this list is not empty, it is printed below the\n current input line. The list of possible expansions can be formatted in\n different ways to make more advanced expansion suggestions more readable to\n the user, see `edlin_expand:expand/2` for documentation of that.\n\n Trivial example (beep on anything except empty line, which is expanded to\n `\"quit\"`):\n\n ```erlang\n fun(\"\") -> {yes, \"quit\", []};\n (_) -> {no, \"\", [\"quit\"]} end\n ```\n\n This option is only supported by the standard shell (`group.erl`).\n\n- **`{line_history, true | false}`** - Specifies if `get_line` and `get_until`\n I/O requests should be saved in the `m:shell` history buffer.\n\n This option is only supported by the standard shell (`group.erl`).\n\n- **`{log, none | output | input | all}`** - Tells the I/O server that it should log\n I/O requests. Requests will be logged at [`info` level](`t:logger:level/0`) to the\n `[otp, kernel, io, input | output | ctrl]` domain with the following report:\n\n ```erl\n #{ request := IoRequest, server := pid(), server_name => term() }.\n ```\n\n It is important to note that extra care should be taken so that these log reports are not\n logged to `t:standard_io/0` as that may cause the system to enter an infinite loop.\n\n Example:\n\n ```\n 1> logger:set_primary_config(level, info).\n ok\n 2> logger:add_handler(stdout, logger_std_h, #{ config => #{ file => \"stdout.log\" }}).\n ok\n 3> io:setopts(user, [{log, output}]).\n ok\n 4> io:format(user, \"Hello~n\", []).\n Hello\n ok\n 5> file:read_file(\"stdout.log\").\n {ok,<<\"2024-11-14T09:53:49.275085+01:00 info: <0.89.0> wrote to user, Hello\\n\">>}\n ```\n\n Not all I/O servers support this option. Use `io:getopts/1` to check if it is available.\n\n > #### Note {: .info }\n >\n > The I/O servers in Erlang/OTP will set the [logger domain](`logger_filters:domain/2`)\n > to `[otp, kernel, io, input | output]`. The default `m:logger` handler will not print\n > this domain, so you need to enable it. This can be done by adding a new filter like this:\n >\n > ```erl\n > logger:add_handler_filter(default, io_domain,\n > {fun logger_filters:domain/2, {log,sub,[otp,kernel,io]}}).\n > ```\n\n- **`{encoding, latin1 | unicode}`** - Specifies how characters are input or\n output from or to the I/O device, implying that, for example, a terminal is\n set to handle Unicode input and output or a file is set to handle UTF-8 data\n encoding.\n\n The option _does not_ affect how data is returned from the I/O functions or\n how it is sent in the I/O protocol, it only affects how the I/O device is to\n handle Unicode characters to the \"physical\" device.\n\n The standard shell is set for `unicode` or `latin1` encoding when the system\n is started. The encoding is set with the help of the `LANG` or `LC_CTYPE`\n environment variables on Unix-like system or by other means on other systems.\n So, the user can input Unicode characters and the I/O device is in\n `{encoding, unicode}` mode if the I/O device supports it. The mode can be\n changed, if the assumption of the runtime system is wrong, by setting this\n option.\n\n > #### Note {: .info }\n >\n > Prior to OTP 26.0, when Erlang was started with the `-oldshell` or\n > `-noshell` flags (for example, in an `escript`), the default encoding for\n > [`standard_io`](`t:standard_io/0`) was set to `latin1`, meaning that any\n > characters > codepoint 255 were escaped and that input was expected to be\n > plain 8-bit ISO Latin-1. As of OTP 26.0, [`standard_io`](`t:standard_io/0`)\n > always defaults to `unicode` if its supported, otherwise `latin1`.\n >\n > If you want to send raw bytes on [`standard_io`](`t:standard_io/0`), you now\n > always need to explicitly set the encoding to `latin1`; otherwise, code\n > points 128-255 will be converted to UTF-8. This is best done by setting the\n > kernel configuration parameter\n > [standard_io_encoding](`e:kernel:kernel_app.md#standard_io_encoding`) to\n > `latin1`.\n\n Files can also be set in `{encoding, unicode}`, meaning that data is written\n and read as UTF-8. More encodings are possible for files, see below.\n\n `{encoding, unicode | latin1}` is supported by both the standard shell\n (`group.erl` including `werl` on Windows), the 'oldshell' (`user.erl`), and\n the file I/O servers.\n\n- **`{encoding, utf8 | utf16 | utf32 | {utf16,big} | {utf16,little} | {utf32,big} | {utf32,little}}`** -\n For disk files, the encoding can be set to various UTF variants. This has the\n effect that data is expected to be read as the specified encoding from the\n file, and the data is written in the specified encoding to the disk file.\n\n `{encoding, utf8}` has the same effect as `{encoding, unicode}` on files.\n\n The extended encodings are only supported on disk files (opened by function\n `file:open/2`).","title":"io.setopts/2","ref":"io.html#setopts/2"},{"type":"function","doc":"","title":"io.write/1","ref":"io.html#write/1"},{"type":"function","doc":"Writes term `Term` to [`IoDevice`](`t:device/0`).","title":"io.write/2","ref":"io.html#write/2"},{"type":"type","doc":"An I/O device, either `t:standard_io/0`, `t:standard_error/0`, `t:user/0`, a `t:file:io_server/0`,\na registered name, or any pid handling I/O protocols.","title":"io.device/0","ref":"io.html#t:device/0"},{"type":"type","doc":"","title":"io.encoding/0","ref":"io.html#t:encoding/0"},{"type":"type","doc":"","title":"io.expand_fun/0","ref":"io.html#t:expand_fun/0"},{"type":"type","doc":"","title":"io.format/0","ref":"io.html#t:format/0"},{"type":"type","doc":"","title":"io.getopt/0","ref":"io.html#t:getopt/0"},{"type":"type","doc":"","title":"io.option/0","ref":"io.html#t:option/0"},{"type":"type","doc":"","title":"io.parse_form_ret/0","ref":"io.html#t:parse_form_ret/0"},{"type":"type","doc":"","title":"io.parse_ret/0","ref":"io.html#t:parse_ret/0"},{"type":"type","doc":"","title":"io.prompt/0","ref":"io.html#t:prompt/0"},{"type":"type","doc":"What the I/O server sends when there is no data.","title":"io.server_no_data/0","ref":"io.html#t:server_no_data/0"},{"type":"type","doc":"","title":"io.setopt/0","ref":"io.html#t:setopt/0"},{"type":"type","doc":"The I/O device `standard_error` can be used to direct output to whatever the\ncurrent operating system considers a suitable I/O device for error output. This\ncan be useful when standard output is redirected.\n\nExample on a Unix-like operating system:\n\n```text\n$ erl -noinput -eval 'io:format(standard_error,\"Error: ~s~n\",[\"error 11\"]),'\\\n'init:stop().' > /dev/null\nError: error 11\n```","title":"io.standard_error/0","ref":"io.html#t:standard_error/0"},{"type":"type","doc":"The default standard I/O device assigned to a process. This device is used when\nno `IoDevice` argument is specified in the function calls in this module.\n\nIt is sometimes desirable to use an explicit `IoDevice` argument that\nrefers to the default I/O device. This is the case with functions that can\naccess either a file or the default I/O device. The atom `standard_io` has this\nspecial meaning. The following example illustrates this:\n\n```erlang\n27> io:read('enter>').\nenter>foo.\n{ok,foo}\n28> io:read(standard_io, 'enter>').\nenter>bar.\n{ok,bar}\n```\n\nBy default all I/O sent to `standard_io` will end up in the [`user`](`t:user/0`)\nI/O device of the node that spawned the calling process.\n\n`standard_io` is an alias for [`group_leader/0`](`erlang:group_leader/0`), so in\norder to change where the default input/output requests are sent you can change\nthe group leader of the current process using\n[`group_leader(NewGroupLeader, self())`](`erlang:group_leader/2`).","title":"io.standard_io/0","ref":"io.html#t:standard_io/0"},{"type":"type","doc":"An I/O device that can be used to interact with the node local `stdout` and\n`stdin`. This can be either a terminal, a pipe, a file, or a combination.\n\nUse `getopts/1` to get more information about the I/O device.\n\nSee [The Interactive Shell](unicode_usage.md#the-interactive-shell) and\n[Escripts and non-interactive I/O](unicode_usage.md#escripts-and-non-interactive-i-o)\nin the Using Unicode In Erlang User's Guide for details on how Unicode is\nhandled by `user`.","title":"io.user/0","ref":"io.html#t:user/0"},{"type":"module","doc":"I/O library functions.\n\nThis module contains functions for converting to and from strings (lists of\ncharacters). They are used for implementing the functions in the `m:io` module.\nThere is no guarantee that the character lists returned from some of the\nfunctions are flat, they can be deep lists. Function `lists:flatten/1` can be\nused for flattening deep lists.","title":"io_lib","ref":"io_lib.html"},{"type":"function","doc":"For details, see `scan_format/2`.","title":"io_lib.build_text/1","ref":"io_lib.html#build_text/1"},{"type":"function","doc":"Returns `true` if `Term` is a flat list of characters in the Unicode range,\notherwise `false`.","title":"io_lib.char_list/1","ref":"io_lib.html#char_list/1"},{"type":"function","doc":"Returns `true` if `Term` is a, possibly deep, list of characters in the Unicode\nrange, otherwise `false`.","title":"io_lib.deep_char_list/1","ref":"io_lib.html#deep_char_list/1"},{"type":"function","doc":"Returns `true` if `Term` is a, possibly deep, list of characters in the ISO\nLatin-1 range, otherwise `false`.","title":"io_lib.deep_latin1_char_list/1","ref":"io_lib.html#deep_latin1_char_list/1"},{"type":"function","doc":"","title":"io_lib.format/2","ref":"io_lib.html#format/2"},{"type":"function","doc":"","title":"io_lib.format/3","ref":"io_lib.html#format/3"},{"type":"function","doc":"Tries to read `String` in accordance with the control sequences in `Format`.\n\nFor a detailed description of the available formatting options, see `io:fread/3`.\nIt is assumed that `String` contains whole lines.\n\nThe function returns:\n\n- **`{ok, InputList, LeftOverChars}`** - The string was read. `InputList` is the\n list of successfully matched and read items, and `LeftOverChars` are the input\n characters not used.\n\n- **`{more, RestFormat, Nchars, InputStack}`** - The string was read, but more\n input is needed to complete the original format string. `RestFormat` is the\n remaining format string, `Nchars` is the number of characters scanned, and\n `InputStack` is the reversed list of inputs matched up to that point.\n\n- **`{error, What}`** - The read operation failed and parameter `What` gives a\n hint about the error.\n\n_Example:_\n\n```erlang\n3> io_lib:fread(\"~f~f~f\", \"15.6 17.3e-6 24.5\").\n{ok,[15.6,1.73e-5,24.5],[]}\n```","title":"io_lib.fread/2","ref":"io_lib.html#fread/2"},{"type":"function","doc":"This is the re-entrant formatted reader. The continuation of the first call to\nthe functions must be `[]`.\n\nFor a complete description of how the re-entrant input scheme works,\nsee Armstrong, Virding, Williams: 'Concurrent Programming in\nErlang', Chapter 13.\n\nThe function returns:\n\n- **`{done, Result, LeftOverChars}`** - The input is complete. The result is one\n of the following:\n\n - **`{ok, InputList}`** - The string was read. `InputList` is the list of\n successfully matched and read items, and `LeftOverChars` are the remaining\n characters.\n\n - **`eof`** - End of file was encountered. `LeftOverChars` are the input\n characters not used.\n\n - **`{error, What}`** - An error occurred and parameter `What` gives a hint\n about the error.\n\n- **`{more, Continuation}`** - More data is required to build a term.\n `Continuation` must be passed to [`fread/3`](`fread/3`) when more data becomes\n available.","title":"io_lib.fread/3","ref":"io_lib.html#fread/3"},{"type":"function","doc":"Returns a character list that represents `Data` formatted in accordance with\n`Format`.\n\nFor a detailed description of the available formatting options, see\n[`io:fwrite/1,2,3`](`io:fwrite/1`). If the format string or argument list\ncontains an error, a fault is generated.\n\nIf and only if the Unicode translation modifier is used in the format string\n(that is, `~ts` or `~tc`), the resulting list can contain characters beyond the\nISO Latin-1 character range (that is, numbers > 255). If so, the result is still\nan ordinary Erlang `t:string/0`, and can well be used in any context where\nUnicode data is allowed.","title":"io_lib.fwrite/2","ref":"io_lib.html#fwrite/2"},{"type":"function","doc":"Returns a character list that represents `Data` formatted in accordance with\n`Format` in the same way as `fwrite/2` and `format/2`, but takes an extra\nargument, a list of options.\n\nValid option:\n\n- **`{chars_limit, CharsLimit}`** - A soft limit on the number of characters\n returned. When the number of characters is reached, remaining structures are\n replaced by \"`...`\". `CharsLimit` defaults to -1, which means no limit on the\n number of characters returned.","title":"io_lib.fwrite/3","ref":"io_lib.html#fwrite/3"},{"type":"function","doc":"Returns the indentation if `String` has been printed, starting at `StartIndent`.","title":"io_lib.indentation/2","ref":"io_lib.html#indentation/2"},{"type":"function","doc":"Returns `true` if `Term` is a flat list of characters in the ISO Latin-1 range,\notherwise `false`.","title":"io_lib.latin1_char_list/1","ref":"io_lib.html#latin1_char_list/1"},{"type":"function","doc":"Returns a character list that represents a new line character.","title":"io_lib.nl/0","ref":"io_lib.html#nl/0"},{"type":"function","doc":"","title":"io_lib.print/1","ref":"io_lib.html#print/1"},{"type":"function","doc":"Returns a list of characters that represents `Term`, but breaks representations\nlonger than one line into many lines and indents each line sensibly.\n\nAlso tries to detect and output lists of printable characters as strings.\n\n- `Column` is the starting column; defaults to 1.\n- `LineLength` is the maximum line length; defaults to 80.\n- `Depth` is the maximum print depth; defaults to -1, which means no limitation.","title":"io_lib.print/4","ref":"io_lib.html#print/4"},{"type":"function","doc":"Returns `true` if `Term` is a flat list of printable ISO Latin-1 characters,\notherwise `false`.","title":"io_lib.printable_latin1_list/1","ref":"io_lib.html#printable_latin1_list/1"},{"type":"function","doc":"Returns `true` if `Term` is a flat list of printable characters, otherwise\n`false`.\n\nWhat is a printable character in this case is determined by startup flag `+pc`\nto the Erlang VM; see `io:printable_range/0` and\n[`erl(1)`](`e:erts:erl_cmd.md`).","title":"io_lib.printable_list/1","ref":"io_lib.html#printable_list/1"},{"type":"function","doc":"Returns `true` if `Term` is a flat list of printable Unicode characters,\notherwise `false`.","title":"io_lib.printable_unicode_list/1","ref":"io_lib.html#printable_unicode_list/1"},{"type":"function","doc":"Returns a list corresponding to the specified format string, where control\nsequences have been replaced with corresponding tuples. This list can be passed\nto:\n\n- `build_text/1` to have the same effect as [`format(Format, Args)`](`format/2`)\n- `unscan_format/1` to get the corresponding pair of `Format` and `Args` (with\n every `*` and corresponding argument expanded to numeric values)\n\nA typical use of this function is to replace unbounded-size control sequences\nlike `~w` and `~p` with the depth-limited variants `~W` and `~P` before\nformatting to text in, for example, a logger.","title":"io_lib.scan_format/2","ref":"io_lib.html#scan_format/2"},{"type":"function","doc":"For details, see `scan_format/2`.","title":"io_lib.unscan_format/1","ref":"io_lib.html#unscan_format/1"},{"type":"function","doc":"","title":"io_lib.write/1","ref":"io_lib.html#write/1"},{"type":"function","doc":"Returns a character list that represents `Term`. Option `Depth` controls the\ndepth of the structures written.\n\nWhen the specified depth is reached, everything below this level is replaced by\n\"`...`\".\n\n`Depth` defaults to -1, which means no limitation. Option `CharsLimit` puts a\nsoft limit on the number of characters returned. When the number of characters is\nreached, remaining structures are replaced by \"`...`\". `CharsLimit` defaults to -1,\nwhich means no limit on the number of characters returned.\n\n_Example:_\n\n```erlang\n1> lists:flatten(io_lib:write({1,[2],[3],[4,5],6,7,8,9})).\n\"{1,[2],[3],[4,5],6,7,8,9}\"\n2> lists:flatten(io_lib:write({1,[2],[3],[4,5],6,7,8,9}, 5)).\n\"{1,[2],[3],[...],...}\"\n3> lists:flatten(io_lib:write({[1,2,3],[4,5],6,7,8,9}, [{chars_limit,20}])).\n\"{[1,2|...],[4|...],...}\"\n```","title":"io_lib.write/2","ref":"io_lib.html#write/2"},{"type":"function","doc":"Returns the list of characters needed to print atom `Atom`.","title":"io_lib.write_atom/1","ref":"io_lib.html#write_atom/1"},{"type":"function","doc":"Returns the list of characters needed to print atom `Atom`. Non-Latin-1\ncharacters are escaped.","title":"io_lib.write_atom_as_latin1/1","ref":"io_lib.html#write_atom_as_latin1/1"},{"type":"function","doc":"Returns the list of characters needed to print a character constant in the\nUnicode character set.","title":"io_lib.write_char/1","ref":"io_lib.html#write_char/1"},{"type":"function","doc":"Returns the list of characters needed to print a character constant in the\nUnicode character set. Non-Latin-1 characters are escaped.","title":"io_lib.write_char_as_latin1/1","ref":"io_lib.html#write_char_as_latin1/1"},{"type":"function","doc":"Returns the list of characters needed to print a character constant in the ISO\nLatin-1 character set.","title":"io_lib.write_latin1_char/1","ref":"io_lib.html#write_latin1_char/1"},{"type":"function","doc":"Returns the list of characters needed to print `Latin1String` as a string.","title":"io_lib.write_latin1_string/1","ref":"io_lib.html#write_latin1_string/1"},{"type":"function","doc":"Returns the list of characters needed to print `String` as a string.","title":"io_lib.write_string/1","ref":"io_lib.html#write_string/1"},{"type":"function","doc":"Returns the list of characters needed to print `String` as a string. Non-Latin-1\ncharacters are escaped.","title":"io_lib.write_string_as_latin1/1","ref":"io_lib.html#write_string_as_latin1/1"},{"type":"type","doc":"An possibly deep list containing only `t:char/0`s.","title":"io_lib.chars/0","ref":"io_lib.html#t:chars/0"},{"type":"type","doc":"","title":"io_lib.chars_limit/0","ref":"io_lib.html#t:chars_limit/0"},{"type":"opaque","doc":"A continuation as returned by `fread/3`.","title":"io_lib.continuation/0","ref":"io_lib.html#t:continuation/0"},{"type":"type","doc":"","title":"io_lib.depth/0","ref":"io_lib.html#t:depth/0"},{"type":"type","doc":"A map describing the contents of a format string.\n\n- `control_char` is the type of control sequence: `$P`, `$w`, and so on.\n- `args` is a list of the arguments used by the control sequence, or an empty\n list if the control sequence does not take any arguments.\n- `width` is the field width.\n- `adjust` is the adjustment.\n- `precision` is the precision of the printed argument.\n- `pad_char` is the padding character.\n- `encoding` is set to `true` if translation modifier `t` is present.\n- `strings` is set to `false` if modifier `l` is present.\n- `maps_order` is set to `undefined` by default, `ordered` if modifier `k` is\n present, or `reversed` or `CmpFun` if modifier `K` is present.","title":"io_lib.format_spec/0","ref":"io_lib.html#t:format_spec/0"},{"type":"type","doc":"","title":"io_lib.fread_error/0","ref":"io_lib.html#t:fread_error/0"},{"type":"type","doc":"","title":"io_lib.fread_item/0","ref":"io_lib.html#t:fread_item/0"},{"type":"type","doc":"","title":"io_lib.latin1_string/0","ref":"io_lib.html#t:latin1_string/0"},{"type":"module","doc":"This module contains regular expression matching functions for strings and\nbinaries.\n\nThe [regular expression](`m:re#module-perl-like-regular-expression-syntax`) syntax and\nsemantics resemble that of Perl.\n\nThe matching algorithms of the library are based on the PCRE library, but not\nall of the PCRE library is interfaced and some parts of the library go beyond\nwhat PCRE offers. Currently PCRE version 8.40 (release date 2017-01-11) is used.\nThe sections of the PCRE documentation that are relevant to this module are\nincluded here.\n\n> #### Note {: .info }\n>\n> The Erlang literal syntax for strings uses the `\\\\` (backslash) character as\n> an escape code. You need to escape backslashes in literal strings, both in\n> your code and in the shell, with an extra backslash, that is, `\"\\\\\\\\\"` or\n> `<<\"\\\\\\\\\">>`.\n>\n> Since Erlang/OTP 27 you can use [verbatim sigils](`e:system:data_types.md#sigil`)\n> to write literal strings. The example above would be written as `~S\"\\\"` or `~B\"\\\"`.","title":"re","ref":"re.html"},{"type":"module","doc":"The following sections contain reference material for the regular expressions\nused by this module. The information is based on the PCRE documentation, with\nchanges where this module behaves differently to the PCRE library.","title":"Perl-Like Regular Expression Syntax - re","ref":"re.html#module-perl-like-regular-expression-syntax"},{"type":"module","doc":"The syntax and semantics of the regular expressions supported by PCRE are\ndescribed in detail in the following sections. Perl's regular expressions are\ndescribed in its own documentation, and regular expressions in general are\ncovered in many books, some with copious examples. Jeffrey Friedl's \"Mastering\nRegular Expressions\", published by O'Reilly, covers regular expressions in great\ndetail. This description of the PCRE regular expressions is intended as\nreference material.\n\nThe reference material is divided into the following sections:\n\n- [Special Start-of-Pattern Items](`m:re#sect1`)\n- [Characters and Metacharacters](`m:re#sect2`)\n- [Backslash](`m:re#sect3`)\n- [Circumflex and Dollar](`m:re#sect4`)\n- [Full Stop (Period, Dot) and \\\\N](`m:re#sect5`)\n- [Matching a Single Data Unit](`m:re#sect6`)\n- [Square Brackets and Character Classes](`m:re#sect7`)\n- [Posix Character Classes](`m:re#sect8`)\n- [Vertical Bar](`m:re#sect9`)\n- [Internal Option Setting](`m:re#sect10`)\n- [Subpatterns](`m:re#sect11`)\n- [Duplicate Subpattern Numbers](`m:re#sect12`)\n- [Named Subpatterns](`m:re#sect13`)\n- [Repetition](`m:re#sect14`)\n- [Atomic Grouping and Possessive Quantifiers](`m:re#sect15`)\n- [Back References](`m:re#sect16`)\n- [Assertions](`m:re#sect17`)\n- [Conditional Subpatterns](`m:re#sect18`)\n- [Comments](`m:re#sect19`)\n- [Recursive Patterns](`m:re#sect20`)\n- [Subpatterns as Subroutines](`m:re#sect21`)\n- [Oniguruma Subroutine Syntax](`m:re#sect22`)\n- [Backtracking Control](`m:re#sect23`)\n\n[](){: #sect1 }","title":"PCRE Regular Expression Details - re","ref":"re.html#module-pcre-regular-expression-details"},{"type":"module","doc":"Some options that can be passed to `compile/2` can also be set by special items\nat the start of a pattern. These are not Perl-compatible, but are provided to\nmake these options accessible to pattern writers who are not able to change the\nprogram that processes the pattern. Any number of these items can appear, but\nthey must all be together right at the start of the pattern string, and the\nletters must be in upper case.\n\n_UTF Support_\n\nUnicode support is basically UTF-8 based. To use Unicode characters, you either\ncall `compile/2` or `run/3` with option `unicode`, or the pattern must start\nwith one of these special sequences:\n\n```text\n(*UTF8)\n(*UTF)\n```\n\nBoth options give the same effect, the input string is interpreted as UTF-8.\nNotice that with these instructions, the automatic conversion of lists to UTF-8\nis not performed by the `re` functions. Therefore, using these sequences is not\nrecommended. Add option `unicode` when running `compile/2` instead.\n\nSome applications that allow their users to supply patterns can wish to restrict\nthem to non-UTF data for security reasons. If option `never_utf` is set at\ncompile time, (\\*UTF), and so on, are not allowed, and their appearance causes\nan error.\n\n_Unicode Property Support_\n\nThe following is another special sequence that can appear at the start of a\npattern:\n\n```text\n(*UCP)\n```\n\nThis has the same effect as setting option `ucp`: it causes sequences such as\n`\\d` and `\\w` to use Unicode properties to determine character types, instead of\nrecognizing only characters with codes < 256 through a lookup table.\n\n_Disabling Startup Optimizations_\n\nIf a pattern starts with `(*NO_START_OPT)`, it has the same effect as setting\noption `no_start_optimize` at compile time.\n\n_Newline Conventions_\n\n[](){: #newline_conventions }\n\nPCRE supports five conventions for indicating line breaks in strings: a single\nCR (carriage return) character, a single LF (line feed) character, the\ntwo-character sequence CRLF, any of the three preceding, and any Unicode newline\nsequence.\n\nA newline convention can also be specified by starting a pattern string with one\nof the following five sequences:\n\n- **(\\*CR)** - Carriage return\n\n- **(\\*LF)** - Line feed\n\n- **(\\*CRLF)** - >Carriage return followed by line feed\n\n- **(\\*ANYCRLF)** - Any of the three above\n\n- **(\\*ANY)** - All Unicode newline sequences\n\nThese override the default and the options specified to `compile/2`. For\nexample, the following pattern changes the convention to CR:\n\n```text\n(*CR)a.b\n```\n\nThis pattern matches `a\\nb`, as LF is no longer a newline. If more than one of\nthem is present, the last one is used.\n\nThe newline convention affects where the circumflex and dollar assertions are\ntrue. It also affects the interpretation of the dot metacharacter when `dotall`\nis not set, and the behavior of `\\N`. However, it does not affect what the `\\R`\nescape sequence matches. By default, this is any Unicode newline sequence, for\nPerl compatibility. However, this can be changed; see the description of `\\R` in\nsection [Newline Sequences](`m:re#newline_sequences`). A change of the `\\R`\nsetting can be combined with a change of the newline convention.\n\n_Setting Match and Recursion Limits_\n\nThe caller of `run/3` can set a limit on the number of times the internal\nmatch() function is called and on the maximum depth of recursive calls. These\nfacilities are provided to catch runaway matches that are provoked by patterns\nwith huge matching trees (a typical example is a pattern with nested unlimited\nrepeats) and to avoid running out of system stack by too much recursion. When\none of these limits is reached, `pcre_exec()` gives an error return. The limits\ncan also be set by items at the start of the pattern of the following forms:\n\n```text\n(*LIMIT_MATCH=d)\n(*LIMIT_RECURSION=d)\n```\n\nHere d is any number of decimal digits. However, the value of the setting must\nbe less than the value set by the caller of [`run/3`](`run/3`) for it to have\nany effect. That is, the pattern writer can lower the limit set by the\nprogrammer, but not raise it. If there is more than one setting of one of these\nlimits, the lower value is used.\n\nThe default value for both the limits is 10,000,000 in the Erlang VM. Notice\nthat the recursion limit does not affect the stack depth of the VM, as PCRE for\nErlang is compiled in such a way that the match function never does recursion on\nthe C stack.\n\nNote that `LIMIT_MATCH` and `LIMIT_RECURSION` can only reduce the value of the\nlimits set by the caller, not increase them.\n\n[](){: #sect2 }","title":"Special Start-of-Pattern Items - re","ref":"re.html#module-special-start-of-pattern-items"},{"type":"module","doc":"A regular expression is a pattern that is matched against a subject string from\nleft to right. Most characters stand for themselves in a pattern and match the\ncorresponding characters in the subject. As a trivial example, the following\npattern matches a portion of a subject string that is identical to itself:\n\n```text\nThe quick brown fox\n```\n\nWhen caseless matching is specified (option `caseless`), letters are matched\nindependently of case.\n\nThe power of regular expressions comes from the ability to include alternatives\nand repetitions in the pattern. These are encoded in the pattern by the use of\n_metacharacters_, which do not stand for themselves but instead are interpreted\nin some special way.\n\nTwo sets of metacharacters exist: those that are recognized anywhere in the\npattern except within square brackets, and those that are recognized within\nsquare brackets. Outside square brackets, the metacharacters are as follows:\n\n- **`\\`** - General escape character with many uses\n\n- **`^`** - Assert start of string (or line, in multiline mode)\n\n- **`$`** - Assert end of string (or line, in multiline mode)\n\n- **`.`** - Match any character except newline (by default)\n\n- **`[`** - Start character class definition\n\n- **`|`** - Start of alternative branch\n\n- **`(`** - Start subpattern\n\n- **`)`** - End subpattern\n\n- **`?`** - Extends the meaning of (, also 0 or 1 quantifier, also quantifier\n minimizer\n\n- **`*`** - 0 or more quantifiers\n\n- **`+`** - 1 or more quantifier, also \"possessive quantifier\"\n\n- **`{`** - Start min/max quantifier\n\nPart of a pattern within square brackets is called a \"character class\". The\nfollowing are the only metacharacters in a character class:\n\n- **`\\`** - General escape character\n\n- **`^`** - Negate the class, but only if the first character\n\n- **`-`** - Indicates character range\n\n- **`[`** - Posix character class (only if followed by Posix syntax)\n\n- **`]`** - Terminates the character class\n\nThe following sections describe the use of each metacharacter.\n\n[](){: #sect3 }","title":"Characters and Metacharacters - re","ref":"re.html#module-characters-and-metacharacters"},{"type":"module","doc":"The backslash character has many uses. First, if it is followed by a character\nthat is not a number or a letter, it takes away any special meaning that a\ncharacter can have. This use of backslash as an escape character applies both\ninside and outside character classes.\n\nFor example, if you want to match a \"\\_\" character, you write `\\_` in the pattern.\nThis escaping action applies if the following character would otherwise be\ninterpreted as a metacharacter, so it is always safe to precede a\nnon-alphanumeric with backslash to specify that it stands for itself. In\nparticular, if you want to match a backslash, write `\\\\`.\n\nIn `unicode` mode, only ASCII numbers and letters have any special meaning after\na backslash. All other characters (in particular, those whose code points\nare > 127) are treated as literals.\n\nIf a pattern is compiled with option `extended`, whitespace in the pattern\n(other than in a character class) and characters between a # outside a character\nclass and the next newline are ignored. An escaping backslash can be used to\ninclude a whitespace or # character as part of the pattern.\n\nTo remove the special meaning from a sequence of characters, put them between\n`\\Q` and `\\E`. This is different from Perl in that `$` and `@` are handled as literals\nin `\\Q`...`\\E` sequences in PCRE, while `$` and `@` cause variable interpolation in\nPerl. Notice the following examples:\n\n```text\nPattern PCRE matches Perl matches\n\n\\Qabc$xyz\\E abc$xyz abc followed by the contents of $xyz\n\\Qabc\\$xyz\\E abc\\$xyz abc\\$xyz\n\\Qabc\\E\\$\\Qxyz\\E abc$xyz abc$xyz\n```\n\nThe `\\Q`...`\\E` sequence is recognized both inside and outside character classes.\nAn isolated `\\E` that is not preceded by `\\Q` is ignored. If `\\Q` is not followed\nby `\\E` later in the pattern, the literal interpretation continues to the end of\nthe pattern (that is, `\\E` is assumed at the end). If the isolated `\\Q` is inside\na character class, this causes an error, as the character class is not\nterminated.\n\n_Non-Printing Characters_\n\n[](){: #non_printing_characters }\n\nA second use of backslash provides a way of encoding non-printing characters in\npatterns in a visible manner. There is no restriction on the appearance of\nnon-printing characters, apart from the binary zero that terminates a pattern.\nWhen a pattern is prepared by text editing, it is often easier to use one of the\nfollowing escape sequences than the binary character it represents:\n\n- **`\\a`** - Alarm, that is, the BEL character (hex 07)\n\n- **`\\cx`** - \"Control-x\", where x is any ASCII character\n\n- **`\\e`** - Escape (hex 1B)\n\n- **`\\f`** - Form feed (hex 0C)\n\n- **`\\n`** - Line feed (hex 0A)\n\n- **`\\r`** - Carriage return (hex 0D)\n\n- **`\\t`** - Tab (hex 09)\n\n- **`\\0dd`** - Character with octal code 0dd\n\n- **`\\ddd`** - Character with octal code ddd, or back reference\n\n- **`\\o{ddd..}`** - character with octal code ddd..\n\n- **`\\xhh`** - Character with hex code hh\n\n- **`\\x{hhh..}`** - Character with hex code hhh..\n\n> #### Note {: .info }\n>\n> Note that `\\0dd` is always an octal code, and that `\\8` and `\\9` are the literal\n> characters \"8\" and \"9\".\n\nThe precise effect of `\\cx` on ASCII characters is as follows: if x is a\nlowercase letter, it is converted to upper case. Then bit 6 of the character\n(hex 40) is inverted. Thus `\\cA` to `\\cZ` become hex 01 to hex 1A (A is 41, Z is\n5A), but `\\c{` becomes hex 3B (`{` is 7B), and `\\c`; becomes hex 7B (; is 3B). If\nthe data item (byte or 16-bit value) following `\\c` has a value > 127, a\ncompile-time error occurs. This locks out non-ASCII characters in all modes.\n\nThe `\\c` facility was designed for use with ASCII characters, but with the\nextension to Unicode it is even less useful than it once was.\n\nAfter `\\0` up to two further octal digits are read. If there are fewer than two\ndigits, just those that are present are used. Thus the sequence `\\0\\x\\015`\nspecifies two binary zeros followed by a CR character (code value 13). Make sure\nyou supply two digits after the initial zero if the pattern character that\nfollows is itself an octal digit.\n\nThe escape `\\o` must be followed by a sequence of octal digits, enclosed in\nbraces. An error occurs if this is not the case. This escape is a recent\naddition to Perl; it provides way of specifying character code points as octal\nnumbers greater than 0777, and it also allows octal numbers and back references\nto be unambiguously specified.\n\nFor greater clarity and unambiguity, it is best to avoid following `\\` by a digit\ngreater than zero. Instead, use `\\o{}` or `\\x{}` to specify character numbers,\nand `\\g{}` to specify back references. The following paragraphs describe the\nold, ambiguous syntax.\n\nThe handling of a backslash followed by a digit other than 0 is complicated, and\nPerl has changed in recent releases, causing PCRE also to change. Outside a\ncharacter class, PCRE reads the digit and any following digits as a decimal\nnumber. If the number is < 8, or if there have been at least that many previous\ncapturing left parentheses in the expression, the entire sequence is taken as a\n_back reference_. A description of how this works is provided later, following\nthe discussion of parenthesized subpatterns.\n\nInside a character class, or if the decimal number following `\\` is > 7 and there\nhave not been that many capturing subpatterns, PCRE handles `\\8` and `\\9` as the\nliteral characters \"8\" and \"9\", and otherwise re-reads up to three octal digits\nfollowing the backslash, and using them to generate a data character. Any\nsubsequent digits stand for themselves. For example:\n\n- **`\\040`** - Another way of writing an ASCII space\n\n- **`\\40`** - The same, provided there are < 40 previous capturing subpatterns\n\n- **`\\7`** - Always a back reference\n\n- **`\\11`** - Can be a back reference, or another way of writing a tab\n\n- **`\\011`** - Always a tab\n\n- **`\\0113`** - A tab followed by character \"3\"\n\n- **`\\113`** - Can be a back reference, otherwise the character with octal code\n 113\n\n- **`\\377`** - Can be a back reference, otherwise value 255 (decimal)\n\n- **`\\81`** - Either a back reference, or the two characters \"8\" and \"1\"\n\nNotice that octal values >= 100 that are specified using this syntax must not be\nintroduced by a leading zero, as no more than three octal digits are ever read.\n\nBy default, after `\\x` that is not followed by `{`, from zero to two hexadecimal\ndigits are read (letters can be in upper or lower case). Any number of\nhexadecimal digits may appear between `\\x{` and `}`. If a character other than a\nhexadecimal digit appears between `\\x{` and `}`, or if there is no terminating\n`}`, an error occurs.\n\nCharacters whose value is less than 256 can be defined by either of the two\nsyntaxes for `\\x`. There is no difference in the way they are handled. For\nexample, `\\xdc` is exactly the same as `\\x{dc}`.\n\n_Constraints on character values_\n\nCharacters that are specified using octal or hexadecimal numbers are limited to\ncertain values, as follows:\n\n- **8-bit non-UTF mode** - < 0x100\n\n- **8-bit UTF-8 mode** - < 0x10ffff and a valid codepoint\n\nInvalid Unicode codepoints are the range 0xd800 to 0xdfff (the so-called\n\"surrogate\" codepoints), and 0xffef.\n\n_Escape sequences in character classes_\n\nAll the sequences that define a single character value can be used both inside\nand outside character classes. Also, inside a character class, `\\b` is\ninterpreted as the backspace character (hex 08).\n\n`\\N` is not allowed in a character class. `\\B`, `\\R`, and `\\X` are not special\ninside a character class. Like other unrecognized escape sequences, they are\ntreated as the literal characters \"B\", \"R\", and \"X\". Outside a character class,\nthese sequences have different meanings.\n\n_Unsupported Escape Sequences_\n\nIn Perl, the sequences `\\l`, `\\L`, `\\u`, and `\\U` are recognized by its string\nhandler and used to modify the case of following characters. PCRE does not\nsupport these escape sequences.\n\n_Absolute and Relative Back References_\n\nThe sequence `\\g` followed by an unsigned or a negative number, optionally\nenclosed in braces, is an absolute or relative back reference. A named back\nreference can be coded as `\\g{name}`. Back references are discussed later,\nfollowing the discussion of parenthesized subpatterns.\n\n_Absolute and Relative Subroutine Calls_\n\nFor compatibility with Oniguruma, the non-Perl syntax `\\g` followed by a name or\na number enclosed either in angle brackets or single quotes, is alternative\nsyntax for referencing a subpattern as a \"subroutine\". Details are discussed\nlater. Notice that `\\g{...}` (Perl syntax) and `\\g<...>` (Oniguruma syntax) are\n_not_ synonymous. The former is a back reference and the latter is a subroutine\ncall.\n\n_Generic Character Types_\n\n[](){: #generic_character_types }\n\nAnother use of backslash is for specifying generic character types:\n\n- **`\\d`** - Any decimal digit\n\n- **`\\D`** - Any character that is not a decimal digit\n\n- **`\\h`** - Any horizontal whitespace character\n\n- **`\\H`** - Any character that is not a horizontal whitespace character\n\n- **`\\s`** - Any whitespace character\n\n- **`\\S`** - Any character that is not a whitespace character\n\n- **`\\v`** - Any vertical whitespace character\n\n- **`\\V`** - Any character that is not a vertical whitespace character\n\n- **`\\w`** - Any \"word\" character\n\n- **`\\W`** - Any \"non-word\" character\n\nThere is also the single sequence `\\N`, which matches a non-newline character.\nThis is the same as the \".\" metacharacter when `dotall` is not set. Perl also\nuses `\\N` to match characters by name, but PCRE does not support this.\n\nEach pair of lowercase and uppercase escape sequences partitions the complete\nset of characters into two disjoint sets. Any given character matches one, and\nonly one, of each pair. The sequences can appear both inside and outside\ncharacter classes. They each match one character of the appropriate type. If the\ncurrent matching point is at the end of the subject string, all fail, as there\nis no character to match.\n\nFor compatibility with Perl, `\\s` did not used to match the VT character (code\n11), which made it different from the the POSIX \"space\" class. However, Perl\nadded VT at release 5.18, and PCRE followed suit at release 8.34. The default\n`\\s` characters are now HT (9), LF (10), VT (11), FF (12), CR (13), and space\n(32), which are defined as white space in the \"C\" locale. This list may vary if\nlocale-specific matching is taking place. For example, in some locales the\n\"non-breaking space\" character (`\\xA0`) is recognized as white space, and in\nothers the VT character is not.\n\nA \"word\" character is an underscore or any character that is a letter or a\ndigit. By default, the definition of letters and digits is controlled by the\nPCRE low-valued character tables, in Erlang's case (and without option\n`unicode`), the ISO Latin-1 character set.\n\nBy default, in `unicode` mode, characters with values > 255, that is, all\ncharacters outside the ISO Latin-1 character set, never match `\\d`, `\\s`, or `\\w`,\nand always match `\\D`, `\\S`, and `\\W`. These sequences retain their original\nmeanings from before UTF support was available, mainly for efficiency reasons.\nHowever, if option `ucp` is set, the behavior is changed so that Unicode\nproperties are used to determine character types, as follows:\n\n- **`\\d`** - Any character that `\\p{Nd}` matches (decimal digit)\n\n- **`\\s`** - Any character that `\\p{Z}` or `\\h` or `\\v`\n\n- **`\\w`** - Any character that matches `\\p{L}` or `\\p{N}` matches, plus\n underscore\n\nThe uppercase escapes match the inverse sets of characters. Notice that `\\d`\nmatches only decimal digits, while `\\w` matches any Unicode digit, any Unicode\nletter, and underscore. Notice also that `ucp` affects `\\b` and `\\B`, as they are\ndefined in terms of `\\w` and `\\W`. Matching these sequences is noticeably slower\nwhen `ucp` is set.\n\nThe sequences `\\h`, `\\H`, `\\v`, and `\\V` are features that were added to Perl in\nrelease 5.10. In contrast to the other sequences, which match only ASCII\ncharacters by default, these always match certain high-valued code points,\nregardless if `ucp` is set.\n\nThe following are the horizontal space characters:\n\n- **U+0009** - Horizontal tab (HT)\n\n- **U+0020** - Space\n\n- **U+00A0** - Non-break space\n\n- **U+1680** - Ogham space mark\n\n- **U+180E** - Mongolian vowel separator\n\n- **U+2000** - En quad\n\n- **U+2001** - Em quad\n\n- **U+2002** - En space\n\n- **U+2003** - Em space\n\n- **U+2004** - Three-per-em space\n\n- **U+2005** - Four-per-em space\n\n- **U+2006** - Six-per-em space\n\n- **U+2007** - Figure space\n\n- **U+2008** - Punctuation space\n\n- **U+2009** - Thin space\n\n- **U+200A** - Hair space\n\n- **U+202F** - Narrow no-break space\n\n- **U+205F** - Medium mathematical space\n\n- **U+3000** - Ideographic space\n\nThe following are the vertical space characters:\n\n- **U+000A** - Line feed (LF)\n\n- **U+000B** - Vertical tab (VT)\n\n- **U+000C** - Form feed (FF)\n\n- **U+000D** - Carriage return (CR)\n\n- **U+0085** - Next line (NEL)\n\n- **U+2028** - Line separator\n\n- **U+2029** - Paragraph separator\n\nIn 8-bit, non-UTF-8 mode, only the characters with code points < 256 are\nrelevant.\n\n_Newline Sequences_\n\n[](){: #newline_sequences }\n\nOutside a character class, by default, the escape sequence `\\R` matches any\nUnicode newline sequence. In non-UTF-8 mode, `\\R` is equivalent to the following:\n\n```text\n(?>\\r\\n|\\n|\\x0b|\\f|\\r|\\x85)\n```\n\nThis is an example of an \"atomic group\", details are provided below.\n\nThis particular group matches either the two-character sequence CR followed by\nLF, or one of the single characters LF (line feed, U+000A), VT (vertical tab,\nU+000B), FF (form feed, U+000C), CR (carriage return, U+000D), or NEL (next\nline, U+0085). The two-character sequence is treated as a single unit that\ncannot be split.\n\nIn Unicode mode, two more characters whose code points are > 255 are added: LS\n(line separator, U+2028) and PS (paragraph separator, U+2029). Unicode character\nproperty support is not needed for these characters to be recognized.\n\n`\\R` can be restricted to match only CR, LF, or CRLF (instead of the complete set\nof Unicode line endings) by setting option `bsr_anycrlf` either at compile time\nor when the pattern is matched. (BSR is an acronym for \"backslash R\".) This can\nbe made the default when PCRE is built; if so, the other behavior can be\nrequested through option `bsr_unicode`. These settings can also be specified by\nstarting a pattern string with one of the following sequences:\n\n- **(\\*BSR_ANYCRLF)** - CR, LF, or CRLF only\n\n- **(\\*BSR_UNICODE)** - Any Unicode newline sequence\n\nThese override the default and the options specified to the compiling function,\nbut they can themselves be overridden by options specified to a matching\nfunction. Notice that these special settings, which are not Perl-compatible, are\nrecognized only at the very start of a pattern, and that they must be in upper\ncase. If more than one of them is present, the last one is used. They can be\ncombined with a change of newline convention; for example, a pattern can start\nwith:\n\n```text\n(*ANY)(*BSR_ANYCRLF)\n```\n\nThey can also be combined with the (*UTF8), (*UTF), or (\\*UCP) special\nsequences. Inside a character class, `\\R` is treated as an unrecognized escape\nsequence, and so matches the letter \"R\" by default.\n\n_Unicode Character Properties_\n\nThree more escape sequences that match characters with specific properties are\navailable. When in 8-bit non-UTF-8 mode, these sequences are limited to testing\ncharacters whose code points are < 256, but they do work in this mode. The\nfollowing are the extra escape sequences:\n\n- **`\\p{_xx_}`** - A character with property _xx_\n\n- **`\\P{_xx_}`** - A character without property _xx_\n\n- **`\\X`** - A Unicode extended grapheme cluster\n\nThe property names represented by _xx_ above are limited to the Unicode script\nnames, the general category properties, \"Any\", which matches any character\n(including newline), and some special PCRE properties (described in the next\nsection). Other Perl properties, such as \"InMusicalSymbols\", are currently not\nsupported by PCRE. Notice that `\\P{Any}` does not match any characters and\nalways causes a match failure.\n\nSets of Unicode characters are defined as belonging to certain scripts. A\ncharacter from one of these sets can be matched using a script name, for\nexample:\n\n```text\n\\p{Greek} \\P{Han}\n```\n\nThose that are not part of an identified script are lumped together as \"Common\".\nThe following is the current list of scripts:\n\n- Arabic\n- Armenian\n- Avestan\n- Balinese\n- Bamum\n- Bassa_Vah\n- Batak\n- Bengali\n- Bopomofo\n- Braille\n- Buginese\n- Buhid\n- Canadian_Aboriginal\n- Carian\n- Caucasian_Albanian\n- Chakma\n- Cham\n- Cherokee\n- Common\n- Coptic\n- Cuneiform\n- Cypriot\n- Cyrillic\n- Deseret\n- Devanagari\n- Duployan\n- Egyptian_Hieroglyphs\n- Elbasan\n- Ethiopic\n- Georgian\n- Glagolitic\n- Gothic\n- Grantha\n- Greek\n- Gujarati\n- Gurmukhi\n- Han\n- Hangul\n- Hanunoo\n- Hebrew\n- Hiragana\n- Imperial_Aramaic\n- Inherited\n- Inscriptional_Pahlavi\n- Inscriptional_Parthian\n- Javanese\n- Kaithi\n- Kannada\n- Katakana\n- Kayah_Li\n- Kharoshthi\n- Khmer\n- Khojki\n- Khudawadi\n- Lao\n- Latin\n- Lepcha\n- Limbu\n- Linear_A\n- Linear_B\n- Lisu\n- Lycian\n- Lydian\n- Mahajani\n- Malayalam\n- Mandaic\n- Manichaean\n- Meetei_Mayek\n- Mende_Kikakui\n- Meroitic_Cursive\n- Meroitic_Hieroglyphs\n- Miao\n- Modi\n- Mongolian\n- Mro\n- Myanmar\n- Nabataean\n- New_Tai_Lue\n- Nko\n- Ogham\n- Ol_Chiki\n- Old_Italic\n- Old_North_Arabian\n- Old_Permic\n- Old_Persian\n- Oriya\n- Old_South_Arabian\n- Old_Turkic\n- Osmanya\n- Pahawh_Hmong\n- Palmyrene\n- Pau_Cin_Hau\n- Phags_Pa\n- Phoenician\n- Psalter_Pahlavi\n- Rejang\n- Runic\n- Samaritan\n- Saurashtra\n- Sharada\n- Shavian\n- Siddham\n- Sinhala\n- Sora_Sompeng\n- Sundanese\n- Syloti_Nagri\n- Syriac\n- Tagalog\n- Tagbanwa\n- Tai_Le\n- Tai_Tham\n- Tai_Viet\n- Takri\n- Tamil\n- Telugu\n- Thaana\n- Thai\n- Tibetan\n- Tifinagh\n- Tirhuta\n- Ugaritic\n- Vai\n- Warang_Citi\n- Yi\n\nEach character has exactly one Unicode general category property, specified by a\ntwo-letter acronym. For compatibility with Perl, negation can be specified by\nincluding a circumflex between the opening brace and the property name. For\nexample, `\\p{^Lu}` is the same as `\\P{Lu}`.\n\nIf only one letter is specified with `\\p` or `\\P`, it includes all the general\ncategory properties that start with that letter. In this case, in the absence of\nnegation, the curly brackets in the escape sequence are optional. The following\ntwo examples have the same effect:\n\n```text\n\\p{L}\n\\pL\n```\n\nThe following general category property codes are supported:\n\n- **C** - Other\n\n- **Cc** - Control\n\n- **Cf** - Format\n\n- **Cn** - Unassigned\n\n- **Co** - Private use\n\n- **Cs** - Surrogate\n\n- **L** - Letter\n\n- **Ll** - Lowercase letter\n\n- **Lm** - Modifier letter\n\n- **Lo** - Other letter\n\n- **Lt** - Title case letter\n\n- **Lu** - Uppercase letter\n\n- **M** - Mark\n\n- **Mc** - Spacing mark\n\n- **Me** - Enclosing mark\n\n- **Mn** - Non-spacing mark\n\n- **N** - Number\n\n- **Nd** - Decimal number\n\n- **Nl** - Letter number\n\n- **No** - Other number\n\n- **P** - Punctuation\n\n- **Pc** - Connector punctuation\n\n- **Pd** - Dash punctuation\n\n- **Pe** - Close punctuation\n\n- **Pf** - Final punctuation\n\n- **Pi** - Initial punctuation\n\n- **Po** - Other punctuation\n\n- **Ps** - Open punctuation\n\n- **S** - Symbol\n\n- **Sc** - Currency symbol\n\n- **Sk** - Modifier symbol\n\n- **Sm** - Mathematical symbol\n\n- **So** - Other symbol\n\n- **Z** - Separator\n\n- **Zl** - Line separator\n\n- **Zp** - Paragraph separator\n\n- **Zs** - Space separator\n\nThe special property L& is also supported. It matches a character that has the\nLu, Ll, or Lt property, that is, a letter that is not classified as a modifier\nor \"other\".\n\nThe Cs (Surrogate) property applies only to characters in the range U+D800 to\nU+DFFF. Such characters are invalid in Unicode strings and so cannot be tested\nby PCRE. Perl does not support the Cs property.\n\nThe long synonyms for property names supported by Perl (such as `\\p{Letter}`)\nare not supported by PCRE. It is not permitted to prefix any of these properties\nwith \"Is\".\n\nNo character in the Unicode table has the Cn (unassigned) property. This\nproperty is instead assumed for any code point that is not in the Unicode table.\n\nSpecifying caseless matching does not affect these escape sequences. For\nexample, `\\p{Lu}` always matches only uppercase letters. This is different from\nthe behavior of current versions of Perl.\n\nMatching characters by Unicode property is not fast, as PCRE must do a\nmultistage table lookup to find a character property. That is why the\ntraditional escape sequences such as `\\d` and `\\w` do not use Unicode properties\nin PCRE by default. However, you can make them do so by setting option `ucp` or\nby starting the pattern with `(*UCP)`.\n\n_Extended Grapheme Clusters_\n\nThe `\\X` escape matches any number of Unicode characters that form an \"extended\ngrapheme cluster\", and treats the sequence as an atomic group (see below). Up to\nand including release 8.31, PCRE matched an earlier, simpler definition that was\nequivalent to `(?>\\PM\\pM*)`. That is, it matched a character without the \"mark\"\nproperty, followed by zero or more characters with the \"mark\" property.\nCharacters with the \"mark\" property are typically non-spacing accents that\naffect the preceding character.\n\nThis simple definition was extended in Unicode to include more complicated kinds\nof composite character by giving each character a grapheme breaking property,\nand creating rules that use these properties to define the boundaries of\nextended grapheme clusters. In PCRE releases later than 8.31, `\\X` matches one of\nthese clusters.\n\n`\\X` always matches at least one character. Then it decides whether to add more\ncharacters according to the following rules for ending a cluster:\n\n1. End at the end of the subject string.\n1. Do not end between CR and LF; otherwise end after any control character.\n1. Do not break Hangul (a Korean script) syllable sequences. Hangul characters\n are of five types: L, V, T, LV, and LVT. An L character can be followed by an\n L, V, LV, or LVT character. An LV or V character can be followed by a V or T\n character. An LVT or T character can be followed only by a T character.\n1. Do not end before extending characters or spacing marks. Characters with the\n \"mark\" property always have the \"extend\" grapheme breaking property.\n1. Do not end after prepend characters.\n1. Otherwise, end the cluster.\n\n_PCRE Additional Properties_\n\nIn addition to the standard Unicode properties described earlier, PCRE supports\nfour more that make it possible to convert traditional escape sequences, such as\n`\\w` and `\\s` to use Unicode properties. PCRE uses these non-standard, non-Perl\nproperties internally when the `ucp` option is passed. However, they can also be\nused explicitly. The properties are as follows:\n\n- **Xan** - Any alphanumeric character. Matches characters that have either the\n L (letter) or the N (number) property.\n\n- **Xps** - Any Posix space character. Matches the characters tab, line feed,\n vertical tab, form feed, carriage return, and any other character that has the\n Z (separator) property.\n\n- **Xsp** - Any Perl space character. Matches the same as Xps, except that\n vertical tab is excluded.\n\n- **Xwd** - Any Perl \"word\" character. Matches the same characters as Xan, plus\n underscore.\n\nPerl and POSIX space are now the same. Perl added VT to its space character set\nat release 5.18 and PCRE changed at release 8.34.\n\nXan matches characters that have either the L (letter) or the N (number)\nproperty. Xps matches the characters tab, linefeed, vertical tab, form feed, or\ncarriage return, and any other character that has the Z (separator) property.\nXsp is the same as Xps; it used to exclude vertical tab, for Perl compatibility,\nbut Perl changed, and so PCRE followed at release 8.34. Xwd matches the same\ncharacters as Xan, plus underscore.\n\nThere is another non-standard property, Xuc, which matches any character that\ncan be represented by a Universal Character Name in C++ and other programming\nlanguages. These are the characters `$`, `@`, `` ` `` (grave accent), and all characters\nwith Unicode code points >= U+00A0, except for the surrogates U+D800 to U+DFFF.\nNotice that most base (ASCII) characters are excluded. (Universal Character\nNames are of the form `\\uHHHH` or `\\UHHHHHHHH`, where H is a hexadecimal digit.\nNotice that the Xuc property does not match these sequences but the characters\nthat they represent.)\n\n_Resetting the Match Start_\n\nThe escape sequence `\\K` causes any previously matched characters not to be\nincluded in the final matched sequence. For example, the following pattern\nmatches \"foobar\", but reports that it has matched \"bar\":\n\n```text\nfoo\\Kbar\n```\n\nThis feature is similar to a lookbehind assertion (described below). However, in\nthis case, the part of the subject before the real match does not have to be of\nfixed length, as lookbehind assertions do. The use of `\\K` does not interfere\nwith the setting of captured substrings. For example, when the following pattern\nmatches \"foobar\", the first substring is still set to \"foo\":\n\n```text\n(foo)\\Kbar\n```\n\nPerl documents that the use of `\\K` within assertions is \"not well defined\". In\nPCRE, `\\K` is acted upon when it occurs inside positive assertions, but is\nignored in negative assertions. Note that when a pattern such as `(?=ab\\K)`\nmatches, the reported start of the match can be greater than the end of the\nmatch.\n\n_Simple Assertions_\n\nThe final use of backslash is for certain simple assertions. An assertion\nspecifies a condition that must be met at a particular point in a match, without\nconsuming any characters from the subject string. The use of subpatterns for\nmore complicated assertions is described below. The following are the\nbackslashed assertions:\n\n- **`\\b`** - Matches at a word boundary.\n\n- **`\\B`** - Matches when not at a word boundary.\n\n- **`\\A`** - Matches at the start of the subject.\n\n- **`\\Z`** - Matches at the end of the subject, and before a newline at the end\n of the subject.\n\n- **`\\z`** - Matches only at the end of the subject.\n\n- **`\\G`** - Matches at the first matching position in the subject.\n\nInside a character class, `\\b` has a different meaning; it matches the backspace\ncharacter. If any other of these assertions appears in a character class, by\ndefault it matches the corresponding literal character (for example, `\\B` matches\nthe letter B).\n\nA word boundary is a position in the subject string where the current character\nand the previous character do not both match `\\w` or `\\W` (that is, one matches\n`\\w` and the other matches `\\W`), or the start or end of the string if the first\nor last character matches `\\w`, respectively. In UTF mode, the meanings of `\\w`\nand `\\W` can be changed by setting option `ucp`. When this is done, it also\naffects `\\b` and `\\B`. PCRE and Perl do not have a separate \"start of word\" or\n\"end of word\" metasequence. However, whatever follows `\\b` normally determines\nwhich it is. For example, the fragment `\\ba` matches \"a\" at the start of a word.\n\nThe `\\A`, `\\Z`, and `\\z` assertions differ from the traditional circumflex and\ndollar (described in the next section) in that they only ever match at the very\nstart and end of the subject string, whatever options are set. Thus, they are\nindependent of multiline mode. These three assertions are not affected by\noptions `notbol` or `noteol`, which affect only the behavior of the circumflex\nand dollar metacharacters. However, if argument `startoffset` of `run/3` is\nnon-zero, indicating that matching is to start at a point other than the\nbeginning of the subject, `\\A` can never match. The difference between `\\Z` and\n`\\z` is that `\\Z` matches before a newline at the end of the string and at the\nvery end, while `\\z` matches only at the end.\n\nThe `\\G` assertion is true only when the current matching position is at the\nstart point of the match, as specified by argument `startoffset` of\n[`run/3`](`run/3`). It differs from `\\A` when the value of `startoffset` is\nnon-zero. By calling [`run/3`](`run/3`) multiple times with appropriate\narguments, you can mimic the Perl option `/g`, and it is in this kind of\nimplementation where `\\G` can be useful.\n\nNotice, however, that the PCRE interpretation of `\\G`, as the start of the\ncurrent match, is subtly different from Perl, which defines it as the end of the\nprevious match. In Perl, these can be different when the previously matched\nstring was empty. As PCRE does only one match at a time, it cannot reproduce\nthis behavior.\n\nIf all the alternatives of a pattern begin with `\\G`, the expression is anchored\nto the starting match position, and the \"anchored\" flag is set in the compiled\nregular expression.\n\n[](){: #sect4 }","title":"Backslash - re","ref":"re.html#module-backslash"},{"type":"module","doc":"The circumflex and dollar metacharacters are zero-width assertions. That is,\nthey test for a particular condition to be true without consuming any characters\nfrom the subject string.\n\nOutside a character class, in the default matching mode, the circumflex\ncharacter is an assertion that is true only if the current matching point is at\nthe start of the subject string. If argument `startoffset` of `run/3` is\nnon-zero, circumflex can never match if option `multiline` is unset. Inside a\ncharacter class, circumflex has an entirely different meaning (see below).\n\nCircumflex needs not to be the first character of the pattern if some\nalternatives are involved, but it is to be the first thing in each alternative\nin which it appears if the pattern is ever to match that branch. If all possible\nalternatives start with a circumflex, that is, if the pattern is constrained to\nmatch only at the start of the subject, it is said to be an \"anchored\" pattern.\n(There are also other constructs that can cause a pattern to be anchored.)\n\nThe dollar character is an assertion that is true only if the current matching\npoint is at the end of the subject string, or immediately before a newline at\nthe end of the string (by default). Notice however that it does not match the\nnewline. Dollar needs not to be the last character of the pattern if some\nalternatives are involved, but it is to be the last item in any branch in which\nit appears. Dollar has no special meaning in a character class.\n\nThe meaning of dollar can be changed so that it matches only at the very end of\nthe string, by setting option `dollar_endonly` at compile time. This does not\naffect the `\\Z` assertion.\n\nThe meanings of the circumflex and dollar characters are changed if option\n`multiline` is set. When this is the case, a circumflex matches immediately\nafter internal newlines and at the start of the subject string. It does not\nmatch after a newline that ends the string. A dollar matches before any newlines\nin the string, and at the very end, when `multiline` is set. When newline is\nspecified as the two-character sequence CRLF, isolated CR and LF characters do\nnot indicate newlines.\n\nFor example, the pattern `/^abc$/` matches the subject string \"def\\\\nabc\" (where\n\\\\n represents a newline) in multiline mode, but not otherwise. So, patterns\nthat are anchored in single-line mode because all branches start with ^ are not\nanchored in multiline mode, and a match for circumflex is possible when argument\n_startoffset_ of [`run/3`](`run/3`) is non-zero. Option `dollar_endonly` is\nignored if `multiline` is set.\n\nNotice that the sequences `\\A`, `\\Z`, and `\\z` can be used to match the start and\nend of the subject in both modes. If all branches of a pattern start with `\\A`,\nit is always anchored, regardless if `multiline` is set.\n\n[](){: #sect5 }","title":"Circumflex and Dollar - re","ref":"re.html#module-circumflex-and-dollar"},{"type":"module","doc":"Outside a character class, a dot in the pattern matches any character in the\nsubject string except (by default) a character that signifies the end of a line.\n\nWhen a line ending is defined as a single character, dot never matches that\ncharacter. When the two-character sequence CRLF is used, dot does not match CR\nif it is immediately followed by LF, otherwise it matches all characters\n(including isolated CRs and LFs). When any Unicode line endings are recognized,\ndot does not match CR, LF, or any of the other line-ending characters.\n\nThe behavior of dot regarding newlines can be changed. If option `dotall` is\nset, a dot matches any character, without exception. If the two-character\nsequence CRLF is present in the subject string, it takes two dots to match it.\n\nThe handling of dot is entirely independent of the handling of circumflex and\ndollar, the only relationship is that both involve newlines. Dot has no special\nmeaning in a character class.\n\nThe escape sequence `\\N` behaves like a dot, except that it is not affected by\noption `PCRE_DOTALL`. That is, it matches any character except one that\nsignifies the end of a line. Perl also uses `\\N` to match characters by name but\nPCRE does not support this.\n\n[](){: #sect6 }","title":"Full Stop (Period, Dot) and \\\\N - re","ref":"re.html#module-full-stop-period-dot-and-n"},{"type":"module","doc":"Outside a character class, the escape sequence `\\C` matches any data unit,\nregardless if a UTF mode is set. One data unit is one byte. Unlike a dot, `\\C`\nalways matches line-ending characters. The feature is provided in Perl to match\nindividual bytes in UTF-8 mode, but it is unclear how it can usefully be used.\nAs `\\C` breaks up characters into individual data units, matching one unit with\n`\\C` in a UTF mode means that the remaining string can start with a malformed UTF\ncharacter. This has undefined results, as PCRE assumes that it deals with valid\nUTF strings.\n\nPCRE does not allow `\\C` to appear in lookbehind assertions (described below) in\na UTF mode, as this would make it impossible to calculate the length of the\nlookbehind.\n\nThe `\\C` escape sequence is best avoided. However, one way of using it that\navoids the problem of malformed UTF characters is to use a lookahead to check\nthe length of the next character, as in the following pattern, which can be used\nwith a UTF-8 string (ignore whitespace and line breaks):\n\n```text\n(?| (?=[\\x00-\\x7f])(\\C) |\n (?=[\\x80-\\x{7ff}])(\\C)(\\C) |\n (?=[\\x{800}-\\x{ffff}])(\\C)(\\C)(\\C) |\n (?=[\\x{10000}-\\x{1fffff}])(\\C)(\\C)(\\C)(\\C))\n```\n\nA group that starts with (?| resets the capturing parentheses numbers in each\nalternative (see section [Duplicate Subpattern Numbers](`m:re#sect12`)). The\nassertions at the start of each branch check the next UTF-8 character for values\nwhose encoding uses 1, 2, 3, or 4 bytes, respectively. The individual bytes of\nthe character are then captured by the appropriate number of groups.\n\n[](){: #sect7 }","title":"Matching a Single Data Unit - re","ref":"re.html#module-matching-a-single-data-unit"},{"type":"module","doc":"An opening square bracket introduces a character class, terminated by a closing\nsquare bracket. A closing square bracket on its own is not special by default.\nHowever, if option `PCRE_JAVASCRIPT_COMPAT` is set, a lone closing square\nbracket causes a compile-time error. If a closing square bracket is required as\na member of the class, it is to be the first data character in the class (after\nan initial circumflex, if present) or escaped with a backslash.\n\nA character class matches a single character in the subject. In a UTF mode, the\ncharacter can be more than one data unit long. A matched character must be in\nthe set of characters defined by the class, unless the first character in the\nclass definition is a circumflex, in which case the subject character must not\nbe in the set defined by the class. If a circumflex is required as a member of\nthe class, ensure that it is not the first character, or escape it with a\nbackslash.\n\nFor example, the character class `[aeiou]` matches any lowercase vowel, while\n`[^aeiou]` matches any character that is not a lowercase vowel. Notice that a\ncircumflex is just a convenient notation for specifying the characters that are\nin the class by enumerating those that are not. A class that starts with a\ncircumflex is not an assertion; it still consumes a character from the subject\nstring, and therefore it fails if the current pointer is at the end of the\nstring.\n\nIn UTF-8 mode, characters with values > 255 (0xffff) can be included in a class\nas a literal string of data units, or by using the `\\x{` escaping mechanism.\n\nWhen caseless matching is set, any letters in a class represent both their\nuppercase and lowercase versions. For example, a caseless `[aeiou]` matches \"A\"\nand \"a\", and a caseless `[^aeiou]` does not match \"A\", but a caseful version\nwould. In a UTF mode, PCRE always understands the concept of case for characters\nwhose values are < 256, so caseless matching is always possible. For characters\nwith higher values, the concept of case is supported only if PCRE is compiled\nwith Unicode property support. If you want to use caseless matching in a UTF\nmode for characters >=, ensure that PCRE is compiled with Unicode property\nsupport and with UTF support.\n\nCharacters that can indicate line breaks are never treated in any special way\nwhen matching character classes, whatever line-ending sequence is in use, and\nwhatever setting of options `PCRE_DOTALL` and `PCRE_MULTILINE` is used. A class\nsuch as `[^a]` always matches one of these characters.\n\nThe minus (hyphen) character can be used to specify a range of characters in a\ncharacter class. For example, `[d-m]` matches any letter between d and m,\ninclusive. If a minus character is required in a class, it must be escaped with\na backslash or appear in a position where it cannot be interpreted as indicating\na range, typically as the first or last character in the class, or immediately\nafter a range. For example, `[b-d-z]` matches letters in the range b to d, a\nhyphen character, or z.\n\nThe literal character \"]\" cannot be the end character of a range. A pattern such\nas `[W-]46]` is interpreted as a class of two characters (\"W\" and \"-\") followed\nby a literal string \"46]\", so it would match \"W46]\" or \"-46]\". However, if \"]\"\nis escaped with a backslash, it is interpreted as the end of range, so\n`[W-\\]46]` is interpreted as a class containing a range followed by two other\ncharacters. The octal or hexadecimal representation of \"]\" can also be used to\nend a range.\n\nAn error is generated if a POSIX character class (see below) or an escape\nsequence other than one that defines a single character appears at a point where\na range ending character is expected. For example, `[z-\\xff]` is valid, but\n`[A-\\d]` and `[A-[:digit:]]` are not.\n\nRanges operate in the collating sequence of character values. They can also be\nused for characters specified numerically, for example, `[\\000-\\037]`. Ranges\ncan include any characters that are valid for the current mode.\n\nIf a range that includes letters is used when caseless matching is set, it\nmatches the letters in either case. For example, `[W-c]` is equivalent to\n`` [][\\\\^_`wxyzabc] ``, matched caselessly. In a non-UTF mode, if character\ntables for a French locale are in use, `[\\xc8-\\xcb]` matches accented E\ncharacters in both cases. In UTF modes, PCRE supports the concept of case for\ncharacters with values > 255 only when it is compiled with Unicode property\nsupport.\n\nThe character escape sequences `\\d`, `\\D`, `\\h`, `\\H`, `\\p`, `\\P`, `\\s`, `\\S`, `\\v`, `\\V`,\n`\\w`, and `\\W` can appear in a character class, and add the characters that they\nmatch to the class. For example, `[\\dABCDEF]` matches any hexadecimal digit. In\nUTF modes, option `ucp` affects the meanings of `\\d`, `\\s`, `\\w` and their\nuppercase partners, just as it does when they appear outside a character class,\nas described in section\n[Generic Character Types](`m:re#generic_character_types`) earlier. The escape\nsequence `\\b` has a different meaning inside a character class; it matches the\nbackspace character. The sequences `\\B`, `\\N`, `\\R`, and `\\X` are not special inside\na character class. Like any other unrecognized escape sequences, they are\ntreated as the literal characters \"B\", \"N\", \"R\", and \"X\".\n\nA circumflex can conveniently be used with the uppercase character types to\nspecify a more restricted set of characters than the matching lowercase type.\nFor example, class `[^\\W_]` matches any letter or digit, but not underscore,\nwhile `[\\w]` includes underscore. A positive character class is to be read as\n\"something OR something OR ...\" and a negative class as \"NOT something AND NOT\nsomething AND NOT ...\".\n\nOnly the following metacharacters are recognized in character classes:\n\n- Backslash\n- Hyphen (only where it can be interpreted as specifying a range)\n- Circumflex (only at the start)\n- Opening square bracket (only when it can be interpreted as introducing a Posix\n class name, or for a special compatibility feature; see the next two sections)\n- Terminating closing square bracket\n\nHowever, escaping other non-alphanumeric characters does no harm.\n\n[](){: #sect8 }","title":"Square Brackets and Character Classes - re","ref":"re.html#module-square-brackets-and-character-classes"},{"type":"module","doc":"Perl supports the Posix notation for character classes. This uses names enclosed\nby `[:` and `:]` within the enclosing square brackets. PCRE also supports this\nnotation. For example, the following matches \"0\", \"1\", any alphabetic character,\nor \"%\":\n\n```text\n[01[:alpha:]%]\n```\n\nThe following are the supported class names:\n\n- **alnum** - Letters and digits\n\n- **alpha** - Letters\n\n- **blank** - Space or tab only\n\n- **cntrl** - Control characters\n\n- **digit** - Decimal digits (same as `\\d`)\n\n- **graph** - Printing characters, excluding space\n\n- **lower** - Lowercase letters\n\n- **print** - Printing characters, including space\n\n- **punct** - Printing characters, excluding letters, digits, and space\n\n- **space** - Whitespace (the same as `\\s` from PCRE 8.34)\n\n- **upper** - Uppercase letters\n\n- **word** - \"Word\" characters (same as `\\w`)\n\n- **xdigit** - Hexadecimal digits\n\nThere is another character class, `ascii`, that erroneously matches Latin-1\ncharacters instead of the 0-127 range specified by POSIX. This cannot be fixed\nwithout altering the behaviour of other classes, so we recommend matching the\nrange with `[\\\\0-\\x7f]` instead.\n\nThe default \"space\" characters are HT (9), LF (10), VT (11), FF (12), CR (13),\nand space (32). If locale-specific matching is taking place, the list of space\ncharacters may be different; there may be fewer or more of them. \"Space\" used to\nbe different to `\\s`, which did not include VT, for Perl compatibility. However,\nPerl changed at release 5.18, and PCRE followed at release 8.34. \"Space\" and `\\s`\nnow match the same set of characters.\n\nThe name \"word\" is a Perl extension, and \"blank\" is a GNU extension from Perl\n5.8. Another Perl extension is negation, which is indicated by a ^ character\nafter the colon. For example, the following matches \"1\", \"2\", or any non-digit:\n\n```text\n[12[:^digit:]]\n```\n\nPCRE (and Perl) also recognize the Posix syntax `[.ch.]` and `[=ch=]` where \"ch\"\nis a \"collating element\", but these are not supported, and an error is given if\nthey are encountered.\n\nBy default, characters with values > 255 do not match any of the Posix character\nclasses. However, if option `PCRE_UCP` is passed to `pcre_compile()`, some of\nthe classes are changed so that Unicode character properties are used. This is\nachieved by replacing certain Posix classes by other sequences, as follows:\n\n- **`[:alnum:]`** - Becomes _`\\p{Xan}`_\n\n- **`[:alpha:]`** - Becomes _`\\p{L}`_\n\n- **`[:blank:]`** - Becomes _`\\h`_\n\n- **`[:digit:]`** - Becomes _`\\p{Nd}`_\n\n- **`[:lower:]`** - Becomes _`\\p{Ll}`_\n\n- **`[:space:]`** - Becomes _`\\p{Xps}`_\n\n- **`[:upper:]`** - Becomes _`\\p{Lu}`_\n\n- **`[:word:]`** - Becomes _`\\p{Xwd}`_\n\nNegated versions, such as `[:^alpha:]`, use `\\P` instead of `\\p`. Three other POSIX\nclasses are handled specially in UCP mode:\n\n- **`[:graph:]`** - This matches characters that have glyphs that mark the page\n when printed. In Unicode property terms, it matches all characters with the L,\n M, N, P, S, or Cf properties, except for:\n\n - **U+061C** - Arabic Letter Mark\n\n - **U+180E** - Mongolian Vowel Separator\n\n - **U+2066 - U+2069** - Various \"isolate\"s\n\n- **`[:print:]`** - This matches the same characters as `[:graph:]` plus space\n characters that are not controls, that is, characters with the Zs property.\n\n- **`[:punct:]`** - This matches all characters that have the Unicode P\n (punctuation) property, plus those characters whose code points are less than\n 128 that have the S (Symbol) property.\n\nThe other POSIX classes are unchanged, and match only characters with code\npoints less than 128.\n\n_Compatibility Feature for Word Boundaries_\n\nIn the POSIX.2 compliant library that was included in 4.4BSD Unix, the ugly\nsyntax `[[:<:]]` and `[[:>:]]` is used for matching \"start of word\" and \"end of\nword\". PCRE treats these items as follows:\n\n- **`[[:<:]]`** - is converted to `\\b(?=\\w)`\n\n- **`[[:>:]]`** - is converted to `\\b(?<=\\w)`\n\nOnly these exact character sequences are recognized. A sequence such as\n`[a[:<:]b]` provokes error for an unrecognized POSIX class name. This support is\nnot compatible with Perl. It is provided to help migrations from other\nenvironments, and is best not used in any new patterns. Note that `\\b` matches at\nthe start and the end of a word (see \"Simple assertions\" above), and in a\nPerl-style pattern the preceding or following character normally shows which is\nwanted, without the need for the assertions that are used above in order to give\nexactly the POSIX behaviour.\n\n[](){: #sect9 }","title":"Posix Character Classes - re","ref":"re.html#module-posix-character-classes"},{"type":"module","doc":"Vertical bar characters are used to separate alternative patterns. For example,\nthe following pattern matches either \"gilbert\" or \"sullivan\":\n\n```text\ngilbert|sullivan\n```\n\nAny number of alternatives can appear, and an empty alternative is permitted\n(matching the empty string). The matching process tries each alternative in\nturn, from left to right, and the first that succeeds is used. If the\nalternatives are within a subpattern (defined in section\n[Subpatterns](`m:re#sect11`)), \"succeeds\" means matching the remaining main\npattern and the alternative in the subpattern.\n\n[](){: #sect10 }","title":"Vertical Bar - re","ref":"re.html#module-vertical-bar"},{"type":"module","doc":"The settings of the Perl-compatible options `caseless`, `multiline`, `dotall`,\nand `extended` can be changed from within the pattern by a sequence of Perl\noption letters enclosed between \"(?\" and \")\". The option letters are as follows:\n\n- **i** - For `caseless`\n\n- **m** - For `multiline`\n\n- **s** - For `dotall`\n\n- **x** - For `extended`\n\nFor example, `(?im)` sets caseless, multiline matching. These options can also\nbe unset by preceding the letter with a hyphen. A combined setting and unsetting\nsuch as `(?im-sx)`, which sets `caseless` and `multiline`, while unsetting\n`dotall` and `extended`, is also permitted. If a letter appears both before and\nafter the hyphen, the option is unset.\n\nThe PCRE-specific options `dupnames`, `ungreedy`, and `extra` can be changed in\nthe same way as the Perl-compatible options by using the characters J, U, and X\nrespectively.\n\nWhen one of these option changes occurs at top-level (that is, not inside\nsubpattern parentheses), the change applies to the remainder of the pattern that\nfollows.\n\nAn option change within a subpattern (see section [Subpatterns](`m:re#sect11`))\naffects only that part of the subpattern that follows it. So, the following\nmatches abc and aBc and no other strings (assuming `caseless` is not used):\n\n```text\n(a(?i)b)c\n```\n\nBy this means, options can be made to have different settings in different parts\nof the pattern. Any changes made in one alternative do carry on into subsequent\nbranches within the same subpattern. For example:\n\n```text\n(a(?i)b|c)\n```\n\nmatches \"ab\", \"aB\", \"c\", and \"C\", although when matching \"C\" the first branch is\nabandoned before the option setting. This is because the effects of option\nsettings occur at compile time. There would be some weird behavior otherwise.\n\n> #### Note {: .info }\n>\n> Other PCRE-specific options can be set by the application when the compiling\n> or matching functions are called. Sometimes the pattern can contain special\n> leading sequences, such as (\\*CRLF), to override what the application has set\n> or what has been defaulted. Details are provided in section\n> [Newline Sequences](`m:re#newline_sequences`) earlier.\n>\n> The (*UTF8) and (*UCP) leading sequences can be used to set UTF and Unicode\n> property modes. They are equivalent to setting options `unicode` and `ucp`,\n> respectively. The (*UTF) sequence is a generic version that can be used with\n> any of the libraries. However, the application can set option `never_utf`,\n> which locks out the use of the (*UTF) sequences.\n\n[](){: #sect11 }","title":"Internal Option Setting - re","ref":"re.html#module-internal-option-setting"},{"type":"module","doc":"Subpatterns are delimited by parentheses (round brackets), which can be nested.\nTurning part of a pattern into a subpattern does two things:\n\n- **1.** - It localizes a set of alternatives. For example, the following\n pattern matches \"cataract\", \"caterpillar\", or \"cat\":\n\n ```text\n cat(aract|erpillar|)\n ```\n\n Without the parentheses, it would match \"cataract\", \"erpillar\", or an empty\n string.\n\n- **2.** - It sets up the subpattern as a capturing subpattern. That is, when\n the complete pattern matches, that portion of the subject string that matched\n the subpattern is passed back to the caller through the return value of\n `run/3`.\n\nOpening parentheses are counted from left to right (starting from 1) to obtain\nnumbers for the capturing subpatterns. For example, if the string \"the red king\"\nis matched against the following pattern, the captured substrings are \"red\nking\", \"red\", and \"king\", and are numbered 1, 2, and 3, respectively:\n\n```text\nthe ((red|white) (king|queen))\n```\n\nIt is not always helpful that plain parentheses fulfill two functions. Often a\ngrouping subpattern is required without a capturing requirement. If an opening\nparenthesis is followed by a question mark and a colon, the subpattern does not\ndo any capturing, and is not counted when computing the number of any subsequent\ncapturing subpatterns. For example, if the string \"the white queen\" is matched\nagainst the following pattern, the captured substrings are \"white queen\" and\n\"queen\", and are numbered 1 and 2:\n\n```text\nthe ((?:red|white) (king|queen))\n```\n\nThe maximum number of capturing subpatterns is 65535.\n\nAs a convenient shorthand, if any option settings are required at the start of a\nnon-capturing subpattern, the option letters can appear between \"?\" and \":\".\nThus, the following two patterns match the same set of strings:\n\n```text\n(?i:saturday|sunday)\n(?:(?i)saturday|sunday)\n```\n\nAs alternative branches are tried from left to right, and options are not reset\nuntil the end of the subpattern is reached, an option setting in one branch does\naffect subsequent branches, so the above patterns match both \"SUNDAY\" and\n\"Saturday\".\n\n[](){: #sect12 }","title":"Subpatterns - re","ref":"re.html#module-subpatterns"},{"type":"module","doc":"Perl 5.10 introduced a feature where each alternative in a subpattern uses the\nsame numbers for its capturing parentheses. Such a subpattern starts with `(?|`\nand is itself a non-capturing subpattern. For example, consider the following\npattern:\n\n```text\n(?|(Sat)ur|(Sun))day\n```\n\nAs the two alternatives are inside a `(?|` group, both sets of capturing\nparentheses are numbered one. Thus, when the pattern matches, you can look at\ncaptured substring number one, whichever alternative matched. This construct is\nuseful when you want to capture a part, but not all, of one of many\nalternatives. Inside a `(?|` group, parentheses are numbered as usual, but the\nnumber is reset at the start of each branch. The numbers of any capturing\nparentheses that follow the subpattern start after the highest number used in\nany branch. The following example is from the Perl documentation; the numbers\nunderneath show in which buffer the captured content is stored:\n\n```text\n# before ---------------branch-reset----------- after\n/ ( a ) (?| x ( y ) z | (p (q) r) | (t) u (v) ) ( z ) /x\n# 1 2 2 3 2 3 4\n```\n\nA back reference to a numbered subpattern uses the most recent value that is set\nfor that number by any subpattern. The following pattern matches \"abcabc\" or\n\"defdef\":\n\n```text\n/(?|(abc)|(def))\\1/\n```\n\nIn contrast, a subroutine call to a numbered subpattern always refers to the\nfirst one in the pattern with the given number. The following pattern matches\n\"abcabc\" or \"defabc\":\n\n```text\n/(?|(abc)|(def))(?1)/\n```\n\nIf a condition test for a subpattern having matched refers to a non-unique\nnumber, the test is true if any of the subpatterns of that number have matched.\n\nAn alternative approach using this \"branch reset\" feature is to use duplicate\nnamed subpatterns, as described in the next section.\n\n[](){: #sect13 }","title":"Duplicate Subpattern Numbers - re","ref":"re.html#module-duplicate-subpattern-numbers"},{"type":"module","doc":"Identifying capturing parentheses by number is simple, but it can be hard to\nkeep track of the numbers in complicated regular expressions. Also, if an\nexpression is modified, the numbers can change. To help with this difficulty,\nPCRE supports the naming of subpatterns. This feature was not added to Perl\nuntil release 5.10. Python had the feature earlier, and PCRE introduced it at\nrelease 4.0, using the Python syntax. PCRE now supports both the Perl and the\nPython syntax. Perl allows identically numbered subpatterns to have different\nnames, but PCRE does not.\n\nIn PCRE, a subpattern can be named in one of three ways: `(? ...)` or\n`(?'name'...)` as in Perl, or `(?P ...)` as in Python. References to\ncapturing parentheses from other parts of the pattern, such as back references,\nrecursion, and conditions, can be made by name and by number.\n\nNames consist of up to 32 alphanumeric characters and underscores, but must\nstart with a non-digit. Named capturing parentheses are still allocated numbers\nas well as names, exactly as if the names were not present. The `capture`\nspecification to `run/3` can use named values if they are present in the regular\nexpression.\n\nBy default, a name must be unique within a pattern, but this constraint can be\nrelaxed by setting option `dupnames` at compile time. (Duplicate names are also\nalways permitted for subpatterns with the same number, set up as described in\nthe previous section.) Duplicate names can be useful for patterns where only one\ninstance of the named parentheses can match. Suppose that you want to match the\nname of a weekday, either as a 3-letter abbreviation or as the full name, and in\nboth cases you want to extract the abbreviation. The following pattern (ignoring\nthe line breaks) does the job:\n\n```text\n(? Mon|Fri|Sun)(?:day)?|\n(? Tue)(?:sday)?|\n(? Wed)(?:nesday)?|\n(? Thu)(?:rsday)?|\n(? Sat)(?:urday)?\n```\n\nThere are five capturing substrings, but only one is ever set after a match. (An\nalternative way of solving this problem is to use a \"branch reset\" subpattern,\nas described in the previous section.)\n\nFor capturing named subpatterns which names are not unique, the first matching\noccurrence (counted from left to right in the subject) is returned from `run/3`,\nif the name is specified in the `values` part of the `capture` statement. The\n`all_names` capturing value matches all the names in the same way.\n\n> #### Note {: .info }\n>\n> You cannot use different names to distinguish between two subpatterns with the\n> same number, as PCRE uses only the numbers when matching. For this reason, an\n> error is given at compile time if different names are specified to subpatterns\n> with the same number. However, you can specify the same name to subpatterns\n> with the same number, even when `dupnames` is not set.\n\n[](){: #sect14 }","title":"Named Subpatterns - re","ref":"re.html#module-named-subpatterns"},{"type":"module","doc":"Repetition is specified by quantifiers, which can follow any of the following\nitems:\n\n- A literal data character\n- The dot metacharacter\n- The `\\C` escape sequence\n- The `\\X` escape sequence\n- The `\\R` escape sequence\n- An escape such as `\\d` or `\\pL` that matches a single character\n- A character class\n- A back reference (see the next section)\n- A parenthesized subpattern (including assertions)\n- A subroutine call to a subpattern (recursive or otherwise)\n\nThe general repetition quantifier specifies a minimum and maximum number of\npermitted matches, by giving the two numbers in curly brackets (braces),\nseparated by a comma. The numbers must be < 65536, and the first must be less\nthan or equal to the second. For example, the following matches \"zz\", \"zzz\", or\n\"zzzz\":\n\n```text\nz{2,4}\n```\n\nA closing brace on its own is not a special character. If the second number is\nomitted, but the comma is present, there is no upper limit. If the second number\nand the comma are both omitted, the quantifier specifies an exact number of\nrequired matches. Thus, the following matches at least three successive vowels,\nbut can match many more:\n\n```text\n[aeiou]{3,}\n```\n\nThe following matches exactly eight digits:\n\n```text\n\\d{8}\n```\n\nAn opening curly bracket that appears in a position where a quantifier is not\nallowed, or one that does not match the syntax of a quantifier, is taken as a\nliteral character. For example, \\{,6\\} is not a quantifier, but a literal string\nof four characters.\n\nIn Unicode mode, quantifiers apply to characters rather than to individual data\nunits. Thus, for example, `\\x{100}{2}` matches two characters, each of which\nis represented by a 2-byte sequence in a UTF-8 string. Similarly, `\\X{3}`\nmatches three Unicode extended grapheme clusters, each of which can be many data\nunits long (and they can be of different lengths).\n\nThe quantifier \\{0\\} is permitted, causing the expression to behave as if the\nprevious item and the quantifier were not present. This can be useful for\nsubpatterns that are referenced as subroutines from elsewhere in the pattern\n(but see also section\n[Defining Subpatterns for Use by Reference Only](`m:re#defining_subpatterns`)).\nItems other than subpatterns that have a \\{0\\} quantifier are omitted from the\ncompiled pattern.\n\nFor convenience, the three most common quantifiers have single-character\nabbreviations:\n\n- **\\*** - Equivalent to \\{0,\\}\n\n- **+** - Equivalent to \\{1,\\}\n\n- **?** - Equivalent to \\{0,1\\}\n\nInfinite loops can be constructed by following a subpattern that can match no\ncharacters with a quantifier that has no upper limit, for example:\n\n```text\n(a?)*\n```\n\nEarlier versions of Perl and PCRE used to give an error at compile time for such\npatterns. However, as there are cases where this can be useful, such patterns\nare now accepted. However, if any repetition of the subpattern matches no\ncharacters, the loop is forcibly broken.\n\nBy default, the quantifiers are \"greedy\", that is, they match as much as\npossible (up to the maximum number of permitted times), without causing the\nremaining pattern to fail. The classic example of where this gives problems is\nin trying to match comments in C programs. These appear between /_ and _/.\nWithin the comment, individual \\* and / characters can appear. An attempt to\nmatch C comments by applying the pattern\n\n```text\n/\\*.*\\*/\n```\n\nto the string\n\n```text\n/* first comment */ not comment /* second comment */\n```\n\nfails, as it matches the entire string owing to the greediness of the .\\* item.\n\nHowever, if a quantifier is followed by a question mark, it ceases to be greedy,\nand instead matches the minimum number of times possible, so the following\npattern does the right thing with the C comments:\n\n```text\n/\\*.*?\\*/\n```\n\nThe meaning of the various quantifiers is not otherwise changed, only the\npreferred number of matches. Do not confuse this use of question mark with its\nuse as a quantifier in its own right. As it has two uses, it can sometimes\nappear doubled, as in\n\n```text\n\\d??\\d\n```\n\nwhich matches one digit by preference, but can match two if that is the only way\nthe remaining pattern matches.\n\nIf option `ungreedy` is set (an option that is not available in Perl), the\nquantifiers are not greedy by default, but individual ones can be made greedy by\nfollowing them with a question mark. That is, it inverts the default behavior.\n\nWhen a parenthesized subpattern is quantified with a minimum repeat count that\nis > 1 or with a limited maximum, more memory is required for the compiled\npattern, in proportion to the size of the minimum or maximum.\n\nIf a pattern starts with .\\* or .\\{0,\\} and option `dotall` (equivalent to Perl\noption `/s`) is set, thus allowing the dot to match newlines, the pattern is\nimplicitly anchored, because whatever follows is tried against every character\nposition in the subject string. So, there is no point in retrying the overall\nmatch at any position after the first. PCRE normally treats such a pattern as if\nit was preceded by `\\A`.\n\nIn cases where it is known that the subject string contains no newlines, it is\nworth setting `dotall` to obtain this optimization, or alternatively using ^ to\nindicate anchoring explicitly.\n\nHowever, there are some cases where the optimization cannot be used. When .\\* is\ninside capturing parentheses that are the subject of a back reference elsewhere\nin the pattern, a match at the start can fail where a later one succeeds.\nConsider, for example:\n\n```text\n(.*)abc\\1\n```\n\nIf the subject is \"xyz123abc123\", the match point is the fourth character.\nTherefore, such a pattern is not implicitly anchored.\n\nAnother case where implicit anchoring is not applied is when the leading .\\* is\ninside an atomic group. Once again, a match at the start can fail where a later\none succeeds. Consider the following pattern:\n\n```text\n(?>.*?a)b\n```\n\nIt matches \"ab\" in the subject \"aab\". The use of the backtracking control verbs\n(*PRUNE) and (*SKIP) also disable this optimization.\n\nWhen a capturing subpattern is repeated, the value captured is the substring\nthat matched the final iteration. For example, after\n\n```text\n(tweedle[dume]{3}\\s*)+\n```\n\nhas matched \"tweedledum tweedledee\", the value of the captured substring is\n\"tweedledee\". However, if there are nested capturing subpatterns, the\ncorresponding captured values can have been set in previous iterations. For\nexample, after\n\n```text\n/(a|(b))+/\n```\n\nmatches \"aba\", the value of the second captured substring is \"b\".\n\n[](){: #sect15 }","title":"Repetition - re","ref":"re.html#module-repetition"},{"type":"module","doc":"With both maximizing (\"greedy\") and minimizing (\"ungreedy\" or \"lazy\")\nrepetition, failure of what follows normally causes the repeated item to be\nre-evaluated to see if a different number of repeats allows the remaining\npattern to match. Sometimes it is useful to prevent this, either to change the\nnature of the match, or to cause it to fail earlier than it otherwise might,\nwhen the author of the pattern knows that there is no point in carrying on.\n\nConsider, for example, the pattern `\\d+foo` when applied to the following subject\nline:\n\n```text\n123456bar\n```\n\nAfter matching all six digits and then failing to match \"foo\", the normal action\nof the matcher is to try again with only five digits matching item `\\d+`, and\nthen with four, and so on, before ultimately failing. \"Atomic grouping\" (a term\ntaken from Jeffrey Friedl's book) provides the means for specifying that once a\nsubpattern has matched, it is not to be re-evaluated in this way.\n\nIf atomic grouping is used for the previous example, the matcher gives up\nimmediately on failing to match \"foo\" the first time. The notation is a kind of\nspecial parenthesis, starting with `(?>` as in the following example:\n\n```text\n(?>\\d+)foo\n```\n\nThis kind of parenthesis \"locks up\" the part of the pattern it contains once it\nhas matched, and a failure further into the pattern is prevented from\nbacktracking into it. Backtracking past it to previous items, however, works as\nnormal.\n\nAn alternative description is that a subpattern of this type matches the string\nof characters that an identical standalone pattern would match, if anchored at\nthe current point in the subject string.\n\nAtomic grouping subpatterns are not capturing subpatterns. Simple cases such as\nthe above example can be thought of as a maximizing repeat that must swallow\neverything it can. So, while both `\\d+` and `\\d+?` are prepared to adjust the\nnumber of digits they match to make the remaining pattern match, `(?>\\d+)` can\nonly match an entire sequence of digits.\n\nAtomic groups in general can contain any complicated subpatterns, and can be\nnested. However, when the subpattern for an atomic group is just a single\nrepeated item, as in the example above, a simpler notation, called a \"possessive\nquantifier\" can be used. This consists of an extra + character following a\nquantifier. Using this notation, the previous example can be rewritten as\n\n```text\n\\d++foo\n```\n\nNotice that a possessive quantifier can be used with an entire group, for\nexample:\n\n```text\n(abc|xyz){2,3}+\n```\n\nPossessive quantifiers are always greedy; the setting of option `ungreedy` is\nignored. They are a convenient notation for the simpler forms of an atomic\ngroup. However, there is no difference in the meaning of a possessive quantifier\nand the equivalent atomic group, but there can be a performance difference;\npossessive quantifiers are probably slightly faster.\n\nThe possessive quantifier syntax is an extension to the Perl 5.8 syntax. Jeffrey\nFriedl originated the idea (and the name) in the first edition of his book. Mike\nMcCloskey liked it, so implemented it when he built the Sun Java package, and\nPCRE copied it from there. It ultimately found its way into Perl at release\n5.10.\n\nPCRE has an optimization that automatically \"possessifies\" certain simple\npattern constructs. For example, the sequence A+B is treated as A++B, as there\nis no point in backtracking into a sequence of A:s when B must follow.\n\nWhen a pattern contains an unlimited repeat inside a subpattern that can itself\nbe repeated an unlimited number of times, the use of an atomic group is the only\nway to avoid some failing matches taking a long time. The pattern\n\n```text\n(\\D+|<\\d+>)*[!?]\n```\n\nmatches an unlimited number of substrings that either consist of non-digits, or\ndigits enclosed in `<>`, followed by `!` or `?`. When it matches, it runs quickly.\nHowever, if it is applied to\n\n```text\naaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n```\n\nit takes a long time before reporting failure. This is because the string can be\ndivided between the internal `\\D+` repeat and the external \\* repeat in many\nways, and all must be tried. (The example uses `[!?]` rather than a single\ncharacter at the end, as both PCRE and Perl have an optimization that allows for\nfast failure when a single character is used. They remember the last single\ncharacter that is required for a match, and fail early if it is not present in\nthe string.) If the pattern is changed so that it uses an atomic group, like the\nfollowing, sequences of non-digits cannot be broken, and failure happens\nquickly:\n\n```text\n((?>\\D+)|<\\d+>)*[!?]\n```\n\n[](){: #sect16 }","title":"Atomic Grouping and Possessive Quantifiers - re","ref":"re.html#module-atomic-grouping-and-possessive-quantifiers"},{"type":"module","doc":"Outside a character class, a backslash followed by a digit > 0 (and possibly\nfurther digits) is a back reference to a capturing subpattern earlier (that is,\nto its left) in the pattern, provided there have been that many previous\ncapturing left parentheses.\n\nHowever, if the decimal number following the backslash is < 10, it is always\ntaken as a back reference, and causes an error only if there are not that many\ncapturing left parentheses in the entire pattern. That is, the parentheses that\nare referenced do need not be to the left of the reference for numbers < 10. A\n\"forward back reference\" of this type can make sense when a repetition is\ninvolved and the subpattern to the right has participated in an earlier\niteration.\n\nIt is not possible to have a numerical \"forward back reference\" to a subpattern\nwhose number is 10 or more using this syntax, as a sequence such as `\\50` is\ninterpreted as a character defined in octal. For more details of the handling of\ndigits following a backslash, see section\n[Non-Printing Characters](`m:re#non_printing_characters`) earlier. There is no\nsuch problem when named parentheses are used. A back reference to any subpattern\nis possible using named parentheses (see below).\n\nAnother way to avoid the ambiguity inherent in the use of digits following a\nbackslash is to use the `\\g` escape sequence. This escape must be followed by an\nunsigned number or a negative number, optionally enclosed in braces. The\nfollowing examples are identical:\n\n```text\n(ring), \\1\n(ring), \\g1\n(ring), \\g{1}\n```\n\nAn unsigned number specifies an absolute reference without the ambiguity that is\npresent in the older syntax. It is also useful when literal digits follow the\nreference. A negative number is a relative reference. Consider the following\nexample:\n\n```text\n(abc(def)ghi)\\g{-1}\n```\n\nThe sequence `\\g{-1}` is a reference to the most recently started capturing\nsubpattern before `\\g`, that is, it is equivalent to `\\2` in this example.\nSimilarly, `\\g{-2}` would be equivalent to `\\1`. The use of relative references\ncan be helpful in long patterns, and also in patterns that are created by\njoining fragments containing references within themselves.\n\nA back reference matches whatever matched the capturing subpattern in the\ncurrent subject string, rather than anything matching the subpattern itself\n(section [Subpattern as Subroutines](`m:re#sect21`) describes a way of doing\nthat). So, the following pattern matches \"sense and sensibility\" and \"response\nand responsibility\", but not \"sense and responsibility\":\n\n```text\n(sens|respons)e and \\1ibility\n```\n\nIf caseful matching is in force at the time of the back reference, the case of\nletters is relevant. For example, the following matches \"rah rah\" and \"RAH RAH\",\nbut not \"RAH rah\", although the original capturing subpattern is matched\ncaselessly:\n\n```text\n((?i)rah)\\s+\\1\n```\n\nThere are many different ways of writing back references to named subpatterns.\nThe .NET syntax `\\k{name}` and the Perl syntax `\\k ` or `\\k'name'` are\nsupported, as is the Python syntax `(?P=name)`. The unified back reference\nsyntax in Perl 5.10, in which `\\g` can be used for both numeric and named\nreferences, is also supported. The previous example can be rewritten in the\nfollowing ways:\n\n```text\n(? (?i)rah)\\s+\\k \n(?'p1'(?i)rah)\\s+\\k{p1}\n(?P (?i)rah)\\s+(?P=p1)\n(? (?i)rah)\\s+\\g{p1}\n```\n\nA subpattern that is referenced by name can appear in the pattern before or\nafter the reference.\n\nThere can be more than one back reference to the same subpattern. If a\nsubpattern has not been used in a particular match, any back references to it\nalways fails. For example, the following pattern always fails if it starts to\nmatch \"a\" rather than \"bc\":\n\n```text\n(a|(bc))\\2\n```\n\nAs there can be many capturing parentheses in a pattern, all digits following\nthe backslash are taken as part of a potential back reference number. If the\npattern continues with a digit character, some delimiter must be used to\nterminate the back reference. If option `extended` is set, this can be\nwhitespace. Otherwise an empty comment (see section [Comments](`m:re#sect19`))\ncan be used.\n\n_Recursive Back References_\n\nA back reference that occurs inside the parentheses to which it refers fails\nwhen the subpattern is first used, so, for example, (`a\\1`) never matches.\nHowever, such references can be useful inside repeated subpatterns. For example,\nthe following pattern matches any number of \"a\"s and also \"aba\", \"ababbaa\", and\nso on:\n\n```text\n(a|b\\1)+\n```\n\nAt each iteration of the subpattern, the back reference matches the character\nstring corresponding to the previous iteration. In order for this to work, the\npattern must be such that the first iteration does not need to match the back\nreference. This can be done using alternation, as in the example above, or by a\nquantifier with a minimum of zero.\n\nBack references of this type cause the group that they reference to be treated\nas an atomic group. Once the whole group has been matched, a subsequent matching\nfailure cannot cause backtracking into the middle of the group.\n\n[](){: #sect17 }","title":"Back References - re","ref":"re.html#module-back-references"},{"type":"module","doc":"An assertion is a test on the characters following or preceding the current\nmatching point that does not consume any characters. The simple assertions coded\nas `\\b`, `\\B`, `\\A`, `\\G`, `\\Z`, `\\z`, `^`, and `$` are described in the previous\nsections.\n\nMore complicated assertions are coded as subpatterns. There are two kinds: those\nthat look ahead of the current position in the subject string, and those that\nlook behind it. An assertion subpattern is matched in the normal way, except\nthat it does not cause the current matching position to be changed.\n\nAssertion subpatterns are not capturing subpatterns. If such an assertion\ncontains capturing subpatterns within it, these are counted for the purposes of\nnumbering the capturing subpatterns in the whole pattern. However, substring\ncapturing is done only for positive assertions. (Perl sometimes, but not always,\nperforms capturing in negative assertions.)\n\n> #### Warning {: .warning }\n>\n> If a positive assertion containing one or more capturing subpatterns succeeds,\n> but failure to match later in the pattern causes backtracking over this\n> assertion, the captures within the assertion are reset only if no higher\n> numbered captures are already set. This is, unfortunately, a fundamental\n> limitation of the current implementation, and as PCRE1 is now in\n> maintenance-only status, it is unlikely ever to change.\n\nFor compatibility with Perl, assertion subpatterns can be repeated. However, it\nmakes no sense to assert the same thing many times, the side effect of capturing\nparentheses can occasionally be useful. In practice, there are only three cases:\n\n- If the quantifier is \\{0\\}, the assertion is never obeyed during matching.\n However, it can contain internal capturing parenthesized groups that are\n called from elsewhere through the subroutine mechanism.\n- If quantifier is \\{0,n\\}, where n > 0, it is treated as if it was \\{0,1\\}. At\n runtime, the remaining pattern match is tried with and without the assertion,\n the order depends on the greediness of the quantifier.\n- If the minimum repetition is > 0, the quantifier is ignored. The assertion is\n obeyed only once when encountered during matching.\n\n_Lookahead Assertions_\n\nLookahead assertions start with (?= for positive assertions and (?\\! for\nnegative assertions. For example, the following matches a word followed by a\nsemicolon, but does not include the semicolon in the match:\n\n```text\n\\w+(?=;)\n```\n\nThe following matches any occurrence of \"foo\" that is not followed by \"bar\":\n\n```text\nfoo(?!bar)\n```\n\nNotice that the apparently similar pattern\n\n```text\n(?!foo)bar\n```\n\ndoes not find an occurrence of \"bar\" that is preceded by something other than\n\"foo\". It finds any occurrence of \"bar\" whatsoever, as the assertion (?\\!foo) is\nalways true when the next three characters are \"bar\". A lookbehind assertion is\nneeded to achieve the other effect.\n\nIf you want to force a matching failure at some point in a pattern, the most\nconvenient way to do it is with (?\\!), as an empty string always matches. So, an\nassertion that requires there is not to be an empty string must always fail. The\nbacktracking control verb (*FAIL) or (*F) is a synonym for (?\\!).\n\n_Lookbehind Assertions_\n\nLookbehind assertions start with (?<= for positive assertions and (?<\\! for\nnegative assertions. For example, the following finds an occurrence of \"bar\"\nthat is not preceded by \"foo\":\n\n```text\n(?[^()]+) | (?p{$re}) )* \\)}x;\n```\n\nItem (?p\\{...\\}) interpolates Perl code at runtime, and in this case refers\nrecursively to the pattern in which it appears.\n\nObviously, PCRE cannot support the interpolation of Perl code. Instead, it\nsupports special syntax for recursion of the entire pattern, and for individual\nsubpattern recursion. After its introduction in PCRE and Python, this kind of\nrecursion was later introduced into Perl at release 5.10.\n\nA special item that consists of (? followed by a number > 0 and a closing\nparenthesis is a recursive subroutine call of the subpattern of the given\nnumber, if it occurs inside that subpattern. (If not, it is a non-recursive\nsubroutine call, which is described in the next section.) The special item (?R)\nor (?0) is a recursive call of the entire regular expression.\n\nThis PCRE pattern solves the nested parentheses problem (assume that option\n`extended` is set so that whitespace is ignored):\n\n```text\n\\( ( [^()]++ | (?R) )* \\)\n```\n\nFirst it matches an opening parenthesis. Then it matches any number of\nsubstrings, which can either be a sequence of non-parentheses or a recursive\nmatch of the pattern itself (that is, a correctly parenthesized substring).\nFinally there is a closing parenthesis. Notice the use of a possessive\nquantifier to avoid backtracking into sequences of non-parentheses.\n\nIf this was part of a larger pattern, you would not want to recurse the entire\npattern, so instead you can use:\n\n```text\n( \\( ( [^()]++ | (?1) )* \\) )\n```\n\nThe pattern is here within parentheses so that the recursion refers to them\ninstead of the whole pattern.\n\nIn a larger pattern, keeping track of parenthesis numbers can be tricky. This is\nmade easier by the use of relative references. Instead of (?1) in the pattern\nabove, you can write (?-2) to refer to the second most recently opened\nparentheses preceding the recursion. That is, a negative number counts capturing\nparentheses leftwards from the point at which it is encountered.\n\nIt is also possible to refer to later opened parentheses, by writing references\nsuch as (?+2). However, these cannot be recursive, as the reference is not\ninside the parentheses that are referenced. They are always non-recursive\nsubroutine calls, as described in the next section.\n\nAn alternative approach is to use named parentheses instead. The Perl syntax for\nthis is (?&name). The earlier PCRE syntax (?P>name) is also supported. We can\nrewrite the above example as follows:\n\n```text\n(? \\( ( [^()]++ | (?&pn) )* \\) )\n```\n\nIf there is more than one subpattern with the same name, the earliest one is\nused.\n\nThis particular example pattern that we have studied contains nested unlimited\nrepeats, and so the use of a possessive quantifier for matching strings of\nnon-parentheses is important when applying the pattern to strings that do not\nmatch. For example, when this pattern is applied to\n\n```text\n(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa()\n```\n\nit gives \"no match\" quickly. However, if a possessive quantifier is not used,\nthe match runs for a long time, as there are so many different ways the + and \\*\nrepeats can carve up the subject, and all must be tested before failure can be\nreported.\n\nAt the end of a match, the values of capturing parentheses are those from the\noutermost level. If the pattern above is matched against\n\n```text\n(ab(cd)ef)\n```\n\nthe value for the inner capturing parentheses (numbered 2) is \"ef\", which is the\nlast value taken on at the top-level. If a capturing subpattern is not matched\nat the top level, its final captured value is unset, even if it was\n(temporarily) set at a deeper level during the matching process.\n\nDo not confuse item (?R) with condition (R), which tests for recursion. Consider\nthe following pattern, which matches text in angle brackets, allowing for\narbitrary nesting. Only digits are allowed in nested brackets (that is, when\nrecursing), while any characters are permitted at the outer level.\n\n```text\n< (?: (?(R) \\d++ | [^<>]*+) | (?R)) * >\n```\n\nHere (?(R) is the start of a conditional subpattern, with two different\nalternatives for the recursive and non-recursive cases. Item (?R) is the actual\nrecursive call.\n\n_Differences in Recursion Processing between PCRE and Perl_\n\nRecursion processing in PCRE differs from Perl in two important ways. In PCRE\n(like Python, but unlike Perl), a recursive subpattern call is always treated as\nan atomic group. That is, once it has matched some of the subject string, it is\nnever re-entered, even if it contains untried alternatives and there is a\nsubsequent matching failure. This can be illustrated by the following pattern,\nwhich means to match a palindromic string containing an odd number of characters\n(for example, \"a\", \"aba\", \"abcba\", \"abcdcba\"):\n\n```text\n^(.|(.)(?1)\\2)$\n```\n\nThe idea is that it either matches a single character, or two identical\ncharacters surrounding a subpalindrome. In Perl, this pattern works; in PCRE it\ndoes not work if the pattern is longer than three characters. Consider the\nsubject string \"abcba\".\n\nAt the top level, the first character is matched, but as it is not at the end of\nthe string, the first alternative fails, the second alternative is taken, and\nthe recursion kicks in. The recursive call to subpattern 1 successfully matches\nthe next character (\"b\"). (Notice that the beginning and end of line tests are\nnot part of the recursion.)\n\nBack at the top level, the next character (\"c\") is compared with what subpattern\n2 matched, which was \"a\". This fails. As the recursion is treated as an atomic\ngroup, there are now no backtracking points, and so the entire match fails.\n(Perl can now re-enter the recursion and try the second alternative.) However,\nif the pattern is written with the alternatives in the other order, things are\ndifferent:\n\n```text\n^((.)(?1)\\2|.)$\n```\n\nThis time, the recursing alternative is tried first, and continues to recurse\nuntil it runs out of characters, at which point the recursion fails. But this\ntime we have another alternative to try at the higher level. That is the\nsignificant difference: in the previous case the remaining alternative is at a\ndeeper recursion level, which PCRE cannot use.\n\nTo change the pattern so that it matches all palindromic strings, not only those\nwith an odd number of characters, it is tempting to change the pattern to this:\n\n```text\n^((.)(?1)\\2|.?)$\n```\n\nAgain, this works in Perl, but not in PCRE, and for the same reason. When a\ndeeper recursion has matched a single character, it cannot be entered again to\nmatch an empty string. The solution is to separate the two cases, and write out\nthe odd and even cases as alternatives at the higher level:\n\n```text\n^(?:((.)(?1)\\2|)|((.)(?3)\\4|.))\n```\n\nIf you want to match typical palindromic phrases, the pattern must ignore all\nnon-word characters, which can be done as follows:\n\n```text\n^\\W*+(?:((.)\\W*+(?1)\\W*+\\2|)|((.)\\W*+(?3)\\W*+\\4|\\W*+.\\W*+))\\W*+$\n```\n\nIf run with option `caseless`, this pattern matches phrases such as \"A man, a\nplan, a canal: Panama\\!\" and it works well in both PCRE and Perl. Notice the use\nof the possessive quantifier \\*+ to avoid backtracking into sequences of\nnon-word characters. Without this, PCRE takes much longer (10 times or more) to\nmatch typical phrases, and Perl takes so long that you think it has gone into a\nloop.\n\n> #### Note {: .info }\n>\n> The palindrome-matching patterns above work only if the subject string does\n> not start with a palindrome that is shorter than the entire string. For\n> example, although \"abcba\" is correctly matched, if the subject is \"ababa\",\n> PCRE finds palindrome \"aba\" at the start, and then fails at top level, as the\n> end of the string does not follow. Once again, it cannot jump back into the\n> recursion to try other alternatives, so the entire match fails.\n\nThe second way in which PCRE and Perl differ in their recursion processing is in\nthe handling of captured values. In Perl, when a subpattern is called\nrecursively or as a subpattern (see the next section), it has no access to any\nvalues that were captured outside the recursion. In PCRE these values can be\nreferenced. Consider the following pattern:\n\n```text\n^(.)(\\1|a(?2))\n```\n\nIn PCRE, it matches \"bab\". The first capturing parentheses match \"b\", then in\nthe second group, when the back reference `\\1` fails to match \"b\", the second\nalternative matches \"a\", and then recurses. In the recursion, `\\1` does now match\n\"b\" and so the whole match succeeds. In Perl, the pattern fails to match because\ninside the recursive call `\\1` cannot access the externally set value.\n\n[](){: #sect21 }","title":"Recursive Patterns - re","ref":"re.html#module-recursive-patterns"},{"type":"module","doc":"If the syntax for a recursive subpattern call (either by number or by name) is\nused outside the parentheses to which it refers, it operates like a subroutine\nin a programming language. The called subpattern can be defined before or after\nthe reference. A numbered reference can be absolute or relative, as in the\nfollowing examples:\n\n```text\n(...(absolute)...)...(?2)...\n(...(relative)...)...(?-1)...\n(...(?+1)...(relative)...\n```\n\nAn earlier example pointed out that the following pattern matches \"sense and\nsensibility\" and \"response and responsibility\", but not \"sense and\nresponsibility\":\n\n```text\n(sens|respons)e and \\1ibility\n```\n\nIf instead the following pattern is used, it matches \"sense and responsibility\"\nand the other two strings:\n\n```text\n(sens|respons)e and (?1)ibility\n```\n\nAnother example is provided in the discussion of DEFINE earlier.\n\nAll subroutine calls, recursive or not, are always treated as atomic groups.\nThat is, once a subroutine has matched some of the subject string, it is never\nre-entered, even if it contains untried alternatives and there is a subsequent\nmatching failure. Any capturing parentheses that are set during the subroutine\ncall revert to their previous values afterwards.\n\nProcessing options such as case-independence are fixed when a subpattern is\ndefined, so if it is used as a subroutine, such options cannot be changed for\ndifferent calls. For example, the following pattern matches \"abcabc\" but not\n\"abcABC\", as the change of processing option does not affect the called\nsubpattern:\n\n```text\n(abc)(?i:(?-1))\n```\n\n[](){: #sect22 }","title":"Subpatterns as Subroutines - re","ref":"re.html#module-subpatterns-as-subroutines"},{"type":"module","doc":"For compatibility with Oniguruma, the non-Perl syntax `\\g` followed by a name or\na number enclosed either in angle brackets or single quotes, is alternative\nsyntax for referencing a subpattern as a subroutine, possibly recursively. Here\nfollows two of the examples used above, rewritten using this syntax:\n\n```text\n(? \\( ( (?>[^()]+) | \\g )* \\) )\n(sens|respons)e and \\g'1'ibility\n```\n\nPCRE supports an extension to Oniguruma: if a number is preceded by a plus or\nminus sign, it is taken as a relative reference, for example:\n\n```text\n(abc)(?i:\\g<-1>)\n```\n\nNotice that `\\g{...}` (Perl syntax) and `\\g<...>` (Oniguruma syntax) are _not_\nsynonymous. The former is a back reference; the latter is a subroutine call.\n\n[](){: #sect23 }","title":"Oniguruma Subroutine Syntax - re","ref":"re.html#module-oniguruma-subroutine-syntax"},{"type":"module","doc":"Perl 5.10 introduced some \"Special Backtracking Control Verbs\", which are still\ndescribed in the Perl documentation as \"experimental and subject to change or\nremoval in a future version of Perl\". It goes on to say: \"Their usage in\nproduction code should be noted to avoid problems during upgrades.\" The same\nremarks apply to the PCRE features described in this section.\n\nThe new verbs make use of what was previously invalid syntax: an opening\nparenthesis followed by an asterisk. They are generally of the form (*VERB) or\n(*VERB:NAME). Some can take either form, possibly behaving differently depending\non whether a name is present. A name is any sequence of characters that does not\ninclude a closing parenthesis. The maximum name length is 255 in the 8-bit\nlibrary and 65535 in the 16-bit and 32-bit libraries. If the name is empty, that\nis, if the closing parenthesis immediately follows the colon, the effect is as\nif the colon was not there. Any number of these verbs can occur in a pattern.\n\nThe behavior of these verbs in repeated groups, assertions, and in subpatterns\ncalled as subroutines (whether or not recursively) is described below.\n\n_Optimizations That Affect Backtracking Verbs_\n\nPCRE contains some optimizations that are used to speed up matching by running\nsome checks at the start of each match attempt. For example, it can know the\nminimum length of matching subject, or that a particular character must be\npresent. When one of these optimizations bypasses the running of a match, any\nincluded backtracking verbs are not processed. processed. You can suppress the\nstart-of-match optimizations by setting option `no_start_optimize` when calling\n`compile/2` or `run/3`, or by starting the pattern with (\\*NO_START_OPT).\n\nExperiments with Perl suggest that it too has similar optimizations, sometimes\nleading to anomalous results.\n\n_Verbs That Act Immediately_\n\nThe following verbs act as soon as they are encountered. They must not be\nfollowed by a name.\n\n```text\n(*ACCEPT)\n```\n\nThis verb causes the match to end successfully, skipping the remainder of the\npattern. However, when it is inside a subpattern that is called as a subroutine,\nonly that subpattern is ended successfully. Matching then continues at the outer\nlevel. If (\\*ACCEPT) is triggered in a positive assertion, the assertion\nsucceeds; in a negative assertion, the assertion fails.\n\nIf (\\*ACCEPT) is inside capturing parentheses, the data so far is captured. For\nexample, the following matches \"AB\", \"AAD\", or \"ACD\". When it matches \"AB\", \"B\"\nis captured by the outer parentheses.\n\n```text\nA((?:A|B(*ACCEPT)|C)D)\n```\n\nThe following verb causes a matching failure, forcing backtracking to occur. It\nis equivalent to (?\\!) but easier to read.\n\n```text\n(*FAIL) or (*F)\n```\n\nThe Perl documentation states that it is probably useful only when combined with\n(?\\{\\}) or (??\\{\\}). Those are Perl features that are not present in PCRE.\n\nA match with the string \"aaaa\" always fails, but the callout is taken before\neach backtrack occurs (in this example, 10 times).\n\n_Recording Which Path Was Taken_\n\nThe main purpose of this verb is to track how a match was arrived at, although\nit also has a secondary use in with advancing the match starting point (see\n(\\*SKIP) below).\n\n> #### Note {: .info }\n>\n> In Erlang, there is no interface to retrieve a mark with [`run/2,3`](`run/2`),\n> so only the secondary purpose is relevant to the Erlang programmer.\n>\n> The rest of this section is therefore deliberately not adapted for reading by\n> the Erlang programmer, but the examples can help in understanding NAMES as\n> they can be used by (\\*SKIP).\n\n```text\n(*MARK:NAME) or (*:NAME)\n```\n\nA name is always required with this verb. There can be as many instances of\n(\\*MARK) as you like in a pattern, and their names do not have to be unique.\n\nWhen a match succeeds, the name of the last encountered (*MARK:NAME),\n(*PRUNE:NAME), or (*THEN:NAME) on the matching path is passed back to the caller\nas described in section \"Extra data for `pcre_exec()`\" in the `pcreapi`\ndocumentation. In the following example of `pcretest` output, the /K modifier\nrequests the retrieval and outputting of (*MARK) data:\n\n```text\nre> /X(*MARK:A)Y|X(*MARK:B)Z/K\ndata> XY\n 0: XY\nMK: A\nXZ\n 0: XZ\nMK: B\n```\n\nThe (\\*MARK) name is tagged with \"MK:\" in this output, and in this example it\nindicates which of the two alternatives matched. This is a more efficient way of\nobtaining this information than putting each alternative in its own capturing\nparentheses.\n\nIf a verb with a name is encountered in a positive assertion that is true, the\nname is recorded and passed back if it is the last encountered. This does not\noccur for negative assertions or failing positive assertions.\n\nAfter a partial match or a failed match, the last encountered name in the entire\nmatch process is returned, for example:\n\n```text\nre> /X(*MARK:A)Y|X(*MARK:B)Z/K\ndata> XP\nNo match, mark = B\n```\n\nNotice that in this unanchored example, the mark is retained from the match\nattempt that started at letter \"X\" in the subject. Subsequent match attempts\nstarting at \"P\" and then with an empty string do not get as far as the (\\*MARK)\nitem, nevertheless do not reset it.\n\n_Verbs That Act after Backtracking_\n\nThe following verbs do nothing when they are encountered. Matching continues\nwith what follows, but if there is no subsequent match, causing a backtrack to\nthe verb, a failure is forced. That is, backtracking cannot pass to the left of\nthe verb. However, when one of these verbs appears inside an atomic group or an\nassertion that is true, its effect is confined to that group, as once the group\nhas been matched, there is never any backtracking into it. In this situation,\nbacktracking can \"jump back\" to the left of the entire atomic group or\nassertion. (Remember also, as stated above, that this localization also applies\nin subroutine calls.)\n\nThese verbs differ in exactly what kind of failure occurs when backtracking\nreaches them. The behavior described below is what occurs when the verb is not\nin a subroutine or an assertion. Subsequent sections cover these special cases.\n\nThe following verb, which must not be followed by a name, causes the whole match\nto fail outright if there is a later matching failure that causes backtracking\nto reach it. Even if the pattern is unanchored, no further attempts to find a\nmatch by advancing the starting point take place.\n\n```text\n(*COMMIT)\n```\n\nIf (\\*COMMIT) is the only backtracking verb that is encountered, once it has\nbeen passed, [`run/2,3`](`run/2`) is committed to find a match at the current\nstarting point, or not at all, for example:\n\n```text\na+(*COMMIT)b\n```\n\nThis matches \"xxaab\" but not \"aacaab\". It can be thought of as a kind of dynamic\nanchor, or \"I've started, so I must finish\". The name of the most recently\npassed (*MARK) in the path is passed back when (*COMMIT) forces a match failure.\n\nIf more than one backtracking verb exists in a pattern, a different one that\nfollows (*COMMIT) can be triggered first, so merely passing (*COMMIT) during a\nmatch does not always guarantee that a match must be at this starting point.\n\nNotice that (\\*COMMIT) at the start of a pattern is not the same as an anchor,\nunless the PCRE start-of-match optimizations are turned off, as shown in the\nfollowing example:\n\n```erlang\n1> re:run(\"xyzabc\",\"(*COMMIT)abc\",[{capture,all,list}]).\n{match,[\"abc\"]}\n2> re:run(\"xyzabc\",\"(*COMMIT)abc\",[{capture,all,list},no_start_optimize]).\nnomatch\n```\n\nFor this pattern, PCRE knows that any match must start with \"a\", so the\noptimization skips along the subject to \"a\" before applying the pattern to the\nfirst set of data. The match attempt then succeeds. In the second call the\n`no_start_optimize` disables the optimization that skips along to the first\ncharacter. The pattern is now applied starting at \"x\", and so the (\\*COMMIT)\ncauses the match to fail without trying any other starting points.\n\nThe following verb causes the match to fail at the current starting position in\nthe subject if there is a later matching failure that causes backtracking to\nreach it:\n\n```text\n(*PRUNE) or (*PRUNE:NAME)\n```\n\nIf the pattern is unanchored, the normal \"bumpalong\" advance to the next\nstarting character then occurs. Backtracking can occur as usual to the left of\n(*PRUNE), before it is reached, or when matching to the right of (*PRUNE), but\nif there is no match to the right, backtracking cannot cross (*PRUNE). In simple\ncases, the use of (*PRUNE) is just an alternative to an atomic group or\npossessive quantifier, but there are some uses of (*PRUNE) that cannot be\nexpressed in any other way. In an anchored pattern, (*PRUNE) has the same effect\nas (\\*COMMIT).\n\nThe behavior of (*PRUNE:NAME) is the not the same as (*MARK:NAME)(*PRUNE). It is\nlike (*MARK:NAME) in that the name is remembered for passing back to the caller.\nHowever, (*SKIP:NAME) searches only for names set with (*MARK).\n\n> #### Note {: .info }\n>\n> The fact that (\\*PRUNE:NAME) remembers the name is useless to the Erlang\n> programmer, as names cannot be retrieved.\n\nThe following verb, when specified without a name, is like (*PRUNE), except that\nif the pattern is unanchored, the \"bumpalong\" advance is not to the next\ncharacter, but to the position in the subject where (*SKIP) was encountered.\n\n```text\n(*SKIP)\n```\n\n(\\*SKIP) signifies that whatever text was matched leading up to it cannot be\npart of a successful match. Consider:\n\n```text\na+(*SKIP)b\n```\n\nIf the subject is \"aaaac...\", after the first match attempt fails (starting at\nthe first character in the string), the starting point skips on to start the\nnext attempt at \"c\". Notice that a possessive quantifier does not have the same\neffect as this example; although it would suppress backtracking during the first\nmatch attempt, the second attempt would start at the second character instead of\nskipping on to \"c\".\n\nWhen (\\*SKIP) has an associated name, its behavior is modified:\n\n```text\n(*SKIP:NAME)\n```\n\nWhen this is triggered, the previous path through the pattern is searched for\nthe most recent (*MARK) that has the same name. If one is found, the \"bumpalong\"\nadvance is to the subject position that corresponds to that (*MARK) instead of\nto where (*SKIP) was encountered. If no (*MARK) with a matching name is found,\n(\\*SKIP) is ignored.\n\nNotice that (*SKIP:NAME) searches only for names set by (*MARK:NAME). It ignores\nnames that are set by (*PRUNE:NAME) or (*THEN:NAME).\n\nThe following verb causes a skip to the next innermost alternative when\nbacktracking reaches it. That is, it cancels any further backtracking within the\ncurrent alternative.\n\n```text\n(*THEN) or (*THEN:NAME)\n```\n\nThe verb name comes from the observation that it can be used for a pattern-based\nif-then-else block:\n\n```text\n( COND1 (*THEN) FOO | COND2 (*THEN) BAR | COND3 (*THEN) BAZ ) ...\n```\n\nIf the COND1 pattern matches, FOO is tried (and possibly further items after the\nend of the group if FOO succeeds). On failure, the matcher skips to the second\nalternative and tries COND2, without backtracking into COND1. If that succeeds\nand BAR fails, COND3 is tried. If BAZ then fails, there are no more\nalternatives, so there is a backtrack to whatever came before the entire group.\nIf (*THEN) is not inside an alternation, it acts like (*PRUNE).\n\nThe behavior of (*THEN:NAME) is the not the same as (*MARK:NAME)(*THEN). It is\nlike (*MARK:NAME) in that the name is remembered for passing back to the caller.\nHowever, (*SKIP:NAME) searches only for names set with (*MARK).\n\n> #### Note {: .info }\n>\n> The fact that (\\*THEN:NAME) remembers the name is useless to the Erlang\n> programmer, as names cannot be retrieved.\n\nA subpattern that does not contain a | character is just a part of the enclosing\nalternative; it is not a nested alternation with only one alternative. The\neffect of (\\*THEN) extends beyond such a subpattern to the enclosing\nalternative. Consider the following pattern, where A, B, and so on, are complex\npattern fragments that do not contain any | characters at this level:\n\n```text\nA (B(*THEN)C) | D\n```\n\nIf A and B are matched, but there is a failure in C, matching does not backtrack\ninto A; instead it moves to the next alternative, that is, D. However, if the\nsubpattern containing (\\*THEN) is given an alternative, it behaves differently:\n\n```text\nA (B(*THEN)C | (*FAIL)) | D\n```\n\nThe effect of (*THEN) is now confined to the inner subpattern. After a failure\nin C, matching moves to (*FAIL), which causes the whole subpattern to fail, as\nthere are no more alternatives to try. In this case, matching does now backtrack\ninto A.\n\nNotice that a conditional subpattern is not considered as having two\nalternatives, as only one is ever used. That is, the | character in a\nconditional subpattern has a different meaning. Ignoring whitespace, consider:\n\n```text\n^.*? (?(?=a) a | b(*THEN)c )\n```\n\nIf the subject is \"ba\", this pattern does not match. As ._? is ungreedy, it\ninitially matches zero characters. The condition (?=a) then fails, the character\n\"b\" is matched, but \"c\" is not. At this point, matching does not backtrack to\n._? as can perhaps be expected from the presence of the | character. The\nconditional subpattern is part of the single alternative that comprises the\nwhole pattern, and so the match fails. (If there was a backtrack into .\\*?,\nallowing it to match \"b\", the match would succeed.)\n\nThe verbs described above provide four different \"strengths\" of control when\nsubsequent matching fails:\n\n- (\\*THEN) is the weakest, carrying on the match at the next alternative.\n- (\\*PRUNE) comes next, fails the match at the current starting position, but\n allows an advance to the next character (for an unanchored pattern).\n- (\\*SKIP) is similar, except that the advance can be more than one character.\n- (\\*COMMIT) is the strongest, causing the entire match to fail.\n\n_More than One Backtracking Verb_\n\nIf more than one backtracking verb is present in a pattern, the one that is\nbacktracked onto first acts. For example, consider the following pattern, where\nA, B, and so on, are complex pattern fragments:\n\n```text\n(A(*COMMIT)B(*THEN)C|ABD)\n```\n\nIf A matches but B fails, the backtrack to (*COMMIT) causes the entire match to\nfail. However, if A and B match, but C fails, the backtrack to (*THEN) causes\nthe next alternative (ABD) to be tried. This behavior is consistent, but is not\nalways the same as in Perl. It means that if two or more backtracking verbs\nappear in succession, the last of them has no effect. Consider the following\nexample:\n\n```text\n...(*COMMIT)(*PRUNE)...\n```\n\nIf there is a matching failure to the right, backtracking onto (*PRUNE) causes\nit to be triggered, and its action is taken. There can never be a backtrack onto\n(*COMMIT).\n\n_Backtracking Verbs in Repeated Groups_\n\nPCRE differs from Perl in its handling of backtracking verbs in repeated groups.\nFor example, consider:\n\n```text\n/(a(*COMMIT)b)+ac/\n```\n\nIf the subject is \"abac\", Perl matches, but PCRE fails because the (\\*COMMIT) in\nthe second repeat of the group acts.\n\n_Backtracking Verbs in Assertions_\n\n(\\*FAIL) in an assertion has its normal effect: it forces an immediate\nbacktrack.\n\n(*ACCEPT) in a positive assertion causes the assertion to succeed without any\nfurther processing. In a negative assertion, (*ACCEPT) causes the assertion to\nfail without any further processing.\n\nThe other backtracking verbs are not treated specially if they appear in a\npositive assertion. In particular, (\\*THEN) skips to the next alternative in the\ninnermost enclosing group that has alternations, regardless if this is within\nthe assertion.\n\nNegative assertions are, however, different, to ensure that changing a positive\nassertion into a negative assertion changes its result. Backtracking into\n(*COMMIT), (*SKIP), or (*PRUNE) causes a negative assertion to be true, without\nconsidering any further alternative branches in the assertion. Backtracking into\n(*THEN) causes it to skip to the next enclosing alternative within the assertion\n(the normal behavior), but if the assertion does not have such an alternative,\n(*THEN) behaves like (*PRUNE).\n\n_Backtracking Verbs in Subroutines_\n\nThese behaviors occur regardless if the subpattern is called recursively. The\ntreatment of subroutines in Perl is different in some cases.\n\n- (\\*FAIL) in a subpattern called as a subroutine has its normal effect: it\n forces an immediate backtrack.\n- (\\*ACCEPT) in a subpattern called as a subroutine causes the subroutine match\n to succeed without any further processing. Matching then continues after the\n subroutine call.\n- (*COMMIT), (*SKIP), and (\\*PRUNE) in a subpattern called as a subroutine cause\n the subroutine match to fail.\n- (*THEN) skips to the next alternative in the innermost enclosing group within\n the subpattern that has alternatives. If there is no such group within the\n subpattern, (*THEN) causes the subroutine match to fail.","title":"Backtracking Control - re","ref":"re.html#module-backtracking-control"},{"type":"function","doc":"The same as [`compile(Regexp,[])`](`compile/2`)","title":"re.compile/1","ref":"re.html#compile/1"},{"type":"function","doc":"Compiles a regular expression, with the syntax described below, into an internal\nformat to be used later as a parameter to `run/2` and `run/3`.\n\nCompiling the regular expression before matching is useful if the same\nexpression is to be used in matching against multiple subjects during the\nlifetime of the program. Compiling once and executing many times is far more\nefficient than compiling each time one wants to match.\n\nWhen option `unicode` is specified, the regular expression is to be specified as\na valid Unicode `charlist()`, otherwise as any valid `t:iodata/0`.\n\n[](){: #compile_options }\n\nOptions:\n\n- **`unicode`** - The regular expression is specified as a Unicode `charlist()`\n and the resulting regular expression code is to be run against a valid Unicode\n `charlist()` subject. Also consider option `ucp` when using Unicode\n characters.\n\n- **`anchored`** - The pattern is forced to be \"anchored\", that is, it is\n constrained to match only at the first matching point in the string that is\n searched (the \"subject string\"). This effect can also be achieved by\n appropriate constructs in the pattern itself.\n\n- **`caseless`** - Letters in the pattern match both uppercase and lowercase\n letters. It is equivalent to Perl option `/i` and can be changed within a\n pattern by a `(?i)` option setting. Uppercase and lowercase letters are\n defined as in the ISO 8859-1 character set.\n\n- **`dollar_endonly`** - A dollar metacharacter in the pattern matches only at\n the end of the subject string. Without this option, a dollar also matches\n immediately before a newline at the end of the string (but not before any\n other newlines). This option is ignored if option `multiline` is specified.\n There is no equivalent option in Perl, and it cannot be set within a pattern.\n\n- **`dotall`** - A dot in the pattern matches all characters, including those\n indicating newline. Without it, a dot does not match when the current position\n is at a newline. This option is equivalent to Perl option `/s` and it can be\n changed within a pattern by a `(?s)` option setting. A negative class, such as\n `[^a]`, always matches newline characters, independent of the setting of this\n option.\n\n- **`extended`** - If this option is set, most white space characters in the\n pattern are totally ignored except when escaped or inside a character class.\n However, white space is not allowed within sequences such as `(?>` that\n introduce various parenthesized subpatterns, nor within a numerical quantifier\n such as `{1,3}`. However, ignorable white space is permitted between an item\n and a following quantifier and between a quantifier and a following + that\n indicates possessiveness.\n\n White space did not used to include the VT character (code 11), because Perl\n did not treat this character as white space. However, Perl changed at release\n 5.18, so PCRE followed at release 8.34, and VT is now treated as white space.\n\n This also causes characters between an unescaped # outside a character class\n and the next newline, inclusive, to be ignored. This is equivalent to Perl's\n `/x` option, and it can be changed within a pattern by a `(?x)` option\n setting.\n\n With this option, comments inside complicated patterns can be included.\n However, notice that this applies only to data characters. Whitespace\n characters can never appear within special character sequences in a pattern,\n for example within sequence `(?(` that introduces a conditional subpattern.\n\n- **`firstline`** - An unanchored pattern is required to match before or at the\n first newline in the subject string, although the matched text can continue\n over the newline.\n\n- **`multiline`** - By default, PCRE treats the subject string as consisting of\n a single line of characters (even if it contains newlines). The \"start of\n line\" metacharacter (`^`) matches only at the start of the string, while the\n \"end of line\" metacharacter (`$`) matches only at the end of the string, or\n before a terminating newline (unless option `dollar_endonly` is specified).\n This is the same as in Perl.\n\n When this option is specified, the \"start of line\" and \"end of line\"\n constructs match immediately following or immediately before internal newlines\n in the subject string, respectively, as well as at the very start and end.\n This is equivalent to Perl option `/m` and can be changed within a pattern by\n a `(?m)` option setting. If there are no newlines in a subject string, or no\n occurrences of `^` or `$` in a pattern, setting `multiline` has no effect.\n\n- **`no_auto_capture`** - Disables the use of numbered capturing parentheses in\n the pattern. Any opening parenthesis that is not followed by `?` behaves as if\n it is followed by `?:`. Named parentheses can still be used for capturing (and\n they acquire numbers in the usual way). There is no equivalent option in Perl.\n\n- **`dupnames`** - Names used to identify capturing subpatterns need not be\n unique. This can be helpful for certain types of pattern when it is known that\n only one instance of the named subpattern can ever be matched. More details of\n named subpatterns are provided below.\n\n- **`ungreedy`** - Inverts the \"greediness\" of the quantifiers so that they are\n not greedy by default, but become greedy if followed by \"?\". It is not\n compatible with Perl. It can also be set by a `(?U)` option setting within the\n pattern.\n\n- **`{newline, NLSpec}`** - Overrides the default definition of a newline in the\n subject string, which is LF (ASCII 10) in Erlang.\n\n - **`cr`** - Newline is indicated by a single character `cr` (ASCII 13).\n\n - **`lf`** - Newline is indicated by a single character LF (ASCII 10), the\n default.\n\n - **`crlf`** - Newline is indicated by the two-character CRLF (ASCII 13\n followed by ASCII 10) sequence.\n\n - **`anycrlf`** - Any of the three preceding sequences is to be recognized.\n\n - **`any`** - Any of the newline sequences above, and the Unicode sequences VT\n (vertical tab, U+000B), FF (formfeed, U+000C), NEL (next line, U+0085), LS\n (line separator, U+2028), and PS (paragraph separator, U+2029).\n\n- **`bsr_anycrlf`** - Specifies specifically that \\\\R is to match only the CR,\n LF, or CRLF sequences, not the Unicode-specific newline characters.\n\n- **`bsr_unicode`** - Specifies specifically that \\\\R is to match all the\n Unicode newline characters (including CRLF, and so on, the default).\n\n- **`no_start_optimize`** - Disables optimization that can malfunction if\n \"Special start-of-pattern items\" are present in the regular expression. A\n typical example would be when matching \"DEFABC\" against \"(*COMMIT)ABC\", where\n the start optimization of PCRE would skip the subject up to \"A\" and never\n realize that the (*COMMIT) instruction is to have made the matching fail. This\n option is only relevant if you use \"start-of-pattern items\", as discussed in\n section [PCRE Regular Expression Details](`m:re#module-pcre-regular-expression-details`).\n\n- **`ucp`** - Specifies that Unicode character properties are to be used when\n resolving \\\\B, \\\\b, \\\\D, \\\\d, \\\\S, \\\\s, \\\\W and \\\\w. Without this flag, only\n ISO Latin-1 properties are used. Using Unicode properties hurts performance,\n but is semantically correct when working with Unicode characters beyond the\n ISO Latin-1 range.\n\n- **`never_utf`** - Specifies that the (*UTF) and/or (*UTF8) \"start-of-pattern\n items\" are forbidden. This flag cannot be combined with option `unicode`.\n Useful if ISO Latin-1 patterns from an external source are to be compiled.","title":"re.compile/2","ref":"re.html#compile/2"},{"type":"function","doc":"Takes a compiled regular expression and an item, and returns the relevant data\nfrom the regular expression.\n\nThe only supported item is `namelist`, which returns the tuple `{namelist, [binary()]}`,\ncontaining the names of all (unique) named subpatterns in the regular expression.\n\nFor example:\n\n```erlang\n1> {ok,MP} = re:compile(\"(? A)|(? B)|(? C)\").\n{ok,{re_pattern,3,0,0,\n <<69,82,67,80,119,0,0,0,0,0,0,0,1,0,0,0,255,255,255,255,\n 255,255,...>>}}\n2> re:inspect(MP,namelist).\n{namelist,[<<\"A\">>,<<\"B\">>,<<\"C\">>]}\n3> {ok,MPD} = re:compile(\"(? A)|(? B)|(? C)\",[dupnames]).\n{ok,{re_pattern,3,0,0,\n <<69,82,67,80,119,0,0,0,0,0,8,0,1,0,0,0,255,255,255,255,\n 255,255,...>>}}\n4> re:inspect(MPD,namelist).\n{namelist,[<<\"B\">>,<<\"C\">>]}\n```\n\nNotice in the second example that the duplicate name only occurs once in the\nreturned list, and that the list is in alphabetical order regardless of where\nthe names are positioned in the regular expression. The order of the names is\nthe same as the order of captured subexpressions if `{capture, all_names}` is\nspecified as an option to `run/3`. You can therefore create a name-to-value\nmapping from the result of [`run/3`](`run/3`) like this:\n\n```erlang\n1> {ok,MP} = re:compile(\"(? A)|(? B)|(? C)\").\n{ok,{re_pattern,3,0,0,\n <<69,82,67,80,119,0,0,0,0,0,0,0,1,0,0,0,255,255,255,255,\n 255,255,...>>}}\n2> {namelist, N} = re:inspect(MP,namelist).\n{namelist,[<<\"A\">>,<<\"B\">>,<<\"C\">>]}\n3> {match,L} = re:run(\"AA\",MP,[{capture,all_names,binary}]).\n{match,[<<\"A\">>,<<>>,<<>>]}\n4> NameMap = lists:zip(N,L).\n[{<<\"A\">>,<<\"A\">>},{<<\"B\">>,<<>>},{<<\"C\">>,<<>>}]\n```","title":"re.inspect/2","ref":"re.html#inspect/2"},{"type":"function","doc":"","title":"re.replace/3","ref":"re.html#replace/3"},{"type":"function","doc":"Replaces the matched part of the `Subject` string with `Replacement`.\n\nThe permissible options are the same as for `run/3`, except that\noption` capture` is not allowed. Instead a `{return, ReturnType}` is present.\nThe default return type is `iodata`, constructed in a way to minimize copying.\nThe `iodata` result can be used directly in many I/O operations. If a flat\n`t:list/0` is desired, specify `{return, list}`. If a binary is desired, specify\n`{return, binary}`.\n\nAs in function [`run/3`](`run/3`), an `t:mp/0` compiled with option `unicode`\nrequires `Subject` to be a Unicode `charlist()`. If compilation is done\nimplicitly and the `unicode` compilation option is specified to this function,\nboth the regular expression and `Subject` are to specified as valid Unicode\n`charlist()`s.\n\nIf the replacement is given as a string, it can contain the special character\n`&`, which inserts the whole matching expression in the result, and the special\nsequence `\\`N (where N is an integer > 0), `\\g`N, or `\\g{`N`}`, resulting in the\nsubexpression number N, is inserted in the result. If no subexpression with that\nnumber is generated by the regular expression, nothing is inserted.\n\nTo insert an & or a \\\\ in the result, precede it with a \\\\. Notice that Erlang\nalready gives a special meaning to \\\\ in literal strings, so a single \\\\ must be\nwritten as `\"\\\\\"` and therefore a double \\\\ as `\"\\\\\\\\\"`.\n\n_Example:_\n\n```erlang\n1> re:replace(\"abcd\",\"c\",\"[&]\",[{return,list}]).\n\"ab[c]d\"\n```\n\nwhile\n\n```erlang\n2> re:replace(\"abcd\",\"c\",\"[\\\\&]\",[{return,list}]).\n\"ab[&]d\"\n```\n\nIf the replacement is given as a fun, it will be called with the whole matching\nexpression as the first argument and a list of subexpression matches in the\norder in which they appear in the regular expression. The returned value will be\ninserted in the result.\n\n_Example:_\n\n```erlang\n3> re:replace(\"abcd\", \".(.)\",\n fun(Whole, [< >]) ->\n <<$#, Whole/binary, $-, (C - $a + $A), $#>>\n end,\n [{return, list}]).\n\"#ab-B#cd\"\n```\n\n> #### Note {: .info }\n>\n> Non-matching optional subexpressions will not be included in the list of\n> subexpression matches if they are the last subexpressions in the regular\n> expression.\n>\n> _Example:_\n>\n> The regular expression `\"(a)(b)?(c)?\"` (\"a\", optionally followed by \"b\",\n> optionally followed by \"c\") will create the following subexpression lists:\n>\n> - `[<<\"a\">>, <<\"b\">>, <<\"c\">>]` when applied to the string `\"abc\"`\n> - `[<<\"a\">>, <<>>, <<\"c\">>]` when applied to the string `\"acx\"`\n> - `[<<\"a\">>, <<\"b\">>]` when applied to the string `\"abx\"`\n> - `[<<\"a\">>]` when applied to the string `\"axx\"`\n\nAs with [`run/3`](`run/3`), compilation errors raise the `badarg` exception.\n`compile/2` can be used to get more information about the error.","title":"re.replace/4","ref":"re.html#replace/4"},{"type":"function","doc":"","title":"re.run/2","ref":"re.html#run/2"},{"type":"function","doc":"Executes a regular expression matching, and returns `match/{match, Captured}` or\n`nomatch`.\n\nThe regular expression can be specified either as `t:iodata/0` in\nwhich case it is automatically compiled (as by [`compile/2`](`compile/2`)) and\nexecuted, or as a precompiled `t:mp/0` in which case it is executed against the\nsubject directly.\n\nWhen compilation is involved, exception `badarg` is thrown if a compilation\nerror occurs. Call [`compile/2`](`compile/2`) to get information about the\nlocation of the error in the regular expression.\n\nIf the regular expression is previously compiled, the option list can only\ncontain the following options:\n\n- `anchored`\n- `{capture, ValueSpec}/{capture, ValueSpec, Type}`\n- `global`\n- `{match_limit, integer() >= 0}`\n- `{match_limit_recursion, integer() >= 0}`\n- `{newline, NLSpec}`\n- `notbol`\n- `notempty`\n- `notempty_atstart`\n- `noteol`\n- `{offset, integer() >= 0}`\n- `report_errors`\n\nOtherwise all options valid for function [`compile/2`](`compile/2`) are also\nallowed. Options allowed both for compilation and execution of a match, namely\n`anchored` and `{newline, NLSpec}`, affect both the compilation and execution if\npresent together with a non-precompiled regular expression.\n\nIf the regular expression was previously compiled with option `unicode`,\n`Subject` is to be provided as a valid Unicode `charlist()`, otherwise any\n`t:iodata/0` will do. If compilation is involved and option `unicode` is\nspecified, both `Subject` and the regular expression are to be specified as\nvalid Unicode `charlists()`.\n\n`{capture, ValueSpec}/{capture, ValueSpec, Type}` defines what to return from\nthe function upon successful matching. The `capture` tuple can contain both a\nvalue specification, telling which of the captured substrings are to be\nreturned, and a type specification, telling how captured substrings are to be\nreturned (as index tuples, lists, or binaries). The options are described in\ndetail below.\n\nIf the capture options describe that no substring capturing is to be done\n(`{capture, none}`), the function returns the single atom `match` upon\nsuccessful matching, otherwise the tuple `{match, ValueList}`. Disabling\ncapturing can be done either by specifying `none` or an empty list as\n`ValueSpec`.\n\nOption `report_errors` adds the possibility that an error tuple is returned. The\ntuple either indicates a matching error (`match_limit` or\n`match_limit_recursion`), or a compilation error, where the error tuple has the\nformat `{error, {compile, CompileErr}}`. Notice that if option `report_errors`\nis not specified, the function never returns error tuples, but reports\ncompilation errors as a `badarg` exception and failed matches because of\nexceeded match limits simply as `nomatch`.\n\nThe following options are relevant for execution:\n\n- **`anchored`** - Limits [`run/3`](`run/3`) to matching at the first matching\n position. If a pattern was compiled with `anchored`, or turned out to be\n anchored by virtue of its contents, it cannot be made unanchored at matching\n time, hence there is no `unanchored` option.\n\n- **`global`** - Implements global (repetitive) search (flag `g` in Perl). Each\n match is returned as a separate `t:list/0` containing the specific match and\n any matching subexpressions (or as specified by option `capture`. The\n `Captured` part of the return value is hence a `t:list/0` of `t:list/0`s when\n this option is specified.\n\n The interaction of option `global` with a regular expression that matches an\n empty string surprises some users. When option `global` is specified,\n [`run/3`](`run/3`) handles empty matches in the same way as Perl: a\n zero-length match at any point is also retried with options\n `[anchored, notempty_atstart]`. If that search gives a result of length > 0,\n the result is included. Example:\n\n ```erlang\n re:run(\"cat\",\"(|at)\",[global]).\n ```\n\n The following matchings are performed:\n\n - **At offset `0`** - The regular expression `(|at)` first match at the\n initial position of string `cat`, giving the result set `[{0,0},{0,0}]` (the\n second `{0,0}` is because of the subexpression marked by the parentheses).\n As the length of the match is 0, we do not advance to the next position yet.\n\n - **At offset `0` with `[anchored, notempty_atstart]`** - The search is\n retried with options `[anchored, notempty_atstart]` at the same position,\n which does not give any interesting result of longer length, so the search\n position is advanced to the next character (`a`).\n\n - **At offset `1`** - The search results in `[{1,0},{1,0}]`, so this search is\n also repeated with the extra options.\n\n - **At offset `1` with `[anchored, notempty_atstart]`** - Alternative `ab` is\n found and the result is \\[\\{1,2\\},\\{1,2\\}]. The result is added to the list\n of results and the position in the search string is advanced two steps.\n\n - **At offset `3`** - The search once again matches the empty string, giving\n `[{3,0},{3,0}]`.\n\n - **At offset `1` with `[anchored, notempty_atstart]`** - This gives no result\n of length > 0 and we are at the last position, so the global search is\n complete.\n\n The result of the call is:\n\n ```erlang\n {match,[[{0,0},{0,0}],[{1,0},{1,0}],[{1,2},{1,2}],[{3,0},{3,0}]]}\n ```\n\n- **`notempty`** - An empty string is not considered to be a valid match if this\n option is specified. If alternatives in the pattern exist, they are tried. If\n all the alternatives match the empty string, the entire match fails.\n\n _Example:_\n\n If the following pattern is applied to a string not beginning with \"a\" or \"b\",\n it would normally match the empty string at the start of the subject:\n\n ```text\n a?b?\n ```\n\n With option `notempty`, this match is invalid, so [`run/3`](`run/3`) searches\n further into the string for occurrences of \"a\" or \"b\".\n\n- **`notempty_atstart`** - Like `notempty`, except that an empty string match\n that is not at the start of the subject is permitted. If the pattern is\n anchored, such a match can occur only if the pattern contains \\\\K.\n\n Perl has no direct equivalent of `notempty` or `notempty_atstart`, but it does\n make a special case of a pattern match of the empty string within its split()\n function, and when using modifier `/g`. The Perl behavior can be emulated\n after matching a null string by first trying the match again at the same\n offset with `notempty_atstart` and `anchored`, and then, if that fails, by\n advancing the starting offset (see below) and trying an ordinary match again.\n\n- **`notbol`** - Specifies that the first character of the subject string is not\n the beginning of a line, so the circumflex metacharacter is not to match\n before it. Setting this without `multiline` (at compile time) causes\n circumflex never to match. This option only affects the behavior of the\n circumflex metacharacter. It does not affect \\\\A.\n\n- **`noteol`** - Specifies that the end of the subject string is not the end of\n a line, so the dollar metacharacter is not to match it nor (except in\n multiline mode) a newline immediately before it. Setting this without\n `multiline` (at compile time) causes dollar never to match. This option\n affects only the behavior of the dollar metacharacter. It does not affect \\\\Z\n or \\\\z.\n\n- **`report_errors`** - Gives better control of the error handling in\n [`run/3`](`run/3`). When specified, compilation errors (if the regular\n expression is not already compiled) and runtime errors are explicitly returned\n as an error tuple.\n\n The following are the possible runtime errors:\n\n - **`match_limit`** - The PCRE library sets a limit on how many times the\n internal match function can be called. Defaults to 10,000,000 in the library\n compiled for Erlang. If `{error, match_limit}` is returned, the execution of\n the regular expression has reached this limit. This is normally to be\n regarded as a `nomatch`, which is the default return value when this occurs,\n but by specifying `report_errors`, you are informed when the match fails\n because of too many internal calls.\n\n - **`match_limit_recursion`** - This error is very similar to `match_limit`,\n but occurs when the internal match function of PCRE is \"recursively\" called\n more times than the `match_limit_recursion` limit, which defaults to\n 10,000,000 as well. Notice that as long as the `match_limit` and\n `match_limit_default` values are kept at the default values, the\n `match_limit_recursion` error cannot occur, as the `match_limit` error\n occurs before that (each recursive call is also a call, but not conversely).\n Both limits can however be changed, either by setting limits directly in the\n regular expression string (see section\n [PCRE Regular Eexpression Details](`m:re#module-pcre-regular-expression-details`)) or by\n specifying options to [`run/3`](`run/3`).\n\n It is important to understand that what is referred to as \"recursion\" when\n limiting matches is not recursion on the C stack of the Erlang machine or on\n the Erlang process stack. The PCRE version compiled into the Erlang VM uses\n machine \"heap\" memory to store values that must be kept over recursion in\n regular expression matches.\n\n- **`{match_limit, integer() >= 0}`** - Limits the execution time of a match in\n an implementation-specific way. It is described as follows by the PCRE\n documentation:\n\n > The match_limit field provides a means of preventing PCRE from using\n > up a vast amount of resources when running patterns that are not going\n > to match, but which have a very large number of possibilities in their\n > search trees. The classic example is a pattern that uses nested\n > unlimited repeats.\n >\n > Internally, pcre_exec() uses a function called match(), which it calls\n > repeatedly (sometimes recursively). The limit set by match_limit is\n > imposed on the number of times this function is called during a match,\n > which has the effect of limiting the amount of backtracking that can\n > take place. For patterns that are not anchored, the count restarts\n > from zero for each position in the subject string.\n\n This means that runaway regular expression matches can fail faster if the\n limit is lowered using this option. The default value 10,000,000 is compiled\n into the Erlang VM.\n\n > #### Note {: .info }\n >\n > This option does in no way affect the execution of the Erlang VM in terms of\n > \"long running BIFs\". [`run/3`](`run/3`) always gives control back to the\n > scheduler of Erlang processes at intervals that ensures the real-time\n > properties of the Erlang system.\n\n- **`{match_limit_recursion, integer() >= 0}`** - Limits the execution time and\n memory consumption of a match in an implementation-specific way, very similar\n to `match_limit`. It is described as follows by the PCRE documentation:\n\n > The match_limit_recursion field is similar to match_limit, but instead\n > of limiting the total number of times that match() is called, it\n > limits the depth of recursion. The recursion depth is a smaller number\n > than the total number of calls, because not all calls to match() are\n > recursive. This limit is of use only if it is set smaller than\n > match_limit.\n >\n > Limiting the recursion depth limits the amount of machine stack that\n > can be used, or, when PCRE has been compiled to use memory on the heap\n > instead of the stack, the amount of heap memory that can be used.\n\n The Erlang VM uses a PCRE library where heap memory is used when regular\n expression match recursion occurs. This therefore limits the use of machine\n heap, not C stack.\n\n Specifying a lower value can result in matches with deep recursion failing,\n when they should have matched:\n\n ```erlang\n 1> re:run(\"aaaaaaaaaaaaaz\",\"(a+)*z\").\n {match,[{0,14},{0,13}]}\n 2> re:run(\"aaaaaaaaaaaaaz\",\"(a+)*z\",[{match_limit_recursion,5}]).\n nomatch\n 3> re:run(\"aaaaaaaaaaaaaz\",\"(a+)*z\",[{match_limit_recursion,5},report_errors]).\n {error,match_limit_recursion}\n ```\n\n This option and option `match_limit` are only to be used in rare cases.\n Understanding of the PCRE library internals is recommended before tampering\n with these limits.\n\n- **`{offset, integer() >= 0}`** - Start matching at the offset (position)\n specified in the subject string. The offset is zero-based, so that the default\n is `{offset,0}` (all of the subject string).\n\n- **`{newline, NLSpec}`** - Overrides the default definition of a newline in the\n subject string, which is LF (ASCII 10) in Erlang.\n\n - **`cr`** - Newline is indicated by a single character CR (ASCII 13).\n\n - **`lf`** - Newline is indicated by a single character LF (ASCII 10), the\n default.\n\n - **`crlf`** - Newline is indicated by the two-character CRLF (ASCII 13\n followed by ASCII 10) sequence.\n\n - **`anycrlf`** - Any of the three preceding sequences is be recognized.\n\n - **`any`** - Any of the newline sequences above, and the Unicode sequences VT\n (vertical tab, U+000B), FF (formfeed, U+000C), NEL (next line, U+0085), LS\n (line separator, U+2028), and PS (paragraph separator, U+2029).\n\n- **`bsr_anycrlf`** - Specifies specifically that \\\\R is to match only the CR\n LF, or CRLF sequences, not the Unicode-specific newline characters. (Overrides\n the compilation option.)\n\n- **`bsr_unicode`** - Specifies specifically that \\\\R is to match all the\n Unicode newline characters (including CRLF, and so on, the default).\n (Overrides the compilation option.)\n\n- **`{capture, ValueSpec}`/`{capture, ValueSpec, Type}`** - Specifies which\n captured substrings are returned and in what format. By default,\n [`run/3`](`run/3`) captures all of the matching part of the substring and all\n capturing subpatterns (all of the pattern is automatically captured). The\n default return type is (zero-based) indexes of the captured parts of the\n string, specified as `{Offset,Length}` pairs (the `index` `Type` of\n capturing).\n\n As an example of the default behavior, the following call returns, as first\n and only captured string, the matching part of the subject (\"abcd\" in the\n middle) as an index pair `{3,4}`, where character positions are zero-based,\n just as in offsets:\n\n ```erlang\n re:run(\"ABCabcdABC\",\"abcd\",[]).\n ```\n\n The return value of this call is:\n\n ```erlang\n {match,[{3,4}]}\n ```\n\n Another (and quite common) case is where the regular expression matches all of\n the subject:\n\n ```erlang\n re:run(\"ABCabcdABC\",\".*abcd.*\",[]).\n ```\n\n Here the return value correspondingly points out all of the string, beginning\n at index 0, and it is 10 characters long:\n\n ```erlang\n {match,[{0,10}]}\n ```\n\n If the regular expression contains capturing subpatterns, like in:\n\n ```erlang\n re:run(\"ABCabcdABC\",\".*(abcd).*\",[]).\n ```\n\n all of the matched subject is captured, as well as the captured substrings:\n\n ```erlang\n {match,[{0,10},{3,4}]}\n ```\n\n The complete matching pattern always gives the first return value in the list\n and the remaining subpatterns are added in the order they occurred in the\n regular expression.\n\n The capture tuple is built up as follows:\n\n - **`ValueSpec`** - Specifies which captured (sub)patterns are to be returned.\n `ValueSpec` can either be an atom describing a predefined set of return\n values, or a list containing the indexes or the names of specific\n subpatterns to return.\n\n The following are the predefined sets of subpatterns:\n\n - **`all`** - All captured subpatterns including the complete matching\n string. This is the default.\n\n - **`all_names`** - All _named_ subpatterns in the regular expression, as if\n a `t:list/0` of all the names _in alphabetical order_ was specified. The\n list of all names can also be retrieved with `inspect/2`.\n\n - **`first`** - Only the first captured subpattern, which is always the\n complete matching part of the subject. All explicitly captured subpatterns\n are discarded.\n\n - **`all_but_first`** - All but the first matching subpattern, that is, all\n explicitly captured subpatterns, but not the complete matching part of the\n subject string. This is useful if the regular expression as a whole\n matches a large part of the subject, but the part you are interested in is\n in an explicitly captured subpattern. If the return type is `list` or\n `binary`, not returning subpatterns you are not interested in is a good\n way to optimize.\n\n - **`none`** - Returns no matching subpatterns, gives the single atom\n `match` as the return value of the function when matching successfully\n instead of the `{match, list()}` return. Specifying an empty list gives\n the same behavior.\n\n The value list is a list of indexes for the subpatterns to return, where\n index 0 is for all of the pattern, and 1 is for the first explicit capturing\n subpattern in the regular expression, and so on. When using named captured\n subpatterns (see below) in the regular expression, one can use `t:atom/0`s\n or `t:string/0`s to specify the subpatterns to be returned. For example,\n consider the regular expression:\n\n ```text\n \".*(abcd).*\"\n ```\n\n matched against string \"ABCabcdABC\", capturing only the \"abcd\" part (the\n first explicit subpattern):\n\n ```erlang\n re:run(\"ABCabcdABC\",\".*(abcd).*\",[{capture,[1]}]).\n ```\n\n The call gives the following result, as the first explicitly captured\n subpattern is \"(abcd)\", matching \"abcd\" in the subject, at (zero-based)\n position 3, of length 4:\n\n ```erlang\n {match,[{3,4}]}\n ```\n\n Consider the same regular expression, but with the subpattern explicitly\n named 'FOO':\n\n ```text\n \".*(? abcd).*\"\n ```\n\n With this expression, we could still give the index of the subpattern with\n the following call:\n\n ```erlang\n re:run(\"ABCabcdABC\",\".*(? abcd).*\",[{capture,[1]}]).\n ```\n\n giving the same result as before. But, as the subpattern is named, we can\n also specify its name in the value list:\n\n ```erlang\n re:run(\"ABCabcdABC\",\".*(? abcd).*\",[{capture,['FOO']}]).\n ```\n\n This would give the same result as the earlier examples, namely:\n\n ```erlang\n {match,[{3,4}]}\n ```\n\n The values list can specify indexes or names not present in the regular\n expression, in which case the return values vary depending on the type. If\n the type is `index`, the tuple `{-1,0}` is returned for values with no\n corresponding subpattern in the regular expression, but for the other types\n (`binary` and `list`), the values are the empty binary or list,\n respectively.\n\n - **`Type`** - Optionally specifies how captured substrings are to be\n returned. If omitted, the default of `index` is used.\n\n `Type` can be one of the following:\n\n - **`index`** - Returns captured substrings as pairs of byte indexes into\n the subject string and length of the matching string in the subject (as if\n the subject string was flattened with `erlang:iolist_to_binary/1` or\n `unicode:characters_to_binary/2` before matching). Notice that option\n `unicode` results in _byte-oriented_ indexes in a (possibly virtual)\n _UTF-8 encoded_ binary. A byte index tuple `{0,2}` can therefore represent\n one or two characters when `unicode` is in effect. This can seem\n counter-intuitive, but has been deemed the most effective and useful way\n to do it. To return lists instead can result in simpler code if that is\n desired. This return type is the default.\n\n - **`list`** - Returns matching substrings as lists of characters (Erlang\n `t:string/0`s). It option `unicode` is used in combination with the \\\\C\n sequence in the regular expression, a captured subpattern can contain\n bytes that are not valid UTF-8 (\\\\C matches bytes regardless of character\n encoding). In that case the `list` capturing can result in the same types\n of tuples that `unicode:characters_to_list/2` can return, namely\n three-tuples with tag `incomplete` or `error`, the successfully converted\n characters and the invalid UTF-8 tail of the conversion as a binary. The\n best strategy is to avoid using the \\\\C sequence when capturing lists.\n\n - **`binary`** - Returns matching substrings as binaries. If option\n `unicode` is used, these binaries are in UTF-8. If the \\\\C sequence is\n used together with `unicode`, the binaries can be invalid UTF-8.\n\n In general, subpatterns that were not assigned a value in the match are\n returned as the tuple `{-1,0}` when `type` is `index`. Unassigned subpatterns\n are returned as the empty binary or list, respectively, for other return\n types. Consider the following regular expression:\n\n ```text\n \".*((? abdd)|a(..d)).*\"\n ```\n\n There are three explicitly capturing subpatterns, where the opening\n parenthesis position determines the order in the result, hence\n `((? abdd)|a(..d))` is subpattern index 1, `(? abdd)` is subpattern\n index 2, and `(..d)` is subpattern index 3. When matched against the following\n string:\n\n ```text\n \"ABCabcdABC\"\n ```\n\n the subpattern at index 2 does not match, as \"abdd\" is not present in the\n string, but the complete pattern matches (because of the alternative\n `a(..d)`). The subpattern at index 2 is therefore unassigned and the default\n return value is:\n\n ```erlang\n {match,[{0,10},{3,4},{-1,0},{4,3}]}\n ```\n\n Setting the capture `Type` to `binary` gives:\n\n ```erlang\n {match,[<<\"ABCabcdABC\">>,<<\"abcd\">>,<<>>,<<\"bcd\">>]}\n ```\n\n Here the empty binary (`<<>>`) represents the unassigned subpattern. In the\n `binary` case, some information about the matching is therefore lost, as\n `<<>>` can also be an empty string captured.\n\n If differentiation between empty matches and non-existing subpatterns is\n necessary, use the `type` `index` and do the conversion to the final type in\n Erlang code.\n\n When option `global` is speciified, the `capture` specification affects each\n match separately, so that:\n\n ```erlang\n re:run(\"cacb\",\"c(a|b)\",[global,{capture,[1],list}]).\n ```\n\n gives\n\n ```erlang\n {match,[[\"a\"],[\"b\"]]}\n ```\n\nFor a descriptions of options only affecting the compilation step, see\n`compile/2`.","title":"re.run/3","ref":"re.html#run/3"},{"type":"function","doc":"","title":"re.split/2","ref":"re.html#split/2"},{"type":"function","doc":"Splits the input into parts by finding tokens according to the regular\nexpression supplied.\n\nThe splitting is basically done by running a global regular\nexpression match and dividing the initial string wherever a match occurs. The\nmatching part of the string is removed from the output.\n\nAs in `run/3`, an `t:mp/0` compiled with option `unicode` requires `Subject` to\nbe a Unicode `charlist()`. If compilation is done implicitly and the `unicode`\ncompilation option is specified to this function, both the regular expression\nand `Subject` are to be specified as valid Unicode `charlist()`s.\n\nThe result is given as a list of \"strings\", the preferred data type specified in\noption `return` (default `iodata`).\n\nIf subexpressions are specified in the regular expression, the matching\nsubexpressions are returned in the resulting list as well. For example:\n\n```erlang\nre:split(\"Erlang\",\"[ln]\",[{return,list}]).\n```\n\ngives\n\n```erlang\n[\"Er\",\"a\",\"g\"]\n```\n\nwhile\n\n```erlang\nre:split(\"Erlang\",\"([ln])\",[{return,list}]).\n```\n\ngives\n\n```erlang\n[\"Er\",\"l\",\"a\",\"n\",\"g\"]\n```\n\nThe text matching the subexpression (marked by the parentheses in the regular\nexpression) is inserted in the result list where it was found. This means that\nconcatenating the result of a split where the whole regular expression is a\nsingle subexpression (as in the last example) always results in the original\nstring.\n\nAs there is no matching subexpression for the last part in the example (the\n\"g\"), nothing is inserted after that. To make the group of strings and the parts\nmatching the subexpressions more obvious, one can use option `group`, which\ngroups together the part of the subject string with the parts matching the\nsubexpressions when the string was split:\n\n```erlang\nre:split(\"Erlang\",\"([ln])\",[{return,list},group]).\n```\n\ngives\n\n```erlang\n[[\"Er\",\"l\"],[\"a\",\"n\"],[\"g\"]]\n```\n\nHere the regular expression first matched the \"l\", causing \"Er\" to be the first\npart in the result. When the regular expression matched, the (only)\nsubexpression was bound to the \"l\", so the \"l\" is inserted in the group together\nwith \"Er\". The next match is of the \"n\", making \"a\" the next part to be\nreturned. As the subexpression is bound to substring \"n\" in this case, the \"n\"\nis inserted into this group. The last group consists of the remaining string, as\nno more matches are found.\n\nBy default, all parts of the string, including the empty strings, are returned\nfrom the function, for example:\n\n```erlang\nre:split(\"Erlang\",\"[lg]\",[{return,list}]).\n```\n\ngives\n\n```erlang\n[\"Er\",\"an\",[]]\n```\n\nas the matching of the \"g\" in the end of the string leaves an empty rest, which\nis also returned. This behavior differs from the default behavior of the split\nfunction in Perl, where empty strings at the end are by default removed. To get\nthe \"trimming\" default behavior of Perl, specify `trim` as an option:\n\n```erlang\nre:split(\"Erlang\",\"[lg]\",[{return,list},trim]).\n```\n\ngives\n\n```erlang\n[\"Er\",\"an\"]\n```\n\nThe \"trim\" option says; \"give me as many parts as possible except the empty\nones\", which sometimes can be useful. You can also specify how many parts you\nwant, by specifying `{parts,`N`}`:\n\n```erlang\nre:split(\"Erlang\",\"[lg]\",[{return,list},{parts,2}]).\n```\n\ngives\n\n```erlang\n[\"Er\",\"ang\"]\n```\n\nNotice that the last part is \"ang\", not \"an\", as splitting was specified into\ntwo parts, and the splitting stops when enough parts are given, which is why the\nresult differs from that of `trim`.\n\nMore than three parts are not possible with this indata, so\n\n```erlang\nre:split(\"Erlang\",\"[lg]\",[{return,list},{parts,4}]).\n```\n\ngives the same result as the default, which is to be viewed as \"an infinite\nnumber of parts\".\n\nSpecifying `0` as the number of parts gives the same effect as option `trim`. If\nsubexpressions are captured, empty subexpressions matched at the end are also\nstripped from the result if `trim` or `{parts,0}` is specified.\n\nThe `trim` behavior corresponds exactly to the Perl default. `{parts,N}`, where\nN is a positive integer, corresponds exactly to the Perl behavior with a\npositive numerical third parameter. The default behavior of\n[`split/3`](`split/3`) corresponds to the Perl behavior when a negative integer\nis specified as the third parameter for the Perl routine.\n\nSummary of options not previously described for function [`run/3`](`run/3`):\n\n- **`{return,ReturnType}`** - Specifies how the parts of the original string are\n presented in the result list. Valid types:\n\n - **`iodata`** - The variant of `t:iodata/0` that gives the least copying of\n data with the current implementation (often a binary, but do not depend on\n it).\n\n - **`binary`** - All parts returned as binaries.\n\n - **`list`** - All parts returned as lists of characters (\"strings\").\n\n- **`group`** - Groups together the part of the string with the parts of the\n string matching the subexpressions of the regular expression.\n\n The return value from the function is in this case a `t:list/0` of\n `t:list/0`s. Each sublist begins with the string picked out of the subject\n string, followed by the parts matching each of the subexpressions in order of\n occurrence in the regular expression.\n\n- **`{parts,N}`** - Specifies the number of parts the subject string is to be\n split into.\n\n The number of parts is to be a positive integer for a specific maximum number\n of parts, and `infinity` for the maximum number of parts possible (the\n default). Specifying `{parts,0}` gives as many parts as possible disregarding\n empty parts at the end, the same as specifying `trim`.\n\n- **`trim`** - Specifies that empty parts at the end of the result list are to\n be disregarded. The same as specifying `{parts,0}`. This corresponds to the\n default behavior of the `split` built-in function in Perl.","title":"re.split/3","ref":"re.html#split/3"},{"type":"function","doc":"The return of this function is a string with the PCRE version of the system that\nwas used in the Erlang/OTP compilation.","title":"re.version/0","ref":"re.html#version/0"},{"type":"type","doc":"","title":"re.capture/0","ref":"re.html#t:capture/0"},{"type":"type","doc":"","title":"re.compile_option/0","ref":"re.html#t:compile_option/0"},{"type":"type","doc":"","title":"re.compile_options/0","ref":"re.html#t:compile_options/0"},{"type":"type","doc":"Opaque data type containing a compiled regular expression.\n\n`t:mp/0` is guaranteed to be a tuple() having the atom `re_pattern` as its first element, to\nallow for matching in guards. The arity of the tuple or the content of the other\nfields can change in future Erlang/OTP releases.","title":"re.mp/0","ref":"re.html#t:mp/0"},{"type":"type","doc":"","title":"re.nl_spec/0","ref":"re.html#t:nl_spec/0"},{"type":"type","doc":"","title":"re.option/0","ref":"re.html#t:option/0"},{"type":"type","doc":"","title":"re.options/0","ref":"re.html#t:options/0"},{"type":"type","doc":"","title":"re.replace_fun/0","ref":"re.html#t:replace_fun/0"},{"type":"module","doc":"String processing functions.\n\nThis module provides functions for string processing.\n\nA string in this module is represented by `t:unicode:chardata/0`, that is, a\nlist of codepoints, binaries with UTF-8-encoded codepoints (_UTF-8 binaries_),\nor a mix of the two.\n\n```text\n\"abcd\" is a valid string\n<<\"abcd\">> is a valid string\n[\"abcd\"] is a valid string\n<<\"abc..åäö\"/utf8>> is a valid string\n<<\"abc..åäö\">> is NOT a valid string,\n but a binary with Latin-1-encoded codepoints\n[<<\"abc\">>, \"..åäö\"] is a valid string\n[atom] is NOT a valid string\n```\n\nThis module operates on grapheme clusters. A _grapheme cluster_ is a\nuser-perceived character, which can be represented by several codepoints.\n\n```text\n\"å\" [229] or [97, 778]\n\"e̊\" [101, 778]\n```\n\nThe string length of \"ß↑e̊\" is 3, even though it is represented by the codepoints\n`[223,8593,101,778]` or the UTF-8 binary `<<195,159,226,134,145,101,204,138>>`.\n\nGrapheme clusters for codepoints of class `prepend` and non-modern (or\ndecomposed) Hangul is not handled for performance reasons in `find/3`,\n`replace/3`, `split/2`, `split/3` and `trim/3`.\n\nSplitting and appending strings is to be done on grapheme clusters borders.\nThere is no verification that the results of appending strings are valid or\nnormalized.\n\nMost of the functions expect all input to be normalized to one form, see for\nexample `unicode:characters_to_nfc_list/1`.\n\nLanguage or locale specific handling of input is not considered in any function.\n\nThe functions can crash for non-valid input strings. For example, the functions\nexpect UTF-8 binaries but not all functions verify that all binaries are encoded\ncorrectly.\n\nUnless otherwise specified the return value type is the same as the input type.\nThat is, binary input returns binary output, list input returns a list output,\nand mixed input can return a mixed output.\n\n```erlang\n1> string:trim(\" sarah \").\n\"sarah\"\n2> string:trim(<<\" sarah \">>).\n<<\"sarah\">>\n3> string:lexemes(\"foo bar\", \" \").\n[\"foo\",\"bar\"]\n4> string:lexemes(<<\"foo bar\">>, \" \").\n[<<\"foo\">>,<<\"bar\">>]\n```\n\nThis module has been reworked in Erlang/OTP 20 to handle `t:unicode:chardata/0`\nand operate on grapheme clusters. The\n[`old functions`](`m:string#obsolete-api-functions`) that only work on Latin-1\nlists as input are still available but should not be used, they will be\ndeprecated in a future release.","title":"string","ref":"string.html"},{"type":"module","doc":"Some of the general string functions can seem to overlap each other. The reason\nis that this string package is the combination of two earlier packages and all\nfunctions of both packages have been retained.","title":"Notes - string","ref":"string.html#module-notes"},{"type":"function","doc":"Converts `String` to a case-agnostic comparable string. Function\n[`casefold/1`](`casefold/1`) is preferred over [`lowercase/1`](`lowercase/1`)\nwhen two strings are to be compared for equality. See also `equal/4`.\n\n_Example:_\n\n```erlang\n1> string:casefold(\"Ω and ẞ SHARP S\").\n\"ω and ss sharp s\"\n```","title":"string.casefold/1","ref":"string.html#casefold/1"},{"type":"function","doc":"","title":"string.centre/2","ref":"string.html#centre/2"},{"type":"function","doc":"Returns a string, where `String` is centered in the string and surrounded by\nblanks or `Character`. The resulting string has length `Number`.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use `pad/3`.","title":"string.centre/3","ref":"string.html#centre/3"},{"type":"function","doc":"","title":"string.chars/2","ref":"string.html#chars/2"},{"type":"function","doc":"Returns a string consisting of `Number` characters `Character`. Optionally, the\nstring can end with string `Tail`.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use\n`lists:duplicate/2`.","title":"string.chars/3","ref":"string.html#chars/3"},{"type":"function","doc":"Returns a string where any trailing `\\n` or `\\r\\n` have been removed from\n`String`.\n\n_Example:_\n\n```erlang\n182> string:chomp(<<\"\\nHello\\n\\n\">>).\n<<\"\\nHello\">>\n183> string:chomp(\"\\nHello\\r\\r\\n\").\n\"\\nHello\\r\"\n```","title":"string.chomp/1","ref":"string.html#chomp/1"},{"type":"function","doc":"Returns the index of the first occurrence of `Character` in `String`. Returns\n`0` if `Character` does not occur.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use `find/2`.","title":"string.chr/2","ref":"string.html#chr/2"},{"type":"function","doc":"Concatenates `String1` and `String2` to form a new string `String3`, which is\nreturned.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use\n`[String1, String2]` as `Data` argument, and call `unicode:characters_to_list/2`\nor `unicode:characters_to_binary/2` to flatten the output.","title":"string.concat/2","ref":"string.html#concat/2"},{"type":"function","doc":"Returns a string containing `String` repeated `Number` times.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use\n`lists:duplicate/2`.","title":"string.copies/2","ref":"string.html#copies/2"},{"type":"function","doc":"Returns the length of the maximum initial segment of `String`, which consists\nentirely of characters not from `Chars`.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use `take/3`.\n\n_Example:_\n\n```erlang\n1> string:cspan(\"\\t abcdef\", \" \\t\").\n0\n```","title":"string.cspan/2","ref":"string.html#cspan/2"},{"type":"function","doc":"","title":"string.equal/2","ref":"string.html#equal/2"},{"type":"function","doc":"","title":"string.equal/3","ref":"string.html#equal/3"},{"type":"function","doc":"Returns `true` if `A` and `B` are equal, otherwise `false`.\n\nIf `IgnoreCase` is `true` the function does [`casefold`ing](`casefold/1`) on the\nfly before the equality test.\n\nIf `Norm` is not `none` the function applies normalization on the fly before the\nequality test. There are four available normalization forms:\n[`nfc`](`unicode:characters_to_nfc_list/1`),\n[`nfd`](`unicode:characters_to_nfd_list/1`),\n[`nfkc`](`unicode:characters_to_nfkc_list/1`), and\n[`nfkd`](`unicode:characters_to_nfkd_list/1`).\n\n_Example:_\n\n```erlang\n1> string:equal(\"åäö\", <<\"åäö\"/utf8>>).\ntrue\n2> string:equal(\"åäö\", unicode:characters_to_nfd_binary(\"åäö\")).\nfalse\n3> string:equal(\"åäö\", unicode:characters_to_nfd_binary(\"ÅÄÖ\"), true, nfc).\ntrue\n```","title":"string.equal/4","ref":"string.html#equal/4"},{"type":"function","doc":"","title":"string.find/2","ref":"string.html#find/2"},{"type":"function","doc":"Removes anything before `SearchPattern` in `String` and returns the remainder of\nthe string or `nomatch` if `SearchPattern` is not found. `Dir`, which can be\n`leading` or `trailing`, indicates from which direction characters are to be\nsearched.\n\n_Example:_\n\n```erlang\n1> string:find(\"ab..cd..ef\", \".\").\n\"..cd..ef\"\n2> string:find(<<\"ab..cd..ef\">>, \"..\", trailing).\n<<\"..ef\">>\n3> string:find(<<\"ab..cd..ef\">>, \"x\", leading).\nnomatch\n4> string:find(\"ab..cd..ef\", \"x\", trailing).\nnomatch\n```","title":"string.find/3","ref":"string.html#find/3"},{"type":"function","doc":"Returns `true` if `String` is the empty string, otherwise `false`.\n\n_Example:_\n\n```erlang\n1> string:is_empty(\"foo\").\nfalse\n2> string:is_empty([\"\",<<>>]).\ntrue\n```","title":"string.is_empty/1","ref":"string.html#is_empty/1"},{"type":"function","doc":"Returns a float between `+0.0` and `1.0` representing the\n[Jaro similarity](https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance)\nbetween the given strings. Strings with a higher similarity will score closer\nto `1.0`, with `+0.0` meaning no similarity and `1.0` meaning an exact match.\n\n_Example:_\n\n```erlang\n1> string:jaro_similarity(\"ditto\", \"ditto\").\n1.0\n2> string:jaro_similarity(\"foo\", \"bar\").\n+0.0\n3> string:jaro_similarity(\"michelle\", \"michael\").\n0.8690476190476191\n4> string:jaro_similarity(<<\"Édouard\"/utf8>>, <<\"Claude\">>).\n0.5317460317460317\n```\n\nThe Jaro distance between two strings can be calculated with\n`JaroDistance = 1.0 - JaroSimilarity`.","title":"string.jaro_similarity/2","ref":"string.html#jaro_similarity/2"},{"type":"function","doc":"Returns a string with the elements of `StringList` separated by the string in\n`Separator`.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use\n`lists:join/2`.\n\n_Example:_\n\n```erlang\n1> join([\"one\", \"two\", \"three\"], \", \").\n\"one, two, three\"\n```","title":"string.join/2","ref":"string.html#join/2"},{"type":"function","doc":"","title":"string.left/2","ref":"string.html#left/2"},{"type":"function","doc":"Returns `String` with the length adjusted in accordance with `Number`. The left\nmargin is fixed. If [`length(String)`](`length/1`) < `Number`, then `String` is\npadded with blanks or `Character`s.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use `pad/2` or\n`pad/3`.\n\n_Example:_\n\n```erlang\n1> string:left(\"Hello\",10,$.).\n\"Hello.....\"\n```","title":"string.left/3","ref":"string.html#left/3"},{"type":"function","doc":"Returns the number of characters in `String`.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use `length/1`.","title":"string.len/1","ref":"string.html#len/1"},{"type":"function","doc":"Returns the number of grapheme clusters in `String`.\n\n_Example:_\n\n```erlang\n1> string:length(\"ß↑e̊\").\n3\n2> string:length(<<195,159,226,134,145,101,204,138>>).\n3\n```","title":"string.length/1","ref":"string.html#length/1"},{"type":"function","doc":"Returns a list of lexemes in `String`, separated by the grapheme clusters in\n`SeparatorList`.\n\nNotice that, as shown in this example, two or more adjacent separator graphemes\nclusters in `String` are treated as one. That is, there are no empty strings in\nthe resulting list of lexemes. See also `split/3` which returns empty strings.\n\nNotice that `[$\\r,$\\n]` is one grapheme cluster.\n\n_Example:_\n\n```erlang\n1> string:lexemes(\"abc de̊fxxghix jkl\\r\\nfoo\", \"x e\" ++ [[$\\r,$\\n]]).\n[\"abc\",\"de̊f\",\"ghi\",\"jkl\",\"foo\"]\n2> string:lexemes(<<\"abc de̊fxxghix jkl\\r\\nfoo\"/utf8>>, \"x e\" ++ [$\\r,$\\n]).\n[<<\"abc\">>,<<\"de̊f\"/utf8>>,<<\"ghi\">>,<<\"jkl\\r\\nfoo\">>]\n```","title":"string.lexemes/2","ref":"string.html#lexemes/2"},{"type":"function","doc":"Converts `String` to lowercase.\n\nNotice that function `casefold/1` should be used when converting a string to be\ntested for equality.\n\n_Example:_\n\n```erlang\n2> string:lowercase(string:uppercase(\"Michał\")).\n\"michał\"\n```","title":"string.lowercase/1","ref":"string.html#lowercase/1"},{"type":"function","doc":"Returns the first codepoint in `String` and the rest of `String` in the tail.\nReturns an empty list if `String` is empty or an `{error, String}` tuple if the\nnext byte is invalid.\n\n_Example:_\n\n```erlang\n1> string:next_codepoint(unicode:characters_to_binary(\"e̊fg\")).\n[101|<<\"̊fg\"/utf8>>]\n```","title":"string.next_codepoint/1","ref":"string.html#next_codepoint/1"},{"type":"function","doc":"Returns the first grapheme cluster in `String` and the rest of `String` in the\ntail. Returns an empty list if `String` is empty or an `{error, String}` tuple\nif the next byte is invalid.\n\n_Example:_\n\n```erlang\n1> string:next_grapheme(unicode:characters_to_binary(\"e̊fg\")).\n[\"e̊\"|<<\"fg\">>]\n```","title":"string.next_grapheme/1","ref":"string.html#next_grapheme/1"},{"type":"function","doc":"Returns lexeme number `N` in `String`, where lexemes are separated by the\ngrapheme clusters in `SeparatorList`.\n\n_Example:_\n\n```erlang\n1> string:nth_lexeme(\"abc.de̊f.ghiejkl\", 3, \".e\").\n\"ghi\"\n```","title":"string.nth_lexeme/3","ref":"string.html#nth_lexeme/3"},{"type":"function","doc":"","title":"string.pad/2","ref":"string.html#pad/2"},{"type":"function","doc":"","title":"string.pad/3","ref":"string.html#pad/3"},{"type":"function","doc":"Pads `String` to `Length` with grapheme cluster `Char`. `Dir`, which can be\n`leading`, `trailing`, or `both`, indicates where the padding should be added.\n\n_Example:_\n\n```erlang\n1> string:pad(<<\"He̊llö\"/utf8>>, 8).\n[<<72,101,204,138,108,108,195,182>>,32,32,32]\n2> io:format(\"'~ts'~n\",[string:pad(\"He̊llö\", 8, leading)]).\n' He̊llö'\n3> io:format(\"'~ts'~n\",[string:pad(\"He̊llö\", 8, both)]).\n' He̊llö '\n```","title":"string.pad/4","ref":"string.html#pad/4"},{"type":"function","doc":"If `Prefix` is the prefix of `String`, removes it and returns the remainder of\n`String`, otherwise returns `nomatch`.\n\n_Example:_\n\n```erlang\n1> string:prefix(<<\"prefix of string\">>, \"pre\").\n<<\"fix of string\">>\n2> string:prefix(\"pre\", \"prefix\").\nnomatch\n```","title":"string.prefix/2","ref":"string.html#prefix/2"},{"type":"function","doc":"Returns the index of the last occurrence of `Character` in `String`. Returns `0`\nif `Character` does not occur.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use `find/3`.","title":"string.rchr/2","ref":"string.html#rchr/2"},{"type":"function","doc":"","title":"string.replace/3","ref":"string.html#replace/3"},{"type":"function","doc":"Replaces `SearchPattern` in `String` with `Replacement`. `Where`, indicates whether\nthe `leading`, the `trailing` or `all` encounters of `SearchPattern` are to be replaced.\n\nCan be implemented as:\n\n```erlang\nlists:join(Replacement, split(String, SearchPattern, Where)).\n```\n\n_Example:_\n\n```erlang\n1> string:replace(<<\"ab..cd..ef\">>, \"..\", \"*\").\n[<<\"ab\">>,\"*\",<<\"cd..ef\">>]\n2> string:replace(<<\"ab..cd..ef\">>, \"..\", \"*\", all).\n[<<\"ab\">>,\"*\",<<\"cd\">>,\"*\",<<\"ef\">>]\n```","title":"string.replace/4","ref":"string.html#replace/4"},{"type":"function","doc":"Returns the reverse list of the grapheme clusters in `String`.\n\n_Example:_\n\n```erlang\n1> Reverse = string:reverse(unicode:characters_to_nfd_binary(\"ÅÄÖ\")).\n[[79,776],[65,776],[65,778]]\n2> io:format(\"~ts~n\",[Reverse]).\nÖÄÅ\n```","title":"string.reverse/1","ref":"string.html#reverse/1"},{"type":"function","doc":"","title":"string.right/2","ref":"string.html#right/2"},{"type":"function","doc":"Returns `String` with the length adjusted in accordance with `Number`. The right\nmargin is fixed. If the length of `(String)` < `Number`, then `String` is padded\nwith blanks or `Character`s.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use `pad/3`.\n\n_Example:_\n\n```erlang\n1> string:right(\"Hello\", 10, $.).\n\".....Hello\"\n```","title":"string.right/3","ref":"string.html#right/3"},{"type":"function","doc":"Returns the position where the last occurrence of `SubString` begins in\n`String`. Returns `0` if `SubString` does not exist in `String`.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use `find/3`.\n\n_Example:_\n\n```erlang\n1> string:rstr(\" Hello Hello World World \", \"Hello World\").\n8\n```","title":"string.rstr/2","ref":"string.html#rstr/2"},{"type":"function","doc":"","title":"string.slice/2","ref":"string.html#slice/2"},{"type":"function","doc":"Returns a substring of `String` of at most `Length` grapheme clusters, starting\nat position `Start`.\n\n_Example:_\n\n```erlang\n1> string:slice(<<\"He̊llö Wörld\"/utf8>>, 4).\n<<\"ö Wörld\"/utf8>>\n2> string:slice([\"He̊llö \", <<\"Wörld\"/utf8>>], 4,4).\n\"ö Wö\"\n3> string:slice([\"He̊llö \", <<\"Wörld\"/utf8>>], 4,50).\n\"ö Wörld\"\n```","title":"string.slice/3","ref":"string.html#slice/3"},{"type":"function","doc":"Returns the length of the maximum initial segment of `String`, which consists\nentirely of characters from `Chars`.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use `take/2`.\n\n_Example:_\n\n```erlang\n1> string:span(\"\\t abcdef\", \" \\t\").\n5\n```","title":"string.span/2","ref":"string.html#span/2"},{"type":"function","doc":"","title":"string.split/2","ref":"string.html#split/2"},{"type":"function","doc":"Splits `String` where `SearchPattern` is encountered and return the remaining\nparts. `Where`, default `leading`, indicates whether the `leading`, the\n`trailing` or `all` encounters of `SearchPattern` will split `String`.\n\n_Example:_\n\n```erlang\n0> string:split(\"ab..bc..cd\", \"..\").\n[\"ab\",\"bc..cd\"]\n1> string:split(<<\"ab..bc..cd\">>, \"..\", trailing).\n[<<\"ab..bc\">>,<<\"cd\">>]\n2> string:split(<<\"ab..bc....cd\">>, \"..\", all).\n[<<\"ab\">>,<<\"bc\">>,<<>>,<<\"cd\">>]\n```","title":"string.split/3","ref":"string.html#split/3"},{"type":"function","doc":"Returns the position where the first occurrence of `SubString` begins in\n`String`. Returns `0` if `SubString` does not exist in `String`.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use `find/2`.\n\n_Example:_\n\n```erlang\n1> string:str(\" Hello Hello World World \", \"Hello World\").\n8\n```","title":"string.str/2","ref":"string.html#str/2"},{"type":"function","doc":"","title":"string.strip/1","ref":"string.html#strip/1"},{"type":"function","doc":"","title":"string.strip/2","ref":"string.html#strip/2"},{"type":"function","doc":"Returns a string, where leading or trailing, or both, blanks or a number of\n`Character` have been removed.\n\n`Direction`, which can be `left`, `right`, or\n`both`, indicates from which direction blanks are to be removed.\n[`strip/1`](`strip/1`) is equivalent to [`strip(String, both)`](`strip/2`).\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use `trim/3`.\n\n_Example:_\n\n```erlang\n1> string:strip(\"...Hello.....\", both, $.).\n\"Hello\"\n```","title":"string.strip/3","ref":"string.html#strip/3"},{"type":"function","doc":"","title":"string.sub_string/2","ref":"string.html#sub_string/2"},{"type":"function","doc":"Returns a substring of `String`, starting at position `Start` to the end of the\nstring, or to and including position `Stop`.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use `slice/3`.\n\n_Example:_\n\n```erlang\n1> sub_string(\"Hello World\", 4, 8).\n\"lo Wo\"\n```","title":"string.sub_string/3","ref":"string.html#sub_string/3"},{"type":"function","doc":"","title":"string.sub_word/2","ref":"string.html#sub_word/2"},{"type":"function","doc":"Returns the word in position `Number` of `String`. Words are separated by blanks\nor `Character`s.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use\n`nth_lexeme/3`.\n\n_Example:_\n\n```erlang\n1> string:sub_word(\" Hello old boy !\",3,$o).\n\"ld b\"\n```","title":"string.sub_word/3","ref":"string.html#sub_word/3"},{"type":"function","doc":"","title":"string.substr/2","ref":"string.html#substr/2"},{"type":"function","doc":"Returns a substring of `String`, starting at position `Start`, and ending at the\nend of the string or at length `Length`.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use `slice/3`.\n\n_Example:_\n\n```erlang\n1> substr(\"Hello World\", 4, 5).\n\"lo Wo\"\n```","title":"string.substr/3","ref":"string.html#substr/3"},{"type":"function","doc":"","title":"string.take/2","ref":"string.html#take/2"},{"type":"function","doc":"","title":"string.take/3","ref":"string.html#take/3"},{"type":"function","doc":"Takes characters from `String` as long as the characters are members of set\n`Characters` or the complement of set `Characters`. `Dir`, which can be\n`leading` or `trailing`, indicates from which direction characters are to be\ntaken.\n\n_Example:_\n\n```erlang\n5> string:take(\"abc0z123\", lists:seq($a,$z)).\n{\"abc\",\"0z123\"}\n6> string:take(<<\"abc0z123\">>, lists:seq($0,$9), true, leading).\n{<<\"abc\">>,<<\"0z123\">>}\n7> string:take(\"abc0z123\", lists:seq($0,$9), false, trailing).\n{\"abc0z\",\"123\"}\n8> string:take(<<\"abc0z123\">>, lists:seq($a,$z), true, trailing).\n{<<\"abc0z\">>,<<\"123\">>}\n```","title":"string.take/4","ref":"string.html#take/4"},{"type":"function","doc":"Converts `String` to titlecase.\n\n_Example:_\n\n```erlang\n1> string:titlecase(\"ß is a SHARP s\").\n\"Ss is a SHARP s\"\n```","title":"string.titlecase/1","ref":"string.html#titlecase/1"},{"type":"function","doc":"Argument `String` is expected to start with a valid text represented float (the\ndigits are ASCII values). Remaining characters in the string after the float are\nreturned in `Rest`.\n\n_Example:_\n\n```erlang\n1> {F1,Fs} = string:to_float(\"1.0-1.0e-1\"),\n1> {F2,[]} = string:to_float(Fs),\n1> F1+F2.\n0.9\n2> string:to_float(\"3/2=1.5\").\n{error,no_float}\n3> string:to_float(\"-1.5eX\").\n{-1.5,\"eX\"}\n```","title":"string.to_float/1","ref":"string.html#to_float/1"},{"type":"function","doc":"Converts `String` to a list of grapheme clusters.\n\n_Example:_\n\n```erlang\n1> string:to_graphemes(\"ß↑e̊\").\n[223,8593,[101,778]]\n2> string:to_graphemes(<<\"ß↑e̊\"/utf8>>).\n[223,8593,[101,778]]\n```","title":"string.to_graphemes/1","ref":"string.html#to_graphemes/1"},{"type":"function","doc":"Argument `String` is expected to start with a valid text represented integer\n(the digits are ASCII values). Remaining characters in the string after the\ninteger are returned in `Rest`.\n\n_Example:_\n\n```erlang\n1> {I1,Is} = string:to_integer(\"33+22\"),\n1> {I2,[]} = string:to_integer(Is),\n1> I1-I2.\n11\n2> string:to_integer(\"0.5\").\n{0,\".5\"}\n3> string:to_integer(\"x=2\").\n{error,no_integer}\n```","title":"string.to_integer/1","ref":"string.html#to_integer/1"},{"type":"function","doc":"The specified string or character is case-converted. Notice that the supported\ncharacter set is ISO/IEC 8859-1 (also called Latin 1); all values outside this\nset are unchanged.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`) use\n`lowercase/1`, `titlecase/1` or `casefold/1`.","title":"string.to_lower/1","ref":"string.html#to_lower/1"},{"type":"function","doc":"The specified string or character is case-converted. Notice that the supported\ncharacter set is ISO/IEC 8859-1 (also called Latin 1); all values outside this\nset are unchanged.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`) use\n`uppercase/1`, `titlecase/1` or `casefold/1`.","title":"string.to_upper/1","ref":"string.html#to_upper/1"},{"type":"function","doc":"Returns a list of tokens in `String`, separated by the characters in\n`SeparatorList`.\n\n_Example:_\n\n```erlang\n1> tokens(\"abc defxxghix jkl\", \"x \").\n[\"abc\", \"def\", \"ghi\", \"jkl\"]\n```\n\nNotice that, as shown in this example, two or more adjacent separator characters\nin `String` are treated as one. That is, there are no empty strings in the\nresulting list of tokens.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use `lexemes/2`.","title":"string.tokens/2","ref":"string.html#tokens/2"},{"type":"function","doc":"","title":"string.trim/1","ref":"string.html#trim/1"},{"type":"function","doc":"Equivalent to [`trim(String, Dir, Whitespace})`](`trim/3`) where \n`Whitespace` is the set of nonbreakable whitespace codepoints, defined\nas Pattern_White_Space in\n[Unicode Standard Annex #31](http://unicode.org/reports/tr31/).","title":"string.trim/2","ref":"string.html#trim/2"},{"type":"function","doc":"Returns a string, where leading or trailing, or both, `Characters` have been\nremoved.\n\n`Dir` which can be `leading`, `trailing`, or `both`, indicates from\nwhich direction characters are to be removed.\n\nNote that `[$\\r,$\\n]` is one grapheme cluster according to the Unicode\nStandard.\n\n_Example:_\n\n```erlang\n1> string:trim(\"\\t Hello \\n\").\n\"Hello\"\n2> string:trim(<<\"\\t Hello \\n\">>, leading).\n<<\"Hello \\n\">>\n3> string:trim(<<\".Hello.\\n\">>, trailing, \"\\n.\").\n<<\".Hello\">>\n```","title":"string.trim/3","ref":"string.html#trim/3"},{"type":"function","doc":"Converts `String` to uppercase.\n\nSee also `titlecase/1`.\n\n_Example:_\n\n```erlang\n1> string:uppercase(\"Michał\").\n\"MICHAŁ\"\n```","title":"string.uppercase/1","ref":"string.html#uppercase/1"},{"type":"function","doc":"","title":"string.words/1","ref":"string.html#words/1"},{"type":"function","doc":"Returns the number of words in `String`, separated by blanks or `Character`.\n\nThis function is [obsolete](`m:string#obsolete-api-functions`). Use `lexemes/2`.\n\n_Example:_\n\n```erlang\n1> words(\" Hello old boy!\", $o).\n4\n```","title":"string.words/2","ref":"string.html#words/2"},{"type":"type","doc":"","title":"string.direction/0","ref":"string.html#t:direction/0"},{"type":"type","doc":"A user-perceived character, consisting of one or more codepoints.","title":"string.grapheme_cluster/0","ref":"string.html#t:grapheme_cluster/0"},{"type":"module","doc":"Functions for converting Unicode characters.\n\nThis module contains functions for converting between different character\nrepresentations. It converts between ISO Latin-1 characters and Unicode\ncharacters, but it can also convert between different Unicode encodings (like\nUTF-8, UTF-16, and UTF-32).\n\nThe default Unicode encoding in Erlang binaries is UTF-8, which is also the\nformat in which built-in functions and libraries in OTP expect to find binary\nUnicode data. In lists, Unicode data is encoded as integers, each integer\nrepresenting one character and encoded simply as the Unicode code point for the\ncharacter.\n\nOther Unicode encodings than integers representing code points or UTF-8 in\nbinaries are referred to as \"external encodings\". The ISO Latin-1 encoding is in\nbinaries and lists referred to as latin1-encoding.\n\nIt is recommended to only use external encodings for communication with external\nentities where this is required. When working inside the Erlang/OTP environment,\nit is recommended to keep binaries in UTF-8 when representing Unicode\ncharacters. ISO Latin-1 encoding is supported both for backward compatibility\nand for communication with external entities not supporting Unicode character\nsets.\n\nPrograms should always operate on a normalized form and compare\ncanonical-equivalent Unicode characters as equal. All characters should thus be\nnormalized to one form once on the system borders. One of the following\nfunctions can convert characters to their normalized forms\n`characters_to_nfc_list/1`, `characters_to_nfc_binary/1`,\n`characters_to_nfd_list/1` or `characters_to_nfd_binary/1`. For general text\n`characters_to_nfc_list/1` or `characters_to_nfc_binary/1` is preferred, and for\nidentifiers one of the compatibility normalization functions, such as\n`characters_to_nfkc_list/1`, is preferred for security reasons. The\nnormalization functions where introduced in OTP 20. Additional information on\nnormalization can be found in the\n[Unicode FAQ](http://unicode.org/faq/normalization.html).","title":"unicode","ref":"unicode.html"},{"type":"function","doc":"Checks for a UTF Byte Order Mark (BOM) in the beginning of a binary.\n\nIf the supplied binary `Bin` begins with a valid BOM for either UTF-8, UTF-16, or\nUTF-32, the function returns the encoding identified along with the BOM length\nin bytes.\n\nIf no BOM is found, the function returns `{latin1,0}`.","title":"unicode.bom_to_encoding/1","ref":"unicode.html#bom_to_encoding/1"},{"type":"function","doc":"","title":"unicode.characters_to_binary/1","ref":"unicode.html#characters_to_binary/1"},{"type":"function","doc":"","title":"unicode.characters_to_binary/2","ref":"unicode.html#characters_to_binary/2"},{"type":"function","doc":"Behaves as `characters_to_list/2`, but produces a binary instead of a Unicode\nlist.\n\n`InEncoding` defines how input is to be interpreted if binaries are present in\n`Data`\n\n`OutEncoding` defines in what format output is to be generated.\n\nOptions:\n\n- **`unicode`** - An alias for `utf8`, as this is the preferred encoding for\n Unicode characters in binaries.\n\n- **`utf16`** - An alias for `{utf16,big}`.\n\n- **`utf32`** - An alias for `{utf32,big}`.\n\nThe atoms `big` and `little` denote big- or little-endian encoding.\n\nErrors and exceptions occur as in `characters_to_list/2`, but the second element\nin tuple `error` or `incomplete` is a `t:binary/0` and not a `t:list/0`.","title":"unicode.characters_to_binary/3","ref":"unicode.html#characters_to_binary/3"},{"type":"function","doc":"","title":"unicode.characters_to_list/1","ref":"unicode.html#characters_to_list/1"},{"type":"function","doc":"Converts a possibly deep list of integers and binaries into a list of integers\nrepresenting Unicode characters. The binaries in the input can have characters\nencoded as one of the following:\n\n- ISO Latin-1 (0-255, one character per byte). Here, case parameter `InEncoding`\n is to be specified as `latin1`.\n- One of the UTF-encodings, which is specified as parameter `InEncoding`.\n\nNote that integers in the list always represent code points regardless of\n`InEncoding` passed. If `InEncoding latin1` is passed, only code points < 256\nare allowed; otherwise, all valid unicode code points are allowed.\n\nIf `InEncoding` is `latin1`, parameter `Data` corresponds to the `t:iodata/0`\ntype, but for `unicode`, parameter `Data` can contain integers > 255 (Unicode\ncharacters beyond the ISO Latin-1 range), which makes it invalid as\n`t:iodata/0`.\n\nThe purpose of the function is mainly to convert combinations of Unicode\ncharacters into a pure Unicode string in list representation for further\nprocessing. For writing the data to an external entity, the reverse function\n`characters_to_binary/3` comes in handy.\n\nOption `unicode` is an alias for `utf8`, as this is the preferred encoding for\nUnicode characters in binaries. `utf16` is an alias for `{utf16,big}` and\n`utf32` is an alias for `{utf32,big}`. The atoms `big` and `little` denote big-\nor little-endian encoding.\n\nIf the data cannot be converted, either because of illegal Unicode/ISO Latin-1\ncharacters in the list, or because of invalid UTF encoding in any binaries, an\nerror tuple is returned. The error tuple contains the tag `error`, a list\nrepresenting the characters that could be converted before the error occurred\nand a representation of the characters including and after the offending\ninteger/bytes. The last part is mostly for debugging, as it still constitutes a\npossibly deep or mixed list, or both, not necessarily of the same depth as the\noriginal data. The error occurs when traversing the list and whatever is left to\ndecode is returned \"as is\".\n\nHowever, if the input `Data` is a pure binary, the third part of the error tuple\nis guaranteed to be a binary as well.\n\nErrors occur for the following reasons:\n\n- Integers out of range.\n\n If `InEncoding` is `latin1`, an error occurs whenever an integer > 255 is\n found in the lists.\n\n If `InEncoding` is of a Unicode type, an error occurs whenever either of the\n following is found:\n\n - An integer > 16#10FFFF (the maximum Unicode character)\n - An integer in the range 16#D800 to 16#DFFF (invalid range reserved for\n UTF-16 surrogate pairs)\n\n- Incorrect UTF encoding.\n\n If `InEncoding` is one of the UTF types, the bytes in any binaries must be\n valid in that encoding.\n\n Errors can occur for various reasons, including the following:\n\n - \"Pure\" decoding errors (like the upper bits of the bytes being wrong).\n - The bytes are decoded to a too large number.\n - The bytes are decoded to a code point in the invalid Unicode range.\n - Encoding is \"overlong\", meaning that a number should have been encoded in\n fewer bytes.\n\n The case of a truncated UTF is handled specially, see the paragraph about\n incomplete binaries below.\n\n If `InEncoding` is `latin1`, binaries are always valid as long as they contain\n whole bytes, as each byte falls into the valid ISO Latin-1 range.\n\nA special type of error is when no actual invalid integers or bytes are found,\nbut a trailing `t:binary/0` consists of too few bytes to decode the last\ncharacter. This error can occur if bytes are read from a file in chunks or if\nbinaries in other ways are split on non-UTF character boundaries. An\n`incomplete` tuple is then returned instead of the `error` tuple. It consists of\nthe same parts as the `error` tuple, but the tag is `incomplete` instead of\n`error` and the last element is always guaranteed to be a binary consisting of\nthe first part of a (so far) valid UTF character.\n\nIf one UTF character is split over two consecutive binaries in the `Data`, the\nconversion succeeds. This means that a character can be decoded from a range of\nbinaries as long as the whole range is specified as input without errors\noccurring.\n\n_Example:_\n\n```erlang\ndecode_data(Data) ->\n case unicode:characters_to_list(Data,unicode) of\n {incomplete,Encoded, Rest} ->\n More = get_some_more_data(),\n Encoded ++ decode_data([Rest, More]);\n {error,Encoded,Rest} ->\n handle_error(Encoded,Rest);\n List ->\n List\n end.\n```\n\nHowever, bit strings that are not whole bytes are not allowed, so a UTF\ncharacter must be split along 8-bit boundaries to ever be decoded.\n\nA `badarg` exception is thrown for the following cases:\n\n- Any parameters are of the wrong type.\n- The list structure is invalid (a number as tail).\n- The binaries do not contain whole bytes (bit strings).","title":"unicode.characters_to_list/2","ref":"unicode.html#characters_to_list/2"},{"type":"function","doc":"Converts a possibly deep list of characters and binaries into a Normalized Form\nof canonical equivalent Composed characters according to the Unicode standard.\n\nAny binaries in the input must be encoded with utf8 encoding.\n\nThe result is an utf8 encoded binary.\n\n```erlang\n4> unicode:characters_to_nfc_binary([<<\"abc..a\">>,[778],$a,[776],$o,[776]]).\n<<\"abc..åäö\"/utf8>>\n```","title":"unicode.characters_to_nfc_binary/1","ref":"unicode.html#characters_to_nfc_binary/1"},{"type":"function","doc":"Converts a possibly deep list of characters and binaries into a Normalized Form\nof canonical equivalent Composed characters according to the Unicode standard.\n\nAny binaries in the input must be encoded with utf8 encoding.\n\nThe result is a list of characters.\n\n```erlang\n3> unicode:characters_to_nfc_list([<<\"abc..a\">>,[778],$a,[776],$o,[776]]).\n\"abc..åäö\"\n```","title":"unicode.characters_to_nfc_list/1","ref":"unicode.html#characters_to_nfc_list/1"},{"type":"function","doc":"Converts a possibly deep list of characters and binaries into a Normalized Form\nof canonical equivalent Decomposed characters according to the Unicode standard.\n\nAny binaries in the input must be encoded with utf8 encoding.\n\nThe result is an utf8 encoded binary.\n\n```erlang\n2> unicode:characters_to_nfd_binary(\"abc..åäö\").\n<<97,98,99,46,46,97,204,138,97,204,136,111,204,136>>\n```","title":"unicode.characters_to_nfd_binary/1","ref":"unicode.html#characters_to_nfd_binary/1"},{"type":"function","doc":"Converts a possibly deep list of characters and binaries into a Normalized Form\nof canonical equivalent Decomposed characters according to the Unicode standard.\n\nAny binaries in the input must be encoded with utf8 encoding.\n\nThe result is a list of characters.\n\n```erlang\n1> unicode:characters_to_nfd_list(\"abc..åäö\").\n[97,98,99,46,46,97,778,97,776,111,776]\n```","title":"unicode.characters_to_nfd_list/1","ref":"unicode.html#characters_to_nfd_list/1"},{"type":"function","doc":"Converts a possibly deep list of characters and binaries into a Normalized Form\nof compatibly equivalent Composed characters according to the Unicode standard.\n\nAny binaries in the input must be encoded with utf8 encoding.\n\nThe result is an utf8 encoded binary.\n\n```erlang\n4> unicode:characters_to_nfkc_binary([<<\"abc..a\">>,[778],$a,[776],$o,[776],[65299,65298]]).\n<<\"abc..åäö32\"/utf8>>\n```","title":"unicode.characters_to_nfkc_binary/1","ref":"unicode.html#characters_to_nfkc_binary/1"},{"type":"function","doc":"Converts a possibly deep list of characters and binaries into a Normalized Form\nof compatibly equivalent Composed characters according to the Unicode standard.\n\nAny binaries in the input must be encoded with utf8 encoding.\n\nThe result is a list of characters.\n\n```erlang\n3> unicode:characters_to_nfkc_list([<<\"abc..a\">>,[778],$a,[776],$o,[776],[65299,65298]]).\n\"abc..åäö32\"\n```","title":"unicode.characters_to_nfkc_list/1","ref":"unicode.html#characters_to_nfkc_list/1"},{"type":"function","doc":"Converts a possibly deep list of characters and binaries into a Normalized Form\nof compatibly equivalent Decomposed characters according to the Unicode\nstandard.\n\nAny binaries in the input must be encoded with utf8 encoding.\n\nThe result is an utf8 encoded binary.\n\n```erlang\n2> unicode:characters_to_nfkd_binary([\"abc..åäö\",[65299,65298]]).\n<<97,98,99,46,46,97,204,138,97,204,136,111,204,136,51,50>>\n```","title":"unicode.characters_to_nfkd_binary/1","ref":"unicode.html#characters_to_nfkd_binary/1"},{"type":"function","doc":"Converts a possibly deep list of characters and binaries into a Normalized Form\nof compatibly equivalent Decomposed characters according to the Unicode\nstandard.\n\nAny binaries in the input must be encoded with utf8 encoding.\n\nThe result is a list of characters.\n\n```erlang\n1> unicode:characters_to_nfkd_list([\"abc..åäö\",[65299,65298]]).\n[97,98,99,46,46,97,778,97,776,111,776,51,50]\n```","title":"unicode.characters_to_nfkd_list/1","ref":"unicode.html#characters_to_nfkd_list/1"},{"type":"function","doc":"Creates a UTF Byte Order Mark (BOM) as a binary from the supplied `InEncoding`.\n\nThe BOM is, if supported at all, expected to be placed first in UTF encoded\nfiles or messages.\n\nThe function returns `<<>>` for `latin1` encoding, as there is no BOM for ISO\nLatin-1.\n\nNotice that the BOM for UTF-8 is seldom used, and it is really not a _byte\norder_ mark. There are obviously no byte order issues with UTF-8, so the BOM is\nonly there to differentiate UTF-8 encoding from other UTF formats.","title":"unicode.encoding_to_bom/1","ref":"unicode.html#encoding_to_bom/1"},{"type":"type","doc":"","title":"unicode.chardata/0","ref":"unicode.html#t:chardata/0"},{"type":"type","doc":"","title":"unicode.charlist/0","ref":"unicode.html#t:charlist/0"},{"type":"type","doc":"","title":"unicode.encoding/0","ref":"unicode.html#t:encoding/0"},{"type":"type","doc":"","title":"unicode.endian/0","ref":"unicode.html#t:endian/0"},{"type":"type","doc":"","title":"unicode.external_chardata/0","ref":"unicode.html#t:external_chardata/0"},{"type":"type","doc":"","title":"unicode.external_charlist/0","ref":"unicode.html#t:external_charlist/0"},{"type":"type","doc":"A `t:binary/0` with characters coded in a user-specified Unicode encoding other\nthan UTF-8 (that is, UTF-16 or UTF-32).","title":"unicode.external_unicode_binary/0","ref":"unicode.html#t:external_unicode_binary/0"},{"type":"type","doc":"A `t:binary/0` with characters coded in ISO Latin-1.","title":"unicode.latin1_binary/0","ref":"unicode.html#t:latin1_binary/0"},{"type":"type","doc":"An `t:integer/0` representing a valid ISO Latin-1 character (0-255).","title":"unicode.latin1_char/0","ref":"unicode.html#t:latin1_char/0"},{"type":"type","doc":"Equivalent to `t:iodata/0`.","title":"unicode.latin1_chardata/0","ref":"unicode.html#t:latin1_chardata/0"},{"type":"type","doc":"Equivalent to `t:iolist/0`.","title":"unicode.latin1_charlist/0","ref":"unicode.html#t:latin1_charlist/0"},{"type":"type","doc":"A `t:binary/0` with characters encoded in the UTF-8 coding standard.","title":"unicode.unicode_binary/0","ref":"unicode.html#t:unicode_binary/0"},{"type":"module","doc":"URI processing functions.\n\nThis module contains functions for parsing and handling URIs\n([RFC 3986](https://www.ietf.org/rfc/rfc3986.txt)) and form-urlencoded query\nstrings ([HTML 5.2](https://www.w3.org/TR/html52/)).\n\nParsing and serializing non-UTF-8 form-urlencoded query strings are also\nsupported ([HTML 5.0](https://www.w3.org/TR/html50/)).\n\nA URI is an identifier consisting of a sequence of characters matching the\nsyntax rule named _URI_ in [RFC 3986](https://www.ietf.org/rfc/rfc3986.txt).\n\nThe generic URI syntax consists of a hierarchical sequence of components\nreferred to as the scheme, authority, path, query, and fragment:\n\n```text\n URI = scheme \":\" hier-part [ \"?\" query ] [ \"#\" fragment ]\n hier-part = \"//\" authority path-abempty\n / path-absolute\n / path-rootless\n / path-empty\n scheme = ALPHA *( ALPHA / DIGIT / \"+\" / \"-\" / \".\" )\n authority = [ userinfo \"@\" ] host [ \":\" port ]\n userinfo = *( unreserved / pct-encoded / sub-delims / \":\" )\n\n reserved = gen-delims / sub-delims\n gen-delims = \":\" / \"/\" / \"?\" / \"#\" / \"[\" / \"]\" / \"@\"\n sub-delims = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n\n unreserved = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n```\n\nThe interpretation of a URI depends only on the characters used and not on how\nthose characters are represented in a network protocol.\n\nThe functions implemented by this module cover the following use cases:\n\n- Parsing URIs into its components and returing a map: `parse/1`\n- Recomposing a map of URI components into a URI string: `recompose/1`\n- Changing inbound binary and percent-encoding of URIs: `transcode/2`\n- Transforming URIs into a normalized form: `normalize/1`, `normalize/2`\n- Composing form-urlencoded query strings from a list of key-value pairs:\n `compose_query/1`, `compose_query/2`\n- Dissecting form-urlencoded query strings into a list of key-value pairs:\n `dissect_query/1`\n- Decoding percent-encoded triplets in URI map or a specific component of URI:\n `percent_decode/1`\n- Preparing and retrieving application specific data included in URI\n components:\n `quote/1`, `quote/2`, `unquote/1`\n\nThere are four different encodings present during the handling of URIs:\n\n- Inbound binary encoding in binaries\n- Inbound percent-encoding in lists and binaries\n- Outbound binary encoding in binaries\n- Outbound percent-encoding in lists and binaries\n\nFunctions with `t:uri_string/0` argument accept lists, binaries and mixed lists\n(lists with binary elements) as input type. All of the functions but\n[`transcode/2`](`transcode/2`) expects input as lists of unicode codepoints,\nUTF-8 encoded binaries and UTF-8 percent-encoded URI parts (\"%C3%B6\" corresponds\nto the unicode character \"ö\").\n\nUnless otherwise specified the return value type and encoding are the same as\nthe input type and encoding. That is, binary input returns binary output, list\ninput returns a list output but mixed input returns list output.\n\nIn case of lists there is only percent-encoding. In binaries, however, both\nbinary encoding and percent-encoding shall be considered.\n[`transcode/2`](`transcode/2`) provides the means to convert between the\nsupported encodings, it takes a `t:uri_string/0` and a list of options\nspecifying inbound and outbound encodings.\n\n[RFC 3986](https://www.ietf.org/rfc/rfc3986.txt) does not mandate any specific\ncharacter encoding and it is usually defined by the protocol or surrounding\ntext. This library takes the same assumption, binary and percent-encoding are\nhandled as one configuration unit, they cannot be set to different values.\n\nQuoting functions are intended to be used by URI producing application during\ncomponent preparation or retrieval phase to avoid conflicts between data and\ncharacters used in URI syntax. Quoting functions use percent encoding, but with\ndifferent rules than for example during execution of\n[`recompose/1`](`recompose/1`). It is user responsibility to provide quoting\nfunctions with application data only and using their output to combine an URI\ncomponent. \nQuoting functions can for instance be used for constructing a path component\nwith a segment containing '/' character which should not collide with '/' used\nas general delimiter in path component.","title":"uri_string","ref":"uri_string.html"},{"type":"function","doc":"This is a utility function meant to be used in the shell for printing the\nallowed characters in each major URI component, and also in the most important\ncharacters sets.\n\nNote that this function does not replace the ABNF rules defined by the standards,\nthese character sets are derived directly from those aformentioned rules. For more\ninformation see the\n[Uniform Resource Identifiers](uri_string_usage.md#percent_encoding) chapter in\nstdlib's Users Guide.","title":"uri_string.allowed_characters/0","ref":"uri_string.html#allowed_characters/0"},{"type":"function","doc":"Composes a form-urlencoded `QueryString` based on a `QueryList`, a list of\nnon-percent-encoded key-value pairs.\n\nForm-urlencoding is defined in section 4.10.21.6 of the [HTML 5.2](https://www.w3.org/TR/html52/)\nspecification and in section 4.10.22.6 of the [HTML 5.0](https://www.w3.org/TR/html50/)\nspecification for non-UTF-8 encodings.\n\nSee also the opposite operation `dissect_query/1`.\n\n_Example:_\n\n```erlang\n1> uri_string:compose_query([{\"foo bar\",\"1\"},{\"city\",\"örebro\"}]).\n\"foo+bar=1&city=%C3%B6rebro\"\n2> uri_string:compose_query([{<<\"foo bar\">>,<<\"1\">>},\n2> {<<\"city\">>,<<\"örebro\"/utf8>>}]).\n<<\"foo+bar=1&city=%C3%B6rebro\">>\n```","title":"uri_string.compose_query/1","ref":"uri_string.html#compose_query/1"},{"type":"function","doc":"Same as [`compose_query/1`](`compose_query/1`) but with an additional `Options`\nparameter, that controls the encoding (\"charset\") used by the encoding\nalgorithm.\n\nThere are two supported encodings: `utf8` (or `unicode`) and `latin1`.\n\nEach character in the entry's name and value that cannot be expressed using the\nselected character encoding, is replaced by a string consisting of a U+0026\nAMPERSAND character (&), a \"#\" (U+0023) character, one or more ASCII digits\nrepresenting the Unicode code point of the character in base ten, and finally a\n\";\" (U+003B) character.\n\nBytes that are out of the range 0x2A, 0x2D, 0x2E, 0x30 to 0x39, 0x41 to 0x5A,\n0x5F, 0x61 to 0x7A, are percent-encoded (U+0025 PERCENT SIGN character (%)\nfollowed by uppercase ASCII hex digits representing the hexadecimal value of the\nbyte).\n\nSee also the opposite operation `dissect_query/1`.\n\n_Example:_\n\n```erlang\n1> uri_string:compose_query([{\"foo bar\",\"1\"},{\"city\",\"örebro\"}],\n1> [{encoding, latin1}]).\n\"foo+bar=1&city=%F6rebro\"\n2> uri_string:compose_query([{<<\"foo bar\">>,<<\"1\">>},\n2> {<<\"city\">>,<<\"東京\"/utf8>>}], [{encoding, latin1}]).\n<<\"foo+bar=1&city=%26%2326481%3B%26%2320140%3B\">>\n```","title":"uri_string.compose_query/2","ref":"uri_string.html#compose_query/2"},{"type":"function","doc":"Dissects an urlencoded `QueryString` and returns a `QueryList`, a list of\nnon-percent-encoded key-value pairs.\n\nForm-urlencoding is defined in section 4.10.21.6 of the [HTML 5.2](https://www.w3.org/TR/html52/)\nspecification and in section 4.10.22.6 of the [HTML 5.0](https://www.w3.org/TR/html50/)\nspecification for non-UTF-8 encodings.\n\nSee also the opposite operation `compose_query/1`.\n\n_Example:_\n\n```erlang\n1> uri_string:dissect_query(\"foo+bar=1&city=%C3%B6rebro\").\n[{\"foo bar\",\"1\"},{\"city\",\"örebro\"}]\n2> uri_string:dissect_query(<<\"foo+bar=1&city=%26%2326481%3B%26%2320140%3B\">>).\n[{<<\"foo bar\">>,<<\"1\">>},\n {<<\"city\">>,<<230,157,177,228,186,172>>}]\n```","title":"uri_string.dissect_query/1","ref":"uri_string.html#dissect_query/1"},{"type":"function","doc":"Transforms an `URI` into a normalized form using Syntax-Based Normalization as\ndefined by [RFC 3986](https://www.ietf.org/rfc/rfc3986.txt).\n\nThis function implements case normalization, percent-encoding normalization,\npath segment normalization and scheme based normalization for HTTP(S) with basic\nsupport for FTP, SSH, SFTP and TFTP.\n\n_Example:_\n\n```erlang\n1> uri_string:normalize(\"/a/b/c/./../../g\").\n\"/a/g\"\n2> uri_string:normalize(<<\"mid/content=5/../6\">>).\n<<\"mid/6\">>\n3> uri_string:normalize(\"http://localhost:80\").\n\"http://localhost/\"\n4> uri_string:normalize(#{scheme => \"http\",port => 80,path => \"/a/b/c/./../../g\",\n4> host => \"localhost-örebro\"}).\n\"http://localhost-%C3%B6rebro/a/g\"\n```","title":"uri_string.normalize/1","ref":"uri_string.html#normalize/1"},{"type":"function","doc":"Same as [`normalize/1`](`normalize/1`) but with an additional `Options`\nparameter, that controls whether the normalized URI shall be returned as an\nuri_map().\n\nThere is one supported option: `return_map`.\n\n_Example:_\n\n```erlang\n1> uri_string:normalize(\"/a/b/c/./../../g\", [return_map]).\n#{path => \"/a/g\"}\n2> uri_string:normalize(<<\"mid/content=5/../6\">>, [return_map]).\n#{path => <<\"mid/6\">>}\n3> uri_string:normalize(\"http://localhost:80\", [return_map]).\n#{scheme => \"http\",path => \"/\",host => \"localhost\"}\n4> uri_string:normalize(#{scheme => \"http\",port => 80,path => \"/a/b/c/./../../g\",\n4> host => \"localhost-örebro\"}, [return_map]).\n#{scheme => \"http\",path => \"/a/g\",host => \"localhost-örebro\"}\n```","title":"uri_string.normalize/2","ref":"uri_string.html#normalize/2"},{"type":"function","doc":"Parses an [RFC 3986](https://www.ietf.org/rfc/rfc3986.txt) compliant\n`t:uri_string/0` into a `t:uri_map/0`, that holds the parsed components of the\n`URI`. If parsing fails, an error tuple is returned.\n\nSee also the opposite operation `recompose/1`.\n\n_Example:_\n\n```erlang\n1> uri_string:parse(\"foo://user@example.com:8042/over/there?name=ferret#nose\").\n#{fragment => \"nose\",host => \"example.com\",\n path => \"/over/there\",port => 8042,query => \"name=ferret\",\n scheme => foo,userinfo => \"user\"}\n2> uri_string:parse(<<\"foo://user@example.com:8042/over/there?name=ferret\">>).\n#{host => <<\"example.com\">>,path => <<\"/over/there\">>,\n port => 8042,query => <<\"name=ferret\">>,scheme => <<\"foo\">>,\n userinfo => <<\"user\">>}\n```","title":"uri_string.parse/1","ref":"uri_string.html#parse/1"},{"type":"function","doc":"Decodes all percent-encoded triplets in the input that can be both a\n`t:uri_string/0` and a `t:uri_map/0`.\n\nNote, that this function performs raw decoding and it shall be used on already\nparsed URI components. Applying this function directly on a standard URI can\neffectively change it.\n\nIf the input encoding is not UTF-8, an error tuple is returned.\n\n_Example:_\n\n```erlang\n1> uri_string:percent_decode(#{host => \"localhost-%C3%B6rebro\",path => [],\n1> scheme => \"http\"}).\n#{host => \"localhost-örebro\",path => [],scheme => \"http\"}\n2> uri_string:percent_decode(<<\"%C3%B6rebro\">>).\n<<\"örebro\"/utf8>>\n```\n\n> #### Warning {: .warning }\n>\n> Using `uri_string:percent_decode/1` directly on a URI is not safe. This\n> example shows, that after each consecutive application of the function the\n> resulting URI will be changed. None of these URIs refer to the same resource.\n>\n> ```erlang\n> 3> uri_string:percent_decode(<<\"http://local%252Fhost/path\">>).\n> <<\"http://local%2Fhost/path\">>\n> 4> uri_string:percent_decode(<<\"http://local%2Fhost/path\">>).\n> <<\"http://local/host/path\">>\n> ```","title":"uri_string.percent_decode/1","ref":"uri_string.html#percent_decode/1"},{"type":"function","doc":"Replaces characters out of unreserved set with their percent encoded\nequivalents.\n\nUnreserved characters defined in\n[RFC 3986](https://www.ietf.org/rfc/rfc3986.txt) are not quoted.\n\n_Example:_\n\n```erlang\n1> uri_string:quote(\"SomeId/04\").\n\"SomeId%2F04\"\n2> uri_string:quote(<<\"SomeId/04\">>).\n<<\"SomeId%2F04\">>\n```\n\n> #### Warning {: .warning }\n>\n> Function is not aware about any URI component context and should not be used\n> on whole URI. If applied more than once on the same data, might produce\n> unexpected results.","title":"uri_string.quote/1","ref":"uri_string.html#quote/1"},{"type":"function","doc":"Same as [`quote/1`](`quote/1`), but `Safe` allows user to provide a list of\ncharacters to be protected from encoding.\n\n_Example:_\n\n```erlang\n1> uri_string:quote(\"SomeId/04\", \"/\").\n\"SomeId/04\"\n2> uri_string:quote(<<\"SomeId/04\">>, \"/\").\n<<\"SomeId/04\">>\n```\n\n> #### Warning {: .warning }\n>\n> Function is not aware about any URI component context and should not be used\n> on whole URI. If applied more than once on the same data, might produce\n> unexpected results.","title":"uri_string.quote/2","ref":"uri_string.html#quote/2"},{"type":"function","doc":"Creates an [RFC 3986](https://www.ietf.org/rfc/rfc3986.txt) compliant\n`URIString` (percent-encoded), based on the components of `URIMap`. If the\n`URIMap` is invalid, an error tuple is returned.\n\nSee also the opposite operation `parse/1`.\n\n_Example:_\n\n```erlang\n1> URIMap = #{fragment => \"nose\", host => \"example.com\", path => \"/over/there\",\n1> port => 8042, query => \"name=ferret\", scheme => \"foo\", userinfo => \"user\"}.\n#{fragment => \"nose\",host => \"example.com\",\n path => \"/over/there\",port => 8042,query => \"name=ferret\",\n scheme => \"foo\",userinfo => \"user\"}\n\n2> uri_string:recompose(URIMap).\n\"foo://example.com:8042/over/there?name=ferret#nose\"\n```","title":"uri_string.recompose/1","ref":"uri_string.html#recompose/1"},{"type":"function","doc":"Convert a `RefURI` reference that might be relative to a given base URI into the\nparsed components of the reference's target, which can then be recomposed to\nform the target URI.\n\n_Example:_\n\n```erlang\n1> uri_string:resolve(\"/abs/ol/ute\", \"http://localhost/a/b/c?q\").\n\"http://localhost/abs/ol/ute\"\n2> uri_string:resolve(\"../relative\", \"http://localhost/a/b/c?q\").\n\"http://localhost/a/relative\"\n3> uri_string:resolve(\"http://localhost/full\", \"http://localhost/a/b/c?q\").\n\"http://localhost/full\"\n4> uri_string:resolve(#{path => \"path\", query => \"xyz\"}, \"http://localhost/a/b/c?q\").\n\"http://localhost/a/b/path?xyz\"\n```","title":"uri_string.resolve/2","ref":"uri_string.html#resolve/2"},{"type":"function","doc":"Same as [`resolve/2`](`resolve/2`) but with an additional `Options` parameter,\nthat controls whether the target URI shall be returned as an uri_map(). There is\none supported option: `return_map`.\n\n_Example:_\n\n```erlang\n1> uri_string:resolve(\"/abs/ol/ute\", \"http://localhost/a/b/c?q\", [return_map]).\n#{host => \"localhost\",path => \"/abs/ol/ute\",scheme => \"http\"}\n2> uri_string:resolve(#{path => \"/abs/ol/ute\"}, #{scheme => \"http\",\n2> host => \"localhost\", path => \"/a/b/c?q\"}, [return_map]).\n#{host => \"localhost\",path => \"/abs/ol/ute\",scheme => \"http\"}\n```","title":"uri_string.resolve/3","ref":"uri_string.html#resolve/3"},{"type":"function","doc":"Transcodes an [RFC 3986](https://www.ietf.org/rfc/rfc3986.txt) compliant\n`URIString`, where `Options` is a list of tagged tuples, specifying the inbound\n(`in_encoding`) and outbound (`out_encoding`) encodings.\n\n`in_encoding` and `out_encoding` specifies both binary encoding and percent-encoding\nfor the input and output data. Mixed encoding, where binary encoding is not the same as\npercent-encoding, is not supported. If an argument is invalid, an error tuple is\nreturned.\n\n_Example:_\n\n```erlang\n1> uri_string:transcode(<<\"foo%00%00%00%F6bar\"/utf32>>,\n1> [{in_encoding, utf32},{out_encoding, utf8}]).\n<<\"foo%C3%B6bar\"/utf8>>\n2> uri_string:transcode(\"foo%F6bar\", [{in_encoding, latin1},\n2> {out_encoding, utf8}]).\n\"foo%C3%B6bar\"\n```","title":"uri_string.transcode/2","ref":"uri_string.html#transcode/2"},{"type":"function","doc":"Percent decode characters.\n\n_Example:_\n\n```erlang\n1> uri_string:unquote(\"SomeId%2F04\").\n\"SomeId/04\"\n2> uri_string:unquote(<<\"SomeId%2F04\">>).\n<<\"SomeId/04\">>\n```\n\n> #### Warning {: .warning }\n>\n> Function is not aware about any URI component context and should not be used\n> on whole URI. If applied more than once on the same data, might produce\n> unexpected results.","title":"uri_string.unquote/1","ref":"uri_string.html#unquote/1"},{"type":"type","doc":"Error tuple indicating the type of error. Possible values of the second\ncomponent:\n\n- `invalid_character`\n- `invalid_encoding`\n- `invalid_input`\n- `invalid_map`\n- `invalid_percent_encoding`\n- `invalid_scheme`\n- `invalid_uri`\n- `invalid_utf8`\n- `missing_value`\n\nThe third component is a term providing additional information about the cause\nof the error.","title":"uri_string.error/0","ref":"uri_string.html#t:error/0"},{"type":"type","doc":"Map holding the main components of a URI.","title":"uri_string.uri_map/0","ref":"uri_string.html#t:uri_map/0"},{"type":"type","doc":"List of unicode codepoints, a UTF-8 encoded binary, or a mix of the two,\nrepresenting an [RFC 3986](https://www.ietf.org/rfc/rfc3986.txt) compliant URI\n(_percent-encoded form_). A URI is a sequence of characters from a very limited\nset: the letters of the basic Latin alphabet, digits, and a few special\ncharacters.","title":"uri_string.uri_string/0","ref":"uri_string.html#t:uri_string/0"},{"type":"extras","doc":"\n# STDLIB Application","title":"STDLIB Application","ref":"stdlib_app.html"},{"type":"extras","doc":"The STDLIB application is mandatory in the sense that the minimal system based\non Erlang/OTP consists of Kernel and STDLIB. The STDLIB application contains no\nservices.","title":"Description - STDLIB Application","ref":"stdlib_app.html#description"},{"type":"extras","doc":"The following configuration parameters are defined for the STDLIB application.\nFor more information about configuration parameters, see the\n[`app(4)`](`e:kernel:app.md`) module in Kernel.\n\n- **`shell_esc = icl | abort`{: #shell_esc }** - Can be used to change the\n behavior of the Erlang shell when _^G_ is pressed.\n\n- **`restricted_shell = module()`{: #restricted_shell }** - Can be used to run\n the Erlang shell in restricted mode.\n\n- **`shell_catch_exception = boolean()`{: #shell_catch_exception }** - Can be\n used to set the exception handling of the evaluator process of Erlang shell.\n\n- **`shell_docs_columns = pos_integer()`{: #shell_docs_columns }** -\n Configures how wide the documentation should be rendered in the shell.\n\n See also `t:shell_docs:config/0`.\n\n- **`shell_expand_location = above | below`{: #shell_expand_location }** - Sets\n where the tab expansion text should appear in the shell. The default is\n `below`. This will open a pager below the cursor that is scrollable one line\n at a time with `Up/Down` arrow keys or 5 lines at a time with `PgUp/PgDn`.\n\n- **`shell_history_length = integer() >= 0`{: #shell_history_length }** - Can be\n used to determine how many commands are saved by the Erlang shell. See\n `m:edlin` for more.\n\n- **`shell_keymap = #{}`{: #shell_keymap }** - Can be used to override the\n default keymap configuration for the shell.\n\n- **`format_shell_func = {Mod, Func} | string() | default`{: #format_shell_func\n }** - Can be used to set the formatting of the Erlang shell output. This has\n an effect on commands that have been submitted and how it is saved in history\n or if the formatting hotkey is pressed while editing an expression (Alt+F by\n default). You can specify a Mod:Func/1 that expects the whole expression as a\n string and returns a formatted expressions as a string. See\n `shell:format_shell_func/1` for how to set it from inside the shell.\n\n If instead a string is provided, it will be used as a shell command. Your\n command must include `${file}` somewhere in the string, for the shell to know\n where the file goes in the command.\n\n ```text\n -stdlib format_shell_func \"\\\"emacs -batch \\${file} -l ~/erlang-format/emacs-format-file -f emacs-format-function\\\"\"\n ```\n\n ```text\n -stdlib format_shell_func \"{shell, erl_pp_format_func}\"\n ```\n\n- **`shell_prompt_func = {Mod, Func} | default`{: #shell_prompt_func }** - where\n\n - `Mod = atom()`\n - `Func = atom()`\n\n Can be used to set a customized Erlang shell prompt function.\n\n- **`shell_multiline_prompt = {Mod, Func} | string() | default`{:\n #shell_multiline_prompt }** - where\n\n - `Mod = atom()`\n - `Func = atom()`\n\n Can be used to set a customized multiline shell prompt function. The multiline\n prompt function takes the main prompt as its only parameter.\n\n- **`shell_saved_results = integer() >= 0`{: #shell_saved_results }** - Can be\n used to determine how many results are saved by the Erlang shell.\n\n- **`shell_session_slogan = string() | fun() -> string())`{:\n #shell_session_slogan }** - The slogan printed when starting an Erlang shell.\n Example:\n\n ```erlang\n $ erl -stdlib shell_session_slogan '\"Test slogan\"'\n Erlang/OTP 26 [DEVELOPMENT] [erts-13.0.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]\n\n Test slogan\n 1>\n ```\n\n- **`shell_slogan = string() | fun(() -> string())`{: #shell_slogan }** - The\n slogan printed when starting the Erlang shell subsystem. Example:\n\n ```erlang\n $ erl -stdlib shell_slogan '\"Test slogan\"'\n Test slogan\n Eshell V13.0.2 (abort with ^G)\n 1>\n ```\n\n The default is the return value of\n [`erlang:system_info(system_version)`](`m:erlang#system_info_system_version`).\n\n- **`shell_strings = boolean()`{: #shell_strings }** - Can be used to determine\n how the Erlang shell outputs lists of integers.","title":"Configuration - STDLIB Application","ref":"stdlib_app.html#configuration"},{"type":"extras","doc":"[`app(4)`](`e:kernel:app.md`), `m:application`, `m:shell`","title":"See Also - STDLIB Application","ref":"stdlib_app.html#see-also"},{"type":"extras","doc":"\n# STDLIB Release Notes\n\nThis document describes the changes made to the STDLIB application.","title":"STDLIB Release Notes","ref":"notes.html"},{"type":"extras","doc":"","title":"STDLIB 6.1.2 - STDLIB Release Notes","ref":"notes.html#stdlib-6-1-2"},{"type":"extras","doc":"- With this change, uri_string:normalize assumes empty path (do not crash) when no path is provided in the URI map.\n\n Own Id: OTP-19266 Aux Id: ERIERL-1127, [PR-8890]\n\n- Fixed spec for `json:format/3`.\n\n Own Id: OTP-19286 Aux Id: [GH-8880], [PR-8914]\n\n[PR-8890]: https://github.com/erlang/otp/pull/8890\n[GH-8880]: https://github.com/erlang/otp/issues/8880\n[PR-8914]: https://github.com/erlang/otp/pull/8914","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 6.1.1 - STDLIB Release Notes","ref":"notes.html#stdlib-6-1-1"},{"type":"extras","doc":"- Remove whitespace stripping of returned binaries in `json:decode/3`.\n\n Own Id: OTP-19227 Aux Id: ERIERL-1130, [PR-8809]\n\n- 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.\n\n Own Id: OTP-19241 Aux Id: [PR-8836]\n\n- With this change, shutdown procedure handles a race condition between supervisor executing a shutdown and child process termination from other reason.\n\n Own Id: OTP-19256 Aux Id: [PR-8780]\n\n[PR-8809]: https://github.com/erlang/otp/pull/8809\n[PR-8836]: https://github.com/erlang/otp/pull/8836\n[PR-8780]: https://github.com/erlang/otp/pull/8780","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 6.1 - STDLIB Release Notes","ref":"notes.html#stdlib-6-1"},{"type":"extras","doc":"- The help printout for incorrect `t:io:format/0` strings now handles the `k` modifier correctly.\n\n Own Id: OTP-19146 Aux Id: [PR-8611], [GH-8568]\n\n- Fixed a bug that caused the shell completion to crash when keyword and tuple appeared on the same line.\n\n Own Id: OTP-19157 Aux Id: [PR-8638]\n\n- 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.\n\n Own Id: OTP-19164 Aux Id: [GH-8605], [PR-7419], OTP-18671\n\n- Fixed an emulator crash relating to compressed ETS tables.\n\n Own Id: OTP-19176 Aux Id: [PR-8683]\n\n- 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\n\n Own Id: OTP-19189\n\n- Multiple issues have been corrected in the markdown parser that creates documentation for the shell. \n \n 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.\n \n The markdown parser is also used in the creation of other documentation formats, so this was a bug that affected other generated documentation formats.\n\n Own Id: OTP-19200 Aux Id: [GH-8738], [PR-8739]\n\n- Fixed category for some codepoint ranges in `unicode_util`.\n\n Own Id: OTP-19210 Aux Id: [GH-8748]\n\n- Fixed `m:argparse` to print sub-commands help when available.\n\n Own Id: OTP-19222 Aux Id: [PR-8777]\n\n[PR-8611]: https://github.com/erlang/otp/pull/8611\n[GH-8568]: https://github.com/erlang/otp/issues/8568\n[PR-8638]: https://github.com/erlang/otp/pull/8638\n[GH-8605]: https://github.com/erlang/otp/issues/8605\n[PR-7419]: https://github.com/erlang/otp/pull/7419\n[PR-8683]: https://github.com/erlang/otp/pull/8683\n[GH-8738]: https://github.com/erlang/otp/issues/8738\n[PR-8739]: https://github.com/erlang/otp/pull/8739\n[GH-8748]: https://github.com/erlang/otp/issues/8748\n[PR-8777]: https://github.com/erlang/otp/pull/8777","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Class annotation to HTML from fenced blocks have been added.\n\n Own Id: OTP-19105 Aux Id: [PR-8499]\n\n- Added JSON formatting functions for indented output.\n\n Own Id: OTP-19112\n\n- Improved illegal pattern error for accidental map associations.\n\n Own Id: OTP-19128 Aux Id: [PR-8555]\n\n- Progress reports for a dynamically started supervisor will now be logged at debug level.\n\n *** POTENTIAL INCOMPATIBILITY ***\n\n Own Id: OTP-19202 Aux Id: [PR-8261], [GH-8715], [PR-8741]\n\n- The `m:zip` module has been updated with support for:\n \n * zip64 archives - Archives larger than 4GB or with more than 2^32 entries.\n * extended timestamps - Higher resolution and in UTC.\n * UID/GID - Save and extract the original UID/GID.\n * Fixes so that permission mode attributes are correctly read and set for files in archives.\n * `zip:list_dir/2` now also returns directories, not only files. (You can disable this behaviour by using the option `skip_directories`).\n \n Various bugs in the original implementation have also been fixed, such as:\n \n * Correctly encode and decode the DOS timestamps for entries within an archive (that is the non-extended timestamp).\n * Fix DOS timestamps to be set to localtime instead of UTC (use extended timestamps for UTC timestamps).\n * Use the unix file attributes read from disk when creating archives instead of setting everything to 644.\n\n Own Id: OTP-19214 Aux Id: [PR-8765]\n\n[PR-8499]: https://github.com/erlang/otp/pull/8499\n[PR-8555]: https://github.com/erlang/otp/pull/8555\n[PR-8261]: https://github.com/erlang/otp/pull/8261\n[GH-8715]: https://github.com/erlang/otp/issues/8715\n[PR-8741]: https://github.com/erlang/otp/pull/8741\n[PR-8765]: https://github.com/erlang/otp/pull/8765","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 6.0.1 - STDLIB Release Notes","ref":"notes.html#stdlib-6-0-1"},{"type":"extras","doc":"- Fix so that missing `-doc({file, File})` files only result in a warning and not an error.\n\n Own Id: OTP-19099 Aux Id: [PR-8542]\n\n- Fixed `m:json` bugs, `json:encode_key_value_list/2` did not generate arrays and `json:decode/3` did not invoke the user callback for `0`.\n\n Own Id: OTP-19106 Aux Id: [PR-8581], [GH-8580], [PR-8519]\n\n[PR-8542]: https://github.com/erlang/otp/pull/8542\n[PR-8581]: https://github.com/erlang/otp/pull/8581\n[GH-8580]: https://github.com/erlang/otp/issues/8580\n[PR-8519]: https://github.com/erlang/otp/pull/8519","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 6.0 - STDLIB Release Notes","ref":"notes.html#stdlib-6-0"},{"type":"extras","doc":"- The specs in module `m:binary` has been updated to reflect what is allowed by the documentation.\n\n Own Id: OTP-18684 Aux Id: [PR-7481]\n\n- Several functions in the `m: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.\n \n The following functions would accept an invalid pattern if the subject binary was empty or if the `{scope,{0,0}}` option was given:\n [`binary:match/2,3`](`binary:match/3`),\n [`binary:matches/2,3`](`binary:matches/2`),\n [`binary:replace/3,4`](`binary:replace/3`), and\n [`binary:split/2,3`](`binary:split/2`)\n \n The call `binary:copy(<<1:1>>, 0)` would return an empty binary instead of raising an exception. Similarly, calls to [`binary:part/2,3`](`binary:part/2`) attempting to extract 0 bytes at position 0 of a bitstring would return an empty binary instead of raising an exception.\n\n Own Id: OTP-18743 Aux Id: [PR-7607], [PR-7628]\n\n- 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.)\n \n 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.\n\n *** POTENTIAL INCOMPATIBILITY ***\n\n Own Id: OTP-18784 Aux Id: [GH-7706], [PR-7726]\n\n- `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.\n\n Own Id: OTP-18930 Aux Id: [PR-7993], [GH-4992]\n\n- The error handling the `simple_one_for_one` supervisor has been enhanced. A transient child returning `ignore` will no longer cause a crash.\n \n 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.\n\n *** POTENTIAL INCOMPATIBILITY ***\n\n Own Id: OTP-19029 Aux Id: [PR-8230]\n\n- 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.\n\n Own Id: OTP-19073 Aux Id: [PR-8375], [GH-8366], [GH-8365], [GH-8364]\n\n[PR-7481]: https://github.com/erlang/otp/pull/7481\n[PR-7607]: https://github.com/erlang/otp/pull/7607\n[PR-7628]: https://github.com/erlang/otp/pull/7628\n[GH-7706]: https://github.com/erlang/otp/issues/7706\n[PR-7726]: https://github.com/erlang/otp/pull/7726\n[PR-7993]: https://github.com/erlang/otp/pull/7993\n[GH-4992]: https://github.com/erlang/otp/issues/4992\n[PR-8230]: https://github.com/erlang/otp/pull/8230\n[PR-8375]: https://github.com/erlang/otp/pull/8375\n[GH-8366]: https://github.com/erlang/otp/issues/8366\n[GH-8365]: https://github.com/erlang/otp/issues/8365\n[GH-8364]: https://github.com/erlang/otp/issues/8364","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The functions [`is_equal/2`](`sets:is_equal/2`), [`map/2`](`sets:map/2`), and [`filtermap/2`](`sets:filtermap/2`) have been added to the modules `m:sets`, `m:ordsets`, and `m:gb_sets`.\n\n Own Id: OTP-18622 Aux Id: [PR-7183], [PR-7232]\n\n- The compiler now emits nicer error message for function head mismatches.\n For example, given:\n \n ```erlang\n a() -> ok;\n a(_) -> error.\n ```\n \n Erlang/OTP 26 and earlier would emit a diagnostic similar to:\n \n ```text\n t.erl:6:1: head mismatch\n % 6| a(_) -> error.\n % | ^\n ```\n \n while in Erlang/OTP 27 the diagnostic is similar to:\n \n ```text\n 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?\n % 6| a(_) -> error.\n % | ^\n ```\n\n Own Id: OTP-18648 Aux Id: [PR-7383]\n\n- [`zip:create/2,3`](`zip:create/2`) will now tolerate POSIX timestamps in the provided `file_info` records.\n\n Own Id: OTP-18668\n\n- The callback function `c:gen_statem:handle_event/4` has been cached in the `gen_statem` engine to optimize callback call speed.\n\n Own Id: OTP-18671 Aux Id: [PR-7419]\n\n- The type `beam_lib:beam/0` is now exported.\n\n Own Id: OTP-18716 Aux Id: [PR-7534]\n\n- The documentation for the `m:binary` module has been improved.\n\n Own Id: OTP-18741 Aux Id: [PR-7585]\n\n- [`binary:replace/3,4`](`binary:replace/3`) now supports using a fun for supplying the replacement binary.\n\n Own Id: OTP-18742 Aux Id: [PR-7590]\n\n- Triple-Quoted Strings has been implemented as per [EEP 64](https://www.erlang.org/eeps/eep-0064). See [String](`e:system:data_types.md#string`) in the Reference Manual.\n \n Example:\n \n ```erlang\n 1> \"\"\"\n a\n b\n c\n \"\"\".\n \"a\\nb\\nc\"\n ```\n \n Adjacent string literals without intervening white space is now a syntax error, to avoid possible confusion with triple-quoted strings. For example:\n \n ```erlang\n 1> \"abc\"\"xyz\".\n \"xyz\".\n * 1:6: adjacent string literals without intervening white space\n ```\n\n *** POTENTIAL INCOMPATIBILITY ***\n\n Own Id: OTP-18750 Aux Id: OTP-18746, [PR-7313], [PR-7451]\n\n- 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`, `m:observer`, and it will be included in crash reports produced by processes using `m:gen_server`, `m:gen_statem`, `m:gen_event`, and `m:gen_fsm`.\n \n The label for a process can be retrieved by calling `proc_lib:get_label/1`.\n \n Note that those functions work on any process, not only processes that use `m:proc_lib`.\n \n Example:\n \n ```text\n 1> self().\n <0.90.0>\n 2> proc_lib:set_label(my_label).\n ok\n 3> i().\n .\n .\n .\n <0.90.0> erlang:apply/2 2586 75011 0\n my_label c:pinfo/2 51\n 4> proc_lib:get_label(self()).\n my_label\n ```\n\n Own Id: OTP-18789 Aux Id: [PR-7720], [PR-8003]\n\n- `-callback` attributes has been added to modules `m:sys` and `m:erl_error`.\n\n Own Id: OTP-18793 Aux Id: [PR-7703]\n\n- Several new functions that accept funs have been added to module `m:timer`.\n \n Functions [`apply_after/2`](`timer:apply_after/2`), [`apply_interval/2`](`timer:apply_interval/2`), and [`apply_repeatedly/2`](`apply_repeatedly/2`) accept a nullary fun as the second argument, while functions [`apply_after/3`](`timer:apply_after/3`), [`apply_interval/3`](`timer:apply_interval/3`), and [`apply_repeatedly/3`](`apply_repeatedly/3`) accept an n-ary fun as the second and a list of n arguments for the fun as the third argument.\n\n Own Id: OTP-18808 Aux Id: [PR-7649]\n\n- Sigils on string literals have been implemented as per [EEP 66](https://www.erlang.org/eeps/eep-0066), 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](`e:system:data_types.md#sigil`).\n \n Examples:\n \n ```erlang\n 1> ~\"Björn\".\n <<\"Björn\"/utf8>>\n 2> ~b\"Björn\".\n <<\"Björn\"/utf8>>\n 3> ~S\"\\s*(\\w+)\".\n \"\\\\s*(\\\\w+)\"\n 4> ~B\"\\s*(\\w+)\".\n <<\"\\\\s*(\\\\w+)\">>\n ```\n\n Own Id: OTP-18825 Aux Id: OTP-18750, [PR-7684]\n\n- Functions `shell:default_multiline_prompt/1`, `shell:inverted_space_prompt/1`, and \n `shell:prompt_width/1` have been exported to help with custom prompt implementations.\n\n Own Id: OTP-18834 Aux Id: [PR-7675], [PR-7816]\n\n- The shell now pages long output from the documentation help command ([`h(Module)`](`c:h/1`)), auto completions and the search command.\n\n Own Id: OTP-18846 Aux Id: [PR-7845]\n\n- The `M-h` hotkey (Alt/Option-h) now outputs help for the module or function directly before the cursor.\n\n Own Id: OTP-18847 Aux Id: [PR-7846]\n\n- 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`.\n\n Own Id: OTP-18848 Aux Id: [PR-7847]\n\n- Added shell functions for viewing, forgetting and saving locally defined functions, types and records.\n\n Own Id: OTP-18852 Aux Id: [PR-7844]\n\n- Added `string:jaro_similarity/2`, which can be used to calculate the similarity between two strings.\n\n Own Id: OTP-18865 Aux Id: [PR-7879]\n\n- 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.\n\n Own Id: OTP-18870 Aux Id: [PR-7857]\n\n- Added functions to retrieve the next higher or lower key/element from `m:gb_trees` and `m:gb_sets`, as well as returning iterators that start at given keys/elements.\n\n Own Id: OTP-18874 Aux Id: [PR-7745]\n\n- When the shell built-in function [`c/1,2`][c12] is used to re-compile a module, the current working directory of the original compilation is now added to the include path.\n \n [c12]: `\\c:c/1`\n\n Own Id: OTP-18908 Aux Id: [PR-7957]\n\n- The `timer` module now uses a private table for its internal state, slightly improving its performance.\n\n Own Id: OTP-18914 Aux Id: [PR-7973]\n\n- [EEP-59 - Documentation Attributes](https://www.erlang.org/eeps/eep-0059) has been implemented.\n \n Documentation attributes can be used to document functions, types, callbacks, and modules.\n 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.\n \n * 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.\n \n * The documentation from `moduledoc` and `doc` gets added by default to the binary beam file, following the format of [EEP-48](https://www.erlang.org/eeps/eep-0048).\n \n * Using the compiler flag `warn_missing_doc` will raise a warning when\n `-doc` attributes are missing in exported functions, types, and callbacks.\n \n * Using the compiler flag `warn_missing_spec_documented` will raise a warning when\n spec attributes are missing in documented functions, types, and callbacks.\n \n * `moduledoc`s and `doc`s 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.\n \n * 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.\n\n Own Id: OTP-18916 Aux Id: [PR-7936]\n\n- New `m: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.\n\n Own Id: OTP-18923 Aux Id: [PR-6791]\n\n- The `maybe` expression is now enabled by default.\n \n 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:\n \n ```erlang\n -feature(maybe_expr, disable).\n ```\n \n Another way to disable the `maybe_expr` feature is by passing the `-disable-feature` option to `erlc`:\n \n ```text\n erlc -disable-feature maybe_expr some_file.erl\n ```\n\n Own Id: OTP-18944 Aux Id: [PR-8067]\n\n- The compiler will now raise a warning when updating record/map literals. As an example, consider this module:\n \n ```erlang\n -module(t).\n -export([f/0]).\n -record(r, {a,b,c}).\n \n f() ->\n #r{a=1}#r{b=2}.\n ```\n \n The compiler raises the following warning:\n \n ```text\n 1> c(t).\n t.erl:6:12: Warning: expression updates a literal\n % 6| #r{a=1}#r{b=2}.\n % | ^\n ```\n\n Own Id: OTP-18951 Aux Id: [PR-8069]\n\n- The documentation has been migrated to use Markdown and ExDoc.\n\n Own Id: OTP-18955 Aux Id: [PR-8026]\n\n- Optimized `ets:foldl` and `ets:foldr` to use new `ets:next_lookup`. Also made them immune against table renaming.\n\n Own Id: OTP-18993 Aux Id: [PR-8048]\n\n- Windows now supports all functions in `m:math`.\n\n Own Id: OTP-19001 Aux Id: [PR-8164]\n\n- `m:erl_lint` (and by extension the [`compiler`](`m:compile`)) will now warn for code using deprecated callbacks.\n \n The only callback currenly deprecated is `format_status/2` in [`gen_server`](`c:gen_server:format_status/2`), [`gen_event`](`c:gen_event:format_status/2`) and [`gen_statem`](`c:gen_server:format_status/2`).\n \n You can use `nowarn_deprecated_callback` to silence the warning.\n\n Own Id: OTP-19010 Aux Id: [PR-8205]\n\n- There is a new module [`json`](`m:json`) for encoding and decoding [JSON](https://en.wikipedia.org/wiki/JSON).\n \n Both encoding and decoding can be customized. Decoding can be done in a SAX-like fashion and handle multiple documents and streams of data.\n\n Own Id: OTP-19020 Aux Id: [PR-8111]\n\n[PR-7183]: https://github.com/erlang/otp/pull/7183\n[PR-7232]: https://github.com/erlang/otp/pull/7232\n[PR-7383]: https://github.com/erlang/otp/pull/7383\n[PR-7419]: https://github.com/erlang/otp/pull/7419\n[PR-7534]: https://github.com/erlang/otp/pull/7534\n[PR-7585]: https://github.com/erlang/otp/pull/7585\n[PR-7590]: https://github.com/erlang/otp/pull/7590\n[PR-7313]: https://github.com/erlang/otp/pull/7313\n[PR-7451]: https://github.com/erlang/otp/pull/7451\n[PR-7720]: https://github.com/erlang/otp/pull/7720\n[PR-8003]: https://github.com/erlang/otp/pull/8003\n[PR-7703]: https://github.com/erlang/otp/pull/7703\n[PR-7649]: https://github.com/erlang/otp/pull/7649\n[PR-7684]: https://github.com/erlang/otp/pull/7684\n[PR-7675]: https://github.com/erlang/otp/pull/7675\n[PR-7816]: https://github.com/erlang/otp/pull/7816\n[PR-7845]: https://github.com/erlang/otp/pull/7845\n[PR-7846]: https://github.com/erlang/otp/pull/7846\n[PR-7847]: https://github.com/erlang/otp/pull/7847\n[PR-7844]: https://github.com/erlang/otp/pull/7844\n[PR-7879]: https://github.com/erlang/otp/pull/7879\n[PR-7857]: https://github.com/erlang/otp/pull/7857\n[PR-7745]: https://github.com/erlang/otp/pull/7745\n[PR-7957]: https://github.com/erlang/otp/pull/7957\n[PR-7973]: https://github.com/erlang/otp/pull/7973\n[PR-7936]: https://github.com/erlang/otp/pull/7936\n[PR-6791]: https://github.com/erlang/otp/pull/6791\n[PR-8067]: https://github.com/erlang/otp/pull/8067\n[PR-8069]: https://github.com/erlang/otp/pull/8069\n[PR-8026]: https://github.com/erlang/otp/pull/8026\n[PR-8048]: https://github.com/erlang/otp/pull/8048\n[PR-8164]: https://github.com/erlang/otp/pull/8164\n[PR-8205]: https://github.com/erlang/otp/pull/8205\n[PR-8111]: https://github.com/erlang/otp/pull/8111","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 5.2.3.2 - STDLIB Release Notes","ref":"notes.html#stdlib-5-2-3-2"},{"type":"extras","doc":"* With this change, shutdown procedure handles a race condition between supervisor executing a shutdown and child process termination from other reason.\n\n Own Id: OTP-19256 Aux Id: PR-8780\n* With this change, uri_string:normalize assumes empty path (do not crash) when no path is provided in the URI map.\n\n Own Id: OTP-19266 Aux Id: ERIERL-1127, PR-8890","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 5.2.3.1 - STDLIB Release Notes","ref":"notes.html#stdlib-5-2-3-1"},{"type":"extras","doc":"* Fixed a bug that caused the shell completion to crash when keyword and tuple appeared on the same line.\n\n Own Id: OTP-19157 Aux Id: PR-8638","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 5.2.3 - STDLIB Release Notes","ref":"notes.html#stdlib-5-2-3"},{"type":"extras","doc":"* Fix shell expansion of `-type a() :: $a.` in the erlang shell.\n\n Own Id: OTP-19062\n* Fix the shell Job Control Mode to not crash when typing `TAB` or `CTRL+R`.\n\n Own Id: OTP-19072 Aux Id: PR-8391","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 5.2.2 - STDLIB Release Notes","ref":"notes.html#stdlib-5-2-2"},{"type":"extras","doc":"* Attempting to use the `maybe` construct in a macro argument could crash the compiler.\n\n Own Id: OTP-19031 Aux Id: GH-8268","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 5.2.1 - STDLIB Release Notes","ref":"notes.html#stdlib-5-2-1"},{"type":"extras","doc":"* The help texts shown by `argparse` will now display sub-command arguments in the correct order.\n\n Own Id: OTP-18900 Aux Id: PR-7945, GH-7934\n* Clarified the argparse documentation regarding the user-defined help template.\n\n Own Id: OTP-18937\n* Fix shell expansion to not crash when expanding invalid using invalid atoms.\n\n Own Id: OTP-18953 Aux Id: GH-8016 PR-8075","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 5.2 - STDLIB Release Notes","ref":"notes.html#stdlib-5-2"},{"type":"extras","doc":"- Make `shell_docs` correctly trim the newline at the end of code blocks.\n\n Own Id: OTP-18777 Aux Id: PR-7663\n\n- Replaced unintentional Erlang Public License 1.1 headers in some files with\n the intended Apache License 2.0 header.\n\n Own Id: OTP-18815 Aux Id: PR-7780\n\n- Fixed a bug where autocompletion could crash the shell when trying to expand a\n nested tuple.\n\n Own Id: OTP-18822 Aux Id: PR-7796\n\n- Removed auto closing feature, in autocompletion, for function arguments,\n tuples, records and maps, since this could interfere with autocompletion of\n atoms.\n\n Own Id: OTP-18823\n\n- Fixed a bug where autocompletion string formatting would remove suggestions\n that had the same name but different case.\n\n Own Id: OTP-18824\n\n- Fix so that ctrl+h, ctrl+backspace in the shell only removes one character\n instead of a whole word.\n\n Own Id: OTP-18826 Aux Id: PR-7797\n\n- Fix so that its possible to override the default keyboard shortcuts for the\n shell.\n\n Own Id: OTP-18827 Aux Id: PR-7797\n\n- Allow shell local func v(), in a restricted shell\n\n Own Id: OTP-18828 Aux Id: PR-7799\n\n- Report syntax error when writing an invalid attribute like '1> -hej.'\n\n Own Id: OTP-18829 Aux Id: PR-7799\n\n- When attempting to match part of a record in the key of a map generator, the\n entire record would be matched.\n\n Own Id: OTP-18866 Aux Id: GH-7875, PR-7878","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The warning for accidental use of a future triple-quoted string delimiter has\n been upgraded to instead warn for adjacent strings without intervening white\n space, which effectively is the same at a string start, but also covers the\n same situation at a string end.\n\n Own Id: OTP-18821 Aux Id: OTP-18746\n\n- The removal of the deprecated `slave` module, originally planned for OTP 27,\n has been postponed to OTP 29.\n\n Own Id: OTP-18840 Aux Id: PR-7629\n\n- Guards have been added to `gen_*:start*` API functions to catch bad arguments\n earlier. Before this change, in some cases, a bad argument could tag along and\n cause the server to fail later, right after start.\n\n Own Id: OTP-18857 Aux Id: GH-7685","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 5.1.1 - STDLIB Release Notes","ref":"notes.html#stdlib-5-1-1"},{"type":"extras","doc":"- Garbage collect the shell process when reducing the amount of saved history\n and results.\n\n Own Id: OTP-18773 Aux Id: PR-7691","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 5.1 - STDLIB Release Notes","ref":"notes.html#stdlib-5-1"},{"type":"extras","doc":"- The compiler could run forever when compiling a call to\n [`is_record/3`](`is_record/3`) with a huge positive tuple size. The call\n [`is_record(A, a, 0)`](`is_record/3`) would crash the compiler when used in a\n function body. When used in a guard the compiler would emit incorrect code\n that would accept `{a>` as a record.\n\n Own Id: OTP-18605 Aux Id: GH-7298, GH-7317\n\n- Fix bug in `ets:tab2file` that could make it fail if another Erlang process\n created the same file at the same time.\n\n Own Id: OTP-18614 Aux Id: GH-7162, PR-7237\n\n- An `{else_clause,Value}` exception will now be reported nicely in the shell.\n\n Own Id: OTP-18616 Aux Id: GH-7258\n\n- Correct return value for error case, so that it matches the documented and\n intended return value \\{error, \\{already_started, pid()\\} when local\n registered names are used.\n\n Own Id: OTP-18627 Aux Id: PR-7072\n\n- `sys:get_state/1,2` and `sys:replace_state/2,3` has been corrected to handle a\n state named `error` as a state name, not as a failed system callback.\n\n For the standard server behaviours this was an issue only for `gen_statem`\n (and `gen_fsm`) when the state name was `error`, and for `gen_server` if the\n complete state was `{error,_}`.\n\n Own Id: OTP-18633\n\n- Multiple problems were fixed in `filelib:safe_relative_path/2`. If its second\n argument was a path that contained symbolic links, an incorrect result patch\n could be returned. Also, paths were sometimes falsely considered unsafe.\n\n Own Id: OTP-18655 Aux Id: GH-6460, PR-7208\n\n- Fix deadlock when `erl.exe` is used as part of a pipe on Windows and trying to\n set the encoding of the `standard_io` device.\n\n Own Id: OTP-18675 Aux Id: PR-7473 GH-7459\n\n- Expanded the documentation about how to use the `standard_io`,\n `standard_error` and `user` I/O devices.\n\n Added the types [`io:standard_io/0`](`t:io:standard_io/0`),\n `io:standard:error/0` and [`io:user/0`](`t:io:user/0`).\n\n Own Id: OTP-18676 Aux Id: PR-7473 GH-7459\n\n- Fix `h/2,3` to properly render multi-clause documentation.\n\n Own Id: OTP-18683 Aux Id: PR-7502\n\n- Timers created by `timer:apply_after/4`, `apply_interval/4`, and\n `apply_repeatedly/4` would silently fail to do the apply if it was not\n possible to spawn a process when the timer expired. This has now been\n corrected, and if the spawn fails, the system will be taken down producing a\n crash dump.\n\n Own Id: OTP-18759 Aux Id: GH-7606\n\n- When an Erlang source file lacked a module definition, there would be a\n spurious \"module name must not be empty\" diagnostic for each spec in the file.\n\n Own Id: OTP-18763 Aux Id: GH-7655","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The argument descriptions for option types in `argparse` have been made less\n ambiguous.\n\n Own Id: OTP-18679 Aux Id: ERIERL-965\n\n- Clarified the documentation of normal shutdown reason on `gen_server:call/2,3`\n\n Own Id: OTP-18690 Aux Id: PR-7511, GH-7510\n\n- Pattern matching and equivalence (`=:=`, `=/=`) comparisons on `0.0` will now\n raise a warning, as it will no longer be considered equivalent to `-0.0` in\n OTP 27.\n\n If a match on `0.0` specifically is desired (distinct from `-0.0`), the\n warning can be suppressed by writing `+0.0` instead.\n\n The arithmetic comparison operators are unaffected, including arithmetic\n equality (`==`).\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18696\n\n- The semantics of the `gen_{server,statem,event}` behaviour's synchronous start\n behaviour introduced in OTP-26.0 with OTP-18471, has been clarified in the\n documentation.\n\n Own Id: OTP-18705 Aux Id: GH-7524, OTP-18471, GH-6339, PR-6843\n\n- Added functionality to set a custom multiline prompt.\n\n Own Id: OTP-18736 Aux Id: PR-7564\n\n- A warning for (accidental use of) Triple-Quoted Strings has been implemented\n as per\n [EEP 64](https://github.com/erlang/eep/blob/master/eeps/eep-0064.md#backwards-incompatibility).\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18746 Aux Id: PR-7313, PR-7456\n\n- The keyboard shortcuts for the shell are now configurable.\n\n Own Id: OTP-18754 Aux Id: PR-7604 PR-7647","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 5.0.2 - STDLIB Release Notes","ref":"notes.html#stdlib-5-0-2"},{"type":"extras","doc":"- Fix bug where when you entered Alt+Enter in the terminal, the cursor would\n move to the last line, instead of moving to the next line.\n\n Own Id: OTP-18580 Aux Id: PR-7242\n\n- Fix eof handling when reading from stdin when erlang is started using\n `-noshell`.\n\n Own Id: OTP-18640 Aux Id: PR-7384 GH-7368 GH-7286 GH-6881\n\n- Fixed problem where output would disappear if it was received after a prompt\n was written in the shell.\n\n Own Id: OTP-18652 Aux Id: PR-7242\n\n- The following functions are now much faster when given a long list or binary:\n\n - erlang:list_to_integer/1\n - erlang:binary_to_integer/1\n - erlang:binary_to_integer/2\n - erlang:list_to_integer/2\n - string:to_integer/1\n\n Own Id: OTP-18659 Aux Id: PR-7426","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 5.0.1 - STDLIB Release Notes","ref":"notes.html#stdlib-5-0-1"},{"type":"extras","doc":"- The POSIX error `exdev` was sometimes incorrectly described as \"cross domain\n link\" in some error messages.\n\n Own Id: OTP-18578 Aux Id: GH-7213","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 5.0 - STDLIB Release Notes","ref":"notes.html#stdlib-5-0"},{"type":"extras","doc":"- All process calls in `dets` have been updated to use the receive queue\n optimizations.\n\n Own Id: OTP-18275 Aux Id: PR-6045\n\n- `proc_lib:start*/*` has become synchronous when the started process fails.\n This requires that a failing process use a new function\n `proc_lib:init_fail/2,3`, or exits, to indicate failure. All OTP behaviours\n have been fixed to do this.\n\n All these start functions now consume the `'EXIT'` message from a process link\n for all error returns. Previously it was only the `start_link/*` functions\n that did this, and only when the started function exited, not when it used\n `init_ack/1,2` or `init_fail/2,3` to create the return value.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18471 Aux Id: GH-6339, PR-6843\n\n- Fixed a bug where `file:read(standard_io, ...)` unexpectedly returned `eof` in\n binary mode.\n\n Own Id: OTP-18486 Aux Id: PR-6881\n\n- In the shell, `v(N)` would fail to retrieve the command if the command's\n return value was `undefined`.\n\n Own Id: OTP-18548 Aux Id: PR-6967","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The Erlang shell has been improved to support the following features:\n\n - Auto-complete variables, record names, record field names, map keys,\n function parameter types and filenames.\n - Open external editor in the shell (with C-o) to edit the current expression\n in an editor.\n - Support defining records (with types), functions and function typespecs, and\n custom types in the shell.\n - Do not save pager commands, and input to io:getline in history.\n\n Own Id: OTP-14835 Aux Id: PR-5924\n\n- Gen_server now caches external functions for use in handle_call, handle_cast\n and handle_info.\n\n Own Id: OTP-15597 Aux Id: PR-5831\n\n- The TTY/terminal subsystem has been rewritten by moving more code to Erlang\n from the old linked-in driver and implementing all the I/O primitives needed\n in a NIF instead.\n\n On Unix platforms the user should not notice a lot of difference, besides\n better handling of unicode characters and fixing of some long standing bugs.\n\n Windows users will notice that erl.exe has the same functionality as a normal\n Unix shell and that werl.exe has been removed and replaced with a symlink to\n erl.exe. This makes the Windows Erlang terminal experience identical to that\n of Unix.\n\n The re-write brings with it a number of bug fixes and feature additions:\n\n - The TTY is now reset when Erlang exits, fixing zsh to not break when\n terminating an Erlang session.\n - `standard_error` now uses the same unicode mode as `standard_io`.\n - Hitting backspace when searching the shell history with an empty search\n string no longer breaks the shell.\n - Tab expansion now works on remote nodes started using the JCL interface.\n - It is now possible to configure the shell slogan and the session slogans\n (that is the texts that appear when you start an Erlang shell). See the\n kernel documentation for more details.\n - Added shell:start_interactive for starting the interactive shell from a\n non-interactive Erlang session (for example an escript).\n - On Windows, when starting in detached mode the standard handler are now set\n to `nul` devices instead of being unset.\n - Standard I/O now always defaults to `unicode` mode if supported. Previously\n the default was `latin1` if the runtime system had been started with\n `-oldshell` or `-noshell` (for example in an `escript`). To send raw bytes\n over standard out, one now explicitly has to specify\n `io:setopts(standard_io, [{encoding, latin1}]).`\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17932 Aux Id: PR-6144 GH-3150 GH-3390 GH-4343 GH-4225\n\n- Added the `zip:zip_get_crc32/2` function to retrieve the CRC32 checksum from\n an opened ZIP archive.\n\n Own Id: OTP-18159 Aux Id: PR-6904\n\n- Added the options `post_process_args` and `detached` to the `peer:start`\n function.\n\n Own Id: OTP-18176 Aux Id: PR-6118\n\n- The `re:replace/3,4` functions now accept a fun as the replacement argument.\n\n Own Id: OTP-18221 Aux Id: PR-6197\n\n- The performance of the `base64` module has been significantly improved. For\n example, on an x86_64 system with the JIT both encode and decode are more than\n three times faster than in Erlang/OTP 25.\n\n Own Id: OTP-18228 Aux Id: GH-5639\n\n- Improved implementation of `timer:apply_interval/4` reducing load on the timer\n server, and introduction of the new function `timer:apply_repeatedly/4`.\n `timer:apply_repeatedly/4` is similar to `timer:apply_interval/4`, but\n `timer:apply_repeatedly/4` prevents parallel execution of triggered `apply`\n operations which `timer:apply_interval/4` does not.\n\n Own Id: OTP-18236 Aux Id: PR-6256\n\n- The `base64` module now supports encoding and decoding with an alternate URL\n safe alphabet, and an option for accepting or adding missing `=` padding\n characters.\n\n Own Id: OTP-18247 Aux Id: PR-6280, PR-6711\n\n- Add `shell:whereis/0` which can be used to locate the current shell process.\n\n Own Id: OTP-18272 Aux Id: PR-6279\n\n- The Erlang shell's auto-completion when typing `tab` has been changed to\n happen after the editing current line instead of before it.\n\n This behaviour can be configured using a the `shell_expand_location` STDLIB\n configuration parameter.\n\n Own Id: OTP-18278 Aux Id: PR-6260\n\n- New function `ets:lookup_element/4` with a `Default` argument returned if the\n key did not exist in the table. The old `ets:lookup_element/3` raises a\n `badarg` exception which can be both inconvenient and slower.\n\n Own Id: OTP-18279 Aux Id: PR-6234\n\n- Typing `Ctrl+L` in a shell now clears the screen and redraws the current line\n instead of only redrawing the current line. To only redraw the current line,\n you must now type `Alt+L`. This brings the behaviour of `Ctrl+L` closer to how\n bash and other shells work.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18285 Aux Id: PR-6262\n\n- `peer` nodes using `standard_io` connections now include standard error from\n the node in the io stream from the started node.\n\n Own Id: OTP-18287 Aux Id: PR-5955\n\n- A limitation in the binary syntax has been removed. It is now possible to\n match binary patterns in parallel. Example: `< > = < > = Bin`\n\n Own Id: OTP-18297 Aux Id: GH-6348\n\n- Improve type specification of `unicode:characters_to_list()`.\n\n Own Id: OTP-18301 Aux Id: PR-6350\n\n- In the `lists` module, the `zip` family of functions now takes options to\n allow handling lists of different lengths.\n\n Own Id: OTP-18318 Aux Id: PR-6347\n\n- It is documented that `$\\^X` is the ASCII code for Control X, where X is an\n uppercase or lowercase letter. However, this notation would work for any\n character X, even then it didn't make sense.\n\n In Erlang/OTP 26, it is now documented that the following characters are also\n allowed to follow the `\\^` characters: `@`, `[`, `\\`, `]`, `^`, `_`, and `?`.\n Attempt to use other characters will be rejected with a compiler error.\n\n The value for `$\\^?` is now 127 (instead of 31 as in earlier releases).\n\n Own Id: OTP-18337 Aux Id: GH-6477, PR-6503\n\n- The `binary:encode_hex/2` function has been added to allow the encoded\n hexadecimal digits to be in either lower or upper case.\n\n Own Id: OTP-18354 Aux Id: PR-6297\n\n- Variants of `timer:tc()` with user specified time unit have been introduced.\n\n Own Id: OTP-18355 Aux Id: PR-6507\n\n- New function `math:tau/0`. Returns `2*math:pi()`.\n\n Own Id: OTP-18361 Aux Id: PR-6536\n\n- The BIFs [`min/2`](`min/2`) and [`max/2`](`max/2`) are now allowed to be used\n in guards and match specs.\n\n Own Id: OTP-18367 Aux Id: GH-6544\n\n- Optimized `gen_server:multi_call()`.\n\n Own Id: OTP-18385 Aux Id: PR-6698\n\n- Map comprehensions as suggested in EEP 58 has now been implemented.\n\n Own Id: OTP-18413 Aux Id: EEP-58, PR-6727\n\n- Some map operations have been optimized by changing the internal sort order of\n atom keys. This changes the (undocumented) order of how atom keys in small\n maps are printed and returned by `maps:to_list/1` and `maps:next/1`. The new\n order is unpredictable and may change between different invocations of the\n Erlang VM.\n\n For applications where order is important, there is a new function\n `maps:iterator/2` for creating iterators that return the map elements in a\n deterministic order. There are also new modifiers `k` and `K` for the format\n string for [`io:format()`](`t:io:format/0`) to support printing map elements\n ordered.\n\n Own Id: OTP-18414 Aux Id: PR-6151\n\n- Make gen_server fail \"silently\" with a new return value for init/1.\n\n Own Id: OTP-18423 Aux Id: https://github.com/erlang/backlog/issues/142\n\n- Improved the selective receive optimization, which can now be enabled for\n references returned from other functions.\n\n This greatly improves the performance of `gen_server:send_request/3`,\n `gen_server:wait_response/2`, and similar functions.\n\n Own Id: OTP-18431 Aux Id: PR-6739\n\n- It is no longer necessary to enable a feature in the runtime system in order\n to load modules that are using it. It is sufficient to enable the feature in\n the compiler when compiling it.\n\n That means that to use feature `maybe_expr` in Erlang/OTP 26, it is sufficient\n to enable it during compilation.\n\n In Erlang/OTP 27, feature `maybe_expr` will be enabled by default, but it will\n be possible to disable it.\n\n Own Id: OTP-18445\n\n- Static supervisors are very idle processes after they have started so they\n will now be hibernated after start to improve resource management.\n\n Own Id: OTP-18474 Aux Id: PR-6895\n\n- Deprecates `dbg:stop_clear/0` because it is simply a function alias to\n `dbg:stop/0`\n\n Own Id: OTP-18478 Aux Id: GH-6903\n\n- Support has been added in `ms_transform` for the actions `caller_line/0`,\n `current_stacktrace/0`, and `current_stacktrace/1`.\n\n Own Id: OTP-18494 Aux Id: PR-6924\n\n- The family of enumeration functions in module `lists` has been extended with\n `enumerate/3` that allows a step value to be supplied.\n\n Own Id: OTP-18495 Aux Id: PR-6943\n\n- Update Unicode to version 15.0.0.\n\n Own Id: OTP-18500\n\n- The regular expression library powering the `re` module is likely to be\n changed in Erlang/OTP 27. See\n [Upcoming Potential Incompatibilities](`e:general_info:upcoming_incompatibilities.md#new_re_engine`).\n\n Own Id: OTP-18511 Aux Id: PR-7017\n\n- Improved the performance of `sets:subtract/2` when subtracting a small number\n of elements.\n\n Own Id: OTP-18515 Aux Id: GH-6990\n\n- The linter will no longer raise warnings for underspecified opaque types.\n\n Own Id: OTP-18518 Aux Id: GH-7015\n\n- Added the new built-in type `t:dynamic/0` introduced in EEP-61, improving\n support for gradual type checkers.\n\n Own Id: OTP-18522\n\n- The by `gen_statem` previously used call proxy process that was used for\n preventing late replies from reaching the client at timeout or connection loss\n has been removed. It is no longer needed since _process aliases_ take care of\n this, are used, and supported by all Erlang nodes that an OTP 26 Erlang node\n can communicate with.\n\n Own Id: OTP-18537 Aux Id: PR-7081\n\n- Added the `argparse` module for simplified argument handling in escripts and\n similar.\n\n Own Id: OTP-18558 Aux Id: PR-6852\n\n- Added support for multiple line expressions and navigation in the shell. Added\n new keybindings:\n\n - navigate up (ctrl+up)/(alt+up)\n - navigate down (ctrl+down)/(alt+down)\n - insert newline in middle of line (alt+enter)\n - navigate top (alt+<)/(alt+shift+up)\n - navigate bottom (alt+>)/(alt+shift+down)\n - clear current expression (alt+c)\n - cancel search (alt+c)\n - opening editor on mac (option+o)/(alt+o)\n\n Modifies the prompt for new lines to make it clearer that the prompt has\n entered multi-line mode. Supports terminal with small window size, recommend\n not go lower than 7 rows and 40 columns. Modifies the search prompt to support\n multi-line statements. Redraw the prompt after continuing from JCL menu.\n\n Own Id: OTP-18575 Aux Id: PR-7169","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 4.3.1.5 - STDLIB Release Notes","ref":"notes.html#stdlib-4-3-1-5"},{"type":"extras","doc":"* With this change, shutdown procedure handles a race condition between supervisor executing a shutdown and child process termination from other reason.\n\n Own Id: OTP-19256 Aux Id: PR-8780\n* With this change, uri_string:normalize assumes empty path (do not crash) when no path is provided in the URI map.\n\n Own Id: OTP-19266 Aux Id: ERIERL-1127, PR-8890","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 4.3.1.4 - STDLIB Release Notes","ref":"notes.html#stdlib-4-3-1-4"},{"type":"extras","doc":"* Attempting to use the `maybe` construct in a macro argument could crash the compiler.\n\n Own Id: OTP-19031 Aux Id: GH-8268","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 4.3.1.3 - STDLIB Release Notes","ref":"notes.html#stdlib-4-3-1-3"},{"type":"extras","doc":"- Garbage collect the shell process when reducing the amount of saved history\n and results.\n\n Own Id: OTP-18773 Aux Id: PR-7691","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 4.3.1.2 - STDLIB Release Notes","ref":"notes.html#stdlib-4-3-1-2"},{"type":"extras","doc":"- The following functions are now much faster when given a long list or binary:\n\n - erlang:list_to_integer/1\n - erlang:binary_to_integer/1\n - erlang:binary_to_integer/2\n - erlang:list_to_integer/2\n - string:to_integer/1\n\n Own Id: OTP-18659 Aux Id: PR-7426","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 4.3.1.1 - STDLIB Release Notes","ref":"notes.html#stdlib-4-3-1-1"},{"type":"extras","doc":"- Static supervisors are very idle processes after they have started so they\n will now be hibernated after start to improve resource management.\n\n Own Id: OTP-18556","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 4.3.1 - STDLIB Release Notes","ref":"notes.html#stdlib-4-3-1"},{"type":"extras","doc":"- The type specs in the `erl_parse` module has been updated to include the\n `maybe` construct and the `!` operator.\n\n Own Id: OTP-18506 Aux Id: GH-6956","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 4.3 - STDLIB Release Notes","ref":"notes.html#stdlib-4-3"},{"type":"extras","doc":"- Fixed a bug that would cause analysis to crash.\n\n Own Id: OTP-18372 Aux Id: GH-6580\n\n- Fixed a crash when formatting stack traces for error reports.\n\n Own Id: OTP-18375 Aux Id: GH-6591\n\n- Instead of crashing, the [`list_to_integer/1`](`list_to_integer/1`) and\n [`list_to_integer/2`](`list_to_integer/2`) BIFs now raise the `system_limit`\n exception for overlong lists that can't be converted to integers. Similarly,\n the `string:to_integer/1` BIF now returns `{error,system_limit}` for overlong\n lists.\n\n Own Id: OTP-18475 Aux Id: PR-6897","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Removal of non-necessary `undefined` types added to the state's `supervisor`\n record.\n\n Own Id: OTP-18393 Aux Id: PR-6666","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 4.2 - STDLIB Release Notes","ref":"notes.html#stdlib-4-2"},{"type":"extras","doc":"- `erl_tar` can now read gzip-compressed tar files that are padded. There is a\n new option `compressed_one` for `file:open/2` that will read a single member\n from a gzip file,\n\n Own Id: OTP-18289 Aux Id: PR-6343\n\n- A concurrent call to `ets:rename` could cause `ets:delete_all_objects` to fail\n halfway through with badarg.\n\n Own Id: OTP-18292 Aux Id: PR-6366\n\n- It is not allowed to call functions from guards. The compiler failed to reject\n a call in a guard when done by constructing a record with a default\n initialization expression that called a function.\n\n Own Id: OTP-18325 Aux Id: GH-6465, GH-6466\n\n- The compiler could crash when using a record with complex field initialization\n expression as a filter in a list comprehension.\n\n Own Id: OTP-18336 Aux Id: GH-6501, PR-6502\n\n- `unicode:characters_to_binary()` could build unnecessarily large call stack.\n\n Own Id: OTP-18351 Aux Id: ERIERL-885, PR-6529","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Improve error message for ets:new/2 name clash. Say \"name already exists\"\n instead of less specific \"invalid options\".\n\n Own Id: OTP-18283 Aux Id: PR-6338","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 4.1.1 - STDLIB Release Notes","ref":"notes.html#stdlib-4-1-1"},{"type":"extras","doc":"- `m:peer` nodes failed to halt when the process supervising the control\n connection crashed. When an alternative control connection was used, this\n supervision process also quite frequently crashed when the `peer` node was\n stopped by the node that started it which caused the `peer` node to linger\n without ever halting.\n\n Own Id: OTP-18249 Aux Id: PR-6301","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 4.1 - STDLIB Release Notes","ref":"notes.html#stdlib-4-1"},{"type":"extras","doc":"- Fixed inconsistency bugs in `m:global` due to `nodeup`/`nodedown` messages not\n being delivered before/after traffic over connections. Also fixed various\n other inconsistency bugs and deadlocks in both `m:global_group` and `global`.\n\n As building blocks for these fixes, a new BIF `erlang:nodes/2` has been\n introduced and `net_kernel:monitor_nodes/2` has been extended.\n\n The [`-hidden`](`e:erts:erl_cmd.md#hidden`) and\n [`-connect_all`](`e:erts:erl_cmd.md#connect_all`) command line arguments did\n not work if multiple instances were present on the command line which has been\n fixed. The new kernel parameter\n [`connect_all`](`e:kernel:kernel_app.md#connect_all`) has also been introduced\n in order to replace the `-connect_all` command line argument.\n\n Own Id: OTP-17934 Aux Id: PR-6007\n\n- Fix the `public_key:ssh*` functions to be listed under the correct release in\n the Removed Functionality User's Guide.\n\n Own Id: OTP-18139 Aux Id: PR-6060\n\n- The type spec for `format_status/1` in `gen_statem`, `gen_server` and\n `gen_event` has been corrected to state that the return value is of the same\n type as the argument (instead of the same value as the argument).\n\n Own Id: OTP-18142 Aux Id: PR-6078\n\n- If the `timer` server child spec was already present in `kernel_sup` but it\n was not started, the `timer` server would fail to start with an\n `{error, already_present}` error instead of restarting the server.\n\n Own Id: OTP-18146 Aux Id: PR-5983\n\n- When changing callback module in `gen_statem` the state_enter calls flag from\n the old module was used in for the first event in the new module, which could\n confuse the new module and cause malfunction. This bug has been corrected.\n\n With this change some `sys` debug message formats have been modified, which\n can be a problem for debug code relying on the format.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18239","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- There is a new configure option, `--enable-deterministic-build`, which will\n apply the `deterministic` compiler option when building Erlang/OTP. The\n `deterministic` option has been improved to eliminate more sources of\n non-determinism in several applications.\n\n Own Id: OTP-18165 Aux Id: PR-5965\n\n- The `rfc339_to_system_time/1,2` functions now allows the minutes part to be\n omitted from the time zone.\n\n Own Id: OTP-18166 Aux Id: PR-6108\n\n- The `receive` statement in `gen_event` has been optimized to not use selective\n receive (which was never needed, and could cause severe performance\n degradation under heavy load).\n\n Own Id: OTP-18194 Aux Id: PR-6199\n\n- Add new API function erl_features:configurable/0\n\n Own Id: OTP-18199 Aux Id: PR-5790","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 4.0.1 - STDLIB Release Notes","ref":"notes.html#stdlib-4-0-1"},{"type":"extras","doc":"- In the initial release of Erlang/OTP 25, the expression bound to the `_`\n pseudo-field in a record initialization would always be evaluated once, even\n if all other fields in the record were explicitly initialized. That would\n break the use case of binding the expression `error(...)` to `_` in order to\n get an exception if not all fields were initialized.\n\n The behavior of binding to `_` has been reverted to the pre-OTP 25 behavior,\n that is, to not evaluate the expression if all fields have been bound to\n explicit values.\n\n Own Id: OTP-18110 Aux Id: GH-6000","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 4.0 - STDLIB Release Notes","ref":"notes.html#stdlib-4-0"},{"type":"extras","doc":"- Improve the Erlang code linter's check of unused types.\n\n Own Id: OTP-17370 Aux Id: GH-4784\n\n- Fix race condition in `proc_lib:stop/3` where the process is not stopped when\n the timeout given is very short.\n\n Own Id: OTP-17480 Aux Id: GH-4853 PR-4872\n\n- Maps are now fully supported in by `ms_transform`.\n\n Own Id: OTP-17518 Aux Id: GH-4915\n\n- Fix gen_server:call with the first argument as self() to throw an error\n instead of failing with a timeout.\n\n The same fix has also been done for gen_statem:call/3, gen_event:sync_notify/2\n and any other functionality relying on the internal gen:call/3 function.\n\n A similar fix was also done when using io:format/2 and the current\n group_leader was set to the current process.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17544 Aux Id: PR-5008\n\n- erl_pp printed unary - and + operators with a space between the operator and\n the operand. This is fixed by not having any space in between.\n\n Own Id: OTP-17566 Aux Id: PR-5095, GH-5093\n\n- Adjust uri_string:normalize behavior for URIs with undefined port (URI string\n with a port colon but no port value or URI map with port => undefined).\n\n Remove redundant normalization from http_request module.\n\n Before this change, normalize would not remove port subcomponent in such cases\n and could for example return \"http://localhost:\" URI.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17627\n\n- Fix reduction counting bug in `re:run` that caused the function to yield too\n frequently when doing `global` matches.\n\n Own Id: OTP-17661 Aux Id: PR-5165\n\n- Fix the memory value returned from `ets:info(Tid,memory)` when the\n `read_concurrency` option is used.\n\n Before this fix the memory used by the scheduler specific lock cache lines was\n not counted towards the total. This caused the returned memory usage to be\n very incorrect on systems with many schedulers for tables with man locks.\n\n Own Id: OTP-17832 Aux Id: PR-5494\n\n- Avoid confusion by correcting the argument order in the gen_event crash log\n printout.\n\n Own Id: OTP-17878\n\n- Fixed `string:next_grapheme/1` to return an empty binary in the tail for\n binary input for the last grapheme cluster.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18009 Aux Id: PR-5785\n\n- Fixed type specifications of the `supervisor:sup_name/0` and\n [`supervisor:sup_ref/0`](`t:supervisor:sup_ref/0`) types.\n\n Own Id: OTP-18034 Aux Id: PR-4661, GH-4622\n\n- If a default record field initialization (`_ = Expr`) was used even though all\n records fields were explicitly initialized, `Expr` would not be evaluated.\n That would not be a problem, except when `Expr` would bind a variable\n subsequently used, in which case the compiler would crash.\n\n As an example, if record `#r{}` is defined to have only one field `a`, the\n following code would crash the compiler:\n\n `#r{a=[],_=V=42}, V`\n\n To fix that problem, the compiler will make sure that `Expr` is always\n evaluated at least once. The compiler will now rewrite the example to\n essentially:\n\n `V=42, #r{a=[]}, V`\n\n Own Id: OTP-18083","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Users can now configure ETS tables with the `{write_concurrency, auto}`\n option. This option forces tables to automatically change the number of locks\n that are used at run-time depending on how much concurrency is detected. The\n `{decentralized_counters, true}` option is enabled by default when\n `{write_concurrency, auto}` is active.\n\n Benchmark results comparing this option with the other ETS optimization\n options are available here:\n\n https://erlang.org/bench/ets_bench_result_lock_config.html\n\n Own Id: OTP-15991 Aux Id: PR-5208\n\n- The `format_status/2` callback for `gen_server`, `gen_statem` and `gen_event`\n has been deprecated in favor of the new `format_status/1` callback.\n\n The new callback adds the possibility to limit and change many more things\n than the just the state, such as the last received message, the reason for\n terminating and more events specific to each type of behavior. See the\n respective modules documentation for more details.\n\n Own Id: OTP-17351 Aux Id: GH-4673 PR-4952\n\n- The `timer` module has been modernized and made more efficient, which makes\n the timer server less susceptible to being overloaded. The `timer:sleep/1`\n function now accepts an arbitrarily large integer.\n\n Own Id: OTP-17481 Aux Id: PR-4811\n\n- Add `lists:enumerate/[1,2]`.\n\n Own Id: OTP-17523 Aux Id: PR-4928\n\n- The configuration files [`.erlang`](`e:erts:erl_cmd.md`),\n [`.erlang.cookie`](`e:system:distributed.md`) and\n [`.erlang.crypt`](`m:beam_lib#module-erlang-crypt`) can now be located in the XDG\n Config Home directory.\n\n See the documentation for each file and `filename:basedir/2` for more details.\n\n Own Id: OTP-17554 Aux Id: GH-5016 PR-5408 OTP-17821\n\n- Support `native` time unit in `calendar` functions `system_time_to_rfc3339/2`\n and `rfc3339_to_system_time`.\n\n Own Id: OTP-17592 Aux Id: ERIERL-663, PR-5243\n\n- The tagged tuple tests and fun-calls have been optimized and are now a little\n bit cheaper than previously.\n\n These optimizations become possible after making sure that all boxed terms\n have at least one word allocated after the arity word. This has been\n accomplished by letting all empty tuples refer to the same empty tuple literal\n which also reduces memory usage for empty tuples.\n\n Own Id: OTP-17608\n\n- The signal queue benchmark in parallel_messages_SUITE and the ETS benchmark in\n ets_SUITE have benchmark result visualization HTML pages with \"fill-screen\"\n buttons to make the graphs bigger. This button did not work as intended\n before. When pressing the button for a graph, the last graph got replaced with\n a bigger version and not the one over the button. This is now fixed.\n\n Own Id: OTP-17630\n\n- The new module `peer` supersedes the `slave` module. The `slave` module is now\n deprecated and will be removed in OTP 27.\n\n `peer` contains an extended and more robust API for starting erlang nodes.\n\n Own Id: OTP-17720 Aux Id: PR-5162\n\n- This change introduces quote and unquote functions in uri_string module - a\n replacement for deprecated encode and decode functions from http_uri.\n\n Own Id: OTP-17778 Aux Id: GH-5368\n\n- In order to make it easier for the user to manage multiple outstanding\n asynchronous `call` requests, new functionality utilizing request identifier\n collections have been introduced in\n [`erpc`](`t:erpc:request_id_collection/0`),\n [`gen_server`](`t:gen_server:request_id_collection/0`),\n [`gen_statem`](`t:gen_statem:request_id_collection/0`), and\n [`gen_event`](`t:gen_event:request_id_collection/0`).\n\n Own Id: OTP-17784 Aux Id: PR-5792\n\n- Update to the Unicode 14.0 specification.\n\n Own Id: OTP-17869 Aux Id: PR-5595\n\n- The following ets types have been renamed to a clearer name: `tab/0` to\n `table/0` and `comp_match_spec/0` to `compiled_match_spec/0`.\n\n The types `table_access/0` and `table_type/0` have been exported.\n\n Own Id: OTP-17901 Aux Id: GH-4968 PR-5649\n\n- Add support for locating `.asn1` files to the default search rules of\n `filelib:find_file/1` and `filelib:find_source/1`.\n\n Own Id: OTP-17908 Aux Id: GH-5655 PR-5669\n\n- Type specifications have been added to the `gen_server`, and the documentation\n has been updated to utilize this.\n\n This surfaced a few type violations that has been corrected in `global`,\n `logger_olp` and `rpc`.\n\n Own Id: OTP-17915 Aux Id: PR-5751, GH-2375, GH-2690\n\n- The non-local function handler for the `erl_eval` can now be called with\n either two or three arguments. When called with three arguments, the first\n argument is the annotation for the node in the abstract format.\n\n All errors during evaluation will now be passed through `erlang:raise/3`. If\n the restricted shell is active and it does not let `erlang:raise/3` through,\n evaluation errors will be printed in less clear way. See the documentation for\n restricted shell in `shell`.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17925 Aux Id: PR-5631\n\n- Added `filelib:ensure_path/1` that ensures that all directories for the given\n path exists (unlike `filelib:ensure_dir/1`, which will not create the last\n segment of the path).\n\n Own Id: OTP-17953 Aux Id: PR-5621\n\n- The functions `groups_from_list/2` and `groups_from_list/3` have been added to\n the `maps` module.\n\n Own Id: OTP-17969 Aux Id: PR-5588\n\n- `gen_server` has been refactored to throw more readable exceptions when a\n callback returns bad values in the `Timeout` field\n (`timeout() | 'hibernate' | {'continue,_}`), and also to verify that argument\n in the `gen_server:enter_loop/3,4,5` API function.\n\n Own Id: OTP-17974 Aux Id: GH-5683\n\n- The functions `uniq/1` and `uniq/2` for removing duplicates have been added to\n the `lists` module.\n\n Own Id: OTP-17977 Aux Id: GH-5606, PR-5766\n\n- Added support for configurable features as described in EEP-60. Features can\n be enabled/disabled during compilation with options\n (`-enable-feature Feature`, `-disable-feature Feature` and\n `+{feature, Feature, enable|disable}`) to `erlc` as well as with directives\n (`-feature(Feature, enable|disable).`) in the file. Similar options can be\n used to `erl` for enabling/disabling features allowed at runtime. The new\n `maybe` expression (EEP-49) is fully supported as the feature `maybe_expr`.\n The features support is documented in the reference manual.\n\n Own Id: OTP-17988\n\n- The function `filename:safe_relative_path/1`, which has been deprecated since\n OTP 25, has been removed. Use `filelib:safe_relative_path/2` instead.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17991\n\n- A new PRNG have been added to the `rand` module: `mwc59` which has been\n developed in collaboration with Sebastiano Vigna. It is intended for\n applications that need really fast pseudo-random numbers, and it comes with\n two output value scramblers, one fast and one thorough.\n\n Two internal functions for the `exsp` generator have also been exported so\n they can be used outside the `rand` plug-in framework to shave off some\n overhead.\n\n The internal `splitmix64` generator has also been exported which can be useful\n for seeding other kinds of PRNG:s than its own.\n\n Own Id: OTP-18011","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.17.2.4 - STDLIB Release Notes","ref":"notes.html#stdlib-3-17-2-4"},{"type":"extras","doc":"- The following functions are now much faster when given a long list or binary:\n\n - erlang:list_to_integer/1\n - erlang:binary_to_integer/1\n - erlang:binary_to_integer/2\n - erlang:list_to_integer/2\n - string:to_integer/1\n\n Own Id: OTP-18659 Aux Id: PR-7426","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.17.2.3 - STDLIB Release Notes","ref":"notes.html#stdlib-3-17-2-3"},{"type":"extras","doc":"- Static supervisors are very idle processes after they have started so they\n will now be hibernated after start to improve resource management.\n\n Own Id: OTP-18556","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.17.2.2 - STDLIB Release Notes","ref":"notes.html#stdlib-3-17-2-2"},{"type":"extras","doc":"- It is not allowed to call functions from guards. The compiler failed to reject\n a call in a guard when done by constructing a record with a default\n initialization expression that called a function.\n\n Own Id: OTP-18325 Aux Id: GH-6465, GH-6466","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.17.2.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-17-2-1"},{"type":"extras","doc":"- When changing callback module in `gen_statem` the state_enter calls flag from\n the old module was used in for the first event in the new module, which could\n confuse the new module and cause malfunction. This bug has been corrected.\n\n With this change some `sys` debug message formats have been modified, which\n can be a problem for debug code relying on the format.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-18239","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.17.2 - STDLIB Release Notes","ref":"notes.html#stdlib-3-17-2"},{"type":"extras","doc":"- The type specifications for `shell_docs:get_doc/3`,\n `shell_docs:get_callback_doc/3`, and `shell_docs:get_type_doc/3` incorrectly\n stated that the returned `Metadata` was an empty map.\n\n Own Id: OTP-18081","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.17.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-17-1"},{"type":"extras","doc":"- The compilation time is no longer recorded in BEAM files. There remained\n several undocumented functions that attempted to retrieve compilation times.\n Those have now been removed.\n\n Own Id: OTP-17962","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.17 - STDLIB Release Notes","ref":"notes.html#stdlib-3-17"},{"type":"extras","doc":"- Fix rendering of nbsp on terminals that do not support unicode.\n\n Own Id: OTP-17662 Aux Id: PR-5206\n\n- Improved the `m:erl_error` printout for when `m:re` fails to compile a regular\n expression to also print hints about why the compilation failed.\n\n Own Id: OTP-17750 Aux Id: PR-5366\n\n- Fixed spec for `supervisor_bridge:start_link()`.\n\n Own Id: OTP-17766 Aux Id: PR-5362\n\n- Added missing shutdown clauses in `supervisor` which could cause erroneous\n error reports.\n\n Own Id: OTP-17767 Aux Id: PR-5344","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add the `no_auto_import_types` to erl_lint to allow a module to define types\n of the same name as a predefined type.\n\n Own Id: OTP-17744 Aux Id: PR-5292","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.16.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-16-1"},{"type":"extras","doc":"- Fixed a bug that could cause a child to become orphaned when a supervisor died\n between unlinking and sending the shutdown signal to this child.\n\n There was also a possibility for erratic supervisor reports caused by a race\n between a supervisor shutting down a child and that child exiting by itself at\n the same time.\n\n Own Id: OTP-17649 Aux Id: GH-5193, PR-5201","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.16 - STDLIB Release Notes","ref":"notes.html#stdlib-3-16"},{"type":"extras","doc":"- Fix `io:format` with `~p` to no longer interpret floats as printable\n characters.\n\n Own Id: OTP-17424 Aux Id: GH-4801 PR-4803\n\n- Fix specs for base64 encode/decode functions to also include 0.\n\n Own Id: OTP-17429 Aux Id: GH-4761\n\n- The failing call `io:format(\"~p\\n\")` would result in a warning for line number\n 0 instead of the correct line and column numbers. This has been corrected, and\n all warnings for failing calls to [`io:format()`](`t:io:format/0`) has been\n rephrased to make it clearer exactly what the problem is.\n\n Own Id: OTP-17430\n\n- When the options `warn_missing_spec` and `export_all` were given, there would\n only be warnings for missing specs for functions that had been explicitly\n exported using an `-export` attribute.\n\n Own Id: OTP-17434 Aux Id: GH-4772\n\n- Calling `c:ls/1` with an atom whose contents is the the name of a file (as\n opposed to a directory) would crash.\n\n Own Id: OTP-17463 Aux Id: GH-4916\n\n- The `MODULE` and `MODULE_STRING` macros would always appear to be defined\n (when tested by `-ifdef`), even though no `-module()` declaration had been\n seen yet. Changed so that `-ifdef ?MODULE.` will not consider ?MODULE defined\n if `-module()` has not been previously seen.\n\n Own Id: OTP-17505 Aux Id: GH-4995\n\n- Fix bug with rendering of missing types and callbacks in shell_docs.\n\n Own Id: OTP-17573 Aux Id: ERL-1264 GH-4270\n\n- When the `deterministic` option was given to the compiler, the `?FILE` macro\n would be expanded to full path of the source file before the first `include`\n directive and to base part of the filename after `include` directive.\n\n Own Id: OTP-17581 Aux Id: PR-5141\n\n- Fixed broken `win32reg:delete_key` and fixed `win32reg:value` for `default`\n value.\n\n Own Id: OTP-17622 Aux Id: PR-5038\n\n- Fixed error information for the call `maps:get(some_key, #{})`.\n\n Own Id: OTP-17634 Aux Id: GH-5196","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Most output functions in the `io` module now print extra error information\n when provided with invalid arguments. The functions are: `io:format`,\n `io:fwrite`, `io:put_chars`, `io:nl` and `io:write`.\n\n Own Id: OTP-17317 Aux Id: PR-4757\n\n- EEP-54 (Provide more information about errors) now includes two new return\n values for the `format_error` callback, `general` and `reason`.\n\n Multi-line error descriptions returned from a `format_error` callback are now\n correctly indented.\n\n The documentation for `m:erl_error`, [`error/3`](`erlang:error/3`) and\n [Errors and Error Handling](`e:system:errors.md`) in the Erlang Reference\n Manual have been extended.\n\n Own Id: OTP-17454 Aux Id: PR-4764\n\n- In the documentation for the `lists` module, it has been clarified that\n predicate funs must return a boolean.\n\n Own Id: OTP-17503 Aux Id: GH-4985\n\n- The documentation for `c:c/1`, `c:c/2`, and `c:c/3` has been clarified.\n\n Own Id: OTP-17571 Aux Id: GH-5103","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.15.2 - STDLIB Release Notes","ref":"notes.html#stdlib-3-15-2"},{"type":"extras","doc":"- Fix a bug that could cause a crash when formatting tuples using the control\n sequences `p` or `P` and limiting the output with the option `chars_limit`.\n\n Own Id: OTP-17525 Aux Id: GH-5053","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.15.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-15-1"},{"type":"extras","doc":"- Fix a bug that could cause a loop when formatting terms using the control\n sequences p or P and limiting the output with the option `chars_limit`.\n\n Own Id: OTP-17459 Aux Id: GH-4824, GH-4842","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.15 - STDLIB Release Notes","ref":"notes.html#stdlib-3-15"},{"type":"extras","doc":"- Time-outs in `gen_statem` with relative time `0` did not behave quite\n according to the intended model. This has now been corrected.\n\n The correction introduces a small potential incompatibility e.g when combining\n a state time-out with inserted events, and the inserted event does a state\n change in the state with the time-out. Before this correction the state\n time-out could be delivered even after the second state change, but now it is\n guaranteed that a state time-out is only delivered in the state it was started\n for, even in this corner case.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15107 Aux Id: ERL-1381, PR-2813\n\n- Fix bugs in `erl_eval` concerning bitstring comprehensions.\n\n Own Id: OTP-16865\n\n- File names that start with a dot (such as \"`.gitignore`\" are now treated as\n file names and not extensions by `filename:extension/1` and\n `filename:rootname/1`.\n\n Own Id: OTP-16905\n\n- Fixed a bug where `beam_lib:chunks/3` with the `allow_missing_chunks` option\n would crash if a named chunk was missing.\n\n Own Id: OTP-16950 Aux Id: ERL-1378\n\n- A floating point zero (0.0) can be both positive (+0.0) and negative (-0.0).\n Multiple bugs in the compiler, runtime system, and STDLIB have been fixed to\n ensure that the minus sign on 0.0 is not lost.\n\n Own Id: OTP-17077 Aux Id: ERL-1431, PR-2903, PR-2905, PR-2906\n\n- Eliminated a Dialyzer crashed when the `-MMD` option is used to generate a\n dependency file and a BEAM file a the same time.\n\n Own Id: OTP-17118 Aux Id: PR-2825\n\n- Fixed bug in `m:shell_docs` and `erl_docgen` that interpreted `em` tags as\n `strong`.\n\n Own Id: OTP-17122\n\n- On Solaris, the `math:acos/1` and `math:asin/1` functions would not fail for\n arguments outside the valid domain.\n\n Own Id: OTP-17133\n\n- Silence `unused_record` warnings when using `ms_transform`. The parse\n transform `ms_transform` replaces records with tuples, which can cause the\n Erlang code linter to emit warnings about unused records.\n\n Own Id: OTP-17186\n\n- Documented a deficiency in the `re` module regarding the `[:ascii:]` character\n class matching Latin-1 characters.\n\n Own Id: OTP-17222 Aux Id: GH-4544\n\n- Fixed `spec` of start functions in generic behaviors.\n\n Own Id: OTP-17342 Aux Id: GH-4725 PR-4726\n\n- Supervisors rejected child specs with a shutdown value of 0.\n\n Own Id: OTP-17364 Aux Id: PR-4747","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- In the `rand` module it is now possible to seed the default algorithm using an\n algorithm alias: `default`.\n\n Generating pseudo random binaries has been implemented with `rand:bytes/1` and\n `rand:bytes_s/2`.\n\n Own Id: OTP-14646 Aux Id: PR-2920\n\n- New functions have been added to the `proplists` module: `to_map/1,2` and\n `from_map/1`.\n\n Own Id: OTP-14647 Aux Id: PR-2910\n\n- New functions have been added to the `queue` module: `all/2`, `any/2`,\n `delete/2`, `delete_r/2`, `delete_with/2`, and `delete_with_r/2`.\n\n Own Id: OTP-14650 Aux Id: PR-2850\n\n- New function have been added to the `queue` module: `fold/2` and\n `filtermap/2`.\n\n Own Id: OTP-14793 Aux Id: PR-2791\n\n- Support for handling abstract code created before OTP R15 has been dropped.\n\n Own Id: OTP-16678 Aux Id: PR-2627\n\n- Extended error information for failing BIF calls as proposed in\n [EEP 54](https://github.com/erlang/eep/blob/master/eeps/eep-0054.md) has been\n implemented.\n\n When a BIF call from the Erlang shell fails, more information about which\n argument or arguments that were in error will be printed. The same extended\n error information will by `proc_lib`, `common_test`, and `qlc` when BIF calls\n fail.\n\n For applications that wish to provide the same extended error information,\n there are new functions `erl_error:format_exception/3` and\n `erl_error:format_exception/4`.\n\n There is a new [`error/3`](`error/3`) BIF that allows applications or\n libraries to provide extended error information in the same way for their own\n exceptions.\n\n Own Id: OTP-16686\n\n- The [_process alias_](`e:system:ref_man_processes.md#process-aliases`) feature\n as outlined by\n [EEP 53](https://github.com/erlang/eep/blob/master/eeps/eep-0053.md) has been\n introduced. It is introduced in order to provide a lightweight mechanism that\n can prevent late replies after timeout or connection loss. For more\n information, see EEP 53 and the documentation of the new\n [`alias/1`](`erlang:alias/1`) BIF and the new options to the\n [`monitor/3`](`erlang:monitor/3`) BIF.\n\n The `call` operation in the framework used by `gen_server`, `gen_statem`, and\n `gen_event` has been updated to utilize alias in order to prevent late\n responses. The `gen_statem` behavior still use a proxy process in the\n distributed case, since it has always prevented late replies and aliases wont\n work against pre OTP 24 nodes. The proxy process can be removed in OTP 26.\n\n The alias feature also made it possible to introduce new functions similar to\n the [`erpc:receive_response()`](`erpc:receive_response/2`) function in the gen\n behaviors, so the new functions\n [`gen_server:receive_response()`](`gen_server:receive_response/2`),\n [`gen_statem:receive_response()`](`gen_statem:receive_response/2`),\n [`gen_event:receive_response()`](`gen_event:receive_response/2`) have also\n been introduced.\n\n Own Id: OTP-16718 Aux Id: PR-2735\n\n- Improved documentation about exit signals emitted when a `gen_server`\n terminates.\n\n Own Id: OTP-16910 Aux Id: PR-2771\n\n- New functions have been added to the `maps` module: `merge_with/3`,\n `intersect/2`, `intersect_with/3`, `filtermap/2`, `from_keys/2`, and\n `maps:foreach/2`.\n\n `maps:merge_with/3` is the same as `merge/2` but takes an extra fun that is\n used to combine items with the same key.\n\n `maps:intersect/2` computes the intersection of two maps.\n\n `maps:intersect_with/3` is the same as `intersect/2` but takes an extra fun\n that is used to combine intersecting items.\n\n `maps:filtermap/2` allows filtering and mapping of a map in a single pass.\n\n `maps:from_keys/2` constructs a map from a list of keys and a single value and\n can be used to to optimize sets operations such as from_list/1, filter/2,\n intersection/2, and subtract/2.\n\n `maps:foreach/2` allows iteration over a map without returning any value.\n\n Own Id: OTP-16936 Aux Id: ERL-1367\n\n- The experimental HiPE application has been removed, together with all related\n functionality in other applications.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-16963\n\n- The `filename:src/1` function which was deprecated in OTP 20 has been removed.\n Use `filelib:find_source/1,3` instead.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-16971\n\n- The pretty printer for floating point number have been changed to make it\n easier to see if the integer part of the number has been rounded. After the\n change the digit that may have been rounded always appears last or just before\n the exponent character (e or E). This is accomplished by always printing the\n number using scientific notation if it is so large that the integer part could\n be rounded.\n\n Own Id: OTP-16980 Aux Id: ERL-1308\n\n- Accept references up to a size of 160-bits from remote nodes. This is the\n first step in an upgrade path toward using references up to 160-bits in a\n future OTP release.\n\n Own Id: OTP-17005 Aux Id: OTP-16718\n\n- Add option `location` to `erl_parse:abstract/2`.\n\n Own Id: OTP-17024\n\n- All long running functions in the maps API are now yielding. In previous\n releases the functions `maps:from_list/1`, `maps:keys/1` and `maps:values/1`\n did not yield. This could cause unfair scheduling of processes.\n\n Own Id: OTP-17057\n\n- The `sets` module now has an optional map-based implementation, as described\n in `EEP 50`.\n\n To use this implementation, pass the `{version,2}` option to `sets:new/1` or\n `sets:from_list/2`.\n\n Own Id: OTP-17059 Aux Id: PR-2864\n\n- Added `shell_docs:supported_tags/0`. This function can be used to retrieve the\n tags currently supported by `shell_docs`.\n\n Own Id: OTP-17120\n\n- The `application/erlang+html` documentation storage format used by\n `m:shell_docs` has been updated to include the tags `b`, `strong`, `h4`, `h5`\n and `h6`.\n\n Own Id: OTP-17121\n\n- Do not pretty-print `catch` expressions with unnecessary parentheses. The\n re-write of the Erlang parser grammar in PR-2584 implies that parentheses\n around `catch` expressions are in many cases no longer required.\n\n Own Id: OTP-17169 Aux Id: PR-2584\n\n- Improved explanation of `{continue,Continue}` in `Module:init/1` of the\n `gen_server` documentation.\n\n Own Id: OTP-17171 Aux Id: PR-3011\n\n- The `erl_eval` module now accepts a map for keeping track of bindings. Using\n an `orddict` for bindings will still work.\n\n Own Id: OTP-17175\n\n- Documented `epp:scan_erl_form/1` and added `epp:scan_file/2`.\n\n Own Id: OTP-17199 Aux Id: PR-2658\n\n- The standard floating point printing algorithm used by the `io` and `io_lib`\n modules has been changed from the algorithm described in \\[1] to the Ryu\n algorithm \\[2]. This gives a significant speed improvement for the printing of\n most floating point numbers and a small memory consumption improvement.\n\n \\[1]: Robert G. Burger and R. Kent Dybvig. 1996. Printing floating-point\n numbers quickly and accurately. In Proceedings of the ACM SIGPLAN 1996\n conference on Programming language design and implementation (PLDI '96).\n Association for Computing Machinery, New York, NY, USA, 108–116.\n DOI:https://doi.org/10.1145/231379.231397\n\n \\[2]: Ulf Adams. 2018. Ryū: fast float-to-string conversion. In Proceedings of\n the 39th ACM SIGPLAN Conference on Programming Language Design and\n Implementation (PLDI 2018). Association for Computing Machinery, New York, NY,\n USA, 270–282. DOI:https://doi.org/10.1145/3192366.3192369\n\n Thanks to Thomas Depierre\n\n Own Id: OTP-17210\n\n- Add hex encoding and decoding functions in the binary module.\n\n Own Id: OTP-17236 Aux Id: PR-3014\n\n- The undocumented and partially broken `ets:filter/3` function has been\n removed.\n\n Own Id: OTP-17263\n\n- Add support in `m:shell_docs` to display any `\"text\"` documentation format.\n This means that `h(Module)` in the shell now can display the `\"text/markdown\"`\n of Elixir documentation.\n\n Own Id: OTP-17267\n\n- The internal hashing of keys within ETS tables of types `set`, `bag`,\n `duplicate_bag` has been salted to diverge from `erlang:phash2`. This to avoid\n bad hashing if `phash2` is used to distribute the keys over separate\n tables/nodes.\n\n Own Id: OTP-17276 Aux Id: PR-2979\n\n- Updated to the Unicode 13.0 specification.\n\n Own Id: OTP-17327 Aux Id: PR-4707\n\n- Add compiler option `{nowarn_unused_record, RecordNames}`. Document compiler\n option `nowarn_unused_type`.\n\n Own Id: OTP-17330\n\n- Implementation of\n [EEP 56](https://github.com/erlang/eep/blob/master/eeps/eep-0056.md) in\n supervisor. It adds the concept of `significant` children as well as the\n `auto_shutdown` supervisor flag.\n\n See the [supervisor manual page](`m:supervisor`) for more information.\n\n Own Id: OTP-17334 Aux Id: PR-4638, EEP-56\n\n- Fixed warnings in code matching on underscore prefixed variables.\n\n Own Id: OTP-17385 Aux Id: OTP-17123","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.14.2.3 - STDLIB Release Notes","ref":"notes.html#stdlib-3-14-2-3"},{"type":"extras","doc":"- It is not allowed to call functions from guards. The compiler failed to reject\n a call in a guard when done by constructing a record with a default\n initialization expression that called a function.\n\n Own Id: OTP-18325 Aux Id: GH-6465, GH-6466","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.14.2.2 - STDLIB Release Notes","ref":"notes.html#stdlib-3-14-2-2"},{"type":"extras","doc":"- Fix a bug that could cause a crash when formatting tuples using the control\n sequences `p` or `P` and limiting the output with the option `chars_limit`.\n\n Own Id: OTP-17525 Aux Id: GH-5053","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.14.2.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-14-2-1"},{"type":"extras","doc":"- Fix a bug that could cause a loop when formatting terms using the control\n sequences p or P and limiting the output with the option `chars_limit`.\n\n Own Id: OTP-17459 Aux Id: GH-4824, GH-4842","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.14.2 - STDLIB Release Notes","ref":"notes.html#stdlib-3-14-2"},{"type":"extras","doc":"- Dictionaries that have become zipped by the zip module did not get executable\n permission (for the file owner) which makes the files inside the dictionary\n inaccessible. This is fixed by giving dictionaries inside a zip archive XRW\n permission.\n\n Own Id: OTP-17295 Aux Id: GH-4687","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.14.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-14-1"},{"type":"extras","doc":"- Handle maps in `erl_parse:tokens()`.\n\n Own Id: OTP-16978\n\n- The erlang shell function `rr` has been fixed to be able to read records from\n files within a code archive.\n\n Own Id: OTP-17182 Aux Id: PR-3002\n\n- If `beam_lib` is asked to return abstract code for a BEAM file produced by\n Elixir and Elixir is not installed on the computer, `beam_lib` will no longer\n crash, but will return an error tuple. The `cover:compile_beam()` and\n `cover:compile_beam_directory()` functions have been updated to also return an\n error tuple in that situation.\n\n Own Id: OTP-17194 Aux Id: GH-4353\n\n- Correct example module `erl_id_trans` regarding the `{char, C}` type.\n\n Own Id: OTP-17273","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.14 - STDLIB Release Notes","ref":"notes.html#stdlib-3-14"},{"type":"extras","doc":"- This change fixes the handling of deep lists in the path component when using\n uri_string:recompose/1.\n\n Own Id: OTP-16941\n\n- Fix `m:shell_docs` to clear shell decorations (bold/underline) when paginating\n output.\n\n Fix various small renderings issues when integrating `m:shell_docs` with edoc.\n\n Own Id: OTP-17047","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Improved the API and documentation of the uri_string module.\n\n Added a new chapter to the Users Guide about Uniform Resource Identifiers and\n their handling with the new API.\n\n Added two new API functions: uri_string:allowed_characters/0 and\n uri_string:percent_decode/1.\n\n This change has been marked as potentially incompatible as\n uri*string:normalize/2 used to decode percent-encoded character triplets that\n corresponded to characters not in the reserved set. After this change,\n uri_string:normalize/2 will only decode those percent-encoded triplets that\n correspond to characters in the unreserved set (ALPHA / DIGIT / \"-\" / \".\" /\n \"*\" / \"~\").\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-16460\n\n- The `shell_docs` module has been expanded with the possibility to configure\n unicode, ansi and column size for the rendered text.\n\n Own Id: OTP-16990","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.13.2 - STDLIB Release Notes","ref":"notes.html#stdlib-3-13-2"},{"type":"extras","doc":"- The functions `digraph:in_edges/2` and `digraph:out_edges/2` would return\n false edges if called for a vertex that had a '\\_' atom in its name term.\n\n Own Id: OTP-16655\n\n- `filelib:wildcard(\"not-a-directory/..\")` should return an empty list. On\n Windows it returned `\"not-a-directory/..\"`.\n\n Own Id: OTP-16700\n\n- Fix the typespec of shell_docs:render to use the correct type for an MFA.\n\n Own Id: OTP-16739\n\n- Fix uri_string:recompose/1 when host is present but input path is not\n absolute.\n\n This change prevents the recompose operation to change the top level domain of\n the host when the path does not start with a slash.\n\n Own Id: OTP-16751 Aux Id: ERL-1283\n\n- The `epp` module would return a badly formed error term when an '`if`'\n preprocessor directive referenced an undefined symbol. `epp:format_error/1`\n would crash when called with the bad error term.\n\n Own Id: OTP-16816 Aux Id: ERL-1310\n\n- `lists:sublist(List, Start, Len)` failed with an exception if\n `Start > length(List) + 1` even though it is explicitly documented that \"It is\n not an error for `Start+Len` to exceed the length of the list\".\n\n Own Id: OTP-16830 Aux Id: ERL-1334, PR-2718","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.13.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-13-1"},{"type":"extras","doc":"- When a temporary child of a `simple_one_for_one supervisor` died, the internal\n state of the supervisor would be corrupted in a way that would cause the\n supervisor to retain the start arguments for subsequent children started by\n the supervisor, causing unnecessary growth of the supervisor's heap. There\n state corruption could potentially cause other problems as well.\n\n Own Id: OTP-16804","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.13 - STDLIB Release Notes","ref":"notes.html#stdlib-3-13"},{"type":"extras","doc":"- Compiling a match specification with excessive nesting caused the runtime\n system to crash due to scheduler stack exhaustion. Instead of crashing the\n runtime system, effected functions will now raise a `system_limit` error\n exception in this situation.\n\n Own Id: OTP-16431 Aux Id: ERL-592\n\n- Initialization of record fields using `_` is no longer allowed if the number\n of affected fields is zero.\n\n Own Id: OTP-16516\n\n- Fix bugs in `eval_bits`.\n\n Own Id: OTP-16545","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Improved the printout of single line logger events for most of the OTP\n behaviours in STDLIB and Kernel. This includes `proc_lib`, `gen_server`,\n `gen_event`, `gen_statem`, `gen_fsm`, `supervisor`, `supervisor_bridge` and\n `application`.\n\n Improved the [`chars_limit`](`m:logger_formatter#chars_limit`) and\n [`depth`](`m:logger_formatter#depth`) handling in `proc_lib` and when\n formatting of exceptions.\n\n Own Id: OTP-15299\n\n- Remove usage and documentation of old requests of the I/O-protocol.\n\n Own Id: OTP-15695\n\n- Improved ETS scalability of concurrent calls that change the size of a table,\n like `ets:insert/2` and `ets:delete/2`.\n\n This performance feature was implemented for `ordered_set` in OTP 22.0 and\n does now apply for all ETS table types.\n\n The improved scalability may come at the cost of longer latency of\n `ets:info(T,size)` and `ets:info(T,memory)`. A new table option\n `decentralized_counters` has therefore been added. It is default `true` for\n `ordered_set` with `write_concurrency` enabled and default `false` for all\n other table types.\n\n Own Id: OTP-15744 Aux Id: OTP-15623, PR-2229\n\n- Handle Unicode filenames in the `zip` module.\n\n Own Id: OTP-16005 Aux Id: ERL-1003, ERL-1150\n\n- Unicode support was updated to the Unicode 12.1 standard.\n\n Own Id: OTP-16073 Aux Id: PR-2339\n\n- All of the modules [`proc_lib`](`proc_lib:start_monitor/3`),\n [`gen_server`](`gen_server:start_monitor/3`),\n [`gen_statem`](`gen_statem:start_monitor/3`), and\n [`gen_event`](`gen_event:start_monitor/0`) have been extended with a\n `start_monitor()` function. For more information, see the documentation of\n `start_monitor()` for these modules.\n\n Own Id: OTP-16120 Aux Id: ERIERL-402, PR-2427\n\n- Updates for new `erlang:term_to_iovec()` BIF.\n\n Own Id: OTP-16128 Aux Id: OTP-15618\n\n- Documented a quirk regarding extraction from file descriptors in `erl_tar`.\n\n Own Id: OTP-16171 Aux Id: ERL-1057\n\n- Added `ok` as return value to `gen_server:reply/2`\n\n Own Id: OTP-16210 Aux Id: PR-2411\n\n- New functions have been added to `m:c` for printing embedded documentation for\n Erlang modules. The functions are:\n\n - **h/1,2,3** - Print the documentation for a Module:Function/Arity.\n\n - **ht/1,2,3** - Print the type documentation for a Module:Type/Arity.\n\n The embedded documentation is created when building the Erlang/OTP\n documentation.\n\n Own Id: OTP-16222\n\n- Add `indent` and `linewidth` to the options of the `erl_pp` module's\n functions.\n\n Own Id: OTP-16276 Aux Id: PR-2443\n\n- Minor updates due to the new spawn improvements made.\n\n Own Id: OTP-16368 Aux Id: OTP-15251\n\n- The compiler will now raise a warning when inlining is used in modules that\n load NIFs.\n\n Own Id: OTP-16429 Aux Id: ERL-303\n\n- Refactored the internal handling of deprecated and removed functions.\n\n Own Id: OTP-16469\n\n- Extend `erl_parse:abstract/1,2` to handle external fun expressions\n (`fun M:F/A`).\n\n Own Id: OTP-16480\n\n- Added `filelib:safe_relative_path/2` to replace\n `filename:safe_relative_path/1`, which did not safely handle symbolic links.\n\n `filename:safe_relative_path/1` has been deprecated.\n\n Own Id: OTP-16483 Aux Id: PR-2542\n\n- The module `shell_docs` has been added. The module contains functions for\n rendering, validating and normalizing embedded documentation.\n\n Own Id: OTP-16500\n\n- Module and function auto-completion in the shell now looks at all available\n modules instead of only those loaded. A module is considered available if it\n either is loaded already or would be loaded if called.\n\n The auto-completion has also been expanded to work in the new `h/1,2,3`\n function in `m:c`.\n\n Own Id: OTP-16501 Aux Id: OTP-16494, OTP-16222, OTP-16406, OTP-16499,\n OTP-16500, PR-2545, ERL-708\n\n- Updated the internal `pcre` library to `8.44`.\n\n Own Id: OTP-16557","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.12.1.2 - STDLIB Release Notes","ref":"notes.html#stdlib-3-12-1-2"},{"type":"extras","doc":"- Fix a bug that could cause a crash when formatting tuples using the control\n sequences `p` or `P` and limiting the output with the option `chars_limit`.\n\n Own Id: OTP-17525 Aux Id: GH-5053","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.12.1.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-12-1-1"},{"type":"extras","doc":"- Fix a bug that could cause a loop when formatting terms using the control\n sequences p or P and limiting the output with the option `chars_limit`.\n\n Own Id: OTP-17459 Aux Id: GH-4824, GH-4842","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.12.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-12-1"},{"type":"extras","doc":"- [re:run(Subject, RE, \\[unicode])](`re:run/3`) returned `nomatch` instead of\n failing with a `badarg` error exception when `Subject` contained illegal utf8\n and `RE` was passed as a binary. This has been corrected along with\n corrections of reduction counting in `re:run()` error cases.\n\n Own Id: OTP-16553","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.12 - STDLIB Release Notes","ref":"notes.html#stdlib-3-12"},{"type":"extras","doc":"- Fix type specification for uri_string:normalize/2 that may also return\n error().\n\n Own Id: OTP-16322\n\n- Improve error handling in uri_string:normalize/2. This change fixes a crash\n when the input URI has faulty percent-encoding.\n\n Own Id: OTP-16351\n\n- Fix minor bugs in the Erlang pretty printer (`erl_pp`).\n\n Own Id: OTP-16435\n\n- Fix the Erlang parser regarding consecutive unary operators.\n\n Own Id: OTP-16439\n\n- Let `calendar:rfc3339_to_system_time()` crash when the time offset is missing.\n\n Own Id: OTP-16514 Aux Id: ERL-1182","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Implement uri_string:resolve/\\{2,3\\} that can be used to resolve a URI\n reference against a base URI.\n\n Own Id: OTP-16321\n\n- In `gen_statem` it is now possible to change the callback module for a running\n server. See `gen_statem`'s documentation for `change_callback_module`,\n `push_callback_module`, and `pop_callback_module`.\n\n Own Id: OTP-16477 Aux Id: PR-2531","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.11.2 - STDLIB Release Notes","ref":"notes.html#stdlib-3-11-2"},{"type":"extras","doc":"- A directory traversal vulnerability has been eliminated in erl_tar. erl_tar\n will now refuse to extract symlinks that points outside the targeted\n extraction directory and will return `{error,{Path,unsafe_symlink}}`. (Thanks\n to Eric Meadows-Jönsson for the bug report and for suggesting a fix.)\n\n Own Id: OTP-16441","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.11.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-11-1"},{"type":"extras","doc":"- The `ets:update_counter/4` core dumped when given an ordered_set with\n write_concurrency enabled and an invalid position. This bug has been fixed.\n\n Own Id: OTP-16378 Aux Id: ERL-1125","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.11 - STDLIB Release Notes","ref":"notes.html#stdlib-3-11"},{"type":"extras","doc":"- The functions [`unicode:characters_to_list()`](`unicode:characters_to_list/2`)\n and [`unicode:characters_to_binary()`](`unicode:characters_to_binary/3`)\n raised a `badarg` exception instead of returning an error tuple when passed\n very large invalid code points as input.\n\n Own Id: OTP-16052\n\n- Fixed a bug in the linter where list and binary comprehensions could suppress\n unsafe variable errors.\n\n Own Id: OTP-16053 Aux Id: ERL-1039\n\n- Fixed incorrect type specifications for `erl_tar:open/2`, `create/2,3`, and\n `add/4`.\n\n Own Id: OTP-16085 Aux Id: PR-2379\n\n- Fixed erroneous type spec for `binary:list_to_bin/1`. Argument type was\n changed from `t:iodata/0` to `t:iolist/0`.\n\n Own Id: OTP-16132 Aux Id: ERL-1041\n\n- Fix a race in `pool:pspawn_link` that caused a `noproc` error to be thrown\n when using it to spawn a very short lived process.\n\n Own Id: OTP-16211\n\n- Fixed a performance issue in ETS lookup when using the `compressed` option and\n the term contained atoms. Before this fix the decompress algorithm for atoms\n would unnecessarily take a global lock to validate the atom.\n\n Own Id: OTP-16316","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Added a new compiler/linter option to disable warnings for unused types\n (`nowarn_unused_type`).\n\n Own Id: OTP-16262 Aux Id: ERIERL-435\n\n- ETS tables have been optimized to not use any locks when running in a system\n with only one scheduler enabled. This can provide significant performance\n gains for applications that use ETS tables heavily.\n\n Own Id: OTP-16315","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.10 - STDLIB Release Notes","ref":"notes.html#stdlib-3-10"},{"type":"extras","doc":"- `re:run()` now yields when validating utf8 in a large subject.\n\n Own Id: OTP-15836 Aux Id: ERL-876\n\n- Upgraded the ERTS internal PCRE library from version 8.42 to version 8.43. See\n [http://pcre.org/original/changelog.txt](http://pcre.org/original/changelog.txt)\n for information about changes made to PCRE. This library implements major\n parts of the `m:re` regular expressions module.\n\n Own Id: OTP-15889\n\n- The bug with ID ERL-717 has been fixed. The functions `io:columns()` and\n `io:rows()` only worked correctly inside interactive erlang shells before this\n fix. These functions returned `{error,enotsup}` before this fix even if stdout\n and stdin were connected to a terminal when they were invoked from an escript\n or a program started with e.g., `erl -noshell`.\n\n Own Id: OTP-15959 Aux Id: ERL-717\n\n- Fixed handling of \"..\" and \"@\" in wildcards. \"..\" would only work when\n preceded by a literal pattern such as in \"a/..\", not when preceded by wildcard\n characters such as in \"\\*/..\". The combination \"@/..\" was also broken, and in\n addition \"@\" in a pattern could degrade performance of the wildcard matching.\n\n Own Id: OTP-15987 Aux Id: ERL-1029\n\n- Make sure `ets:fun2ms()` can handle `++/2` in the head of functions when\n called from the shell.\n\n Own Id: OTP-15992 Aux Id: PR-2322","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Debugging of time-outs in `gen_statem` has been improved. Starting a time-out\n is now logged in `sys:log` and `sys:trace`. Running time-outs are visible in\n server crash logs, and with `sys:get_status`. Due to this system events\n `{start_timer, Action, State}` and `{insert_timout, Event, State}` have been\n added, which may surprise tools that rely on the format of these events.\n\n New features: The `EventContent` of a running time-out can be updated with\n `{TimeoutType, update, NewEventContent}`. Running time-outs can be cancelled\n with `{TimeoutType, cancel}` which is more readable than using\n `Time = infinity`.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15510\n\n- `re:run()` now avoids validating utf8 in the subject more than once in the\n same call. This validation could previously be performed multiple times when\n the `global` option was passed.\n\n Own Id: OTP-15831 Aux Id: ERL-876\n\n- ETS `ordered_set` tables with `write_concurrency` enabled has got a\n performance issue fixed. There were no limits for the values of internal\n statistics counters before this fix. This could result in that the data\n structure sometimes reacted slowly to a change in how many parallel processes\n were using it.\n\n Own Id: OTP-15906\n\n- The `ordsets:union/1` is now faster when passed a long list of ordsets.\n\n Own Id: OTP-15927\n\n- `unicode:characters_to_binary()` could return very small binaries as reference\n counted off heap binaries. This could cause an unnecessary large memory usage\n and an unnecessary load on the binary allocator. Small binaries are now always\n returned as heap binaries.\n\n Own Id: OTP-16002 Aux Id: ERIERL-366\n\n- Display a more meaningful error message when a bad I/O server is used in a\n script written in Erlang (`escript`).\n\n Own Id: OTP-16006 Aux Id: ERL-992\n\n- New feature `ets:info(_, binary)` to get information about all reference\n counted binaries kept by a table. This is the same kind of debug information\n that [`process_info(_, binary)`](`process_info/2`) returns for a process.\n\n Own Id: OTP-16035 Aux Id: ERIERL-366\n\n- Corrected ETS documentation about the behavior of compiled match\n specifications when serialized through external format.\n\n Own Id: OTP-16038 Aux Id: PR-2366","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.9.2 - STDLIB Release Notes","ref":"notes.html#stdlib-3-9-2"},{"type":"extras","doc":"- Fix a bug that could cause a loop when formatting terms using the control\n sequences `p` or `P` and limiting the output with the option `chars_limit`.\n\n Own Id: OTP-15875 Aux Id: ERL-967","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.9.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-9-1"},{"type":"extras","doc":"- Fix a bug that could cause a failure when formatting binaries using the\n control sequences `p` or `P` and limiting the output with the option\n `chars_limit`.\n\n Own Id: OTP-15847 Aux Id: ERL-957","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.9 - STDLIB Release Notes","ref":"notes.html#stdlib-3-9"},{"type":"extras","doc":"- Fix a bug in `string:lexemes/2`.\n\n The bug was found when optimizing the handling of deep lists of Unicode\n characters in the `string` module.\n\n Own Id: OTP-15649\n\n- A bug has been fixed in the `maps` implementation that could cause a crash or\n memory usage to grow until the machine ran out of memory. This could happen\n when inserting a new key-value pair with a key `K1` containing a binary `B1`\n into a map `M` having a key `K2` with a binary `B2` if the following\n conditions were met:\n\n - `B1 =/= B2`\n - `size(B1) >= 4294967296`\n - `size(B2) >= 4294967296`\n - `size(M) >= 32`\n - `(size(B1) rem 4294967296) == (size(B2) rem 4294967296)`\n - the first `(size(B1) rem 4294967296)` bytes are the same both in `B1` and\n `B2`\n - substituting `B1` in `K1` with `B2` would create a term with the same value\n as `K2`\n\n The root cause of the problem is that the `maps` implementation only hashed\n the first `(X rem 4294967296)` bytes of binaries so that different binaries\n could get the same hash value independently of the hash seed.\n\n Own Id: OTP-15707\n\n- Since the introduction of the stack trace variable, the Erlang Pretty Printer\n has left out the exception class `throw` even when the stack trace variable\n cannot be left out, which is not correct Erlang code. The fix is to always\n include the exception class `throw`.\n\n Own Id: OTP-15751\n\n- `record_info/2` is a pseudo-function that requires literal arguments known at\n compile time. Therefore, the following usage is illegal: `fun record/info/2`.\n The compiler would crash when during compilation of that kind of code.\n Corrected to issue a compilation error.\n\n Own Id: OTP-15760 Aux Id: ERL-907","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- A new `rand` module algorithm, `exro928ss` (Xoroshiro928\\*\\*), has been\n implemented. It has got a really long period and good statistical quality for\n all output bits, while still being only about 50% slower than the default\n algorithm.\n\n The same generator is also used as a long period counter in a new `crypto`\n plugin for the `rand` module, algorithm `crypto_aes`. This plugin uses AES-256\n to scramble the counter which buries any detectable statistical artifacts.\n Scrambling is done in chunks which are cached to get good amortized speed\n (about half of the default algorithm).\n\n Own Id: OTP-14461 Aux Id: PR-1857\n\n- Types related to server naming and starting have been exported from\n `gen_statem`. These are: `server_name/0`, `server_ref/0`, `start_opt/0`,\n `start_ret/0` and `enter_loop_opt/0`.\n\n Own Id: OTP-14724 Aux Id: PR-2056\n\n- The default algorithm for the `rand` module has been changed to `exsss`\n (Xorshift116\\*\\*) which is a combination of the Xorshift116 (`exsp`) state\n update and a new scrambler \"StarStar\" from the 2018 paper \"Scrambled Linear\n Pseudorandom Number Generators\" by David Blackman and Sebastiano Vigna. This\n combination should not have the caveat of weak low bits that the previous\n default algorithm(s) have had, with the cost of about 10% lower speed. See\n GitHub pull request #1969.\n\n Own Id: OTP-14731 Aux Id: PR-1969\n\n- The generic state machine behaviour `gen_statem` has gotten code cleanup and\n documentation improvements from GitHub Pull Request #1855, even though the PR\n itself was rejected.\n\n Own Id: OTP-14737 Aux Id: PR-1855\n\n- Update Unicode specification to version 11.0.\n\n Own Id: OTP-15111\n\n- ETS option `write_concurrency` now also affects and improves the scalability\n of `ordered_set` tables. The implementation is based on a data structure\n called contention adapting search tree, where the lock granularity adapts to\n the actual amount of concurrency exploited by the applications in runtime.\n\n Own Id: OTP-15128\n\n- Optimized `maps:new/0` with trivial Erlang implementation, making use of\n literal terms (the empty map) not needing dynamic heap allocation.\n\n Own Id: OTP-15200 Aux Id: PR-1878\n\n- The `gen_*` behaviours have been changed so that if logging of the last N\n messages through `sys:log/2,3` is active for the server, this log is included\n in the terminate report.\n\n To accomplish this the format of \"System Events\" as defined in the man page\n for `sys` has been clarified and cleaned up, a new function `sys:get_log/1`\n has been added, and `sys:get_debug/3` has been deprecated. Due to these\n changes, code that relies on the internal badly documented format of \"System\n Events\", need to be corrected.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15381\n\n- The `gen_statem` behaviour engine loop has been optimized for better\n performance in particular when the callback module returns some actions, that\n is better performance for more realistic applications than the Echo Benchmark.\n\n Own Id: OTP-15452\n\n- Do not allow function specifications for functions residing in other modules.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15563 Aux Id: ERL-845, OTP-15562\n\n- The `persistent_term` functions [`put/2`](`put/2`) and [`erase/1`](`erase/1`)\n are now yielding.\n\n Own Id: OTP-15615\n\n- Previously, all ETS tables used centralized counter variables to keep track of\n the number of items stored and the amount of memory consumed. These counters\n can cause scalability problems (especially on big NUMA systems). This change\n adds an implementation of a decentralized counter and modifies the\n implementation of ETS so that ETS tables of type `ordered_set` with\n `write_concurrency` enabled use the decentralized counter. Experiments\n indicate that this change substantially improves the scalability of ETS\n `ordered_set` tables with `write_concurrency` enabled in scenarios with\n frequent `ets:insert/2` and `ets:delete/2` calls.\n\n Own Id: OTP-15623 Aux Id: PR-2190\n\n- Use `ssh` instead of `rsh` as the default remote shell.\n\n Own Id: OTP-15633 Aux Id: PR-1787\n\n- Added `beam_lib:strip/2` and friends, which accept a list of chunks that\n should be preserved when stripping.\n\n Own Id: OTP-15680 Aux Id: PR-2114\n\n- Optimize printing of maps with `io_lib:write()`. Also optimize pretty printing\n of strings (`~s` and `~ts`) when limiting the output with the `chars_limit`\n option.\n\n Own Id: OTP-15705\n\n- There are new compiler options `nowarn_removed` and `{nowarn_removed,Items}`\n to suppress warnings for functions and modules that have been removed from\n OTP.\n\n Own Id: OTP-15749 Aux Id: ERL-904\n\n- Let the Erlang Pretty Printer put atomic parts on the same line.\n\n Own Id: OTP-15755\n\n- Add option `quote_singleton_atom_types` to the Erlang Pretty Printer's\n functions. Setting the option to `true` adds quotes to all singleton atom\n types.\n\n Own Id: OTP-15756","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.8.2.4 - STDLIB Release Notes","ref":"notes.html#stdlib-3-8-2-4"},{"type":"extras","doc":"- [re:run(Subject, RE, \\[unicode])](`re:run/3`) returned `nomatch` instead of\n failing with a `badarg` error exception when `Subject` contained illegal utf8\n and `RE` was passed as a binary. This has been corrected along with\n corrections of reduction counting in `re:run()` error cases.\n\n Own Id: OTP-16553","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.8.2.3 - STDLIB Release Notes","ref":"notes.html#stdlib-3-8-2-3"},{"type":"extras","doc":"- A directory traversal vulnerability has been eliminated in erl_tar. erl_tar\n will now refuse to extract symlinks that points outside the targeted\n extraction directory and will return `{error,{Path,unsafe_symlink}}`. (Thanks\n to Eric Meadows-Jönsson for the bug report and for suggesting a fix.)\n\n Own Id: OTP-16441","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.8.2.2 - STDLIB Release Notes","ref":"notes.html#stdlib-3-8-2-2"},{"type":"extras","doc":"- Fix a bug that could cause a loop when formatting terms using the control\n sequences `p` or `P` and limiting the output with the option `chars_limit`.\n\n Own Id: OTP-15875 Aux Id: ERL-967","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.8.2.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-8-2-1"},{"type":"extras","doc":"- Fix a bug that could cause a failure when formatting binaries using the\n control sequences `p` or `P` and limiting the output with the option\n `chars_limit`.\n\n Own Id: OTP-15847 Aux Id: ERL-957","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.8.2 - STDLIB Release Notes","ref":"notes.html#stdlib-3-8-2"},{"type":"extras","doc":"- A bug in gen_statem has been fixed where the internal timeout message could\n arrive as an info to the callback module during high load due to incorrect use\n of asynchronous timer cancel.\n\n Own Id: OTP-15295","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.8.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-8-1"},{"type":"extras","doc":"- Fixed a performance regression when reading files opened with the `compressed`\n flag.\n\n Own Id: OTP-15706 Aux Id: ERIERL-336","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.8 - STDLIB Release Notes","ref":"notes.html#stdlib-3-8"},{"type":"extras","doc":"- Fix a bug in the Erlang Pretty Printer: long atom names in combination with\n `<<>>` could cause a crash.\n\n Own Id: OTP-15592 Aux Id: ERL-818\n\n- Fix bugs that could cause wrong results or bad performance when formatting\n lists of characters using the control sequences `p` or `P` and limiting the\n output with the option `chars_limit`.\n\n Own Id: OTP-15639","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Improved ETS documentation about safe table traversal and the partially bound\n key optimization for `ordered_set`.\n\n Own Id: OTP-15545 Aux Id: PR-2103, PR-2139\n\n- Optimize `calendar:gregorian_days_to_date/1`.\n\n Own Id: OTP-15572 Aux Id: PR-2121\n\n- Optimize functions `calendar:rfc3339_to_system_time()` and\n `calendar:system_time_to_rfc3339()`.\n\n Own Id: OTP-15630","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.7.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-7-1"},{"type":"extras","doc":"- Optimize pretty printing of terms. The slower behaviour was introduced in\n Erlang/OTP 20.\n\n Own Id: OTP-15573 Aux Id: ERIERL-306","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.7 - STDLIB Release Notes","ref":"notes.html#stdlib-3-7"},{"type":"extras","doc":"- Document `bit_size` in match specifications and allow it in `ets:fun2ms`.\n\n Own Id: OTP-15343 Aux Id: PR-1962\n\n- The `beam()` type in `beam_lib` is defined as\n `module() | file:filename() | binary()`. The `t:module/0` is misleading.\n Giving the module name as an atom will only work if the BEAM file is in a\n current directory.\n\n To avoid confusion, `t:module/0` has been removed from the type. That means\n that there will be a Dialyzer warning for code that call `beam_lib` with an\n atom as filename, but the calls will still work.\n\n Own Id: OTP-15378 Aux Id: ERL-696\n\n- `unicode_util` crashed on certain emoji grapheme clusters in binary strings.\n\n Own Id: OTP-15428 Aux Id: ERL-777\n\n- When an external fun was used, warnings for unused variables could be\n suppressed.\n\n Own Id: OTP-15437 Aux Id: ERL-762\n\n- Fix reduction count in lists:member/2\n\n Own Id: OTP-15474 Aux Id: ERIERL-229","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- When specified, the `+{source,Name}` option will now override the actual file\n name in stack traces, instead of only affecting the return value of\n `Mod:module_info()`.\n\n The `+deterministic` flag will also affect stack traces now, omitting all path\n information except the file name, fixing a long-standing issue where\n deterministic builds required deterministic paths.\n\n Own Id: OTP-15245 Aux Id: ERL-706\n\n- List subtraction (The `--` operator) will now yield properly on large inputs.\n\n Own Id: OTP-15371\n\n- `calendar:system_time_to_rfc3339/1,2` no longer remove trailing zeros from\n fractions.\n\n Own Id: OTP-15464","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.6 - STDLIB Release Notes","ref":"notes.html#stdlib-3-6"},{"type":"extras","doc":"- The specs of `filename:basedir/2,3` are corrected.\n\n Own Id: OTP-15252 Aux Id: ERL-667","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Let `dets:open_file()` exit with a `badarg` message if given a raw file name\n (a binary).\n\n Own Id: OTP-15253 Aux Id: OTP-13229, ERL-55\n\n- The `Format` argument of the formatting functions in modules `io` and `io_lib`\n is accepted even if it is, for example, a list of binaries. This is how it\n used to be before Erlang/OTP 21.0.\n\n Own Id: OTP-15304","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.5.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-5-1"},{"type":"extras","doc":"- Fix a bug that could cause a crash when formatting a list of non-characters\n using the control sequences `p` or `P` and limiting the output with the option\n `chars_limit`.\n\n Own Id: OTP-15159","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.5 - STDLIB Release Notes","ref":"notes.html#stdlib-3-5"},{"type":"extras","doc":"- `gen_statem` improvements.\n\n When using an exception that is valid but not allowed in a state enter call,\n the reason has been changed from `{bad_action_from_state_function,Action}` to\n `{bad_state_enter_action_from_state_function,Action}`.\n\n Timer parsing has been improved. Many erroneous timeout tuples was not handled\n correctly.\n\n The documentation has been updated, in particular the User's Guide and the\n pointer to it from the Reference Manual is much more obvious.\n\n Own Id: OTP-14015\n\n- The type specifications for [`file:posix/0`](`t:file:posix/0`) and\n [`inet:posix/0`](`t:inet:posix/0`) have been updated according to which errors\n file and socket operations should be able to return.\n\n Own Id: OTP-14019 Aux Id: ERL-550\n\n- File operations used to accept [filenames](`t:file:name_all/0`) containing\n null characters (integer value zero). This caused the name to be truncated and\n in some cases arguments to primitive operations to be mixed up. Filenames\n containing null characters inside the filename are now _rejected_ and will\n cause primitive file operations to fail.\n\n Also environment variable operations used to accept\n [names](`t:os:env_var_name/0`) and [values](`t:os:env_var_value/0`) of\n environment variables containing null characters (integer value zero). This\n caused operations to silently produce erroneous results. Environment variable\n names and values containing null characters inside the name or value are now\n _rejected_ and will cause environment variable operations to fail.\n\n Primitive environment variable operations also used to accept the `$=`\n character in environment variable names causing various problems. `$=`\n characters in environment variable names are now also _rejected_.\n\n Also `os:cmd/1` now reject null characters inside its\n [command](`t:os:os_command/0`).\n\n `erlang:open_port/2` will also reject null characters inside the port name\n from now on.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-14543 Aux Id: ERL-370\n\n- Make `io_lib:unscan_format/1` work with pad char and default precision.\n\n Own Id: OTP-14958 Aux Id: PR-1735\n\n- The control sequence modifiers `t` and `l` can be used together in the same\n control sequence which makes it possible to have Unicode atoms and no\n detection of printable character lists at the same time.\n\n Own Id: OTP-14971 Aux Id: PR-1743\n\n- Fix a bug in the Erlang code linter: the check of guard expressions no longer\n returns `false` if the map syntax is used. The bug affected the Erlang shell,\n the Debugger, and other modules evaluating abstract code.\n\n Own Id: OTP-15035 Aux Id: ERL-613\n\n- A sys debug fun of type \\{Fun,State\\} should not be possible to install twice.\n This was, however, possible if the current State was 'undefined', which was\n mistaken for non-existing fun. This has been corrected.\n\n Own Id: OTP-15049\n\n- Fix `io:putchars/2` stacktrace rewriting at errors to point to a valid\n function.\n\n Own Id: OTP-15101","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The `gen_server` has gotten a new callback `handle_continue/2` for check\n pointing the state. This is useful at least when implementing behaviours on\n top of `gen_server` and for some start up scenarios.\n\n Own Id: OTP-13019 Aux Id: PR-1490\n\n- The semantics of timeout parameter `{clean_timeout,infinity}` to\n `gen_statem:call/3` has been changed to use a proxy process for the call. With\n this change `clean_timeout` implicates a proxy process with no exceptions.\n This may be a hard to observe incompatibility: in the presence of network\n problems a late reply could arrive in the caller's message queue when catching\n errors. That will not happen after this correction.\n\n The semantics of timeout parameter `infinity` has not been changed.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-13073 Aux Id: PR-1595\n\n- A new logging API is added to Erlang/OTP, see the `m:logger` manual page, and\n section [Logging](`e:kernel:logger_chapter.md`) in the Kernel User's Guide.\n\n Calls to `error_logger` are automatically redirected to the new API, and\n legacy error logger event handlers can still be used. It is, however,\n recommended to use the Logger API directly when writing new code.\n\n Notice the following potential incompatibilities:\n\n - Kernel configuration parameters `error_logger` still works, but is overruled\n if the default handler's output destination is configured with Kernel\n configuration parameter `logger`.\n\n In general, parameters for configuring error logger are overwritten by new\n parameters for configuring Logger.\n\n - The concept of SASL error logging is deprecated, meaning that by default the\n SASL application does not affect which log events are logged.\n\n By default, supervisor reports and crash reports are logged by the default\n Logger handler started by Kernel, and end up at the same destination\n (terminal or file) as other standard log event from Erlang/OTP.\n\n Progress reports are not logged by default, but can be enabled by setting\n the primary log level to info, for example with the Kernel configuration\n parameter `logger_level`.\n\n To obtain backwards compatibility with the SASL error logging functionality\n from earlier releases, set Kernel configuration parameter\n `logger_sasl_compatible` to `true`. This prevents the default Logger handler\n from logging any supervisor-, crash-, or progress reports. Instead, SASL\n adds a separate Logger handler during application start, which takes care of\n these log events. The SASL configuration parameters `sasl_error_logger` and\n `sasl_errlog_type` specify the destination (terminal or file) and severity\n level to log for these events.\n\n Since Logger is new in Erlang/OTP 21.0, we do reserve the right to introduce\n changes to the Logger API and functionality in patches following this release.\n These changes might or might not be backwards compatible with the initial\n version.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-13295\n\n- Add functions `calendar:system_time_to_local_time/2` and\n `calendar:system_time_to_universal_time/2`.\n\n Own Id: OTP-13413\n\n- Functions `rand:uniform_real/0` and `rand:uniform_real_s/1` have been added.\n They produce uniformly distributed numbers in the range `0.0 =< X < 1.0` that\n are as close to random real numbers as Normalized IEEE 754 Double Precision\n allows. Because the random real number exactly `0.0` is infinitely improbable\n they will never return exactly `0.0`.\n\n These properties are useful when you need to call for example `math:log(X)` or\n `1 / X` on a random value `X`, since that will never fail with a number from\n these new functions.\n\n Own Id: OTP-13764 Aux Id: PR-1574\n\n- Added maps:iterator/0 and maps:next/1 to be used for iterating over the\n key-value associations in a map.\n\n Own Id: OTP-14012\n\n- Changed the default behaviour of `.erlang` loading: `.erlang` is no longer\n loaded from the current directory. `c:erlangrc(PathList)` can be used to\n search and load an `.erlang` file from user specified directories.\n\n `escript`, `erlc`, `dialyzer` and `typer` no longer load an `.erlang` at all.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-14439\n\n- Added new uri_string module to stdlib for handling URIs (RFC 3986).\n\n Own Id: OTP-14496\n\n- Update Unicode specification to version 10.0.\n\n Own Id: OTP-14503\n\n- `filelib:wildcard()` now allows characters with a special meaning to be\n escaped using backslashes.\n\n This is an incompatible change, but note that the use of backslashes in\n wildcards would already work differently on Windows and Unix. Existing calls\n to `filelib:wildcard()` needs to be updated. On Windows, directory separators\n must always be written as a slash.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-14577\n\n- The supervisor now stores its child specifications in a map instead of a list.\n This causes a significant improvement when starting many children under a\n non-simple_one_for_one supervisor.\n\n Own Id: OTP-14586\n\n- The `base64` module is optimized.\n\n Note that the functions `encode/1`, `decode/1`, and `mime_decode/1` fail\n unless called with an argument of the documented type. They used to accept any\n `t:iodata/0`.\n\n Own Id: OTP-14624 Aux Id: PR-1565\n\n- Add function `lists:search/2`.\n\n Own Id: OTP-14675 Aux Id: PR-102\n\n- uri_string module extended with functions for handling\n application/x-www-form-urlencoded query strings based on the HTML5\n specification.\n\n Own Id: OTP-14747\n\n- Add functions `calendar:rfc3339_to_system_time/1,2` and\n `calendar:system_time_to_rfc3339/1,2`.\n\n Own Id: OTP-14764\n\n- The stack traces returned by the functions of the `erl_eval` module more\n accurately reflect where the exception occurred.\n\n Own Id: OTP-14826 Aux Id: PR 1540\n\n- Add options `atime`, `mtime`, `ctime`, `uid`, and `gid` to the\n `erl_tar:add/3,4` functions.\n\n Own Id: OTP-14834 Aux Id: PR 1608\n\n- Added `ets:whereis/1` for retrieving the table identifier of a named table.\n\n Own Id: OTP-14884\n\n- Improved URI normalization functions in the uri_string module.\n\n Own Id: OTP-14910\n\n- The new functions `io_lib:fwrite/3` and `io_lib:format/3` take a third\n argument, an option list. The only option is `chars_limit`, which is used for\n limiting the number of returned characters. The limit is soft, which means\n that the number of returned characters exceeds the limit with at most a\n smallish amount. If the limit is set, the functions `format/3` and `fwrite/3`\n try to distribute the number of characters evenly over the control sequences\n `pPswW`. Furthermore, the control sequences `pPwP` try to distribute the\n number of characters evenly over substructures.\n\n A modification of the control sequences `pPwW` is that even if there is no\n limit on the number of returned characters, all associations of a map are\n printed to the same depth. The aim is to give a more consistent output as the\n order of map keys is not defined. As before, if the depth is less than the\n number of associations of a map, the selection of associations to print is\n arbitrary.\n\n Own Id: OTP-14983\n\n- Add functions `ordsets:is_empty/1` and `sets:is_empty/1`.\n\n Own Id: OTP-14996 Aux Id: ERL-557, PR-1703\n\n- Improve performance of `string:uppercase/1`, `string:lowercase/1` and\n `string:casefold/1` when handling ASCII characters.\n\n Own Id: OTP-14998\n\n- External funs with literal values for module, name, and arity (e.g.\n `erlang:abs/1`) are now treated as literals. That means more efficient code\n that produces less garbage on the heap.\n\n Own Id: OTP-15003\n\n- sys:statistics(Pid,get) did not report 'out' messages from gen_server. This is\n now corrected.\n\n Own Id: OTP-15047\n\n- A sys debug function can now have the format \\{Id,Fun,State\\} in addition to\n the old \\{Fun,State\\}. This allows installing multiple instances of a debug\n fun.\n\n Own Id: OTP-15048\n\n- The `lib` module is removed:\n\n - `lib:error_message/2` is removed.\n - `lib:flush_receive/0` is removed.\n - `lib:nonl/1` is removed.\n - `lib:progname/0` is replaced by `ct:get_progname/0`.\n - `lib:send/2` is removed.\n - `lib:sendw/2` is removed.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15072 Aux Id: PR 1786, OTP-15114\n\n- Function `ets:delete_all_objects/1` now yields the scheduler thread for large\n tables that take significant time to clear. This to improve real time\n characteristics of other runnable processes.\n\n Own Id: OTP-15078\n\n- In control sequences of the functions `io:fwrite/2,3` and `io_lib:fwrite/2,3`\n containing `p` or `P`, a field width of value `0` means that no line breaks\n are inserted. This is in contrast to the old behaviour, where `0` used to\n insert line breaks after every subterm. To insert line breaks after every\n subterm, a field width of value `1` can be used.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-15103 Aux Id: ERL-607","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.4.5.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-4-5-1"},{"type":"extras","doc":"- List subtraction (The `--` operator) will now yield properly on large inputs.\n\n Own Id: OTP-15371","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.4.5 - STDLIB Release Notes","ref":"notes.html#stdlib-3-4-5"},{"type":"extras","doc":"- The `Module:init/1` function in `gen_statem` may return an actions list\n containing any action, but an erroneous check only allowed state enter actions\n so e.g `{next_event,internal,event}` caused a server crash. This bug has been\n fixed.\n\n Own Id: OTP-13995","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.4.4 - STDLIB Release Notes","ref":"notes.html#stdlib-3-4-4"},{"type":"extras","doc":"- Correct `filelib:find_source()` and `filelib:find_file()` to by default also\n search one level below `src`. This is in accordance with the Design Principles\n which states that an application can have Erlang source files one level below\n the `src` directory.\n\n Own Id: OTP-14832 Aux Id: ERL-527\n\n- The contract of `erl_tar:table/2` is corrected.\n\n Own Id: OTP-14860 Aux Id: PR 1670\n\n- Correct a few contracts.\n\n Own Id: OTP-14889\n\n- Fix string:prefix/2 to handle an empty string as second argument.\n\n Own Id: OTP-14942 Aux Id: PR-1702","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.4.3 - STDLIB Release Notes","ref":"notes.html#stdlib-3-4-3"},{"type":"extras","doc":"- Make `ets:i/1` exit cleaner when ^D is input while browsing a table. Only the\n old Erlang shell is affected ([erl](`e:erts:erl_cmd.md`) flag `-oldshell`).\n\n Own Id: OTP-14663\n\n- Fixed handling of windows UNC paths in module `filename`.\n\n Own Id: OTP-14693","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Improve performance of the new string functionality when handling ASCII\n characters.\n\n Own Id: OTP-14670\n\n- Added a clarification to the documentation of `unicode:characters_to_list/2`.\n\n Own Id: OTP-14798","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.4.2 - STDLIB Release Notes","ref":"notes.html#stdlib-3-4-2"},{"type":"extras","doc":"- Fix a bug in the Erlang shell where recursively defined records with typed\n fields could cause a loop.\n\n Own Id: OTP-14488 Aux Id: PR-1489\n\n- Make edlin handle grapheme clusters instead of codepoints to improve the\n handling multi-codepoints characters.\n\n Own Id: OTP-14542\n\n- There could be false warnings for `erlang:get_stacktrace/0` being used outside\n of a `try` block when using multiple `catch` clauses.\n\n Own Id: OTP-14600 Aux Id: ERL-478","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The Erlang code linter no longer checks that the functions mentioned in\n `nowarn_deprecated_function` options are declared in the module.\n\n Own Id: OTP-14378\n\n- General Unicode improvements.\n\n Own Id: OTP-14462","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.4.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-4-1"},{"type":"extras","doc":"- A bug in `proc_lib:format()` introduced in Erlang/OTP 20.0 is corrected.\n\n Own Id: OTP-14482 Aux Id: PR-1488\n\n- Fix string:len/1 to be compatible with previous versions.\n\n Own Id: OTP-14487 Aux Id: ERIERL-40\n\n- In OTP-20.0, the behavior of c, make, and ct_make was changed so that in some\n cases the beam files by default would be written to the directory where the\n source files were found. This is now changed back to the old behavior so beam\n files are by default written to current directory.\n\n Own Id: OTP-14489 Aux Id: ERL-438","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.4 - STDLIB Release Notes","ref":"notes.html#stdlib-3-4"},{"type":"extras","doc":"- For many releases, it has been legal to override a BIF with a local function\n having the same name. However, calling a local function with the same name as\n guard BIF as filter in a list comprehension was not allowed.\n\n Own Id: OTP-13690\n\n- A new (default) pseudo-random number generator algorithm Xoroshiro116+ has\n been implemented in the `rand` module.\n\n The old algorithm implementations had a number of flaws so they are all\n deprecated, but corrected versions of two of them have been added. See the\n documentation.\n\n Own Id: OTP-14295 Aux Id: PR-1372\n\n- The Erlang shell, `qlc:string_to_handle()`, and the Debugger (the Evaluator\n area and Edit variable window of the Bindings area) can parse pids, ports,\n references, and external funs, as long as they can be created in the running\n system.\n\n Own Id: OTP-14296\n\n- Internal code change: Calls to `catch` followed by a call to\n `erlang:get_stacktrace/0` has been rewritten to use `try` instead of `catch`\n to make the code future-proof.\n\n Own Id: OTP-14400\n\n- The `ms_transform` module, used by `ets:fun2ms/1` and `dbg:fun2ms/1`,\n evaluates constant arithmetic expressions. This is necessary since the Erlang\n compiler, which normally evaluates constant expressions, does not recognize\n the format generated by `ms_transform`.\n\n Own Id: OTP-14454 Aux Id: ERIERL-29\n\n- The state machine engine `gen_statem` can now handle generic time-outs\n (multiple named) as well as absolute time-out time. See the documentation.\n\n The `gen_statem` callback `Module:init/1` has become mandatory to harmonize\n with other `gen_*` modules. This may be an incompatibility for `gen_statem`\n callback modules that use `gen_statem:enter_loop/4-6`.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-14531","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Improved unicode support for strings. Added normalization functions in the\n `unicode` module. Extended the `string` module API with new functions with\n improved unicode handling and that works on grapheme clusters. The new\n functions operates on the [`unicode:chardata()`](`t:unicode:chardata/0`) type,\n thus they also accept `UTF-8 binaries` as input.\n\n The old string API have been marked as obsolete. The return values have been\n changed for some error cases.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-10289 Aux Id: OTP-10309\n\n- There are two new guard BIFs '[`floor/1`](`floor/1`)' and\n '[`ceil/1`](`ceil/1`)'. They both return integers. In the '`math`' module,\n there are two new BIFs with the same names that return floating point values.\n\n Own Id: OTP-13692\n\n- Making code_change, terminate and handle_info callbacks optional in the OTP\n behaviours.\n\n Own Id: OTP-13801\n\n- The support for Dets files created with Erlang/OTP R7 and earlier is removed.\n\n Own Id: OTP-13830\n\n- Replaced usage of deprecated symbolic [`time unit`](`t:erlang:time_unit/0`)\n representations.\n\n Own Id: OTP-13831 Aux Id: OTP-13735\n\n- The function `fmod/2` has been added to the `math` module.\n\n Own Id: OTP-14000\n\n- The EXIT signals received from processes using `proc_lib` now looks like EXIT\n signals from processes that were spawned using `spawn_link`. In particular,\n that means that the stack trace is now included in the EXIT signal so that it\n can see where the process crashed.\n\n Own Id: OTP-14001\n\n- `sets:add_element/2` is faster when adding an element that is already present,\n and `sets:del_element/2` is faster when the element to be deleted is not\n present. This optimization can make certain operations, such as sets:union/2\n with many overlapping elements, up to two orders of magnitude faster.\n\n Own Id: OTP-14035\n\n- Add information in doc about supervisor shutdown reason when maximum restart\n frequency is reached.\n\n Own Id: OTP-14037 Aux Id: PR-1233\n\n- Added `rand:jump/[0|1]` functions.\n\n Own Id: OTP-14038 Aux Id: PR-1235\n\n- Functions for detecting changed code has been added. `code:modified_modules/0`\n returns all currently loaded modules that have changed on disk.\n `code:module_status/1` returns the status for a module. In the shell and in\n `c` module, `mm/0` is short for `code:modified_modules/0`, and `lm/0` reloads\n all currently loaded modules that have changed on disk.\n\n Own Id: OTP-14059\n\n- Each assert macro in `assert.hrl` now has a corresponding version with an\n extra argument, for adding comments to assertions. These can for example be\n printed as part of error reports, to clarify the meaning of the check that\n failed.\n\n Own Id: OTP-14066\n\n- `error_logger_tty_h` and `error_logger_file_h` now inserts the node\n information for nonlocal messages before the message itself instead of after,\n both for readability and so as not to change the line termination property at\n the end of the message.\n\n Own Id: OTP-14068\n\n- The Erlang code linter checks for badly formed type constraints.\n\n Own Id: OTP-14070 Aux Id: PR-1214\n\n- By default, there will now be a warning when `export_all` is used. The warning\n can be disabled using `nowarn_export_all`.\n\n Own Id: OTP-14071\n\n- When a `gen_server` process crashes, the stacktrace for the client will be\n printed to facilitate debugging.\n\n Own Id: OTP-14089\n\n- Optimized ETS operations by changing table identifier type from integer to\n reference. The reference enables a more direct mapping to the table with less\n potential lock contention and makes especially creation and deletion of tables\n scale much better.\n\n The change of the opaque type for the ETS table identifiers may cause failure\n in code that make faulty assumptions about this opaque type.\n\n > #### Note {: .info }\n >\n > The number of tables stored at one Erlang node _used_ to be limited. This is\n > no longer the case (except by memory usage). The previous default limit was\n > about 1400 tables and could be increased by setting the environment variable\n > `ERL_MAX_ETS_TABLES` before starting the Erlang runtime system. This hard\n > limit has been removed, but it is currently useful to set the\n > `ERL_MAX_ETS_TABLES` anyway. It should be set to an approximate of the\n > maximum amount of tables used. This since an internal table for named tables\n > is sized using this value. If large amounts of named tables are used and\n > `ERL_MAX_ETS_TABLES` hasn't been increased, the performance of named table\n > lookup will degrade.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-14094\n\n- `take/2` has been added to `dict`, `orddict`, and `gb_trees`. `take_any/2` has\n been added to `gb_trees`.\n\n Own Id: OTP-14102\n\n- Extend gen_event API to handle options as well.\n\n Own Id: OTP-14123\n\n- Advice on how to tune the supervisor restart frequency (intensity and period)\n is added to System Documentation - Design Principles - Supervisor Behaviour.\n\n Own Id: OTP-14168 Aux Id: PR-1289\n\n- gen_fsm is deprecated and is replaced by gen_statem, however for backwards\n compatibility reasons gen_fsm may continue to exist as an undocumented feature\n for quite some time.\n\n Own Id: OTP-14183\n\n- The shell functions `c/1` and `c/2` have been extended so that if the argument\n is a module name instead of a file name, it automatically locates the .beam\n file and the corresponding source file, and then recompiles the module using\n the same compiler options (plus any options passed to c/2). If compilation\n fails, the old beam file is preserved. Also adds `c(Mod, Opts, Filter)`, where\n the Filter argument allows you to remove old compiler options before the new\n options are added.\n\n New utility functions `file_find/2/3` and `find_source/1/2/3` have been added\n to `filelib`.\n\n Own Id: OTP-14190\n\n- `erl_tar` in previous versions of OTP only supports the USTAR format. That\n limited path names to at most 255 bytes, and did not support Unicode\n characters in names in a portable way.\n\n `erl_tar` now has support for reading tar archives in the formats currently in\n common use, such as v7, STAR, USTAR, PAX, and GNU tar's extensions to the\n STAR/USTAR format. When writing tar archives, `erl_tar` can now write them in\n the `PAX` format if necessary (for example, to support very long filenames or\n filenames with Unicode characters). If possible, `erl_tar` will still write\n tar archives in the USTAR for maximum portability.\n\n Own Id: OTP-14226\n\n- `base64:mime_decode/1` has been optimized so that it is now almost as fast\n as`base64:decode/1`; it used be noticeably slower.\n\n Own Id: OTP-14245\n\n- `erl_tar` will now strip any leading '`/`' from pathnames when extracting\n files from a tar archive and write a message to the error logger. There is\n also new check for directory traversal attacks; if a relative path points\n above the current working directory the extraction will be aborted.\n\n Own Id: OTP-14278\n\n- Miscellaneous updates due to atoms containing arbitrary Unicode characters.\n\n Own Id: OTP-14285\n\n- The Crypto application now supports generation of cryptographically strong\n random numbers (floats < 1.0 and integer arbitrary ranges) as a plugin to the\n 'rand' module.\n\n Own Id: OTP-14317 Aux Id: PR-1372\n\n- Add new function `ets:select_replace/2` which performs atomic\n \"compare-and-swap\" operations for ETS objects using match specifications.\n\n Own Id: OTP-14319 Aux Id: PR-1076\n\n- The Erlang code linter checks for bad `dialyzer` attributes. It also checks\n for bad type variables in type declarations.\n\n Own Id: OTP-14323\n\n- Two new functions has been implemented in the `rand` module; `normal/2` and\n `normal_s/3`, that both produce normal distribution (pseudo) random numbers\n with mean value and variance according to arguments.\n\n Own Id: OTP-14328 Aux Id: PR-1382\n\n- Upgraded the OTP internal PCRE library from version 8.33 to version 8.40. This\n library is used for implementation of the `m:re` regular expressions module.\n\n Besides various bug fixes, the new version allows for better stack protection.\n In order to utilize this feature, the stack size of normal scheduler threads\n is now by default set to 128 kilo words on all platforms. The stack size of\n normal scheduler threads can be set upon system start by passing the\n [`+sss`](`e:erts:erl_cmd.md#sched_thread_stack_size`) command line argument to\n the [`erl`](`e:erts:erl_cmd.md`) command.\n\n See\n [http://pcre.org/original/changelog.txt](http://pcre.org/original/changelog.txt)\n for information about changes made to PCRE between the versions 8.33 and 8.40.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-14331 Aux Id: ERL-208\n\n- Added function `re:version/0` which returns information about the OTP internal\n PCRE version used for implementation of the `re` module.\n\n Own Id: OTP-14347 Aux Id: PR-1412\n\n- The format of debug information that is stored in BEAM files (when\n `debug_info` is used) has been changed. The purpose of the change is to better\n support other BEAM-based languages such as Elixir or LFE.\n\n All tools included in OTP (dialyzer, debugger, cover, and so on) will handle\n both the new format and the previous format. Tools that retrieve the debug\n information using `beam_lib:chunk(Beam, [abstract_code])` will continue to\n work with both the new and old format. Tools that call\n `beam_lib:chunk(Beam, [\"Abst\"])` will not work with the new format.\n\n For more information, see the description of `debug_info` in the documentation\n for `beam_lib` and the description of the `{debug_info,{Backend,Data}}` option\n in the documentation for `compile`.\n\n Own Id: OTP-14369 Aux Id: PR-1367\n\n- Add option hibernate_after to gen_server, gen_statem and gen_event. Also added\n to the deprecated gen_fsm behaviour.\n\n Own Id: OTP-14405\n\n- The size of crash reports created by `gen_server`, `gen_statem` and `proc_lib`\n is limited with aid of the Kernel application variable\n `error_logger_format_depth`. The purpose is to limit the size of the messages\n sent to the `error_logger` process when processes with huge message queues or\n states crash.\n\n The crash report generated by `proc_lib` includes the new tag\n `message_queue_len`. The neighbour report also includes the new tag\n `current_stacktrace`. Finally, the neighbour report no longer includes the\n tags `messages` and `dictionary`.\n\n The new function `error_logger:get_format_depth/0` can be used to retrieve the\n value of the Kernel application variable `error_logger_format_depth`.\n\n Own Id: OTP-14417","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.3 - STDLIB Release Notes","ref":"notes.html#stdlib-3-3"},{"type":"extras","doc":"- An escript with only two lines would not work.\n\n Own Id: OTP-14098\n\n- Characters (`$char`) can be used in constant pattern expressions. They can\n also be used in types and contracts.\n\n Own Id: OTP-14103 Aux Id: ERL-313\n\n- The signatures of `erl_parse:anno_to_term/1` and `erl_parse:anno_from_term/1`\n are corrected. Using these functions no longer results in false Dialyzer\n warnings.\n\n Own Id: OTP-14131\n\n- Pretty-printing of maps is improved.\n\n Own Id: OTP-14175 Aux Id: seq13277\n\n- If any of the following functions in the `zip` module crashed, a file would be\n left open: `extract()`, `unzip()`, `create()`, or `zip()`. This has been\n corrected.\n\n A `zip` file having a \"Unix header\" could not be unpacked.\n\n Own Id: OTP-14189 Aux Id: ERL-348, ERL-349\n\n- Improve the Erlang shell's tab-completion of long names.\n\n Own Id: OTP-14200 Aux Id: ERL-352\n\n- The reference manual for `sys` had some faulty information about the\n 'get_modules' message used by processes where modules change dynamically\n during runtime. The documentation is now corrected.\n\n Own Id: OTP-14248 Aux Id: ERL-367","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Bug fixes, new features and improvements to gen_statem:\n\n A new type init_result/1 has replaced the old init_result/0, so if you used\n that old type (that was never documented) you have to change your code, which\n may be regarded as a potential incompatibility.\n\n Changing callback modes after code change did not work since the new callback\n mode was not recorded. This bug has been fixed.\n\n The event types state_timeout and \\{call,From\\} could not be generated with a\n \\{next_event,EventType,EventContent\\} action since they did not pass the\n runtime type check. This bug has now been corrected.\n\n State entry calls can now be repeated using (new) state callback returns\n \\{repeat*state,...\\}, \\{repeat_state_and_data,*\\} and repeat_state_and_data.\n\n There have been lots of code cleanup in particular regarding timer handling.\n For example is async cancel_timer now used. Error handling has also been\n cleaned up.\n\n To align with probable future changes to the rest of gen\\_\\*, terminate/3 has\n now got a fallback and code_change/4 is not mandatory.\n\n Own Id: OTP-14114\n\n- `filename:safe_relative_path/1` to sanitize a relative path has been added.\n\n Own Id: OTP-14215","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.2 - STDLIB Release Notes","ref":"notes.html#stdlib-3-2"},{"type":"extras","doc":"- When a simple_one_for_one supervisor is shutting down, and a child exits with\n an exit reason of the form \\{shutdown, Term\\}, an error report was earlier\n printed. This is now corrected.\n\n Own Id: OTP-13907 Aux Id: PR-1158, ERL-163\n\n- Allow empty list as parameter of the fun used with `dbg:fun2ms/1`.\n\n Own Id: OTP-13974","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The new behaviour gen_statem has been improved with 3 new features: the\n possibility to use old style non-proxy timeouts for gen_statem:call/2,3, state\n entry code, and state timeouts. These are backwards compatible. Minor code and\n documentation improvements has been performed including a borderline semantics\n correction of timeout zero handling.\n\n Own Id: OTP-13929 Aux Id: PR-1170, ERL-284","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-1"},{"type":"extras","doc":"- The `zip:unzip/1,2` and `zip:extract/1,2` functions have been updated to\n handle directory traversal exploits. Any element in the zip file that contains\n a path that points to a directory above the top level working directory,\n `cwd`, will instead be extracted in `cwd`. An error message is printed for any\n such element in the zip file during the unzip operation. The `keep_old_files`\n option determines if a file will overwrite a previous file with the same name\n within the zip file.\n\n Own Id: OTP-13633\n\n- Correct the contracts for `ets:match_object/1,3`.\n\n Own Id: OTP-13721 Aux Id: PR-1113\n\n- Errors in type specification and Emacs template generation for\n `gen_statem:code_change/4` has been fixed from bugs.erlang.org's Jira cases\n ERL-172 and ERL-187.\n\n Own Id: OTP-13746 Aux Id: ERL-172, ERL-187","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- gen_statem has been changed to set the callback mode for a server to what\n Module:callback_mode/0 returns. This facilitates e.g code downgrade since the\n callback mode now becomes a property of the currently active code, not of the\n server process.\n\n Exception handling from Module:init/1 has also been improved.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-13752","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 3.0.1 - STDLIB Release Notes","ref":"notes.html#stdlib-3-0-1"},{"type":"extras","doc":"- Correct a bug regarding typed records in the Erlang shell. The bug was\n introduced in OTP-19.0.\n\n Own Id: OTP-13719 Aux Id: ERL-182","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 3.0 - STDLIB Release Notes","ref":"notes.html#stdlib-3-0"},{"type":"extras","doc":"- Fix a race bug affecting `dets:open_file/2`.\n\n Own Id: OTP-13260 Aux Id: seq13002\n\n- Don't search for non-existing Map keys twice\n\n For `maps:get/2,3` and `maps:find/2`, searching for an immediate key, e.g. an\n atom, in a small map, the search was performed twice if the key did not exist.\n\n Own Id: OTP-13459\n\n- Avoid stray corner-case math errors on Solaris, e.g. an error is thrown on\n underflows in exp() and pow() when it shouldn't be.\n\n Own Id: OTP-13531\n\n- Fix linting of map key variables\n\n Map keys cannot be unbound and then used in parallel matching.\n\n Example: `#{ K := V } = #{ k := K } = M.` This is illegal if `'K'` is not\n bound.\n\n Own Id: OTP-13534 Aux Id: ERL-135\n\n- Fixed a bug in re on openbsd where sometimes re:run would return an incorrect\n result.\n\n Own Id: OTP-13602\n\n- To avoid potential timer bottleneck on supervisor restart, timer server is no\n longer used when the supervisor is unable to restart a child.\n\n Own Id: OTP-13618 Aux Id: PR-1001\n\n- The Erlang code preprocessor (`epp`) can handle file names spanning over many\n tokens. Example: `-include(\"a\" \"file\" \"name\").`.\n\n Own Id: OTP-13662 Aux Id: seq13136","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The types of The Abstract Format in the `erl_parse` module have been refined.\n\n Own Id: OTP-10292\n\n- Undocumented syntax for function specifications,\n `-spec F/A :: Domain -> Range`, has been removed (without deprecation).\n\n Using the `is_subtype(V, T)` syntax for constraints (in function\n specifications) is no longer documented, and the newer syntax `V :: T` should\n be used instead. The Erlang Parser still recognizes the `is_subtype` syntax,\n and will continue to do so for some time.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-11879\n\n- The '`random`' module has been deprecated. Use the '`rand`' module instead.\n\n Own Id: OTP-12502 Aux Id: OTP-12501\n\n- Background: In record fields with a type declaration but without an\n initializer, the Erlang parser inserted automatically the singleton type\n `'undefined'` to the list of declared types, if that value was not present\n there. That is, the record declaration:\n\n \\-record(rec, \\{f1 :: float(), f2 = 42 :: integer(), f3 ::\n some_mod:some_typ()\\}).\n\n was translated by the parser to:\n\n \\-record(rec, \\{f1 :: float() | 'undefined', f2 = 42 :: integer(), f3 ::\n some_mod:some_typ() | 'undefined'\\}).\n\n The rationale for this was that creation of a \"dummy\" `#rec{}` record should\n not result in a warning from dialyzer that, for example, the implicit\n initialization of the `#rec.f1` field violates its type declaration.\n\n Problems: This seemingly innocent action has some unforeseen consequences.\n\n For starters, there is no way for programmers to declare that e.g. only floats\n make sense for the `f1` field of `#rec{}` records when there is no \"obvious\"\n default initializer for this field. (This also affects tools like PropEr that\n use these declarations produced by the Erlang parser to generate random\n instances of records for testing purposes.)\n\n It also means that dialyzer does not warn if e.g. an\n [`is_atom/1`](`is_atom/1`) test or something more exotic like an\n [`atom_to_list/1`](`atom_to_list/1`) call is performed on the value of the\n `f1` field.\n\n Similarly, there is no way to extend dialyzer to warn if it finds record\n constructions where `f1` is not initialized to some float.\n\n Last but not least, it is semantically problematic when the type of the field\n is an opaque type: creating a union of an opaque and a structured type is very\n problematic for analysis because it fundamentally breaks the opacity of the\n term at that point.\n\n Change: To solve these problems the parser will not automatically insert the\n `'undefined'` value anymore; instead the user has the option to choose the\n places where this value makes sense (for the field) and where it does not and\n insert the `| 'undefined'` there manually.\n\n Consequences of this change: This change means that dialyzer will issue a\n warning for all places where records with uninitialized fields are created and\n those fields have a declared type that is incompatible with `'undefined'`\n (e.g. `t:float/0`). This warning can be suppressed easily by adding\n `| 'undefined'` to the type of this field. This also adds documentation that\n the user really intends to create records where this field is uninitialized.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-12719\n\n- Remove deprecated functions in the modules `erl_scan` and `erl_parse`.\n\n Own Id: OTP-12861\n\n- The pre-processor can now expand the ?FUNCTION_NAME and ?FUNCTION_ARITY\n macros.\n\n Own Id: OTP-13059\n\n- A new behaviour `gen_statem` has been implemented. It has been thoroughly\n reviewed, is stable enough to be used by at least two heavy OTP applications,\n and is here to stay. But depending on user feedback, we do not expect but\n might find it necessary to make minor not backwards compatible changes into\n OTP-20.0, so its state can be designated as \"not quite experimental\"...\n\n The `gen_statem` behaviour is intended to replace `gen_fsm` for new code. It\n has the same features and add some really useful:\n\n - State code is gathered\n - The state can be any term\n - Events can be postponed\n - Events can be self generated\n - A reply can be sent from a later state\n - There can be multiple sys traceable replies\n\n The callback model(s) for `gen_statem` differs from the one for `gen_fsm`, but\n it is still fairly easy to rewrite from `gen_fsm` to `gen_statem`.\n\n Own Id: OTP-13065 Aux Id: PR-960\n\n- Optimize binary:split/2 and binary:split/3 with native BIF implementation.\n\n Own Id: OTP-13082\n\n- Background: The types of record fields have since R12B been put in a separate\n form by `epp:parse_file()`, leaving the record declaration form untyped. The\n separate form, however, does not follow the syntax of type declarations, and\n parse transforms inspecting `-type()` attributes need to know about the\n special syntax. Since the compiler stores the return value of\n `epp:parse_file()` as debug information in the abstract code chunk (`\"Abst\"`\n or `abstract_code`), tools too need to know about the special syntax, if they\n inspect `-type()` attributes in abstract code.\n\n Change: No separate type form is created by `epp:parse_file()`, but the type\n information is kept in the record fields. This means that all parse transforms\n and all tools inspecting `-record()` declarations need to recognize\n `{typed_record_field, Field, Type}`.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-13148\n\n- Unsized fields of the type `bytes` in binary generators are now forbidden.\n (The other ways of writing unsized fields, such as `binary`, are already\n forbidden.)\n\n Own Id: OTP-13152\n\n- The type `t:map/0` is built-in, and cannot be redefined.\n\n Own Id: OTP-13153\n\n- Let `dets:open_file()` exit with a `badarg` message if given a raw file name\n (a binary).\n\n Own Id: OTP-13229 Aux Id: ERL-55\n\n- Add `filename:basedir/2,3`\n\n basedir returns suitable path(s) for 'user_cache', 'user_config', 'user_data',\n 'user_log', 'site_config' and 'site_data'. On linux and linux like systems the\n paths will respect the XDG environment variables.\n\n Own Id: OTP-13392\n\n- There are new preprocessor directives `-error(Term)` and `-warning(Term)` to\n cause a compilation error or a compilation warning, respectively.\n\n Own Id: OTP-13476\n\n- Optimize `'++'` operator and `lists:append/2` by using a single pass to build\n a new list while checking for properness.\n\n Own Id: OTP-13487\n\n- Add `maps:update_with/3,4` and `maps:take/2`\n\n Own Id: OTP-13522 Aux Id: PR-1025\n\n- `lists:join/2` has been added. Similar to `string:join/2` but works with\n arbitrary lists.\n\n Own Id: OTP-13523\n\n- Obfuscate asserts to make Dialyzer shut up.\n\n Own Id: OTP-13524 Aux Id: PR-1002\n\n- Supervisors now explicitly add their callback module in the return from\n sys:get_status/1,2. This is to simplify custom supervisor implementations. The\n Misc part of the return value from sys:get_status/1,2 for a supervisor is now:\n\n \\[\\{data, [\\{\"State\", State\\}]\\},\\{supervisor,\\[\\{\"Callback\",Module\\}]\\}]\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-13619 Aux Id: PR-1000\n\n- Relax translation of initial calls in `proc_lib`, i.e. remove the restriction\n to only do the translation for `gen_server` and `gen_fsm`. This enables user\n defined `gen` based generic callback modules to be displayed nicely in `c:i()`\n and observer.\n\n Own Id: OTP-13623\n\n- The function `queue:lait/1` (misspelling of `liat/1`) is now deprecated.\n\n Own Id: OTP-13658","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 2.8.0.1 - STDLIB Release Notes","ref":"notes.html#stdlib-2-8-0-1"},{"type":"extras","doc":"- List subtraction (The `--` operator) will now yield properly on large inputs.\n\n Own Id: OTP-15371","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 2.8 - STDLIB Release Notes","ref":"notes.html#stdlib-2-8"},{"type":"extras","doc":"- Fix evaluation in matching of bound map key variables in the interpreter.\n\n Prior to this patch, the following code would not evaluate:\n `X = key,(fun(#{X := value}) -> true end)(#{X => value})`\n\n Own Id: OTP-13218\n\n- Fix `erl_eval` not using non-local function handler.\n\n Own Id: OTP-13228 Aux Id: ERL-32\n\n- The Erlang Code Linter no longer crashes if there is a `-deprecated()`\n attribute but no `-module()` declaration.\n\n Own Id: OTP-13230 Aux Id: ERL-62\n\n- The timestamp in the result returned by `dets:info(Tab, safe_fixed)` was\n unintentionally broken as a result of the time API rewrites in OTP 18.0. This\n has now been fixed.\n\n Own Id: OTP-13239 Aux Id: OTP-11997\n\n- A rare race condition in `beam_lib` when using encrypted abstract format has\n been eliminated.\n\n Own Id: OTP-13278\n\n- Improved maps:with/2 and maps:without/2 algorithms\n\n The new implementation speeds up the execution significantly for all sizes of\n input.\n\n Own Id: OTP-13376","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Time warp safety improvements.\n\n Introduced the options `monotonic_timestamp`, and `strict_monotonic_timestamp`\n to the trace, sequential trace, and system profile functionality. This since\n the already existing `timestamp` option is not time warp safe.\n\n Introduced the option `safe_fixed_monotonic_time` to `ets:info/2` and\n `dets:info/2`. This since the already existing `safe_fixed` option is not time\n warp safe.\n\n Own Id: OTP-13222 Aux Id: OTP-11997\n\n- In the shell Ctrl+W (delete word) will no longer consider \".\" as being part of\n a word.\n\n Own Id: OTP-13281","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 2.7 - STDLIB Release Notes","ref":"notes.html#stdlib-2-7"},{"type":"extras","doc":"- The Erlang Pretty Printer uses `::` for function type constraints.\n\n A bug concerning pretty printing of annotated type union elements in map pair\n types has been fixed.\n\n Some minor issues regarding the documentation of types and specs have been\n corrected.\n\n Own Id: OTP-13084\n\n- The shell command `rp` prints strings as lists of integers if pretty printing\n of lists is set to `false`.\n\n Own Id: OTP-13145\n\n- The shell would crash if a bit syntax expression with conflicting types were\n given (e.g. if a field type was given as '`integer-binary`'). (Thanks to\n Aleksei Magusev for reporting this bug.)\n\n Own Id: OTP-13157\n\n- The `rand:export_seed/0` would never return '`undefined`' even if no seed has\n previously been created. Fixed to return '`undefined`' if there is no seed in\n the process dictionary.\n\n Own Id: OTP-13162","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add support for the Delete, Home and End keys in the Erlang shell.\n\n Own Id: OTP-13032\n\n- `beam_lib:all_chunks/1` and `beam_lib:build_module/1` have been documented.\n\n Own Id: OTP-13063","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 2.6 - STDLIB Release Notes","ref":"notes.html#stdlib-2-6"},{"type":"extras","doc":"- In OTP 18.0, `qlc` does not handle syntax errors well. This bug has been\n fixed.\n\n Own Id: OTP-12946\n\n- Optimize zip:unzip/2 when uncompressing to memory.\n\n Own Id: OTP-12950\n\n- The STDLIB reference manual is updated to show correct information about the\n return value of `gen_fsm:reply/2`.\n\n Own Id: OTP-12973\n\n- re:split2,3 and re:replace/3,4 now correctly handles pre-compiled patterns\n that have been compiled using the '`unicode`' option.\n\n Own Id: OTP-12977\n\n- Export `shell:catch_exception/1` as documented.\n\n Own Id: OTP-12990","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- A mechanism for limiting the amount of text that the built-in error logger\n events will produce has been introduced. It is useful for limiting both the\n size of log files and the CPU time used to produce them.\n\n This mechanism is experimental in the sense that it may be changed if it turns\n out that it does not solve the problem it is supposed to solve. In that case,\n there may be backward incompatible improvements to this mechanism.\n\n See the documentation for the config parameter `error_logger_format_depth` in\n the Kernel application for information about how to turn on this feature.\n\n Own Id: OTP-12864","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 2.5 - STDLIB Release Notes","ref":"notes.html#stdlib-2-5"},{"type":"extras","doc":"- Fix handling of single dot in filename:join/2\n\n The reference manual says that filename:join(A,B) is equivalent to\n filename:join(\\[A,B]). In some rare cases this turns out not to be true. For\n example:\n\n `filename:join(\"/a/.\",\"b\") -> \"/a/./b\"` vs\n `filename:join([\"/a/.\",\"b\"]) -> \"/a/b\"`.\n\n This has been corrected. A single dot is now only kept if it occurs at the\n very beginning or the very end of the resulting path.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-12158\n\n- The undocumented option `generic_debug` for `gen_server` has been removed.\n\n Own Id: OTP-12183\n\n- erl_lint:icrt_export/4 has been rewritten to make the code really follow the\n scoping rules of Erlang, and not just in most situations by accident.\n\n Own Id: OTP-12186\n\n- Add 'trim_all' option to binary:split/3\n\n This option can be set to remove \\_ALL\\_ empty parts of the result of a call\n to binary:split/3.\n\n Own Id: OTP-12301\n\n- Correct orddict(3) regarding evaluation order of `fold()` and `t:map/0`.\n\n Own Id: OTP-12651 Aux Id: seq12832\n\n- Correct `maps` module error exceptions\n\n Bad input to maps module function will now yield the following exceptions:\n\n - \\{badmap, NotMap\\}, or\n - badarg.\n\n Own Id: OTP-12657\n\n- It is now possible to paste text in JCL mode (using Ctrl-Y) that has been\n copied in the previous shell session. Also a bug that caused the JCL mode to\n crash when pasting text has been fixed.\n\n Own Id: OTP-12673\n\n- Add `uptime()` shell command.\n\n Own Id: OTP-12752\n\n- Cache nowarn_bif_clash functions in erl_lint.\n\n This patch stores nowarn_bif_clash in the lint record. By using erlc\n +'\\{eprof,lint_module\\}' when compiling the erlang parser, we noticed the time\n spent on nowarn_function/2 reduced from 30% to 0.01%.\n\n Own Id: OTP-12754\n\n- Optimize the Erlang Code Linter by using the cached filename information.\n\n Own Id: OTP-12772\n\n- If a child of a simple_one_for_one returns ignore from its start function no\n longer store the child for any restart type. It is not possible to restart or\n delete the child because the supervisor is a simple_one_for_one.\n\n Own Id: OTP-12793\n\n- Make `ets:file2tab` preserve enabled `read_concurrency` and\n `write_concurrency` options for tables.\n\n Own Id: OTP-12814\n\n- There are many cases where user code needs to be able to distinguish between a\n socket that was closed normally and one that was aborted. Setting the option\n \\{show_econnreset, true\\} enables the user to receive ECONNRESET errors on\n both active and passive sockets.\n\n Own Id: OTP-12841","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Allow maps for supervisor flags and child specs\n\n Earlier, supervisor flags and child specs were given as tuples. While this is\n kept for backwards compatibility, it is now also allowed to give these\n parameters as maps, see [sup_flags](`m:supervisor#sup_flags`) and\n [child_spec](`m:supervisor#child_spec`).\n\n Own Id: OTP-11043\n\n- A new system message, `terminate`, is added. This can be sent with\n `sys:terminate/2,3`. If the receiving process handles system messages properly\n it will terminate shortly after receiving this message.\n\n The new function `proc_lib:stop/1,3` utilizes this new system message and\n monitors the receiving process in order to facilitate a synchronous stop\n mechanism for 'special processes'.\n\n `proc_lib:stop/1,3` is used by the following functions:\n\n - `gen_server:stop/1,3` (new)\n - `gen_fsm:stop/1,3` (new)\n - `gen_event:stop/1,3` (modified to be synchronous)\n - `wx_object:stop/1,3` (new)\n\n Own Id: OTP-11173 Aux Id: seq12353\n\n- Remove the `pg` module, which has been deprecated through OTP-17, is now\n removed from the STDLIB application. This module has been marked experimental\n for more than 15 years, and has largely been superseded by the `pg2` module\n from the Kernel application.\n\n Own Id: OTP-11907\n\n- New BIF: `erlang:get_keys/0`, lists all keys associated with the process\n dictionary. Note: `erlang:get_keys/0` is auto-imported.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-12151 Aux Id: seq12521\n\n- Add three new functions to `io_lib`\\-- `scan_format/2`, `unscan_format/1`, and\n `build_text/1`\\-- which expose the parsed form of the format control sequences\n to make it possible to easily modify or filter the input to `io_lib:format/2`.\n This can e.g. be used in order to replace unbounded-size control sequences\n like `~w` or `~p` with corresponding depth-limited `~W` and `~P` before doing\n the actual formatting.\n\n Own Id: OTP-12167\n\n- Introduce the `erl_anno` module, an abstraction of the second element of\n tokens and tuples in the abstract format.\n\n Own Id: OTP-12195\n\n- Support variables as Map keys in expressions and patterns\n\n Erlang will accept any expression as keys in Map expressions and it will\n accept literals or bound variables as keys in Map patterns.\n\n Own Id: OTP-12218\n\n- The last traces of Mnemosyne Rules have been removed.\n\n Own Id: OTP-12257\n\n- Properly support maps in match_specs\n\n Own Id: OTP-12270\n\n- New function `ets:take/2`. Works the same as `ets:delete/2` but also returns\n the deleted object(s).\n\n Own Id: OTP-12309\n\n- `string:tokens/2` is somewhat faster, especially if the list of separators\n only contains one separator character.\n\n Own Id: OTP-12422 Aux Id: seq12774\n\n- The documentation of the Abstract Format (in the ERTS User's Guide) has been\n updated with types and specification. (Thanks to Anthony Ramine.)\n\n The explicit representation of parentheses used in types of the abstract\n format has been removed. Instead the new functions\n `erl_parse:type_inop_prec()` and `erl_parse:type_preop_prec()` can be used for\n inserting parentheses where needed.\n\n Own Id: OTP-12492\n\n- Prevent zip:zip_open/\\[12] from leaking file descriptors if parent process\n dies.\n\n Own Id: OTP-12566\n\n- Add a new random number generator, see `rand` module. It have better\n characteristics and an improved interface.\n\n Own Id: OTP-12586 Aux Id: OTP-12501, OTP-12502\n\n- `filename:split/1` when given an empty binary will now return an empty list,\n to make it consistent with return value when given an empty list.\n\n Own Id: OTP-12716\n\n- Add `sync` option to `ets:tab2file/3`.\n\n Own Id: OTP-12737 Aux Id: seq12805\n\n- Add functions `gb_sets:iterator_from()` and `gb_trees:iterator_from()`.\n (Thanks to Kirill Kinduk.)\n\n Own Id: OTP-12742\n\n- Add `maps:filter/2` to maps module.\n\n Own Id: OTP-12745\n\n- Change some internal data structures to Maps in order to speed up compilation\n time. Measured speed up is around 10%-15%.\n\n Own Id: OTP-12774\n\n- Update `orddict` to use parameterized types and specs. (Thanks to UENISHI\n Kota.)\n\n Own Id: OTP-12785\n\n- The assert macros in `eunit` has been moved out to\n `stdlib/include/assert.hrl`. This files get included by `eunit.hrl`. Thus,\n nothing changes for eunit users, but the asserts can now also be included\n separately.\n\n Own Id: OTP-12808","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 2.4 - STDLIB Release Notes","ref":"notes.html#stdlib-2-4"},{"type":"extras","doc":"- Behaviour of character types \\\\d, \\\\w and \\\\s has always been to not match\n characters with value above 255, not 128, i.e. they are limited to ISO-Latin-1\n and not ASCII\n\n Own Id: OTP-12521","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- c:m/1 now displays the module's MD5 sum.\n\n Own Id: OTP-12500\n\n- Make ets:i/1 handle binary input from IO server.\n\n Own Id: OTP-12550","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 2.3 - STDLIB Release Notes","ref":"notes.html#stdlib-2-3"},{"type":"extras","doc":"- The documentation of string:tokens/2 now explicitly specifies that adjacent\n separator characters do not give any empty strings in the resulting list of\n tokens.\n\n Own Id: OTP-12036\n\n- Fix broken deprecation warnings in ssh application\n\n Own Id: OTP-12187\n\n- Maps: Properly align union typed assoc values in documentation\n\n Own Id: OTP-12190\n\n- Fix filelib:wildcard/2 when 'Cwd' ends with a dot\n\n Own Id: OTP-12212\n\n- Allow `Name/Arity` syntax in maps values inside attributes.\n\n Own Id: OTP-12213\n\n- Fix edlin to correctly save text killed with ctrl-u. Prior to this fix,\n entering text into the Erlang shell and then killing it with ctrl-u followed\n by yanking it back with ctrl-y would result in the yanked text being the\n reverse of the original killed text.\n\n Own Id: OTP-12224\n\n- If a callback function was terminated with exit/1, there would be no stack\n trace in the ERROR REPORT produced by gen_server. This has been corrected.\n\n To keep the backwards compatibility, the actual exit reason for the process is\n not changed.\n\n Own Id: OTP-12263 Aux Id: seq12733\n\n- Warnings produced by `ms_transform` could point out the wrong line number.\n\n Own Id: OTP-12264","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Supports tar file creation on other media than file systems mounted on the\n local machine.\n\n The `erl_tar` api is extended with `erl_tar:init/3` that enables usage of user\n provided media storage routines. A ssh-specific set of such routines is hidden\n in the new function `ssh_sftp:open_tar/3` to simplify creating a tar archive\n on a remote ssh server.\n\n A chunked file reading option is added to `erl_tar:add/3,4` to save memory on\n e.g small embedded systems. The size of the slices read from a file in that\n case can be specified.\n\n Own Id: OTP-12180 Aux Id: seq12715\n\n- I/O requests are optimized for long message queues in the calling process.\n\n Own Id: OTP-12315","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 2.2 - STDLIB Release Notes","ref":"notes.html#stdlib-2-2"},{"type":"extras","doc":"- The type spec of the FormFunc argument to sys:handle_debug/4 was erroneously\n pointing to dbg_fun(). This is now corrected and the new type is format_fun().\n\n Own Id: OTP-11800\n\n- Behaviors such as gen_fsm and gen_server should always invoke format_status/2\n before printing the state to the logs.\n\n Own Id: OTP-11967\n\n- The documentation of `dets:insert_new/2` has been corrected. (Thanks to Alexei\n Sholik for reporting the bug.)\n\n Own Id: OTP-12024\n\n- Printing a term with io_lib:format and control sequence w, precision P and\n field width F, where F = printed length of the term, an exception would be raised.\n\n These two problems are now corrected.\n\n Own Id: OTP-12041\n\n- The documentation of `maps:values/1` has been corrected.\n\n Own Id: OTP-12055\n\n- Expand shell functions in map expressions.\n\n Own Id: OTP-12063","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add maps:with/2\n\n Own Id: OTP-12137","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 2.1.1 - STDLIB Release Notes","ref":"notes.html#stdlib-2-1-1"},{"type":"extras","doc":"- OTP-11850 fixed filelib:wildcard/1 to work with broken symlinks. This\n correction, however, introduced problems since symlinks were no longer\n followed for functions like filelib:ensure_dir/1, filelib:is_dir/1,\n filelib:file_size/1, etc. This is now corrected.\n\n Own Id: OTP-12054 Aux Id: seq12660","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 2.1 - STDLIB Release Notes","ref":"notes.html#stdlib-2-1"},{"type":"extras","doc":"- `filelib:wildcard(\"broken_symlink\")` would return an empty list if\n \"broken_symlink\" was a symlink that did not point to an existing file.\n\n Own Id: OTP-11850 Aux Id: seq12571\n\n- `erl_tar` can now handle files names that contain Unicode characters. See\n \"UNICODE SUPPORT\" in the documentation for `erl_tar`.\n\n When creating a tar file, `erl_tar` would sometime write a too short end of\n tape marker. GNU tar would correctly extract files from such tar file, but\n would complain about \"A lone zero block at...\".\n\n Own Id: OTP-11854\n\n- When redefining and exporting the type `t:map/0` the Erlang Code Linter\n (`erl_lint`) erroneously emitted an error. This bug has been fixed.\n\n Own Id: OTP-11872\n\n- Fix evaluation of map updates in the debugger and erl_eval\n\n Reported-by: José Valim\n\n Own Id: OTP-11922","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The following native functions now bump an appropriate amount of reductions\n and yield when out of reductions:\n\n - `erlang:binary_to_list/1`\n - `erlang:binary_to_list/3`\n - `erlang:bitstring_to_list/1`\n - `erlang:list_to_binary/1`\n - `erlang:iolist_to_binary/1`\n - `erlang:list_to_bitstring/1`\n - `binary:list_to_bin/1`\n\n Characteristics impact:\n\n - **Performance** - The functions converting from lists got a performance loss\n for very small lists, and a performance gain for very large lists.\n\n - **Priority** - Previously a process executing one of these functions\n effectively got an unfair priority boost. This priority boost depended on\n the input size. The larger the input was, the larger the priority boost got.\n This unfair priority boost is now lost.\n\n Own Id: OTP-11888\n\n- Add `maps:get/3` to maps module. The function will return the supplied default\n value if the key does not exist in the map.\n\n Own Id: OTP-11951","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 2.0 - STDLIB Release Notes","ref":"notes.html#stdlib-2-0"},{"type":"extras","doc":"- The option dupnames did not work as intended in re. When looking for names\n with \\{capture, \\[Name, ...]\\}, re:run returned a random instance of the match\n for that name, instead of the leftmost matching instance, which was what the\n documentation stated. This is now corrected to adhere to the documentation.\n The option \\{capture,all_names\\} along with a re:inspect/2 function is also\n added to further help in using named subpatterns.\n\n Own Id: OTP-11205\n\n- If option 'binary' was set for standard_input, then c:i() would hang if the\n output was more than one page long - i.e. then input after \"(c)ontinue (q)uit\n -->\" could not be read. This has been corrected. (Thanks to José Valim)\n\n Own Id: OTP-11589\n\n- stdlib/lists: Add function droplast/1 This functions drops the last element of\n a non-empty list. lists:last/1 and lists:droplast/1 are the dual of hd/1 and\n tl/1 but for the end of a list. (Thanks to Hans Svensson)\n\n Own Id: OTP-11677\n\n- Allow all auto imports to be suppressed at once. Introducing the\n no_auto_import attribute: -compile(no_auto_import). Useful for code generation\n tools that always use the qualified function names and want to avoid the auto\n imported functions clashing with local ones. (Thanks to José Valim.)\n\n Own Id: OTP-11682\n\n- supervisor_bridge does no longer report normal termination of children. The\n reason is that in some cases, for instance when the restart strategy is\n simple_one_for_one, the log could be completely overloaded with reports about\n normally terminating processes. (Thanks to Artem Ocheredko)\n\n Own Id: OTP-11685\n\n- The type annotations for alternative registries using the \\{via, Module,\n Name\\} syntax for sup_name() and sup_ref() in the supervisor module are now\n consistent with the documentation. Dialyzer should no longer complain about\n valid supervisor:start_link() and supervisor:start_child() calls. (Thanks to\n Caleb Helbling.)\n\n Own Id: OTP-11707\n\n- Two Dets bugs have been fixed. When trying to open a short file that is not a\n Dets file, the file was deleted even with just read access. Calling\n `dets:is_dets_file/1` with a file that is not a Dets file, a file descriptor\n was left open. (Thanks to Håkan Mattsson for reporting the bugs.)\n\n Own Id: OTP-11709\n\n- Fix race bug in `ets:all`. Concurrent creation of tables could cause other\n tables to not be included in the result. (Thanks to Florian Schintke for bug\n report)\n\n Own Id: OTP-11726\n\n- erl_eval now properly evaluates '=='/2 when it is used in guards. (Thanks to\n José Valim)\n\n Own Id: OTP-11747\n\n- Calls to proplists:get_value/3 are replaced by the faster lists:keyfind/3 in\n io_lib_pretty. Elements in the list are always 2-tuples. (Thanks to Andrew\n Thompson)\n\n Own Id: OTP-11752\n\n- A qlc bug where filters were erroneously optimized away has been fixed. Thanks\n to Sam Bobroff for reporting the bug.\n\n Own Id: OTP-11758\n\n- A number of compiler errors where unusual or nonsensical code would crash the\n compiler have been reported by Ulf Norell and corrected by Anthony Ramine.\n\n Own Id: OTP-11770\n\n- Since Erlang/OTP R16B the Erlang Core Linter (`erl_lint`) has not emitted\n errors when built-in types were re-defined. This bug has been fixed. (Thanks\n to Roberto Aloi.)\n\n Own Id: OTP-11772\n\n- The functions `sys:get_state/1,2` and `sys:replace_state/2,3` are fixed so\n they can now be run while the process is sys suspended. To accomplish this,\n the new callbacks `Mod:system_get_state/1` and `Mod:system_replace_state/2`\n are added, which are also implemented by the generic behaviours `gen_server`,\n `gen_event` and `gen_fsm`.\n\n The potential incompatibility refers to:\n\n - The previous behaviour of intercepting the system message and passing a\n tuple of size 2 as the last argument to `sys:handle_system_msg/6` is no\n longer supported.\n - The error handling when `StateFun` in `sys:replace_state/2,3` fails is\n changed from being totally silent to possibly (if the callback module does\n not catch) throw an exception in the client process.\n\n (Thanks to James Fish and Steve Vinoski)\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-11817","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Options to set match_limit and match_limit_recursion are added to re:run. The\n option report_errors is also added to get more information when re:run fails\n due to limits or compilation errors.\n\n Own Id: OTP-10285\n\n- The pre-defined types `array/0`, `dict/0`, `digraph/0`, `gb_set/0`,\n `gb_tree/0`, `queue/0`, `set/0`, and `tid/0` have been deprecated. They will\n be removed in Erlang/OTP 18.0.\n\n Instead the types [`array:array/0`](`t:array:array/0`),\n [`dict:dict/0`](`t:dict:dict/0`), [`digraph:graph/0`](`t:digraph:graph/0`),\n `gb_set:set/0`, `gb_tree:tree/0`, [`queue:queue/0`](`t:queue:queue/0`),\n [`sets:set/0`](`t:sets:set/0`), and [`ets:tid/0`](`t:ets:tid/0`) can be used.\n (Note: it has always been necessary to use [`ets:tid/0`](`t:ets:tid/0`).)\n\n It is allowed in Erlang/OTP 17.0 to locally re-define the types `array/0`,\n `dict/0`, and so on.\n\n New types [`array:array/1`](`t:array:array/1`),\n [`dict:dict/2`](`t:dict:dict/2`), [`gb_sets:set/1`](`t:gb_sets:set/1`),\n [`gb_trees:tree/2`](`t:gb_trees:tree/2`),\n [`queue:queue/1`](`t:queue:queue/1`), and [`sets:set/1`](`t:sets:set/1`) have\n been added.\n\n A compiler option, `nowarn_deprecated_type`, has been introduced. By including\n the attribute\n\n `-compile(nowarn_deprecated_type).`\n\n in an Erlang source file, warnings about deprecated types can be avoided in\n Erlang/OTP 17.0.\n\n The option can also be given as a compiler flag:\n\n `erlc +nowarn_deprecated_type file.erl`\n\n Own Id: OTP-10342\n\n- Calls to erlang:open_port/2 with 'spawn' are updated to handle space in the\n command path.\n\n Own Id: OTP-10842\n\n- Dialyzer's `unmatched_return` warnings have been corrected.\n\n Own Id: OTP-10908\n\n- Forbid unsized fields in patterns of binary generators and simplified\n v3_core's translation of bit string generators. (Thanks to Anthony Ramine.)\n\n Own Id: OTP-11186\n\n- The version of the PCRE library Used by Erlang's re module is raised to 8.33\n from 7.6. This means, among other things, better Unicode and Unicode Character\n Properties support. New options connected to PCRE 8.33 are also added to the\n re module (ucd, notempty_atstart, no_start_optimize). PCRE has extended the\n regular expression syntax between 7.6 and 8.33, why this imposes a potential\n incompatibility. Only very complicated regular expressions may be affected,\n but if you know you are using obscure features, please test run your regular\n expressions and verify that their behavior has not changed.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-11204\n\n- Added dict:is_empty/1 and orddict:is_empty/1. (Thanks to Magnus Henoch.)\n\n Own Id: OTP-11353\n\n- A call to either the [`garbage_collect/1`](`garbage_collect/1`) BIF or the\n [`check_process_code/2`](`check_process_code/2`) BIF may trigger garbage\n collection of another processes than the process calling the BIF. The previous\n implementations performed these kinds of garbage collections without\n considering the internal state of the process being garbage collected. In\n order to be able to more easily and more efficiently implement yielding native\n code, these types of garbage collections have been rewritten. A garbage\n collection like this is now triggered by an asynchronous request signal, the\n actual garbage collection is performed by the process being garbage collected\n itself, and finalized by a reply signal to the process issuing the request.\n Using this approach processes can disable garbage collection and yield without\n having to set up the heap in a state that can be garbage collected.\n\n The [`garbage_collect/2`](`erlang:garbage_collect/2`), and\n [`check_process_code/3`](`erlang:check_process_code/3`) BIFs have been\n introduced. Both taking an option list as last argument. Using these, one can\n issue asynchronous requests.\n\n `code:purge/1` and `code:soft_purge/1` have been rewritten to utilize\n asynchronous `check_process_code` requests in order to parallelize work.\n\n Characteristics impact: A call to the\n [`garbage_collect/1`](`garbage_collect/1`) BIF or the\n [`check_process_code/2`](`check_process_code/2`) BIF will normally take longer\n time to complete while the system as a whole wont be as much negatively\n effected by the operation as before. A call to `code:purge/1` and\n `code:soft_purge/1` may complete faster or slower depending on the state of\n the system while the system as a whole wont be as much negatively effected by\n the operation as before.\n\n Own Id: OTP-11388 Aux Id: OTP-11535, OTP-11648\n\n- Improve the documentation of the supervisor's `via` reference. (Thanks to\n MaximMinin.)\n\n Own Id: OTP-11399\n\n- `orddict:from_list/1` now uses the optimized sort routines in the `lists`\n module instead of (essentially) an insertion sort. Depending on the input\n data, the speed of the new `from_list/1` is anything from slightly faster up\n to several orders of magnitude faster than the old `from_list/1`.\n\n (Thanks to Steve Vinoski.)\n\n Own Id: OTP-11552\n\n- EEP43: New data type - Maps\n\n With Maps you may for instance:\n\n - \\_\\_\\_\\_ - `M0 = #{ a => 1, b => 2}, % create associations`\n\n - \\_\\_\\_\\_ - `M1 = M0#{ a := 10 }, % update values`\n\n - \\_\\_\\_\\_ - `M2 = M1#{ \"hi\" => \"hello\"}, % add new associations`\n\n - \\_\\_\\_\\_ - `#{ \"hi\" := V1, a := V2, b := V3} = M2. % match keys with values`\n\n For information on how to use Maps please see Map Expressions in the\n [Reference Manual](`e:system:expressions.md#map-expressions`).\n\n The current implementation is without the following features:\n\n - \\_\\_\\_\\_ - No variable keys\n\n - \\_\\_\\_\\_ - No single value access\n\n - \\_\\_\\_\\_ - No map comprehensions\n\n Note that Maps is _experimental_ during OTP 17.0.\n\n Own Id: OTP-11616\n\n- When tab completing the erlang shell now expands zero-arity functions all the\n way to closing parenthesis, unless there is another function with the same\n name and a different arity. (Thanks to Pierre Fenoll.)\n\n Own Id: OTP-11684\n\n- The Erlang Code Preprocessor (`epp`) could loop when encountering a circular\n macro definition in an included file. This bug has been fixed.\n\n Thanks to Maruthavanan Subbarayan for reporting the bug, and to Richard\n Carlsson for providing a bug fix.\n\n Own Id: OTP-11728\n\n- The Erlang Code Linter (`erl_lint`) has since Erlang/OTP R13B emitted warnings\n whenever any of the types `t:arity/0`, `t:bitstring/0`, `t:iodata/0`, or\n `t:boolean/0` were re-defined. Now errors are emitted instead.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-11771\n\n- The `encoding` option of `erl_parse:abstract/2` has been extended to include\n `none` and a callback function (a predicate).\n\n Own Id: OTP-11807\n\n- Export zip option types to allow referal from other modules.\n\n Thanks to Pierre Fenoll and Håkan Mattson\n\n Own Id: OTP-11828\n\n- The module `pg` has been deprecated and will be removed in Erlang/OTP 18.\n\n Own Id: OTP-11840","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.19.4 - STDLIB Release Notes","ref":"notes.html#stdlib-1-19-4"},{"type":"extras","doc":"- Fix typo in gen_server.erl. Thanks to Brian L. Troutwine.\n\n Own Id: OTP-11398\n\n- Spec for atan2 should be atan2(Y, X), not atan2(X, Y). Thanks to Ary\n Borenszweig.\n\n Own Id: OTP-11465","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add XML marker for regexp syntax. Thanks to Håkan Mattson.\n\n Own Id: OTP-11442","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.19.3 - STDLIB Release Notes","ref":"notes.html#stdlib-1-19-3"},{"type":"extras","doc":"- The functions `dets:foldl/3`, `dets:foldr/3`, and `dets:traverse/2` did not\n release the table after having traversed the table to the end. The bug was\n introduced in R16B. (Thanks to Manuel Duran Aguete.)\n\n Own Id: OTP-11245\n\n- If the `fun M:F/A` construct was used erroneously the linter could crash.\n (Thanks to Mikhail Sobolev.)\n\n Own Id: OTP-11254\n\n- The specifications of `io_lib:fread/2,3` have been corrected. (Thanks to Chris\n King and Kostis Sagonas for pinpointing the bug.)\n\n Own Id: OTP-11261","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Fixed type typo in gen_server.\n\n Own Id: OTP-11200\n\n- Update type specs in filelib and io_prompt. Thanks to Jose Valim.\n\n Own Id: OTP-11208\n\n- Fix typo in abcast() function comment. Thanks to Johannes Weissl.\n\n Own Id: OTP-11219\n\n- Make edlin understand a few important control keys. Thanks to Stefan\n Zegenhagen.\n\n Own Id: OTP-11251\n\n- Export the edge/0 type from the digraph module. Thanks to Alex Ronne Petersen.\n\n Own Id: OTP-11266\n\n- Fix variable usage tracking in erl_lint and fixed unsafe variable tracking in\n try expressions. Thanks to Anthony Ramine.\n\n Own Id: OTP-11268","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.19.2 - STDLIB Release Notes","ref":"notes.html#stdlib-1-19-2"},{"type":"extras","doc":"- The Erlang scanner no longer accepts floating point numbers in the input\n string.\n\n Own Id: OTP-10990\n\n- When converting a faulty binary to a list with unicode:characters_to_list, the\n error return value could contain a faulty \"rest\", i.e. the io_list of\n characters that could not be converted was wrong. This happened only if input\n was a sub binary and conversion was from utf8. This is now corrected.\n\n Own Id: OTP-11080\n\n- The type `hook_function()` has been corrected in `erl_pp`, the Erlang Pretty\n Printer.\n\n The printing of invalid forms, e.g. record field types, has also been fixed.\n It has been broken since R16B.\n\n (Thanks to Tomáš Janoušek.)\n\n Own Id: OTP-11100\n\n- Fix receive support in erl_eval with a BEAM module. Thanks to Anthony Ramine.\n\n Own Id: OTP-11137","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Delete obsolete note about simple-one-for-one supervisor. Thanks to Magnus\n Henoch.\n\n Own Id: OTP-10938\n\n- When selecting encoding of a script written in Erlang (`escript`) the optional\n directive on the second line is now recognized.\n\n Own Id: OTP-10951\n\n- The function `erl_parse:abstract/2` has been documented.\n\n Own Id: OTP-10992\n\n- Integrate elliptic curve contribution from Andreas Schultz\n\n In order to be able to support elliptic curve cipher suites in SSL/TLS,\n additions to handle elliptic curve infrastructure has been added to public_key\n and crypto.\n\n This also has resulted in a rewrite of the crypto API to gain consistency and\n remove unnecessary overhead. All OTP applications using crypto has been\n updated to use the new API.\n\n Impact: Elliptic curve cryptography (ECC) offers equivalent security with\n smaller key sizes than other public key algorithms. Smaller key sizes result\n in savings for power, memory, bandwidth, and computational cost that make ECC\n especially attractive for constrained environments.\n\n Own Id: OTP-11009\n\n- Added sys:get_state/1,2 and sys:replace_state/2,3. Thanks to Steve Vinoski.\n\n Own Id: OTP-11013\n\n- Optimizations to gen mechanism. Thanks to Loïc Hoguin.\n\n Own Id: OTP-11025\n\n- Optimizations to gen.erl. Thanks to Loïc Hoguin.\n\n Own Id: OTP-11035\n\n- Use erlang:demonitor(Ref, \\[flush]) where applicable. Thanks to Loïc Hoguin.\n\n Own Id: OTP-11039\n\n- Erlang source files with non-ASCII characters are now encoded in UTF-8\n (instead of latin1).\n\n Own Id: OTP-11041 Aux Id: OTP-10907\n\n- Fix rest_for_one and one_for_all restarting a child not terminated. Thanks to\n James Fish.\n\n Own Id: OTP-11042\n\n- Fix excessive CPU consumption of timer_server. Thanks to Aliaksey\n Kandratsenka.\n\n Own Id: OTP-11053\n\n- Rename and document lists:zf/2 as lists:filtermap/2. Thanks to Anthony Ramine.\n\n Own Id: OTP-11078\n\n- Fixed an inconsistent state in epp. Thanks to Anthony Ramine\n\n Own Id: OTP-11079\n\n- c:ls(File) will now print File, similar to ls(1) in Unix. The error messages\n have also been improved. (Thanks to Bengt Kleberg.)\n\n Own Id: OTP-11108\n\n- Support callback attributes in erl_pp. Thanks to Anthony Ramine.\n\n Own Id: OTP-11140\n\n- Improve erl_lint performance. Thanks to José Valim.\n\n Own Id: OTP-11143","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.19.1 - STDLIB Release Notes","ref":"notes.html#stdlib-1-19-1"},{"type":"extras","doc":"- Bugs related to Unicode have been fixed in the `erl_eval` module.\n\n Own Id: OTP-10622 Aux Id: kunagi-351 \\[262]\n\n- `filelib:wildcard(\"some/relative/path/*.beam\", Path)` would fail to match any\n file. That is, filelib:wildcard/2 would not work if the first component of the\n pattern did not contain any wildcard characters. (A previous attempt to fix\n the problem in R15B02 seems to have made matters worse.)\n\n (Thanks to Samuel Rivas and Tuncer Ayaz.)\n\n There is also an incompatible change to the `Path` argument. It is no longer\n allowed to be a binary.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-10812","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The new STDLIB application variable `shell_strings` can be used for\n determining how the Erlang shell outputs lists of integers. The new function\n `shell:strings/1` toggles the value of the variable.\n\n The control sequence modifier `l` can be used for turning off the string\n recognition of `~p` and `~P`.\n\n Own Id: OTP-10755\n\n- Miscellaneous updates due to Unicode support.\n\n Own Id: OTP-10820\n\n- Extend `~ts` to handle binaries with characters coded in ISO-latin-1\n\n Own Id: OTP-10836\n\n- The +pc flag to erl can be used to set the range of characters considered\n printable. This affects how the shell and io:format(\"~tp\",...) functionality\n does heuristic string detection. More can be read in STDLIB users guide.\n\n Own Id: OTP-10884","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.19 - STDLIB Release Notes","ref":"notes.html#stdlib-1-19"},{"type":"extras","doc":"- Wildcards such as \"some/path/\\*\" passed to `filelib:wildcard/2` would fail to\n match any file. (Thanks to Samuel Rivas for reporting this bug.)\n\n Own Id: OTP-6874 Aux Id: kunagi-190 \\[101]\n\n- Fixed error handling in proc_lib:start which could hang if the spawned process\n died in init.\n\n Own Id: OTP-9803 Aux Id: kunagi-209 \\[120]\n\n- Allow \\*\\* in filelib:wildcard\n\n Two adjacent \\* used as a single pattern will match all files and zero or more\n directories and subdirectories. (Thanks to José Valim)\n\n Own Id: OTP-10431\n\n- Add the \\\\gN and \\\\g\\{N\\} syntax for back references in re:replace/3,4 to\n allow use with numeric replacement strings. (Thanks to Vance Shipley)\n\n Own Id: OTP-10455\n\n- Export ets:match_pattern/0 type (Thanks to Joseph Wayne Norton)\n\n Own Id: OTP-10472\n\n- Fix printing the empty binary at depth 1 with ~W (Thanks to Andrew Thompson)\n\n Own Id: OTP-10504\n\n- The type `ascii_string()` in the `base64` module has been corrected. The type\n [`file:file_info()`](`t:file:file_info/0`) has been cleaned up. The type\n [`file:fd()`](`t:file:fd/0`) has been made opaque in the documentation.\n\n Own Id: OTP-10624 Aux Id: kunagi-352 \\[263]","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Dets tables are no longer fixed while traversing with a bound key (when only\n the objects with the right key are matched). This optimization affects the\n functions `match/2`, `match_object/2`, `select/2`, `match_delete/2`, and\n `select_delete/2`.\n\n Own Id: OTP-10097\n\n- Support for Unicode has been implemented.\n\n Own Id: OTP-10302\n\n- The linter now warns for opaque types that are not exported, as well as for\n under-specified opaque types.\n\n Own Id: OTP-10436\n\n- The type [`file:name()`](`t:file:name/0`) has been substituted for the type\n [`file:filename()`](`t:file:filename/0`) in the following functions in the\n `filename` module: `absname/2`, `absname_join/2`, `join/1,2`, and `split/1`.\n\n Own Id: OTP-10474\n\n- If a child process fails in its start function, then the error reason was\n earlier only reported as an error report from the error_handler, and\n supervisor:start_link would only return `{error,shutdown}`. This has been\n changed so the supervisor will now return `{error,{shutdown,Reason}}`, where\n `Reason` identifies the failing child and its error reason. (Thanks to Tomas\n Pihl)\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-10490\n\n- Where necessary a comment stating encoding has been added to Erlang files. The\n comment is meant to be removed in Erlang/OTP R17B when UTF-8 becomes the\n default encoding.\n\n Own Id: OTP-10630\n\n- The contracts and types of the modules `erl_scan` and `sys` have been\n corrected and improved. (Thanks to Kostis Sagonas.)\n\n Own Id: OTP-10658\n\n- The Erlang shell now skips the rest of the line when it encounters an Erlang\n scanner error.\n\n Own Id: OTP-10659\n\n- Clean up some specs in the proplists module. (Thanks to Kostis Sagonas.)\n\n Own Id: OTP-10663\n\n- Some examples overflowing the width of PDF pages have been corrected.\n\n Own Id: OTP-10665\n\n- Enable escript to accept emulator arguments when script file has no shebang.\n Thanks to Magnus Henoch\n\n Own Id: OTP-10691\n\n- Fix bug in queue:out/1, queue:out_r/1 that makes it O(N^2) in worst case.\n Thanks to Aleksandr Erofeev.\n\n Own Id: OTP-10722\n\n- There are new functions in the `epp` module which read the character encoding\n from files. See `m:epp` for more information.\n\n Own Id: OTP-10742 Aux Id: OTP-10302\n\n- The functions in `io_lib` have been adjusted for Unicode. The existing\n functions `write_string()` and so on now take Unicode strings, while the old\n behavior has been taken over by new functions `write_latin1_string()` and so\n on. There are also new functions to write Unicode strings as Latin-1 strings,\n mainly targetted towards the Erlang pretty printer (`erl_pp`).\n\n Own Id: OTP-10745 Aux Id: OTP-10302\n\n- The new functions `proc_lib:format/2` and `erl_parse:abstract/2` accept an\n encoding as second argument.\n\n Own Id: OTP-10749 Aux Id: OTP-10302\n\n- Increased potential concurrency in ETS for `write_concurrency` option. The\n number of internal table locks has increased from 16 to 64. This makes it four\n times less likely that two concurrent processes writing to the same table\n would collide and thereby serialized. The cost is an increased constant memory\n footprint for tables using write_concurrency. The memory consumption per\n inserted record is not affected. The increased footprint can be particularly\n large if `write_concurrency` is combined with `read_concurrency`.\n\n Own Id: OTP-10787","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.18.3 - STDLIB Release Notes","ref":"notes.html#stdlib-1-18-3"},{"type":"extras","doc":"- Minor test updates\n\n Own Id: OTP-10591","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 1.18.2 - STDLIB Release Notes","ref":"notes.html#stdlib-1-18-2"},{"type":"extras","doc":"- Fixed bug where if given an invalid drive letter on windows ensure dir would\n go into an infinite loop.\n\n Own Id: OTP-10104\n\n- Calls to gen_server:enter_loop/4 where ServerName has a global scope and no\n timeout is given now works correctly.\n\n Thanks to Sam Bobroff for reporting the issue.\n\n Own Id: OTP-10130\n\n- fix escript/primary archive reloading\n\n If the mtime of an escript/primary archive file changes after being added to\n the code path, correctly reload the archive and update the cache. (Thanks to\n Tuncer Ayaz)\n\n Own Id: OTP-10151\n\n- Fix bug that in some cases could cause corrupted binaries in ETS tables with\n `compressed` option.\n\n Own Id: OTP-10182\n\n- Fix filename:nativename/1 on Win32\n\n Don't choke on paths given as binary argument on Win32. Thanks to Jan Klötzke\n\n Own Id: OTP-10188\n\n- Fix bug in `ets:test_ms/2` that could cause emulator crash when using `'$_'`\n in match spec.\n\n Own Id: OTP-10190\n\n- Fix bug where zip archives wrongly have a first disk number set to 1\n\n Own Id: OTP-10223","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The message printed by the Erlang shell as an explanation of the `badarith`\n error has been corrected. (Thanks to Matthias Lang.)\n\n Own Id: OTP-10054","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.18.1 - STDLIB Release Notes","ref":"notes.html#stdlib-1-18-1"},{"type":"extras","doc":"- References to `is_constant/1` (which was removed in the R12 release) has been\n removed from documentation and code.\n\n Own Id: OTP-6454 Aux Id: seq10407\n\n- Leave control back to gen_server during supervisor's restart loop\n\n When an attempt to restart a child failed, supervisor would earlier keep the\n execution flow and try to restart the child over and over again until it\n either succeeded or the restart frequency limit was reached. If none of these\n happened, supervisor would hang forever in this loop.\n\n This commit adds a timer of 0 ms where the control is left back to the\n gen_server which implements the supervisor. This way any incoming request to\n the supervisor will be handled - which could help breaking the infinite loop -\n e.g. shutdown request for the supervisor or for the problematic child.\n\n This introduces some incompatibilities in stdlib due to new return values from\n supervisor:\n\n - restart_child/2 can now return \\{error,restarting\\}\n - delete_child/2 can now return \\{error,restarting\\}\n - which_children/1 returns a list of \\{Id,Child,Type,Mods\\}, where Child, in\n addition to the old pid() or 'undefined', now also can be 'restarting'.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-9549\n\n- If a temporary child's start function returned 'ignore', then the supervisor\n would keep it's child specification. This has been corrected. Child\n specifications for non-existing temporary children shall never be kept.\n\n Own Id: OTP-9782 Aux Id: seq11964\n\n- Use universal time as base in error logger\n\n Previous conversion used the deprecated\n calendar:local_time_to_universal_time/1\n\n Own Id: OTP-9854\n\n- Calling a guard test (such as is_list/1) from the top-level in a guard, would\n cause a compiler crash if there was a local definition with the same name.\n Corrected to reject the program with an error message.\n\n Own Id: OTP-9866\n\n- Fix the type spec from the doc of binary:part/3 (Thanks to Ricardo Catalinas\n Jiménez)\n\n Own Id: OTP-9920\n\n- Correct spelling of registered (Thanks to Richard Carlsson)\n\n Own Id: OTP-9925\n\n- Put gb_trees documentation into alphabetical order (Thanks to Aidan Hobson\n Sayers)\n\n Own Id: OTP-9929\n\n- Fix bug in ETS with `compressed` option and insertion of term containing large\n integers (>2G) on 64-bit machines. Seen to cause emulator crash. (Thanks to\n Diego Llarrull for excellent bug report)\n\n Own Id: OTP-9932\n\n- Add plugin support for alternative name lookup This patch introduces a new way\n of locating a behaviour instance: \\{via, Module, Name\\}. (Thanks to Ulf Wiger)\n\n Own Id: OTP-9945\n\n- The function `digraph_utils:condensation/1` used to create a digraph\n containing loops contradicting the documentation which states that the created\n digraph is free of cycles. This bug has been fixed. (Thanks to Kostis Sagonas\n for finding the bug.)\n\n Own Id: OTP-9953\n\n- When an escript ends now all printout to standard output and standard error\n gets out on the terminal. This bug has been corrected by changing the\n behaviour of erlang:halt/0,1, which should fix the same problem for other\n escript-like applications, i.e that data stored in the output port driver\n buffers got lost when printing on a TTY and exiting through erlang:halt/0,1.\n\n The BIF:s erlang:halt/0,1 has gotten improved semantics and there is a new BIF\n erlang:halt/2 to accomplish something like the old semantics. See the\n documentation.\n\n Now erlang:halt/0 and erlang:halt/1 with an integer argument will close all\n ports and allow all pending async threads operations to finish before exiting\n the emulator. Previously erlang:halt/0 and erlang:halt(0) would just wait for\n pending async threads operations but not close ports. And erlang:halt/1 with a\n non-zero integer argument would not even wait for pending async threads\n operations.\n\n To roughly the old behaviour, to not wait for ports and async threads\n operations when you exit the emulator, you use erlang:halt/2 with an integer\n first argument and an option list containing \\{flush,false\\} as the second\n argument. Note that now is flushing not dependant of the exit code, and you\n cannot only flush async threads operations which we deemed as a strange\n behaviour anyway.\n\n Also, erlang:halt/1,2 has gotten a new feature: If the first argument is the\n atom 'abort' the emulator is aborted producing a core dump, if the operating\n system so allows.\n\n Own Id: OTP-9985\n\n- Add escript win32 alternative invocation. escript can now be started as both\n \"escript.exe\" and \"escript\" (Thanks to Pierre Rouleau)\n\n Own Id: OTP-9997","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 1.18 - STDLIB Release Notes","ref":"notes.html#stdlib-1-18"},{"type":"extras","doc":"- Improved algorithm in module `random`. Avoid seed values that are even\n divisors of the primes and by that prevent getting sub-seeds that are stuck on\n zero. Worst case was random:seed(0,0,0) that produced a series of only zeros.\n This is an incompatible change in the sense that applications that relies on\n reproducing a specific series for a given seed will fail. The pseudo random\n output is still deterministic but different compared to earlier versions.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8713\n\n- Calls to `global:whereis_name/1` have been substituted for calls to\n `global:safe_whereis_name/1` since the latter is not safe at all.\n\n The reason for not doing this earlier is that setting a global lock masked out\n a bug concerning the restart of supervised children. The bug has now been\n fixed by a modification of `global:whereis_name/1`. (Thanks to Ulf Wiger for\n code contribution.)\n\n A minor race conditions in `gen_fsm:start*` has been fixed: if one of these\n functions returned `{error, Reason}` or ignore, the name could still be\n registered (either locally or in `global`. (This is the same modification as\n was done for gen_server in OTP-7669.)\n\n The undocumented function `global:safe_whereis_name/1` has been removed.\n\n Own Id: OTP-9212 Aux Id: seq7117, OTP-4174\n\n- If a child of a supervisor terminates with reason \\{shutdown,Term\\} it is now\n handled by the supervisor as if the reason was 'shutdown'.\n\n For children with restart type 'permanent', this implies no change. For\n children with restart type 'transient', the child will no longer be restarted\n and no supervisor report will be written. For children with restart type\n 'temporary', no supervisor report will be written.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-9222\n\n- Minor improvement of documentation regarding supervisor restart strategy for\n temporary and transient child processes.\n\n Own Id: OTP-9381\n\n- A Dets table with sufficiently large buckets could not always be repaired.\n This bug has been fixed.\n\n The format of Dets files has been modified. When downgrading tables created\n with the new system will be repaired. Otherwise the modification should not be\n noticeable.\n\n Own Id: OTP-9607\n\n- A few contracts in the `lists` module have been corrected.\n\n Own Id: OTP-9616\n\n- Add '-callback' attributes in stdlib's behaviours\n\n Replace the behaviour_info(callbacks) export in stdlib's behaviours with\n -callback' attributes for all the callbacks. Update the documentation with\n information on the callback attribute Automatically generate 'behaviour_info'\n function from '-callback' attributes\n\n 'behaviour_info(callbacks)' is a special function that is defined in a module\n which describes a behaviour and returns a list of its callbacks.\n\n This function is now automatically generated using the '-callback' specs. An\n error is returned by lint if user defines both '-callback' attributes and the\n behaviour_info/1 function. If no type info is needed for a callback use a\n generic spec for it. Add '-callback' attribute to language syntax\n\n Behaviours may define specs for their callbacks using the familiar spec\n syntax, replacing the '-spec' keyword with '-callback'. Simple lint checks are\n performed to ensure that no callbacks are defined twice and all types referred\n are declared.\n\n These attributes can be then used by tools to provide documentation to the\n behaviour or find discrepancies in the callback definitions in the callback\n module.\n\n Add callback specs into 'application' module in kernel Add callback specs to\n tftp module following internet documentation Add callback specs to\n inets_service module following possibly deprecated comments\n\n Own Id: OTP-9621\n\n- If a Dets table had been properly closed but the space management data could\n not been read, it was not possible to repair the file. This bug has been\n fixed.\n\n Own Id: OTP-9622\n\n- The Unicode noncharacter code points 16#FFFE and 16#FFFE were not allowed to\n be encoded or decoded using the `unicode` module or bit syntax. That was\n inconsistent with the other noncharacters 16#FDD0 to 16#FDEF that could be\n encoded/decoded. To resolve the inconsistency, 16#FFFE and 16#FFFE can now be\n encoded and decoded. (Thanks to Alisdair Sullivan.)\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-9624\n\n- Make epp search directory of current file first when including another file\n This completes a partial fix in R11 that only worked for include_lib().\n (Thanks to Richard Carlsson)\n\n Own Id: OTP-9645\n\n- ms_transform: Fix incorrect \\`variable shadowed' warnings\n\n This patch removes incorrect passing of variable bindings from one function\n clause to another. (Thanks to Haitao Li)\n\n Own Id: OTP-9646\n\n- Explicitly kill dynamic children in supervisors\n\n According to the supervisor's documentation: \"Important note on\n simple-one-for-one supervisors: The dynamically created child processes of a\n simple-one-for-one supervisor are not explicitly killed, regardless of\n shutdown strategy, but are expected to terminate when the supervisor does\n (that is, when an exit signal from the parent process is received).\"\n\n All is fine as long as we stop simple_one_for_one supervisor manually. Dynamic\n children catch the exit signal from the supervisor and leave. But, if this\n happens when we stop an application, after the top supervisor has stopped, the\n application master kills all remaining processes associated to this\n application. So, dynamic children that trap exit signals can be killed during\n their cleanup (here we mean inside terminate/2). This is unpredictable and\n highly time-dependent.\n\n In this commit, supervisor module is patched to explicitly terminate dynamic\n children accordingly to the shutdown strategy.\n\n NOTE: Order in which dynamic children are stopped is not defined. In fact,\n this is \"almost\" done at the same time.\n\n Stack errors when dynamic children are stopped\n\n Because a simple_one_for_one supervisor can have many workers, we stack errors\n during its shutdown to report only one message for each encountered error\n type. Instead of reporting the child's pid, we use the number of concerned\n children. (Thanks to Christopher Faulet)\n\n Own Id: OTP-9647\n\n- Allow an infinite timeout to shutdown worker processes\n\n Now, in child specification, the shutdown value can also be set to infinity\n for worker children. This restriction was removed because this is not always\n possible to predict the shutdown time for a worker. This is highly\n application-dependent. Add a warning to docs about workers' shutdown strategy\n (Thanks to Christopher Faulet)\n\n Own Id: OTP-9648\n\n- A badarg would sometimes occur in supervisor when printing error reports and\n the child pid was undefined. This has been corrected.\n\n Own Id: OTP-9669\n\n- Fix re:split spec not to accept option 'global'(Thanks to Shunichi Shinohara)\n\n Own Id: OTP-9691","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Fix a few tests that used to fail on the HiPE platform.\n\n Own Id: OTP-9637\n\n- Variables are now now allowed in '`fun M:F/A`' as suggested by Richard O'Keefe\n in EEP-23.\n\n The representation of '`fun M:F/A`' in the abstract format has been changed in\n an incompatible way. Tools that directly read or manipulate the abstract\n format (such as parse transforms) may need to be updated. The compiler can\n handle both the new and the old format (i.e. extracting the abstract format\n from a pre-R15 BEAM file and compiling it using compile:forms/1,2 will work).\n The `syntax_tools` application can also handle both formats.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-9643\n\n- Tuple funs (a two-element tuple with a module name and a function) are now\n officially deprecated and will be removed in R16. Use '`fun M:F/A`' instead.\n To make you aware that your system uses tuple funs, the very first time a\n tuple fun is applied, a warning will be sent to the error logger.\n\n Own Id: OTP-9649\n\n- The deprecated '`regexp`' module has been removed. Use the '`re`' module\n instead.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-9737\n\n- `filename:find_src/1,2` will now work on stripped BEAM files (reported by Per\n Hedeland). The HiPE compiler will also work on stripped BEAM files. The BEAM\n compiler will no longer include compilation options given in the source code\n itself in `M:module_info(compile)` (because those options will be applied\n anyway if the module is re-compiled).\n\n Own Id: OTP-9752","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.17.5 - STDLIB Release Notes","ref":"notes.html#stdlib-1-17-5"},{"type":"extras","doc":"- erl_tar:extract failed when executed inside a directory with some parent\n directory to which the user has no read access. This has been corrected.\n\n Own Id: OTP-9368\n\n- A bug in `erl_scan:set_attribute/3` has been fixed.\n\n Own Id: OTP-9412\n\n- The contract of `io_lib:fread()` has been corrected.\n\n Own Id: OTP-9413 Aux Id: seq11873\n\n- A crash in io*lib:fread/2 when end of input data was encountered while trying\n to match literal characters, which should return \\{more,*,_,_\\} but instead\n crashed, has been corrected. Reported by Klas Johansson.\n\n A similar peculiarity for io:fread when encountering end of file before any\n field data has also been corrected.\n\n Own Id: OTP-9439\n\n- The contract of `timer:now_diff()` has been corrected. (Thanks to Alex\n Morarash).\n\n Own Id: OTP-9450\n\n- Fix minor typo in gen_fsm documentation (Thanks to Haitao Li)\n\n Own Id: OTP-9456\n\n- The contracts of `zip:zip_list_dir/1` and `zip:zip_get/2` have been corrected.\n\n Own Id: OTP-9471 Aux Id: seq11887, OTP-9472\n\n- A bug in `zip:zip_open()` has been fixed.\n\n Own Id: OTP-9472 Aux Id: seq11887, OTP-9471\n\n- Fix trivial documentation errors(Thanks to Matthias Lang)\n\n Own Id: OTP-9498\n\n- Add a proplist() type\n\n Recently I was adding specs to an API and found that there is no canonical\n proplist() type defined. (Thanks to Ryan Zezeski)\n\n Own Id: OTP-9499\n\n- fix supervisors restarting temporary children\n\n In the current implementation of supervisors, temporary children should never\n be restarted. However, when a temporary child is restarted as part of a\n one_for_all or rest_for_one strategy where the failing process is not the\n temporary child, the supervisor still tries to restart it.\n\n Because the supervisor doesn't keep some of the MFA information of temporary\n children, this causes the supervisor to hit its restart limit and crash.\n\n This patch fixes the behaviour by inserting a clause in terminate_children/2-3\n (private function) that will omit temporary children when building a list of\n killed processes, to avoid having the supervisor trying to restart them again.\n\n Only supervisors in need of restarting children used the list, so the change\n should be of no impact for the functions that called terminate_children/2-3\n only to kill all children.\n\n The documentation has been modified to make this behaviour more explicit.\n (Thanks to Fred Hebert)\n\n Own Id: OTP-9502\n\n- fix broken edoc annotations (Thanks to Richard Carlsson)\n\n Own Id: OTP-9516\n\n- XML files have been corrected.\n\n Own Id: OTP-9550 Aux Id: OTP-9541\n\n- Handle rare race in the crypto key server functionality\n\n Own Id: OTP-9586","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Types and specifications have been added.\n\n Own Id: OTP-9356\n\n- The contracts of the `queue` module have been modified.\n\n Own Id: OTP-9418\n\n- Contracts in STDLIB and Kernel have been improved and type errors have been\n corrected.\n\n Own Id: OTP-9485\n\n- Types for several BIFs have been extended/corrected. Also the types for types\n for `lists:keyfind/3`, `lists:keysearch/3`, and `lists:keyemember/3` have been\n corrected. The incorrect/incomplete types could cause false dialyzer warnings.\n\n Own Id: OTP-9496","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.17.4 - STDLIB Release Notes","ref":"notes.html#stdlib-1-17-4"},{"type":"extras","doc":"- The default value `undefined` was added to records field types in such a way\n that the result was not always a well-formed type. This bug has been fixed.\n\n Own Id: OTP-9147\n\n- Update index file atomically\n\n Since the log_mf_h index file might be read by other processes than the error\n handler (e.g. by the rb tool), this file should be updated atomically. This\n will avoid hitting the time gap between opening the file in write mode (and\n thus emptying the file) and the actual update with the new contents. To do\n this, a temporary file is written, and the file:rename/1 used to replace the\n real index file.\n\n Own Id: OTP-9148\n\n- Fixed various typos across the documentation (Thanks to Tuncer Ayaz)\n\n Own Id: OTP-9154\n\n- Supervisors should not save child-specs for temporary processes when they\n terminate as they should not be restarted. Saving the temporary child spec\n will result in that you cannot start a new temporary process with the same\n child spec as an already terminated temporary process. Since R14B02 you cannot\n restart a temporary temporary process as arguments are no longer saved, it has\n however always been semantically incorrect to restart a temporary process.\n Thanks to Filipe David Manana for reporting this and suggesting a solution.\n\n Own Id: OTP-9167 Aux Id: OTP-9064\n\n- Various small documentation fixes (Thanks to Bernard Duggan)\n\n Own Id: OTP-9172\n\n- Fix format_status bug for unregistered gen_event processes\n\n Port the gen_fsm code for format_status to gen_event in order to prevent a\n lists:concat(\\[...,pid()]) crash when calling sys:get_status/1 on an\n unregistered gen_event process.\n\n Refactor format*status header code from gen*\\* behaviours to module gen.\n\n Extend the format_status tests in gen_event_SUITE to cover format_status bugs\n with anonymous gen_event processes. (Thanks To Geoff Cant)\n\n Own Id: OTP-9218\n\n- List of pids changed to 'set' in supervisor for dynamic temporary children.\n Accessing the list would not scale well when adding/deleting many children.\n (Thanks to Evgeniy Khramtsov)\n\n Own Id: OTP-9242\n\n- Change pool module to attempt to attach to nodes that are already running\n\n The pool module prints out an error message and takes no further action for\n nodes that are already running. This patch changes that behavior so that if\n the return from slave:start/3 is \\{already_running, Node\\} then an attempt to\n attach to the node is still made. This makes sense because the node has been\n specified by the user in the .hosts.erlang file indicating a wish for the node\n to be part of the pool and a manual attach can be successfully made after the\n pool is started.(Thanks to Kelly McLaughlin)\n\n Own Id: OTP-9244\n\n- unicode: document 16#FFFE and 16#FFFF (non chars)(Thanks to Tuncer Ayaz)\n\n Own Id: OTP-9256\n\n- re: remove gratuitous \"it \" in manpage (Thanks to Tuncer Ayaz)\n\n Own Id: OTP-9307\n\n- A bug in erl_eval(3) has been fixed.\n\n Own Id: OTP-9322","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add `timer:tc/1` and remove the catch in `tc/2` and `tc/3`. The time measuring\n functions will thus no longer trap exits, errors or throws caused by the\n measured function.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-9169\n\n- Allow supervisor:terminate_child(SupRef,Pid) for simple_one_for_one\n supervisors\n\n supervisor:terminate_child/2 was earlier not allowed if the supervisor used\n restart strategy simple_one_for_one. This is now changed so that children of\n this type of supervisors can be terminated by specifying the child's Pid.\n\n (Thanks to Vance Shipley.)\n\n Own Id: OTP-9201\n\n- Types and specifications have been added.\n\n Own Id: OTP-9267\n\n- Erlang types and specifications are used for documentation.\n\n Own Id: OTP-9271\n\n- Allow Dets tablenames to be arbitrary terms.\n\n Own Id: OTP-9282\n\n- A specification that could cause problems for Dialyzer has been fixed. An\n opaque type in erl_eval has been turned in to a ordinary type. This is a\n temporary fix.\n\n Own Id: OTP-9333","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.17.3 - STDLIB Release Notes","ref":"notes.html#stdlib-1-17-3"},{"type":"extras","doc":"- Two bugs in io:format for ~F.~Ps has been corrected. When length(S) >=\n abs(F) > P, the precision P was incorrectly ignored. When F == P > length(S)\n the result was incorrectly left adjusted. Bug found by Ali Yakout who also\n provided a fix.\n\n Own Id: OTP-8989 Aux Id: seq11741\n\n- Fix exception generation in the io module\n\n Some functions did not generate correct badarg exception on a badarg\n exception.\n\n Own Id: OTP-9045\n\n- Fixes to the dict and orddict module documentation\n\n Fixed grammar and one inconsistency (Key - Value instead of key/value, since\n everywhere else the former is used). (thanks to Filipe David Manana)\n\n Own Id: OTP-9083\n\n- Add ISO week number calculation functions to the calendar module in stdlib\n\n This new feature adds the missing week number function to the calendar module\n of the stdlib application. The implementation conforms to the ISO 8601\n standard. The new feature has been implemented tested and documented (thanks\n to Imre Horvath).\n\n Own Id: OTP-9087","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Implement the 'MAY' clauses from RFC4648 regarding the pad character to make\n mime_decode() and mime_decode_to_string() functions more tolerant of badly\n padded base64. The RFC is quoted below for easy reference.\n\n \"RFC4648 Section 3.3 with reference to MIME decoding: Furthermore, such\n specifications MAY ignore the pad character, \"=\", treating it as non-alphabet\n data, if it is present before the end of the encoded data. If more than the\n allowed number of pad characters is found at the end of the string (e.g., a\n base 64 string terminated with \"===\"), the excess pad characters MAY also be\n ignored.\"\n\n Own Id: OTP-9020\n\n- Supervisors will no longer save start parameters for temporary processes as\n they will not be restarted. In the case of simple_one_for_one workers such as\n ssl-connection processes this will substantial reduce the memory footprint of\n the supervisor.\n\n Own Id: OTP-9064\n\n- When running escript it is now possible to add the -n flag and the escript\n will be compiled using +native.\n\n Own Id: OTP-9076","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.17.2.1 - STDLIB Release Notes","ref":"notes.html#stdlib-1-17-2-1"},{"type":"extras","doc":"- Several type specifications for standard libraries were wrong in the R14B01\n release. This is now corrected. The corrections concern types in\n re,io,filename and the module erlang itself.\n\n Own Id: OTP-9008","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 1.17.2 - STDLIB Release Notes","ref":"notes.html#stdlib-1-17-2"},{"type":"extras","doc":"- When several clients accessed a Dets table simultaneously, one of them calling\n `dets:insert_new/2`, the Dets server could crash. Alternatively, under the\n same conditions, `ok` was sometimes returned instead of `true`. (Thanks to\n John Hughes.)\n\n Own Id: OTP-8856\n\n- When several clients accessed a Dets table simultaneously, inserted or updated\n objects were sometimes lost due to the Dets file being truncated. (Thanks to\n John Hughes.)\n\n Own Id: OTP-8898\n\n- When several clients accessed a Dets table simultaneously, modifications of\n the Dets server's internal state were sometimes thrown away. The symptoms are\n diverse: error with reason `bad_object`; inserted objects not returned by\n `lookup()`; et cetera. (Thanks to John Hughes.)\n\n Own Id: OTP-8899\n\n- If a Dets table was closed after calling `bchunk/2`, `match/1,3`,\n `match_object/1,3`, or `select/1,3` and then opened again, a subsequent call\n using the returned continuation would normally return a reply. This bug has\n fixed; now the call fails with reason `badarg`.\n\n Own Id: OTP-8903\n\n- Cover did not collect coverage data for files such as Yecc parses containing\n include directives. The bug has been fixed by modifying `epp`, the Erlang Code\n Preprocessor.\n\n Own Id: OTP-8911\n\n- If a Dets table with fewer slots than keys was opened and then closed after\n just a lookup, the contents were no longer well-formed. This bug has been\n fixed. (Thanks to Matthew Evans.)\n\n Own Id: OTP-8923\n\n- In a supervisor, when it terminates a child, if that child happens to have\n exited fractionally early, with normal, the supervisor reports this as an\n error. This should not be reported as an error.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8938 Aux Id: seq11615","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The documentation filelib:wildcard/1,2 now describes the character set syntax\n for wildcards.\n\n Own Id: OTP-8879 Aux Id: seq11683\n\n- Buffer overflows have been prevented in `erlc`, `dialyzer`, `typer`,\n `run_test`, `heart`, `escript`, and `erlexec`.\n\n (Thanks to Michael Santos.)\n\n Own Id: OTP-8892\n\n- Using a float for the number of copies for `string:copies/2` resulted in an\n infinite loop. Now it will fail with an exception instead. (Thanks to Michael\n Santos.)\n\n Own Id: OTP-8915\n\n- New ETS option `compressed`, to enable a more compact storage format at the\n expence of heavier table operations. For test and evaluation, `erl +ec` can be\n used to force compression on all ETS tables.\n\n Own Id: OTP-8922 Aux Id: seq11658\n\n- The default maximum number of slots of a Dets table has been changed as to be\n equal to the maximum number of slots. (Thanks to Richard Carlsson.)\n\n Own Id: OTP-8959","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.17.1 - STDLIB Release Notes","ref":"notes.html#stdlib-1-17-1"},{"type":"extras","doc":"- reference() has been substituted for ref() in the documentation.\n\n Own Id: OTP-8733","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The ms_transform now warns if the fun head shadows surrounding variables (just\n like the warnings you would get for an ordinary fun in the same context).\n\n Own Id: OTP-6759\n\n- ets:select_reverse/\\{1,2,3\\} are now documented.\n\n Own Id: OTP-7863\n\n- Large parts of the `ethread` library have been rewritten. The `ethread`\n library is an Erlang runtime system internal, portable thread library used by\n the runtime system itself.\n\n Most notable improvement is a reader optimized rwlock implementation which\n dramatically improve the performance of read-lock/read-unlock operations on\n multi processor systems by avoiding ping-ponging of the rwlock cache lines.\n The reader optimized rwlock implementation is used by miscellaneous rwlocks in\n the runtime system that are known to be read-locked frequently, and can be\n enabled on ETS tables by passing the\n [\\{read_concurrency, true\\}](`m:ets#new_2_read_concurrency`) option upon table\n creation. See the documentation of `ets:new/2` for more information. The\n reader optimized rwlock implementation can be fine tuned when starting the\n runtime system. For more information, see the documentation of the\n [\\+rg](`e:erts:erl_cmd.md#%2Brg`) command line argument of `erl`.\n\n There is also a new implementation of rwlocks that is not optimized for\n readers. Both implementations interleaves readers and writers during\n contention as opposed to, e.g., the NPTL (Linux) pthread rwlock implementation\n which use either a reader or writer preferred strategy. The reader/writer\n preferred strategy is problematic since it starves threads doing the\n non-preferred operation.\n\n The new rwlock implementations in general performs better in ERTS than common\n pthread implementations. However, in some extremely heavily contended cases\n this is not the case. Such heavy contention can more or less only appear on\n ETS tables. This when multiple processes do very large amounts of write locked\n operations simultaneously on the same table. Such use of ETS is bad regardless\n of rwlock implementation, will never scale, and is something we strongly\n advise against.\n\n The new rwlock implementations depend on atomic operations. If no native\n atomic implementation is found, a fallback solution will be used. Using the\n fallback implies a performance degradation. That is, it is more important now\n than before to build OTP with a native atomic implementation.\n\n The `ethread` library contains native atomic implementations for, x86 (32 and\n 64 bit), powerpc (32 bit), sparc V9 (32 and 64 bit), and tilera (32 bit). On\n other hardware gcc's builtin support for atomic memory access will be used if\n such exists. If no such support is found, `configure` will warn about no\n atomic implementation available.\n\n The `ethread` library can now also use the `libatomic_ops` library for atomic\n memory accesses. This makes it possible for the Erlang runtime system to\n utilize optimized native atomic operations on more platforms than before. If\n `configure` warns about no atomic implementation available, try using the\n `libatomic_ops` library. Use the\n [\\--with-libatomic_ops=PATH](`e:system:install.md#advanced-configuration-and-build-of-erlang-otp`)\n `configure` command line argument when specifying where the `libatomic_ops`\n installation is located. The `libatomic_ops` library can be downloaded from:\n [http://www.hpl.hp.com/research/linux/atomic_ops/](http://www.hpl.hp.com/research/linux/atomic_ops/)\n\n The changed API of the `ethread` library has also caused modifications in the\n Erlang runtime system. Preparations for the to come \"delayed deallocation\"\n feature has also been done since it depends on the `ethread` library.\n\n _Note_: When building for x86, the `ethread` library will now use instructions\n that first appeared on the pentium 4 processor. If you want the runtime system\n to be compatible with older processors (back to 486) you need to pass the\n [\\--enable-ethread-pre-pentium4-compatibility](`e:system:install.md#advanced-configuration-and-build-of-erlang-otp`)\n `configure` command line argument when configuring the system.\n\n Own Id: OTP-8544\n\n- Some Built In Functions (BIFs) from the module erlang was never made\n autoimported for backward compatibility reasons. As local functions now\n override autoimports, new autoimports is no longer a problem, why the\n following BIFs are finally made autoimported: monitor/2, monitor/3,\n demonitor/2, demonitor/3, error/1, error/2, integer_to_list/2,\n list_to_integer/2.\n\n Own Id: OTP-8763","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.17 - STDLIB Release Notes","ref":"notes.html#stdlib-1-17"},{"type":"extras","doc":"- The Erlang code preprocessor (`epp`) sent extra messages on the form\n `{eof,Location}` to the client when parsing the `file` attribute. This bug,\n introduced in R11B, has been fixed.\n\n Own Id: OTP-8470\n\n- The abstract type 'fun' could not be printed by the Erlang pretty printer\n (`erl_pp`). This bug has been fixed.\n\n Own Id: OTP-8473\n\n- The function `erl_scan:reserved_word/1` no longer returns `true` when given\n the word `spec`. This bug was introduced in STDLIB-1.15.3 (R12B-3).\n\n Own Id: OTP-8567\n\n- The documentation of `lists:keysort/2` states that the sort is stable.\n\n Own Id: OTP-8628 Aux Id: seq11576\n\n- The shell's line editing has been improved to more resemble the behaviour of\n readline and other shells. (Thanks to Dave Peticolas)\n\n Own Id: OTP-8635\n\n- The Erlang code preprocessor (`epp`) did not correctly handle premature\n end-of-input when defining macros. This bug, introduced in STDLIB 1.16, has\n been fixed.\n\n Own Id: OTP-8665 Aux Id: OTP-7810","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The module binary from EEP31 (and EEP9) is implemented.\n\n Own Id: OTP-8217\n\n- The erlang pretty printer (`erl_pp`) no longer quotes atoms in types.\n\n Own Id: OTP-8501\n\n- The Erlang code preprocessor (`epp`) now considers records with no fields as\n typed.\n\n Own Id: OTP-8503\n\n- Added function `zip:foldl/3` to iterate over zip archives.\n\n Added functions to create and extract escripts. See `escript:create/2` and\n `escript:extract/2`.\n\n The undocumented function `escript:foldl/3` has been removed. The same\n functionality can be achieved with the more flexible functions\n `escript:extract/2` and `zip:foldl/3`.\n\n Record fields has been annotated with type info. Source files as been adapted\n to fit within 80 chars and trailing whitespace has been removed.\n\n Own Id: OTP-8521\n\n- The Erlang parser no longer duplicates the singleton type `undefined` in the\n type of record fields without initial value.\n\n Own Id: OTP-8522\n\n- A regular expression with many levels of parenthesis could cause a buffer\n overflow. That has been corrected. (Thanks to Michael Santos.)\n\n Own Id: OTP-8539\n\n- When defining macros the closing right parenthesis before the dot is now\n mandatory.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8562\n\n- Some properties of a compiled re pattern are defined to allow for guard tests.\n\n Own Id: OTP-8577\n\n- Local and imported functions now override the auto-imported BIFs when the\n names clash. The pre R14 behaviour was that auto-imported BIFs would override\n local functions. To avoid that old programs change behaviour, the following\n will generate an error:\n\n - Doing a call without explicit module name to a local function having a name\n clashing with the name of an auto-imported BIF that was present (and\n auto-imported) before OTP R14A\n - Explicitly importing a function having a name clashing with the name of an\n autoimported BIF that was present (and autoimported) before OTP R14A\n - Using any form of the old compiler directive `nowarn_bif_clash`\n\n If the BIF was added or auto-imported in OTP R14A or later, overriding it with\n an import or a local function will only result in a warning,\n\n To resolve clashes, you can either use the explicit module name `erlang` to\n call the BIF, or you can remove the auto-import of that specific BIF by using\n the new compiler directive `-compile({no_auto_import,[F/A]}).`, which makes\n all calls to the local or imported function without explicit module name pass\n without warnings or errors.\n\n The change makes it possible to add auto-imported BIFs without breaking or\n silently changing old code in the future. However some current code\n ingeniously utilizing the old behaviour or the `nowarn_bif_clash` compiler\n directive, might need changing to be accepted by the compiler.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8579\n\n- The undocumented, unsupport, and deprecated function `lists:flat_length/1` has\n been removed.\n\n Own Id: OTP-8584\n\n- A bug in re that could cause certain regular expression matches never to\n terminate is corrected. (Thanks to Michael Santos and Gordon Guthrie.)\n\n Own Id: OTP-8589\n\n- Nested records can now be accessed without parenthesis. See the Reference\n Manual for examples. (Thanks to YAMASHINA Hio and Tuncer Ayaz.)\n\n Own Id: OTP-8597\n\n- `receive` statements that can only read out a newly created reference are now\n specially optimized so that it will execute in constant time regardless of the\n number of messages in the receive queue for the process. That optimization\n will benefit calls to `gen_server:call()`. (See `gen:do_call/4` for an example\n of a receive statement that will be optimized.)\n\n Own Id: OTP-8623\n\n- The beam_lib:cmp/2 function now compares BEAM files in stricter way. The BEAM\n files will be considered different if there are any changes except in the\n compilation information (\"CInf\") chunk. beam_lib:cmp/2 used to ignore\n differences in the debug information (significant for Dialyzer) and other\n chunks that did not directly change the run-time behavior.\n\n Own Id: OTP-8625\n\n- When a gen_server, gen_fsm process, or gen_event terminates abnormally,\n sometimes the text representation of the process state can occupy many lines\n of the error log, depending on the definition of the state term. A mechanism\n to trim out parts of the state from the log has been added (using a\n format_status/2 callback). See the documentation.\n\n Own Id: OTP-8630\n\n- Calling `sys:get_status()` for processes that have globally registered names\n that were not atoms would cause a crash. Corrected. (Thanks to Steve Vinoski.)\n\n Own Id: OTP-8656\n\n- The Erlang scanner has been augmented with two new tokens: `..` and `...`.\n\n Own Id: OTP-8657\n\n- Expressions evaluating to integers can now be used in types and function\n specifications where hitherto only integers were allowed (\"Erlang_Integer\").\n\n Own Id: OTP-8664\n\n- The compiler optimizes record operations better.\n\n Own Id: OTP-8668\n\n- The recently added BIFs erlang:min/2, erlang:max/2 and erlang:port_command/3\n are now auto-imported (as they were originally intended to be). Due to the\n recent compiler change (OTP-8579), the only impact on old code defining it's\n own min/2, max/2 or port_command/3 functions will be a warning, the local\n functions will still be used. The warning can be removed by using\n -compile(\\{no_auto_import,\\[min/2,max/2,port_command/3]\\}). in the source\n file.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8669 Aux Id: OTP-8579\n\n- Now, binary_to_term/2 is auto-imported. This will cause a compile warning if\n and only if a module has got a local function with that name.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8671\n\n- The predefined builtin type tid() has been removed. Instead, ets:tid() should\n be used.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8687","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.16.5 - STDLIB Release Notes","ref":"notes.html#stdlib-1-16-5"},{"type":"extras","doc":"- Because of a race condition, using filelib:ensure_dir/1 from multiple\n processes to create the same path or parts of the same directory structure,\n filelib:ensure_dir/1 could return a meaningless \\{error,eexist\\}. That race\n condition has been eliminated, and \\{error,eexist\\} will now be returned only\n if there exists a regular file, device file, or some other non-directory file\n with the same name. (Thanks to Tuncer Ayaz.)\n\n Own Id: OTP-8389\n\n- A number of bugs concerning re and unicode are corrected:\n\n re:compile no longer loses unicode option, which also fixes bug in re:split.\n\n re:replace now handles unicode charlist replacement argument\n\n re:replace now handles unicode RE charlist argument correctly\n\n re:replace now handles binary unicode output correctly when nothing is\n replaced.\n\n Most code, testcases and error isolation done by Rory Byrne.\n\n Own Id: OTP-8394\n\n- The loading of native code was not properly atomic in the SMP emulator, which\n could cause crashes. Also a per-MFA information table for the native code has\n now been protected with a lock since it turns that it could be accessed\n concurrently in the SMP emulator. (Thanks to Mikael Pettersson.)\n\n Own Id: OTP-8397\n\n- user.erl (used in oldshell) is updated to handle unicode in prompt strings\n (io:get_line/\\{1,2\\}). io_lib is also updated to format prompts with the 't'\n modifier (i.e. ~ts instead of ~s).\n\n Own Id: OTP-8418 Aux Id: OTP-8393\n\n- The re module: A regular expression with an option change at the start of a\n pattern that had top-level alternatives could cause overwriting and/or a\n crash. (Thanks to Michael Santos.)\n\n Own Id: OTP-8438","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The ability for the gen_server and gen_fsm callback modules to format their\n own state for display under the sys:get_status/1,2 calls has been restored and\n documented. (Thanks to Steve Vinoski.)\n\n Own Id: OTP-8324\n\n- c:nc/\\{1,2\\} used to assume that the beam file was created in the same\n directory as the source code and failed to load the code if it was not.\n Corrected to look for the beam file in the current directory or in the\n directory specified by the `{outdir,Dir}` option. (Thanks to Alex Suraci.)\n\n Own Id: OTP-8337\n\n- The documentation is now possible to build in an open source environment after\n a number of bugs are fixed and some features are added in the documentation\n build process.\n\n \\- The arity calculation is updated.\n\n \\- The module prefix used in the function names for bif's are removed in the\n generated links so the links will look like\n \"http://www.erlang.org/doc/man/erlang.html#append_element-2\" instead of\n \"http://www.erlang.org/doc/man/erlang.html#erlang:append_element-2\".\n\n \\- Enhanced the menu positioning in the html documentation when a new page is\n loaded.\n\n \\- A number of corrections in the generation of man pages (thanks to Sergei\n Golovan)\n\n \\- The legal notice is taken from the xml book file so OTP's build process can\n be used for non OTP applications.\n\n Own Id: OTP-8343\n\n- Shell tab completion now works for quoted module and function names. (Thanks\n to Ulf Wiger.)\n\n Own Id: OTP-8383\n\n- Explicit top directories in archive files are now optional.\n\n For example, if an archive (app-vsn.ez) just contains an app-vsn/ebin/mod.beam\n file, the file info for the app-vsn and app-vsn/ebin directories are faked\n using the file info from the archive file as origin. The virtual direcories\n can also be listed. For short, the top directories are virtual if they does\n not exist.\n\n Own Id: OTP-8387\n\n- Macros overloading has been implemented. (Thanks to Christopher Faulet.)\n\n Own Id: OTP-8388\n\n- The new function `shell:prompt_func/1` and the new application configuration\n parameter `shell_prompt_func` can be used for customizing the Erlang shell\n prompt.\n\n Own Id: OTP-8393\n\n- Improved handling of typed records in escripts\n\n Own Id: OTP-8434\n\n- Added supervisor:count_children/1 to count the number of children being\n managed without the memory impact of which_children/1. (Thanks to Jay Nelson.)\n\n Own Id: OTP-8436","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.16.4 - STDLIB Release Notes","ref":"notes.html#stdlib-1-16-4"},{"type":"extras","doc":"- The documentation is now built with open source tools (xsltproc and fop) that\n exists on most platforms. One visible change is that the frames are removed.\n\n Own Id: OTP-8201\n\n- \\[escript] The restriction that the first line in escripts must begin with\n `#!` has been removed.\n\n \\[escript] Some command line options to the escript executable has now been\n documented. For example you can run an escript in the debugger by just adding\n a command line option.\n\n \\[escript] The documentation of the escript header syntax has been clarified.\n For example the header is optional. This means that it is possible to directly\n \"execute\" `.erl`, `.beam` and`.zip` files.\n\n Own Id: OTP-8215\n\n- Optimized array:from_orddict/1, it is now faster and uses less memory if the\n orddict was sparse.\n\n Changed array:reset/2, it will now never expand the array which it could\n before for non fixed arrays. See the documentation.\n\n Own Id: OTP-8216\n\n- The Erlang Pretty Printer (`erl_pp`) now puts the leading `[` of list\n comprehensions as well as the leading `<<` of bit string comprehensions on a\n separate line in order to expose the Cover counter of the template.\n\n Own Id: OTP-8227\n\n- The extension \".xrl\" used for Leex input files is now recognized by the\n compiler.\n\n Own Id: OTP-8232\n\n- Some clarifications have been made in the documentation regarding\n `gen_server`, `gen_fsm`, and `gen_event` behavior when handling `'EXIT'`\n messages from the parent process. For more information see the `m:gen_server`,\n `m:gen_fsm`, and `m:gen_event` documentation.\n\n Own Id: OTP-8255 Aux Id: seq11419\n\n- The -on_load() directive can be used to run a function when a module is\n loaded. It is documented in the section about code loading in the Reference\n Manual.\n\n Own Id: OTP-8295","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.16.3.1 - STDLIB Release Notes","ref":"notes.html#stdlib-1-16-3-1"},{"type":"extras","doc":"- An erroneous type spec for `gen:start/6` caused dialyzer to erroneously issue\n warnings when `{spawn_opt, SpawnOptionList}` was passed in the option list to\n the `gen_server` and `gen_fsm` start functions.\n\n Own Id: OTP-8068 Aux Id: seq11323, seq11314","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 1.16.3 - STDLIB Release Notes","ref":"notes.html#stdlib-1-16-3"},{"type":"extras","doc":"- The linter used to crash on invalid `-opaque` declarations.\n\n Own Id: OTP-8051\n\n- Bugs in `digraph:add_edge/5` and `digraph:del_path/3` have been fixed. (Thanks\n to Crystal Din.)\n\n Own Id: OTP-8066\n\n- When trying to insert objects with `dets:insert_new()` into a Dets table of\n type `duplicate_bag`, already existing objects would sometimes be duplicated.\n This bug has been fixed. (Thanks to Crystal Din.)\n\n Own Id: OTP-8070\n\n- Running erlc in a very deep directory (with a path length of more 256 or more\n characters) would cause the emulator to crash in a call to\n [`list_to_atom/1`](`list_to_atom/1`). (Thanks to Chris Newcombe.)\n\n Own Id: OTP-8124\n\n- A few minor bugs have been fixed in the Erlang Code Preprocessor (`epp`).\n\n Own Id: OTP-8130\n\n- A bug in The Erlang Meta Interpreter (`erl_eval`) has been fixed: exceptions\n generated in the template of bit string comprehensions were not handled\n properly. (Thanks to Ulf Wiger.)\n\n Own Id: OTP-8133","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Option `{capture,none}` was missing in documentation for `re:run/3`.\n\n Own Id: OTP-8113\n\n- When [`erl_scan:tokens()`](`t:erl_scan:tokens/0`) returns an error tuple\n `{error, ErrorInfo, EndLocation`\\}, the list `LeftOverChars` is the remaining\n characters of the input data, starting from `EndLocation`. It used to be the\n empty list.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-8129\n\n- The Erlang Meta Interpreter (`erl_eval`) has been somewhat optimized when it\n comes to interpreting `receive`\\-expressions. (Thanks to Richard Carlsson.)\n\n Own Id: OTP-8139\n\n- The Erlang Pretty Printer (`erl_pp`) has been modified as to handle types.\n\n Own Id: OTP-8150","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.16.2 - STDLIB Release Notes","ref":"notes.html#stdlib-1-16-2"},{"type":"extras","doc":"- The text of tokens returned by the Erlang scanner (`erl_scan`) was sometimes\n empty when the `text` option was given and `StartLocation` was a line. This\n bug has been fixed.\n\n Own Id: OTP-7965\n\n- The documentation for `base64:decode/1` has been updated to point out that it\n strips whitespace.\n\n `base64:decode/1` and `base64:mime_decode/1` would sometimes fail instead of\n stripping away non-base64 characters.\n\n Own Id: OTP-7984\n\n- Two types in the `gen` module were corrected.\n\n Own Id: OTP-8029 Aux Id: seq11296\n\n- `array:from_orddict([])` and `array:from_list([])` would construct fixed\n arrays instead of extendible arrays.\n\n Own Id: OTP-8033","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Interpreted escripts are now tail recursive.\n\n The function erl_eval:expr/5 has been introduced.\n\n Own Id: OTP-7933\n\n- `gen_server:call/2,3` will be somewhat faster if the calling process has a\n many messages in its message queue.\n\n Own Id: OTP-7979\n\n- Random now supports seed with arity one, `random:seed/1`, which takes a\n three-tuple.\n\n Own Id: OTP-8019\n\n- The `regexp` module now recognizes the escape sequences `\\xXY` and `\\x{X...}`.\n\n Own Id: OTP-8024","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.16.1 - STDLIB Release Notes","ref":"notes.html#stdlib-1-16-1"},{"type":"extras","doc":"- The documentation of `dets:open_file/1` now states that the file is repaired\n if it has not been properly closed. (Thanks to Ulf Wiger.)\n\n Own Id: OTP-7895","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The Erlang scanner no longer returns the text of tokens when the start\n location is a pair of a line and column unless the new option `text` is\n supplied (incompatibility with R13A).\n\n There are new functions to access the attributes of tokens:\n `attributes_info/1,2` and `set_attribute/3`.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-7892 Aux Id: OTP-7810\n\n- Several glitches and performance issues in the Unicode and I/O-system\n implementation of R13A have been corrected.\n\n Own Id: OTP-7896 Aux Id: OTP-7648 OTP-7887\n\n- The type spec of filelib:wildcard/2 has been corrected.\n\n Own Id: OTP-7915\n\n- New functions: `gb_sets:is_disjoint/2`, `ordsets:is_disjoint/2`, and\n `gb_sets:is_disjoint/2`.\n\n Own Id: OTP-7947\n\n- The function `gb_trees:map/2` which was added in R13A is now documented.\n\n Own Id: OTP-7948","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.16 - STDLIB Release Notes","ref":"notes.html#stdlib-1-16"},{"type":"extras","doc":"- Fixed a minor race conditions in `gen_server:start*`: if one of these\n functions returned `{error,Reason}` or `ignore`, the name could still be\n registered (either locally or in `global`).\n\n A process started by `proc_lib` in some cases depended on its process\n dictionary not to be erased, and would crash when terminating abnormally and\n not generate a proper crash report. This has been corrected (but the initial\n call will not be shown in the error report if the process dictionary has been\n erased). NOTE: There is no longer any need to erase the process dictionary for\n memory conservation reasons, since the actual call arguments are no longer\n saved in the process dictionary.\n\n Own Id: OTP-7669\n\n- The Erlang preprocessor used wrong line number when stringifying macro\n arguments. (Thanks to John Hughes.)\n\n Own Id: OTP-7702\n\n- A bug in the `qlc` module has been fixed: merge join sometimes failed to\n return all answers. (Thanks to Bernard Duggan.)\n\n Own Id: OTP-7714","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- A new option, `key_equality`, has been added to `qlc:table/2`. This option\n makes it possible for `qlc` to better handle tables that use `==/2` when\n comparing keys for equality (examples of such tables are ordered ETS tables\n and gb_table in qlc(3)).\n\n Own Id: OTP-6674\n\n- The functions `lists:seq/1,2` return the empty list in a few cases when they\n used to generate an exception, for example `lists:seq(1, 0)`. See lists(3) for\n details. (Thanks to Richard O'Keefe.)\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-7230\n\n- The order of objects visited in select for ordered_set is now documented.\n\n Own Id: OTP-7339\n\n- It is now possible to debug code in escripts and archives.\n\n Own Id: OTP-7626\n\n- Support for Unicode is implemented as described in EEP10. Formatting and\n reading of unicode data both from terminals and files is supported by the io\n and io_lib modules. Files can be opened in modes with automatic translation to\n and from different unicode formats. The module 'unicode' contains functions\n for conversion between external and internal unicode formats and the re module\n has support for unicode data. There is also language syntax for specifying\n string and character data beyond the ISO-latin-1 range.\n\n The interactive shell will support input and output of unicode characters when\n the terminal and operating system supports it.\n\n Please see the EEP and the io/io_lib manual pages as well as the stdlib users\n guide for details.\n\n _I/O-protocol incompatibilities:_\n\n The io_protocol between io_Server and client is updated to handle protocol\n data in unicode formats. The updated protocol is now documented. The\n specification resides in the stdlib _users manual_, which is a new part of the\n manual.\n\n _io module incompatibilities:_\n\n The io:put_chars, io:get_chars and io:get_line all handle and return unicode\n data. In the case where binaries can be provided (as to io:put_chars), they\n shall be encoded in UTF-8. When binaries are returned (as by\n io:get_line/get_chars when the io_server is set in _binary mode_) the returned\n data is also _always_ encoded as UTF-8. The file module however still returns\n byte-oriented data, why file:read can be used instead of io:get_chars to read\n binary data in ISO-latin-1.\n\n _io_lib module incompatibilities:_\n\n io_lib:format can, given new format directives (i.e \"~ts\" and \"~tc\"), return\n lists containing integers larger than 255.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-7648 Aux Id: OTP-7580 OTP-7514 OTP-7494 OTP-7443 OTP-7181 EEP10\n EEP11\n\n- The function `pool:attach/1` now returns `already_attached` if the node is\n already attached, rather than `allready_attached` (sic\\!). (Thanks to Edwin\n Fine.)\n\n Own Id: OTP-7653 Aux Id: OTP-7603\n\n- Preprocessor directives are now allowed in escripts. This means that for\n example macros may be used in escripts.\n\n Own Id: OTP-7662\n\n- When a process started with `proc_lib`, `gen_server`, or `gen_fsm` exits with\n reason `{shutdown,Term}`, a crash report will no longer be generated (to allow\n a clean shutdown, but still provide additional information to process that are\n linked to the terminating process).\n\n Own Id: OTP-7740 Aux Id: seq10847\n\n- A new BIF, `lists:keyfind/3`, has been added. It works like\n `lists:keysearch/3` except that it does not wrap the returned tuple in a\n `value` tuple in case of success. (Thanks to James Hague for suggesting this\n function.)\n\n Own Id: OTP-7752\n\n- `lists:suffix(Suffix, List)` used to have a a complexity of\n `length(Suffix)*length(List)` (which could become quite slow for some inputs).\n It has now been re-implemented so that its complexity is\n `length(Suffix)+length(List)`. (Thanks to Richard O'Keefe for the new\n implementation.)\n\n Own Id: OTP-7797\n\n- The Erlang scanner has been augmented as to return white spaces, comments, and\n exact location of tokens. The functions `string/3`, `tokens/4`, and\n `token_info/1,2` are new. See erl_scan(3) for details.\n\n `tokens/3,4` have been modified as to return a list of tokens instead of an\n error when `eof` is encountered before the dot.\n\n Own Id: OTP-7810\n\n- `filelib:fold_files/5` now uses the `re` module instead of the `regexp` module\n for regular expression matching. In practice, this change will not be a\n problem for most regular expressions used for `filelib:fold_files/5`. (The\n major difference in regular expression is that parenthesis and curly brackets\n is treated as literal characters by `regexp` but as special characters by\n `re`; fortunately, those characters are rarely used in filenames.)\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-7819\n\n- `digraph:new(Type)` will now cause a `badarg` exception if `Type` is not a\n valid type. Similarly, `digraph_utils:subgraph/2,3` will now cause a `badarg`\n if the arguments are invalid. (Those functions used to return error tuples if\n something was wrong.)\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-7824\n\n- The argument passed to `random:uniform/1` must now be an integer (as stated in\n the documentation). In previous releases, a floating point number was also\n allowed.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-7827\n\n- The copyright notices have been updated.\n\n Own Id: OTP-7851\n\n- A few missing match spec functions was added to dbg:fun2ms; exception_trace/0\n and trace/2,3.\n\n There is a new function queue:member/2.\n\n A bug in io_lib:fread that made it accidentally concatenate fields separated\n by newline has been corrected. Reported and analyzed by Matthew Palmer to\n erlang-patches.\n\n Own Id: OTP-7865","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.15.5 - STDLIB Release Notes","ref":"notes.html#stdlib-1-15-5"},{"type":"extras","doc":"- A bug in the `qlc` module has been fixed: when merge joining two query handles\n the temporary file used for equivalence classes was not truncated properly\n which could result in poor performance.\n\n Own Id: OTP-7552\n\n- The characters 16#C0 and 16#E0 (\"A\" and \"a\" with grave accent), were not\n properly converted by the `string:to_lower/1` and `string:to_upper/1`\n functions. (Thanks to Richard O'Keefe.)\n\n Own Id: OTP-7589\n\n- The function `pool:attach/1` now returns `already_attached` if the node is\n already attached, rather than `allready_attached` (sic\\!). (Thanks to Edwin\n Fine.)\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-7603\n\n- The documentation for `io:get_line/1,2` now mentions that the return value can\n also be `{error,Reason}`.\n\n Own Id: OTP-7604 Aux Id: seq11063","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The split function is now added to the re library. Exceptions and errors from\n both run, replace and split are made more consistent.\n\n Own Id: OTP-7514 Aux Id: OTP-7494\n\n- Processes spawned using `proc_lib` (including `gen_server` and other library\n modules that use `proc_lib`) no longer keep the entire argument list for the\n initial call, but only the arity.\n\n Also, if `proc_lib:spawn/1` is used to spawn a fun, the actual fun is not\n kept, but only module, function name, and arity of the function that\n implements the fun.\n\n The reason for the change is that keeping the initial fun (or a fun in an\n argument list), would prevent upgrading the code for the module. A secondary\n reason is that keeping the fun and function arguments could waste a\n significant amount of memory.\n\n The drawback with the change is that the crash reports will provide less\n precise information about the initial call (only `Module:Function/Arity`\n instead of `Module:Function(Arguments)`). The function\n `proc_lib:initial_call/1` still returns a list, but each argument has been\n replaced with a dummy atom.\n\n Own Id: OTP-7531 Aux Id: seq11036\n\n- There is now experimental support for loading of code from archive files. See\n the documentation of `code`, `init`, `erl_prim_loader `and `escript` for more\n info.\n\n The error handling of `escripts` has been improved.\n\n An `escript` may now set explicit arguments to the emulator, such as\n `-smp enabled`.\n\n An `escript` may now contain a precompiled beam file.\n\n An `escript` may now contain an archive file containing one or more\n applications (experimental).\n\n The internal module `code_aux` has been removed.\n\n Own Id: OTP-7548 Aux Id: otp-6622\n\n- Enabled explicit control of which types of files that should be compressed in\n a ZIP archive.\n\n Own Id: OTP-7549 Aux Id: otp-6622\n\n- In the job control mode, the \"s\" and \"r\" commands now take an optional\n argument to specify which shell to start. (Thanks to Robert Virding.)\n\n Own Id: OTP-7617","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.15.4 - STDLIB Release Notes","ref":"notes.html#stdlib-1-15-4"},{"type":"extras","doc":"- A bug in the calendar module could cause\n calendar:local_time_to_universal_time_dst/1 to return duplicate identical\n values for local times in timezones without DST. Multiple values should only\n be returned when a local time is within the hour occurring twice due to shift\n from DST to non-DST, and certainly only in timezones with DST. The correct\n behaviour is now implemented.\n\n Own Id: OTP-7344 Aux Id: seq10960\n\n- The documentation of `(d)ets:init_table()` has been corrected. (Thanks to Paul\n Mineiro.)\n\n Own Id: OTP-7413\n\n- The soft upper limit of 60 on the number of non-white characters on a line,\n which was introduced in R12B-0 for the control sequences `p` and `P` of the\n functions `io:fwrite/2,3` and `io_lib:fwrite/2`, has been removed. This means\n that terms whose printed representation fits on a line will have no NEWLINEs.\n The Erlang shell still uses the 60 character limit, though.\n\n Own Id: OTP-7421 Aux Id: OTP-6708\n\n- Some debug code has been removed from Dets.\n\n Own Id: OTP-7424\n\n- The documentation of `dets:match_delete/2` has been corrected. (Thanks to Paul\n Mineiro.)\n\n Own Id: OTP-7445\n\n- Corrections of digraph(3). (Thanks to Vlad Dumitrescu.)\n\n Own Id: OTP-7492\n\n- For the process that an escript runs in, the `trap_exit` process flag is now\n `false` instead of `true` (as in previous releases). Scripts that depend on\n the previous (counter-intuitive) behaviour might not work. (Thanks to Bengt\n Kleberg.)\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-7517","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The documentation of `lists:(u)sort/2` now states what is expected of an\n ordering function.\n\n Own Id: OTP-7489\n\n- The re module is extended with repetitive matches (global option) and\n replacement function.\n\n Own Id: OTP-7494 Aux Id: OTP-7181\n\n- The Erlang shell now displays a nicer error message when evaluating an\n undefined command. (Thanks to Richard Carlsson.)\n\n Own Id: OTP-7495","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.15.3 - STDLIB Release Notes","ref":"notes.html#stdlib-1-15-3"},{"type":"extras","doc":"- zip:unzip to/from binary with empty directories did not work. (Thanks to\n Martin Dvorak.)\n\n Own Id: OTP-7248\n\n- The documentation of the control sequence `w` of the `io_lib` module now\n states that floating point numbers are printed accurately.\n\n Own Id: OTP-7324 Aux Id: OTP-7084\n\n- zip:unzip was not supporting a flavour of the zip format found in jar-files.\n\n Own Id: OTP-7382 Aux Id: seq10970","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- An experimental module \"re\" is added to the emulator which interfaces a\n publicly available regular expression library for Perl-like regular\n expressions (PCRE). The interface is purely experimental and _will_ be subject\n to change.\n\n The implementation is for reference and testing in connection to the relevant\n EEP.\n\n Own Id: OTP-7181","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.15.2 - STDLIB Release Notes","ref":"notes.html#stdlib-1-15-2"},{"type":"extras","doc":"- When inserting many small objects, Dets sometimes crashed when reaching the\n maximum number of slots. (Thanks to Daniel Goertzen.)\n\n Own Id: OTP-7146\n\n- Processes linked to the Erlang shell did not get an exit signal when the\n evaluator process was killed. This bug, introduced in R12B-0, has been fixed.\n\n Own Id: OTP-7184 Aux Id: OTP-6554\n\n- Invalid arguments to `ets:update_counter/3` were not handled correctly. A\n tuple position (`Pos`) less than 1 caused the element directly following the\n key to be updated (as if no position at all had been specified). All invalid\n values for `Pos` will now fail with `badarg`.\n\n Own Id: OTP-7226\n\n- For certain terminals, io:columns/0 could return 0 instead of enotsup. That is\n now corrected.\n\n Own Id: OTP-7229 Aux Id: seq10886\n\n- `qlc:info()` can now handle port identifiers, pids, references, and funs.\n (Thanks to Wojciech Kaczmare for reporting this bug.)\n\n When evaluating the `parent_fun` messages sent to the process calling\n `qlc:cursor()` were sometimes erroneously consumed. This bug has been fixed.\n\n Own Id: OTP-7232\n\n- `erl_parse:abstract()` can now handle bit strings.\n\n Own Id: OTP-7234","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The `queue` module has been rewritten to make it easier to use. Suggestions\n and discussion from and with among others Lev Walkin, Anders Ramsell and Rober\n Virding in december 2007 on erlang-questions@erlang.org. It was also discussed\n to change the internal representation to contain length information which\n would speed up `len/1` but that change has been postponed. Anyone interested\n may write an EEP and try to reach an acceptable compromise for queue overhead\n and thereby the speed of all other operations than `len/1`. The `queue` module\n is now optimized for fast and minimal garbage `in/2` and `out/1` and such. See\n the documentation.\n\n New functions: `is_queue/1`, [`get/1`](`get/1`), `get_r/1`, `peek/1`,\n `peek_r/1`, `drop/1`, `drop_r/1` and `liat/1`. `is_queue/1` is a new\n predicate, `liat/1` is a correction of an old misspelling, and the others\n (`get`\\*, `peek`\\* and `drop`\\*) are new interface functions.\n\n Own Id: OTP-7064\n\n- The functions `io_lib:write/1,2` and `io_lib:print/1,4` have been changed when\n it comes to writing floating point numbers. This change affects the control\n sequences `p`, `P`, `w`, and `W` of the `io_lib` module. (Thanks to Bob\n Ippolito for code contribution.)\n\n Own Id: OTP-7084\n\n- Updated the documentation for `erlang:function_exported/3` and `io:format/2`\n functions to no longer state that those functions are kept mainly for\n backwards compatibility.\n\n Own Id: OTP-7186\n\n- A new BIF ets:update_element/3. To update individual elements within an\n ets-tuple, without having to read, update and write back the entire tuple.\n\n Own Id: OTP-7200\n\n- `string:join/2` now accepts an empty list as first argument.\n\n Own Id: OTP-7231 Aux Id: OTP-6671\n\n- `qlc:info/1,2` accepts a new option, `depth`. The type `SelectedObjects` used\n in the description of `qlc:table/2` has been augmented.\n\n Own Id: OTP-7238\n\n- [`tuple_size/1`](`tuple_size/1`) and [`byte_size/1`](`byte_size/1`) have been\n substituted for [`size/1`](`size/1`) in the documentation.\n\n Own Id: OTP-7244","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.15.1 - STDLIB Release Notes","ref":"notes.html#stdlib-1-15-1"},{"type":"extras","doc":"- Ets:select/3 in combination with ets:repair_continuation/2 and ordered_set\n data tables could result in function_clause although used as intended. This is\n now corrected. Thanks to Paul Mineiro for finding and isolating the bug\\!\n\n Own Id: OTP-7025\n\n- The compiler warning for the deprecated function `ftp:close/1` now mentions\n the correct replacement function.\n\n The warning for the removed functions in the `httpd_util` module have been\n changed to say they have been removed, not merely deprecated. (Thanks to\n Fredrik Thulin.)\n\n Own Id: OTP-7034 Aux Id: seq10825\n\n- In `(Expr)#r{}` (no fields are updated), `Expr` is no longer evaluated more\n than once. There is also a test that `Expr` is of the correct record type.\n (Thanks to Dominic Williams.)\n\n Own Id: OTP-7078 Aux Id: OTP-4962\n\n- Documentation bugfixes and clarifications.\n\n (Thanks to Joern (opendev@gmail.com), Matthias Lang, and Richard Carlsson.)\n\n Own Id: OTP-7079\n\n- Duplicated objects were sometimes not deleted from the list of answers when a\n QLC table was traversed using a match specification. (Thanks to Dmitri\n Girenko.)\n\n Own Id: OTP-7114","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The documentation has been updated so as to reflect the last updates of the\n Erlang shell as well as the minor modifications of the control sequence `p` of\n the `io_lib` module.\n\n Superfluous empty lines have been removed from code examples and from Erlang\n shell examples.\n\n Own Id: OTP-6944 Aux Id: OTP-6554, OTP-6911\n\n- [`tuple_size/1`](`tuple_size/1`) and [`byte_size/1`](`byte_size/1`) have been\n substituted for [`size/1`](`size/1`).\n\n Own Id: OTP-7009\n\n- It is now possible to hibernate a gen_server/gen_event/gen_fsm. In gen_server\n and gen_fsm, hibernation is triggered by returning the atom\n 'hibernate' instead of a timeout value. In the gen_event case hibernation is\n triggered by a event handler returning a tuple with an extra element\n containing the atom 'hibernate'.\n\n Own Id: OTP-7026 Aux Id: seq10817\n\n- Some undocumented debug functionality has been added to Dets.\n\n Own Id: OTP-7066\n\n- The functions `digraph_utils:is_tree/1`, `digraph_utils:is_arborescence/1`,\n and `digraph_utils:arborescence_root/1` are new.\n\n Own Id: OTP-7081\n\n- The compiler could generate suboptimal code for record updates if the record\n update code consisted of multiple source code lines.\n\n Own Id: OTP-7101","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.15 - STDLIB Release Notes","ref":"notes.html#stdlib-1-15"},{"type":"extras","doc":"- Bugs have been fixed in `qlc`:\n\n - Setting the `lookup_fun` option of `qlc:table/2` to `undefined` could cause\n a crash.\n - If a QLC restricted some column of a table in such a way that a traversal\n using a match specification was possible and the QLC also compared the key\n column or some indexed column of the the table with a column of some other\n table, `qlc` always chose to traverse the table first, never considering\n lookup join. This has been changed so that lookup join is always preferred;\n if an initial traversal using the match specification is desired, the query\n needs to be rewritten introducing an extra QLC with the filter(s)\n restricting the column.\n - When trying to find candidates for match specifications and lookup, filters\n using variables from one generator only are ignored unless they are placed\n immediately after the generator and possibly other filters using variables\n from the same generator. In particular, filters joining two tables should\n not be placed between the generator and the filters using the generator\n only.\n - The call-back function `TraverseFun` used for implementing QLC tables is\n allowed to return a term other than a list since STDLIB 1.14 (OTP-5195).\n However, when the returned term was a fun `qlc` often tried to call the fun\n instead of returning it.\n\n A few minor optimizations have been implemented as well.\n\n Own Id: OTP-6673\n\n- A bug concerning the use of parameterized modules from the shell has been\n fixed.\n\n Own Id: OTP-6785\n\n- A bug regarding the size expression of the bit syntax has been fixed in the\n `erl_eval` module.\n\n Own Id: OTP-6787\n\n- The log_mf_h event handler didn't close the index file when it was done\n reading it causing a file descriptor leak.\n\n Own Id: OTP-6800\n\n- Definitions for the `filename()` and `dirname()` types have been added to the\n documentation for the `filelib` module.\n\n Own Id: OTP-6870\n\n- file:write_file/3, file:write/2 and file:read/2 could crash (contrary to\n documentation) for odd enough file system problems, e.g write to full file\n system. This bug has now been corrected.\n\n In this process the file module has been rewritten to produce better error\n codes. Posix error codes now originate from the OS file system calls or are\n generated only for very similar causes (for example 'enomem' is generated if a\n memory allocation fails, and 'einval' is generated if the file handle in\n Erlang is a file handle but currently invalid).\n\n More Erlang-ish error codes are now generated. For example `{error,badarg}` is\n now returned from `file:close/1` if the argument is not of a file handle type.\n See file(3).\n\n The possibility to write a single byte using `file:write/2` instead of a list\n or binary of one byte, contradictory to the documentation, has been removed.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-6967 Aux Id: OTP-6597 OTP-6291\n\n- A bug concerning the evaluation of the `++/2` operator has been fixed in\n `erl_eval`. (Thanks to Matthew Dempsky.)\n\n Own Id: OTP-6977","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The behaviour of the internal functions gen:call/3,4 has been changed slightly\n in the rare case that when the caller was linked to the called server, and the\n server crashed during the call; its exit signal was consumed by the\n gen:call/3,4 code and converted to an exit exception. This exit signal is no\n longer consumed.\n\n To even notice this change, 1) the calling process has to be linked to the\n called server.\n\n 2. the call must not be remote by name that is it must be local or remote by\n pid, local by name or global by name.\n\n 3. the calling process has to have set\n [`process_flag(trap_exit, true)`](`process_flag/2`).\n\n 4. the server has to crash during the call.\n\n 5. the calling process has to be sensitive to getting previously consumed\n `{'EXIT',Pid,Reason}` messages in its message queue.\n\n The old behaviour was once the only way for a client to notice if the server\n died, but has since `erlang:monitor(process, {Name,Node})` was introduced and\n used in gen:call been regarded as an undesired behaviour if not a bug.\n\n The affected user APIs are: `gen_server:call/2,3`,\n `gen_fsm:sync_send_event/2,3`, `gen_fsm:sync_send_all_state_event/2,3`,\n `gen_event:_`, `sys:_` and maybe a few others that hardly will be noticed.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-3954 Aux Id: Seq 4538\n\n- When an exception occurs the Erlang shell now displays the class, the reason,\n and the stacktrace in a clearer way (rather than dumping the raw EXIT tuples\n as before). `proc_lib:format/1` displays the exception of crash reports in the\n same clearer way.\n\n The new shell command `catch_exception` and the new application configuration\n parameter `shell_catch_exception` can be used for catching exceptions that\n would normally exit the Erlang shell.\n\n Own Id: OTP-6554 Aux Id: OTP-6289\n\n- The function `string:join/2` joins strings in a list with a separator.\n Example: '`string:join([\"a\", \"b\", \"c\"], \", \") gives \"a, b, c\"`'\n\n Own Id: OTP-6671\n\n- The control sequence `P` of the `Format` argument of the functions\n `io:fwrite/2,3` and `io_lib:fwrite/2` now inserts fewer line breaks when\n printing tuples and lists. A soft upper limit of 60 on the number of non-white\n characters on a line has been introduced.\n\n Own Id: OTP-6708\n\n- The new module `array` provides a fast functional array implementation.\n\n Own Id: OTP-6733\n\n- Functions that have long been deprecated have now been removed from the\n following modules: `dict`, `erl_eval`, `erl_pp`, `io`, `io_lib`, `lists`,\n `orddict`, `ordsets`, `sets`, and `string`.\n\n The undocumented function `lists:zf/3` has also been removed (use a list\n comprehension or `lists:zf/2` instead).\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-6845\n\n- Minor documentation corrections for file:pread/2 and file:pread/3.\n\n Own Id: OTP-6853\n\n- Contract directives for modules in Kernel and STDLIB.\n\n Own Id: OTP-6895\n\n- The `ets:fixtable/2` function, which has been deprecated for several releases,\n has been removed.\n\n The `ets:info/1` function has been reimplemented as a BIF, which guarantees\n that information returned is consistent.\n\n The `ets:info/2` function now fails with reason `badarg` if the second\n argument is invalid. (Dialyzer can be used to find buggy code where the second\n argument is misspelled.)\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-6906\n\n- The Erlang pretty printer `erl_pp` now inserts more newlines in order to\n facilitate line coverage analysis by `Cover`. (Thanks to Thomas Arts.)\n\n Own Id: OTP-6911\n\n- The documentation for ets:safe_fixtable/2, ets:foldl/3, and ets:foldr/3 is now\n clearer about what will happen if objects are inserted during table\n traversals.\n\n Own Id: OTP-6928 Aux Id: seq10779\n\n- It is now possible to extract files in tar files directly into binaries. It is\n also possible to add files to tar files directly from binaries.\n\n Own Id: OTP-6943\n\n- The functions `keystore/4` and `keytake/3` are new in the `lists` module.\n\n Own Id: OTP-6953\n\n- The new `qlc` option `tmpdir_usage` can be used for outputting messages onto\n the error logger when a temporary file is about to be created, or to prohibit\n the usage of temporary files altogether.\n\n Own Id: OTP-6964","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.14.5.3 - STDLIB Release Notes","ref":"notes.html#stdlib-1-14-5-3"},{"type":"extras","doc":"- The allowed syntax for -type() and -spec() was updated.\n\n Own Id: OTP-6861 Aux Id: OTP-6834","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.14.5.2 - STDLIB Release Notes","ref":"notes.html#stdlib-1-14-5-2"},{"type":"extras","doc":"- The compiler will for forward compatibility ignore the -type() and -spec()\n attributes that will be introduced in the R12B release.\n\n Own Id: OTP-6834","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.14.5.1 - STDLIB Release Notes","ref":"notes.html#stdlib-1-14-5-1"},{"type":"extras","doc":"- The log_mf_h event handler didn't close the index file when it was done\n reading it causing a file descriptor leak.\n\n Own Id: OTP-6800","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The dict:size/1 and orddict:size/1 functions have been documented.\n\n Own Id: OTP-6818","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.14.5 - STDLIB Release Notes","ref":"notes.html#stdlib-1-14-5"},{"type":"extras","doc":"- Bugs have been fixed in Dets concerning comparison (==) and matching (=:=).\n\n The STDLIB manual pages have been updated as to more carefully state when\n terms are matched and when they are compared.\n\n Own Id: OTP-4738 Aux Id: OTP-4685\n\n- The shell has been updated to fix the following flaws: Shell process exit left\n you with an unresponsive initial shell if not using oldshell. Starting a\n restricted shell with a nonexisting callback module resulted in a shell where\n no commands could be used, not even init:stop/0. Fun's could not be used as\n parameters to local shell functions (in shell_default or user_default) when\n restricted_shell was active.\n\n Own Id: OTP-6537\n\n- A bug in QLC's parse transform has been fixed.\n\n Own Id: OTP-6590\n\n- A bug concerning `lists:sort/1` and `lists:keysort/2` and a mix of floating\n point numbers and integers has been fixed.\n\n Own Id: OTP-6606\n\n- When calling `erlang:garbage_collect/0` in the Erlang shell not only the\n evaluator process (the one returned by calling `self/0` in the Erlang shell)\n is garbage collected, but also the process holding the history list.\n\n Own Id: OTP-6659\n\n- Functions of the `beam_lib` module that used to catch exceptions and return a\n tuple `{'EXIT',Reason}` now exit with the reason `Reason`.\n\n Own Id: OTP-6711\n\n- The `erl_eval` module now calls the non-local function handler whenever an\n operator is evaluated (exceptions are `andalso`, `orelse`, and `catch`). The\n non-local function handler is now also called when the function or operator\n occurs in a guard test (such calls used to be ignored).\n\n These changes affect the Erlang shell when running in restricted mode: the\n callback function `non_local_allowed/3` is now called for operators such as\n `'!'/2`. This means that `non_local_allowed/3` may need to\n be changed as to let operators through. Note that `erlang:'!'/2` as well as\n `erlang:send/2,3` have to be restricted in order to stop message passing in\n the shell.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-6714 Aux Id: seq10374","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The new compiler option `warn_obsolete_guard` can be used for turning on\n warnings for calls to old type testing BIFs.\n\n Own Id: OTP-6585\n\n- For scripts written using `escript`, there is a new function\n `escript:script_name/0`, which can be used to retrieve the pathame of the\n script. The documentation has been clarified regarding pre-defined macros such\n as ?MODULE and the module name.\n\n Own Id: OTP-6593\n\n- Minor Makefile changes.\n\n Own Id: OTP-6689 Aux Id: OTP-6742","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.14.4 - STDLIB Release Notes","ref":"notes.html#stdlib-1-14-4"},{"type":"extras","doc":"- The MD5 calculation of a BEAM file done by `code:module_md5/1`,\n `beam_lib:md5/1`, and by the compiler for the default value of the `vsn`\n attribute have all been changed so that its result will be the same on all\n platforms; modules containing funs could get different MD5s on different\n platforms.\n\n Own Id: OTP-6459\n\n- When sorting terms using the `file_sorter` module (the option `Format` set to\n `term`), file errors were not always properly handled. This bug has been\n fixed.\n\n The directory supplied with the `tmpdir` option is no longer checked unless it\n is actually used. The error reason `not_a_directory` can no longer be\n returned; instead a `file_error` tuple is returned\n\n Own Id: OTP-6526\n\n- Bugs regarding `try`/`catch` have been fixed in the `erl_eval` module.\n\n Own Id: OTP-6539\n\n- When sorting the operands of a join operation, QLC called `file:open/3` with\n bad arguments. This bug has been fixed.\n\n Own Id: OTP-6562 Aux Id: seq10606","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The functions `beam_lib:cmp/1` and `beam_lib:strip/1` (and similar functions)\n have been updated to handle optional chunks (such as \"FunT\") in more general\n way in order to be future compatible.\n\n The function `beam_lib:chunks/3` has been added.\n\n The function `beam_lib:md5/1` has been added.\n\n Own Id: OTP-6443\n\n- Added base64 as a module to stdlib, encoding and decoding\n\n Own Id: OTP-6470\n\n- Added the functions to_upper/1 and to_lower/1 to the string module. These\n provide case conversion for ISO/IEC 8859-1 characters (Latin1) and strings.\n\n Own Id: OTP-6472\n\n- The callback function `non_local_allowed/3` used by the restricted shell can\n now return the value `{{restricted,NewFuncSpec,NewArgList},NewState}` which\n can be used for letting the shell call some other function than the one\n specified.\n\n Own Id: OTP-6497 Aux Id: seq10555\n\n- There is a new `escript` program that can be used for writing scripts in\n Erlang. Erlang scripts don't need to be compiled and any arguments can be\n passed to them without risk that they are interpreted by the Erlang system.\n\n Own Id: OTP-6505\n\n- The `Format` argument of the functions `io:fwrite/2,3` and `io_lib:fwrite/2`\n is now allowed to be a binary.\n\n Own Id: OTP-6517","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.14.3.1 - STDLIB Release Notes","ref":"notes.html#stdlib-1-14-3-1"},{"type":"extras","doc":"- The control sequences `p` and `P` of the `Format` argument of the functions\n `io:fwrite/2,3` and `io_lib:fwrite/2` could cause a `badarg` failure when\n applied to binaries. This bug was introduced in STDLIB 1.14.3. (Thanks to\n Denis Bilenko.)\n\n Own Id: OTP-6495","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Added the option \\{cwd, Dir\\} to make zip-archives with relative pathnames\n without having to do (a global) file:set_cwd.\n\n Own Id: OTP-6491 Aux Id: seq10551","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.14.3 - STDLIB Release Notes","ref":"notes.html#stdlib-1-14-3"},{"type":"extras","doc":"- The `spawn_opt/2,3,4,5` option `monitor` \\-- introduced in Kernel 2.11.2 -- is\n currently not possible to use when starting a process using `proc_lib`, that\n is, also when starting a gen_server, gen_fsm etc.\n\n This limitation has now been properly documented and the behavior of the\n `gen_fsm`, `gen_server`, and `proc_lib` `start` and `start_link` functions\n when providing this option has been changed from hanging indefinitely to\n failing with reason `badarg`.\n\n (Thanks to Fredrik Linder)\n\n Own Id: OTP-6345","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The control sequence `P` of the `Format` argument of the functions\n `io:fwrite/2,3` and `io_lib:fwrite/2` now replaces the tail of binary strings\n with `...` when the maximum depth has been reached. For instance,\n `io:fwrite(\"~P\", [<<\"a binary string\">>, 3]).` prints `<<\"a binary\"...>>`.\n\n The indentation takes more care not to exceed the right margin, if possible.\n\n If the maximum depth is reached while printing a tuple, `,...` is printed\n instead of `|...` (this change applies to the control sequence `W` as well).\n\n Own Id: OTP-6354\n\n- The Erlang shell command `h/0` that prints the history list now avoids\n printing (huge) terms referred to by `v/1` but instead just prints the call to\n `v/1`.\n\n Own Id: OTP-6390","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.14.2.2 - STDLIB Release Notes","ref":"notes.html#stdlib-1-14-2-2"},{"type":"extras","doc":"- The functions `dets:select/1,3`, `dets:match/1,3`, and `dets:match_object/1,3`\n have been changed as to never return `{[],Continuation}`. This change affects\n the corresponding functions in Mnesia.\n\n Bugs have been fixed in QLC: `qlc:info()` could crash if the `tmpdir` option\n did not designate a valid directory; the results of looking up keys are kept\n in RAM, which should improve performance.\n\n Own Id: OTP-6359","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 1.14.2.1 - STDLIB Release Notes","ref":"notes.html#stdlib-1-14-2-1"},{"type":"extras","doc":"- A bug in `erl_pp:exprs()` has been fixed.\n\n Own Id: OTP-6321 Aux Id: seq10497","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 1.14.2 - STDLIB Release Notes","ref":"notes.html#stdlib-1-14-2"},{"type":"extras","doc":"- The control sequences `p` and `P` of the `Format` argument of the functions\n `io:format/2,3` and `io_lib:format/2` did not handle binaries very well. This\n bug, introduced in stdlib-1.14, has been fixed.\n\n Own Id: OTP-6230\n\n- `filelib:wildcard(Wc, PathWithRedundantSlashes)`, where\n `PathWithRedundantSlashes` is a directory path containing redundant slashes,\n such as `/tmp/` or `//tmp`, could return incorrect results. (Thanks to Martin\n Bjorklund.)\n\n Own Id: OTP-6271\n\n- The Erlang code preprocessor crashed if the predefined macros ?MODULE or\n ?MODULE_STRING were used before the module declaration. This bug has been\n fixed.\n\n Own Id: OTP-6277","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Support for faster join of two tables has been added to the `qlc` module.\n There are two kinds of fast joins: lookup join that uses existing indices, and\n merge join that takes two sorted inputs. There is a new `join` option that can\n be used to force QLC to use a particular kind of join in some QLC expression.\n\n Several other changes have also been included:\n\n - The new `tmpdir` option of `cursor/2`, `eval/2`, `fold/4`, and `info/2` can\n be used to set the directory that join uses for temporary files. The option\n also overrides the `tmpdir` option of `keysort/3` and `sort/2`.\n - The new `lookup` option can be used to assert that constants are looked up\n when evaluating some QLC expression.\n - The `cache` and `cache_all` options accept new tags: `ets`, `list`, and\n `no`. The tag `list` caches answers in a list using a temporary file if the\n answers cannot be held in RAM. Combining `{cache,list}` and `{unique, true}`\n is equivalent to calling `sort/2` with the option `unique` set to `true`.\n The old tags `true` (equivalent to `ets`) and `false` (equivalent to `no`)\n are recognized for backward compatibility.\n - The new option `max_list_size` can be used to set the limit where merge join\n starts to use temporary files for large equivalence classes and when answers\n cached in lists are put on temporary files.\n - There is a new callback `is_sorted_key` to be supplied as an option to\n `table/2`.\n - QLC analyzes each and every QLC expression when trying to find constants for\n the lookup function. Hitherto only QLC expressions with exactly one\n generator were analyzed.\n\n Note that only filters with guard syntax placed immediately after the\n generator are analyzed. The restriction to guard filters is an incompatible\n change. See `m:qlc` for further details.\n\n - In a similar way several match specifications for traversal of QLC tables\n can be utilized for different generators of one single QLC expression.\n - A bug has been fixed: when caching answers to a sufficiently complex query\n it could happen that some answers were not returned.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-6038\n\n- The Erlang pretty printer (`erl_pp`) is now much faster when the code is\n deeply nested. A few minor bugs have been fixed as well.\n\n Own Id: OTP-6227 Aux Id: OTP-5924\n\n- The Erlang shell now tries to garbage collect large binaries. Under certain\n circumstances such binaries could otherwise linger on for an indefinite amount\n of time.\n\n Own Id: OTP-6239\n\n- To help Dialyzer find more bugs, many functions in the Kernel and STDLIB\n applications now only accept arguments of the type that is documented.\n\n For instance, the functions `lists:prefix/2` and `lists:suffix/2` are\n documented to only accept lists as their arguments, but they actually accepted\n anything and returned `false`. That has been changed so that the functions\n cause an exception if one or both arguments are not lists.\n\n Also, the `string:strip/3` function is documented to take a character argument\n that is a character to strip from one or both ends of the string. Given a list\n instead of a character, it used to do nothing, but will now cause an\n exception.\n\n Dialyzer will find most cases where those functions are passed arguments of\n the wrong type.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-6295","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.14.1 - STDLIB Release Notes","ref":"notes.html#stdlib-1-14-1"},{"type":"extras","doc":"- The functions `c:y/1,2` which call `yecc:file/1,2` are now listed by\n `c:help/0`.\n\n Documentation of `c:y/1,2` has been added to `m:c`.\n\n The fact that the control sequence character `s` recognizes binaries and deep\n character lists has been documented in `m:io`. This feature was added in\n R11B-0 (OTP-5403).\n\n Own Id: OTP-6140\n\n- The shell command rr() sometimes failed to read record definitions from\n file(s). This problem has been fixed.\n\n Own Id: OTP-6166 Aux Id: OTP-5878\n\n- The nonlocal function handler in `erl_eval`, which is used for implementing\n the restricted mode of the Erlang shell, did not handle calls to\n `erlang:apply/3` correctly. This bug has been fixed.\n\n Own Id: OTP-6169 Aux Id: seq10374\n\n- ets:rename/1 could deadlock, or crash the SMP emulator when the table wasn't a\n named table.\n\n ets:next/2, and ets:prev/2 could return erroneous results on the SMP emulator.\n\n Own Id: OTP-6198 Aux Id: seq10392, seq10415\n\n- When closing a Dets table the space management data was sometimes saved in\n such a way that opening the table could not be done without repairing the\n file. This bug has been fixed.\n\n Own Id: OTP-6206","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 1.14 - STDLIB Release Notes","ref":"notes.html#stdlib-1-14"},{"type":"extras","doc":"- A bugfix in QLC: two of the call-back functions used for implementing QLC\n tables, `TraverseFun` and `LookupFun`, are now allowed to return a term other\n than a list. Such a term is immediately returned as the results of the current\n query, and is useful mostly for returning error tuples.\n\n Several other minor bugs have been also been fixed.\n\n Own Id: OTP-5195\n\n- The STDLIB modules `error_logger_file_h` and `error_logger_tty_h` now read the\n environment variable `utc_log` from the SASL application.\n\n Own Id: OTP-5535\n\n- `ets:info/1` has been corrected to behave according to the documentation and\n return a list of tuples, not a tuple with tuples.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-5639\n\n- Referencing a so far undeclared record from the default value of some record\n declaration is from now on considered an error by the linter. It is also an\n error if the default value of a record declaration uses or binds a variable.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-5878\n\n- When a file `.hrl` file is included using `-include_lib`, the include path is\n temporarily updated to include the directory the `.hrl` file was found in,\n which will allow that `.hrl` file to itself include files from the same\n directory as itself using `-include`. (Thanks to Richard Carlsson.)\n\n Own Id: OTP-5944\n\n- Corrected `filelib:ensure_dir/1` which sometimes returned `true` and sometimes\n `ok` to always return `ok` when successful. This goes against the\n documentation which said `true`, but `ok` was judged to be a more logical\n return value.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-5960 Aux Id: seq10240\n\n- The shell now handles records better when used in calls on the form\n `{Module, Function}(ArgList)`.\n\n Own Id: OTP-5990 Aux Id: OTP-5876\n\n- The functions `lists:ukeysort/2` and `lists:ukeymerge/3` have been changed in\n such a way that two tuples are considered equal if their keys match.\n\n For the sake of consistency, `lists:usort/2` and `lists:umerge/3` have been\n modified too: two elements are considered equal if they compare equal.\n\n The `file_sorter` module has been modified in a similar way: the `unique`\n option now applies to the key (`keysort()` and `keymerge()`) and the ordering\n function (the option `{order, Order} `).\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-6019\n\n- Correction in documentation for `ets:update_counter/3`; failure with `badarg`\n also if the counter to be updated is the key.\n\n Own Id: OTP-6072\n\n- When sorting terms using the `file_sorter` module and an ordering fun, the\n sort was not always stable. This bug has been fixed.\n\n Own Id: OTP-6088","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Improvements of the linter:\n\n - The `compile` attribute is recognized after function definitions.\n - The new compiler option `nowarn_deprecated_function` can be used for turning\n off warnings for calls to deprecated functions.\n - The new compiler option `{nowarn_unused_function,[{Name,Arity}]}` turns off\n warnings for unused local functions for the mentioned functions. The new\n options `{nowarn_deprecated_function,[{Module,Name,Arity}]}` and\n `{nowarn_bif_clash,[{Name,Arity}]}` work similarly.\n\n The Erlang code preprocessor `epp` now recognizes the `file` attribute. This\n attribute is meant to be used by tools such as Yecc that generate source code\n files.\n\n Own Id: OTP-5362\n\n- The formatting option `~s` of `io:fwrite` and `io_lib:fwrite` has been\n extended to handle arguments that are binaries or I/O lists.\n\n Own Id: OTP-5403\n\n- The control sequences `p` and `P` of the `Format` argument of the functions\n `io:format/2,3` and `io_lib:format/2` have been changed as to display the\n contents of binaries containing printable characters as strings.\n\n Own Id: OTP-5485\n\n- The linter emits warnings for functions exported more than once in `export`\n attributes.\n\n Own Id: OTP-5494\n\n- A manual for STDLIB has been added, `stdlib(6)`. It mentions the configuration\n parameters for the Erlang shell.\n\n Own Id: OTP-5530\n\n- Added the `zip` module with functions for reading and creating zip archives.\n See `m:zip`.\n\n Own Id: OTP-5786\n\n- Simple-one-for-one supervisors now store the pids of child processes using\n `dict` instead of a list. This significantly improves performance when there\n are many dynamic supervised child processes. (Thanks to Mickaël Rémond et al.)\n\n Own Id: OTP-5898\n\n- When given the new option '`strict_record_tests`', the compiler will generate\n code that verifies the record type for '`R#record.field`' operations in\n guards. Code that verifies record types in bodies has already been generated\n since R10B, but in this release there will be a '`{badrecord,RecordTag}`'\n instead of a '`badmatch`' if the record verification test fails. See the\n documentation for the `compile` module for more information.\n\n The Erlang shell always applies strict record tests.\n\n Own Id: OTP-5915 Aux Id: OTP-5714\n\n- The Erlang pretty printer (`erl_pp`) now tries to insert line breaks at\n appropriate places.\n\n Own Id: OTP-5924\n\n- The `public` option has been removed from `digraph:new/1`. The reason is that\n several functions in the `digraph` module are implemented using multiple ETS\n accesses, which is not thread safe. (Thanks to Ulf Wiger.)\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-5985\n\n- The function `lists:keyreplace/4` checks that the fourth argument (`NewTuple`)\n is a tuple.\n\n Own Id: OTP-6023\n\n- Added an example of how to reconstruct source code from debug info (abstract\n code) to `m:beam_lib`. (Thanks to Mats Cronqvist who wrote the example.)\n\n Own Id: OTP-6073\n\n- The new compiler option `warn_unused_record` is used for finding unused\n locally defined record types.\n\n Own Id: OTP-6105","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.13.12 - STDLIB Release Notes","ref":"notes.html#stdlib-1-13-12"},{"type":"extras","doc":"- `shell_default:xm/1` has been added. It calls `xref:m/1`.\n\n Own Id: OTP-5405 Aux Id: OTP-4101\n\n- Warnings are output whenever so far undeclared records are referenced from\n some default value of a record declaration. In STDLIB 1.14 (R11B) such forward\n references will cause a compilation error.\n\n Own Id: OTP-5878\n\n- The linter's check of the `deprecated` attribute did not take the compile\n option `export_all` into account. This bug has been fixed.\n\n Own Id: OTP-5917\n\n- The Erlang pretty printer did not handle `try/catch` correctly. This bug has\n been fixed.\n\n Own Id: OTP-5926\n\n- Corrected documentation for `lists:nthtail/3`.\n\n Added documentation for `lists:keymap/3`.\n\n Tried to clarify some other type declarations and function descriptions in\n `m:lists`.\n\n Corrected documentation for `timer:now_diff/2`.\n\n Fixed broken links in `m:gen_fsm`, `m:gen_server`, `m:io_lib` and `lib(3)`.\n\n Own Id: OTP-5931\n\n- Type checks have been added to functions in `lists.erl`.\n\n Own Id: OTP-5939","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The new STDLIB module `erl_expand_records` expands records in abstract code.\n It is used by the Erlang shell, which means that Compiler is no longer used by\n the shell.\n\n Own Id: OTP-5876 Aux Id: OTP-5435\n\n- The compiler will now warn that the `megaco:format_versions/1` function is\n deprecated.\n\n Own Id: OTP-5976","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.13.11 - STDLIB Release Notes","ref":"notes.html#stdlib-1-13-11"},{"type":"extras","doc":"- When calling `gen_server:enter_loop` with a registered server name, it was\n only checked that the registered name existed, not that it actually was the\n name of the calling process.\n\n Own Id: OTP-5854","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- More detail on `beam_lib:version/1` in documentation.\n\n Own Id: OTP-5789\n\n- The new function `io:read/3` works like `io:read/1,2` but takes a third\n argument, `StartLine`.\n\n Own Id: OTP-5813\n\n- The new function `gen_fsm:enter_loop/4,5,6`, similar to\n `gen_server:enter_loop/3,4,5`, has been added.\n\n Own Id: OTP-5846 Aux Id: seq10163\n\n- The function `c:i/1` is now exported.\n\n Own Id: OTP-5848 Aux Id: seq10164","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.13.10 - STDLIB Release Notes","ref":"notes.html#stdlib-1-13-10"},{"type":"extras","doc":"- A couple of type errors have been fixed in `sofs`.\n\n Own Id: OTP-5739\n\n- The pre-processor used to complain that the macro definition\n '`-define(S(S), ??S).`' was circular, which it isn't. (Thanks to Richard\n Carlsson.)\n\n Own Id: OTP-5777","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"STDLIB 1.13.9 - STDLIB Release Notes","ref":"notes.html#stdlib-1-13-9"},{"type":"extras","doc":"- The linter, QLC and the module `erl_pp` did not handle the new '`fun M:F/A`'\n construct in all situations. This problem has been fixed.\n\n Own Id: OTP-5644","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The manual pages for most of the Kernel and some of the STDLIB modules have\n been updated, in particular regarding type definitions.\n\n The documentation of the return value for `erts:info/1` has been corrected.\n\n The documentation for `erlang:statistics/1` now lists all possible arguments.\n\n Own Id: OTP-5360\n\n- Replaced some tuple funs with the new `fun M:F/A` construct.\n\n The high-order functions in the lists module no longer accept bad funs under\n any circumstances. '`lists:map(bad_fun, [])`' used to return '`[]`' but now\n causes an exception.\n\n Unused, broken compatibility code in the `ets` module was removed. (Thanks to\n Dialyzer.)\n\n Eliminated 5 discrepancies found by Dialyzer in the Appmon application.\n\n Own Id: OTP-5633\n\n- The `c:i/0` function will now run in a paged mode if there are more than 100\n processes in the system. (Thanks to Ulf Wiger.)\n\n `erlang:system_info(process_count)` has been optimized and does now return\n exactly the same value as [`length(processes())`](`length/1`). Previously\n `erlang:system_info(process_count)` did not include exiting processes which\n are included in [`length(processes())`](`length/1`).\n\n The `+P` flag for `erl`, which sets the maximum number of processes allowed to\n exist at the same, no longer accepts values higher than 134217727. (You will\n still probably run out of memory before you'll be able to reach that limit.)\n\n Own Id: OTP-5645 Aux Id: seq9984","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.13.8 - STDLIB Release Notes","ref":"notes.html#stdlib-1-13-8"},{"type":"extras","doc":"- Very minor corrections in `beam_lib` and its documentation.\n\n Own Id: OTP-5589","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The `erlang:port_info/1` BIF is now documented. Minor corrections of the\n documentation for `erlang:port_info/2`.\n\n Added a note to the documentation of the `math` module that all functions are\n not available on all platforms.\n\n Added more information about the '`+c`' option in the `erl` man page in the\n ERTS documentation.\n\n Own Id: OTP-5555\n\n- The new `fun M:F/A` construct creates a fun that refers to the latest version\n of `M:F/A`. This syntax is meant to replace tuple funs `{M,F}` which have many\n problems.\n\n The new type test [`is_function(Fun,A)`](`is_function/2`) (which may be used\n in guards) test whether `Fun` is a fun that can be applied with `A` arguments.\n (Currently, `Fun` can also be a tuple fun.)\n\n Own Id: OTP-5584","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.13.7 - STDLIB Release Notes","ref":"notes.html#stdlib-1-13-7"},{"type":"extras","doc":"- `filelib:wildcard/2` was broken (it ignored its second argument).\n\n Also, `filelib:wildcard(\"Filename\")` (where the argument does not contain any\n meta-characters) would always return `[\"Filename\"]`. Corrected so that an\n empty list will be returned if `\"Filename\"` does not actually exist. (Same\n correction in `filelib:wildcard/2`.) (This change is a slight\n incompatibility.)\n\n `filelib:wildcard/1,2` will generate a different exception when given bad\n patterns such as `\"{a,\"`. The exception used to be caused by\n '[`exit(missing_delimiter)`](`exit/1`)' but is now\n '`erlang:error({badpattern,missing_delimiter})`'.\n\n Own Id: OTP-5523 Aux Id: seq9824","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Further improvements of encrypted debug info: New option `encrypt_debug_info`\n for compiler.\n\n Own Id: OTP-5541 Aux Id: seq9837","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.13.6 - STDLIB Release Notes","ref":"notes.html#stdlib-1-13-6"},{"type":"extras","doc":"- When opening a Dets table read only an attempt was sometimes made to re-hash\n the table resulting in an error message. This problem has been fixed.\n\n Own Id: OTP-5487 Aux Id: OTP-4989","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- It is now possible to encrypt the debug information in Beam files, to help\n keep the source code secret. See the documentation for `compile` on how to\n provide the key for encrypting, and the documentation for `beam_lib` on how to\n provide the key for decryption so that tools such as the Debugger, Xref, or\n Cover can be used.\n\n The `beam_lib:chunks/2` functions now accepts an additional chunk type\n `compile_info` to retrieve the compilation information directly as a term.\n (Thanks to Tobias Lindahl.)\n\n Own Id: OTP-5460 Aux Id: seq9787","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.13.5 - STDLIB Release Notes","ref":"notes.html#stdlib-1-13-5"},{"type":"extras","doc":"- Closing a Dets table kept in RAM would cause a crash if the file could not be\n written. This problem has been fixed by returning an error tuple.\n\n Own Id: OTP-5402\n\n- `erl_pp` now correctly pretty-prints `fun F/A`.\n\n Own Id: OTP-5412\n\n- The Erlang shell failed if the compiler was not in the code path. This problem\n has been fixed, but in order to evaluate records the compiler is still needed.\n\n Own Id: OTP-5435\n\n- Corrected the example in the documentation for `ets:match/2`. Also clarified\n that `ets:update_counter/3` updates the counter atomically. (Thanks to Anders\n Svensson.)\n\n Own Id: OTP-5452 Aux Id: seq9770, seq9789","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The possibility to start the Erlang shell in parallel with the rest of the\n system was reintroduced for backwards compatibility in STDLIB 1.13.1. The flag\n to be used for this is now called `async_shell_start` and has been documented.\n New shells started from the JCL menu are not synchronized with `init` anymore.\n This makes it possible to start a new shell (e.g. for debugging purposes) even\n if the initial shell has not come up.\n\n Own Id: OTP-5406 Aux Id: OTP-5218\n\n- The compiler will now produce warnings when using the deprecated functions in\n the `snmp` module.\n\n Own Id: OTP-5425\n\n- The function `c:zi/0` has been removed. Use `c:i/0` instead.\n\n Own Id: OTP-5432\n\n- Corrected two minor bugs found by the Dialyzer: Calling a parameterized module\n from a restricted shell (i.e. if `shell:start_restricted/1` has been used)\n would crash the shell evaluator. A debug printout in `gen_fsm` had a clause\n that would never match; causing less information to be printed.\n\n And a somewhat more serious one also found by Dialyzer: `rpc:yield/1` would\n crash unless the call started by `rpc:async_call/4` had already finished;\n `rpc:nb_yield(Key,infinity)` would also crash.\n\n Cleaned up and removed redundant code found by Dialyzer in\n `erlang:dmonitor_p/2`.\n\n Own Id: OTP-5462","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.13.4 - STDLIB Release Notes","ref":"notes.html#stdlib-1-13-4"},{"type":"extras","doc":"- Bugs in the Erlang shell have been fixed.\n\n Own Id: OTP-5327\n\n- Some dead code reported by Dialyzer was eliminated.\n\n A bug in `dbg` when tracing to wrap trace files has been corrected. It failed\n to delete any already existing wrap trace files with the same names when\n starting a new wrap trace.\n\n Own Id: OTP-5329\n\n- The linter could output invalid warnings about bit patterns in record\n initializations. This problem has been fixed.\n\n Own Id: OTP-5338\n\n- `ordsets:is_set(NoList)`, where `NoList` is any term except a list, would\n crash. For consistency with `sets:is_set/1` and `gb_sets:is_set/1`, it now\n returns `false`.\n\n Own Id: OTP-5341\n\n- A BIF `erlang:raise/3` has been added. See the manual for details. It is\n intended for internal system programming only, advanced error handling.\n\n Own Id: OTP-5376 Aux Id: OTP-5257","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The `deprecated` attribute is now checked by the linter. See `m:xref` for a\n description of the `deprecated` attribute.\n\n Own Id: OTP-5276\n\n- The restricted shell will now indicate if the return value from a user\n predicate is on an incorrect form.\n\n Own Id: OTP-5335","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.13.3 - STDLIB Release Notes","ref":"notes.html#stdlib-1-13-3"},{"type":"extras","doc":"- Bugs concerning unused and shadowed variables have been fixed in the linter.\n\n Own Id: OTP-5091\n\n- A bug in the evaluator that caused the shell to choke on bit syntax\n expressions has been fixed.\n\n Own Id: OTP-5237\n\n- `io:format/2` et.al no longer crashes for some combinations of precision and\n value for format character \"g\". Previously it crashed if the precision P was 4\n or lower and the absolute value of the float to print was lower than 10^4 but\n 10^(P-1) or higher. Now it will not crash depending on the value of the float.\n\n Own Id: OTP-5263\n\n- Bugs in the handling of the bit syntax have been fixed in the Erlang shell.\n\n Own Id: OTP-5269\n\n- `gb_sets:del_element/2` was changed to do the same as `gb_sets:delete_any/2`\n which was the original intention, not as `gb_sets:delete/2`. Code that relies\n on `gb_sets:del_element/2` causing an error if the element does not exist must\n be changed to call `gb_sets:delete/2` instead.\n\n The documentation was also updated to explicitly document functions that were\n only referred to as 'aliases' of a documented function. Also, a list of all\n functions common to the `gb_sets`, `sets`, and `ordsets` was added.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-5277\n\n- Debug messages have been removed from the QLC module.\n\n Own Id: OTP-5283","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The size of continuations returned from `dets:match/1,3`,\n `dets:match_object/1,3`, and `dets:select/1,3` has been reduced. This affects\n the amount of data Mnesia sends between nodes while evaluating QLC queries.\n\n Own Id: OTP-5232","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.13.2 - STDLIB Release Notes","ref":"notes.html#stdlib-1-13-2"},{"type":"extras","doc":"- The `-rsh` switch for starting a remote shell (introduced with OTP-5210)\n clashed with an already existing switch used by `slave`. Therefore the switch\n for the remote shell is now instead named `-remsh`.\n\n Own Id: OTP-5248 Aux Id: OTP-5210","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"STDLIB 1.13.1 - STDLIB Release Notes","ref":"notes.html#stdlib-1-13-1"},{"type":"extras","doc":"- The Pman 'trace shell' functionality was broken as has now been fixed.\n Furthermore, Pman could not correctly find the pid of the active shell if more\n than one shell process was running on the node. This has also been corrected.\n\n Own Id: OTP-5191\n\n- When the undocumented feature \"parameterized modules\" was used, the ?MODULE\n macro did not work correctly.\n\n Own Id: OTP-5224","title":"Fixed Bugs and Malfunctions - STDLIB Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- You can now start Erlang with the `-rsh` flag which gives you a remote initial\n shell instead of a local one. Example:\n\n ```text\n erl -sname this_node -rsh other_node@other_host\n ```\n\n Own Id: OTP-5210\n\n- The man page for the `lists` module has been updated with description of the\n new `zip`, `unzip`, and `partition/2` functions.\n\n Own Id: OTP-5213\n\n- The top level group leader used to be listed as job #1 in the job list in JCL\n mode. Since there is no shell associated with this process that can be\n connected to, it will no longer be listed.\n\n Own Id: OTP-5214\n\n- The possibility to start the Erlang shell in parallel with the rest of the\n system has been reintroduced for backwards compatibility. Note that this old\n behaviour is error prone and should not be used unless for some reason\n necessary.\n\n Own Id: OTP-5218 Aux Id: seq9534\n\n- The `shell` commands `rr/1,2,3` now accepts wildcards when reading record\n definitions from BEAM files.\n\n Own Id: OTP-5226","title":"Improvements and New Features - STDLIB Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"\n# Introduction","title":"Introduction","ref":"introduction.html"},{"type":"extras","doc":"The Standard Erlang Libraries application, _STDLIB_, is mandatory in the sense\nthat the minimal system based on Erlang/OTP consists of _STDLIB_ and _Kernel_.\n\n_STDLIB_ contains the following functional areas:\n\n- Erlang shell\n- Command interface\n- Query interface\n- Interface to standard Erlang I/O servers\n- Interface to the Erlang built-in term storage BIFs\n- Regular expression matching functions for strings and binaries\n- Finite state machine\n- Event handling\n- Functions for the server of a client-server relation\n- Function to control applications in a distributed manner\n- Start and control of slave nodes\n- Operations on finite sets and relations represented as sets\n- Library for handling binary data\n- Disk-based term storage\n- List processing\n- Maps processing","title":"Scope - Introduction","ref":"introduction.html#scope"},{"type":"extras","doc":"It is assumed that the reader is familiar with the Erlang programming language.","title":"Prerequisites - Introduction","ref":"introduction.html#prerequisites"},{"type":"extras","doc":"\n# The Erlang I/O Protocol\n\nThe I/O protocol in Erlang enables bi-directional communication between clients\nand servers.\n\n- The I/O server is a process that handles the requests and performs the\n requested task on, for example, an I/O device.\n- The client is any Erlang process wishing to read or write data from/to the I/O\n device.\n\nThe common I/O protocol has been present in OTP since the beginning, but has\nbeen undocumented and has also evolved over the years. In an addendum to Robert\nVirding's rationale, the original I/O protocol is described. This section\ndescribes the current I/O protocol.\n\nThe original I/O protocol was simple and flexible. Demands for memory efficiency\nand execution time efficiency have triggered extensions to the protocol over the\nyears, making the protocol larger and somewhat less easy to implement than the\noriginal. It can certainly be argued that the current protocol is too complex,\nbut this section describes how it looks today, not how it should have looked.\n\nThe basic ideas from the original protocol still hold. The I/O server and client\ncommunicate with one single, rather simplistic protocol and no server state is\never present in the client. Any I/O server can be used together with any client\ncode, and the client code does not need to be aware of the I/O device that the\nI/O server communicates with.","title":"The Erlang I/O Protocol","ref":"io_protocol.html"},{"type":"extras","doc":"As described in Robert's paper, I/O servers and clients communicate using\n`io_request`/`io_reply` tuples as follows:\n\n```erlang\n{io_request, From, ReplyAs, Request}\n{io_reply, ReplyAs, Reply}\n```\n\nThe client sends an `io_request` tuple to the I/O server and the server\neventually sends a corresponding `io_reply` tuple.\n\n- `From` is the `t:pid/0` of the client, the process which the I/O server sends\n the I/O reply to.\n- `ReplyAs` can be any datum and is returned in the corresponding `io_reply`.\n The `m:io` module monitors the I/O server and uses the monitor reference as\n the `ReplyAs` datum. A more complicated client can have many outstanding I/O\n requests to the same I/O server and can use different references (or something\n else) to differentiate among the incoming I/O replies. Element `ReplyAs` is to\n be considered opaque by the I/O server.\n\n Notice that the `t:pid/0` of the I/O server is not explicitly present in tuple\n `io_reply`. The reply can be sent from any process, not necessarily the actual\n I/O server.\n\n- `Request` and `Reply` are described below.\n\nWhen an I/O server receives an `io_request` tuple, it acts upon the `Request`\npart and eventually sends an `io_reply` tuple with the corresponding `Reply`\npart.","title":"Protocol Basics - The Erlang I/O Protocol","ref":"io_protocol.html#protocol-basics"},{"type":"extras","doc":"To output characters on an I/O device, the following `Request`s exist:\n\n```erlang\n{put_chars, Encoding, Characters}\n{put_chars, Encoding, Module, Function, Args}\n```\n\n- `Encoding` is `unicode` or `latin1`, meaning that the characters are (in case\n of binaries) encoded as UTF-8 or ISO Latin-1 (pure bytes). A well-behaved I/O\n server is also to return an error indication if list elements contain\n integers > 255 when `Encoding` is set to `latin1`.\n\n Notice that this does not in any way tell how characters are to be put on the\n I/O device or handled by the I/O server. Different I/O servers can handle the\n characters however they want, this only tells the I/O server which format the\n data is expected to have. In the `Module`/`Function`/`Args` case, `Encoding`\n tells which format the designated function produces.\n\n Notice also that byte-oriented data is simplest sent using the ISO Latin-1\n encoding.\n\n- `Characters` are the data to be put on the I/O device. If `Encoding` is\n `latin1`, this is an `t:iolist/0`. If `Encoding` is `unicode`, this is an\n Erlang standard mixed Unicode list (one integer in a list per character,\n characters in binaries represented as UTF-8).\n- `Module`, `Function`, and `Args` denote a function that is called to produce\n the data (like `io_lib:format/2`).\n\n `Args` is a list of arguments to the function. The function is to produce data\n in the specified `Encoding`. The I/O server is to call the function as\n [`apply(Mod, Func, Args)`](`apply/3`) and put the returned data on the I/O\n device as if it was sent in a `{put_chars, Encoding, Characters}` request. If\n the function returns anything else than a binary or list, or throws an\n exception, an error is to be sent back to the client.\n\nThe I/O server replies to the client with an `io_reply` tuple, where element\n`Reply` is one of:\n\n```erlang\nok\n{error, Error}\n```\n\n- `Error` describes the error to the client, which can do whatever it wants with\n it. The `m:io` module typically returns it \"as is\".","title":"Output Requests - The Erlang I/O Protocol","ref":"io_protocol.html#output-requests"},{"type":"extras","doc":"To read characters from an I/O device, the following `Request`s exist:\n\n```erlang\n{get_until, Encoding, Prompt, Module, Function, ExtraArgs}\n```\n\n- `Encoding` denotes how data is to be sent back to the client and what data is\n sent to the function denoted by `Module`/`Function`/`ExtraArgs`. If the\n function supplied returns data as a list, the data is converted to this\n encoding. If the function supplied returns data in some other format, no\n conversion can be done, and it is up to the client-supplied function to return\n data in a proper way.\n\n If `Encoding` is `latin1`, lists of integers `0..255` or binaries containing\n plain bytes are sent back to the client when possible. If `Encoding` is\n `unicode`, lists with integers in the whole Unicode range or binaries encoded\n in UTF-8 are sent to the client. The user-supplied function always sees lists\n of integers, never binaries, but the list can contain numbers > 255 if\n `Encoding` is `unicode`.\n\n- `Prompt` is a list of characters (not mixed, no binaries) or an atom to be\n output as a prompt for input on the I/O device. `Prompt` is often ignored by\n the I/O server; if set to `''`, it is always to be ignored (and results in\n nothing being written to the I/O device).\n- `Module`, `Function`, and `ExtraArgs` denote a function and arguments to\n determine when enough data is written. The function is to take two more\n arguments, the last state, and a list of characters. The function is to return\n one of:\n\n ```erlang\n {done, Result, RestChars}\n {more, Continuation}\n ```\n\n `Result` can be any Erlang term, but if it is a `t:list/0`, the I/O server can\n convert it to a `t:binary/0` of appropriate format before returning it to the\n client, if the I/O server is set in binary mode (see below).\n\n The function is called with the data the I/O server finds on its I/O device,\n returning one of:\n\n - `{done, Result, RestChars}` when enough data is read. In this case `Result`\n is sent to the client and `RestChars` is kept in the I/O server as a buffer\n for later input.\n - `{more, Continuation}`, which indicates that more characters are needed to\n complete the request.\n\n `Continuation` is sent as the state in later calls to the function when more\n characters are available. When no more characters are available, the function\n must return `{done, eof, Rest}`. The initial state is the empty list. The data\n when an end of file is reached on the IO device is the atom `eof`.\n\n An emulation of the `get_line` request can be (inefficiently) implemented\n using the following functions:\n\n ```erlang\n -module(demo).\n -export([until_newline/3, get_line/1]).\n\n until_newline(_ThisFar,eof,_MyStopCharacter) ->\n {done,eof,[]};\n until_newline(ThisFar,CharList,MyStopCharacter) ->\n case\n lists:splitwith(fun(X) -> X =/= MyStopCharacter end, CharList)\n of\n \t{L,[]} ->\n {more,ThisFar++L};\n \t{L2,[MyStopCharacter|Rest]} ->\n \t {done,ThisFar++L2++[MyStopCharacter],Rest}\n end.\n\n get_line(IoServer) ->\n IoServer ! {io_request,\n self(),\n IoServer,\n {get_until, unicode, '', ?MODULE, until_newline, [$\\n]}},\n receive\n {io_reply, IoServer, Data} ->\n \t Data\n end.\n ```\n\n Notice that the last element in the `Request` tuple (`[$\\n]`) is appended to\n the argument list when the function is called. The function is to be called\n like [`apply(Module, Function, [ State, Data | ExtraArgs ])`](`apply/3`) by\n the I/O server.\n\nA fixed number of characters is requested using the following `Request`:\n\n```erlang\n{get_chars, Encoding, Prompt, N}\n```\n\n- `Encoding` and `Prompt` as for `get_until`.\n- `N` is the number of characters to be read from the I/O device.\n\nA single line (as in former example) is requested with the following `Request`:\n\n```erlang\n{get_line, Encoding, Prompt}\n```\n\n- `Encoding` and `Prompt` as for `get_until`.\n\nClearly, `get_chars` and `get_line` could be implemented with the `get_until`\nrequest (and indeed they were originally), but demands for efficiency have made\nthese additions necessary.\n\nThe I/O server replies to the client with an `io_reply` tuple, where element\n`Reply` is one of:\n\n```erlang\nData\neof\n{error, Error}\n```\n\n- `Data` is the characters read, in list or binary form (depending on the I/O\n server mode, see the next section).\n- `eof` is returned when input end is reached and no more data is available to\n the client process.\n- `Error` describes the error to the client, which can do whatever it wants with\n it. The `m:io` module typically returns it as is.","title":"Input Requests - The Erlang I/O Protocol","ref":"io_protocol.html#input-requests"},{"type":"extras","doc":"Demands for efficiency when reading data from an I/O server has not only lead to\nthe addition of the `get_line` and `get_chars` requests, but has also added the\nconcept of I/O server options. No options are mandatory to implement, but all\nI/O servers in the Erlang standard libraries honor the `binary` option, which\nallows element `Data` of the `io_reply` tuple to be a binary instead of a list\n_when possible_. If the data is sent as a binary, Unicode data is sent in the\nstandard Erlang Unicode format, that is, UTF-8 (notice that the function of the\n`get_until` request still gets list data regardless of the I/O server mode).\n\nNotice that the `get_until` request allows for a function with the data\nspecified as always being a list. Also, the return value data from such a\nfunction can be of any type (as is indeed the case when an\n[`io:fread/2,3`](`io:fread/2`) request is sent to an I/O server). The client\nmust be prepared for data received as answers to those requests to be in various\nforms. However, the I/O server is to convert the results to binaries whenever\npossible (that is, when the function supplied to `get_until` returns a list).\nThis is done in the example in section\n[An Annotated and Working Example I/O Server](io_protocol.md#example_io_server).\n\nAn I/O server in binary mode affects the data sent to the client, so that it\nmust be able to handle binary data. For convenience, the modes of an I/O server\ncan be set and retrieved using the following I/O requests:\n\n```erlang\n{setopts, Opts}\n```\n\n- `Opts` is a list of options in the format recognized by the `m:proplists`\n module (and by the I/O server).\n\nAs an example, the I/O server for the interactive shell (in `group.erl`)\nunderstands the following options:\n\n```erlang\n{binary, boolean()} (or binary/list)\n{echo, boolean()}\n{expand_fun, fun()}\n{encoding, unicode/latin1} (or unicode/latin1)\n```\n\nOptions `binary` and `encoding` are common for all I/O servers in OTP, while\n`echo` and `expand` are valid only for this I/O server. Option `unicode`\nnotifies how characters are put on the physical I/O device, that is, if the\nterminal itself is Unicode-aware. It does not affect how characters are sent in\nthe I/O protocol, where each request contains encoding information for the\nprovided or returned data.\n\nThe I/O server is to send one of the following as `Reply`:\n\n```erlang\nok\n{error, Error}\n```\n\nAn error (preferably `enotsup`) is to be expected if the option is not supported\nby the I/O server (like if an `echo` option is sent in a `setopts` request to a\nplain file).\n\nTo retrieve options, the following request is used:\n\n```erlang\ngetopts\n```\n\nThis request asks for a complete list of all options supported by the I/O server\nas well as their current values.\n\nThe I/O server replies:\n\n```erlang\nOptList\n{error, Error}\n```\n\n- `OptList` is a list of tuples `{Option, Value}`, where `Option` always is an\n atom.","title":"I/O Server Modes - The Erlang I/O Protocol","ref":"io_protocol.html#i-o-server-modes"},{"type":"extras","doc":"The `Request` element can in itself contain many `Request`s by using the\nfollowing format:\n\n```erlang\n{requests, Requests}\n```\n\n- `Requests` is a list of valid `io_request` tuples for the protocol. They must\n be executed in the order that they appear in the list. The execution is to\n continue until one of the requests results in an error or the list is\n consumed. The result of the last request is sent back to the client.\n\nThe I/O server can, for a list of requests, send any of the following valid\nresults in the reply, depending on the requests in the list:\n\n```erlang\nok\n{ok, Data}\n{ok, Options}\n{error, Error}\n```","title":"Multiple I/O Requests - The Erlang I/O Protocol","ref":"io_protocol.html#multiple-i-o-requests"},{"type":"extras","doc":"The following I/O request is optional to implement and a client is to be\nprepared for an error return:\n\n```erlang\n{get_geometry, Geometry}\n```\n\n- `Geometry` is the atom `rows` or the atom `columns`.\n\nThe I/O server is to send one of the following as `Reply`:\n\n```erlang\nN\n{error, Error}\n```\n\n- `N` is the number of character rows or columns that the I/O device has, if\n applicable to the I/O device handled by the I/O server, otherwise\n `{error, enotsup}` is a good answer.","title":"Optional I/O Request - The Erlang I/O Protocol","ref":"io_protocol.html#optional-i-o-request"},{"type":"extras","doc":"If an I/O server encounters a request that it does not recognize (that is, the\n`io_request` tuple has the expected format, but the `Request` is unknown), the\nI/O server is to send a valid reply with the error tuple:\n\n```erlang\n{error, request}\n```\n\nThis makes it possible to extend the protocol with optional requests and for the\nclients to be somewhat backward compatible.","title":"Unimplemented Request Types - The Erlang I/O Protocol","ref":"io_protocol.html#unimplemented-request-types"},{"type":"extras","doc":"[](){: #example_io_server }\n\nAn I/O server is any process capable of handling the I/O protocol. There is no\ngeneric I/O server behavior, but could well be. The framework is simple, a\nprocess handling incoming requests, usually both I/O-requests and other I/O\ndevice-specific requests (positioning, closing, and so on).\n\nThe example I/O server stores characters in an ETS table, making up a fairly\ncrude RAM file.\n\nThe module begins with the usual directives, a function to start the I/O server\nand a main loop handling the requests:\n\n```erlang\n-module(ets_io_server).\n\n-export([start_link/0, init/0, loop/1, until_newline/3, until_enough/3]).\n\n-define(CHARS_PER_REC, 10).\n\n-record(state, {\n\t table,\n\t position, % absolute\n\t mode % binary | list\n\t }).\n\nstart_link() ->\n spawn_link(?MODULE,init,[]).\n\ninit() ->\n Table = ets:new(noname,[ordered_set]),\n ?MODULE:loop(#state{table = Table, position = 0, mode=list}).\n\nloop(State) ->\n receive\n\t{io_request, From, ReplyAs, Request} ->\n\t case request(Request,State) of\n\t\t{Tag, Reply, NewState} when Tag =:= ok; Tag =:= error ->\n\t\t reply(From, ReplyAs, Reply),\n\t\t ?MODULE:loop(NewState);\n\t\t{stop, Reply, _NewState} ->\n\t\t reply(From, ReplyAs, Reply),\n\t\t exit(Reply)\n\t end;\n\t%% Private message\n\t{From, rewind} ->\n\t From ! {self(), ok},\n\t ?MODULE:loop(State#state{position = 0});\n\t_Unknown ->\n\t ?MODULE:loop(State)\n end.\n```\n\nThe main loop receives messages from the client (which can use the the `m:io`\nmodule to send requests). For each request, the function `request/2` is called\nand a reply is eventually sent using function `reply/3`.\n\nThe \"private\" message `{From, rewind}` results in the current position in the\npseudo-file to be reset to `0` (the beginning of the \"file\"). This is a typical\nexample of I/O device-specific messages not being part of the I/O protocol. It\nis usually a bad idea to embed such private messages in `io_request` tuples, as\nthat can confuse the reader.\n\nFirst, we examine the reply function:\n\n```erlang\nreply(From, ReplyAs, Reply) ->\n From ! {io_reply, ReplyAs, Reply}.\n```\n\nIt sends the `io_reply` tuple back to the client, providing element `ReplyAs`\nreceived in the request along with the result of the request, as described\nearlier.\n\nWe need to handle some requests. First the requests for writing characters:\n\n```erlang\nrequest({put_chars, Encoding, Chars}, State) ->\n put_chars(unicode:characters_to_list(Chars,Encoding),State);\nrequest({put_chars, Encoding, Module, Function, Args}, State) ->\n try\n\trequest({put_chars, Encoding, apply(Module, Function, Args)}, State)\n catch\n\t_:_ ->\n\t {error, {error,Function}, State}\n end;\n```\n\nThe `Encoding` says how the characters in the request are represented. We want\nto store the characters as lists in the ETS table, so we convert them to lists\nusing function `unicode:characters_to_list/2`. The conversion function\nconveniently accepts the encoding types `unicode` and `latin1`, so we can use\n`Encoding` directly.\n\nWhen `Module`, `Function`, and `Arguments` are provided, we apply it and do the\nsame with the result as if the data was provided directly.\n\nWe handle the requests for retrieving data:\n\n```erlang\nrequest({get_until, Encoding, _Prompt, M, F, As}, State) ->\n get_until(Encoding, M, F, As, State);\nrequest({get_chars, Encoding, _Prompt, N}, State) ->\n %% To simplify the code, get_chars is implemented using get_until\n get_until(Encoding, ?MODULE, until_enough, [N], State);\nrequest({get_line, Encoding, _Prompt}, State) ->\n %% To simplify the code, get_line is implemented using get_until\n get_until(Encoding, ?MODULE, until_newline, [$\\n], State);\n```\n\nHere we have cheated a little by more or less only implementing `get_until` and\nusing internal helpers to implement `get_chars` and `get_line`. In production\ncode, this can be inefficient, but that depends on the frequency of the\ndifferent requests. Before we start implementing functions `put_chars/2` and\n`get_until/5`, we examine the few remaining requests:\n\n```erlang\nrequest({get_geometry,_}, State) ->\n {error, {error,enotsup}, State};\nrequest({setopts, Opts}, State) ->\n setopts(Opts, State);\nrequest(getopts, State) ->\n getopts(State);\nrequest({requests, Reqs}, State) ->\n multi_request(Reqs, {ok, ok, State});\n```\n\nRequest `get_geometry` has no meaning for this I/O server, so the reply is\n`{error, enotsup}`. The only option we handle is `binary`/`list`, which is done\nin separate functions.\n\nThe multi-request tag (`requests`) is handled in a separate loop function\napplying the requests in the list one after another, returning the last result.\n\n`{error, request}` must be returned if the request is not recognized:\n\n```erlang\nrequest(_Other, State) ->\n {error, {error, request}, State}.\n```\n\nNext we handle the different requests, first the fairly generic multi-request\ntype:\n\n```erlang\nmulti_request([R|Rs], {ok, _Res, State}) ->\n multi_request(Rs, request(R, State));\nmulti_request([_|_], Error) ->\n Error;\nmulti_request([], Result) ->\n Result.\n```\n\nWe loop through the requests one at the time, stopping when we either encounter\nan error or the list is exhausted. The last return value is sent back to the\nclient (it is first returned to the main loop and then sent back by function\n`io_reply`).\n\nRequests `getopts` and `setopts` are also simple to handle. We only change or\nread the state record:\n\n```erlang\nsetopts(Opts0,State) ->\n Opts = proplists:unfold(\n\t proplists:substitute_negations(\n\t [{list,binary}],\n\t Opts0)),\n case check_valid_opts(Opts) of\n\ttrue ->\n\t case proplists:get_value(binary, Opts) of\n\t\t true ->\n\t\t\t{ok,ok,State#state{mode=binary}};\n\t\t false ->\n\t\t\t{ok,ok,State#state{mode=binary}};\n\t\t _ ->\n\t\t\t{ok,ok,State}\n\t\tend;\n\tfalse ->\n\t {error,{error,enotsup},State}\n end.\ncheck_valid_opts([]) ->\n true;\ncheck_valid_opts([{binary,Bool}|T]) when is_boolean(Bool) ->\n check_valid_opts(T);\ncheck_valid_opts(_) ->\n false.\n\ngetopts(#state{mode=M} = S) ->\n {ok,[{binary, case M of\n\t\t binary ->\n\t\t\t true;\n\t\t _ ->\n\t\t\t false\n\t\t end}],S}.\n```\n\nAs a convention, all I/O servers handle both `{setopts, [binary]}`,\n`{setopts, [list]}`, and `{setopts,[{binary, boolean()}]}`, hence the trick with\n`proplists:substitute_negations/2` and `proplists:unfold/1`. If invalid options\nare sent to us, we send `{error, enotsup}` back to the client.\n\nRequest `getopts` is to return a list of `{Option, Value}` tuples. This has the\ntwofold function of providing both the current values and the available options\nof this I/O server. We have only one option, and hence return that.\n\nSo far this I/O server is fairly generic (except for request `rewind` handled in\nthe main loop and the creation of an ETS table). Most I/O servers contain code\nsimilar to this one.\n\nTo make the example runnable, we start implementing the reading and writing of\nthe data to/from the ETS table. First function `put_chars/3`:\n\n```erlang\nput_chars(Chars, #state{table = T, position = P} = State) ->\n R = P div ?CHARS_PER_REC,\n C = P rem ?CHARS_PER_REC,\n [ apply_update(T,U) || U <- split_data(Chars, R, C) ],\n {ok, ok, State#state{position = (P + length(Chars))}}.\n```\n\nWe already have the data as (Unicode) lists and therefore only split the list in\nruns of a predefined size and put each run in the table at the current position\n(and forward). Functions `split_data/3` and `apply_update/2` are implemented\nbelow.\n\nNow we want to read data from the table. Function `get_until/5` reads data and\napplies the function until it says that it is done. The result is sent back to\nthe client:\n\n```erlang\nget_until(Encoding, Mod, Func, As,\n\t #state{position = P, mode = M, table = T} = State) ->\n case get_loop(Mod,Func,As,T,P,[]) of\n\t{done,Data,_,NewP} when is_binary(Data); is_list(Data) ->\n\t if\n\t\tM =:= binary ->\n\t\t {ok,\n\t\t unicode:characters_to_binary(Data, unicode, Encoding),\n\t\t State#state{position = NewP}};\n\t\ttrue ->\n\t\t case check(Encoding,\n\t\t unicode:characters_to_list(Data, unicode))\n of\n\t\t\t{error, _} = E ->\n\t\t\t {error, E, State};\n\t\t\tList ->\n\t\t\t {ok, List,\n\t\t\t State#state{position = NewP}}\n\t\t end\n\t end;\n\t{done,Data,_,NewP} ->\n\t {ok, Data, State#state{position = NewP}};\n\tError ->\n\t {error, Error, State}\n end.\n\nget_loop(M,F,A,T,P,C) ->\n {NewP,L} = get(P,T),\n case catch apply(M,F,[C,L|A]) of\n\t{done, List, Rest} ->\n\t {done, List, [], NewP - length(Rest)};\n\t{more, NewC} ->\n\t get_loop(M,F,A,T,NewP,NewC);\n\t_ ->\n\t {error,F}\n end.\n```\n\nHere we also handle the mode (`binary` or `list`) that can be set by request\n`setopts`. By default, all OTP I/O servers send data back to the client as\nlists, but switching mode to `binary` can increase efficiency if the I/O server\nhandles it in an appropriate way. The implementation of `get_until` is difficult\nto get efficient, as the supplied function is defined to take lists as\narguments, but `get_chars` and `get_line` can be optimized for binary mode.\nHowever, this example does not optimize anything.\n\nIt is important though that the returned data is of the correct type depending\non the options set. We therefore convert the lists to binaries in the correct\nencoding _if possible_ before returning. The function supplied in the\n`get_until` request tuple can, as its final result return anything, so only\nfunctions returning lists can get them converted to binaries. If the request\ncontains encoding tag `unicode`, the lists can contain all Unicode code points\nand the binaries are to be in UTF-8. If the encoding tag is `latin1`, the client\nis only to get characters in the range `0..255`. Function `check/2` takes care\nof not returning arbitrary Unicode code points in lists if the encoding was\nspecified as `latin1`. If the function does not return a list, the check cannot\nbe performed and the result is that of the supplied function untouched.\n\nTo manipulate the table we implement the following utility functions:\n\n```erlang\ncheck(unicode, List) ->\n List;\ncheck(latin1, List) ->\n try\n\t[ throw(not_unicode) || X <- List,\n\t\t\t\tX > 255 ],\n\tList\n catch\n\tthrow:_ ->\n\t {error,{cannot_convert, unicode, latin1}}\n end.\n```\n\nThe function check provides an error tuple if Unicode code points > 255 are to\nbe returned if the client requested `latin1`.\n\nThe two functions `until_newline/3` and `until_enough/3` are helpers used\ntogether with function `get_until/5` to implement `get_chars` and `get_line`\n(inefficiently):\n\n```erlang\nuntil_newline([],eof,_MyStopCharacter) ->\n {done,eof,[]};\nuntil_newline(ThisFar,eof,_MyStopCharacter) ->\n {done,ThisFar,[]};\nuntil_newline(ThisFar,CharList,MyStopCharacter) ->\n case\n lists:splitwith(fun(X) -> X =/= MyStopCharacter end, CharList)\n of\n\t{L,[]} ->\n {more,ThisFar++L};\n\t{L2,[MyStopCharacter|Rest]} ->\n\t {done,ThisFar++L2++[MyStopCharacter],Rest}\n end.\n\nuntil_enough([],eof,_N) ->\n {done,eof,[]};\nuntil_enough(ThisFar,eof,_N) ->\n {done,ThisFar,[]};\nuntil_enough(ThisFar,CharList,N)\n when length(ThisFar) + length(CharList) >= N ->\n {Res,Rest} = my_split(N,ThisFar ++ CharList, []),\n {done,Res,Rest};\nuntil_enough(ThisFar,CharList,_N) ->\n {more,ThisFar++CharList}.\n```\n\nAs can be seen, the functions above are just the type of functions that are to\nbe provided in `get_until` requests.\n\nTo complete the I/O server, we only need to read and write the table in an\nappropriate way:\n\n```erlang\nget(P,Tab) ->\n R = P div ?CHARS_PER_REC,\n C = P rem ?CHARS_PER_REC,\n case ets:lookup(Tab,R) of\n\t[] ->\n\t {P,eof};\n\t[{R,List}] ->\n\t case my_split(C,List,[]) of\n\t\t{_,[]} ->\n\t\t {P+length(List),eof};\n\t\t{_,Data} ->\n\t\t {P+length(Data),Data}\n\t end\n end.\n\nmy_split(0,Left,Acc) ->\n {lists:reverse(Acc),Left};\nmy_split(_,[],Acc) ->\n {lists:reverse(Acc),[]};\nmy_split(N,[H|T],Acc) ->\n my_split(N-1,T,[H|Acc]).\n\nsplit_data([],_,_) ->\n [];\nsplit_data(Chars, Row, Col) ->\n {This,Left} = my_split(?CHARS_PER_REC - Col, Chars, []),\n [ {Row, Col, This} | split_data(Left, Row + 1, 0) ].\n\napply_update(Table, {Row, Col, List}) ->\n case ets:lookup(Table,Row) of\n\t[] ->\n\t ets:insert(Table,{Row, lists:duplicate(Col,0) ++ List});\n\t[{Row, OldData}] ->\n\t {Part1,_} = my_split(Col,OldData,[]),\n\t {_,Part2} = my_split(Col+length(List),OldData,[]),\n\t ets:insert(Table,{Row, Part1 ++ List ++ Part2})\n end.\n```\n\nThe table is read or written in chunks of `?CHARS_PER_REC`, overwriting when\nnecessary. The implementation is clearly not efficient, it is just working.\n\nThis concludes the example. It is fully runnable and you can read or write to\nthe I/O server by using, for example, the `m:io` module or even the `m:file`\nmodule. It is as simple as that to implement a fully fledged I/O server in\nErlang.","title":"An Annotated and Working Example I/O Server - The Erlang I/O Protocol","ref":"io_protocol.html#an-annotated-and-working-example-i-o-server"},{"type":"extras","doc":"\n# Creating a custom shell\n\nThis guide will show how to create a custom shell. The most common\nuse case for this is to support other languages running on the Erlang VM,\nbut it can also be used to create specialized debugging shells a system.\n\nThis guide will build on top of the built-in [Erlang line editor](`m:edlin`),\nwhich means that the keybindings described in [tty - A Command-Line Interface](`e:erts:tty.md`)\ncan be used edit the input before it is passed to the custom shell. This\nsomewhat limits what the custom shell can do, but it also means that we do not\nhave to implement line editing ourselves. If you need more control over the\nshell, then use [Creating a terminal application](terminal_interface.md) as\na starting-point to build your own line editor and shell.","title":"Creating a custom shell","ref":"custom_shell.html"},{"type":"extras","doc":"The custom shell that we are going to build is a process inspection shell\nthat supports the following commands:\n\n* `list` - lists all processes\n* `inspect pid()` - inspect a process\n* `suspend pid()` - suspend a process\n* `resume pid()` - resume a process\n\nLets get started!","title":"A process inspection shell - Creating a custom shell","ref":"custom_shell.html#a-process-inspection-shell"},{"type":"extras","doc":"The custom shell will be implemented in an `m:escript`, but it could just\nas well be in a regular system or as a remote shell. To start a custom shell\nwe first need to start Erlang in `-noinput` or `-noshell` mode. `m:escript` are\nstarted by default in `-noshell` mode, so we don't have to do anything special here.\nTo start the custom shell we then call `shell:start_interactive/1`.\n\n```\n#!/usr/bin/env escript\n%% pshell.es\n-export([start/0]).\nmain(_Args) ->\n shell:start_interactive({?MODULE, start, []}),\n timer:sleep(infinity). %% Make sure the escript does not exit\n\n-spec start() -> pid().\nstart() ->\n spawn(fun() ->\n io:format(~\"Starting process inspection shell~n\"),\n loop()\n end).\n\nloop() ->\n receive _M -> loop() end.\n```\n\nIf we run the above we will get this:\n\n```\n$ ./pshell.es\nErlang/OTP 28 [DEVELOPMENT] [erts-15.0.1] [source-b395339a02] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]\n\nStarting process inspection shell\n\n```\n\nThe `t:io:standard_io/0` of the created shell process will be set to the\nErlang line editor, which means that we can use the normal `m:io` functions\nto read and write data to the terminal.","title":"Starting with a custom shell - Creating a custom shell","ref":"custom_shell.html#starting-with-a-custom-shell"},{"type":"extras","doc":"Let's start adding the shell interface. We will use `io:get_line/1` to read from\n`t:io:standard_io/0` as this shell will be line based. However, for a more complex\nshell it is better to send [`get_until` I/O requests](io_protocol.md#input-requests)\nas commands read that way can span multiple lines. So we expand our `loop/0` with\na `io:get_line/1` and pass the results to our parser.\n\n```\nloop() ->\n case io:get_line(\"> \") of\n eof -> ok;\n {error, Reason} -> exit(Reason);\n Data -> eval(string:trim(Data))\n end,\n loop().\n\neval(\"list\") ->\n Format = \" ~.10ts | ~.10ts | ~.10ts~n\",\n io:format(Format,[\"Pid\", \"Name\", \"MsgQ Len\"]),\n [begin\n [{registered_name,Name},{message_queue_len,Len}]\n = erlang:process_info(Pid, [registered_name, message_queue_len]),\n io:format(Format,[to_list(Pid), to_list(Name), to_list(Len)])\n end || Pid <- processes()];\neval(Unknown) ->\n io:format(\"Unknown command: '~ts'~n\",[Unknown]).\n\nto_list(Pid) when is_pid(Pid) ->\n pid_to_list(Pid);\nto_list(Atom) when is_atom(Atom) ->\n atom_to_list(Atom);\nto_list(Int) when is_integer(Int) ->\n integer_to_list(Int);\nto_list(List) when is_list(List) ->\n List.\n```\n\nIf we run the above we will get this:\n\n```txt\n$ ./pshell.es\nErlang/OTP 28 [DEVELOPMENT] [erts-15.0.1] [source-b395339a02] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]\n\nStarting process inspection shell\n> list\n Pid | Name | MsgQ Len \n <0.0.0> | init | 0 \n <0.1.0> | erts_code_ | 0 \n <0.2.0> | | 0 \n <0.3.0> | | 0 \n <0.4.0> | | 0 \n <0.5.0> | | 0 \n <0.6.0> | | 0 \n <0.7.0> | | 0 \n <0.8.0> | socket_reg | 0 \n <0.10.0> | | 0 \n <0.11.0> | erl_prim_l | 0 \n <0.43.0> | logger | 0 \n <0.45.0> | applicatio | 0\n...\n```\n\nWith this all in place we can now easily add `inspect`, `suspend` and `resume` as well.\n\n```\neval(\"inspect \" ++ PidStr) ->\n case parse_pid(PidStr) of\n invalid -> ok;\n Pid ->\n [{registered_name, Name}, {memory, Memory}, {messages, Messages}, {status, Status}] =\n erlang:process_info(Pid, [registered_name, memory, messages, status]),\n io:format(\"Pid: ~p~nName: ~ts~nStatus: ~p~nMemory: ~p~nMessages: ~p~n\",\n [Pid, to_list(Name), Status, Memory, Messages])\n end;\neval(\"suspend \" ++ PidStr) ->\n case parse_pid(PidStr) of\n invalid -> ok;\n Pid ->\n erlang:suspend_process(Pid),\n io:format(\"Suspeneded ~ts~n\")\n end;\neval(\"resume \" ++ PidStr) ->\n case parse_pid(PidStr) of\n invalid -> ok;\n Pid ->\n erlang:resumne_process(Pid),\n io:format(\"Resumed ~ts~n\")\n end;\n```","title":"Adding our first command - Creating a custom shell","ref":"custom_shell.html#adding-our-first-command"},{"type":"extras","doc":"Wouldn't it be great if we could add some simple auto-completion for our shell? We can do that\nby setting a `m:edlin_expand` fun for our shell. This is done by calling [`io:setopts([{expand_fun, Fun}])`](`io:setopts/2`). The fun that we provide is will receive the reversed current line from\n`m:edlin` and is expected to return possible expansions. Let's start by adding a simple fun to\nexpand our commands.\n\n```\n-spec start() -> pid().\nstart() ->\n spawn(fun() ->\n io:setopts([{expand_fun, fun expand_fun/1}]),\n io:format(~\"Starting process inspection shell~n\"),\n loop()\n end).\n\n-spec expand_fun(ReverseLine :: string()) -> {yes, string(), list(string())} |\n {no, nil(), nil()}.\nexpand_fun(\"\") -> %% If line is empty, we list all available commands\n {yes, \"\", [\"list\", \"inspect\", \"suspend\", \"resume\"]};\nexpand_fun(Curr) ->\n expand_fun(lists:reverse(Curr), [\"list\", \"inspect\", \"suspend\", \"resume\"]).\n\nexpand_fun(_Curr, []) ->\n {no, \"\", []};\nexpand_fun(Curr, [Cmd | T]) ->\n case lists:prefix(Curr, Cmd) of\n true ->\n %% If Curr is a prefix of Cmd we subtract Curr from Cmd to get the\n %% characters we need to complete with.\n {yes, lists:reverse(lists:reverse(Cmd) -- lists:reverse(Curr)), []};\n false ->\n expand_fun(Curr, T)\n end.\n```\n\nWith the above code we will get expansions of our commands if we hit ` ` in the shell.\nIts possible to make very complex completion algorithms, for example the Erlang shell\nhas completions based on the function specifications of your code. It is important though that\nthe shell still feels responsive, so calling out to a LLM model for completion may or may not\nbe a good idea.\n\nThe complete source code for this example can be found [here](assets/pshell.es).","title":"Adding autocompletion - Creating a custom shell","ref":"custom_shell.html#adding-autocompletion"},{"type":"extras","doc":"\n# Creating a terminal application\n\nThis guide will show how to create a very simple tic-tac-toe game in\nthe shell. We will go through how to read key-strokes and how to update\nthe screen to show the tic-tac-toe board. The game will be implemented as an\n`m:escript`, but it can just as well be implemented in a regular system.\n\nLet us start by drawing the board which will look like this:\n\n```txt\n╔═══════╤═══════╤═══════╗\n║┌─────┐│ │ ║\n║│ ││ │ ║ Place an X by pressing Enter\n║└─────┘│ │ ║\n╟───────┼───────┼───────╢\n║ │ │ ║\n║ │ │ ║\n║ │ │ ║\n╟───────┼───────┼───────╢\n║ │ │ ║\n║ │ │ ║\n║ │ │ ║\n╚═══════╧═══════╧═══════╝\n```\n{: .monospace-font }\n\n\nWe will use the alternate screen buffer for our game so first we need to set that up:\n\n```\n#!/usr/bin/env escript\nmain(_Args) ->\n \n io:put_chars(\"\\e[?1049h\"), %% Enable alternate screen buffer\n io:put_chars(\"\\e[?25l\"), %% Hide the cursor\n draw_board(),\n timer:sleep(5000),\n io:put_chars(\"\\e[?25h\"), %% Show the cursor\n io:put_chars(\"\\e[?1049l\"), %% Disable alternate screen buffer\n ok.\n```\n\nWe then use the box drawing parts of Unicode to draw our board:\n\n```\ndraw_board() ->\n io:put_chars(\"\\e[5;0H\"), %% Move cursor to top left\n io:put_chars(\n [\" ╔═══════╤═══════╤═══════╗\\r\\n\",\n \" ║ │ │ ║\\r\\n\",\n \" ║ │ │ ║ Place an X by pressing Enter\\r\\n\",\n \" ║ │ │ ║\\r\\n\",\n \" ╟───────┼───────┼───────╢\\r\\n\",\n \" ║ │ │ ║\\r\\n\",\n \" ║ │ │ ║\\r\\n\",\n \" ║ │ │ ║\\r\\n\",\n \" ╟───────┼───────┼───────╢\\r\\n\",\n \" ║ │ │ ║\\r\\n\",\n \" ║ │ │ ║\\r\\n\",\n \" ║ │ │ ║\\r\\n\",\n \" ╚═══════╧═══════╧═══════╝\\r\\n\"]),\n ok.\n```\n{: .monospace-font }\n\nLet us add some interactivity to our game! To do that we need to change the\nshell from running in `cooked` to `raw` mode. This is done by calling\n[`shell:start_interactive({noshell, raw})`](`shell:start_interactive/1`).\nWe can then use `io:get_chars/2` to read key strokes from the user. The key\nstrokes will be returned as [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code), \nso we will have need to handle the codes for up, down, left, right and enter.\n\nIt could look something like this:\n\n```\nmain(_Args) ->\n ok = shell:start_interactive({noshell, raw}),\n \n io:put_chars(\"\\e[?1049h\"), %% Enable alternate screen buffer\n io:put_chars(\"\\e[?25l\"), %% Hide the cursor\n draw_board(),\n loop(0),\n io:put_chars(\"\\e[?25h\"), %% Show the cursor\n io:put_chars(\"\\e[?1049l\"), %% Disable alternate screen buffer\n ok.\n\nloop(Pos) ->\n io:put_chars(draw_selection(Pos)),\n %% Read at most 1024 characters from stdin.\n {ok, Chars} = io:get_chars(\"\", 1024),\n case handle_input(Chars, Pos) of\n stop -> stop;\n NewPos ->\n io:put_chars(clear_selection(Pos)),\n loop(NewPos)\n end.\n\nhandle_input(\"\\e[A\" ++ Rest, Pos) ->\n %% Up key\n handle_input(Rest, max(0, Pos - 3));\nhandle_input(\"\\e[B\" ++ Rest, Pos) ->\n %% Down key\n handle_input(Rest, min(8, Pos + 3));\nhandle_input(\"\\e[C\" ++ Rest, Pos) ->\n %% right key\n handle_input(Rest, min(8, Pos + 1));\nhandle_input(\"\\e[D\" ++ Rest, Pos) ->\n %% left key\n handle_input(Rest, max(0, Pos - 1));\nhandle_input(\"q\" ++ _, _State) ->\n stop;\nhandle_input([_ | T], State) ->\n handle_input(T, State);\nhandle_input([], State) ->\n State.\n```\n\nNote that when using `io:get_chars/2` with the shell set in `{noshell, raw}` mode\nit will return as soon as any data is available. The number of characters\nis the maximum number that will be returned. We use 1024 here to make sure that\nwe always get all the data in one read.\n\nWe also need to draw the selection marker, we do this using some simple drawing\nroutines.\n\n```\n%% Clear/draw the selection markers, making sure\n%% not to overwrite if a X or O exists.\n%% \\b = Move cursor left\n%% \\e[C = Move cursor right\n%% \\n = Move cursor down\nclear_selection(Pos) ->\n [set_position(Pos),\n \" \",\"\\b\\b\\b\\b\\b\\b\\b\\n\",\n \" \\e[C\\e[C\\e[C\\e[C\\e[C \",\n \"\\b\\b\\b\\b\\b\\b\\b\\n\",\" \"].\n\ndraw_selection(Pos) ->\n [set_position(Pos),\n \"┌─────┐\",\"\\b\\b\\b\\b\\b\\b\\b\\n\",\n \"│\\e[C\\e[C\\e[C\\e[C\\e[C│\",\n \"\\b\\b\\b\\b\\b\\b\\b\\n\",\"└─────┘\"].\n\n%% Set the cursor position to be at the top\n%% left of the field of the given position\nset_position(Pos) ->\n Row = 6 + (Pos div 3) * 4,\n Col = 7 + (Pos rem 3) * 8,\n io_lib:format(\"\\e[~p;~pH\",[Row, Col]).\n```\n{: #monospace-font }\n\nNow we have a program where we can move the marker around the board.\nTo complete the game we need to add some state so that we know which\nsquares are marked and whos turn it is. You can find the final solution\nin [tic-tac-toe.es](assets/tic-tac-toe.es).","title":"Creating a terminal application","ref":"terminal_interface.html"},{"type":"extras","doc":"\n# Using Unicode in Erlang","title":"Using Unicode in Erlang","ref":"unicode_usage.html"},{"type":"extras","doc":"Implementing support for Unicode character sets is an ongoing process. The\nErlang Enhancement Proposal (EEP) 10 outlined the basics of Unicode support and\nspecified a default encoding in binaries that all Unicode-aware modules are to\nhandle in the future.\n\nHere is an overview what has been done so far:\n\n- The functionality described in EEP10 was implemented in Erlang/OTP R13A.\n- Erlang/OTP R14B01 added support for Unicode filenames, but it was not complete\n and was by default disabled on platforms where no guarantee was given for the\n filename encoding.\n- With Erlang/OTP R16A came support for UTF-8 encoded source code, with\n enhancements to many of the applications to support both Unicode encoded\n filenames and support for UTF-8 encoded files in many circumstances. Most\n notable is the support for UTF-8 in files read by `file:consult/1`, release\n handler support for UTF-8, and more support for Unicode character sets in the\n I/O system.\n- In Erlang/OTP 17.0, the encoding default for Erlang source files was switched\n to UTF-8.\n- In Erlang/OTP 20.0, atoms and function can contain Unicode characters. Module\n names, application names, and node names are still restricted to the ISO\n Latin-1 range.\n\n Support was added for normalizations forms in `unicode` and the `string`\n module now handles utf8-encoded binaries.\n\nThis section outlines the current Unicode support and gives some recipes for\nworking with Unicode data.","title":"Unicode Implementation - Using Unicode in Erlang","ref":"unicode_usage.html#unicode-implementation"},{"type":"extras","doc":"Experience with the Unicode support in Erlang has made it clear that\nunderstanding Unicode characters and encodings is not as easy as one would\nexpect. The complexity of the field and the implications of the standard require\nthorough understanding of concepts rarely before thought of.\n\nAlso, the Erlang implementation requires understanding of concepts that were\nnever an issue for many (Erlang) programmers. To understand and use Unicode\ncharacters requires that you study the subject thoroughly, even if you are an\nexperienced programmer.\n\nAs an example, contemplate the issue of converting between upper and lower case\nletters. Reading the standard makes you realize that there is not a simple one\nto one mapping in all scripts, for example:\n\n- In German, the letter \"ß\" (sharp s) is in lower case, but the uppercase\n equivalent is \"SS\".\n- In Greek, the letter \"Σ\" has two different lowercase forms, \"ς\" in word-final\n position and \"σ\" elsewhere.\n- In Turkish, both dotted and dotless \"i\" exist in lower case and upper case\n forms.\n- Cyrillic \"I\" has usually no lowercase form.\n- Languages with no concept of upper case (or lower case).\n\nSo, a conversion function must know not only one character at a time, but\npossibly the whole sentence, the natural language to translate to, the\ndifferences in input and output string length, and so on. Erlang/OTP has\ncurrently no Unicode `uppercase`/`lowercase` functionality with language\nspecific handling, but publicly available libraries address these issues.\n\nAnother example is the accented characters, where the same glyph has two\ndifferent representations. The Swedish letter \"ö\" is one example. The Unicode\nstandard has a code point for it, but you can also write it as \"o\" followed by\n\"U+0308\" (Combining Diaeresis, with the simplified meaning that the last letter\nis to have \"¨\" above). They have the same glyph, user perceived character. They\nare for most purposes the same, but have different representations. For example,\nMacOS X converts all filenames to use Combining Diaeresis, while most other\nprograms (including Erlang) try to hide that by doing the opposite when, for\nexample, listing directories. However it is done, it is usually important to\nnormalize such characters to avoid confusion.\n\nThe list of examples can be made long. One need a kind of knowledge that was not\nneeded when programs only considered one or two languages. The complexity of\nhuman languages and scripts has certainly made this a challenge when\nconstructing a universal standard. Supporting Unicode properly in your program\nwill require effort.","title":"Understanding Unicode - Using Unicode in Erlang","ref":"unicode_usage.html#understanding-unicode"},{"type":"extras","doc":"Unicode is a standard defining code points (numbers) for all known, living or\ndead, scripts. In principle, every symbol used in any language has a Unicode\ncode point. Unicode code points are defined and published by the Unicode\nConsortium, which is a non-profit organization.\n\nSupport for Unicode is increasing throughout the world of computing, as the\nbenefits of one common character set are overwhelming when programs are used in\na global environment. Along with the base of the standard, the code points for\nall the scripts, some _encoding standards_ are available.\n\nIt is vital to understand the difference between encodings and Unicode\ncharacters. Unicode characters are code points according to the Unicode\nstandard, while the encodings are ways to represent such code points. An\nencoding is only a standard for representation. UTF-8 can, for example, be used\nto represent a very limited part of the Unicode character set (for example\nISO-Latin-1) or the full Unicode range. It is only an encoding format.\n\nAs long as all character sets were limited to 256 characters, each character\ncould be stored in one single byte, so there was more or less only one practical\nencoding for the characters. Encoding each character in one byte was so common\nthat the encoding was not even named. With the Unicode system there are much\nmore than 256 characters, so a common way is needed to represent these. The\ncommon ways of representing the code points are the encodings. This means a\nwhole new concept to the programmer, the concept of character representation,\nwhich was a non-issue earlier.\n\nDifferent operating systems and tools support different encodings. For example,\nLinux and MacOS X have chosen the UTF-8 encoding, which is backward compatible\nwith 7-bit ASCII and therefore affects programs written in plain English the\nleast. Windows supports a limited version of UTF-16, namely all the code planes\nwhere the characters can be stored in one single 16-bit entity, which includes\nmost living languages.\n\nThe following are the most widely spread encodings:\n\n- **Bytewise representation** - This is not a proper Unicode representation, but\n the representation used for characters before the Unicode standard. It can\n still be used to represent character code points in the Unicode standard with\n numbers < 256, which exactly corresponds to the ISO Latin-1 character set. In\n Erlang, this is commonly denoted `latin1` encoding, which is slightly\n misleading as ISO Latin-1 is a character code range, not an encoding.\n\n- **UTF-8** - Each character is stored in one to four bytes depending on code\n point. The encoding is backward compatible with bytewise representation of\n 7-bit ASCII, as all 7-bit characters are stored in one single byte in UTF-8.\n The characters beyond code point 127 are stored in more bytes, letting the\n most significant bit in the first character indicate a multi-byte character.\n For details on the encoding, the RFC is publicly available.\n\n Notice that UTF-8 is _not_ compatible with bytewise representation for code\n points from 128 through 255, so an ISO Latin-1 bytewise representation is\n generally incompatible with UTF-8.\n\n- **UTF-16** - This encoding has many similarities to UTF-8, but the basic unit\n is a 16-bit number. This means that all characters occupy at least two bytes,\n and some high numbers four bytes. Some programs, libraries, and operating\n systems claiming to use UTF-16 only allow for characters that can be stored in\n one 16-bit entity, which is usually sufficient to handle living languages. As\n the basic unit is more than one byte, byte-order issues occur, which is why\n UTF-16 exists in both a big-endian and a little-endian variant.\n\n In Erlang, the full UTF-16 range is supported when applicable, like in the\n `m:unicode` module and in the bit syntax.\n\n- **UTF-32** - The most straightforward representation. Each character is stored\n in one single 32-bit number. There is no need for escapes or any variable\n number of entities for one character. All Unicode code points can be stored in\n one single 32-bit entity. As with UTF-16, there are byte-order issues. UTF-32\n can be both big-endian and little-endian.\n\n- **UCS-4** - Basically the same as UTF-32, but without some Unicode semantics,\n defined by IEEE, and has little use as a separate encoding standard. For all\n normal (and possibly abnormal) use, UTF-32 and UCS-4 are interchangeable.\n\nCertain number ranges are unused in the Unicode standard and certain ranges are\neven deemed invalid. The most notable invalid range is 16#D800-16#DFFF, as the\nUTF-16 encoding does not allow for encoding of these numbers. This is possibly\nbecause the UTF-16 encoding standard, from the beginning, was expected to be\nable to hold all Unicode characters in one 16-bit entity, but was then extended,\nleaving a hole in the Unicode range to handle backward compatibility.\n\nCode point 16#FEFF is used for Byte Order Marks (BOMs) and use of that character\nis not encouraged in other contexts. It is valid though, as the character\n\"ZWNBS\" (Zero Width Non Breaking Space). BOMs are used to identify encodings and\nbyte order for programs where such parameters are not known in advance. BOMs are\nmore seldom used than expected, but can become more widely spread as they\nprovide the means for programs to make educated guesses about the Unicode format\nof a certain file.","title":"What Unicode Is - Using Unicode in Erlang","ref":"unicode_usage.html#what-unicode-is"},{"type":"extras","doc":"To support Unicode in Erlang, problems in various areas have been addressed.\nThis section describes each area briefly and more thoroughly later in this\nUser's Guide.\n\n- **Representation** - To handle Unicode characters in Erlang, a common\n representation in both lists and binaries is needed. EEP (10) and the\n subsequent initial implementation in Erlang/OTP R13A settled a standard\n representation of Unicode characters in Erlang.\n\n- **Manipulation** - The Unicode characters need to be processed by the Erlang\n program, which is why library functions must be able to handle them. In some\n cases functionality has been added to already existing interfaces (as the\n `m:string` module now can handle strings with any code points). In some cases\n new functionality or options have been added (as in the `m:io` module, the\n file handling, the `m:unicode` module, and the bit syntax). Today most modules\n in Kernel and STDLIB, as well as the VM are Unicode-aware.\n\n- **File I/O** - I/O is by far the most problematic area for Unicode. A file is\n an entity where bytes are stored, and the lore of programming has been to\n treat characters and bytes as interchangeable. With Unicode characters, you\n must decide on an encoding when you want to store the data in a file. In\n Erlang, you can open a text file with an encoding option, so that you can read\n characters from it rather than bytes, but you can also open a file for\n bytewise I/O.\n\n The Erlang I/O-system has been designed (or at least used) in a way where you\n expect any I/O server to handle any string data. That is, however, no longer\n the case when working with Unicode characters. The Erlang programmer must now\n know the capabilities of the device where the data ends up. Also, ports in\n Erlang are byte-oriented, so an arbitrary string of (Unicode) characters\n cannot be sent to a port without first converting it to an encoding of choice.\n\n- **Terminal I/O** - Terminal I/O is slightly easier than file I/O. The output\n is meant for human reading and is usually Erlang syntax (for example, in the\n shell). There exists syntactic representation of any Unicode character without\n displaying the glyph (instead written as `\\x`\\{`HHH`\\}). Unicode data can\n therefore usually be displayed even if the terminal as such does not support\n the whole Unicode range.\n\n- **Filenames** - Filenames can be stored as Unicode strings in different ways\n depending on the underlying operating system and file system. This can be\n handled fairly easy by a program. The problems arise when the file system is\n inconsistent in its encodings. For example, Linux allows files to be named\n with any sequence of bytes, leaving to each program to interpret those bytes.\n On systems where these \"transparent\" filenames are used, Erlang must be\n informed about the filename encoding by a startup flag. The default is\n bytewise interpretation, which is usually wrong, but allows for interpretation\n of _all_ filenames.\n\n The concept of \"raw filenames\" can be used to handle wrongly encoded filenames\n if one enables Unicode filename translation (`+fnu`) on platforms where this\n is not the default.\n\n- **Source code encoding** - The Erlang source code has support for the UTF-8\n encoding and bytewise encoding. The default in Erlang/OTP R16B was bytewise\n (`latin1`) encoding. It was changed to UTF-8 in Erlang/OTP 17.0. You can\n control the encoding by a comment like the following in the beginning of the\n file:\n\n ```erlang\n %% -*- coding: utf-8 -*-\n ```\n\n This of course requires your editor to support UTF-8 as well. The same comment\n is also interpreted by functions like `file:consult/1`, the release handler,\n and so on, so that you can have all text files in your source directories in\n UTF-8 encoding.\n\n- **The language** - Having the source code in UTF-8 also allows you to write\n string literals, function names, and atoms containing Unicode characters with\n code points > 255. Module names, application names, and node names are still\n restricted to the ISO Latin-1 range. Binary literals, where you use type\n `/utf8`, can also be expressed using Unicode characters > 255. Having module\n names or application names using characters other than 7-bit ASCII can cause\n trouble on operating systems with inconsistent file naming schemes, and can\n hurt portability, so it is not recommended.\n\n EEP 40 suggests that the language is also to allow for Unicode characters >\n 255 in variable names. Whether to implement that EEP is yet to be decided.","title":"Areas of Unicode Support - Using Unicode in Erlang","ref":"unicode_usage.html#areas-of-unicode-support"},{"type":"extras","doc":"In Erlang, strings are lists of integers. A string was until Erlang/OTP R13\ndefined to be encoded in the ISO Latin-1 (ISO 8859-1) character set, which is,\ncode point by code point, a subrange of the Unicode character set.\n\nThe standard list encoding for strings was therefore easily extended to handle\nthe whole Unicode range. A Unicode string in Erlang is a list containing\nintegers, where each integer is a valid Unicode code point and represents one\ncharacter in the Unicode character set.\n\nErlang strings in ISO Latin-1 are a subset of Unicode strings.\n\nOnly if a string contains code points < 256, can it be directly converted to a\nbinary by using, for example, `erlang:iolist_to_binary/1` or can be sent\ndirectly to a port. If the string contains Unicode characters > 255, an encoding\nmust be decided upon and the string is to be converted to a binary in the\npreferred encoding using\n[`unicode:characters_to_binary/1,2,3`](`unicode:characters_to_binary/1`).\nStrings are not generally lists of bytes, as they were before Erlang/OTP R13,\nthey are lists of characters. Characters are not generally bytes, they are\nUnicode code points.\n\nBinaries are more troublesome. For performance reasons, programs often store\ntextual data in binaries instead of lists, mainly because they are more compact\n(one byte per character instead of two words per character, as is the case with\nlists). Using `erlang:list_to_binary/1`, an ISO Latin-1 Erlang string can be\nconverted into a binary, effectively using bytewise encoding: one byte per\ncharacter. This was convenient for those limited Erlang strings, but cannot be\ndone for arbitrary Unicode lists.\n\nAs the UTF-8 encoding is widely spread and provides some backward compatibility\nin the 7-bit ASCII range, it is selected as the standard encoding for Unicode\ncharacters in binaries for Erlang.\n\nThe standard binary encoding is used whenever a library function in Erlang is to\nhandle Unicode data in binaries, but is of course not enforced when\ncommunicating externally. Functions and bit syntax exist to encode and decode\nboth UTF-8, UTF-16, and UTF-32 in binaries. However, library functions dealing\nwith binaries and Unicode in general only deal with the default encoding.\n\nCharacter data can be combined from many sources, sometimes available in a mix\nof strings and binaries. Erlang has for long had the concept of `iodata` or\n`iolist`s, where binaries and lists can be combined to represent a sequence of\nbytes. In the same way, the Unicode-aware modules often allow for combinations\nof binaries and lists, where the binaries have characters encoded in UTF-8 and\nthe lists contain such binaries or numbers representing Unicode code points:\n\n```erlang\nunicode_binary() = binary() with characters encoded in UTF-8 coding standard\n\nchardata() = charlist() | unicode_binary()\n\ncharlist() = maybe_improper_list(char() | unicode_binary() | charlist(),\n unicode_binary() | nil())\n```\n\nThe module `m:unicode` even supports similar mixes with binaries containing\nother encodings than UTF-8, but that is a special case to allow for conversions\nto and from external data:\n\n```erlang\nexternal_unicode_binary() = binary() with characters coded in a user-specified\n Unicode encoding other than UTF-8 (UTF-16 or UTF-32)\n\nexternal_chardata() = external_charlist() | external_unicode_binary()\n\nexternal_charlist() = maybe_improper_list(char() | external_unicode_binary() |\n external_charlist(), external_unicode_binary() | nil())\n```","title":"Standard Unicode Representation - Using Unicode in Erlang","ref":"unicode_usage.html#standard-unicode-representation"},{"type":"extras","doc":"[](){: #unicode_in_erlang } As from Erlang/OTP R16, Erlang source files can be\nwritten in UTF-8 or bytewise (`latin1`) encoding. For information about how to\nstate the encoding of an Erlang source file, see the [`epp`](`m:epp#encoding`)\nmodule. As from Erlang/OTP R16, strings and comments can be written using\nUnicode. As from Erlang/OTP 20, also atoms and functions can be written using\nUnicode. Modules, applications, and nodes must still be named using characters\nfrom the ISO Latin-1 character set. (These restrictions in the language are\nindependent of the encoding of the source file.)","title":"Basic Language Support - Using Unicode in Erlang","ref":"unicode_usage.html#basic-language-support"},{"type":"extras","doc":"The bit syntax contains types for handling binary data in the three main\nencodings. The types are named `utf8`, `utf16`, and `utf32`. The `utf16` and\n`utf32` types can be in a big-endian or a little-endian variant:\n\n```text\n< > = Bin1,\n< > = Bin2,\nBin3 = <<$H/utf32-little, $e/utf32-little, $l/utf32-little, $l/utf32-little,\n$o/utf32-little>>,\n```\n\nFor convenience, literal strings can be encoded with a Unicode encoding in\nbinaries using the following (or similar) syntax:\n\n```text\nBin4 = <<\"Hello\"/utf16>>,\n```","title":"Bit Syntax - Using Unicode in Erlang","ref":"unicode_usage.html#bit-syntax"},{"type":"extras","doc":"For source code, there is an extension to syntax `\\`OOO (backslash followed by\nthree octal numbers) and `\\x`HH (backslash followed by `x`, followed by two\nhexadecimal characters), namely `\\x{`H ...`}` (backslash followed by `x`,\nfollowed by left curly bracket, any number of hexadecimal digits, and a\nterminating right curly bracket). This allows for entering characters of any\ncode point literally in a string even when the encoding of the source file is\nbytewise (`latin1`).\n\nIn the shell, if using a Unicode input device, or in source code stored in\nUTF-8, `$` can be followed directly by a Unicode character producing an integer.\nIn the following example, the code point of a Cyrillic `с` is output:\n\n```text\n7> $с.\n1089\n```","title":"String and Character Literals - Using Unicode in Erlang","ref":"unicode_usage.html#string-and-character-literals"},{"type":"extras","doc":"In certain output functions and in the output of return values in the shell,\nErlang tries to detect string data in lists and binaries heuristically.\nTypically you will see heuristic detection in a situation like this:\n\n```erlang\n1> [97,98,99].\n\"abc\"\n2> <<97,98,99>>.\n<<\"abc\">>\n3> <<195,165,195,164,195,182>>.\n<<\"åäö\"/utf8>>\n```\n\nHere the shell detects lists containing printable characters or binaries\ncontaining printable characters in bytewise or UTF-8 encoding. But what is a\nprintable character? One view is that anything the Unicode standard thinks is\nprintable, is also printable according to the heuristic detection. The result is\nthen that almost any list of integers are deemed a string, and all sorts of\ncharacters are printed, maybe also characters that your terminal lacks in its\nfont set (resulting in some unappreciated generic output). Another way is to\nkeep it backward compatible so that only the ISO Latin-1 character set is used\nto detect a string. A third way is to let the user decide exactly what Unicode\nranges that are to be viewed as characters.\n\nAs from Erlang/OTP R16B you can select the ISO Latin-1 range or the whole\nUnicode range by supplying startup flag `+pc latin1` or `+pc unicode`,\nrespectively. For backward compatibility, `latin1` is default. This only\ncontrols how heuristic string detection is done. More ranges are expected to be\nadded in the future, enabling tailoring of the heuristics to the language and\nregion relevant to the user.\n\nThe following examples show the two startup options:\n\n```erlang\n$ erl +pc latin1\nErlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]\n\nEshell V5.10.1 (abort with ^G)\n1> [1024].\n[1024]\n2> [1070,1085,1080,1082,1086,1076].\n[1070,1085,1080,1082,1086,1076]\n3> [229,228,246].\n\"åäö\"\n4> <<208,174,208,189,208,184,208,186,208,190,208,180>>.\n<<208,174,208,189,208,184,208,186,208,190,208,180>>\n5> <<229/utf8,228/utf8,246/utf8>>.\n<<\"åäö\"/utf8>>\n```\n\n```erlang\n$ erl +pc unicode\nErlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]\n\nEshell V5.10.1 (abort with ^G)\n1> [1024].\n\"Ѐ\"\n2> [1070,1085,1080,1082,1086,1076].\n\"Юникод\"\n3> [229,228,246].\n\"åäö\"\n4> <<208,174,208,189,208,184,208,186,208,190,208,180>>.\n<<\"Юникод\"/utf8>>\n5> <<229/utf8,228/utf8,246/utf8>>.\n<<\"åäö\"/utf8>>\n```\n\nIn the examples, you can see that the default Erlang shell interprets only\ncharacters from the ISO Latin1 range as printable and only detects lists or\nbinaries with those \"printable\" characters as containing string data. The valid\nUTF-8 binary containing the Russian word \"Юникод\", is not printed as a string.\nWhen started with all Unicode characters printable (`+pc unicode`), the shell\noutputs anything containing printable Unicode data (in binaries, either UTF-8 or\nbytewise encoded) as string data.\n\nThese heuristics are also used by `io:format/2`, `io_lib:format/2`, and friends\nwhen modifier `t` is used with `~p` or `~P`:\n\n```erlang\n$ erl +pc latin1\nErlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]\n\nEshell V5.10.1 (abort with ^G)\n1> io:format(\"~tp~n\",[{<<\"åäö\">>, <<\"åäö\"/utf8>>, <<208,174,208,189,208,184,208,186,208,190,208,180>>}]).\n{<<\"åäö\">>,<<\"åäö\"/utf8>>,<<208,174,208,189,208,184,208,186,208,190,208,180>>}\nok\n```\n\n```erlang\n$ erl +pc unicode\nErlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]\n\nEshell V5.10.1 (abort with ^G)\n1> io:format(\"~tp~n\",[{<<\"åäö\">>, <<\"åäö\"/utf8>>, <<208,174,208,189,208,184,208,186,208,190,208,180>>}]).\n{<<\"åäö\">>,<<\"åäö\"/utf8>>,<<\"Юникод\"/utf8>>}\nok\n```\n\nNotice that this only affects _heuristic_ interpretation of lists and binaries\non output. For example, the `~ts` format sequence always outputs a valid list of\ncharacters, regardless of the `+pc` setting, as the programmer has explicitly\nrequested string output.","title":"Heuristic String Detection - Using Unicode in Erlang","ref":"unicode_usage.html#heuristic-string-detection"},{"type":"extras","doc":"The interactive Erlang shell can support Unicode input and output.\n\nOn Windows, proper operation requires that a suitable font is installed and\nselected for the Erlang application to use. If no suitable font is available on\nyour system, try installing the [DejaVu fonts](http://dejavu-fonts.org), which\nare freely available, and then select that font in the Erlang shell application.\n\nOn Unix-like operating systems, the terminal is to be able to handle UTF-8 on\ninput and output (this is done by, for example, modern versions of XTerm, KDE\nKonsole, and the Gnome terminal) and your locale settings must be proper. As an\nexample, a `LANG` environment variable can be set as follows:\n\n```text\n$ echo $LANG\nen_US.UTF-8\n```\n\nMost systems handle variable `LC_CTYPE` before `LANG`, so if that is set, it\nmust be set to `UTF-8`:\n\n```text\n$ echo $LC_CTYPE\nen_US.UTF-8\n```\n\nThe `LANG` or `LC_CTYPE` setting are to be consistent with what the terminal is\ncapable of. There is no portable way for Erlang to ask the terminal about its\nUTF-8 capacity, we have to rely on the language and character type settings.\n\nTo investigate what Erlang thinks about the terminal, the call\n[`io:getopts()`](`io:getopts/1`) can be used when the shell is started:\n\n```erlang\n$ LC_CTYPE=en_US.ISO-8859-1 erl\nErlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]\n\nEshell V5.10.1 (abort with ^G)\n1> lists:keyfind(encoding, 1, io:getopts()).\n{encoding,latin1}\n2> q().\nok\n$ LC_CTYPE=en_US.UTF-8 erl\nErlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]\n\nEshell V5.10.1 (abort with ^G)\n1> lists:keyfind(encoding, 1, io:getopts()).\n{encoding,unicode}\n2>\n```\n\nWhen (finally?) everything is in order with the locale settings, fonts. and the\nterminal emulator, you have probably found a way to input characters in the\nscript you desire. For testing, the simplest way is to add some keyboard\nmappings for other languages, usually done with some applet in your desktop\nenvironment.\n\nIn a KDE environment, select _KDE Control Center (Personal Settings)_ >\n_Regional and Accessibility_ > _Keyboard Layout_.\n\nOn Windows XP, select _Control Panel_ > _Regional and Language Options_, select\ntab _Language_, and click button _Details..._ in the square named _Text Services\nand Input Languages_.\n\nYour environment probably provides similar means of changing the keyboard\nlayout. Ensure that you have a way to switch back and forth between keyboards\neasily if you are not used to this. For example, entering commands using a\nCyrillic character set is not easily done in the Erlang shell.\n\nNow you are set up for some Unicode input and output. The simplest thing to do\nis to enter a string in the shell:\n\n```erlang\n$ erl\nErlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]\n\nEshell V5.10.1 (abort with ^G)\n1> lists:keyfind(encoding, 1, io:getopts()).\n{encoding,unicode}\n2> \"Юникод\".\n\"Юникод\"\n3> io:format(\"~ts~n\", [v(2)]).\nЮникод\nok\n4>\n```\n\nWhile strings can be input as Unicode characters, the language elements are\nstill limited to the ISO Latin-1 character set. Only character constants and\nstrings are allowed to be beyond that range:\n\n```text\n$ erl\nErlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]\n\nEshell V5.10.1 (abort with ^G)\n1> $ξ.\n958\n2> Юникод.\n* 1: illegal character\n2>\n```","title":"The Interactive Shell - Using Unicode in Erlang","ref":"unicode_usage.html#the-interactive-shell"},{"type":"extras","doc":"When Erlang is started without an interactive shell (`-noshell`, `-noinput` or\nas an escript) the unicode support is identified using environment variables\njust as for [interactive shells](unicode_usage.md#the-interactive-shell).\nWorking with unicode in non-interactive sessions works just the same as for\ninteractive sessions.\n\nIn some situations you may need to be able to read and write raw bytes from\n[`standard_io`](`t:io:standard_io/0`). If that is the case, then you want to set\nthe [standard_io_encoding](`e:kernel:kernel_app.md#standard_io_encoding`)\nconfiguration parameter to `latin1` and use the `m:file` API to read and write\ndata (as explained in\n[Unicode Data in Files](unicode_usage.md#unicode-data-in-files)).\n\nIn the example below we first read the character `ξ` from\n[`standard_io`](`t:io:standard_io/0`) and then print the\n[charlist()](`t:unicode:charlist/0`) represented by it.\n\n```erlang\n#!/usr/bin/env escript\n%%! -kernel standard_io_encoding latin1\n\nmain(_) ->\n {ok, Char} = file:read_line(standard_io),\n ok = file:write(standard_io, string:trim(Char)),\n ok = file:write(standard_io, io_lib:format(\": ~w~n\",[string:trim(Char)])),\n ok.\n```\n\n```text\n$ escript test.es\nξ\nξ: [206,190]\n```\n\n`ξ` would normally be represented as the integer 958, but since we are using\nbytewise encoding (`latin1`), it is represented by 206 and 190, which is the\nutf-8 bytes representing `ξ`. When we echo those bytes back to\n[`standard_io`](`t:io:standard_io/0`), the terminal will see the bytes as utf-8\nand show the correct value even though in Erlang we never knew that it was\nindeed a unicode string.\n\n[](){: #unicode_file_names }","title":"Escripts and non-interactive I/O - Using Unicode in Erlang","ref":"unicode_usage.html#escripts-and-non-interactive-i-o"},{"type":"extras","doc":"Most modern operating systems support Unicode filenames in some way. There are\nmany different ways to do this and Erlang by default treats the different\napproaches differently:\n\n- **Mandatory Unicode file naming** - Windows, Android and, for most cases,\n MacOS X enforce Unicode support for filenames. All files created in the file\n system have names that can consistently be interpreted. In MacOS X and\n Android, all filenames are retrieved in UTF-8 encoding. In Windows, each\n system call handling filenames has a special Unicode-aware variant, giving\n much the same effect. There are no filenames on these systems that are not\n Unicode filenames. So, the default behavior of the Erlang VM is to work in\n \"Unicode filename translation mode\". This means that a filename can be\n specified as a Unicode list, which is automatically translated to the proper\n name encoding for the underlying operating system and file system.\n\n Doing, for example, a `file:list_dir/1` on one of these systems can return\n Unicode lists with code points > 255, depending on the content of the file\n system.\n\n- **Transparent file naming** - Most Unix operating systems have adopted a\n simpler approach, namely that Unicode file naming is not enforced, but by\n convention. Those systems usually use UTF-8 encoding for Unicode filenames,\n but do not enforce it. On such a system, a filename containing characters with\n code points from 128 through 255 can be named as plain ISO Latin-1 or use\n UTF-8 encoding. As no consistency is enforced, the Erlang VM cannot do\n consistent translation of all filenames.\n\n By default on such systems, Erlang starts in `utf8` filename mode if the\n terminal supports UTF-8, otherwise in `latin1` mode.\n\n In `latin1` mode, filenames are bytewise encoded. This allows for list\n representation of all filenames in the system. However, a a file named\n \"Östersund.txt\", appears in `file:list_dir/1` either as \"Östersund.txt\" (if\n the filename was encoded in bytewise ISO Latin-1 by the program creating the\n file) or more probably as `[195,150,115,116,101,114,115,117,110,100]`, which\n is a list containing UTF-8 bytes (not what you want). If you use Unicode\n filename translation on such a system, non-UTF-8 filenames are ignored by\n functions like `file:list_dir/1`. They can be retrieved with function\n `file:list_dir_all/1`, but wrongly encoded filenames appear as \"raw\n filenames\".\n\nThe Unicode file naming support was introduced in Erlang/OTP R14B01. A VM\noperating in Unicode filename translation mode can work with files having names\nin any language or character set (as long as it is supported by the underlying\noperating system and file system). The Unicode character list is used to denote\nfilenames or directory names. If the file system content is listed, you also get\nUnicode lists as return value. The support lies in the Kernel and STDLIB\nmodules, which is why most applications (that do not explicitly require the\nfilenames to be in the ISO Latin-1 range) benefit from the Unicode support\nwithout change.\n\nOn operating systems with mandatory Unicode filenames, this means that you more\neasily conform to the filenames of other (non-Erlang) applications. You can also\nprocess filenames that, at least on Windows, were inaccessible (because of\nhaving names that could not be represented in ISO Latin-1). Also, you avoid\ncreating incomprehensible filenames on MacOS X, as the `vfs` layer of the\noperating system accepts all your filenames as UTF-8 does not rewrite them.\n\nFor most systems, turning on Unicode filename translation is no problem even if\nit uses transparent file naming. Very few systems have mixed filename encodings.\nA consistent UTF-8 named system works perfectly in Unicode filename mode. It was\nstill, however, considered experimental in Erlang/OTP R14B01 and is still not\nthe default on such systems.\n\nUnicode filename translation is turned on with switch `+fnu`. On Linux, a VM\nstarted without explicitly stating the filename translation mode defaults to\n`latin1` as the native filename encoding. On Windows, MacOS X and Android, the\ndefault behavior is that of Unicode filename translation. Therefore\n`file:native_name_encoding/0` by default returns `utf8` on those systems\n(Windows does not use UTF-8 on the file system level, but this can safely be\nignored by the Erlang programmer). The default behavior can, as stated earlier,\nbe changed using option `+fnu` or `+fnl` to the VM, see the\n[`erl`](`e:erts:erl_cmd.md`) program. If the VM is started in Unicode filename\ntranslation mode, `file:native_name_encoding/0` returns atom `utf8`. Switch\n`+fnu` can be followed by `w`, `i`, or `e` to control how wrongly encoded\nfilenames are to be reported.\n\n- `w` means that a warning is sent to the `error_logger` whenever a wrongly\n encoded filename is \"skipped\" in directory listings. `w` is the default.\n- `i` means that wrongly encoded filenames are silently ignored.\n- `e` means that the API function returns an error whenever a wrongly encoded\n filename (or directory name) is encountered.\n\nNotice that `file:read_link/1` always returns an error if the link points to an\ninvalid filename.\n\nIn Unicode filename mode, filenames given to BIF [`open_port/2`](`open_port/2`)\nwith option `{spawn_executable,...}` are also interpreted as Unicode. So is the\nparameter list specified in option `args` available when using\n`spawn_executable`. The UTF-8 translation of arguments can be avoided using\nbinaries, see section\n[Notes About Raw Filenames](unicode_usage.md#notes-about-raw-filenames).\n\nNotice that the file encoding options specified when opening a file has nothing\nto do with the filename encoding convention. You can very well open files\ncontaining data encoded in UTF-8, but having filenames in bytewise (`latin1`)\nencoding or conversely.\n\n> #### Note {: .info }\n>\n> Erlang drivers and NIF-shared objects still cannot be named with names\n> containing code points > 127. This limitation will be removed in a future\n> release. However, Erlang modules can, but it is definitely not a good idea and\n> is still considered experimental.","title":"Unicode Filenames - Using Unicode in Erlang","ref":"unicode_usage.html#unicode-filenames"},{"type":"extras","doc":"> #### Note {: .info }\n>\n> Note that raw filenames _not_ necessarily are encoded the same way as on the\n> OS level.\n\nRaw filenames were introduced together with Unicode filename support in ERTS\n5.8.2 (Erlang/OTP R14B01). The reason \"raw filenames\" were introduced in the\nsystem was to be able to represent filenames, specified in different encodings\non the same system, consistently. It can seem practical to have the VM\nautomatically translate a filename that is not in UTF-8 to a list of Unicode\ncharacters, but this would open up for both duplicate filenames and other\ninconsistent behavior.\n\nConsider a directory containing a file named \"björn\" in ISO Latin-1, while the\nErlang VM is operating in Unicode filename mode (and therefore expects UTF-8\nfile naming). The ISO Latin-1 name is not valid UTF-8 and one can be tempted to\nthink that automatic conversion in, for example, `file:list_dir/1` is a good\nidea. But what would happen if we later tried to open the file and have the name\nas a Unicode list (magically converted from the ISO Latin-1 filename)? The VM\nconverts the filename to UTF-8, as this is the encoding expected. Effectively\nthis means trying to open the file named <<\"björn\"/utf8>>. This file does not\nexist, and even if it existed it would not be the same file as the one that was\nlisted. We could even create two files named \"björn\", one named in UTF-8\nencoding and one not. If `file:list_dir/1` would automatically convert the ISO\nLatin-1 filename to a list, we would get two identical filenames as the result.\nTo avoid this, we must differentiate between filenames that are properly encoded\naccording to the Unicode file naming convention (that is, UTF-8) and filenames\nthat are invalid under the encoding. By the common function `file:list_dir/1`,\nthe wrongly encoded filenames are ignored in Unicode filename translation mode,\nbut by function `file:list_dir_all/1` the filenames with invalid encoding are\nreturned as \"raw\" filenames, that is, as binaries.\n\nThe `file` module accepts raw filenames as input.\n`open_port({spawn_executable, ...} ...)` also accepts them. As mentioned\nearlier, the arguments specified in the option list to\n`open_port({spawn_executable, ...} ...)` undergo the same conversion as the\nfilenames, meaning that the executable is provided with arguments in UTF-8 as\nwell. This translation is avoided consistently with how the filenames are\ntreated, by giving the argument as a binary.\n\nTo force Unicode filename translation mode on systems where this is not the\ndefault was considered experimental in Erlang/OTP R14B01. This was because the\ninitial implementation did not ignore wrongly encoded filenames, so that raw\nfilenames could spread unexpectedly throughout the system. As from Erlang/OTP\nR16B, the wrongly encoded filenames are only retrieved by special functions\n(such as `file:list_dir_all/1`). Since the impact on existing code is therefore\nmuch lower it is now supported. Unicode filename translation is expected to be\ndefault in future releases.\n\nEven if you are operating without Unicode file naming translation automatically\ndone by the VM, you can access and create files with names in UTF-8 encoding by\nusing raw filenames encoded as UTF-8. Enforcing the UTF-8 encoding regardless of\nthe mode the Erlang VM is started in can in some circumstances be a good idea,\nas the convention of using UTF-8 filenames is spreading.","title":"Notes About Raw Filenames - Using Unicode in Erlang","ref":"unicode_usage.html#notes-about-raw-filenames"},{"type":"extras","doc":"The `vfs` layer of MacOS X enforces UTF-8 filenames in an aggressive way. Older\nversions did this by refusing to create non-UTF-8 conforming filenames, while\nnewer versions replace offending bytes with the sequence \"%HH\", where HH is the\noriginal character in hexadecimal notation. As Unicode translation is enabled by\ndefault on MacOS X, the only way to come up against this is to either start the\nVM with flag `+fnl` or to use a raw filename in bytewise (`latin1`) encoding. If\nusing a raw filename, with a bytewise encoding containing characters from 127\nthrough 255, to create a file, the file cannot be opened using the same name as\nthe one used to create it. There is no remedy for this behavior, except keeping\nthe filenames in the correct encoding.\n\nMacOS X reorganizes the filenames so that the representation of accents, and so\non, uses the \"combining characters\". For example, character `ö` is represented\nas code points `[111,776]`, where `111` is character `o` and `776` is the\nspecial accent character \"Combining Diaeresis\". This way of normalizing Unicode\nis otherwise very seldom used. Erlang normalizes those filenames in the opposite\nway upon retrieval, so that filenames using combining accents are not passed up\nto the Erlang application. In Erlang, filename \"björn\" is retrieved as\n`[98,106,246,114,110]`, not as `[98,106,117,776,114,110]`, although the file\nsystem can think differently. The normalization into combining accents is redone\nwhen accessing files, so this can usually be ignored by the Erlang programmer.","title":"Notes About MacOS X - Using Unicode in Erlang","ref":"unicode_usage.html#notes-about-macos-x"},{"type":"extras","doc":"[](){: #unicode_in_environment_and_parameters }\n\nEnvironment variables and their interpretation are handled much in the same way\nas filenames. If Unicode filenames are enabled, environment variables as well as\nparameters to the Erlang VM are expected to be in Unicode.\n\nIf Unicode filenames are enabled, the calls to [`os:getenv/0,1`](`os:getenv/0`),\n`os:putenv/2`, and `os:unsetenv/1` handle Unicode strings. On Unix-like\nplatforms, the built-in functions translate environment variables in UTF-8\nto/from Unicode strings, possibly with code points > 255. On Windows, the\nUnicode versions of the environment system API are used, and code points > 255\nare allowed.\n\nOn Unix-like operating systems, parameters are expected to be UTF-8 without\ntranslation if Unicode filenames are enabled.","title":"Unicode in Environment and Parameters - Using Unicode in Erlang","ref":"unicode_usage.html#unicode-in-environment-and-parameters"},{"type":"extras","doc":"Most of the modules in Erlang/OTP are Unicode-unaware in the sense that they\nhave no notion of Unicode and should not have. Typically they handle non-textual\nor byte-oriented data (such as `gen_tcp`).\n\nModules handling textual data (such as `m:io_lib` and `m:string` are sometimes\nsubject to conversion or extension to be able to handle Unicode characters.\n\nFortunately, most textual data has been stored in lists and range checking has\nbeen sparse, so modules like `string` work well for Unicode strings with little\nneed for conversion or extension.\n\nSome modules are, however, changed to be explicitly Unicode-aware. These modules\ninclude:\n\n- **`unicode`** - The `m:unicode` module is clearly Unicode-aware. It contains\n functions for conversion between different Unicode formats and some utilities\n for identifying byte order marks. Few programs handling Unicode data survive\n without this module.\n\n- **`io`** - The `m:io` module has been extended along with the actual I/O\n protocol to handle Unicode data. This means that many functions require\n binaries to be in UTF-8, and there are modifiers to format control sequences\n to allow for output of Unicode strings.\n\n- **`file`, `group`, `user`** - I/O-servers throughout the system can handle\n Unicode data and have options for converting data upon output or input to/from\n the device. As shown earlier, the `m:shell` module has support for Unicode\n terminals and the `m:file` module allows for translation to and from various\n Unicode formats on disk.\n\n Reading and writing of files with Unicode data is, however, not best done with\n the `file` module, as its interface is byte-oriented. A file opened with a\n Unicode encoding (like UTF-8) is best read or written using the `m:io` module.\n\n- **`re`** - The `m:re` module allows for matching Unicode strings as a special\n option. As the library is centered on matching in binaries, the Unicode\n support is UTF-8-centered.\n\n- **`wx`** - The graphical library `m:wx` has extensive support for Unicode\n text.\n\nThe `m:string` module works perfectly for Unicode strings and ISO Latin-1\nstrings, except the language-dependent functions `string:uppercase/1` and\n`string:lowercase/1`. These two functions can never function correctly for\nUnicode characters in their current form, as there are language and locale\nissues to consider when converting text between cases. Converting case in an\ninternational environment is a large subject not yet addressed in OTP.","title":"Unicode-Aware Modules - Using Unicode in Erlang","ref":"unicode_usage.html#unicode-aware-modules"},{"type":"extras","doc":"Although Erlang can handle Unicode data in many forms does not automatically\nmean that the content of any file can be Unicode text. The external entities,\nsuch as ports and I/O servers, are not generally Unicode capable.\n\nPorts are always byte-oriented, so before sending data that you are not sure is\nbytewise-encoded to a port, ensure to encode it in a proper Unicode encoding.\nSometimes this means that only part of the data must be encoded as, for example,\nUTF-8. Some parts can be binary data (like a length indicator) or something else\nthat must not undergo character encoding, so no automatic translation is\npresent.\n\nI/O servers behave a little differently. The I/O servers connected to terminals\n(or `stdout`) can usually cope with Unicode data regardless of the encoding\noption. This is convenient when one expects a modern environment but do not want\nto crash when writing to an archaic terminal or pipe.\n\nA file can have an encoding option that makes it generally usable by the `m:io`\nmodule (for example `{encoding,utf8}`), but is by default opened as a\nbyte-oriented file. The `m:file` module is byte-oriented, so only ISO Latin-1\ncharacters can be written using that module. Use the `io` module if Unicode data\nis to be output to a file with other `encoding` than `latin1` (bytewise\nencoding). It is slightly confusing that a file opened with, for example,\n`file:open(Name,[read,{encoding,utf8}])` cannot be properly read using\n`file:read(File,N)`, but using the `io` module to retrieve the Unicode data from\nit. The reason is that `file:read` and `file:write` (and friends) are purely\nbyte-oriented, and should be, as that is the way to access files other than text\nfiles, byte by byte. As with ports, you can write encoded data into a file by\n\"manually\" converting the data to the encoding of choice (using the `m:unicode`\nmodule or the bit syntax) and then output it on a bytewise (`latin1`) encoded\nfile.\n\nRecommendations:\n\n- Use the `m:file` module for files opened for bytewise access\n (`{encoding,latin1}`).\n- Use the `m:io` module when accessing files with any other encoding (for\n example `{encoding,utf8}`).\n\nFunctions reading Erlang syntax from files recognize the `coding:` comment and\ncan therefore handle Unicode data on input. When writing Erlang terms to a file,\nyou are advised to insert such comments when applicable:\n\n```erlang\n$ erl +fna +pc unicode\nErlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]\n\nEshell V5.10.1 (abort with ^G)\n1> file:write_file(\"test.term\",<<\"%% coding: utf-8\\n[{\\\"Юникод\\\",4711}].\\n\"/utf8>>).\nok\n2> file:consult(\"test.term\").\n{ok,[[{\"Юникод\",4711}]]}\n```","title":"Unicode Data in Files - Using Unicode in Erlang","ref":"unicode_usage.html#unicode-data-in-files"},{"type":"extras","doc":"[](){: #unicode_options_summary }\n\nThe Unicode support is controlled by both command-line switches, some standard\nenvironment variables, and the OTP version you are using. Most options affect\nmainly how Unicode data is displayed, not the functionality of the APIs in the\nstandard libraries. This means that Erlang programs usually do not need to\nconcern themselves with these options, they are more for the development\nenvironment. An Erlang program can be written so that it works well regardless\nof the type of system or the Unicode options that are in effect.\n\nHere follows a summary of the settings affecting Unicode:\n\n- **The `LANG` and `LC_CTYPE` environment variables** - The language setting in\n the operating system mainly affects the shell. The terminal (that is, the\n group leader) operates with `{encoding, unicode}` only if the environment\n tells it that UTF-8 is allowed. This setting is to correspond to the terminal\n you are using.\n\n The environment can also affect filename interpretation, if Erlang is started\n with flag `+fna` (which is default from Erlang/OTP 17.0).\n\n You can check the setting of this by calling [`io:getopts()`](`io:getopts/1`),\n which gives you an option list containing `{encoding,unicode}` or\n `{encoding,latin1}`.\n\n- **The `+pc` \\{`unicode`|`latin1`\\} flag to [`erl(1)`](`e:erts:erl_cmd.md`)** -\n This flag affects what is interpreted as string data when doing heuristic\n string detection in the shell and in `m:io`/\n [`io_lib:format`](`io_lib:format/2`) with the `\"~tp\"` and `~tP` formatting\n instructions, as described earlier.\n\n You can check this option by calling `io:printable_range/0`, which returns\n `unicode` or `latin1`. To be compatible with future (expected) extensions to\n the settings, rather use `io_lib:printable_list/1` to check if a list is\n printable according to the setting. That function takes into account new\n possible settings returned from `io:printable_range/0`.\n\n- **The `+fn`\\{`l`|`u`|`a`\\} [\\{`w`|`i`|`e`\\}] flag to\n [`erl(1)`](`e:erts:erl_cmd.md`)** - This flag affects how the filenames are to\n be interpreted. On operating systems with transparent file naming, this must\n be specified to allow for file naming in Unicode characters (and for correct\n interpretation of filenames containing characters > 255).\n\n - `+fnl` means bytewise interpretation of filenames, which was the usual way\n to represent ISO Latin-1 filenames before UTF-8 file naming got widespread.\n - `+fnu` means that filenames are encoded in UTF-8, which is nowadays the\n common scheme (although not enforced).\n - `+fna` means that you automatically select between `+fnl` and `+fnu`, based\n on environment variables `LANG` and `LC_CTYPE`. This is optimistic\n heuristics indeed, nothing enforces a user to have a terminal with the same\n encoding as the file system, but this is usually the case. This is the\n default on all Unix-like operating systems, except MacOS X.\n\n The filename translation mode can be read with function\n `file:native_name_encoding/0`, which returns `latin1` (bytewise encoding) or\n `utf8`.\n\n- **`epp:default_encoding/0`** - This function returns the default encoding for\n Erlang source files (if no encoding comment is present) in the currently\n running release. In Erlang/OTP R16B, `latin1` (bytewise encoding) was\n returned. As from Erlang/OTP 17.0, `utf8` is returned.\n\n The encoding of each file can be specified using comments as described in the\n [`epp`](`m:epp#encoding`) module.\n\n- **[`io:setopts/1,2`](`io:setopts/1`) and\n [`standard_io_encoding`](`e:kernel:kernel_app.md#standard_io_encoding`)** -\n When Erlang is started the encoding for [`standard_io`](`t:io:standard_io/0`)\n is by default set to what the\n [locale settings indicate](unicode_usage.md#the-interactive-shell). You can\n override the default by setting the kernel configuration parameter\n [`standard_io_encoding`](`e:kernel:kernel_app.md#standard_io_encoding`) to the\n desired encoding.\n\n You can set the encoding of a file or other I/O server with function\n [`io:setopts/2`](`io:setopts/1`). This can also be set when opening a file.\n Setting the terminal (or other [`standard_io`](`t:io:standard_io/0`) server)\n unconditionally to option `{encoding,utf8}` implies that UTF-8 encoded\n characters are written to the device, regardless of how Erlang was started or\n the user's environment.\n\n > #### Note {: .info }\n >\n > If you use [`io:setopts/2`](`io:setopts/1`) to change the encoding of\n > [`standard_io`](`t:io:standard_io/0`) the I/O server may already have read\n > some data using the default encoding. To avoid this you should set the\n > encoding using\n > [`standard_io_encoding`](`e:kernel:kernel_app.md#standard_io_encoding`).\n\n Opening files with option `encoding` is convenient when writing or reading\n text files in a known encoding.\n\n You can retrieve the `encoding` setting for an I/O server with function\n [`io:getopts()`](`io:getopts/1`).","title":"Summary of Options - Using Unicode in Erlang","ref":"unicode_usage.html#summary-of-options"},{"type":"extras","doc":"When starting with Unicode, one often stumbles over some common issues. This\nsection describes some methods of dealing with Unicode data.","title":"Recipes - Using Unicode in Erlang","ref":"unicode_usage.html#recipes"},{"type":"extras","doc":"A common method of identifying encoding in text files is to put a Byte Order\nMark (BOM) first in the file. The BOM is the code point 16#FEFF encoded in the\nsame way as the remaining file. If such a file is to be read, the first few\nbytes (depending on encoding) are not part of the text. This code outlines how\nto open a file that is believed to have a BOM, and sets the files encoding and\nposition for further sequential reading (preferably using the `m:io` module).\n\nNotice that error handling is omitted from the code:\n\n```erlang\nopen_bom_file_for_reading(File) ->\n {ok,F} = file:open(File,[read,binary]),\n {ok,Bin} = file:read(F,4),\n {Type,Bytes} = unicode:bom_to_encoding(Bin),\n file:position(F,Bytes),\n io:setopts(F,[{encoding,Type}]),\n {ok,F}.\n```\n\nFunction `unicode:bom_to_encoding/1` identifies the encoding from a binary of at\nleast four bytes. It returns, along with a term suitable for setting the\nencoding of the file, the byte length of the BOM, so that the file position can\nbe set accordingly. Notice that function `file:position/2` always works on\nbyte-offsets, so that the byte length of the BOM is needed.\n\nTo open a file for writing and place the BOM first is even simpler:\n\n```erlang\nopen_bom_file_for_writing(File,Encoding) ->\n {ok,F} = file:open(File,[write,binary]),\n ok = file:write(File,unicode:encoding_to_bom(Encoding)),\n io:setopts(F,[{encoding,Encoding}]),\n {ok,F}.\n```\n\nThe file is in both these cases then best processed using the `m:io` module, as\nthe functions in that module can handle code points beyond the ISO Latin-1\nrange.","title":"Byte Order Marks - Using Unicode in Erlang","ref":"unicode_usage.html#byte-order-marks"},{"type":"extras","doc":"When reading and writing to Unicode-aware entities, like a file opened for\nUnicode translation, you probably want to format text strings using the\nfunctions in the `m:io` module or the `m:io_lib` module. For backward\ncompatibility reasons, these functions do not accept any list as a string, but\nrequire a special _translation modifier_ when working with Unicode texts. The\nmodifier is `t`. When applied to control character `s` in a formatting string,\nit accepts all Unicode code points and expects binaries to be in UTF-8:\n\n```erlang\n1> io:format(\"~ts~n\",[<<\"åäö\"/utf8>>]).\nåäö\nok\n2> io:format(\"~s~n\",[<<\"åäö\"/utf8>>]).\nåäö\nok\n```\n\nClearly, the second `io:format/2` gives undesired output, as the UTF-8 binary is\nnot in `latin1`. For backward compatibility, the non-prefixed control character\n`s` expects bytewise-encoded ISO Latin-1 characters in binaries and lists\ncontaining only code points < 256.\n\nAs long as the data is always lists, modifier `t` can be used for any string,\nbut when binary data is involved, care must be taken to make the correct choice\nof formatting characters. A bytewise-encoded binary is also interpreted as a\nstring, and printed even when using `~ts`, but it can be mistaken for a valid\nUTF-8 string. Avoid therefore using the `~ts` control if the binary contains\nbytewise-encoded characters and not UTF-8.\n\nFunction `io_lib:format/2` behaves similarly. It is defined to return a deep\nlist of characters and the output can easily be converted to binary data for\noutputting on any device by a simple `erlang:list_to_binary/1`. When the\ntranslation modifier is used, the list can, however, contain characters that\ncannot be stored in one byte. The call to `erlang:list_to_binary/1` then fails.\nHowever, if the I/O server you want to communicate with is Unicode-aware, the\nreturned list can still be used directly:\n\n```erlang\n$ erl +pc unicode\nErlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]\n\nEshell V5.10.1 (abort with ^G)\n1> io_lib:format(\"~ts~n\", [\"Γιούνικοντ\"]).\n[\"Γιούνικοντ\",\"\\n\"]\n2> io:put_chars(io_lib:format(\"~ts~n\", [\"Γιούνικοντ\"])).\nΓιούνικοντ\nok\n```\n\nThe Unicode string is returned as a Unicode list, which is recognized as such,\nas the Erlang shell uses the Unicode encoding (and is started with all Unicode\ncharacters considered printable). The Unicode list is valid input to function\n`io:put_chars/2`, so data can be output on any Unicode-capable device. If the\ndevice is a terminal, characters are output in format `\\x{`H...`}` if encoding\nis `latin1`. Otherwise in UTF-8 (for the non-interactive terminal: \"oldshell\" or\n\"noshell\") or whatever is suitable to show the character properly (for an\ninteractive terminal: the regular shell).\n\nSo, you can always send Unicode data to the\n[`standard_io`](`t:io:standard_io/0`) device. Files, however, accept only\nUnicode code points beyond ISO Latin-1 if `encoding` is set to something else\nthan `latin1`.","title":"Formatted I/O - Using Unicode in Erlang","ref":"unicode_usage.html#formatted-i-o"},{"type":"extras","doc":"While it is strongly encouraged that the encoding of characters in binary data\nis known before processing, that is not always possible. On a typical Linux\nsystem, there is a mix of UTF-8 and ISO Latin-1 text files, and there are seldom\nany BOMs in the files to identify them.\n\nUTF-8 is designed so that ISO Latin-1 characters with numbers beyond the 7-bit\nASCII range are seldom considered valid when decoded as UTF-8. Therefore one can\nusually use heuristics to determine if a file is in UTF-8 or if it is encoded in\nISO Latin-1 (one byte per character). The `m:unicode` module can be used to\ndetermine if data can be interpreted as UTF-8:\n\n```erlang\nheuristic_encoding_bin(Bin) when is_binary(Bin) ->\n case unicode:characters_to_binary(Bin,utf8,utf8) of\n\tBin ->\n\t utf8;\n\t_ ->\n\t latin1\n end.\n```\n\nIf you do not have a complete binary of the file content, you can instead chunk\nthrough the file and check part by part. The return-tuple\n`{incomplete,Decoded,Rest}` from function\n[`unicode:characters_to_binary/1,2,3`](`unicode:characters_to_binary/1`) comes\nin handy. The incomplete rest from one chunk of data read from the file is\nprepended to the next chunk and we therefore avoid the problem of character\nboundaries when reading chunks of bytes in UTF-8 encoding:\n\n```erlang\nheuristic_encoding_file(FileName) ->\n {ok,F} = file:open(FileName,[read,binary]),\n loop_through_file(F,<<>>,file:read(F,1024)).\n\nloop_through_file(_,<<>>,eof) ->\n utf8;\nloop_through_file(_,_,eof) ->\n latin1;\nloop_through_file(F,Acc,{ok,Bin}) when is_binary(Bin) ->\n case unicode:characters_to_binary([Acc,Bin]) of\n\t{error,_,_} ->\n\t latin1;\n\t{incomplete,_,Rest} ->\n\t loop_through_file(F,Rest,file:read(F,1024));\n\tRes when is_binary(Res) ->\n\t loop_through_file(F,<<>>,file:read(F,1024))\n end.\n```\n\nAnother option is to try to read the whole file in UTF-8 encoding and see if it\nfails. Here we need to read the file using function `io:get_chars/3`, as we have\nto read characters with a code point > 255:\n\n```erlang\nheuristic_encoding_file2(FileName) ->\n {ok,F} = file:open(FileName,[read,binary,{encoding,utf8}]),\n loop_through_file2(F,io:get_chars(F,'',1024)).\n\nloop_through_file2(_,eof) ->\n utf8;\nloop_through_file2(_,{error,_Err}) ->\n latin1;\nloop_through_file2(F,Bin) when is_binary(Bin) ->\n loop_through_file2(F,io:get_chars(F,'',1024)).\n```","title":"Heuristic Identification of UTF-8 - Using Unicode in Erlang","ref":"unicode_usage.html#heuristic-identification-of-utf-8"},{"type":"extras","doc":"For various reasons, you can sometimes have a list of UTF-8 bytes. This is not a\nregular string of Unicode characters, as each list element does not contain one\ncharacter. Instead you get the \"raw\" UTF-8 encoding that you have in binaries.\nThis is easily converted to a proper Unicode string by first converting byte per\nbyte into a binary, and then converting the binary of UTF-8 encoded characters\nback to a Unicode string:\n\n```erlang\nutf8_list_to_string(StrangeList) ->\n unicode:characters_to_list(list_to_binary(StrangeList)).\n```","title":"Lists of UTF-8 Bytes - Using Unicode in Erlang","ref":"unicode_usage.html#lists-of-utf-8-bytes"},{"type":"extras","doc":"When working with binaries, you can get the horrible \"double UTF-8 encoding\",\nwhere strange characters are encoded in your binaries or files. In other words,\nyou can get a UTF-8 encoded binary that for the second time is encoded as UTF-8.\nA common situation is where you read a file, byte by byte, but the content is\nalready UTF-8. If you then convert the bytes to UTF-8, using, for example, the\n`m:unicode` module, or by writing to a file opened with option\n`{encoding,utf8}`, you have each _byte_ in the input file encoded as UTF-8, not\neach character of the original text (one character can have been encoded in many\nbytes). There is no real remedy for this other than to be sure of which data is\nencoded in which format, and never convert UTF-8 data (possibly read byte by\nbyte from a file) into UTF-8 again.\n\nBy far the most common situation where this occurs, is when you get lists of\nUTF-8 instead of proper Unicode strings, and then convert them to UTF-8 in a\nbinary or on a file:\n\n```erlang\nwrong_thing_to_do() ->\n {ok,Bin} = file:read_file(\"an_utf8_encoded_file.txt\"),\n MyList = binary_to_list(Bin), %% Wrong! It is an utf8 binary!\n {ok,C} = file:open(\"catastrophe.txt\",[write,{encoding,utf8}]),\n io:put_chars(C,MyList), %% Expects a Unicode string, but get UTF-8\n %% bytes in a list!\n file:close(C). %% The file catastrophe.txt contains more or less unreadable\n %% garbage!\n```\n\nEnsure you know what a binary contains before converting it to a string. If no\nother option exists, try heuristics:\n\n```erlang\nif_you_can_not_know() ->\n {ok,Bin} = file:read_file(\"maybe_utf8_encoded_file.txt\"),\n MyList = case unicode:characters_to_list(Bin) of\n L when is_list(L) ->\n L;\n _ ->\n binary_to_list(Bin) %% The file was bytewise encoded\n end,\n %% Now we know that the list is a Unicode string, not a list of UTF-8 bytes\n {ok,G} = file:open(\"greatness.txt\",[write,{encoding,utf8}]),\n io:put_chars(G,MyList), %% Expects a Unicode string, which is what it gets!\n file:close(G). %% The file contains valid UTF-8 encoded Unicode characters!\n```","title":"Double UTF-8 Encoding - Using Unicode in Erlang","ref":"unicode_usage.html#double-utf-8-encoding"},{"type":"extras","doc":"\n# Uniform Resource Identifiers","title":"Uniform Resource Identifiers","ref":"uri_string_usage.html"},{"type":"extras","doc":"At the time of writing this document, in October 2020, there are two major\nstandards concerning Universal Resource Identifiers and Universal Resource\nLocators:\n\n- [RFC 3986 - Uniform Resource Identifier (URI): Generic Syntax](https://www.ietf.org/rfc/rfc3986.txt)\n- [WHAT WG URL - Living standard](https://url.spec.whatwg.org/)\n\nThe former is a classical standard with a proper formal syntax, using the so\ncalled [Augmented Backus-Naur Form (ABNF)](https://www.ietf.org/rfc/rfc2234.txt)\nfor describing the grammar, while the latter is a living document describing the\ncurrent pratice, that is, how a majority of Web browsers work with URIs. WHAT WG\nURL is Web focused and it has no formal grammar but a plain english description\nof the algorithms that should be followed.\n\nWhat is the difference between them, if any? They provide an overlapping\ndefinition for resource identifiers and they are not compatible. The\n`m:uri_string` module implements\n[RFC 3986](https://www.ietf.org/rfc/rfc3986.txt) and the term URI will be used\nthroughout this document. A URI is an identifier, a string of characters that\nidentifies a particular resource.\n\nFor a more complete problem statement regarding the URIs check the\n[URL Problem Statement and Directions](https://tools.ietf.org/html/draft-ruby-url-problem-01).","title":"Basics - Uniform Resource Identifiers","ref":"uri_string_usage.html#basics"},{"type":"extras","doc":"Let's start with what it is not. It is not the text that you type in the address\nbar in your Web browser. Web browsers do all possible heuristics to convert the\ninput into a valid URI that could be sent over the network.\n\nA URI is an identifier consisting of a sequence of characters matching the\nsyntax rule named `URI` in [RFC 3986](https://www.ietf.org/rfc/rfc3986.txt).\n\nIt is crucial to clarify that a _character_ is a symbol that is displayed on a\nterminal or written to paper and should not be confused with its internal\nrepresentation.\n\nA URI more specifically, is a sequence of characters from a subset of the US\nASCII character set. The generic URI syntax consists of a hierarchical sequence\nof components referred to as the scheme, authority, path, query, and fragment.\nThere is a formal description for each of these components in\n[ABNF](https://www.ietf.org/rfc/rfc2234.txt) notation in\n[RFC 3986](https://www.ietf.org/rfc/rfc3986.txt):\n\n```text\n URI = scheme \":\" hier-part [ \"?\" query ] [ \"#\" fragment ]\n hier-part = \"//\" authority path-abempty\n / path-absolute\n / path-rootless\n / path-empty\n scheme = ALPHA *( ALPHA / DIGIT / \"+\" / \"-\" / \".\" )\n authority = [ userinfo \"@\" ] host [ \":\" port ]\n userinfo = *( unreserved / pct-encoded / sub-delims / \":\" )\n\n reserved = gen-delims / sub-delims\n gen-delims = \":\" / \"/\" / \"?\" / \"#\" / \"[\" / \"]\" / \"@\"\n sub-delims = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n\n unreserved = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n```","title":"What is a URI? - Uniform Resource Identifiers","ref":"uri_string_usage.html#what-is-a-uri"},{"type":"extras","doc":"As producing and consuming standard URIs can get quite complex, Erlang/OTP\nprovides a module, `m:uri_string`, to handle all the most difficult operations\nsuch as parsing, recomposing, normalizing and resolving URIs against a base URI.\n\nThe API functions in `m:uri_string` work on two basic data types\n[`uri_string()`](`t:uri_string:uri_string/0`) and\n[`uri_map()`](`t:uri_string:uri_map/0`).\n[`uri_string()`](`t:uri_string:uri_string/0`) represents a standard URI, while\n[`uri_map()`](`t:uri_string:uri_map/0`) is a wider datatype, that can represent\nURI components using [Unicode](unicode_usage.md#what-unicode-is) characters.\n[`uri_map()`](`t:uri_string:uri_map/0`) is a convenient choice for enabling\noperations such as producing standard compliant URIs out of components that have\nspecial or [Unicode](unicode_usage.md#what-unicode-is) characters. It is easier\nto explain this by an example.\n\nLet's say that we would like to create the following URI and send it over the\nnetwork: `http://cities/örebro?foo bar`. This is not a valid URI as it contains\ncharacters that are not allowed in a URI such as \"ö\" and the space. We can\nverify this by parsing the URI:\n\n```erlang\n 1> uri_string:parse(\"http://cities/örebro?foo bar\").\n {error,invalid_uri,\":\"}\n```\n\nThe URI parser tries all possible combinations to interpret the input and fails\nat the last attempt when it encounters the colon character `\":\"`. Note, that the\ninital fault occurs when the parser attempts to interpret the character `\"ö\"`\nand after a failure back-tracks to the point where it has another possible\nparsing alternative.\n\nThe proper way to solve this problem is to use `uri_string:recompose/1` with a\n[`uri_map()`](`t:uri_string:uri_map/0`) as input:\n\n```erlang\n 2> uri_string:recompose(#{scheme => \"http\", host => \"cities\", path => \"/örebro\",\n query => \"foo bar\"}).\n \"http://cities/%C3%B6rebro?foo%20bar\"\n```\n\nThe result is a valid URI where all the special characters are encoded as\ndefined by the standard. Applying `uri_string:parse/1` and\n`uri_string:percent_decode/1` on the URI returns the original input:\n\n```erlang\n 3> uri_string:percent_decode(uri_string:parse(\"http://cities/%C3%B6rebro?foo%20bar\")).\n #{host => \"cities\",path => \"/örebro\",query => \"foo bar\",\n scheme => \"http\"}\n```\n\nThis symmetric property is heavily used in our property test suite.","title":"The uri_string module - Uniform Resource Identifiers","ref":"uri_string_usage.html#the-uri_string-module"},{"type":"extras","doc":"As you have seen in the previous chapter, a standard URI can only contain a\nstrict subset of the US ASCII character set, moreover the allowed set of\ncharacters is not the same in the different URI components. Percent-encoding is\na mechanism to represent a data octet in a component when that octet's\ncorresponding character is outside of the allowed set or is being used as a\ndelimiter. This is what you see when `\"ö\"` is encoded as `%C3%B6` and `space` as\n`%20`. Most of the API functions are expecting UTF-8 encoding when handling\npercent-encoded triplets. The UTF-8 encoding of the\n[Unicode](unicode_usage.md#what-unicode-is) character `\"ö\"` is two octets:\n`OxC3 0xB6`. The character `space` is in the first 128 characters of\n[Unicode](unicode_usage.md#what-unicode-is) and it is encoded using a single\noctet `0x20`.\n\n> #### Note {: .info }\n>\n> [Unicode](unicode_usage.md#what-unicode-is) is backward compatible with ASCII,\n> the encoding of the first 128 characters is the same binary value as in ASCII.\n\n[](){: #percent_encoding } It is a major source of confusion exactly which\ncharacters will be percent-encoded. In order to make it easier to answer this\nquestion the library provides a utility function,\n[`uri_string:allowed_characters/0 `](`uri_string:allowed_characters/0`), that\nlists the allowed set of characters in each major URI component, and also in the\nmost important standard character sets.\n\n```erlang\n 1> uri_string:allowed_characters().\n [{scheme,\n \"+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\"},\n {userinfo,\n \"!$%&'()*+,-.0123456789:;=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~\"},\n {host,\n \"!$&'()*+,-.0123456789:;=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~\"},\n {ipv4,\".0123456789\"},\n {ipv6,\".0123456789:ABCDEFabcdef\"},\n {regname,\n \"!$%&'()*+,-.0123456789;=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~\"},\n {path,\n \"!$%&'()*+,-./0123456789:;=@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~\"},\n {query,\n \"!$%&'()*+,-./0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~\"},\n {fragment,\n \"!$%&'()*+,-./0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~\"},\n {reserved,\"!#$&'()*+,/:;=?@[]\"},\n {unreserved,\n \"-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~\"}]\n```\n\nIf a URI component has a character that is not allowed, it will be\npercent-encoded when the URI is produced:\n\n```erlang\n 2> uri_string:recompose(#{scheme => \"https\", host => \"local#host\", path => \"\"}).\n \"https://local%23host\"\n```\n\nConsuming a URI containing percent-encoded triplets can take many steps. The\nfollowing example shows how to handle an input URI that is not normalized and\ncontains multiple percent-encoded triplets. First, the input\n[`uri_string()`](`t:uri_string:uri_string/0`) is to be parsed into a\n[`uri_map()`](`t:uri_string:uri_map/0`). The parsing only splits the URI into\nits components without doing any decoding:\n\n```text\n 3> uri_string:parse(\"http://%6C%6Fcal%23host/%F6re%26bro%20\").\n #{host => \"%6C%6Fcal%23host\",path => \"/%F6re%26bro%20\",\n scheme => \"http\"}}\n```\n\nThe input is a valid URI but how can you decode those percent-encoded octets?\nYou can try to normalize the input with `uri_string:normalize/1`. The normalize\noperation decodes those percent-encoded triplets that correspond to a character\nin the unreserved set. Normalization is a safe, idempotent operation that\nconverts a URI into its canonical form:\n\n```erlang\n 4> uri_string:normalize(\"http://%6C%6Fcal%23host/%F6re%26bro%20\").\n \"http://local%23host/%F6re%26bro%20\"\n 5> uri_string:normalize(\"http://%6C%6Fcal%23host/%F6re%26bro%20\", [return_map]).\n #{host => \"local%23host\",path => \"/%F6re%26bro%20\",\n scheme => \"http\"}\n```\n\nThere are still a few percent-encoded triplets left in the output. At this\npoint, when the URI is already parsed, it is safe to apply application specific\ndecoding on the remaining character triplets. Erlang/OTP provides a function,\n`uri_string:percent_decode/1` for raw percent decoding that you can use on the\nhost and path components, or on the whole map:\n\n```erlang\n 6> uri_string:percent_decode(\"local%23host\").\n \"local#host\"\n 7> uri_string:percent_decode(\"/%F6re%26bro%20\").\n {error,invalid_utf8,<<\"/öre&bro \">>}\n 8> uri_string:percent_decode(#{host => \"local%23host\",path => \"/%F6re%26bro%20\",\n scheme => \"http\"}).\n {error,{invalid,{path,{invalid_utf8,<<\"/öre&bro \">>}}}}\n```\n\nThe `host` was successfully decoded but the path contains at least one character\nwith non-UTF-8 encoding. In order to be able to decode this, you have to make\nassumptions about the encoding used in these triplets. The most obvious choice\nis _latin-1_, so you can try `uri_string:transcode/2`, to transcode the path to\nUTF-8 and run the percent-decode operation on the transcoded string:\n\n```erlang\n 9> uri_string:transcode(\"/%F6re%26bro%20\", [{in_encoding, latin1}]).\n \"/%C3%B6re%26bro%20\"\n 10> uri_string:percent_decode(\"/%C3%B6re%26bro%20\").\n \"/öre&bro \"\n```\n\nIt is important to emphasize that it is not safe to apply\n`uri_string:percent_decode/1` directly on an input URI:\n\n```erlang\n 11> uri_string:percent_decode(\"http://%6C%6Fcal%23host/%C3%B6re%26bro%20\").\n \"http://local#host/öre&bro \"\n 12> uri_string:parse(\"http://local#host/öre&bro \").\n {error,invalid_uri,\":\"}\n```\n\n> #### Note {: .info }\n>\n> Percent-encoding is implemented in `uri_string:recompose/1` and it happens\n> when converting a [`uri_map()`](`t:uri_string:uri_map/0`) into a\n> [`uri_string()`](`t:uri_string:uri_string/0`). Applying any percent-encoding\n> directly on an input URI would not be safe just as in the case of\n> `uri_string:percent_decode/1`, the output could be an invalid URI. Quoting\n> functions allow users to perform raw percent encoding and decoding on\n> application data which cannot be handled automatically by\n> `uri_string:recompose/1`. For example in scenario when user would need to use\n> '/' or sub-delimeter as data rather than delimeter in a path component.","title":"Percent-encoding - Uniform Resource Identifiers","ref":"uri_string_usage.html#percent-encoding"},{"type":"extras","doc":"Normalization is the operation of converting the input URI into a _canonical_\nform and keeping the reference to the same underlying resource. The most common\napplication of normalization is determining whether two URIs are equivalent\nwithout accessing their referenced resources.\n\nNormalization has 6 distinct steps. First the input URI is parsed into an\nintermediate form that can handle [Unicode](unicode_usage.md#what-unicode-is)\ncharacters. This datatype is the [`uri_map()`](`t:uri_string:uri_map/0`), that\ncan hold the components of the URI in map elements of type\n`t:unicode:chardata/0`. After having the intermediate form, a sequence of\nnormalization algorithms are applied to the individual URI components:\n\n- **Case normalization** - Converts the `scheme` and `host` components to lower\n case as they are not case sensitive.\n\n- **Percent-encoding normalization** - Decodes percent-encoded triplets that\n correspond to characters in the unreserved set.\n\n- **Scheme-based normalization** - Applying rules for the schemes http, https,\n ftp, ssh, sftp and tftp.\n\n- **Path segment normalization** - Converts the path into a canonical form.\n\nAfter these steps, the intermediate data structure, an\n[`uri_map()`](`t:uri_string:uri_map/0`), is fully normalized. The last step is\napplying `uri_string:recompose/1` that converts the intermediate structure into\na valid canonical URI string.\n\nNotice the order, the\n[`uri_string:normalize(URIMap, [return_map])`](`uri_string:normalize/2`) that we\nused many times in this user guide is a shortcut in the normalization process\nreturning the intermediate datastructure, and allowing us to inspect and apply\nfurther decoding on the remaining percent-encoded triplets.\n\n```text\n 13> uri_string:normalize(\"hTTp://LocalHost:80/%c3%B6rebro/a/../b\").\n \"http://localhost/%C3%B6rebro/b\"\n 14> uri_string:normalize(\"hTTp://LocalHost:80/%c3%B6rebro/a/../b\", [return_map]).\n #{host => \"localhost\",path => \"/%C3%B6rebro/b\",\n scheme => \"http\"}\n```","title":"Normalization - Uniform Resource Identifiers","ref":"uri_string_usage.html#normalization"},{"type":"extras","doc":"The current URI implementation provides support for producing and consuming\nstandard URIs. The API is not meant to be directly exposed in a Web browser's\naddress bar where users can basically enter free text. Application designers\nshall implement proper heuristics to map the input into a parsable URI.","title":"Special considerations - Uniform Resource Identifiers","ref":"uri_string_usage.html#special-considerations"},{"type":"extras","doc":"\n# assert.hrl\n\nAssert macros.","title":"assert.hrl","ref":"assert_hrl.html"},{"type":"extras","doc":"The include file `assert.hrl` provides macros for inserting assertions in your\nprogram code.\n\nInclude the following directive in the module from which the function is called:\n\n```erlang\n-include_lib(\"stdlib/include/assert.hrl\").\n```\n\nWhen an assertion succeeds, the assert macro yields the atom `ok`. When an\nassertion fails, an exception of type `error` is generated. The associated error\nterm has the form `{Macro, Info}`. `Macro` is the macro name, for example,\n`assertEqual`. `Info` is a list of tagged values, such as\n`[{module, M}, {line, L}, ...]`, which gives more information about the location\nand cause of the exception. All entries in the `Info` list are optional; do not\nrely programmatically on any of them being present.\n\nEach assert macro has a corresponding version with an extra argument, for adding\ncomments to assertions. These can for example be printed as part of error\nreports, to clarify the meaning of the check that failed. For example,\n`?assertEqual(0, fib(0), \"Fibonacci is defined for zero\")`. The comment text can\nbe any character data (string, UTF8-binary, or deep list of such data), and will\nbe included in the error term as `{comment, Text}`.\n\nIf the macro `NOASSERT` is defined when `assert.hrl` is read by the compiler,\nthe macros are defined as equivalent to the atom `ok`. The test will not be\nperformed and there is no cost at runtime.\n\nFor example, using `erlc` to compile your modules, the following disables all\nassertions:\n\n```text\nerlc -DNOASSERT=true *.erl\n```\n\n(The value of `NOASSERT` does not matter, only the fact that it is defined.)\n\nA few other macros also have effect on the enabling or disabling of assertions:\n\n- If `NODEBUG` is defined, it implies `NOASSERT` (unless `DEBUG` is also\n defined, which overrides `NODEBUG`).\n- If `ASSERT` is defined, it overrides `NOASSERT`, that is, the assertions\n remain enabled.\n\nIf you prefer, you can thus use only `DEBUG`/`NODEBUG` as the main flags to\ncontrol the behavior of the assertions (which is useful if you have other\ncompiler conditionals or debugging macros controlled by those flags), or you can\nuse `ASSERT`/`NOASSERT` to control only the assert macros.","title":"Description - assert.hrl","ref":"assert_hrl.html#description"},{"type":"extras","doc":"- **`assert(BoolExpr)`**\n\n- **`assert(BoolExpr, Comment)`** - Tests that `BoolExpr` completes normally\n returning `true`.\n\n- **`assertNot(BoolExpr)`**\n\n- **`assertNot(BoolExpr, Comment)`** - Tests that `BoolExpr` completes normally\n returning `false`.\n\n- **`assertMatch(GuardedPattern, Expr)`**\n\n- **`assertMatch(GuardedPattern, Expr, Comment)`** - Tests that `Expr` completes\n normally yielding a value that matches `GuardedPattern`, for example:\n\n ```text\n ?assertMatch({bork, _}, f())\n ```\n\n Notice that a guard `when ...` can be included:\n\n ```erlang\n ?assertMatch({bork, X} when X > 0, f())\n ```\n\n- **`assertNotMatch(GuardedPattern, Expr)`**\n\n- **`assertNotMatch(GuardedPattern, Expr, Comment)`** - Tests that `Expr`\n completes normally yielding a value that does not match `GuardedPattern`.\n\n As in `assertMatch`, `GuardedPattern` can have a `when` part.\n\n- **`assertEqual(ExpectedValue, Expr)`**\n\n- **`assertEqual(ExpectedValue, Expr, Comment)`** - Tests that `Expr` completes\n normally yielding a value that is exactly equal to `ExpectedValue`.\n\n- **`assertNotEqual(ExpectedValue, Expr)`**\n\n- **`assertNotEqual(ExpectedValue, Expr, Comment)`** - Tests that `Expr`\n completes normally yielding a value that is not exactly equal to\n `ExpectedValue`.\n\n- **`assertException(Class, Term, Expr)`**\n\n- **`assertException(Class, Term, Expr, Comment)`** - Tests that `Expr`\n completes abnormally with an exception of type `Class` and with the associated\n `Term`. The assertion fails if `Expr` raises a different exception or if it\n completes normally returning any value.\n\n Notice that both `Class` and `Term` can be guarded patterns, as in\n `assertMatch`.\n\n- **`assertNotException(Class, Term, Expr)`**\n\n- **`assertNotException(Class, Term, Expr, Comment)`** - Tests that `Expr` does\n not evaluate abnormally with an exception of type `Class` and with the\n associated `Term`. The assertion succeeds if `Expr` raises a different\n exception or if it completes normally returning any value.\n\n As in `assertException`, both `Class` and `Term` can be guarded patterns.\n\n- **`assertError(Term, Expr)`**\n\n- **`assertError(Term, Expr, Comment)`** - Equivalent to\n `assertException(error, Term, Expr)`\n\n- **`assertExit(Term, Expr)`**\n\n- **`assertExit(Term, Expr, Comment)`** - Equivalent to\n `assertException(exit, Term, Expr)`\n\n- **`assertThrow(Term, Expr)`**\n\n- **`assertThrow(Term, Expr, Comment)`** - Equivalent to\n `assertException(throw, Term, Expr)`","title":"Macros - assert.hrl","ref":"assert_hrl.html#macros"},{"type":"extras","doc":"`m:compile`, [`erlc(3)`](`e:erts:erlc_cmd.md`)","title":"See Also - assert.hrl","ref":"assert_hrl.html#see-also"}],"content_type":"text/plain","producer":{"name":"ex_doc","version":[48,46,51,52,46,49]}} \ No newline at end of file diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/epp.html b/prs/9045/lib/stdlib-6.1.2/doc/html/epp.html index b0a17835f49c..51211134f44f 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/epp.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/epp.html @@ -146,7 +146,7 @@

    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)

    +modules. The format is as follows:

    {ErrorLine, Module, ErrorDescriptor}

    A string describing the error is obtained with the following call:

    Module:format_error(ErrorDescriptor)

    diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/erl_error.html b/prs/9045/lib/stdlib-6.1.2/doc/html/erl_error.html index 9881615fab28..ca7f1a98ed81 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/erl_error.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/erl_error.html @@ -323,7 +323,7 @@

    format_fun()

    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
    @@ -444,23 +444,23 @@

    format_error(Reason, StackTrace)

    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]).
    -
    -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).
    +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).
     ** exception error: my_error_module: badarg
          in function  my_error_module:atom_to_string/1
             called as my_error_module:atom_to_string(1)
    @@ -548,18 +548,18 @@ 

    format_exception(Class, Reason, StackTrace,

    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.

    diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/erl_eval.html b/prs/9045/lib/stdlib-6.1.2/doc/html/erl_eval.html index 87b34601e3bc..1bf7e13eed84 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/erl_eval.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/erl_eval.html @@ -147,13 +147,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.

    @@ -167,7 +167,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 on 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 diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/erl_lint.html b/prs/9045/lib/stdlib-6.1.2/doc/html/erl_lint.html index 196d043e30d8..342af5164539 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/erl_lint.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/erl_lint.html @@ -145,7 +145,7 @@

      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)

      +modules. The format is as follows:

      {ErrorLine, Module, ErrorDescriptor}

      A string describing the error is obtained with the following call:

      Module:format_error(ErrorDescriptor)

      diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/erl_parse.html b/prs/9045/lib/stdlib-6.1.2/doc/html/erl_parse.html index aacdf2fd78aa..f73525c3f97d 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/erl_parse.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/erl_parse.html @@ -144,7 +144,7 @@

      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)

      +The format is as follows:

      {ErrorLine, Module, ErrorDescriptor}

      A string describing the error is obtained with the following call:

      Module:format_error(ErrorDescriptor)

      diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/erl_scan.html b/prs/9045/lib/stdlib-6.1.2/doc/html/erl_scan.html index 48ba10c44138..af986690a932 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/erl_scan.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/erl_scan.html @@ -142,7 +142,7 @@

      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)

      +modules. The format is as follows:

      {ErrorLocation, Module, ErrorDescriptor}

      A string describing the error is obtained with the following call:

      Module:format_error(ErrorDescriptor)

      diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/erl_tar.html b/prs/9045/lib/stdlib-6.1.2/doc/html/erl_tar.html index 5492071d85a9..028a2072a48e 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/erl_tar.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/erl_tar.html @@ -1297,14 +1297,14 @@

      init/3

      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 diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/escript.html b/prs/9045/lib/stdlib-6.1.2/doc/html/escript.html index 5b2ae5241e66..50abbf06e148 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/escript.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/escript.html @@ -528,67 +528,67 @@

    create(File, Options)

    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]).
    +> 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,
    +> {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}]).
    +      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.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}], []}]).
    +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, [{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},
    +> 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"...>>}]}
    +
    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"...>>}]}
    @@ -621,16 +621,16 @@

    extract(File, Options)

    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}], []}]).
    +{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}]}
    +>
    {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}]}
    diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/ets.html b/prs/9045/lib/stdlib-6.1.2/doc/html/ets.html index 9ea8b4969a64..5a4d3e19ae20 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/ets.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/ets.html @@ -226,10 +226,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 @@ -242,11 +242,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"]]

    +2> ets:match(T,{[$5,$5,$5,$- |'$1'],'$2'}). +[["1234","John Smith"]]

    @@ -1942,19 +1942,19 @@

    fun2ms(LiteralFun)

    -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 @@ -2579,12 +2579,12 @@

    match(Table, Pattern)

    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 @@ -2836,10 +2836,10 @@

    match_spec_run(List, CompiledMatchSpec)

    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.

    @@ -3202,19 +3202,19 @@

    repair_continuation(Continuation, MatchSpec 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 @@ -3259,21 +3259,21 @@

    safe_fixtable(Table, Fix)

    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 @@ -3361,7 +3361,7 @@

    select(Table, MatchSpec)

    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 @@ -3522,16 +3522,16 @@

    select_replace(Table, MatchSpec)

    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),
    +New = update_object(Old),
    +Success = (1 =:= ets:select_replace(T, [{Old, [], [{const, New}]}])),
    @@ -3566,22 +3566,22 @@

    select_reverse(Continuation)

    ordered_set, the traversal of the table continues to objects with keys earlier in the Erlang term order. The returned list also contains objects with keys in reverse order. For all other table types, the behavior is exactly that of -select/1.

    Example:

    1> T = ets:new(x,[ordered_set]).
    -2> [ ets:insert(T,{N}) || N <- lists:seq(1,10) ].
    +select/1.

    Example:

    1> T = ets:new(x,[ordered_set]).
    +2> [ ets:insert(T,{N}) || N <- lists:seq(1,10) ].
     ...
    -3> {R0,C0} = ets:select_reverse(T,[{'_',[],['$_']}],4).
    +3> {R0,C0} = ets:select_reverse(T,[{'_',[],['$_']}],4).
     ...
     4> R0.
    -[{10},{9},{8},{7}]
    -5> {R1,C1} = ets:select_reverse(C0).
    +[{10},{9},{8},{7}]
    +5> {R1,C1} = ets:select_reverse(C0).
     ...
     6> R1.
    -[{6},{5},{4},{3}]
    -7> {R2,C2} = ets:select_reverse(C1).
    +[{6},{5},{4},{3}]
    +7> {R2,C2} = ets:select_reverse(C1).
     ...
     8> R2.
    -[{2},{1}]
    -9> '$end_of_table' = ets:select_reverse(C2).
    +[{2},{1}]
    +9> '$end_of_table' = ets:select_reverse(C2).
     ...
    @@ -3982,10 +3982,10 @@

    table(Table, Options)

    match specification that matches all objects.

  • {select, MatchSpec} - As for select, the table is traversed by calling select/3 and select/1. The difference is that the match specification is explicitly specified. This is how to state match specifications that cannot -easily be expressed within the syntax provided by QLC.

  • Examples:

    An explicit match specification is here used to traverse the table:

    9> true = ets:insert(Table = ets:new(t, []), [{1,a},{2,b},{3,c},{4,d}]),
    -MS = ets:fun2ms(fun({X,Y}) when (X > 1) or (X < 5) -> {Y} end),
    -QH1 = ets:table(Table, [{traverse, {select, MS}}]).

    An example with an implicit match specification:

    10> QH2 = qlc:q([{Y} || {X,Y} <- ets:table(Table), (X > 1) or (X < 5)]).

    The latter example is equivalent to the former, which can be verified using -function qlc:info/1:

    11> qlc:info(QH1) =:= qlc:info(QH2).
    +easily be expressed within the syntax provided by QLC.

    Examples:

    An explicit match specification is here used to traverse the table:

    9> true = ets:insert(Table = ets:new(t, []), [{1,a},{2,b},{3,c},{4,d}]),
    +MS = ets:fun2ms(fun({X,Y}) when (X > 1) or (X < 5) -> {Y} end),
    +QH1 = ets:table(Table, [{traverse, {select, MS}}]).

    An example with an implicit match specification:

    10> QH2 = qlc:q([{Y} || {X,Y} <- ets:table(Table), (X > 1) or (X < 5)]).

    The latter example is equivalent to the former, which can be verified using +function qlc:info/1:

    11> qlc:info(QH1) =:= qlc:info(QH2).
     true

    qlc:info/1 returns information about a query handle, and in this case identical information is returned for the two query handles.

    diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/file_sorter.html b/prs/9045/lib/stdlib-6.1.2/doc/html/file_sorter.html index 8a2d66717cc2..2fc9d769ba7d 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/file_sorter.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/file_sorter.html @@ -201,35 +201,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 diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/filelib.html b/prs/9045/lib/stdlib-6.1.2/doc/html/filelib.html index 7d5ff938ce71..275adf0e6201 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/filelib.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/filelib.html @@ -1036,15 +1036,15 @@

      safe_relative_path(Filename, Cwd)

      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
      diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/filename.html b/prs/9045/lib/stdlib-6.1.2/doc/html/filename.html index 6ca45e4f41b8..038d57eec041 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/filename.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/filename.html @@ -532,20 +532,20 @@

      absname(Filename)

      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:/"
      @@ -685,58 +685,58 @@

      basedir(Type, Application, Opts)

      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"]
      @@ -765,12 +765,12 @@

      basename(Filename)

      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("/"). +[]
      @@ -801,15 +801,15 @@

      basename(Filename, Ext)

      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"
      @@ -838,10 +838,10 @@

      dirname(Filename)

      -

      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"
      @@ -871,10 +871,10 @@

      extension(Filename)

      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"). +[]
      @@ -934,10 +934,10 @@

      join(Components)

      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/local/bin"
    -18> filename:join(["a/b///c/"]).
    -"a/b/c"
    6> filename:join(["B:a\\b///c/"]). % Windows
    +18> filename:join(["a/b///c/"]).
    +"a/b/c"
    6> filename:join(["B:a\\b///c/"]). % Windows
     "b:a/b/c"
    @@ -997,8 +997,8 @@

    nativename(Path)

    Converts Path to a form accepted by the command shell and native applications on the current platform. On Windows, forward slashes are converted to backward -slashes. On all platforms, the name is normalized as done by join/1.

    Examples:

    19> filename:nativename("/usr/local/bin/"). % Unix
    -"/usr/local/bin"
    7> filename:nativename("/usr/local/bin/"). % Windows
    +slashes. On all platforms, the name is normalized as done by join/1.

    Examples:

    19> filename:nativename("/usr/local/bin/"). % Unix
    +"/usr/local/bin"
    7> filename:nativename("/usr/local/bin/"). % Windows
     "\\usr\\local\\bin"
    @@ -1058,9 +1058,9 @@

    rootname(Filename)

    -

    Removes the filename extension.

    Examples:

    1> filename:rootname("/beam.src/kalle").
    +

    Removes the filename extension.

    Examples:

    1> filename:rootname("/beam.src/kalle").
     "/beam.src/kalle"
    -2> filename:rootname("/beam.src/foo.erl").
    +2> filename:rootname("/beam.src/foo.erl").
     "/beam.src/foo"
    @@ -1090,9 +1090,9 @@

    rootname(Filename, Ext)

    -

    Removes the filename extension Ext from Filename.

    Examples:

    1> filename:rootname("/beam.src/foo.erl", ".erl").
    +

    Removes the filename extension Ext from Filename.

    Examples:

    1> filename:rootname("/beam.src/foo.erl", ".erl").
     "/beam.src/foo"
    -2> filename:rootname("/beam.src/foo.beam", ".erl").
    +2> filename:rootname("/beam.src/foo.beam", ".erl").
     "/beam.src/foo.beam"
    @@ -1121,12 +1121,12 @@

    split(Filename)

    -

    Returns a list whose elements are the path components of Filename.

    Examples:

    24> filename:split("/usr/local/bin").
    -["/","usr","local","bin"]
    -25> filename:split("foo/bar").
    -["foo","bar"]
    -26> filename:split("a:\\msdev\\include").
    -["a:/","msdev","include"]
    +

    Returns a list whose elements are the path components of Filename.

    Examples:

    24> filename:split("/usr/local/bin").
    +["/","usr","local","bin"]
    +25> filename:split("foo/bar").
    +["foo","bar"]
    +26> filename:split("a:\\msdev\\include").
    +["a:/","msdev","include"]
    diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/gen_event.html b/prs/9045/lib/stdlib-6.1.2/doc/html/gen_event.html index c3412edd02cc..07fa95f3ffac 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/gen_event.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/gen_event.html @@ -1309,15 +1309,15 @@

    format_status(Status)

    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 diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/gen_fsm.html b/prs/9045/lib/stdlib-6.1.2/doc/html/gen_fsm.html index 3c0bb7d11ca0..0c5b5d6231c0 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/gen_fsm.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/gen_fsm.html @@ -141,163 +141,163 @@

    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}.
    +-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).
    +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.
     -endif.
     
    -terminate(_Reason, State, _Data) ->
    -    State =/= locked andalso do_lock(),
    +terminate(_Reason, State, _Data) ->
    +    State =/= locked andalso do_lock(),
         ok.
    -code_change(_Vsn, State, Data, _Extra) ->
    -    {ok, State, Data}.
    +code_change(_Vsn, State, Data, _Extra) ->
    +    {ok, State, Data}.
     
     %% Internal functions
    --ifdef(BEFORE_REWRITE).
    +-ifdef(BEFORE_REWRITE).
     -else.
    -handle_call(From, stop, Data) ->
    -     {stop_and_reply, normal,  {reply, From, ok}, Data}.
    +handle_call(From, stop, Data) ->
    +     {stop_and_reply, normal,  {reply, From, ok}, 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}.
     %% These are internal functions for handling all state events
     %% and not behaviour callbacks as in gen_fsm
     -endif.
     
    -analyze_lock(Digit, #{code := Code, remaining := Remaining} = Data) ->
    +analyze_lock(Digit, #{code := Code, remaining := Remaining} = Data) ->
          case Remaining of
    -         [Digit] ->
    -         do_unlock(),
    -         {open,  Data#{remaining := Code}};
    -         [Digit|Rest] -> % Incomplete
    -             {locked, Data#{remaining := Rest}};
    +         [Digit] ->
    +         do_unlock(),
    +         {open,  Data#{remaining := Code}};
    +         [Digit|Rest] -> % Incomplete
    +             {locked, Data#{remaining := Rest}};
              _Wrong ->
    -             {locked, Data#{remaining := Code}}
    +             {locked, Data#{remaining := Code}}
          end.
     
    -do_lock() ->
    -    io:format("Lock~n", []).
    -do_unlock() ->
    -    io:format("Unlock~n", []).

    +do_lock() -> + io:format("Lock~n", []). +do_unlock() -> + io:format("Unlock~n", []).

    diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/gen_server.html b/prs/9045/lib/stdlib-6.1.2/doc/html/gen_server.html index 306f1583f6ff..8e11deb3c517 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/gen_server.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/gen_server.html @@ -1285,15 +1285,15 @@

    format_status(Status)

    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, diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/gen_statem.html b/prs/9045/lib/stdlib-6.1.2/doc/html/gen_statem.html index c69d7b567a82..8e7682ab27c4 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/gen_statem.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/gen_statem.html @@ -182,7 +182,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 @@ -308,97 +308,97 @@

    Pushbutton Code

    -

    The following is the complete callback module file pushbutton.erl:

    -module(pushbutton).
    --behaviour(gen_statem).
    +

    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

    + {next_state,State,Data}.

    Note

    @@ -3183,15 +3183,15 @@

    format_status(Status)

    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}, @@ -3365,8 +3365,8 @@

    init(Args)

    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]).
    diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/io.html b/prs/9045/lib/stdlib-6.1.2/doc/html/io.html index 44a4d4f8bab4..216b213ef2e9 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/io.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/io.html @@ -154,7 +154,7 @@

    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)
    @@ -890,7 +890,7 @@

    expand_fun()

    format()

    - + View Source @@ -983,7 +983,7 @@

    option()

    parse_form_ret()

    - + View Source @@ -1019,7 +1019,7 @@

    parse_form_ret()

    parse_ret()

    - + View Source @@ -1195,12 +1195,12 @@

    standard_io()

    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 @@ -1318,7 +1318,7 @@

    columns(IoDevice)

    format(Format)

    - + View Source @@ -1346,7 +1346,7 @@

    format(Format)

    format(Format, Data)

    - + View Source @@ -1374,7 +1374,7 @@

    format(Format, Data)

    format(IoDevice, Format, Data)

    - + View Source @@ -1403,7 +1403,7 @@

    format(IoDevice, Format, Data)

    fread(Prompt, Format)

    - + View Source @@ -1435,7 +1435,7 @@

    fread(Prompt, Format)

    fread(IoDevice, Prompt, Format)

    - + View Source @@ -1475,33 +1475,33 @@

    fread(IoDevice, Prompt, Format)

    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 "]}
    @@ -1513,7 +1513,7 @@

    fread(IoDevice, Prompt, Format)

    fwrite(Format)

    - + View Source @@ -1541,7 +1541,7 @@

    fwrite(Format)

    fwrite(Format, Data)

    - + View Source @@ -1569,7 +1569,7 @@

    fwrite(Format, Data)

    fwrite(IoDevice, Format, Data)

    - + View Source @@ -1590,7 +1590,7 @@

    fwrite(IoDevice, Format, Data)

    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 @@ -1608,25 +1608,25 @@

    fwrite(IoDevice, Format, Data)

    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 @@ -1644,18 +1644,18 @@

      fwrite(IoDevice, Format, Data)

      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 @@ -1666,122 +1666,122 @@

      fwrite(IoDevice, Format, Data)

      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]).
      +Here T = [{attributes,[[{id,age,1.5},
      +                        {mode,explicit},
      +                        {typename,"INTEGER"}],
      +                       [{id,cho},
      +                        {mode,explicit},
      +                        {typename,'Cho'}]]},
      +          {typename,'Person'},
      +          {tag,{'PRIVATE',3}},
      +          {mode,implicit}]
       ok

      As from Erlang/OTP 21.0, a field width of value 0 can be used for specifying that a line is infinitely long, which means that no line breaks are inserted. -For example:

      5> io:fwrite("~0p~n", [lists:seq(1, 30)]).
      -[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30]
      +For example:

      5> io:fwrite("~0p~n", [lists:seq(1, 30)]).
      +[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30]
       ok

      When the modifier l is specified, no detection of printable character lists -takes place, for example:

      6> S = [{a,"a"}, {b, "b"}],
      -   io:fwrite("~15p~n", [S]).
      -[{a,"a"},
      - {b,"b"}]
      +takes place, for example:

      6> S = [{a,"a"}, {b, "b"}],
      +   io:fwrite("~15p~n", [S]).
      +[{a,"a"},
      + {b,"b"}]
       ok
      -7> io:fwrite("~15lp~n", [S]).
      -[{a,[97]},
      - {b,[98]}]
      +7> io:fwrite("~15lp~n", [S]).
      +[{a,[97]},
      + {b,[98]}]
       ok

      The Unicode translation modifier t specifies how to treat characters outside the Latin-1 range of codepoints, in atoms, strings, and binaries. For example, -printing an atom containing a character > 255:

      8> io:fwrite("~p~n",[list_to_atom([1024])]).
      +printing an atom containing a character > 255:

      8> io:fwrite("~p~n",[list_to_atom([1024])]).
       '\x{400}'
       ok
      -9> io:fwrite("~tp~n",[list_to_atom([1024])]).
      +9> io:fwrite("~tp~n",[list_to_atom([1024])]).
       'Ѐ'
       ok

      By default, Erlang only detects lists of characters in the Latin-1 range as strings, but the +pc unicode flag can be used to change this (see -printable_range/0 for details). For example:

      10> io:fwrite("~p~n",[[214]]).
      +printable_range/0 for details). For example:

      10> io:fwrite("~p~n",[[214]]).
       "Ö"
       ok
      -11> io:fwrite("~p~n",[[1024]]).
      -[1024]
      +11> io:fwrite("~p~n",[[1024]]).
      +[1024]
       ok
      -12> io:fwrite("~tp~n",[[1024]]).
      -[1024]
      -ok

      but if Erlang was started with +pc unicode:

      13> io:fwrite("~p~n",[[1024]]).
      -[1024]
      +12> io:fwrite("~tp~n",[[1024]]).
      +[1024]
      +ok

      but if Erlang was started with +pc unicode:

      13> io:fwrite("~p~n",[[1024]]).
      +[1024]
       ok
      -14> io:fwrite("~tp~n",[[1024]]).
      +14> io:fwrite("~tp~n",[[1024]]).
       "Ѐ"
       ok

      Similarly, binaries that look like UTF-8 encoded strings are output with the -binary string syntax if the t modifier is specified:

      15> io:fwrite("~p~n", [<<208,128>>]).
      +binary string syntax if the t modifier is specified:

      15> io:fwrite("~p~n", [<<208,128>>]).
       <<208,128>>
       ok
      -16> io:fwrite("~tp~n", [<<208,128>>]).
      +16> io:fwrite("~tp~n", [<<208,128>>]).
       <<"Ѐ"/utf8>>
       ok
      -17> io:fwrite("~tp~n", [<<128,128>>]).
      +17> io:fwrite("~tp~n", [<<128,128>>]).
       <<128,128>>
       ok
    • W - Writes data in the same way as ~w, but takes an extra argument that is the maximum depth to which terms are printed. Anything below this -depth is replaced with .... For example, using T above:

      8> io:fwrite("~W~n", [T,9]).
      -[{attributes,[[{id,age,1.5},{mode,explicit},{typename,...}],
      -[{id,cho},{mode,...},{...}]]},{typename,'Person'},
      -{tag,{'PRIVATE',3}},{mode,implicit}]
      +depth is replaced with .... For example, using T above:

      8> io:fwrite("~W~n", [T,9]).
      +[{attributes,[[{id,age,1.5},{mode,explicit},{typename,...}],
      +[{id,cho},{mode,...},{...}]]},{typename,'Person'},
      +{tag,{'PRIVATE',3}},{mode,implicit}]
       ok

      If the maximum depth is reached, it cannot be read in the resultant output. Also, the ,... form in a tuple denotes that there are more elements in the tuple but these are below the print depth.

    • P - Writes data in the same way as ~p, but takes an extra argument that is the maximum depth to which terms are printed. Anything below this -depth is replaced with ..., for example:

      9> io:fwrite("~62P~n", [T,9]).
      -[{attributes,[[{id,age,1.5},{mode,explicit},{typename,...}],
      -              [{id,cho},{mode,...},{...}]]},
      - {typename,'Person'},
      - {tag,{'PRIVATE',3}},
      - {mode,implicit}]
      +depth is replaced with ..., for example:

      9> io:fwrite("~62P~n", [T,9]).
      +[{attributes,[[{id,age,1.5},{mode,explicit},{typename,...}],
      +              [{id,cho},{mode,...},{...}]]},
      + {typename,'Person'},
      + {tag,{'PRIVATE',3}},
      + {mode,implicit}]
       ok
    • B - Writes an integer in base 2-36, the default base is 10. A leading -dash is printed for negative integers.

      The precision field selects base, for example:

      1> io:fwrite("~.16B~n", [31]).
      +dash is printed for negative integers.

      The precision field selects base, for example:

      1> io:fwrite("~.16B~n", [31]).
       1F
       ok
      -2> io:fwrite("~.2B~n", [-19]).
      +2> io:fwrite("~.2B~n", [-19]).
       -10011
       ok
      -3> io:fwrite("~.36B~n", [5*36+35]).
      +3> io:fwrite("~.36B~n", [5*36+35]).
       5Z
       ok
    • X - Like B, but takes an extra argument that is a prefix to insert -before the number, but after the leading dash, if any.

      The prefix can be a possibly deep list of characters or an atom. Example:

      1> io:fwrite("~X~n", [31,"10#"]).
      +before the number, but after the leading dash, if any.

      The prefix can be a possibly deep list of characters or an atom. Example:

      1> io:fwrite("~X~n", [31,"10#"]).
       10#31
       ok
      -2> io:fwrite("~.16X~n", [-31,"0x"]).
      +2> io:fwrite("~.16X~n", [-31,"0x"]).
       -0x1F
       ok
    • # - Like B, but prints the number with an Erlang style #-separated -base prefix. Example:

      1> io:fwrite("~.10#~n", [31]).
      +base prefix. Example:

      1> io:fwrite("~.10#~n", [31]).
       10#31
       ok
      -2> io:fwrite("~.16#~n", [-31]).
      +2> io:fwrite("~.16#~n", [-31]).
       -16#1F
      -ok
    • b - Like B, but prints lowercase letters.

    • x - Like X, but prints lowercase letters.

    • + - Like #, but prints lowercase letters.

    • n - Writes a new line.

    • i - Ignores the next term.

    The function returns:

    • ok - The formatting succeeded.

    If an error occurs, there is no output. Example:

    1> io:fwrite("~s ~w ~i ~w ~c ~n",['abc def', 'abc def', {foo, 1},{foo, 1}, 65]).
    -abc def 'abc def'  {foo,1} A
    +ok
  • b - Like B, but prints lowercase letters.

  • x - Like X, but prints lowercase letters.

  • + - Like #, but prints lowercase letters.

  • n - Writes a new line.

  • i - Ignores the next term.

  • The function returns:

    • ok - The formatting succeeded.

    If an error occurs, there is no output. Example:

    1> io:fwrite("~s ~w ~i ~w ~c ~n",['abc def', 'abc def', {foo, 1},{foo, 1}, 65]).
    +abc def 'abc def'  {foo,1} A
     ok
    -2> io:fwrite("~s", [65]).
    +2> io:fwrite("~s", [65]).
     ** exception error: bad argument
          in function  io:format/3
             called as io:format(<0.53.0>,"~s","A")

    In this example, an attempt was made to output the single character 65 with the @@ -1978,20 +1978,20 @@

    getopts(IoDevice)

    -

    Requests all available options and their current values for a IoDevice.

    For example:

    1> {ok,F} = file:open("/dev/null",[read]).
    -{ok,<0.42.0>}
    -2> io:getopts(F).
    -[{binary,false},{encoding,latin1}]

    Here the file I/O server returns all available options for a file, which are the +

    Requests all available options and their current values for a IoDevice.

    For example:

    1> {ok,F} = file:open("/dev/null",[read]).
    +{ok,<0.42.0>}
    +2> io:getopts(F).
    +[{binary,false},{encoding,latin1}]

    Here the file I/O server returns all available options for a file, which are the expected ones, encoding and binary. However, the standard shell has some -more options:

    3> io:getopts().
    -[{expand_fun,#Fun<group.0.120017273>},
    - {echo,true},
    - {binary,false},
    - {encoding,unicode},
    - {terminal,true},
    - {stdout,true},
    - {stderr,true},
    - {stdin,true}]

    This example is, as can be seen, run in an environment where the terminal +more options:

    3> io:getopts().
    +[{expand_fun,#Fun<group.0.120017273>},
    + {echo,true},
    + {binary,false},
    + {encoding,unicode},
    + {terminal,true},
    + {stdout,true},
    + {stderr,true},
    + {stdin,true}]

    This example is, as can be seen, run in an environment where the terminal supports Unicode input and output.

    The stdin, stdout and stderr options are read only and indicates whether the stream is a terminal or not. When it is a terminal, most systems that Erlang runs on allows the use of ANSI escape codes @@ -2063,7 +2063,7 @@

    nl(IoDevice)

    parse_erl_exprs(Prompt)

    - + View Source @@ -2091,7 +2091,7 @@

    parse_erl_exprs(Prompt)

    parse_erl_exprs(IoDevice, Prompt)

    - + View Source @@ -2120,7 +2120,7 @@

    parse_erl_exprs(IoDevice, Prompt)

    parse_erl_exprs(IoDevice, Prompt, StartLocation)

    - + View Source @@ -2153,7 +2153,7 @@

    parse_erl_exprs(IoDevice, Prompt, StartLoca

    parse_erl_exprs(IoDevice, Prompt, StartLocation, Options)

    - + View Source @@ -2182,12 +2182,12 @@

    parse_erl_exprs(IoDevice, Prompt, StartLoca and parsed as if it was a sequence of Erlang expressions until a final dot (.) is reached.

    The function returns:

    • {ok, ExprList, EndLocation} - The parsing was successful.

    • {eof, EndLocation} - End of file was encountered by the tokenizer.

    • eof - End of file was encountered by the I/O server.

    • {error, ErrorInfo, ErrorLocation} - An error occurred while tokenizing or parsing.

    • {error, ErrorDescription} - Other (rare) error condition, such as -{error, estale} if reading from an NFS file system.

    Example:

    25> io:parse_erl_exprs('enter>').
    -enter>abc(), "hey".
    -{ok, [{call,1,{atom,1,abc},[]},{string,1,"hey"}],2}
    -26> io:parse_erl_exprs('enter>').
    -enter>abc("hey".
    -{error,{1,erl_parse,["syntax error before: ",["'.'"]]},2}
    +{error, estale} if reading from an NFS file system.

    Example:

    25> io:parse_erl_exprs('enter>').
    +enter>abc(), "hey".
    +{ok, [{call,1,{atom,1,abc},[]},{string,1,"hey"}],2}
    +26> io:parse_erl_exprs('enter>').
    +enter>abc("hey".
    +{error,{1,erl_parse,["syntax error before: ",["'.'"]]},2}

    @@ -2199,7 +2199,7 @@

    parse_erl_exprs(IoDevice, Prompt, StartLoca

    parse_erl_form(Prompt)

    - + View Source @@ -2227,7 +2227,7 @@

    parse_erl_form(Prompt)

    parse_erl_form(IoDevice, Prompt)

    - + View Source @@ -2256,7 +2256,7 @@

    parse_erl_form(IoDevice, Prompt)

    parse_erl_form(IoDevice, Prompt, StartLocation)

    - + View Source @@ -2289,7 +2289,7 @@

    parse_erl_form(IoDevice, Prompt, StartLocat

    parse_erl_form(IoDevice, Prompt, StartLocation, Options)

    - + View Source @@ -2427,7 +2427,7 @@

    put_chars(IoDevice, CharData)

    read(Prompt)

    - + View Source @@ -2459,7 +2459,7 @@

    read(Prompt)

    read(IoDevice, Prompt)

    - + View Source @@ -2494,7 +2494,7 @@

    read(IoDevice, Prompt)

    read(IoDevice, Prompt, StartLocation)

    - + View Source @@ -2532,7 +2532,7 @@

    read(IoDevice, Prompt, StartLocation)

    read(IoDevice, Prompt, StartLocation, Options)

    - + View Source @@ -2632,7 +2632,7 @@

    rows(IoDevice)

    scan_erl_exprs(Prompt)

    - + View Source @@ -2661,7 +2661,7 @@

    scan_erl_exprs(Prompt)

    scan_erl_exprs(Device, Prompt)

    - + View Source @@ -2693,7 +2693,7 @@

    scan_erl_exprs(Device, Prompt)

    scan_erl_exprs(Device, Prompt, StartLocation)

    - + View Source @@ -2726,7 +2726,7 @@

    scan_erl_exprs(Device, Prompt, StartLocatio

    scan_erl_exprs(Device, Prompt, StartLocation, Options)

    - + View Source @@ -2754,12 +2754,12 @@

    scan_erl_exprs(Device, Prompt, StartLocatio argument Options of function erl_scan:tokens/4. The data is tokenized as if it were a sequence of Erlang expressions until a final dot (.) is reached. This token is also returned.

    The function returns:

    • {ok, Tokens, EndLocation} - The tokenization succeeded.

    • {eof, EndLocation} - End of file was encountered by the tokenizer.

    • eof - End of file was encountered by the I/O server.

    • {error, ErrorInfo, ErrorLocation} - An error occurred while tokenizing.

    • {error, ErrorDescription} - Other (rare) error condition, such as -{error, estale} if reading from an NFS file system.

    Example:

    23> io:scan_erl_exprs('enter>').
    -enter>abc(), "hey".
    -{ok,[{atom,1,abc},{'(',1},{')',1},{',',1},{string,1,"hey"},{dot,1}],2}
    -24> io:scan_erl_exprs('enter>').
    +{error, estale} if reading from an NFS file system.

    Example:

    23> io:scan_erl_exprs('enter>').
    +enter>abc(), "hey".
    +{ok,[{atom,1,abc},{'(',1},{')',1},{',',1},{string,1,"hey"},{dot,1}],2}
    +24> io:scan_erl_exprs('enter>').
     enter>1.0er.
    -{error,{1,erl_scan,{illegal,float}},2}
    +
    {error,{1,erl_scan,{illegal,float}},2}

    @@ -2771,7 +2771,7 @@

    scan_erl_exprs(Device, Prompt, StartLocatio

    scan_erl_form(Prompt)

    - + View Source @@ -2800,7 +2800,7 @@

    scan_erl_form(Prompt)

    scan_erl_form(IoDevice, Prompt)

    - + View Source @@ -2832,7 +2832,7 @@

    scan_erl_form(IoDevice, Prompt)

    scan_erl_form(IoDevice, Prompt, StartLocation)

    - + View Source @@ -2865,7 +2865,7 @@

    scan_erl_form(IoDevice, Prompt, StartLocati

    scan_erl_form(IoDevice, Prompt, StartLocation, Options)

    - + View Source @@ -2933,7 +2933,7 @@

    setopts(Opts)

    setopts(IoDevice, Opts)

    - + View Source @@ -2974,9 +2974,25 @@

    setopts(IoDevice, Opts)

    current input line. The list of possible expansions can be formatted in different ways to make more advanced expansion suggestions more readable to the user, see edlin_expand:expand/2 for documentation of that.

    Trivial example (beep on anything except empty line, which is expanded to -"quit"):

    fun("") -> {yes, "quit", []};
    -   (_) -> {no, "", ["quit"]} end

    This option is only supported by the standard shell (group.erl).

  • {line_history, true | false} - Specifies if get_line and get_until -I/O requests should be saved in the shell history buffer.

    This option is only supported by the standard shell (group.erl).

  • {encoding, latin1 | unicode} - Specifies how characters are input or +"quit"):

    fun("") -> {yes, "quit", []};
    +   (_) -> {no, "", ["quit"]} end

    This option is only supported by the standard shell (group.erl).

  • {line_history, true | false} - Specifies if get_line and get_until +I/O requests should be saved in the shell history buffer.

    This option is only supported by the standard shell (group.erl).

  • {log, none | output | input | all} - Tells the I/O server that it should log +I/O requests. Requests will be logged at info level to the +[otp, kernel, io, input | output | ctrl] domain with the following report:

    #{ request := IoRequest, server := pid(), server_name => term() }.

    It is important to note that extra care should be taken so that these log reports are not +logged to standard_io/0 as that may cause the system to enter an infinite loop.

    Example:

    1> logger:set_primary_config(level, info).
    +ok
    +2> logger:add_handler(stdout, logger_std_h, #{ config => #{ file => "stdout.log" }}).
    +ok
    +3> io:setopts(user, [{log, output}]).
    +ok
    +4> io:format(user, "Hello~n", []).
    +Hello
    +ok
    +5> file:read_file("stdout.log").
    +{ok,<<"2024-11-14T09:53:49.275085+01:00 info: <0.89.0> wrote to user, Hello\n">>}

    Not all I/O servers support this option. Use io:getopts/1 to check if it is available.

    Note

    The I/O servers in Erlang/OTP will set the logger domain +to [otp, kernel, io, input | output]. The default logger handler will not print +this domain, so you need to enable it. This can be done by adding a new filter like this:

    logger:add_handler_filter(default, io_domain,
    +   {fun logger_filters:domain/2, {log,sub,[otp,kernel,io]}}).
  • {encoding, latin1 | unicode} - Specifies how characters are input or output from or to the I/O device, implying that, for example, a terminal is set to handle Unicode input and output or a file is set to handle UTF-8 data encoding.

    The option does not affect how data is returned from the I/O functions or @@ -3016,7 +3032,7 @@

    setopts(IoDevice, Opts)

    write(Term)

    - + View Source @@ -3044,7 +3060,7 @@

    write(Term)

    write(IoDevice, Term)

    - + View Source diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/io_lib.html b/prs/9045/lib/stdlib-6.1.2/doc/html/io_lib.html index c7d669dce89c..962d937bedfb 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/io_lib.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/io_lib.html @@ -1038,8 +1038,8 @@

    fread(Format, String)

    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],[]}
    @@ -1544,11 +1544,11 @@

    write(Term, DepthOrOptions)

    "...".

    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|...],...}"
    diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/io_protocol.html b/prs/9045/lib/stdlib-6.1.2/doc/html/io_protocol.html index fdcb52fe6d67..88ba0f3d5a0f 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/io_protocol.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/io_protocol.html @@ -152,8 +152,8 @@

    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 @@ -170,8 +170,8 @@

      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 +

        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 @@ -190,14 +190,14 @@

          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 +{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 +

      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 @@ -213,8 +213,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 @@ -224,38 +224,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.

    @@ -281,22 +281,22 @@

    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.

    @@ -304,22 +304,22 @@

    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}

      +{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 +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.

      @@ -329,7 +329,7 @@

      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.

      @@ -341,128 +341,128 @@

      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),
      +		    ?MODULE:loop(NewState);
      +		{stop, Reply, _NewState} ->
      +		    reply(From, ReplyAs, Reply),
      +		    exit(Reply)
       	    end;
       	%% Private message
      -	{From, rewind} ->
      -	    From ! {self(), ok},
      -	    ?MODULE:loop(State#state{position = 0});
      +	{From, rewind} ->
      +	    From ! {self(), ok},
      +	    ?MODULE:loop(State#state{position = 0});
       	_Unknown ->
      -	    ?MODULE:loop(State)
      +	    ?MODULE:loop(State)
           end.

      The main loop receives messages from the client (which can use the the io module to send requests). For each request, the function request/2 is called and a reply is eventually sent using function reply/3.

      The "private" message {From, rewind} results in the current position in the pseudo-file to be reset to 0 (the beginning of the "file"). This is a typical example of I/O device-specific messages not being part of the I/O protocol. It is usually a bad idea to embed such private messages in io_request tuples, as -that can confuse the reader.

      First, we examine the reply function:

      reply(From, ReplyAs, Reply) ->
      -    From ! {io_reply, ReplyAs, Reply}.

      It sends the io_reply tuple back to the client, providing element ReplyAs +that can confuse the reader.

      First, we examine the reply function:

      reply(From, ReplyAs, Reply) ->
      +    From ! {io_reply, ReplyAs, Reply}.

      It sends the io_reply tuple back to the client, providing element ReplyAs received in the request along with the result of the request, as described -earlier.

      We need to handle some requests. First the requests for writing characters:

      request({put_chars, Encoding, Chars}, State) ->
      -    put_chars(unicode:characters_to_list(Chars,Encoding),State);
      -request({put_chars, Encoding, Module, Function, Args}, State) ->
      +earlier.

      We need to handle some requests. First the requests for writing characters:

      request({put_chars, Encoding, Chars}, State) ->
      +    put_chars(unicode:characters_to_list(Chars,Encoding),State);
      +request({put_chars, Encoding, Module, Function, Args}, State) ->
           try
      -	request({put_chars, Encoding, apply(Module, Function, Args)}, State)
      +	request({put_chars, Encoding, apply(Module, Function, Args)}, State)
           catch
       	_:_ ->
      -	    {error, {error,Function}, State}
      +	    {error, {error,Function}, State}
           end;

      The Encoding says how the characters in the request are represented. We want to store the characters as lists in the ETS table, so we convert them to lists using function unicode:characters_to_list/2. The conversion function conveniently accepts the encoding types unicode and latin1, so we can use Encoding directly.

      When Module, Function, and Arguments are provided, we apply it and do the -same with the result as if the data was provided directly.

      We handle the requests for retrieving data:

      request({get_until, Encoding, _Prompt, M, F, As}, State) ->
      -    get_until(Encoding, M, F, As, State);
      -request({get_chars, Encoding, _Prompt, N}, State) ->
      +same with the result as if the data was provided directly.

      We handle the requests for retrieving data:

      request({get_until, Encoding, _Prompt, M, F, As}, State) ->
      +    get_until(Encoding, M, F, As, State);
      +request({get_chars, Encoding, _Prompt, N}, State) ->
           %% To simplify the code, get_chars is implemented using get_until
      -    get_until(Encoding, ?MODULE, until_enough, [N], State);
      -request({get_line, Encoding, _Prompt}, State) ->
      +    get_until(Encoding, ?MODULE, until_enough, [N], State);
      +request({get_line, Encoding, _Prompt}, State) ->
           %% To simplify the code, get_line is implemented using get_until
      -    get_until(Encoding, ?MODULE, until_newline, [$\n], State);

      Here we have cheated a little by more or less only implementing get_until and + get_until(Encoding, ?MODULE, until_newline, [$\n], State);

      Here we have cheated a little by more or less only implementing get_until and using internal helpers to implement get_chars and get_line. In production code, this can be inefficient, but that depends on the frequency of the different requests. Before we start implementing functions put_chars/2 and -get_until/5, we examine the few remaining requests:

      request({get_geometry,_}, State) ->
      -    {error, {error,enotsup}, State};
      -request({setopts, Opts}, State) ->
      -    setopts(Opts, State);
      -request(getopts, State) ->
      -    getopts(State);
      -request({requests, Reqs}, State) ->
      -     multi_request(Reqs, {ok, ok, State});

      Request get_geometry has no meaning for this I/O server, so the reply is +get_until/5, we examine the few remaining requests:

      request({get_geometry,_}, State) ->
      +    {error, {error,enotsup}, State};
      +request({setopts, Opts}, State) ->
      +    setopts(Opts, State);
      +request(getopts, State) ->
      +    getopts(State);
      +request({requests, Reqs}, State) ->
      +     multi_request(Reqs, {ok, ok, State});

      Request get_geometry has no meaning for this I/O server, so the reply is {error, enotsup}. The only option we handle is binary/list, which is done in separate functions.

      The multi-request tag (requests) is handled in a separate loop function -applying the requests in the list one after another, returning the last result.

      {error, request} must be returned if the request is not recognized:

      request(_Other, State) ->
      -    {error, {error, request}, State}.

      Next we handle the different requests, first the fairly generic multi-request -type:

      multi_request([R|Rs], {ok, _Res, State}) ->
      -    multi_request(Rs, request(R, State));
      -multi_request([_|_], Error) ->
      +applying the requests in the list one after another, returning the last result.

      {error, request} must be returned if the request is not recognized:

      request(_Other, State) ->
      +    {error, {error, request}, State}.

      Next we handle the different requests, first the fairly generic multi-request +type:

      multi_request([R|Rs], {ok, _Res, State}) ->
      +    multi_request(Rs, request(R, State));
      +multi_request([_|_], Error) ->
           Error;
      -multi_request([], Result) ->
      +multi_request([], Result) ->
           Result.

      We loop through the requests one at the time, stopping when we either encounter an error or the list is exhausted. The last return value is sent back to the client (it is first returned to the main loop and then sent back by function io_reply).

      Requests getopts and setopts are also simple to handle. We only change or -read the state record:

      setopts(Opts0,State) ->
      -    Opts = proplists:unfold(
      -	     proplists:substitute_negations(
      -	       [{list,binary}],
      -	       Opts0)),
      -    case check_valid_opts(Opts) of
      +read the state record:

      setopts(Opts0,State) ->
      +    Opts = proplists:unfold(
      +	     proplists:substitute_negations(
      +	       [{list,binary}],
      +	       Opts0)),
      +    case check_valid_opts(Opts) of
       	true ->
      -	        case proplists:get_value(binary, Opts) of
      +	        case proplists:get_value(binary, Opts) of
       		    true ->
      -			{ok,ok,State#state{mode=binary}};
      +			{ok,ok,State#state{mode=binary}};
       		    false ->
      -			{ok,ok,State#state{mode=binary}};
      +			{ok,ok,State#state{mode=binary}};
       		    _ ->
      -			{ok,ok,State}
      +			{ok,ok,State}
       		end;
       	false ->
      -	    {error,{error,enotsup},State}
      +	    {error,{error,enotsup},State}
           end.
      -check_valid_opts([]) ->
      +check_valid_opts([]) ->
           true;
      -check_valid_opts([{binary,Bool}|T]) when is_boolean(Bool) ->
      -    check_valid_opts(T);
      -check_valid_opts(_) ->
      +check_valid_opts([{binary,Bool}|T]) when is_boolean(Bool) ->
      +    check_valid_opts(T);
      +check_valid_opts(_) ->
           false.
       
      -getopts(#state{mode=M} = S) ->
      -    {ok,[{binary, case M of
      +getopts(#state{mode=M} = S) ->
      +    {ok,[{binary, case M of
       		      binary ->
       			  true;
       		      _ ->
       			  false
      -		  end}],S}.

      As a convention, all I/O servers handle both {setopts, [binary]}, + end}],S}.

      As a convention, all I/O servers handle both {setopts, [binary]}, {setopts, [list]}, and {setopts,[{binary, boolean()}]}, hence the trick with proplists:substitute_negations/2 and proplists:unfold/1. If invalid options are sent to us, we send {error, enotsup} back to the client.

      Request getopts is to return a list of {Option, Value} tuples. This has the @@ -470,50 +470,50 @@

      of this I/O server. We have only one option, and hence return that.

      So far this I/O server is fairly generic (except for request rewind handled in the main loop and the creation of an ETS table). Most I/O servers contain code similar to this one.

      To make the example runnable, we start implementing the reading and writing of -the data to/from the ETS table. First function put_chars/3:

      put_chars(Chars, #state{table = T, position = P} = State) ->
      +the data to/from the ETS table. First function put_chars/3:

      put_chars(Chars, #state{table = T, position = P} = State) ->
           R = P div ?CHARS_PER_REC,
           C = P rem ?CHARS_PER_REC,
      -    [ apply_update(T,U) || U <- split_data(Chars, R, C) ],
      -    {ok, ok, State#state{position = (P + length(Chars))}}.

      We already have the data as (Unicode) lists and therefore only split the list in + [ apply_update(T,U) || U <- split_data(Chars, R, C) ], + {ok, ok, State#state{position = (P + length(Chars))}}.

      We already have the data as (Unicode) lists and therefore only split the list in runs of a predefined size and put each run in the table at the current position (and forward). Functions split_data/3 and apply_update/2 are implemented below.

      Now we want to read data from the table. Function get_until/5 reads data and applies the function until it says that it is done. The result is sent back to -the client:

      get_until(Encoding, Mod, Func, As,
      -	  #state{position = P, mode = M, table = T} = State) ->
      -    case get_loop(Mod,Func,As,T,P,[]) of
      -	{done,Data,_,NewP} when is_binary(Data); is_list(Data) ->
      +the client:

      get_until(Encoding, Mod, Func, As,
      +	  #state{position = P, mode = M, table = T} = State) ->
      +    case get_loop(Mod,Func,As,T,P,[]) of
      +	{done,Data,_,NewP} when is_binary(Data); is_list(Data) ->
       	    if
       		M =:= binary ->
      -		    {ok,
      -		     unicode:characters_to_binary(Data, unicode, Encoding),
      -		     State#state{position = NewP}};
      +		    {ok,
      +		     unicode:characters_to_binary(Data, unicode, Encoding),
      +		     State#state{position = NewP}};
       		true ->
      -		    case check(Encoding,
      -		               unicode:characters_to_list(Data, unicode))
      +		    case check(Encoding,
      +		               unicode:characters_to_list(Data, unicode))
                           of
      -			{error, _} = E ->
      -			    {error, E, State};
      +			{error, _} = E ->
      +			    {error, E, State};
       			List ->
      -			    {ok, List,
      -			     State#state{position = NewP}}
      +			    {ok, List,
      +			     State#state{position = NewP}}
       		    end
       	    end;
      -	{done,Data,_,NewP} ->
      -	    {ok, Data, State#state{position = NewP}};
      +	{done,Data,_,NewP} ->
      +	    {ok, Data, State#state{position = NewP}};
       	Error ->
      -	    {error, Error, State}
      +	    {error, Error, State}
           end.
       
      -get_loop(M,F,A,T,P,C) ->
      -    {NewP,L} = get(P,T),
      -    case catch apply(M,F,[C,L|A]) of
      -	{done, List, Rest} ->
      -	    {done, List, [], NewP - length(Rest)};
      -	{more, NewC} ->
      -	    get_loop(M,F,A,T,NewP,NewC);
      +get_loop(M,F,A,T,P,C) ->
      +    {NewP,L} = get(P,T),
      +    case catch apply(M,F,[C,L|A]) of
      +	{done, List, Rest} ->
      +	    {done, List, [], NewP - length(Rest)};
      +	{more, NewC} ->
      +	    get_loop(M,F,A,T,NewP,NewC);
       	_ ->
      -	    {error,F}
      +	    {error,F}
           end.

      Here we also handle the mode (binary or list) that can be set by request setopts. By default, all OTP I/O servers send data back to the client as lists, but switching mode to binary can increase efficiency if the I/O server @@ -530,80 +530,80 @@

      is only to get characters in the range 0..255. Function check/2 takes care of not returning arbitrary Unicode code points in lists if the encoding was specified as latin1. If the function does not return a list, the check cannot -be performed and the result is that of the supplied function untouched.

      To manipulate the table we implement the following utility functions:

      check(unicode, List) ->
      +be performed and the result is that of the supplied function untouched.

      To manipulate the table we implement the following utility functions:

      check(unicode, List) ->
           List;
      -check(latin1, List) ->
      +check(latin1, List) ->
           try
      -	[ throw(not_unicode) || X <- List,
      -				X > 255 ],
      +	[ throw(not_unicode) || X <- List,
      +				X > 255 ],
       	List
           catch
       	throw:_ ->
      -	    {error,{cannot_convert, unicode, latin1}}
      +	    {error,{cannot_convert, unicode, latin1}}
           end.

      The function check provides an error tuple if Unicode code points > 255 are to be returned if the client requested latin1.

      The two functions until_newline/3 and until_enough/3 are helpers used together with function get_until/5 to implement get_chars and get_line -(inefficiently):

      until_newline([],eof,_MyStopCharacter) ->
      -    {done,eof,[]};
      -until_newline(ThisFar,eof,_MyStopCharacter) ->
      -    {done,ThisFar,[]};
      -until_newline(ThisFar,CharList,MyStopCharacter) ->
      +(inefficiently):

      until_newline([],eof,_MyStopCharacter) ->
      +    {done,eof,[]};
      +until_newline(ThisFar,eof,_MyStopCharacter) ->
      +    {done,ThisFar,[]};
      +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.
       
      -until_enough([],eof,_N) ->
      -    {done,eof,[]};
      -until_enough(ThisFar,eof,_N) ->
      -    {done,ThisFar,[]};
      -until_enough(ThisFar,CharList,N)
      -  when length(ThisFar) + length(CharList) >= N ->
      -    {Res,Rest} = my_split(N,ThisFar ++ CharList, []),
      -    {done,Res,Rest};
      -until_enough(ThisFar,CharList,_N) ->
      -    {more,ThisFar++CharList}.

      As can be seen, the functions above are just the type of functions that are to +until_enough([],eof,_N) -> + {done,eof,[]}; +until_enough(ThisFar,eof,_N) -> + {done,ThisFar,[]}; +until_enough(ThisFar,CharList,N) + when length(ThisFar) + length(CharList) >= N -> + {Res,Rest} = my_split(N,ThisFar ++ CharList, []), + {done,Res,Rest}; +until_enough(ThisFar,CharList,_N) -> + {more,ThisFar++CharList}.

      As can be seen, the functions above are just the type of functions that are to be provided in get_until requests.

      To complete the I/O server, we only need to read and write the table in an -appropriate way:

      get(P,Tab) ->
      +appropriate way:

      get(P,Tab) ->
           R = P div ?CHARS_PER_REC,
           C = P rem ?CHARS_PER_REC,
      -    case ets:lookup(Tab,R) of
      -	[] ->
      -	    {P,eof};
      -	[{R,List}] ->
      -	    case my_split(C,List,[]) of
      -		{_,[]} ->
      -		    {P+length(List),eof};
      -		{_,Data} ->
      -		    {P+length(Data),Data}
      +    case ets:lookup(Tab,R) of
      +	[] ->
      +	    {P,eof};
      +	[{R,List}] ->
      +	    case my_split(C,List,[]) of
      +		{_,[]} ->
      +		    {P+length(List),eof};
      +		{_,Data} ->
      +		    {P+length(Data),Data}
       	    end
           end.
       
      -my_split(0,Left,Acc) ->
      -    {lists:reverse(Acc),Left};
      -my_split(_,[],Acc) ->
      -    {lists:reverse(Acc),[]};
      -my_split(N,[H|T],Acc) ->
      -    my_split(N-1,T,[H|Acc]).
      -
      -split_data([],_,_) ->
      -    [];
      -split_data(Chars, Row, Col) ->
      -    {This,Left} = my_split(?CHARS_PER_REC - Col, Chars, []),
      -    [ {Row, Col, This} | split_data(Left, Row + 1, 0) ].
      -
      -apply_update(Table, {Row, Col, List}) ->
      -    case ets:lookup(Table,Row) of
      -	[] ->
      -	    ets:insert(Table,{Row, lists:duplicate(Col,0) ++ List});
      -	[{Row, OldData}] ->
      -	    {Part1,_} = my_split(Col,OldData,[]),
      -	    {_,Part2} = my_split(Col+length(List),OldData,[]),
      -	    ets:insert(Table,{Row, Part1 ++ List ++ Part2})
      +my_split(0,Left,Acc) ->
      +    {lists:reverse(Acc),Left};
      +my_split(_,[],Acc) ->
      +    {lists:reverse(Acc),[]};
      +my_split(N,[H|T],Acc) ->
      +    my_split(N-1,T,[H|Acc]).
      +
      +split_data([],_,_) ->
      +    [];
      +split_data(Chars, Row, Col) ->
      +    {This,Left} = my_split(?CHARS_PER_REC - Col, Chars, []),
      +    [ {Row, Col, This} | split_data(Left, Row + 1, 0) ].
      +
      +apply_update(Table, {Row, Col, List}) ->
      +    case ets:lookup(Table,Row) of
      +	[] ->
      +	    ets:insert(Table,{Row, lists:duplicate(Col,0) ++ List});
      +	[{Row, OldData}] ->
      +	    {Part1,_} = my_split(Col,OldData,[]),
      +	    {_,Part2} = my_split(Col+length(List),OldData,[]),
      +	    ets:insert(Table,{Row, Part1 ++ List ++ Part2})
           end.

      The table is read or written in chunks of ?CHARS_PER_REC, overwriting when necessary. The implementation is clearly not efficient, it is just working.

      This concludes the example. It is fully runnable and you can read or write to the I/O server by using, for example, the io module or even the file diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/json.html b/prs/9045/lib/stdlib-6.1.2/doc/html/json.html index a28937d3f2bf..bb06e9d61edd 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/json.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/json.html @@ -1017,8 +1017,8 @@

      decode(Binary)

      Example

      -
      > json:decode(<<"{\"foo\": 1}">>).
      -#{<<"foo">> => 1}
      +
      > json:decode(<<"{\"foo\": 1}">>).
      +#{<<"foo">> => 1}
      @@ -1070,9 +1070,9 @@

      decode(Binary, Acc0, Decoders)

      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,<<>>}
      +

      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,<<>>}
      @@ -1105,11 +1105,11 @@

      decode_continue/2

      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,<<>>}
      @@ -1179,7 +1179,7 @@

      encode(Term)

      Examples

      -
      > iolist_to_binary(json:encode(#{foo => <<"bar">>})).
      +
      > iolist_to_binary(json:encode(#{foo => <<"bar">>})).
       <<"{\"foo\":\"bar\"}">>
      @@ -1221,10 +1221,10 @@

      encode(Term, Encoder)

      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}])).
      +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}">>
      @@ -1616,11 +1616,11 @@

      format(Term)

      -

      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
      @@ -1685,20 +1685,20 @@

      format(Term, Encoder, Options)

      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
      diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/lists.html b/prs/9045/lib/stdlib-6.1.2/doc/html/lists.html index 2226fc11131d..11e6cd16cb22 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/lists.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/lists.html @@ -1173,8 +1173,8 @@

      append(ListOfLists)

      -

      Returns a list in which all the sublists of ListOfLists have been appended.

      Example:

      > lists:append([[1, 2, 3], [a, b], [4, 5, 6]]).
      -[1,2,3,a,b,4,5,6]
      +

      Returns a list in which all the sublists of ListOfLists have been appended.

      Example:

      > lists:append([[1, 2, 3], [a, b], [4, 5, 6]]).
      +[1,2,3,a,b,4,5,6]
      @@ -1203,7 +1203,7 @@

      append(List1, List2)

      Returns a new list List3, which is made from the elements of List1 followed -by the elements of List2.

      Example:

      > lists:append("abc", "def").
      +by the elements of List2.

      Example:

      > lists:append("abc", "def").
       "abcdef"

      lists:append(A, B) is equivalent to A ++ B.

      @@ -1234,7 +1234,7 @@

      concat(Things)

      Concatenates the text representation of the elements of Things. The elements -of Things can be atoms, integers, floats, or strings.

      Example:

      > lists:concat([doc, '/', file, '.', 3]).
      +of Things can be atoms, integers, floats, or strings.

      Example:

      > lists:concat([doc, '/', file, '.', 3]).
       "doc/file.3"
      @@ -1353,8 +1353,8 @@

      duplicate(N, Elem)

      -

      Returns a list containing N copies of term Elem.

      Example:

      > lists:duplicate(5, xx).
      -[xx,xx,xx,xx,xx]
      +

      Returns a list containing N copies of term Elem.

      Example:

      > lists:duplicate(5, xx).
      +[xx,xx,xx,xx,xx]
      @@ -1455,12 +1455,12 @@

      enumerate(Index, Step, List1)

      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 had been 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:

      > lists:enumerate([a,b,c]).
      -[{1,a},{2,b},{3,c}]
      > lists:enumerate(10, [a,b,c]).
      -[{10,a},{11,b},{12,c}]
      > 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:

      > lists:enumerate([a,b,c]).
      +[{1,a},{2,b},{3,c}]
      > lists:enumerate(10, [a,b,c]).
      +[{10,a},{11,b},{12,c}]
      > lists:enumerate(0, -2, [a,b,c]).
      +[{0,a},{-2,b},{-4,c}]
      @@ -1529,15 +1529,15 @@

      filtermap(Fun, List1)

      Calls Fun(Elem) on successive elements Elem of List1 in order 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, where a value -of true is synonymous with {true, Elem}.

      That is, filtermap behaves as if it had been defined as follows:

      filtermap(Fun, List1) ->
      -    lists:foldr(fun(Elem, Acc) ->
      -                       case Fun(Elem) of
      +of true is synonymous with {true, Elem}.

      That is, filtermap behaves as if it had been defined as follows:

      filtermap(Fun, List1) ->
      +    lists:foldr(fun(Elem, Acc) ->
      +                       case Fun(Elem) of
                                  false -> Acc;
      -                           true -> [Elem|Acc];
      -                           {true,Value} -> [Value|Acc]
      +                           true -> [Elem|Acc];
      +                           {true,Value} -> [Value|Acc]
                              end
      -                end, [], List1).

      Example:

      > lists:filtermap(fun(X) -> case X rem 2 of 0 -> {true, X div 2}; _ -> false end end, [1,2,3,4,5]).
      -[1,2]
      +
      end, [], List1).

      Example:

      > lists:filtermap(fun(X) -> case X rem 2 of 0 -> {true, X div 2}; _ -> false end end, [1,2,3,4,5]).
      +[1,2]
      @@ -1596,9 +1596,9 @@

      flatmap(Fun, List1)

      Takes a function from As to lists of Bs, and a list of As (List1) and produces a list of Bs by applying the function to every element in List1 and -appending the resulting lists.

      That is, flatmap behaves as if it had been defined as follows:

      flatmap(Fun, List1) ->
      -    append(map(Fun, List1)).

      Example:

      > lists:flatmap(fun(X)->[X,X] end, [a,b,c]).
      -[a,a,b,b,c,c]
      +appending the resulting lists.

      That is, flatmap behaves as if it had been defined as follows:

      flatmap(Fun, List1) ->
      +    append(map(Fun, List1)).

      Example:

      > lists:flatmap(fun(X)->[X,X] end, [a,b,c]).
      +[a,a,b,b,c,c]
      @@ -1694,9 +1694,9 @@

      foldl(Fun, Acc0, List)

      Calls Fun(Elem, AccIn) on successive elements A of List, starting with AccIn == Acc0. Fun/2 must return a new accumulator, which is passed to the next call. The function returns the final value of the accumulator. Acc0 is -returned if the list is empty.

      Example:

      > lists:foldl(fun(X, Sum) -> X + Sum end, 0, [1,2,3,4,5]).
      +returned if the list is empty.

      Example:

      > lists:foldl(fun(X, Sum) -> X + Sum end, 0, [1,2,3,4,5]).
       15
      -> lists:foldl(fun(X, Prod) -> X * Prod end, 1, [1,2,3,4,5]).
      +> lists:foldl(fun(X, Prod) -> X * Prod end, 1, [1,2,3,4,5]).
       120
      @@ -1733,11 +1733,11 @@

      foldr(Fun, Acc0, List)

      -

      Like foldl/3, but the list is traversed from right to left.

      Example:

      > P = fun(A, AccIn) -> io:format("~p ", [A]), AccIn end.
      +

      Like foldl/3, but the list is traversed from right to left.

      Example:

      > P = fun(A, AccIn) -> io:format("~p ", [A]), AccIn end.
       #Fun<erl_eval.12.2225172>
      -> lists:foldl(P, void, [1,2,3]).
      +> lists:foldl(P, void, [1,2,3]).
       1 2 3 void
      -> lists:foldr(P, void, [1,2,3]).
      +> lists:foldr(P, void, [1,2,3]).
       3 2 1 void

      foldl/3 is tail recursive and is usually preferred to foldr/3.

      @@ -1800,12 +1800,12 @@

      join(Sep, List1)

      Inserts Sep between each element in List1. Has no effect on the empty list -and on a singleton list. For example:

      > lists:join(x, [a,b,c]).
      -[a,x,b,x,c]
      -> lists:join(x, [a]).
      -[a]
      -> lists:join(x, []).
      -[]
      +and on a singleton list. For example:

      > lists:join(x, [a,b,c]).
      +[a,x,b,x,c]
      +> lists:join(x, [a]).
      +[a]
      +> lists:join(x, []).
      +[]
      @@ -1906,10 +1906,10 @@

      keymap(Fun, N, TupleList1)

      Returns a list of tuples where, for each tuple in TupleList1, the Nth element Term1 of the tuple has been replaced with the result of calling -Fun(Term1).

      Examples:

      > Fun = fun(Atom) -> atom_to_list(Atom) end.
      +Fun(Term1).

      Examples:

      > Fun = fun(Atom) -> atom_to_list(Atom) end.
       #Fun<erl_eval.6.10732646>
      -2> lists:keymap(Fun, 2, [{name,jane,22},{name,lizzie,20},{name,lydia,15}]).
      -[{name,"jane",22},{name,"lizzie",20},{name,"lydia",15}]
      +2>
      lists:keymap(Fun, 2, [{name,jane,22},{name,lizzie,20},{name,lydia,15}]). +[{name,"jane",22},{name,"lizzie",20},{name,"lydia",15}]
      @@ -2250,9 +2250,9 @@

      mapfoldl(Fun, Acc0, List1)

      -

      Combines the operations of map/2 and foldl/3 into one pass.

      Example:

      Summing the elements in a list and double them at the same time:

      > lists:mapfoldl(fun(X, Sum) -> {2*X, X+Sum} end,
      -0, [1,2,3,4,5]).
      -{[2,4,6,8,10],15}
      +

      Combines the operations of map/2 and foldl/3 into one pass.

      Example:

      Summing the elements in a list and double them at the same time:

      > lists:mapfoldl(fun(X, Sum) -> {2*X, X+Sum} end,
      +0, [1,2,3,4,5]).
      +{[2,4,6,8,10],15}
      @@ -2544,7 +2544,7 @@

      nth(N, List)

      -

      Returns the Nth element of List.

      Example:

      > lists:nth(3, [a, b, c, d, e]).
      +

      Returns the Nth element of List.

      Example:

      > lists:nth(3, [a, b, c, d, e]).
       c
      @@ -2574,14 +2574,14 @@

      nthtail(N, List)

      Returns the Nth tail of List, that is, the sublist of List starting at -N+1 and continuing up to the end of the list.

      Example

      > lists:nthtail(3, [a, b, c, d, e]).
      -[d,e]
      -> tl(tl(tl([a, b, c, d, e]))).
      -[d,e]
      -> lists:nthtail(0, [a, b, c, d, e]).
      -[a,b,c,d,e]
      -> lists:nthtail(5, [a, b, c, d, e]).
      -[]
      +N+1 and continuing up to the end of the list.

      Example

      > lists:nthtail(3, [a, b, c, d, e]).
      +[d,e]
      +> tl(tl(tl([a, b, c, d, e]))).
      +[d,e]
      +> lists:nthtail(0, [a, b, c, d, e]).
      +[a,b,c,d,e]
      +> lists:nthtail(5, [a, b, c, d, e]).
      +[]
      @@ -2617,10 +2617,10 @@

      partition(Pred, List)

      Partitions List into two lists, where the first list contains all elements for which Pred(Elem) returns true, and the second list contains all elements for -which Pred(Elem) returns false.

      Examples:

      > lists:partition(fun(A) -> A rem 2 == 1 end, [1,2,3,4,5,6,7]).
      -{[1,3,5,7],[2,4,6]}
      -> lists:partition(fun(A) -> is_atom(A) end, [a,b,1,c,d,2,3,4,e]).
      -{[a,b,c,d,e],[1,2,3,4]}

      For a different way to partition a list, see splitwith/2.

      +which Pred(Elem) returns false.

      Examples:

      > lists:partition(fun(A) -> A rem 2 == 1 end, [1,2,3,4,5,6,7]).
      +{[1,3,5,7],[2,4,6]}
      +> lists:partition(fun(A) -> is_atom(A) end, [a,b,1,c,d,2,3,4,e]).
      +{[a,b,c,d,e],[1,2,3,4]}

      For a different way to partition a list, see splitwith/2.

      @@ -2705,8 +2705,8 @@

      reverse(List1, Tail)

      Returns a list with the elements in List1 in reverse order, with tail Tail -appended.

      Example:

      > lists:reverse([1, 2, 3, 4], [a, b, c]).
      -[4,3,2,1,a,b,c]
      +appended.

      Example:

      > lists:reverse([1, 2, 3, 4], [a, b, c]).
      +[4,3,2,1,a,b,c]
      @@ -2799,17 +2799,17 @@

      seq(From, To, Incr)

      Returns a sequence of integers that starts with From and contains the successive results of adding Incr to the previous element, until To is reached or passed (in the latter case, To is not an element of the sequence). -Incr defaults to 1.

      Failures:

      • If To < From - Incr and Incr > 0.
      • If To > From - Incr and Incr < 0.
      • If Incr =:= 0 and From =/= To.

      The following equalities hold for all sequences:

      length(lists:seq(From, To)) =:= To - From + 1
      -length(lists:seq(From, To, Incr)) =:= (To - From + Incr) div Incr

      Examples:

      > lists:seq(1, 10).
      -[1,2,3,4,5,6,7,8,9,10]
      -> lists:seq(1, 20, 3).
      -[1,4,7,10,13,16,19]
      -> lists:seq(1, 0, 1).
      -[]
      -> lists:seq(10, 6, 4).
      -[]
      -> lists:seq(1, 1, 0).
      -[1]
      +Incr defaults to 1.

      Failures:

      • If To < From - Incr and Incr > 0.
      • If To > From - Incr and Incr < 0.
      • If Incr =:= 0 and From =/= To.

      The following equalities hold for all sequences:

      length(lists:seq(From, To)) =:= To - From + 1
      +length(lists:seq(From, To, Incr)) =:= (To - From + Incr) div Incr

      Examples:

      > lists:seq(1, 10).
      +[1,2,3,4,5,6,7,8,9,10]
      +> lists:seq(1, 20, 3).
      +[1,4,7,10,13,16,19]
      +> lists:seq(1, 0, 1).
      +[]
      +> lists:seq(10, 6, 4).
      +[]
      +> lists:seq(1, 1, 0).
      +[1]
      @@ -2934,11 +2934,11 @@

      splitwith(Pred, List)

      Partitions List into two lists according to Pred. -splitwith/2 behaves as if it is defined as follows:

      splitwith(Pred, List) ->
      -    {takewhile(Pred, List), dropwhile(Pred, List)}.

      Examples:

      > lists:splitwith(fun(A) -> A rem 2 == 1 end, [1,2,3,4,5,6,7]).
      -{[1],[2,3,4,5,6,7]}
      -> lists:splitwith(fun(A) -> is_atom(A) end, [a,b,1,c,d,2,3,4,e]).
      -{[a,b],[1,c,d,2,3,4,e]}

      The Pred function must return a boolean. For a different way to partition a +splitwith/2 behaves as if it is defined as follows:

      splitwith(Pred, List) ->
      +    {takewhile(Pred, List), dropwhile(Pred, List)}.

      Examples:

      > lists:splitwith(fun(A) -> A rem 2 == 1 end, [1,2,3,4,5,6,7]).
      +{[1],[2,3,4,5,6,7]}
      +> lists:splitwith(fun(A) -> is_atom(A) end, [a,b,1,c,d,2,3,4,e]).
      +{[a,b],[1,c,d,2,3,4,e]}

      The Pred function must return a boolean. For a different way to partition a list, see partition/2.

      @@ -3005,12 +3005,12 @@

      sublist(List1, Start, Len)

      Returns the sublist of List1 starting at Start and with (maximum) Len -elements. It is not an error for Start+Len to exceed the length of the list.

      Examples:

      > lists:sublist([1,2,3,4], 2, 2).
      -[2,3]
      -> lists:sublist([1,2,3,4], 2, 5).
      -[2,3,4]
      -> lists:sublist([1,2,3,4], 5, 2).
      -[]
      +elements. It is not an error for Start+Len to exceed the length of the list.

      Examples:

      > lists:sublist([1,2,3,4], 2, 2).
      +[2,3]
      +> lists:sublist([1,2,3,4], 2, 5).
      +[2,3,4]
      +> lists:sublist([1,2,3,4], 5, 2).
      +[]
      @@ -3040,7 +3040,7 @@

      subtract(List1, List2)

      Returns a new list List3 that is a copy of List1, subjected to the following procedure: for each element in List2, its first occurrence in List1 is -deleted.

      Example:

      > lists:subtract("123212", "212").
      +deleted.

      Example:

      > lists:subtract("123212", "212").
       "312".

      lists:subtract(A, B) is equivalent to A -- B.

      @@ -3376,10 +3376,10 @@

      uniq(List1)

      Returns a list containing the elements of List1 with duplicated elements removed (preserving the order of the elements). The first occurrence of each -element is kept.

      Examples:

      > lists:uniq([3,3,1,2,1,2,3]).
      -[3,1,2]
      -> lists:uniq([a, a, 1, b, 2, a, 3]).
      -[a, 1, b, 2, 3]
      +element is kept.

      Examples:

      > lists:uniq([3,3,1,2,1,2,3]).
      +[3,1,2]
      +> lists:uniq([a, a, 1, b, 2, a, 3]).
      +[a, 1, b, 2, 3]
      @@ -3411,8 +3411,8 @@

      uniq(Fun, List1)

      Returns a list containing the elements of List1 without the elements for which Fun returned duplicate values (preserving the order of the elements). The -first occurrence of each element is kept.

      Examples:

      > lists:uniq(fun({X, _}) -> X end, [{b, 2}, {a, 1}, {c, 3}, {a, 2}]).
      -[{b, 2}, {a, 1}, {c, 3}]
      +first occurrence of each element is kept.

      Examples:

      > lists:uniq(fun({X, _}) -> X end, [{b, 2}, {a, 1}, {c, 3}, {a, 2}]).
      +[{b, 2}, {a, 1}, {c, 3}]
      @@ -3696,14 +3696,14 @@

      zip(List1, List2, How)

      tuple is taken from the first list and the second element is taken from the corresponding element in the second list.

      The How parameter specifies the behavior if the given lists are of different lengths.

      • fail - The call will fail if the given lists are not of equal length. -This is the default.

      • trim - Surplus elements from the longer list will be ignored.

        Examples:

        > lists:zip([a, b], [1, 2, 3], trim).
        -[{a,1},{b,2}]
        -> lists:zip([a, b, c], [1, 2], trim).
        -[{a,1},{b,2}]
      • {pad, Defaults} - The shorter list will be padded to the length of the -longer list, using the respective elements from the given Defaults tuple.

        Examples:

        > lists:zip([a, b], [1, 2, 3], {pad, {x, 0}}).
        -[{a,1},{b,2},{x,3}]
        -> lists:zip([a, b, c], [1, 2], {pad, {x, 0}}).
        -[{a,1},{b,2},{c,0}]
      +This is the default.

    • trim - Surplus elements from the longer list will be ignored.

      Examples:

      > lists:zip([a, b], [1, 2, 3], trim).
      +[{a,1},{b,2}]
      +> lists:zip([a, b, c], [1, 2], trim).
      +[{a,1},{b,2}]
    • {pad, Defaults} - The shorter list will be padded to the length of the +longer list, using the respective elements from the given Defaults tuple.

      Examples:

      > lists:zip([a, b], [1, 2, 3], {pad, {x, 0}}).
      +[{a,1},{b,2},{x,3}]
      +> lists:zip([a, b, c], [1, 2], {pad, {x, 0}}).
      +[{a,1},{b,2},{c,0}]
    @@ -3788,10 +3788,10 @@

    zipwith3(Combine, List1, List2, List3, How)

    Combines the elements of three lists into one list. For each triple X, Y, Z of list elements from the three lists, the element in the result list is Combine(X, Y, Z).

    For a description of the How parameter, see zip/3.

    zipwith3(fun(X, Y, Z) -> {X,Y,Z} end, List1, List2, List3) is -equivalent to zip3(List1, List2, List3).

    Examples:

    > lists:zipwith3(fun(X, Y, Z) -> X+Y+Z end, [1,2,3], [4,5,6], [7,8,9]).
    -[12,15,18]
    -> lists:zipwith3(fun(X, Y, Z) -> [X,Y,Z] end, [a,b,c], [x,y,z], [1,2,3]).
    -[[a,x,1],[b,y,2],[c,z,3]]
    +equivalent to zip3(List1, List2, List3).

    Examples:

    > lists:zipwith3(fun(X, Y, Z) -> X+Y+Z end, [1,2,3], [4,5,6], [7,8,9]).
    +[12,15,18]
    +> lists:zipwith3(fun(X, Y, Z) -> [X,Y,Z] end, [a,b,c], [x,y,z], [1,2,3]).
    +[[a,x,1],[b,y,2],[c,z,3]]

    @@ -3870,8 +3870,8 @@

    zipwith(Combine, List1, List2, How)

    Combines the elements of two lists into one list. For each pair X, Y of list elements from the two lists, the element in the result list is Combine(X, Y).

    For a description of the How parameter, see zip/3.

    zipwith(fun(X, Y) -> {X,Y} end, List1, List2) is equivalent to -zip(List1, List2).

    Example:

    > lists:zipwith(fun(X, Y) -> X+Y end, [1,2,3], [4,5,6]).
    -[5,7,9]
    +zip(List1, List2).

    Example:

    > lists:zipwith(fun(X, Y) -> X+Y end, [1,2,3], [4,5,6]).
    +[5,7,9]
    diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/maps.html b/prs/9045/lib/stdlib-6.1.2/doc/html/maps.html index 66424b522d06..4931d486212c 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/maps.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/maps.html @@ -751,10 +751,10 @@

    filter(Pred, MapOrIter)

    Returns a map Map for which predicate Pred holds true in MapOrIter.

    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.

    Example:

    > M = #{a => 2, b => 3, c=> 4, "a" => 1, "b" => 2, "c" => 4},
    -  Pred = fun(K,V) -> is_atom(K) andalso (V rem 2) =:= 0 end,
    -  maps:filter(Pred,M).
    -#{a => 2,c => 4}
    +valid iterator, or with badarg if Pred is not a function of arity 2.

    Example:

    > M = #{a => 2, b => 3, c=> 4, "a" => 1, "b" => 2, "c" => 4},
    +  Pred = fun(K,V) -> is_atom(K) andalso (V rem 2) =:= 0 end,
    +  maps:filter(Pred,M).
    +#{a => 2,c => 4}
    @@ -793,10 +793,10 @@

    filtermap(Fun, MapOrIter)

    map. If it returns false, the association is not copied. If it returns {true, NewValue}, the value for Key is replaced with NewValue in the result map.

    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.

    Example:

    > Fun = fun(K,V) when is_atom(K) -> {true, V*2}; (_,V) -> (V rem 2) =:= 0 end,
    -  Map = #{k1 => 1, "k2" => 2, "k3" => 3},
    -  maps:filtermap(Fun,Map).
    -#{k1 => 2,"k2" => 2}
    +valid iterator, or with badarg if Fun is not a function of arity 2.

    Example:

    > Fun = fun(K,V) when is_atom(K) -> {true, V*2}; (_,V) -> (V rem 2) =:= 0 end,
    +  Map = #{k1 => 1, "k2" => 2, "k3" => 3},
    +  maps:filtermap(Fun,Map).
    +#{k1 => 2,"k2" => 2}
    @@ -827,10 +827,10 @@

    find(Key, Map)

    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.

    Example:

    > 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.

    Example:

    > Map = #{"hi" => 42},
       Key = "hi",
    -  maps:find(Key,Map).
    -{ok,42}
    +
    maps:find(Key,Map). +{ok,42}
    @@ -871,9 +871,9 @@

    fold(Fun, Init, MapOrIter)

    which is passed to the next successive call. This function returns the final value of the accumulator. The initial accumulator value Init is returned if the map is empty.

    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.

    Example:

    > Fun = fun(K,V,AccIn) when is_list(K) -> AccIn + V end,
    -  Map = #{"k1" => 1, "k2" => 2, "k3" => 3},
    -  maps:fold(Fun,0,Map).
    +valid iterator, or with badarg if Fun is not a function of arity 3.

    Example:

    > Fun = fun(K,V,AccIn) when is_list(K) -> AccIn + V end,
    +  Map = #{"k1" => 1, "k2" => 2, "k3" => 3},
    +  maps:fold(Fun,0,Map).
     6
    @@ -940,8 +940,8 @@

    from_keys(Keys, Value)

    Takes a list of keys and a value and builds a map where all keys point to the -same value. The key can be in any order, and keys and value can be of any term.

    Example:

    > Keys = ["a", "b", "c"], maps:from_keys(Keys, ok).
    -#{"a" => ok,"b" => ok,"c" => ok}
    +same value. The key can be in any order, and keys and value can be of any term.

    Example:

    > Keys = ["a", "b", "c"], maps:from_keys(Keys, ok).
    +#{"a" => ok,"b" => ok,"c" => ok}
    @@ -973,9 +973,9 @@

    from_list(List)

    Takes a list of key-value tuples elements and builds a map. The associations can be in any order, and both keys and values in the association can be of any term.

    If the same key appears more than once, the latter (right-most) value is used -and the previous values are ignored.

    Example:

    > List = [{"a",ignored},{1337,"value two"},{42,value_three},{"a",1}],
    -  maps:from_list(List).
    -#{42 => value_three,1337 => "value two","a" => 1}
    +and the previous values are ignored.

    Example:

    > List = [{"a",ignored},{1337,"value two"},{42,value_three},{"a",1}],
    +  maps:from_list(List).
    +#{42 => value_three,1337 => "value two","a" => 1}
    @@ -1007,8 +1007,8 @@

    get(Key, Map)

    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.

    Example:

    > Key = 1337,
    -  Map = #{42 => value_two,1337 => "value one","a" => 1},
    -  maps:get(Key,Map).
    +  Map = #{42 => value_two,1337 => "value one","a" => 1},
    +  maps:get(Key,Map).
     "value one"
    @@ -1040,11 +1040,11 @@

    get(Key, Map, Default)

    Returns value Value associated with Key if Map contains Key. If no value -is associated with Key, Default is returned.

    The call fails with a {badmap,Map} exception if Map is not a map.

    Example:

    > Map = #{ key1 => val1, key2 => val2 }.
    -#{key1 => val1,key2 => val2}
    -> maps:get(key1, Map, "Default value").
    +is associated with Key, Default is returned.

    The call fails with a {badmap,Map} exception if Map is not a map.

    Example:

    > Map = #{ key1 => val1, key2 => val2 }.
    +#{key1 => val1,key2 => val2}
    +> maps:get(key1, Map, "Default value").
     val1
    -> maps:get(key3, Map, "Default value").
    +> maps:get(key3, Map, "Default value").
     "Default value"
    @@ -1084,11 +1084,11 @@

    groups_from_list(KeyFun, List)

    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:

    > EvenOdd = fun(X) -> case X rem 2 of 0 -> even; 1 -> odd end end,
    -maps:groups_from_list(EvenOdd, [1, 2, 3]).
    -#{even => [2], odd => [1, 3]}
    -> maps:groups_from_list(fun erlang:length/1, ["ant", "buffalo", "cat", "dingo"]).
    -#{3 => ["ant", "cat"], 5 => ["dingo"], 7 => ["buffalo"]}
    +list.

    Examples:

    > EvenOdd = fun(X) -> case X rem 2 of 0 -> even; 1 -> odd end end,
    +maps:groups_from_list(EvenOdd, [1, 2, 3]).
    +#{even => [2], odd => [1, 3]}
    +> maps:groups_from_list(fun erlang:length/1, ["ant", "buffalo", "cat", "dingo"]).
    +#{3 => ["ant", "cat"], 5 => ["dingo"], 7 => ["buffalo"]}
    @@ -1130,15 +1130,15 @@

    groups_from_list(KeyFun, ValueFun, List)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:

    > EvenOdd = fun(X) -> case X rem 2 of 0 -> even; 1 -> odd end end,
    -> Square = fun(X) -> X * X end,
    -> maps:groups_from_list(EvenOdd, Square, [1, 2, 3]).
    -#{even => [4], odd => [1, 9]}
    -> maps:groups_from_list(
    +list.

    Examples:

    > EvenOdd = fun(X) -> case X rem 2 of 0 -> even; 1 -> odd end end,
    +> Square = fun(X) -> X * X end,
    +> maps:groups_from_list(EvenOdd, Square, [1, 2, 3]).
    +#{even => [4], odd => [1, 9]}
    +> maps:groups_from_list(
         fun erlang: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"]}

    @@ -1170,10 +1170,10 @@

    intersect(Map1, Map2)

    Intersects two maps into a single map Map3. If a key exists in both maps, the -value in Map1 is superseded by the value in Map2.

    The call fails with a {badmap,Map} exception if Map1 or Map2 is not a map.

    Example:

    > Map1 = #{a => "value_one", b => "value_two"},
    -  Map2 = #{a => 1, c => 2},
    -  maps:intersect(Map1,Map2).
    -#{a => 1}
    +value in Map1 is superseded by the value in Map2.

    The call fails with a {badmap,Map} exception if Map1 or Map2 is not a map.

    Example:

    > Map1 = #{a => "value_one", b => "value_two"},
    +  Map2 = #{a => 1, c => 2},
    +  maps:intersect(Map1,Map2).
    +#{a => 1}
    @@ -1213,10 +1213,10 @@

    intersect_with(Combiner, Map1, Map2)

    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.

    Example:

    > Map1 = #{a => "value_one", b => "value_two"},
    -  Map2 = #{a => 1, c => 2},
    -  maps:intersect_with(fun(_Key, Value1, Value2) -> {Value1, Value2} end, Map1, Map2).
    -#{a => {"value_one",1}}
    +three arguments.

    Example:

    > Map1 = #{a => "value_one", b => "value_two"},
    +  Map2 = #{a => 1, c => 2},
    +  maps:intersect_with(fun(_Key, Value1, Value2) -> {Value1, Value2} end, Map1, Map2).
    +#{a => {"value_one",1}}
    @@ -1247,11 +1247,11 @@

    is_key(Key, Map)

    Returns true if map Map contains Key and returns false if it does not -contain the Key.

    The call fails with a {badmap,Map} exception if Map is not a map.

    Example:

    > Map = #{"42" => value}.
    -#{"42" => value}
    -> maps:is_key("42",Map).
    +contain the Key.

    The call fails with a {badmap,Map} exception if Map is not a map.

    Example:

    > Map = #{"42" => value}.
    +#{"42" => value}
    +> maps:is_key("42",Map).
     true
    -> maps:is_key(value,Map).
    +> maps:is_key(value,Map).
     false
    @@ -1284,15 +1284,15 @@

    iterator(Map)

    Returns a map iterator Iterator that can be used by maps:next/1 to traverse the key-value associations in a map. When iterating over a map, the -memory usage is guaranteed to be bounded no matter the size of the map.

    The call fails with a {badmap,Map} exception if Map is not a map.

    Example:

    > M = #{ a => 1, b => 2 }.
    -#{a => 1,b => 2}
    -> I = maps:iterator(M), ok.
    +memory usage is guaranteed to be bounded no matter the size of the map.

    The call fails with a {badmap,Map} exception if Map is not a map.

    Example:

    > M = #{ a => 1, b => 2 }.
    +#{a => 1,b => 2}
    +> I = maps:iterator(M), ok.
     ok
    -> {K1, V1, I2} = maps:next(I), {K1, V1}.
    -{a,1}
    -> {K2, V2, I3} = maps:next(I2),{K2, V2}.
    -{b,2}
    -> maps:next(I3).
    +> {K1, V1, I2} = maps:next(I), {K1, V1}.
    +{a,1}
    +> {K2, V2, I3} = maps:next(I2),{K2, V2}.
    +{b,2}
    +> maps:next(I3).
     none
    @@ -1330,34 +1330,34 @@

    iterator(Map, Order)

    Returns a map iterator Iterator that can be used by maps:next/1 to traverse the key-value associations in a map sorted by key using the given Order.

    The call fails with a {badmap,Map} exception if Map is not a map or if -Order is invalid.

    Example (when Order is ordered):

    > M = #{ a => 1, b => 2 }.
    -#{a => 1,b => 2}
    -> OrdI = maps:iterator(M, ordered), ok.
    +Order is invalid.

    Example (when Order is ordered):

    > M = #{ a => 1, b => 2 }.
    +#{a => 1,b => 2}
    +> OrdI = maps:iterator(M, ordered), ok.
     ok
    -> {K1, V1, OrdI2} = maps:next(OrdI), {K1, V1}.
    -{a,1}
    -> {K2, V2, OrdI3} = maps:next(OrdI2),{K2, V2}.
    -{b,2}
    -> maps:next(OrdI3).
    -none

    Example (when Order is reversed):

    > M = #{ a => 1, b => 2 }.
    -#{a => 1,b => 2}
    -> RevI = maps:iterator(M, reversed), ok.
    +> {K1, V1, OrdI2} = maps:next(OrdI), {K1, V1}.
    +{a,1}
    +> {K2, V2, OrdI3} = maps:next(OrdI2),{K2, V2}.
    +{b,2}
    +> maps:next(OrdI3).
    +none

    Example (when Order is reversed):

    > M = #{ a => 1, b => 2 }.
    +#{a => 1,b => 2}
    +> RevI = maps:iterator(M, reversed), ok.
     ok
    -> {K2, V2, RevI2} = maps:next(RevI), {K2, V2}.
    -{b,2}
    -> {K1, V1, RevI3} = maps:next(RevI2),{K1, V1}.
    -{a,1}
    -> maps:next(RevI3).
    -none

    Example (when Order is an arithmetic sorting function):

    > M = #{ -1 => a, -1.0 => b, 0 => c, 0.0 => d }.
    -#{-1 => a,0 => c,-1.0 => b,0.0 => d}
    -> ArithOrdI = maps:iterator(M, fun(A, B) -> A =< B end), ok.
    +> {K2, V2, RevI2} = maps:next(RevI), {K2, V2}.
    +{b,2}
    +> {K1, V1, RevI3} = maps:next(RevI2),{K1, V1}.
    +{a,1}
    +> maps:next(RevI3).
    +none

    Example (when Order is an arithmetic sorting function):

    > M = #{ -1 => a, -1.0 => b, 0 => c, 0.0 => d }.
    +#{-1 => a,0 => c,-1.0 => b,0.0 => d}
    +> ArithOrdI = maps:iterator(M, fun(A, B) -> A =< B end), ok.
     ok
    -> maps:to_list(ArithOrdI).
    -[{-1,a},{-1.0,b},{0,c},{0.0,d}]
    -> ArithRevI = maps:iterator(M, fun(A, B) -> B < A end), ok.
    +> maps:to_list(ArithOrdI).
    +[{-1,a},{-1.0,b},{0,c},{0.0,d}]
    +> ArithRevI = maps:iterator(M, fun(A, B) -> B < A end), ok.
     ok
    -> maps:to_list(ArithRevI).
    -[{0.0,d},{0,c},{-1.0,b},{-1,a}]
    +>
    maps:to_list(ArithRevI). +[{0.0,d},{0,c},{-1.0,b},{-1,a}]
    @@ -1387,9 +1387,9 @@

    keys(Map)

    -

    Returns a complete list of keys, in any order, which resides within Map.

    The call fails with a {badmap,Map} exception if Map is not a map.

    Example:

    > Map = #{42 => value_three,1337 => "value two","a" => 1},
    -  maps:keys(Map).
    -[42,1337,"a"]
    +

    Returns a complete list of keys, in any order, which resides within Map.

    The call fails with a {badmap,Map} exception if Map is not a map.

    Example:

    > Map = #{42 => value_three,1337 => "value two","a" => 1},
    +  maps:keys(Map).
    +[42,1337,"a"]
    @@ -1427,10 +1427,10 @@

    map(Fun, MapOrIter)

    Key to value Value1 association in MapOrIter in any order. Function fun Fun/2 must return value Value2 to be associated with key Key for the new map Map.

    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.

    Example:

    > Fun = fun(K,V1) when is_list(K) -> V1*2 end,
    -  Map = #{"k1" => 1, "k2" => 2, "k3" => 3},
    -  maps:map(Fun,Map).
    -#{"k1" => 2,"k2" => 4,"k3" => 6}
    +valid iterator, or with badarg if Fun is not a function of arity 2.

    Example:

    > Fun = fun(K,V1) when is_list(K) -> V1*2 end,
    +  Map = #{"k1" => 1, "k2" => 2, "k3" => 3},
    +  maps:map(Fun,Map).
    +#{"k1" => 2,"k2" => 4,"k3" => 6}
    @@ -1461,10 +1461,10 @@

    merge(Map1, Map2)

    Merges two maps into a single map Map3. If two keys exist in both maps, the -value in Map1 is superseded by the value in Map2.

    The call fails with a {badmap,Map} exception if Map1 or Map2 is not a map.

    Example:

    > Map1 = #{a => "value_one", b => "value_two"},
    -  Map2 = #{a => 1, c => 2},
    -  maps:merge(Map1,Map2).
    -#{a => 1,b => "value_two",c => 2}
    +value in Map1 is superseded by the value in Map2.

    The call fails with a {badmap,Map} exception if Map1 or Map2 is not a map.

    Example:

    > Map1 = #{a => "value_one", b => "value_two"},
    +  Map2 = #{a => 1, c => 2},
    +  maps:merge(Map1,Map2).
    +#{a => 1,b => "value_two",c => 2}
    @@ -1504,10 +1504,10 @@

    merge_with(Combiner, Map1, Map2)

    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.

    Example:

    > Map1 = #{a => "value_one", b => "value_two"},
    -  Map2 = #{a => 1, c => 2},
    -  maps:merge_with(fun(_Key, Value1, Value2) -> {Value1, Value2} end, Map1, Map2).
    -#{a => {"value_one",1},b => "value_two",c => 2}
    +three arguments.

    Example:

    > Map1 = #{a => "value_one", b => "value_two"},
    +  Map2 = #{a => 1, c => 2},
    +  maps:merge_with(fun(_Key, Value1, Value2) -> {Value1, Value2} end, Map1, Map2).
    +#{a => {"value_one",1},b => "value_two",c => 2}
    @@ -1570,17 +1570,17 @@

    next(Iterator)

    Returns the next key-value association in Iterator and a new iterator for the -remaining associations in the iterator.

    If there are no more associations in the iterator, none is returned.

    Example:

    > Map = #{a => 1, b => 2, c => 3}.
    -#{a => 1,b => 2,c => 3}
    -> I = maps:iterator(Map), ok.
    +remaining associations in the iterator.

    If there are no more associations in the iterator, none is returned.

    Example:

    > Map = #{a => 1, b => 2, c => 3}.
    +#{a => 1,b => 2,c => 3}
    +> I = maps:iterator(Map), ok.
     ok
    -> {K1, V1, I1} = maps:next(I), {K1, V1}.
    -{a,1}
    -> {K2, V2, I2} = maps:next(I1), {K2, V2}.
    -{b,2}
    -> {K3, V3, I3} = maps:next(I2), {K3, V3}.
    -{c,3}
    -> maps:next(I3).
    +> {K1, V1, I1} = maps:next(I), {K1, V1}.
    +{a,1}
    +> {K2, V2, I2} = maps:next(I1), {K2, V2}.
    +{b,2}
    +> {K3, V3, I3} = maps:next(I2), {K3, V3}.
    +{c,3}
    +> maps:next(I3).
     none
    @@ -1614,12 +1614,12 @@

    put(Key, Value, Map1)

    Associates Key with value Value and inserts the association into map Map2. If key Key already exists in map Map1, the old associated value is replaced by value Value. The function returns a new map Map2 containing the new -association and the old associations in Map1.

    The call fails with a {badmap,Map} exception if Map1 is not a map.

    Example:

    > Map = #{"a" => 1}.
    -#{"a" => 1}
    -> maps:put("a", 42, Map).
    -#{"a" => 42}
    -> maps:put("b", 1337, Map).
    -#{"a" => 1,"b" => 1337}
    +association and the old associations in Map1.

    The call fails with a {badmap,Map} exception if Map1 is not a map.

    Example:

    > Map = #{"a" => 1}.
    +#{"a" => 1}
    +> maps:put("a", 42, Map).
    +#{"a" => 42}
    +> maps:put("b", 1337, Map).
    +#{"a" => 1,"b" => 1337}
    @@ -1650,12 +1650,12 @@

    remove(Key, Map1)

    Removes the Key, if it exists, and its associated value from Map1 and -returns a new map Map2 without key Key.

    The call fails with a {badmap,Map} exception if Map1 is not a map.

    Example:

    > Map = #{"a" => 1}.
    -#{"a" => 1}
    -> maps:remove("a",Map).
    -#{}
    -> maps:remove("b",Map).
    -#{"a" => 1}
    +returns a new map Map2 without key Key.

    The call fails with a {badmap,Map} exception if Map1 is not a map.

    Example:

    > Map = #{"a" => 1}.
    +#{"a" => 1}
    +> maps:remove("a",Map).
    +#{}
    +> maps:remove("b",Map).
    +#{"a" => 1}
    @@ -1686,8 +1686,8 @@

    size(Map)

    Returns the number of key-value associations in Map. This operation occurs in -constant time.

    Example:

    > Map = #{42 => value_two,1337 => "value one","a" => 1},
    -  maps:size(Map).
    +constant time.

    Example:

    > Map = #{42 => value_two,1337 => "value one","a" => 1},
    +  maps:size(Map).
     3
    @@ -1720,11 +1720,11 @@

    take(Key, Map1)

    The function removes the Key, if it exists, and its associated value from Map1 and returns a tuple with the removed Value and the new map Map2 -without key Key. If the key does not exist error is returned.

    The call will fail with a {badmap,Map} exception if Map1 is not a map.

    Example:

    > Map = #{"a" => "hello", "b" => "world"}.
    -#{"a" => "hello", "b" => "world"}
    -> maps:take("a",Map).
    -{"hello",#{"b" => "world"}}
    -> maps:take("does not exist",Map).
    +without key Key. If the key does not exist error is returned.

    The call will fail with a {badmap,Map} exception if Map1 is not a map.

    Example:

    > Map = #{"a" => "hello", "b" => "world"}.
    +#{"a" => "hello", "b" => "world"}
    +> maps:take("a",Map).
    +{"hello",#{"b" => "world"}}
    +> maps:take("does not exist",Map).
     error
    @@ -1759,12 +1759,12 @@

    to_list(MapOrIterator)

    Returns a list of pairs representing the key-value associations of MapOrIterator, where the pairs [{K1,V1}, ..., {Kn,Vn}] are returned in arbitrary order.

    The call fails with a {badmap,Map} exception if MapOrIterator is not a map -or an iterator obtained by a call to iterator/1 or iterator/2.

    Example:

    > Map = #{42 => value_three,1337 => "value two","a" => 1},
    -  maps:to_list(Map).
    -[{42,value_three},{1337,"value two"},{"a",1}]

    Example (using iterator/2):

    > Map = #{ z => 1, y => 2, x => 3 }.
    -#{x => 3,y => 2,z => 1}
    -> maps:to_list(maps:iterator(Map, ordered)).
    -[{x,3},{y,2},{z,1}]
    +or an iterator obtained by a call to iterator/1 or iterator/2.

    Example:

    > Map = #{42 => value_three,1337 => "value two","a" => 1},
    +  maps:to_list(Map).
    +[{42,value_three},{1337,"value two"},{"a",1}]

    Example (using iterator/2):

    > Map = #{ z => 1, y => 2, x => 3 }.
    +#{x => 3,y => 2,z => 1}
    +> maps:to_list(maps:iterator(Map, ordered)).
    +[{x,3},{y,2},{z,1}]
    @@ -1797,10 +1797,10 @@

    update(Key, Value, Map1)

    If Key exists in Map1, the old associated value is replaced by value Value. The function returns a new map Map2 containing the new associated value.

    The call fails with a {badmap,Map} exception if Map1 is not a map, or with a -{badkey,Key} exception if no value is associated with Key.

    Example:

    > Map = #{"a" => 1}.
    -#{"a" => 1}
    -> maps:update("a", 42, Map).
    -#{"a" => 42}
    +{badkey,Key} exception if no value is associated with Key.

    Example:

    > Map = #{"a" => 1}.
    +#{"a" => 1}
    +> maps:update("a", 42, Map).
    +#{"a" => 42}
    @@ -1836,10 +1836,10 @@

    update_with(Key, Fun, Map1)

    Update a value in a Map1 associated with Key by calling Fun on the old value to get a new value. An exception {badkey,Key} is generated if Key is -not present in the map.

    Example:

    > Map = #{"counter" => 1},
    -  Fun = fun(V) -> V + 1 end,
    -  maps:update_with("counter",Fun,Map).
    -#{"counter" => 2}
    +not present in the map.

    Example:

    > Map = #{"counter" => 1},
    +  Fun = fun(V) -> V + 1 end,
    +  maps:update_with("counter",Fun,Map).
    +#{"counter" => 2}
    @@ -1875,10 +1875,10 @@

    update_with(Key, Fun, Init, Map1)

    Update a value in a Map1 associated with Key by calling Fun on the old value to get a new value. If Key is not present in Map1 then Init will be -associated with Key.

    Example:

    > Map = #{"counter" => 1},
    -  Fun = fun(V) -> V + 1 end,
    -  maps:update_with("new counter",Fun,42,Map).
    -#{"counter" => 1,"new counter" => 42}
    +associated with Key.

    Example:

    > Map = #{"counter" => 1},
    +  Fun = fun(V) -> V + 1 end,
    +  maps:update_with("new counter",Fun,42,Map).
    +#{"counter" => 1,"new counter" => 42}
    @@ -1908,9 +1908,9 @@

    values(Map)

    -

    Returns a complete list of values, in arbitrary order, contained in map Map.

    The call fails with a {badmap,Map} exception if Map is not a map.

    Example:

    > Map = #{42 => value_three,1337 => "value two","a" => 1},
    -  maps:values(Map).
    -[value_three,"value two",1]
    +

    Returns a complete list of values, in arbitrary order, contained in map Map.

    The call fails with a {badmap,Map} exception if Map is not a map.

    Example:

    > Map = #{42 => value_three,1337 => "value two","a" => 1},
    +  maps:values(Map).
    +[value_three,"value two",1]
    @@ -1942,10 +1942,10 @@

    with(Ks, Map1)

    Returns a new map Map2 with the keys K1 through Kn and their associated values from map Map1. Any key in Ks that does not exist in Map1 is -ignored.

    Example:

    > Map = #{42 => value_three,1337 => "value two","a" => 1},
    -  Ks = ["a",42,"other key"],
    -  maps:with(Ks,Map).
    -#{42 => value_three,"a" => 1}
    +ignored.

    Example:

    > Map = #{42 => value_three,1337 => "value two","a" => 1},
    +  Ks = ["a",42,"other key"],
    +  maps:with(Ks,Map).
    +#{42 => value_three,"a" => 1}
    @@ -1976,10 +1976,10 @@

    without(Ks, Map1)

    Returns a new map Map2 without keys K1 through Kn and their associated -values from map Map1. Any key in Ks that does not exist in Map1 is ignored

    Example:

    > Map = #{42 => value_three,1337 => "value two","a" => 1},
    -  Ks = ["a",42,"other key"],
    -  maps:without(Ks,Map).
    -#{1337 => "value two"}
    +values from map Map1. Any key in Ks that does not exist in Map1 is ignored

    Example:

    > Map = #{42 => value_three,1337 => "value two","a" => 1},
    +  Ks = ["a",42,"other key"],
    +  maps:without(Ks,Map).
    +#{1337 => "value two"}
    diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/ms_transform.html b/prs/9045/lib/stdlib-6.1.2/doc/html/ms_transform.html index cce008f10de9..e742540b455b 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/ms_transform.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/ms_transform.html @@ -160,31 +160,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 @@ -195,12 +195,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 @@ -222,22 +222,22 @@

    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)).

    + end)).

    @@ -245,11 +245,11 @@

    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. @@ -264,10 +264,10 @@

    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.

    @@ -280,24 +280,24 @@

    {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"}]

    +{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"}]

    @@ -344,18 +344,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 @@ -364,32 +364,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)).
    -{ok,[{matched,nonode@nohost,1},{saved,1}]}

    As can be seen, the fun used with dbg:fun2ms/1 takes a single list as +ets:new(toy_table, <something>):

    3> dbg:tp(ets,new,dbg:fun2ms(fun([toy_table,_]) -> true end)).
    +{ok,[{matched,nonode@nohost,1},{saved,1}]}

    As can be seen, the fun used with dbg:fun2ms/1 takes a single list as parameter instead of a single tuple. The list matches a list of the parameters to the traced function. A single variable can also be used. The body of the fun expresses, in a more imperative way, actions to be taken if the fun head (and the guards) matches. true is returned here, only because the body of a fun -cannot be empty. The return value is discarded.

    The following trace output is received during test:

    (<0.86.0>) call ets:new(toy_table, [ordered_set])

    Assume that we have not found the problem yet, and want to see what ets:new/2 -returns. We use a slightly different trace pattern:

    4> dbg:tp(ets,new,dbg:fun2ms(fun([toy_table,_]) -> return_trace() end)).

    The following trace output is received during test:

    (<0.86.0>) call ets:new(toy_table,[ordered_set])
    -(<0.86.0>) returned from ets:new/2 -> 24

    The call to return_trace results in a trace message when the function returns. +cannot be empty. The return value is discarded.

    The following trace output is received during test:

    (<0.86.0>) call ets:new(toy_table, [ordered_set])

    Assume that we have not found the problem yet, and want to see what ets:new/2 +returns. We use a slightly different trace pattern:

    4> dbg:tp(ets,new,dbg:fun2ms(fun([toy_table,_]) -> return_trace() end)).

    The following trace output is received during test:

    (<0.86.0>) call ets:new(toy_table,[ordered_set])
    +(<0.86.0>) returned from ets:new/2 -> 24

    The call to return_trace results in a trace message when the function returns. It applies only to the specific function call triggering the match specification (and matching the head/guards of the match specification). This is by far the most common call in the body of a dbg match specification.

    The test now fails with {badmatch,24} because the atom toy_table does not match the number returned for an unnamed table. So, the problem is found, the table is to be named, and the arguments supplied by the test program do not -include named_table. We rewrite the start function:

    start(Args) ->
    -    toy_table = ets:new(toy_table, [named_table|Args]).

    With the same tracing turned on, the following trace output is received:

    (<0.86.0>) call ets:new(toy_table,[named_table,ordered_set])
    -(<0.86.0>) returned from ets:new/2 -> toy_table

    Assume that the module now passes all testing and goes into the system. After a +include named_table. We rewrite the start function:

    start(Args) ->
    +    toy_table = ets:new(toy_table, [named_table|Args]).

    With the same tracing turned on, the following trace output is received:

    (<0.86.0>) call ets:new(toy_table,[named_table,ordered_set])
    +(<0.86.0>) returned from ets:new/2 -> toy_table

    Assume that the module now passes all testing and goes into the system. After a while, it is found that table toy_table grows while the system is running and that there are many elements with atoms as keys. We expected only integer keys and so does the rest of the system, but clearly not the entire system. We turn -on call tracing and try to see calls to the module with an atom as the key:

    1> dbg:tracer().
    -{ok,<0.88.0>}
    -2> dbg:p(all,call).
    -{ok,[{matched,nonode@nohost,25}]}
    -3> dbg:tpl(toy,store,dbg:fun2ms(fun([A,_]) when is_atom(A) -> true end)).
    -{ok,[{matched,nonode@nohost,1},{saved,1}]}

    We use dbg:tpl/3 to ensure to catch local calls (assume that the module has +on call tracing and try to see calls to the module with an atom as the key:

    1> dbg:tracer().
    +{ok,<0.88.0>}
    +2> dbg:p(all,call).
    +{ok,[{matched,nonode@nohost,25}]}
    +3> dbg:tpl(toy,store,dbg:fun2ms(fun([A,_]) when is_atom(A) -> true end)).
    +{ok,[{matched,nonode@nohost,1},{saved,1}]}

    We use dbg:tpl/3 to ensure to catch local calls (assume that the module has grown since the smaller version and we are unsure if this inserting of atoms is not done locally). When in doubt, always use local call tracing.

    Assume that nothing happens when tracing in this way. The function is never called with these parameters. We conclude that someone else (some other module) @@ -397,11 +397,11 @@

    calling function. The calling function can be retrieved using the match specification function caller. To get it into the trace message, the match specification function message must be used. The filter call looks like this -(looking for calls to ets:insert/2):

    4> dbg:tpl(ets,insert,dbg:fun2ms(fun([toy_table,{A,_}]) when is_atom(A) ->
    -                                    message(caller())
    -                                  end)).
    -{ok,[{matched,nonode@nohost,1},{saved,2}]}

    The caller is now displayed in the "additional message" part of the trace -output, and the following is displayed after a while:

    (<0.86.0>) call ets:insert(toy_table,{garbage,can}) ({evil_mod,evil_fun,2})

    You have realized that function evil_fun of the evil_mod module, with arity +(looking for calls to ets:insert/2):

    4> dbg:tpl(ets,insert,dbg:fun2ms(fun([toy_table,{A,_}]) when is_atom(A) ->
    +                                    message(caller())
    +                                  end)).
    +{ok,[{matched,nonode@nohost,1},{saved,2}]}

    The caller is now displayed in the "additional message" part of the trace +output, and the following is displayed after a while:

    (<0.86.0>) call ets:insert(toy_table,{garbage,can}) ({evil_mod,evil_fun,2})

    You have realized that function evil_fun of the evil_mod module, with arity 2, is causing all this trouble.

    This example illustrates the most used calls in match specifications for dbg. The other, more esoteric, calls are listed and explained in Match specifications in Erlang in ERTS User's Guide, @@ -436,26 +436,26 @@

    [{{'$1','$2'},[{is_atom,'$1'}],['$2']}].

  • Variables that are not included in the head are imported from the environment and made into match specification const expressions. Example from the shell:

    1> X = 25.
     25
    -2> ets:fun2ms(fun({A,B}) when A > X -> B end).
    -[{{'$1','$2'},[{'>','$1',{const,25}}],['$2']}]
  • Matching with = cannot be used in the body. It can only be used on the -top-level in the head of the fun. Example from the shell again:

    1> ets:fun2ms(fun({A,[B|C]} = D) when A > B -> D end).
    -[{{'$1',['$2'|'$3']},[{'>','$1','$2'}],['$_']}]
    -2> ets:fun2ms(fun({A,[B|C]=D}) when A > B -> D end).
    -Error: fun with head matching ('=' in head) cannot be translated into
    +2> ets:fun2ms(fun({A,B}) when A > X -> B end).
    +[{{'$1','$2'},[{'>','$1',{const,25}}],['$2']}]
  • Matching with = cannot be used in the body. It can only be used on the +top-level in the head of the fun. Example from the shell again:

    1> ets:fun2ms(fun({A,[B|C]} = D) when A > B -> D end).
    +[{{'$1',['$2'|'$3']},[{'>','$1','$2'}],['$_']}]
    +2> ets:fun2ms(fun({A,[B|C]=D}) when A > B -> D end).
    +Error: fun with head matching ('=' in head) cannot be translated into
     match_spec
    -{error,transform_error}
    -3> ets:fun2ms(fun({A,[B|C]}) when A > B -> D = [B|C], D end).
    -Error: fun with body matching ('=' in body) is illegal as match_spec
    -{error,transform_error}

    All variables are bound in the head of a match specification, so the +{error,transform_error} +3> ets:fun2ms(fun({A,[B|C]}) when A > B -> D = [B|C], D end). +Error: fun with body matching ('=' in body) is illegal as match_spec +{error,transform_error}

  • All variables are bound in the head of a match specification, so the translator cannot allow multiple bindings. The special case when matching is done on the top-level makes the variable bind to '$_' in the resulting match specification. It is to allow a more natural access to the whole matched -object. Pseudo function object() can be used instead, see below.

    The following expressions are translated equally:

    ets:fun2ms(fun({a,_} = A) -> A end).
    -ets:fun2ms(fun({a,_}) -> object() end).
  • The special match specification variables '$_' and '$*' can be accessed +object. Pseudo function object() can be used instead, see below.

    The following expressions are translated equally:

    ets:fun2ms(fun({a,_} = A) -> A end).
    +ets:fun2ms(fun({a,_}) -> object() end).
  • The special match specification variables '$_' and '$*' can be accessed through the pseudo functions object() (for '$_') and bindings() (for '$*'). As an example, one can translate the following ets:match_object/2 -call to a ets:select/2 call:

    ets:match_object(Table, {'$1',test,'$2'}).

    This is the same as:

    ets:select(Table, ets:fun2ms(fun({A,test,B}) -> object() end)).

    In this simple case, the former expression is probably preferable in terms of -readability.

    The ets:select/2 call conceptually looks like this in the resulting code:

    ets:select(Table, [{{'$1',test,'$2'},[],['$_']}]).

    Matching on the top-level of the fun head can be a more natural way to access +call to a ets:select/2 call:

    ets:match_object(Table, {'$1',test,'$2'}).

    This is the same as:

    ets:select(Table, ets:fun2ms(fun({A,test,B}) -> object() end)).

    In this simple case, the former expression is probably preferable in terms of +readability.

    The ets:select/2 call conceptually looks like this in the resulting code:

    ets:select(Table, [{{'$1',test,'$2'},[],['$_']}]).

    Matching on the top-level of the fun head can be a more natural way to access '$_', see above.

  • Term constructions/literals are translated as much as is needed to get them into valid match specification. This way tuples are made into match specification tuple constructions (a one element tuple containing the tuple) diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/notes.html b/prs/9045/lib/stdlib-6.1.2/doc/html/notes.html index c5727ef5d394..5f22bc4b766d 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/notes.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/notes.html @@ -208,8 +208,8 @@

    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.
      @@ -242,12 +242,12 @@ 

      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

  • diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/orddict.html b/prs/9045/lib/stdlib-6.1.2/doc/html/orddict.html index caadc27c82f7..7f9d16bec15a 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/orddict.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/orddict.html @@ -148,13 +148,13 @@

    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.

    @@ -543,16 +543,16 @@

    append(Key, Value, Orddict1)

    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]
    @@ -589,12 +589,12 @@

    append_list(Key, ValList, Orddict1)

    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]}]
    @@ -623,10 +623,10 @@

    erase(Key, Orddict1)

    -

    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}]
    @@ -656,11 +656,11 @@

    fetch(Key, Orddict)

    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,[])
    @@ -689,10 +689,10 @@

    fetch_keys(Orddict)

    -

    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]
    @@ -725,10 +725,10 @@

    filter(Pred, Orddict1)

    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}]
    @@ -758,11 +758,11 @@

    find(Key, Orddict)

    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
    @@ -800,10 +800,10 @@

    fold(Fun, Acc0, Orddict)

    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}]
    @@ -922,10 +922,10 @@

    map(Fun, Orddict1)

    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}]
    @@ -961,15 +961,15 @@

    merge(Fun, Orddict1, Orddict2)

    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}]
    @@ -1055,12 +1055,12 @@

    store(Key, Value, Orddict1)

    Stores a Key-Value pair in a dictionary. If the Key already exists in -Orddict1, the associated value is replaced by Value.

    Example:

    1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
    -[{a,1},{b,2}]
    -2> orddict:store(a, 99, OrdDict1).
    -[{a,99},{b,2}]
    -3> orddict:store(c, 100, OrdDict1).
    -[{a,1},{b,2},{c,100}]
    +Orddict1, the associated value is replaced by Value.

    Example:

    1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
    +[{a,1},{b,2}]
    +2> orddict:store(a, 99, OrdDict1).
    +[{a,99},{b,2}]
    +3> orddict:store(c, 100, OrdDict1).
    +[{a,1},{b,2},{c,100}]
    @@ -1096,11 +1096,11 @@

    take(Key, Orddict)

    This function returns value from dictionary and new dictionary without this -value. Returns error if the key is not present in the dictionary.

    Example:

    1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
    -[{a,1},{b,2}]
    -2> orddict:take(a, OrdDict1).
    -{1,[{b,2}]}
    -3> orddict:take(missing, OrdDict1).
    +value. Returns error if the key is not present in the dictionary.

    Example:

    1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
    +[{a,1},{b,2}]
    +2> orddict:take(a, OrdDict1).
    +{1,[{b,2}]}
    +3> orddict:take(missing, OrdDict1).
     error
    @@ -1162,10 +1162,10 @@

    update(Key, Fun, Orddict1)

    Updates a value in a dictionary by calling Fun on the value to get a new -value. An exception is generated if Key is not present in the dictionary.

    Example:

    1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
    -[{a,1},{b,2}]
    -2> orddict:update(a, fun (V) -> V + 100 end, OrdDict1).
    -[{a,101},{b,2}]
    +value. An exception is generated if Key is not present in the dictionary.

    Example:

    1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
    +[{a,1},{b,2}]
    +2> orddict:update(a, fun (V) -> V + 100 end, OrdDict1).
    +[{a,101},{b,2}]
    @@ -1200,14 +1200,14 @@

    update(Key, Fun, Initial, Orddict1)

    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 follows:

    append(Key, Val, D) ->
    -    update(Key, fun (Old) -> Old ++ [Val] end, [Val], D).

    Example 1:

    1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
    -[{a,1},{b,2}]
    -2> orddict:update(c, fun (V) -> V + 100 end, 99, OrdDict1).
    -[{a,1},{b,2},{c,99}]

    Example 2:

    1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
    -[{a,1},{b,2}]
    -2> orddict:update(a, fun (V) -> V + 100 end, 99, OrdDict1).
    -[{a,101},{b,2}]
    +first value.

    For example, append/3 can be defined as follows:

    append(Key, Val, D) ->
    +    update(Key, fun (Old) -> Old ++ [Val] end, [Val], D).

    Example 1:

    1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
    +[{a,1},{b,2}]
    +2> orddict:update(c, fun (V) -> V + 100 end, 99, OrdDict1).
    +[{a,1},{b,2},{c,99}]

    Example 2:

    1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
    +[{a,1},{b,2}]
    +2> orddict:update(a, fun (V) -> V + 100 end, 99, OrdDict1).
    +[{a,101},{b,2}]
    @@ -1241,8 +1241,8 @@

    update_counter(Key, Increment, Orddict1)Adds Increment to the value associated with Key and store 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).

    diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/peer.html b/prs/9045/lib/stdlib-6.1.2/doc/html/peer.html index 580bfa8e17e2..df03ebc43142 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/peer.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/peer.html @@ -167,127 +167,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).
    @@ -739,11 +739,11 @@

    start_options()

    connection type. Default is true.

  • args - Extra command line arguments to append to the "erl" command. Arguments are passed as is, no escaping or quoting is needed or accepted.

  • post_process_args - Allows the user to change the arguments passed to exec before the peer is started. This can for example be useful when the -exec program wants the arguments to "erl" as a single argument. Example:

    peer:start(#{ name => peer:random_name(),
    -  exec => {os:find_executable("bash"),["-c","erl"]},
    +exec program wants the arguments to "erl" as a single argument. Example:

    peer:start(#{ name => peer:random_name(),
    +  exec => {os:find_executable("bash"),["-c","erl"]},
       post_process_args =>
    -     fun(["-c"|Args]) -> ["-c", lists:flatten(lists:join($\s, Args))] end
    -  }).
  • env - List of environment variables with their values. This list is + fun(["-c"|Args]) -> ["-c", lists:flatten(lists:join($\s, Args))] end + }).

  • env - List of environment variables with their values. This list is applied to a locally started executable. If you need to change the environment of the remote peer, adjust args to contain -env ENV_KEY ENV_VALUE.

  • wait_boot - Specifies the start/start_link timeout. See wait_boot datatype.

  • shutdown - Specifies the peer node stopping behaviour. See diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/proc_lib.html b/prs/9045/lib/stdlib-6.1.2/doc/html/proc_lib.html index 17390ec6da0a..557bfc89f40e 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/proc_lib.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/proc_lib.html @@ -1001,21 +1001,21 @@

    init_ack(Parent, Ret)

    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().
     
     ...
    @@ -1088,21 +1088,21 @@

    init_fail(Parent, Return, Exception)

    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().
     
     ...
    diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/proplists.html b/prs/9045/lib/stdlib-6.1.2/doc/html/proplists.html index c1042840684a..708774b6873d 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/proplists.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/proplists.html @@ -538,7 +538,7 @@

    append_values(Key, ListIn)

    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]
    @@ -632,10 +632,10 @@

    expand(Expansions, ListIn)

    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.

    @@ -1040,7 +1040,7 @@

    split(List, Keys)

    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]}
    @@ -1163,7 +1163,7 @@

    to_map(List)

    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}
    diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/qlc.html b/prs/9045/lib/stdlib-6.1.2/doc/html/qlc.html index 08f64830f8c5..914dc3b45263 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/qlc.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/qlc.html @@ -291,24 +291,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 @@ -316,11 +316,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 @@ -334,7 +334,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 @@ -356,62 +356,62 @@

    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]).
    -
    -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
    +-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
                   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) ->
    -    [].
    +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_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 @@ -447,49 +447,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}]),
    -F2 = fun(I) ->
    -qlc:q([V || {K,V} <- ets:table(E2), K == I])
    +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}]),
    +F2 = fun(I) ->
    +qlc:q([V || {K,V} <- ets:table(E2), K == I])
     end,
    -Q2 = F2({2,2}),
    -io:format("~s~n", [qlc:info(Q2)]).
    -ets:table(#Ref<0.3098908599.2283929601.256125>,
    -          [{traverse,
    -            {select,
    -             [{{'$1', '$2'}, [{'==', '$1', {const, {2, 2}}}], ['$2']}]}}])
    -3> lists:sort(qlc:e(Q2)).
    -[a,b,c]

    Looking up only {2,2} would not return b and c.

    If the table uses ==/2 when comparing keys for equality, the qlc module +Q2 = F2({2,2}), +io:format("~s~n", [qlc:info(Q2)]). +ets:table(#Ref<0.3098908599.2283929601.256125>, + [{traverse, + {select, + [{{'$1', '$2'}, [{'==', '$1', {const, {2, 2}}}], ['$2']}]}}]) +3> lists:sort(qlc:e(Q2)). +[a,b,c]

    Looking up only {2,2} would not return b and c.

    If the table uses ==/2 when comparing keys for equality, the qlc module looks up the constant regardless of which operator is used in the QLC. However, -==/2 is to be preferred:

    4> E3 = ets:new(t, [ordered_set]), % uses ==/2 for key equality
    -true = ets:insert(E3, [{{2,2.0},b}]),
    -F3 = fun(I) ->
    -qlc:q([V || {K,V} <- ets:table(E3), K == I])
    +==/2 is to be preferred:

    4> E3 = ets:new(t, [ordered_set]), % uses ==/2 for key equality
    +true = ets:insert(E3, [{{2,2.0},b}]),
    +F3 = fun(I) ->
    +qlc:q([V || {K,V} <- ets:table(E3), K == I])
     end,
    -Q3 = F3({2,2}),
    -io:format("~s~n", [qlc:info(Q3)]).
    -ets:match_spec_run(ets:lookup(#Ref<0.3098908599.2283929601.256211>,
    -                              {2, 2}),
    -                   ets:match_spec_compile([{{'$1', '$2'}, [], ['$2']}]))
    -5> qlc:e(Q3).
    -[b]

    Lookup join is handled analogously to lookup of constants in a table: if the +Q3 = F3({2,2}), +io:format("~s~n", [qlc:info(Q3)]). +ets:match_spec_run(ets:lookup(#Ref<0.3098908599.2283929601.256211>, + {2, 2}), + ets:match_spec_compile([{{'$1', '$2'}, [], ['$2']}])) +5> qlc:e(Q3). +[b]

    Lookup join is handled analogously to lookup of constants in a table: if the join operator is ==/2, and the table where constants are to be looked up uses =:=/2 when testing keys for equality, then the qlc module does not consider lookup join for that table.

    @@ -1703,15 +1703,15 @@

    cursor(QH, Options)

    and (eventually) delete_cursor/1. Calls erlang:spawn_opt/2 to spawn and link to a process that evaluates the query handle. The value of option spawn_options is used as last argument when calling -spawn_opt/2. Defaults to [link].

    Example:

    1> QH = qlc:q([{X,Y} || X <- [a,b], Y <- [1,2]]),
    -QC = qlc:cursor(QH),
    -qlc:next_answers(QC, 1).
    -[{a,1}]
    -2> qlc:next_answers(QC, 1).
    -[{a,2}]
    -3> qlc:next_answers(QC, all_remaining).
    -[{b,1},{b,2}]
    -4> qlc:delete_cursor(QC).
    +spawn_opt/2. Defaults to [link].

    Example:

    1> QH = qlc:q([{X,Y} || X <- [a,b], Y <- [1,2]]),
    +QC = qlc:cursor(QH),
    +qlc:next_answers(QC, 1).
    +[{a,1}]
    +2> qlc:next_answers(QC, 1).
    +[{a,2}]
    +3> qlc:next_answers(QC, all_remaining).
    +[{b,1},{b,2}]
    +4> qlc:delete_cursor(QC).
     ok

    @@ -1891,9 +1891,9 @@

    eval(QH, Options)

    Evaluates a query handle in the calling process and collects all answers in a -list.

    Example:

    1> QH = qlc:q([{X,Y} || X <- [a,b], Y <- [1,2]]),
    -qlc:eval(QH).
    -[{a,1},{a,2},{b,1},{b,2}]
    +list.

    Example:

    1> QH = qlc:q([{X,Y} || X <- [a,b], Y <- [1,2]]),
    +qlc:eval(QH).
    +[{a,1},{a,2},{b,1},{b,2}]
    @@ -1979,8 +1979,8 @@

    fold(Function, Acc0, QH, Options)

    Calls Function on successive answers to the query handle together with an extra argument AccIn.

    The query handle and the function are evaluated in the calling process. Function must return a new accumulator, which is passed to -the next call. Acc0 is returned if there are no answers to the query handle.

    Example:

    1> QH = [1,2,3,4,5,6],
    -qlc:fold(fun(X, Sum) -> X + Sum end, 0, QH).
    +the next call. Acc0 is returned if there are no answers to the query handle.

    Example:

    1> QH = [1,2,3,4,5,6],
    +qlc:fold(fun(X, Sum) -> X + Sum end, 0, QH).
     21
    @@ -2097,59 +2097,59 @@

    info(QH, Options)

    returned.
  • The default is to show all parts of objects and match specifications, but if option {depth, Depth} is specified, parts of terms below a certain depth are replaced by '...'.
  • Examples:

    In the following example two simple QLCs are inserted only to hold option -{unique, true}:

    1> QH = qlc:q([{X,Y} || X <- [x,y], Y <- [a,b]]),
    -io:format("~s~n", [qlc:info(QH, unique_all)]).
    +{unique, true}:

    1> QH = qlc:q([{X,Y} || X <- [x,y], Y <- [a,b]]),
    +io:format("~s~n", [qlc:info(QH, unique_all)]).
     begin
         V1 =
    -        qlc:q([
    +        qlc:q([
                    SQV ||
    -                   SQV <- [x, y]
    -              ],
    -              [{unique, true}]),
    +                   SQV <- [x, y]
    +              ],
    +              [{unique, true}]),
         V2 =
    -        qlc:q([
    +        qlc:q([
                    SQV ||
    -                   SQV <- [a, b]
    -              ],
    -              [{unique, true}]),
    -    qlc:q([
    -           {X,Y} ||
    +                   SQV <- [a, b]
    +              ],
    +              [{unique, true}]),
    +    qlc:q([
    +           {X,Y} ||
                    X <- V1,
                    Y <- V2
    -          ],
    -          [{unique, true}])
    +          ],
    +          [{unique, true}])
     end

    In the following example QLC V2 has been inserted to show the joined generators and the join method chosen. A convention is used for lookup join: the first generator (G2) is the one traversed, the second (G1) is the table -where constants are looked up.

    1> E1 = ets:new(e1, []),
    -E2 = ets:new(e2, []),
    -true = ets:insert(E1, [{1,a},{2,b}]),
    -true = ets:insert(E2, [{a,1},{b,2}]),
    -Q = qlc:q([{X,Z,W} ||
    -{X, Z} <- ets:table(E1),
    -{W, Y} <- ets:table(E2),
    -X =:= Y]),
    -io:format("~s~n", [qlc:info(Q)]).
    +where constants are looked up.

    1> E1 = ets:new(e1, []),
    +E2 = ets:new(e2, []),
    +true = ets:insert(E1, [{1,a},{2,b}]),
    +true = ets:insert(E2, [{a,1},{b,2}]),
    +Q = qlc:q([{X,Z,W} ||
    +{X, Z} <- ets:table(E1),
    +{W, Y} <- ets:table(E2),
    +X =:= Y]),
    +io:format("~s~n", [qlc:info(Q)]).
     begin
         V1 =
    -        qlc:q([
    +        qlc:q([
                    P0 ||
    -                   P0 = {W, Y} <-
    -                       ets:table(#Ref<0.3098908599.2283929601.256549>)
    -              ]),
    +                   P0 = {W, Y} <-
    +                       ets:table(#Ref<0.3098908599.2283929601.256549>)
    +              ]),
         V2 =
    -        qlc:q([
    -               [G1 | G2] ||
    +        qlc:q([
    +               [G1 | G2] ||
                        G2 <- V1,
                        G1 <-
    -                       ets:table(#Ref<0.3098908599.2283929601.256548>),
    -                   element(2, G1) =:= element(1, G2)
    -              ],
    -              [{join, lookup}]),
    -    qlc:q([
    -           {X, Z, W} ||
    -               [{X, Z} | {W, Y}] <- V2
    -          ])
    +                       ets:table(#Ref<0.3098908599.2283929601.256548>),
    +                   element(2, G1) =:= element(1, G2)
    +              ],
    +              [{join, lookup}]),
    +    qlc:q([
    +           {X, Z, W} ||
    +               [{X, Z} | {W, Y}] <- V2
    +          ])
     end
    @@ -2358,13 +2358,13 @@

    q(QLC, Options)

    Returns a query handle for a QLC. The QLC must be the first argument to this function, otherwise it is evaluated as an ordinary list comprehension. It is -also necessary to add the following line to the source code:

    -include_lib("stdlib/include/qlc.hrl").

    This causes a parse transform to substitute a fun for the QLC. The (compiled) +also necessary to add the following line to the source code:

    -include_lib("stdlib/include/qlc.hrl").

    This causes a parse transform to substitute a fun for the QLC. The (compiled) fun is called when the query handle is evaluated.

    When calling qlc:q/1,2 from the Erlang shell, the parse transform is automatically called. When this occurs, the fun substituted for the QLC is not compiled but is evaluated by erl_eval. This is also true when expressions are evaluated by file:eval/1,2 or in the debugger.

    To be explicit, this does not work:

    ...
    -A = [X || {X} <- [{1},{2}]],
    -QH = qlc:q(A),
    +A = [X || {X} <- [{1},{2}]],
    +QH = qlc:q(A),
     ...

    Variable A is bound to the evaluated value of the list comprehension ([1,2]). The compiler complains with an error message ("argument is not a query list comprehension"); the shell process stops with a badarg reason.

    Options:

    • Option {cache, ets} can be used to cache the answers to a QLC. The answers @@ -2392,40 +2392,40 @@

      q(QLC, Options)

      results of looking up constants, running match specifications, and joining handles.

      Example:

      In the following example the cached results of the merge join are traversed for each value of A. Notice that without option cache the join would have been -carried out three times, once for each value of A.

      1> Q = qlc:q([{A,X,Z,W} ||
      -A <- [a,b,c],
      -{X,Z} <- [{a,1},{b,4},{c,6}],
      -{W,Y} <- [{2,a},{3,b},{4,c}],
      -X =:= Y],
      -{cache, list}),
      -io:format("~s~n", [qlc:info(Q)]).
      +carried out three times, once for each value of A.

      1> Q = qlc:q([{A,X,Z,W} ||
      +A <- [a,b,c],
      +{X,Z} <- [{a,1},{b,4},{c,6}],
      +{W,Y} <- [{2,a},{3,b},{4,c}],
      +X =:= Y],
      +{cache, list}),
      +io:format("~s~n", [qlc:info(Q)]).
       begin
           V1 =
      -        qlc:q([
      +        qlc:q([
                      P0 ||
      -                   P0 = {X, Z} <-
      -                       qlc:keysort(1, [{a, 1}, {b, 4}, {c, 6}], [])
      -              ]),
      +                   P0 = {X, Z} <-
      +                       qlc:keysort(1, [{a, 1}, {b, 4}, {c, 6}], [])
      +              ]),
           V2 =
      -        qlc:q([
      +        qlc:q([
                      P0 ||
      -                   P0 = {W, Y} <-
      -                       qlc:keysort(2, [{2, a}, {3, b}, {4, c}], [])
      -              ]),
      +                   P0 = {W, Y} <-
      +                       qlc:keysort(2, [{2, a}, {3, b}, {4, c}], [])
      +              ]),
           V3 =
      -        qlc:q([
      -               [G1 | G2] ||
      +        qlc:q([
      +               [G1 | G2] ||
                          G1 <- V1,
                          G2 <- V2,
      -                   element(1, G1) == element(2, G2)
      -              ],
      -              [{join, merge}, {cache, list}]),
      -    qlc:q([
      -           {A, X, Z, W} ||
      -               A <- [a, b, c],
      -               [{X, Z} | {W, Y}] <- V3,
      +                   element(1, G1) == element(2, G2)
      +              ],
      +              [{join, merge}, {cache, list}]),
      +    qlc:q([
      +           {A, X, Z, W} ||
      +               A <- [a, b, c],
      +               [{X, Z} | {W, Y}] <- V3,
                      X =:= Y
      -          ])
      +          ])
       end

      sort/1,2 and keysort/2,3 can also be used for caching answers and for removing duplicates. When sorting answers are cached in a list, possibly stored on a temporary file, and no ETS tables are used.

      Sometimes (see table/2) traversal of tables can be done by looking up key @@ -2437,32 +2437,32 @@

      q(QLC, Options)

      limit on the number of keys to look up.

      Example:

      In the following example, using the gb_table module from section Implementing a QLC Table, there are six keys to look up: {1,a}, {1,b}, {1,c}, {2,a}, {2,b}, and {2,c}. The reason -is that the two elements of key {X, Y} are compared separately.

      1> T = gb_trees:empty(),
      -QH = qlc:q([X || {{X,Y},_} <- gb_table:table(T),
      -((X == 1) or (X == 2)) andalso
      -((Y == a) or (Y == b) or (Y == c))]),
      -io:format("~s~n", [qlc:info(QH)]).
      -ets:match_spec_run(
      -       lists:flatmap(fun(K) ->
      +is that the two elements of key {X, Y} are compared separately.

      1> T = gb_trees:empty(),
      +QH = qlc:q([X || {{X,Y},_} <- gb_table:table(T),
      +((X == 1) or (X == 2)) andalso
      +((Y == a) or (Y == b) or (Y == c))]),
      +io:format("~s~n", [qlc:info(QH)]).
      +ets:match_spec_run(
      +       lists:flatmap(fun(K) ->
                                   case
      -                                gb_trees:lookup(K,
      -                                                gb_trees:from_orddict([]))
      +                                gb_trees:lookup(K,
      +                                                gb_trees:from_orddict([]))
                                   of
      -                                {value, V} ->
      -                                    [{K, V}];
      +                                {value, V} ->
      +                                    [{K, V}];
                                       none ->
      -                                    []
      +                                    []
                                   end
                            end,
      -                     [{1, a},
      -                      {1, b},
      -                      {1, c},
      -                      {2, a},
      -                      {2, b},
      -                      {2, c}]),
      -       ets:match_spec_compile([{{{'$1', '$2'}, '_'},
      -                                [],
      -                                ['$1']}]))

      Options:

      • Option {lookup, true} can be used to ensure that the qlc module looks up + [{1, a}, + {1, b}, + {1, c}, + {2, a}, + {2, b}, + {2, c}]), + ets:match_spec_compile([{{{'$1', '$2'}, '_'}, + [], + ['$1']}]))

      Options:

      • Option {lookup, true} can be used to ensure that the qlc module looks up constants in some QLC table. If there are more than one QLC table among the list expressions of the generators, constants must be looked up in at least one of the tables. The evaluation of the query fails if there are no constants @@ -2659,11 +2659,11 @@

        string_to_handle(QueryString, Options, Bind

        A string version of q/1,2. When the query handle is evaluated, the fun created by the parse transform is interpreted by erl_eval. The query -string is to be one single QLC terminated by a period.

        Example:

        1> L = [1,2,3],
        -Bs = erl_eval:add_binding('L', L, erl_eval:new_bindings()),
        -QH = qlc:string_to_handle("[X+1 || X <- L].", [], Bs),
        -qlc:eval(QH).
        -[2,3,4]

        This function is probably mainly useful when called from outside of Erlang, for +string is to be one single QLC terminated by a period.

        Example:

        1> L = [1,2,3],
        +Bs = erl_eval:add_binding('L', L, erl_eval:new_bindings()),
        +QH = qlc:string_to_handle("[X+1 || X <- L].", [], Bs),
        +qlc:eval(QH).
        +[2,3,4]

        This function is probably mainly useful when called from outside of Erlang, for example from a driver written in C.

        Note

        Query handles created this way may have worse performance than when created directly via q/1,2.

        diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/queue.html b/prs/9045/lib/stdlib-6.1.2/doc/html/queue.html index 0341722b4bbf..e90f66e06019 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/queue.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/queue.html @@ -729,10 +729,10 @@

        all(Pred, Q)

        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).
         true
        @@ -764,10 +764,10 @@

        any(Pred, Q)

        Returns true if Pred(Item) returns true for at least one item Item in -Q, otherwise false.

        Example:

        1> Queue = queue:from_list([1,2,3,4,5]).
        -2> queue:any(fun (E) -> E > 10 end, Queue).
        +Q, otherwise false.

        Example:

        1> Queue = queue:from_list([1,2,3,4,5]).
        +2> queue:any(fun (E) -> E > 10 end, Queue).
         false
        -3> queue:any(fun (E) -> E > 3 end, Queue).
        +3> queue:any(fun (E) -> E > 3 end, Queue).
         true
        @@ -799,9 +799,9 @@

        delete(Item, Q1)

        Returns a copy of Q1 where the first item matching Item is deleted, if there -is such an item.

        Example:

        1> Queue = queue:from_list([1,2,3,4,5]).
        -2> Queue1 = queue:delete(3, Queue).
        -3> queue:member(3, Queue1).
        +is such an item.

        Example:

        1> Queue = queue:from_list([1,2,3,4,5]).
        +2> Queue1 = queue:delete(3, Queue).
        +3> queue:member(3, Queue1).
         false
        @@ -833,10 +833,10 @@

        delete_r(Item, Q1)

        Returns a copy of Q1 where the last item matching Item is deleted, if there -is such an item.

        Example:

        1> Queue = queue:from_list([1,2,3,4,3,5]).
        -2> Queue1 = queue:delete_r(3, Queue).
        -3> queue:to_list(Queue1).
        -[1,2,3,4,5]
        +is such an item.

        Example:

        1> Queue = queue:from_list([1,2,3,4,3,5]).
        +2> Queue1 = queue:delete_r(3, Queue).
        +3> queue:to_list(Queue1).
        +[1,2,3,4,5]
        @@ -872,10 +872,10 @@

        delete_with(Pred, Q1)

        Returns a copy of Q1 where the first item for which Pred returns true is -deleted, if there is such an item.

        Example:

        1> Queue = queue:from_list([100,1,2,3,4,5]).
        -2> Queue1 = queue:delete_with(fun (E) -> E > 0, Queue).
        -3> queue:to_list(Queue1).
        -[1,2,3,4,5]
        +deleted, if there is such an item.

        Example:

        1> Queue = queue:from_list([100,1,2,3,4,5]).
        +2> Queue1 = queue:delete_with(fun (E) -> E > 0, Queue).
        +3> queue:to_list(Queue1).
        +[1,2,3,4,5]
        @@ -911,10 +911,10 @@

        delete_with_r(Pred, Q1)

        Returns a copy of Q1 where the last item for which Pred returns true is -deleted, if there is such an item.

        Example:

        1> Queue = queue:from_list([1,2,3,4,5,100]).
        -2> Queue1 = queue:delete_with(fun (E) -> E > 10, Queue).
        -3> queue:to_list(Queue1).
        -[1,2,3,4,5]
        +deleted, if there is such an item.

        Example:

        1> Queue = queue:from_list([1,2,3,4,5,100]).
        +2> Queue1 = queue:delete_with(fun (E) -> E > 10, Queue).
        +3> queue:to_list(Queue1).
        +[1,2,3,4,5]
        @@ -945,19 +945,19 @@

        filter(Fun, Q1)

        Returns a queue Q2 that is the result of calling Fun(Item) on all items in Q1.

        If Fun(Item) returns true, Item is copied to the result queue. If it returns false, Item is not copied. If it returns a list, the list elements -are inserted instead of Item in the result queue.

        Example 1:

        1> Queue = queue:from_list([1,2,3,4,5]).
        -{[5,4,3],[1,2]}
        -2> Queue1 = queue:filter(fun (E) -> E > 2 end, Queue).
        -{[5],[3,4]}
        -3> queue:to_list(Queue1).
        -[3,4,5]

        So, Fun(Item) returning [Item] is thereby semantically equivalent to +are inserted instead of Item in the result queue.

        Example 1:

        1> Queue = queue:from_list([1,2,3,4,5]).
        +{[5,4,3],[1,2]}
        +2> Queue1 = queue:filter(fun (E) -> E > 2 end, Queue).
        +{[5],[3,4]}
        +3> queue:to_list(Queue1).
        +[3,4,5]

        So, Fun(Item) returning [Item] is thereby semantically equivalent to returning true, just as returning [] is semantically equivalent to returning -false. But returning a list builds more garbage than returning an atom.

        Example 2:

        1> Queue = queue:from_list([1,2,3,4,5]).
        -{[5,4,3],[1,2]}
        -2> Queue1 = queue:filter(fun (E) -> [E, E+1] end, Queue).
        -{[6,5,5,4,4,3],[1,2,2,3]}
        -3> queue:to_list(Queue1).
        -[1,2,2,3,3,4,4,5,5,6]
        +false. But returning a list builds more garbage than returning an atom.

        Example 2:

        1> Queue = queue:from_list([1,2,3,4,5]).
        +{[5,4,3],[1,2]}
        +2> Queue1 = queue:filter(fun (E) -> [E, E+1] end, Queue).
        +{[6,5,5,4,4,3],[1,2,2,3]}
        +3> queue:to_list(Queue1).
        +[1,2,2,3,3,4,4,5,5,6]
        @@ -996,15 +996,15 @@

        filtermap(Fun, Q1)

        Returns a queue Q2 that is the result of calling Fun(Item) on all items in Q1.

        If Fun(Item) returns true, Item is copied to the result queue. If it returns false, Item is not copied. If it returns {true, NewItem}, the -queue element at this position is replaced with NewItem in the result queue.

        Example 1:

        1> Queue = queue:from_list([1,2,3,4,5]).
        -{[5,4,3],[1,2]}
        -2> Queue1 = queue:filtermap(fun (E) -> E > 2 end, Queue).
        -{[5],[3,4]}
        -3> queue:to_list(Queue1).
        -[3,4,5]
        -4> Queue1 = queue:filtermap(fun (E) -> {true, E+100} end, Queue).
        -{"ihg","ef"}
        -5> queue:to_list(Queue1).
        +queue element at this position is replaced with NewItem in the result queue.

        Example 1:

        1> Queue = queue:from_list([1,2,3,4,5]).
        +{[5,4,3],[1,2]}
        +2> Queue1 = queue:filtermap(fun (E) -> E > 2 end, Queue).
        +{[5],[3,4]}
        +3> queue:to_list(Queue1).
        +[3,4,5]
        +4> Queue1 = queue:filtermap(fun (E) -> {true, E+100} end, Queue).
        +{"ihg","ef"}
        +5> queue:to_list(Queue1).
         "efghi
        @@ -1045,9 +1045,9 @@

        fold(Fun, Acc0, Q)

        AccIn == Acc0. The queue is traversed in queue order, that is, from front to rear. Fun/2 must return a new accumulator, which is passed to the next call. The function returns the final value of the accumulator. Acc0 is returned if -the queue is empty.

        Example:

        1> queue:fold(fun(X, Sum) -> X + Sum end, 0, queue:from_list([1,2,3,4,5])).
        +the queue is empty.

        Example:

        1> queue:fold(fun(X, Sum) -> X + Sum end, 0, queue:from_list([1,2,3,4,5])).
         15
        -2> queue:fold(fun(X, Prod) -> X * Prod end, 1, queue:from_list([1,2,3,4,5])).
        +2> queue:fold(fun(X, Prod) -> X * Prod end, 1, queue:from_list([1,2,3,4,5])).
         120
        @@ -1105,12 +1105,12 @@

        in(Item, Q1)

        -

        Inserts Item at the rear of queue Q1. Returns the resulting queue Q2.

        Example:

        1> Queue = queue:from_list([1,2,3,4,5]).
        -{[5,4,3],[1,2]}
        -2> Queue1 = queue:in(100, Queue).
        -{[100,5,4,3],[1,2]}
        -3> queue:to_list(Queue1).
        -[1,2,3,4,5,100]
        +

        Inserts Item at the rear of queue Q1. Returns the resulting queue Q2.

        Example:

        1> Queue = queue:from_list([1,2,3,4,5]).
        +{[5,4,3],[1,2]}
        +2> Queue1 = queue:in(100, Queue).
        +{[100,5,4,3],[1,2]}
        +3> queue:to_list(Queue1).
        +[1,2,3,4,5,100]
        @@ -1138,12 +1138,12 @@

        in_r(Item, Q1)

        -

        Inserts Item at the front of queue Q1. Returns the resulting queue Q2.

        Example:

        1> Queue = queue:from_list([1,2,3,4,5]).
        -{[5,4,3],[1,2]}
        -2> Queue1 = queue:in_r(100, Queue).
        -{[5,4,3],[100,1,2]}
        -3> queue:to_list(Queue1).
        -[100,1,2,3,4,5]
        +

        Inserts Item at the front of queue Q1. Returns the resulting queue Q2.

        Example:

        1> Queue = queue:from_list([1,2,3,4,5]).
        +{[5,4,3],[1,2]}
        +2> Queue1 = queue:in_r(100, Queue).
        +{[5,4,3],[100,1,2]}
        +3> queue:to_list(Queue1).
        +[100,1,2,3,4,5]
        @@ -1231,12 +1231,12 @@

        join(Q1, Q2)

        Returns a queue Q3 that is the result of joining Q1 and Q2 with Q1 in -front of Q2.

        Example:

        1> Queue1 = queue:from_list([1,3]).
        -{[3],[1]}
        -2> Queue2 = queue:from_list([2,4]).
        -{[4],[2]}
        -3> queue:to_list(queue:join(Queue1, Queue2)).
        -[1,3,2,4]
        +front of Q2.

        Example:

        1> Queue1 = queue:from_list([1,3]).
        +{[3],[1]}
        +2> Queue2 = queue:from_list([2,4]).
        +{[4],[2]}
        +3> queue:to_list(queue:join(Queue1, Queue2)).
        +[1,3,2,4]
        @@ -1350,12 +1350,12 @@

        out(Q1)

        Removes the item at the front of queue Q1. Returns tuple {{value, Item}, Q2}, where Item is the item removed and Q2 is the -resulting queue. If Q1 is empty, tuple {empty, Q1} is returned.

        Example:

        1> Queue = queue:from_list([1,2,3,4,5]).
        -{[5,4,3],[1,2]}
        -2> {{value, 1=Item}, Queue1} = queue:out(Queue).
        -{{value,1},{[5,4,3],[2]}}
        -3> queue:to_list(Queue1).
        -[2,3,4,5]
        +resulting queue. If Q1 is empty, tuple {empty, Q1} is returned.

        Example:

        1> Queue = queue:from_list([1,2,3,4,5]).
        +{[5,4,3],[1,2]}
        +2> {{value, 1=Item}, Queue1} = queue:out(Queue).
        +{{value,1},{[5,4,3],[2]}}
        +3> queue:to_list(Queue1).
        +[2,3,4,5]
        @@ -1385,12 +1385,12 @@

        out_r(Q1)

        Removes the item at the rear of queue Q1. Returns tuple {{value, Item}, Q2}, where Item is the item removed and Q2 is the new queue. If Q1 is empty, -tuple {empty, Q1} is returned.

        Example:

        1> Queue = queue:from_list([1,2,3,4,5]).
        -{[5,4,3],[1,2]}
        -2> {{value, 5=Item}, Queue1} = queue:out_r(Queue).
        -{{value,5},{[4,3],[1,2]}}
        -3> queue:to_list(Queue1).
        -[1,2,3,4]
        +tuple {empty, Q1} is returned.

        Example:

        1> Queue = queue:from_list([1,2,3,4,5]).
        +{[5,4,3],[1,2]}
        +2> {{value, 5=Item}, Queue1} = queue:out_r(Queue).
        +{{value,5},{[4,3],[1,2]}}
        +3> queue:to_list(Queue1).
        +[1,2,3,4]
        @@ -1475,9 +1475,9 @@

        to_list(Q)

        Returns a list of the items in the queue in the same order; the front item of -the queue becomes the head of the list.

        Example:

        1> Queue = queue:from_list([1,2,3,4,5]).
        -{[5,4,3],[1,2]}
        -2> List == queue:to_list(Queue).
        +the queue becomes the head of the list.

        Example:

        1> Queue = queue:from_list([1,2,3,4,5]).
        +{[5,4,3],[1,2]}
        +2> List == queue:to_list(Queue).
         true
        @@ -1518,12 +1518,12 @@

        drop(Q1)

        -

        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]
        @@ -1551,12 +1551,12 @@

        drop_r(Q1)

        -

        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]
        @@ -1584,9 +1584,9 @@

        get(Q)

        -

        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
        @@ -1615,9 +1615,9 @@

        get_r(Q)

        -

        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
        @@ -1647,12 +1647,12 @@

        peek(Q)

        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}
        @@ -1681,12 +1681,12 @@

        peek_r(Q)

        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}
        @@ -1726,10 +1726,10 @@

        cons(Item, Q1)

        -

        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]
        @@ -1757,7 +1757,7 @@

        daeh(Q)

        -

        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
        @@ -1786,7 +1786,7 @@

        head(Q)

        -

        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
        @@ -1815,10 +1815,10 @@

        init(Q1)

        -

        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]
        @@ -1878,7 +1878,7 @@

        last(Q)

        -

        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
        @@ -1907,10 +1907,10 @@

        liat(Q1)

        -

        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]
        @@ -1938,10 +1938,10 @@

        snoc(Q1, Item)

        -

        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]
        diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/rand.html b/prs/9045/lib/stdlib-6.1.2/doc/html/rand.html index 597351917dd0..5ab3cc8a0684 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/rand.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/rand.html @@ -207,13 +207,13 @@

        a reasonably unpredictable seed.

        The functions with explicit state don't use the process dictionary.

        Examples

        Simple use; create and seed the default algorithm with a non-fixed seed, if not already done, and generate two uniformly distibuted -floating point numbers.

        R0 = rand:uniform(),
        -R1 = rand:uniform(),

        Use a specified algorithm:

        _ = rand:seed(exro928ss),
        -R2 = rand:uniform(),

        Use a specified algorithm with a fixed seed:

        _ = rand:seed(exro928ss, {123, 123534, 345345}),
        -R3 = rand:uniform(),

        Use the functional API with a non-fixed seed:

        S0 = rand:seed_s(exsss),
        -{R4, S1} = rand:uniform_s(S0),

        Generate a textbook basic form Box-Muller standard normal distribution number:

        R5 = rand:uniform_real(),
        -R6 = rand:uniform(),
        -SND0 = math:sqrt(-2 * math:log(R5)) * math:cos(math:pi() * R6)

        Generate a standard normal distribution number:

        {SND1, S2} = rand:normal_s(S1),

        Generate a normal distribution number with with mean -3 and variance 0.5:

        {ND0, S3} = rand:normal_s(-3, 0.5, S2),

        Quality of the Generated Numbers

        Note

        The builtin random number generator algorithms are not cryptographically +floating point numbers.

        R0 = rand:uniform(),
        +R1 = rand:uniform(),

        Use a specified algorithm:

        _ = rand:seed(exro928ss),
        +R2 = rand:uniform(),

        Use a specified algorithm with a fixed seed:

        _ = rand:seed(exro928ss, {123, 123534, 345345}),
        +R3 = rand:uniform(),

        Use the functional API with a non-fixed seed:

        S0 = rand:seed_s(exsss),
        +{R4, S1} = rand:uniform_s(S0),

        Generate a textbook basic form Box-Muller standard normal distribution number:

        R5 = rand:uniform_real(),
        +R6 = rand:uniform(),
        +SND0 = math:sqrt(-2 * math:log(R5)) * math:cos(math:pi() * R6)

        Generate a standard normal distribution number:

        {SND1, S2} = rand:normal_s(S1),

        Generate a normal distribution number with with mean -3 and variance 0.5:

        {ND0, S3} = rand:normal_s(-3, 0.5, S2),

        Quality of the Generated Numbers

        Note

        The builtin random number generator algorithms are not cryptographically strong. If a cryptographically strong random number generator is needed, use something like crypto:rand_seed/0.

        For all these generators except exro928ss and exsss the lowest bit(s) have got a slightly less random behaviour than all other bits. @@ -224,7 +224,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.

        @@ -1953,10 +1953,10 @@

        uniform_s(State)

        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.

        @@ -2117,7 +2117,7 @@

        mwc59(CX0)

        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 diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/random.html b/prs/9045/lib/stdlib-6.1.2/doc/html/random.html index 28febef5cd86..c6237aaa8c40 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/random.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/random.html @@ -478,9 +478,9 @@

        seed(A1, A2, A3)

        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.

        diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/re.html b/prs/9045/lib/stdlib-6.1.2/doc/html/re.html index e0db277a2a34..a35af54814d7 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/re.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/re.html @@ -1381,9 +1381,9 @@

        follows (COMMIT) can be triggered first, so merely passing (COMMIT) during a match does not always guarantee that a match must be at this starting point.

        Notice that (*COMMIT) at the start of a pattern is not the same as an anchor, unless the PCRE start-of-match optimizations are turned off, as shown in the -following example:

        1> re:run("xyzabc","(*COMMIT)abc",[{capture,all,list}]).
        -{match,["abc"]}
        -2> re:run("xyzabc","(*COMMIT)abc",[{capture,all,list},no_start_optimize]).
        +following example:

        1> re:run("xyzabc","(*COMMIT)abc",[{capture,all,list}]).
        +{match,["abc"]}
        +2> re:run("xyzabc","(*COMMIT)abc",[{capture,all,list},no_start_optimize]).
         nomatch

        For this pattern, PCRE knows that any match must start with "a", so the optimization skips along the subject to "a" before applying the pattern to the first set of data. The match attempt then succeeds. In the second call the @@ -2116,32 +2116,32 @@

        inspect(MP, Item)

        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,
        +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,
        +                  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 + 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,
        +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">>,<<>>}]
        +
        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">>,<<>>}]
        @@ -2234,16 +2234,16 @@

        replace(Subject, RE, Replacement, Options)< 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", @@ -2360,7 +2360,7 @@

        run(Subject, RE, Options)

        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 @@ -2372,7 +2372,7 @@

            run(Subject, RE, Options)

            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 @@ -2443,12 +2443,12 @@

        run(Subject, RE, Options)

        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 @@ -2470,9 +2470,9 @@

        run(Subject, RE, Options)

        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 @@ -2497,12 +2497,12 @@

          run(Subject, RE, Options)

          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 @@ -2537,12 +2537,12 @@

          run(Subject, RE, Options)

          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.

      @@ -2631,7 +2631,7 @@

      split(Subject, RE, Options)

      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 @@ -2639,21 +2639,21 @@

      split(Subject, RE, Options)

      "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 diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/search.html b/prs/9045/lib/stdlib-6.1.2/doc/html/search.html index 7be3b03914d0..c4118efb1acf 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/search.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/search.html @@ -128,7 +128,7 @@

      - +

      diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/sets.html b/prs/9045/lib/stdlib-6.1.2/doc/html/sets.html index a6c8aaf4629e..f05ee40d99b2 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/sets.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/sets.html @@ -160,11 +160,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 (==).

      Example:

      1> sets:is_element(1.0, sets:from_list([1])).
      +as different if and only if they do not compare equal (==).

      Example:

      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
      -2> gb_sets:is_element(1.0, gb_sets:from_list([1])).
      +2> gb_sets:is_element(1.0, gb_sets:from_list([1])).
       true

      diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/shell.html b/prs/9045/lib/stdlib-6.1.2/doc/html/shell.html index 8c5c75ffdc79..19a5acd75dd9 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/shell.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/shell.html @@ -172,7 +172,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:

      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 @@ -272,74 +272,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).
      @@ -365,31 +365,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}).
       true

      Command 50 inserts another tuple into the ETS table. This time the first argument is the table identifier itself. The shell can parse commands with pids (<0.60.0>), ports (#Port<0.536>), references (#Ref<0.1662103692.2407792644.214210>), and external functions (#Fun<a.b.1>), but the command fails unless the corresponding pid, port, -reference, or function can be created in the running system.

      51> halt().
      +reference, or function can be created in the running system.

      51> halt().
       strider 2>

      Command 51 exits the Erlang runtime system.

      @@ -857,7 +857,7 @@

      format_shell_func(ShellFormatFunc)

      stdlib app config for how to set it before shell started.

      If instead a string is provided, it will be used as a shell command. Your command must include ${file} somewhere in the string, for the shell to know -where the file goes in the command.

      shell:format_shell_func("\"emacs -batch \${file} -l ~/erlang-format/emacs-format-file -f emacs-format-function\"").
      shell:format_shell_func({shell, erl_pp_format_func}).
      +where the file goes in the command.

      shell:format_shell_func("\"emacs -batch \${file} -l ~/erlang-format/emacs-format-file -f emacs-format-function\"").
      shell:format_shell_func({shell, erl_pp_format_func}).
      @@ -1048,19 +1048,19 @@

      prompt_width(String, Encoding)

      It receives a prompt and computes its width, considering its Unicode characters -and ANSI escapes.

      Useful for creating custom multiline prompts.

      Example:

      1> shell:prompt_width("olá> ", unicode).
      +and ANSI escapes.

      Useful for creating custom multiline prompts.

      Example:

      1> shell:prompt_width("olá> ", unicode).
       5
       %% "olá> " is printed as "ol\341> " on a latin1 systems
      -2> shell:prompt_width("olá> ", latin1).
      +2> shell:prompt_width("olá> ", latin1).
       8
       %% Ansi escapes are ignored
      -3> shell:prompt_width("\e[32molá\e[0m> ", unicode).
      +3> shell:prompt_width("\e[32molá\e[0m> ", unicode).
       5
       %% Double width characters count as 2
      -4> shell:prompt_width("😀> ", unicode).
      +4> shell:prompt_width("😀> ", unicode).
       4
       %% "😀> " is printed as "\x{1F600}> " on latin1 systems
      -5> shell:prompt_width("😀> ", latin1).
      +5> shell:prompt_width("😀> ", latin1).
       11
      diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/shell_default.html b/prs/9045/lib/stdlib-6.1.2/doc/html/shell_default.html index a198c73520d5..2199122d9f9d 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/shell_default.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/shell_default.html @@ -135,10 +135,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.

      diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/slave.html b/prs/9045/lib/stdlib-6.1.2/doc/html/slave.html index 787e80948b90..f00080a4fab8 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/slave.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/slave.html @@ -381,7 +381,7 @@

      pseudo(Master, ServerList)

      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]]).
      @@ -535,9 +535,9 @@

      start(Host, Name, Args)

      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 diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/sofs.html b/prs/9045/lib/stdlib-6.1.2/doc/html/sofs.html index c1bf95e9f1a1..de65ef6a6272 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/sofs.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/sofs.html @@ -268,11 +268,11 @@

      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 SetFuns:

    fun sofs:union/1
    -fun(S) -> sofs:partition(1, 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
    +{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

    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 @@ -1838,10 +1838,10 @@

    canonical_relation(SetOfSets)

    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.

    1> Ss = sofs:from_term([[a,b],[b,c]]),
    -CR = sofs:canonical_relation(Ss),
    -sofs:to_external(CR).
    -[{a,[a,b]},{b,[a,b]},{b,[b,c]},{c,[b,c]}]
    +respect to R.

    1> Ss = sofs:from_term([[a,b],[b,c]]),
    +CR = sofs:canonical_relation(Ss),
    +sofs:to_external(CR).
    +[{a,[a,b]},{b,[a,b]},{b,[b,c]},{c,[b,c]}]
    @@ -1871,11 +1871,11 @@

    composite(Function1, Function2)

    Returns the composite of the functions Function1 and -Function2.

    1> F1 = sofs:a_function([{a,1},{b,2},{c,2}]),
    -F2 = sofs:a_function([{1,x},{2,y},{3,z}]),
    -F = sofs:composite(F1, F2),
    -sofs:to_external(F).
    -[{a,x},{b,y},{c,y}]
    +Function2.

    1> F1 = sofs:a_function([{a,1},{b,2},{c,2}]),
    +F2 = sofs:a_function([{1,x},{2,y},{3,z}]),
    +F = sofs:composite(F1, F2),
    +sofs:to_external(F).
    +[{a,x},{b,y},{c,y}]
    @@ -1905,11 +1905,11 @@

    constant_function(Set, AnySet)

    Creates the function that maps each element of set Set -onto AnySet.

    1> S = sofs:set([a,b]),
    -E = sofs:from_term(1),
    -R = sofs:constant_function(S, E),
    -sofs:to_external(R).
    -[{a,1},{b,1}]
    +onto AnySet.

    1> S = sofs:set([a,b]),
    +E = sofs:from_term(1),
    +R = sofs:constant_function(S, E),
    +sofs:to_external(R).
    +[{a,1},{b,1}]
    @@ -1937,10 +1937,10 @@

    converse(BinRel1)

    -

    Returns the converse of the binary relation BinRel1.

    1> R1 = sofs:relation([{1,a},{2,b},{3,a}]),
    -R2 = sofs:converse(R1),
    -sofs:to_external(R2).
    -[{a,1},{a,3},{b,2}]
    +

    Returns the converse of the binary relation BinRel1.

    1> R1 = sofs:relation([{1,a},{2,b},{3,a}]),
    +R2 = sofs:converse(R1),
    +sofs:to_external(R2).
    +[{a,1},{a,3},{b,2}]
    @@ -2058,10 +2058,10 @@

    domain(BinRel)

    -

    Returns the domain of the binary relation BinRel.

    1> R = sofs:relation([{1,a},{1,b},{2,b},{2,c}]),
    -S = sofs:domain(R),
    -sofs:to_external(S).
    -[1,2]
    +

    Returns the domain of the binary relation BinRel.

    1> R = sofs:relation([{1,a},{1,b},{2,b},{2,c}]),
    +S = sofs:domain(R),
    +sofs:to_external(S).
    +[1,2]
    @@ -2091,11 +2091,11 @@

    drestriction(BinRel1, Set)

    Returns the difference between the binary relation BinRel1 and the -restriction of BinRel1 to Set.

    1> R1 = sofs:relation([{1,a},{2,b},{3,c}]),
    -S = sofs:set([2,4,6]),
    -R2 = sofs:drestriction(R1, S),
    -sofs:to_external(R2).
    -[{1,a},{3,c}]

    drestriction(R, S) is equivalent to +restriction of BinRel1 to Set.

    1> R1 = sofs:relation([{1,a},{2,b},{3,c}]),
    +S = sofs:set([2,4,6]),
    +R2 = sofs:drestriction(R1, S),
    +sofs:to_external(R2).
    +[{1,a},{3,c}]

    drestriction(R, S) is equivalent to difference(R, restriction(R, S)).

    @@ -2126,12 +2126,12 @@

    drestriction(SetFun, Set1, Set2)

    Returns a subset of Set1 containing those elements that do not give an element -in Set2 as the result of applying SetFun.

    1> SetFun = {external, fun({_A,B,C}) -> {B,C} end},
    -R1 = sofs:relation([{a,aa,1},{b,bb,2},{c,cc,3}]),
    -R2 = sofs:relation([{bb,2},{cc,3},{dd,4}]),
    -R3 = sofs:drestriction(SetFun, R1, R2),
    -sofs:to_external(R3).
    -[{a,aa,1}]

    drestriction(F, S1, S2) is equivalent to +in Set2 as the result of applying SetFun.

    1> SetFun = {external, fun({_A,B,C}) -> {B,C} end},
    +R1 = sofs:relation([{a,aa,1},{b,bb,2},{c,cc,3}]),
    +R2 = sofs:relation([{bb,2},{cc,3},{dd,4}]),
    +R3 = sofs:drestriction(SetFun, R1, R2),
    +sofs:to_external(R3).
    +[{a,aa,1}]

    drestriction(F, S1, S2) is equivalent to difference(S1, restriction(F, S1, S2)).

    @@ -2196,12 +2196,12 @@

    extension(BinRel1, Set, AnySet)

    Returns the extension of BinRel1 such that for each element E in Set that does not belong to the domain of -BinRel1, BinRel2 contains the pair (E, AnySet).

    1> S = sofs:set([b,c]),
    -A = sofs:empty_set(),
    -R = sofs:family([{a,[1,2]},{b,[3]}]),
    -X = sofs:extension(R, S, A),
    -sofs:to_external(X).
    -[{a,[1,2]},{b,[3]},{c,[]}]
    +BinRel1, BinRel2 contains the pair (E, AnySet).

    1> S = sofs:set([b,c]),
    +A = sofs:empty_set(),
    +R = sofs:family([{a,[1,2]},{b,[3]}]),
    +X = sofs:extension(R, S, A),
    +sofs:to_external(X).
    +[{a,[1,2]},{b,[3]},{c,[]}]
    @@ -2290,11 +2290,11 @@

    family_difference(Family1, Family2)

    If Family1 and Family2 are families, then Family3 is the family such that the index set is equal to the index set of Family1, and Family3[i] is the difference between Family1[i] and Family2[i] if -Family2 maps i, otherwise Family1[i].

    1> F1 = sofs:family([{a,[1,2]},{b,[3,4]}]),
    -F2 = sofs:family([{b,[4,5]},{c,[6,7]}]),
    -F3 = sofs:family_difference(F1, F2),
    -sofs:to_external(F3).
    -[{a,[1,2]},{b,[3]}]
    +Family2 maps i, otherwise Family1[i].

    1> F1 = sofs:family([{a,[1,2]},{b,[3,4]}]),
    +F2 = sofs:family([{b,[4,5]},{c,[6,7]}]),
    +F3 = sofs:family_difference(F1, F2),
    +sofs:to_external(F3).
    +[{a,[1,2]},{b,[3]}]
    @@ -2325,10 +2325,10 @@

    family_domain(Family1)

    If Family1 is a family and Family1[i] is a binary relation for every i in the index set of Family1, then Family2 is the family with the same index set as Family1 such that Family2[i] is the -domain of Family1[i].

    1> FR = sofs:from_term([{a,[{1,a},{2,b},{3,c}]},{b,[]},{c,[{4,d},{5,e}]}]),
    -F = sofs:family_domain(FR),
    -sofs:to_external(F).
    -[{a,[1,2,3]},{b,[]},{c,[4,5]}]
    +domain of Family1[i].

    1> FR = sofs:from_term([{a,[{1,a},{2,b},{3,c}]},{b,[]},{c,[{4,d},{5,e}]}]),
    +F = sofs:family_domain(FR),
    +sofs:to_external(F).
    +[{a,[1,2,3]},{b,[]},{c,[4,5]}]
    @@ -2359,10 +2359,10 @@

    family_field(Family1)

    If Family1 is a family and Family1[i] is a binary relation for every i in the index set of Family1, then Family2 is the family with the same index set as Family1 such that Family2[i] is the -field of Family1[i].

    1> FR = sofs:from_term([{a,[{1,a},{2,b},{3,c}]},{b,[]},{c,[{4,d},{5,e}]}]),
    -F = sofs:family_field(FR),
    -sofs:to_external(F).
    -[{a,[1,2,3,a,b,c]},{b,[]},{c,[4,5,d,e]}]

    family_field(Family1) is equivalent to +field of Family1[i].

    1> FR = sofs:from_term([{a,[{1,a},{2,b},{3,c}]},{b,[]},{c,[{4,d},{5,e}]}]),
    +F = sofs:family_field(FR),
    +sofs:to_external(F).
    +[{a,[1,2,3,a,b,c]},{b,[]},{c,[4,5,d,e]}]

    family_field(Family1) is equivalent to family_union(family_domain(Family1), family_range(Family1)).

    @@ -2395,10 +2395,10 @@

    family_intersection(Family1)

    for every i in the index set of Family1, then Family2 is the family with the same index set as Family1 such that Family2[i] is the intersection of Family1[i].

    If Family1[i] is an empty set for some i, the process exits with a badarg -message.

    1> F1 = sofs:from_term([{a,[[1,2,3],[2,3,4]]},{b,[[x,y,z],[x,y]]}]),
    -F2 = sofs:family_intersection(F1),
    -sofs:to_external(F2).
    -[{a,[2,3]},{b,[x,y]}]
    +message.

    1> F1 = sofs:from_term([{a,[[1,2,3],[2,3,4]]},{b,[[x,y,z],[x,y]]}]),
    +F2 = sofs:family_intersection(F1),
    +sofs:to_external(F2).
    +[{a,[2,3]},{b,[x,y]}]
    @@ -2430,11 +2430,11 @@

    family_intersection(Family1, Family2)

    If Family1 and Family2 are families, then Family3 is the family such that the index set is the intersection of Family1:s and Family2:s index sets, and Family3[i] is the intersection of Family1[i] -and Family2[i].

    1> F1 = sofs:family([{a,[1,2]},{b,[3,4]},{c,[5,6]}]),
    -F2 = sofs:family([{b,[4,5]},{c,[7,8]},{d,[9,10]}]),
    -F3 = sofs:family_intersection(F1, F2),
    -sofs:to_external(F3).
    -[{b,[4]},{c,[]}]
    +and Family2[i].

    1> F1 = sofs:family([{a,[1,2]},{b,[3,4]},{c,[5,6]}]),
    +F2 = sofs:family([{b,[4,5]},{c,[7,8]},{d,[9,10]}]),
    +F3 = sofs:family_intersection(F1, F2),
    +sofs:to_external(F3).
    +[{b,[4]},{c,[]}]
    @@ -2465,10 +2465,10 @@

    family_projection(SetFun, Family1)

    If Family1 is a family, then Family2 is the family with the same index set as Family1 such that Family2[i] is the result of calling -SetFun with Family1[i] as argument.

    1> F1 = sofs:from_term([{a,[[1,2],[2,3]]},{b,[[]]}]),
    -F2 = sofs:family_projection(fun sofs:union/1, F1),
    -sofs:to_external(F2).
    -[{a,[1,2,3]},{b,[]}]
    +SetFun with Family1[i] as argument.

    1> F1 = sofs:from_term([{a,[[1,2],[2,3]]},{b,[[]]}]),
    +F2 = sofs:family_projection(fun sofs:union/1, F1),
    +sofs:to_external(F2).
    +[{a,[1,2,3]},{b,[]}]
    @@ -2499,10 +2499,10 @@

    family_range(Family1)

    If Family1 is a family and Family1[i] is a binary relation for every i in the index set of Family1, then Family2 is the family with the same index set as Family1 such that Family2[i] is the -range of Family1[i].

    1> FR = sofs:from_term([{a,[{1,a},{2,b},{3,c}]},{b,[]},{c,[{4,d},{5,e}]}]),
    -F = sofs:family_range(FR),
    -sofs:to_external(F).
    -[{a,[a,b,c]},{b,[]},{c,[d,e]}]
    +range of Family1[i].

    1> FR = sofs:from_term([{a,[{1,a},{2,b},{3,c}]},{b,[]},{c,[{4,d},{5,e}]}]),
    +F = sofs:family_range(FR),
    +sofs:to_external(F).
    +[{a,[a,b,c]},{b,[]},{c,[d,e]}]
    @@ -2536,11 +2536,11 @@

    family_specification(Fun, Family1)

    index set for which Fun applied to Family1[i] returns true. If Fun is a tuple {external, Fun2}, then Fun2 is applied to the external set of Family1[i], otherwise Fun is -applied to Family1[i].

    1> F1 = sofs:family([{a,[1,2,3]},{b,[1,2]},{c,[1]}]),
    -SpecFun = fun(S) -> sofs:no_elements(S) =:= 2 end,
    -F2 = sofs:family_specification(SpecFun, F1),
    -sofs:to_external(F2).
    -[{b,[1,2]}]
    +applied to Family1[i].

    1> F1 = sofs:family([{a,[1,2,3]},{b,[1,2]},{c,[1]}]),
    +SpecFun = fun(S) -> sofs:no_elements(S) =:= 2 end,
    +F2 = sofs:family_specification(SpecFun, F1),
    +sofs:to_external(F2).
    +[{b,[1,2]}]
    @@ -2635,10 +2635,10 @@

    family_to_relation(Family)

    If Family is a family, then BinRel is the binary relation containing all pairs (i, x) such that i belongs to the index set of Family and -x belongs to Family[i].

    1> F = sofs:family([{a,[]}, {b,[1]}, {c,[2,3]}]),
    -R = sofs:family_to_relation(F),
    -sofs:to_external(R).
    -[{b,1},{c,2},{c,3}]
    +x belongs to Family[i].

    1> F = sofs:family([{a,[]}, {b,[1]}, {c,[2,3]}]),
    +R = sofs:family_to_relation(F),
    +sofs:to_external(R).
    +[{b,1},{c,2},{c,3}]
    @@ -2669,10 +2669,10 @@

    family_union(Family1)

    If Family1 is a family and Family1[i] is a set of sets for each i in the index set of Family1, then Family2 is the family with the same index set as Family1 such that Family2[i] is the -union of Family1[i].

    1> F1 = sofs:from_term([{a,[[1,2],[2,3]]},{b,[[]]}]),
    -F2 = sofs:family_union(F1),
    -sofs:to_external(F2).
    -[{a,[1,2,3]},{b,[]}]

    family_union(F) is equivalent to +union of Family1[i].

    1> F1 = sofs:from_term([{a,[[1,2],[2,3]]},{b,[[]]}]),
    +F2 = sofs:family_union(F1),
    +sofs:to_external(F2).
    +[{a,[1,2,3]},{b,[]}]

    family_union(F) is equivalent to family_projection(fun sofs:union/1, F).

    @@ -2705,11 +2705,11 @@

    family_union(Family1, Family2)

    If Family1 and Family2 are families, then Family3 is the family such that the index set is the union of Family1:s and Family2:s index sets, and Family3[i] is the union of Family1[i] and Family2[i] if -both map i, otherwise Family1[i] or Family2[i].

    1> F1 = sofs:family([{a,[1,2]},{b,[3,4]},{c,[5,6]}]),
    -F2 = sofs:family([{b,[4,5]},{c,[7,8]},{d,[9,10]}]),
    -F3 = sofs:family_union(F1, F2),
    -sofs:to_external(F3).
    -[{a,[1,2]},{b,[3,4,5]},{c,[5,6,7,8]},{d,[9,10]}]
    +both map i, otherwise Family1[i] or Family2[i].

    1> F1 = sofs:family([{a,[1,2]},{b,[3,4]},{c,[5,6]}]),
    +F2 = sofs:family([{b,[4,5]},{c,[7,8]},{d,[9,10]}]),
    +F3 = sofs:family_union(F1, F2),
    +sofs:to_external(F3).
    +[{a,[1,2]},{b,[3,4,5]},{c,[5,6,7,8]},{d,[9,10]}]
    @@ -2737,10 +2737,10 @@

    field(BinRel)

    -

    Returns the field of the binary relation BinRel.

    1> R = sofs:relation([{1,a},{1,b},{2,b},{2,c}]),
    -S = sofs:field(R),
    -sofs:to_external(S).
    -[1,2,a,b,c]

    field(R) is equivalent to +

    Returns the field of the binary relation BinRel.

    1> R = sofs:relation([{1,a},{1,b},{2,b},{2,c}]),
    +S = sofs:field(R),
    +sofs:to_external(S).
    +[1,2,a,b,c]

    field(R) is equivalent to union(domain(R), range(R)).

    @@ -2802,11 +2802,11 @@

    from_sets/1

    Returns the unordered set containing the sets of -list ListOfSets.

    1> S1 = sofs:relation([{a,1},{b,2}]),
    -S2 = sofs:relation([{x,3},{y,4}]),
    -S = sofs:from_sets([S1,S2]),
    -sofs:to_external(S).
    -[[{a,1},{b,2}],[{x,3},{y,4}]]

    Returns the ordered set containing the sets of the +list ListOfSets.

    1> S1 = sofs:relation([{a,1},{b,2}]),
    +S2 = sofs:relation([{x,3},{y,4}]),
    +S = sofs:from_sets([S1,S2]),
    +sofs:to_external(S).
    +[[{a,1},{b,2}],[{x,3},{y,4}]]

    Returns the ordered set containing the sets of the non-empty tuple TupleOfSets.

    @@ -2867,22 +2867,22 @@

    from_term(Term, Type)

    traversing term Term, sorting lists, removing duplicates, and deriving or verifying a valid type for the so obtained external set.

    An explicitly specified type Type can be used to limit the depth of the traversal; an atomic type stops the traversal, as shown by the -following example where "foo" and {"foo"} are left unmodified:

    1> S = sofs:from_term([{{"foo"},[1,1]},{"foo",[2,2]}],
    -                      [{atom,[atom]}]),
    -   sofs:to_external(S).
    -[{{"foo"},[1]},{"foo",[2]}]

    from_term can be used for creating atomic or ordered sets. The only purpose of +following example where "foo" and {"foo"} are left unmodified:

    1> S = sofs:from_term([{{"foo"},[1,1]},{"foo",[2,2]}],
    +                      [{atom,[atom]}]),
    +   sofs:to_external(S).
    +[{{"foo"},[1]},{"foo",[2]}]

    from_term can be used for creating atomic or ordered sets. The only purpose of such a set is that of later building unordered sets, as all functions in this module that do anything operate on unordered sets. Creating unordered sets from a collection of ordered sets can be the way to go if the ordered sets are big and one does not want to waste heap by rebuilding the elements of the unordered set. The following example shows that a set can be built "layer by -layer":

    1> A = sofs:from_term(a),
    -S = sofs:set([1,2,3]),
    -P1 = sofs:from_sets({A,S}),
    -P2 = sofs:from_term({b,[6,5,4]}),
    -Ss = sofs:from_sets([P1,P2]),
    -sofs:to_external(Ss).
    -[{a,[1,2,3]},{b,[4,5,6]}]

    Other functions that create sets are from_external/2 and from_sets/1. +layer":

    1> A = sofs:from_term(a),
    +S = sofs:set([1,2,3]),
    +P1 = sofs:from_sets({A,S}),
    +P2 = sofs:from_term({b,[6,5,4]}),
    +Ss = sofs:from_sets([P1,P2]),
    +sofs:to_external(Ss).
    +[{a,[1,2,3]},{b,[4,5,6]}]

    Other functions that create sets are from_external/2 and from_sets/1. Special cases of from_term/2 are a_function/1,2, empty_set/0, family/1,2, relation/1,2, and set/1,2.

    @@ -2914,11 +2914,11 @@

    image(BinRel, Set1)

    Returns the image of set Set1 under the binary relation -BinRel.

    1> R = sofs:relation([{1,a},{2,b},{2,c},{3,d}]),
    -S1 = sofs:set([1,2]),
    -S2 = sofs:image(R, S1),
    -sofs:to_external(S2).
    -[a,b,c]
    +BinRel.

    1> R = sofs:relation([{1,a},{2,b},{2,c},{3,d}]),
    +S1 = sofs:set([1,2]),
    +S2 = sofs:image(R, S1),
    +sofs:to_external(S2).
    +[a,b,c]
    @@ -3003,10 +3003,10 @@

    intersection_of_family(Family)

    -

    Returns the intersection of family Family.

    Intersecting an empty family exits the process with a badarg message.

    1> F = sofs:family([{a,[0,2,4]},{b,[0,1,2]},{c,[2,3]}]),
    -S = sofs:intersection_of_family(F),
    -sofs:to_external(S).
    -[2]
    +

    Returns the intersection of family Family.

    Intersecting an empty family exits the process with a badarg message.

    1> F = sofs:family([{a,[0,2,4]},{b,[0,1,2]},{c,[2,3]}]),
    +S = sofs:intersection_of_family(F),
    +sofs:to_external(S).
    +[2]
    @@ -3034,10 +3034,10 @@

    inverse(Function1)

    -

    Returns the inverse of function Function1.

    1> R1 = sofs:relation([{1,a},{2,b},{3,c}]),
    -R2 = sofs:inverse(R1),
    -sofs:to_external(R2).
    -[{a,1},{b,2},{c,3}]
    +

    Returns the inverse of function Function1.

    1> R1 = sofs:relation([{1,a},{2,b},{3,c}]),
    +R2 = sofs:inverse(R1),
    +sofs:to_external(R2).
    +[{a,1},{b,2},{c,3}]
    @@ -3067,11 +3067,11 @@

    inverse_image(BinRel, Set1)

    Returns the inverse image of Set1 under the binary -relation BinRel.

    1> R = sofs:relation([{1,a},{2,b},{2,c},{3,d}]),
    -S1 = sofs:set([c,d,e]),
    -S2 = sofs:inverse_image(R, S1),
    -sofs:to_external(S2).
    -[2,3]
    +relation BinRel.

    1> R = sofs:relation([{1,a},{2,b},{2,c},{3,d}]),
    +S1 = sofs:set([c,d,e]),
    +S2 = sofs:inverse_image(R, S1),
    +sofs:to_external(S2).
    +[2,3]
    @@ -3188,9 +3188,9 @@

    is_equal(AnySet1, AnySet2)

    Returns true if AnySet1 and AnySet2 are equal, otherwise false. The following example shows that ==/2 is used when comparing sets for -equality:

    1> S1 = sofs:set([1.0]),
    -S2 = sofs:set([1]),
    -sofs:is_equal(S1, S2).
    +equality:

    1> S1 = sofs:set([1.0]),
    +S2 = sofs:set([1]),
    +sofs:is_equal(S1, S2).
     true
    @@ -3347,11 +3347,11 @@

    join(Relation1, I, Relation2, J)

    Returns the natural join of the relations Relation1 -and Relation2 on coordinates I and J.

    1> R1 = sofs:relation([{a,x,1},{b,y,2}]),
    -R2 = sofs:relation([{1,f,g},{1,h,i},{2,3,4}]),
    -J = sofs:join(R1, 3, R2, 1),
    -sofs:to_external(J).
    -[{a,x,1,f,g},{a,x,1,h,i},{b,y,2,3,4}]
    +and Relation2 on coordinates I and J.

    1> R1 = sofs:relation([{a,x,1},{b,y,2}]),
    +R2 = sofs:relation([{1,f,g},{1,h,i},{2,3,4}]),
    +J = sofs:join(R1, 3, R2, 1),
    +sofs:to_external(J).
    +[{a,x,1,f,g},{a,x,1,h,i},{b,y,2,3,4}]
    @@ -3387,11 +3387,11 @@

    multiple_relative_product(TupleOfBinRels, B

    If TupleOfBinRels is a non-empty tuple {R[1], ..., R[n]} of binary relations and BinRel1 is a binary relation, then BinRel2 is the multiple relative product of the ordered -set (R[i], ..., R[n]) and BinRel1.

    1> Ri = sofs:relation([{a,1},{b,2},{c,3}]),
    -R = sofs:relation([{a,b},{b,c},{c,a}]),
    -MP = sofs:multiple_relative_product({Ri, Ri}, R),
    -sofs:to_external(sofs:range(MP)).
    -[{1,2},{2,3},{3,1}]
    +set (R[i], ..., R[n]) and BinRel1.

    1> Ri = sofs:relation([{a,1},{b,2},{c,3}]),
    +R = sofs:relation([{a,b},{b,c},{c,a}]),
    +MP = sofs:multiple_relative_product({Ri, Ri}, R),
    +sofs:to_external(sofs:range(MP)).
    +[{1,2},{2,3},{3,1}]

    @@ -3449,11 +3449,11 @@

    partition(SetOfSets)

    Returns the partition of the union of the set of sets SetOfSets such that two elements are considered equal if they belong to the -same elements of SetOfSets.

    1> Sets1 = sofs:from_term([[a,b,c],[d,e,f],[g,h,i]]),
    -Sets2 = sofs:from_term([[b,c,d],[e,f,g],[h,i,j]]),
    -P = sofs:partition(sofs:union(Sets1, Sets2)),
    -sofs:to_external(P).
    -[[a],[b,c],[d],[e,f],[g],[h,i],[j]]
    +same elements of SetOfSets.

    1> Sets1 = sofs:from_term([[a,b,c],[d,e,f],[g,h,i]]),
    +Sets2 = sofs:from_term([[b,c,d],[e,f,g],[h,i,j]]),
    +P = sofs:partition(sofs:union(Sets1, Sets2)),
    +sofs:to_external(P).
    +[[a],[b,c],[d],[e,f],[g],[h,i],[j]]
    @@ -3482,11 +3482,11 @@

    partition(SetFun, Set)

    Returns the partition of Set such that two elements are -considered equal if the results of applying SetFun are equal.

    1> Ss = sofs:from_term([[a],[b],[c,d],[e,f]]),
    -SetFun = fun(S) -> sofs:from_term(sofs:no_elements(S)) end,
    -P = sofs:partition(SetFun, Ss),
    -sofs:to_external(P).
    -[[[a],[b]],[[c,d],[e,f]]]
    +considered equal if the results of applying SetFun are equal.

    1> Ss = sofs:from_term([[a],[b],[c,d],[e,f]]),
    +SetFun = fun(S) -> sofs:from_term(sofs:no_elements(S)) end,
    +P = sofs:partition(SetFun, Ss),
    +sofs:to_external(P).
    +[[[a],[b]],[[c,d],[e,f]]]
    @@ -3523,11 +3523,11 @@

    partition(SetFun, Set1, Set2)

    Returns a pair of sets that, regarded as constituting a set, forms a partition of Set1. If the result of applying SetFun to an element of Set1 gives an element in Set2, the element belongs to Set3, -otherwise the element belongs to Set4.

    1> R1 = sofs:relation([{1,a},{2,b},{3,c}]),
    -S = sofs:set([2,4,6]),
    -{R2,R3} = sofs:partition(1, R1, S),
    -{sofs:to_external(R2),sofs:to_external(R3)}.
    -{[{2,b}],[{1,a},{3,c}]}

    partition(F, S1, S2) is equivalent to +otherwise the element belongs to Set4.

    1> R1 = sofs:relation([{1,a},{2,b},{3,c}]),
    +S = sofs:set([2,4,6]),
    +{R2,R3} = sofs:partition(1, R1, S),
    +{sofs:to_external(R2),sofs:to_external(R3)}.
    +{[{2,b}],[{1,a},{3,c}]}

    partition(F, S1, S2) is equivalent to {restriction(F, S1, S2), drestriction(F, S1, S2)}.

    @@ -3561,11 +3561,11 @@

    partition_family(SetFun, Set)

    partition of Set such that two elements are considered equal if the results of applying SetFun are the same value i. This i is the index that Family maps onto the -equivalence class.

    1> S = sofs:relation([{a,a,a,a},{a,a,b,b},{a,b,b,b}]),
    -SetFun = {external, fun({A,_,C,_}) -> {A,C} end},
    -F = sofs:partition_family(SetFun, S),
    -sofs:to_external(F).
    -[{{a,a},[{a,a,a,a}]},{{a,b},[{a,a,b,b},{a,b,b,b}]}]
    +equivalence class.

    1> S = sofs:relation([{a,a,a,a},{a,a,b,b},{a,b,b,b}]),
    +SetFun = {external, fun({A,_,C,_}) -> {A,C} end},
    +F = sofs:partition_family(SetFun, S),
    +sofs:to_external(F).
    +[{{a,a},[{a,a,a,a}]},{{a,b},[{a,a,b,b},{a,b,b,b}]}]
    @@ -3596,12 +3596,12 @@

    product(TupleOfSets)

    Returns the Cartesian product of the non-empty tuple of sets TupleOfSets. If (x[1], ..., x[n]) is an element of the n-ary relation Relation, then x[i] is drawn from element i of -TupleOfSets.

    1> S1 = sofs:set([a,b]),
    -S2 = sofs:set([1,2]),
    -S3 = sofs:set([x,y]),
    -P3 = sofs:product({S1,S2,S3}),
    -sofs:to_external(P3).
    -[{a,1,x},{a,1,y},{a,2,x},{a,2,y},{b,1,x},{b,1,y},{b,2,x},{b,2,y}]
    +TupleOfSets.

    1> S1 = sofs:set([a,b]),
    +S2 = sofs:set([1,2]),
    +S3 = sofs:set([x,y]),
    +P3 = sofs:product({S1,S2,S3}),
    +sofs:to_external(P3).
    +[{a,1,x},{a,1,y},{a,2,x},{a,2,y},{b,1,x},{b,1,y},{b,2,x},{b,2,y}]
    @@ -3630,11 +3630,11 @@

    product(Set1, Set2)

    Returns the Cartesian product of Set1 and -Set2.

    1> S1 = sofs:set([1,2]),
    -S2 = sofs:set([a,b]),
    -R = sofs:product(S1, S2),
    -sofs:to_external(R).
    -[{1,a},{1,b},{2,a},{2,b}]

    product(S1, S2) is equivalent to +Set2.

    1> S1 = sofs:set([1,2]),
    +S2 = sofs:set([a,b]),
    +R = sofs:product(S1, S2),
    +sofs:to_external(R).
    +[{1,a},{1,b},{2,a},{2,b}]

    product(S1, S2) is equivalent to product({S1, S2}).

    @@ -3665,10 +3665,10 @@

    projection(SetFun, Set1)

    Returns the set created by substituting each element of Set1 by the result of applying SetFun to the element.

    If SetFun is a number i >= 1 and Set1 is a relation, then the returned set -is the projection of Set1 onto coordinate i.

    1> S1 = sofs:from_term([{1,a},{2,b},{3,a}]),
    -S2 = sofs:projection(2, S1),
    -sofs:to_external(S2).
    -[a,b]
    +is the projection of Set1 onto coordinate i.

    1> S1 = sofs:from_term([{1,a},{2,b},{3,a}]),
    +S2 = sofs:projection(2, S1),
    +sofs:to_external(S2).
    +[a,b]
    @@ -3696,10 +3696,10 @@

    range(BinRel)

    -

    Returns the range of the binary relation BinRel.

    1> R = sofs:relation([{1,a},{1,b},{2,b},{2,c}]),
    -S = sofs:range(R),
    -sofs:to_external(S).
    -[a,b,c]
    +

    Returns the range of the binary relation BinRel.

    1> R = sofs:relation([{1,a},{1,b},{2,b},{2,c}]),
    +S = sofs:range(R),
    +sofs:to_external(S).
    +[a,b,c]
    @@ -3790,10 +3790,10 @@

    relation_to_family(BinRel)

    Returns family Family such that the index set is equal to the domain of the binary relation BinRel, and Family[i] -is the image of the set of i under BinRel.

    1> R = sofs:relation([{b,1},{c,2},{c,3}]),
    -F = sofs:relation_to_family(R),
    -sofs:to_external(F).
    -[{b,[1]},{c,[2,3]}]
    +is the image of the set of i under BinRel.

    1> R = sofs:relation([{b,1},{c,2},{c,3}]),
    +F = sofs:relation_to_family(R),
    +sofs:to_external(F).
    +[{b,[1]},{c,[2,3]}]
    @@ -3827,11 +3827,11 @@

    relative_product1(BinRel1, BinRel2)

    Returns the relative product of the converse of the binary relation BinRel1 and the binary -relation BinRel2.

    1> R1 = sofs:relation([{1,a},{1,aa},{2,b}]),
    -R2 = sofs:relation([{1,u},{2,v},{3,c}]),
    -R3 = sofs:relative_product1(R1, R2),
    -sofs:to_external(R3).
    -[{a,u},{aa,u},{b,v}]

    relative_product1(R1, R2) is equivalent to +relation BinRel2.

    1> R1 = sofs:relation([{1,a},{1,aa},{2,b}]),
    +R2 = sofs:relation([{1,u},{2,v},{3,c}]),
    +R3 = sofs:relative_product1(R1, R2),
    +sofs:to_external(R3).
    +[{a,u},{aa,u},{b,v}]

    relative_product1(R1, R2) is equivalent to relative_product(converse(R1), R2).

    @@ -3908,11 +3908,11 @@

    relative_product/2

    (R[i], ..., R[n]) and BinRel1.

    If BinRel1 is omitted, the relation of equality between the elements of the Cartesian product of the ranges of R[i], range R[1] × ... × range R[n], is used instead (intuitively, nothing is -"lost").

    1> TR = sofs:relation([{1,a},{1,aa},{2,b}]),
    -R1 = sofs:relation([{1,u},{2,v},{3,c}]),
    -R2 = sofs:relative_product([TR, R1]),
    -sofs:to_external(R2).
    -[{1,{a,u}},{1,{aa,u}},{2,{b,v}}]

    Notice that relative_product([R1], R2) is different +"lost").

    1> TR = sofs:relation([{1,a},{1,aa},{2,b}]),
    +R1 = sofs:relation([{1,u},{2,v},{3,c}]),
    +R2 = sofs:relative_product([TR, R1]),
    +sofs:to_external(R2).
    +[{1,{a,u}},{1,{aa,u}},{2,{b,v}}]

    Notice that relative_product([R1], R2) is different from relative_product(R1, R2); the list of one element is not identified with the element itself.

    Returns the relative product of the binary relations BinRel1 and BinRel2.

    @@ -3945,11 +3945,11 @@

    restriction(BinRel1, Set)

    Returns the restriction of the binary relation BinRel1 -to Set.

    1> R1 = sofs:relation([{1,a},{2,b},{3,c}]),
    -S = sofs:set([1,2,4]),
    -R2 = sofs:restriction(R1, S),
    -sofs:to_external(R2).
    -[{1,a},{2,b}]
    +to Set.

    1> R1 = sofs:relation([{1,a},{2,b},{3,c}]),
    +S = sofs:set([1,2,4]),
    +R2 = sofs:restriction(R1, S),
    +sofs:to_external(R2).
    +[{1,a},{2,b}]
    @@ -3979,11 +3979,11 @@

    restriction(SetFun, Set1, Set2)

    Returns a subset of Set1 containing those elements that gives an element in -Set2 as the result of applying SetFun.

    1> S1 = sofs:relation([{1,a},{2,b},{3,c}]),
    -S2 = sofs:set([b,c,d]),
    -S3 = sofs:restriction(2, S1, S2),
    -sofs:to_external(S3).
    -[{2,b},{3,c}]
    +Set2 as the result of applying SetFun.

    1> S1 = sofs:relation([{1,a},{2,b},{3,c}]),
    +S2 = sofs:set([b,c,d]),
    +S3 = sofs:restriction(2, S1, S2),
    +sofs:to_external(S3).
    +[{2,b},{3,c}]
    @@ -4072,12 +4072,12 @@

    specification(Fun, Set1)

    Returns the set containing every element of Set1 for which Fun returns true. If Fun is a tuple {external, Fun2}, Fun2 is applied to the external set of each element, otherwise Fun is -applied to each element.

    1> R1 = sofs:relation([{a,1},{b,2}]),
    -R2 = sofs:relation([{x,1},{x,2},{y,3}]),
    -S1 = sofs:from_sets([R1,R2]),
    -S2 = sofs:specification(fun sofs:is_a_function/1, S1),
    -sofs:to_external(S2).
    -[[{a,1},{b,2}]]
    +applied to each element.

    1> R1 = sofs:relation([{a,1},{b,2}]),
    +R2 = sofs:relation([{x,1},{x,2},{y,3}]),
    +S1 = sofs:from_sets([R1,R2]),
    +S2 = sofs:specification(fun sofs:is_a_function/1, S1),
    +sofs:to_external(S2).
    +[[{a,1},{b,2}]]
    @@ -4107,10 +4107,10 @@

    strict_relation(BinRel1)

    Returns the strict relation corresponding to the -binary relation BinRel1.

    1> R1 = sofs:relation([{1,1},{1,2},{2,1},{2,2}]),
    -R2 = sofs:strict_relation(R1),
    -sofs:to_external(R2).
    -[{1,2},{2,1}]
    +binary relation BinRel1.

    1> R1 = sofs:relation([{1,1},{1,2},{2,1},{2,2}]),
    +R2 = sofs:strict_relation(R1),
    +sofs:to_external(R2).
    +[{1,2},{2,1}]
    @@ -4139,29 +4139,29 @@

    substitution(SetFun, Set1)

    Returns a function, the domain of which is Set1. The value of an element of -the domain is the result of applying SetFun to the element.

    1> L = [{a,1},{b,2}].
    -[{a,1},{b,2}]
    -2> sofs:to_external(sofs:projection(1,sofs:relation(L))).
    -[a,b]
    -3> sofs:to_external(sofs:substitution(1,sofs:relation(L))).
    -[{{a,1},a},{{b,2},b}]
    -4> SetFun = {external, fun({A,_}=E) -> {E,A} end},
    -sofs:to_external(sofs:projection(SetFun,sofs:relation(L))).
    -[{{a,1},a},{{b,2},b}]

    The relation of equality between the elements of {a,b,c}:

    1> I = sofs:substitution(fun(A) -> A end, sofs:set([a,b,c])),
    -sofs:to_external(I).
    -[{a,a},{b,b},{c,c}]

    Let SetOfSets be a set of sets and BinRel a binary relation. The function +the domain is the result of applying SetFun to the element.

    1> L = [{a,1},{b,2}].
    +[{a,1},{b,2}]
    +2> sofs:to_external(sofs:projection(1,sofs:relation(L))).
    +[a,b]
    +3> sofs:to_external(sofs:substitution(1,sofs:relation(L))).
    +[{{a,1},a},{{b,2},b}]
    +4> SetFun = {external, fun({A,_}=E) -> {E,A} end},
    +sofs:to_external(sofs:projection(SetFun,sofs:relation(L))).
    +[{{a,1},a},{{b,2},b}]

    The relation of equality between the elements of {a,b,c}:

    1> I = sofs:substitution(fun(A) -> A end, sofs:set([a,b,c])),
    +sofs:to_external(I).
    +[{a,a},{b,b},{c,c}]

    Let SetOfSets be a set of sets and BinRel a binary relation. The function that maps each element Set of SetOfSets onto the image of -Set under BinRel is returned by the following function:

    images(SetOfSets, BinRel) ->
    -   Fun = fun(Set) -> sofs:image(BinRel, Set) end,
    -   sofs:substitution(Fun, SetOfSets).

    External unordered sets are represented as sorted lists. So, creating the image +Set under BinRel is returned by the following function:

    images(SetOfSets, BinRel) ->
    +   Fun = fun(Set) -> sofs:image(BinRel, Set) end,
    +   sofs:substitution(Fun, SetOfSets).

    External unordered sets are represented as sorted lists. So, creating the image of a set under a relation R can traverse all elements of R (to that comes the sorting of results, the image). In image/2, BinRel is traversed once for each element of SetOfSets, which can take too long. The following efficient function can be used instead under the assumption that the image of each element -of SetOfSets under BinRel is non-empty:

    images2(SetOfSets, BinRel) ->
    -   CR = sofs:canonical_relation(SetOfSets),
    -   R = sofs:relative_product1(CR, BinRel),
    -   sofs:relation_to_family(R).
    +of SetOfSets under BinRel is non-empty:

    images2(SetOfSets, BinRel) ->
    +   CR = sofs:canonical_relation(SetOfSets),
    +   R = sofs:relative_product1(CR, BinRel),
    +   sofs:relation_to_family(R).
    @@ -4190,11 +4190,11 @@

    symdiff(Set1, Set2)

    Returns the symmetric difference (or the -Boolean sum) of Set1 and Set2.

    1> S1 = sofs:set([1,2,3]),
    -S2 = sofs:set([2,3,4]),
    -P = sofs:symdiff(S1, S2),
    -sofs:to_external(P).
    -[1,4]
    +Boolean sum) of Set1 and Set2.

    1> S1 = sofs:set([1,2,3]),
    +S2 = sofs:set([2,3,4]),
    +P = sofs:symdiff(S1, S2),
    +sofs:to_external(P).
    +[1,4]
    @@ -4401,10 +4401,10 @@

    union_of_family(Family)

    -

    Returns the union of family Family.

    1> F = sofs:family([{a,[0,2,4]},{b,[0,1,2]},{c,[2,3]}]),
    -S = sofs:union_of_family(F),
    -sofs:to_external(S).
    -[0,1,2,3,4]
    +

    Returns the union of family Family.

    1> F = sofs:family([{a,[0,2,4]},{b,[0,1,2]},{c,[2,3]}]),
    +S = sofs:union_of_family(F),
    +sofs:to_external(S).
    +[0,1,2,3,4]
    @@ -4435,10 +4435,10 @@

    weak_relation(BinRel1)

    Returns a subset S of the weak relation W corresponding to the binary relation BinRel1. Let F be the field of BinRel1. The subset S is defined so that x S y if x -W y for some x in F and for some y in F.

    1> R1 = sofs:relation([{1,1},{1,2},{3,1}]),
    -R2 = sofs:weak_relation(R1),
    -sofs:to_external(R2).
    -[{1,1},{1,2},{2,2},{3,1},{3,3}]
    +W y for some x in F and for some y in F.

    1> R1 = sofs:relation([{1,1},{1,2},{3,1}]),
    +R2 = sofs:weak_relation(R1),
    +sofs:to_external(R2).
    +[{1,1},{1,2},{2,2},{3,1},{3,3}]
    diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/stdlib.epub b/prs/9045/lib/stdlib-6.1.2/doc/html/stdlib.epub index 9c61534e0343..0d070db40452 100644 Binary files a/prs/9045/lib/stdlib-6.1.2/doc/html/stdlib.epub and b/prs/9045/lib/stdlib-6.1.2/doc/html/stdlib.epub differ diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/stdlib_app.html b/prs/9045/lib/stdlib-6.1.2/doc/html/stdlib_app.html index 2d9511d5c6c7..7c4c7099f5a4 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/stdlib_app.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/stdlib_app.html @@ -168,13 +168,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.

  • diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/string.html b/prs/9045/lib/stdlib-6.1.2/doc/html/string.html index 3fc98a4a8e56..11cc23e7767e 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/string.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/string.html @@ -155,14 +155,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  ">>).
    +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 +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 @@ -1078,7 +1078,7 @@

    casefold(String)

    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"
    @@ -1110,9 +1110,9 @@

    chomp(String)

    Returns a string where any trailing \n or \r\n have been removed from -String.

    Example:

    182> string:chomp(<<"\nHello\n\n">>).
    +String.

    Example:

    182> string:chomp(<<"\nHello\n\n">>).
     <<"\nHello">>
    -183> string:chomp("\nHello\r\r\n").
    +183> string:chomp("\nHello\r\r\n").
     "\nHello\r"
    @@ -1213,11 +1213,11 @@

    equal(A, B, IgnoreCase, Norm)

    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
    @@ -1283,13 +1283,13 @@

    find(String, SearchPattern, Dir)

    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).
    +2> string:find(<<"ab..cd..ef">>, "..", trailing).
     <<"..ef">>
    -3> string:find(<<"ab..cd..ef">>, "x", leading).
    +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
    @@ -1320,9 +1320,9 @@

    is_empty(String)

    -

    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
    @@ -1360,13 +1360,13 @@

    jaro_similarity(String1, String2)

    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.

    @@ -1398,9 +1398,9 @@

    length(String)

    -

    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
    @@ -1435,10 +1435,10 @@

    lexemes(String, SeparatorList)

    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">>]
    @@ -1469,7 +1469,7 @@

    lowercase(String)

    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ł"
    @@ -1503,8 +1503,8 @@

    next_codepoint(String)

    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>>]
    @@ -1538,8 +1538,8 @@

    next_grapheme(String)

    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">>]
    @@ -1574,7 +1574,7 @@

    nth_lexeme(String, N, SeparatorList)

    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"
    @@ -1672,11 +1672,11 @@

    pad(String, Length, Dir, Char)

    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ö  '
    @@ -1708,9 +1708,9 @@

    prefix(String, Prefix)

    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").
    +String, otherwise returns nomatch.

    Example:

    1> string:prefix(<<"prefix of string">>, "pre").
     <<"fix of string">>
    -2> string:prefix("pre", "prefix").
    +2> string:prefix("pre", "prefix").
     nomatch
    @@ -1781,10 +1781,10 @@

    replace(String, SearchPattern, Replacement,

    Replaces SearchPattern in String with Replacement. Where, indicates whether -the leading, the trailing or all encounters of SearchPattern are to be replaced.

    Can be implemented as:

    lists:join(Replacement, split(String, SearchPattern, Where)).

    Example:

    1> string:replace(<<"ab..cd..ef">>, "..", "*").
    -[<<"ab">>,"*",<<"cd..ef">>]
    -2> string:replace(<<"ab..cd..ef">>, "..", "*", all).
    -[<<"ab">>,"*",<<"cd">>,"*",<<"ef">>]
    +the leading, the trailing or all encounters of SearchPattern are to be replaced.

    Can be implemented as:

    lists:join(Replacement, split(String, SearchPattern, Where)).

    Example:

    1> string:replace(<<"ab..cd..ef">>, "..", "*").
    +[<<"ab">>,"*",<<"cd..ef">>]
    +2> string:replace(<<"ab..cd..ef">>, "..", "*", all).
    +[<<"ab">>,"*",<<"cd">>,"*",<<"ef">>]
    @@ -1814,9 +1814,9 @@

    reverse(String)

    -

    Returns the reverse list of the grapheme clusters in String.

    Example:

    1> Reverse = string:reverse(unicode:characters_to_nfd_binary("ÅÄÖ")).
    -[[79,776],[65,776],[65,778]]
    -2> io:format("~ts~n",[Reverse]).
    +

    Returns the reverse list of the grapheme clusters in String.

    Example:

    1> Reverse = string:reverse(unicode:characters_to_nfd_binary("ÅÄÖ")).
    +[[79,776],[65,776],[65,778]]
    +2> io:format("~ts~n",[Reverse]).
     ÖÄÅ
    @@ -1885,11 +1885,11 @@

    slice(String, Start, Length)

    Returns a substring of String of at most Length grapheme clusters, starting -at position Start.

    Example:

    1> string:slice(<<"He̊llö Wörld"/utf8>>, 4).
    +at position Start.

    Example:

    1> string:slice(<<"He̊llö Wörld"/utf8>>, 4).
     <<"ö Wörld"/utf8>>
    -2> string:slice(["He̊llö ", <<"Wörld"/utf8>>], 4,4).
    +2> string:slice(["He̊llö ", <<"Wörld"/utf8>>], 4,4).
     "ö Wö"
    -3> string:slice(["He̊llö ", <<"Wörld"/utf8>>], 4,50).
    +3> string:slice(["He̊llö ", <<"Wörld"/utf8>>], 4,50).
     "ö Wörld"
    @@ -1957,12 +1957,12 @@

    split(String, SearchPattern, Where)

    Splits String where SearchPattern is encountered and return the remaining parts. Where, default leading, indicates whether the leading, the -trailing or all encounters of SearchPattern will split String.

    Example:

    0> string:split("ab..bc..cd", "..").
    -["ab","bc..cd"]
    -1> string:split(<<"ab..bc..cd">>, "..", trailing).
    -[<<"ab..bc">>,<<"cd">>]
    -2> string:split(<<"ab..bc....cd">>, "..", all).
    -[<<"ab">>,<<"bc">>,<<>>,<<"cd">>]
    +trailing or all encounters of SearchPattern will split String.

    Example:

    0> string:split("ab..bc..cd", "..").
    +["ab","bc..cd"]
    +1> string:split(<<"ab..bc..cd">>, "..", trailing).
    +[<<"ab..bc">>,<<"cd">>]
    +2> string:split(<<"ab..bc....cd">>, "..", all).
    +[<<"ab">>,<<"bc">>,<<>>,<<"cd">>]
    @@ -2073,14 +2073,14 @@

    take(String, Characters, Complement, Dir)Takes characters from String as long as the characters are members of set Characters or the complement of set Characters. Dir, which can be leading or trailing, indicates from which direction characters are to be -taken.

    Example:

    5> string:take("abc0z123", lists:seq($a,$z)).
    -{"abc","0z123"}
    -6> string:take(<<"abc0z123">>, lists:seq($0,$9), true, leading).
    -{<<"abc">>,<<"0z123">>}
    -7> string:take("abc0z123", lists:seq($0,$9), false, trailing).
    -{"abc0z","123"}
    -8> string:take(<<"abc0z123">>, lists:seq($a,$z), true, trailing).
    -{<<"abc0z">>,<<"123">>}
    +taken.

    Example:

    5> string:take("abc0z123", lists:seq($a,$z)).
    +{"abc","0z123"}
    +6> string:take(<<"abc0z123">>, lists:seq($0,$9), true, leading).
    +{<<"abc">>,<<"0z123">>}
    +7> string:take("abc0z123", lists:seq($0,$9), false, trailing).
    +{"abc0z","123"}
    +8> string:take(<<"abc0z123">>, lists:seq($a,$z), true, trailing).
    +{<<"abc0z">>,<<"123">>}

    @@ -2110,7 +2110,7 @@

    titlecase(String)

    -

    Converts String to titlecase.

    Example:

    1> string:titlecase("ß is a SHARP s").
    +

    Converts String to titlecase.

    Example:

    1> string:titlecase("ß is a SHARP s").
     "Ss is a SHARP s"
    @@ -2146,14 +2146,14 @@

    to_float(String)

    Argument String is expected to start with a valid text represented float (the digits are ASCII values). Remaining characters in the string after the float are -returned in Rest.

    Example:

    1> {F1,Fs} = string:to_float("1.0-1.0e-1"),
    -1> {F2,[]} = string:to_float(Fs),
    +returned in Rest.

    Example:

    1> {F1,Fs} = string:to_float("1.0-1.0e-1"),
    +1> {F2,[]} = string:to_float(Fs),
     1> F1+F2.
     0.9
    -2> string:to_float("3/2=1.5").
    -{error,no_float}
    -3> string:to_float("-1.5eX").
    -{-1.5,"eX"}
    +2>
    string:to_float("3/2=1.5"). +{error,no_float} +3> string:to_float("-1.5eX"). +{-1.5,"eX"}
    @@ -2183,10 +2183,10 @@

    to_graphemes(String)

    -

    Converts String to a list of grapheme clusters.

    Example:

    1> string:to_graphemes("ß↑e̊").
    -[223,8593,[101,778]]
    -2> string:to_graphemes(<<"ß↑e̊"/utf8>>).
    -[223,8593,[101,778]]
    +

    Converts String to a list of grapheme clusters.

    Example:

    1> string:to_graphemes("ß↑e̊").
    +[223,8593,[101,778]]
    +2> string:to_graphemes(<<"ß↑e̊"/utf8>>).
    +[223,8593,[101,778]]
    @@ -2221,14 +2221,14 @@

    to_integer(String)

    Argument String is expected to start with a valid text represented integer (the digits are ASCII values). Remaining characters in the string after the -integer are returned in Rest.

    Example:

    1> {I1,Is} = string:to_integer("33+22"),
    -1> {I2,[]} = string:to_integer(Is),
    +integer are returned in Rest.

    Example:

    1> {I1,Is} = string:to_integer("33+22"),
    +1> {I2,[]} = string:to_integer(Is),
     1> I1-I2.
     11
    -2> string:to_integer("0.5").
    -{0,".5"}
    -3> string:to_integer("x=2").
    -{error,no_integer}
    +2>
    string:to_integer("0.5"). +{0,".5"} +3> string:to_integer("x=2"). +{error,no_integer}
    @@ -2329,11 +2329,11 @@

    trim(String, Dir, Characters)

    Returns a string, where leading or trailing, or both, Characters have been removed.

    Dir which can be leading, trailing, or both, indicates from which direction characters are to be removed.

    Note that [$\r,$\n] is one grapheme cluster according to the Unicode -Standard.

    Example:

    1> string:trim("\t  Hello  \n").
    +Standard.

    Example:

    1> string:trim("\t  Hello  \n").
     "Hello"
    -2> string:trim(<<"\t  Hello  \n">>, leading).
    +2> string:trim(<<"\t  Hello  \n">>, leading).
     <<"Hello  \n">>
    -3> string:trim(<<".Hello.\n">>, trailing, "\n.").
    +3> string:trim(<<".Hello.\n">>, trailing, "\n.").
     <<".Hello">>
    @@ -2364,7 +2364,7 @@

    uppercase(String)

    -

    Converts String to uppercase.

    See also titlecase/1.

    Example:

    1> string:uppercase("Michał").
    +

    Converts String to uppercase.

    See also titlecase/1.

    Example:

    1> string:uppercase("Michał").
     "MICHAŁ"
    @@ -2626,7 +2626,7 @@

    cspan(String, Chars)

    Returns the length of the maximum initial segment of String, which consists -entirely of characters not from Chars.

    This function is obsolete. Use take/3.

    Example:

    1> string:cspan("\t    abcdef", " \t").
    +entirely of characters not from Chars.

    This function is obsolete. Use take/3.

    Example:

    1> string:cspan("\t    abcdef", " \t").
     0
    @@ -2658,7 +2658,7 @@

    join(StringList, Separator)

    Returns a string with the elements of StringList separated by the string in Separator.

    This function is obsolete. Use -lists:join/2.

    Example:

    1> join(["one", "two", "three"], ", ").
    +lists:join/2.

    Example:

    1> join(["one", "two", "three"], ", ").
     "one, two, three"
    @@ -2721,7 +2721,7 @@

    left(String, Number, Character)

    Returns String with the length adjusted in accordance with Number. The left margin is fixed. If length(String) < Number, then String is padded with blanks or Characters.

    This function is obsolete. Use pad/2 or -pad/3.

    Example:

    1> string:left("Hello",10,$.).
    +pad/3.

    Example:

    1> string:left("Hello",10,$.).
     "Hello....."
    @@ -2844,7 +2844,7 @@

    right(String, Number, Character)

    Returns String with the length adjusted in accordance with Number. The right margin is fixed. If the length of (String) < Number, then String is padded -with blanks or Characters.

    This function is obsolete. Use pad/3.

    Example:

    1> string:right("Hello", 10, $.).
    +with blanks or Characters.

    This function is obsolete. Use pad/3.

    Example:

    1> string:right("Hello", 10, $.).
     ".....Hello"
    @@ -2875,7 +2875,7 @@

    rstr(String, SubString)

    Returns the position where the last occurrence of SubString begins in -String. Returns 0 if SubString does not exist in String.

    This function is obsolete. Use find/3.

    Example:

    1> string:rstr(" Hello Hello World World ", "Hello World").
    +String. Returns 0 if SubString does not exist in String.

    This function is obsolete. Use find/3.

    Example:

    1> string:rstr(" Hello Hello World World ", "Hello World").
     8
    @@ -2906,7 +2906,7 @@

    span(String, Chars)

    Returns the length of the maximum initial segment of String, which consists -entirely of characters from Chars.

    This function is obsolete. Use take/2.

    Example:

    1> string:span("\t    abcdef", " \t").
    +entirely of characters from Chars.

    This function is obsolete. Use take/2.

    Example:

    1> string:span("\t    abcdef", " \t").
     5
    @@ -2937,7 +2937,7 @@

    str(String, SubString)

    Returns the position where the first occurrence of SubString begins in -String. Returns 0 if SubString does not exist in String.

    This function is obsolete. Use find/2.

    Example:

    1> string:str(" Hello Hello World World ", "Hello World").
    +String. Returns 0 if SubString does not exist in String.

    This function is obsolete. Use find/2.

    Example:

    1> string:str(" Hello Hello World World ", "Hello World").
     8
    @@ -3031,7 +3031,7 @@

    strip(String, Direction, Character)

    Returns a string, where leading or trailing, or both, blanks or a number of Character have been removed.

    Direction, which can be left, right, or both, indicates from which direction blanks are to be removed. -strip/1 is equivalent to strip(String, both).

    This function is obsolete. Use trim/3.

    Example:

    1> string:strip("...Hello.....", both, $.).
    +strip/1 is equivalent to strip(String, both).

    This function is obsolete. Use trim/3.

    Example:

    1> string:strip("...Hello.....", both, $.).
     "Hello"
    @@ -3095,7 +3095,7 @@

    sub_string(String, Start, Stop)

    Returns a substring of String, starting at position Start to the end of the -string, or to and including position Stop.

    This function is obsolete. Use slice/3.

    Example:

    1> sub_string("Hello World", 4, 8).
    +string, or to and including position Stop.

    This function is obsolete. Use slice/3.

    Example:

    1> sub_string("Hello World", 4, 8).
     "lo Wo"
    @@ -3155,7 +3155,7 @@

    sub_word(String, Number, Character)

    Returns the word in position Number of String. Words are separated by blanks or Characters.

    This function is obsolete. Use -nth_lexeme/3.

    Example:

    1> string:sub_word(" Hello old boy !",3,$o).
    +nth_lexeme/3.

    Example:

    1> string:sub_word(" Hello old boy !",3,$o).
     "ld b"
    @@ -3219,7 +3219,7 @@

    substr(String, Start, Length)

    Returns a substring of String, starting at position Start, and ending at the -end of the string or at length Length.

    This function is obsolete. Use slice/3.

    Example:

    1> substr("Hello World", 4, 5).
    +end of the string or at length Length.

    This function is obsolete. Use slice/3.

    Example:

    1> substr("Hello World", 4, 5).
     "lo Wo"
    @@ -3317,8 +3317,8 @@

    tokens(String, SeparatorList)

    Returns a list of tokens in String, separated by the characters in -SeparatorList.

    Example:

    1> tokens("abc defxxghix jkl", "x ").
    -["abc", "def", "ghi", "jkl"]

    Notice that, as shown in this example, two or more adjacent separator characters +SeparatorList.

    Example:

    1> tokens("abc defxxghix jkl", "x ").
    +["abc", "def", "ghi", "jkl"]

    Notice that, as shown in this example, two or more adjacent separator characters in String are treated as one. That is, there are no empty strings in the resulting list of tokens.

    This function is obsolete. Use lexemes/2.

    @@ -3377,7 +3377,7 @@

    words(String, Character)

    -

    Returns the number of words in String, separated by blanks or Character.

    This function is obsolete. Use lexemes/2.

    Example:

    1> words(" Hello old boy!", $o).
    +

    Returns the number of words in String, separated by blanks or Character.

    This function is obsolete. Use lexemes/2.

    Example:

    1> words(" Hello old boy!", $o).
     4
    diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/supervisor.html b/prs/9045/lib/stdlib-6.1.2/doc/html/supervisor.html index d4a52d5569ba..841d47b3c7a1 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/supervisor.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/supervisor.html @@ -164,10 +164,10 @@

    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
    -                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
    +                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 @@ -211,13 +211,13 @@

      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, +

      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 occations 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 diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/terminal_interface.html b/prs/9045/lib/stdlib-6.1.2/doc/html/terminal_interface.html index d8aa816cdc3f..74d8330fb82e 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/terminal_interface.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/terminal_interface.html @@ -147,18 +147,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",
    @@ -170,51 +170,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.
    -    {ok, Chars} = io:get_chars("", 1024),
    -    case handle_input(Chars, Pos) of
    +    {ok, 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 @@ -224,24 +224,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.

    diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/timer.html b/prs/9045/lib/stdlib-6.1.2/doc/html/timer.html index cb9e6f0d9080..8ef22c5cdc64 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/timer.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/timer.html @@ -152,15 +152,15 @@

    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}
    +

    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),
     ...

    @@ -187,20 +187,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
    diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/unicode.html b/prs/9045/lib/stdlib-6.1.2/doc/html/unicode.html index a77517490d6d..e97e779a36f3 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/unicode.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/unicode.html @@ -1077,13 +1077,13 @@

    characters_to_list(Data, InEncoding)

    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 @@ -1118,7 +1118,7 @@

    characters_to_nfc_binary(CD)

    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]]).
    +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>>
    @@ -1150,7 +1150,7 @@

    characters_to_nfc_list(CD)

    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..åäö"
    @@ -1182,7 +1182,7 @@

    characters_to_nfd_binary(CD)

    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..åäö").
    +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>>
    @@ -1214,8 +1214,8 @@

    characters_to_nfd_list(CD)

    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]
    @@ -1246,7 +1246,7 @@

    characters_to_nfkc_binary(CD)

    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]]).
    +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>>
    @@ -1278,7 +1278,7 @@

    characters_to_nfkc_list(CD)

    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"
    @@ -1311,7 +1311,7 @@

    characters_to_nfkd_binary(CD)

    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]]).
    +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>>
    @@ -1344,8 +1344,8 @@

    characters_to_nfkd_list(CD)

    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]
    diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/unicode_usage.html b/prs/9045/lib/stdlib-6.1.2/doc/html/unicode_usage.html index 2d07b9ca2916..34ae702109ef 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/unicode_usage.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/unicode_usage.html @@ -345,20 +345,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())

    +external_charlist() = maybe_improper_list(char() | external_unicode_binary() | + external_charlist(), external_unicode_binary() | nil())

    @@ -406,7 +406,7 @@

    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">>
    @@ -426,27 +426,27 @@ 

    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]
    +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>>
    @@ -459,17 +459,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 @@ -492,19 +492,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 @@ -517,14 +517,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 @@ -557,10 +557,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 @@ -796,13 +796,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]
     
    -Eshell V5.10.1  (abort with ^G)
    -1> file:write_file("test.term",<<"%% coding: utf-8\n[{\"Юникод\",4711}].\n"/utf8>>).
    +Eshell V5.10.1  (abort with ^G)
    +1> file:write_file("test.term",<<"%% coding: utf-8\n[{\"Юникод\",4711}].\n"/utf8>>).
     ok
    -2> file:consult("test.term").
    -{ok,[[{"Юникод",4711}]]}

    +2> file:consult("test.term"). +{ok,[[{"Юникод",4711}]]}

    @@ -881,21 +881,21 @@

    same way as the remaining file. If such a file is to be read, the first few bytes (depending on encoding) are not part of the text. This code outlines how to open a file that is believed to have a BOM, and sets the files encoding and -position for further sequential reading (preferably using the io module).

    Notice that error handling is omitted from the code:

    open_bom_file_for_reading(File) ->
    -    {ok,F} = file:open(File,[read,binary]),
    -    {ok,Bin} = file:read(F,4),
    -    {Type,Bytes} = unicode:bom_to_encoding(Bin),
    -    file:position(F,Bytes),
    -    io:setopts(F,[{encoding,Type}]),
    -    {ok,F}.

    Function unicode:bom_to_encoding/1 identifies the encoding from a binary of at +position for further sequential reading (preferably using the io module).

    Notice that error handling is omitted from the code:

    open_bom_file_for_reading(File) ->
    +    {ok,F} = file:open(File,[read,binary]),
    +    {ok,Bin} = file:read(F,4),
    +    {Type,Bytes} = unicode:bom_to_encoding(Bin),
    +    file:position(F,Bytes),
    +    io:setopts(F,[{encoding,Type}]),
    +    {ok,F}.

    Function unicode:bom_to_encoding/1 identifies the encoding from a binary of at least four bytes. It returns, along with a term suitable for setting the encoding of the file, the byte length of the BOM, so that the file position can be set accordingly. Notice that function file:position/2 always works on -byte-offsets, so that the byte length of the BOM is needed.

    To open a file for writing and place the BOM first is even simpler:

    open_bom_file_for_writing(File,Encoding) ->
    -    {ok,F} = file:open(File,[write,binary]),
    -    ok = file:write(File,unicode:encoding_to_bom(Encoding)),
    -    io:setopts(F,[{encoding,Encoding}]),
    -    {ok,F}.

    The file is in both these cases then best processed using the io module, as +byte-offsets, so that the byte length of the BOM is needed.

    To open a file for writing and place the BOM first is even simpler:

    open_bom_file_for_writing(File,Encoding) ->
    +    {ok,F} = file:open(File,[write,binary]),
    +    ok = file:write(File,unicode:encoding_to_bom(Encoding)),
    +    io:setopts(F,[{encoding,Encoding}]),
    +    {ok,F}.

    The file is in both these cases then best processed using the io module, as the functions in that module can handle code points beyond the ISO Latin-1 range.

    @@ -909,10 +909,10 @@

    compatibility reasons, these functions do not accept any list as a string, but require a special translation modifier when working with Unicode texts. The modifier is t. When applied to control character s in a formatting string, -it accepts all Unicode code points and expects binaries to be in UTF-8:

    1> io:format("~ts~n",[<<"åäö"/utf8>>]).
    +it accepts all Unicode code points and expects binaries to be in UTF-8:

    1> io:format("~ts~n",[<<"åäö"/utf8>>]).
     åäö
     ok
    -2> io:format("~s~n",[<<"åäö"/utf8>>]).
    +2> io:format("~s~n",[<<"åäö"/utf8>>]).
     åäÃ
     ok

    Clearly, the second io:format/2 gives undesired output, as the UTF-8 binary is not in latin1. For backward compatibility, the non-prefixed control character @@ -929,12 +929,12 @@

    cannot be stored in one byte. The call to erlang:list_to_binary/1 then fails. However, if the I/O server you want to communicate with is Unicode-aware, the returned list can still be used directly:

    $ 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_lib:format("~ts~n", ["Γιούνικοντ"]).
    -["Γιούνικοντ","\n"]
    -2> io:put_chars(io_lib:format("~ts~n", ["Γιούνικοντ"])).
    +Eshell V5.10.1 (abort with ^G)
    +1> io_lib:format("~ts~n", ["Γιούνικοντ"]).
    +["Γιούνικοντ","\n"]
    +2> io:put_chars(io_lib:format("~ts~n", ["Γιούνικοντ"])).
     Γιούνικοντ
     ok

    The Unicode string is returned as a Unicode list, which is recognized as such, as the Erlang shell uses the Unicode encoding (and is started with all Unicode @@ -959,8 +959,8 @@

    ASCII range are seldom considered valid when decoded as UTF-8. Therefore one can usually use heuristics to determine if a file is in UTF-8 or if it is encoded in ISO Latin-1 (one byte per character). The unicode module can be used to -determine if data can be interpreted as UTF-8:

    heuristic_encoding_bin(Bin) when is_binary(Bin) ->
    -    case unicode:characters_to_binary(Bin,utf8,utf8) of
    +determine if data can be interpreted as UTF-8:

    heuristic_encoding_bin(Bin) when is_binary(Bin) ->
    +    case unicode:characters_to_binary(Bin,utf8,utf8) of
     	Bin ->
     	    utf8;
     	_ ->
    @@ -971,34 +971,34 @@ 

    unicode:characters_to_binary/1,2,3 comes in handy. The incomplete rest from one chunk of data read from the file is prepended to the next chunk and we therefore avoid the problem of character -boundaries when reading chunks of bytes in UTF-8 encoding:

    heuristic_encoding_file(FileName) ->
    -    {ok,F} = file:open(FileName,[read,binary]),
    -    loop_through_file(F,<<>>,file:read(F,1024)).
    +boundaries when reading chunks of bytes in UTF-8 encoding:

    heuristic_encoding_file(FileName) ->
    +    {ok,F} = file:open(FileName,[read,binary]),
    +    loop_through_file(F,<<>>,file:read(F,1024)).
     
    -loop_through_file(_,<<>>,eof) ->
    +loop_through_file(_,<<>>,eof) ->
         utf8;
    -loop_through_file(_,_,eof) ->
    +loop_through_file(_,_,eof) ->
         latin1;
    -loop_through_file(F,Acc,{ok,Bin}) when is_binary(Bin) ->
    -    case unicode:characters_to_binary([Acc,Bin]) of
    -	{error,_,_} ->
    +loop_through_file(F,Acc,{ok,Bin}) when is_binary(Bin) ->
    +    case unicode:characters_to_binary([Acc,Bin]) of
    +	{error,_,_} ->
     	    latin1;
    -	{incomplete,_,Rest} ->
    -	    loop_through_file(F,Rest,file:read(F,1024));
    -	Res when is_binary(Res) ->
    -	    loop_through_file(F,<<>>,file:read(F,1024))
    +	{incomplete,_,Rest} ->
    +	    loop_through_file(F,Rest,file:read(F,1024));
    +	Res when is_binary(Res) ->
    +	    loop_through_file(F,<<>>,file:read(F,1024))
         end.

    Another option is to try to read the whole file in UTF-8 encoding and see if it fails. Here we need to read the file using function io:get_chars/3, as we have -to read characters with a code point > 255:

    heuristic_encoding_file2(FileName) ->
    -    {ok,F} = file:open(FileName,[read,binary,{encoding,utf8}]),
    -    loop_through_file2(F,io:get_chars(F,'',1024)).
    +to read characters with a code point > 255:

    heuristic_encoding_file2(FileName) ->
    +    {ok,F} = file:open(FileName,[read,binary,{encoding,utf8}]),
    +    loop_through_file2(F,io:get_chars(F,'',1024)).
     
    -loop_through_file2(_,eof) ->
    +loop_through_file2(_,eof) ->
         utf8;
    -loop_through_file2(_,{error,_Err}) ->
    +loop_through_file2(_,{error,_Err}) ->
         latin1;
    -loop_through_file2(F,Bin) when is_binary(Bin) ->
    -    loop_through_file2(F,io:get_chars(F,'',1024)).

    +loop_through_file2(F,Bin) when is_binary(Bin) -> + loop_through_file2(F,io:get_chars(F,'',1024)).

    @@ -1009,8 +1009,8 @@

    character. Instead you get the "raw" UTF-8 encoding that you have in binaries. This is easily converted to a proper Unicode string by first converting byte per byte into a binary, and then converting the binary of UTF-8 encoded characters -back to a Unicode string:

    utf8_list_to_string(StrangeList) ->
    -  unicode:characters_to_list(list_to_binary(StrangeList)).

    +back to a Unicode string:

    utf8_list_to_string(StrangeList) ->
    +  unicode:characters_to_list(list_to_binary(StrangeList)).

    @@ -1028,26 +1028,26 @@

    encoded in which format, and never convert UTF-8 data (possibly read byte by byte from a file) into UTF-8 again.

    By far the most common situation where this occurs, is when you get lists of UTF-8 instead of proper Unicode strings, and then convert them to UTF-8 in a -binary or on a file:

    wrong_thing_to_do() ->
    -  {ok,Bin} = file:read_file("an_utf8_encoded_file.txt"),
    -  MyList = binary_to_list(Bin), %% Wrong! It is an utf8 binary!
    -  {ok,C} = file:open("catastrophe.txt",[write,{encoding,utf8}]),
    -  io:put_chars(C,MyList), %% Expects a Unicode string, but get UTF-8
    +binary or on a file:

    wrong_thing_to_do() ->
    +  {ok,Bin} = file:read_file("an_utf8_encoded_file.txt"),
    +  MyList = binary_to_list(Bin), %% Wrong! It is an utf8 binary!
    +  {ok,C} = file:open("catastrophe.txt",[write,{encoding,utf8}]),
    +  io:put_chars(C,MyList), %% Expects a Unicode string, but get UTF-8
                               %% bytes in a list!
    -  file:close(C). %% The file catastrophe.txt contains more or less unreadable
    +  file:close(C). %% The file catastrophe.txt contains more or less unreadable
                      %% garbage!

    Ensure you know what a binary contains before converting it to a string. If no -other option exists, try heuristics:

    if_you_can_not_know() ->
    -  {ok,Bin} = file:read_file("maybe_utf8_encoded_file.txt"),
    -  MyList = case unicode:characters_to_list(Bin) of
    -    L when is_list(L) ->
    +other option exists, try heuristics:

    if_you_can_not_know() ->
    +  {ok,Bin} = file:read_file("maybe_utf8_encoded_file.txt"),
    +  MyList = case unicode:characters_to_list(Bin) of
    +    L when is_list(L) ->
           L;
         _ ->
    -      binary_to_list(Bin) %% The file was bytewise encoded
    +      binary_to_list(Bin) %% The file was bytewise encoded
       end,
       %% Now we know that the list is a Unicode string, not a list of UTF-8 bytes
    -  {ok,G} = file:open("greatness.txt",[write,{encoding,utf8}]),
    -  io:put_chars(G,MyList), %% Expects a Unicode string, which is what it gets!
    -  file:close(G). %% The file contains valid UTF-8 encoded Unicode characters!
    +
    {ok,G} = file:open("greatness.txt",[write,{encoding,utf8}]), + io:put_chars(G,MyList), %% Expects a Unicode string, which is what it gets! + file:close(G). %% The file contains valid UTF-8 encoded Unicode characters!
    diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/uri_string.html b/prs/9045/lib/stdlib-6.1.2/doc/html/uri_string.html index 26b29962f9a3..7d283a2835bf 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/uri_string.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/uri_string.html @@ -607,10 +607,10 @@

    compose_query(QueryList)

    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>>}]).
    +2> uri_string:compose_query([{<<"foo bar">>,<<"1">>},
    +2> {<<"city">>,<<"örebro"/utf8>>}]).
     <<"foo+bar=1&city=%C3%B6rebro">>

    @@ -654,11 +654,11 @@

    compose_query(QueryList, Options)

    ";" (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}]).
    +2> uri_string:compose_query([{<<"foo bar">>,<<"1">>},
    +2> {<<"city">>,<<"東京"/utf8>>}], [{encoding, latin1}]).
     <<"foo+bar=1&city=%26%2326481%3B%26%2320140%3B">>
    @@ -695,11 +695,11 @@

    dissect_query(QueryString)

    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>>}]
    @@ -733,14 +733,14 @@

    normalize(URI)

    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">>).
    +2> uri_string:normalize(<<"mid/content=5/../6">>).
     <<"mid/6">>
    -3> uri_string:normalize("http://localhost:80").
    +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"
    @@ -777,15 +777,15 @@

    normalize(URI, Options)

    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"}
    @@ -817,14 +817,14 @@

    parse(URIString)

    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">>,
    +  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">>}
    +
    userinfo => <<"user">>}
    @@ -863,15 +863,15 @@

    percent_decode(URI)

    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">>).
    +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">>).
    +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">>).
    +4> uri_string:percent_decode(<<"http://local%2Fhost/path">>).
     <<"http://local/host/path">>
    @@ -904,9 +904,9 @@

    quote(Data)

    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">>).
    +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.

    @@ -941,9 +941,9 @@

    quote(Data, Safe)

    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">>, "/").
    +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.

    @@ -978,13 +978,13 @@

    recompose(URIMap)

    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"
    @@ -1021,13 +1021,13 @@

    resolve(RefURI, BaseURI)

    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").
     "http://localhost/abs/ol/ute"
    -2> uri_string:resolve("../relative", "http://localhost/a/b/c?q").
    +2> uri_string:resolve("../relative", "http://localhost/a/b/c?q").
     "http://localhost/a/relative"
    -3> uri_string:resolve("http://localhost/full", "http://localhost/a/b/c?q").
    +3> uri_string:resolve("http://localhost/full", "http://localhost/a/b/c?q").
     "http://localhost/full"
    -4> uri_string:resolve(#{path => "path", query => "xyz"}, "http://localhost/a/b/c?q").
    +4> uri_string:resolve(#{path => "path", query => "xyz"}, "http://localhost/a/b/c?q").
     "http://localhost/a/b/path?xyz"
    @@ -1065,11 +1065,11 @@

    resolve(RefURI, BaseURI, Options)

    Same as resolve/2 but with an additional Options parameter, that controls whether the target URI shall be returned as an uri_map(). There is -one supported option: return_map.

    Example:

    1> uri_string:resolve("/abs/ol/ute", "http://localhost/a/b/c?q", [return_map]).
    -#{host => "localhost",path => "/abs/ol/ute",scheme => "http"}
    -2> uri_string:resolve(#{path => "/abs/ol/ute"}, #{scheme => "http",
    -2> host => "localhost", path => "/a/b/c?q"}, [return_map]).
    -#{host => "localhost",path => "/abs/ol/ute",scheme => "http"}
    +one supported option: return_map.

    Example:

    1> uri_string:resolve("/abs/ol/ute", "http://localhost/a/b/c?q", [return_map]).
    +#{host => "localhost",path => "/abs/ol/ute",scheme => "http"}
    +2> uri_string:resolve(#{path => "/abs/ol/ute"}, #{scheme => "http",
    +2> host => "localhost", path => "/a/b/c?q"}, [return_map]).
    +#{host => "localhost",path => "/abs/ol/ute",scheme => "http"}
    @@ -1109,11 +1109,11 @@

    transcode(URIString, Options)

    (in_encoding) and outbound (out_encoding) encodings.

    in_encoding and out_encoding specifies both binary encoding and percent-encoding for the input and output data. Mixed encoding, where binary encoding is not the same as percent-encoding, is not supported. If an argument is invalid, an error tuple is -returned.

    Example:

    1> uri_string:transcode(<<"foo%00%00%00%F6bar"/utf32>>,
    -1> [{in_encoding, utf32},{out_encoding, utf8}]).
    +returned.

    Example:

    1> uri_string:transcode(<<"foo%00%00%00%F6bar"/utf32>>,
    +1> [{in_encoding, utf32},{out_encoding, utf8}]).
     <<"foo%C3%B6bar"/utf8>>
    -2> uri_string:transcode("foo%F6bar", [{in_encoding, latin1},
    -2> {out_encoding, utf8}]).
    +2> uri_string:transcode("foo%F6bar", [{in_encoding, latin1},
    +2> {out_encoding, utf8}]).
     "foo%C3%B6bar"
    @@ -1144,9 +1144,9 @@

    unquote(QuotedData)

    -

    Percent decode characters.

    Example:

    1> uri_string:unquote("SomeId%2F04").
    +

    Percent decode characters.

    Example:

    1> uri_string:unquote("SomeId%2F04").
     "SomeId/04"
    -2> uri_string:unquote(<<"SomeId%2F04">>).
    +2> uri_string:unquote(<<"SomeId%2F04">>).
     <<"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.

    diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/uri_string_usage.html b/prs/9045/lib/stdlib-6.1.2/doc/html/uri_string_usage.html index 26680d0ca8f1..4e9fd924e6cc 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/uri_string_usage.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/uri_string_usage.html @@ -200,19 +200,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.

    +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.

    @@ -235,27 +235,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 @@ -267,32 +267,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 diff --git a/prs/9045/lib/stdlib-6.1.2/doc/html/zip.html b/prs/9045/lib/stdlib-6.1.2/doc/html/zip.html index d717ffb4e2b8..dda61517677b 100644 --- a/prs/9045/lib/stdlib-6.1.2/doc/html/zip.html +++ b/prs/9045/lib/stdlib-6.1.2/doc/html/zip.html @@ -1060,28 +1060,28 @@

    foldl(Fun, Acc0, Archive)

    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",
    +> {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",
    +       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}).
    +       0,0,3,0,0,...>>}}
    +> catch zip:foldl(fun("foo", _, B, _) -> throw(B()); (_,_,_,Acc) -> Acc end, [], {Name, Bin}).
     <<"FOO">>
    diff --git a/prs/9045/lib/syntax_tools-3.2.1/doc/html/.build b/prs/9045/lib/syntax_tools-3.2.1/doc/html/.build index 005b3febd0a5..b0b723009ebb 100644 --- a/prs/9045/lib/syntax_tools-3.2.1/doc/html/.build +++ b/prs/9045/lib/syntax_tools-3.2.1/doc/html/.build @@ -21,7 +21,7 @@ dist/lato-latin-ext-300-normal-VPGGJKJL.woff2 dist/lato-latin-ext-400-normal-N27NCBWW.woff2 dist/lato-latin-ext-700-normal-Q2L5DVMW.woff2 dist/remixicon-NKANDIL5.woff2 -dist/search_data-0D84CF55.js +dist/search_data-3B2B9E37.js dist/sidebar_items-127CA51B.js epp_dodger.html erl_comment_scan.html diff --git a/prs/9045/lib/syntax_tools-3.2.1/doc/html/dist/search_data-0D84CF55.js b/prs/9045/lib/syntax_tools-3.2.1/doc/html/dist/search_data-0D84CF55.js deleted file mode 100644 index fc28b9f6b8c0..000000000000 --- a/prs/9045/lib/syntax_tools-3.2.1/doc/html/dist/search_data-0D84CF55.js +++ /dev/null @@ -1 +0,0 @@ -searchData={"items":[{"type":"module","title":"epp_dodger","doc":"Bypassing the Erlang preprocessor.\n\nThis module tokenises and parses most Erlang source code without expanding\npreprocessor directives and macro applications, as long as these are\nsyntactically \"well-behaved\". Because the normal parse trees of the `erl_parse`\nmodule cannot represent these things (normally, they are expanded by the Erlang\npreprocessor [`//stdlib/epp`](`m:epp`) before the parser sees them), an extended\nsyntax tree is created, using the `m:erl_syntax` module.","ref":"epp_dodger.html"},{"type":"function","title":"epp_dodger.parse/1","doc":"","ref":"epp_dodger.html#parse/1"},{"type":"function","title":"epp_dodger.parse/2","doc":"","ref":"epp_dodger.html#parse/2"},{"type":"function","title":"epp_dodger.parse/3","doc":"Reads and parses program text from an I/O stream.\n\nCharacters are read from `IODevice` until end-of-file; apart from\nthis, the behavior is the same as for `parse_file/2`. `StartLocation`\nis the initial location.\n\n_See also: _`parse/2`, `parse_file/2`, `parse_form/2`, `quick_parse/3`.","ref":"epp_dodger.html#parse/3"},{"type":"function","title":"epp_dodger.parse_file/1","doc":"","ref":"epp_dodger.html#parse_file/1"},{"type":"function","title":"epp_dodger.parse_file/2","doc":"Reads and parses a file.\n\nIf successful, `{ok, Forms}` is returned, where `Forms` is a list of\nabstract syntax trees representing the \"program forms\" of the file\n(see `erl_syntax:is_form/1`). Otherwise, `{error, errorinfo()}` is\nreturned, typically if the file could not be opened. Note that parse\nerrors show up as error markers in the returned list of forms; they do\nnot cause this function to fail or return `{error, errorinfo()}`.\n\nOptions:\n\n- **`{no_fail, boolean()}`** - If `true`, this makes `epp_dodger` replace any\n program forms that could not be parsed with nodes of type `text` (see\n `erl_syntax:text/1`), representing the raw token sequence of the form, instead\n of reporting a parse error. The default value is `false`.\n\n- **`{clever, boolean()}`** - If set to `true`, this makes `epp_dodger` try to\n repair the source code as it seems fit, in certain cases where parsing would\n otherwise fail. Currently, it inserts `++` operators between string literals\n and macros where it looks like concatenation was intended. The default value\n is `false`.\n\n_See also: _`parse/2`, `quick_parse_file/1`, `erl_syntax:is_form/1`.","ref":"epp_dodger.html#parse_file/2"},{"type":"function","title":"epp_dodger.parse_form/2","doc":"","ref":"epp_dodger.html#parse_form/2"},{"type":"function","title":"epp_dodger.parse_form/3","doc":"Reads and parses a single program form from an I/O stream.\n\nCharacters are read from `IODevice` until an end-of-form marker is\nfound (a period character followed by whitespace), or until\nend-of-file; apart from this, the behavior is similar to that of\n[`parse/3`](`parse/3`), except that the return values also contain the\nfinal location given that `StartLocation` is the initial location, and\nthat `{eof, Location}` may be returned.\n\n_See also: _`parse/3`, `parse_form/2`, `quick_parse_form/3`.","ref":"epp_dodger.html#parse_form/3"},{"type":"function","title":"epp_dodger.quick_parse/1","doc":"","ref":"epp_dodger.html#quick_parse/1"},{"type":"function","title":"epp_dodger.quick_parse/2","doc":"","ref":"epp_dodger.html#quick_parse/2"},{"type":"function","title":"epp_dodger.quick_parse/3","doc":"Similar to `parse/3`, but does a more quick-and-dirty processing of the code.\n\nSee `quick_parse_file/2` for details.\n\n_See also: _`parse/3`, `quick_parse/2`, `quick_parse_file/2`,\n`quick_parse_form/2`.","ref":"epp_dodger.html#quick_parse/3"},{"type":"function","title":"epp_dodger.quick_parse_file/1","doc":"","ref":"epp_dodger.html#quick_parse_file/1"},{"type":"function","title":"epp_dodger.quick_parse_file/2","doc":"Similar to `parse_file/2`, but does a more quick-and-dirty processing of the\ncode.\n\nMacro definitions and other preprocessor directives are discarded, and all\nmacro calls are replaced with atoms. This is useful when only the main structure\nof the code is of interest, and not the details. Furthermore, the quick-parse\nmethod can usually handle more strange cases than the normal, more exact\nparsing.\n\nOptions: see `parse_file/2`. However, note that for\n[`quick_parse_file/2`](`quick_parse_file/2`), the option `no_fail` is `true` by\ndefault.\n\n_See also: _`parse_file/2`, `quick_parse/2`.","ref":"epp_dodger.html#quick_parse_file/2"},{"type":"function","title":"epp_dodger.quick_parse_form/2","doc":"","ref":"epp_dodger.html#quick_parse_form/2"},{"type":"function","title":"epp_dodger.quick_parse_form/3","doc":"Similar to `parse_form/3`, but does a more quick-and-dirty processing of the\ncode. See `quick_parse_file/2` for details.\n\n_See also: _`parse/3`, `parse_form/3`, `quick_parse_form/2`.","ref":"epp_dodger.html#quick_parse_form/3"},{"type":"function","title":"epp_dodger.tokens_to_string/1","doc":"Generates a string corresponding to the given token sequence.\n\nThe string can be re-tokenized to yield the same token list again.","ref":"epp_dodger.html#tokens_to_string/1"},{"type":"type","title":"epp_dodger.errorinfo/0","doc":"","ref":"epp_dodger.html#t:errorinfo/0"},{"type":"type","title":"epp_dodger.option/0","doc":"","ref":"epp_dodger.html#t:option/0"},{"type":"module","title":"erl_comment_scan","doc":"Functions for reading comment lines from Erlang source code.","ref":"erl_comment_scan.html"},{"type":"function","title":"erl_comment_scan.file/1","doc":"Extracts comments from an Erlang source code file.\n\nReturns a list of entries representing _multi-line_ comments, listed\nin order of increasing line-numbers. For each entry, `Text` is a list\nof strings representing the consecutive comment lines in top-down\norder; the strings contain _all_ characters following (but not\nincluding) the first comment-introducing `%` character on the line, up\nto (but not including) the line-terminating newline.\n\nFurthermore, `Line` is the line number and `Column` the left column of the\ncomment (that is, the column of the comment-introducing `%` character). `Indent` is\nthe indentation (or padding), measured in character positions between the last\nnon-whitespace character before the comment (or the left margin), and the left\ncolumn of the comment. `Line` and `Column` are always positive integers, and\n`Indentation` is a nonnegative integer.\n\nEvaluation exits with reason `{read, Reason}` if a read error occurred, where\n`Reason` is an atom corresponding to a Posix error code; see the module\n[`//kernel/file`](`m:file`) for details.","ref":"erl_comment_scan.html#file/1"},{"type":"function","title":"erl_comment_scan.join_lines/1","doc":"join_lines(CommentLines) ->\n\nJoins individual comment lines into multi-line comments.\n\nThe input is a list of entries representing individual comment lines,\n_in order of decreasing line-numbers_; see `scan_lines/1` for\ndetails. The result is a list of entries representing _multi-line_\ncomments, _still listed in order of decreasing line-numbers_, but\nwhere for each entry, `Text` is a list of consecutive comment lines in\norder of _increasing_ line-numbers (that is, top-down).\n\n_See also: _`scan_lines/1`.","ref":"erl_comment_scan.html#join_lines/1"},{"type":"function","title":"erl_comment_scan.scan_lines/1","doc":"Extracts individual comment lines from a source code string.\n\nReturns a list of comment lines found in the text, listed in order of\n_decreasing_ line-numbers, that is, the last comment line in the input\nis first in the resulting list. `Text` is a single string, containing\nall characters following (but not including) the first\ncomment-introducing `%` character on the line, up to (but not\nincluding) the line-terminating newline. For details on `Line`,\n`Column` and `Indent`, see `file/1`.","ref":"erl_comment_scan.html#scan_lines/1"},{"type":"function","title":"erl_comment_scan.string/1","doc":"Extracts comments from a string containing Erlang source code.\n\nExcept for reading directly from a string, the behavior is the same\nas for `file/1`.\n\n_See also: _`file/1`.","ref":"erl_comment_scan.html#string/1"},{"type":"type","title":"erl_comment_scan.comment/0","doc":"","ref":"erl_comment_scan.html#t:comment/0"},{"type":"type","title":"erl_comment_scan.commentLine/0","doc":"","ref":"erl_comment_scan.html#t:commentLine/0"},{"type":"module","title":"erl_prettypr","doc":"Pretty printing of abstract Erlang syntax trees.\n\nThis module is a front end to the pretty-printing library module `prettypr`, for\ntext formatting of abstract syntax trees defined by the module `erl_syntax`.","ref":"erl_prettypr.html"},{"type":"function","title":"erl_prettypr.best/1","doc":"","ref":"erl_prettypr.html#best/1"},{"type":"function","title":"erl_prettypr.best/2","doc":"Creates a fixed \"best\" abstract layout for a syntax tree.\n\nThis is similar to the [`layout/2`](`layout/2`) function, except that\nhere, the final layout has been selected with respect to the given\noptions. The atom `empty` is returned if no such layout could be\nproduced. For information on the options, see the\n[`format/2`](`format/2`) function.\n\n_See also: _`best/1`, `format/2`, `layout/2`, `prettypr:best/3`.","ref":"erl_prettypr.html#best/2"},{"type":"function","title":"erl_prettypr.format/1","doc":"","ref":"erl_prettypr.html#format/1"},{"type":"function","title":"erl_prettypr.format/2","doc":"Prettyprint-formats an abstract Erlang syntax tree as text.\n\nFor example, if you have a `.beam` file that has been compiled with\n`debug_info`, the following should print the source code for the\nmodule (as it looks in the debug info representation):\n\n```text\n {ok,{_,[{abstract_code,{_,AC}}]}} =\n beam_lib:chunks(\"myfile.beam\",[abstract_code]),\n io:put_chars(erl_prettypr:format(erl_syntax:form_list(AC)))\n```\n\nAvailable options:\n\n- **`{hook, none | hook()}`** - Unless the value is `none`, the\n given function is called for each node whose list of annotations is\n not empty. The default value is `none`.\n\n- **`{paper, integer()}`** - Specifies the preferred maximum number of\n characters on any line, including indentation. The default value is 80.\n\n- **`{ribbon, integer()}`** - Specifies the preferred maximum number of\n characters on any line, not counting indentation. The default value is 65.\n\n- **`{user, term()}`** - User-specific data for use in hook functions. The\n default value is `undefined`.\n\n- **`{encoding, epp:source_encoding()}`** - Specifies the encoding of the\n generated file.\n\nA hook function (see the [`hook()`](`t:hook/0`) type) is passed the current\nsyntax tree node, the context, and a continuation. The context can be examined\nand manipulated by functions such as [`get_ctxt_user/1`](`get_ctxt_user/1`) and\n[`set_ctxt_user/2`](`set_ctxt_user/2`). The hook must return a \"document\" data\nstructure (see `layout/2` and `best/2`); this may be constructed in part or in\nwhole by applying the continuation function. For example, the following is a\ntrivial hook:\n\n```text\n fun (Node, Ctxt, Cont) -> Cont(Node, Ctxt) end\n```\n\nwhich yields the same result as if no hook was given. The following, however:\n\n```text\n fun (Node, Ctxt, Cont) ->\n Doc = Cont(Node, Ctxt),\n prettypr:beside(prettypr:text(\" \"),\n prettypr:beside(Doc,\n prettypr:text(\" \")))\n end\n```\n\nwill place the text of any annotated node (regardless of the annotation data)\nbetween HTML \"boldface begin\" and \"boldface end\" tags.\n\n_See also: _`m:erl_syntax`, `best/2`, `format/1`, `get_ctxt_user/1`, `layout/2`,\n`set_ctxt_user/2`.","ref":"erl_prettypr.html#format/2"},{"type":"function","title":"erl_prettypr.get_ctxt_hook/1","doc":"Returns the hook function field of the prettyprinter context.\n\n_See also: _`set_ctxt_hook/2`.","ref":"erl_prettypr.html#get_ctxt_hook/1"},{"type":"function","title":"erl_prettypr.get_ctxt_linewidth/1","doc":"Returns the line widh field of the prettyprinter context.\n\n_See also: _`set_ctxt_linewidth/2`.","ref":"erl_prettypr.html#get_ctxt_linewidth/1"},{"type":"function","title":"erl_prettypr.get_ctxt_paperwidth/1","doc":"Returns the paper widh field of the prettyprinter context.\n\n_See also: _`set_ctxt_paperwidth/2`.","ref":"erl_prettypr.html#get_ctxt_paperwidth/1"},{"type":"function","title":"erl_prettypr.get_ctxt_precedence/1","doc":"Returns the operator precedence field of the prettyprinter context.\n\n_See also: _`set_ctxt_precedence/2`.","ref":"erl_prettypr.html#get_ctxt_precedence/1"},{"type":"function","title":"erl_prettypr.get_ctxt_user/1","doc":"Returns the user data field of the prettyprinter context.\n\n_See also: _`set_ctxt_user/2`.","ref":"erl_prettypr.html#get_ctxt_user/1"},{"type":"function","title":"erl_prettypr.layout/1","doc":"","ref":"erl_prettypr.html#layout/1"},{"type":"function","title":"erl_prettypr.layout/2","doc":"Creates an abstract document layout for a syntax tree.\n\nThe result represents a set of possible layouts (see module\n`m:prettypr`). For information on the options, see `format/2`;\nhowever, note that the `paper` and `ribbon` options are ignored by\nthis function.\n\nThis function provides a low-level interface to the pretty printer, returning a\nflexible representation of possible layouts, independent of the paper width\neventually to be used for formatting. This can be included as part of another\ndocument and/or further processed directly by the functions in the `prettypr`\nmodule, or used in a hook function (see [`format/2`](`format/2`) for details).\n\n_See also: _`m:prettypr`, `format/2`, `layout/1`.","ref":"erl_prettypr.html#layout/2"},{"type":"function","title":"erl_prettypr.set_ctxt_hook/2","doc":"Updates the hook function field of the prettyprinter context.\n\n_See also: _`get_ctxt_hook/1`.","ref":"erl_prettypr.html#set_ctxt_hook/2"},{"type":"function","title":"erl_prettypr.set_ctxt_linewidth/2","doc":"Updates the line widh field of the prettyprinter context.\n\n> #### Note {: .info }\n>\n> Changing this value (and passing the resulting context to a\n> continuation function) does not affect the normal formatting, but may\n> affect user-defined behaviour in hook functions.\n\n_See also: _`get_ctxt_linewidth/1`.","ref":"erl_prettypr.html#set_ctxt_linewidth/2"},{"type":"function","title":"erl_prettypr.set_ctxt_paperwidth/2","doc":"Updates the paper widh field of the prettyprinter context.\n\n> #### Note {: .info }\n>\n> Changing this value (and passing the resulting context to a\n> continuation function) does not affect the normal formatting, but may\n> affect user-defined behaviour in hook functions.\n\n_See also: _`get_ctxt_paperwidth/1`.","ref":"erl_prettypr.html#set_ctxt_paperwidth/2"},{"type":"function","title":"erl_prettypr.set_ctxt_precedence/2","doc":"Updates the operator precedence field of the prettyprinter context.\n\nSee the [`//stdlib/erl_parse`](`m:erl_parse`) module for operator\nprecedences.\n\n_See also: _[//stdlib/erl_parse](`m:erl_parse`), `get_ctxt_precedence/1`.","ref":"erl_prettypr.html#set_ctxt_precedence/2"},{"type":"function","title":"erl_prettypr.set_ctxt_user/2","doc":"Updates the user data field of the prettyprinter context.\n\n_See also: _`get_ctxt_user/1`.","ref":"erl_prettypr.html#set_ctxt_user/2"},{"type":"type","title":"erl_prettypr.clause_t/0","doc":"","ref":"erl_prettypr.html#t:clause_t/0"},{"type":"type","title":"erl_prettypr.context/0","doc":"","ref":"erl_prettypr.html#t:context/0"},{"type":"type","title":"erl_prettypr.hook/0","doc":"","ref":"erl_prettypr.html#t:hook/0"},{"type":"type","title":"erl_prettypr.syntaxTree/0","doc":"An abstract syntax tree.\n\nSee the `m:erl_syntax` module for details.","ref":"erl_prettypr.html#t:syntaxTree/0"},{"type":"module","title":"erl_recomment","doc":"Inserting comments into abstract Erlang syntax trees\n\nThis module contains functions for inserting comments, described by position,\nindentation and text, as attachments on an abstract syntax tree, at the correct\nplaces.","ref":"erl_recomment.html"},{"type":"function","title":"erl_recomment.quick_recomment_forms/2","doc":"Like `recomment_forms/2`, but only inserts top-level comments.\n\nComments within function definitions or declarations (\"forms\") are\nsimply ignored.","ref":"erl_recomment.html#quick_recomment_forms/2"},{"type":"function","title":"erl_recomment.recomment_forms/2","doc":"Attaches comments to the syntax tree/trees representing a program.\n\nThe given `Forms` should be a single syntax tree of type `form_list`,\nor a list of syntax trees representing \"program forms\". The syntax\ntrees must contain valid position information (for details, see\n[`recomment_tree/2`](`recomment_tree/2`)). The result is a\ncorresponding syntax tree of type `form_list` in which all comments in\nthe list `Comments` have been attached at the proper places.\n\nAssuming `Forms` represents a program (or any sequence of \"program forms\"), any\ncomments whose first lines are not directly associated with a specific program\nform will become standalone comments inserted between the neighbouring program\nforms. Furthermore, comments whose column position is less than or equal to one\nwill not be attached to a program form that begins at a conflicting line number\n(this can happen with preprocessor-generated `line`\\-attributes).\n\nIf `Forms` is a syntax tree of some other type than `form_list`, the comments\nwill be inserted directly using [`recomment_tree/2`](`recomment_tree/2`), and\nany comments left over from that process are added as postcomments on the\nresult.\n\nEntries in `Comments` represent multi-line comments. For each entry, `Line` is\nthe line number and `Column` the left column of the comment (the column of the\nfirst comment-introducing \"`%`\" character). `Indentation` is the number of\ncharacter positions between the last non-whitespace character before the comment\n(or the left margin) and the left column of the comment. `Text` is a list of\nstrings representing the consecutive comment lines in top-down order, where each\nstring contains all characters following (but not including) the\ncomment-introducing \"`%`\" and up to (but not including) the terminating newline.\n(see module `m:erl_comment_scan`.)\n\nEvaluation exits with reason `{bad_position, Pos}` if the associated position\ninformation `Pos` of some subtree in the input does not have a recognizable\nformat, or with reason `{bad_tree, L, C}` if insertion of a comment at line `L`,\ncolumn `C`, fails because the tree structure is ill-formed.\n\n_See also: _`m:erl_comment_scan`, `quick_recomment_forms/2`, `recomment_tree/2`.","ref":"erl_recomment.html#recomment_forms/2"},{"type":"function","title":"erl_recomment.recomment_tree/2","doc":"Attaches comments to a syntax tree.\n\nThe result is a pair `{NewTree, Remainder}` where `NewTree` is the\ngiven `Tree` where comments from the list `Comments` have been\nattached at the proper places. `Remainder` is the list of entries in\n`Comments` which have not been inserted, because their line numbers\nare greater than those of any node in the tree. The entries in\n`Comments` are inserted in order; if two comments become attached to\nthe same node, they will appear in the same order in the program text.\n\nThe nodes of the syntax tree must contain valid position information. This can\nbe single integers, assumed to represent a line number, or 2- or 3-tuples where\nthe first or second element is an integer, in which case the leftmost integer\nelement is assumed to represent the line number. Line numbers less than one are\nignored (usually, the default line number for newly created nodes is zero).\n\nFor details on the `Line`, `Column` and `Indentation` fields, and the behaviour\nin case of errors, see [`recomment_forms/2`](`recomment_forms/2`).\n\n_See also: _`recomment_forms/2`.","ref":"erl_recomment.html#recomment_tree/2"},{"type":"type","title":"erl_recomment.syntaxTree/0","doc":"An abstract syntax tree. See the `m:erl_syntax` module for details.","ref":"erl_recomment.html#t:syntaxTree/0"},{"type":"module","title":"erl_syntax","doc":"Abstract Erlang syntax trees.\n\nThis module defines an abstract data type for representing Erlang source code as\nsyntax trees, in a way that is backwards compatible with the data structures\ncreated by the Erlang standard library parser module `m:erl_parse` (often referred\nto as \"parse trees\", which is a bit of a misnomer). This means that all\n`erl_parse` trees are valid abstract syntax trees, but the reverse is not true:\nabstract syntax trees can in general not be used as input to functions expecting\nan `erl_parse` tree. However, as long as an abstract syntax tree represents a\ncorrect Erlang program, the function `revert/1` should be able to transform it\nto the corresponding `erl_parse` representation.\n\nA recommended starting point for the first-time user is the documentation of the\n[`syntaxTree()`](`t:syntaxTree/0`) data type, and the function `type/1`.\n\n> #### Note {: .info }\n>\n> This module deals with the composition and decomposition of _syntactic_ entities\n> (as opposed to semantic ones); its purpose is to hide all direct references to\n> the data structures used to represent these entities. With few exceptions, the\n> functions in this module perform no semantic interpretation of their inputs, and\n> in general, the user is assumed to pass type-correct arguments — if this is not\n> done, the effects are not defined.\n\nWith the exception of the [`erl_parse()`](`t:erl_parse/0`) data structures, the\ninternal representations of abstract syntax trees are subject to change without\nnotice, and should not be documented outside this module. Furthermore, we do not\ngive any guarantees on how an abstract syntax tree may or may not be\nrepresented, _with the following exceptions_: no syntax tree is represented by a\nsingle atom, such as `none`, by a list constructor `[X | Y]`, or by the empty\nlist `[]`. This can be relied on when writing functions that operate on syntax\ntrees.","ref":"erl_syntax.html"},{"type":"function","title":"erl_syntax./0","doc":"Creates an abstract empty list.\n\nThe result represents \"`[]`\". The empty list is traditionally called\n\"nil\".\n\n_See also: _`is_list_skeleton/1`, `list/2`.","ref":"erl_syntax.html#nil/0"},{"type":"function","title":"erl_syntax.abstract/1","doc":"Returns the syntax tree corresponding to an Erlang term.\n\n`Term` must be a literal term, meaning one that can be represented as a\nsource code literal. Thus, it must not contain a process identifier,\nport, reference, or function value as a subterm. The function\nrecognises printable strings, in order to get a compact and readable\nrepresentation. Evaluation fails with reason `badarg` if `Term` is not\na literal term.\n\n_See also: _`concrete/1`, `is_literal/1`.","ref":"erl_syntax.html#abstract/1"},{"type":"function","title":"erl_syntax.add_ann/2","doc":"Appends the term `Annotation` to the list of user annotations of `Node`.\n\nNote: this is equivalent to\n[`set_ann(Node, [Annotation | get_ann(Node)])`](`set_ann/2`), but potentially\nmore efficient.\n\n_See also: _`get_ann/1`, `set_ann/2`.","ref":"erl_syntax.html#add_ann/2"},{"type":"function","title":"erl_syntax.add_postcomments/2","doc":"Appends `Comments` to the post-comments of `Node`.\n\nNote: This is equivalent to\n[`set_postcomments(Node, get_postcomments(Node) ++ Comments)`](`set_postcomments/2`),\nbut potentially more efficient.\n\n_See also: _`add_precomments/2`, `comment/2`, `get_postcomments/1`,\n`join_comments/2`, `set_postcomments/2`.","ref":"erl_syntax.html#add_postcomments/2"},{"type":"function","title":"erl_syntax.add_precomments/2","doc":"Appends `Comments` to the pre-comments of `Node`.\n\nNote: This is equivalent to\n[`set_precomments(Node, get_precomments(Node) ++ Comments)`](`set_precomments/2`),\nbut potentially more efficient.\n\n_See also: _`add_postcomments/2`, `comment/2`, `get_precomments/1`,\n`join_comments/2`, `set_precomments/2`.","ref":"erl_syntax.html#add_precomments/2"},{"type":"function","title":"erl_syntax.annotated_type/2","doc":"Creates an abstract annotated type expression.\n\nThe result represents \"`Name :: Type`\".\n\n_See also: _`annotated_type_body/1`, `annotated_type_name/1`.","ref":"erl_syntax.html#annotated_type/2"},{"type":"function","title":"erl_syntax.annotated_type_body/1","doc":"Returns the type subtrees of an `annotated_type` node.\n\n_See also: _`annotated_type/2`.","ref":"erl_syntax.html#annotated_type_body/1"},{"type":"function","title":"erl_syntax.annotated_type_name/1","doc":"Returns the name subtree of an `annotated_type` node.\n\n_See also: _`annotated_type/2`.","ref":"erl_syntax.html#annotated_type_name/1"},{"type":"function","title":"erl_syntax.application/2","doc":"Creates an abstract function application expression.\n\nIf `Arguments` is `[A1, ..., An]`, the result represents\n\"`Operator(A1, ..., An)`\".\n\n_See also: _`application/3`, `application_arguments/1`,\n`application_operator/1`.","ref":"erl_syntax.html#application/2"},{"type":"function","title":"erl_syntax.application/3","doc":"Creates an abstract function application expression.\n\nIf `Module` is `none`, this is call is equivalent to\n[`application(Function, Arguments)`](`application/2`), otherwise it is\nequivalent to [`application(module_qualifier(Module, Function),\nArguments)`](`application/2`).\n\n(This is a utility function.)\n\n_See also: _`application/2`, `module_qualifier/2`.","ref":"erl_syntax.html#application/3"},{"type":"function","title":"erl_syntax.application_arguments/1","doc":"Returns the list of argument subtrees of an `application` node.\n\n_See also: _`application/2`.","ref":"erl_syntax.html#application_arguments/1"},{"type":"function","title":"erl_syntax.application_operator/1","doc":"Returns the operator subtree of an `application` node.\n\nIf `Node` represents \"`M:F(...)`\", then the result is the subtree\nrepresenting \"`M:F`\".\n\n_See also: _`application/2`, `module_qualifier/2`.","ref":"erl_syntax.html#application_operator/1"},{"type":"function","title":"erl_syntax.arity_qualifier/2","doc":"Creates an abstract arity qualifier.\n\nThe result represents \"`Body/Arity`\".\n\n_See also: _`arity_qualifier_argument/1`, `arity_qualifier_body/1`.","ref":"erl_syntax.html#arity_qualifier/2"},{"type":"function","title":"erl_syntax.arity_qualifier_argument/1","doc":"Returns the argument (the arity) subtree of an `arity_qualifier` node.\n\n_See also: _`arity_qualifier/2`.","ref":"erl_syntax.html#arity_qualifier_argument/1"},{"type":"function","title":"erl_syntax.arity_qualifier_body/1","doc":"Returns the body subtree of an `arity_qualifier` node.\n\n_See also: _`arity_qualifier/2`.","ref":"erl_syntax.html#arity_qualifier_body/1"},{"type":"function","title":"erl_syntax.atom/1","doc":"Creates an abstract atom literal.\n\nThe print name of the atom is the character sequence represented by\n`Name`.\n\n_See also: _`atom_literal/1`, `atom_literal/2`, `atom_name/1`, `atom_value/1`,\n`is_atom/2`.","ref":"erl_syntax.html#atom/1"},{"type":"function","title":"erl_syntax.atom_literal/1","doc":"Returns the literal string represented by an `atom` node.\n\nThis includes surrounding single-quote characters if\nnecessary. Characters beyond 255 will be escaped.\n\nNote that, for example, the result of [`atom(\"x\\ny\")`](`atom/1`)\nrepresents any and all of `'x\\ny'`, `'x\\12y'`, `'x\\012y'`, and\n`'x\\^Jy'`; see `string/1`.\n\n_See also: _`atom/1`, `string/1`.","ref":"erl_syntax.html#atom_literal/1"},{"type":"function","title":"erl_syntax.atom_literal/2","doc":"Returns the literal string represented by an `atom` node.\n\nThis includes surrounding single-quote characters if\nnecessary. Depending on the encoding a character beyond 255 will be\nescaped (`latin1`) or copied as is (`utf8`).\n\n_See also: _`atom/1`, `atom_literal/1`, `string/1`.","ref":"erl_syntax.html#atom_literal/2"},{"type":"function","title":"erl_syntax.atom_name/1","doc":"Returns the printname of an `atom` node.\n\n_See also: _`atom/1`.","ref":"erl_syntax.html#atom_name/1"},{"type":"function","title":"erl_syntax.atom_value/1","doc":"Returns the value represented by an `atom` node.\n\n_See also: _`atom/1`.","ref":"erl_syntax.html#atom_value/1"},{"type":"function","title":"erl_syntax.attribute/1","doc":"","ref":"erl_syntax.html#attribute/1"},{"type":"function","title":"erl_syntax.attribute/2","doc":"Creates an abstract program attribute.\n\nIf `Arguments` is `[A1, ..., An]`, the result represents\n\"`-Name(A1, ..., An).`\". Otherwise, if `Arguments` is `none`,\nthe result represents \"`-Name.`\". The latter form makes it possible\nto represent preprocessor directives such as \"`-endif.`\". Attributes\nare source code forms.\n\n> #### Note {: .info }\n>\n> The preprocessor macro definition directive \"`-define(Name, Body).`\"\n> has relatively few requirements on the syntactical form of `Body`\n> (viewed as a sequence of tokens). The `text` node type can be used for\n> a `Body` that is not a normal Erlang construct.\n\n_See also: _`attribute/1`, `attribute_arguments/1`, `attribute_name/1`,\n`is_form/1`, `text/1`.","ref":"erl_syntax.html#attribute/2"},{"type":"function","title":"erl_syntax.attribute_arguments/1","doc":"Returns the list of argument subtrees of an `attribute` node, if any.\n\nIf `Node` represents \"`-Name.`\", the result is `none`. Otherwise, if\n`Node` represents \"`-Name(E1, ..., En).`\", `[E1, ..., E1]` is\nreturned.\n\n_See also: _`attribute/1`.","ref":"erl_syntax.html#attribute_arguments/1"},{"type":"function","title":"erl_syntax.attribute_name/1","doc":"Returns the name subtree of an `attribute` node.\n\n_See also: _`attribute/1`.","ref":"erl_syntax.html#attribute_name/1"},{"type":"function","title":"erl_syntax.binary/1","doc":"Creates an abstract binary-object template.\n\nIf `Fields` is `[F1, ..., Fn]`, the result represents \"`< >`\".\n\n_See also: _`binary_field/2`, `binary_fields/1`.","ref":"erl_syntax.html#binary/1"},{"type":"function","title":"erl_syntax.binary_comp/2","doc":"Creates an abstract binary comprehension.\n\nIf `Body` is `[E1, ..., En]`, the result represents \"`< >`\".\n\n_See also: _`binary_comp_body/1`, `binary_comp_template/1`, `generator/2`.","ref":"erl_syntax.html#binary_comp/2"},{"type":"function","title":"erl_syntax.binary_comp_body/1","doc":"Returns the list of body subtrees of a `binary_comp` node.\n\n_See also: _`binary_comp/2`.","ref":"erl_syntax.html#binary_comp_body/1"},{"type":"function","title":"erl_syntax.binary_comp_template/1","doc":"Returns the template subtree of a `binary_comp` node.\n\n_See also: _`binary_comp/2`.","ref":"erl_syntax.html#binary_comp_template/1"},{"type":"function","title":"erl_syntax.binary_field/1","doc":"","ref":"erl_syntax.html#binary_field/1"},{"type":"function","title":"erl_syntax.binary_field/2","doc":"Creates an abstract binary template field.\n\nIf `Types` is the empty list, the result simply represents\n\"`Body`\", otherwise, if `Types` is `[T1, ..., Tn]`, the result\nrepresents \"`Body/T1-...-Tn`\".\n\n_See also: _`binary/1`, `binary_field/1`, `binary_field/3`,\n`binary_field_body/1`, `binary_field_size/1`, `binary_field_types/1`.","ref":"erl_syntax.html#binary_field/2"},{"type":"function","title":"erl_syntax.binary_field/3","doc":"Creates an abstract binary template field.\n\nIf `Size` is `none`, this is equivalent to \"[`binary_field(Body,\nTypes)`](`binary_field/2`)\", otherwise it is equivalent to\n\"[`binary_field(size_qualifier(Body, Size),\nTypes)`](`binary_field/2`)\".\n\n(This is a utility function.)\n\n_See also: _`binary/1`, `binary_field/2`, `size_qualifier/2`.","ref":"erl_syntax.html#binary_field/3"},{"type":"function","title":"erl_syntax.binary_field_body/1","doc":"Returns the body subtree of a `binary_field`.\n\n_See also: _`binary_field/2`.","ref":"erl_syntax.html#binary_field_body/1"},{"type":"function","title":"erl_syntax.binary_field_size/1","doc":"Returns the size specifier subtree of a `binary_field` node, if any.\n\nIf `Node` represents \"`Body:Size`\" or \"`Body:Size/T1, ...,\nTn`\", the result is `Size`, otherwise `none` is returned.\n\n(This is a utility function.)\n\n_See also: _`binary_field/2`, `binary_field/3`.","ref":"erl_syntax.html#binary_field_size/1"},{"type":"function","title":"erl_syntax.binary_field_types/1","doc":"Returns the list of type-specifier subtrees of a `binary_field` node.\n\nIf `Node` represents \"`.../T1, ..., Tn`\", the result is `[T1,\n..., Tn]`, otherwise the result is the empty list.\n\n_See also: _`binary_field/2`.","ref":"erl_syntax.html#binary_field_types/1"},{"type":"function","title":"erl_syntax.binary_fields/1","doc":"Returns the list of field subtrees of a `binary` node.\n\n_See also: _`binary/1`, `binary_field/2`.","ref":"erl_syntax.html#binary_fields/1"},{"type":"function","title":"erl_syntax.binary_generator/2","doc":"Creates an abstract binary_generator.\n\nThe result represents \"`Pattern <= Body`\".\n\n_See also: _`binary_comp/2`, `binary_generator_body/1`,\n`binary_generator_pattern/1`, `list_comp/2`, `map_comp/2`.","ref":"erl_syntax.html#binary_generator/2"},{"type":"function","title":"erl_syntax.binary_generator_body/1","doc":"Returns the body subtree of a `generator` node.\n\n_See also: _`binary_generator/2`.","ref":"erl_syntax.html#binary_generator_body/1"},{"type":"function","title":"erl_syntax.binary_generator_pattern/1","doc":"Returns the pattern subtree of a `generator` node.\n\n_See also: _`binary_generator/2`.","ref":"erl_syntax.html#binary_generator_pattern/1"},{"type":"function","title":"erl_syntax.bitstring_type/2","doc":"Creates an abstract bitstring type.\n\nThe result represents \"`<<_:M, _:_N>>`\".\n\n_See also: _`bitstring_type_m/1`, `bitstring_type_n/1`.","ref":"erl_syntax.html#bitstring_type/2"},{"type":"function","title":"erl_syntax.bitstring_type_m/1","doc":"Returns the number of start bits, `M`, of a `bitstring_type` node.\n\n_See also: _`bitstring_type/2`.","ref":"erl_syntax.html#bitstring_type_m/1"},{"type":"function","title":"erl_syntax.bitstring_type_n/1","doc":"Returns the segment size, `N`, of a `bitstring_type` node.\n\n_See also: _`bitstring_type/2`.","ref":"erl_syntax.html#bitstring_type_n/1"},{"type":"function","title":"erl_syntax.block_expr/1","doc":"Creates an abstract block expression.\n\nIf `Body` is `[B1, ..., Bn]`, the result represents \"`begin B1, ...,\nBn end`\".\n\n_See also: _`block_expr_body/1`.","ref":"erl_syntax.html#block_expr/1"},{"type":"function","title":"erl_syntax.block_expr_body/1","doc":"Returns the list of body subtrees of a `block_expr` node.\n\n_See also: _`block_expr/1`.","ref":"erl_syntax.html#block_expr_body/1"},{"type":"function","title":"erl_syntax.case_expr/2","doc":"Creates an abstract case-expression.\n\nIf `Clauses` is `[C1, ..., Cn]`, the result represents \"`case\nArgument of C1; ...; Cn end`\". More exactly, if each `Ci`\nrepresents \"`(Pi) Gi -> Bi`\", then the result represents \"`case\nArgument of P1G1 -> B1; ...; PnGn -> Bn end`\".\n\n_See also: _`case_expr_argument/1`, `case_expr_clauses/1`, `clause/3`,\n`if_expr/1`.","ref":"erl_syntax.html#case_expr/2"},{"type":"function","title":"erl_syntax.case_expr_argument/1","doc":"Returns the argument subtree of a `case_expr` node.\n\n_See also: _`case_expr/2`.","ref":"erl_syntax.html#case_expr_argument/1"},{"type":"function","title":"erl_syntax.case_expr_clauses/1","doc":"Returns the list of clause subtrees of a `case_expr` node.\n\n_See also: _`case_expr/2`.","ref":"erl_syntax.html#case_expr_clauses/1"},{"type":"function","title":"erl_syntax.catch_expr/1","doc":"Creates an abstract catch-expression.\n\nThe result represents \"`catch Expr`\".\n\n_See also: _`catch_expr_body/1`.","ref":"erl_syntax.html#catch_expr/1"},{"type":"function","title":"erl_syntax.catch_expr_body/1","doc":"Returns the body subtree of a `catch_expr` node.\n\n_See also: _`catch_expr/1`.","ref":"erl_syntax.html#catch_expr_body/1"},{"type":"function","title":"erl_syntax.char/1","doc":"Creates an abstract character literal.\n\nThe result represents \"`$Name`\", where `Name` corresponds to `Value`.\n\n> #### Note {: .info }\n\nThe literal corresponding to a particular character value is not\nuniquely defined. For example, the character \"`a`\" can be written both\nas \"`$a`\" and \"`$\\141`\", and a Tab character can be written as\n\"`$\\11`\", \"`$\\011`\", or \"`$\\t`\".\n\n_See also: _`char_literal/1`, `char_literal/2`, `char_value/1`, `is_char/2`.","ref":"erl_syntax.html#char/1"},{"type":"function","title":"erl_syntax.char_literal/1","doc":"Returns the literal string represented by a `char` node.\n\nThis includes the leading \"`$`\" character. Characters beyond 255 will\nbe escaped.\n\n_See also: _`char/1`.","ref":"erl_syntax.html#char_literal/1"},{"type":"function","title":"erl_syntax.char_literal/2","doc":"Returns the literal string represented by a `char` node.\n\nThis includes the leading \"`$`\" character. Depending on the encoding a\ncharacter beyond 255 will be escaped (`latin1`) or copied as is\n(`utf8`).\n\n_See also: _`char/1`.","ref":"erl_syntax.html#char_literal/2"},{"type":"function","title":"erl_syntax.char_value/1","doc":"Returns the value represented by a `char` node.\n\n_See also: _`char/1`.","ref":"erl_syntax.html#char_value/1"},{"type":"function","title":"erl_syntax.class_qualifier/2","doc":"Creates an abstract class qualifier.\n\nThe result represents \"`Class:Body`\".\n\n_See also: _`class_qualifier_argument/1`, `class_qualifier_body/1`,\n`class_qualifier_stacktrace/1`, `try_expr/4`.","ref":"erl_syntax.html#class_qualifier/2"},{"type":"function","title":"erl_syntax.class_qualifier/3","doc":"Creates an abstract class qualifier.\n\nThe result represents \"`Class:Body:Stacktrace`\".\n\n_See also: _`class_qualifier_argument/1`, `class_qualifier_body/1`,\n`try_expr/4`.","ref":"erl_syntax.html#class_qualifier/3"},{"type":"function","title":"erl_syntax.class_qualifier_argument/1","doc":"Returns the argument (the class) subtree of a `class_qualifier` node.\n\n_See also: _`class_qualifier/2`.","ref":"erl_syntax.html#class_qualifier_argument/1"},{"type":"function","title":"erl_syntax.class_qualifier_body/1","doc":"Returns the body subtree of a `class_qualifier` node.\n\n_See also: _`class_qualifier/2`.","ref":"erl_syntax.html#class_qualifier_body/1"},{"type":"function","title":"erl_syntax.class_qualifier_stacktrace/1","doc":"Returns the stacktrace subtree of a `class_qualifier` node.\n\n_See also: _`class_qualifier/2`.","ref":"erl_syntax.html#class_qualifier_stacktrace/1"},{"type":"function","title":"erl_syntax.clause/2","doc":"","ref":"erl_syntax.html#clause/2"},{"type":"function","title":"erl_syntax.clause/3","doc":"Creates an abstract clause.\n\nIf `Patterns` is `[P1, ..., Pn]` and `Body` is `[B1, ..., Bm]`, then\nif `Guard` is `none`, the result represents \"`(P1, ..., Pn) ->\nB1, ..., Bm`\", otherwise, unless `Guard` is a list, the result\nrepresents \"`(P1, ..., Pn) when Guard -> B1, ..., Bm`\".\n\nFor simplicity, the `Guard` argument may also be any of the following:\n\n- An empty list `[]`. This is equivalent to passing `none`.\n- A nonempty list `[E1, ..., Ej]` of syntax trees. This is equivalent to passing\n `conjunction([E1, ..., Ej])`.\n- A nonempty list of lists of syntax trees\n `[[E1_1, ..., E1_k1], ..., [Ej_1, ..., Ej_kj]]`, which is equivalent to\n passing\n `disjunction([conjunction([E1_1, ..., E1_k1]), ..., conjunction([Ej_1, ..., Ej_kj])])`.\n\n_See also: _`clause/2`, `clause_body/1`, `clause_guard/1`, `clause_patterns/1`.","ref":"erl_syntax.html#clause/3"},{"type":"function","title":"erl_syntax.clause_body/1","doc":"Return the list of body subtrees of a `clause` node.\n\n_See also: _`clause/3`.","ref":"erl_syntax.html#clause_body/1"},{"type":"function","title":"erl_syntax.clause_guard/1","doc":"Returns the guard subtree of a `clause` node, if any.\n\nIf `Node` represents \"`(P1, ..., Pn) when Guard -> B1, ...,\nBm`\", `Guard` is returned. Otherwise, the result is `none`.\n\n_See also: _`clause/3`.","ref":"erl_syntax.html#clause_guard/1"},{"type":"function","title":"erl_syntax.clause_patterns/1","doc":"Returns the list of pattern subtrees of a `clause` node.\n\n_See also: _`clause/3`.","ref":"erl_syntax.html#clause_patterns/1"},{"type":"function","title":"erl_syntax.comment/1","doc":"","ref":"erl_syntax.html#comment/1"},{"type":"function","title":"erl_syntax.comment/2","doc":"Creates an abstract comment with the given padding and text.\n\nIf `Strings` is a (possibly empty) list `[\"Txt1\", ..., \"TxtN\"]`,\nthe result represents the source code text\n\n```text\n Txt1\n ...\n TxtN\n```\n\n`Padding` states the number of empty character positions to the left of the\ncomment separating it horizontally from source code on the same line (if any).\nIf `Padding` is `none`, a default positive number is used. If `Padding` is an\ninteger less than 1, there should be no separating space. Comments are in\nthemselves regarded as source program forms.\n\n_See also: _`comment/1`, `is_form/1`.","ref":"erl_syntax.html#comment/2"},{"type":"function","title":"erl_syntax.comment_padding/1","doc":"Returns the amount of padding before the comment, or `none`.\n\n`none` means that a default padding may be used.\n\n_See also: _`comment/2`.","ref":"erl_syntax.html#comment_padding/1"},{"type":"function","title":"erl_syntax.comment_text/1","doc":"Returns the lines of text of the abstract comment.\n\n_See also: _`comment/2`.","ref":"erl_syntax.html#comment_text/1"},{"type":"function","title":"erl_syntax.compact_list/1","doc":"Yields the most compact form for an abstract list skeleton.\n\nThe result either represents \"`[E1, ..., En | Tail]`\", where\n`Tail` is not a list skeleton, or otherwise simply \"`[E1, ...,\nEn]`\". Annotations on subtrees of `Node` that represent list\nskeletons may be lost, but comments will be propagated to the\nresult. Returns `Node` itself if `Node` does not represent a list\nskeleton.\n\n_See also: _`list/2`, `normalize_list/1`.","ref":"erl_syntax.html#compact_list/1"},{"type":"function","title":"erl_syntax.concrete/1","doc":"Returns the Erlang term represented by a syntax tree.\n\nEvaluation fails with reason `badarg` if `Node` does not represent a\nliteral term.\n\n> #### Note {: .info }\n>\n> The set of syntax trees which have a concrete representation is larger\n> than the set of trees which can be built using the function\n> `abstract/1`. An abstract character will be concretised as an\n> integer, while `abstract/1` does not at present yield an abstract\n> character for any input. (Use the `char/1` function to explicitly\n> create an abstract character.)\n\n> #### Note {: .info }\n>\n> `arity_qualifier` nodes are recognized. This is to follow the Erlang\n> Parser when it comes to wild attributes: both `{F, A}` and `F/A` are\n> recognized, which makes it possible to turn wild attributes into\n> recognized attributes without at the same time making it impossible to\n> compile files using the new syntax with the old version of the Erlang\n> Compiler.\n\n_See also: _`abstract/1`, `char/1`, `is_literal/1`.","ref":"erl_syntax.html#concrete/1"},{"type":"function","title":"erl_syntax.conjunction/1","doc":"Creates an abstract conjunction.\n\nIf `List` is `[E1, ..., En]`, the result represents \"`E1, ..., En`\".\n\n_See also: _`conjunction_body/1`, `disjunction/1`.","ref":"erl_syntax.html#conjunction/1"},{"type":"function","title":"erl_syntax.conjunction_body/1","doc":"Returns the list of body subtrees of a `conjunction` node.\n\n_See also: _`conjunction/1`.","ref":"erl_syntax.html#conjunction_body/1"},{"type":"function","title":"erl_syntax.cons/2","doc":"\"Optimizing\" list skeleton cons operation.\n\nCreates an abstract list skeleton whose first element is `Head` and\nwhose tail corresponds to `Tail`. This is similar to [`list([Head],\nTail)`](`list/2`), except that `Tail` must not be `none`,\nand the result does not necessarily represent exactly \"`[Head | Tail]`\", but\nmay depend on the `Tail` subtree.\n\nFor example, if `Tail` represents `[X, Y]`, the result may represent\n\"`[Head, X, Y]`\", rather than \"`[Head | [X, Y]]`\". Annotations on\n`Tail` itself may be lost if `Tail` represents a list skeleton, but\ncomments on `Tail` are propagated to the result.\n\n_See also: _`list/2`, `list_head/1`, `list_tail/1`.","ref":"erl_syntax.html#cons/2"},{"type":"function","title":"erl_syntax.constrained_function_type/2","doc":"Creates an abstract constrained function type.\n\nIf `FunctionConstraint` is `[C1, ..., Cn]`, the result represents\n\"`FunctionType when C1, ...Cn`\".\n\n_See also: _`constrained_function_type_argument/1`,\n`constrained_function_type_body/1`.","ref":"erl_syntax.html#constrained_function_type/2"},{"type":"function","title":"erl_syntax.constrained_function_type_argument/1","doc":"Returns the function constraint subtree of a `constrained_function_type` node.\n\n_See also: _`constrained_function_type/2`.","ref":"erl_syntax.html#constrained_function_type_argument/1"},{"type":"function","title":"erl_syntax.constrained_function_type_body/1","doc":"Returns the function type subtree of a `constrained_function_type` node.\n\n_See also: _`constrained_function_type/2`.","ref":"erl_syntax.html#constrained_function_type_body/1"},{"type":"function","title":"erl_syntax.constraint/2","doc":"Creates an abstract (subtype) constraint.\n\nThe result represents \"`Name :: Type`\".\n\n_See also: _`constraint_argument/1`, `constraint_body/1`.","ref":"erl_syntax.html#constraint/2"},{"type":"function","title":"erl_syntax.constraint_argument/1","doc":"Returns the name subtree of a `constraint` node.\n\n_See also: _`constraint/2`.","ref":"erl_syntax.html#constraint_argument/1"},{"type":"function","title":"erl_syntax.constraint_body/1","doc":"Returns the type subtree of a `constraint` node.\n\n_See also: _`constraint/2`.","ref":"erl_syntax.html#constraint_body/1"},{"type":"function","title":"erl_syntax.copy_ann/2","doc":"Copies the list of user annotations from `Source` to `Target`.\n\nNote: this is equivalent to [`set_ann(Target, get_ann(Source))`](`set_ann/2`),\nbut potentially more efficient.\n\n_See also: _`get_ann/1`, `set_ann/2`.","ref":"erl_syntax.html#copy_ann/2"},{"type":"function","title":"erl_syntax.copy_attrs/2","doc":"Copies the attributes from `Source` to `Target`.\n\nNote: this is equivalent to\n[`set_attrs(Target, get_attrs(Source))`](`set_attrs/2`), but potentially more\nefficient.\n\n_See also: _`get_attrs/1`, `set_attrs/2`.","ref":"erl_syntax.html#copy_attrs/2"},{"type":"function","title":"erl_syntax.copy_comments/2","doc":"Copies the pre- and postcomments from `Source` to `Target`.\n\nNote: This is equivalent to\n[`set_postcomments(set_precomments(Target, get_precomments(Source)), get_postcomments(Source))`](`set_postcomments/2`),\nbut potentially more efficient.\n\n_See also: _`comment/2`, `get_postcomments/1`, `get_precomments/1`,\n`set_postcomments/2`, `set_precomments/2`.","ref":"erl_syntax.html#copy_comments/2"},{"type":"function","title":"erl_syntax.copy_pos/2","doc":"Copies the annotation from `Source` to `Target`.\n\nThis is equivalent to [`set_pos(Target, get_pos(Source))`](`set_pos/2`), but\npotentially more efficient.\n\n_See also: _`get_pos/1`, `set_pos/2`.","ref":"erl_syntax.html#copy_pos/2"},{"type":"function","title":"erl_syntax.data/1","doc":"**For special purposes only**. Returns the associated data of a syntax tree node.\n\nEvaluation fails with reason `badarg` if [`is_tree(Node)`](`is_tree/1`) does not\nyield `true`.\n\n_See also: _`tree/2`.","ref":"erl_syntax.html#data/1"},{"type":"function","title":"erl_syntax.disjunction/1","doc":"Creates an abstract disjunction.\n\nIf `List` is `[E1, ..., En]`, the result represents \"`E1; ...; En`\".\n\n_See also: _`conjunction/1`, `disjunction_body/1`.","ref":"erl_syntax.html#disjunction/1"},{"type":"function","title":"erl_syntax.disjunction_body/1","doc":"Returns the list of body subtrees of a `disjunction` node.\n\n_See also: _`disjunction/1`.","ref":"erl_syntax.html#disjunction_body/1"},{"type":"function","title":"erl_syntax.else_expr/1","doc":"Creates an abstract else-expression.\n\nIf `Clauses` is `[C1, ..., Cn]`, the result\nrepresents \"`else C1; ...; Cn end`\". More exactly, if each `Ci` represents\n\"`(Pi) Gi -> Bi`\", then the result represents\n\"`else (P1) G1 -> B1; ...; (Pn) Gn -> Bn end`\".\n\n_See also: _`clause/3`, `else_expr_clauses/1`, `maybe_expr/2`.","ref":"erl_syntax.html#else_expr/1"},{"type":"function","title":"erl_syntax.else_expr_clauses/1","doc":"Returns the list of clause subtrees of an `else_expr` node.\n\n_See also: _`else_expr/1`.","ref":"erl_syntax.html#else_expr_clauses/1"},{"type":"function","title":"erl_syntax.eof_marker/0","doc":"Creates an abstract end-of-file marker.\n\nThis represents the end of input when reading a sequence of source\ncode forms. An end-of-file marker is itself regarded as a source code\nform (namely, the last in any sequence in which it occurs). It has no\ndefined lexical form.\n\n> #### Note {: .info }\n>\n> This is retained only for backwards compatibility with existing parsers\n> and tools.\n\n_See also: _`error_marker/1`, `is_form/1`, `warning_marker/1`.","ref":"erl_syntax.html#eof_marker/0"},{"type":"function","title":"erl_syntax.error_marker/1","doc":"Creates an abstract error marker.\n\nThe result represents an occurrence of an error in the source code,\nwith an associated Erlang I/O ErrorInfo structure given by `Error`\n(see module [`//stdlib/io`](`m:io`) for details). Error markers are\nregarded as source code forms, but have no defined lexical form.\n\n> #### Note {: .info }\n>\n> This is supported only for backwards compatibility with existing parsers\n> and tools.\n\n_See also: _`eof_marker/0`, `error_marker_info/1`, `is_form/1`,\n`warning_marker/1`.","ref":"erl_syntax.html#error_marker/1"},{"type":"function","title":"erl_syntax.error_marker_info/1","doc":"Returns the ErrorInfo structure of an `error_marker` node.\n\n_See also: _`error_marker/1`.","ref":"erl_syntax.html#error_marker_info/1"},{"type":"function","title":"erl_syntax.flatten_form_list/1","doc":"Flattens sublists of a `form_list` node.\n\nReturns `Node` with all subtrees of type `form_list` recursively\nexpanded, yielding a single \"flat\" abstract form sequence.\n\n_See also: _`form_list/1`.","ref":"erl_syntax.html#flatten_form_list/1"},{"type":"function","title":"erl_syntax.float/1","doc":"Creates an abstract floating-point literal.\n\nThe lexical representation is the decimal floating-point numeral of\n`Value`.\n\n_See also: _`float_literal/1`, `float_value/1`.","ref":"erl_syntax.html#float/1"},{"type":"function","title":"erl_syntax.float_literal/1","doc":"Returns the numeral string represented by a `float` node.\n\n_See also: _`float/1`.","ref":"erl_syntax.html#float_literal/1"},{"type":"function","title":"erl_syntax.float_value/1","doc":"Returns the value represented by a `float` node.\n\nNote that floating-point values should usually not be compared for\nequality.\n\n_See also: _`float/1`.","ref":"erl_syntax.html#float_value/1"},{"type":"function","title":"erl_syntax.form_list/1","doc":"Creates an abstract sequence of \"source code forms\".\n\nIf `Forms` is `[F1, ..., Fn]`, where each `Fi` is a form (see\n`is_form/1`), the result represents:\n\n```text\nF1\n...\nFn\n```\n\nwhere the `Fi` are separated by one or more line breaks. A node of type\n`form_list` is itself regarded as a source code form; see `flatten_form_list/1`.\n\n> #### Note {: .info }\n>\n> This is simply a way of grouping source code forms into a single syntax\ntree, usually to form an Erlang module definition.\n\n_See also: _`flatten_form_list/1`, `form_list_elements/1`, `is_form/1`.","ref":"erl_syntax.html#form_list/1"},{"type":"function","title":"erl_syntax.form_list_elements/1","doc":"Returns the list of subnodes of a `form_list` node.\n\n_See also: _`form_list/1`.","ref":"erl_syntax.html#form_list_elements/1"},{"type":"function","title":"erl_syntax.fun_expr/1","doc":"Creates an abstract fun-expression.\n\nIf `Clauses` is `[C1, ..., Cn]`, the result represents \"`fun C1;\n...; Cn end`\". More exactly, if each `Ci` represents \"`(Pi1, ...,\nPim) Gi -> Bi`\", then the result represents \"`fun (P11, ...,\nP1m) G1 -> B1; ...; (Pn1, ..., Pnm) Gn -> Bn end`\".\n\n_See also: _`fun_expr_arity/1`, `fun_expr_clauses/1`.","ref":"erl_syntax.html#fun_expr/1"},{"type":"function","title":"erl_syntax.fun_expr_arity/1","doc":"Returns the arity of a `fun_expr` node.\n\nThe result is the number of parameter patterns in the first clause of\nthe fun-expression; subsequent clauses are ignored.\n\nAn exception is thrown if [`fun_expr_clauses(Node)`](`fun_expr_clauses/1`)\nreturns an empty list, or if the first element of that list is not a syntax tree\n`C` of type `clause` such that [`clause_patterns(C)`](`clause_patterns/1`) is a\nnonempty list.\n\n_See also: _`clause/3`, `clause_patterns/1`, `fun_expr/1`, `fun_expr_clauses/1`.","ref":"erl_syntax.html#fun_expr_arity/1"},{"type":"function","title":"erl_syntax.fun_expr_clauses/1","doc":"Returns the list of clause subtrees of a `fun_expr` node.\n\n_See also: _`fun_expr/1`.","ref":"erl_syntax.html#fun_expr_clauses/1"},{"type":"function","title":"erl_syntax.fun_type/0","doc":"Creates an abstract fun of any type.\n\nThe result represents \"`fun()`\".","ref":"erl_syntax.html#fun_type/0"},{"type":"function","title":"erl_syntax.function/2","doc":"Creates an abstract function definition.\n\nIf `Clauses` is `[C1, ..., Cn]`, the result represents \"`Name C1;\n...; Name Cn.`\". More exactly, if each `Ci` represents \"`(Pi1, ...,\nPim) Gi -> Bi`\", then the result represents \"`Name(P11, ...,\nP1m) G1 -> B1; ...; Name(Pn1, ..., Pnm) Gn -> Bn.`\".\nFunction definitions are source code forms.\n\n_See also: _`function_arity/1`, `function_clauses/1`, `function_name/1`,\n`is_form/1`.","ref":"erl_syntax.html#function/2"},{"type":"function","title":"erl_syntax.function_arity/1","doc":"Returns the arity of a `function` node.\n\nThe result is the number of parameter patterns in the first clause of\nthe function; subsequent clauses are ignored.\n\nAn exception is thrown if [`function_clauses(Node)`](`function_clauses/1`)\nreturns an empty list, or if the first element of that list is not a syntax tree\n`C` of type `clause` such that [`clause_patterns(C)`](`clause_patterns/1`) is a\nnonempty list.\n\n_See also: _`clause/3`, `clause_patterns/1`, `function/2`, `function_clauses/1`.","ref":"erl_syntax.html#function_arity/1"},{"type":"function","title":"erl_syntax.function_clauses/1","doc":"Returns the list of clause subtrees of a `function` node.\n\n_See also: _`function/2`.","ref":"erl_syntax.html#function_clauses/1"},{"type":"function","title":"erl_syntax.function_name/1","doc":"Returns the name subtree of a `function` node.\n\n_See also: _`function/2`.","ref":"erl_syntax.html#function_name/1"},{"type":"function","title":"erl_syntax.function_type/1","doc":"","ref":"erl_syntax.html#function_type/1"},{"type":"function","title":"erl_syntax.function_type/2","doc":"Creates an abstract function type.\n\nIf `Arguments` is `[T1, ..., Tn]` *and* it occurs within a function\nspecification, the result represents \"`(T1, ...Tn) -> Return`\";\notherwise it represents \"`fun((T1, ...Tn) -> Return)`\". If\n`Arguments` is `any_arity`, it represents \"`fun((...) -> Return)`\".\n\nNote that the `m:erl_parse` representation is identical for\n\"`FunctionType`\" and \"`fun(FunctionType)`\".\n\n_See also: _`function_type_arguments/1`, `function_type_return/1`.","ref":"erl_syntax.html#function_type/2"},{"type":"function","title":"erl_syntax.function_type_arguments/1","doc":"Returns the argument types subtrees of a `function_type` node.\n\nIf `Node` represents \"`fun((...) -> Return)`\", `any_arity` is\nreturned; otherwise, if `Node` represents \"`(T1, ...Tn) ->\nReturn`\" or \"`fun((T1, ...Tn) -> Return)`\", `[T1, ..., Tn]` is\nreturned.\n\n_See also: _`function_type/1`, `function_type/2`.","ref":"erl_syntax.html#function_type_arguments/1"},{"type":"function","title":"erl_syntax.function_type_return/1","doc":"Returns the return type subtrees of a `function_type` node.\n\n_See also: _`function_type/1`, `function_type/2`.","ref":"erl_syntax.html#function_type_return/1"},{"type":"function","title":"erl_syntax.generator/2","doc":"Creates an abstract list generator.\n\nThe result represents \"`Pattern <- Body`\".\n\n_See also: _`binary_comp/2`, `generator_body/1`, `generator_pattern/1`,\n`map_comp/2`, `list_comp/2`.","ref":"erl_syntax.html#generator/2"},{"type":"function","title":"erl_syntax.generator_body/1","doc":"Returns the body subtree of a `generator` node.\n\n_See also: _`generator/2`.","ref":"erl_syntax.html#generator_body/1"},{"type":"function","title":"erl_syntax.generator_pattern/1","doc":"Returns the pattern subtree of a `generator` node.\n\n_See also: _`generator/2`.","ref":"erl_syntax.html#generator_pattern/1"},{"type":"function","title":"erl_syntax.get_ann/1","doc":"Returns the list of user annotations associated with a syntax tree.\n\nFor a newly created node, this is the empty list. The annotations may\nbe any terms.\n\n_See also: _`get_attrs/1`, `set_ann/2`.","ref":"erl_syntax.html#get_ann/1"},{"type":"function","title":"erl_syntax.get_attrs/1","doc":"Returns a representation of the attributes associated with a syntax tree node.\n\nThe attributes are all the extra information that can be attached to a node.\nCurrently, this includes position information, source code comments, and user\nannotations. The result of this function cannot be inspected directly; only\nattached to another node (see `set_attrs/2`).\n\nFor accessing individual attributes, see `get_pos/1`, `get_ann/1`,\n`get_precomments/1` and `get_postcomments/1`.\n\n_See also: _`get_ann/1`, `get_pos/1`, `get_postcomments/1`, `get_precomments/1`,\n`set_attrs/2`.","ref":"erl_syntax.html#get_attrs/1"},{"type":"function","title":"erl_syntax.get_pos/1","doc":"Returns the annotation (see [`//stdlib/erl_anno`](`m:erl_anno`)) associated with\n`Node`.\n\nBy default, all new tree nodes have their associated position\ninformation set to the integer zero. Use\n[`//stdlib/erl_anno:location/1`](`erl_anno:location/1`) or\n[`//stdlib/erl_anno:line/1`](`erl_anno:line/1`) to get the position information.\n\n_See also: _`get_attrs/1`, `set_pos/2`.","ref":"erl_syntax.html#get_pos/1"},{"type":"function","title":"erl_syntax.get_postcomments/1","doc":"Returns the associated post-comments of a node.\n\nThis is a possibly empty list of abstract comments, in top-down\ntextual order. When the code is formatted, post-comments are typically\ndisplayed to the right of and/or below the node. For example:\n\n```erlang\n{foo, X, Y} % Post-comment of tuple\n```\n\nIf possible, the comment should be moved past any following separator characters\non the same line, rather than placing the separators on the following line.\nFor example:\n\n```erlang\nfoo([X | Xs], Y) ->\n foo(Xs, bar(X)); % Post-comment of 'bar(X)' node\n ...\n```\n\n(where the comment is moved past the rightmost \"`)`\" and the \"`;`\").\n\n_See also: _`comment/2`, `get_attrs/1`, `get_precomments/1`,\n`set_postcomments/2`.","ref":"erl_syntax.html#get_postcomments/1"},{"type":"function","title":"erl_syntax.get_precomments/1","doc":"Returns the associated pre-comments of a node.\n\nThis is a possibly empty list of abstract comments, in top-down\ntextual order. When the code is formatted, pre-comments are typically\ndisplayed directly above the node. For example:\n\n```erlang\n% Pre-comment of function\nfoo(X) -> {bar, X}.\n```\n\nIf possible, the comment should be moved before any preceding separator\ncharacters on the same line. For example:\n\n```erlang\nfoo([X | Xs]) ->\n % Pre-comment of 'bar(X)' node\n [bar(X) | foo(Xs)];\n...\n```\n\n(where the comment is moved before the \"`[`\").\n\n_See also: _`comment/2`, `get_attrs/1`, `get_postcomments/1`,\n`set_precomments/2`.","ref":"erl_syntax.html#get_precomments/1"},{"type":"function","title":"erl_syntax.has_comments/1","doc":"Yields `false` if the node has no associated comments, and `true` otherwise.\n\nNote: This is equivalent to\n`(get_precomments(Node) == []) and (get_postcomments(Node) == [])`, but\npotentially more efficient.\n\n_See also: _`get_postcomments/1`, `get_precomments/1`, `remove_comments/1`.","ref":"erl_syntax.html#has_comments/1"},{"type":"function","title":"erl_syntax.if_expr/1","doc":"Creates an abstract if-expression.\n\nIf `Clauses` is `[C1, ..., Cn]`, the result represents \"`if C1; ...;\nCn end`\". More exactly, if each `Ci` represents \"`() Gi -> Bi`\",\nthen the result represents \"`if G1 -> B1; ...; Gn -> Bn end`\".\n\n_See also: _`case_expr/2`, `clause/3`, `if_expr_clauses/1`.","ref":"erl_syntax.html#if_expr/1"},{"type":"function","title":"erl_syntax.if_expr_clauses/1","doc":"Returns the list of clause subtrees of an `if_expr` node.\n\n_See also: _`if_expr/1`.","ref":"erl_syntax.html#if_expr_clauses/1"},{"type":"function","title":"erl_syntax.implicit_fun/1","doc":"Creates an abstract \"implicit fun\" expression.\n\nThe result represents \"`fun Name`\". `Name` should represent either\n`F/A` or `M:F/A`\n\n_See also: _`arity_qualifier/2`, `implicit_fun/2`, `implicit_fun/3`,\n`implicit_fun_name/1`, `module_qualifier/2`.","ref":"erl_syntax.html#implicit_fun/1"},{"type":"function","title":"erl_syntax.implicit_fun/2","doc":"Creates an abstract \"implicit fun\" expression.\n\nIf `Arity` is `none`, this is equivalent to\n[`implicit_fun(Name)`](`implicit_fun/1`), otherwise it is equivalent\nto [`implicit_fun(arity_qualifier(Name, Arity))`](`implicit_fun/1`).\n\n(This is a utility function.)\n\n_See also: _`implicit_fun/1`, `implicit_fun/3`.","ref":"erl_syntax.html#implicit_fun/2"},{"type":"function","title":"erl_syntax.implicit_fun/3","doc":"Creates an abstract module-qualified \"implicit fun\" expression.\n\nIf `Module` is `none`, this is equivalent to [`implicit_fun(Name,\nArity)`](`implicit_fun/2`), otherwise it is equivalent to\n`implicit_fun(module_qualifier(Module, arity_qualifier(Name, Arity))`.\n\n(This is a utility function.)\n\n_See also: _`implicit_fun/1`, `implicit_fun/2`.","ref":"erl_syntax.html#implicit_fun/3"},{"type":"function","title":"erl_syntax.implicit_fun_name/1","doc":"Returns the name subtree of an `implicit_fun` node.\n\nIf `Node` represents \"`fun N/A`\" or \"`fun M:N/A`\", then the\nresult is the subtree representing \"`N/A`\" or \"`M:N/A`\", respectively.\n\n_See also: _`arity_qualifier/2`, `implicit_fun/1`, `module_qualifier/2`.","ref":"erl_syntax.html#implicit_fun_name/1"},{"type":"function","title":"erl_syntax.infix_expr/3","doc":"Creates an abstract infix operator expression.\n\nThe result represents \"`Left Operator Right`\".\n\n_See also: _`infix_expr_left/1`, `infix_expr_operator/1`, `infix_expr_right/1`,\n`prefix_expr/2`.","ref":"erl_syntax.html#infix_expr/3"},{"type":"function","title":"erl_syntax.infix_expr_left/1","doc":"Returns the left argument subtree of an `infix_expr` node.\n\n_See also: _`infix_expr/3`.","ref":"erl_syntax.html#infix_expr_left/1"},{"type":"function","title":"erl_syntax.infix_expr_operator/1","doc":"Returns the operator subtree of an `infix_expr` node.\n\n_See also: _`infix_expr/3`.","ref":"erl_syntax.html#infix_expr_operator/1"},{"type":"function","title":"erl_syntax.infix_expr_right/1","doc":"Returns the right argument subtree of an `infix_expr` node.\n\n_See also: _`infix_expr/3`.","ref":"erl_syntax.html#infix_expr_right/1"},{"type":"function","title":"erl_syntax.integer/1","doc":"Creates an abstract integer literal.\n\nThe lexical representation is the canonical decimal numeral of `Value`.\n\n_See also: _`integer_literal/1`, `integer_value/1`, `is_integer/2`.","ref":"erl_syntax.html#integer/1"},{"type":"function","title":"erl_syntax.integer_literal/1","doc":"Returns the numeral string represented by an `integer` node.\n\n_See also: _`integer/1`.","ref":"erl_syntax.html#integer_literal/1"},{"type":"function","title":"erl_syntax.integer_range_type/2","doc":"Creates an abstract range type.\n\nThe result represents \"`Low .. High`\".\n\n_See also: _`integer_range_type_high/1`, `integer_range_type_low/1`.","ref":"erl_syntax.html#integer_range_type/2"},{"type":"function","title":"erl_syntax.integer_range_type_high/1","doc":"Returns the high limit of an `integer_range_type` node.\n\n_See also: _`integer_range_type/2`.","ref":"erl_syntax.html#integer_range_type_high/1"},{"type":"function","title":"erl_syntax.integer_range_type_low/1","doc":"Returns the low limit of an `integer_range_type` node.\n\n_See also: _`integer_range_type/2`.","ref":"erl_syntax.html#integer_range_type_low/1"},{"type":"function","title":"erl_syntax.integer_value/1","doc":"Returns the value represented by an `integer` node.\n\n_See also: _`integer/1`.","ref":"erl_syntax.html#integer_value/1"},{"type":"function","title":"erl_syntax.is_atom/2","doc":"Returns `true` if `Node` has type `atom` and represents `Value`, otherwise\n`false`.\n\n_See also: _`atom/1`.","ref":"erl_syntax.html#is_atom/2"},{"type":"function","title":"erl_syntax.is_char/2","doc":"Returns `true` if `Node` has type `char` and represents `Value`, otherwise\n`false`.\n\n_See also: _`char/1`.","ref":"erl_syntax.html#is_char/2"},{"type":"function","title":"erl_syntax.is_form/1","doc":"Returns `true` if `Node` is a syntax tree representing a so-called \"source code\nform\", otherwise `false`.\n\nForms are the Erlang source code units which, placed in sequence,\nconstitute an Erlang program. Current form types are:\n\n* `attribute`\n* `comment`\n* `error_marker`\n* `eof_marker`\n* `form_list`\n* `function`\n* `warning_marker`\n* `text`\n\n\n_See also: _`attribute/2`, `comment/2`, `eof_marker/0`, `error_marker/1`,\n`form_list/1`, `function/2`, `type/1`, `warning_marker/1`.","ref":"erl_syntax.html#is_form/1"},{"type":"function","title":"erl_syntax.is_integer/2","doc":"Returns `true` if `Node` has type `integer` and represents `Value`, otherwise\n`false`.\n\n_See also: _`integer/1`.","ref":"erl_syntax.html#is_integer/2"},{"type":"function","title":"erl_syntax.is_leaf/1","doc":"Returns `true` if `Node` is a leaf node, otherwise `false`.\n\nThe currently recognised leaf node types are:\n\n* `atom`\n* `char`\n* `comment`\n* `eof_marker`\n* `error_marker`\n* `float`\n* `fun_type`\n* `integer`\n* `nil`\n* `operator`\n* `string`\n* `text`\n* `underscore`\n* `variable`\n* `warning_marker`\n\nA node of type `map_expr` is a leaf node if and only if it has no argument and\nno fields. A node of type `map_type` is a leaf node if and only if it has no\nfields (`any_size`). A node of type `tuple` is a leaf node if and only if its\narity is zero. A node of type `tuple_type` is a leaf node if and only if it has\nno elements (`any_size`).\n\nNote: not all literals are leaf nodes, and vice versa. For example,\ntuples with nonzero arity and nonempty lists may be literals, but are\nnot leaf nodes. Variables, on the other hand, are leaf nodes but not\nliterals.\n\n_See also: _`is_literal/1`, `type/1`.","ref":"erl_syntax.html#is_leaf/1"},{"type":"function","title":"erl_syntax.is_list_skeleton/1","doc":"Returns `true` if `Node` has type `list` or `nil`, otherwise `false`.\n\n_See also: _`list/2`, `nil/0`.","ref":"erl_syntax.html#is_list_skeleton/1"},{"type":"function","title":"erl_syntax.is_literal/1","doc":"Returns `true` if `Node` represents a literal term, otherwise `false`.\n\nThis function returns `true` if and only if the value of\n[`concrete(Node)`](`concrete/1`) is defined.\n\n_See also: _`abstract/1`, `concrete/1`.","ref":"erl_syntax.html#is_literal/1"},{"type":"function","title":"erl_syntax.is_proper_list/1","doc":"Returns `true` if `Node` represents a proper list, and `false` otherwise.\n\nA proper list is a list skeleton either on the form \"`[]`\" or \"`[E1,\n..., En]`\", or \"`[... | Tail]`\" where recursively `Tail` also\nrepresents a proper list.\n\n> #### Note {: .info }\n>\n> Since `Node` is a syntax tree, the actual run-time values\n> corresponding to its subtrees can often be partially or completely\n> unknown. For example, if `Node` represents \"`[... | Ns]`\"\n> (where `Ns` is a variable), the function will return `false`\n> because it is not known whether `Ns` will be bound to a list at\n> run-time. Conversely, if `Node` represents, for example, \"`[1, 2, 3]`\" or\n> \"`[A | []]`\", the function will return `true`.\n\n_See also: _`list/2`.","ref":"erl_syntax.html#is_proper_list/1"},{"type":"function","title":"erl_syntax.is_string/2","doc":"Returns `true` if `Node` has type `string` and represents `Value`, otherwise\n`false`.\n\n_See also: _`string/1`.","ref":"erl_syntax.html#is_string/2"},{"type":"function","title":"erl_syntax.is_tree/1","doc":"**For special purposes only**. Returns `true` if `Tree` is an abstract syntax tree\nand `false` otherwise.\n\n> #### Note {: .info }\n>\n> This function yields `false` for all \"old-style\" `m:erl_parse`-compatible\n> \"parse trees\".\n\n_See also: _`tree/2`.","ref":"erl_syntax.html#is_tree/1"},{"type":"function","title":"erl_syntax.join_comments/2","doc":"Appends the comments of `Source` to the current comments of `Target`.\n\nNote: This is equivalent to\n[`add_postcomments(get_postcomments(Source), add_precomments(get_precomments(Source), Target))`](`add_postcomments/2`),\nbut potentially more efficient.\n\n_See also: _`add_postcomments/2`, `add_precomments/2`, `comment/2`,\n`get_postcomments/1`, `get_precomments/1`.","ref":"erl_syntax.html#join_comments/2"},{"type":"function","title":"erl_syntax.list/1","doc":"","ref":"erl_syntax.html#list/1"},{"type":"function","title":"erl_syntax.list/2","doc":"Constructs an abstract list skeleton.\n\nThe result has type `list` or `nil`. If `List` is a nonempty list\n`[E1, ..., En]`, the result has type `list` and represents either\n\"`[E1, ..., En]`\" if `Tail` is `none`, or otherwise \"`[E1, ...,\nEn | Tail]`\". If `List` is the empty list, `Tail` _must_ be `none`,\nand in that case the result has type `nil` and represents \"`[]`\" (see\n`nil/0`).\n\nThe difference between lists as semantic objects (built up of individual \"cons\"\nand \"nil\" terms) and the various syntactic forms for denoting lists may be\nbewildering at first. This module provides functions both for exact control of\nthe syntactic representation as well as for the simple composition and\ndeconstruction in terms of cons and head/tail operations.\n\n> #### Note {: .info }\n>\n> In [`list(Elements, none)`](`list/2`), the \"nil\" list terminator is\n> implicit and has no associated information (see `get_attrs/1`). However,\n> in the seemingly equivalent [`list(Elements, Tail)`](`list/2`) where\n> `Tail` has the type `nil`, the list terminator subtree `Tail` may have\n> attached attributes such as position, comments, and annotations, which\n> will be preserved in the result.\n\n_See also: _`compact_list/1`, `cons/2`, `get_attrs/1`, `is_list_skeleton/1`,\n`is_proper_list/1`, `list/1`, `list_elements/1`, `list_head/1`, `list_length/1`,\n`list_prefix/1`, `list_suffix/1`, `list_tail/1`, `nil/0`, `normalize_list/1`.","ref":"erl_syntax.html#list/2"},{"type":"function","title":"erl_syntax.list_comp/2","doc":"Creates an abstract list comprehension.\n\nIf `Body` is `[E1, ..., En]`, the result represents \"`[Template ||\nE1, ..., En]`\".\n\n_See also: _`generator/2`, `list_comp_body/1`, `list_comp_template/1`.","ref":"erl_syntax.html#list_comp/2"},{"type":"function","title":"erl_syntax.list_comp_body/1","doc":"Returns the list of body subtrees of a `list_comp` node.\n\n_See also: _`list_comp/2`.","ref":"erl_syntax.html#list_comp_body/1"},{"type":"function","title":"erl_syntax.list_comp_template/1","doc":"Returns the template subtree of a `list_comp` node.\n\n_See also: _`list_comp/2`.","ref":"erl_syntax.html#list_comp_template/1"},{"type":"function","title":"erl_syntax.list_elements/1","doc":"Returns the list of element subtrees of a list skeleton.\n\n`Node` must represent a proper list. For example, if `Node` represents\n\"`[X1, X2 | [X3, X4 | []]`\", then\n[`list_elements(Node)`](`list_elements/1`) yields the list `[X1, X2,\nX3, X4]`.\n\n_See also: _`is_proper_list/1`, `list/2`.","ref":"erl_syntax.html#list_elements/1"},{"type":"function","title":"erl_syntax.list_head/1","doc":"Returns the head element subtree of a `list` node.\n\nIf `Node` represents \"`[Head ...]`\", the result will represent \"`Head`\".\n\n_See also: _`cons/2`, `list/2`, `list_tail/1`.","ref":"erl_syntax.html#list_head/1"},{"type":"function","title":"erl_syntax.list_length/1","doc":"Returns the number of element subtrees of a list skeleton.\n\n`Node` must represent a proper list. For example, if `Node` represents\n\"`[X1 | [X2, X3 | [X4, X5, X6]]]`\", then\n[`list_length(Node)`](`list_length/1`) returns the integer 6.\n\n> #### Note {: .info }\n>\n> This is equivalent to [`length(list_elements(Node))`](`length/1`), but\n> potentially more efficient.\n\n_See also: _`is_proper_list/1`, `list/2`, `list_elements/1`.","ref":"erl_syntax.html#list_length/1"},{"type":"function","title":"erl_syntax.list_prefix/1","doc":"Returns the prefix element subtrees of a `list` node.\n\nIf `Node` represents \"`[E1, ..., En]`\" or \"`[E1, ..., En |\nTail]`\", the returned value is `[E1, ..., En]`.\n\n_See also: _`list/2`.","ref":"erl_syntax.html#list_prefix/1"},{"type":"function","title":"erl_syntax.list_suffix/1","doc":"Returns the suffix subtree of a `list` node, if one exists.\n\nIf `Node` represents \"`[E1, ..., En | Tail]`\", the returned value is\n`Tail`. Otherwise, if `Node` represents \"`[E1, ..., En]`\", `none` is\nreturned.\n\n> #### Note {: .info }\n>\n> Even if this function returns a `Tail` that is not `none`, the type\n> of `Tail` can be `nil` if the tail has been given explicitly and the\n> list skeleton has not been compacted (see `compact_list/1`).\n\n_See also: _`compact_list/1`, `list/2`, `nil/0`.","ref":"erl_syntax.html#list_suffix/1"},{"type":"function","title":"erl_syntax.list_tail/1","doc":"Returns the tail of a `list` node.\n\nIf `Node` represents a single-element list \"`[E]`\", then the result\nhas type `nil`, representing \"`[]`\". If `Node` represents \"`[E1,\nE2 ...]`\", the result will represent \"`[E2 ...]`\", and if `Node`\nrepresents \"`[Head | Tail]`\", the result will represent\n\"`Tail`\".\n\n_See also: _`cons/2`, `list/2`, `list_head/1`.","ref":"erl_syntax.html#list_tail/1"},{"type":"function","title":"erl_syntax.macro/1","doc":"","ref":"erl_syntax.html#macro/1"},{"type":"function","title":"erl_syntax.macro/2","doc":"Creates an abstract macro application.\n\nIf `Arguments` is `none`, the result represents \"`?Name`\",\notherwise, if `Arguments` is `[A1, ..., An]`, the result represents\n\"`?Name(A1, ..., An)`\".\n\nNotes: if `Arguments` is the empty list, the result will thus represent\n\"`?Name()`\", including a pair of matching parentheses.\n\nThe only syntactical limitation imposed by the preprocessor on the arguments to\na macro application (viewed as sequences of tokens) is that they must be\nbalanced with respect to parentheses, brackets, `begin ... end`, `case ... end`,\nand so on. The `text` node type can be used to represent arguments which are not\nregular Erlang constructs.\n\n_See also: _`macro/1`, `macro_arguments/1`, `macro_name/1`, `text/1`.","ref":"erl_syntax.html#macro/2"},{"type":"function","title":"erl_syntax.macro_arguments/1","doc":"Returns the list of argument subtrees of a `macro` node, if any.\n\nIf `Node` represents \"`?Name`\", `none` is returned. Otherwise, if\n`Node` represents \"`?Name(A1, ..., An)`\", `[A1, ..., An]` is\nreturned.\n\n_See also: _`macro/2`.","ref":"erl_syntax.html#macro_arguments/1"},{"type":"function","title":"erl_syntax.macro_name/1","doc":"Returns the name subtree of a `macro` node.\n\n_See also: _`macro/2`.","ref":"erl_syntax.html#macro_name/1"},{"type":"function","title":"erl_syntax.make_tree/2","doc":"Creates a syntax tree with the given type and subtrees.\n\n`Type` must be a node type name (see `type/1`) that does not denote a\nleaf node type (see `is_leaf/1`). `Groups` must be a _nonempty_ list\nof groups of syntax trees, representing the subtrees of a node of the\ngiven type, in left-to-right order as they would occur in the printed\nprogram text, grouped by category as done by `subtrees/1`.\n\nThe result of\n[`copy_attrs(Node, make_tree(type(Node), subtrees(Node)))`](`copy_attrs/2`) (see\n`update_tree/2`) represents the same source code text as the original `Node`,\nassuming that [`subtrees(Node)`](`subtrees/1`) yields a nonempty list. However,\nit does not necessarily have the same data representation as `Node`.\n\n_See also: _`copy_attrs/2`, `is_leaf/1`, `subtrees/1`, `type/1`,\n`update_tree/2`.","ref":"erl_syntax.html#make_tree/2"},{"type":"function","title":"erl_syntax.map_comp/2","doc":"Creates an abstract map comprehension.\n\nIf `Body` is `[E1, ..., En]`, the result represents \"`#{Template ||\nE1, ..., En}`\".\n\n_See also: _`generator/2`, `map_comp_body/1`, `map_comp_template/1`.","ref":"erl_syntax.html#map_comp/2"},{"type":"function","title":"erl_syntax.map_comp_body/1","doc":"Returns the list of body subtrees of a `map_comp` node.\n\n_See also: _`map_comp/2`.","ref":"erl_syntax.html#map_comp_body/1"},{"type":"function","title":"erl_syntax.map_comp_template/1","doc":"Returns the template subtree of a `map_comp` node.\n\n_See also: _`map_comp/2`.","ref":"erl_syntax.html#map_comp_template/1"},{"type":"function","title":"erl_syntax.map_expr/1","doc":"","ref":"erl_syntax.html#map_expr/1"},{"type":"function","title":"erl_syntax.map_expr/2","doc":"Creates an abstract map expression.\n\nIf `Fields` is `[F1, ..., Fn]`, then if `Argument` is `none`, the\nresult represents \"`#{F1, ..., Fn}`\", otherwise it represents\n\"`Argument#{F1, ..., Fn}`\".\n\n_See also: _`map_expr/1`, `map_expr_argument/1`, `map_expr_fields/1`,\n`map_field_assoc/2`, `map_field_exact/2`.","ref":"erl_syntax.html#map_expr/2"},{"type":"function","title":"erl_syntax.map_expr_argument/1","doc":"Returns the argument subtree of a `map_expr` node, if any.\n\nIf `Node` represents \"`#{...}`\", `none` is returned. Otherwise, if\n`Node` represents \"`Argument#{...}`\", `Argument` is returned.\n\n_See also: _`map_expr/2`.","ref":"erl_syntax.html#map_expr_argument/1"},{"type":"function","title":"erl_syntax.map_expr_fields/1","doc":"Returns the list of field subtrees of a `map_expr` node.\n\n_See also: _`map_expr/2`.","ref":"erl_syntax.html#map_expr_fields/1"},{"type":"function","title":"erl_syntax.map_field_assoc/2","doc":"Creates an abstract map assoc field.\n\nThe result represents \"`Name => Value`\".\n\n_See also: _`map_expr/2`, `map_field_assoc_name/1`, `map_field_assoc_value/1`.","ref":"erl_syntax.html#map_field_assoc/2"},{"type":"function","title":"erl_syntax.map_field_assoc_name/1","doc":"Returns the name subtree of a `map_field_assoc` node.\n\n_See also: _`map_field_assoc/2`.","ref":"erl_syntax.html#map_field_assoc_name/1"},{"type":"function","title":"erl_syntax.map_field_assoc_value/1","doc":"Returns the value subtree of a `map_field_assoc` node.\n\n_See also: _`map_field_assoc/2`.","ref":"erl_syntax.html#map_field_assoc_value/1"},{"type":"function","title":"erl_syntax.map_field_exact/2","doc":"Creates an abstract map exact field.\n\nThe result represents \"`Name := Value`\".\n\n_See also: _`map_expr/2`, `map_field_exact_name/1`, `map_field_exact_value/1`.","ref":"erl_syntax.html#map_field_exact/2"},{"type":"function","title":"erl_syntax.map_field_exact_name/1","doc":"Returns the name subtree of a `map_field_exact` node.\n\n_See also: _`map_field_exact/2`.","ref":"erl_syntax.html#map_field_exact_name/1"},{"type":"function","title":"erl_syntax.map_field_exact_value/1","doc":"Returns the value subtree of a `map_field_exact` node.\n\n_See also: _`map_field_exact/2`.","ref":"erl_syntax.html#map_field_exact_value/1"},{"type":"function","title":"erl_syntax.map_generator/2","doc":"Creates an abstract map_generator.\n\nThe result represents \"`Pattern <- Body`\".\n\n_See also: _`binary_comp/2`, `list_comp/2`, `map_comp/2`, `map_generator_body/1`,\n`map_generator_pattern/1`.","ref":"erl_syntax.html#map_generator/2"},{"type":"function","title":"erl_syntax.map_generator_body/1","doc":"Returns the body subtree of a `map_generator` node.\n\n_See also: _`map_generator/2`.","ref":"erl_syntax.html#map_generator_body/1"},{"type":"function","title":"erl_syntax.map_generator_pattern/1","doc":"Returns the pattern subtree of a `map_generator` node.\n\n_See also: _`map_generator/2`.","ref":"erl_syntax.html#map_generator_pattern/1"},{"type":"function","title":"erl_syntax.map_type/0","doc":"","ref":"erl_syntax.html#map_type/0"},{"type":"function","title":"erl_syntax.map_type/1","doc":"Creates an abstract type map.\n\nIf `Fields` is `[F1, ..., Fn]`, the result represents \"`#{F1, ...,\nFn}`\"; otherwise, if `Fields` is `any_size`, it represents\n\"`t:map/0`\".\n\n_See also: _`map_type_fields/1`.","ref":"erl_syntax.html#map_type/1"},{"type":"function","title":"erl_syntax.map_type_assoc/2","doc":"Creates an abstract map type assoc field.\n\nThe result represents \"`Name => Value`\".\n\n_See also: _`map_type/1`, `map_type_assoc_name/1`, `map_type_assoc_value/1`.","ref":"erl_syntax.html#map_type_assoc/2"},{"type":"function","title":"erl_syntax.map_type_assoc_name/1","doc":"Returns the name subtree of a `map_type_assoc` node.\n\n_See also: _`map_type_assoc/2`.","ref":"erl_syntax.html#map_type_assoc_name/1"},{"type":"function","title":"erl_syntax.map_type_assoc_value/1","doc":"Returns the value subtree of a `map_type_assoc` node.\n\n_See also: _`map_type_assoc/2`.","ref":"erl_syntax.html#map_type_assoc_value/1"},{"type":"function","title":"erl_syntax.map_type_exact/2","doc":"Creates an abstract map type exact field.\n\nThe result represents \"`Name := Value`\".\n\n_See also: _`map_type/1`, `map_type_exact_name/1`, `map_type_exact_value/1`.","ref":"erl_syntax.html#map_type_exact/2"},{"type":"function","title":"erl_syntax.map_type_exact_name/1","doc":"Returns the name subtree of a `map_type_exact` node.\n\n_See also: _`map_type_exact/2`.","ref":"erl_syntax.html#map_type_exact_name/1"},{"type":"function","title":"erl_syntax.map_type_exact_value/1","doc":"Returns the value subtree of a `map_type_exact` node.\n\n_See also: _`map_type_exact/2`.","ref":"erl_syntax.html#map_type_exact_value/1"},{"type":"function","title":"erl_syntax.map_type_fields/1","doc":"Returns the list of field subtrees of a `map_type` node.\n\nIf `Node` represents \"`t:map/0`\", `any_size` is returned; otherwise,\nif `Node` represents \"`#{F1, ..., Fn}`\", `[F1, ..., Fn]` is\nreturned.\n\n_See also: _`map_type/0`, `map_type/1`.","ref":"erl_syntax.html#map_type_fields/1"},{"type":"function","title":"erl_syntax.match_expr/2","doc":"Creates an abstract match-expression.\n\nThe result represents \"`Pattern = Body`\".\n\n_See also: _`match_expr_body/1`, `match_expr_pattern/1`.","ref":"erl_syntax.html#match_expr/2"},{"type":"function","title":"erl_syntax.match_expr_body/1","doc":"Returns the body subtree of a `match_expr` node.\n\n_See also: _`match_expr/2`.","ref":"erl_syntax.html#match_expr_body/1"},{"type":"function","title":"erl_syntax.match_expr_pattern/1","doc":"Returns the pattern subtree of a `match_expr` node.\n\n_See also: _`match_expr/2`.","ref":"erl_syntax.html#match_expr_pattern/1"},{"type":"function","title":"erl_syntax.maybe_expr/1","doc":"","ref":"erl_syntax.html#maybe_expr/1"},{"type":"function","title":"erl_syntax.maybe_expr/2","doc":"Creates an abstract maybe-expression.\n\nIf `Body` is `[B1, ..., Bn]`, and `OptionalElse` is `none`, the result\nrepresents \"`maybe B1, ..., Bn end`\". If `Body` is `[B1, ...,\nBn]`, and `OptionalElse` reprsents an `else_expr` node with clauses\n`[C1, ..., Cn]`, the result represents \"`maybe B1, ..., Bn else\nC1; ..., Cn end`\".\n\nSee `clause` for documentation on `m:erl_parse` clauses.\n\n_See also: _`maybe_expr_body/1`, `maybe_expr_else/1`.","ref":"erl_syntax.html#maybe_expr/2"},{"type":"function","title":"erl_syntax.maybe_expr_body/1","doc":"Returns the list of body subtrees of a `maybe_expr` node.\n\n_See also: _`maybe_expr/2`.","ref":"erl_syntax.html#maybe_expr_body/1"},{"type":"function","title":"erl_syntax.maybe_expr_else/1","doc":"Returns the else subtree of a `maybe_expr` node.\n\n_See also: _`maybe_expr/2`.","ref":"erl_syntax.html#maybe_expr_else/1"},{"type":"function","title":"erl_syntax.maybe_match_expr/2","doc":"Creates an abstract maybe-expression, as used in `maybe` blocks.\n\nThe result represents \"`Pattern ?= Body`\".\n\n_See also: _`maybe_expr/2`, `maybe_match_expr_body/1`,\n`maybe_match_expr_pattern/1`.","ref":"erl_syntax.html#maybe_match_expr/2"},{"type":"function","title":"erl_syntax.maybe_match_expr_body/1","doc":"Returns the body subtree of a `maybe_expr` node.\n\n_See also: _`maybe_match_expr/2`.","ref":"erl_syntax.html#maybe_match_expr_body/1"},{"type":"function","title":"erl_syntax.maybe_match_expr_pattern/1","doc":"Returns the pattern subtree of a `maybe_expr` node.\n\n_See also: _`maybe_match_expr/2`.","ref":"erl_syntax.html#maybe_match_expr_pattern/1"},{"type":"function","title":"erl_syntax.meta/1","doc":"Creates a meta-representation of a syntax tree.\n\nThe result represents an Erlang expression \"`MetaTree`\" which, if\nevaluated, will yield a new syntax tree representing the same source\ncode text as `Tree` (although the actual data representation may be\ndifferent). The expression represented by `MetaTree` is\n_implementation independent_ with regard to the data structures used\nby the abstract syntax tree implementation. Comments attached to nodes\nof `Tree` will be preserved, but other attributes are lost.\n\nAny node in `Tree` whose node type is `variable` (see `type/1`), and whose list\nof annotations (see `get_ann/1`) contains the atom `meta_var`, will remain\nunchanged in the resulting tree, except that exactly one occurrence of\n`meta_var` is removed from its annotation list.\n\nThe main use of the function [`meta/1`](`meta/1`) is to transform a\ndata structure `Tree`, which represents a piece of program code, into\na form that is _representation independent when printed_. For example,\nsuppose `Tree` represents a variable named \"V\". Then (assuming a\nfunction `print/1` for printing syntax trees), evaluating\n`print(abstract(Tree))` — simply using `abstract/1` to map the actual\ndata structure onto a syntax tree representation — would output a\nstring that might look something like \"`{tree, variable, ..., \"V\",\n...}`\", which is obviously dependent on the implementation of the\nabstract syntax trees. This could, for example, be useful for caching\na syntax tree in a file. However, in some situations like in a program\ngenerator generator (with two \"generator\"), it may be\nunacceptable. Using `print(meta(Tree))` instead would output a\n_representation independent_ syntax tree generating expression; in the\nabove case, something like \"`erl_syntax:variable(\"V\")`\".\n\n_See also: _`abstract/1`, `get_ann/1`, `type/1`.","ref":"erl_syntax.html#meta/1"},{"type":"function","title":"erl_syntax.module_qualifier/2","doc":"Creates an abstract module qualifier.\n\nThe result represents \"`Module:Body`\".\n\n_See also: _`module_qualifier_argument/1`, `module_qualifier_body/1`.","ref":"erl_syntax.html#module_qualifier/2"},{"type":"function","title":"erl_syntax.module_qualifier_argument/1","doc":"Returns the argument (the module) subtree of a `module_qualifier` node.\n\n_See also: _`module_qualifier/2`.","ref":"erl_syntax.html#module_qualifier_argument/1"},{"type":"function","title":"erl_syntax.module_qualifier_body/1","doc":"Returns the body subtree of a `module_qualifier` node.\n\n_See also: _`module_qualifier/2`.","ref":"erl_syntax.html#module_qualifier_body/1"},{"type":"function","title":"erl_syntax.named_fun_expr/2","doc":"Creates an abstract named fun-expression.\n\nIf `Clauses` is `[C1, ..., Cn]`, the result represents \"`fun\nName C1; ...; Name Cn end`\". More exactly, if each `Ci`\nrepresents \"`(Pi1, ..., Pim) Gi -> Bi`\", then the result\nrepresents \"`fun Name(P11, ..., P1m) G1 -> B1; ...;\nName(Pn1, ..., Pnm) Gn -> Bn end`\".\n\n_See also: _`named_fun_expr_arity/1`, `named_fun_expr_clauses/1`,\n`named_fun_expr_name/1`.","ref":"erl_syntax.html#named_fun_expr/2"},{"type":"function","title":"erl_syntax.named_fun_expr_arity/1","doc":"Returns the arity of a `named_fun_expr` node.\n\nThe result is the number of parameter patterns in the first clause of\nthe named fun-expression; subsequent clauses are ignored.\n\nAn exception is thrown if\n[`named_fun_expr_clauses(Node)`](`named_fun_expr_clauses/1`) returns an empty\nlist, or if the first element of that list is not a syntax tree `C` of type\n`clause` such that [`clause_patterns(C)`](`clause_patterns/1`) is a nonempty\nlist.\n\n_See also: _`clause/3`, `clause_patterns/1`, `named_fun_expr/2`,\n`named_fun_expr_clauses/1`.","ref":"erl_syntax.html#named_fun_expr_arity/1"},{"type":"function","title":"erl_syntax.named_fun_expr_clauses/1","doc":"Returns the list of clause subtrees of a `named_fun_expr` node.\n\n_See also: _`named_fun_expr/2`.","ref":"erl_syntax.html#named_fun_expr_clauses/1"},{"type":"function","title":"erl_syntax.named_fun_expr_name/1","doc":"Returns the name subtree of a `named_fun_expr` node.\n\n_See also: _`named_fun_expr/2`.","ref":"erl_syntax.html#named_fun_expr_name/1"},{"type":"function","title":"erl_syntax.normalize_list/1","doc":"Expands an abstract list skeleton to its most explicit form.\n\nIf `Node` represents \"`[E1, ..., En | Tail]`\", the result\nrepresents \"`[E1 | ... [En | Tail1] ... ]`\", where `Tail1` is\nthe result of [`normalize_list(Tail)`](`normalize_list/1`). If `Node`\nrepresents \"`[E1, ..., En]`\", the result simply represents \"`[E1\n| ... [En | []] ... ]`\". If `Node` does not represent a list\nskeleton, `Node` itself is returned.\n\n_See also: _`compact_list/1`, `list/2`.","ref":"erl_syntax.html#normalize_list/1"},{"type":"function","title":"erl_syntax.operator/1","doc":"Creates an abstract operator.\n\nThe name of the operator is the character sequence represented by\n`Name`. This is analogous to the print name of an atom, but an\noperator is never written within single-quotes; for example, the\nresult of [`operator('++')`](`operator/1`) represents \"`++`\" rather\nthan \"`'++'`\".\n\n_See also: _`atom/1`, `operator_literal/1`, `operator_name/1`.","ref":"erl_syntax.html#operator/1"},{"type":"function","title":"erl_syntax.operator_literal/1","doc":"Returns the literal string represented by an `operator` node.\n\nThis is simply the operator name as a string.\n\n_See also: _`operator/1`.","ref":"erl_syntax.html#operator_literal/1"},{"type":"function","title":"erl_syntax.operator_name/1","doc":"Returns the name of an `operator` node.\n\nNote that the name is returned as an atom.\n\n_See also: _`operator/1`.","ref":"erl_syntax.html#operator_name/1"},{"type":"function","title":"erl_syntax.parentheses/1","doc":"Creates an abstract parenthesised expression.\n\nThe result represents \"`(Body)`\", independently of the context.\n\n_See also: _`parentheses_body/1`.","ref":"erl_syntax.html#parentheses/1"},{"type":"function","title":"erl_syntax.parentheses_body/1","doc":"Returns the body subtree of a `parentheses` node.\n\n_See also: _`parentheses/1`.","ref":"erl_syntax.html#parentheses_body/1"},{"type":"function","title":"erl_syntax.prefix_expr/2","doc":"Creates an abstract prefix operator expression.\n\nThe result represents \"`Operator Argument`\".\n\n_See also: _`infix_expr/3`, `prefix_expr_argument/1`, `prefix_expr_operator/1`.","ref":"erl_syntax.html#prefix_expr/2"},{"type":"function","title":"erl_syntax.prefix_expr_argument/1","doc":"Returns the argument subtree of a `prefix_expr` node.\n\n_See also: _`prefix_expr/2`.","ref":"erl_syntax.html#prefix_expr_argument/1"},{"type":"function","title":"erl_syntax.prefix_expr_operator/1","doc":"Returns the operator subtree of a `prefix_expr` node.\n\n_See also: _`prefix_expr/2`.","ref":"erl_syntax.html#prefix_expr_operator/1"},{"type":"function","title":"erl_syntax.receive_expr/1","doc":"","ref":"erl_syntax.html#receive_expr/1"},{"type":"function","title":"erl_syntax.receive_expr/3","doc":"Creates an abstract receive-expression.\n\nIf `Timeout` is `none`, the result represents \"`receive C1; ...;\nCn end`\" (the `Action` argument is ignored). Otherwise, if\n`Clauses` is `[C1, ..., Cn]` and `Action` is `[A1, ..., Am]`, the\nresult represents \"`receive C1; ...; Cn after Timeout -> A1,\n..., Am end`\". More exactly, if each `Ci` represents \"`(Pi) Gi\n-> Bi`\", then the result represents \"`receive P1 G1 -> B1; ...;\nPn Gn -> Bn ... end`\".\n\nNote that in Erlang, a receive-expression must have at least one clause if no\ntimeout part is specified.\n\n_See also: _`case_expr/2`, `clause/3`, `receive_expr/1`,\n`receive_expr_action/1`, `receive_expr_clauses/1`, `receive_expr_timeout/1`.","ref":"erl_syntax.html#receive_expr/3"},{"type":"function","title":"erl_syntax.receive_expr_action/1","doc":"Returns the list of action body subtrees of a `receive_expr` node.\n\nIf `Node` represents \"`receive C1; ...; Cn end`\", this is the\nempty list.\n\n_See also: _`receive_expr/3`.","ref":"erl_syntax.html#receive_expr_action/1"},{"type":"function","title":"erl_syntax.receive_expr_clauses/1","doc":"Returns the list of clause subtrees of a `receive_expr` node.\n\n_See also: _`receive_expr/3`.","ref":"erl_syntax.html#receive_expr_clauses/1"},{"type":"function","title":"erl_syntax.receive_expr_timeout/1","doc":"Returns the timeout subtree of a `receive_expr` node, if any.\n\nIf `Node` represents \"`receive C1; ...; Cn end`\", `none` is\nreturned. Otherwise, if `Node` represents \"`receive C1; ...; Cn\nafter Timeout -> ... end`\", `Timeout` is returned.\n\n_See also: _`receive_expr/3`.","ref":"erl_syntax.html#receive_expr_timeout/1"},{"type":"function","title":"erl_syntax.record_access/3","doc":"Creates an abstract record field access expression.\n\nThe result represents \"`Argument#Type.Field`\".\n\n_See also: _`record_access_argument/1`, `record_access_field/1`,\n`record_access_type/1`, `record_expr/3`.","ref":"erl_syntax.html#record_access/3"},{"type":"function","title":"erl_syntax.record_access_argument/1","doc":"Returns the argument subtree of a `record_access` node.\n\n_See also: _`record_access/3`.","ref":"erl_syntax.html#record_access_argument/1"},{"type":"function","title":"erl_syntax.record_access_field/1","doc":"Returns the field subtree of a `record_access` node.\n\n_See also: _`record_access/3`.","ref":"erl_syntax.html#record_access_field/1"},{"type":"function","title":"erl_syntax.record_access_type/1","doc":"Returns the type subtree of a `record_access` node.\n\n_See also: _`record_access/3`.","ref":"erl_syntax.html#record_access_type/1"},{"type":"function","title":"erl_syntax.record_expr/2","doc":"","ref":"erl_syntax.html#record_expr/2"},{"type":"function","title":"erl_syntax.record_expr/3","doc":"Creates an abstract record expression.\n\nIf `Fields` is `[F1, ..., Fn]`, then if `Argument` is `none`, the\nresult represents \"`#Type{F1, ..., Fn}`\", otherwise it\nrepresents \"`Argument#Type{F1, ..., Fn}`\".\n\n_See also: _`record_access/3`, `record_expr/2`, `record_expr_argument/1`,\n`record_expr_fields/1`, `record_expr_type/1`, `record_field/2`,\n`record_index_expr/2`.","ref":"erl_syntax.html#record_expr/3"},{"type":"function","title":"erl_syntax.record_expr_argument/1","doc":"Returns the argument subtree of a `record_expr` node, if any.\n\nIf `Node` represents \"`#Type{...}`\", `none` is returned. Otherwise,\nif `Node` represents \"`Argument#Type{...}`\", `Argument` is\nreturned.\n\n_See also: _`record_expr/3`.","ref":"erl_syntax.html#record_expr_argument/1"},{"type":"function","title":"erl_syntax.record_expr_fields/1","doc":"Returns the list of field subtrees of a `record_expr` node.\n\n_See also: _`record_expr/3`.","ref":"erl_syntax.html#record_expr_fields/1"},{"type":"function","title":"erl_syntax.record_expr_type/1","doc":"Returns the type subtree of a `record_expr` node.\n\n_See also: _`record_expr/3`.","ref":"erl_syntax.html#record_expr_type/1"},{"type":"function","title":"erl_syntax.record_field/1","doc":"","ref":"erl_syntax.html#record_field/1"},{"type":"function","title":"erl_syntax.record_field/2","doc":"Creates an abstract record field specification.\n\nIf `Value` is `none`, the result represents simply \"`Name`\",\notherwise it represents \"`Name = Value`\".\n\n_See also: _`record_expr/3`, `record_field_name/1`, `record_field_value/1`.","ref":"erl_syntax.html#record_field/2"},{"type":"function","title":"erl_syntax.record_field_name/1","doc":"Returns the name subtree of a `record_field` node.\n\n_See also: _`record_field/2`.","ref":"erl_syntax.html#record_field_name/1"},{"type":"function","title":"erl_syntax.record_field_value/1","doc":"Returns the value subtree of a `record_field` node, if any.\n\nIf `Node` represents \"`Name`\", `none` is returned. Otherwise, if\n`Node` represents \"`Name = Value`\", `Value` is returned.\n\n_See also: _`record_field/2`.","ref":"erl_syntax.html#record_field_value/1"},{"type":"function","title":"erl_syntax.record_index_expr/2","doc":"Creates an abstract record field index expression. The result represents\n\"`#Type.Field`\".\n\n> #### Note {: .info }\n>\n> The function name `record_index/2` is reserved by the Erlang compiler,\n> which is why that name could not be used for this constructor.\n\n_See also: _`record_expr/3`, `record_index_expr_field/1`,\n`record_index_expr_type/1`.","ref":"erl_syntax.html#record_index_expr/2"},{"type":"function","title":"erl_syntax.record_index_expr_field/1","doc":"Returns the field subtree of a `record_index_expr` node.\n\n_See also: _`record_index_expr/2`.","ref":"erl_syntax.html#record_index_expr_field/1"},{"type":"function","title":"erl_syntax.record_index_expr_type/1","doc":"Returns the type subtree of a `record_index_expr` node.\n\n_See also: _`record_index_expr/2`.","ref":"erl_syntax.html#record_index_expr_type/1"},{"type":"function","title":"erl_syntax.record_type/2","doc":"Creates an abstract record type.\n\nIf `Fields` is `[F1, ..., Fn]`, the result represents \"`#Name{F1,\n..., Fn}`\".\n\n_See also: _`record_type_fields/1`, `record_type_name/1`.","ref":"erl_syntax.html#record_type/2"},{"type":"function","title":"erl_syntax.record_type_field/2","doc":"Creates an abstract record type field.\n\nThe result represents \"`Name :: Type`\".\n\n_See also: _`record_type_field_name/1`, `record_type_field_type/1`.","ref":"erl_syntax.html#record_type_field/2"},{"type":"function","title":"erl_syntax.record_type_field_name/1","doc":"Returns the name subtree of a `record_type_field` node.\n\n_See also: _`record_type_field/2`.","ref":"erl_syntax.html#record_type_field_name/1"},{"type":"function","title":"erl_syntax.record_type_field_type/1","doc":"Returns the type subtree of a `record_type_field` node.\n\n_See also: _`record_type_field/2`.","ref":"erl_syntax.html#record_type_field_type/1"},{"type":"function","title":"erl_syntax.record_type_fields/1","doc":"Returns the fields subtree of a `record_type` node.\n\n_See also: _`record_type/2`.","ref":"erl_syntax.html#record_type_fields/1"},{"type":"function","title":"erl_syntax.record_type_name/1","doc":"Returns the name subtree of a `record_type` node.\n\n_See also: _`record_type/2`.","ref":"erl_syntax.html#record_type_name/1"},{"type":"function","title":"erl_syntax.remove_comments/1","doc":"Clears the associated comments of `Node`.\n\nNote: This is equivalent to\n[`set_precomments(set_postcomments(Node, []), [])`](`set_precomments/2`), but\npotentially more efficient.\n\n_See also: _`set_postcomments/2`, `set_precomments/2`.","ref":"erl_syntax.html#remove_comments/1"},{"type":"function","title":"erl_syntax.revert/1","doc":"Returns an `m:erl_parse`-compatible representation of a syntax tree, if possible.\n\nIf `Tree` represents a well-formed Erlang program or expression, the conversion\nshould work without problems. Typically, `is_tree/1` yields `true` if conversion\nfailed (that is, the result is still an abstract syntax tree), and `false`\notherwise.\n\nThe `is_tree/1` test is not completely foolproof. For a few special\nnode types (for example `arity_qualifier`), if such a node occurs in a\ncontext where it is not expected, it will be left unchanged as a\nnon-reverted subtree of the result. This can only happen if `Tree`\ndoes not actually represent legal Erlang code.\n\n_See also: _[//stdlib/erl_parse](`m:erl_parse`), `revert_forms/1`.","ref":"erl_syntax.html#revert/1"},{"type":"function","title":"erl_syntax.revert_forms/1","doc":"Reverts a sequence of Erlang source code forms.\n\nThe sequence can be given either as a `form_list` syntax tree\n(possibly nested), or as a list of \"program form\" syntax trees. If\nsuccessful, the corresponding flat list of `m:erl_parse`-compatible\nsyntax trees is returned (see `revert/1`). If some program form could\nnot be reverted, `{error, Form}` is thrown. Standalone comments in the\nform sequence are discarded.\n\n_See also: _`form_list/1`, `is_form/1`, `revert/1`.","ref":"erl_syntax.html#revert_forms/1"},{"type":"function","title":"erl_syntax.set_ann/2","doc":"Sets the list of user annotations of `Node` to `Annotations`.\n\n_See also: _`add_ann/2`, `copy_ann/2`, `get_ann/1`.","ref":"erl_syntax.html#set_ann/2"},{"type":"function","title":"erl_syntax.set_attrs/2","doc":"Sets the attributes of `Node` to `Attributes`.\n\n_See also: _`copy_attrs/2`, `get_attrs/1`.","ref":"erl_syntax.html#set_attrs/2"},{"type":"function","title":"erl_syntax.set_pos/2","doc":"Sets the position information of `Node` to `Pos`.\n\n_See also: _`copy_pos/2`, `get_pos/1`.","ref":"erl_syntax.html#set_pos/2"},{"type":"function","title":"erl_syntax.set_postcomments/2","doc":"Sets the post-comments of `Node` to `Comments`.\n\n`Comments` should be a possibly empty list of abstract comments, in\ntop-down textual order\n\n_See also: _`add_postcomments/2`, `comment/2`, `copy_comments/2`,\n`get_postcomments/1`, `join_comments/2`, `remove_comments/1`,\n`set_precomments/2`.","ref":"erl_syntax.html#set_postcomments/2"},{"type":"function","title":"erl_syntax.set_precomments/2","doc":"Sets the pre-comments of `Node` to `Comments`.\n\n`Comments` should be a possibly empty list of abstract comments, in\ntop-down textual order.\n\n_See also: _`add_precomments/2`, `comment/2`, `copy_comments/2`,\n`get_precomments/1`, `join_comments/2`, `remove_comments/1`,\n`set_postcomments/2`.","ref":"erl_syntax.html#set_precomments/2"},{"type":"function","title":"erl_syntax.size_qualifier/2","doc":"Creates an abstract size qualifier.\n\nThe result represents \"`Body:Size`\".\n\n_See also: _`size_qualifier_argument/1`, `size_qualifier_body/1`.","ref":"erl_syntax.html#size_qualifier/2"},{"type":"function","title":"erl_syntax.size_qualifier_argument/1","doc":"Returns the argument subtree (the size) of a `size_qualifier` node.\n\n_See also: _`size_qualifier/2`.","ref":"erl_syntax.html#size_qualifier_argument/1"},{"type":"function","title":"erl_syntax.size_qualifier_body/1","doc":"Returns the body subtree of a `size_qualifier` node.\n\n_See also: _`size_qualifier/2`.","ref":"erl_syntax.html#size_qualifier_body/1"},{"type":"function","title":"erl_syntax.strict_binary_generator/2","doc":"Creates an abstract strict binary_generator.\n\nThe result represents \"`*Pattern*<:- *Body*`\".\n\n_See also: _`binary_comp/2`, `strict_binary_generator_body/1`,\n`strict_binary_generator_pattern/1`, `list_comp/2`.","ref":"erl_syntax.html#strict_binary_generator/2"},{"type":"function","title":"erl_syntax.strict_binary_generator_body/1","doc":"Returns the body subtree of a `generator` node.\n\n_See also: _`strict_binary_generator/2`.","ref":"erl_syntax.html#strict_binary_generator_body/1"},{"type":"function","title":"erl_syntax.strict_binary_generator_pattern/1","doc":"Returns the pattern subtree of a `generator` node.\n\n_See also: _`strict_binary_generator/2`.","ref":"erl_syntax.html#strict_binary_generator_pattern/1"},{"type":"function","title":"erl_syntax.strict_generator/2","doc":"Creates an abstract strict list generator.\n\nThe result represents \"`*Pattern*<:- *Body*`\".\n\n_See also: _`binary_comp/2`, `strict_generator_body/1`,\n`strict_generator_pattern/1`, `list_comp/2`.","ref":"erl_syntax.html#strict_generator/2"},{"type":"function","title":"erl_syntax.strict_generator_body/1","doc":"Returns the body subtree of a `generator` node.\n\n_See also: _`strict_generator/2`.","ref":"erl_syntax.html#strict_generator_body/1"},{"type":"function","title":"erl_syntax.strict_generator_pattern/1","doc":"Returns the pattern subtree of a `generator` node.\n\n_See also: _`strict_generator/2`.","ref":"erl_syntax.html#strict_generator_pattern/1"},{"type":"function","title":"erl_syntax.strict_map_generator/2","doc":"Creates an abstract strict map_generator. The result represents\n\"`*Pattern*<- *Body*`\".\n\n_See also: _`list_comp/2`, `map_comp/2`,\n`strict_map_generator_body/1`,\n`strict_map_generator_pattern/1`.","ref":"erl_syntax.html#strict_map_generator/2"},{"type":"function","title":"erl_syntax.strict_map_generator_body/1","doc":"Returns the body subtree of a `generator` node.\n\n_See also: _`strict_map_generator/2`.","ref":"erl_syntax.html#strict_map_generator_body/1"},{"type":"function","title":"erl_syntax.strict_map_generator_pattern/1","doc":"Returns the pattern subtree of a `generator` node.\n\n_See also: _`strict_map_generator/2`.","ref":"erl_syntax.html#strict_map_generator_pattern/1"},{"type":"function","title":"erl_syntax.string/1","doc":"Creates an abstract string literal.\n\nThe result represents `\"Text\"` (including the surrounding\ndouble-quotes), where `Text` corresponds to the sequence of characters\nin `Value`, but not representing a _specific_ string literal.\n\nFor example, the result of [`string(\"x\\ny\")`](`string/1`) represents any and all\nof `\"x\\ny\"`, `\"x\\12y\"`, `\"x\\012y\"` and `\"x\\^Jy\"`; see `char/1`.\n\n_See also: _`char/1`, `is_string/2`, `string_literal/1`, `string_literal/2`,\n`string_value/1`.","ref":"erl_syntax.html#string/1"},{"type":"function","title":"erl_syntax.string_literal/1","doc":"Returns the literal string represented by a `string` node.\n\nThis includes surrounding double-quote characters. Characters beyond\n255 will be escaped.\n\n_See also: _`string/1`.","ref":"erl_syntax.html#string_literal/1"},{"type":"function","title":"erl_syntax.string_literal/2","doc":"Returns the literal string represented by a `string` node.\n\nThis includes surrounding double-quote characters. Depending on the\nencoding characters beyond 255 will be escaped (`latin1`) or copied as\nis (`utf8`).\n\n_See also: _`string/1`.","ref":"erl_syntax.html#string_literal/2"},{"type":"function","title":"erl_syntax.string_value/1","doc":"Returns the value represented by a `string` node.\n\n_See also: _`string/1`.","ref":"erl_syntax.html#string_value/1"},{"type":"function","title":"erl_syntax.subtrees/1","doc":"Returns the grouped list of all subtrees of a syntax tree.\n\nIf `Node` is a leaf node (see `is_leaf/1`), this is the empty list,\notherwise the result is always a nonempty list, containing the lists\nof subtrees of `Node`, in left-to-right order as they occur in the\nprinted program text, and grouped by category. Often, each group\ncontains only a single subtree.\n\nDepending on the type of `Node`, the size of some groups may be\nvariable (for example, the group consisting of all the elements of a\ntuple), while others always contain the same number of elements —\nusually exactly one (for example, the group containing the argument\nexpression of a case-expression). Note, however, that the exact\nstructure of the returned list (for a given node type) should in\ngeneral not be depended upon, since it might be subject to change\nwithout notice.\n\nThe function `subtrees/1` and the constructor functions `make_tree/2` and\n`update_tree/2` can be a great help if one wants to traverse a syntax tree,\nvisiting all its subtrees, but treat nodes of the tree in a uniform way in most\nor all cases. Using these functions makes this simple, and also assures that\nyour code is not overly sensitive to extensions of the syntax tree data type,\nbecause any node types not explicitly handled by your code can be left to a\ndefault case.\n\nFor example:\n\n```text\n postorder(F, Tree) ->\n F(case subtrees(Tree) of\n [] -> Tree;\n List -> update_tree(Tree,\n [[postorder(F, Subtree)\n || Subtree <- Group]\n || Group <- List])\n end).\n```\n\nmaps the function `F` on `Tree` and all its subtrees, doing a post-order\ntraversal of the syntax tree. (Note the use of `update_tree/2` to preserve node\nattributes.) For a simple function like:\n\n```text\n f(Node) ->\n case type(Node) of\n atom -> atom(\"a_\" ++ atom_name(Node));\n _ -> Node\n end.\n```\n\nthe call `postorder(fun f/1, Tree)` will yield a new representation of `Tree` in\nwhich all atom names have been extended with the prefix \"a_\", but nothing else\n(including comments, annotations, and line numbers) has been changed.\n\n_See also: _`copy_attrs/2`, `is_leaf/1`, `make_tree/2`, `type/1`.","ref":"erl_syntax.html#subtrees/1"},{"type":"function","title":"erl_syntax.text/1","doc":"Creates an abstract piece of source code text.\n\nThe result represents exactly the sequence of characters in\n`String`. This is useful in cases where one wants full control of the\nresulting output, such as the appearance of floating-point numbers or\nmacro definitions.\n\n_See also: _`text_string/1`.","ref":"erl_syntax.html#text/1"},{"type":"function","title":"erl_syntax.text_string/1","doc":"Returns the character sequence represented by a `text` node.\n\n_See also: _`text/1`.","ref":"erl_syntax.html#text_string/1"},{"type":"function","title":"erl_syntax.tree/1","doc":"","ref":"erl_syntax.html#tree/1"},{"type":"function","title":"erl_syntax.tree/2","doc":"**For special purposes only**. Creates an abstract syntax tree node with type tag\n`Type` and associated data `Data`.\n\nThis function and the related `is_tree/1` and `data/1` provide a uniform way to\nextend the set of `erl_parse` node types. The associated data is any term, whose\nformat may depend on the type tag.\n\n> #### Notes {: .info }\n>\n> - Any nodes created outside of this module must have type tags distinct from\n> those currently defined by this module; see `type/1` for a complete list.\n>\n> - The type tag of a syntax tree node may also be used as a primary tag by the\n> `erl_parse` representation; in that case, the selector functions for that node\n> type _must_ handle both the abstract syntax tree and the `m:erl_parse` form. The\n> function [`type(T)`](`type/1`) should return the correct type tag regardless\n> of the representation of `T`, so that the user sees no difference between\n> `erl_syntax` and `erl_parse` nodes.\n\n_See also: _`data/1`, `is_tree/1`, `type/1`.","ref":"erl_syntax.html#tree/2"},{"type":"function","title":"erl_syntax.try_after_expr/2","doc":"","ref":"erl_syntax.html#try_after_expr/2"},{"type":"function","title":"erl_syntax.try_expr/2","doc":"","ref":"erl_syntax.html#try_expr/2"},{"type":"function","title":"erl_syntax.try_expr/3","doc":"","ref":"erl_syntax.html#try_expr/3"},{"type":"function","title":"erl_syntax.try_expr/4","doc":"Creates an abstract try-expression.\n\nIf `Body` is `[B1, ..., Bn]`, `Clauses` is `[C1, ..., Cj]`, `Handlers`\nis `[H1, ..., Hk]`, and `After` is `[A1, ..., Am]`, the result\nrepresents \"`try B1, ..., Bn of C1; ...; Cj catch H1; ...; Hk after\nA1, ..., Am end`\". More exactly, if each `Ci` represents \"`(CPi) CGi\n-> CBi`\", and each `Hi` represents \"`(HPi) HGi -> HBi`\", then the\nresult represents \"`try B1, ..., Bn of CP1 CG1 -> CB1; ...; CPj CGj ->\nCBj catch HP1 HG1 -> HB1; ...; HPk HGk -> HBk after A1, ..., Am end`\";\nsee `case_expr/2`. If `Clauses` is the empty list, the `of ...`\nsection is left out. If `After` is the empty list, the `after ...`\nsection is left out. If `Handlers` is the empty list, and `After` is\nnonempty, the `catch ...` section is left out.\n\n_See also: _`case_expr/2`, `class_qualifier/2`, `clause/3`, `try_after_expr/2`,\n`try_expr/2`, `try_expr/3`, `try_expr_after/1`, `try_expr_body/1`,\n`try_expr_clauses/1`, `try_expr_handlers/1`.","ref":"erl_syntax.html#try_expr/4"},{"type":"function","title":"erl_syntax.try_expr_after/1","doc":"Returns the list of \"after\" subtrees of a `try_expr` node.\n\n_See also: _`try_expr/4`.","ref":"erl_syntax.html#try_expr_after/1"},{"type":"function","title":"erl_syntax.try_expr_body/1","doc":"Returns the list of body subtrees of a `try_expr` node.\n\n_See also: _`try_expr/4`.","ref":"erl_syntax.html#try_expr_body/1"},{"type":"function","title":"erl_syntax.try_expr_clauses/1","doc":"Returns the list of case-clause subtrees of a `try_expr` node. If `Node`\nrepresents \"`try Body catch H1; ...; Hn end`\", the result is the empty\nlist.\n\n_See also: _`try_expr/4`.","ref":"erl_syntax.html#try_expr_clauses/1"},{"type":"function","title":"erl_syntax.try_expr_handlers/1","doc":"Returns the list of handler-clause subtrees of a `try_expr` node.\n\n_See also: _`try_expr/4`.","ref":"erl_syntax.html#try_expr_handlers/1"},{"type":"function","title":"erl_syntax.tuple/1","doc":"Creates an abstract tuple.\n\nIf `Elements` is `[X1, ..., Xn]`, the result represents \"`{X1, ...,\nXn}`\".\n\n> #### Note {: .info }\n>\n> The Erlang language has distinct 1-tuples, meaning `{X}` is always distinct\n> from `X` itself.\n\n_See also: _`tuple_elements/1`, `tuple_size/1`.","ref":"erl_syntax.html#tuple/1"},{"type":"function","title":"erl_syntax.tuple_elements/1","doc":"Returns the list of element subtrees of a `tuple` node.\n\n_See also: _`tuple/1`.","ref":"erl_syntax.html#tuple_elements/1"},{"type":"function","title":"erl_syntax.tuple_size/1","doc":"Returns the number of elements of a `tuple` node.\n\n> #### Note {: .info }\n>\n> This is equivalent to [`length(tuple_elements(Node))`](`length/1`),\n> but potentially more efficient.\n\n_See also: _`tuple/1`, `tuple_elements/1`.","ref":"erl_syntax.html#tuple_size/1"},{"type":"function","title":"erl_syntax.tuple_type/0","doc":"","ref":"erl_syntax.html#tuple_type/0"},{"type":"function","title":"erl_syntax.tuple_type/1","doc":"Creates an abstract type tuple.\n\nIf `Elements` is `[T1, ..., Tn]`, the result represents \"`{T1, ...,\nTn}`\"; otherwise, if `Elements` is `any_size`, it represents\n\"`t:tuple/0`\".\n\n_See also: _`tuple_type_elements/1`.","ref":"erl_syntax.html#tuple_type/1"},{"type":"function","title":"erl_syntax.tuple_type_elements/1","doc":"Returns the list of type element subtrees of a `tuple_type` node.\n\nIf `Node` represents \"`t:tuple/0`\", `any_size` is returned; otherwise,\nif `Node` represents \"`{T1, ..., Tn}`\", `[T1, ..., Tn]` is returned.\n\n_See also: _`tuple_type/0`, `tuple_type/1`.","ref":"erl_syntax.html#tuple_type_elements/1"},{"type":"function","title":"erl_syntax.type/1","doc":"Returns the type tag of `Node`.\n\nIf `Node` does not represent a syntax tree, evaluation fails with\nreason `badarg`. Node types currently defined by this module are:\n\n* `application`\n* `annotated_type`\n* `arity_qualifier`\n* `atom`\n* `attribute`\n* `binary`\n* `binary_field`\n* `bitstring_type`\n* `block_expr`\n* `case_expr`\n* `catch_expr`\n* `char`\n* `class_qualifier`\n* `clause`\n* `comment`\n* `conjunction`\n* `constrained_function_type`\n* `constraint`\n* `disjunction`\n* `else_expr`\n* `eof_marker`\n* `error_marker`\n* `float`\n* `form_list`\n* `fun_expr`\n* `fun_type`\n* `function`\n* `function_type`\n* `generator`\n* `if_expr`\n* `implicit_fun`\n* `infix_expr`\n* `integer`\n* `integer_range_type`\n* `list`\n* `list_comp`\n* `macro`\n* `map_expr`\n* `map_field_assoc`\n* `map_field_exact`\n* `map_type`\n* `map_type_assoc`\n* `map_type_exact`\n* `match_expr`\n* `maybe_expr`\n* `maybe_match_expr`\n* `module_qualifier`\n* `named_fun_expr`\n* `nil`\n* `operator`\n* `parentheses`\n* `prefix_expr`\n* `receive_expr`\n* `record_access`\n* `record_expr`\n* `record_field`\n* `record_index_expr`\n* `record_type`\n* `record_type_field`\n* `size_qualifier`\n* `string`\n* `text`\n* `try_expr`\n* `tuple`\n* `tuple_type`\n* `typed_record_field`\n* `type_application`\n* `type_union`\n* `underscore`\n* `user_type_application`\n* `variable`\n* `warning_marker`\n* `zip_generator`\n\nThe user may (for special purposes) create additional nodes with other type\ntags, using the `tree/2` function.\n\nNote: The primary constructor functions for a node type should always have the\nsame name as the node type itself.\n\n_See also: _`annotated_type/2`, `application/3`, `arity_qualifier/2`, `atom/1`,\n`attribute/2`, `binary/1`, `binary_field/2`, `bitstring_type/2`, `block_expr/1`,\n`case_expr/2`, `catch_expr/1`, `char/1`, `class_qualifier/2`, `clause/3`,\n`comment/2`, `conjunction/1`, `constrained_function_type/2`, `constraint/2`,\n`disjunction/1`, `else_expr/1`, `eof_marker/0`, `error_marker/1`, `float/1`,\n`form_list/1`, `fun_expr/1`, `fun_type/0`, `function/2`, `function_type/1`,\n`function_type/2`, `generator/2`, `if_expr/1`, `implicit_fun/2`, `infix_expr/3`,\n`integer/1`, `integer_range_type/2`, `list/2`, `list_comp/2`, `macro/2`,\n`map_expr/2`, `map_field_assoc/2`, `map_field_exact/2`, `map_type/0`,\n`map_type/1`, `map_type_assoc/2`, `map_type_exact/2`, `match_expr/2`,\n`maybe_expr/1`, `maybe_expr/2`, `maybe_match_expr/2`, `module_qualifier/2`,\n`named_fun_expr/2`, `nil/0`, `operator/1`, `parentheses/1`, `prefix_expr/2`,\n`receive_expr/3`, `record_access/3`, `record_expr/2`, `record_field/2`,\n`record_index_expr/2`, `record_type/2`, `record_type_field/2`,\n`size_qualifier/2`, `string/1`, `text/1`, `tree/2`, `try_expr/3`, `tuple/1`,\n`tuple_type/0`, `tuple_type/1`, `type_application/2`, `type_union/1`,\n`typed_record_field/2`, `underscore/0`, `user_type_application/2`, `variable/1`,\n`warning_marker/1`,`zip_generator/1`.","ref":"erl_syntax.html#type/1"},{"type":"function","title":"erl_syntax.type_application/2","doc":"Creates an abstract type application expression.\n\nIf `Arguments` is `[T1, ..., Tn]`, the result represents\n\"`TypeName(T1, ...Tn)`\".\n\n_See also: _`type_application/3`, `type_application_arguments/1`,\n`type_application_name/1`, `user_type_application/2`.","ref":"erl_syntax.html#type_application/2"},{"type":"function","title":"erl_syntax.type_application/3","doc":"Creates an abstract type application expression.\n\nIf `Module` is `none`, this is call is equivalent to\n[`type_application(TypeName, Arguments)`](`type_application/2`),\notherwise it is equivalent to\n[`type_application(module_qualifier(Module, TypeName),\nArguments)`](`type_application/2`).\n\n(This is a utility function.)\n\n_See also: _`module_qualifier/2`, `type_application/2`.","ref":"erl_syntax.html#type_application/3"},{"type":"function","title":"erl_syntax.type_application_arguments/1","doc":"Returns the arguments subtrees of a `type_application` node.\n\n_See also: _`type_application/2`.","ref":"erl_syntax.html#type_application_arguments/1"},{"type":"function","title":"erl_syntax.type_application_name/1","doc":"Returns the type name subtree of a `type_application` node.\n\n_See also: _`type_application/2`.","ref":"erl_syntax.html#type_application_name/1"},{"type":"function","title":"erl_syntax.type_union/1","doc":"Creates an abstract type union.\n\nIf `Types` is `[T1, ..., Tn]`, the result represents \"`T1 | ... |\nTn`\".\n\n_See also: _`type_union_types/1`.","ref":"erl_syntax.html#type_union/1"},{"type":"function","title":"erl_syntax.type_union_types/1","doc":"Returns the list of type subtrees of a `type_union` node.\n\n_See also: _`type_union/1`.","ref":"erl_syntax.html#type_union_types/1"},{"type":"function","title":"erl_syntax.typed_record_field/2","doc":"Creates an abstract typed record field specification.\n\nThe result represents \"`Field :: Type`\".\n\n_See also: _`typed_record_field_body/1`, `typed_record_field_type/1`.","ref":"erl_syntax.html#typed_record_field/2"},{"type":"function","title":"erl_syntax.typed_record_field_body/1","doc":"Returns the field subtree of a `typed_record_field` node.\n\n_See also: _`typed_record_field/2`.","ref":"erl_syntax.html#typed_record_field_body/1"},{"type":"function","title":"erl_syntax.typed_record_field_type/1","doc":"Returns the type subtree of a `typed_record_field` node.\n\n_See also: _`typed_record_field/2`.","ref":"erl_syntax.html#typed_record_field_type/1"},{"type":"function","title":"erl_syntax.underscore/0","doc":"Creates an abstract universal pattern (\"`_`\").\n\nThe lexical representation is a single underscore character. Note that\nthis is _not_ a variable, lexically speaking.\n\n_See also: _`variable/1`.","ref":"erl_syntax.html#underscore/0"},{"type":"function","title":"erl_syntax.update_tree/2","doc":"Creates a syntax tree with the same type and attributes as the given tree.\n\nThis is equivalent to [`copy_attrs(Node, make_tree(type(Node),\nGroups))`](`copy_attrs/2`).\n\n_See also: _`copy_attrs/2`, `make_tree/2`, `type/1`.","ref":"erl_syntax.html#update_tree/2"},{"type":"function","title":"erl_syntax.user_type_application/2","doc":"Creates an abstract user type.\n\nIf `Arguments` is `[T1, ..., Tn]`, the result represents\n\"`TypeName(T1, ...Tn)`\".\n\n_See also: _`type_application/2`, `user_type_application_arguments/1`,\n`user_type_application_name/1`.","ref":"erl_syntax.html#user_type_application/2"},{"type":"function","title":"erl_syntax.user_type_application_arguments/1","doc":"Returns the arguments subtrees of a `user_type_application` node.\n\n_See also: _`user_type_application/2`.","ref":"erl_syntax.html#user_type_application_arguments/1"},{"type":"function","title":"erl_syntax.user_type_application_name/1","doc":"Returns the type name subtree of a `user_type_application` node.\n\n_See also: _`user_type_application/2`.","ref":"erl_syntax.html#user_type_application_name/1"},{"type":"function","title":"erl_syntax.variable/1","doc":"Creates an abstract variable with the given name.\n\n`Name` may be any atom or string that represents a lexically valid\nvariable name, but _not_ a single underscore character; see\n`underscore/0`.\n\n> #### Note {: .info }\n>\n> No check is performed to verify whether the character sequence\n> represents a proper variable name, that is, whether its first character\n> is an uppercase Erlang character, or whether it contains illegal characters\n> such as control characters or whitespace.\n\n_See also: _`underscore/0`, `variable_literal/1`, `variable_name/1`.","ref":"erl_syntax.html#variable/1"},{"type":"function","title":"erl_syntax.variable_literal/1","doc":"Returns the name of a `variable` node as a string.\n\n_See also: _`variable/1`.","ref":"erl_syntax.html#variable_literal/1"},{"type":"function","title":"erl_syntax.variable_name/1","doc":"Returns the name of a `variable` node as an atom.\n\n_See also: _`variable/1`.","ref":"erl_syntax.html#variable_name/1"},{"type":"function","title":"erl_syntax.warning_marker/1","doc":"Creates an abstract warning marker.\n\nThe result represents an occurrence of a possible problem in the\nsource code, with an associated Erlang I/O ErrorInfo structure given\nby `Error` (see module [`//stdlib/io`](`m:io`) for details). Warning\nmarkers are regarded as source code forms, but have no defined lexical\nform.\n\n> #### Note {: .info }\n>\n> This is supported only for backwards compatibility with existing parsers\n> and tools.\n\n_See also: _`eof_marker/0`, `error_marker/1`, `is_form/1`,\n`warning_marker_info/1`.","ref":"erl_syntax.html#warning_marker/1"},{"type":"function","title":"erl_syntax.warning_marker_info/1","doc":"Returns the ErrorInfo structure of a `warning_marker` node.\n\n_See also: _`warning_marker/1`.","ref":"erl_syntax.html#warning_marker_info/1"},{"type":"function","title":"erl_syntax.zip_generator/1","doc":"Creates an abstract zip_generator.\n\nThe result represents `G1 && ... Gn`, where each `G` is a generator.\n\n_See also: _`binary_comp/2`, `list_comp/2`, `map_comp/2`, `map_generator_body/1`,\n`map_generator_pattern/1`.","ref":"erl_syntax.html#zip_generator/1"},{"type":"function","title":"erl_syntax.zip_generator_body/1","doc":"Returns the body subtree of a `zip_generator` node.\n\n_See also: _`zip_generator/1`.","ref":"erl_syntax.html#zip_generator_body/1"},{"type":"type","title":"erl_syntax.annotation_or_location/0","doc":"","ref":"erl_syntax.html#t:annotation_or_location/0"},{"type":"type","title":"erl_syntax.encoding/0","doc":"","ref":"erl_syntax.html#t:encoding/0"},{"type":"type","title":"erl_syntax.erl_parse/0","doc":"","ref":"erl_syntax.html#t:erl_parse/0"},{"type":"type","title":"erl_syntax.forms/0","doc":"","ref":"erl_syntax.html#t:forms/0"},{"type":"type","title":"erl_syntax.guard/0","doc":"","ref":"erl_syntax.html#t:guard/0"},{"type":"type","title":"erl_syntax.padding/0","doc":"","ref":"erl_syntax.html#t:padding/0"},{"type":"type","title":"erl_syntax.syntaxTree/0","doc":"","ref":"erl_syntax.html#t:syntaxTree/0"},{"type":"type","title":"erl_syntax.syntaxTreeAttributes/0","doc":"","ref":"erl_syntax.html#t:syntaxTreeAttributes/0"},{"type":"type","title":"erl_syntax.tree/0","doc":"","ref":"erl_syntax.html#t:tree/0"},{"type":"type","title":"erl_syntax.wrapper/0","doc":"","ref":"erl_syntax.html#t:wrapper/0"},{"type":"module","title":"erl_syntax_lib","doc":"Support library for abstract Erlang syntax trees.\n\nThis module contains utility functions for working with the abstract data type\ndefined in the module `m:erl_syntax`.","ref":"erl_syntax_lib.html"},{"type":"function","title":"erl_syntax_lib.analyze_application/1","doc":"Returns the name of a called function.\n\nThe result is a representation of the name of the applied function\n`F/A`, if `Node` represents a function application \"`F(X_1, ...,\nX_A)`\". If the function is not explicitly named (that is, `F` is given\nby some expression), only the arity `A` is returned.\n\nThe evaluation throws `syntax_error` if `Node` does not represent a well-formed\napplication expression.\n\n_See also: _`analyze_function_name/1`.","ref":"erl_syntax_lib.html#analyze_application/1"},{"type":"function","title":"erl_syntax_lib.analyze_attribute/1","doc":"Analyzes an attribute node.\n\nIf `Node` represents a preprocessor directive, the atom `preprocessor`\nis returned. Otherwise, if `Node` represents a module attribute\n\"`-Name...`\", a tuple `{Name, Info}` is returned, where `Info` depends\non `Name`, as follows:\n\n- **`{module, Info}`** - where `Info = analyze_module_attribute(Node)`.\n\n- **`{export, Info}`** - where `Info = analyze_export_attribute(Node)`.\n\n- **`{import, Info}`** - where `Info = analyze_import_attribute(Node)`.\n\n- **`{file, Info}`** - where `Info = analyze_file_attribute(Node)`.\n\n- **`{record, Info}`** - where `Info = analyze_record_attribute(Node)`.\n\n- **`{Name, Info}`** - where `{Name, Info} = analyze_wild_attribute(Node)`.\n\nThe evaluation throws `syntax_error` if `Node` does not represent a well-formed\nmodule attribute.\n\n_See also: _`analyze_export_attribute/1`, `analyze_file_attribute/1`,\n`analyze_import_attribute/1`, `analyze_module_attribute/1`,\n`analyze_record_attribute/1`, `analyze_wild_attribute/1`.","ref":"erl_syntax_lib.html#analyze_attribute/1"},{"type":"function","title":"erl_syntax_lib.analyze_export_attribute/1","doc":"Returns the list of function names declared by an export attribute.\n\nWe do not guarantee that each name occurs at most once in the\nlist. The order of listing is not defined.\n\nThe evaluation throws `syntax_error` if `Node` does not represent a well-formed\nexport attribute.\n\n_See also: _`analyze_attribute/1`.","ref":"erl_syntax_lib.html#analyze_export_attribute/1"},{"type":"function","title":"erl_syntax_lib.analyze_file_attribute/1","doc":"Returns the file name and line number of a `file` attribute.\n\nThe result is the pair `{File, Line}` if `Node` represents\n\"`-file(File, Line).`\".\n\nThe evaluation throws `syntax_error` if `Node` does not represent a well-formed\n`file` attribute.\n\n_See also: _`analyze_attribute/1`.","ref":"erl_syntax_lib.html#analyze_file_attribute/1"},{"type":"function","title":"erl_syntax_lib.analyze_form/1","doc":"Analyzes a \"source code form\" node.\n\nIf `Node` is a \"form\" type (see `erl_syntax:is_form/1`), the returned\nvalue is a tuple `{Type, Info}` where `Type` is the node type and\n`Info` depends on `Type`, as follows:\n\n- **`{attribute, Info}`** - where `Info = analyze_attribute(Node)`.\n\n- **`{error_marker, Info}`** - where\n `Info = erl_syntax:error_marker_info(Node)`.\n\n- **`{function, Info}`** - where `Info = analyze_function(Node)`.\n\n- **`{warning_marker, Info}`** - where\n `Info = erl_syntax:warning_marker_info(Node)`.\n\nFor other types of forms, only the node type is returned.\n\nThe evaluation throws `syntax_error` if `Node` is not well-formed.\n\n_See also: _`analyze_attribute/1`, `analyze_function/1`,\n`erl_syntax:error_marker_info/1`, `erl_syntax:is_form/1`,\n`erl_syntax:warning_marker_info/1`.","ref":"erl_syntax_lib.html#analyze_form/1"},{"type":"function","title":"erl_syntax_lib.analyze_forms/1","doc":"Analyzes a sequence of \"program forms\".\n\nThe given `Forms` may be a single syntax tree of type `form_list`, or\na list of \"program form\" syntax trees. The returned value is a list of\npairs `{Key, Info}`, where each value of `Key` occurs at most once in\nthe list; the absence of a particular key indicates that there is no\nwell-defined value for that key.\n\nEach entry in the resulting list contains the following corresponding\ninformation about the program forms:\n\n- **`{attributes, Attributes}`**\n\n - `Attributes = [{atom(), term()}]`\n\n `Attributes` is a list of pairs representing the names and\n corresponding values of all so-called \"wild\" attributes (as, for\n example, \"`-compile(...)`\") occurring in `Forms` (see\n [`analyze_wild_attribute/1`](`analyze_wild_attribute/1`)). We do not\n guarantee that each name occurs at most once in the list. The order\n of listing is not defined.\n\n- **`{errors, Errors}`**\n\n - `Errors = [term()]`\n\n `Errors` is the list of error descriptors of all `error_marker` nodes that\n occur in `Forms`. The order of listing is not defined.\n\n- **`{exports, Exports}`**\n\n - `Exports = [FunctionName]`\n - `FunctionName = atom() | {atom(), integer()} | {ModuleName, FunctionName}`\n - `ModuleName = atom()`\n\n `Exports` is a list of representations of those function names that are listed\n by export declaration attributes in `Forms` (see\n [`analyze_export_attribute/1`](`analyze_export_attribute/1`)). We do not\n guarantee that each name occurs at most once in the list. The order of listing\n is not defined.\n\n- **`{functions, Functions}`**\n\n - `Functions = [{atom(), integer()}]`\n\n `Functions` is a list of the names of the functions that are defined in\n `Forms` (see [`analyze_function/1`](`analyze_function/1`)). We do not\n guarantee that each name occurs at most once in the list. The order of listing\n is not defined.\n\n- **`{imports, Imports}`**\n\n - `Imports = [{Module, Names}]`\n - `Module = atom()`\n - `Names = [FunctionName]`\n - `FunctionName = atom() | {atom(), integer()} | {ModuleName, FunctionName}`\n - `ModuleName = atom()`\n\n `Imports` is a list of pairs representing those module names and corresponding\n function names that are listed by import declaration attributes in `Forms`\n (see [`analyze_import_attribute/1`](`analyze_import_attribute/1`)), where each\n `Module` occurs at most once in `Imports`. We do not guarantee that each name\n occurs at most once in the lists of function names. The order of listing is\n not defined.\n\n- **`{module, ModuleName}`**\n\n - `ModuleName = atom()`\n\n `ModuleName` is the name declared by a module attribute in `Forms`. If no\n module name is defined in `Forms`, the result will contain no entry for the\n `module` key. If multiple module name declarations should occur, all but the\n first will be ignored.\n\n- **`{records, Records}`**\n\n - `Records = [{atom(), Fields}]`\n - `Fields = [{atom(), {Default, Type}}]`\n - `Default = none | syntaxTree()`\n - `Type = none | syntaxTree()`\n\n `Records` is a list of pairs representing the names and corresponding field\n declarations of all record declaration attributes occurring in `Forms`. For\n fields declared without a default value, the corresponding value for `Default`\n is the atom `none`. Similarly, for fields declared without a type, the\n corresponding value for `Type` is the atom `none` (see\n [`analyze_record_attribute/1`](`analyze_record_attribute/1`)). We do not\n guarantee that each record name occurs at most once in the list. The order of\n listing is not defined.\n\n- **`{warnings, Warnings}`**\n\n - `Warnings = [term()]`\n\n `Warnings` is the list of error descriptors of all `warning_marker` nodes that\n occur in `Forms`. The order of listing is not defined.\n\nThe evaluation throws `syntax_error` if an ill-formed Erlang construct is\nencountered.\n\n_See also: _`analyze_export_attribute/1`, `analyze_function/1`,\n`analyze_import_attribute/1`, `analyze_record_attribute/1`,\n`analyze_wild_attribute/1`, `erl_syntax:error_marker_info/1`,\n`erl_syntax:warning_marker_info/1`.","ref":"erl_syntax_lib.html#analyze_forms/1"},{"type":"function","title":"erl_syntax_lib.analyze_function/1","doc":"Returns the name and arity of a function definition.\n\nThe result is a pair `{Name, A}` if `Node` represents a function\ndefinition \"`Name(P_1, ..., P_A) -> ...`\".\n\nThe evaluation throws `syntax_error` if `Node` does not represent a well-formed\nfunction definition.","ref":"erl_syntax_lib.html#analyze_function/1"},{"type":"function","title":"erl_syntax_lib.analyze_function_name/1","doc":"Returns the function name represented by a syntax tree.\n\nIf `Node` represents a function name, such as \"`foo/1`\" or\n\"`bloggs:fred/2`\", a uniform representation of that name is\nreturned. Different nestings of arity and module name qualifiers in\nthe syntax tree does not affect the result.\n\nThe evaluation throws `syntax_error` if `Node` does not represent a well-formed\nfunction name.","ref":"erl_syntax_lib.html#analyze_function_name/1"},{"type":"function","title":"erl_syntax_lib.analyze_implicit_fun/1","doc":"Returns the name of an implicit fun expression \"`fun F`\".\n\nThe result is a representation of the function name `F`. (See\n[`analyze_function_name/1`](`analyze_function_name/1`).)\n\nThe evaluation throws `syntax_error` if `Node` does not represent a well-formed\nimplicit fun.\n\n_See also: _`analyze_function_name/1`.","ref":"erl_syntax_lib.html#analyze_implicit_fun/1"},{"type":"function","title":"erl_syntax_lib.analyze_import_attribute/1","doc":"Returns the module name and (if present) list of function names declared by an\nimport attribute.\n\nThe returned value is an atom `Module` or a pair `{Module, Names}`,\nwhere `Names` is a list of function names declared as imported from\nthe module named by `Module`. We do not guarantee that each name\noccurs at most once in `Names`. The order of listing is not defined.\n\nThe evaluation throws `syntax_error` if `Node` does not represent a well-formed\nimport attribute.\n\n_See also: _`analyze_attribute/1`.","ref":"erl_syntax_lib.html#analyze_import_attribute/1"},{"type":"function","title":"erl_syntax_lib.analyze_module_attribute/1","doc":"Returns the module name and possible parameters declared by a module attribute.\n\nIf the attribute is a plain module declaration such as `-module(name)`, the\nresult is the module name. If the attribute is a parameterized module\ndeclaration, the result is a tuple containing the module name and a list of the\nparameter variable names.\n\nThe evaluation throws `syntax_error` if `Node` does not represent a well-formed\nmodule attribute.\n\n_See also: _`analyze_attribute/1`.","ref":"erl_syntax_lib.html#analyze_module_attribute/1"},{"type":"function","title":"erl_syntax_lib.analyze_record_attribute/1","doc":"Returns the name and the list of fields of a record declaration attribute.\n\nThe result is a pair `{Name, Fields}`, if `Node` represents\n\"`-record(Name, {...}).`\", where `Fields` is a list of pairs\n`{Label, {Default, Type}}` for each field \"`Label`\", \"`Label = Default`\",\n\"`Label :: Type`\", or \"`Label = Default :: Type`\" in the declaration, listed in\nleft-to-right order. If the field has no default-value declaration, the value\nfor `Default` will be the atom `none`. If the field has no type declaration, the\nvalue for `Type` will be the atom `none`. We do not guarantee that each label\noccurs at most once in the list.\n\nThe evaluation throws `syntax_error` if `Node` does not represent a well-formed\nrecord declaration attribute.\n\n_See also: _`analyze_attribute/1`, `analyze_record_field/1`.","ref":"erl_syntax_lib.html#analyze_record_attribute/1"},{"type":"function","title":"erl_syntax_lib.analyze_record_expr/1","doc":"Returns the record name and field name/names of a record expression.\n\nIf `Node` has type `record_expr`, `record_index_expr` or\n`record_access`, a pair `{Type, Info}` is returned, otherwise an atom\n`Type` is returned. `Type` is the node type of `Node`, and `Info`\ndepends on `Type`, as follows:\n\n- **`record_expr`:** - `{atom(), [{atom(), Value}]}`\n\n- **`record_access`:** - `{atom(), atom()}`\n\n- **`record_index_expr`:** - `{atom(), atom()}`\n\nFor a `record_expr` node, `Info` represents the record name and the list of\ndescriptors for the involved fields, listed in the order they appear. A field\ndescriptor is a pair `{Label, Value}`, if `Node` represents \"`Label = Value`\".\nFor a `record_access` node, `Info` represents the record name and the field\nname. For a `record_index_expr` node, `Info` represents the record name and the\nname field name.\n\nThe evaluation throws `syntax_error` if `Node` represents a record expression\nthat is not well-formed.\n\n_See also: _`analyze_record_attribute/1`, `analyze_record_field/1`.","ref":"erl_syntax_lib.html#analyze_record_expr/1"},{"type":"function","title":"erl_syntax_lib.analyze_record_field/1","doc":"Returns the label, value-expression, and type of a record field specifier.\n\nThe result is a pair `{Label, {Default, Type}}`, if `Node` represents\n\"`Label`\", \"`Label = Default`\", \"`Label :: Type`\", or \"`Label =\nDefault :: Type`\". If the field has no value-expression, the value for\n`Default` will be the atom `none`. If the field has no type, the\nvalue for `Type` will be the atom `none`.\n\nThe evaluation throws `syntax_error` if `Node` does not represent a well-formed\nrecord field specifier.\n\n_See also: _`analyze_record_attribute/1`, `analyze_record_expr/1`.","ref":"erl_syntax_lib.html#analyze_record_field/1"},{"type":"function","title":"erl_syntax_lib.analyze_type_application/1","doc":"Returns the name of a used type.\n\nThe result is a representation of the name of the used pre-defined or\nlocal type `N/A`, if `Node` represents a local (user) type application\n\"`N(T_1, ..., T_A)`\", or a representation of the name of the used\nremote type `M:N/A` if `Node` represents a remote user type\napplication \"`M:N(T_1, ..., T_A)`\".\n\nThe evaluation throws `syntax_error` if `Node` does not represent a well-formed\n(user) type application expression.\n\n_See also: _`analyze_type_name/1`.","ref":"erl_syntax_lib.html#analyze_type_application/1"},{"type":"function","title":"erl_syntax_lib.analyze_type_name/1","doc":"Returns the type name represented by a syntax tree.\n\nIf `Node` represents a type name, such as \"`foo/1`\" or\n\"`bloggs:fred/2`\", a uniform representation of that name is returned.\n\nThe evaluation throws `syntax_error` if `Node` does not represent a well-formed\ntype name.","ref":"erl_syntax_lib.html#analyze_type_name/1"},{"type":"function","title":"erl_syntax_lib.analyze_wild_attribute/1","doc":"Returns the name and value of a \"wild\" attribute.\n\nThe result is the pair `{Name, Value}`, if `Node` represents\n\"`-Name(Value)`\".\n\nNote that no checking is done whether `Name` is a reserved attribute name such\nas `module` or `export`: it is assumed that the attribute is \"wild\".\n\nThe evaluation throws `syntax_error` if `Node` does not represent a well-formed\nwild attribute.\n\n_See also: _`analyze_attribute/1`.","ref":"erl_syntax_lib.html#analyze_wild_attribute/1"},{"type":"function","title":"erl_syntax_lib.annotate_bindings/1","doc":"Adds or updates annotations on nodes in a syntax tree.\n\nEquivalent to [`annotate_bindings(Tree,\nBindings)`](`annotate_bindings/2`) where the top-level environment\n`Bindings` is taken from the annotation `{env, Bindings}` on the root\nnode of `Tree`. An exception is thrown if no such annotation should\nexist.\n\n_See also: _`annotate_bindings/2`.","ref":"erl_syntax_lib.html#annotate_bindings/1"},{"type":"function","title":"erl_syntax_lib.annotate_bindings/2","doc":"Adds or updates annotations on nodes in a syntax tree.\n\n`Bindings` specifies the set of bound variables in the environment of\nthe top level node. The following annotations are affected:\n\n- `{env, Vars}`, representing the input environment of the subtree.\n- `{bound, Vars}`, representing the variables that are bound in the subtree.\n- `{free, Vars}`, representing the free variables in the subtree.\n\n`Bindings` and `Vars` are ordered-set lists (see module `m:ordsets`) of atoms\nrepresenting variable names.\n\n_See also: _[//stdlib/ordsets](`m:ordsets`), `annotate_bindings/1`.","ref":"erl_syntax_lib.html#annotate_bindings/2"},{"type":"function","title":"erl_syntax_lib.fold/3","doc":"Folds a function over all nodes of a syntax tree.\n\nThe result is the value of `Function(X1, Function(X2, ... Function(Xn,\nStart) ... ))`, where `[X1, X2, ..., Xn]` are the nodes of `Tree` in a\npost-order traversal.\n\n_See also: _`fold_subtrees/3`, `foldl_listlist/3`.","ref":"erl_syntax_lib.html#fold/3"},{"type":"function","title":"erl_syntax_lib.fold_subtrees/3","doc":"Folds a function over the immediate subtrees of a syntax tree.\n\nThis is similar to [`fold/3`](`fold/3`), but only on the immediate\nsubtrees of `Tree`, in left-to-right order; it does not include the\nroot node of `Tree`.\n\n_See also: _`fold/3`.","ref":"erl_syntax_lib.html#fold_subtrees/3"},{"type":"function","title":"erl_syntax_lib.foldl_listlist/3","doc":"Like `lists:foldl/3`, but over a list of lists.\n\n_See also: _[//stdlib/lists:foldl/3](`lists:foldl/3`), `fold/3`.","ref":"erl_syntax_lib.html#foldl_listlist/3"},{"type":"function","title":"erl_syntax_lib.function_name_expansions/1","doc":"Creates a mapping from corresponding short names to full function names.\n\nNames are represented by nested tuples of atoms and integers (see\n[`analyze_function_name/1`](`analyze_function_name/1`)). The result is\na list containing a pair `{ShortName, Name}` for each element `Name`\nin the given list, where the corresponding `ShortName` is the\nrightmost-innermost part of `Name`. The list thus represents a finite\nmapping from unqualified names to the corresponding qualified names.\n\nNote that the resulting list can contain more than one tuple\n`{ShortName, Name}` for the same `ShortName`, possibly with different\nvalues for `Name`, depending on the given list.\n\n_See also: _`analyze_function_name/1`.","ref":"erl_syntax_lib.html#function_name_expansions/1"},{"type":"function","title":"erl_syntax_lib.is_fail_expr/1","doc":"Returns `true` if `Tree` represents an expression that never terminates\nnormally.\n\nNote that the reverse does not apply. Currently, the detected cases\nare calls to [`exit/1`](`exit/1`), [`throw/1`](`throw/1`),\n`erlang:error/1` and `erlang:error/2`.\n\n_See also: _[//erts/erlang:error/1](`erlang:error/1`),\n[//erts/erlang:error/2](`erlang:error/2`),\n[//erts/erlang:exit/1](`erlang:exit/1`),\n[//erts/erlang:throw/1](`erlang:throw/1`).","ref":"erl_syntax_lib.html#is_fail_expr/1"},{"type":"function","title":"erl_syntax_lib.limit/2","doc":"Equivalent to [`limit(Tree, Depth, Text)`](`limit/3`) using the text `\"...\"` as\ndefault replacement.\n\n_See also: _`limit/3`, `erl_syntax:text/1`.","ref":"erl_syntax_lib.html#limit/2"},{"type":"function","title":"erl_syntax_lib.limit/3","doc":"Limits a syntax tree to a specified depth.\n\nReplaces all non-leaf subtrees in\n`Tree` at the given `Depth` by `Node`. If `Depth` is negative, the result is\nalways `Node`, even if `Tree` has no subtrees.\n\nWhen a group of subtrees (as, for example, the argument list of an\n`application` node) is at the specified depth, and there are two or\nmore subtrees in the group, these will be collectively replaced by\n`Node` even if they are leaf nodes. Groups of subtrees that are above\nthe specified depth will be limited in size, as if each subsequent\ntree in the group were one level deeper than the previous. For example,\nif `Tree` represents a list of integers \"`[1, 2, 3, 4, 5, 6, 7, 8, 9,\n10]`\", the result of [`limit(Tree, 5)`](`limit/2`) will represent `[1,\n2, 3, 4, ...]`.\n\nThe resulting syntax tree is typically only useful for pretty-printing or\nsimilar visual formatting.\n\n_See also: _`limit/2`.","ref":"erl_syntax_lib.html#limit/3"},{"type":"function","title":"erl_syntax_lib.map/2","doc":"Applies a function to each node of a syntax tree.\n\nThe result of each application replaces the corresponding original\nnode. The order of traversal is bottom-up.\n\n_See also: _`map_subtrees/2`.","ref":"erl_syntax_lib.html#map/2"},{"type":"function","title":"erl_syntax_lib.map_subtrees/2","doc":"Applies a function to each immediate subtree of a syntax tree.\n\nThe result of each application replaces the corresponding original\nnode.\n\n_See also: _`map/2`.","ref":"erl_syntax_lib.html#map_subtrees/2"},{"type":"function","title":"erl_syntax_lib.mapfold/3","doc":"Combines map and fold in a single operation.\n\nThis is similar to [`map/2`](`map/2`), but also propagates an extra\nvalue from each application of the `Function` to the next, while doing\na post-order traversal of the tree like [`fold/3`](`fold/3`). The\nvalue `Start` is passed to the first function application, and the\nfinal result is the result of the last application.\n\n_See also: _`fold/3`, `map/2`.","ref":"erl_syntax_lib.html#mapfold/3"},{"type":"function","title":"erl_syntax_lib.mapfold_subtrees/3","doc":"Does a mapfold operation over the immediate subtrees of a syntax tree.\n\nThis is similar to [`mapfold/3`](`mapfold/3`), but only on the\nimmediate subtrees of `Tree`, in left-to-right order; it does not\ninclude the root node of `Tree`.\n\n_See also: _`mapfold/3`.","ref":"erl_syntax_lib.html#mapfold_subtrees/3"},{"type":"function","title":"erl_syntax_lib.mapfoldl_listlist/3","doc":"Like `lists:mapfoldl/3`, but over a list of lists.\n\nThe list of lists in the result has the same structure as the given\nlist of lists.","ref":"erl_syntax_lib.html#mapfoldl_listlist/3"},{"type":"function","title":"erl_syntax_lib.new_variable_name/1","doc":"Returns an atom which is not already in the set `Used`.\n\nThis is equivalent to [`new_variable_name(Function,\nUsed)`](`new_variable_name/2`), where `Function` maps a given integer\n`N` to the atom whose name consists of \"`V`\" followed by the numeral\nfor `N`.\n\n_See also: _`new_variable_name/2`.","ref":"erl_syntax_lib.html#new_variable_name/1"},{"type":"function","title":"erl_syntax_lib.new_variable_name/2","doc":"Returns a user-named atom which is not already in the set `Used`.\n\nThe atom is generated by applying the given `Function` to a generated\ninteger. Integers are generated using an algorithm which tries to keep\nthe names randomly distributed within a reasonably small range\nrelative to the number of elements in the set.\n\nThis function uses the module `m:rand` to generate new keys. The seed it uses can\nbe initialized by calling `rand:seed/1` or `rand:seed/2` before this function is\nfirst called.\n\n_See also: _[//stdlib/rand](`m:rand`), [//stdlib/sets](`m:sets`),\n`new_variable_name/1`.","ref":"erl_syntax_lib.html#new_variable_name/2"},{"type":"function","title":"erl_syntax_lib.new_variable_names/2","doc":"Like [`new_variable_name/1`](`new_variable_name/1`), but generates a list of `N`\nnew names.\n\n_See also: _`new_variable_name/1`.","ref":"erl_syntax_lib.html#new_variable_names/2"},{"type":"function","title":"erl_syntax_lib.new_variable_names/3","doc":"Like [`new_variable_name/2`](`new_variable_name/2`), but generates a list of `N`\nnew names.\n\n_See also: _`new_variable_name/2`.","ref":"erl_syntax_lib.html#new_variable_names/3"},{"type":"function","title":"erl_syntax_lib.strip_comments/1","doc":"Removes all comments from all nodes of a syntax tree.\n\nAll other attributes (such as position information) remain\nunchanged. Standalone comments in form lists are removed; any other\nstandalone comments are changed into null-comments (no text, no\nindentation).","ref":"erl_syntax_lib.html#strip_comments/1"},{"type":"function","title":"erl_syntax_lib.to_comment/1","doc":"","ref":"erl_syntax_lib.html#to_comment/1"},{"type":"function","title":"erl_syntax_lib.to_comment/2","doc":"Equivalent to [`to_comment(Tree, Prefix, F)`](`to_comment/3`) for a default\nformatting function `F`.\n\nThe default `F` simply calls `erl_prettypr:format/1`.\n\n_See also: _`to_comment/3`, `erl_prettypr:format/1`.","ref":"erl_syntax_lib.html#to_comment/2"},{"type":"function","title":"erl_syntax_lib.to_comment/3","doc":"Transforms a syntax tree into an abstract comment.\n\nThe lines of the comment contain the text for `Node`, as produced by\nthe given `Printer` function. Each line of the comment is prefixed by\nthe string `Prefix` (this does not include the initial \"`%`\" character\nof the comment line).\n\nFor example, the result of\n[`to_comment(erl_syntax:abstract([a,b,c]))`](`to_comment/1`) represents\n\n```erlang\n%% [a,b,c]\n```\n\n(see [`to_comment/1`](`to_comment/1`)).\n\n> #### Note {: .info }\n>\n> The text returned by the formatting function will be split\n> automatically into separate comment lines at each line break. No extra\n> work is needed.\n\n_See also: _`to_comment/1`, `to_comment/2`.","ref":"erl_syntax_lib.html#to_comment/3"},{"type":"function","title":"erl_syntax_lib.variables/1","doc":"Returns the names of variables occurring in a syntax tree.\n\nThe result is a set of variable names represented by atoms. Macro\nnames are not included.\n\n_See also: _[//stdlib/sets](`m:sets`).","ref":"erl_syntax_lib.html#variables/1"},{"type":"type","title":"erl_syntax_lib.appFunName/0","doc":"","ref":"erl_syntax_lib.html#t:appFunName/0"},{"type":"type","title":"erl_syntax_lib.field/0","doc":"","ref":"erl_syntax_lib.html#t:field/0"},{"type":"type","title":"erl_syntax_lib.field_default/0","doc":"","ref":"erl_syntax_lib.html#t:field_default/0"},{"type":"type","title":"erl_syntax_lib.field_type/0","doc":"","ref":"erl_syntax_lib.html#t:field_type/0"},{"type":"type","title":"erl_syntax_lib.fields/0","doc":"","ref":"erl_syntax_lib.html#t:fields/0"},{"type":"type","title":"erl_syntax_lib.functionN/0","doc":"","ref":"erl_syntax_lib.html#t:functionN/0"},{"type":"type","title":"erl_syntax_lib.functionName/0","doc":"","ref":"erl_syntax_lib.html#t:functionName/0"},{"type":"type","title":"erl_syntax_lib.info/0","doc":"","ref":"erl_syntax_lib.html#t:info/0"},{"type":"type","title":"erl_syntax_lib.info_pair/0","doc":"","ref":"erl_syntax_lib.html#t:info_pair/0"},{"type":"type","title":"erl_syntax_lib.key/0","doc":"","ref":"erl_syntax_lib.html#t:key/0"},{"type":"type","title":"erl_syntax_lib.name/0","doc":"","ref":"erl_syntax_lib.html#t:name/0"},{"type":"type","title":"erl_syntax_lib.ordset/1","doc":"","ref":"erl_syntax_lib.html#t:ordset/1"},{"type":"type","title":"erl_syntax_lib.set/1","doc":"","ref":"erl_syntax_lib.html#t:set/1"},{"type":"type","title":"erl_syntax_lib.shortname/0","doc":"","ref":"erl_syntax_lib.html#t:shortname/0"},{"type":"type","title":"erl_syntax_lib.syntaxTree/0","doc":"An abstract syntax tree. See the `m:erl_syntax` module for details.","ref":"erl_syntax_lib.html#t:syntaxTree/0"},{"type":"type","title":"erl_syntax_lib.typeName/0","doc":"","ref":"erl_syntax_lib.html#t:typeName/0"},{"type":"module","title":"merl","doc":"Metaprogramming in Erlang.\n\nMerl is a user-friendly interface to the `erl_syntax` module,\nmaking it easy both to build new ASTs from scratch and to match and\ndecompose existing ASTs. For details that are outside the scope of\nMerl itself, see the documentation of `m:erl_syntax`.","ref":"merl.html"},{"type":"module","title":"Quick start - merl","doc":"To enable the full power of Merl, your module needs to include the Merl header\nfile:\n\n```erlang\n-include_lib(\"syntax_tools/include/merl.hrl\").\n```\n\nThen, you can use the `?Q(Text)` macros in your code to create ASTs or match on\nexisting ASTs. For example:\n\n```erlang\nTuple = ?Q(\"{foo, 42}\"),\n?Q(\"{foo, _@Number}\") = Tuple,\nCall = ?Q(\"foo:bar(_@Number)\")\n```\n\nCalling `merl:print(Call)` will then print the following code:\n\n```erlang\nfoo:bar(42)\n```\n\nThe `?Q` macros turn the quoted code fragments into ASTs, and lifts\nmetavariables such as `_@Tuple` and `_@Number` to the level of your Erlang code,\nso you can use the corresponding Erlang variables `Tuple` and `Number` directly.\nThis is the most straightforward way to use Merl, and in many cases it's all you\nneed.\n\nYou can even write case switches using `?Q` macros as patterns. For example:\n\n```erlang\ncase AST of\n ?Q(\"{foo, _@Foo}\") -> handle(Foo);\n ?Q(\"{bar, _@Bar}\") when erl_syntax:is_integer(Bar) -> handle(Bar);\n _ -> handle_default()\nend\n```\n\nThese case switches only allow `?Q(...)` or `_` as clause patterns, and the\nguards may contain any expressions, not just Erlang guard expressions.\n\nIf the macro `MERL_NO_TRANSFORM` is defined before the `merl.hrl` header file is\nincluded, the parse transform used by Merl will be disabled, and in that case,\nthe match expressions `?Q(...) = ...`, case switches using `?Q(...)` patterns,\nand automatic metavariables like `_@Tuple` cannot be used in your code, but the\nMerl macros and functions still work. To do metavariable substitution, you need\nto use the `?Q(Text, Map)` macro. For example:\n\n```erlang\nTuple = ?Q(\"{foo, _@bar, _@baz}\", [{bar, Bar}, {baz,Baz}])\n```\n\nThe text given to a `?Q(Text)` macro can be either a single string or a list of\nstrings. The latter is useful when you need to split a long expression over\nmultiple lines. For example:\n\n```erlang\n?Q([\"case _@Expr of\",\n \" {foo, X} -> f(X);\",\n \" {bar, X} -> g(X)\",\n \" _ -> h(X)\"\n\"end\"])\n```\n\nIf there is a syntax error somewhere in the text (like the missing semicolon in\nthe second clause above) this allows Merl to generate an error message pointing\nto the exact line in your source code. (Just remember to comma-separate the\nstrings in the list, otherwise Erlang will concatenate the string fragments as\nif they were a single string.)","ref":"merl.html#module-quick-start"},{"type":"module","title":"Metavariable syntax - merl","doc":"There are several ways to write a metavariable in your quoted code:\n\n- Atoms starting with `@`, for example `'@foo'` or `'@Foo'`\n- Variables starting with `_@`, for example `_@bar` or `_@Bar`\n- Strings starting with `\"'@`, for example `\"'@File\"`\n- Integers starting with 909, for example `9091` or `909123`\n\nFollowing the prefix, one or more `_` or `0` characters may be used to indicate\n\"lifting\" of the variable one or more levels, and after that, a `@` or `9`\ncharacter indicates a glob metavariable (matching zero or more elements in a\nsequence) rather than a normal metavariable. For example:\n\n- `'@_foo'` is lifted one level, and `_@__foo` is lifted two levels\n- `_@@bar` is a glob variable, and `_@_@bar` is a lifted glob variable\n- `90901` is a lifted variable,`90991` is a glob variable, and `9090091` is a\n glob variable lifted two levels\n\n(Note that the last character in the name is never considered to be a lift or\nglob marker, hence, `_@__` and `90900` are only lifted one level, not two. Also\nnote that globs only matter for matching; when doing substitutions, a non-glob\nvariable can be used to inject a sequence of elements, and vice versa.)\n\nIf the name after the prefix and any lift and glob markers is `_` or `0`, the\nvariable is treated as an anonymous catch-all pattern in matches. For example,\n`_@_`, `_@@_`, `_@__`, or even `_@__@_`.\n\nFinally, if the name without any prefixes or lift/glob markers begins with an\nuppercase character, as in `_@Foo` or `_@_@Foo`, it will become a variable on\nthe Erlang level, and can be used to easily deconstruct and construct syntax\ntrees:\n\n```erlang\ncase Input of\n ?Q(\"{foo, _@Number}\") -> ?Q(\"foo:bar(_@Number)\");\n ...\n```\n\nWe refer to these as \"automatic metavariables\". If in addition the name ends\nwith `@`, as in `_@Foo@`, the value of the variable as an Erlang term will be\nautomatically converted to the corresponding abstract syntax tree when used to\nconstruct a larger tree. For example, in:\n\n```erlang\nBar = {bar, 42},\nFoo = ?Q(\"{foo, _@Bar@}\")\n```\n\n(where Bar is just some term, not a syntax tree) the result `Foo` will be a\nsyntax tree representing `{foo, {bar, 42}}`. This avoids the need for temporary\nvariables in order to inject data, as in\n\n```erlang\nTmpBar = erl_syntax:abstract(Bar),\nFoo = ?Q(\"{foo, _@TmpBar}\")\n```\n\nIf the context requires an integer rather than a variable, an atom, or a string,\nyou cannot use the uppercase convention to mark an automatic metavariable.\nInstead, if the integer (without the `909`\\-prefix and lift/glob markers) ends\nin a `9`, the integer will become an Erlang-level variable prefixed with `Q`,\nand if it ends with `99` it will also be automatically abstracted. For example,\nthe following will increment the arity of the exported function f:\n\n```erlang\ncase Form of\n ?Q(\"-export([f/90919]).\") ->\n Q2 = erl_syntax:concrete(Q1) + 1,\n ?Q(\"-export([f/909299]).\");\n ...\n```","ref":"merl.html#module-metavariable-syntax"},{"type":"module","title":"When to use the various forms of metavariables - merl","doc":"Merl can only parse a fragment of text if it follows the basic syntactical rules\nof Erlang. In most places, a normal Erlang variable can be used as metavariable,\nfor example:\n\n```erlang\n?Q(\"f(_@Arg)\") = Expr\n```\n\nbut if you want to match on something like the name of a function, you have to\nuse an atom as metavariable:\n\n```erlang\n?Q(\"'@Name'() -> _@@_.\" = Function\n```\n\n(note the anonymous glob variable `_@@_` to ignore the function body).\n\nIn some contexts, only a string or an integer is allowed. For example, the\ndirective `-file(Name, Line)` requires that `Name` is a string literal and\n`Line` an integer literal:\n\n```erlang\n?Q(\"-file(\\\"'@File\\\", 9090).\") = ?Q(\"-file(\\\"foo.erl\\\", 42).\")).\n```\n\nThis will extract the string literal `\"foo.erl\"` into the variable `Foo`. Note\nthe use of the anonymous variable `9090` to ignore the line number. To match and\nalso bind a metavariable that must be an integer literal, we can use the\nconvention of ending the integer with a 9, turning it into a Q-prefixed variable\non the Erlang level (see the previous section).\n\n#### Globs\n\nWhenever you want to match out a number of elements in a sequence (zero or more)\nrather than a fixed set of elements, you need to use a glob. For example:\n\n```erlang\n?Q(\"{_@@Elements}\") = ?Q({a, b, c})\n```\n\nwill bind Elements to the list of individual syntax trees representing the atoms\n`a`, `b`, and `c`. This can also be used with static prefix and suffix elements\nin the sequence. For example:\n\n```erlang\n?Q(\"{a, b, _@@Elements}\") = ?Q({a, b, c, d})\n```\n\nwill bind Elements to the list of the `c` and `d` subtrees, and\n\n```erlang\n?Q(\"{_@@Elements, c, d}\") = ?Q({a, b, c, d})\n```\n\nwill bind Elements to the list of the `a` and `b` subtrees. You can even use\nplain metavariables in the prefix or suffix:\n\n```erlang\n?Q(\"{_@First, _@@Rest}\") = ?Q({a, b, c})\n```\n\nor\n\n```erlang\n?Q(\"{_@@_, _@Last}\") = ?Q({a, b, c})\n```\n\n(ignoring all but the last element). However, you cannot have two globs as part\nof the same sequence.\n\n#### Lifted metavariables\n\nIn some cases, the Erlang syntax rules make it impossible to place a\nmetavariable directly where you would like it. For example, you cannot write:\n\n```erlang\n?Q(\"-export([_@@Name]).\")\n```\n\nto match out all name/arity pairs in the export list, or to insert a list of\nexports in a declaration, because the Erlang parser only allows elements on the\nform `A/I` (where `A` is an atom and `I` an integer) in the export list. A\nvariable like the above is not allowed, but neither is a single atom or integer,\nso `'@@Name'` or `909919` would not work either.\n\nWhat you have to do in such cases is to write your metavariable in a\nsyntactically valid position, and use lifting markers to denote where it should\nreally apply, as in:\n\n```erlang\n?Q(\"-export(['@_@Name'/0]).\")\n```\n\nThis causes the variable to be lifted (after parsing) to the next higher level\nin the syntax tree, replacing that entire subtree. In this case, the\n`'@_@Name'/0` will be replaced with `'@@Name'`, and the `/0` part was just used\nas dummy notation and will be discarded.\n\nYou may even need to apply lifting more than once. To match the entire export\nlist as a single syntax tree, you can write:\n\n```erlang\n?Q(\"-export(['@__Name'/0]).\")\n```\n\nusing two underscores, but with no glob marker this time. This will make the\nentire `['@__Name'/0]` part be replaced with `'@Name'`.\n\nSometimes, the tree structure of a code fragment is not very obvious, and parts\nof the structure may be invisible when printed as source code. For instance, a\nsimple function definition like the following:\n\n```erlang\nzero() -> 0.\n```\n\nconsists of the name (the atom `zero`), and a list of clauses containing the\nsingle clause `() -> 0`. The clause consists of an argument list (empty), a\nguard (empty), and a body (which is always a list of expressions) containing the\nsingle expression `0`. This means that to match out the name and the list of\nclauses of any function, you'll need to use a pattern like\n`?Q(\"'@Name'() -> _@_@Body.\")`, using a dummy clause whose body is a glob lifted\none level.\n\nTo visualize the structure of a syntax tree, you can use the function\n`merl:show(T)`, which prints a summary. For example, entering\n\n```erlang\nmerl:show(merl:quote(\"inc(X, Y) when Y > 0 -> X + Y.\"))\n```\n\nin the Erlang shell will print the following (where the `+` signs separate\ngroups of subtrees on the same level):\n\n```text\nfunction: inc(X, Y) when ... -> X + Y.\n atom: inc\n +\n clause: (X, Y) when ... -> X + Y\n variable: X\n variable: Y\n +\n disjunction: Y > 0\n conjunction: Y > 0\n infix_expr: Y > 0\n variable: Y\n +\n operator: >\n +\n integer: 0\n +\n infix_expr: X + Y\n variable: X\n +\n operator: +\n +\n variable: Y\n```\n\nThis shows another important non-obvious case: a clause guard, even if it's as\nsimple as `Y > 0`, always consists of a single disjunction of one or more\nconjunctions of tests, much like a tuple of tuples. Thus:\n\n- `\"when _@Guard ->\"` will only match a guard with exactly one test\n- `\"when _@@Guard ->\"` will match a guard with one or more comma-separated tests\n (but no semicolons), binding `Guard` to the list of tests\n- `\"when _@_Guard ->\"` will match just like the previous pattern, but binds\n `Guard` to the conjunction subtree\n- `\"when _@_@Guard ->\"` will match an arbitrary nonempty guard, binding `Guard`\n to the list of conjunction subtrees\n- `\"when _@__Guard ->\"` will match like the previous pattern, but binds `Guard`\n to the whole disjunction subtree\n- and finally, `\"when _@__@Guard ->\"` will match any clause, binding `Guard` to\n `[]` if the guard is empty and to `[Disjunction]` otherwise\n\nThus, the following pattern matches all possible clauses:\n\n```erlang\n \"(_@Args) when _@__@Guard -> _@Body\"\n```","ref":"merl.html#module-when-to-use-the-various-forms-of-metavariables"},{"type":"function","title":"merl.alpha/2","doc":"Alpha converts a pattern (renames variables).\n\nSimilar to tsubst/1, but only renames variables (including globs).\n\n_See also: _`tsubst/2`.","ref":"merl.html#alpha/2"},{"type":"function","title":"merl.compile/1","doc":"","ref":"merl.html#compile/1"},{"type":"function","title":"merl.compile/2","doc":"Compile a syntax tree or list of syntax trees representing a module into a\nbinary BEAM object.\n\n_See also: _`compile/1`, `compile_and_load/2`.","ref":"merl.html#compile/2"},{"type":"function","title":"merl.compile_and_load/1","doc":"","ref":"merl.html#compile_and_load/1"},{"type":"function","title":"merl.compile_and_load/2","doc":"Compile a syntax tree or list of syntax trees representing a module and load the\nresulting module into memory.\n\n_See also: _`compile/2`, `compile_and_load/1`.","ref":"merl.html#compile_and_load/2"},{"type":"function","title":"merl.match/2","doc":"Match a pattern against a syntax tree (or patterns against syntax trees)\nreturning an environment mapping variable names to subtrees; the environment is\nalways sorted on keys.\n\n> #### Note {: .info }\n>\n> Multiple occurrences of metavariables in the pattern is not\n> allowed, but is not checked.\n\n_See also: _`switch/2`, `template/1`.","ref":"merl.html#match/2"},{"type":"function","title":"merl.meta_template/1","doc":"Turn a template into a syntax tree representing the template.\n\nMeta-variables in the template are turned into normal Erlang variables\nif their names (after the metavariable prefix characters) begin with\nan uppercase character. For example, `_@Foo` in the template becomes the\nvariable `Foo` in the meta-template. Furthermore, variables ending\nwith `@` are automatically wrapped in a call to merl:term/1, so\n`_@Foo@` in the template becomes `merl:term(Foo)` in the\nmeta-template.","ref":"merl.html#meta_template/1"},{"type":"function","title":"merl.print/1","doc":"Pretty-print a syntax tree or template to the standard output.\n\nThis is a utility function for development and debugging.","ref":"merl.html#print/1"},{"type":"function","title":"merl.qquote/2","doc":"","ref":"merl.html#qquote/2"},{"type":"function","title":"merl.qquote/3","doc":"Parse text and substitute meta-variables.\n\nTakes an initial scanner starting position as first argument.\n\nThe macro `?Q(Text, Env)` expands to `merl:qquote(?LINE, Text, Env)`.\n\n_See also: _`quote/2`.","ref":"merl.html#qquote/3"},{"type":"function","title":"merl.quote/1","doc":"","ref":"merl.html#quote/1"},{"type":"function","title":"merl.quote/2","doc":"Parse text.\n\nTakes an initial scanner starting position as first argument.\n\nThe macro `?Q(Text)` expands to `merl:quote(?LINE, Text)`.\n\n_See also: _`quote/1`.","ref":"merl.html#quote/2"},{"type":"function","title":"merl.show/1","doc":"Print the structure of a syntax tree or template to the standard output.\n\nThis is a utility function for development and debugging.","ref":"merl.html#show/1"},{"type":"function","title":"merl.subst/2","doc":"Substitute metavariables in a pattern or list of patterns, yielding a syntax\ntree or list of trees as result.\n\nBoth for normal metavariables and glob metavariables, the substituted\nvalue may be a single element or a list of elements. For example, if a\nlist representing `1, 2, 3` is substituted for `var` in either of\n`[foo, _@var, bar]` or `[foo, _@var, bar]`, the result represents\n`[foo, 1, 2, 3, bar]`.","ref":"merl.html#subst/2"},{"type":"function","title":"merl.switch/2","doc":"Match against one or more clauses with patterns and optional guards.\n\nNote that clauses following a default action will be ignored.\n\n_See also: _`match/2`.","ref":"merl.html#switch/2"},{"type":"function","title":"merl.template/1","doc":"Turn a syntax tree or list of trees into a template or templates.\n\nTemplates can be instantiated or matched against, and reverted back to\nnormal syntax trees using `tree/1`. If the input is already a\ntemplate, it is not modified further.\n\n_See also: _`match/2`, `subst/2`, `tree/1`.","ref":"merl.html#template/1"},{"type":"function","title":"merl.template_vars/1","doc":"Return an ordered list of the metavariables in the template.","ref":"merl.html#template_vars/1"},{"type":"function","title":"merl.term/1","doc":"Create a syntax tree for a constant term.","ref":"merl.html#term/1"},{"type":"function","title":"merl.tree/1","doc":"Revert a template to a normal syntax tree.\n\nAny remaining metavariables are turned into `@`\\-prefixed atoms or\n`909`\\-prefixed integers.\n\n_See also: _`template/1`.","ref":"merl.html#tree/1"},{"type":"function","title":"merl.tsubst/2","doc":"Like `subst/2`, but does not convert the result from a template back to a tree.\n\nUseful if you want to do multiple separate substitutions.\n\n_See also: _`subst/2`, `tree/1`.","ref":"merl.html#tsubst/2"},{"type":"function","title":"merl.var/1","doc":"Create a variable.","ref":"merl.html#var/1"},{"type":"type","title":"merl.default_action/0","doc":"","ref":"merl.html#t:default_action/0"},{"type":"type","title":"merl.env/0","doc":"","ref":"merl.html#t:env/0"},{"type":"type","title":"merl.guard_test/0","doc":"","ref":"merl.html#t:guard_test/0"},{"type":"type","title":"merl.guarded_action/0","doc":"","ref":"merl.html#t:guarded_action/0"},{"type":"type","title":"merl.guarded_actions/0","doc":"","ref":"merl.html#t:guarded_actions/0"},{"type":"type","title":"merl.id/0","doc":"","ref":"merl.html#t:id/0"},{"type":"type","title":"merl.location/0","doc":"","ref":"merl.html#t:location/0"},{"type":"type","title":"merl.pattern/0","doc":"","ref":"merl.html#t:pattern/0"},{"type":"type","title":"merl.pattern_or_patterns/0","doc":"","ref":"merl.html#t:pattern_or_patterns/0"},{"type":"type","title":"merl.switch_action/0","doc":"","ref":"merl.html#t:switch_action/0"},{"type":"type","title":"merl.switch_clause/0","doc":"","ref":"merl.html#t:switch_clause/0"},{"type":"type","title":"merl.template/0","doc":"","ref":"merl.html#t:template/0"},{"type":"type","title":"merl.template_or_templates/0","doc":"","ref":"merl.html#t:template_or_templates/0"},{"type":"type","title":"merl.text/0","doc":"","ref":"merl.html#t:text/0"},{"type":"type","title":"merl.tree/0","doc":"","ref":"merl.html#t:tree/0"},{"type":"type","title":"merl.tree_or_trees/0","doc":"","ref":"merl.html#t:tree_or_trees/0"},{"type":"module","title":"merl_transform","doc":"Parse transform for merl.\n\nEnables the use of automatic metavariables and using quasi-quotes in\nmatches and case switches. Also optimizes calls to functions in `merl`\nby partially evaluating them, turning strings to templates, and so on,\nat compile-time.\n\nUsing `-include_lib(\"syntax_tools/include/merl.hrl\").` enables this transform,\nunless the macro `MERL_NO_TRANSFORM` is defined first.","ref":"merl_transform.html"},{"type":"module","title":"prettypr","doc":"A generic pretty printer library.\n\nThis module uses a strict-style context passing implementation of John\nHughes algorithm, described in \"The design of a Pretty-printing\nLibrary\". The paragraph-style formatting, empty documents, floating\ndocuments, and null strings are my own additions to the algorithm.\n\nTo get started, you should read about the [`document()`](`t:document/0`) data\ntype; the main constructor functions: `text/1`, `above/2`, `beside/2`, `nest/2`,\n`sep/1`, and `par/2`; and the main layout function `format/3`.\n\nIf you simply want to format a paragraph of plain text, you probably want to use\nthe `text_par/2` function, as in the following example:\n\n```text\n prettypr:format(prettypr:text_par(\"Lorem ipsum dolor sit amet\"), 20)\n```","ref":"prettypr.html"},{"type":"function","title":"prettypr.above/2","doc":"Concatenates documents vertically.\n\nReturns a document representing the concatenation of the documents\n`D1` and `D2` such that the first line of `D2` follows directly below\nthe last line of `D1`, and the first character of `D2` is in the same\nhorizontal column as the first character of `D1`, in all possible\nlayouts.\n\nExamples:\n\n```text\nab cd => ab\n cd\n\n abc\nabc fgh => de\n de ij fgh\n ij\n```","ref":"prettypr.html#above/2"},{"type":"function","title":"prettypr.beside/2","doc":"Concatenates documents horizontally.\n\nReturns a document representing the concatenation of the documents\n`D1` and `D2` such that the last character of `D1` is horizontally\nadjacent to the first character of `D2`, in all possible\nlayouts. (Note: any indentation of `D2` is lost.)\n\nExamples:\n\n```text\nab cd => abcd\n\nab ef ab\ncd gh => cdef\n gh\n```","ref":"prettypr.html#beside/2"},{"type":"function","title":"prettypr.best/3","doc":"Selects a \"best\" layout for a document, creating a corresponding fixed-layout\ndocument.\n\nIf no layout could be produced, the atom `empty` is returned instead.\nFor details about `PaperWidth` and `LineWidth`, see `format/3`. The\nfunction is idempotent.\n\nOne possible use of this function is to compute a fixed layout for a document,\nwhich can then be included as part of a larger document. For example:\n\n```text\n above(text(\"Example:\"), nest(8, best(D, W - 12, L - 6)))\n```\n\nwill format `D` as a displayed-text example indented by 8, whose right margin is\nindented by 4 relative to the paper width `W` of the surrounding document, and\nwhose maximum individual line length is shorter by 6 than the line length `L` of\nthe surrounding document.\n\nThis function is used by the `format/3` function to prepare a document before\nbeing laid out as text.","ref":"prettypr.html#best/3"},{"type":"function","title":"prettypr.break/1","doc":"Forces a line break at the end of the given document.\n\nThis is a utility function; see `empty/0` for details.","ref":"prettypr.html#break/1"},{"type":"function","title":"prettypr.empty/0","doc":"Yields the empty document, which has neither height nor width.\n\n(`empty` is thus different from an empty [`text`](`text/1`) string,\nwhich has zero width but height 1.)\n\nEmpty documents are occasionally useful; in particular, they have the property\nthat [`above(X, empty())`](`above/2`) will force a new line after `X` without\nleaving an empty line below it; since this is a common idiom, the utility\nfunction `break/1` will place a given document in such a context.\n\n_See also: _`text/1`.","ref":"prettypr.html#empty/0"},{"type":"function","title":"prettypr.floating/1","doc":"","ref":"prettypr.html#floating/1"},{"type":"function","title":"prettypr.floating/3","doc":"Creates a \"floating\" document.\n\nThe result represents the same set of layouts as `D`; however, a\nfloating document may be moved relative to other floating documents\nimmediately beside or above it, according to their relative horizontal\nand vertical priorities. These priorities are set with the `Hp` and\n`Vp` parameters; if omitted, both default to zero.\n\n> #### Note {: .info }\n>\n> Floating documents appear to work well, but are currently less general\n> than you might wish, losing effect when embedded in certain contexts. It is\n> possible to nest floating-operators (even with different priorities), but the\n> effects may be difficult to predict. In any case, note that the way the\n> algorithm reorders floating documents amounts to a \"bubblesort\", so don't expect\n> it to be able to sort large sequences of floating documents quickly.","ref":"prettypr.html#floating/3"},{"type":"function","title":"prettypr.follow/2","doc":"","ref":"prettypr.html#follow/2"},{"type":"function","title":"prettypr.follow/3","doc":"Separates two documents by either a single space, or a line break and\nindentation.\n\nIn other words, one of the layouts:\n\n```text\nabc def\n```\n\nor:\n\n```text\nabc\n def\n```\n\nwill be generated, using the optional offset in the latter case. This is often\nuseful for typesetting programming language constructs.\n\nThis is a utility function; see `par/2` for further details.\n\n_See also: _`follow/2`.","ref":"prettypr.html#follow/3"},{"type":"function","title":"prettypr.format/1","doc":"","ref":"prettypr.html#format/1"},{"type":"function","title":"prettypr.format/2","doc":"","ref":"prettypr.html#format/2"},{"type":"function","title":"prettypr.format/3","doc":"Computes a layout for a document and returns the corresponding text.\n\nSee [`document()`](`t:document/0`) for further information. Throws\n`no_layout` if no layout could be selected.\n\n`PaperWidth` specifies the total width (in character positions) of the field for\nwhich the text is to be laid out. `LineWidth` specifies the desired maximum\nwidth (in number of characters) of the text printed on any single line,\ndisregarding leading and trailing white space. These parameters need to be\nproperly balanced in order to produce good layouts. By default, `PaperWidth` is\n80 and `LineWidth` is 65.\n\n_See also: _`best/3`.","ref":"prettypr.html#format/3"},{"type":"function","title":"prettypr.nest/2","doc":"Indents a document a number of character positions to the right.\n\nNote that `N` can be negative, shifting the text to the left, or zero,\nin which case `D` is returned unchanged.","ref":"prettypr.html#nest/2"},{"type":"function","title":"prettypr.null_text/1","doc":"Similar to `text/1`, but the result is treated as having zero width.\n\nThis is regardless of the actual length of the string. Null text is\ntypically used for markup, which is supposed to have no effect on the\nactual layout.\n\nThe standard example is when formatting source code as HTML to be\nplaced within ` ... ` markup, and using elements like ` `\nand ` ` to make parts of the source code stand out. In this case,\nthe markup does not add to the width of the text when viewed in an\nHTML browser, so the layout engine should simply pretend that the\nmarkup has zero width.\n\n_See also: _`empty/0`, `text/1`.","ref":"prettypr.html#null_text/1"},{"type":"function","title":"prettypr.par/1","doc":"","ref":"prettypr.html#par/1"},{"type":"function","title":"prettypr.par/2","doc":"Arranges documents in a paragraph-like layout.\n\nReturns a document representing all possible left-aligned\nparagraph-like layouts of the (nonempty) sequence `Docs` of\ndocuments. Elements in `Docs` are separated horizontally by a single\nspace character and vertically with a single line break. All lines\nfollowing the first (if any) are indented to the same left column,\nwhose indentation is specified by the optional `Offset` parameter\nrelative to the position of the first element in `Docs`. For example,\nwith an offset of -4, the following layout can be produced, for a list\nof documents representing the numbers 0 to 15:\n\n```text\n 0 1 2 3\n4 5 6 7 8 9\n10 11 12 13\n14 15\n```\n\nor with an offset of +2:\n\n```text\n0 1 2 3 4 5 6\n 7 8 9 10 11\n 12 13 14 15\n```\n\nThe utility function `text_par/2` can be used to easily transform a string of\ntext into a `par` representation by splitting it into words.\n\nNote that whenever a document in `Docs` contains a line break, it will be placed\non a separate line. Thus, neither a layout such as:\n\n```text\nab cd\n ef\n```\n\nnor:\n\n```text\nab\ncd ef\n```\n\nwill be generated. However, a useful idiom for making the former variant\npossible (when wanted) is [`beside(par([D1, text(\"\")], N), D2)`](`beside/2`) for\ntwo documents `D1` and `D2`. This will break the line between `D1` and `D2` if\n`D1` contains a line break (or if otherwise necessary), and optionally further\nindent `D2` by `N` character positions. The utility function `follow/3` creates\nthis context for two documents `D1` and `D2`, and an optional integer `N`.\n\n_See also: _`par/1`, `text_par/2`.","ref":"prettypr.html#par/2"},{"type":"function","title":"prettypr.sep/1","doc":"Arranges documents horizontally or vertically, separated by whitespace.\n\nReturns a document representing two alternative layouts of the\n(nonempty) sequence `Docs` of documents, such that either all elements\nin `Docs` are concatenated horizontally, and separated by a space\ncharacter, or all elements are concatenated vertically (without extra\nseparation).\n\n> #### Note {: .info }\n>\n> If some document in `Docs` contains a line break, the vertical layout\n> will always be selected.\n\nExamples:\n\n```text\n ab\nab cd ef => ab cd ef | cd\n ef\n\nab ab\ncd ef => cd\n ef\n```\n\n_See also: _`par/2`.","ref":"prettypr.html#sep/1"},{"type":"function","title":"prettypr.text/1","doc":"Yields a document representing a fixed, unbreakable sequence of characters.\n\nThe string should contain only _printable_ characters (tabs allowed\nbut not recommended), and _not_ newline, line feed, vertical tab,\nand so on. A tab character (`\\t`) is interpreted as padding of 1-8 space\ncharacters to the next column of 8 characters _within the string_.\n\n_See also: _`empty/0`, `null_text/1`, `text_par/2`.","ref":"prettypr.html#text/1"},{"type":"function","title":"prettypr.text_par/1","doc":"","ref":"prettypr.html#text_par/1"},{"type":"function","title":"prettypr.text_par/2","doc":"Yields a document representing paragraph-formatted plain text.\n\nThe `Indentation` parameter specifies the extra indentation\nof the first line of the paragraph. For example, [`text_par(\"Lorem\nipsum dolor sit amet\", N)`](`text_par/2`) could represent:\n\n```text\nLorem ipsum dolor\nsit amet\n```\n\nif N = 0, or:\n\n```text\n Lorem ipsum\ndolor sit amet\n```\n\nif `N` = 2, or:\n\n```text\nLorem ipsum dolor\n sit amet\n```\n\nif `N` = -2.\n\n(The sign of the indentation is thus reversed compared to the `par/2` function,\nand the behaviour varies slightly depending on the sign in order to match the\nexpected layout of a paragraph of text.)\n\nNote that this is just a utility function, which does all the work of splitting\nthe given string into words separated by whitespace and setting up a\n[`par`](`par/2`) with the proper indentation, containing a list of\n[`text`](`text/1`) elements.\n\n_See also: _`par/2`, `text/1`, `text_par/1`.","ref":"prettypr.html#text_par/2"},{"type":"type","title":"prettypr.deep_string/0","doc":"","ref":"prettypr.html#t:deep_string/0"},{"type":"type","title":"prettypr.document/0","doc":"An abstract character-based \"document\" representing\na number of possible layouts, which can be processed to produce a\nsingle concrete layout.\n\nA concrete layout can then be rendered as a sequence of characters\ncontaining linebreaks, which can be passed to a printer or terminal\nthat uses a fixed-width font.\n\nFor example, a document `sep([text(\"foo\"), text(\"bar\")])`\nrepresents the two layouts:\n\n```text\nfoo bar\n```\n\nand:\n\n```text\nfoo\nbar\n```\n\nWhich layout is chosen depends on the available horizontal space.\nWhen processing a document, the main parameters are the _paper\nwidth_ and the _line width_ (also known as the \"ribbon\nwidth\"). In the resulting layout, no text should be printed beyond\nthe paper width (which by default is 80 characters) as long as it can\nbe avoided, and each single line of text (its indentation not\ncounted, hence \"ribbon\") should preferably be no wider than the\nspecified line width (which by default is 65).\n\nDocuments can be joined into a single new document using the\nconstructor functions of this module. Note that the new document\noften represents a larger number of possible layouts than just the\nsum of the components.","ref":"prettypr.html#t:document/0"},{"type":"extras","title":"Syntax_Tools Release Notes","doc":"\n# Syntax_Tools Release Notes\n\nThis document describes the changes made to the Syntax_Tools application.","ref":"notes.html"},{"type":"extras","title":"Syntax_Tools 3.2.1 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-3-2-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","doc":"- The documentation for `syntax_tools` has been polished after the migration to the new documentation system.\n\n Own Id: OTP-19102 Aux Id: [PR-8515]\n\n[PR-8515]: https://github.com/erlang/otp/pull/8515","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Syntax_Tools 3.2 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-3-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","doc":"- The `m:epp_dodger` module can now handle the `maybe` and `else` keywords.\n\n Own Id: OTP-18608 Aux Id: [GH-7266], [PR-7267]\n\n- Reverting a `#wrapper` will no longer throw away changes made to positions/annotations.\n\n Own Id: OTP-18805 Aux Id: [PR-7398]\n\n[GH-7266]: https://github.com/erlang/otp/issues/7266\n[PR-7267]: https://github.com/erlang/otp/pull/7267\n[PR-7398]: https://github.com/erlang/otp/pull/7398","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Syntax_Tools Release Notes","doc":"- The type `t:erl_syntax:annotation_or_location/0` is now exported.\n\n Own Id: OTP-18715 Aux Id: [PR-7535]\n\n- The documentation has been migrated to use Markdown and ExDoc.\n\n Own Id: OTP-18955 Aux Id: [PR-8026]\n\n[PR-7535]: https://github.com/erlang/otp/pull/7535\n[PR-8026]: https://github.com/erlang/otp/pull/8026","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Syntax_Tools 3.1 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-3-1"},{"type":"extras","title":"Improvements and New Features - Syntax_Tools Release Notes","doc":"- Map comprehensions as suggested in EEP 58 has now been implemented.\n\n Own Id: OTP-18413 Aux Id: EEP-58, PR-6727","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Syntax_Tools 3.0.1 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-3-0-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","doc":"- `erl_syntax_lib:annotate_bindings/1,2` will now properly annotate named\n functions and their arguments.\n\n Own Id: OTP-18380 Aux Id: PR-6523, GH-4733","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Syntax_Tools 3.0 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-3-0"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","doc":"- The `erl_syntax_lib:analyze_attribute/1` function would return\n `{Name, {Name, Value}}` instead of `{Name, Value}` (which is the documented\n return value).\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17894 Aux Id: PR-5509","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Syntax_Tools Release Notes","doc":"- Added support for configurable features as described in EEP-60. Features can\n be enabled/disabled during compilation with options\n (`-enable-feature Feature`, `-disable-feature Feature` and\n `+{feature, Feature, enable|disable}`) to `erlc` as well as with directives\n (`-feature(Feature, enable|disable).`) in the file. Similar options can be\n used to `erl` for enabling/disabling features allowed at runtime. The new\n `maybe` expression (EEP-49) is fully supported as the feature `maybe_expr`.\n The features support is documented in the reference manual.\n\n Own Id: OTP-17988","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Syntax_Tools 2.6 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-2-6"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","doc":"- The type spec of `erl_syntax:function_type/2` has been fixed.\n\n Own Id: OTP-17302 Aux Id: PR-4705\n\n- Output parentheses around `BitStringExpr` when pretty-printing binary\n comprehensions.\n\n Own Id: OTP-17321","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Syntax_Tools Release Notes","doc":"- Support for handling abstract code created before OTP R15 has been dropped.\n\n Own Id: OTP-16678 Aux Id: PR-2627\n\n- The `igor` and `erl_tidy` modules have been the removed and are now maintained\n by their original author Richard Carlsson. They can be found at\n [github.com/richcarl/igor](https://github.com/richcarl/igor) and\n [github.com/richcarl/erl_tidy](https://github.com/richcarl/erl_tidy),\n respectively.\n\n Own Id: OTP-17180","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Syntax_Tools 2.5 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-2-5"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","doc":"- `epp_dodger` was unable to handle a parameterized macro in a function head.\n\n Own Id: OTP-17064 Aux Id: GH-4445, PR-2964","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Syntax_Tools Release Notes","doc":"- All functions in `erl_tidy` in syntax_tools have now been deprecated and are\n scheduled for removal in OTP 24. Users who still need it can find it at\n [https://github.com/richcarl/erl_tidy](https://github.com/richcarl/erl_tidy).\n\n Own Id: OTP-17167 Aux Id: OTP-17046","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Syntax_Tools 2.4 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-2-4"},{"type":"extras","title":"Improvements and New Features - Syntax_Tools Release Notes","doc":"- In the `syntax_tools` application, the `igor` module and all functions in\n `erl_tidy` except `file/2` have been deprecated.\n\n Own Id: OTP-17046","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Syntax_Tools 2.3.1 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-2-3-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","doc":"- Minor documentation fix of `erl_syntax:operator/1`.\n\n Own Id: OTP-16732 Aux Id: PR-2659","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Syntax_Tools 2.3 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-2-3"},{"type":"extras","title":"Improvements and New Features - Syntax_Tools Release Notes","doc":"- Remove incomplete support for `cond` expressions.\n\n Own Id: OTP-15925 Aux Id: PR-2304\n\n- Improved indentation for code generated with `erl_prettypr` and `tidier`.\n\n Own Id: OTP-16386 Aux Id: PR-2451","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Syntax_Tools 2.2.1 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-2-2-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","doc":"- Add missing calls to `erl_syntax:unwrap/1`. The nodes concerned represent\n names and values of maps and map types.\n\n Own Id: OTP-16012 Aux Id: PR-2348","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Syntax_Tools 2.2 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-2-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","doc":"- All incorrect (that is, all) uses of \"can not\" has been corrected to \"cannot\"\n in source code comments, documentation, examples, and so on.\n\n Own Id: OTP-14282 Aux Id: PR-1891","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Syntax_Tools Release Notes","doc":"- Correct links in the documentation.\n\n Own Id: OTP-15761","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Syntax_Tools 2.1.7.1 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-2-1-7-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","doc":"- Add missing calls to `erl_syntax:unwrap/1`. The nodes concerned represent\n names and values of maps and map types.\n\n Own Id: OTP-16012 Aux Id: PR-2348","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Syntax_Tools 2.1.7 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-2-1-7"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","doc":"- Fix pretty-printing of type funs.\n\n Own Id: OTP-15519 Aux Id: ERL-815","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Syntax_Tools 2.1.6 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-2-1-6"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","doc":"- Fix the `TypeName` type in erl_syntax_lib.\n\n Own Id: OTP-15207 Aux Id: PR-1888\n\n- Correct unfolding of the stacktrace variable.\n\n Own Id: OTP-15291 Aux Id: ERL-719\n\n- Correct `erl_syntax:revert/1` bug regarding the types `t:map/0` and\n `t:tuple/0`.\n\n Own Id: OTP-15294","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Syntax_Tools Release Notes","doc":"- Support bitstrings as literals in module `erl_syntax`.\n\n Own Id: OTP-15165 Aux Id: PR-1842","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Syntax_Tools 2.1.5 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-2-1-5"},{"type":"extras","title":"Improvements and New Features - Syntax_Tools Release Notes","doc":"- Update to use the new string api instead of the old.\n\n Own Id: OTP-15036","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Syntax_Tools 2.1.4.2 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-2-1-4-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","doc":"- Add missing calls to `erl_syntax:unwrap/1`. The nodes concerned represent\n names and values of maps and map types.\n\n Own Id: OTP-16012 Aux Id: PR-2348","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Syntax_Tools 2.1.4.1 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-2-1-4-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","doc":"- Fix a bug regarding reverting map types.\n\n Own Id: OTP-15098 Aux Id: ERIERL-177","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Syntax_Tools 2.1.4 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-2-1-4"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","doc":"- Removed all old unused files in the documentation.\n\n Own Id: OTP-14475 Aux Id: ERL-409, PR-1493","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Syntax_Tools 2.1.3 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-2-1-3"},{"type":"extras","title":"Improvements and New Features - Syntax_Tools Release Notes","doc":"- General Unicode improvements.\n\n Own Id: OTP-14462\n\n- A process trapping exits and calling `erl_tidy` no longer hangs if an error\n occurs.\n\n Own Id: OTP-14471 Aux Id: ERL-413","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Syntax_Tools 2.1.2 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-2-1-2"},{"type":"extras","title":"Improvements and New Features - Syntax_Tools Release Notes","doc":"- Miscellaneous updates due to atoms containing arbitrary Unicode characters.\n\n Own Id: OTP-14285","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Syntax_Tools 2.1.1.1 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-2-1-1-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","doc":"- Fix a bug regarding reverting map types.\n\n Own Id: OTP-15098 Aux Id: ERIERL-177","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Syntax_Tools 2.1.1 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-2-1-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","doc":"- The address to the FSF in the license header has been updated.\n\n Own Id: OTP-14084","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Syntax_Tools 2.1 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-2-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","doc":"- Fix a bug where `erl_tidy` crashed on the tilde character when printing to\n standard output.\n\n Own Id: OTP-13725 Aux Id: ERL-151, PR-1071\n\n- `merl_transform` could get into an infinite loop when syntactically incorrect\n text was passed to a `merl:qquote/2,3` call.\n\n Own Id: OTP-13755","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Syntax_Tools Release Notes","doc":"- Improve types and specs in OTP documentation generated from Erlang source\n files.\n\n Own Id: OTP-13720 Aux Id: ERL-120","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Syntax_Tools 2.0 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-2-0"},{"type":"extras","title":"Improvements and New Features - Syntax_Tools Release Notes","doc":"- The abstract data type in `erl_syntax` is augmented with types and function\n specifications.\n\n The module `erl_prettypr` pretty prints types and function specification, and\n the output can be parsed.\n\n The types of record fields are no longer ignored. As a consequence\n `erl_syntax_lib:analyze_record_field/1` returns `{Default, Type}` instead of\n `Default`. The functions `analyze_record_attribute`, `analyze_attribute`,\n `analyze_form`, and `analyze_forms` in the `erl_syntax_lib` module are also\n affected by this incompatible change.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-12863","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Syntax_Tools 1.7 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-1-7"},{"type":"extras","title":"Improvements and New Features - Syntax_Tools Release Notes","doc":"- Use the new `erl_anno` module.\n\n Own Id: OTP-12732\n\n- The `merl` module has been added to the `syntax_tools` application. The Merl\n library is a simpler way to work with erl_syntax parse trees.\n\n Own Id: OTP-12769","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Syntax_Tools 1.6.18 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-1-6-18"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","doc":"- Fix bad format of error in epp_dodger:parse_file/3\n\n Own Id: OTP-12406","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Syntax_Tools 1.6.17 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-1-6-17"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","doc":"- Teach Maps to erl_syntax\n\n Affected functions:\n\n - erl_syntax:abstract/1\n - erl_syntax:concrete/1\n - erl_syntax:is_leaf/1\n - erl_syntax:is_literal/1\n\n Own Id: OTP-12265","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Syntax_Tools 1.6.16 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-1-6-16"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","doc":"- The default encoding for Erlang source files is now UTF-8. As a temporary\n measure to ease the transition from the old default of Latin-1, if EDoc\n encounters byte sequences that are not valid UTF-8 sequences, EDoc will re-try\n in Latin-1 mode. This workaround will be removed in a future release.\n\n Own Id: OTP-12008","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Syntax_Tools 1.6.15 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-1-6-15"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","doc":"- Fix reverting map in syntax_tools\n\n There was a bug in erl_syntax when running e.g. erl_syntax:revert_forms,\n affecting maps. Instead of getting Key/Value you got Key/Key in the resulting\n abstract form.\n\n Own Id: OTP-11930","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Syntax_Tools 1.6.14 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-1-6-14"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","doc":"- Application upgrade (appup) files are corrected for the following\n applications:\n\n `asn1, common_test, compiler, crypto, debugger, dialyzer, edoc, eldap, erl_docgen, et, eunit, gs, hipe, inets, observer, odbc, os_mon, otp_mibs, parsetools, percept, public_key, reltool, runtime_tools, ssh, syntax_tools, test_server, tools, typer, webtool, wx, xmerl`\n\n A new test utility for testing appup files is added to test_server. This is\n now used by most applications in OTP.\n\n (Thanks to Tobias Schlager)\n\n Own Id: OTP-11744","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Syntax_Tools Release Notes","doc":"- Add implementation of having erl_tidy print to screen instead of writing to\n the file provided. (Thanks to Aaron France)\n\n Own Id: OTP-11632\n\n- Support Maps syntax in syntax_tools (Thanks to Anthony Ramine).\n\n Own Id: OTP-11663","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Syntax_Tools 1.6.13 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-1-6-13"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","doc":"- In syntax_tools-1.6.12 (OTP R16B03) a bug was introduced which broke reverting\n of local implicit funs. Implicit funs were mistakenly thought to be using\n abstract terms for their name and arity. This has now been corrected. (Thanks\n to Anthony Ramine)\n\n Own Id: OTP-11576","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Improvements and New Features - Syntax_Tools Release Notes","doc":"- The default encoding of Erlang files has been changed from ISO-8859-1 to\n UTF-8.\n\n The encoding of XML files has also been changed to UTF-8.\n\n Own Id: OTP-10907","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Syntax_Tools 1.6.12 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-1-6-12"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","doc":"- Fix transformation of implicit funs in igor (Thanks to Anthony Ramine)\n\n Own Id: OTP-11506","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Syntax_Tools 1.6.11 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-1-6-11"},{"type":"extras","title":"Improvements and New Features - Syntax_Tools Release Notes","doc":"- Miscellaneous updates due to Unicode support.\n\n Own Id: OTP-10820","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Syntax_Tools 1.6.10 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-1-6-10"},{"type":"extras","title":"Improvements and New Features - Syntax_Tools Release Notes","doc":"- Support for Unicode has been implemented.\n\n Own Id: OTP-10302","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Syntax_Tools 1.6.9 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-1-6-9"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","doc":"- Syntax Tools 1.6.9\n\n Minor bugfixes, spec annotations and documentation cleanup. Thanks to Richard\n Carlsson\n\n Own Id: OTP-10208","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Syntax_Tools 1.6.8 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-1-6-8"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","doc":"- Minor suppressions and fixes of compilation warnings\n\n Own Id: OTP-10016","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Syntax_Tools 1.6.7.2 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-1-6-7-2"},{"type":"extras","title":"Improvements and New Features - Syntax_Tools Release Notes","doc":"- Variables are now now allowed in '`fun M:F/A`' as suggested by Richard O'Keefe\n in EEP-23.\n\n The representation of '`fun M:F/A`' in the abstract format has been changed in\n an incompatible way. Tools that directly read or manipulate the abstract\n format (such as parse transforms) may need to be updated. The compiler can\n handle both the new and the old format (i.e. extracting the abstract format\n from a pre-R15 BEAM file and compiling it using compile:forms/1,2 will work).\n The `syntax_tools` application can also handle both formats.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-9643\n\n- Eliminate use of deprecated regexp module\n\n Own Id: OTP-9810","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Syntax_Tools 1.6.7.1 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-1-6-7-1"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","doc":"- In a file containing declarations and comments without any empty lines between\n them, the `recomment_forms()` function would associate a multi-line comment\n with the declaration above it rather than the one following it. (Thanks to\n Richard Carlsson and Kostis Sagonas.)\n\n Own Id: OTP-9180","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Syntax_Tools 1.6.7 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-1-6-7"},{"type":"extras","title":"Improvements and New Features - Syntax_Tools Release Notes","doc":"- Miscellaneous updates\n\n Own Id: OTP-8976","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Syntax_Tools 1.6.6 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-1-6-6"},{"type":"extras","title":"Improvements and New Features - Syntax_Tools Release Notes","doc":"- Minor changes and clean-ups.\n\n Own Id: OTP-8709","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Syntax_Tools 1.6.5 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-1-6-5"},{"type":"extras","title":"Improvements and New Features - Syntax_Tools Release Notes","doc":"- The documentation is now possible to build in an open source environment after\n a number of bugs are fixed and some features are added in the documentation\n build process.\n\n \\- The arity calculation is updated.\n\n \\- The module prefix used in the function names for bif's are removed in the\n generated links so the links will look like\n \"http://www.erlang.org/doc/man/erlang.html#append_element-2\" instead of\n \"http://www.erlang.org/doc/man/erlang.html#erlang:append_element-2\".\n\n \\- Enhanced the menu positioning in the html documentation when a new page is\n loaded.\n\n \\- A number of corrections in the generation of man pages (thanks to Sergei\n Golovan)\n\n \\- The legal notice is taken from the xml book file so OTP's build process can\n be used for non OTP applications.\n\n Own Id: OTP-8343","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Syntax_Tools 1.6.4 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-1-6-4"},{"type":"extras","title":"Improvements and New Features - Syntax_Tools Release Notes","doc":"- The documentation is now built with open source tools (xsltproc and fop) that\n exists on most platforms. One visible change is that the frames are removed.\n\n Own Id: OTP-8201","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Syntax_Tools 1.6.3 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-1-6-3"},{"type":"extras","title":"Improvements and New Features - Syntax_Tools Release Notes","doc":"- Miscellaneous updates.\n\n Own Id: OTP-8190","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Syntax_Tools 1.6.2 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-1-6-2"},{"type":"extras","title":"Improvements and New Features - Syntax_Tools Release Notes","doc":"- Miscellaneous updates.\n\n Own Id: OTP-8038","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Syntax_Tools 1.6 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-1-6"},{"type":"extras","title":"Improvements and New Features - Syntax_Tools Release Notes","doc":"- Miscellaneous updates.\n\n Own Id: OTP-7877","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Syntax_Tools 1.5.6 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-1-5-6"},{"type":"extras","title":"Improvements and New Features - Syntax_Tools Release Notes","doc":"- Minor updates.\n\n Own Id: OTP-7642","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Syntax_Tools 1.5.5 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-1-5-5"},{"type":"extras","title":"Improvements and New Features - Syntax_Tools Release Notes","doc":"- Minor changes.\n\n Own Id: OTP-7388","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Syntax_Tools 1.5.4 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-1-5-4"},{"type":"extras","title":"Improvements and New Features - Syntax_Tools Release Notes","doc":"- Minor updates, mostly cosmetic.\n\n Own Id: OTP-7243","ref":"notes.html#improvements-and-new-features"},{"type":"extras","title":"Syntax_Tools 1.5.3 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-1-5-3"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","doc":"- A missing directory (`examples`) has been added and another broken link in the\n documentation has been fixed.\n\n Own Id: OTP-6468","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Syntax_Tools 1.5.2 - Syntax_Tools Release Notes","doc":"","ref":"notes.html#syntax_tools-1-5-2"},{"type":"extras","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","doc":"- Fixed some broken links in the documentation.\n\n Own Id: OTP-6420","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","title":"Syntax_Tools 1.5.1 - Syntax_Tools Release Notes","doc":"Miscellaneous changes.","ref":"notes.html#syntax_tools-1-5-1"},{"type":"extras","title":"Erlang Syntax and Metaprogramming tools","doc":"\n# Erlang Syntax and Metaprogramming tools","ref":"chapter.html"},{"type":"extras","title":"Overview - Erlang Syntax and Metaprogramming tools","doc":"This package contains modules for handling abstract syntax trees (ASTs) in\nErlang, in a way that is compatible with the \"abstract format\" parse trees of\nthe stdlib module `erl_parse`, together with utilities for reading source files,\n[pretty-printing syntax trees](`m:erl_prettypr`), and doing\n[metaprogramming](`m:merl`) in Erlang.\n\nThe abstract layer (defined in `m:erl_syntax`) is nicely structured and the node\ntypes are context-independent. The layer makes it possible to transparently\nattach source-code comments and user annotations to nodes of the tree. Using the\nabstract layer makes applications less sensitive to changes in the `m:erl_parse`\ndata structures, only requiring the `erl_syntax` module to be up-to-date.\n\nThe pretty printer `m:erl_prettypr` is implemented on top of the library module\n`m:prettypr`: this is a powerful and flexible generic pretty printing library,\nwhich is also distributed separately.\n\nFor a short demonstration of parsing and pretty-printing, simply compile the\nincluded module [assets/demo.erl](assets/demo.erl), and execute `demo:run()` from the Erlang\nshell. It will compile the remaining modules and give you further instructions.","ref":"chapter.html#overview"}],"content_type":"text/plain","producer":{"name":"ex_doc","version":[48,46,51,52,46,49]}} \ No newline at end of file diff --git a/prs/9045/lib/syntax_tools-3.2.1/doc/html/dist/search_data-3B2B9E37.js b/prs/9045/lib/syntax_tools-3.2.1/doc/html/dist/search_data-3B2B9E37.js new file mode 100644 index 000000000000..2233b9f915f0 --- /dev/null +++ b/prs/9045/lib/syntax_tools-3.2.1/doc/html/dist/search_data-3B2B9E37.js @@ -0,0 +1 @@ +searchData={"items":[{"type":"module","doc":"Bypassing the Erlang preprocessor.\n\nThis module tokenises and parses most Erlang source code without expanding\npreprocessor directives and macro applications, as long as these are\nsyntactically \"well-behaved\". Because the normal parse trees of the `erl_parse`\nmodule cannot represent these things (normally, they are expanded by the Erlang\npreprocessor [`//stdlib/epp`](`m:epp`) before the parser sees them), an extended\nsyntax tree is created, using the `m:erl_syntax` module.","title":"epp_dodger","ref":"epp_dodger.html"},{"type":"function","doc":"","title":"epp_dodger.parse/1","ref":"epp_dodger.html#parse/1"},{"type":"function","doc":"","title":"epp_dodger.parse/2","ref":"epp_dodger.html#parse/2"},{"type":"function","doc":"Reads and parses program text from an I/O stream.\n\nCharacters are read from `IODevice` until end-of-file; apart from\nthis, the behavior is the same as for `parse_file/2`. `StartLocation`\nis the initial location.\n\n_See also: _`parse/2`, `parse_file/2`, `parse_form/2`, `quick_parse/3`.","title":"epp_dodger.parse/3","ref":"epp_dodger.html#parse/3"},{"type":"function","doc":"","title":"epp_dodger.parse_file/1","ref":"epp_dodger.html#parse_file/1"},{"type":"function","doc":"Reads and parses a file.\n\nIf successful, `{ok, Forms}` is returned, where `Forms` is a list of\nabstract syntax trees representing the \"program forms\" of the file\n(see `erl_syntax:is_form/1`). Otherwise, `{error, errorinfo()}` is\nreturned, typically if the file could not be opened. Note that parse\nerrors show up as error markers in the returned list of forms; they do\nnot cause this function to fail or return `{error, errorinfo()}`.\n\nOptions:\n\n- **`{no_fail, boolean()}`** - If `true`, this makes `epp_dodger` replace any\n program forms that could not be parsed with nodes of type `text` (see\n `erl_syntax:text/1`), representing the raw token sequence of the form, instead\n of reporting a parse error. The default value is `false`.\n\n- **`{clever, boolean()}`** - If set to `true`, this makes `epp_dodger` try to\n repair the source code as it seems fit, in certain cases where parsing would\n otherwise fail. Currently, it inserts `++` operators between string literals\n and macros where it looks like concatenation was intended. The default value\n is `false`.\n\n_See also: _`parse/2`, `quick_parse_file/1`, `erl_syntax:is_form/1`.","title":"epp_dodger.parse_file/2","ref":"epp_dodger.html#parse_file/2"},{"type":"function","doc":"","title":"epp_dodger.parse_form/2","ref":"epp_dodger.html#parse_form/2"},{"type":"function","doc":"Reads and parses a single program form from an I/O stream.\n\nCharacters are read from `IODevice` until an end-of-form marker is\nfound (a period character followed by whitespace), or until\nend-of-file; apart from this, the behavior is similar to that of\n[`parse/3`](`parse/3`), except that the return values also contain the\nfinal location given that `StartLocation` is the initial location, and\nthat `{eof, Location}` may be returned.\n\n_See also: _`parse/3`, `parse_form/2`, `quick_parse_form/3`.","title":"epp_dodger.parse_form/3","ref":"epp_dodger.html#parse_form/3"},{"type":"function","doc":"","title":"epp_dodger.quick_parse/1","ref":"epp_dodger.html#quick_parse/1"},{"type":"function","doc":"","title":"epp_dodger.quick_parse/2","ref":"epp_dodger.html#quick_parse/2"},{"type":"function","doc":"Similar to `parse/3`, but does a more quick-and-dirty processing of the code.\n\nSee `quick_parse_file/2` for details.\n\n_See also: _`parse/3`, `quick_parse/2`, `quick_parse_file/2`,\n`quick_parse_form/2`.","title":"epp_dodger.quick_parse/3","ref":"epp_dodger.html#quick_parse/3"},{"type":"function","doc":"","title":"epp_dodger.quick_parse_file/1","ref":"epp_dodger.html#quick_parse_file/1"},{"type":"function","doc":"Similar to `parse_file/2`, but does a more quick-and-dirty processing of the\ncode.\n\nMacro definitions and other preprocessor directives are discarded, and all\nmacro calls are replaced with atoms. This is useful when only the main structure\nof the code is of interest, and not the details. Furthermore, the quick-parse\nmethod can usually handle more strange cases than the normal, more exact\nparsing.\n\nOptions: see `parse_file/2`. However, note that for\n[`quick_parse_file/2`](`quick_parse_file/2`), the option `no_fail` is `true` by\ndefault.\n\n_See also: _`parse_file/2`, `quick_parse/2`.","title":"epp_dodger.quick_parse_file/2","ref":"epp_dodger.html#quick_parse_file/2"},{"type":"function","doc":"","title":"epp_dodger.quick_parse_form/2","ref":"epp_dodger.html#quick_parse_form/2"},{"type":"function","doc":"Similar to `parse_form/3`, but does a more quick-and-dirty processing of the\ncode. See `quick_parse_file/2` for details.\n\n_See also: _`parse/3`, `parse_form/3`, `quick_parse_form/2`.","title":"epp_dodger.quick_parse_form/3","ref":"epp_dodger.html#quick_parse_form/3"},{"type":"function","doc":"Generates a string corresponding to the given token sequence.\n\nThe string can be re-tokenized to yield the same token list again.","title":"epp_dodger.tokens_to_string/1","ref":"epp_dodger.html#tokens_to_string/1"},{"type":"type","doc":"","title":"epp_dodger.errorinfo/0","ref":"epp_dodger.html#t:errorinfo/0"},{"type":"type","doc":"","title":"epp_dodger.option/0","ref":"epp_dodger.html#t:option/0"},{"type":"module","doc":"Functions for reading comment lines from Erlang source code.","title":"erl_comment_scan","ref":"erl_comment_scan.html"},{"type":"function","doc":"Extracts comments from an Erlang source code file.\n\nReturns a list of entries representing _multi-line_ comments, listed\nin order of increasing line-numbers. For each entry, `Text` is a list\nof strings representing the consecutive comment lines in top-down\norder; the strings contain _all_ characters following (but not\nincluding) the first comment-introducing `%` character on the line, up\nto (but not including) the line-terminating newline.\n\nFurthermore, `Line` is the line number and `Column` the left column of the\ncomment (that is, the column of the comment-introducing `%` character). `Indent` is\nthe indentation (or padding), measured in character positions between the last\nnon-whitespace character before the comment (or the left margin), and the left\ncolumn of the comment. `Line` and `Column` are always positive integers, and\n`Indentation` is a nonnegative integer.\n\nEvaluation exits with reason `{read, Reason}` if a read error occurred, where\n`Reason` is an atom corresponding to a Posix error code; see the module\n[`//kernel/file`](`m:file`) for details.","title":"erl_comment_scan.file/1","ref":"erl_comment_scan.html#file/1"},{"type":"function","doc":"join_lines(CommentLines) ->\n\nJoins individual comment lines into multi-line comments.\n\nThe input is a list of entries representing individual comment lines,\n_in order of decreasing line-numbers_; see `scan_lines/1` for\ndetails. The result is a list of entries representing _multi-line_\ncomments, _still listed in order of decreasing line-numbers_, but\nwhere for each entry, `Text` is a list of consecutive comment lines in\norder of _increasing_ line-numbers (that is, top-down).\n\n_See also: _`scan_lines/1`.","title":"erl_comment_scan.join_lines/1","ref":"erl_comment_scan.html#join_lines/1"},{"type":"function","doc":"Extracts individual comment lines from a source code string.\n\nReturns a list of comment lines found in the text, listed in order of\n_decreasing_ line-numbers, that is, the last comment line in the input\nis first in the resulting list. `Text` is a single string, containing\nall characters following (but not including) the first\ncomment-introducing `%` character on the line, up to (but not\nincluding) the line-terminating newline. For details on `Line`,\n`Column` and `Indent`, see `file/1`.","title":"erl_comment_scan.scan_lines/1","ref":"erl_comment_scan.html#scan_lines/1"},{"type":"function","doc":"Extracts comments from a string containing Erlang source code.\n\nExcept for reading directly from a string, the behavior is the same\nas for `file/1`.\n\n_See also: _`file/1`.","title":"erl_comment_scan.string/1","ref":"erl_comment_scan.html#string/1"},{"type":"type","doc":"","title":"erl_comment_scan.comment/0","ref":"erl_comment_scan.html#t:comment/0"},{"type":"type","doc":"","title":"erl_comment_scan.commentLine/0","ref":"erl_comment_scan.html#t:commentLine/0"},{"type":"module","doc":"Pretty printing of abstract Erlang syntax trees.\n\nThis module is a front end to the pretty-printing library module `prettypr`, for\ntext formatting of abstract syntax trees defined by the module `erl_syntax`.","title":"erl_prettypr","ref":"erl_prettypr.html"},{"type":"function","doc":"","title":"erl_prettypr.best/1","ref":"erl_prettypr.html#best/1"},{"type":"function","doc":"Creates a fixed \"best\" abstract layout for a syntax tree.\n\nThis is similar to the [`layout/2`](`layout/2`) function, except that\nhere, the final layout has been selected with respect to the given\noptions. The atom `empty` is returned if no such layout could be\nproduced. For information on the options, see the\n[`format/2`](`format/2`) function.\n\n_See also: _`best/1`, `format/2`, `layout/2`, `prettypr:best/3`.","title":"erl_prettypr.best/2","ref":"erl_prettypr.html#best/2"},{"type":"function","doc":"","title":"erl_prettypr.format/1","ref":"erl_prettypr.html#format/1"},{"type":"function","doc":"Prettyprint-formats an abstract Erlang syntax tree as text.\n\nFor example, if you have a `.beam` file that has been compiled with\n`debug_info`, the following should print the source code for the\nmodule (as it looks in the debug info representation):\n\n```text\n {ok,{_,[{abstract_code,{_,AC}}]}} =\n beam_lib:chunks(\"myfile.beam\",[abstract_code]),\n io:put_chars(erl_prettypr:format(erl_syntax:form_list(AC)))\n```\n\nAvailable options:\n\n- **`{hook, none | hook()}`** - Unless the value is `none`, the\n given function is called for each node whose list of annotations is\n not empty. The default value is `none`.\n\n- **`{paper, integer()}`** - Specifies the preferred maximum number of\n characters on any line, including indentation. The default value is 80.\n\n- **`{ribbon, integer()}`** - Specifies the preferred maximum number of\n characters on any line, not counting indentation. The default value is 65.\n\n- **`{user, term()}`** - User-specific data for use in hook functions. The\n default value is `undefined`.\n\n- **`{encoding, epp:source_encoding()}`** - Specifies the encoding of the\n generated file.\n\nA hook function (see the [`hook()`](`t:hook/0`) type) is passed the current\nsyntax tree node, the context, and a continuation. The context can be examined\nand manipulated by functions such as [`get_ctxt_user/1`](`get_ctxt_user/1`) and\n[`set_ctxt_user/2`](`set_ctxt_user/2`). The hook must return a \"document\" data\nstructure (see `layout/2` and `best/2`); this may be constructed in part or in\nwhole by applying the continuation function. For example, the following is a\ntrivial hook:\n\n```text\n fun (Node, Ctxt, Cont) -> Cont(Node, Ctxt) end\n```\n\nwhich yields the same result as if no hook was given. The following, however:\n\n```text\n fun (Node, Ctxt, Cont) ->\n Doc = Cont(Node, Ctxt),\n prettypr:beside(prettypr:text(\" \"),\n prettypr:beside(Doc,\n prettypr:text(\" \")))\n end\n```\n\nwill place the text of any annotated node (regardless of the annotation data)\nbetween HTML \"boldface begin\" and \"boldface end\" tags.\n\n_See also: _`m:erl_syntax`, `best/2`, `format/1`, `get_ctxt_user/1`, `layout/2`,\n`set_ctxt_user/2`.","title":"erl_prettypr.format/2","ref":"erl_prettypr.html#format/2"},{"type":"function","doc":"Returns the hook function field of the prettyprinter context.\n\n_See also: _`set_ctxt_hook/2`.","title":"erl_prettypr.get_ctxt_hook/1","ref":"erl_prettypr.html#get_ctxt_hook/1"},{"type":"function","doc":"Returns the line widh field of the prettyprinter context.\n\n_See also: _`set_ctxt_linewidth/2`.","title":"erl_prettypr.get_ctxt_linewidth/1","ref":"erl_prettypr.html#get_ctxt_linewidth/1"},{"type":"function","doc":"Returns the paper widh field of the prettyprinter context.\n\n_See also: _`set_ctxt_paperwidth/2`.","title":"erl_prettypr.get_ctxt_paperwidth/1","ref":"erl_prettypr.html#get_ctxt_paperwidth/1"},{"type":"function","doc":"Returns the operator precedence field of the prettyprinter context.\n\n_See also: _`set_ctxt_precedence/2`.","title":"erl_prettypr.get_ctxt_precedence/1","ref":"erl_prettypr.html#get_ctxt_precedence/1"},{"type":"function","doc":"Returns the user data field of the prettyprinter context.\n\n_See also: _`set_ctxt_user/2`.","title":"erl_prettypr.get_ctxt_user/1","ref":"erl_prettypr.html#get_ctxt_user/1"},{"type":"function","doc":"","title":"erl_prettypr.layout/1","ref":"erl_prettypr.html#layout/1"},{"type":"function","doc":"Creates an abstract document layout for a syntax tree.\n\nThe result represents a set of possible layouts (see module\n`m:prettypr`). For information on the options, see `format/2`;\nhowever, note that the `paper` and `ribbon` options are ignored by\nthis function.\n\nThis function provides a low-level interface to the pretty printer, returning a\nflexible representation of possible layouts, independent of the paper width\neventually to be used for formatting. This can be included as part of another\ndocument and/or further processed directly by the functions in the `prettypr`\nmodule, or used in a hook function (see [`format/2`](`format/2`) for details).\n\n_See also: _`m:prettypr`, `format/2`, `layout/1`.","title":"erl_prettypr.layout/2","ref":"erl_prettypr.html#layout/2"},{"type":"function","doc":"Updates the hook function field of the prettyprinter context.\n\n_See also: _`get_ctxt_hook/1`.","title":"erl_prettypr.set_ctxt_hook/2","ref":"erl_prettypr.html#set_ctxt_hook/2"},{"type":"function","doc":"Updates the line widh field of the prettyprinter context.\n\n> #### Note {: .info }\n>\n> Changing this value (and passing the resulting context to a\n> continuation function) does not affect the normal formatting, but may\n> affect user-defined behaviour in hook functions.\n\n_See also: _`get_ctxt_linewidth/1`.","title":"erl_prettypr.set_ctxt_linewidth/2","ref":"erl_prettypr.html#set_ctxt_linewidth/2"},{"type":"function","doc":"Updates the paper widh field of the prettyprinter context.\n\n> #### Note {: .info }\n>\n> Changing this value (and passing the resulting context to a\n> continuation function) does not affect the normal formatting, but may\n> affect user-defined behaviour in hook functions.\n\n_See also: _`get_ctxt_paperwidth/1`.","title":"erl_prettypr.set_ctxt_paperwidth/2","ref":"erl_prettypr.html#set_ctxt_paperwidth/2"},{"type":"function","doc":"Updates the operator precedence field of the prettyprinter context.\n\nSee the [`//stdlib/erl_parse`](`m:erl_parse`) module for operator\nprecedences.\n\n_See also: _[//stdlib/erl_parse](`m:erl_parse`), `get_ctxt_precedence/1`.","title":"erl_prettypr.set_ctxt_precedence/2","ref":"erl_prettypr.html#set_ctxt_precedence/2"},{"type":"function","doc":"Updates the user data field of the prettyprinter context.\n\n_See also: _`get_ctxt_user/1`.","title":"erl_prettypr.set_ctxt_user/2","ref":"erl_prettypr.html#set_ctxt_user/2"},{"type":"type","doc":"","title":"erl_prettypr.clause_t/0","ref":"erl_prettypr.html#t:clause_t/0"},{"type":"type","doc":"","title":"erl_prettypr.context/0","ref":"erl_prettypr.html#t:context/0"},{"type":"type","doc":"","title":"erl_prettypr.hook/0","ref":"erl_prettypr.html#t:hook/0"},{"type":"type","doc":"An abstract syntax tree.\n\nSee the `m:erl_syntax` module for details.","title":"erl_prettypr.syntaxTree/0","ref":"erl_prettypr.html#t:syntaxTree/0"},{"type":"module","doc":"Inserting comments into abstract Erlang syntax trees\n\nThis module contains functions for inserting comments, described by position,\nindentation and text, as attachments on an abstract syntax tree, at the correct\nplaces.","title":"erl_recomment","ref":"erl_recomment.html"},{"type":"function","doc":"Like `recomment_forms/2`, but only inserts top-level comments.\n\nComments within function definitions or declarations (\"forms\") are\nsimply ignored.","title":"erl_recomment.quick_recomment_forms/2","ref":"erl_recomment.html#quick_recomment_forms/2"},{"type":"function","doc":"Attaches comments to the syntax tree/trees representing a program.\n\nThe given `Forms` should be a single syntax tree of type `form_list`,\nor a list of syntax trees representing \"program forms\". The syntax\ntrees must contain valid position information (for details, see\n[`recomment_tree/2`](`recomment_tree/2`)). The result is a\ncorresponding syntax tree of type `form_list` in which all comments in\nthe list `Comments` have been attached at the proper places.\n\nAssuming `Forms` represents a program (or any sequence of \"program forms\"), any\ncomments whose first lines are not directly associated with a specific program\nform will become standalone comments inserted between the neighbouring program\nforms. Furthermore, comments whose column position is less than or equal to one\nwill not be attached to a program form that begins at a conflicting line number\n(this can happen with preprocessor-generated `line`\\-attributes).\n\nIf `Forms` is a syntax tree of some other type than `form_list`, the comments\nwill be inserted directly using [`recomment_tree/2`](`recomment_tree/2`), and\nany comments left over from that process are added as postcomments on the\nresult.\n\nEntries in `Comments` represent multi-line comments. For each entry, `Line` is\nthe line number and `Column` the left column of the comment (the column of the\nfirst comment-introducing \"`%`\" character). `Indentation` is the number of\ncharacter positions between the last non-whitespace character before the comment\n(or the left margin) and the left column of the comment. `Text` is a list of\nstrings representing the consecutive comment lines in top-down order, where each\nstring contains all characters following (but not including) the\ncomment-introducing \"`%`\" and up to (but not including) the terminating newline.\n(see module `m:erl_comment_scan`.)\n\nEvaluation exits with reason `{bad_position, Pos}` if the associated position\ninformation `Pos` of some subtree in the input does not have a recognizable\nformat, or with reason `{bad_tree, L, C}` if insertion of a comment at line `L`,\ncolumn `C`, fails because the tree structure is ill-formed.\n\n_See also: _`m:erl_comment_scan`, `quick_recomment_forms/2`, `recomment_tree/2`.","title":"erl_recomment.recomment_forms/2","ref":"erl_recomment.html#recomment_forms/2"},{"type":"function","doc":"Attaches comments to a syntax tree.\n\nThe result is a pair `{NewTree, Remainder}` where `NewTree` is the\ngiven `Tree` where comments from the list `Comments` have been\nattached at the proper places. `Remainder` is the list of entries in\n`Comments` which have not been inserted, because their line numbers\nare greater than those of any node in the tree. The entries in\n`Comments` are inserted in order; if two comments become attached to\nthe same node, they will appear in the same order in the program text.\n\nThe nodes of the syntax tree must contain valid position information. This can\nbe single integers, assumed to represent a line number, or 2- or 3-tuples where\nthe first or second element is an integer, in which case the leftmost integer\nelement is assumed to represent the line number. Line numbers less than one are\nignored (usually, the default line number for newly created nodes is zero).\n\nFor details on the `Line`, `Column` and `Indentation` fields, and the behaviour\nin case of errors, see [`recomment_forms/2`](`recomment_forms/2`).\n\n_See also: _`recomment_forms/2`.","title":"erl_recomment.recomment_tree/2","ref":"erl_recomment.html#recomment_tree/2"},{"type":"type","doc":"An abstract syntax tree. See the `m:erl_syntax` module for details.","title":"erl_recomment.syntaxTree/0","ref":"erl_recomment.html#t:syntaxTree/0"},{"type":"module","doc":"Abstract Erlang syntax trees.\n\nThis module defines an abstract data type for representing Erlang source code as\nsyntax trees, in a way that is backwards compatible with the data structures\ncreated by the Erlang standard library parser module `m:erl_parse` (often referred\nto as \"parse trees\", which is a bit of a misnomer). This means that all\n`erl_parse` trees are valid abstract syntax trees, but the reverse is not true:\nabstract syntax trees can in general not be used as input to functions expecting\nan `erl_parse` tree. However, as long as an abstract syntax tree represents a\ncorrect Erlang program, the function `revert/1` should be able to transform it\nto the corresponding `erl_parse` representation.\n\nA recommended starting point for the first-time user is the documentation of the\n[`syntaxTree()`](`t:syntaxTree/0`) data type, and the function `type/1`.\n\n> #### Note {: .info }\n>\n> This module deals with the composition and decomposition of _syntactic_ entities\n> (as opposed to semantic ones); its purpose is to hide all direct references to\n> the data structures used to represent these entities. With few exceptions, the\n> functions in this module perform no semantic interpretation of their inputs, and\n> in general, the user is assumed to pass type-correct arguments — if this is not\n> done, the effects are not defined.\n\nWith the exception of the [`erl_parse()`](`t:erl_parse/0`) data structures, the\ninternal representations of abstract syntax trees are subject to change without\nnotice, and should not be documented outside this module. Furthermore, we do not\ngive any guarantees on how an abstract syntax tree may or may not be\nrepresented, _with the following exceptions_: no syntax tree is represented by a\nsingle atom, such as `none`, by a list constructor `[X | Y]`, or by the empty\nlist `[]`. This can be relied on when writing functions that operate on syntax\ntrees.","title":"erl_syntax","ref":"erl_syntax.html"},{"type":"function","doc":"Creates an abstract empty list.\n\nThe result represents \"`[]`\". The empty list is traditionally called\n\"nil\".\n\n_See also: _`is_list_skeleton/1`, `list/2`.","title":"erl_syntax./0","ref":"erl_syntax.html#nil/0"},{"type":"function","doc":"Returns the syntax tree corresponding to an Erlang term.\n\n`Term` must be a literal term, meaning one that can be represented as a\nsource code literal. Thus, it must not contain a process identifier,\nport, reference, or function value as a subterm. The function\nrecognises printable strings, in order to get a compact and readable\nrepresentation. Evaluation fails with reason `badarg` if `Term` is not\na literal term.\n\n_See also: _`concrete/1`, `is_literal/1`.","title":"erl_syntax.abstract/1","ref":"erl_syntax.html#abstract/1"},{"type":"function","doc":"Appends the term `Annotation` to the list of user annotations of `Node`.\n\nNote: this is equivalent to\n[`set_ann(Node, [Annotation | get_ann(Node)])`](`set_ann/2`), but potentially\nmore efficient.\n\n_See also: _`get_ann/1`, `set_ann/2`.","title":"erl_syntax.add_ann/2","ref":"erl_syntax.html#add_ann/2"},{"type":"function","doc":"Appends `Comments` to the post-comments of `Node`.\n\nNote: This is equivalent to\n[`set_postcomments(Node, get_postcomments(Node) ++ Comments)`](`set_postcomments/2`),\nbut potentially more efficient.\n\n_See also: _`add_precomments/2`, `comment/2`, `get_postcomments/1`,\n`join_comments/2`, `set_postcomments/2`.","title":"erl_syntax.add_postcomments/2","ref":"erl_syntax.html#add_postcomments/2"},{"type":"function","doc":"Appends `Comments` to the pre-comments of `Node`.\n\nNote: This is equivalent to\n[`set_precomments(Node, get_precomments(Node) ++ Comments)`](`set_precomments/2`),\nbut potentially more efficient.\n\n_See also: _`add_postcomments/2`, `comment/2`, `get_precomments/1`,\n`join_comments/2`, `set_precomments/2`.","title":"erl_syntax.add_precomments/2","ref":"erl_syntax.html#add_precomments/2"},{"type":"function","doc":"Creates an abstract annotated type expression.\n\nThe result represents \"`Name :: Type`\".\n\n_See also: _`annotated_type_body/1`, `annotated_type_name/1`.","title":"erl_syntax.annotated_type/2","ref":"erl_syntax.html#annotated_type/2"},{"type":"function","doc":"Returns the type subtrees of an `annotated_type` node.\n\n_See also: _`annotated_type/2`.","title":"erl_syntax.annotated_type_body/1","ref":"erl_syntax.html#annotated_type_body/1"},{"type":"function","doc":"Returns the name subtree of an `annotated_type` node.\n\n_See also: _`annotated_type/2`.","title":"erl_syntax.annotated_type_name/1","ref":"erl_syntax.html#annotated_type_name/1"},{"type":"function","doc":"Creates an abstract function application expression.\n\nIf `Arguments` is `[A1, ..., An]`, the result represents\n\"`Operator(A1, ..., An)`\".\n\n_See also: _`application/3`, `application_arguments/1`,\n`application_operator/1`.","title":"erl_syntax.application/2","ref":"erl_syntax.html#application/2"},{"type":"function","doc":"Creates an abstract function application expression.\n\nIf `Module` is `none`, this is call is equivalent to\n[`application(Function, Arguments)`](`application/2`), otherwise it is\nequivalent to [`application(module_qualifier(Module, Function),\nArguments)`](`application/2`).\n\n(This is a utility function.)\n\n_See also: _`application/2`, `module_qualifier/2`.","title":"erl_syntax.application/3","ref":"erl_syntax.html#application/3"},{"type":"function","doc":"Returns the list of argument subtrees of an `application` node.\n\n_See also: _`application/2`.","title":"erl_syntax.application_arguments/1","ref":"erl_syntax.html#application_arguments/1"},{"type":"function","doc":"Returns the operator subtree of an `application` node.\n\nIf `Node` represents \"`M:F(...)`\", then the result is the subtree\nrepresenting \"`M:F`\".\n\n_See also: _`application/2`, `module_qualifier/2`.","title":"erl_syntax.application_operator/1","ref":"erl_syntax.html#application_operator/1"},{"type":"function","doc":"Creates an abstract arity qualifier.\n\nThe result represents \"`Body/Arity`\".\n\n_See also: _`arity_qualifier_argument/1`, `arity_qualifier_body/1`.","title":"erl_syntax.arity_qualifier/2","ref":"erl_syntax.html#arity_qualifier/2"},{"type":"function","doc":"Returns the argument (the arity) subtree of an `arity_qualifier` node.\n\n_See also: _`arity_qualifier/2`.","title":"erl_syntax.arity_qualifier_argument/1","ref":"erl_syntax.html#arity_qualifier_argument/1"},{"type":"function","doc":"Returns the body subtree of an `arity_qualifier` node.\n\n_See also: _`arity_qualifier/2`.","title":"erl_syntax.arity_qualifier_body/1","ref":"erl_syntax.html#arity_qualifier_body/1"},{"type":"function","doc":"Creates an abstract atom literal.\n\nThe print name of the atom is the character sequence represented by\n`Name`.\n\n_See also: _`atom_literal/1`, `atom_literal/2`, `atom_name/1`, `atom_value/1`,\n`is_atom/2`.","title":"erl_syntax.atom/1","ref":"erl_syntax.html#atom/1"},{"type":"function","doc":"Returns the literal string represented by an `atom` node.\n\nThis includes surrounding single-quote characters if\nnecessary. Characters beyond 255 will be escaped.\n\nNote that, for example, the result of [`atom(\"x\\ny\")`](`atom/1`)\nrepresents any and all of `'x\\ny'`, `'x\\12y'`, `'x\\012y'`, and\n`'x\\^Jy'`; see `string/1`.\n\n_See also: _`atom/1`, `string/1`.","title":"erl_syntax.atom_literal/1","ref":"erl_syntax.html#atom_literal/1"},{"type":"function","doc":"Returns the literal string represented by an `atom` node.\n\nThis includes surrounding single-quote characters if\nnecessary. Depending on the encoding a character beyond 255 will be\nescaped (`latin1`) or copied as is (`utf8`).\n\n_See also: _`atom/1`, `atom_literal/1`, `string/1`.","title":"erl_syntax.atom_literal/2","ref":"erl_syntax.html#atom_literal/2"},{"type":"function","doc":"Returns the printname of an `atom` node.\n\n_See also: _`atom/1`.","title":"erl_syntax.atom_name/1","ref":"erl_syntax.html#atom_name/1"},{"type":"function","doc":"Returns the value represented by an `atom` node.\n\n_See also: _`atom/1`.","title":"erl_syntax.atom_value/1","ref":"erl_syntax.html#atom_value/1"},{"type":"function","doc":"","title":"erl_syntax.attribute/1","ref":"erl_syntax.html#attribute/1"},{"type":"function","doc":"Creates an abstract program attribute.\n\nIf `Arguments` is `[A1, ..., An]`, the result represents\n\"`-Name(A1, ..., An).`\". Otherwise, if `Arguments` is `none`,\nthe result represents \"`-Name.`\". The latter form makes it possible\nto represent preprocessor directives such as \"`-endif.`\". Attributes\nare source code forms.\n\n> #### Note {: .info }\n>\n> The preprocessor macro definition directive \"`-define(Name, Body).`\"\n> has relatively few requirements on the syntactical form of `Body`\n> (viewed as a sequence of tokens). The `text` node type can be used for\n> a `Body` that is not a normal Erlang construct.\n\n_See also: _`attribute/1`, `attribute_arguments/1`, `attribute_name/1`,\n`is_form/1`, `text/1`.","title":"erl_syntax.attribute/2","ref":"erl_syntax.html#attribute/2"},{"type":"function","doc":"Returns the list of argument subtrees of an `attribute` node, if any.\n\nIf `Node` represents \"`-Name.`\", the result is `none`. Otherwise, if\n`Node` represents \"`-Name(E1, ..., En).`\", `[E1, ..., E1]` is\nreturned.\n\n_See also: _`attribute/1`.","title":"erl_syntax.attribute_arguments/1","ref":"erl_syntax.html#attribute_arguments/1"},{"type":"function","doc":"Returns the name subtree of an `attribute` node.\n\n_See also: _`attribute/1`.","title":"erl_syntax.attribute_name/1","ref":"erl_syntax.html#attribute_name/1"},{"type":"function","doc":"Creates an abstract binary-object template.\n\nIf `Fields` is `[F1, ..., Fn]`, the result represents \"`< >`\".\n\n_See also: _`binary_field/2`, `binary_fields/1`.","title":"erl_syntax.binary/1","ref":"erl_syntax.html#binary/1"},{"type":"function","doc":"Creates an abstract binary comprehension.\n\nIf `Body` is `[E1, ..., En]`, the result represents \"`< >`\".\n\n_See also: _`binary_comp_body/1`, `binary_comp_template/1`, `generator/2`.","title":"erl_syntax.binary_comp/2","ref":"erl_syntax.html#binary_comp/2"},{"type":"function","doc":"Returns the list of body subtrees of a `binary_comp` node.\n\n_See also: _`binary_comp/2`.","title":"erl_syntax.binary_comp_body/1","ref":"erl_syntax.html#binary_comp_body/1"},{"type":"function","doc":"Returns the template subtree of a `binary_comp` node.\n\n_See also: _`binary_comp/2`.","title":"erl_syntax.binary_comp_template/1","ref":"erl_syntax.html#binary_comp_template/1"},{"type":"function","doc":"","title":"erl_syntax.binary_field/1","ref":"erl_syntax.html#binary_field/1"},{"type":"function","doc":"Creates an abstract binary template field.\n\nIf `Types` is the empty list, the result simply represents\n\"`Body`\", otherwise, if `Types` is `[T1, ..., Tn]`, the result\nrepresents \"`Body/T1-...-Tn`\".\n\n_See also: _`binary/1`, `binary_field/1`, `binary_field/3`,\n`binary_field_body/1`, `binary_field_size/1`, `binary_field_types/1`.","title":"erl_syntax.binary_field/2","ref":"erl_syntax.html#binary_field/2"},{"type":"function","doc":"Creates an abstract binary template field.\n\nIf `Size` is `none`, this is equivalent to \"[`binary_field(Body,\nTypes)`](`binary_field/2`)\", otherwise it is equivalent to\n\"[`binary_field(size_qualifier(Body, Size),\nTypes)`](`binary_field/2`)\".\n\n(This is a utility function.)\n\n_See also: _`binary/1`, `binary_field/2`, `size_qualifier/2`.","title":"erl_syntax.binary_field/3","ref":"erl_syntax.html#binary_field/3"},{"type":"function","doc":"Returns the body subtree of a `binary_field`.\n\n_See also: _`binary_field/2`.","title":"erl_syntax.binary_field_body/1","ref":"erl_syntax.html#binary_field_body/1"},{"type":"function","doc":"Returns the size specifier subtree of a `binary_field` node, if any.\n\nIf `Node` represents \"`Body:Size`\" or \"`Body:Size/T1, ...,\nTn`\", the result is `Size`, otherwise `none` is returned.\n\n(This is a utility function.)\n\n_See also: _`binary_field/2`, `binary_field/3`.","title":"erl_syntax.binary_field_size/1","ref":"erl_syntax.html#binary_field_size/1"},{"type":"function","doc":"Returns the list of type-specifier subtrees of a `binary_field` node.\n\nIf `Node` represents \"`.../T1, ..., Tn`\", the result is `[T1,\n..., Tn]`, otherwise the result is the empty list.\n\n_See also: _`binary_field/2`.","title":"erl_syntax.binary_field_types/1","ref":"erl_syntax.html#binary_field_types/1"},{"type":"function","doc":"Returns the list of field subtrees of a `binary` node.\n\n_See also: _`binary/1`, `binary_field/2`.","title":"erl_syntax.binary_fields/1","ref":"erl_syntax.html#binary_fields/1"},{"type":"function","doc":"Creates an abstract binary_generator.\n\nThe result represents \"`Pattern <= Body`\".\n\n_See also: _`binary_comp/2`, `binary_generator_body/1`,\n`binary_generator_pattern/1`, `list_comp/2`, `map_comp/2`.","title":"erl_syntax.binary_generator/2","ref":"erl_syntax.html#binary_generator/2"},{"type":"function","doc":"Returns the body subtree of a `generator` node.\n\n_See also: _`binary_generator/2`.","title":"erl_syntax.binary_generator_body/1","ref":"erl_syntax.html#binary_generator_body/1"},{"type":"function","doc":"Returns the pattern subtree of a `generator` node.\n\n_See also: _`binary_generator/2`.","title":"erl_syntax.binary_generator_pattern/1","ref":"erl_syntax.html#binary_generator_pattern/1"},{"type":"function","doc":"Creates an abstract bitstring type.\n\nThe result represents \"`<<_:M, _:_N>>`\".\n\n_See also: _`bitstring_type_m/1`, `bitstring_type_n/1`.","title":"erl_syntax.bitstring_type/2","ref":"erl_syntax.html#bitstring_type/2"},{"type":"function","doc":"Returns the number of start bits, `M`, of a `bitstring_type` node.\n\n_See also: _`bitstring_type/2`.","title":"erl_syntax.bitstring_type_m/1","ref":"erl_syntax.html#bitstring_type_m/1"},{"type":"function","doc":"Returns the segment size, `N`, of a `bitstring_type` node.\n\n_See also: _`bitstring_type/2`.","title":"erl_syntax.bitstring_type_n/1","ref":"erl_syntax.html#bitstring_type_n/1"},{"type":"function","doc":"Creates an abstract block expression.\n\nIf `Body` is `[B1, ..., Bn]`, the result represents \"`begin B1, ...,\nBn end`\".\n\n_See also: _`block_expr_body/1`.","title":"erl_syntax.block_expr/1","ref":"erl_syntax.html#block_expr/1"},{"type":"function","doc":"Returns the list of body subtrees of a `block_expr` node.\n\n_See also: _`block_expr/1`.","title":"erl_syntax.block_expr_body/1","ref":"erl_syntax.html#block_expr_body/1"},{"type":"function","doc":"Creates an abstract case-expression.\n\nIf `Clauses` is `[C1, ..., Cn]`, the result represents \"`case\nArgument of C1; ...; Cn end`\". More exactly, if each `Ci`\nrepresents \"`(Pi) Gi -> Bi`\", then the result represents \"`case\nArgument of P1G1 -> B1; ...; PnGn -> Bn end`\".\n\n_See also: _`case_expr_argument/1`, `case_expr_clauses/1`, `clause/3`,\n`if_expr/1`.","title":"erl_syntax.case_expr/2","ref":"erl_syntax.html#case_expr/2"},{"type":"function","doc":"Returns the argument subtree of a `case_expr` node.\n\n_See also: _`case_expr/2`.","title":"erl_syntax.case_expr_argument/1","ref":"erl_syntax.html#case_expr_argument/1"},{"type":"function","doc":"Returns the list of clause subtrees of a `case_expr` node.\n\n_See also: _`case_expr/2`.","title":"erl_syntax.case_expr_clauses/1","ref":"erl_syntax.html#case_expr_clauses/1"},{"type":"function","doc":"Creates an abstract catch-expression.\n\nThe result represents \"`catch Expr`\".\n\n_See also: _`catch_expr_body/1`.","title":"erl_syntax.catch_expr/1","ref":"erl_syntax.html#catch_expr/1"},{"type":"function","doc":"Returns the body subtree of a `catch_expr` node.\n\n_See also: _`catch_expr/1`.","title":"erl_syntax.catch_expr_body/1","ref":"erl_syntax.html#catch_expr_body/1"},{"type":"function","doc":"Creates an abstract character literal.\n\nThe result represents \"`$Name`\", where `Name` corresponds to `Value`.\n\n> #### Note {: .info }\n\nThe literal corresponding to a particular character value is not\nuniquely defined. For example, the character \"`a`\" can be written both\nas \"`$a`\" and \"`$\\141`\", and a Tab character can be written as\n\"`$\\11`\", \"`$\\011`\", or \"`$\\t`\".\n\n_See also: _`char_literal/1`, `char_literal/2`, `char_value/1`, `is_char/2`.","title":"erl_syntax.char/1","ref":"erl_syntax.html#char/1"},{"type":"function","doc":"Returns the literal string represented by a `char` node.\n\nThis includes the leading \"`$`\" character. Characters beyond 255 will\nbe escaped.\n\n_See also: _`char/1`.","title":"erl_syntax.char_literal/1","ref":"erl_syntax.html#char_literal/1"},{"type":"function","doc":"Returns the literal string represented by a `char` node.\n\nThis includes the leading \"`$`\" character. Depending on the encoding a\ncharacter beyond 255 will be escaped (`latin1`) or copied as is\n(`utf8`).\n\n_See also: _`char/1`.","title":"erl_syntax.char_literal/2","ref":"erl_syntax.html#char_literal/2"},{"type":"function","doc":"Returns the value represented by a `char` node.\n\n_See also: _`char/1`.","title":"erl_syntax.char_value/1","ref":"erl_syntax.html#char_value/1"},{"type":"function","doc":"Creates an abstract class qualifier.\n\nThe result represents \"`Class:Body`\".\n\n_See also: _`class_qualifier_argument/1`, `class_qualifier_body/1`,\n`class_qualifier_stacktrace/1`, `try_expr/4`.","title":"erl_syntax.class_qualifier/2","ref":"erl_syntax.html#class_qualifier/2"},{"type":"function","doc":"Creates an abstract class qualifier.\n\nThe result represents \"`Class:Body:Stacktrace`\".\n\n_See also: _`class_qualifier_argument/1`, `class_qualifier_body/1`,\n`try_expr/4`.","title":"erl_syntax.class_qualifier/3","ref":"erl_syntax.html#class_qualifier/3"},{"type":"function","doc":"Returns the argument (the class) subtree of a `class_qualifier` node.\n\n_See also: _`class_qualifier/2`.","title":"erl_syntax.class_qualifier_argument/1","ref":"erl_syntax.html#class_qualifier_argument/1"},{"type":"function","doc":"Returns the body subtree of a `class_qualifier` node.\n\n_See also: _`class_qualifier/2`.","title":"erl_syntax.class_qualifier_body/1","ref":"erl_syntax.html#class_qualifier_body/1"},{"type":"function","doc":"Returns the stacktrace subtree of a `class_qualifier` node.\n\n_See also: _`class_qualifier/2`.","title":"erl_syntax.class_qualifier_stacktrace/1","ref":"erl_syntax.html#class_qualifier_stacktrace/1"},{"type":"function","doc":"","title":"erl_syntax.clause/2","ref":"erl_syntax.html#clause/2"},{"type":"function","doc":"Creates an abstract clause.\n\nIf `Patterns` is `[P1, ..., Pn]` and `Body` is `[B1, ..., Bm]`, then\nif `Guard` is `none`, the result represents \"`(P1, ..., Pn) ->\nB1, ..., Bm`\", otherwise, unless `Guard` is a list, the result\nrepresents \"`(P1, ..., Pn) when Guard -> B1, ..., Bm`\".\n\nFor simplicity, the `Guard` argument may also be any of the following:\n\n- An empty list `[]`. This is equivalent to passing `none`.\n- A nonempty list `[E1, ..., Ej]` of syntax trees. This is equivalent to passing\n `conjunction([E1, ..., Ej])`.\n- A nonempty list of lists of syntax trees\n `[[E1_1, ..., E1_k1], ..., [Ej_1, ..., Ej_kj]]`, which is equivalent to\n passing\n `disjunction([conjunction([E1_1, ..., E1_k1]), ..., conjunction([Ej_1, ..., Ej_kj])])`.\n\n_See also: _`clause/2`, `clause_body/1`, `clause_guard/1`, `clause_patterns/1`.","title":"erl_syntax.clause/3","ref":"erl_syntax.html#clause/3"},{"type":"function","doc":"Return the list of body subtrees of a `clause` node.\n\n_See also: _`clause/3`.","title":"erl_syntax.clause_body/1","ref":"erl_syntax.html#clause_body/1"},{"type":"function","doc":"Returns the guard subtree of a `clause` node, if any.\n\nIf `Node` represents \"`(P1, ..., Pn) when Guard -> B1, ...,\nBm`\", `Guard` is returned. Otherwise, the result is `none`.\n\n_See also: _`clause/3`.","title":"erl_syntax.clause_guard/1","ref":"erl_syntax.html#clause_guard/1"},{"type":"function","doc":"Returns the list of pattern subtrees of a `clause` node.\n\n_See also: _`clause/3`.","title":"erl_syntax.clause_patterns/1","ref":"erl_syntax.html#clause_patterns/1"},{"type":"function","doc":"","title":"erl_syntax.comment/1","ref":"erl_syntax.html#comment/1"},{"type":"function","doc":"Creates an abstract comment with the given padding and text.\n\nIf `Strings` is a (possibly empty) list `[\"Txt1\", ..., \"TxtN\"]`,\nthe result represents the source code text\n\n```text\n Txt1\n ...\n TxtN\n```\n\n`Padding` states the number of empty character positions to the left of the\ncomment separating it horizontally from source code on the same line (if any).\nIf `Padding` is `none`, a default positive number is used. If `Padding` is an\ninteger less than 1, there should be no separating space. Comments are in\nthemselves regarded as source program forms.\n\n_See also: _`comment/1`, `is_form/1`.","title":"erl_syntax.comment/2","ref":"erl_syntax.html#comment/2"},{"type":"function","doc":"Returns the amount of padding before the comment, or `none`.\n\n`none` means that a default padding may be used.\n\n_See also: _`comment/2`.","title":"erl_syntax.comment_padding/1","ref":"erl_syntax.html#comment_padding/1"},{"type":"function","doc":"Returns the lines of text of the abstract comment.\n\n_See also: _`comment/2`.","title":"erl_syntax.comment_text/1","ref":"erl_syntax.html#comment_text/1"},{"type":"function","doc":"Yields the most compact form for an abstract list skeleton.\n\nThe result either represents \"`[E1, ..., En | Tail]`\", where\n`Tail` is not a list skeleton, or otherwise simply \"`[E1, ...,\nEn]`\". Annotations on subtrees of `Node` that represent list\nskeletons may be lost, but comments will be propagated to the\nresult. Returns `Node` itself if `Node` does not represent a list\nskeleton.\n\n_See also: _`list/2`, `normalize_list/1`.","title":"erl_syntax.compact_list/1","ref":"erl_syntax.html#compact_list/1"},{"type":"function","doc":"Returns the Erlang term represented by a syntax tree.\n\nEvaluation fails with reason `badarg` if `Node` does not represent a\nliteral term.\n\n> #### Note {: .info }\n>\n> The set of syntax trees which have a concrete representation is larger\n> than the set of trees which can be built using the function\n> `abstract/1`. An abstract character will be concretised as an\n> integer, while `abstract/1` does not at present yield an abstract\n> character for any input. (Use the `char/1` function to explicitly\n> create an abstract character.)\n\n> #### Note {: .info }\n>\n> `arity_qualifier` nodes are recognized. This is to follow the Erlang\n> Parser when it comes to wild attributes: both `{F, A}` and `F/A` are\n> recognized, which makes it possible to turn wild attributes into\n> recognized attributes without at the same time making it impossible to\n> compile files using the new syntax with the old version of the Erlang\n> Compiler.\n\n_See also: _`abstract/1`, `char/1`, `is_literal/1`.","title":"erl_syntax.concrete/1","ref":"erl_syntax.html#concrete/1"},{"type":"function","doc":"Creates an abstract conjunction.\n\nIf `List` is `[E1, ..., En]`, the result represents \"`E1, ..., En`\".\n\n_See also: _`conjunction_body/1`, `disjunction/1`.","title":"erl_syntax.conjunction/1","ref":"erl_syntax.html#conjunction/1"},{"type":"function","doc":"Returns the list of body subtrees of a `conjunction` node.\n\n_See also: _`conjunction/1`.","title":"erl_syntax.conjunction_body/1","ref":"erl_syntax.html#conjunction_body/1"},{"type":"function","doc":"\"Optimizing\" list skeleton cons operation.\n\nCreates an abstract list skeleton whose first element is `Head` and\nwhose tail corresponds to `Tail`. This is similar to [`list([Head],\nTail)`](`list/2`), except that `Tail` must not be `none`,\nand the result does not necessarily represent exactly \"`[Head | Tail]`\", but\nmay depend on the `Tail` subtree.\n\nFor example, if `Tail` represents `[X, Y]`, the result may represent\n\"`[Head, X, Y]`\", rather than \"`[Head | [X, Y]]`\". Annotations on\n`Tail` itself may be lost if `Tail` represents a list skeleton, but\ncomments on `Tail` are propagated to the result.\n\n_See also: _`list/2`, `list_head/1`, `list_tail/1`.","title":"erl_syntax.cons/2","ref":"erl_syntax.html#cons/2"},{"type":"function","doc":"Creates an abstract constrained function type.\n\nIf `FunctionConstraint` is `[C1, ..., Cn]`, the result represents\n\"`FunctionType when C1, ...Cn`\".\n\n_See also: _`constrained_function_type_argument/1`,\n`constrained_function_type_body/1`.","title":"erl_syntax.constrained_function_type/2","ref":"erl_syntax.html#constrained_function_type/2"},{"type":"function","doc":"Returns the function constraint subtree of a `constrained_function_type` node.\n\n_See also: _`constrained_function_type/2`.","title":"erl_syntax.constrained_function_type_argument/1","ref":"erl_syntax.html#constrained_function_type_argument/1"},{"type":"function","doc":"Returns the function type subtree of a `constrained_function_type` node.\n\n_See also: _`constrained_function_type/2`.","title":"erl_syntax.constrained_function_type_body/1","ref":"erl_syntax.html#constrained_function_type_body/1"},{"type":"function","doc":"Creates an abstract (subtype) constraint.\n\nThe result represents \"`Name :: Type`\".\n\n_See also: _`constraint_argument/1`, `constraint_body/1`.","title":"erl_syntax.constraint/2","ref":"erl_syntax.html#constraint/2"},{"type":"function","doc":"Returns the name subtree of a `constraint` node.\n\n_See also: _`constraint/2`.","title":"erl_syntax.constraint_argument/1","ref":"erl_syntax.html#constraint_argument/1"},{"type":"function","doc":"Returns the type subtree of a `constraint` node.\n\n_See also: _`constraint/2`.","title":"erl_syntax.constraint_body/1","ref":"erl_syntax.html#constraint_body/1"},{"type":"function","doc":"Copies the list of user annotations from `Source` to `Target`.\n\nNote: this is equivalent to [`set_ann(Target, get_ann(Source))`](`set_ann/2`),\nbut potentially more efficient.\n\n_See also: _`get_ann/1`, `set_ann/2`.","title":"erl_syntax.copy_ann/2","ref":"erl_syntax.html#copy_ann/2"},{"type":"function","doc":"Copies the attributes from `Source` to `Target`.\n\nNote: this is equivalent to\n[`set_attrs(Target, get_attrs(Source))`](`set_attrs/2`), but potentially more\nefficient.\n\n_See also: _`get_attrs/1`, `set_attrs/2`.","title":"erl_syntax.copy_attrs/2","ref":"erl_syntax.html#copy_attrs/2"},{"type":"function","doc":"Copies the pre- and postcomments from `Source` to `Target`.\n\nNote: This is equivalent to\n[`set_postcomments(set_precomments(Target, get_precomments(Source)), get_postcomments(Source))`](`set_postcomments/2`),\nbut potentially more efficient.\n\n_See also: _`comment/2`, `get_postcomments/1`, `get_precomments/1`,\n`set_postcomments/2`, `set_precomments/2`.","title":"erl_syntax.copy_comments/2","ref":"erl_syntax.html#copy_comments/2"},{"type":"function","doc":"Copies the annotation from `Source` to `Target`.\n\nThis is equivalent to [`set_pos(Target, get_pos(Source))`](`set_pos/2`), but\npotentially more efficient.\n\n_See also: _`get_pos/1`, `set_pos/2`.","title":"erl_syntax.copy_pos/2","ref":"erl_syntax.html#copy_pos/2"},{"type":"function","doc":"**For special purposes only**. Returns the associated data of a syntax tree node.\n\nEvaluation fails with reason `badarg` if [`is_tree(Node)`](`is_tree/1`) does not\nyield `true`.\n\n_See also: _`tree/2`.","title":"erl_syntax.data/1","ref":"erl_syntax.html#data/1"},{"type":"function","doc":"Creates an abstract disjunction.\n\nIf `List` is `[E1, ..., En]`, the result represents \"`E1; ...; En`\".\n\n_See also: _`conjunction/1`, `disjunction_body/1`.","title":"erl_syntax.disjunction/1","ref":"erl_syntax.html#disjunction/1"},{"type":"function","doc":"Returns the list of body subtrees of a `disjunction` node.\n\n_See also: _`disjunction/1`.","title":"erl_syntax.disjunction_body/1","ref":"erl_syntax.html#disjunction_body/1"},{"type":"function","doc":"Creates an abstract else-expression.\n\nIf `Clauses` is `[C1, ..., Cn]`, the result\nrepresents \"`else C1; ...; Cn end`\". More exactly, if each `Ci` represents\n\"`(Pi) Gi -> Bi`\", then the result represents\n\"`else (P1) G1 -> B1; ...; (Pn) Gn -> Bn end`\".\n\n_See also: _`clause/3`, `else_expr_clauses/1`, `maybe_expr/2`.","title":"erl_syntax.else_expr/1","ref":"erl_syntax.html#else_expr/1"},{"type":"function","doc":"Returns the list of clause subtrees of an `else_expr` node.\n\n_See also: _`else_expr/1`.","title":"erl_syntax.else_expr_clauses/1","ref":"erl_syntax.html#else_expr_clauses/1"},{"type":"function","doc":"Creates an abstract end-of-file marker.\n\nThis represents the end of input when reading a sequence of source\ncode forms. An end-of-file marker is itself regarded as a source code\nform (namely, the last in any sequence in which it occurs). It has no\ndefined lexical form.\n\n> #### Note {: .info }\n>\n> This is retained only for backwards compatibility with existing parsers\n> and tools.\n\n_See also: _`error_marker/1`, `is_form/1`, `warning_marker/1`.","title":"erl_syntax.eof_marker/0","ref":"erl_syntax.html#eof_marker/0"},{"type":"function","doc":"Creates an abstract error marker.\n\nThe result represents an occurrence of an error in the source code,\nwith an associated Erlang I/O ErrorInfo structure given by `Error`\n(see module [`//stdlib/io`](`m:io`) for details). Error markers are\nregarded as source code forms, but have no defined lexical form.\n\n> #### Note {: .info }\n>\n> This is supported only for backwards compatibility with existing parsers\n> and tools.\n\n_See also: _`eof_marker/0`, `error_marker_info/1`, `is_form/1`,\n`warning_marker/1`.","title":"erl_syntax.error_marker/1","ref":"erl_syntax.html#error_marker/1"},{"type":"function","doc":"Returns the ErrorInfo structure of an `error_marker` node.\n\n_See also: _`error_marker/1`.","title":"erl_syntax.error_marker_info/1","ref":"erl_syntax.html#error_marker_info/1"},{"type":"function","doc":"Flattens sublists of a `form_list` node.\n\nReturns `Node` with all subtrees of type `form_list` recursively\nexpanded, yielding a single \"flat\" abstract form sequence.\n\n_See also: _`form_list/1`.","title":"erl_syntax.flatten_form_list/1","ref":"erl_syntax.html#flatten_form_list/1"},{"type":"function","doc":"Creates an abstract floating-point literal.\n\nThe lexical representation is the decimal floating-point numeral of\n`Value`.\n\n_See also: _`float_literal/1`, `float_value/1`.","title":"erl_syntax.float/1","ref":"erl_syntax.html#float/1"},{"type":"function","doc":"Returns the numeral string represented by a `float` node.\n\n_See also: _`float/1`.","title":"erl_syntax.float_literal/1","ref":"erl_syntax.html#float_literal/1"},{"type":"function","doc":"Returns the value represented by a `float` node.\n\nNote that floating-point values should usually not be compared for\nequality.\n\n_See also: _`float/1`.","title":"erl_syntax.float_value/1","ref":"erl_syntax.html#float_value/1"},{"type":"function","doc":"Creates an abstract sequence of \"source code forms\".\n\nIf `Forms` is `[F1, ..., Fn]`, where each `Fi` is a form (see\n`is_form/1`), the result represents:\n\n```text\nF1\n...\nFn\n```\n\nwhere the `Fi` are separated by one or more line breaks. A node of type\n`form_list` is itself regarded as a source code form; see `flatten_form_list/1`.\n\n> #### Note {: .info }\n>\n> This is simply a way of grouping source code forms into a single syntax\ntree, usually to form an Erlang module definition.\n\n_See also: _`flatten_form_list/1`, `form_list_elements/1`, `is_form/1`.","title":"erl_syntax.form_list/1","ref":"erl_syntax.html#form_list/1"},{"type":"function","doc":"Returns the list of subnodes of a `form_list` node.\n\n_See also: _`form_list/1`.","title":"erl_syntax.form_list_elements/1","ref":"erl_syntax.html#form_list_elements/1"},{"type":"function","doc":"Creates an abstract fun-expression.\n\nIf `Clauses` is `[C1, ..., Cn]`, the result represents \"`fun C1;\n...; Cn end`\". More exactly, if each `Ci` represents \"`(Pi1, ...,\nPim) Gi -> Bi`\", then the result represents \"`fun (P11, ...,\nP1m) G1 -> B1; ...; (Pn1, ..., Pnm) Gn -> Bn end`\".\n\n_See also: _`fun_expr_arity/1`, `fun_expr_clauses/1`.","title":"erl_syntax.fun_expr/1","ref":"erl_syntax.html#fun_expr/1"},{"type":"function","doc":"Returns the arity of a `fun_expr` node.\n\nThe result is the number of parameter patterns in the first clause of\nthe fun-expression; subsequent clauses are ignored.\n\nAn exception is thrown if [`fun_expr_clauses(Node)`](`fun_expr_clauses/1`)\nreturns an empty list, or if the first element of that list is not a syntax tree\n`C` of type `clause` such that [`clause_patterns(C)`](`clause_patterns/1`) is a\nnonempty list.\n\n_See also: _`clause/3`, `clause_patterns/1`, `fun_expr/1`, `fun_expr_clauses/1`.","title":"erl_syntax.fun_expr_arity/1","ref":"erl_syntax.html#fun_expr_arity/1"},{"type":"function","doc":"Returns the list of clause subtrees of a `fun_expr` node.\n\n_See also: _`fun_expr/1`.","title":"erl_syntax.fun_expr_clauses/1","ref":"erl_syntax.html#fun_expr_clauses/1"},{"type":"function","doc":"Creates an abstract fun of any type.\n\nThe result represents \"`fun()`\".","title":"erl_syntax.fun_type/0","ref":"erl_syntax.html#fun_type/0"},{"type":"function","doc":"Creates an abstract function definition.\n\nIf `Clauses` is `[C1, ..., Cn]`, the result represents \"`Name C1;\n...; Name Cn.`\". More exactly, if each `Ci` represents \"`(Pi1, ...,\nPim) Gi -> Bi`\", then the result represents \"`Name(P11, ...,\nP1m) G1 -> B1; ...; Name(Pn1, ..., Pnm) Gn -> Bn.`\".\nFunction definitions are source code forms.\n\n_See also: _`function_arity/1`, `function_clauses/1`, `function_name/1`,\n`is_form/1`.","title":"erl_syntax.function/2","ref":"erl_syntax.html#function/2"},{"type":"function","doc":"Returns the arity of a `function` node.\n\nThe result is the number of parameter patterns in the first clause of\nthe function; subsequent clauses are ignored.\n\nAn exception is thrown if [`function_clauses(Node)`](`function_clauses/1`)\nreturns an empty list, or if the first element of that list is not a syntax tree\n`C` of type `clause` such that [`clause_patterns(C)`](`clause_patterns/1`) is a\nnonempty list.\n\n_See also: _`clause/3`, `clause_patterns/1`, `function/2`, `function_clauses/1`.","title":"erl_syntax.function_arity/1","ref":"erl_syntax.html#function_arity/1"},{"type":"function","doc":"Returns the list of clause subtrees of a `function` node.\n\n_See also: _`function/2`.","title":"erl_syntax.function_clauses/1","ref":"erl_syntax.html#function_clauses/1"},{"type":"function","doc":"Returns the name subtree of a `function` node.\n\n_See also: _`function/2`.","title":"erl_syntax.function_name/1","ref":"erl_syntax.html#function_name/1"},{"type":"function","doc":"","title":"erl_syntax.function_type/1","ref":"erl_syntax.html#function_type/1"},{"type":"function","doc":"Creates an abstract function type.\n\nIf `Arguments` is `[T1, ..., Tn]` *and* it occurs within a function\nspecification, the result represents \"`(T1, ...Tn) -> Return`\";\notherwise it represents \"`fun((T1, ...Tn) -> Return)`\". If\n`Arguments` is `any_arity`, it represents \"`fun((...) -> Return)`\".\n\nNote that the `m:erl_parse` representation is identical for\n\"`FunctionType`\" and \"`fun(FunctionType)`\".\n\n_See also: _`function_type_arguments/1`, `function_type_return/1`.","title":"erl_syntax.function_type/2","ref":"erl_syntax.html#function_type/2"},{"type":"function","doc":"Returns the argument types subtrees of a `function_type` node.\n\nIf `Node` represents \"`fun((...) -> Return)`\", `any_arity` is\nreturned; otherwise, if `Node` represents \"`(T1, ...Tn) ->\nReturn`\" or \"`fun((T1, ...Tn) -> Return)`\", `[T1, ..., Tn]` is\nreturned.\n\n_See also: _`function_type/1`, `function_type/2`.","title":"erl_syntax.function_type_arguments/1","ref":"erl_syntax.html#function_type_arguments/1"},{"type":"function","doc":"Returns the return type subtrees of a `function_type` node.\n\n_See also: _`function_type/1`, `function_type/2`.","title":"erl_syntax.function_type_return/1","ref":"erl_syntax.html#function_type_return/1"},{"type":"function","doc":"Creates an abstract list generator.\n\nThe result represents \"`Pattern <- Body`\".\n\n_See also: _`binary_comp/2`, `generator_body/1`, `generator_pattern/1`,\n`map_comp/2`, `list_comp/2`.","title":"erl_syntax.generator/2","ref":"erl_syntax.html#generator/2"},{"type":"function","doc":"Returns the body subtree of a `generator` node.\n\n_See also: _`generator/2`.","title":"erl_syntax.generator_body/1","ref":"erl_syntax.html#generator_body/1"},{"type":"function","doc":"Returns the pattern subtree of a `generator` node.\n\n_See also: _`generator/2`.","title":"erl_syntax.generator_pattern/1","ref":"erl_syntax.html#generator_pattern/1"},{"type":"function","doc":"Returns the list of user annotations associated with a syntax tree.\n\nFor a newly created node, this is the empty list. The annotations may\nbe any terms.\n\n_See also: _`get_attrs/1`, `set_ann/2`.","title":"erl_syntax.get_ann/1","ref":"erl_syntax.html#get_ann/1"},{"type":"function","doc":"Returns a representation of the attributes associated with a syntax tree node.\n\nThe attributes are all the extra information that can be attached to a node.\nCurrently, this includes position information, source code comments, and user\nannotations. The result of this function cannot be inspected directly; only\nattached to another node (see `set_attrs/2`).\n\nFor accessing individual attributes, see `get_pos/1`, `get_ann/1`,\n`get_precomments/1` and `get_postcomments/1`.\n\n_See also: _`get_ann/1`, `get_pos/1`, `get_postcomments/1`, `get_precomments/1`,\n`set_attrs/2`.","title":"erl_syntax.get_attrs/1","ref":"erl_syntax.html#get_attrs/1"},{"type":"function","doc":"Returns the annotation (see [`//stdlib/erl_anno`](`m:erl_anno`)) associated with\n`Node`.\n\nBy default, all new tree nodes have their associated position\ninformation set to the integer zero. Use\n[`//stdlib/erl_anno:location/1`](`erl_anno:location/1`) or\n[`//stdlib/erl_anno:line/1`](`erl_anno:line/1`) to get the position information.\n\n_See also: _`get_attrs/1`, `set_pos/2`.","title":"erl_syntax.get_pos/1","ref":"erl_syntax.html#get_pos/1"},{"type":"function","doc":"Returns the associated post-comments of a node.\n\nThis is a possibly empty list of abstract comments, in top-down\ntextual order. When the code is formatted, post-comments are typically\ndisplayed to the right of and/or below the node. For example:\n\n```erlang\n{foo, X, Y} % Post-comment of tuple\n```\n\nIf possible, the comment should be moved past any following separator characters\non the same line, rather than placing the separators on the following line.\nFor example:\n\n```erlang\nfoo([X | Xs], Y) ->\n foo(Xs, bar(X)); % Post-comment of 'bar(X)' node\n ...\n```\n\n(where the comment is moved past the rightmost \"`)`\" and the \"`;`\").\n\n_See also: _`comment/2`, `get_attrs/1`, `get_precomments/1`,\n`set_postcomments/2`.","title":"erl_syntax.get_postcomments/1","ref":"erl_syntax.html#get_postcomments/1"},{"type":"function","doc":"Returns the associated pre-comments of a node.\n\nThis is a possibly empty list of abstract comments, in top-down\ntextual order. When the code is formatted, pre-comments are typically\ndisplayed directly above the node. For example:\n\n```erlang\n% Pre-comment of function\nfoo(X) -> {bar, X}.\n```\n\nIf possible, the comment should be moved before any preceding separator\ncharacters on the same line. For example:\n\n```erlang\nfoo([X | Xs]) ->\n % Pre-comment of 'bar(X)' node\n [bar(X) | foo(Xs)];\n...\n```\n\n(where the comment is moved before the \"`[`\").\n\n_See also: _`comment/2`, `get_attrs/1`, `get_postcomments/1`,\n`set_precomments/2`.","title":"erl_syntax.get_precomments/1","ref":"erl_syntax.html#get_precomments/1"},{"type":"function","doc":"Yields `false` if the node has no associated comments, and `true` otherwise.\n\nNote: This is equivalent to\n`(get_precomments(Node) == []) and (get_postcomments(Node) == [])`, but\npotentially more efficient.\n\n_See also: _`get_postcomments/1`, `get_precomments/1`, `remove_comments/1`.","title":"erl_syntax.has_comments/1","ref":"erl_syntax.html#has_comments/1"},{"type":"function","doc":"Creates an abstract if-expression.\n\nIf `Clauses` is `[C1, ..., Cn]`, the result represents \"`if C1; ...;\nCn end`\". More exactly, if each `Ci` represents \"`() Gi -> Bi`\",\nthen the result represents \"`if G1 -> B1; ...; Gn -> Bn end`\".\n\n_See also: _`case_expr/2`, `clause/3`, `if_expr_clauses/1`.","title":"erl_syntax.if_expr/1","ref":"erl_syntax.html#if_expr/1"},{"type":"function","doc":"Returns the list of clause subtrees of an `if_expr` node.\n\n_See also: _`if_expr/1`.","title":"erl_syntax.if_expr_clauses/1","ref":"erl_syntax.html#if_expr_clauses/1"},{"type":"function","doc":"Creates an abstract \"implicit fun\" expression.\n\nThe result represents \"`fun Name`\". `Name` should represent either\n`F/A` or `M:F/A`\n\n_See also: _`arity_qualifier/2`, `implicit_fun/2`, `implicit_fun/3`,\n`implicit_fun_name/1`, `module_qualifier/2`.","title":"erl_syntax.implicit_fun/1","ref":"erl_syntax.html#implicit_fun/1"},{"type":"function","doc":"Creates an abstract \"implicit fun\" expression.\n\nIf `Arity` is `none`, this is equivalent to\n[`implicit_fun(Name)`](`implicit_fun/1`), otherwise it is equivalent\nto [`implicit_fun(arity_qualifier(Name, Arity))`](`implicit_fun/1`).\n\n(This is a utility function.)\n\n_See also: _`implicit_fun/1`, `implicit_fun/3`.","title":"erl_syntax.implicit_fun/2","ref":"erl_syntax.html#implicit_fun/2"},{"type":"function","doc":"Creates an abstract module-qualified \"implicit fun\" expression.\n\nIf `Module` is `none`, this is equivalent to [`implicit_fun(Name,\nArity)`](`implicit_fun/2`), otherwise it is equivalent to\n`implicit_fun(module_qualifier(Module, arity_qualifier(Name, Arity))`.\n\n(This is a utility function.)\n\n_See also: _`implicit_fun/1`, `implicit_fun/2`.","title":"erl_syntax.implicit_fun/3","ref":"erl_syntax.html#implicit_fun/3"},{"type":"function","doc":"Returns the name subtree of an `implicit_fun` node.\n\nIf `Node` represents \"`fun N/A`\" or \"`fun M:N/A`\", then the\nresult is the subtree representing \"`N/A`\" or \"`M:N/A`\", respectively.\n\n_See also: _`arity_qualifier/2`, `implicit_fun/1`, `module_qualifier/2`.","title":"erl_syntax.implicit_fun_name/1","ref":"erl_syntax.html#implicit_fun_name/1"},{"type":"function","doc":"Creates an abstract infix operator expression.\n\nThe result represents \"`Left Operator Right`\".\n\n_See also: _`infix_expr_left/1`, `infix_expr_operator/1`, `infix_expr_right/1`,\n`prefix_expr/2`.","title":"erl_syntax.infix_expr/3","ref":"erl_syntax.html#infix_expr/3"},{"type":"function","doc":"Returns the left argument subtree of an `infix_expr` node.\n\n_See also: _`infix_expr/3`.","title":"erl_syntax.infix_expr_left/1","ref":"erl_syntax.html#infix_expr_left/1"},{"type":"function","doc":"Returns the operator subtree of an `infix_expr` node.\n\n_See also: _`infix_expr/3`.","title":"erl_syntax.infix_expr_operator/1","ref":"erl_syntax.html#infix_expr_operator/1"},{"type":"function","doc":"Returns the right argument subtree of an `infix_expr` node.\n\n_See also: _`infix_expr/3`.","title":"erl_syntax.infix_expr_right/1","ref":"erl_syntax.html#infix_expr_right/1"},{"type":"function","doc":"Creates an abstract integer literal.\n\nThe lexical representation is the canonical decimal numeral of `Value`.\n\n_See also: _`integer_literal/1`, `integer_value/1`, `is_integer/2`.","title":"erl_syntax.integer/1","ref":"erl_syntax.html#integer/1"},{"type":"function","doc":"Returns the numeral string represented by an `integer` node.\n\n_See also: _`integer/1`.","title":"erl_syntax.integer_literal/1","ref":"erl_syntax.html#integer_literal/1"},{"type":"function","doc":"Creates an abstract range type.\n\nThe result represents \"`Low .. High`\".\n\n_See also: _`integer_range_type_high/1`, `integer_range_type_low/1`.","title":"erl_syntax.integer_range_type/2","ref":"erl_syntax.html#integer_range_type/2"},{"type":"function","doc":"Returns the high limit of an `integer_range_type` node.\n\n_See also: _`integer_range_type/2`.","title":"erl_syntax.integer_range_type_high/1","ref":"erl_syntax.html#integer_range_type_high/1"},{"type":"function","doc":"Returns the low limit of an `integer_range_type` node.\n\n_See also: _`integer_range_type/2`.","title":"erl_syntax.integer_range_type_low/1","ref":"erl_syntax.html#integer_range_type_low/1"},{"type":"function","doc":"Returns the value represented by an `integer` node.\n\n_See also: _`integer/1`.","title":"erl_syntax.integer_value/1","ref":"erl_syntax.html#integer_value/1"},{"type":"function","doc":"Returns `true` if `Node` has type `atom` and represents `Value`, otherwise\n`false`.\n\n_See also: _`atom/1`.","title":"erl_syntax.is_atom/2","ref":"erl_syntax.html#is_atom/2"},{"type":"function","doc":"Returns `true` if `Node` has type `char` and represents `Value`, otherwise\n`false`.\n\n_See also: _`char/1`.","title":"erl_syntax.is_char/2","ref":"erl_syntax.html#is_char/2"},{"type":"function","doc":"Returns `true` if `Node` is a syntax tree representing a so-called \"source code\nform\", otherwise `false`.\n\nForms are the Erlang source code units which, placed in sequence,\nconstitute an Erlang program. Current form types are:\n\n* `attribute`\n* `comment`\n* `error_marker`\n* `eof_marker`\n* `form_list`\n* `function`\n* `warning_marker`\n* `text`\n\n\n_See also: _`attribute/2`, `comment/2`, `eof_marker/0`, `error_marker/1`,\n`form_list/1`, `function/2`, `type/1`, `warning_marker/1`.","title":"erl_syntax.is_form/1","ref":"erl_syntax.html#is_form/1"},{"type":"function","doc":"Returns `true` if `Node` has type `integer` and represents `Value`, otherwise\n`false`.\n\n_See also: _`integer/1`.","title":"erl_syntax.is_integer/2","ref":"erl_syntax.html#is_integer/2"},{"type":"function","doc":"Returns `true` if `Node` is a leaf node, otherwise `false`.\n\nThe currently recognised leaf node types are:\n\n* `atom`\n* `char`\n* `comment`\n* `eof_marker`\n* `error_marker`\n* `float`\n* `fun_type`\n* `integer`\n* `nil`\n* `operator`\n* `string`\n* `text`\n* `underscore`\n* `variable`\n* `warning_marker`\n\nA node of type `map_expr` is a leaf node if and only if it has no argument and\nno fields. A node of type `map_type` is a leaf node if and only if it has no\nfields (`any_size`). A node of type `tuple` is a leaf node if and only if its\narity is zero. A node of type `tuple_type` is a leaf node if and only if it has\nno elements (`any_size`).\n\nNote: not all literals are leaf nodes, and vice versa. For example,\ntuples with nonzero arity and nonempty lists may be literals, but are\nnot leaf nodes. Variables, on the other hand, are leaf nodes but not\nliterals.\n\n_See also: _`is_literal/1`, `type/1`.","title":"erl_syntax.is_leaf/1","ref":"erl_syntax.html#is_leaf/1"},{"type":"function","doc":"Returns `true` if `Node` has type `list` or `nil`, otherwise `false`.\n\n_See also: _`list/2`, `nil/0`.","title":"erl_syntax.is_list_skeleton/1","ref":"erl_syntax.html#is_list_skeleton/1"},{"type":"function","doc":"Returns `true` if `Node` represents a literal term, otherwise `false`.\n\nThis function returns `true` if and only if the value of\n[`concrete(Node)`](`concrete/1`) is defined.\n\n_See also: _`abstract/1`, `concrete/1`.","title":"erl_syntax.is_literal/1","ref":"erl_syntax.html#is_literal/1"},{"type":"function","doc":"Returns `true` if `Node` represents a proper list, and `false` otherwise.\n\nA proper list is a list skeleton either on the form \"`[]`\" or \"`[E1,\n..., En]`\", or \"`[... | Tail]`\" where recursively `Tail` also\nrepresents a proper list.\n\n> #### Note {: .info }\n>\n> Since `Node` is a syntax tree, the actual run-time values\n> corresponding to its subtrees can often be partially or completely\n> unknown. For example, if `Node` represents \"`[... | Ns]`\"\n> (where `Ns` is a variable), the function will return `false`\n> because it is not known whether `Ns` will be bound to a list at\n> run-time. Conversely, if `Node` represents, for example, \"`[1, 2, 3]`\" or\n> \"`[A | []]`\", the function will return `true`.\n\n_See also: _`list/2`.","title":"erl_syntax.is_proper_list/1","ref":"erl_syntax.html#is_proper_list/1"},{"type":"function","doc":"Returns `true` if `Node` has type `string` and represents `Value`, otherwise\n`false`.\n\n_See also: _`string/1`.","title":"erl_syntax.is_string/2","ref":"erl_syntax.html#is_string/2"},{"type":"function","doc":"**For special purposes only**. Returns `true` if `Tree` is an abstract syntax tree\nand `false` otherwise.\n\n> #### Note {: .info }\n>\n> This function yields `false` for all \"old-style\" `m:erl_parse`-compatible\n> \"parse trees\".\n\n_See also: _`tree/2`.","title":"erl_syntax.is_tree/1","ref":"erl_syntax.html#is_tree/1"},{"type":"function","doc":"Appends the comments of `Source` to the current comments of `Target`.\n\nNote: This is equivalent to\n[`add_postcomments(get_postcomments(Source), add_precomments(get_precomments(Source), Target))`](`add_postcomments/2`),\nbut potentially more efficient.\n\n_See also: _`add_postcomments/2`, `add_precomments/2`, `comment/2`,\n`get_postcomments/1`, `get_precomments/1`.","title":"erl_syntax.join_comments/2","ref":"erl_syntax.html#join_comments/2"},{"type":"function","doc":"","title":"erl_syntax.list/1","ref":"erl_syntax.html#list/1"},{"type":"function","doc":"Constructs an abstract list skeleton.\n\nThe result has type `list` or `nil`. If `List` is a nonempty list\n`[E1, ..., En]`, the result has type `list` and represents either\n\"`[E1, ..., En]`\" if `Tail` is `none`, or otherwise \"`[E1, ...,\nEn | Tail]`\". If `List` is the empty list, `Tail` _must_ be `none`,\nand in that case the result has type `nil` and represents \"`[]`\" (see\n`nil/0`).\n\nThe difference between lists as semantic objects (built up of individual \"cons\"\nand \"nil\" terms) and the various syntactic forms for denoting lists may be\nbewildering at first. This module provides functions both for exact control of\nthe syntactic representation as well as for the simple composition and\ndeconstruction in terms of cons and head/tail operations.\n\n> #### Note {: .info }\n>\n> In [`list(Elements, none)`](`list/2`), the \"nil\" list terminator is\n> implicit and has no associated information (see `get_attrs/1`). However,\n> in the seemingly equivalent [`list(Elements, Tail)`](`list/2`) where\n> `Tail` has the type `nil`, the list terminator subtree `Tail` may have\n> attached attributes such as position, comments, and annotations, which\n> will be preserved in the result.\n\n_See also: _`compact_list/1`, `cons/2`, `get_attrs/1`, `is_list_skeleton/1`,\n`is_proper_list/1`, `list/1`, `list_elements/1`, `list_head/1`, `list_length/1`,\n`list_prefix/1`, `list_suffix/1`, `list_tail/1`, `nil/0`, `normalize_list/1`.","title":"erl_syntax.list/2","ref":"erl_syntax.html#list/2"},{"type":"function","doc":"Creates an abstract list comprehension.\n\nIf `Body` is `[E1, ..., En]`, the result represents \"`[Template ||\nE1, ..., En]`\".\n\n_See also: _`generator/2`, `list_comp_body/1`, `list_comp_template/1`.","title":"erl_syntax.list_comp/2","ref":"erl_syntax.html#list_comp/2"},{"type":"function","doc":"Returns the list of body subtrees of a `list_comp` node.\n\n_See also: _`list_comp/2`.","title":"erl_syntax.list_comp_body/1","ref":"erl_syntax.html#list_comp_body/1"},{"type":"function","doc":"Returns the template subtree of a `list_comp` node.\n\n_See also: _`list_comp/2`.","title":"erl_syntax.list_comp_template/1","ref":"erl_syntax.html#list_comp_template/1"},{"type":"function","doc":"Returns the list of element subtrees of a list skeleton.\n\n`Node` must represent a proper list. For example, if `Node` represents\n\"`[X1, X2 | [X3, X4 | []]`\", then\n[`list_elements(Node)`](`list_elements/1`) yields the list `[X1, X2,\nX3, X4]`.\n\n_See also: _`is_proper_list/1`, `list/2`.","title":"erl_syntax.list_elements/1","ref":"erl_syntax.html#list_elements/1"},{"type":"function","doc":"Returns the head element subtree of a `list` node.\n\nIf `Node` represents \"`[Head ...]`\", the result will represent \"`Head`\".\n\n_See also: _`cons/2`, `list/2`, `list_tail/1`.","title":"erl_syntax.list_head/1","ref":"erl_syntax.html#list_head/1"},{"type":"function","doc":"Returns the number of element subtrees of a list skeleton.\n\n`Node` must represent a proper list. For example, if `Node` represents\n\"`[X1 | [X2, X3 | [X4, X5, X6]]]`\", then\n[`list_length(Node)`](`list_length/1`) returns the integer 6.\n\n> #### Note {: .info }\n>\n> This is equivalent to [`length(list_elements(Node))`](`length/1`), but\n> potentially more efficient.\n\n_See also: _`is_proper_list/1`, `list/2`, `list_elements/1`.","title":"erl_syntax.list_length/1","ref":"erl_syntax.html#list_length/1"},{"type":"function","doc":"Returns the prefix element subtrees of a `list` node.\n\nIf `Node` represents \"`[E1, ..., En]`\" or \"`[E1, ..., En |\nTail]`\", the returned value is `[E1, ..., En]`.\n\n_See also: _`list/2`.","title":"erl_syntax.list_prefix/1","ref":"erl_syntax.html#list_prefix/1"},{"type":"function","doc":"Returns the suffix subtree of a `list` node, if one exists.\n\nIf `Node` represents \"`[E1, ..., En | Tail]`\", the returned value is\n`Tail`. Otherwise, if `Node` represents \"`[E1, ..., En]`\", `none` is\nreturned.\n\n> #### Note {: .info }\n>\n> Even if this function returns a `Tail` that is not `none`, the type\n> of `Tail` can be `nil` if the tail has been given explicitly and the\n> list skeleton has not been compacted (see `compact_list/1`).\n\n_See also: _`compact_list/1`, `list/2`, `nil/0`.","title":"erl_syntax.list_suffix/1","ref":"erl_syntax.html#list_suffix/1"},{"type":"function","doc":"Returns the tail of a `list` node.\n\nIf `Node` represents a single-element list \"`[E]`\", then the result\nhas type `nil`, representing \"`[]`\". If `Node` represents \"`[E1,\nE2 ...]`\", the result will represent \"`[E2 ...]`\", and if `Node`\nrepresents \"`[Head | Tail]`\", the result will represent\n\"`Tail`\".\n\n_See also: _`cons/2`, `list/2`, `list_head/1`.","title":"erl_syntax.list_tail/1","ref":"erl_syntax.html#list_tail/1"},{"type":"function","doc":"","title":"erl_syntax.macro/1","ref":"erl_syntax.html#macro/1"},{"type":"function","doc":"Creates an abstract macro application.\n\nIf `Arguments` is `none`, the result represents \"`?Name`\",\notherwise, if `Arguments` is `[A1, ..., An]`, the result represents\n\"`?Name(A1, ..., An)`\".\n\nNotes: if `Arguments` is the empty list, the result will thus represent\n\"`?Name()`\", including a pair of matching parentheses.\n\nThe only syntactical limitation imposed by the preprocessor on the arguments to\na macro application (viewed as sequences of tokens) is that they must be\nbalanced with respect to parentheses, brackets, `begin ... end`, `case ... end`,\nand so on. The `text` node type can be used to represent arguments which are not\nregular Erlang constructs.\n\n_See also: _`macro/1`, `macro_arguments/1`, `macro_name/1`, `text/1`.","title":"erl_syntax.macro/2","ref":"erl_syntax.html#macro/2"},{"type":"function","doc":"Returns the list of argument subtrees of a `macro` node, if any.\n\nIf `Node` represents \"`?Name`\", `none` is returned. Otherwise, if\n`Node` represents \"`?Name(A1, ..., An)`\", `[A1, ..., An]` is\nreturned.\n\n_See also: _`macro/2`.","title":"erl_syntax.macro_arguments/1","ref":"erl_syntax.html#macro_arguments/1"},{"type":"function","doc":"Returns the name subtree of a `macro` node.\n\n_See also: _`macro/2`.","title":"erl_syntax.macro_name/1","ref":"erl_syntax.html#macro_name/1"},{"type":"function","doc":"Creates a syntax tree with the given type and subtrees.\n\n`Type` must be a node type name (see `type/1`) that does not denote a\nleaf node type (see `is_leaf/1`). `Groups` must be a _nonempty_ list\nof groups of syntax trees, representing the subtrees of a node of the\ngiven type, in left-to-right order as they would occur in the printed\nprogram text, grouped by category as done by `subtrees/1`.\n\nThe result of\n[`copy_attrs(Node, make_tree(type(Node), subtrees(Node)))`](`copy_attrs/2`) (see\n`update_tree/2`) represents the same source code text as the original `Node`,\nassuming that [`subtrees(Node)`](`subtrees/1`) yields a nonempty list. However,\nit does not necessarily have the same data representation as `Node`.\n\n_See also: _`copy_attrs/2`, `is_leaf/1`, `subtrees/1`, `type/1`,\n`update_tree/2`.","title":"erl_syntax.make_tree/2","ref":"erl_syntax.html#make_tree/2"},{"type":"function","doc":"Creates an abstract map comprehension.\n\nIf `Body` is `[E1, ..., En]`, the result represents \"`#{Template ||\nE1, ..., En}`\".\n\n_See also: _`generator/2`, `map_comp_body/1`, `map_comp_template/1`.","title":"erl_syntax.map_comp/2","ref":"erl_syntax.html#map_comp/2"},{"type":"function","doc":"Returns the list of body subtrees of a `map_comp` node.\n\n_See also: _`map_comp/2`.","title":"erl_syntax.map_comp_body/1","ref":"erl_syntax.html#map_comp_body/1"},{"type":"function","doc":"Returns the template subtree of a `map_comp` node.\n\n_See also: _`map_comp/2`.","title":"erl_syntax.map_comp_template/1","ref":"erl_syntax.html#map_comp_template/1"},{"type":"function","doc":"","title":"erl_syntax.map_expr/1","ref":"erl_syntax.html#map_expr/1"},{"type":"function","doc":"Creates an abstract map expression.\n\nIf `Fields` is `[F1, ..., Fn]`, then if `Argument` is `none`, the\nresult represents \"`#{F1, ..., Fn}`\", otherwise it represents\n\"`Argument#{F1, ..., Fn}`\".\n\n_See also: _`map_expr/1`, `map_expr_argument/1`, `map_expr_fields/1`,\n`map_field_assoc/2`, `map_field_exact/2`.","title":"erl_syntax.map_expr/2","ref":"erl_syntax.html#map_expr/2"},{"type":"function","doc":"Returns the argument subtree of a `map_expr` node, if any.\n\nIf `Node` represents \"`#{...}`\", `none` is returned. Otherwise, if\n`Node` represents \"`Argument#{...}`\", `Argument` is returned.\n\n_See also: _`map_expr/2`.","title":"erl_syntax.map_expr_argument/1","ref":"erl_syntax.html#map_expr_argument/1"},{"type":"function","doc":"Returns the list of field subtrees of a `map_expr` node.\n\n_See also: _`map_expr/2`.","title":"erl_syntax.map_expr_fields/1","ref":"erl_syntax.html#map_expr_fields/1"},{"type":"function","doc":"Creates an abstract map assoc field.\n\nThe result represents \"`Name => Value`\".\n\n_See also: _`map_expr/2`, `map_field_assoc_name/1`, `map_field_assoc_value/1`.","title":"erl_syntax.map_field_assoc/2","ref":"erl_syntax.html#map_field_assoc/2"},{"type":"function","doc":"Returns the name subtree of a `map_field_assoc` node.\n\n_See also: _`map_field_assoc/2`.","title":"erl_syntax.map_field_assoc_name/1","ref":"erl_syntax.html#map_field_assoc_name/1"},{"type":"function","doc":"Returns the value subtree of a `map_field_assoc` node.\n\n_See also: _`map_field_assoc/2`.","title":"erl_syntax.map_field_assoc_value/1","ref":"erl_syntax.html#map_field_assoc_value/1"},{"type":"function","doc":"Creates an abstract map exact field.\n\nThe result represents \"`Name := Value`\".\n\n_See also: _`map_expr/2`, `map_field_exact_name/1`, `map_field_exact_value/1`.","title":"erl_syntax.map_field_exact/2","ref":"erl_syntax.html#map_field_exact/2"},{"type":"function","doc":"Returns the name subtree of a `map_field_exact` node.\n\n_See also: _`map_field_exact/2`.","title":"erl_syntax.map_field_exact_name/1","ref":"erl_syntax.html#map_field_exact_name/1"},{"type":"function","doc":"Returns the value subtree of a `map_field_exact` node.\n\n_See also: _`map_field_exact/2`.","title":"erl_syntax.map_field_exact_value/1","ref":"erl_syntax.html#map_field_exact_value/1"},{"type":"function","doc":"Creates an abstract map_generator.\n\nThe result represents \"`Pattern <- Body`\".\n\n_See also: _`binary_comp/2`, `list_comp/2`, `map_comp/2`, `map_generator_body/1`,\n`map_generator_pattern/1`.","title":"erl_syntax.map_generator/2","ref":"erl_syntax.html#map_generator/2"},{"type":"function","doc":"Returns the body subtree of a `map_generator` node.\n\n_See also: _`map_generator/2`.","title":"erl_syntax.map_generator_body/1","ref":"erl_syntax.html#map_generator_body/1"},{"type":"function","doc":"Returns the pattern subtree of a `map_generator` node.\n\n_See also: _`map_generator/2`.","title":"erl_syntax.map_generator_pattern/1","ref":"erl_syntax.html#map_generator_pattern/1"},{"type":"function","doc":"","title":"erl_syntax.map_type/0","ref":"erl_syntax.html#map_type/0"},{"type":"function","doc":"Creates an abstract type map.\n\nIf `Fields` is `[F1, ..., Fn]`, the result represents \"`#{F1, ...,\nFn}`\"; otherwise, if `Fields` is `any_size`, it represents\n\"`t:map/0`\".\n\n_See also: _`map_type_fields/1`.","title":"erl_syntax.map_type/1","ref":"erl_syntax.html#map_type/1"},{"type":"function","doc":"Creates an abstract map type assoc field.\n\nThe result represents \"`Name => Value`\".\n\n_See also: _`map_type/1`, `map_type_assoc_name/1`, `map_type_assoc_value/1`.","title":"erl_syntax.map_type_assoc/2","ref":"erl_syntax.html#map_type_assoc/2"},{"type":"function","doc":"Returns the name subtree of a `map_type_assoc` node.\n\n_See also: _`map_type_assoc/2`.","title":"erl_syntax.map_type_assoc_name/1","ref":"erl_syntax.html#map_type_assoc_name/1"},{"type":"function","doc":"Returns the value subtree of a `map_type_assoc` node.\n\n_See also: _`map_type_assoc/2`.","title":"erl_syntax.map_type_assoc_value/1","ref":"erl_syntax.html#map_type_assoc_value/1"},{"type":"function","doc":"Creates an abstract map type exact field.\n\nThe result represents \"`Name := Value`\".\n\n_See also: _`map_type/1`, `map_type_exact_name/1`, `map_type_exact_value/1`.","title":"erl_syntax.map_type_exact/2","ref":"erl_syntax.html#map_type_exact/2"},{"type":"function","doc":"Returns the name subtree of a `map_type_exact` node.\n\n_See also: _`map_type_exact/2`.","title":"erl_syntax.map_type_exact_name/1","ref":"erl_syntax.html#map_type_exact_name/1"},{"type":"function","doc":"Returns the value subtree of a `map_type_exact` node.\n\n_See also: _`map_type_exact/2`.","title":"erl_syntax.map_type_exact_value/1","ref":"erl_syntax.html#map_type_exact_value/1"},{"type":"function","doc":"Returns the list of field subtrees of a `map_type` node.\n\nIf `Node` represents \"`t:map/0`\", `any_size` is returned; otherwise,\nif `Node` represents \"`#{F1, ..., Fn}`\", `[F1, ..., Fn]` is\nreturned.\n\n_See also: _`map_type/0`, `map_type/1`.","title":"erl_syntax.map_type_fields/1","ref":"erl_syntax.html#map_type_fields/1"},{"type":"function","doc":"Creates an abstract match-expression.\n\nThe result represents \"`Pattern = Body`\".\n\n_See also: _`match_expr_body/1`, `match_expr_pattern/1`.","title":"erl_syntax.match_expr/2","ref":"erl_syntax.html#match_expr/2"},{"type":"function","doc":"Returns the body subtree of a `match_expr` node.\n\n_See also: _`match_expr/2`.","title":"erl_syntax.match_expr_body/1","ref":"erl_syntax.html#match_expr_body/1"},{"type":"function","doc":"Returns the pattern subtree of a `match_expr` node.\n\n_See also: _`match_expr/2`.","title":"erl_syntax.match_expr_pattern/1","ref":"erl_syntax.html#match_expr_pattern/1"},{"type":"function","doc":"","title":"erl_syntax.maybe_expr/1","ref":"erl_syntax.html#maybe_expr/1"},{"type":"function","doc":"Creates an abstract maybe-expression.\n\nIf `Body` is `[B1, ..., Bn]`, and `OptionalElse` is `none`, the result\nrepresents \"`maybe B1, ..., Bn end`\". If `Body` is `[B1, ...,\nBn]`, and `OptionalElse` reprsents an `else_expr` node with clauses\n`[C1, ..., Cn]`, the result represents \"`maybe B1, ..., Bn else\nC1; ..., Cn end`\".\n\nSee `clause` for documentation on `m:erl_parse` clauses.\n\n_See also: _`maybe_expr_body/1`, `maybe_expr_else/1`.","title":"erl_syntax.maybe_expr/2","ref":"erl_syntax.html#maybe_expr/2"},{"type":"function","doc":"Returns the list of body subtrees of a `maybe_expr` node.\n\n_See also: _`maybe_expr/2`.","title":"erl_syntax.maybe_expr_body/1","ref":"erl_syntax.html#maybe_expr_body/1"},{"type":"function","doc":"Returns the else subtree of a `maybe_expr` node.\n\n_See also: _`maybe_expr/2`.","title":"erl_syntax.maybe_expr_else/1","ref":"erl_syntax.html#maybe_expr_else/1"},{"type":"function","doc":"Creates an abstract maybe-expression, as used in `maybe` blocks.\n\nThe result represents \"`Pattern ?= Body`\".\n\n_See also: _`maybe_expr/2`, `maybe_match_expr_body/1`,\n`maybe_match_expr_pattern/1`.","title":"erl_syntax.maybe_match_expr/2","ref":"erl_syntax.html#maybe_match_expr/2"},{"type":"function","doc":"Returns the body subtree of a `maybe_expr` node.\n\n_See also: _`maybe_match_expr/2`.","title":"erl_syntax.maybe_match_expr_body/1","ref":"erl_syntax.html#maybe_match_expr_body/1"},{"type":"function","doc":"Returns the pattern subtree of a `maybe_expr` node.\n\n_See also: _`maybe_match_expr/2`.","title":"erl_syntax.maybe_match_expr_pattern/1","ref":"erl_syntax.html#maybe_match_expr_pattern/1"},{"type":"function","doc":"Creates a meta-representation of a syntax tree.\n\nThe result represents an Erlang expression \"`MetaTree`\" which, if\nevaluated, will yield a new syntax tree representing the same source\ncode text as `Tree` (although the actual data representation may be\ndifferent). The expression represented by `MetaTree` is\n_implementation independent_ with regard to the data structures used\nby the abstract syntax tree implementation. Comments attached to nodes\nof `Tree` will be preserved, but other attributes are lost.\n\nAny node in `Tree` whose node type is `variable` (see `type/1`), and whose list\nof annotations (see `get_ann/1`) contains the atom `meta_var`, will remain\nunchanged in the resulting tree, except that exactly one occurrence of\n`meta_var` is removed from its annotation list.\n\nThe main use of the function [`meta/1`](`meta/1`) is to transform a\ndata structure `Tree`, which represents a piece of program code, into\na form that is _representation independent when printed_. For example,\nsuppose `Tree` represents a variable named \"V\". Then (assuming a\nfunction `print/1` for printing syntax trees), evaluating\n`print(abstract(Tree))` — simply using `abstract/1` to map the actual\ndata structure onto a syntax tree representation — would output a\nstring that might look something like \"`{tree, variable, ..., \"V\",\n...}`\", which is obviously dependent on the implementation of the\nabstract syntax trees. This could, for example, be useful for caching\na syntax tree in a file. However, in some situations like in a program\ngenerator generator (with two \"generator\"), it may be\nunacceptable. Using `print(meta(Tree))` instead would output a\n_representation independent_ syntax tree generating expression; in the\nabove case, something like \"`erl_syntax:variable(\"V\")`\".\n\n_See also: _`abstract/1`, `get_ann/1`, `type/1`.","title":"erl_syntax.meta/1","ref":"erl_syntax.html#meta/1"},{"type":"function","doc":"Creates an abstract module qualifier.\n\nThe result represents \"`Module:Body`\".\n\n_See also: _`module_qualifier_argument/1`, `module_qualifier_body/1`.","title":"erl_syntax.module_qualifier/2","ref":"erl_syntax.html#module_qualifier/2"},{"type":"function","doc":"Returns the argument (the module) subtree of a `module_qualifier` node.\n\n_See also: _`module_qualifier/2`.","title":"erl_syntax.module_qualifier_argument/1","ref":"erl_syntax.html#module_qualifier_argument/1"},{"type":"function","doc":"Returns the body subtree of a `module_qualifier` node.\n\n_See also: _`module_qualifier/2`.","title":"erl_syntax.module_qualifier_body/1","ref":"erl_syntax.html#module_qualifier_body/1"},{"type":"function","doc":"Creates an abstract named fun-expression.\n\nIf `Clauses` is `[C1, ..., Cn]`, the result represents \"`fun\nName C1; ...; Name Cn end`\". More exactly, if each `Ci`\nrepresents \"`(Pi1, ..., Pim) Gi -> Bi`\", then the result\nrepresents \"`fun Name(P11, ..., P1m) G1 -> B1; ...;\nName(Pn1, ..., Pnm) Gn -> Bn end`\".\n\n_See also: _`named_fun_expr_arity/1`, `named_fun_expr_clauses/1`,\n`named_fun_expr_name/1`.","title":"erl_syntax.named_fun_expr/2","ref":"erl_syntax.html#named_fun_expr/2"},{"type":"function","doc":"Returns the arity of a `named_fun_expr` node.\n\nThe result is the number of parameter patterns in the first clause of\nthe named fun-expression; subsequent clauses are ignored.\n\nAn exception is thrown if\n[`named_fun_expr_clauses(Node)`](`named_fun_expr_clauses/1`) returns an empty\nlist, or if the first element of that list is not a syntax tree `C` of type\n`clause` such that [`clause_patterns(C)`](`clause_patterns/1`) is a nonempty\nlist.\n\n_See also: _`clause/3`, `clause_patterns/1`, `named_fun_expr/2`,\n`named_fun_expr_clauses/1`.","title":"erl_syntax.named_fun_expr_arity/1","ref":"erl_syntax.html#named_fun_expr_arity/1"},{"type":"function","doc":"Returns the list of clause subtrees of a `named_fun_expr` node.\n\n_See also: _`named_fun_expr/2`.","title":"erl_syntax.named_fun_expr_clauses/1","ref":"erl_syntax.html#named_fun_expr_clauses/1"},{"type":"function","doc":"Returns the name subtree of a `named_fun_expr` node.\n\n_See also: _`named_fun_expr/2`.","title":"erl_syntax.named_fun_expr_name/1","ref":"erl_syntax.html#named_fun_expr_name/1"},{"type":"function","doc":"Expands an abstract list skeleton to its most explicit form.\n\nIf `Node` represents \"`[E1, ..., En | Tail]`\", the result\nrepresents \"`[E1 | ... [En | Tail1] ... ]`\", where `Tail1` is\nthe result of [`normalize_list(Tail)`](`normalize_list/1`). If `Node`\nrepresents \"`[E1, ..., En]`\", the result simply represents \"`[E1\n| ... [En | []] ... ]`\". If `Node` does not represent a list\nskeleton, `Node` itself is returned.\n\n_See also: _`compact_list/1`, `list/2`.","title":"erl_syntax.normalize_list/1","ref":"erl_syntax.html#normalize_list/1"},{"type":"function","doc":"Creates an abstract operator.\n\nThe name of the operator is the character sequence represented by\n`Name`. This is analogous to the print name of an atom, but an\noperator is never written within single-quotes; for example, the\nresult of [`operator('++')`](`operator/1`) represents \"`++`\" rather\nthan \"`'++'`\".\n\n_See also: _`atom/1`, `operator_literal/1`, `operator_name/1`.","title":"erl_syntax.operator/1","ref":"erl_syntax.html#operator/1"},{"type":"function","doc":"Returns the literal string represented by an `operator` node.\n\nThis is simply the operator name as a string.\n\n_See also: _`operator/1`.","title":"erl_syntax.operator_literal/1","ref":"erl_syntax.html#operator_literal/1"},{"type":"function","doc":"Returns the name of an `operator` node.\n\nNote that the name is returned as an atom.\n\n_See also: _`operator/1`.","title":"erl_syntax.operator_name/1","ref":"erl_syntax.html#operator_name/1"},{"type":"function","doc":"Creates an abstract parenthesised expression.\n\nThe result represents \"`(Body)`\", independently of the context.\n\n_See also: _`parentheses_body/1`.","title":"erl_syntax.parentheses/1","ref":"erl_syntax.html#parentheses/1"},{"type":"function","doc":"Returns the body subtree of a `parentheses` node.\n\n_See also: _`parentheses/1`.","title":"erl_syntax.parentheses_body/1","ref":"erl_syntax.html#parentheses_body/1"},{"type":"function","doc":"Creates an abstract prefix operator expression.\n\nThe result represents \"`Operator Argument`\".\n\n_See also: _`infix_expr/3`, `prefix_expr_argument/1`, `prefix_expr_operator/1`.","title":"erl_syntax.prefix_expr/2","ref":"erl_syntax.html#prefix_expr/2"},{"type":"function","doc":"Returns the argument subtree of a `prefix_expr` node.\n\n_See also: _`prefix_expr/2`.","title":"erl_syntax.prefix_expr_argument/1","ref":"erl_syntax.html#prefix_expr_argument/1"},{"type":"function","doc":"Returns the operator subtree of a `prefix_expr` node.\n\n_See also: _`prefix_expr/2`.","title":"erl_syntax.prefix_expr_operator/1","ref":"erl_syntax.html#prefix_expr_operator/1"},{"type":"function","doc":"","title":"erl_syntax.receive_expr/1","ref":"erl_syntax.html#receive_expr/1"},{"type":"function","doc":"Creates an abstract receive-expression.\n\nIf `Timeout` is `none`, the result represents \"`receive C1; ...;\nCn end`\" (the `Action` argument is ignored). Otherwise, if\n`Clauses` is `[C1, ..., Cn]` and `Action` is `[A1, ..., Am]`, the\nresult represents \"`receive C1; ...; Cn after Timeout -> A1,\n..., Am end`\". More exactly, if each `Ci` represents \"`(Pi) Gi\n-> Bi`\", then the result represents \"`receive P1 G1 -> B1; ...;\nPn Gn -> Bn ... end`\".\n\nNote that in Erlang, a receive-expression must have at least one clause if no\ntimeout part is specified.\n\n_See also: _`case_expr/2`, `clause/3`, `receive_expr/1`,\n`receive_expr_action/1`, `receive_expr_clauses/1`, `receive_expr_timeout/1`.","title":"erl_syntax.receive_expr/3","ref":"erl_syntax.html#receive_expr/3"},{"type":"function","doc":"Returns the list of action body subtrees of a `receive_expr` node.\n\nIf `Node` represents \"`receive C1; ...; Cn end`\", this is the\nempty list.\n\n_See also: _`receive_expr/3`.","title":"erl_syntax.receive_expr_action/1","ref":"erl_syntax.html#receive_expr_action/1"},{"type":"function","doc":"Returns the list of clause subtrees of a `receive_expr` node.\n\n_See also: _`receive_expr/3`.","title":"erl_syntax.receive_expr_clauses/1","ref":"erl_syntax.html#receive_expr_clauses/1"},{"type":"function","doc":"Returns the timeout subtree of a `receive_expr` node, if any.\n\nIf `Node` represents \"`receive C1; ...; Cn end`\", `none` is\nreturned. Otherwise, if `Node` represents \"`receive C1; ...; Cn\nafter Timeout -> ... end`\", `Timeout` is returned.\n\n_See also: _`receive_expr/3`.","title":"erl_syntax.receive_expr_timeout/1","ref":"erl_syntax.html#receive_expr_timeout/1"},{"type":"function","doc":"Creates an abstract record field access expression.\n\nThe result represents \"`Argument#Type.Field`\".\n\n_See also: _`record_access_argument/1`, `record_access_field/1`,\n`record_access_type/1`, `record_expr/3`.","title":"erl_syntax.record_access/3","ref":"erl_syntax.html#record_access/3"},{"type":"function","doc":"Returns the argument subtree of a `record_access` node.\n\n_See also: _`record_access/3`.","title":"erl_syntax.record_access_argument/1","ref":"erl_syntax.html#record_access_argument/1"},{"type":"function","doc":"Returns the field subtree of a `record_access` node.\n\n_See also: _`record_access/3`.","title":"erl_syntax.record_access_field/1","ref":"erl_syntax.html#record_access_field/1"},{"type":"function","doc":"Returns the type subtree of a `record_access` node.\n\n_See also: _`record_access/3`.","title":"erl_syntax.record_access_type/1","ref":"erl_syntax.html#record_access_type/1"},{"type":"function","doc":"","title":"erl_syntax.record_expr/2","ref":"erl_syntax.html#record_expr/2"},{"type":"function","doc":"Creates an abstract record expression.\n\nIf `Fields` is `[F1, ..., Fn]`, then if `Argument` is `none`, the\nresult represents \"`#Type{F1, ..., Fn}`\", otherwise it\nrepresents \"`Argument#Type{F1, ..., Fn}`\".\n\n_See also: _`record_access/3`, `record_expr/2`, `record_expr_argument/1`,\n`record_expr_fields/1`, `record_expr_type/1`, `record_field/2`,\n`record_index_expr/2`.","title":"erl_syntax.record_expr/3","ref":"erl_syntax.html#record_expr/3"},{"type":"function","doc":"Returns the argument subtree of a `record_expr` node, if any.\n\nIf `Node` represents \"`#Type{...}`\", `none` is returned. Otherwise,\nif `Node` represents \"`Argument#Type{...}`\", `Argument` is\nreturned.\n\n_See also: _`record_expr/3`.","title":"erl_syntax.record_expr_argument/1","ref":"erl_syntax.html#record_expr_argument/1"},{"type":"function","doc":"Returns the list of field subtrees of a `record_expr` node.\n\n_See also: _`record_expr/3`.","title":"erl_syntax.record_expr_fields/1","ref":"erl_syntax.html#record_expr_fields/1"},{"type":"function","doc":"Returns the type subtree of a `record_expr` node.\n\n_See also: _`record_expr/3`.","title":"erl_syntax.record_expr_type/1","ref":"erl_syntax.html#record_expr_type/1"},{"type":"function","doc":"","title":"erl_syntax.record_field/1","ref":"erl_syntax.html#record_field/1"},{"type":"function","doc":"Creates an abstract record field specification.\n\nIf `Value` is `none`, the result represents simply \"`Name`\",\notherwise it represents \"`Name = Value`\".\n\n_See also: _`record_expr/3`, `record_field_name/1`, `record_field_value/1`.","title":"erl_syntax.record_field/2","ref":"erl_syntax.html#record_field/2"},{"type":"function","doc":"Returns the name subtree of a `record_field` node.\n\n_See also: _`record_field/2`.","title":"erl_syntax.record_field_name/1","ref":"erl_syntax.html#record_field_name/1"},{"type":"function","doc":"Returns the value subtree of a `record_field` node, if any.\n\nIf `Node` represents \"`Name`\", `none` is returned. Otherwise, if\n`Node` represents \"`Name = Value`\", `Value` is returned.\n\n_See also: _`record_field/2`.","title":"erl_syntax.record_field_value/1","ref":"erl_syntax.html#record_field_value/1"},{"type":"function","doc":"Creates an abstract record field index expression. The result represents\n\"`#Type.Field`\".\n\n> #### Note {: .info }\n>\n> The function name `record_index/2` is reserved by the Erlang compiler,\n> which is why that name could not be used for this constructor.\n\n_See also: _`record_expr/3`, `record_index_expr_field/1`,\n`record_index_expr_type/1`.","title":"erl_syntax.record_index_expr/2","ref":"erl_syntax.html#record_index_expr/2"},{"type":"function","doc":"Returns the field subtree of a `record_index_expr` node.\n\n_See also: _`record_index_expr/2`.","title":"erl_syntax.record_index_expr_field/1","ref":"erl_syntax.html#record_index_expr_field/1"},{"type":"function","doc":"Returns the type subtree of a `record_index_expr` node.\n\n_See also: _`record_index_expr/2`.","title":"erl_syntax.record_index_expr_type/1","ref":"erl_syntax.html#record_index_expr_type/1"},{"type":"function","doc":"Creates an abstract record type.\n\nIf `Fields` is `[F1, ..., Fn]`, the result represents \"`#Name{F1,\n..., Fn}`\".\n\n_See also: _`record_type_fields/1`, `record_type_name/1`.","title":"erl_syntax.record_type/2","ref":"erl_syntax.html#record_type/2"},{"type":"function","doc":"Creates an abstract record type field.\n\nThe result represents \"`Name :: Type`\".\n\n_See also: _`record_type_field_name/1`, `record_type_field_type/1`.","title":"erl_syntax.record_type_field/2","ref":"erl_syntax.html#record_type_field/2"},{"type":"function","doc":"Returns the name subtree of a `record_type_field` node.\n\n_See also: _`record_type_field/2`.","title":"erl_syntax.record_type_field_name/1","ref":"erl_syntax.html#record_type_field_name/1"},{"type":"function","doc":"Returns the type subtree of a `record_type_field` node.\n\n_See also: _`record_type_field/2`.","title":"erl_syntax.record_type_field_type/1","ref":"erl_syntax.html#record_type_field_type/1"},{"type":"function","doc":"Returns the fields subtree of a `record_type` node.\n\n_See also: _`record_type/2`.","title":"erl_syntax.record_type_fields/1","ref":"erl_syntax.html#record_type_fields/1"},{"type":"function","doc":"Returns the name subtree of a `record_type` node.\n\n_See also: _`record_type/2`.","title":"erl_syntax.record_type_name/1","ref":"erl_syntax.html#record_type_name/1"},{"type":"function","doc":"Clears the associated comments of `Node`.\n\nNote: This is equivalent to\n[`set_precomments(set_postcomments(Node, []), [])`](`set_precomments/2`), but\npotentially more efficient.\n\n_See also: _`set_postcomments/2`, `set_precomments/2`.","title":"erl_syntax.remove_comments/1","ref":"erl_syntax.html#remove_comments/1"},{"type":"function","doc":"Returns an `m:erl_parse`-compatible representation of a syntax tree, if possible.\n\nIf `Tree` represents a well-formed Erlang program or expression, the conversion\nshould work without problems. Typically, `is_tree/1` yields `true` if conversion\nfailed (that is, the result is still an abstract syntax tree), and `false`\notherwise.\n\nThe `is_tree/1` test is not completely foolproof. For a few special\nnode types (for example `arity_qualifier`), if such a node occurs in a\ncontext where it is not expected, it will be left unchanged as a\nnon-reverted subtree of the result. This can only happen if `Tree`\ndoes not actually represent legal Erlang code.\n\n_See also: _[//stdlib/erl_parse](`m:erl_parse`), `revert_forms/1`.","title":"erl_syntax.revert/1","ref":"erl_syntax.html#revert/1"},{"type":"function","doc":"Reverts a sequence of Erlang source code forms.\n\nThe sequence can be given either as a `form_list` syntax tree\n(possibly nested), or as a list of \"program form\" syntax trees. If\nsuccessful, the corresponding flat list of `m:erl_parse`-compatible\nsyntax trees is returned (see `revert/1`). If some program form could\nnot be reverted, `{error, Form}` is thrown. Standalone comments in the\nform sequence are discarded.\n\n_See also: _`form_list/1`, `is_form/1`, `revert/1`.","title":"erl_syntax.revert_forms/1","ref":"erl_syntax.html#revert_forms/1"},{"type":"function","doc":"Sets the list of user annotations of `Node` to `Annotations`.\n\n_See also: _`add_ann/2`, `copy_ann/2`, `get_ann/1`.","title":"erl_syntax.set_ann/2","ref":"erl_syntax.html#set_ann/2"},{"type":"function","doc":"Sets the attributes of `Node` to `Attributes`.\n\n_See also: _`copy_attrs/2`, `get_attrs/1`.","title":"erl_syntax.set_attrs/2","ref":"erl_syntax.html#set_attrs/2"},{"type":"function","doc":"Sets the position information of `Node` to `Pos`.\n\n_See also: _`copy_pos/2`, `get_pos/1`.","title":"erl_syntax.set_pos/2","ref":"erl_syntax.html#set_pos/2"},{"type":"function","doc":"Sets the post-comments of `Node` to `Comments`.\n\n`Comments` should be a possibly empty list of abstract comments, in\ntop-down textual order\n\n_See also: _`add_postcomments/2`, `comment/2`, `copy_comments/2`,\n`get_postcomments/1`, `join_comments/2`, `remove_comments/1`,\n`set_precomments/2`.","title":"erl_syntax.set_postcomments/2","ref":"erl_syntax.html#set_postcomments/2"},{"type":"function","doc":"Sets the pre-comments of `Node` to `Comments`.\n\n`Comments` should be a possibly empty list of abstract comments, in\ntop-down textual order.\n\n_See also: _`add_precomments/2`, `comment/2`, `copy_comments/2`,\n`get_precomments/1`, `join_comments/2`, `remove_comments/1`,\n`set_postcomments/2`.","title":"erl_syntax.set_precomments/2","ref":"erl_syntax.html#set_precomments/2"},{"type":"function","doc":"Creates an abstract size qualifier.\n\nThe result represents \"`Body:Size`\".\n\n_See also: _`size_qualifier_argument/1`, `size_qualifier_body/1`.","title":"erl_syntax.size_qualifier/2","ref":"erl_syntax.html#size_qualifier/2"},{"type":"function","doc":"Returns the argument subtree (the size) of a `size_qualifier` node.\n\n_See also: _`size_qualifier/2`.","title":"erl_syntax.size_qualifier_argument/1","ref":"erl_syntax.html#size_qualifier_argument/1"},{"type":"function","doc":"Returns the body subtree of a `size_qualifier` node.\n\n_See also: _`size_qualifier/2`.","title":"erl_syntax.size_qualifier_body/1","ref":"erl_syntax.html#size_qualifier_body/1"},{"type":"function","doc":"Creates an abstract strict binary_generator.\n\nThe result represents \"`*Pattern*<:- *Body*`\".\n\n_See also: _`binary_comp/2`, `strict_binary_generator_body/1`,\n`strict_binary_generator_pattern/1`, `list_comp/2`.","title":"erl_syntax.strict_binary_generator/2","ref":"erl_syntax.html#strict_binary_generator/2"},{"type":"function","doc":"Returns the body subtree of a `generator` node.\n\n_See also: _`strict_binary_generator/2`.","title":"erl_syntax.strict_binary_generator_body/1","ref":"erl_syntax.html#strict_binary_generator_body/1"},{"type":"function","doc":"Returns the pattern subtree of a `generator` node.\n\n_See also: _`strict_binary_generator/2`.","title":"erl_syntax.strict_binary_generator_pattern/1","ref":"erl_syntax.html#strict_binary_generator_pattern/1"},{"type":"function","doc":"Creates an abstract strict list generator.\n\nThe result represents \"`*Pattern*<:- *Body*`\".\n\n_See also: _`binary_comp/2`, `strict_generator_body/1`,\n`strict_generator_pattern/1`, `list_comp/2`.","title":"erl_syntax.strict_generator/2","ref":"erl_syntax.html#strict_generator/2"},{"type":"function","doc":"Returns the body subtree of a `generator` node.\n\n_See also: _`strict_generator/2`.","title":"erl_syntax.strict_generator_body/1","ref":"erl_syntax.html#strict_generator_body/1"},{"type":"function","doc":"Returns the pattern subtree of a `generator` node.\n\n_See also: _`strict_generator/2`.","title":"erl_syntax.strict_generator_pattern/1","ref":"erl_syntax.html#strict_generator_pattern/1"},{"type":"function","doc":"Creates an abstract strict map_generator. The result represents\n\"`*Pattern*<- *Body*`\".\n\n_See also: _`list_comp/2`, `map_comp/2`,\n`strict_map_generator_body/1`,\n`strict_map_generator_pattern/1`.","title":"erl_syntax.strict_map_generator/2","ref":"erl_syntax.html#strict_map_generator/2"},{"type":"function","doc":"Returns the body subtree of a `generator` node.\n\n_See also: _`strict_map_generator/2`.","title":"erl_syntax.strict_map_generator_body/1","ref":"erl_syntax.html#strict_map_generator_body/1"},{"type":"function","doc":"Returns the pattern subtree of a `generator` node.\n\n_See also: _`strict_map_generator/2`.","title":"erl_syntax.strict_map_generator_pattern/1","ref":"erl_syntax.html#strict_map_generator_pattern/1"},{"type":"function","doc":"Creates an abstract string literal.\n\nThe result represents `\"Text\"` (including the surrounding\ndouble-quotes), where `Text` corresponds to the sequence of characters\nin `Value`, but not representing a _specific_ string literal.\n\nFor example, the result of [`string(\"x\\ny\")`](`string/1`) represents any and all\nof `\"x\\ny\"`, `\"x\\12y\"`, `\"x\\012y\"` and `\"x\\^Jy\"`; see `char/1`.\n\n_See also: _`char/1`, `is_string/2`, `string_literal/1`, `string_literal/2`,\n`string_value/1`.","title":"erl_syntax.string/1","ref":"erl_syntax.html#string/1"},{"type":"function","doc":"Returns the literal string represented by a `string` node.\n\nThis includes surrounding double-quote characters. Characters beyond\n255 will be escaped.\n\n_See also: _`string/1`.","title":"erl_syntax.string_literal/1","ref":"erl_syntax.html#string_literal/1"},{"type":"function","doc":"Returns the literal string represented by a `string` node.\n\nThis includes surrounding double-quote characters. Depending on the\nencoding characters beyond 255 will be escaped (`latin1`) or copied as\nis (`utf8`).\n\n_See also: _`string/1`.","title":"erl_syntax.string_literal/2","ref":"erl_syntax.html#string_literal/2"},{"type":"function","doc":"Returns the value represented by a `string` node.\n\n_See also: _`string/1`.","title":"erl_syntax.string_value/1","ref":"erl_syntax.html#string_value/1"},{"type":"function","doc":"Returns the grouped list of all subtrees of a syntax tree.\n\nIf `Node` is a leaf node (see `is_leaf/1`), this is the empty list,\notherwise the result is always a nonempty list, containing the lists\nof subtrees of `Node`, in left-to-right order as they occur in the\nprinted program text, and grouped by category. Often, each group\ncontains only a single subtree.\n\nDepending on the type of `Node`, the size of some groups may be\nvariable (for example, the group consisting of all the elements of a\ntuple), while others always contain the same number of elements —\nusually exactly one (for example, the group containing the argument\nexpression of a case-expression). Note, however, that the exact\nstructure of the returned list (for a given node type) should in\ngeneral not be depended upon, since it might be subject to change\nwithout notice.\n\nThe function `subtrees/1` and the constructor functions `make_tree/2` and\n`update_tree/2` can be a great help if one wants to traverse a syntax tree,\nvisiting all its subtrees, but treat nodes of the tree in a uniform way in most\nor all cases. Using these functions makes this simple, and also assures that\nyour code is not overly sensitive to extensions of the syntax tree data type,\nbecause any node types not explicitly handled by your code can be left to a\ndefault case.\n\nFor example:\n\n```text\n postorder(F, Tree) ->\n F(case subtrees(Tree) of\n [] -> Tree;\n List -> update_tree(Tree,\n [[postorder(F, Subtree)\n || Subtree <- Group]\n || Group <- List])\n end).\n```\n\nmaps the function `F` on `Tree` and all its subtrees, doing a post-order\ntraversal of the syntax tree. (Note the use of `update_tree/2` to preserve node\nattributes.) For a simple function like:\n\n```text\n f(Node) ->\n case type(Node) of\n atom -> atom(\"a_\" ++ atom_name(Node));\n _ -> Node\n end.\n```\n\nthe call `postorder(fun f/1, Tree)` will yield a new representation of `Tree` in\nwhich all atom names have been extended with the prefix \"a_\", but nothing else\n(including comments, annotations, and line numbers) has been changed.\n\n_See also: _`copy_attrs/2`, `is_leaf/1`, `make_tree/2`, `type/1`.","title":"erl_syntax.subtrees/1","ref":"erl_syntax.html#subtrees/1"},{"type":"function","doc":"Creates an abstract piece of source code text.\n\nThe result represents exactly the sequence of characters in\n`String`. This is useful in cases where one wants full control of the\nresulting output, such as the appearance of floating-point numbers or\nmacro definitions.\n\n_See also: _`text_string/1`.","title":"erl_syntax.text/1","ref":"erl_syntax.html#text/1"},{"type":"function","doc":"Returns the character sequence represented by a `text` node.\n\n_See also: _`text/1`.","title":"erl_syntax.text_string/1","ref":"erl_syntax.html#text_string/1"},{"type":"function","doc":"","title":"erl_syntax.tree/1","ref":"erl_syntax.html#tree/1"},{"type":"function","doc":"**For special purposes only**. Creates an abstract syntax tree node with type tag\n`Type` and associated data `Data`.\n\nThis function and the related `is_tree/1` and `data/1` provide a uniform way to\nextend the set of `erl_parse` node types. The associated data is any term, whose\nformat may depend on the type tag.\n\n> #### Notes {: .info }\n>\n> - Any nodes created outside of this module must have type tags distinct from\n> those currently defined by this module; see `type/1` for a complete list.\n>\n> - The type tag of a syntax tree node may also be used as a primary tag by the\n> `erl_parse` representation; in that case, the selector functions for that node\n> type _must_ handle both the abstract syntax tree and the `m:erl_parse` form. The\n> function [`type(T)`](`type/1`) should return the correct type tag regardless\n> of the representation of `T`, so that the user sees no difference between\n> `erl_syntax` and `erl_parse` nodes.\n\n_See also: _`data/1`, `is_tree/1`, `type/1`.","title":"erl_syntax.tree/2","ref":"erl_syntax.html#tree/2"},{"type":"function","doc":"","title":"erl_syntax.try_after_expr/2","ref":"erl_syntax.html#try_after_expr/2"},{"type":"function","doc":"","title":"erl_syntax.try_expr/2","ref":"erl_syntax.html#try_expr/2"},{"type":"function","doc":"","title":"erl_syntax.try_expr/3","ref":"erl_syntax.html#try_expr/3"},{"type":"function","doc":"Creates an abstract try-expression.\n\nIf `Body` is `[B1, ..., Bn]`, `Clauses` is `[C1, ..., Cj]`, `Handlers`\nis `[H1, ..., Hk]`, and `After` is `[A1, ..., Am]`, the result\nrepresents \"`try B1, ..., Bn of C1; ...; Cj catch H1; ...; Hk after\nA1, ..., Am end`\". More exactly, if each `Ci` represents \"`(CPi) CGi\n-> CBi`\", and each `Hi` represents \"`(HPi) HGi -> HBi`\", then the\nresult represents \"`try B1, ..., Bn of CP1 CG1 -> CB1; ...; CPj CGj ->\nCBj catch HP1 HG1 -> HB1; ...; HPk HGk -> HBk after A1, ..., Am end`\";\nsee `case_expr/2`. If `Clauses` is the empty list, the `of ...`\nsection is left out. If `After` is the empty list, the `after ...`\nsection is left out. If `Handlers` is the empty list, and `After` is\nnonempty, the `catch ...` section is left out.\n\n_See also: _`case_expr/2`, `class_qualifier/2`, `clause/3`, `try_after_expr/2`,\n`try_expr/2`, `try_expr/3`, `try_expr_after/1`, `try_expr_body/1`,\n`try_expr_clauses/1`, `try_expr_handlers/1`.","title":"erl_syntax.try_expr/4","ref":"erl_syntax.html#try_expr/4"},{"type":"function","doc":"Returns the list of \"after\" subtrees of a `try_expr` node.\n\n_See also: _`try_expr/4`.","title":"erl_syntax.try_expr_after/1","ref":"erl_syntax.html#try_expr_after/1"},{"type":"function","doc":"Returns the list of body subtrees of a `try_expr` node.\n\n_See also: _`try_expr/4`.","title":"erl_syntax.try_expr_body/1","ref":"erl_syntax.html#try_expr_body/1"},{"type":"function","doc":"Returns the list of case-clause subtrees of a `try_expr` node. If `Node`\nrepresents \"`try Body catch H1; ...; Hn end`\", the result is the empty\nlist.\n\n_See also: _`try_expr/4`.","title":"erl_syntax.try_expr_clauses/1","ref":"erl_syntax.html#try_expr_clauses/1"},{"type":"function","doc":"Returns the list of handler-clause subtrees of a `try_expr` node.\n\n_See also: _`try_expr/4`.","title":"erl_syntax.try_expr_handlers/1","ref":"erl_syntax.html#try_expr_handlers/1"},{"type":"function","doc":"Creates an abstract tuple.\n\nIf `Elements` is `[X1, ..., Xn]`, the result represents \"`{X1, ...,\nXn}`\".\n\n> #### Note {: .info }\n>\n> The Erlang language has distinct 1-tuples, meaning `{X}` is always distinct\n> from `X` itself.\n\n_See also: _`tuple_elements/1`, `tuple_size/1`.","title":"erl_syntax.tuple/1","ref":"erl_syntax.html#tuple/1"},{"type":"function","doc":"Returns the list of element subtrees of a `tuple` node.\n\n_See also: _`tuple/1`.","title":"erl_syntax.tuple_elements/1","ref":"erl_syntax.html#tuple_elements/1"},{"type":"function","doc":"Returns the number of elements of a `tuple` node.\n\n> #### Note {: .info }\n>\n> This is equivalent to [`length(tuple_elements(Node))`](`length/1`),\n> but potentially more efficient.\n\n_See also: _`tuple/1`, `tuple_elements/1`.","title":"erl_syntax.tuple_size/1","ref":"erl_syntax.html#tuple_size/1"},{"type":"function","doc":"","title":"erl_syntax.tuple_type/0","ref":"erl_syntax.html#tuple_type/0"},{"type":"function","doc":"Creates an abstract type tuple.\n\nIf `Elements` is `[T1, ..., Tn]`, the result represents \"`{T1, ...,\nTn}`\"; otherwise, if `Elements` is `any_size`, it represents\n\"`t:tuple/0`\".\n\n_See also: _`tuple_type_elements/1`.","title":"erl_syntax.tuple_type/1","ref":"erl_syntax.html#tuple_type/1"},{"type":"function","doc":"Returns the list of type element subtrees of a `tuple_type` node.\n\nIf `Node` represents \"`t:tuple/0`\", `any_size` is returned; otherwise,\nif `Node` represents \"`{T1, ..., Tn}`\", `[T1, ..., Tn]` is returned.\n\n_See also: _`tuple_type/0`, `tuple_type/1`.","title":"erl_syntax.tuple_type_elements/1","ref":"erl_syntax.html#tuple_type_elements/1"},{"type":"function","doc":"Returns the type tag of `Node`.\n\nIf `Node` does not represent a syntax tree, evaluation fails with\nreason `badarg`. Node types currently defined by this module are:\n\n* `application`\n* `annotated_type`\n* `arity_qualifier`\n* `atom`\n* `attribute`\n* `binary`\n* `binary_field`\n* `bitstring_type`\n* `block_expr`\n* `case_expr`\n* `catch_expr`\n* `char`\n* `class_qualifier`\n* `clause`\n* `comment`\n* `conjunction`\n* `constrained_function_type`\n* `constraint`\n* `disjunction`\n* `else_expr`\n* `eof_marker`\n* `error_marker`\n* `float`\n* `form_list`\n* `fun_expr`\n* `fun_type`\n* `function`\n* `function_type`\n* `generator`\n* `if_expr`\n* `implicit_fun`\n* `infix_expr`\n* `integer`\n* `integer_range_type`\n* `list`\n* `list_comp`\n* `macro`\n* `map_expr`\n* `map_field_assoc`\n* `map_field_exact`\n* `map_type`\n* `map_type_assoc`\n* `map_type_exact`\n* `match_expr`\n* `maybe_expr`\n* `maybe_match_expr`\n* `module_qualifier`\n* `named_fun_expr`\n* `nil`\n* `operator`\n* `parentheses`\n* `prefix_expr`\n* `receive_expr`\n* `record_access`\n* `record_expr`\n* `record_field`\n* `record_index_expr`\n* `record_type`\n* `record_type_field`\n* `size_qualifier`\n* `string`\n* `text`\n* `try_expr`\n* `tuple`\n* `tuple_type`\n* `typed_record_field`\n* `type_application`\n* `type_union`\n* `underscore`\n* `user_type_application`\n* `variable`\n* `warning_marker`\n* `zip_generator`\n\nThe user may (for special purposes) create additional nodes with other type\ntags, using the `tree/2` function.\n\nNote: The primary constructor functions for a node type should always have the\nsame name as the node type itself.\n\n_See also: _`annotated_type/2`, `application/3`, `arity_qualifier/2`, `atom/1`,\n`attribute/2`, `binary/1`, `binary_field/2`, `bitstring_type/2`, `block_expr/1`,\n`case_expr/2`, `catch_expr/1`, `char/1`, `class_qualifier/2`, `clause/3`,\n`comment/2`, `conjunction/1`, `constrained_function_type/2`, `constraint/2`,\n`disjunction/1`, `else_expr/1`, `eof_marker/0`, `error_marker/1`, `float/1`,\n`form_list/1`, `fun_expr/1`, `fun_type/0`, `function/2`, `function_type/1`,\n`function_type/2`, `generator/2`, `if_expr/1`, `implicit_fun/2`, `infix_expr/3`,\n`integer/1`, `integer_range_type/2`, `list/2`, `list_comp/2`, `macro/2`,\n`map_expr/2`, `map_field_assoc/2`, `map_field_exact/2`, `map_type/0`,\n`map_type/1`, `map_type_assoc/2`, `map_type_exact/2`, `match_expr/2`,\n`maybe_expr/1`, `maybe_expr/2`, `maybe_match_expr/2`, `module_qualifier/2`,\n`named_fun_expr/2`, `nil/0`, `operator/1`, `parentheses/1`, `prefix_expr/2`,\n`receive_expr/3`, `record_access/3`, `record_expr/2`, `record_field/2`,\n`record_index_expr/2`, `record_type/2`, `record_type_field/2`,\n`size_qualifier/2`, `string/1`, `text/1`, `tree/2`, `try_expr/3`, `tuple/1`,\n`tuple_type/0`, `tuple_type/1`, `type_application/2`, `type_union/1`,\n`typed_record_field/2`, `underscore/0`, `user_type_application/2`, `variable/1`,\n`warning_marker/1`,`zip_generator/1`.","title":"erl_syntax.type/1","ref":"erl_syntax.html#type/1"},{"type":"function","doc":"Creates an abstract type application expression.\n\nIf `Arguments` is `[T1, ..., Tn]`, the result represents\n\"`TypeName(T1, ...Tn)`\".\n\n_See also: _`type_application/3`, `type_application_arguments/1`,\n`type_application_name/1`, `user_type_application/2`.","title":"erl_syntax.type_application/2","ref":"erl_syntax.html#type_application/2"},{"type":"function","doc":"Creates an abstract type application expression.\n\nIf `Module` is `none`, this is call is equivalent to\n[`type_application(TypeName, Arguments)`](`type_application/2`),\notherwise it is equivalent to\n[`type_application(module_qualifier(Module, TypeName),\nArguments)`](`type_application/2`).\n\n(This is a utility function.)\n\n_See also: _`module_qualifier/2`, `type_application/2`.","title":"erl_syntax.type_application/3","ref":"erl_syntax.html#type_application/3"},{"type":"function","doc":"Returns the arguments subtrees of a `type_application` node.\n\n_See also: _`type_application/2`.","title":"erl_syntax.type_application_arguments/1","ref":"erl_syntax.html#type_application_arguments/1"},{"type":"function","doc":"Returns the type name subtree of a `type_application` node.\n\n_See also: _`type_application/2`.","title":"erl_syntax.type_application_name/1","ref":"erl_syntax.html#type_application_name/1"},{"type":"function","doc":"Creates an abstract type union.\n\nIf `Types` is `[T1, ..., Tn]`, the result represents \"`T1 | ... |\nTn`\".\n\n_See also: _`type_union_types/1`.","title":"erl_syntax.type_union/1","ref":"erl_syntax.html#type_union/1"},{"type":"function","doc":"Returns the list of type subtrees of a `type_union` node.\n\n_See also: _`type_union/1`.","title":"erl_syntax.type_union_types/1","ref":"erl_syntax.html#type_union_types/1"},{"type":"function","doc":"Creates an abstract typed record field specification.\n\nThe result represents \"`Field :: Type`\".\n\n_See also: _`typed_record_field_body/1`, `typed_record_field_type/1`.","title":"erl_syntax.typed_record_field/2","ref":"erl_syntax.html#typed_record_field/2"},{"type":"function","doc":"Returns the field subtree of a `typed_record_field` node.\n\n_See also: _`typed_record_field/2`.","title":"erl_syntax.typed_record_field_body/1","ref":"erl_syntax.html#typed_record_field_body/1"},{"type":"function","doc":"Returns the type subtree of a `typed_record_field` node.\n\n_See also: _`typed_record_field/2`.","title":"erl_syntax.typed_record_field_type/1","ref":"erl_syntax.html#typed_record_field_type/1"},{"type":"function","doc":"Creates an abstract universal pattern (\"`_`\").\n\nThe lexical representation is a single underscore character. Note that\nthis is _not_ a variable, lexically speaking.\n\n_See also: _`variable/1`.","title":"erl_syntax.underscore/0","ref":"erl_syntax.html#underscore/0"},{"type":"function","doc":"Creates a syntax tree with the same type and attributes as the given tree.\n\nThis is equivalent to [`copy_attrs(Node, make_tree(type(Node),\nGroups))`](`copy_attrs/2`).\n\n_See also: _`copy_attrs/2`, `make_tree/2`, `type/1`.","title":"erl_syntax.update_tree/2","ref":"erl_syntax.html#update_tree/2"},{"type":"function","doc":"Creates an abstract user type.\n\nIf `Arguments` is `[T1, ..., Tn]`, the result represents\n\"`TypeName(T1, ...Tn)`\".\n\n_See also: _`type_application/2`, `user_type_application_arguments/1`,\n`user_type_application_name/1`.","title":"erl_syntax.user_type_application/2","ref":"erl_syntax.html#user_type_application/2"},{"type":"function","doc":"Returns the arguments subtrees of a `user_type_application` node.\n\n_See also: _`user_type_application/2`.","title":"erl_syntax.user_type_application_arguments/1","ref":"erl_syntax.html#user_type_application_arguments/1"},{"type":"function","doc":"Returns the type name subtree of a `user_type_application` node.\n\n_See also: _`user_type_application/2`.","title":"erl_syntax.user_type_application_name/1","ref":"erl_syntax.html#user_type_application_name/1"},{"type":"function","doc":"Creates an abstract variable with the given name.\n\n`Name` may be any atom or string that represents a lexically valid\nvariable name, but _not_ a single underscore character; see\n`underscore/0`.\n\n> #### Note {: .info }\n>\n> No check is performed to verify whether the character sequence\n> represents a proper variable name, that is, whether its first character\n> is an uppercase Erlang character, or whether it contains illegal characters\n> such as control characters or whitespace.\n\n_See also: _`underscore/0`, `variable_literal/1`, `variable_name/1`.","title":"erl_syntax.variable/1","ref":"erl_syntax.html#variable/1"},{"type":"function","doc":"Returns the name of a `variable` node as a string.\n\n_See also: _`variable/1`.","title":"erl_syntax.variable_literal/1","ref":"erl_syntax.html#variable_literal/1"},{"type":"function","doc":"Returns the name of a `variable` node as an atom.\n\n_See also: _`variable/1`.","title":"erl_syntax.variable_name/1","ref":"erl_syntax.html#variable_name/1"},{"type":"function","doc":"Creates an abstract warning marker.\n\nThe result represents an occurrence of a possible problem in the\nsource code, with an associated Erlang I/O ErrorInfo structure given\nby `Error` (see module [`//stdlib/io`](`m:io`) for details). Warning\nmarkers are regarded as source code forms, but have no defined lexical\nform.\n\n> #### Note {: .info }\n>\n> This is supported only for backwards compatibility with existing parsers\n> and tools.\n\n_See also: _`eof_marker/0`, `error_marker/1`, `is_form/1`,\n`warning_marker_info/1`.","title":"erl_syntax.warning_marker/1","ref":"erl_syntax.html#warning_marker/1"},{"type":"function","doc":"Returns the ErrorInfo structure of a `warning_marker` node.\n\n_See also: _`warning_marker/1`.","title":"erl_syntax.warning_marker_info/1","ref":"erl_syntax.html#warning_marker_info/1"},{"type":"function","doc":"Creates an abstract zip_generator.\n\nThe result represents `G1 && ... Gn`, where each `G` is a generator.\n\n_See also: _`binary_comp/2`, `list_comp/2`, `map_comp/2`, `map_generator_body/1`,\n`map_generator_pattern/1`.","title":"erl_syntax.zip_generator/1","ref":"erl_syntax.html#zip_generator/1"},{"type":"function","doc":"Returns the body subtree of a `zip_generator` node.\n\n_See also: _`zip_generator/1`.","title":"erl_syntax.zip_generator_body/1","ref":"erl_syntax.html#zip_generator_body/1"},{"type":"type","doc":"","title":"erl_syntax.annotation_or_location/0","ref":"erl_syntax.html#t:annotation_or_location/0"},{"type":"type","doc":"","title":"erl_syntax.encoding/0","ref":"erl_syntax.html#t:encoding/0"},{"type":"type","doc":"","title":"erl_syntax.erl_parse/0","ref":"erl_syntax.html#t:erl_parse/0"},{"type":"type","doc":"","title":"erl_syntax.forms/0","ref":"erl_syntax.html#t:forms/0"},{"type":"type","doc":"","title":"erl_syntax.guard/0","ref":"erl_syntax.html#t:guard/0"},{"type":"type","doc":"","title":"erl_syntax.padding/0","ref":"erl_syntax.html#t:padding/0"},{"type":"type","doc":"","title":"erl_syntax.syntaxTree/0","ref":"erl_syntax.html#t:syntaxTree/0"},{"type":"type","doc":"","title":"erl_syntax.syntaxTreeAttributes/0","ref":"erl_syntax.html#t:syntaxTreeAttributes/0"},{"type":"type","doc":"","title":"erl_syntax.tree/0","ref":"erl_syntax.html#t:tree/0"},{"type":"type","doc":"","title":"erl_syntax.wrapper/0","ref":"erl_syntax.html#t:wrapper/0"},{"type":"module","doc":"Support library for abstract Erlang syntax trees.\n\nThis module contains utility functions for working with the abstract data type\ndefined in the module `m:erl_syntax`.","title":"erl_syntax_lib","ref":"erl_syntax_lib.html"},{"type":"function","doc":"Returns the name of a called function.\n\nThe result is a representation of the name of the applied function\n`F/A`, if `Node` represents a function application \"`F(X_1, ...,\nX_A)`\". If the function is not explicitly named (that is, `F` is given\nby some expression), only the arity `A` is returned.\n\nThe evaluation throws `syntax_error` if `Node` does not represent a well-formed\napplication expression.\n\n_See also: _`analyze_function_name/1`.","title":"erl_syntax_lib.analyze_application/1","ref":"erl_syntax_lib.html#analyze_application/1"},{"type":"function","doc":"Analyzes an attribute node.\n\nIf `Node` represents a preprocessor directive, the atom `preprocessor`\nis returned. Otherwise, if `Node` represents a module attribute\n\"`-Name...`\", a tuple `{Name, Info}` is returned, where `Info` depends\non `Name`, as follows:\n\n- **`{module, Info}`** - where `Info = analyze_module_attribute(Node)`.\n\n- **`{export, Info}`** - where `Info = analyze_export_attribute(Node)`.\n\n- **`{import, Info}`** - where `Info = analyze_import_attribute(Node)`.\n\n- **`{file, Info}`** - where `Info = analyze_file_attribute(Node)`.\n\n- **`{record, Info}`** - where `Info = analyze_record_attribute(Node)`.\n\n- **`{Name, Info}`** - where `{Name, Info} = analyze_wild_attribute(Node)`.\n\nThe evaluation throws `syntax_error` if `Node` does not represent a well-formed\nmodule attribute.\n\n_See also: _`analyze_export_attribute/1`, `analyze_file_attribute/1`,\n`analyze_import_attribute/1`, `analyze_module_attribute/1`,\n`analyze_record_attribute/1`, `analyze_wild_attribute/1`.","title":"erl_syntax_lib.analyze_attribute/1","ref":"erl_syntax_lib.html#analyze_attribute/1"},{"type":"function","doc":"Returns the list of function names declared by an export attribute.\n\nWe do not guarantee that each name occurs at most once in the\nlist. The order of listing is not defined.\n\nThe evaluation throws `syntax_error` if `Node` does not represent a well-formed\nexport attribute.\n\n_See also: _`analyze_attribute/1`.","title":"erl_syntax_lib.analyze_export_attribute/1","ref":"erl_syntax_lib.html#analyze_export_attribute/1"},{"type":"function","doc":"Returns the file name and line number of a `file` attribute.\n\nThe result is the pair `{File, Line}` if `Node` represents\n\"`-file(File, Line).`\".\n\nThe evaluation throws `syntax_error` if `Node` does not represent a well-formed\n`file` attribute.\n\n_See also: _`analyze_attribute/1`.","title":"erl_syntax_lib.analyze_file_attribute/1","ref":"erl_syntax_lib.html#analyze_file_attribute/1"},{"type":"function","doc":"Analyzes a \"source code form\" node.\n\nIf `Node` is a \"form\" type (see `erl_syntax:is_form/1`), the returned\nvalue is a tuple `{Type, Info}` where `Type` is the node type and\n`Info` depends on `Type`, as follows:\n\n- **`{attribute, Info}`** - where `Info = analyze_attribute(Node)`.\n\n- **`{error_marker, Info}`** - where\n `Info = erl_syntax:error_marker_info(Node)`.\n\n- **`{function, Info}`** - where `Info = analyze_function(Node)`.\n\n- **`{warning_marker, Info}`** - where\n `Info = erl_syntax:warning_marker_info(Node)`.\n\nFor other types of forms, only the node type is returned.\n\nThe evaluation throws `syntax_error` if `Node` is not well-formed.\n\n_See also: _`analyze_attribute/1`, `analyze_function/1`,\n`erl_syntax:error_marker_info/1`, `erl_syntax:is_form/1`,\n`erl_syntax:warning_marker_info/1`.","title":"erl_syntax_lib.analyze_form/1","ref":"erl_syntax_lib.html#analyze_form/1"},{"type":"function","doc":"Analyzes a sequence of \"program forms\".\n\nThe given `Forms` may be a single syntax tree of type `form_list`, or\na list of \"program form\" syntax trees. The returned value is a list of\npairs `{Key, Info}`, where each value of `Key` occurs at most once in\nthe list; the absence of a particular key indicates that there is no\nwell-defined value for that key.\n\nEach entry in the resulting list contains the following corresponding\ninformation about the program forms:\n\n- **`{attributes, Attributes}`**\n\n - `Attributes = [{atom(), term()}]`\n\n `Attributes` is a list of pairs representing the names and\n corresponding values of all so-called \"wild\" attributes (as, for\n example, \"`-compile(...)`\") occurring in `Forms` (see\n [`analyze_wild_attribute/1`](`analyze_wild_attribute/1`)). We do not\n guarantee that each name occurs at most once in the list. The order\n of listing is not defined.\n\n- **`{errors, Errors}`**\n\n - `Errors = [term()]`\n\n `Errors` is the list of error descriptors of all `error_marker` nodes that\n occur in `Forms`. The order of listing is not defined.\n\n- **`{exports, Exports}`**\n\n - `Exports = [FunctionName]`\n - `FunctionName = atom() | {atom(), integer()} | {ModuleName, FunctionName}`\n - `ModuleName = atom()`\n\n `Exports` is a list of representations of those function names that are listed\n by export declaration attributes in `Forms` (see\n [`analyze_export_attribute/1`](`analyze_export_attribute/1`)). We do not\n guarantee that each name occurs at most once in the list. The order of listing\n is not defined.\n\n- **`{functions, Functions}`**\n\n - `Functions = [{atom(), integer()}]`\n\n `Functions` is a list of the names of the functions that are defined in\n `Forms` (see [`analyze_function/1`](`analyze_function/1`)). We do not\n guarantee that each name occurs at most once in the list. The order of listing\n is not defined.\n\n- **`{imports, Imports}`**\n\n - `Imports = [{Module, Names}]`\n - `Module = atom()`\n - `Names = [FunctionName]`\n - `FunctionName = atom() | {atom(), integer()} | {ModuleName, FunctionName}`\n - `ModuleName = atom()`\n\n `Imports` is a list of pairs representing those module names and corresponding\n function names that are listed by import declaration attributes in `Forms`\n (see [`analyze_import_attribute/1`](`analyze_import_attribute/1`)), where each\n `Module` occurs at most once in `Imports`. We do not guarantee that each name\n occurs at most once in the lists of function names. The order of listing is\n not defined.\n\n- **`{module, ModuleName}`**\n\n - `ModuleName = atom()`\n\n `ModuleName` is the name declared by a module attribute in `Forms`. If no\n module name is defined in `Forms`, the result will contain no entry for the\n `module` key. If multiple module name declarations should occur, all but the\n first will be ignored.\n\n- **`{records, Records}`**\n\n - `Records = [{atom(), Fields}]`\n - `Fields = [{atom(), {Default, Type}}]`\n - `Default = none | syntaxTree()`\n - `Type = none | syntaxTree()`\n\n `Records` is a list of pairs representing the names and corresponding field\n declarations of all record declaration attributes occurring in `Forms`. For\n fields declared without a default value, the corresponding value for `Default`\n is the atom `none`. Similarly, for fields declared without a type, the\n corresponding value for `Type` is the atom `none` (see\n [`analyze_record_attribute/1`](`analyze_record_attribute/1`)). We do not\n guarantee that each record name occurs at most once in the list. The order of\n listing is not defined.\n\n- **`{warnings, Warnings}`**\n\n - `Warnings = [term()]`\n\n `Warnings` is the list of error descriptors of all `warning_marker` nodes that\n occur in `Forms`. The order of listing is not defined.\n\nThe evaluation throws `syntax_error` if an ill-formed Erlang construct is\nencountered.\n\n_See also: _`analyze_export_attribute/1`, `analyze_function/1`,\n`analyze_import_attribute/1`, `analyze_record_attribute/1`,\n`analyze_wild_attribute/1`, `erl_syntax:error_marker_info/1`,\n`erl_syntax:warning_marker_info/1`.","title":"erl_syntax_lib.analyze_forms/1","ref":"erl_syntax_lib.html#analyze_forms/1"},{"type":"function","doc":"Returns the name and arity of a function definition.\n\nThe result is a pair `{Name, A}` if `Node` represents a function\ndefinition \"`Name(P_1, ..., P_A) -> ...`\".\n\nThe evaluation throws `syntax_error` if `Node` does not represent a well-formed\nfunction definition.","title":"erl_syntax_lib.analyze_function/1","ref":"erl_syntax_lib.html#analyze_function/1"},{"type":"function","doc":"Returns the function name represented by a syntax tree.\n\nIf `Node` represents a function name, such as \"`foo/1`\" or\n\"`bloggs:fred/2`\", a uniform representation of that name is\nreturned. Different nestings of arity and module name qualifiers in\nthe syntax tree does not affect the result.\n\nThe evaluation throws `syntax_error` if `Node` does not represent a well-formed\nfunction name.","title":"erl_syntax_lib.analyze_function_name/1","ref":"erl_syntax_lib.html#analyze_function_name/1"},{"type":"function","doc":"Returns the name of an implicit fun expression \"`fun F`\".\n\nThe result is a representation of the function name `F`. (See\n[`analyze_function_name/1`](`analyze_function_name/1`).)\n\nThe evaluation throws `syntax_error` if `Node` does not represent a well-formed\nimplicit fun.\n\n_See also: _`analyze_function_name/1`.","title":"erl_syntax_lib.analyze_implicit_fun/1","ref":"erl_syntax_lib.html#analyze_implicit_fun/1"},{"type":"function","doc":"Returns the module name and (if present) list of function names declared by an\nimport attribute.\n\nThe returned value is an atom `Module` or a pair `{Module, Names}`,\nwhere `Names` is a list of function names declared as imported from\nthe module named by `Module`. We do not guarantee that each name\noccurs at most once in `Names`. The order of listing is not defined.\n\nThe evaluation throws `syntax_error` if `Node` does not represent a well-formed\nimport attribute.\n\n_See also: _`analyze_attribute/1`.","title":"erl_syntax_lib.analyze_import_attribute/1","ref":"erl_syntax_lib.html#analyze_import_attribute/1"},{"type":"function","doc":"Returns the module name and possible parameters declared by a module attribute.\n\nIf the attribute is a plain module declaration such as `-module(name)`, the\nresult is the module name. If the attribute is a parameterized module\ndeclaration, the result is a tuple containing the module name and a list of the\nparameter variable names.\n\nThe evaluation throws `syntax_error` if `Node` does not represent a well-formed\nmodule attribute.\n\n_See also: _`analyze_attribute/1`.","title":"erl_syntax_lib.analyze_module_attribute/1","ref":"erl_syntax_lib.html#analyze_module_attribute/1"},{"type":"function","doc":"Returns the name and the list of fields of a record declaration attribute.\n\nThe result is a pair `{Name, Fields}`, if `Node` represents\n\"`-record(Name, {...}).`\", where `Fields` is a list of pairs\n`{Label, {Default, Type}}` for each field \"`Label`\", \"`Label = Default`\",\n\"`Label :: Type`\", or \"`Label = Default :: Type`\" in the declaration, listed in\nleft-to-right order. If the field has no default-value declaration, the value\nfor `Default` will be the atom `none`. If the field has no type declaration, the\nvalue for `Type` will be the atom `none`. We do not guarantee that each label\noccurs at most once in the list.\n\nThe evaluation throws `syntax_error` if `Node` does not represent a well-formed\nrecord declaration attribute.\n\n_See also: _`analyze_attribute/1`, `analyze_record_field/1`.","title":"erl_syntax_lib.analyze_record_attribute/1","ref":"erl_syntax_lib.html#analyze_record_attribute/1"},{"type":"function","doc":"Returns the record name and field name/names of a record expression.\n\nIf `Node` has type `record_expr`, `record_index_expr` or\n`record_access`, a pair `{Type, Info}` is returned, otherwise an atom\n`Type` is returned. `Type` is the node type of `Node`, and `Info`\ndepends on `Type`, as follows:\n\n- **`record_expr`:** - `{atom(), [{atom(), Value}]}`\n\n- **`record_access`:** - `{atom(), atom()}`\n\n- **`record_index_expr`:** - `{atom(), atom()}`\n\nFor a `record_expr` node, `Info` represents the record name and the list of\ndescriptors for the involved fields, listed in the order they appear. A field\ndescriptor is a pair `{Label, Value}`, if `Node` represents \"`Label = Value`\".\nFor a `record_access` node, `Info` represents the record name and the field\nname. For a `record_index_expr` node, `Info` represents the record name and the\nname field name.\n\nThe evaluation throws `syntax_error` if `Node` represents a record expression\nthat is not well-formed.\n\n_See also: _`analyze_record_attribute/1`, `analyze_record_field/1`.","title":"erl_syntax_lib.analyze_record_expr/1","ref":"erl_syntax_lib.html#analyze_record_expr/1"},{"type":"function","doc":"Returns the label, value-expression, and type of a record field specifier.\n\nThe result is a pair `{Label, {Default, Type}}`, if `Node` represents\n\"`Label`\", \"`Label = Default`\", \"`Label :: Type`\", or \"`Label =\nDefault :: Type`\". If the field has no value-expression, the value for\n`Default` will be the atom `none`. If the field has no type, the\nvalue for `Type` will be the atom `none`.\n\nThe evaluation throws `syntax_error` if `Node` does not represent a well-formed\nrecord field specifier.\n\n_See also: _`analyze_record_attribute/1`, `analyze_record_expr/1`.","title":"erl_syntax_lib.analyze_record_field/1","ref":"erl_syntax_lib.html#analyze_record_field/1"},{"type":"function","doc":"Returns the name of a used type.\n\nThe result is a representation of the name of the used pre-defined or\nlocal type `N/A`, if `Node` represents a local (user) type application\n\"`N(T_1, ..., T_A)`\", or a representation of the name of the used\nremote type `M:N/A` if `Node` represents a remote user type\napplication \"`M:N(T_1, ..., T_A)`\".\n\nThe evaluation throws `syntax_error` if `Node` does not represent a well-formed\n(user) type application expression.\n\n_See also: _`analyze_type_name/1`.","title":"erl_syntax_lib.analyze_type_application/1","ref":"erl_syntax_lib.html#analyze_type_application/1"},{"type":"function","doc":"Returns the type name represented by a syntax tree.\n\nIf `Node` represents a type name, such as \"`foo/1`\" or\n\"`bloggs:fred/2`\", a uniform representation of that name is returned.\n\nThe evaluation throws `syntax_error` if `Node` does not represent a well-formed\ntype name.","title":"erl_syntax_lib.analyze_type_name/1","ref":"erl_syntax_lib.html#analyze_type_name/1"},{"type":"function","doc":"Returns the name and value of a \"wild\" attribute.\n\nThe result is the pair `{Name, Value}`, if `Node` represents\n\"`-Name(Value)`\".\n\nNote that no checking is done whether `Name` is a reserved attribute name such\nas `module` or `export`: it is assumed that the attribute is \"wild\".\n\nThe evaluation throws `syntax_error` if `Node` does not represent a well-formed\nwild attribute.\n\n_See also: _`analyze_attribute/1`.","title":"erl_syntax_lib.analyze_wild_attribute/1","ref":"erl_syntax_lib.html#analyze_wild_attribute/1"},{"type":"function","doc":"Adds or updates annotations on nodes in a syntax tree.\n\nEquivalent to [`annotate_bindings(Tree,\nBindings)`](`annotate_bindings/2`) where the top-level environment\n`Bindings` is taken from the annotation `{env, Bindings}` on the root\nnode of `Tree`. An exception is thrown if no such annotation should\nexist.\n\n_See also: _`annotate_bindings/2`.","title":"erl_syntax_lib.annotate_bindings/1","ref":"erl_syntax_lib.html#annotate_bindings/1"},{"type":"function","doc":"Adds or updates annotations on nodes in a syntax tree.\n\n`Bindings` specifies the set of bound variables in the environment of\nthe top level node. The following annotations are affected:\n\n- `{env, Vars}`, representing the input environment of the subtree.\n- `{bound, Vars}`, representing the variables that are bound in the subtree.\n- `{free, Vars}`, representing the free variables in the subtree.\n\n`Bindings` and `Vars` are ordered-set lists (see module `m:ordsets`) of atoms\nrepresenting variable names.\n\n_See also: _[//stdlib/ordsets](`m:ordsets`), `annotate_bindings/1`.","title":"erl_syntax_lib.annotate_bindings/2","ref":"erl_syntax_lib.html#annotate_bindings/2"},{"type":"function","doc":"Folds a function over all nodes of a syntax tree.\n\nThe result is the value of `Function(X1, Function(X2, ... Function(Xn,\nStart) ... ))`, where `[X1, X2, ..., Xn]` are the nodes of `Tree` in a\npost-order traversal.\n\n_See also: _`fold_subtrees/3`, `foldl_listlist/3`.","title":"erl_syntax_lib.fold/3","ref":"erl_syntax_lib.html#fold/3"},{"type":"function","doc":"Folds a function over the immediate subtrees of a syntax tree.\n\nThis is similar to [`fold/3`](`fold/3`), but only on the immediate\nsubtrees of `Tree`, in left-to-right order; it does not include the\nroot node of `Tree`.\n\n_See also: _`fold/3`.","title":"erl_syntax_lib.fold_subtrees/3","ref":"erl_syntax_lib.html#fold_subtrees/3"},{"type":"function","doc":"Like `lists:foldl/3`, but over a list of lists.\n\n_See also: _[//stdlib/lists:foldl/3](`lists:foldl/3`), `fold/3`.","title":"erl_syntax_lib.foldl_listlist/3","ref":"erl_syntax_lib.html#foldl_listlist/3"},{"type":"function","doc":"Creates a mapping from corresponding short names to full function names.\n\nNames are represented by nested tuples of atoms and integers (see\n[`analyze_function_name/1`](`analyze_function_name/1`)). The result is\na list containing a pair `{ShortName, Name}` for each element `Name`\nin the given list, where the corresponding `ShortName` is the\nrightmost-innermost part of `Name`. The list thus represents a finite\nmapping from unqualified names to the corresponding qualified names.\n\nNote that the resulting list can contain more than one tuple\n`{ShortName, Name}` for the same `ShortName`, possibly with different\nvalues for `Name`, depending on the given list.\n\n_See also: _`analyze_function_name/1`.","title":"erl_syntax_lib.function_name_expansions/1","ref":"erl_syntax_lib.html#function_name_expansions/1"},{"type":"function","doc":"Returns `true` if `Tree` represents an expression that never terminates\nnormally.\n\nNote that the reverse does not apply. Currently, the detected cases\nare calls to [`exit/1`](`exit/1`), [`throw/1`](`throw/1`),\n`erlang:error/1` and `erlang:error/2`.\n\n_See also: _[//erts/erlang:error/1](`erlang:error/1`),\n[//erts/erlang:error/2](`erlang:error/2`),\n[//erts/erlang:exit/1](`erlang:exit/1`),\n[//erts/erlang:throw/1](`erlang:throw/1`).","title":"erl_syntax_lib.is_fail_expr/1","ref":"erl_syntax_lib.html#is_fail_expr/1"},{"type":"function","doc":"Equivalent to [`limit(Tree, Depth, Text)`](`limit/3`) using the text `\"...\"` as\ndefault replacement.\n\n_See also: _`limit/3`, `erl_syntax:text/1`.","title":"erl_syntax_lib.limit/2","ref":"erl_syntax_lib.html#limit/2"},{"type":"function","doc":"Limits a syntax tree to a specified depth.\n\nReplaces all non-leaf subtrees in\n`Tree` at the given `Depth` by `Node`. If `Depth` is negative, the result is\nalways `Node`, even if `Tree` has no subtrees.\n\nWhen a group of subtrees (as, for example, the argument list of an\n`application` node) is at the specified depth, and there are two or\nmore subtrees in the group, these will be collectively replaced by\n`Node` even if they are leaf nodes. Groups of subtrees that are above\nthe specified depth will be limited in size, as if each subsequent\ntree in the group were one level deeper than the previous. For example,\nif `Tree` represents a list of integers \"`[1, 2, 3, 4, 5, 6, 7, 8, 9,\n10]`\", the result of [`limit(Tree, 5)`](`limit/2`) will represent `[1,\n2, 3, 4, ...]`.\n\nThe resulting syntax tree is typically only useful for pretty-printing or\nsimilar visual formatting.\n\n_See also: _`limit/2`.","title":"erl_syntax_lib.limit/3","ref":"erl_syntax_lib.html#limit/3"},{"type":"function","doc":"Applies a function to each node of a syntax tree.\n\nThe result of each application replaces the corresponding original\nnode. The order of traversal is bottom-up.\n\n_See also: _`map_subtrees/2`.","title":"erl_syntax_lib.map/2","ref":"erl_syntax_lib.html#map/2"},{"type":"function","doc":"Applies a function to each immediate subtree of a syntax tree.\n\nThe result of each application replaces the corresponding original\nnode.\n\n_See also: _`map/2`.","title":"erl_syntax_lib.map_subtrees/2","ref":"erl_syntax_lib.html#map_subtrees/2"},{"type":"function","doc":"Combines map and fold in a single operation.\n\nThis is similar to [`map/2`](`map/2`), but also propagates an extra\nvalue from each application of the `Function` to the next, while doing\na post-order traversal of the tree like [`fold/3`](`fold/3`). The\nvalue `Start` is passed to the first function application, and the\nfinal result is the result of the last application.\n\n_See also: _`fold/3`, `map/2`.","title":"erl_syntax_lib.mapfold/3","ref":"erl_syntax_lib.html#mapfold/3"},{"type":"function","doc":"Does a mapfold operation over the immediate subtrees of a syntax tree.\n\nThis is similar to [`mapfold/3`](`mapfold/3`), but only on the\nimmediate subtrees of `Tree`, in left-to-right order; it does not\ninclude the root node of `Tree`.\n\n_See also: _`mapfold/3`.","title":"erl_syntax_lib.mapfold_subtrees/3","ref":"erl_syntax_lib.html#mapfold_subtrees/3"},{"type":"function","doc":"Like `lists:mapfoldl/3`, but over a list of lists.\n\nThe list of lists in the result has the same structure as the given\nlist of lists.","title":"erl_syntax_lib.mapfoldl_listlist/3","ref":"erl_syntax_lib.html#mapfoldl_listlist/3"},{"type":"function","doc":"Returns an atom which is not already in the set `Used`.\n\nThis is equivalent to [`new_variable_name(Function,\nUsed)`](`new_variable_name/2`), where `Function` maps a given integer\n`N` to the atom whose name consists of \"`V`\" followed by the numeral\nfor `N`.\n\n_See also: _`new_variable_name/2`.","title":"erl_syntax_lib.new_variable_name/1","ref":"erl_syntax_lib.html#new_variable_name/1"},{"type":"function","doc":"Returns a user-named atom which is not already in the set `Used`.\n\nThe atom is generated by applying the given `Function` to a generated\ninteger. Integers are generated using an algorithm which tries to keep\nthe names randomly distributed within a reasonably small range\nrelative to the number of elements in the set.\n\nThis function uses the module `m:rand` to generate new keys. The seed it uses can\nbe initialized by calling `rand:seed/1` or `rand:seed/2` before this function is\nfirst called.\n\n_See also: _[//stdlib/rand](`m:rand`), [//stdlib/sets](`m:sets`),\n`new_variable_name/1`.","title":"erl_syntax_lib.new_variable_name/2","ref":"erl_syntax_lib.html#new_variable_name/2"},{"type":"function","doc":"Like [`new_variable_name/1`](`new_variable_name/1`), but generates a list of `N`\nnew names.\n\n_See also: _`new_variable_name/1`.","title":"erl_syntax_lib.new_variable_names/2","ref":"erl_syntax_lib.html#new_variable_names/2"},{"type":"function","doc":"Like [`new_variable_name/2`](`new_variable_name/2`), but generates a list of `N`\nnew names.\n\n_See also: _`new_variable_name/2`.","title":"erl_syntax_lib.new_variable_names/3","ref":"erl_syntax_lib.html#new_variable_names/3"},{"type":"function","doc":"Removes all comments from all nodes of a syntax tree.\n\nAll other attributes (such as position information) remain\nunchanged. Standalone comments in form lists are removed; any other\nstandalone comments are changed into null-comments (no text, no\nindentation).","title":"erl_syntax_lib.strip_comments/1","ref":"erl_syntax_lib.html#strip_comments/1"},{"type":"function","doc":"","title":"erl_syntax_lib.to_comment/1","ref":"erl_syntax_lib.html#to_comment/1"},{"type":"function","doc":"Equivalent to [`to_comment(Tree, Prefix, F)`](`to_comment/3`) for a default\nformatting function `F`.\n\nThe default `F` simply calls `erl_prettypr:format/1`.\n\n_See also: _`to_comment/3`, `erl_prettypr:format/1`.","title":"erl_syntax_lib.to_comment/2","ref":"erl_syntax_lib.html#to_comment/2"},{"type":"function","doc":"Transforms a syntax tree into an abstract comment.\n\nThe lines of the comment contain the text for `Node`, as produced by\nthe given `Printer` function. Each line of the comment is prefixed by\nthe string `Prefix` (this does not include the initial \"`%`\" character\nof the comment line).\n\nFor example, the result of\n[`to_comment(erl_syntax:abstract([a,b,c]))`](`to_comment/1`) represents\n\n```erlang\n%% [a,b,c]\n```\n\n(see [`to_comment/1`](`to_comment/1`)).\n\n> #### Note {: .info }\n>\n> The text returned by the formatting function will be split\n> automatically into separate comment lines at each line break. No extra\n> work is needed.\n\n_See also: _`to_comment/1`, `to_comment/2`.","title":"erl_syntax_lib.to_comment/3","ref":"erl_syntax_lib.html#to_comment/3"},{"type":"function","doc":"Returns the names of variables occurring in a syntax tree.\n\nThe result is a set of variable names represented by atoms. Macro\nnames are not included.\n\n_See also: _[//stdlib/sets](`m:sets`).","title":"erl_syntax_lib.variables/1","ref":"erl_syntax_lib.html#variables/1"},{"type":"type","doc":"","title":"erl_syntax_lib.appFunName/0","ref":"erl_syntax_lib.html#t:appFunName/0"},{"type":"type","doc":"","title":"erl_syntax_lib.field/0","ref":"erl_syntax_lib.html#t:field/0"},{"type":"type","doc":"","title":"erl_syntax_lib.field_default/0","ref":"erl_syntax_lib.html#t:field_default/0"},{"type":"type","doc":"","title":"erl_syntax_lib.field_type/0","ref":"erl_syntax_lib.html#t:field_type/0"},{"type":"type","doc":"","title":"erl_syntax_lib.fields/0","ref":"erl_syntax_lib.html#t:fields/0"},{"type":"type","doc":"","title":"erl_syntax_lib.functionN/0","ref":"erl_syntax_lib.html#t:functionN/0"},{"type":"type","doc":"","title":"erl_syntax_lib.functionName/0","ref":"erl_syntax_lib.html#t:functionName/0"},{"type":"type","doc":"","title":"erl_syntax_lib.info/0","ref":"erl_syntax_lib.html#t:info/0"},{"type":"type","doc":"","title":"erl_syntax_lib.info_pair/0","ref":"erl_syntax_lib.html#t:info_pair/0"},{"type":"type","doc":"","title":"erl_syntax_lib.key/0","ref":"erl_syntax_lib.html#t:key/0"},{"type":"type","doc":"","title":"erl_syntax_lib.name/0","ref":"erl_syntax_lib.html#t:name/0"},{"type":"type","doc":"","title":"erl_syntax_lib.ordset/1","ref":"erl_syntax_lib.html#t:ordset/1"},{"type":"type","doc":"","title":"erl_syntax_lib.set/1","ref":"erl_syntax_lib.html#t:set/1"},{"type":"type","doc":"","title":"erl_syntax_lib.shortname/0","ref":"erl_syntax_lib.html#t:shortname/0"},{"type":"type","doc":"An abstract syntax tree. See the `m:erl_syntax` module for details.","title":"erl_syntax_lib.syntaxTree/0","ref":"erl_syntax_lib.html#t:syntaxTree/0"},{"type":"type","doc":"","title":"erl_syntax_lib.typeName/0","ref":"erl_syntax_lib.html#t:typeName/0"},{"type":"module","doc":"Metaprogramming in Erlang.\n\nMerl is a user-friendly interface to the `erl_syntax` module,\nmaking it easy both to build new ASTs from scratch and to match and\ndecompose existing ASTs. For details that are outside the scope of\nMerl itself, see the documentation of `m:erl_syntax`.","title":"merl","ref":"merl.html"},{"type":"module","doc":"To enable the full power of Merl, your module needs to include the Merl header\nfile:\n\n```erlang\n-include_lib(\"syntax_tools/include/merl.hrl\").\n```\n\nThen, you can use the `?Q(Text)` macros in your code to create ASTs or match on\nexisting ASTs. For example:\n\n```erlang\nTuple = ?Q(\"{foo, 42}\"),\n?Q(\"{foo, _@Number}\") = Tuple,\nCall = ?Q(\"foo:bar(_@Number)\")\n```\n\nCalling `merl:print(Call)` will then print the following code:\n\n```erlang\nfoo:bar(42)\n```\n\nThe `?Q` macros turn the quoted code fragments into ASTs, and lifts\nmetavariables such as `_@Tuple` and `_@Number` to the level of your Erlang code,\nso you can use the corresponding Erlang variables `Tuple` and `Number` directly.\nThis is the most straightforward way to use Merl, and in many cases it's all you\nneed.\n\nYou can even write case switches using `?Q` macros as patterns. For example:\n\n```erlang\ncase AST of\n ?Q(\"{foo, _@Foo}\") -> handle(Foo);\n ?Q(\"{bar, _@Bar}\") when erl_syntax:is_integer(Bar) -> handle(Bar);\n _ -> handle_default()\nend\n```\n\nThese case switches only allow `?Q(...)` or `_` as clause patterns, and the\nguards may contain any expressions, not just Erlang guard expressions.\n\nIf the macro `MERL_NO_TRANSFORM` is defined before the `merl.hrl` header file is\nincluded, the parse transform used by Merl will be disabled, and in that case,\nthe match expressions `?Q(...) = ...`, case switches using `?Q(...)` patterns,\nand automatic metavariables like `_@Tuple` cannot be used in your code, but the\nMerl macros and functions still work. To do metavariable substitution, you need\nto use the `?Q(Text, Map)` macro. For example:\n\n```erlang\nTuple = ?Q(\"{foo, _@bar, _@baz}\", [{bar, Bar}, {baz,Baz}])\n```\n\nThe text given to a `?Q(Text)` macro can be either a single string or a list of\nstrings. The latter is useful when you need to split a long expression over\nmultiple lines. For example:\n\n```erlang\n?Q([\"case _@Expr of\",\n \" {foo, X} -> f(X);\",\n \" {bar, X} -> g(X)\",\n \" _ -> h(X)\"\n\"end\"])\n```\n\nIf there is a syntax error somewhere in the text (like the missing semicolon in\nthe second clause above) this allows Merl to generate an error message pointing\nto the exact line in your source code. (Just remember to comma-separate the\nstrings in the list, otherwise Erlang will concatenate the string fragments as\nif they were a single string.)","title":"Quick start - merl","ref":"merl.html#module-quick-start"},{"type":"module","doc":"There are several ways to write a metavariable in your quoted code:\n\n- Atoms starting with `@`, for example `'@foo'` or `'@Foo'`\n- Variables starting with `_@`, for example `_@bar` or `_@Bar`\n- Strings starting with `\"'@`, for example `\"'@File\"`\n- Integers starting with 909, for example `9091` or `909123`\n\nFollowing the prefix, one or more `_` or `0` characters may be used to indicate\n\"lifting\" of the variable one or more levels, and after that, a `@` or `9`\ncharacter indicates a glob metavariable (matching zero or more elements in a\nsequence) rather than a normal metavariable. For example:\n\n- `'@_foo'` is lifted one level, and `_@__foo` is lifted two levels\n- `_@@bar` is a glob variable, and `_@_@bar` is a lifted glob variable\n- `90901` is a lifted variable,`90991` is a glob variable, and `9090091` is a\n glob variable lifted two levels\n\n(Note that the last character in the name is never considered to be a lift or\nglob marker, hence, `_@__` and `90900` are only lifted one level, not two. Also\nnote that globs only matter for matching; when doing substitutions, a non-glob\nvariable can be used to inject a sequence of elements, and vice versa.)\n\nIf the name after the prefix and any lift and glob markers is `_` or `0`, the\nvariable is treated as an anonymous catch-all pattern in matches. For example,\n`_@_`, `_@@_`, `_@__`, or even `_@__@_`.\n\nFinally, if the name without any prefixes or lift/glob markers begins with an\nuppercase character, as in `_@Foo` or `_@_@Foo`, it will become a variable on\nthe Erlang level, and can be used to easily deconstruct and construct syntax\ntrees:\n\n```erlang\ncase Input of\n ?Q(\"{foo, _@Number}\") -> ?Q(\"foo:bar(_@Number)\");\n ...\n```\n\nWe refer to these as \"automatic metavariables\". If in addition the name ends\nwith `@`, as in `_@Foo@`, the value of the variable as an Erlang term will be\nautomatically converted to the corresponding abstract syntax tree when used to\nconstruct a larger tree. For example, in:\n\n```erlang\nBar = {bar, 42},\nFoo = ?Q(\"{foo, _@Bar@}\")\n```\n\n(where Bar is just some term, not a syntax tree) the result `Foo` will be a\nsyntax tree representing `{foo, {bar, 42}}`. This avoids the need for temporary\nvariables in order to inject data, as in\n\n```erlang\nTmpBar = erl_syntax:abstract(Bar),\nFoo = ?Q(\"{foo, _@TmpBar}\")\n```\n\nIf the context requires an integer rather than a variable, an atom, or a string,\nyou cannot use the uppercase convention to mark an automatic metavariable.\nInstead, if the integer (without the `909`\\-prefix and lift/glob markers) ends\nin a `9`, the integer will become an Erlang-level variable prefixed with `Q`,\nand if it ends with `99` it will also be automatically abstracted. For example,\nthe following will increment the arity of the exported function f:\n\n```erlang\ncase Form of\n ?Q(\"-export([f/90919]).\") ->\n Q2 = erl_syntax:concrete(Q1) + 1,\n ?Q(\"-export([f/909299]).\");\n ...\n```","title":"Metavariable syntax - merl","ref":"merl.html#module-metavariable-syntax"},{"type":"module","doc":"Merl can only parse a fragment of text if it follows the basic syntactical rules\nof Erlang. In most places, a normal Erlang variable can be used as metavariable,\nfor example:\n\n```erlang\n?Q(\"f(_@Arg)\") = Expr\n```\n\nbut if you want to match on something like the name of a function, you have to\nuse an atom as metavariable:\n\n```erlang\n?Q(\"'@Name'() -> _@@_.\" = Function\n```\n\n(note the anonymous glob variable `_@@_` to ignore the function body).\n\nIn some contexts, only a string or an integer is allowed. For example, the\ndirective `-file(Name, Line)` requires that `Name` is a string literal and\n`Line` an integer literal:\n\n```erlang\n?Q(\"-file(\\\"'@File\\\", 9090).\") = ?Q(\"-file(\\\"foo.erl\\\", 42).\")).\n```\n\nThis will extract the string literal `\"foo.erl\"` into the variable `Foo`. Note\nthe use of the anonymous variable `9090` to ignore the line number. To match and\nalso bind a metavariable that must be an integer literal, we can use the\nconvention of ending the integer with a 9, turning it into a Q-prefixed variable\non the Erlang level (see the previous section).\n\n#### Globs\n\nWhenever you want to match out a number of elements in a sequence (zero or more)\nrather than a fixed set of elements, you need to use a glob. For example:\n\n```erlang\n?Q(\"{_@@Elements}\") = ?Q({a, b, c})\n```\n\nwill bind Elements to the list of individual syntax trees representing the atoms\n`a`, `b`, and `c`. This can also be used with static prefix and suffix elements\nin the sequence. For example:\n\n```erlang\n?Q(\"{a, b, _@@Elements}\") = ?Q({a, b, c, d})\n```\n\nwill bind Elements to the list of the `c` and `d` subtrees, and\n\n```erlang\n?Q(\"{_@@Elements, c, d}\") = ?Q({a, b, c, d})\n```\n\nwill bind Elements to the list of the `a` and `b` subtrees. You can even use\nplain metavariables in the prefix or suffix:\n\n```erlang\n?Q(\"{_@First, _@@Rest}\") = ?Q({a, b, c})\n```\n\nor\n\n```erlang\n?Q(\"{_@@_, _@Last}\") = ?Q({a, b, c})\n```\n\n(ignoring all but the last element). However, you cannot have two globs as part\nof the same sequence.\n\n#### Lifted metavariables\n\nIn some cases, the Erlang syntax rules make it impossible to place a\nmetavariable directly where you would like it. For example, you cannot write:\n\n```erlang\n?Q(\"-export([_@@Name]).\")\n```\n\nto match out all name/arity pairs in the export list, or to insert a list of\nexports in a declaration, because the Erlang parser only allows elements on the\nform `A/I` (where `A` is an atom and `I` an integer) in the export list. A\nvariable like the above is not allowed, but neither is a single atom or integer,\nso `'@@Name'` or `909919` would not work either.\n\nWhat you have to do in such cases is to write your metavariable in a\nsyntactically valid position, and use lifting markers to denote where it should\nreally apply, as in:\n\n```erlang\n?Q(\"-export(['@_@Name'/0]).\")\n```\n\nThis causes the variable to be lifted (after parsing) to the next higher level\nin the syntax tree, replacing that entire subtree. In this case, the\n`'@_@Name'/0` will be replaced with `'@@Name'`, and the `/0` part was just used\nas dummy notation and will be discarded.\n\nYou may even need to apply lifting more than once. To match the entire export\nlist as a single syntax tree, you can write:\n\n```erlang\n?Q(\"-export(['@__Name'/0]).\")\n```\n\nusing two underscores, but with no glob marker this time. This will make the\nentire `['@__Name'/0]` part be replaced with `'@Name'`.\n\nSometimes, the tree structure of a code fragment is not very obvious, and parts\nof the structure may be invisible when printed as source code. For instance, a\nsimple function definition like the following:\n\n```erlang\nzero() -> 0.\n```\n\nconsists of the name (the atom `zero`), and a list of clauses containing the\nsingle clause `() -> 0`. The clause consists of an argument list (empty), a\nguard (empty), and a body (which is always a list of expressions) containing the\nsingle expression `0`. This means that to match out the name and the list of\nclauses of any function, you'll need to use a pattern like\n`?Q(\"'@Name'() -> _@_@Body.\")`, using a dummy clause whose body is a glob lifted\none level.\n\nTo visualize the structure of a syntax tree, you can use the function\n`merl:show(T)`, which prints a summary. For example, entering\n\n```erlang\nmerl:show(merl:quote(\"inc(X, Y) when Y > 0 -> X + Y.\"))\n```\n\nin the Erlang shell will print the following (where the `+` signs separate\ngroups of subtrees on the same level):\n\n```text\nfunction: inc(X, Y) when ... -> X + Y.\n atom: inc\n +\n clause: (X, Y) when ... -> X + Y\n variable: X\n variable: Y\n +\n disjunction: Y > 0\n conjunction: Y > 0\n infix_expr: Y > 0\n variable: Y\n +\n operator: >\n +\n integer: 0\n +\n infix_expr: X + Y\n variable: X\n +\n operator: +\n +\n variable: Y\n```\n\nThis shows another important non-obvious case: a clause guard, even if it's as\nsimple as `Y > 0`, always consists of a single disjunction of one or more\nconjunctions of tests, much like a tuple of tuples. Thus:\n\n- `\"when _@Guard ->\"` will only match a guard with exactly one test\n- `\"when _@@Guard ->\"` will match a guard with one or more comma-separated tests\n (but no semicolons), binding `Guard` to the list of tests\n- `\"when _@_Guard ->\"` will match just like the previous pattern, but binds\n `Guard` to the conjunction subtree\n- `\"when _@_@Guard ->\"` will match an arbitrary nonempty guard, binding `Guard`\n to the list of conjunction subtrees\n- `\"when _@__Guard ->\"` will match like the previous pattern, but binds `Guard`\n to the whole disjunction subtree\n- and finally, `\"when _@__@Guard ->\"` will match any clause, binding `Guard` to\n `[]` if the guard is empty and to `[Disjunction]` otherwise\n\nThus, the following pattern matches all possible clauses:\n\n```erlang\n \"(_@Args) when _@__@Guard -> _@Body\"\n```","title":"When to use the various forms of metavariables - merl","ref":"merl.html#module-when-to-use-the-various-forms-of-metavariables"},{"type":"function","doc":"Alpha converts a pattern (renames variables).\n\nSimilar to tsubst/1, but only renames variables (including globs).\n\n_See also: _`tsubst/2`.","title":"merl.alpha/2","ref":"merl.html#alpha/2"},{"type":"function","doc":"","title":"merl.compile/1","ref":"merl.html#compile/1"},{"type":"function","doc":"Compile a syntax tree or list of syntax trees representing a module into a\nbinary BEAM object.\n\n_See also: _`compile/1`, `compile_and_load/2`.","title":"merl.compile/2","ref":"merl.html#compile/2"},{"type":"function","doc":"","title":"merl.compile_and_load/1","ref":"merl.html#compile_and_load/1"},{"type":"function","doc":"Compile a syntax tree or list of syntax trees representing a module and load the\nresulting module into memory.\n\n_See also: _`compile/2`, `compile_and_load/1`.","title":"merl.compile_and_load/2","ref":"merl.html#compile_and_load/2"},{"type":"function","doc":"Match a pattern against a syntax tree (or patterns against syntax trees)\nreturning an environment mapping variable names to subtrees; the environment is\nalways sorted on keys.\n\n> #### Note {: .info }\n>\n> Multiple occurrences of metavariables in the pattern is not\n> allowed, but is not checked.\n\n_See also: _`switch/2`, `template/1`.","title":"merl.match/2","ref":"merl.html#match/2"},{"type":"function","doc":"Turn a template into a syntax tree representing the template.\n\nMeta-variables in the template are turned into normal Erlang variables\nif their names (after the metavariable prefix characters) begin with\nan uppercase character. For example, `_@Foo` in the template becomes the\nvariable `Foo` in the meta-template. Furthermore, variables ending\nwith `@` are automatically wrapped in a call to merl:term/1, so\n`_@Foo@` in the template becomes `merl:term(Foo)` in the\nmeta-template.","title":"merl.meta_template/1","ref":"merl.html#meta_template/1"},{"type":"function","doc":"Pretty-print a syntax tree or template to the standard output.\n\nThis is a utility function for development and debugging.","title":"merl.print/1","ref":"merl.html#print/1"},{"type":"function","doc":"","title":"merl.qquote/2","ref":"merl.html#qquote/2"},{"type":"function","doc":"Parse text and substitute meta-variables.\n\nTakes an initial scanner starting position as first argument.\n\nThe macro `?Q(Text, Env)` expands to `merl:qquote(?LINE, Text, Env)`.\n\n_See also: _`quote/2`.","title":"merl.qquote/3","ref":"merl.html#qquote/3"},{"type":"function","doc":"","title":"merl.quote/1","ref":"merl.html#quote/1"},{"type":"function","doc":"Parse text.\n\nTakes an initial scanner starting position as first argument.\n\nThe macro `?Q(Text)` expands to `merl:quote(?LINE, Text)`.\n\n_See also: _`quote/1`.","title":"merl.quote/2","ref":"merl.html#quote/2"},{"type":"function","doc":"Print the structure of a syntax tree or template to the standard output.\n\nThis is a utility function for development and debugging.","title":"merl.show/1","ref":"merl.html#show/1"},{"type":"function","doc":"Substitute metavariables in a pattern or list of patterns, yielding a syntax\ntree or list of trees as result.\n\nBoth for normal metavariables and glob metavariables, the substituted\nvalue may be a single element or a list of elements. For example, if a\nlist representing `1, 2, 3` is substituted for `var` in either of\n`[foo, _@var, bar]` or `[foo, _@var, bar]`, the result represents\n`[foo, 1, 2, 3, bar]`.","title":"merl.subst/2","ref":"merl.html#subst/2"},{"type":"function","doc":"Match against one or more clauses with patterns and optional guards.\n\nNote that clauses following a default action will be ignored.\n\n_See also: _`match/2`.","title":"merl.switch/2","ref":"merl.html#switch/2"},{"type":"function","doc":"Turn a syntax tree or list of trees into a template or templates.\n\nTemplates can be instantiated or matched against, and reverted back to\nnormal syntax trees using `tree/1`. If the input is already a\ntemplate, it is not modified further.\n\n_See also: _`match/2`, `subst/2`, `tree/1`.","title":"merl.template/1","ref":"merl.html#template/1"},{"type":"function","doc":"Return an ordered list of the metavariables in the template.","title":"merl.template_vars/1","ref":"merl.html#template_vars/1"},{"type":"function","doc":"Create a syntax tree for a constant term.","title":"merl.term/1","ref":"merl.html#term/1"},{"type":"function","doc":"Revert a template to a normal syntax tree.\n\nAny remaining metavariables are turned into `@`\\-prefixed atoms or\n`909`\\-prefixed integers.\n\n_See also: _`template/1`.","title":"merl.tree/1","ref":"merl.html#tree/1"},{"type":"function","doc":"Like `subst/2`, but does not convert the result from a template back to a tree.\n\nUseful if you want to do multiple separate substitutions.\n\n_See also: _`subst/2`, `tree/1`.","title":"merl.tsubst/2","ref":"merl.html#tsubst/2"},{"type":"function","doc":"Create a variable.","title":"merl.var/1","ref":"merl.html#var/1"},{"type":"type","doc":"","title":"merl.default_action/0","ref":"merl.html#t:default_action/0"},{"type":"type","doc":"","title":"merl.env/0","ref":"merl.html#t:env/0"},{"type":"type","doc":"","title":"merl.guard_test/0","ref":"merl.html#t:guard_test/0"},{"type":"type","doc":"","title":"merl.guarded_action/0","ref":"merl.html#t:guarded_action/0"},{"type":"type","doc":"","title":"merl.guarded_actions/0","ref":"merl.html#t:guarded_actions/0"},{"type":"type","doc":"","title":"merl.id/0","ref":"merl.html#t:id/0"},{"type":"type","doc":"","title":"merl.location/0","ref":"merl.html#t:location/0"},{"type":"type","doc":"","title":"merl.pattern/0","ref":"merl.html#t:pattern/0"},{"type":"type","doc":"","title":"merl.pattern_or_patterns/0","ref":"merl.html#t:pattern_or_patterns/0"},{"type":"type","doc":"","title":"merl.switch_action/0","ref":"merl.html#t:switch_action/0"},{"type":"type","doc":"","title":"merl.switch_clause/0","ref":"merl.html#t:switch_clause/0"},{"type":"type","doc":"","title":"merl.template/0","ref":"merl.html#t:template/0"},{"type":"type","doc":"","title":"merl.template_or_templates/0","ref":"merl.html#t:template_or_templates/0"},{"type":"type","doc":"","title":"merl.text/0","ref":"merl.html#t:text/0"},{"type":"type","doc":"","title":"merl.tree/0","ref":"merl.html#t:tree/0"},{"type":"type","doc":"","title":"merl.tree_or_trees/0","ref":"merl.html#t:tree_or_trees/0"},{"type":"module","doc":"Parse transform for merl.\n\nEnables the use of automatic metavariables and using quasi-quotes in\nmatches and case switches. Also optimizes calls to functions in `merl`\nby partially evaluating them, turning strings to templates, and so on,\nat compile-time.\n\nUsing `-include_lib(\"syntax_tools/include/merl.hrl\").` enables this transform,\nunless the macro `MERL_NO_TRANSFORM` is defined first.","title":"merl_transform","ref":"merl_transform.html"},{"type":"module","doc":"A generic pretty printer library.\n\nThis module uses a strict-style context passing implementation of John\nHughes algorithm, described in \"The design of a Pretty-printing\nLibrary\". The paragraph-style formatting, empty documents, floating\ndocuments, and null strings are my own additions to the algorithm.\n\nTo get started, you should read about the [`document()`](`t:document/0`) data\ntype; the main constructor functions: `text/1`, `above/2`, `beside/2`, `nest/2`,\n`sep/1`, and `par/2`; and the main layout function `format/3`.\n\nIf you simply want to format a paragraph of plain text, you probably want to use\nthe `text_par/2` function, as in the following example:\n\n```text\n prettypr:format(prettypr:text_par(\"Lorem ipsum dolor sit amet\"), 20)\n```","title":"prettypr","ref":"prettypr.html"},{"type":"function","doc":"Concatenates documents vertically.\n\nReturns a document representing the concatenation of the documents\n`D1` and `D2` such that the first line of `D2` follows directly below\nthe last line of `D1`, and the first character of `D2` is in the same\nhorizontal column as the first character of `D1`, in all possible\nlayouts.\n\nExamples:\n\n```text\nab cd => ab\n cd\n\n abc\nabc fgh => de\n de ij fgh\n ij\n```","title":"prettypr.above/2","ref":"prettypr.html#above/2"},{"type":"function","doc":"Concatenates documents horizontally.\n\nReturns a document representing the concatenation of the documents\n`D1` and `D2` such that the last character of `D1` is horizontally\nadjacent to the first character of `D2`, in all possible\nlayouts. (Note: any indentation of `D2` is lost.)\n\nExamples:\n\n```text\nab cd => abcd\n\nab ef ab\ncd gh => cdef\n gh\n```","title":"prettypr.beside/2","ref":"prettypr.html#beside/2"},{"type":"function","doc":"Selects a \"best\" layout for a document, creating a corresponding fixed-layout\ndocument.\n\nIf no layout could be produced, the atom `empty` is returned instead.\nFor details about `PaperWidth` and `LineWidth`, see `format/3`. The\nfunction is idempotent.\n\nOne possible use of this function is to compute a fixed layout for a document,\nwhich can then be included as part of a larger document. For example:\n\n```text\n above(text(\"Example:\"), nest(8, best(D, W - 12, L - 6)))\n```\n\nwill format `D` as a displayed-text example indented by 8, whose right margin is\nindented by 4 relative to the paper width `W` of the surrounding document, and\nwhose maximum individual line length is shorter by 6 than the line length `L` of\nthe surrounding document.\n\nThis function is used by the `format/3` function to prepare a document before\nbeing laid out as text.","title":"prettypr.best/3","ref":"prettypr.html#best/3"},{"type":"function","doc":"Forces a line break at the end of the given document.\n\nThis is a utility function; see `empty/0` for details.","title":"prettypr.break/1","ref":"prettypr.html#break/1"},{"type":"function","doc":"Yields the empty document, which has neither height nor width.\n\n(`empty` is thus different from an empty [`text`](`text/1`) string,\nwhich has zero width but height 1.)\n\nEmpty documents are occasionally useful; in particular, they have the property\nthat [`above(X, empty())`](`above/2`) will force a new line after `X` without\nleaving an empty line below it; since this is a common idiom, the utility\nfunction `break/1` will place a given document in such a context.\n\n_See also: _`text/1`.","title":"prettypr.empty/0","ref":"prettypr.html#empty/0"},{"type":"function","doc":"","title":"prettypr.floating/1","ref":"prettypr.html#floating/1"},{"type":"function","doc":"Creates a \"floating\" document.\n\nThe result represents the same set of layouts as `D`; however, a\nfloating document may be moved relative to other floating documents\nimmediately beside or above it, according to their relative horizontal\nand vertical priorities. These priorities are set with the `Hp` and\n`Vp` parameters; if omitted, both default to zero.\n\n> #### Note {: .info }\n>\n> Floating documents appear to work well, but are currently less general\n> than you might wish, losing effect when embedded in certain contexts. It is\n> possible to nest floating-operators (even with different priorities), but the\n> effects may be difficult to predict. In any case, note that the way the\n> algorithm reorders floating documents amounts to a \"bubblesort\", so don't expect\n> it to be able to sort large sequences of floating documents quickly.","title":"prettypr.floating/3","ref":"prettypr.html#floating/3"},{"type":"function","doc":"","title":"prettypr.follow/2","ref":"prettypr.html#follow/2"},{"type":"function","doc":"Separates two documents by either a single space, or a line break and\nindentation.\n\nIn other words, one of the layouts:\n\n```text\nabc def\n```\n\nor:\n\n```text\nabc\n def\n```\n\nwill be generated, using the optional offset in the latter case. This is often\nuseful for typesetting programming language constructs.\n\nThis is a utility function; see `par/2` for further details.\n\n_See also: _`follow/2`.","title":"prettypr.follow/3","ref":"prettypr.html#follow/3"},{"type":"function","doc":"","title":"prettypr.format/1","ref":"prettypr.html#format/1"},{"type":"function","doc":"","title":"prettypr.format/2","ref":"prettypr.html#format/2"},{"type":"function","doc":"Computes a layout for a document and returns the corresponding text.\n\nSee [`document()`](`t:document/0`) for further information. Throws\n`no_layout` if no layout could be selected.\n\n`PaperWidth` specifies the total width (in character positions) of the field for\nwhich the text is to be laid out. `LineWidth` specifies the desired maximum\nwidth (in number of characters) of the text printed on any single line,\ndisregarding leading and trailing white space. These parameters need to be\nproperly balanced in order to produce good layouts. By default, `PaperWidth` is\n80 and `LineWidth` is 65.\n\n_See also: _`best/3`.","title":"prettypr.format/3","ref":"prettypr.html#format/3"},{"type":"function","doc":"Indents a document a number of character positions to the right.\n\nNote that `N` can be negative, shifting the text to the left, or zero,\nin which case `D` is returned unchanged.","title":"prettypr.nest/2","ref":"prettypr.html#nest/2"},{"type":"function","doc":"Similar to `text/1`, but the result is treated as having zero width.\n\nThis is regardless of the actual length of the string. Null text is\ntypically used for markup, which is supposed to have no effect on the\nactual layout.\n\nThe standard example is when formatting source code as HTML to be\nplaced within ` ... ` markup, and using elements like ` `\nand ` ` to make parts of the source code stand out. In this case,\nthe markup does not add to the width of the text when viewed in an\nHTML browser, so the layout engine should simply pretend that the\nmarkup has zero width.\n\n_See also: _`empty/0`, `text/1`.","title":"prettypr.null_text/1","ref":"prettypr.html#null_text/1"},{"type":"function","doc":"","title":"prettypr.par/1","ref":"prettypr.html#par/1"},{"type":"function","doc":"Arranges documents in a paragraph-like layout.\n\nReturns a document representing all possible left-aligned\nparagraph-like layouts of the (nonempty) sequence `Docs` of\ndocuments. Elements in `Docs` are separated horizontally by a single\nspace character and vertically with a single line break. All lines\nfollowing the first (if any) are indented to the same left column,\nwhose indentation is specified by the optional `Offset` parameter\nrelative to the position of the first element in `Docs`. For example,\nwith an offset of -4, the following layout can be produced, for a list\nof documents representing the numbers 0 to 15:\n\n```text\n 0 1 2 3\n4 5 6 7 8 9\n10 11 12 13\n14 15\n```\n\nor with an offset of +2:\n\n```text\n0 1 2 3 4 5 6\n 7 8 9 10 11\n 12 13 14 15\n```\n\nThe utility function `text_par/2` can be used to easily transform a string of\ntext into a `par` representation by splitting it into words.\n\nNote that whenever a document in `Docs` contains a line break, it will be placed\non a separate line. Thus, neither a layout such as:\n\n```text\nab cd\n ef\n```\n\nnor:\n\n```text\nab\ncd ef\n```\n\nwill be generated. However, a useful idiom for making the former variant\npossible (when wanted) is [`beside(par([D1, text(\"\")], N), D2)`](`beside/2`) for\ntwo documents `D1` and `D2`. This will break the line between `D1` and `D2` if\n`D1` contains a line break (or if otherwise necessary), and optionally further\nindent `D2` by `N` character positions. The utility function `follow/3` creates\nthis context for two documents `D1` and `D2`, and an optional integer `N`.\n\n_See also: _`par/1`, `text_par/2`.","title":"prettypr.par/2","ref":"prettypr.html#par/2"},{"type":"function","doc":"Arranges documents horizontally or vertically, separated by whitespace.\n\nReturns a document representing two alternative layouts of the\n(nonempty) sequence `Docs` of documents, such that either all elements\nin `Docs` are concatenated horizontally, and separated by a space\ncharacter, or all elements are concatenated vertically (without extra\nseparation).\n\n> #### Note {: .info }\n>\n> If some document in `Docs` contains a line break, the vertical layout\n> will always be selected.\n\nExamples:\n\n```text\n ab\nab cd ef => ab cd ef | cd\n ef\n\nab ab\ncd ef => cd\n ef\n```\n\n_See also: _`par/2`.","title":"prettypr.sep/1","ref":"prettypr.html#sep/1"},{"type":"function","doc":"Yields a document representing a fixed, unbreakable sequence of characters.\n\nThe string should contain only _printable_ characters (tabs allowed\nbut not recommended), and _not_ newline, line feed, vertical tab,\nand so on. A tab character (`\\t`) is interpreted as padding of 1-8 space\ncharacters to the next column of 8 characters _within the string_.\n\n_See also: _`empty/0`, `null_text/1`, `text_par/2`.","title":"prettypr.text/1","ref":"prettypr.html#text/1"},{"type":"function","doc":"","title":"prettypr.text_par/1","ref":"prettypr.html#text_par/1"},{"type":"function","doc":"Yields a document representing paragraph-formatted plain text.\n\nThe `Indentation` parameter specifies the extra indentation\nof the first line of the paragraph. For example, [`text_par(\"Lorem\nipsum dolor sit amet\", N)`](`text_par/2`) could represent:\n\n```text\nLorem ipsum dolor\nsit amet\n```\n\nif N = 0, or:\n\n```text\n Lorem ipsum\ndolor sit amet\n```\n\nif `N` = 2, or:\n\n```text\nLorem ipsum dolor\n sit amet\n```\n\nif `N` = -2.\n\n(The sign of the indentation is thus reversed compared to the `par/2` function,\nand the behaviour varies slightly depending on the sign in order to match the\nexpected layout of a paragraph of text.)\n\nNote that this is just a utility function, which does all the work of splitting\nthe given string into words separated by whitespace and setting up a\n[`par`](`par/2`) with the proper indentation, containing a list of\n[`text`](`text/1`) elements.\n\n_See also: _`par/2`, `text/1`, `text_par/1`.","title":"prettypr.text_par/2","ref":"prettypr.html#text_par/2"},{"type":"type","doc":"","title":"prettypr.deep_string/0","ref":"prettypr.html#t:deep_string/0"},{"type":"type","doc":"An abstract character-based \"document\" representing\na number of possible layouts, which can be processed to produce a\nsingle concrete layout.\n\nA concrete layout can then be rendered as a sequence of characters\ncontaining linebreaks, which can be passed to a printer or terminal\nthat uses a fixed-width font.\n\nFor example, a document `sep([text(\"foo\"), text(\"bar\")])`\nrepresents the two layouts:\n\n```text\nfoo bar\n```\n\nand:\n\n```text\nfoo\nbar\n```\n\nWhich layout is chosen depends on the available horizontal space.\nWhen processing a document, the main parameters are the _paper\nwidth_ and the _line width_ (also known as the \"ribbon\nwidth\"). In the resulting layout, no text should be printed beyond\nthe paper width (which by default is 80 characters) as long as it can\nbe avoided, and each single line of text (its indentation not\ncounted, hence \"ribbon\") should preferably be no wider than the\nspecified line width (which by default is 65).\n\nDocuments can be joined into a single new document using the\nconstructor functions of this module. Note that the new document\noften represents a larger number of possible layouts than just the\nsum of the components.","title":"prettypr.document/0","ref":"prettypr.html#t:document/0"},{"type":"extras","doc":"\n# Syntax_Tools Release Notes\n\nThis document describes the changes made to the Syntax_Tools application.","title":"Syntax_Tools Release Notes","ref":"notes.html"},{"type":"extras","doc":"","title":"Syntax_Tools 3.2.1 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-3-2-1"},{"type":"extras","doc":"- The documentation for `syntax_tools` has been polished after the migration to the new documentation system.\n\n Own Id: OTP-19102 Aux Id: [PR-8515]\n\n[PR-8515]: https://github.com/erlang/otp/pull/8515","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Syntax_Tools 3.2 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-3-2"},{"type":"extras","doc":"- The `m:epp_dodger` module can now handle the `maybe` and `else` keywords.\n\n Own Id: OTP-18608 Aux Id: [GH-7266], [PR-7267]\n\n- Reverting a `#wrapper` will no longer throw away changes made to positions/annotations.\n\n Own Id: OTP-18805 Aux Id: [PR-7398]\n\n[GH-7266]: https://github.com/erlang/otp/issues/7266\n[PR-7267]: https://github.com/erlang/otp/pull/7267\n[PR-7398]: https://github.com/erlang/otp/pull/7398","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The type `t:erl_syntax:annotation_or_location/0` is now exported.\n\n Own Id: OTP-18715 Aux Id: [PR-7535]\n\n- The documentation has been migrated to use Markdown and ExDoc.\n\n Own Id: OTP-18955 Aux Id: [PR-8026]\n\n[PR-7535]: https://github.com/erlang/otp/pull/7535\n[PR-8026]: https://github.com/erlang/otp/pull/8026","title":"Improvements and New Features - Syntax_Tools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Syntax_Tools 3.1 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-3-1"},{"type":"extras","doc":"- Map comprehensions as suggested in EEP 58 has now been implemented.\n\n Own Id: OTP-18413 Aux Id: EEP-58, PR-6727","title":"Improvements and New Features - Syntax_Tools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Syntax_Tools 3.0.1 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-3-0-1"},{"type":"extras","doc":"- `erl_syntax_lib:annotate_bindings/1,2` will now properly annotate named\n functions and their arguments.\n\n Own Id: OTP-18380 Aux Id: PR-6523, GH-4733","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Syntax_Tools 3.0 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-3-0"},{"type":"extras","doc":"- The `erl_syntax_lib:analyze_attribute/1` function would return\n `{Name, {Name, Value}}` instead of `{Name, Value}` (which is the documented\n return value).\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-17894 Aux Id: PR-5509","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Added support for configurable features as described in EEP-60. Features can\n be enabled/disabled during compilation with options\n (`-enable-feature Feature`, `-disable-feature Feature` and\n `+{feature, Feature, enable|disable}`) to `erlc` as well as with directives\n (`-feature(Feature, enable|disable).`) in the file. Similar options can be\n used to `erl` for enabling/disabling features allowed at runtime. The new\n `maybe` expression (EEP-49) is fully supported as the feature `maybe_expr`.\n The features support is documented in the reference manual.\n\n Own Id: OTP-17988","title":"Improvements and New Features - Syntax_Tools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Syntax_Tools 2.6 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-2-6"},{"type":"extras","doc":"- The type spec of `erl_syntax:function_type/2` has been fixed.\n\n Own Id: OTP-17302 Aux Id: PR-4705\n\n- Output parentheses around `BitStringExpr` when pretty-printing binary\n comprehensions.\n\n Own Id: OTP-17321","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Support for handling abstract code created before OTP R15 has been dropped.\n\n Own Id: OTP-16678 Aux Id: PR-2627\n\n- The `igor` and `erl_tidy` modules have been the removed and are now maintained\n by their original author Richard Carlsson. They can be found at\n [github.com/richcarl/igor](https://github.com/richcarl/igor) and\n [github.com/richcarl/erl_tidy](https://github.com/richcarl/erl_tidy),\n respectively.\n\n Own Id: OTP-17180","title":"Improvements and New Features - Syntax_Tools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Syntax_Tools 2.5 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-2-5"},{"type":"extras","doc":"- `epp_dodger` was unable to handle a parameterized macro in a function head.\n\n Own Id: OTP-17064 Aux Id: GH-4445, PR-2964","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- All functions in `erl_tidy` in syntax_tools have now been deprecated and are\n scheduled for removal in OTP 24. Users who still need it can find it at\n [https://github.com/richcarl/erl_tidy](https://github.com/richcarl/erl_tidy).\n\n Own Id: OTP-17167 Aux Id: OTP-17046","title":"Improvements and New Features - Syntax_Tools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Syntax_Tools 2.4 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-2-4"},{"type":"extras","doc":"- In the `syntax_tools` application, the `igor` module and all functions in\n `erl_tidy` except `file/2` have been deprecated.\n\n Own Id: OTP-17046","title":"Improvements and New Features - Syntax_Tools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Syntax_Tools 2.3.1 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-2-3-1"},{"type":"extras","doc":"- Minor documentation fix of `erl_syntax:operator/1`.\n\n Own Id: OTP-16732 Aux Id: PR-2659","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Syntax_Tools 2.3 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-2-3"},{"type":"extras","doc":"- Remove incomplete support for `cond` expressions.\n\n Own Id: OTP-15925 Aux Id: PR-2304\n\n- Improved indentation for code generated with `erl_prettypr` and `tidier`.\n\n Own Id: OTP-16386 Aux Id: PR-2451","title":"Improvements and New Features - Syntax_Tools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Syntax_Tools 2.2.1 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-2-2-1"},{"type":"extras","doc":"- Add missing calls to `erl_syntax:unwrap/1`. The nodes concerned represent\n names and values of maps and map types.\n\n Own Id: OTP-16012 Aux Id: PR-2348","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Syntax_Tools 2.2 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-2-2"},{"type":"extras","doc":"- All incorrect (that is, all) uses of \"can not\" has been corrected to \"cannot\"\n in source code comments, documentation, examples, and so on.\n\n Own Id: OTP-14282 Aux Id: PR-1891","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Correct links in the documentation.\n\n Own Id: OTP-15761","title":"Improvements and New Features - Syntax_Tools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Syntax_Tools 2.1.7.1 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-2-1-7-1"},{"type":"extras","doc":"- Add missing calls to `erl_syntax:unwrap/1`. The nodes concerned represent\n names and values of maps and map types.\n\n Own Id: OTP-16012 Aux Id: PR-2348","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Syntax_Tools 2.1.7 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-2-1-7"},{"type":"extras","doc":"- Fix pretty-printing of type funs.\n\n Own Id: OTP-15519 Aux Id: ERL-815","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Syntax_Tools 2.1.6 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-2-1-6"},{"type":"extras","doc":"- Fix the `TypeName` type in erl_syntax_lib.\n\n Own Id: OTP-15207 Aux Id: PR-1888\n\n- Correct unfolding of the stacktrace variable.\n\n Own Id: OTP-15291 Aux Id: ERL-719\n\n- Correct `erl_syntax:revert/1` bug regarding the types `t:map/0` and\n `t:tuple/0`.\n\n Own Id: OTP-15294","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Support bitstrings as literals in module `erl_syntax`.\n\n Own Id: OTP-15165 Aux Id: PR-1842","title":"Improvements and New Features - Syntax_Tools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Syntax_Tools 2.1.5 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-2-1-5"},{"type":"extras","doc":"- Update to use the new string api instead of the old.\n\n Own Id: OTP-15036","title":"Improvements and New Features - Syntax_Tools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Syntax_Tools 2.1.4.2 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-2-1-4-2"},{"type":"extras","doc":"- Add missing calls to `erl_syntax:unwrap/1`. The nodes concerned represent\n names and values of maps and map types.\n\n Own Id: OTP-16012 Aux Id: PR-2348","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Syntax_Tools 2.1.4.1 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-2-1-4-1"},{"type":"extras","doc":"- Fix a bug regarding reverting map types.\n\n Own Id: OTP-15098 Aux Id: ERIERL-177","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Syntax_Tools 2.1.4 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-2-1-4"},{"type":"extras","doc":"- Removed all old unused files in the documentation.\n\n Own Id: OTP-14475 Aux Id: ERL-409, PR-1493","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Syntax_Tools 2.1.3 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-2-1-3"},{"type":"extras","doc":"- General Unicode improvements.\n\n Own Id: OTP-14462\n\n- A process trapping exits and calling `erl_tidy` no longer hangs if an error\n occurs.\n\n Own Id: OTP-14471 Aux Id: ERL-413","title":"Improvements and New Features - Syntax_Tools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Syntax_Tools 2.1.2 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-2-1-2"},{"type":"extras","doc":"- Miscellaneous updates due to atoms containing arbitrary Unicode characters.\n\n Own Id: OTP-14285","title":"Improvements and New Features - Syntax_Tools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Syntax_Tools 2.1.1.1 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-2-1-1-1"},{"type":"extras","doc":"- Fix a bug regarding reverting map types.\n\n Own Id: OTP-15098 Aux Id: ERIERL-177","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Syntax_Tools 2.1.1 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-2-1-1"},{"type":"extras","doc":"- The address to the FSF in the license header has been updated.\n\n Own Id: OTP-14084","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Syntax_Tools 2.1 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-2-1"},{"type":"extras","doc":"- Fix a bug where `erl_tidy` crashed on the tilde character when printing to\n standard output.\n\n Own Id: OTP-13725 Aux Id: ERL-151, PR-1071\n\n- `merl_transform` could get into an infinite loop when syntactically incorrect\n text was passed to a `merl:qquote/2,3` call.\n\n Own Id: OTP-13755","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Improve types and specs in OTP documentation generated from Erlang source\n files.\n\n Own Id: OTP-13720 Aux Id: ERL-120","title":"Improvements and New Features - Syntax_Tools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Syntax_Tools 2.0 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-2-0"},{"type":"extras","doc":"- The abstract data type in `erl_syntax` is augmented with types and function\n specifications.\n\n The module `erl_prettypr` pretty prints types and function specification, and\n the output can be parsed.\n\n The types of record fields are no longer ignored. As a consequence\n `erl_syntax_lib:analyze_record_field/1` returns `{Default, Type}` instead of\n `Default`. The functions `analyze_record_attribute`, `analyze_attribute`,\n `analyze_form`, and `analyze_forms` in the `erl_syntax_lib` module are also\n affected by this incompatible change.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-12863","title":"Improvements and New Features - Syntax_Tools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Syntax_Tools 1.7 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-1-7"},{"type":"extras","doc":"- Use the new `erl_anno` module.\n\n Own Id: OTP-12732\n\n- The `merl` module has been added to the `syntax_tools` application. The Merl\n library is a simpler way to work with erl_syntax parse trees.\n\n Own Id: OTP-12769","title":"Improvements and New Features - Syntax_Tools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Syntax_Tools 1.6.18 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-1-6-18"},{"type":"extras","doc":"- Fix bad format of error in epp_dodger:parse_file/3\n\n Own Id: OTP-12406","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Syntax_Tools 1.6.17 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-1-6-17"},{"type":"extras","doc":"- Teach Maps to erl_syntax\n\n Affected functions:\n\n - erl_syntax:abstract/1\n - erl_syntax:concrete/1\n - erl_syntax:is_leaf/1\n - erl_syntax:is_literal/1\n\n Own Id: OTP-12265","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Syntax_Tools 1.6.16 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-1-6-16"},{"type":"extras","doc":"- The default encoding for Erlang source files is now UTF-8. As a temporary\n measure to ease the transition from the old default of Latin-1, if EDoc\n encounters byte sequences that are not valid UTF-8 sequences, EDoc will re-try\n in Latin-1 mode. This workaround will be removed in a future release.\n\n Own Id: OTP-12008","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Syntax_Tools 1.6.15 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-1-6-15"},{"type":"extras","doc":"- Fix reverting map in syntax_tools\n\n There was a bug in erl_syntax when running e.g. erl_syntax:revert_forms,\n affecting maps. Instead of getting Key/Value you got Key/Key in the resulting\n abstract form.\n\n Own Id: OTP-11930","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Syntax_Tools 1.6.14 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-1-6-14"},{"type":"extras","doc":"- Application upgrade (appup) files are corrected for the following\n applications:\n\n `asn1, common_test, compiler, crypto, debugger, dialyzer, edoc, eldap, erl_docgen, et, eunit, gs, hipe, inets, observer, odbc, os_mon, otp_mibs, parsetools, percept, public_key, reltool, runtime_tools, ssh, syntax_tools, test_server, tools, typer, webtool, wx, xmerl`\n\n A new test utility for testing appup files is added to test_server. This is\n now used by most applications in OTP.\n\n (Thanks to Tobias Schlager)\n\n Own Id: OTP-11744","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- Add implementation of having erl_tidy print to screen instead of writing to\n the file provided. (Thanks to Aaron France)\n\n Own Id: OTP-11632\n\n- Support Maps syntax in syntax_tools (Thanks to Anthony Ramine).\n\n Own Id: OTP-11663","title":"Improvements and New Features - Syntax_Tools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Syntax_Tools 1.6.13 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-1-6-13"},{"type":"extras","doc":"- In syntax_tools-1.6.12 (OTP R16B03) a bug was introduced which broke reverting\n of local implicit funs. Implicit funs were mistakenly thought to be using\n abstract terms for their name and arity. This has now been corrected. (Thanks\n to Anthony Ramine)\n\n Own Id: OTP-11576","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"- The default encoding of Erlang files has been changed from ISO-8859-1 to\n UTF-8.\n\n The encoding of XML files has also been changed to UTF-8.\n\n Own Id: OTP-10907","title":"Improvements and New Features - Syntax_Tools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Syntax_Tools 1.6.12 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-1-6-12"},{"type":"extras","doc":"- Fix transformation of implicit funs in igor (Thanks to Anthony Ramine)\n\n Own Id: OTP-11506","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Syntax_Tools 1.6.11 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-1-6-11"},{"type":"extras","doc":"- Miscellaneous updates due to Unicode support.\n\n Own Id: OTP-10820","title":"Improvements and New Features - Syntax_Tools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Syntax_Tools 1.6.10 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-1-6-10"},{"type":"extras","doc":"- Support for Unicode has been implemented.\n\n Own Id: OTP-10302","title":"Improvements and New Features - Syntax_Tools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Syntax_Tools 1.6.9 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-1-6-9"},{"type":"extras","doc":"- Syntax Tools 1.6.9\n\n Minor bugfixes, spec annotations and documentation cleanup. Thanks to Richard\n Carlsson\n\n Own Id: OTP-10208","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Syntax_Tools 1.6.8 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-1-6-8"},{"type":"extras","doc":"- Minor suppressions and fixes of compilation warnings\n\n Own Id: OTP-10016","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Syntax_Tools 1.6.7.2 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-1-6-7-2"},{"type":"extras","doc":"- Variables are now now allowed in '`fun M:F/A`' as suggested by Richard O'Keefe\n in EEP-23.\n\n The representation of '`fun M:F/A`' in the abstract format has been changed in\n an incompatible way. Tools that directly read or manipulate the abstract\n format (such as parse transforms) may need to be updated. The compiler can\n handle both the new and the old format (i.e. extracting the abstract format\n from a pre-R15 BEAM file and compiling it using compile:forms/1,2 will work).\n The `syntax_tools` application can also handle both formats.\n\n \\*** POTENTIAL INCOMPATIBILITY \\***\n\n Own Id: OTP-9643\n\n- Eliminate use of deprecated regexp module\n\n Own Id: OTP-9810","title":"Improvements and New Features - Syntax_Tools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Syntax_Tools 1.6.7.1 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-1-6-7-1"},{"type":"extras","doc":"- In a file containing declarations and comments without any empty lines between\n them, the `recomment_forms()` function would associate a multi-line comment\n with the declaration above it rather than the one following it. (Thanks to\n Richard Carlsson and Kostis Sagonas.)\n\n Own Id: OTP-9180","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Syntax_Tools 1.6.7 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-1-6-7"},{"type":"extras","doc":"- Miscellaneous updates\n\n Own Id: OTP-8976","title":"Improvements and New Features - Syntax_Tools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Syntax_Tools 1.6.6 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-1-6-6"},{"type":"extras","doc":"- Minor changes and clean-ups.\n\n Own Id: OTP-8709","title":"Improvements and New Features - Syntax_Tools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Syntax_Tools 1.6.5 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-1-6-5"},{"type":"extras","doc":"- The documentation is now possible to build in an open source environment after\n a number of bugs are fixed and some features are added in the documentation\n build process.\n\n \\- The arity calculation is updated.\n\n \\- The module prefix used in the function names for bif's are removed in the\n generated links so the links will look like\n \"http://www.erlang.org/doc/man/erlang.html#append_element-2\" instead of\n \"http://www.erlang.org/doc/man/erlang.html#erlang:append_element-2\".\n\n \\- Enhanced the menu positioning in the html documentation when a new page is\n loaded.\n\n \\- A number of corrections in the generation of man pages (thanks to Sergei\n Golovan)\n\n \\- The legal notice is taken from the xml book file so OTP's build process can\n be used for non OTP applications.\n\n Own Id: OTP-8343","title":"Improvements and New Features - Syntax_Tools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Syntax_Tools 1.6.4 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-1-6-4"},{"type":"extras","doc":"- The documentation is now built with open source tools (xsltproc and fop) that\n exists on most platforms. One visible change is that the frames are removed.\n\n Own Id: OTP-8201","title":"Improvements and New Features - Syntax_Tools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Syntax_Tools 1.6.3 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-1-6-3"},{"type":"extras","doc":"- Miscellaneous updates.\n\n Own Id: OTP-8190","title":"Improvements and New Features - Syntax_Tools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Syntax_Tools 1.6.2 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-1-6-2"},{"type":"extras","doc":"- Miscellaneous updates.\n\n Own Id: OTP-8038","title":"Improvements and New Features - Syntax_Tools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Syntax_Tools 1.6 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-1-6"},{"type":"extras","doc":"- Miscellaneous updates.\n\n Own Id: OTP-7877","title":"Improvements and New Features - Syntax_Tools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Syntax_Tools 1.5.6 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-1-5-6"},{"type":"extras","doc":"- Minor updates.\n\n Own Id: OTP-7642","title":"Improvements and New Features - Syntax_Tools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Syntax_Tools 1.5.5 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-1-5-5"},{"type":"extras","doc":"- Minor changes.\n\n Own Id: OTP-7388","title":"Improvements and New Features - Syntax_Tools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Syntax_Tools 1.5.4 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-1-5-4"},{"type":"extras","doc":"- Minor updates, mostly cosmetic.\n\n Own Id: OTP-7243","title":"Improvements and New Features - Syntax_Tools Release Notes","ref":"notes.html#improvements-and-new-features"},{"type":"extras","doc":"","title":"Syntax_Tools 1.5.3 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-1-5-3"},{"type":"extras","doc":"- A missing directory (`examples`) has been added and another broken link in the\n documentation has been fixed.\n\n Own Id: OTP-6468","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"","title":"Syntax_Tools 1.5.2 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-1-5-2"},{"type":"extras","doc":"- Fixed some broken links in the documentation.\n\n Own Id: OTP-6420","title":"Fixed Bugs and Malfunctions - Syntax_Tools Release Notes","ref":"notes.html#fixed-bugs-and-malfunctions"},{"type":"extras","doc":"Miscellaneous changes.","title":"Syntax_Tools 1.5.1 - Syntax_Tools Release Notes","ref":"notes.html#syntax_tools-1-5-1"},{"type":"extras","doc":"\n# Erlang Syntax and Metaprogramming tools","title":"Erlang Syntax and Metaprogramming tools","ref":"chapter.html"},{"type":"extras","doc":"This package contains modules for handling abstract syntax trees (ASTs) in\nErlang, in a way that is compatible with the \"abstract format\" parse trees of\nthe stdlib module `erl_parse`, together with utilities for reading source files,\n[pretty-printing syntax trees](`m:erl_prettypr`), and doing\n[metaprogramming](`m:merl`) in Erlang.\n\nThe abstract layer (defined in `m:erl_syntax`) is nicely structured and the node\ntypes are context-independent. The layer makes it possible to transparently\nattach source-code comments and user annotations to nodes of the tree. Using the\nabstract layer makes applications less sensitive to changes in the `m:erl_parse`\ndata structures, only requiring the `erl_syntax` module to be up-to-date.\n\nThe pretty printer `m:erl_prettypr` is implemented on top of the library module\n`m:prettypr`: this is a powerful and flexible generic pretty printing library,\nwhich is also distributed separately.\n\nFor a short demonstration of parsing and pretty-printing, simply compile the\nincluded module [assets/demo.erl](assets/demo.erl), and execute `demo:run()` from the Erlang\nshell. It will compile the remaining modules and give you further instructions.","title":"Overview - Erlang Syntax and Metaprogramming tools","ref":"chapter.html#overview"}],"content_type":"text/plain","producer":{"name":"ex_doc","version":[48,46,51,52,46,49]}} \ No newline at end of file diff --git a/prs/9045/lib/syntax_tools-3.2.1/doc/html/erl_syntax.html b/prs/9045/lib/syntax_tools-3.2.1/doc/html/erl_syntax.html index faefc6a399b7..c1ee704b4b07 100644 --- a/prs/9045/lib/syntax_tools-3.2.1/doc/html/erl_syntax.html +++ b/prs/9045/lib/syntax_tools-3.2.1/doc/html/erl_syntax.html @@ -6972,10 +6972,10 @@

    get_postcomments(Node)

    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.

    @@ -7008,10 +7008,10 @@

    get_precomments(Node)

    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.

    diff --git a/prs/9045/lib/syntax_tools-3.2.1/doc/html/merl.html b/prs/9045/lib/syntax_tools-3.2.1/doc/html/merl.html index 3a301351df44..9311449bcfc2 100644 --- a/prs/9045/lib/syntax_tools-3.2.1/doc/html/merl.html +++ b/prs/9045/lib/syntax_tools-3.2.1/doc/html/merl.html @@ -144,30 +144,30 @@

    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 @@ -190,23 +190,23 @@

    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]).");
         ...

    @@ -215,40 +215,40 @@

    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
       +
    diff --git a/prs/9045/lib/syntax_tools-3.2.1/doc/html/search.html b/prs/9045/lib/syntax_tools-3.2.1/doc/html/search.html
    index 14a112146221..89405213049a 100644
    --- a/prs/9045/lib/syntax_tools-3.2.1/doc/html/search.html
    +++ b/prs/9045/lib/syntax_tools-3.2.1/doc/html/search.html
    @@ -128,7 +128,7 @@ 

    - +

    diff --git a/prs/9045/lib/tftp-1.2.1/doc/html/getting_started.html b/prs/9045/lib/tftp-1.2.1/doc/html/getting_started.html index 291e70973fce..96deaa5780c3 100644 --- a/prs/9045/lib/tftp-1.2.1/doc/html/getting_started.html +++ b/prs/9045/lib/tftp-1.2.1/doc/html/getting_started.html @@ -134,9 +134,9 @@

    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" > file.txt

    Step 2. Start the TFTP server:

          1> {ok, Pid} = tftp:start([{port, 19999}]).
    -      {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" > file.txt

    Step 2. Start the TFTP server:

          1> {ok, Pid} = tftp:start([{port, 19999}]).
    +      {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">>}
    diff --git a/prs/9045/lib/tftp-1.2.1/doc/html/tftp.epub b/prs/9045/lib/tftp-1.2.1/doc/html/tftp.epub index 0a6db0f8f5f5..c3aae9c9547a 100644 Binary files a/prs/9045/lib/tftp-1.2.1/doc/html/tftp.epub and b/prs/9045/lib/tftp-1.2.1/doc/html/tftp.epub differ diff --git a/prs/9045/lib/tftp-1.2.1/doc/html/tftp.html b/prs/9045/lib/tftp-1.2.1/doc/html/tftp.html index b211356b1552..9819fe652ae7 100644 --- a/prs/9045/lib/tftp-1.2.1/doc/html/tftp.html +++ b/prs/9045/lib/tftp-1.2.1/doc/html/tftp.html @@ -140,7 +140,7 @@

    Overwiew

    -

    This is a complete implementation of the following IETF standards:

    RFC 1350, The TFTP Protocol (revision 2).
    +

    This is a complete implementation of the following IETF standards:

    RFC 1350, The TFTP Protocol (revision 2).
     RFC 2347, TFTP Option Extension.
     RFC 2348, TFTP Blocksize Option.
     RFC 2349, TFTP Timeout Interval and Transfer Size Options.

    The only feature that not is implemented in this release is diff --git a/prs/9045/lib/tools-4.1/doc/html/cover.html b/prs/9045/lib/tools-4.1/doc/html/cover.html index 6809bf046166..dd25a14e9e2e 100644 --- a/prs/9045/lib/tools-4.1/doc/html/cover.html +++ b/prs/9045/lib/tools-4.1/doc/html/cover.html @@ -1567,7 +1567,7 @@

    analyse(Arg)

    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]).

    @@ -1609,7 +1609,7 @@

    analyse(Arg1, Arg2)

    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).
    @@ -1718,7 +1718,7 @@

    analyse_to_file(Arg)

    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], []).
    diff --git a/prs/9045/lib/tools-4.1/doc/html/cover_chapter.html b/prs/9045/lib/tools-4.1/doc/html/cover_chapter.html index aa991d4cecc0..cdc1df823ad4 100644 --- a/prs/9045/lib/tools-4.1/doc/html/cover_chapter.html +++ b/prs/9045/lib/tools-4.1/doc/html/cover_chapter.html @@ -152,81 +152,81 @@

    Example

    -

    Assume that a test case for the following program should be verified:

    -module(channel).
    --behaviour(gen_server).
    +

    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]).
    +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().

    +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 +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 @@ -244,56 +244,56 @@

    {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}},
    -     {{channel,52},{1,0}}]}

    For channel, the result shows that the uncovered line is line number 49.

    +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}},
    +     {{channel,52},{1,0}}]}

    For channel, the result shows that the uncovered line is line number 49.

    @@ -302,53 +302,53 @@

    Analysis of type calls is used to find out how many times something has been called and is represented by an integer Calls.

    If the analysis is made on module level, the result is given as a tuple {Module,Calls}. Here Calls is the total number of calls to functions in the -module:

    8> cover:analyse(channel, calls, module).
    -{ok,{channel,12}}

    For channel, the result shows that a total of twelve calls have been made to +module:

    8> cover:analyse(channel, calls, module).
    +{ok,{channel,12}}

    For channel, the result shows that a total of twelve calls have been made to functions in the module.

    If the analysis is made on function level, the result is given as a list of -tuples {Function,Calls}. Here Calls is the number of calls to each function:

    9> cover:analyse(channel, calls, function).
    -{ok,[{{channel,start_link,0},1},
    -     {{channel,stop,0},1},
    -     {{channel,alloc,0},1},
    -     {{channel,free,1},1},
    -     {{channel,init,1},1},
    -     {{channel,handle_call,3},3},
    -     {{channel,terminate,2},1},
    -     {{channel,channels,0},1},
    -     {{channel,alloc,1},1},
    -     {{channel,free,2},1}]}

    For channel, the result shows that handle_call/3 is the most called function +tuples {Function,Calls}. Here Calls is the number of calls to each function:

    9> cover:analyse(channel, calls, function).
    +{ok,[{{channel,start_link,0},1},
    +     {{channel,stop,0},1},
    +     {{channel,alloc,0},1},
    +     {{channel,free,1},1},
    +     {{channel,init,1},1},
    +     {{channel,handle_call,3},3},
    +     {{channel,terminate,2},1},
    +     {{channel,channels,0},1},
    +     {{channel,alloc,1},1},
    +     {{channel,free,2},1}]}

    For channel, the result shows that handle_call/3 is the most called function in the module (three calls). All other functions have been called once.

    If the analysis is made on clause level, the result is given as a list of tuples -{Clause,Calls}. Here Calls is the number of calls to each function clause:

    10> cover:analyse(channel, calls, clause).
    -{ok,[{{channel,start_link,0,1},1},
    -     {{channel,stop,0,1},1},
    -     {{channel,alloc,0,1},1},
    -     {{channel,free,1,1},1},
    -     {{channel,init,1,1},1},
    -     {{channel,handle_call,3,1},1},
    -     {{channel,handle_call,3,2},1},
    -     {{channel,handle_call,3,3},1},
    -     {{channel,terminate,2,1},1},
    -     {{channel,channels,0,1},1},
    -     {{channel,alloc,1,1},1},
    -     {{channel,alloc,1,2},0},
    -     {{channel,free,2,1},1}]}

    For channel, the result shows that all clauses have been called once, except +{Clause,Calls}. Here Calls is the number of calls to each function clause:

    10> cover:analyse(channel, calls, clause).
    +{ok,[{{channel,start_link,0,1},1},
    +     {{channel,stop,0,1},1},
    +     {{channel,alloc,0,1},1},
    +     {{channel,free,1,1},1},
    +     {{channel,init,1,1},1},
    +     {{channel,handle_call,3,1},1},
    +     {{channel,handle_call,3,2},1},
    +     {{channel,handle_call,3,3},1},
    +     {{channel,terminate,2,1},1},
    +     {{channel,channels,0,1},1},
    +     {{channel,alloc,1,1},1},
    +     {{channel,alloc,1,2},0},
    +     {{channel,free,2,1},1}]}

    For channel, the result shows that all clauses have been called once, except the second clause of channel:alloc/1 which has not been called at all.

    Finally, if the analysis is made on line level, the result is given as a list of tuples {Line,Calls}. Here Calls is the number of times each line has been -executed:

    11> cover:analyse(channel, calls, line).
    -{ok,[{{channel,9},1},
    -     {{channel,12},1},
    -     {{channel,17},1},
    -     {{channel,20},1},
    -     {{channel,25},1},
    -     {{channel,28},1},
    -     {{channel,31},1},
    -     {{channel,32},1},
    -     {{channel,35},1},
    -     {{channel,36},1},
    -     {{channel,39},1},
    -     {{channel,44},1},
    -     {{channel,47},1},
    -     {{channel,49},0},
    -     {{channel,52},1}]}

    For channel, the result shows that all lines have been executed once, except +executed:

    11> cover:analyse(channel, calls, line).
    +{ok,[{{channel,9},1},
    +     {{channel,12},1},
    +     {{channel,17},1},
    +     {{channel,20},1},
    +     {{channel,25},1},
    +     {{channel,28},1},
    +     {{channel,31},1},
    +     {{channel,32},1},
    +     {{channel,35},1},
    +     {{channel,36},1},
    +     {{channel,39},1},
    +     {{channel,44},1},
    +     {{channel,47},1},
    +     {{channel,49},0},
    +     {{channel,52},1}]}

    For channel, the result shows that all lines have been executed once, except line number 49 which has not been executed at all.

    @@ -356,65 +356,65 @@

    Analysis to File

    A line level calls analysis of channel can be written to a file using -cover:analyse_to_file/1:

    12> cover:analyse_to_file(channel).
    -{ok,"channel.COVER.out"}

    The function creates a copy of channel.erl where it for each executable line +cover:analyse_to_file/1:

    12> cover:analyse_to_file(channel).
    +{ok,"channel.COVER.out"}

    The function creates a copy of channel.erl where it for each executable line is specified how many times that line has been executed. The output file is called channel.COVER.out.

    File generated from /Users/bjorng/git/otp/channel.erl by COVER 2024-03-20 at 13:25:04
     
     ****************************************************************************
     
    -        |  -module(channel).
    -        |  -behaviour(gen_server).
    +        |  -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() ->
    -     1..|      gen_server:start_link({local,channel}, channel, [], []).
    +        |  start_link() ->
    +     1..|      gen_server:start_link({local,channel}, channel, [], []).
             |
    -        |  stop() ->
    -     1..|      gen_server:call(channel, stop).
    +        |  stop() ->
    +     1..|      gen_server:call(channel, stop).
             |
             |  %%%-Client interface functions-------------------------------------------
             |
    -        |  alloc() ->
    -     1..|      gen_server:call(channel, alloc).
    +        |  alloc() ->
    +     1..|      gen_server:call(channel, alloc).
             |
    -        |  free(Channel) ->
    -     1..|      gen_server:call(channel, {free,Channel}).
    +        |  free(Channel) ->
    +     1..|      gen_server:call(channel, {free,Channel}).
             |
             |  %%%-gen_server callback functions----------------------------------------
             |
    -        |  init(_Arg) ->
    -     1..|      {ok,channels()}.
    +        |  init(_Arg) ->
    +     1..|      {ok,channels()}.
             |
    -        |  handle_call(stop, _Client, Channels) ->
    -     1..|      {stop,normal,ok,Channels};
    +        |  handle_call(stop, _Client, Channels) ->
    +     1..|      {stop,normal,ok,Channels};
             |
    -        |  handle_call(alloc, _Client, Channels) ->
    -     1..|      {Ch,Channels2} = alloc(Channels),
    -     1..|      {reply,{ok,Ch},Channels2};
    +        |  handle_call(alloc, _Client, Channels) ->
    +     1..|      {Ch,Channels2} = alloc(Channels),
    +     1..|      {reply,{ok,Ch},Channels2};
             |
    -        |  handle_call({free,Channel}, _Client, Channels) ->
    -     1..|      Channels2 = free(Channel, Channels),
    -     1..|      {reply,ok,Channels2}.
    +        |  handle_call({free,Channel}, _Client, Channels) ->
    +     1..|      Channels2 = free(Channel, Channels),
    +     1..|      {reply,ok,Channels2}.
             |
    -        |  terminate(_Reason, _Channels) ->
    +        |  terminate(_Reason, _Channels) ->
          1..|      ok.
             |
             |  %%%-Internal functions---------------------------------------------------
             |
    -        |  channels() ->
    -     1..|      [ch1,ch2,ch3].
    +        |  channels() ->
    +     1..|      [ch1,ch2,ch3].
             |
    -        |  alloc([Channel|Channels]) ->
    -     1..|      {Channel,Channels};
    -        |  alloc([]) ->
    +        |  alloc([Channel|Channels]) ->
    +     1..|      {Channel,Channels};
    +        |  alloc([]) ->
          0..|      false.
             |
    -        |  free(Channel, Channels) ->
    -     1..|      [Channel|Channels].

    + | free(Channel, Channels) -> + 1..| [Channel|Channels].

    @@ -425,11 +425,11 @@

    and test.erl should be extended accordingly. Incidentally, when the test case is corrected a bug in channel will be discovered.

    When the Cover analysis is ready, Cover is stopped and all cover-compiled modules are unloaded. The code for channel is now -loaded as usual from a .beam file in the current path.

    13> code:which(channel).
    +loaded as usual from a .beam file in the current path.

    13> code:which(channel).
     cover_compiled
    -14> cover:stop().
    +14> cover:stop().
     ok
    -15> code:which(channel).
    +15> code:which(channel).
     "./channel.beam"

    @@ -457,12 +457,12 @@

    Cover uses the concept of executable lines, which is code lines 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 or receive -statement is not executable.

    In the example below, lines number 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
    +statement is not executable.

    In the example below, lines number 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;
    diff --git a/prs/9045/lib/tools-4.1/doc/html/cprof.html b/prs/9045/lib/tools-4.1/doc/html/cprof.html
    index fa840763fda9..46ac278a3fba 100644
    --- a/prs/9045/lib/tools-4.1/doc/html/cprof.html
    +++ b/prs/9045/lib/tools-4.1/doc/html/cprof.html
    @@ -596,7 +596,7 @@ 

    analyse(Module, Limit)

    -

    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 diff --git a/prs/9045/lib/tools-4.1/doc/html/cprof_chapter.html b/prs/9045/lib/tools-4.1/doc/html/cprof_chapter.html index 1f4f30a574f6..b69cda601737 100644 --- a/prs/9045/lib/tools-4.1/doc/html/cprof_chapter.html +++ b/prs/9045/lib/tools-4.1/doc/html/cprof_chapter.html @@ -162,36 +162,36 @@

    Example: Background work

    -

    From the Erlang shell:

    1> cprof:start(), cprof:pause(). % Stop counters just after start
    +

    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 @@ -201,20 +201,20 @@

    Example: One module

    -

    From the Erlang shell:

    1> cprof:start(),R=calendar:day_of_the_week(1896,4,27),cprof:pause(),R.
    +

    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 @@ -224,60 +224,60 @@

    Example: In the code

    -

    Write a module:

    -module(sort).
    --export([do/1]).
    +

    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.

    diff --git a/prs/9045/lib/tools-4.1/doc/html/erlang-el.html b/prs/9045/lib/tools-4.1/doc/html/erlang-el.html index 793d710cc0d0..12bb76cf52a5 100644 --- a/prs/9045/lib/tools-4.1/doc/html/erlang-el.html +++ b/prs/9045/lib/tools-4.1/doc/html/erlang-el.html @@ -217,23 +217,23 @@

    • 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() }.

    +-record { two :: int(), % hello + three = hello :: string(), % there + four = 42 :: int() }.

    diff --git a/prs/9045/lib/tools-4.1/doc/html/fprof.html b/prs/9045/lib/tools-4.1/doc/html/fprof.html index 46e47933eab3..fe75d83bd61b 100644 --- a/prs/9045/lib/tools-4.1/doc/html/fprof.html +++ b/prs/9045/lib/tools-4.1/doc/html/fprof.html @@ -181,61 +181,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}]}.
    -
    -{[{{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 +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 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 @@ -252,12 +252,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 @@ -265,88 +265,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},
    -  {{prim_file,open_int,4},                1,   19.755,    0.017},
    -  {{prim_file,open_int_setopts,3},        1,    0.147,    0.016}],
    - { {prim_file,drv_command,2},           772, 1593.322,   12.867},     %
    - [{{prim_file,drv_command,4},           772, 1578.973,   27.265},
    -  {suspend,                              22,    1.482,    0.000}]}.

    The time for file operations in the linked in driver distributes itself as 1 % +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},
    +  {{prim_file,open_int,4},                1,   19.755,    0.017},
    +  {{prim_file,open_int_setopts,3},        1,    0.147,    0.016}],
    + { {prim_file,drv_command,2},           772, 1593.322,   12.867},     %
    + [{{prim_file,drv_command,4},           772, 1578.973,   27.265},
    +  {suspend,                              22,    1.482,    0.000}]}.

    The time for file operations in the linked in driver distributes itself as 1 % for open, 11 % for write, and 87 % for close. All data is probably buffered in the operating system until the close.

    The observant reader may notice that the ACC times for prim_file:drv_command/2 and prim_file:drv_command/4 is not equal between the paragraphs above, even though it is easy to believe that prim_file:drv_command/2 is just a passthrough function.

    The missing time can be found in the paragraph for prim_file:drv_command/4 where it is evident that not only prim_file:drv_command/2 is called but also a -fun:

    {[{{prim_file,drv_command,2},           772, 1578.973,   27.265}],
    - { {prim_file,drv_command,4},           772, 1578.973,   27.265},     %
    - [{{erlang,port_command,2},             772, 1458.356, 1456.643},
    -  {{prim_file,'-drv_command/2-fun-0-',1}, 772,   87.897,   12.736},
    -  {suspend,                              50,    4.582,    0.000},
    -  {garbage_collect,                      25,    0.873,    0.873}]}.

    And some more missing time can be explained by the fact that +fun:

    {[{{prim_file,drv_command,2},           772, 1578.973,   27.265}],
    + { {prim_file,drv_command,4},           772, 1578.973,   27.265},     %
    + [{{erlang,port_command,2},             772, 1458.356, 1456.643},
    +  {{prim_file,'-drv_command/2-fun-0-',1}, 772,   87.897,   12.736},
    +  {suspend,                              50,    4.582,    0.000},
    +  {garbage_collect,                      25,    0.873,    0.873}]}.

    And some more missing time can be explained by the fact that prim_file:open_int/4 both calls prim_file:drv_command/2 directly as well as -through prim_file:open_int_setopts/3, which complicates the picture.

    {[{{prim_file,open,2},                    1,   20.309,    0.029},
    -  {{prim_file,open_int,4},                1,    0.000,    0.057}],
    - { {prim_file,open_int,4},                2,   20.309,    0.086},     %
    - [{{prim_file,drv_command,2},             1,   19.755,    0.017},
    -  {{prim_file,open_int_setopts,3},        1,    0.360,    0.032},
    -  {{prim_file,drv_open,2},                1,    0.071,    0.030},
    -  {{erlang,list_to_binary,1},             1,    0.020,    0.020},
    -  {{prim_file,i32,1},                     1,    0.017,    0.017},
    -  {{prim_file,open_int,4},                1,    0.000,    0.057}]}.
    +through prim_file:open_int_setopts/3, which complicates the picture.

    {[{{prim_file,open,2},                    1,   20.309,    0.029},
    +  {{prim_file,open_int,4},                1,    0.000,    0.057}],
    + { {prim_file,open_int,4},                2,   20.309,    0.086},     %
    + [{{prim_file,drv_command,2},             1,   19.755,    0.017},
    +  {{prim_file,open_int_setopts,3},        1,    0.360,    0.032},
    +  {{prim_file,drv_open,2},                1,    0.071,    0.030},
    +  {{erlang,list_to_binary,1},             1,    0.020,    0.020},
    +  {{prim_file,i32,1},                     1,    0.017,    0.017},
    +  {{prim_file,open_int,4},                1,    0.000,    0.057}]}.
     .
     .
     .
    -{[{{prim_file,open_int,4},                1,    0.360,    0.032},
    -  {{prim_file,open_int_setopts,3},        1,    0.000,    0.016}],
    - { {prim_file,open_int_setopts,3},        2,    0.360,    0.048},     %
    - [{suspend,                               1,    0.165,    0.000},
    -  {{prim_file,drv_command,2},             1,    0.147,    0.016},
    -  {{prim_file,open_int_setopts,3},        1,    0.000,    0.016}]}.

    +{[{{prim_file,open_int,4}, 1, 0.360, 0.032}, + {{prim_file,open_int_setopts,3}, 1, 0.000, 0.016}], + { {prim_file,open_int_setopts,3}, 2, 0.360, 0.048}, % + [{suspend, 1, 0.165, 0.000}, + {{prim_file,drv_command,2}, 1, 0.147, 0.016}, + {{prim_file,open_int_setopts,3}, 1, 0.000, 0.016}]}.

    diff --git a/prs/9045/lib/tools-4.1/doc/html/fprof_chapter.html b/prs/9045/lib/tools-4.1/doc/html/fprof_chapter.html index a5614772feac..98fc1aafd038 100644 --- a/prs/9045/lib/tools-4.1/doc/html/fprof_chapter.html +++ b/prs/9045/lib/tools-4.1/doc/html/fprof_chapter.html @@ -182,10 +182,10 @@

    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.

    diff --git a/prs/9045/lib/tools-4.1/doc/html/lcnt_chapter.html b/prs/9045/lib/tools-4.1/doc/html/lcnt_chapter.html index 820aed9cf9a5..d5a963778e47 100644 --- a/prs/9045/lib/tools-4.1/doc/html/lcnt_chapter.html +++ b/prs/9045/lib/tools-4.1/doc/html/lcnt_chapter.html @@ -239,20 +239,20 @@

    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]
    +

    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).
           .
           .
           .
    @@ -356,63 +356,63 @@ 

    The Big Bang Benchmark

    -
    -module(big).
    --export([bang/1]).
    +
    -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).

    +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).

    diff --git a/prs/9045/lib/tools-4.1/doc/html/make.html b/prs/9045/lib/tools-4.1/doc/html/make.html index ee7c6d83f2db..4e6d3a150f6a 100644 --- a/prs/9045/lib/tools-4.1/doc/html/make.html +++ b/prs/9045/lib/tools-4.1/doc/html/make.html @@ -148,8 +148,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]}.

    +debug_info flag.

    {'file1',[debug_info,{i,"../foo"}]}.
    +{'*',[debug_info]}.

    diff --git a/prs/9045/lib/tools-4.1/doc/html/notes.html b/prs/9045/lib/tools-4.1/doc/html/notes.html index 5d75ef9fe418..3006e81fe3b0 100644 --- a/prs/9045/lib/tools-4.1/doc/html/notes.html +++ b/prs/9045/lib/tools-4.1/doc/html/notes.html @@ -161,25 +161,25 @@

    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]).
      +
      • 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

      +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

    @@ -192,12 +192,12 @@

    """. "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

  • diff --git a/prs/9045/lib/tools-4.1/doc/html/tools.epub b/prs/9045/lib/tools-4.1/doc/html/tools.epub index b6833b5cb4ae..6ef716d4adfe 100644 Binary files a/prs/9045/lib/tools-4.1/doc/html/tools.epub and b/prs/9045/lib/tools-4.1/doc/html/tools.epub differ diff --git a/prs/9045/lib/tools-4.1/doc/html/tprof.html b/prs/9045/lib/tools-4.1/doc/html/tprof.html index 1e2d3c664218..f4c8f764553d 100644 --- a/prs/9045/lib/tools-4.1/doc/html/tprof.html +++ b/prs/9045/lib/tools-4.1/doc/html/tprof.html @@ -166,137 +166,137 @@

    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}).
    +

    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}}}).
    -
    -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}).
    +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}).
     <...>
    -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]
    -pg:join/3                      1      4         4  [ 4.04]
    -erl_eval:add_bindings/2        1      5         5  [ 5.05]
    -erl_eval:do_apply/7            2      6         3  [ 6.06]
    -gen:call/4                     1      8         8  [ 8.08]
    -erl_eval:expr_list/7           4     10         2  [10.10]
    -gen:do_call/4                  1     16        16  [16.16]
    -erl_eval:ret_expr/3            4     16         4  [16.16]
    -erl_eval:merge_bindings/4      3     24         8  [24.24]
    -                                     99            [100.0]

    By default, there is no limit for the profiling time. For ad-hoc +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] +pg:join/3 1 4 4 [ 4.04] +erl_eval:add_bindings/2 1 5 5 [ 5.05] +erl_eval:do_apply/7 2 6 3 [ 6.06] +gen:call/4 1 8 8 [ 8.08] +erl_eval:expr_list/7 4 10 2 [10.10] +gen:do_call/4 1 16 16 [16.16] +erl_eval:ret_expr/3 4 16 4 [16.16] +erl_eval:merge_bindings/4 3 24 8 [24.24] + 99 [100.0]

    By default, there is no limit for the profiling time. For ad-hoc profiling, it is possible to configure a time limit. If the profiled function does not return before that time expires, the process is terminated with reason kill. Any unlinked children processes started by the user-supplied function are kept; it is the responsibility of -the developer to take care of such processes.

    9> tprof:profile(timer, sleep, [100000], #{timeout => 1000}).

    By default, only one ad-hoc or server-aided profiling session is +the developer to take care of such processes.

    9> tprof:profile(timer, sleep, [100000], #{timeout => 1000}).

    By default, only one ad-hoc or server-aided profiling session is allowed at any point in time. It is possible to force multiple ad-hoc sessions concurrently, but it is the responsibility of the developer -to ensure that trace patterns do not overlap:

    1> tprof:profile(fun() -> lists:seq(1, 32) end,
    -    #{registered => false, pattern => [{lists, '_', '_'}]}).

    +to ensure that trace patterns do not overlap:

    1> tprof:profile(fun() -> lists:seq(1, 32) end,
    +    #{registered => false, pattern => [{lists, '_', '_'}]}).

    @@ -307,50 +307,50 @@

    patterns and processes to trace while the system handles actual traffic. Data can extracted, inspected, and printed at any time. The following example traces activity of all processes supervised by -the Kernel supervisor:

    1> tprof:start(#{type => call_memory}).
    -{ok,<0.200.0>}
    -2> tprof:enable_trace({all_children, kernel_sup}).
    +the Kernel supervisor:

    1> tprof:start(#{type => call_memory}).
    +{ok,<0.200.0>}
    +2> tprof:enable_trace({all_children, kernel_sup}).
     34
    -3> tprof:set_pattern('_', '_' , '_').
    +3> tprof:set_pattern('_', '_' , '_').
     16728
    -4> Sample = tprof:collect().
    -{call_memory,
    -    [{gen_server,try_dispatch,4,[{<0.154.0>,2,6}]},
    -     {erlang,iolist_to_iovec,1,[{<0.161.0>,1,8}]},
    +4> Sample = tprof:collect().
    +{call_memory,
    +    [{gen_server,try_dispatch,4,[{<0.154.0>,2,6}]},
    +     {erlang,iolist_to_iovec,1,[{<0.161.0>,1,8}]},
     <...>
    -5 > tprof:format(tprof:inspect(Sample)).
    +5 > tprof:format(tprof:inspect(Sample)).
     
     ****** Process <0.154.0>    -- 14.21 % of total allocations ***
    -FUNCTION                   CALLS  WORDS  PER CALL  [    %]
    -maps:iterator/1                2      4         2  [15.38]
    -gen_server:try_dispatch/4      2      6         3  [23.08]
    -net_kernel:handle_info/2       2     16         8  [61.54]
    -                                     26            [100.0]
    +FUNCTION                   CALLS  WORDS  PER CALL  [    %]
    +maps:iterator/1                2      4         2  [15.38]
    +gen_server:try_dispatch/4      2      6         3  [23.08]
    +net_kernel:handle_info/2       2     16         8  [61.54]
    +                                     26            [100.0]
     
     ****** Process <0.161.0>    -- 85.79 % of total allocations ***
    -FUNCTION                        CALLS  WORDS  PER CALL  [    %]
    -disk_log:handle/2                   2      2         1  [ 1.27]
    -disk_log_1:maybe_start_timer/1      1      3         3  [ 1.91]
    -disk_log_1:mf_write_cache/1         1      3         3  [ 1.91]
    +FUNCTION                        CALLS  WORDS  PER CALL  [    %]
    +disk_log:handle/2                   2      2         1  [ 1.27]
    +disk_log_1:maybe_start_timer/1      1      3         3  [ 1.91]
    +disk_log_1:mf_write_cache/1         1      3         3  [ 1.91]
     <...>

    It is possible to profile the entire running system, and then examine individual -processes:

    1> tprof:start(#{type => call_memory}).
    -2> tprof:enable_trace(all), tprof:set_pattern('_', '_' , '_').
    +processes:

    1> tprof:start(#{type => call_memory}).
    +2> tprof:enable_trace(all), tprof:set_pattern('_', '_' , '_').
     9041
    -3> timer:sleep(10000), tprof:disable_trace(all), Sample = tprof:collect().
    -{call_memory,
    -    [{user_drv,server,3,[{<0.64.0>,12,136}]},
    -     {user_drv,contains_ctrl_g_or_ctrl_c,1,[{<0.64.0>,80,10}]},
    +3> timer:sleep(10000), tprof:disable_trace(all), Sample = tprof:collect().
    +{call_memory,
    +    [{user_drv,server,3,[{<0.64.0>,12,136}]},
    +     {user_drv,contains_ctrl_g_or_ctrl_c,1,[{<0.64.0>,80,10}]},
     <...>
    -4> Inspected = tprof:inspect(Sample, process, measurement), Shell = maps:get(self(), Inspected).
    -{call_memory, 2743,
    -    [{shell,{enc,0},1,2,2,0.07291286912139992},
    +4> Inspected = tprof:inspect(Sample, process, measurement), Shell = maps:get(self(), Inspected).
    +{call_memory, 2743,
    +    [{shell,{enc,0},1,2,2,0.07291286912139992},
     <...>
    -5> tprof:format(Shell).
    +5> tprof:format(Shell).
     
    -FUNCTION                           CALLS  WORDS  PER CALL  [    %]
    +FUNCTION                           CALLS  WORDS  PER CALL  [    %]
     <...>
    -erl_lint:start/2                       2    300       150  [10.94]
    -shell:used_records/1                 114    342         3  [12.47]
    +
    erl_lint:start/2 2 300 150 [10.94] +shell:used_records/1 114 342 3 [12.47]
    @@ -1376,12 +1376,12 @@

    clear_pattern(Mod, Fun, Arity)

    -

    Disables tracing functions matching the supplied pattern.

    1> tprof:set_pattern(lists, seq, '_').
    +

    Disables tracing functions matching the supplied pattern.

    1> tprof:set_pattern(lists, seq, '_').
     2
    -2> tprof:clear_pattern(lists, seq, 3).
    +2> tprof:clear_pattern(lists, seq, 3).
     1
    -3> tprof:get_trace_map().
    -#{lists => [{seq,2}]}

    Requires that the default tprof server has been started.

    +3>
    tprof:get_trace_map(). +#{lists => [{seq,2}]}

    Requires that the default tprof server has been started.

    @@ -2223,13 +2223,13 @@

    set_pattern(Mod, Fun, Arity)

    Enables tracing for all functions matching the supplied pattern.

    Patterns are additive, following the same rules as trace:function/4. -Returns the number of functions matching the supplied pattern.

    1> tprof:set_pattern(lists, seq, '_').
    +Returns the number of functions matching the supplied pattern.

    1> tprof:set_pattern(lists, seq, '_').
     2
    -2> tprof:set_pattern(lists, keyfind, 3).
    +2> tprof:set_pattern(lists, keyfind, 3).
     1
    -3> tprof:get_trace_map().
    -#{lists => [{keyfind,3},{seq,2},{seq,3}]}

    If no functions match the pattern, an error tuple is returned:

    > tprof:set_pattern(no_module, func, '_').
    -{error,{trace_pattern,no_module,func,'_'}}

    Requires that the default tprof server has been started.

    +3>
    tprof:get_trace_map(). +#{lists => [{keyfind,3},{seq,2},{seq,3}]}

    If no functions match the pattern, an error tuple is returned:

    > tprof:set_pattern(no_module, func, '_').
    +{error,{trace_pattern,no_module,func,'_'}}

    Requires that the default tprof server has been started.

    diff --git a/prs/9045/lib/tools-4.1/doc/html/xref_chapter.html b/prs/9045/lib/tools-4.1/doc/html/xref_chapter.html index 1d3e12793fe6..cfe710c1c48f 100644 --- a/prs/9045/lib/tools-4.1/doc/html/xref_chapter.html +++ b/prs/9045/lib/tools-4.1/doc/html/xref_chapter.html @@ -146,25 +146,25 @@

    Module Check

    -

    Assume we want to check the following module:

    -module(my_module).
    +

    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 @@ -179,28 +179,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 @@ -230,8 +230,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()).

    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:

    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) ->
    +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).
    +

    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}]).
    diff --git a/prs/9045/lib/xmerl-2.1/doc/html/xmerl_ug.html b/prs/9045/lib/xmerl-2.1/doc/html/xmerl_ug.html index b7b4eb962038..f553f02e24d6 100644 --- a/prs/9045/lib/xmerl-2.1/doc/html/xmerl_ug.html +++ b/prs/9045/lib/xmerl-2.1/doc/html/xmerl_ug.html @@ -199,16 +199,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{} @@ -277,41 +277,41 @@

    color NMTOKENS #REQUIRED condition (useless | bad | serviceable | moderate | good | excellent | new | outstanding) "excellent" >

    If you want to parse the XML file motorcycles.xml you run it in the Erlang shell -like:

    3> {ParseResult,Misc}=xmerl_scan:file("motorcycles.xml").
    -{{xmlElement,motorcycles,
    +like:

    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.

    @@ -348,22 +348,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>
    @@ -393,40 +393,40 @@ 

    the DTD is referenced. If so, it is possible to pass a RootAttribute {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}]),
    +"],
    +    Export=xmerl:export_simple([NewRootEl],xmerl_xml,[{prolog,Prolog}]),
         ...

    The result will be:

    
     <?xml version="1.0" encoding="utf-8" ?>
     <!DOCTYPE motorcycles SYSTEM "motorcycles.dtd">
    @@ -475,32 +475,32 @@ 

    Assume that you want to transform the motorcycles.xml document to HTML. If you want the same structure and tags of the resulting HTML document as of the XML document -then you can use the xmerl:export/2 function. The following:

    2> {Doc,Misc}=xmerl_scan:file('motorcycles.xml').
    -{{xmlElement,motorcycles,
    +then you can use the xmerl:export/2 function. The following:

    2> {Doc,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,
     ...
    -3> DocHtml=xmerl:export([Doc],xmerl_html).
    -["<!DOCTYPE HTML PUBLIC \\"",
    +3> DocHtml=xmerl:export([Doc],xmerl_html).
    +["<!DOCTYPE HTML PUBLIC \\"",
      "-//W3C//DTD HTML 4.01 Transitional//EN",
      "\\"",
    - [],
    + [],
      ">\
     ",
    - [[["<","motorcycles",">"],
    -   ["\
    + [[["<","motorcycles",">"],
    +   ["\
       ",
    -    [["<",
    +    [["<",
           "bike",
    -      [[" ","year","=\\"","2000","\\""],[" ","color","=\\"","black","\\""]],
    -      ">"],
    +      [[" ","year","=\\"","2000","\\""],[" ","color","=\\"","black","\\""]],
    +      ">"],
     ...

    Will give the result result_export.html

    Perhaps you want to do something more arranged for human reading. Suppose that you want to list all different brands in the beginning with links to each group of motorcycles. You also want all motorcycles sorted by brand, then some flashy @@ -511,17 +511,17 @@

    HTML it also applies to transformations to other formats.

    xmerl_xs does not implement the entire XSLT specification but the basic functionality. For all details see the reference manual

    First, some words about the xmerl_xs functionality:

    You need to write template functions to be able to control what kind of output you want. Thus if you want to encapsulate a bike element in <p> tags you -simply write a function:

    template(E = #xmlElement{name='bike'}) ->
    -    ["<p>",xslapply(fun template/1,E),"</p>"];

    With xslapply you tell the XSLT processor in which order it should traverse +simply write a function:

    template(E = #xmlElement{name='bike'}) ->
    +    ["<p>",xslapply(fun template/1,E),"</p>"];

    With xslapply you tell the XSLT processor in which order it should traverse the XML structure. By default it goes in preorder traversal, but with the -following we make a deliberate choice to break that order:

    template(E = #xmlElement{name='bike'}) ->
    -    ["<p>",xslapply(fun template/1,select("bike/name/manufacturer")),"</p>"];

    If you want to output the content of an XML element or an attribute you will get -the value as a string by the value_of function:

    template(E = #xmlElement{name='motorcycles'}) ->
    -    ["<p>",value_of(select("bike/name/manufacturer",E),"</p>"];

    In the xmerl_xs functions you can provide a select(String) call, which is an +following we make a deliberate choice to break that order:

    template(E = #xmlElement{name='bike'}) ->
    +    ["<p>",xslapply(fun template/1,select("bike/name/manufacturer")),"</p>"];

    If you want to output the content of an XML element or an attribute you will get +the value as a string by the value_of function:

    template(E = #xmlElement{name='motorcycles'}) ->
    +    ["<p>",value_of(select("bike/name/manufacturer",E),"</p>"];

    In the xmerl_xs functions you can provide a select(String) call, which is an XPath functionality. For more details see the xmerl_xs tutorial.

    Now, back to the example where we wanted to make the output more arranged. With -the template:

    template(E = #xmlElement{name='motorcycles'}) ->
    -    [    "<head>\
    +the template:

    template(E = #xmlElement{name='motorcycles'}) ->
    +    [    "<head>\
     <title>motorcycles</title>\
     </head>\
     ",
    @@ -531,32 +531,32 @@ 

    ", \011 "<ul>\ ", -\011 remove_duplicates(value_of(select("bike/name/manufacturer",E))), +\011 remove_duplicates(value_of(select("bike/name/manufacturer",E))), \011 "\ </ul>\ ", -\011 sort_by_manufacturer(xslapply(fun template/1, E)), +\011 sort_by_manufacturer(xslapply(fun template/1, E)), "</body>\ ", \011 "</html>\ -"];

    We match on the top element and embed the inner parts in an HTML body. Then we +"];

    We match on the top element and embed the inner parts in an HTML body. Then we extract the string values of all motorcycle brands, sort them and removes duplicates by remove_duplicates(value_of(select("bike/name/manufacturer", E))). We also process the substructure of the top element and pass it to a function that sorts all motorcycle information by brand according to the task formulation in the -beginning of this example.

    The next template matches on the bike element:

    template(E = #xmlElement{name='bike'}) ->
    -    {value_of(select("name/manufacturer",E)),["<dt>",xslapply(fun template/1,select("name",E)),"</dt>",
    +beginning of this example.

    The next template matches on the bike element:

    template(E = #xmlElement{name='bike'}) ->
    +    {value_of(select("name/manufacturer",E)),["<dt>",xslapply(fun template/1,select("name",E)),"</dt>",
         "<dd><ul>\
     ",
    -    "<li style="color:green">Manufacturing year: ",xslapply(fun template/1,select("@year",E)),"</li>\
    +    "<li style="color:green">Manufacturing year: ",xslapply(fun template/1,select("@year",E)),"</li>\
     ",
    -    "<li style="color:red">Color: ",xslapply(fun template/1,select("@color",E)),"</li>\
    +    "<li style="color:red">Color: ",xslapply(fun template/1,select("@color",E)),"</li>\
     ",
    -    "<li style="color:blue">Shape : ",xslapply(fun template/1,select("@condition",E)),"</li>\
    +    "<li style="color:blue">Shape : ",xslapply(fun template/1,select("@condition",E)),"</li>\
     ",
         "</ul></dd>\
    -"]};

    This creates a tuple with the brand of the motorcycle and the output format. We +"]};

    This creates a tuple with the brand of the motorcycle and the output format. We use the brand name only for sorting purpose. We have to end the template function with the "built in clause" template(E) -> built_in_rules(fun template/1, E).

    The entire program is motorcycles2html.erl:

    
    @@ -567,106 +567,106 @@ 

    %%% %%% Created : 2 Sep 2004 by Bertil Karlsson <bertil@localhost.localdomain> %%%------------------------------------------------------------------- --module(motorcycles2html). +-module(motorcycles2html). --include_lib("xmerl/include/xmerl.hrl"). +-include_lib("xmerl/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 ]). --export([process_xml/1,process_to_file/2,process_to_file/1]). - -process_xml(Doc) -> - template(Doc). - -process_to_file(FileName) -> - process_to_file(FileName,'motorcycles.xml'). - -process_to_file(FileName,XMLDoc) -> - case file:open(FileName,[write]) of - {ok,IOF} -> - {XMLContent,_} = xmerl_scan:file(XMLDoc), - TransformedXML=process_xml(XMLContent), - io:format(IOF,"~s",[TransformedXML]), - file:close(IOF); - {error,Reason} -> - io:format("could not open file due to ~p.~n",[Reason]) +-export([process_xml/1,process_to_file/2,process_to_file/1]). + +process_xml(Doc) -> + template(Doc). + +process_to_file(FileName) -> + process_to_file(FileName,'motorcycles.xml'). + +process_to_file(FileName,XMLDoc) -> + case file:open(FileName,[write]) of + {ok,IOF} -> + {XMLContent,_} = xmerl_scan:file(XMLDoc), + TransformedXML=process_xml(XMLContent), + io:format(IOF,"~s",[TransformedXML]), + file:close(IOF); + {error,Reason} -> + io:format("could not open file due to ~p.~n",[Reason]) end. %%% templates -template(E = #xmlElement{name='motorcycles'}) -> - [ "<head>\n<title>motorcycles</title>\n</head>\n", +template(E = #xmlElement{name='motorcycles'}) -> + [ "<head>\n<title>motorcycles</title>\n</head>\n", "<body>\n", "<h1>Used Motorcycles</h1>\n", "<ul>\n", - remove_duplicates(value_of(select("bike/name/manufacturer",E))), + remove_duplicates(value_of(select("bike/name/manufacturer",E))), "\n</ul>\n", - sort_by_manufacturer(xslapply(fun template/1, E)), + sort_by_manufacturer(xslapply(fun template/1, E)), "</body>\n", - "</html>\n"]; -template(E = #xmlElement{name='bike'}) -> - {value_of(select("name/manufacturer",E)),["<dt>",xslapply(fun template/1,select("name",E)),"</dt>", + "</html>\n"]; +template(E = #xmlElement{name='bike'}) -> + {value_of(select("name/manufacturer",E)),["<dt>",xslapply(fun template/1,select("name",E)),"</dt>", "<dd><ul>\n", - "<li style=\"color:green\">Manufacturing year: ",xslapply(fun template/1,select("@year",E)),"</li>\n", - "<li style=\"color:red\">Color: ",xslapply(fun template/1,select("@color",E)),"</li>\n", - "<li style=\"color:blue\">Shape : ",xslapply(fun template/1,select("@condition",E)),"</li>\n", - "</ul></dd>\n"]}; -template(E) -> built_in_rules(fun template/1, E). + "<li style=\"color:green\">Manufacturing year: ",xslapply(fun template/1,select("@year",E)),"</li>\n", + "<li style=\"color:red\">Color: ",xslapply(fun template/1,select("@color",E)),"</li>\n", + "<li style=\"color:blue\">Shape : ",xslapply(fun template/1,select("@condition",E)),"</li>\n", + "</ul></dd>\n"]}; +template(E) -> built_in_rules(fun template/1, E). %%%%%%%%%%% helper routines %% sorts on the bike name element, unwraps the bike information and %% inserts a line feed and indentation on each bike element. -sort_by_manufacturer(L) -> - Tuples=[X1||X1={_,_} <- L], - SortedTS = lists:keysort(1,Tuples), +sort_by_manufacturer(L) -> + Tuples=[X1||X1={_,_} <- L], + SortedTS = lists:keysort(1,Tuples), InsertRefName_UnWrap= - fun([{[Name],V}|Rest],Name,F)-> - [V|F(Rest,Name,F)]; - ([{[Name],V}|Rest],_PreviousName,F) -> - [["<a name=\"",Name,"\"></>"],V|F(Rest,Name,F)]; - ([],_,_) -> [] + fun([{[Name],V}|Rest],Name,F)-> + [V|F(Rest,Name,F)]; + ([{[Name],V}|Rest],_PreviousName,F) -> + [["<a name=\"",Name,"\"></>"],V|F(Rest,Name,F)]; + ([],_,_) -> [] end, - SortedRefed=InsertRefName_UnWrap(SortedTS,no_name,InsertRefName_UnWrap), + SortedRefed=InsertRefName_UnWrap(SortedTS,no_name,InsertRefName_UnWrap), % SortedTs=[Y||{X,Y}<-lists:keysort(1,Tuples)], WS = "\n ", - Fun=fun([H|T],Acc,F)-> - F(T,[H,WS|Acc],F); - ([],Acc,_F)-> - lists:reverse([WS|Acc]) + Fun=fun([H|T],Acc,F)-> + F(T,[H,WS|Acc],F); + ([],Acc,_F)-> + lists:reverse([WS|Acc]) end, - if length(SortedRefed) > 0 -> - Fun(SortedRefed,[],Fun); - true -> [] + if length(SortedRefed) > 0 -> + Fun(SortedRefed,[],Fun); + true -> [] end. %% removes all but the first of an element in L and inserts a html %% reference for each list element. -remove_duplicates(L) -> - remove_duplicates(L,[]). +remove_duplicates(L) -> + remove_duplicates(L,[]). -remove_duplicates([],Acc) -> - make_ref(lists:sort(lists:reverse(Acc))); -remove_duplicates([A|L],Acc) -> - case lists:delete(A,L) of +remove_duplicates([],Acc) -> + make_ref(lists:sort(lists:reverse(Acc))); +remove_duplicates([A|L],Acc) -> + case lists:delete(A,L) of L -> - remove_duplicates(L,[A|Acc]); + remove_duplicates(L,[A|Acc]); L1 -> - remove_duplicates([A|L1],[Acc]) + remove_duplicates([A|L1],[Acc]) end. -make_ref([]) -> []; -make_ref([H]) when is_atom(H) -> - "<ul><a href=\"#"++atom_to_list(H)++"\">"++atom_to_list(H)++"</a></ul>"; -make_ref([H]) when is_list(H) -> +make_ref([]) -> []; +make_ref([H]) when is_atom(H) -> + "<ul><a href=\"#"++atom_to_list(H)++"\">"++atom_to_list(H)++"</a></ul>"; +make_ref([H]) when is_list(H) -> "<ul><a href=\"#"++H++"\">\s"++H++"</a></ul>"; -make_ref([H|T]) when is_atom(H) -> - ["<ul><a href=\"#"++atom_to_list(H)++"\">\s"++atom_to_list(H)++",\n</a></ul>" - |make_ref(T)]; -make_ref([H|T]) when is_list(H) -> - ["<ul><a href=\"#"++H++"\">\s"++H++",\n</a></ul>"|make_ref(T)].

    If we run it like this: +make_ref([H|T]) when is_atom(H) -> + ["<ul><a href=\"#"++atom_to_list(H)++"\">\s"++atom_to_list(H)++",\n</a></ul>" + |make_ref(T)]; +make_ref([H|T]) when is_list(H) -> + ["<ul><a href=\"#"++H++"\">\s"++H++",\n</a></ul>"|make_ref(T)].

    If we run it like this: motorcycles2html:process_to_file('result_xs.html', 'motorcycles2.xml'). The result will be result_xs.html. When the input file is of the same structure as the previous "motorcycles" XML files but it has a little more diff --git a/prs/9045/lib/xmerl-2.1/doc/html/xmerl_xs_examples.html b/prs/9045/lib/xmerl-2.1/doc/html/xmerl_xs_examples.html index 2f024da0939d..176ee4163821 100644 --- a/prs/9045/lib/xmerl-2.1/doc/html/xmerl_xs_examples.html +++ b/prs/9045/lib/xmerl-2.1/doc/html/xmerl_xs_examples.html @@ -141,13 +141,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">
     
    @@ -208,60 +208,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.

    @@ -280,21 +280,21 @@

    for-each

    The function for-each is quite common in XSLT stylesheets. I <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>"];

    diff --git a/prs/9045/lib/xmerl-2.1/doc/html/xmerl_xsd.html b/prs/9045/lib/xmerl-2.1/doc/html/xmerl_xsd.html index f2030f2dcfda..190e90ba7be0 100644 --- a/prs/9045/lib/xmerl-2.1/doc/html/xmerl_xsd.html +++ b/prs/9045/lib/xmerl-2.1/doc/html/xmerl_xsd.html @@ -812,9 +812,9 @@

    validate(Xml, State, Opts)

    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.